| .. | .. |
|---|
| 7 | 7 | |
|---|
| 8 | 8 | #include <linux/kernel.h> |
|---|
| 9 | 9 | #include <linux/platform_device.h> |
|---|
| 10 | | -#include <linux/gpio.h> |
|---|
| 10 | +#include <linux/gpio/consumer.h> |
|---|
| 11 | 11 | #include <linux/module.h> |
|---|
| 12 | 12 | #include <linux/slab.h> |
|---|
| 13 | 13 | #include <linux/interrupt.h> |
|---|
| .. | .. |
|---|
| 17 | 17 | #include <linux/regulator/consumer.h> |
|---|
| 18 | 18 | |
|---|
| 19 | 19 | #include <linux/usb/gadget.h> |
|---|
| 20 | | -#include <linux/usb/gpio_vbus.h> |
|---|
| 21 | 20 | #include <linux/usb/otg.h> |
|---|
| 22 | 21 | |
|---|
| 23 | 22 | |
|---|
| .. | .. |
|---|
| 29 | 28 | * Needs to be loaded before the UDC driver that will use it. |
|---|
| 30 | 29 | */ |
|---|
| 31 | 30 | struct gpio_vbus_data { |
|---|
| 31 | + struct gpio_desc *vbus_gpiod; |
|---|
| 32 | + struct gpio_desc *pullup_gpiod; |
|---|
| 32 | 33 | struct usb_phy phy; |
|---|
| 33 | 34 | struct device *dev; |
|---|
| 34 | 35 | struct regulator *vbus_draw; |
|---|
| .. | .. |
|---|
| 83 | 84 | gpio_vbus->mA = mA; |
|---|
| 84 | 85 | } |
|---|
| 85 | 86 | |
|---|
| 86 | | -static int is_vbus_powered(struct gpio_vbus_mach_info *pdata) |
|---|
| 87 | +static int is_vbus_powered(struct gpio_vbus_data *gpio_vbus) |
|---|
| 87 | 88 | { |
|---|
| 88 | | - int vbus; |
|---|
| 89 | | - |
|---|
| 90 | | - vbus = gpio_get_value(pdata->gpio_vbus); |
|---|
| 91 | | - if (pdata->gpio_vbus_inverted) |
|---|
| 92 | | - vbus = !vbus; |
|---|
| 93 | | - |
|---|
| 94 | | - return vbus; |
|---|
| 89 | + return gpiod_get_value(gpio_vbus->vbus_gpiod); |
|---|
| 95 | 90 | } |
|---|
| 96 | 91 | |
|---|
| 97 | 92 | static void gpio_vbus_work(struct work_struct *work) |
|---|
| 98 | 93 | { |
|---|
| 99 | 94 | struct gpio_vbus_data *gpio_vbus = |
|---|
| 100 | 95 | container_of(work, struct gpio_vbus_data, work.work); |
|---|
| 101 | | - struct gpio_vbus_mach_info *pdata = dev_get_platdata(gpio_vbus->dev); |
|---|
| 102 | | - int gpio, status, vbus; |
|---|
| 96 | + int status, vbus; |
|---|
| 103 | 97 | |
|---|
| 104 | 98 | if (!gpio_vbus->phy.otg->gadget) |
|---|
| 105 | 99 | return; |
|---|
| 106 | 100 | |
|---|
| 107 | | - vbus = is_vbus_powered(pdata); |
|---|
| 101 | + vbus = is_vbus_powered(gpio_vbus); |
|---|
| 108 | 102 | if ((vbus ^ gpio_vbus->vbus) == 0) |
|---|
| 109 | 103 | return; |
|---|
| 110 | 104 | gpio_vbus->vbus = vbus; |
|---|
| 111 | 105 | |
|---|
| 112 | 106 | /* Peripheral controllers which manage the pullup themselves won't have |
|---|
| 113 | | - * gpio_pullup configured here. If it's configured here, we'll do what |
|---|
| 114 | | - * isp1301_omap::b_peripheral() does and enable the pullup here... although |
|---|
| 115 | | - * that may complicate usb_gadget_{,dis}connect() support. |
|---|
| 107 | + * a pullup GPIO configured here. If it's configured here, we'll do |
|---|
| 108 | + * what isp1301_omap::b_peripheral() does and enable the pullup here... |
|---|
| 109 | + * although that may complicate usb_gadget_{,dis}connect() support. |
|---|
| 116 | 110 | */ |
|---|
| 117 | | - gpio = pdata->gpio_pullup; |
|---|
| 118 | 111 | |
|---|
| 119 | 112 | if (vbus) { |
|---|
| 120 | 113 | status = USB_EVENT_VBUS; |
|---|
| .. | .. |
|---|
| 126 | 119 | set_vbus_draw(gpio_vbus, 100); |
|---|
| 127 | 120 | |
|---|
| 128 | 121 | /* optionally enable D+ pullup */ |
|---|
| 129 | | - if (gpio_is_valid(gpio)) |
|---|
| 130 | | - gpio_set_value(gpio, !pdata->gpio_pullup_inverted); |
|---|
| 122 | + if (gpio_vbus->pullup_gpiod) |
|---|
| 123 | + gpiod_set_value(gpio_vbus->pullup_gpiod, 1); |
|---|
| 131 | 124 | |
|---|
| 132 | 125 | atomic_notifier_call_chain(&gpio_vbus->phy.notifier, |
|---|
| 133 | 126 | status, gpio_vbus->phy.otg->gadget); |
|---|
| 134 | 127 | usb_phy_set_event(&gpio_vbus->phy, USB_EVENT_ENUMERATED); |
|---|
| 135 | 128 | } else { |
|---|
| 136 | 129 | /* optionally disable D+ pullup */ |
|---|
| 137 | | - if (gpio_is_valid(gpio)) |
|---|
| 138 | | - gpio_set_value(gpio, pdata->gpio_pullup_inverted); |
|---|
| 130 | + if (gpio_vbus->pullup_gpiod) |
|---|
| 131 | + gpiod_set_value(gpio_vbus->pullup_gpiod, 0); |
|---|
| 139 | 132 | |
|---|
| 140 | 133 | set_vbus_draw(gpio_vbus, 0); |
|---|
| 141 | 134 | |
|---|
| .. | .. |
|---|
| 154 | 147 | static irqreturn_t gpio_vbus_irq(int irq, void *data) |
|---|
| 155 | 148 | { |
|---|
| 156 | 149 | struct platform_device *pdev = data; |
|---|
| 157 | | - struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev); |
|---|
| 158 | 150 | struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); |
|---|
| 159 | 151 | struct usb_otg *otg = gpio_vbus->phy.otg; |
|---|
| 160 | 152 | |
|---|
| 161 | 153 | dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", |
|---|
| 162 | | - is_vbus_powered(pdata) ? "supplied" : "inactive", |
|---|
| 154 | + is_vbus_powered(gpio_vbus) ? "supplied" : "inactive", |
|---|
| 163 | 155 | otg->gadget ? otg->gadget->name : "none"); |
|---|
| 164 | 156 | |
|---|
| 165 | 157 | if (otg->gadget) |
|---|
| .. | .. |
|---|
| 175 | 167 | struct usb_gadget *gadget) |
|---|
| 176 | 168 | { |
|---|
| 177 | 169 | struct gpio_vbus_data *gpio_vbus; |
|---|
| 178 | | - struct gpio_vbus_mach_info *pdata; |
|---|
| 179 | 170 | struct platform_device *pdev; |
|---|
| 180 | | - int gpio; |
|---|
| 181 | 171 | |
|---|
| 182 | 172 | gpio_vbus = container_of(otg->usb_phy, struct gpio_vbus_data, phy); |
|---|
| 183 | 173 | pdev = to_platform_device(gpio_vbus->dev); |
|---|
| 184 | | - pdata = dev_get_platdata(gpio_vbus->dev); |
|---|
| 185 | | - gpio = pdata->gpio_pullup; |
|---|
| 186 | 174 | |
|---|
| 187 | 175 | if (!gadget) { |
|---|
| 188 | 176 | dev_dbg(&pdev->dev, "unregistering gadget '%s'\n", |
|---|
| 189 | 177 | otg->gadget->name); |
|---|
| 190 | 178 | |
|---|
| 191 | 179 | /* optionally disable D+ pullup */ |
|---|
| 192 | | - if (gpio_is_valid(gpio)) |
|---|
| 193 | | - gpio_set_value(gpio, pdata->gpio_pullup_inverted); |
|---|
| 180 | + if (gpio_vbus->pullup_gpiod) |
|---|
| 181 | + gpiod_set_value(gpio_vbus->pullup_gpiod, 0); |
|---|
| 194 | 182 | |
|---|
| 195 | 183 | set_vbus_draw(gpio_vbus, 0); |
|---|
| 196 | 184 | |
|---|
| .. | .. |
|---|
| 242 | 230 | |
|---|
| 243 | 231 | static int gpio_vbus_probe(struct platform_device *pdev) |
|---|
| 244 | 232 | { |
|---|
| 245 | | - struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev); |
|---|
| 246 | 233 | struct gpio_vbus_data *gpio_vbus; |
|---|
| 247 | 234 | struct resource *res; |
|---|
| 248 | | - int err, gpio, irq; |
|---|
| 235 | + struct device *dev = &pdev->dev; |
|---|
| 236 | + int err, irq; |
|---|
| 249 | 237 | unsigned long irqflags; |
|---|
| 250 | | - |
|---|
| 251 | | - if (!pdata || !gpio_is_valid(pdata->gpio_vbus)) |
|---|
| 252 | | - return -EINVAL; |
|---|
| 253 | | - gpio = pdata->gpio_vbus; |
|---|
| 254 | 238 | |
|---|
| 255 | 239 | gpio_vbus = devm_kzalloc(&pdev->dev, sizeof(struct gpio_vbus_data), |
|---|
| 256 | 240 | GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 273 | 257 | gpio_vbus->phy.otg->usb_phy = &gpio_vbus->phy; |
|---|
| 274 | 258 | gpio_vbus->phy.otg->set_peripheral = gpio_vbus_set_peripheral; |
|---|
| 275 | 259 | |
|---|
| 276 | | - err = devm_gpio_request(&pdev->dev, gpio, "vbus_detect"); |
|---|
| 277 | | - if (err) { |
|---|
| 278 | | - dev_err(&pdev->dev, "can't request vbus gpio %d, err: %d\n", |
|---|
| 279 | | - gpio, err); |
|---|
| 260 | + /* Look up the VBUS sensing GPIO */ |
|---|
| 261 | + gpio_vbus->vbus_gpiod = devm_gpiod_get(dev, "vbus", GPIOD_IN); |
|---|
| 262 | + if (IS_ERR(gpio_vbus->vbus_gpiod)) { |
|---|
| 263 | + err = PTR_ERR(gpio_vbus->vbus_gpiod); |
|---|
| 264 | + dev_err(&pdev->dev, "can't request vbus gpio, err: %d\n", err); |
|---|
| 280 | 265 | return err; |
|---|
| 281 | 266 | } |
|---|
| 282 | | - gpio_direction_input(gpio); |
|---|
| 267 | + gpiod_set_consumer_name(gpio_vbus->vbus_gpiod, "vbus_detect"); |
|---|
| 283 | 268 | |
|---|
| 284 | 269 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
|---|
| 285 | 270 | if (res) { |
|---|
| 286 | 271 | irq = res->start; |
|---|
| 287 | 272 | irqflags = (res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED; |
|---|
| 288 | 273 | } else { |
|---|
| 289 | | - irq = gpio_to_irq(gpio); |
|---|
| 274 | + irq = gpiod_to_irq(gpio_vbus->vbus_gpiod); |
|---|
| 290 | 275 | irqflags = VBUS_IRQ_FLAGS; |
|---|
| 291 | 276 | } |
|---|
| 292 | 277 | |
|---|
| 293 | 278 | gpio_vbus->irq = irq; |
|---|
| 294 | 279 | |
|---|
| 295 | | - /* if data line pullup is in use, initialize it to "not pulling up" */ |
|---|
| 296 | | - gpio = pdata->gpio_pullup; |
|---|
| 297 | | - if (gpio_is_valid(gpio)) { |
|---|
| 298 | | - err = devm_gpio_request(&pdev->dev, gpio, "udc_pullup"); |
|---|
| 299 | | - if (err) { |
|---|
| 300 | | - dev_err(&pdev->dev, |
|---|
| 301 | | - "can't request pullup gpio %d, err: %d\n", |
|---|
| 302 | | - gpio, err); |
|---|
| 303 | | - return err; |
|---|
| 304 | | - } |
|---|
| 305 | | - gpio_direction_output(gpio, pdata->gpio_pullup_inverted); |
|---|
| 280 | + /* |
|---|
| 281 | + * The VBUS sensing GPIO should have a pulldown, which will normally be |
|---|
| 282 | + * part of a resistor ladder turning a 4.0V-5.25V level on VBUS into a |
|---|
| 283 | + * value the GPIO detects as active. Some systems will use comparators. |
|---|
| 284 | + * Get the optional D+ or D- pullup GPIO. If the data line pullup is |
|---|
| 285 | + * in use, initialize it to "not pulling up" |
|---|
| 286 | + */ |
|---|
| 287 | + gpio_vbus->pullup_gpiod = devm_gpiod_get_optional(dev, "pullup", |
|---|
| 288 | + GPIOD_OUT_LOW); |
|---|
| 289 | + if (IS_ERR(gpio_vbus->pullup_gpiod)) { |
|---|
| 290 | + err = PTR_ERR(gpio_vbus->pullup_gpiod); |
|---|
| 291 | + dev_err(&pdev->dev, "can't request pullup gpio, err: %d\n", |
|---|
| 292 | + err); |
|---|
| 293 | + return err; |
|---|
| 306 | 294 | } |
|---|
| 295 | + if (gpio_vbus->pullup_gpiod) |
|---|
| 296 | + gpiod_set_consumer_name(gpio_vbus->pullup_gpiod, "udc_pullup"); |
|---|
| 307 | 297 | |
|---|
| 308 | 298 | err = devm_request_irq(&pdev->dev, irq, gpio_vbus_irq, irqflags, |
|---|
| 309 | 299 | "vbus_detect", pdev); |
|---|
| .. | .. |
|---|
| 330 | 320 | return err; |
|---|
| 331 | 321 | } |
|---|
| 332 | 322 | |
|---|
| 333 | | - device_init_wakeup(&pdev->dev, pdata->wakeup); |
|---|
| 323 | + /* TODO: wakeup could be enabled here with device_init_wakeup(dev, 1) */ |
|---|
| 334 | 324 | |
|---|
| 335 | 325 | return 0; |
|---|
| 336 | 326 | } |
|---|