diff options
Diffstat (limited to 'drivers/extcon')
| -rw-r--r-- | drivers/extcon/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/extcon/extcon-intel-int3496.c | 4 | ||||
| -rw-r--r-- | drivers/extcon/extcon-ptn5150.c | 56 | ||||
| -rw-r--r-- | drivers/extcon/extcon-usbc-cros-ec.c | 2 | ||||
| -rw-r--r-- | drivers/extcon/extcon-usbc-tusb320.c | 24 | ||||
| -rw-r--r-- | drivers/extcon/extcon.c | 23 |
6 files changed, 80 insertions, 30 deletions
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index aec46bf03302..68d9df7d2dae 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -158,6 +158,7 @@ config EXTCON_PTN5150 tristate "NXP PTN5150 CC LOGIC USB EXTCON support" depends on I2C && (GPIOLIB || COMPILE_TEST) depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH + depends on TYPEC || !TYPEC select REGMAP_I2C help Say Y here to enable support for USB peripheral and USB host diff --git a/drivers/extcon/extcon-intel-int3496.c b/drivers/extcon/extcon-intel-int3496.c index ded1a85a5549..7d16d5b7d58f 100644 --- a/drivers/extcon/extcon-intel-int3496.c +++ b/drivers/extcon/extcon-intel-int3496.c @@ -106,7 +106,7 @@ static irqreturn_t int3496_thread_isr(int irq, void *priv) struct int3496_data *data = priv; /* Let the pin settle before processing it */ - mod_delayed_work(system_wq, &data->work, DEBOUNCE_TIME); + mod_delayed_work(system_percpu_wq, &data->work, DEBOUNCE_TIME); return IRQ_HANDLED; } @@ -181,7 +181,7 @@ static int int3496_probe(struct platform_device *pdev) } /* process id-pin so that we start with the right status */ - queue_delayed_work(system_wq, &data->work, 0); + queue_delayed_work(system_percpu_wq, &data->work, 0); flush_delayed_work(&data->work); platform_set_drvdata(pdev, data); diff --git a/drivers/extcon/extcon-ptn5150.c b/drivers/extcon/extcon-ptn5150.c index 78ad86c4a3be..eca1b140aeb0 100644 --- a/drivers/extcon/extcon-ptn5150.c +++ b/drivers/extcon/extcon-ptn5150.c @@ -18,6 +18,7 @@ #include <linux/extcon-provider.h> #include <linux/gpio/consumer.h> #include <linux/usb/role.h> +#include <linux/usb/typec_mux.h> /* PTN5150 registers */ #define PTN5150_REG_DEVICE_ID 0x01 @@ -38,7 +39,11 @@ #define PTN5150_REG_DEVICE_ID_VERSION GENMASK(7, 3) #define PTN5150_REG_DEVICE_ID_VENDOR GENMASK(2, 0) +#define PTN5150_POLARITY_CC1 0x1 +#define PTN5150_POLARITY_CC2 0x2 + #define PTN5150_REG_CC_PORT_ATTACHMENT GENMASK(4, 2) +#define PTN5150_REG_CC_POLARITY GENMASK(1, 0) #define PTN5150_REG_CC_VBUS_DETECTION BIT(7) #define PTN5150_REG_INT_CABLE_ATTACH_MASK BIT(0) #define PTN5150_REG_INT_CABLE_DETACH_MASK BIT(1) @@ -53,6 +58,7 @@ struct ptn5150_info { int irq; struct work_struct irq_work; struct mutex mutex; + struct typec_switch *orient_sw; struct usb_role_switch *role_sw; }; @@ -71,6 +77,7 @@ static const struct regmap_config ptn5150_regmap_config = { static void ptn5150_check_state(struct ptn5150_info *info) { + enum typec_orientation orient = TYPEC_ORIENTATION_NONE; unsigned int port_status, reg_data, vbus; enum usb_role usb_role = USB_ROLE_NONE; int ret; @@ -81,6 +88,23 @@ static void ptn5150_check_state(struct ptn5150_info *info) return; } + orient = FIELD_GET(PTN5150_REG_CC_POLARITY, reg_data); + switch (orient) { + case PTN5150_POLARITY_CC1: + orient = TYPEC_ORIENTATION_NORMAL; + break; + case PTN5150_POLARITY_CC2: + orient = TYPEC_ORIENTATION_REVERSE; + break; + default: + orient = TYPEC_ORIENTATION_NONE; + break; + } + + ret = typec_switch_set(info->orient_sw, orient); + if (ret) + dev_err(info->dev, "failed to set orientation: %d\n", ret); + port_status = FIELD_GET(PTN5150_REG_CC_PORT_ATTACHMENT, reg_data); switch (port_status) { @@ -152,6 +176,12 @@ static void ptn5150_irq_work(struct work_struct *work) dev_err(info->dev, "failed to set none role: %d\n", ret); + + ret = typec_switch_set(info->orient_sw, + TYPEC_ORIENTATION_NONE); + if (ret) + dev_err(info->dev, + "failed to set orientation: %d\n", ret); } } @@ -219,12 +249,14 @@ static void ptn5150_work_sync_and_put(void *data) cancel_work_sync(&info->irq_work); usb_role_switch_put(info->role_sw); + typec_switch_put(info->orient_sw); } static int ptn5150_i2c_probe(struct i2c_client *i2c) { struct device *dev = &i2c->dev; struct device_node *np = i2c->dev.of_node; + struct fwnode_handle *connector; struct ptn5150_info *info; int ret; @@ -311,7 +343,17 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c) if (ret) return -EINVAL; + connector = device_get_named_child_node(dev, "connector"); + if (connector) { + info->orient_sw = fwnode_typec_switch_get(connector); + if (IS_ERR(info->orient_sw)) + return dev_err_probe(info->dev, PTR_ERR(info->orient_sw), + "failed to get orientation switch\n"); + } + info->role_sw = usb_role_switch_get(info->dev); + if (!info->role_sw && connector) + info->role_sw = fwnode_usb_role_switch_get(connector); if (IS_ERR(info->role_sw)) return dev_err_probe(info->dev, PTR_ERR(info->role_sw), "failed to get role switch\n"); @@ -331,6 +373,19 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c) return 0; } +static int ptn5150_resume(struct device *dev) +{ + struct i2c_client *i2c = to_i2c_client(dev); + struct ptn5150_info *info = i2c_get_clientdata(i2c); + + /* Need to check possible pending interrupt events */ + schedule_work(&info->irq_work); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(ptn5150_pm_ops, NULL, ptn5150_resume); + static const struct of_device_id ptn5150_dt_match[] = { { .compatible = "nxp,ptn5150" }, { }, @@ -346,6 +401,7 @@ MODULE_DEVICE_TABLE(i2c, ptn5150_i2c_id); static struct i2c_driver ptn5150_i2c_driver = { .driver = { .name = "ptn5150", + .pm = pm_sleep_ptr(&ptn5150_pm_ops), .of_match_table = ptn5150_dt_match, }, .probe = ptn5150_i2c_probe, diff --git a/drivers/extcon/extcon-usbc-cros-ec.c b/drivers/extcon/extcon-usbc-cros-ec.c index 1fb627ea8b50..a2ef710b0d6d 100644 --- a/drivers/extcon/extcon-usbc-cros-ec.c +++ b/drivers/extcon/extcon-usbc-cros-ec.c @@ -68,7 +68,7 @@ static int cros_ec_pd_command(struct cros_ec_extcon_info *info, struct cros_ec_command *msg; int ret; - msg = kzalloc(struct_size(msg, data, max(outsize, insize)), GFP_KERNEL); + msg = kzalloc_flex(*msg, data, max(outsize, insize)); if (!msg) return -ENOMEM; diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c index 2eab341de6b7..920b03421850 100644 --- a/drivers/extcon/extcon-usbc-tusb320.c +++ b/drivers/extcon/extcon-usbc-tusb320.c @@ -454,20 +454,18 @@ static int tusb320_typec_probe(struct i2c_client *client, priv->port_type = priv->cap.type; /* This goes into register 0x8 field CURRENT_MODE_ADVERTISE */ - ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str); - if (ret) - goto err_put; - - ret = typec_find_pwr_opmode(cap_str); - if (ret < 0) - goto err_put; - - priv->pwr_opmode = ret; + if (!fwnode_property_read_string(connector, "typec-power-opmode", + &cap_str)) { + ret = typec_find_pwr_opmode(cap_str); + if (ret < 0) + goto err_put; + priv->pwr_opmode = ret; - /* Initialize the hardware with the devicetree settings. */ - ret = tusb320_set_adv_pwr_mode(priv); - if (ret) - goto err_put; + /* Initialize the hardware with the devicetree settings. */ + ret = tusb320_set_adv_pwr_mode(priv); + if (ret) + goto err_put; + } priv->cap.revision = USB_TYPEC_REV_1_1; priv->cap.accessory[0] = TYPEC_ACCESSORY_AUDIO; diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index e7f55c021e56..98d85cc114a7 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -1060,7 +1060,7 @@ struct extcon_dev *extcon_dev_allocate(const unsigned int *supported_cable) if (!supported_cable) return ERR_PTR(-EINVAL); - edev = kzalloc(sizeof(*edev), GFP_KERNEL); + edev = kzalloc_obj(*edev); if (!edev) return ERR_PTR(-ENOMEM); @@ -1098,8 +1098,7 @@ static int extcon_alloc_cables(struct extcon_dev *edev) if (!edev->max_supported) return 0; - edev->cables = kcalloc(edev->max_supported, sizeof(*edev->cables), - GFP_KERNEL); + edev->cables = kzalloc_objs(*edev->cables, edev->max_supported); if (!edev->cables) return -ENOMEM; @@ -1160,13 +1159,11 @@ static int extcon_alloc_muex(struct extcon_dev *edev) for (index = 0; edev->mutually_exclusive[index]; index++) ; - edev->attrs_muex = kcalloc(index + 1, sizeof(*edev->attrs_muex), - GFP_KERNEL); + edev->attrs_muex = kzalloc_objs(*edev->attrs_muex, index + 1); if (!edev->attrs_muex) return -ENOMEM; - edev->d_attrs_muex = kcalloc(index, sizeof(*edev->d_attrs_muex), - GFP_KERNEL); + edev->d_attrs_muex = kzalloc_objs(*edev->d_attrs_muex, index); if (!edev->d_attrs_muex) { kfree(edev->attrs_muex); return -ENOMEM; @@ -1210,9 +1207,8 @@ static int extcon_alloc_groups(struct extcon_dev *edev) if (!edev->max_supported) return 0; - edev->extcon_dev_type.groups = kcalloc(edev->max_supported + 2, - sizeof(*edev->extcon_dev_type.groups), - GFP_KERNEL); + edev->extcon_dev_type.groups = kzalloc_objs(*edev->extcon_dev_type.groups, + edev->max_supported + 2); if (!edev->extcon_dev_type.groups) return -ENOMEM; @@ -1294,8 +1290,7 @@ int extcon_dev_register(struct extcon_dev *edev) spin_lock_init(&edev->lock); if (edev->max_supported) { - edev->nh = kcalloc(edev->max_supported, sizeof(*edev->nh), - GFP_KERNEL); + edev->nh = kzalloc_objs(*edev->nh, edev->max_supported); if (!edev->nh) { ret = -ENOMEM; goto err_alloc_nh; @@ -1371,10 +1366,10 @@ void extcon_dev_unregister(struct extcon_dev *edev) return; } - ida_free(&extcon_dev_ids, edev->id); - device_unregister(&edev->dev); + ida_free(&extcon_dev_ids, edev->id); + if (edev->mutually_exclusive && edev->max_supported) { for (index = 0; edev->mutually_exclusive[index]; index++) |
