summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Tso <kyletso@google.com>2022-12-25 00:08:03 +0800
committerKyle Tso <kyletso@google.com>2023-01-16 20:07:33 +0800
commit4cbc8e45b6cdb6bb21b75f2bdd4ed87ef1367cdd (patch)
tree2da3a7fd9902199a4c7f7b6e2e27c7c1c7200c4d
parent877d745d7be9cf68628548b22bc92a68e6b1844d (diff)
downloadtangorpro-4cbc8e45b6cdb6bb21b75f2bdd4ed87ef1367cdd.tar.gz
pogo_transport: Update the CC orientation to SS PHY in some cases
The reg base of the Superspeed PHY is based on the CC orientation. If the host mode is enabled before CC orientation is decided, the orientation information should be updated to the Superspeed PHY. Register a callback in Type-C SW stack to receive the CC-change event. When the condition is satified, update the CC orientation through extcon and cast a vote to "SSPHY_RESTART" votable to trigger the PHY restart. Bug: 257490462 Change-Id: I955ff6705482a4ce12b8233f0e36d185ad7022cd Signed-off-by: Kyle Tso <kyletso@google.com>
-rw-r--r--pogo/pogo_transport.c89
1 files changed, 82 insertions, 7 deletions
diff --git a/pogo/pogo_transport.c b/pogo/pogo_transport.c
index d8baeff..b070ac2 100644
--- a/pogo/pogo_transport.c
+++ b/pogo/pogo_transport.c
@@ -40,6 +40,7 @@
#define KEEP_HUB_PATH 2
#define POGO_VOTER "POGO"
+#define SSPHY_RESTART_EL "SSPHY_RESTART"
enum pogo_event_type {
/* Reported when docking status changes */
@@ -67,6 +68,8 @@ enum pogo_event_type {
/* Bypass the accessory detection and enable POGO Vout and POGO USB capability */
/* This event is for debug only and never used in normal operations. */
EVENT_FORCE_ACC_CONNECT,
+ /* Reported when CC orientation has changed */
+ EVENT_ORIENTATION_CHANGED,
};
static bool modparam_force_usb;
@@ -160,12 +163,16 @@ struct pogo_transport {
/* When true, disable voltage based detection of pogo partners */
bool disable_voltage_detection;
struct gvotable_election *charger_mode_votable;
+ struct gvotable_election *ssphy_restart_votable;
/* Used for cancellable work such as pogo debouncing */
struct kthread_delayed_work pogo_accessory_debounce_work;
/* Pogo accessory detection status */
enum pogo_accessory_detection accessory_detection_enabled;
+
+ /* Orientation of USB-C, 0:TYPEC_POLARITY_CC1 1:TYPEC_POLARITY_CC2 */
+ enum typec_cc_polarity polarity;
};
static const unsigned int pogo_extcon_cable[] = {
@@ -202,6 +209,21 @@ static void update_extcon_dev(struct pogo_transport *pogo_transport, bool docked
dev_err(pogo_transport->dev, "%s Failed to clear EXTCON_USB\n", __func__);
}
+static void ssphy_restart_control(struct pogo_transport *pogo_transport, bool enable)
+{
+ if (!pogo_transport->ssphy_restart_votable)
+ pogo_transport->ssphy_restart_votable =
+ gvotable_election_get_handle(SSPHY_RESTART_EL);
+
+ if (IS_ERR_OR_NULL(pogo_transport->ssphy_restart_votable)) {
+ logbuffer_log(pogo_transport->log, "SSPHY_RESTART get failed %ld\n",
+ PTR_ERR(pogo_transport->ssphy_restart_votable));
+ return;
+ }
+
+ gvotable_cast_long_vote(pogo_transport->ssphy_restart_votable, POGO_VOTER, enable, enable);
+}
+
static void disable_and_bypass_hub(struct pogo_transport *pogo_transport)
{
int ret;
@@ -215,6 +237,12 @@ static void disable_and_bypass_hub(struct pogo_transport *pogo_transport)
gpio_get_value(pogo_transport->pogo_hub_sel_gpio));
pogo_transport->pogo_hub_active = false;
+ /*
+ * No further action in the callback of the votable if it is disabled. Disable it here for
+ * the bookkeeping purpose in the dumpstate.
+ */
+ ssphy_restart_control(pogo_transport, false);
+
if (pogo_transport->hub_ldo && regulator_is_enabled(pogo_transport->hub_ldo) > 0) {
ret = regulator_disable(pogo_transport->hub_ldo);
if (ret)
@@ -445,8 +473,28 @@ static void update_pogo_transport(struct pogo_transport *pogo_transport,
}
break;
case EVENT_MOVE_DATA_TO_USB:
- if (pogo_transport->pogo_usb_active)
+ if (pogo_transport->pogo_usb_active) {
switch_to_usbc_locked(pogo_transport);
+
+ /*
+ * During the function call "switch_to_usbc_locked", the USB controller
+ * restarted and the orientation of the USB phy was reset to the default
+ * value CC1 because Type-C drivers had no chance to update the real
+ * orientation. Update and restart the superspeed phy if CC2 is connected.
+ */
+ if (pogo_transport->polarity == TYPEC_POLARITY_CC2) {
+ union extcon_property_value prop;
+ prop.intval = (int)TYPEC_POLARITY_CC2;
+ ret = extcon_set_property_sync(chip->extcon, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_TYPEC_POLARITY,
+ prop);
+ if (ret)
+ logbuffer_log(pogo_transport->log,
+ "Failed to set polarity, ret %d", ret);
+
+ ssphy_restart_control(pogo_transport, true);
+ }
+ }
break;
case EVENT_MOVE_DATA_TO_POGO:
/* Currently this event is bundled to force_pogo. This case is unreachable. */
@@ -605,6 +653,20 @@ static void update_pogo_transport(struct pogo_transport *pogo_transport,
pogo_transport->pogo_usb_capable = true;
break;
#endif
+ case EVENT_ORIENTATION_CHANGED:
+ /* Update the orientation and restart the ssphy if hub is enabled */
+ if (pogo_transport->pogo_hub_active) {
+ union extcon_property_value prop;
+ prop.intval = (int)pogo_transport->polarity;
+ ret = extcon_set_property_sync(chip->extcon, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_TYPEC_POLARITY, prop);
+ if (ret)
+ logbuffer_log(pogo_transport->log, "Failed to set polarity, ret %d",
+ ret);
+
+ ssphy_restart_control(pogo_transport, true);
+ }
+ break;
default:
break;
}
@@ -749,6 +811,17 @@ static void data_active_changed(void *data)
pogo_transport_event(pogo_transport, EVENT_DATA_ACTIVE_CHANGED, 0);
}
+static void orientation_changed(void *data)
+{
+ struct pogo_transport *pogo_transport = data;
+ struct max77759_plat *chip = pogo_transport->chip;
+
+ if (pogo_transport->polarity != chip->polarity) {
+ pogo_transport->polarity = chip->polarity;
+ pogo_transport_event(pogo_transport, EVENT_ORIENTATION_CHANGED, 0);
+ }
+}
+
static irqreturn_t pogo_isr(int irq, void *dev_id)
{
struct pogo_transport *pogo_transport = dev_id;
@@ -1236,6 +1309,9 @@ static int pogo_transport_probe(struct platform_device *pdev)
#endif
register_data_active_callback(data_active_changed, pogo_transport);
+ register_orientation_callback(orientation_changed, pogo_transport);
+ /* run once in case orientation has changed before registering the callback */
+ orientation_changed((void *)pogo_transport);
dev_info(&pdev->dev, "force usb:%d\n", modparam_force_usb ? 1 : 0);
put_device(&data_client->dev);
of_node_put(data_np);
@@ -1364,8 +1440,8 @@ static ssize_t enable_hub_store(struct device *dev, struct device_attribute *att
else
pogo_transport->force_hub_enabled = false;
- logbuffer_log(pogo_transport->log, "%s: %sable hub, force_hub_enabled %u", __func__,
- enable_hub ? "en" : "dis", pogo_transport->force_hub_enabled);
+ dev_info(pogo_transport->dev, "hub %u, force_hub_enabled %u\n", enable_hub,
+ pogo_transport->force_hub_enabled);
if (enable_hub)
pogo_transport_event(pogo_transport, EVENT_ENABLE_HUB, 0);
else
@@ -1391,8 +1467,7 @@ static ssize_t hall1_s_store(struct device *dev, struct device_attribute *attr,
return size;
if (!pogo_transport->accessory_detection_enabled) {
- logbuffer_log(pogo_transport->log, "%s:Accessory detection disabled ? skipping",
- __func__);
+ dev_info(pogo_transport->dev, "Accessory detection disabled\n");
return size;
}
@@ -1413,8 +1488,8 @@ static ssize_t hall1_s_store(struct device *dev, struct device_attribute *attr,
else
pogo_transport->mfg_acc_test = false;
- logbuffer_log(pogo_transport->log, "%s: %sable accessory detection, mfg %u", __func__,
- enable_acc_detect ? "en" : "dis", pogo_transport->mfg_acc_test);
+ dev_info(pogo_transport->dev, "accessory detection %u, mfg %u\n", enable_acc_detect,
+ pogo_transport->mfg_acc_test);
if (enable_acc_detect)
pogo_transport_event(pogo_transport, EVENT_HALL_SENSOR_ACC_DETECTED, 0);
else