diff options
author | Kishon Vijay Abraham I <kishon@ti.com> | 2012-09-06 10:57:07 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-09-06 13:15:59 -0400 |
commit | 0e98de67bacba812b1b465b90a3f940d24401c27 (patch) | |
tree | c30e6cd16ac5f3d33a696f50304c6538cc20e121 /drivers/usb/otg | |
parent | 657b306a7bdfca4ae1514b533a0e7c3c6d26dbc6 (diff) |
usb: otg: make twl6030_usb as a comparator driver to omap_usb2
All the PHY configuration other than VBUS, ID GND and OTG SRP are removed
from twl6030. The phy configurations are taken care by the dedicated
usb2 phy driver. So twl6030 is made as comparator driver for VBUS and
ID detection.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/otg')
-rw-r--r-- | drivers/usb/otg/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/otg/twl6030-usb.c | 118 |
2 files changed, 19 insertions, 101 deletions
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 13fd1ddf742f..d8c8a42bff3e 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
@@ -68,7 +68,7 @@ config TWL4030_USB | |||
68 | 68 | ||
69 | config TWL6030_USB | 69 | config TWL6030_USB |
70 | tristate "TWL6030 USB Transceiver Driver" | 70 | tristate "TWL6030 USB Transceiver Driver" |
71 | depends on TWL4030_CORE | 71 | depends on TWL4030_CORE && OMAP_USB2 |
72 | select USB_OTG_UTILS | 72 | select USB_OTG_UTILS |
73 | help | 73 | help |
74 | Enable this to support the USB OTG transceiver on TWL6030 | 74 | Enable this to support the USB OTG transceiver on TWL6030 |
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index 6907d8df7a27..32525bb667ee 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 */ |
@@ -107,7 +108,7 @@ struct twl6030_usb { | |||
107 | unsigned long features; | 108 | unsigned long features; |
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); |
@@ -313,23 +273,8 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | |||
313 | return IRQ_HANDLED; | 273 | return IRQ_HANDLED; |
314 | } | 274 | } |
315 | 275 | ||
316 | static int twl6030_set_peripheral(struct usb_otg *otg, | 276 | static int twl6030_enable_irq(struct twl6030_usb *twl) |
317 | struct usb_gadget *gadget) | ||
318 | { | 277 | { |
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 | { | ||
331 | struct twl6030_usb *twl = phy_to_twl(x); | ||
332 | |||
333 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); | 278 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); |
334 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); | 279 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); |
335 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C); | 280 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C); |
@@ -362,9 +307,9 @@ static void otg_set_vbus_work(struct work_struct *data) | |||
362 | CHARGERUSB_CTRL1); | 307 | CHARGERUSB_CTRL1); |
363 | } | 308 | } |
364 | 309 | ||
365 | static int twl6030_set_vbus(struct usb_otg *otg, bool enabled) | 310 | static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled) |
366 | { | 311 | { |
367 | struct twl6030_usb *twl = phy_to_twl(otg->phy); | 312 | struct twl6030_usb *twl = comparator_to_twl(comparator); |
368 | 313 | ||
369 | twl->vbus_enable = enabled; | 314 | twl->vbus_enable = enabled; |
370 | schedule_work(&twl->set_vbus_work); | 315 | schedule_work(&twl->set_vbus_work); |
@@ -372,23 +317,12 @@ static int twl6030_set_vbus(struct usb_otg *otg, bool enabled) | |||
372 | return 0; | 317 | return 0; |
373 | } | 318 | } |
374 | 319 | ||
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) | 320 | static int __devinit twl6030_usb_probe(struct platform_device *pdev) |
387 | { | 321 | { |
322 | u32 ret; | ||
388 | struct twl6030_usb *twl; | 323 | struct twl6030_usb *twl; |
389 | int status, err; | 324 | int status, err; |
390 | struct twl4030_usb_data *pdata; | 325 | struct twl4030_usb_data *pdata; |
391 | struct usb_otg *otg; | ||
392 | struct device *dev = &pdev->dev; | 326 | struct device *dev = &pdev->dev; |
393 | pdata = dev->platform_data; | 327 | pdata = dev->platform_data; |
394 | 328 | ||
@@ -396,28 +330,20 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
396 | if (!twl) | 330 | if (!twl) |
397 | return -ENOMEM; | 331 | return -ENOMEM; |
398 | 332 | ||
399 | otg = devm_kzalloc(dev, sizeof *otg, GFP_KERNEL); | ||
400 | if (!otg) | ||
401 | return -ENOMEM; | ||
402 | |||
403 | twl->dev = &pdev->dev; | 333 | twl->dev = &pdev->dev; |
404 | twl->irq1 = platform_get_irq(pdev, 0); | 334 | twl->irq1 = platform_get_irq(pdev, 0); |
405 | twl->irq2 = platform_get_irq(pdev, 1); | 335 | twl->irq2 = platform_get_irq(pdev, 1); |
406 | twl->features = pdata->features; | 336 | twl->features = pdata->features; |
407 | twl->linkstat = OMAP_MUSB_UNKNOWN; | 337 | twl->linkstat = OMAP_MUSB_UNKNOWN; |
408 | 338 | ||
409 | twl->phy.dev = twl->dev; | 339 | twl->comparator.set_vbus = twl6030_set_vbus; |
410 | twl->phy.label = "twl6030"; | 340 | twl->comparator.start_srp = twl6030_start_srp; |
411 | twl->phy.otg = otg; | ||
412 | twl->phy.init = twl6030_phy_init; | ||
413 | twl->phy.shutdown = twl6030_phy_shutdown; | ||
414 | twl->phy.set_suspend = twl6030_phy_suspend; | ||
415 | 341 | ||
416 | otg->phy = &twl->phy; | 342 | ret = omap_usb2_set_comparator(&twl->comparator); |
417 | otg->set_host = twl6030_set_host; | 343 | if (ret == -ENODEV) { |
418 | otg->set_peripheral = twl6030_set_peripheral; | 344 | dev_info(&pdev->dev, "phy not ready, deferring probe"); |
419 | otg->set_vbus = twl6030_set_vbus; | 345 | return -EPROBE_DEFER; |
420 | otg->start_srp = twl6030_start_srp; | 346 | } |
421 | 347 | ||
422 | /* init spinlock for workqueue */ | 348 | /* init spinlock for workqueue */ |
423 | spin_lock_init(&twl->lock); | 349 | spin_lock_init(&twl->lock); |
@@ -427,7 +353,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
427 | dev_err(&pdev->dev, "ldo init failed\n"); | 353 | dev_err(&pdev->dev, "ldo init failed\n"); |
428 | return err; | 354 | return err; |
429 | } | 355 | } |
430 | usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2); | ||
431 | 356 | ||
432 | platform_set_drvdata(pdev, twl); | 357 | platform_set_drvdata(pdev, twl); |
433 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | 358 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) |
@@ -458,9 +383,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
458 | } | 383 | } |
459 | 384 | ||
460 | twl->asleep = 0; | 385 | twl->asleep = 0; |
461 | pdata->phy_init(dev); | 386 | 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"); | 387 | dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); |
465 | 388 | ||
466 | return 0; | 389 | return 0; |
@@ -470,10 +393,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) | |||
470 | { | 393 | { |
471 | struct twl6030_usb *twl = platform_get_drvdata(pdev); | 394 | struct twl6030_usb *twl = platform_get_drvdata(pdev); |
472 | 395 | ||
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, | 396 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, |
478 | REG_INT_MSK_LINE_C); | 397 | REG_INT_MSK_LINE_C); |
479 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, | 398 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, |
@@ -481,7 +400,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) | |||
481 | free_irq(twl->irq1, twl); | 400 | free_irq(twl->irq1, twl); |
482 | free_irq(twl->irq2, twl); | 401 | free_irq(twl->irq2, twl); |
483 | regulator_put(twl->usb3v3); | 402 | regulator_put(twl->usb3v3); |
484 | pdata->phy_exit(twl->dev); | ||
485 | device_remove_file(twl->dev, &dev_attr_vbus); | 403 | device_remove_file(twl->dev, &dev_attr_vbus); |
486 | cancel_work_sync(&twl->set_vbus_work); | 404 | cancel_work_sync(&twl->set_vbus_work); |
487 | 405 | ||