Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * USB GPIO Based Connection Detection Driver
0004  *
0005  * Copyright (C) 2019 MediaTek Inc.
0006  *
0007  * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
0008  *
0009  * Some code borrowed from drivers/extcon/extcon-usb-gpio.c
0010  */
0011 
0012 #include <linux/device.h>
0013 #include <linux/gpio/consumer.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/irq.h>
0016 #include <linux/module.h>
0017 #include <linux/of.h>
0018 #include <linux/pinctrl/consumer.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/power_supply.h>
0021 #include <linux/regulator/consumer.h>
0022 #include <linux/usb/role.h>
0023 
0024 #define USB_GPIO_DEB_MS     20  /* ms */
0025 #define USB_GPIO_DEB_US     ((USB_GPIO_DEB_MS) * 1000)  /* us */
0026 
0027 #define USB_CONN_IRQF   \
0028     (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT)
0029 
0030 struct usb_conn_info {
0031     struct device *dev;
0032     struct usb_role_switch *role_sw;
0033     enum usb_role last_role;
0034     struct regulator *vbus;
0035     struct delayed_work dw_det;
0036     unsigned long debounce_jiffies;
0037 
0038     struct gpio_desc *id_gpiod;
0039     struct gpio_desc *vbus_gpiod;
0040     int id_irq;
0041     int vbus_irq;
0042 
0043     struct power_supply_desc desc;
0044     struct power_supply *charger;
0045 };
0046 
0047 /*
0048  * "DEVICE" = VBUS and "HOST" = !ID, so we have:
0049  * Both "DEVICE" and "HOST" can't be set as active at the same time
0050  * so if "HOST" is active (i.e. ID is 0)  we keep "DEVICE" inactive
0051  * even if VBUS is on.
0052  *
0053  *  Role          |   ID  |  VBUS
0054  * ------------------------------------
0055  *  [1] DEVICE    |   H   |   H
0056  *  [2] NONE      |   H   |   L
0057  *  [3] HOST      |   L   |   H
0058  *  [4] HOST      |   L   |   L
0059  *
0060  * In case we have only one of these signals:
0061  * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1
0062  * - ID only - we want to distinguish between [1] and [4], so VBUS = ID
0063  */
0064 static void usb_conn_detect_cable(struct work_struct *work)
0065 {
0066     struct usb_conn_info *info;
0067     enum usb_role role;
0068     int id, vbus, ret;
0069 
0070     info = container_of(to_delayed_work(work),
0071                 struct usb_conn_info, dw_det);
0072 
0073     /* check ID and VBUS */
0074     id = info->id_gpiod ?
0075         gpiod_get_value_cansleep(info->id_gpiod) : 1;
0076     vbus = info->vbus_gpiod ?
0077         gpiod_get_value_cansleep(info->vbus_gpiod) : id;
0078 
0079     if (!id)
0080         role = USB_ROLE_HOST;
0081     else if (vbus)
0082         role = USB_ROLE_DEVICE;
0083     else
0084         role = USB_ROLE_NONE;
0085 
0086     dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n",
0087         usb_role_string(info->last_role), usb_role_string(role), id, vbus);
0088 
0089     if (info->last_role == role) {
0090         dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role));
0091         return;
0092     }
0093 
0094     if (info->last_role == USB_ROLE_HOST && info->vbus)
0095         regulator_disable(info->vbus);
0096 
0097     ret = usb_role_switch_set_role(info->role_sw, role);
0098     if (ret)
0099         dev_err(info->dev, "failed to set role: %d\n", ret);
0100 
0101     if (role == USB_ROLE_HOST && info->vbus) {
0102         ret = regulator_enable(info->vbus);
0103         if (ret)
0104             dev_err(info->dev, "enable vbus regulator failed\n");
0105     }
0106 
0107     info->last_role = role;
0108 
0109     if (info->vbus)
0110         dev_dbg(info->dev, "vbus regulator is %s\n",
0111             regulator_is_enabled(info->vbus) ? "enabled" : "disabled");
0112 
0113     power_supply_changed(info->charger);
0114 }
0115 
0116 static void usb_conn_queue_dwork(struct usb_conn_info *info,
0117                  unsigned long delay)
0118 {
0119     queue_delayed_work(system_power_efficient_wq, &info->dw_det, delay);
0120 }
0121 
0122 static irqreturn_t usb_conn_isr(int irq, void *dev_id)
0123 {
0124     struct usb_conn_info *info = dev_id;
0125 
0126     usb_conn_queue_dwork(info, info->debounce_jiffies);
0127 
0128     return IRQ_HANDLED;
0129 }
0130 
0131 static enum power_supply_property usb_charger_properties[] = {
0132     POWER_SUPPLY_PROP_ONLINE,
0133 };
0134 
0135 static int usb_charger_get_property(struct power_supply *psy,
0136                     enum power_supply_property psp,
0137                     union power_supply_propval *val)
0138 {
0139     struct usb_conn_info *info = power_supply_get_drvdata(psy);
0140 
0141     switch (psp) {
0142     case POWER_SUPPLY_PROP_ONLINE:
0143         val->intval = info->last_role == USB_ROLE_DEVICE;
0144         break;
0145     default:
0146         return -EINVAL;
0147     }
0148 
0149     return 0;
0150 }
0151 
0152 static int usb_conn_psy_register(struct usb_conn_info *info)
0153 {
0154     struct device *dev = info->dev;
0155     struct power_supply_desc *desc = &info->desc;
0156     struct power_supply_config cfg = {
0157         .of_node = dev->of_node,
0158     };
0159 
0160     desc->name = "usb-charger";
0161     desc->properties = usb_charger_properties;
0162     desc->num_properties = ARRAY_SIZE(usb_charger_properties);
0163     desc->get_property = usb_charger_get_property;
0164     desc->type = POWER_SUPPLY_TYPE_USB;
0165     cfg.drv_data = info;
0166 
0167     info->charger = devm_power_supply_register(dev, desc, &cfg);
0168     if (IS_ERR(info->charger))
0169         dev_err(dev, "Unable to register charger\n");
0170 
0171     return PTR_ERR_OR_ZERO(info->charger);
0172 }
0173 
0174 static int usb_conn_probe(struct platform_device *pdev)
0175 {
0176     struct device *dev = &pdev->dev;
0177     struct usb_conn_info *info;
0178     int ret = 0;
0179 
0180     info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
0181     if (!info)
0182         return -ENOMEM;
0183 
0184     info->dev = dev;
0185     info->id_gpiod = devm_gpiod_get_optional(dev, "id", GPIOD_IN);
0186     if (IS_ERR(info->id_gpiod))
0187         return PTR_ERR(info->id_gpiod);
0188 
0189     info->vbus_gpiod = devm_gpiod_get_optional(dev, "vbus", GPIOD_IN);
0190     if (IS_ERR(info->vbus_gpiod))
0191         return PTR_ERR(info->vbus_gpiod);
0192 
0193     if (!info->id_gpiod && !info->vbus_gpiod) {
0194         dev_err(dev, "failed to get gpios\n");
0195         return -ENODEV;
0196     }
0197 
0198     if (info->id_gpiod)
0199         ret = gpiod_set_debounce(info->id_gpiod, USB_GPIO_DEB_US);
0200     if (!ret && info->vbus_gpiod)
0201         ret = gpiod_set_debounce(info->vbus_gpiod, USB_GPIO_DEB_US);
0202     if (ret < 0)
0203         info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEB_MS);
0204 
0205     INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
0206 
0207     info->vbus = devm_regulator_get_optional(dev, "vbus");
0208     if (PTR_ERR(info->vbus) == -ENODEV)
0209         info->vbus = NULL;
0210 
0211     if (IS_ERR(info->vbus)) {
0212         ret = PTR_ERR(info->vbus);
0213         return dev_err_probe(dev, ret, "failed to get vbus :%d\n", ret);
0214     }
0215 
0216     info->role_sw = usb_role_switch_get(dev);
0217     if (IS_ERR(info->role_sw))
0218         return dev_err_probe(dev, PTR_ERR(info->role_sw),
0219                      "failed to get role switch\n");
0220 
0221     ret = usb_conn_psy_register(info);
0222     if (ret)
0223         goto put_role_sw;
0224 
0225     if (info->id_gpiod) {
0226         info->id_irq = gpiod_to_irq(info->id_gpiod);
0227         if (info->id_irq < 0) {
0228             dev_err(dev, "failed to get ID IRQ\n");
0229             ret = info->id_irq;
0230             goto put_role_sw;
0231         }
0232 
0233         ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
0234                         usb_conn_isr, USB_CONN_IRQF,
0235                         pdev->name, info);
0236         if (ret < 0) {
0237             dev_err(dev, "failed to request ID IRQ\n");
0238             goto put_role_sw;
0239         }
0240     }
0241 
0242     if (info->vbus_gpiod) {
0243         info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
0244         if (info->vbus_irq < 0) {
0245             dev_err(dev, "failed to get VBUS IRQ\n");
0246             ret = info->vbus_irq;
0247             goto put_role_sw;
0248         }
0249 
0250         ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
0251                         usb_conn_isr, USB_CONN_IRQF,
0252                         pdev->name, info);
0253         if (ret < 0) {
0254             dev_err(dev, "failed to request VBUS IRQ\n");
0255             goto put_role_sw;
0256         }
0257     }
0258 
0259     platform_set_drvdata(pdev, info);
0260     device_set_wakeup_capable(&pdev->dev, true);
0261 
0262     /* Perform initial detection */
0263     usb_conn_queue_dwork(info, 0);
0264 
0265     return 0;
0266 
0267 put_role_sw:
0268     usb_role_switch_put(info->role_sw);
0269     return ret;
0270 }
0271 
0272 static int usb_conn_remove(struct platform_device *pdev)
0273 {
0274     struct usb_conn_info *info = platform_get_drvdata(pdev);
0275 
0276     cancel_delayed_work_sync(&info->dw_det);
0277 
0278     if (info->last_role == USB_ROLE_HOST && info->vbus)
0279         regulator_disable(info->vbus);
0280 
0281     usb_role_switch_put(info->role_sw);
0282 
0283     return 0;
0284 }
0285 
0286 static int __maybe_unused usb_conn_suspend(struct device *dev)
0287 {
0288     struct usb_conn_info *info = dev_get_drvdata(dev);
0289 
0290     if (device_may_wakeup(dev)) {
0291         if (info->id_gpiod)
0292             enable_irq_wake(info->id_irq);
0293         if (info->vbus_gpiod)
0294             enable_irq_wake(info->vbus_irq);
0295         return 0;
0296     }
0297 
0298     if (info->id_gpiod)
0299         disable_irq(info->id_irq);
0300     if (info->vbus_gpiod)
0301         disable_irq(info->vbus_irq);
0302 
0303     pinctrl_pm_select_sleep_state(dev);
0304 
0305     return 0;
0306 }
0307 
0308 static int __maybe_unused usb_conn_resume(struct device *dev)
0309 {
0310     struct usb_conn_info *info = dev_get_drvdata(dev);
0311 
0312     if (device_may_wakeup(dev)) {
0313         if (info->id_gpiod)
0314             disable_irq_wake(info->id_irq);
0315         if (info->vbus_gpiod)
0316             disable_irq_wake(info->vbus_irq);
0317         return 0;
0318     }
0319 
0320     pinctrl_pm_select_default_state(dev);
0321 
0322     if (info->id_gpiod)
0323         enable_irq(info->id_irq);
0324     if (info->vbus_gpiod)
0325         enable_irq(info->vbus_irq);
0326 
0327     usb_conn_queue_dwork(info, 0);
0328 
0329     return 0;
0330 }
0331 
0332 static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
0333              usb_conn_suspend, usb_conn_resume);
0334 
0335 static const struct of_device_id usb_conn_dt_match[] = {
0336     { .compatible = "gpio-usb-b-connector", },
0337     { }
0338 };
0339 MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
0340 
0341 static struct platform_driver usb_conn_driver = {
0342     .probe      = usb_conn_probe,
0343     .remove     = usb_conn_remove,
0344     .driver     = {
0345         .name   = "usb-conn-gpio",
0346         .pm = &usb_conn_pm_ops,
0347         .of_match_table = usb_conn_dt_match,
0348     },
0349 };
0350 
0351 module_platform_driver(usb_conn_driver);
0352 
0353 MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
0354 MODULE_DESCRIPTION("USB GPIO based connection detection driver");
0355 MODULE_LICENSE("GPL v2");