Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * gpio-vbus.c - simple GPIO VBUS sensing driver for B peripheral devices
0004  *
0005  * Copyright (c) 2008 Philipp Zabel <philipp.zabel@gmail.com>
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/gpio/consumer.h>
0011 #include <linux/module.h>
0012 #include <linux/slab.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/usb.h>
0015 #include <linux/workqueue.h>
0016 
0017 #include <linux/regulator/consumer.h>
0018 
0019 #include <linux/usb/gadget.h>
0020 #include <linux/usb/otg.h>
0021 
0022 
0023 /*
0024  * A simple GPIO VBUS sensing driver for B peripheral only devices
0025  * with internal transceivers. It can control a D+ pullup GPIO and
0026  * a regulator to limit the current drawn from VBUS.
0027  *
0028  * Needs to be loaded before the UDC driver that will use it.
0029  */
0030 struct gpio_vbus_data {
0031     struct gpio_desc    *vbus_gpiod;
0032     struct gpio_desc    *pullup_gpiod;
0033     struct usb_phy      phy;
0034     struct device          *dev;
0035     struct regulator       *vbus_draw;
0036     int         vbus_draw_enabled;
0037     unsigned        mA;
0038     struct delayed_work work;
0039     int         vbus;
0040     int         irq;
0041 };
0042 
0043 
0044 /*
0045  * This driver relies on "both edges" triggering.  VBUS has 100 msec to
0046  * stabilize, so the peripheral controller driver may need to cope with
0047  * some bouncing due to current surges (e.g. charging local capacitance)
0048  * and contact chatter.
0049  *
0050  * REVISIT in desperate straits, toggling between rising and falling
0051  * edges might be workable.
0052  */
0053 #define VBUS_IRQ_FLAGS \
0054     (IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)
0055 
0056 
0057 /* interface to regulator framework */
0058 static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)
0059 {
0060     struct regulator *vbus_draw = gpio_vbus->vbus_draw;
0061     int enabled;
0062     int ret;
0063 
0064     if (!vbus_draw)
0065         return;
0066 
0067     enabled = gpio_vbus->vbus_draw_enabled;
0068     if (mA) {
0069         regulator_set_current_limit(vbus_draw, 0, 1000 * mA);
0070         if (!enabled) {
0071             ret = regulator_enable(vbus_draw);
0072             if (ret < 0)
0073                 return;
0074             gpio_vbus->vbus_draw_enabled = 1;
0075         }
0076     } else {
0077         if (enabled) {
0078             ret = regulator_disable(vbus_draw);
0079             if (ret < 0)
0080                 return;
0081             gpio_vbus->vbus_draw_enabled = 0;
0082         }
0083     }
0084     gpio_vbus->mA = mA;
0085 }
0086 
0087 static int is_vbus_powered(struct gpio_vbus_data *gpio_vbus)
0088 {
0089     return gpiod_get_value(gpio_vbus->vbus_gpiod);
0090 }
0091 
0092 static void gpio_vbus_work(struct work_struct *work)
0093 {
0094     struct gpio_vbus_data *gpio_vbus =
0095         container_of(work, struct gpio_vbus_data, work.work);
0096     int status, vbus;
0097 
0098     if (!gpio_vbus->phy.otg->gadget)
0099         return;
0100 
0101     vbus = is_vbus_powered(gpio_vbus);
0102     if ((vbus ^ gpio_vbus->vbus) == 0)
0103         return;
0104     gpio_vbus->vbus = vbus;
0105 
0106     /* Peripheral controllers which manage the pullup themselves won't have
0107      * a pullup GPIO configured here.  If it's configured here, we'll do
0108      * what isp1301_omap::b_peripheral() does and enable the pullup here...
0109      * although that may complicate usb_gadget_{,dis}connect() support.
0110      */
0111 
0112     if (vbus) {
0113         status = USB_EVENT_VBUS;
0114         gpio_vbus->phy.otg->state = OTG_STATE_B_PERIPHERAL;
0115         gpio_vbus->phy.last_event = status;
0116         usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget);
0117 
0118         /* drawing a "unit load" is *always* OK, except for OTG */
0119         set_vbus_draw(gpio_vbus, 100);
0120 
0121         /* optionally enable D+ pullup */
0122         if (gpio_vbus->pullup_gpiod)
0123             gpiod_set_value(gpio_vbus->pullup_gpiod, 1);
0124 
0125         atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
0126                        status, gpio_vbus->phy.otg->gadget);
0127         usb_phy_set_event(&gpio_vbus->phy, USB_EVENT_ENUMERATED);
0128     } else {
0129         /* optionally disable D+ pullup */
0130         if (gpio_vbus->pullup_gpiod)
0131             gpiod_set_value(gpio_vbus->pullup_gpiod, 0);
0132 
0133         set_vbus_draw(gpio_vbus, 0);
0134 
0135         usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget);
0136         status = USB_EVENT_NONE;
0137         gpio_vbus->phy.otg->state = OTG_STATE_B_IDLE;
0138         gpio_vbus->phy.last_event = status;
0139 
0140         atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
0141                        status, gpio_vbus->phy.otg->gadget);
0142         usb_phy_set_event(&gpio_vbus->phy, USB_EVENT_NONE);
0143     }
0144 }
0145 
0146 /* VBUS change IRQ handler */
0147 static irqreturn_t gpio_vbus_irq(int irq, void *data)
0148 {
0149     struct platform_device *pdev = data;
0150     struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
0151     struct usb_otg *otg = gpio_vbus->phy.otg;
0152 
0153     dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n",
0154         is_vbus_powered(gpio_vbus) ? "supplied" : "inactive",
0155         otg->gadget ? otg->gadget->name : "none");
0156 
0157     if (otg->gadget)
0158         schedule_delayed_work(&gpio_vbus->work, msecs_to_jiffies(100));
0159 
0160     return IRQ_HANDLED;
0161 }
0162 
0163 /* OTG transceiver interface */
0164 
0165 /* bind/unbind the peripheral controller */
0166 static int gpio_vbus_set_peripheral(struct usb_otg *otg,
0167                     struct usb_gadget *gadget)
0168 {
0169     struct gpio_vbus_data *gpio_vbus;
0170     struct platform_device *pdev;
0171 
0172     gpio_vbus = container_of(otg->usb_phy, struct gpio_vbus_data, phy);
0173     pdev = to_platform_device(gpio_vbus->dev);
0174 
0175     if (!gadget) {
0176         dev_dbg(&pdev->dev, "unregistering gadget '%s'\n",
0177             otg->gadget->name);
0178 
0179         /* optionally disable D+ pullup */
0180         if (gpio_vbus->pullup_gpiod)
0181             gpiod_set_value(gpio_vbus->pullup_gpiod, 0);
0182 
0183         set_vbus_draw(gpio_vbus, 0);
0184 
0185         usb_gadget_vbus_disconnect(otg->gadget);
0186         otg->state = OTG_STATE_UNDEFINED;
0187 
0188         otg->gadget = NULL;
0189         return 0;
0190     }
0191 
0192     otg->gadget = gadget;
0193     dev_dbg(&pdev->dev, "registered gadget '%s'\n", gadget->name);
0194 
0195     /* initialize connection state */
0196     gpio_vbus->vbus = 0; /* start with disconnected */
0197     gpio_vbus_irq(gpio_vbus->irq, pdev);
0198     return 0;
0199 }
0200 
0201 /* effective for B devices, ignored for A-peripheral */
0202 static int gpio_vbus_set_power(struct usb_phy *phy, unsigned mA)
0203 {
0204     struct gpio_vbus_data *gpio_vbus;
0205 
0206     gpio_vbus = container_of(phy, struct gpio_vbus_data, phy);
0207 
0208     if (phy->otg->state == OTG_STATE_B_PERIPHERAL)
0209         set_vbus_draw(gpio_vbus, mA);
0210     return 0;
0211 }
0212 
0213 /* for non-OTG B devices: set/clear transceiver suspend mode */
0214 static int gpio_vbus_set_suspend(struct usb_phy *phy, int suspend)
0215 {
0216     struct gpio_vbus_data *gpio_vbus;
0217 
0218     gpio_vbus = container_of(phy, struct gpio_vbus_data, phy);
0219 
0220     /* draw max 0 mA from vbus in suspend mode; or the previously
0221      * recorded amount of current if not suspended
0222      *
0223      * NOTE: high powered configs (mA > 100) may draw up to 2.5 mA
0224      * if they're wake-enabled ... we don't handle that yet.
0225      */
0226     return gpio_vbus_set_power(phy, suspend ? 0 : gpio_vbus->mA);
0227 }
0228 
0229 /* platform driver interface */
0230 
0231 static int gpio_vbus_probe(struct platform_device *pdev)
0232 {
0233     struct gpio_vbus_data *gpio_vbus;
0234     struct resource *res;
0235     struct device *dev = &pdev->dev;
0236     int err, irq;
0237     unsigned long irqflags;
0238 
0239     gpio_vbus = devm_kzalloc(&pdev->dev, sizeof(struct gpio_vbus_data),
0240                  GFP_KERNEL);
0241     if (!gpio_vbus)
0242         return -ENOMEM;
0243 
0244     gpio_vbus->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
0245                       GFP_KERNEL);
0246     if (!gpio_vbus->phy.otg)
0247         return -ENOMEM;
0248 
0249     platform_set_drvdata(pdev, gpio_vbus);
0250     gpio_vbus->dev = &pdev->dev;
0251     gpio_vbus->phy.label = "gpio-vbus";
0252     gpio_vbus->phy.dev = gpio_vbus->dev;
0253     gpio_vbus->phy.set_power = gpio_vbus_set_power;
0254     gpio_vbus->phy.set_suspend = gpio_vbus_set_suspend;
0255 
0256     gpio_vbus->phy.otg->state = OTG_STATE_UNDEFINED;
0257     gpio_vbus->phy.otg->usb_phy = &gpio_vbus->phy;
0258     gpio_vbus->phy.otg->set_peripheral = gpio_vbus_set_peripheral;
0259 
0260     /* Look up the VBUS sensing GPIO */
0261     gpio_vbus->vbus_gpiod = devm_gpiod_get(dev, "vbus", GPIOD_IN);
0262     if (IS_ERR(gpio_vbus->vbus_gpiod)) {
0263         err = PTR_ERR(gpio_vbus->vbus_gpiod);
0264         dev_err(&pdev->dev, "can't request vbus gpio, err: %d\n", err);
0265         return err;
0266     }
0267     gpiod_set_consumer_name(gpio_vbus->vbus_gpiod, "vbus_detect");
0268 
0269     res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
0270     if (res) {
0271         irq = res->start;
0272         irqflags = (res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
0273     } else {
0274         irq = gpiod_to_irq(gpio_vbus->vbus_gpiod);
0275         irqflags = VBUS_IRQ_FLAGS;
0276     }
0277 
0278     gpio_vbus->irq = irq;
0279 
0280     /*
0281      * The VBUS sensing GPIO should have a pulldown, which will normally be
0282      * part of a resistor ladder turning a 4.0V-5.25V level on VBUS into a
0283      * value the GPIO detects as active. Some systems will use comparators.
0284      * Get the optional D+ or D- pullup GPIO. If the data line pullup is
0285      * in use, initialize it to "not pulling up"
0286      */
0287     gpio_vbus->pullup_gpiod = devm_gpiod_get_optional(dev, "pullup",
0288                               GPIOD_OUT_LOW);
0289     if (IS_ERR(gpio_vbus->pullup_gpiod)) {
0290         err = PTR_ERR(gpio_vbus->pullup_gpiod);
0291         dev_err(&pdev->dev, "can't request pullup gpio, err: %d\n",
0292             err);
0293         return err;
0294     }
0295     if (gpio_vbus->pullup_gpiod)
0296         gpiod_set_consumer_name(gpio_vbus->pullup_gpiod, "udc_pullup");
0297 
0298     err = devm_request_irq(&pdev->dev, irq, gpio_vbus_irq, irqflags,
0299                    "vbus_detect", pdev);
0300     if (err) {
0301         dev_err(&pdev->dev, "can't request irq %i, err: %d\n",
0302             irq, err);
0303         return err;
0304     }
0305 
0306     INIT_DELAYED_WORK(&gpio_vbus->work, gpio_vbus_work);
0307 
0308     gpio_vbus->vbus_draw = devm_regulator_get(&pdev->dev, "vbus_draw");
0309     if (IS_ERR(gpio_vbus->vbus_draw)) {
0310         dev_dbg(&pdev->dev, "can't get vbus_draw regulator, err: %ld\n",
0311             PTR_ERR(gpio_vbus->vbus_draw));
0312         gpio_vbus->vbus_draw = NULL;
0313     }
0314 
0315     /* only active when a gadget is registered */
0316     err = usb_add_phy(&gpio_vbus->phy, USB_PHY_TYPE_USB2);
0317     if (err) {
0318         dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
0319             err);
0320         return err;
0321     }
0322 
0323     /* TODO: wakeup could be enabled here with device_init_wakeup(dev, 1) */
0324 
0325     return 0;
0326 }
0327 
0328 static int gpio_vbus_remove(struct platform_device *pdev)
0329 {
0330     struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
0331 
0332     device_init_wakeup(&pdev->dev, 0);
0333     cancel_delayed_work_sync(&gpio_vbus->work);
0334 
0335     usb_remove_phy(&gpio_vbus->phy);
0336 
0337     return 0;
0338 }
0339 
0340 #ifdef CONFIG_PM
0341 static int gpio_vbus_pm_suspend(struct device *dev)
0342 {
0343     struct gpio_vbus_data *gpio_vbus = dev_get_drvdata(dev);
0344 
0345     if (device_may_wakeup(dev))
0346         enable_irq_wake(gpio_vbus->irq);
0347 
0348     return 0;
0349 }
0350 
0351 static int gpio_vbus_pm_resume(struct device *dev)
0352 {
0353     struct gpio_vbus_data *gpio_vbus = dev_get_drvdata(dev);
0354 
0355     if (device_may_wakeup(dev))
0356         disable_irq_wake(gpio_vbus->irq);
0357 
0358     return 0;
0359 }
0360 
0361 static const struct dev_pm_ops gpio_vbus_dev_pm_ops = {
0362     .suspend    = gpio_vbus_pm_suspend,
0363     .resume     = gpio_vbus_pm_resume,
0364 };
0365 #endif
0366 
0367 MODULE_ALIAS("platform:gpio-vbus");
0368 
0369 static struct platform_driver gpio_vbus_driver = {
0370     .driver = {
0371         .name  = "gpio-vbus",
0372 #ifdef CONFIG_PM
0373         .pm = &gpio_vbus_dev_pm_ops,
0374 #endif
0375     },
0376     .probe      = gpio_vbus_probe,
0377     .remove     = gpio_vbus_remove,
0378 };
0379 
0380 module_platform_driver(gpio_vbus_driver);
0381 
0382 MODULE_DESCRIPTION("simple GPIO controlled OTG transceiver driver");
0383 MODULE_AUTHOR("Philipp Zabel");
0384 MODULE_LICENSE("GPL");