diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 16:23:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 16:23:01 -0400 |
commit | d9a807461fc8cc0d6ba589ea0730d139122af012 (patch) | |
tree | 9d8c7a044659d821748dd40718a22557c04e4299 /drivers/usb/otg/twl6030-usb.c | |
parent | 3498d13b8090c0b0ef911409fbc503a7c4cca6ef (diff) | |
parent | 70c048a238c780c226eb4b115ebaa908cb3b34ec (diff) |
Merge tag 'usb-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB changes from Greg Kroah-Hartman:
"Here is the big USB pull request for 3.7-rc1
There are lots of gadget driver changes (including copying a bunch of
files into the drivers/staging/ccg/ directory so that the other gadget
drivers can be fixed up properly without breaking that driver), and we
remove the old obsolete ub.c driver from the tree.
There are also the usual XHCI set of updates, and other various driver
changes and updates. We also are trying hard to remove the old dbg()
macro, but the final bits of that removal will be coming in through
the networking tree before we can delete it for good.
All of these patches have been in the linux-next tree.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
Fix up several annoying - but fairly mindless - conflicts due to the
termios structure having moved into the tty device, and often clashing
with dbg -> dev_dbg conversion.
* tag 'usb-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (339 commits)
USB: ezusb: move ezusb.c from drivers/usb/serial to drivers/usb/misc
USB: uas: fix gcc warning
USB: uas: fix locking
USB: Fix race condition when removing host controllers
USB: uas: add locking
USB: uas: fix abort
USB: uas: remove aborted field, replace with status bit.
USB: uas: fix task management
USB: uas: keep track of command urbs
xhci: Intel Panther Point BEI quirk.
powerpc/usb: remove checking PHY_CLK_VALID for UTMI PHY
USB: ftdi_sio: add TIAO USB Multi-Protocol Adapter (TUMPA) support
Revert "usb : Add sysfs files to control port power."
USB: serial: remove vizzini driver
usb: host: xhci: Fix Null pointer dereferencing with 71c731a for non-x86 systems
Increase XHCI suspend timeout to 16ms
USB: ohci-at91: fix null pointer in ohci_hcd_at91_overcurrent_irq
USB: sierra_ms: don't keep unused variable
fsl/usb: Add support for USB controller version 2.4
USB: qcaux: add Pantech vendor class match
...
Diffstat (limited to 'drivers/usb/otg/twl6030-usb.c')
-rw-r--r-- | drivers/usb/otg/twl6030-usb.c | 157 |
1 files changed, 44 insertions, 113 deletions
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index 6907d8df7a27..fcadef7864f1 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c | |||
@@ -25,8 +25,9 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/usb/otg.h> | ||
29 | #include <linux/usb/musb-omap.h> | 28 | #include <linux/usb/musb-omap.h> |
29 | #include <linux/usb/phy_companion.h> | ||
30 | #include <linux/usb/omap_usb.h> | ||
30 | #include <linux/i2c/twl.h> | 31 | #include <linux/i2c/twl.h> |
31 | #include <linux/regulator/consumer.h> | 32 | #include <linux/regulator/consumer.h> |
32 | #include <linux/err.h> | 33 | #include <linux/err.h> |
@@ -87,7 +88,7 @@ | |||
87 | #define VBUS_DET BIT(2) | 88 | #define VBUS_DET BIT(2) |
88 | 89 | ||
89 | struct twl6030_usb { | 90 | struct twl6030_usb { |
90 | struct usb_phy phy; | 91 | struct phy_companion comparator; |
91 | struct device *dev; | 92 | struct device *dev; |
92 | 93 | ||
93 | /* for vbus reporting with irqs disabled */ | 94 | /* for vbus reporting with irqs disabled */ |
@@ -104,10 +105,10 @@ struct twl6030_usb { | |||
104 | u8 asleep; | 105 | u8 asleep; |
105 | bool irq_enabled; | 106 | bool irq_enabled; |
106 | bool vbus_enable; | 107 | bool vbus_enable; |
107 | unsigned long features; | 108 | const char *regulator; |
108 | }; | 109 | }; |
109 | 110 | ||
110 | #define phy_to_twl(x) container_of((x), struct twl6030_usb, phy) | 111 | #define comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator) |
111 | 112 | ||
112 | /*-------------------------------------------------------------------------*/ | 113 | /*-------------------------------------------------------------------------*/ |
113 | 114 | ||
@@ -137,50 +138,9 @@ static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address) | |||
137 | return ret; | 138 | return ret; |
138 | } | 139 | } |
139 | 140 | ||
140 | static int twl6030_phy_init(struct usb_phy *x) | 141 | static int twl6030_start_srp(struct phy_companion *comparator) |
141 | { | 142 | { |
142 | struct twl6030_usb *twl; | 143 | struct twl6030_usb *twl = comparator_to_twl(comparator); |
143 | struct device *dev; | ||
144 | struct twl4030_usb_data *pdata; | ||
145 | |||
146 | twl = phy_to_twl(x); | ||
147 | dev = twl->dev; | ||
148 | pdata = dev->platform_data; | ||
149 | |||
150 | if (twl->linkstat == OMAP_MUSB_ID_GROUND) | ||
151 | pdata->phy_power(twl->dev, 1, 1); | ||
152 | else | ||
153 | pdata->phy_power(twl->dev, 0, 1); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static void twl6030_phy_shutdown(struct usb_phy *x) | ||
159 | { | ||
160 | struct twl6030_usb *twl; | ||
161 | struct device *dev; | ||
162 | struct twl4030_usb_data *pdata; | ||
163 | |||
164 | twl = phy_to_twl(x); | ||
165 | dev = twl->dev; | ||
166 | pdata = dev->platform_data; | ||
167 | pdata->phy_power(twl->dev, 0, 0); | ||
168 | } | ||
169 | |||
170 | static int twl6030_phy_suspend(struct usb_phy *x, int suspend) | ||
171 | { | ||
172 | struct twl6030_usb *twl = phy_to_twl(x); | ||
173 | struct device *dev = twl->dev; | ||
174 | struct twl4030_usb_data *pdata = dev->platform_data; | ||
175 | |||
176 | pdata->phy_suspend(dev, suspend); | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static int twl6030_start_srp(struct usb_otg *otg) | ||
182 | { | ||
183 | struct twl6030_usb *twl = phy_to_twl(otg->phy); | ||
184 | 144 | ||
185 | twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET); | 145 | twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET); |
186 | twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET); | 146 | twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET); |
@@ -193,13 +153,6 @@ static int twl6030_start_srp(struct usb_otg *otg) | |||
193 | 153 | ||
194 | static int twl6030_usb_ldo_init(struct twl6030_usb *twl) | 154 | static int twl6030_usb_ldo_init(struct twl6030_usb *twl) |
195 | { | 155 | { |
196 | char *regulator_name; | ||
197 | |||
198 | if (twl->features & TWL6025_SUBCLASS) | ||
199 | regulator_name = "ldousb"; | ||
200 | else | ||
201 | regulator_name = "vusb"; | ||
202 | |||
203 | /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ | 156 | /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ |
204 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG); | 157 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG); |
205 | 158 | ||
@@ -209,7 +162,7 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl) | |||
209 | /* Program MISC2 register and set bit VUSB_IN_VBAT */ | 162 | /* Program MISC2 register and set bit VUSB_IN_VBAT */ |
210 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2); | 163 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2); |
211 | 164 | ||
212 | twl->usb3v3 = regulator_get(twl->dev, regulator_name); | 165 | twl->usb3v3 = regulator_get(twl->dev, twl->regulator); |
213 | if (IS_ERR(twl->usb3v3)) | 166 | if (IS_ERR(twl->usb3v3)) |
214 | return -ENODEV; | 167 | return -ENODEV; |
215 | 168 | ||
@@ -313,23 +266,8 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | |||
313 | return IRQ_HANDLED; | 266 | return IRQ_HANDLED; |
314 | } | 267 | } |
315 | 268 | ||
316 | static int twl6030_set_peripheral(struct usb_otg *otg, | 269 | static int twl6030_enable_irq(struct twl6030_usb *twl) |
317 | struct usb_gadget *gadget) | ||
318 | { | ||
319 | if (!otg) | ||
320 | return -ENODEV; | ||
321 | |||
322 | otg->gadget = gadget; | ||
323 | if (!gadget) | ||
324 | otg->phy->state = OTG_STATE_UNDEFINED; | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static int twl6030_enable_irq(struct usb_phy *x) | ||
330 | { | 270 | { |
331 | struct twl6030_usb *twl = phy_to_twl(x); | ||
332 | |||
333 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); | 271 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); |
334 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); | 272 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); |
335 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C); | 273 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C); |
@@ -362,9 +300,9 @@ static void otg_set_vbus_work(struct work_struct *data) | |||
362 | CHARGERUSB_CTRL1); | 300 | CHARGERUSB_CTRL1); |
363 | } | 301 | } |
364 | 302 | ||
365 | static int twl6030_set_vbus(struct usb_otg *otg, bool enabled) | 303 | static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled) |
366 | { | 304 | { |
367 | struct twl6030_usb *twl = phy_to_twl(otg->phy); | 305 | struct twl6030_usb *twl = comparator_to_twl(comparator); |
368 | 306 | ||
369 | twl->vbus_enable = enabled; | 307 | twl->vbus_enable = enabled; |
370 | schedule_work(&twl->set_vbus_work); | 308 | schedule_work(&twl->set_vbus_work); |
@@ -372,52 +310,44 @@ static int twl6030_set_vbus(struct usb_otg *otg, bool enabled) | |||
372 | return 0; | 310 | return 0; |
373 | } | 311 | } |
374 | 312 | ||
375 | static int twl6030_set_host(struct usb_otg *otg, struct usb_bus *host) | ||
376 | { | ||
377 | if (!otg) | ||
378 | return -ENODEV; | ||
379 | |||
380 | otg->host = host; | ||
381 | if (!host) | ||
382 | otg->phy->state = OTG_STATE_UNDEFINED; | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static int __devinit twl6030_usb_probe(struct platform_device *pdev) | 313 | static int __devinit twl6030_usb_probe(struct platform_device *pdev) |
387 | { | 314 | { |
315 | u32 ret; | ||
388 | struct twl6030_usb *twl; | 316 | struct twl6030_usb *twl; |
389 | int status, err; | 317 | int status, err; |
390 | struct twl4030_usb_data *pdata; | 318 | struct device_node *np = pdev->dev.of_node; |
391 | struct usb_otg *otg; | 319 | struct device *dev = &pdev->dev; |
392 | struct device *dev = &pdev->dev; | 320 | struct twl4030_usb_data *pdata = dev->platform_data; |
393 | pdata = dev->platform_data; | ||
394 | 321 | ||
395 | twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL); | 322 | twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL); |
396 | if (!twl) | 323 | if (!twl) |
397 | return -ENOMEM; | 324 | return -ENOMEM; |
398 | 325 | ||
399 | otg = devm_kzalloc(dev, sizeof *otg, GFP_KERNEL); | ||
400 | if (!otg) | ||
401 | return -ENOMEM; | ||
402 | |||
403 | twl->dev = &pdev->dev; | 326 | twl->dev = &pdev->dev; |
404 | twl->irq1 = platform_get_irq(pdev, 0); | 327 | twl->irq1 = platform_get_irq(pdev, 0); |
405 | twl->irq2 = platform_get_irq(pdev, 1); | 328 | twl->irq2 = platform_get_irq(pdev, 1); |
406 | twl->features = pdata->features; | ||
407 | twl->linkstat = OMAP_MUSB_UNKNOWN; | 329 | twl->linkstat = OMAP_MUSB_UNKNOWN; |
408 | 330 | ||
409 | twl->phy.dev = twl->dev; | 331 | twl->comparator.set_vbus = twl6030_set_vbus; |
410 | twl->phy.label = "twl6030"; | 332 | twl->comparator.start_srp = twl6030_start_srp; |
411 | twl->phy.otg = otg; | 333 | |
412 | twl->phy.init = twl6030_phy_init; | 334 | ret = omap_usb2_set_comparator(&twl->comparator); |
413 | twl->phy.shutdown = twl6030_phy_shutdown; | 335 | if (ret == -ENODEV) { |
414 | twl->phy.set_suspend = twl6030_phy_suspend; | 336 | dev_info(&pdev->dev, "phy not ready, deferring probe"); |
337 | return -EPROBE_DEFER; | ||
338 | } | ||
415 | 339 | ||
416 | otg->phy = &twl->phy; | 340 | if (np) { |
417 | otg->set_host = twl6030_set_host; | 341 | twl->regulator = "usb"; |
418 | otg->set_peripheral = twl6030_set_peripheral; | 342 | } else if (pdata) { |
419 | otg->set_vbus = twl6030_set_vbus; | 343 | if (pdata->features & TWL6025_SUBCLASS) |
420 | otg->start_srp = twl6030_start_srp; | 344 | twl->regulator = "ldousb"; |
345 | else | ||
346 | twl->regulator = "vusb"; | ||
347 | } else { | ||
348 | dev_err(&pdev->dev, "twl6030 initialized without pdata\n"); | ||
349 | return -EINVAL; | ||
350 | } | ||
421 | 351 | ||
422 | /* init spinlock for workqueue */ | 352 | /* init spinlock for workqueue */ |
423 | spin_lock_init(&twl->lock); | 353 | spin_lock_init(&twl->lock); |
@@ -427,7 +357,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
427 | dev_err(&pdev->dev, "ldo init failed\n"); | 357 | dev_err(&pdev->dev, "ldo init failed\n"); |
428 | return err; | 358 | return err; |
429 | } | 359 | } |
430 | usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2); | ||
431 | 360 | ||
432 | platform_set_drvdata(pdev, twl); | 361 | platform_set_drvdata(pdev, twl); |
433 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | 362 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) |
@@ -458,9 +387,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
458 | } | 387 | } |
459 | 388 | ||
460 | twl->asleep = 0; | 389 | twl->asleep = 0; |
461 | pdata->phy_init(dev); | 390 | twl6030_enable_irq(twl); |
462 | twl6030_phy_suspend(&twl->phy, 0); | ||
463 | twl6030_enable_irq(&twl->phy); | ||
464 | dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); | 391 | dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); |
465 | 392 | ||
466 | return 0; | 393 | return 0; |
@@ -470,10 +397,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) | |||
470 | { | 397 | { |
471 | struct twl6030_usb *twl = platform_get_drvdata(pdev); | 398 | struct twl6030_usb *twl = platform_get_drvdata(pdev); |
472 | 399 | ||
473 | struct twl4030_usb_data *pdata; | ||
474 | struct device *dev = &pdev->dev; | ||
475 | pdata = dev->platform_data; | ||
476 | |||
477 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, | 400 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, |
478 | REG_INT_MSK_LINE_C); | 401 | REG_INT_MSK_LINE_C); |
479 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, | 402 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, |
@@ -481,19 +404,27 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) | |||
481 | free_irq(twl->irq1, twl); | 404 | free_irq(twl->irq1, twl); |
482 | free_irq(twl->irq2, twl); | 405 | free_irq(twl->irq2, twl); |
483 | regulator_put(twl->usb3v3); | 406 | regulator_put(twl->usb3v3); |
484 | pdata->phy_exit(twl->dev); | ||
485 | device_remove_file(twl->dev, &dev_attr_vbus); | 407 | device_remove_file(twl->dev, &dev_attr_vbus); |
486 | cancel_work_sync(&twl->set_vbus_work); | 408 | cancel_work_sync(&twl->set_vbus_work); |
487 | 409 | ||
488 | return 0; | 410 | return 0; |
489 | } | 411 | } |
490 | 412 | ||
413 | #ifdef CONFIG_OF | ||
414 | static const struct of_device_id twl6030_usb_id_table[] = { | ||
415 | { .compatible = "ti,twl6030-usb" }, | ||
416 | {} | ||
417 | }; | ||
418 | MODULE_DEVICE_TABLE(of, twl6030_usb_id_table); | ||
419 | #endif | ||
420 | |||
491 | static struct platform_driver twl6030_usb_driver = { | 421 | static struct platform_driver twl6030_usb_driver = { |
492 | .probe = twl6030_usb_probe, | 422 | .probe = twl6030_usb_probe, |
493 | .remove = __exit_p(twl6030_usb_remove), | 423 | .remove = __exit_p(twl6030_usb_remove), |
494 | .driver = { | 424 | .driver = { |
495 | .name = "twl6030_usb", | 425 | .name = "twl6030_usb", |
496 | .owner = THIS_MODULE, | 426 | .owner = THIS_MODULE, |
427 | .of_match_table = of_match_ptr(twl6030_usb_id_table), | ||
497 | }, | 428 | }, |
498 | }; | 429 | }; |
499 | 430 | ||