diff options
Diffstat (limited to 'drivers/usb/typec/ucsi')
-rw-r--r-- | drivers/usb/typec/ucsi/debugfs.c | 3 | ||||
-rw-r--r-- | drivers/usb/typec/ucsi/displayport.c | 2 | ||||
-rw-r--r-- | drivers/usb/typec/ucsi/psy.c | 9 | ||||
-rw-r--r-- | drivers/usb/typec/ucsi/ucsi.c | 2 | ||||
-rw-r--r-- | drivers/usb/typec/ucsi/ucsi_ccg.c | 4 | ||||
-rw-r--r-- | drivers/usb/typec/ucsi/ucsi_glink.c | 54 |
6 files changed, 70 insertions, 4 deletions
diff --git a/drivers/usb/typec/ucsi/debugfs.c b/drivers/usb/typec/ucsi/debugfs.c index 0c7bf88d4a7f..f67733cecfdf 100644 --- a/drivers/usb/typec/ucsi/debugfs.c +++ b/drivers/usb/typec/ucsi/debugfs.c @@ -84,6 +84,9 @@ void ucsi_debugfs_register(struct ucsi *ucsi) void ucsi_debugfs_unregister(struct ucsi *ucsi) { + if (IS_ERR_OR_NULL(ucsi) || !ucsi->debugfs) + return; + debugfs_remove_recursive(ucsi->debugfs->dentry); kfree(ucsi->debugfs); } diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c index 73cd5bf35047..d9d3c91125ca 100644 --- a/drivers/usb/typec/ucsi/displayport.c +++ b/drivers/usb/typec/ucsi/displayport.c @@ -315,7 +315,7 @@ struct typec_altmode *ucsi_register_displayport(struct ucsi_connector *con, struct ucsi_dp *dp; /* We can't rely on the firmware with the capabilities. */ - desc->vdo |= DP_CAP_DP_SIGNALING | DP_CAP_RECEPTACLE; + desc->vdo |= DP_CAP_DP_SIGNALLING(0) | DP_CAP_RECEPTACLE; /* Claiming that we support all pin assignments */ desc->vdo |= all_assignments << 8; diff --git a/drivers/usb/typec/ucsi/psy.c b/drivers/usb/typec/ucsi/psy.c index 384b42267f1f..b35c6e07911e 100644 --- a/drivers/usb/typec/ucsi/psy.c +++ b/drivers/usb/typec/ucsi/psy.c @@ -37,6 +37,15 @@ static int ucsi_psy_get_scope(struct ucsi_connector *con, struct device *dev = con->ucsi->dev; device_property_read_u8(dev, "scope", &scope); + if (scope == POWER_SUPPLY_SCOPE_UNKNOWN) { + u32 mask = UCSI_CAP_ATTR_POWER_AC_SUPPLY | + UCSI_CAP_ATTR_BATTERY_CHARGING; + + if (con->ucsi->cap.attributes & mask) + scope = POWER_SUPPLY_SCOPE_SYSTEM; + else + scope = POWER_SUPPLY_SCOPE_DEVICE; + } val->intval = scope; return 0; } diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index c6dfe3dff346..61b64558f96c 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -787,6 +787,7 @@ static void ucsi_unregister_partner(struct ucsi_connector *con) typec_set_mode(con->port, TYPEC_STATE_SAFE); + typec_partner_set_usb_power_delivery(con->partner, NULL); ucsi_unregister_partner_pdos(con); ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP); typec_unregister_partner(con->partner); @@ -884,6 +885,7 @@ static void ucsi_handle_connector_change(struct work_struct *work) if (ret < 0) { dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n", __func__, ret); + clear_bit(EVENT_PENDING, &con->ucsi->flags); goto out_unlock; } diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index 607061a37eca..449c125f6f87 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -501,8 +501,8 @@ static void ucsi_ccg_nvidia_altmode(struct ucsi_ccg *uc, case NVIDIA_FTB_DP_OFFSET: if (alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DBG_VDO) alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DP_VDO | - DP_CAP_DP_SIGNALING | DP_CAP_USB | - DP_CONF_SET_PIN_ASSIGN(BIT(DP_PIN_ASSIGN_E)); + DP_CAP_DP_SIGNALLING(0) | DP_CAP_USB | + DP_CONF_SET_PIN_ASSIGN(BIT(DP_PIN_ASSIGN_E)); break; case NVIDIA_FTB_DBG_OFFSET: if (alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DP_VDO) diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c index bb1854b3311d..db6e248f8208 100644 --- a/drivers/usb/typec/ucsi/ucsi_glink.c +++ b/drivers/usb/typec/ucsi/ucsi_glink.c @@ -8,9 +8,13 @@ #include <linux/mutex.h> #include <linux/property.h> #include <linux/soc/qcom/pdr.h> +#include <linux/usb/typec_mux.h> +#include <linux/gpio/consumer.h> #include <linux/soc/qcom/pmic_glink.h> #include "ucsi.h" +#define PMIC_GLINK_MAX_PORTS 2 + #define UCSI_BUF_SIZE 48 #define MSG_TYPE_REQ_RESP 1 @@ -52,6 +56,9 @@ struct ucsi_notify_ind_msg { struct pmic_glink_ucsi { struct device *dev; + struct gpio_desc *port_orientation[PMIC_GLINK_MAX_PORTS]; + struct typec_switch *port_switch[PMIC_GLINK_MAX_PORTS]; + struct pmic_glink_client *client; struct ucsi *ucsi; @@ -220,8 +227,20 @@ static void pmic_glink_ucsi_notify(struct work_struct *work) } con_num = UCSI_CCI_CONNECTOR(cci); - if (con_num) + if (con_num) { + if (con_num < PMIC_GLINK_MAX_PORTS && + ucsi->port_orientation[con_num - 1]) { + int orientation = gpiod_get_value(ucsi->port_orientation[con_num - 1]); + + if (orientation >= 0) { + typec_switch_set(ucsi->port_switch[con_num - 1], + orientation ? TYPEC_ORIENTATION_REVERSE + : TYPEC_ORIENTATION_NORMAL); + } + } + ucsi_connector_change(ucsi->ucsi, con_num); + } if (ucsi->sync_pending && cci & UCSI_CCI_BUSY) { ucsi->sync_val = -EBUSY; @@ -282,6 +301,7 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, { struct pmic_glink_ucsi *ucsi; struct device *dev = &adev->dev; + struct fwnode_handle *fwnode; int ret; ucsi = devm_kzalloc(dev, sizeof(*ucsi), GFP_KERNEL); @@ -309,6 +329,38 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, ucsi_set_drvdata(ucsi->ucsi, ucsi); + device_for_each_child_node(dev, fwnode) { + struct gpio_desc *desc; + u32 port; + + ret = fwnode_property_read_u32(fwnode, "reg", &port); + if (ret < 0) { + dev_err(dev, "missing reg property of %pOFn\n", fwnode); + return ret; + } + + if (port >= PMIC_GLINK_MAX_PORTS) { + dev_warn(dev, "invalid connector number, ignoring\n"); + continue; + } + + desc = devm_gpiod_get_index_optional(&adev->dev, "orientation", port, GPIOD_IN); + + /* If GPIO isn't found, continue */ + if (!desc) + continue; + + if (IS_ERR(desc)) + return dev_err_probe(dev, PTR_ERR(desc), + "unable to acquire orientation gpio\n"); + ucsi->port_orientation[port] = desc; + + ucsi->port_switch[port] = fwnode_typec_switch_get(fwnode); + if (IS_ERR(ucsi->port_switch[port])) + return dev_err_probe(dev, PTR_ERR(ucsi->port_switch[port]), + "failed to acquire orientation-switch\n"); + } + ucsi->client = devm_pmic_glink_register_client(dev, PMIC_GLINK_OWNER_USBC, pmic_glink_ucsi_callback, |