diff options
Diffstat (limited to 'drivers/usb/otg/twl6030-usb.c')
-rw-r--r-- | drivers/usb/otg/twl6030-usb.c | 69 |
1 files changed, 25 insertions, 44 deletions
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index 0eabb049b6a9..a3d0c0405cca 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c | |||
@@ -26,10 +26,10 @@ | |||
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> | 28 | #include <linux/usb/otg.h> |
29 | #include <linux/usb/musb-omap.h> | ||
29 | #include <linux/i2c/twl.h> | 30 | #include <linux/i2c/twl.h> |
30 | #include <linux/regulator/consumer.h> | 31 | #include <linux/regulator/consumer.h> |
31 | #include <linux/err.h> | 32 | #include <linux/err.h> |
32 | #include <linux/notifier.h> | ||
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | 35 | ||
@@ -100,7 +100,7 @@ struct twl6030_usb { | |||
100 | 100 | ||
101 | int irq1; | 101 | int irq1; |
102 | int irq2; | 102 | int irq2; |
103 | u8 linkstat; | 103 | enum omap_musb_vbus_id_status linkstat; |
104 | u8 asleep; | 104 | u8 asleep; |
105 | bool irq_enabled; | 105 | bool irq_enabled; |
106 | bool vbus_enable; | 106 | bool vbus_enable; |
@@ -147,7 +147,7 @@ static int twl6030_phy_init(struct usb_phy *x) | |||
147 | dev = twl->dev; | 147 | dev = twl->dev; |
148 | pdata = dev->platform_data; | 148 | pdata = dev->platform_data; |
149 | 149 | ||
150 | if (twl->linkstat == USB_EVENT_ID) | 150 | if (twl->linkstat == OMAP_MUSB_ID_GROUND) |
151 | pdata->phy_power(twl->dev, 1, 1); | 151 | pdata->phy_power(twl->dev, 1, 1); |
152 | else | 152 | else |
153 | pdata->phy_power(twl->dev, 0, 1); | 153 | pdata->phy_power(twl->dev, 0, 1); |
@@ -235,13 +235,13 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev, | |||
235 | spin_lock_irqsave(&twl->lock, flags); | 235 | spin_lock_irqsave(&twl->lock, flags); |
236 | 236 | ||
237 | switch (twl->linkstat) { | 237 | switch (twl->linkstat) { |
238 | case USB_EVENT_VBUS: | 238 | case OMAP_MUSB_VBUS_VALID: |
239 | ret = snprintf(buf, PAGE_SIZE, "vbus\n"); | 239 | ret = snprintf(buf, PAGE_SIZE, "vbus\n"); |
240 | break; | 240 | break; |
241 | case USB_EVENT_ID: | 241 | case OMAP_MUSB_ID_GROUND: |
242 | ret = snprintf(buf, PAGE_SIZE, "id\n"); | 242 | ret = snprintf(buf, PAGE_SIZE, "id\n"); |
243 | break; | 243 | break; |
244 | case USB_EVENT_NONE: | 244 | case OMAP_MUSB_VBUS_OFF: |
245 | ret = snprintf(buf, PAGE_SIZE, "none\n"); | 245 | ret = snprintf(buf, PAGE_SIZE, "none\n"); |
246 | break; | 246 | break; |
247 | default: | 247 | default: |
@@ -256,8 +256,7 @@ static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL); | |||
256 | static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | 256 | static irqreturn_t twl6030_usb_irq(int irq, void *_twl) |
257 | { | 257 | { |
258 | struct twl6030_usb *twl = _twl; | 258 | struct twl6030_usb *twl = _twl; |
259 | struct usb_otg *otg = twl->phy.otg; | 259 | enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN; |
260 | int status; | ||
261 | u8 vbus_state, hw_state; | 260 | u8 vbus_state, hw_state; |
262 | 261 | ||
263 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | 262 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); |
@@ -268,22 +267,18 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | |||
268 | if (vbus_state & VBUS_DET) { | 267 | if (vbus_state & VBUS_DET) { |
269 | regulator_enable(twl->usb3v3); | 268 | regulator_enable(twl->usb3v3); |
270 | twl->asleep = 1; | 269 | twl->asleep = 1; |
271 | status = USB_EVENT_VBUS; | 270 | status = OMAP_MUSB_VBUS_VALID; |
272 | otg->default_a = false; | ||
273 | twl->phy.state = OTG_STATE_B_IDLE; | ||
274 | twl->linkstat = status; | 271 | twl->linkstat = status; |
275 | twl->phy.last_event = status; | 272 | omap_musb_mailbox(status); |
276 | atomic_notifier_call_chain(&twl->phy.notifier, | ||
277 | status, otg->gadget); | ||
278 | } else { | 273 | } else { |
279 | status = USB_EVENT_NONE; | 274 | if (twl->linkstat != OMAP_MUSB_UNKNOWN) { |
280 | twl->linkstat = status; | 275 | status = OMAP_MUSB_VBUS_OFF; |
281 | twl->phy.last_event = status; | 276 | twl->linkstat = status; |
282 | atomic_notifier_call_chain(&twl->phy.notifier, | 277 | omap_musb_mailbox(status); |
283 | status, otg->gadget); | 278 | if (twl->asleep) { |
284 | if (twl->asleep) { | 279 | regulator_disable(twl->usb3v3); |
285 | regulator_disable(twl->usb3v3); | 280 | twl->asleep = 0; |
286 | twl->asleep = 0; | 281 | } |
287 | } | 282 | } |
288 | } | 283 | } |
289 | } | 284 | } |
@@ -295,8 +290,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | |||
295 | static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | 290 | static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) |
296 | { | 291 | { |
297 | struct twl6030_usb *twl = _twl; | 292 | struct twl6030_usb *twl = _twl; |
298 | struct usb_otg *otg = twl->phy.otg; | 293 | enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN; |
299 | int status = USB_EVENT_NONE; | ||
300 | u8 hw_state; | 294 | u8 hw_state; |
301 | 295 | ||
302 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | 296 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); |
@@ -307,13 +301,11 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | |||
307 | twl->asleep = 1; | 301 | twl->asleep = 1; |
308 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR); | 302 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR); |
309 | twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); | 303 | twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); |
310 | status = USB_EVENT_ID; | 304 | status = OMAP_MUSB_ID_GROUND; |
311 | otg->default_a = true; | 305 | otg->default_a = true; |
312 | twl->phy.state = OTG_STATE_A_IDLE; | 306 | twl->phy.state = OTG_STATE_A_IDLE; |
313 | twl->linkstat = status; | 307 | twl->linkstat = status; |
314 | twl->phy.last_event = status; | 308 | omap_musb_mailbox(status); |
315 | atomic_notifier_call_chain(&twl->phy.notifier, status, | ||
316 | otg->gadget); | ||
317 | } else { | 309 | } else { |
318 | twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); | 310 | twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); |
319 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); | 311 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); |
@@ -402,20 +394,19 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
402 | struct device *dev = &pdev->dev; | 394 | struct device *dev = &pdev->dev; |
403 | pdata = dev->platform_data; | 395 | pdata = dev->platform_data; |
404 | 396 | ||
405 | twl = kzalloc(sizeof *twl, GFP_KERNEL); | 397 | twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL); |
406 | if (!twl) | 398 | if (!twl) |
407 | return -ENOMEM; | 399 | return -ENOMEM; |
408 | 400 | ||
409 | otg = kzalloc(sizeof *otg, GFP_KERNEL); | 401 | otg = devm_kzalloc(dev, sizeof *otg, GFP_KERNEL); |
410 | if (!otg) { | 402 | if (!otg) |
411 | kfree(twl); | ||
412 | return -ENOMEM; | 403 | return -ENOMEM; |
413 | } | ||
414 | 404 | ||
415 | twl->dev = &pdev->dev; | 405 | twl->dev = &pdev->dev; |
416 | twl->irq1 = platform_get_irq(pdev, 0); | 406 | twl->irq1 = platform_get_irq(pdev, 0); |
417 | twl->irq2 = platform_get_irq(pdev, 1); | 407 | twl->irq2 = platform_get_irq(pdev, 1); |
418 | twl->features = pdata->features; | 408 | twl->features = pdata->features; |
409 | twl->linkstat = OMAP_MUSB_UNKNOWN; | ||
419 | 410 | ||
420 | twl->phy.dev = twl->dev; | 411 | twl->phy.dev = twl->dev; |
421 | twl->phy.label = "twl6030"; | 412 | twl->phy.label = "twl6030"; |
@@ -436,18 +427,14 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
436 | err = twl6030_usb_ldo_init(twl); | 427 | err = twl6030_usb_ldo_init(twl); |
437 | if (err) { | 428 | if (err) { |
438 | dev_err(&pdev->dev, "ldo init failed\n"); | 429 | dev_err(&pdev->dev, "ldo init failed\n"); |
439 | kfree(otg); | ||
440 | kfree(twl); | ||
441 | return err; | 430 | return err; |
442 | } | 431 | } |
443 | usb_set_transceiver(&twl->phy); | 432 | usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2); |
444 | 433 | ||
445 | platform_set_drvdata(pdev, twl); | 434 | platform_set_drvdata(pdev, twl); |
446 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | 435 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) |
447 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | 436 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
448 | 437 | ||
449 | ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); | ||
450 | |||
451 | INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); | 438 | INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); |
452 | 439 | ||
453 | twl->irq_enabled = true; | 440 | twl->irq_enabled = true; |
@@ -458,8 +445,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
458 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | 445 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", |
459 | twl->irq1, status); | 446 | twl->irq1, status); |
460 | device_remove_file(twl->dev, &dev_attr_vbus); | 447 | device_remove_file(twl->dev, &dev_attr_vbus); |
461 | kfree(otg); | ||
462 | kfree(twl); | ||
463 | return status; | 448 | return status; |
464 | } | 449 | } |
465 | 450 | ||
@@ -471,8 +456,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
471 | twl->irq2, status); | 456 | twl->irq2, status); |
472 | free_irq(twl->irq1, twl); | 457 | free_irq(twl->irq1, twl); |
473 | device_remove_file(twl->dev, &dev_attr_vbus); | 458 | device_remove_file(twl->dev, &dev_attr_vbus); |
474 | kfree(otg); | ||
475 | kfree(twl); | ||
476 | return status; | 459 | return status; |
477 | } | 460 | } |
478 | 461 | ||
@@ -503,8 +486,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) | |||
503 | pdata->phy_exit(twl->dev); | 486 | pdata->phy_exit(twl->dev); |
504 | device_remove_file(twl->dev, &dev_attr_vbus); | 487 | device_remove_file(twl->dev, &dev_attr_vbus); |
505 | cancel_work_sync(&twl->set_vbus_work); | 488 | cancel_work_sync(&twl->set_vbus_work); |
506 | kfree(twl->phy.otg); | ||
507 | kfree(twl); | ||
508 | 489 | ||
509 | return 0; | 490 | return 0; |
510 | } | 491 | } |