aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg/twl6030-usb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 16:23:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 16:23:01 -0400
commitd9a807461fc8cc0d6ba589ea0730d139122af012 (patch)
tree9d8c7a044659d821748dd40718a22557c04e4299 /drivers/usb/otg/twl6030-usb.c
parent3498d13b8090c0b0ef911409fbc503a7c4cca6ef (diff)
parent70c048a238c780c226eb4b115ebaa908cb3b34ec (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.c157
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
89struct twl6030_usb { 90struct 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
140static int twl6030_phy_init(struct usb_phy *x) 141static 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
158static 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
170static 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
181static 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
194static int twl6030_usb_ldo_init(struct twl6030_usb *twl) 154static 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
316static int twl6030_set_peripheral(struct usb_otg *otg, 269static 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
329static 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
365static int twl6030_set_vbus(struct usb_otg *otg, bool enabled) 303static 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
375static 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
386static int __devinit twl6030_usb_probe(struct platform_device *pdev) 313static 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
414static const struct of_device_id twl6030_usb_id_table[] = {
415 { .compatible = "ti,twl6030-usb" },
416 {}
417};
418MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
419#endif
420
491static struct platform_driver twl6030_usb_driver = { 421static 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