diff options
Diffstat (limited to 'drivers/usb/otg/twl6030-usb.c')
-rw-r--r-- | drivers/usb/otg/twl6030-usb.c | 119 |
1 files changed, 65 insertions, 54 deletions
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index ed2b26cfe814..e3fa387ca81e 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c | |||
@@ -87,7 +87,7 @@ | |||
87 | #define VBUS_DET BIT(2) | 87 | #define VBUS_DET BIT(2) |
88 | 88 | ||
89 | struct twl6030_usb { | 89 | struct twl6030_usb { |
90 | struct otg_transceiver otg; | 90 | struct usb_phy phy; |
91 | struct device *dev; | 91 | struct device *dev; |
92 | 92 | ||
93 | /* for vbus reporting with irqs disabled */ | 93 | /* for vbus reporting with irqs disabled */ |
@@ -107,7 +107,7 @@ struct twl6030_usb { | |||
107 | unsigned long features; | 107 | unsigned long features; |
108 | }; | 108 | }; |
109 | 109 | ||
110 | #define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg) | 110 | #define phy_to_twl(x) container_of((x), struct twl6030_usb, phy) |
111 | 111 | ||
112 | /*-------------------------------------------------------------------------*/ | 112 | /*-------------------------------------------------------------------------*/ |
113 | 113 | ||
@@ -137,13 +137,13 @@ static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address) | |||
137 | return ret; | 137 | return ret; |
138 | } | 138 | } |
139 | 139 | ||
140 | static int twl6030_phy_init(struct otg_transceiver *x) | 140 | static int twl6030_phy_init(struct usb_phy *x) |
141 | { | 141 | { |
142 | struct twl6030_usb *twl; | 142 | struct twl6030_usb *twl; |
143 | struct device *dev; | 143 | struct device *dev; |
144 | struct twl4030_usb_data *pdata; | 144 | struct twl4030_usb_data *pdata; |
145 | 145 | ||
146 | twl = xceiv_to_twl(x); | 146 | twl = phy_to_twl(x); |
147 | dev = twl->dev; | 147 | dev = twl->dev; |
148 | pdata = dev->platform_data; | 148 | pdata = dev->platform_data; |
149 | 149 | ||
@@ -155,21 +155,21 @@ static int twl6030_phy_init(struct otg_transceiver *x) | |||
155 | return 0; | 155 | return 0; |
156 | } | 156 | } |
157 | 157 | ||
158 | static void twl6030_phy_shutdown(struct otg_transceiver *x) | 158 | static void twl6030_phy_shutdown(struct usb_phy *x) |
159 | { | 159 | { |
160 | struct twl6030_usb *twl; | 160 | struct twl6030_usb *twl; |
161 | struct device *dev; | 161 | struct device *dev; |
162 | struct twl4030_usb_data *pdata; | 162 | struct twl4030_usb_data *pdata; |
163 | 163 | ||
164 | twl = xceiv_to_twl(x); | 164 | twl = phy_to_twl(x); |
165 | dev = twl->dev; | 165 | dev = twl->dev; |
166 | pdata = dev->platform_data; | 166 | pdata = dev->platform_data; |
167 | pdata->phy_power(twl->dev, 0, 0); | 167 | pdata->phy_power(twl->dev, 0, 0); |
168 | } | 168 | } |
169 | 169 | ||
170 | static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend) | 170 | static int twl6030_phy_suspend(struct usb_phy *x, int suspend) |
171 | { | 171 | { |
172 | struct twl6030_usb *twl = xceiv_to_twl(x); | 172 | struct twl6030_usb *twl = phy_to_twl(x); |
173 | struct device *dev = twl->dev; | 173 | struct device *dev = twl->dev; |
174 | struct twl4030_usb_data *pdata = dev->platform_data; | 174 | struct twl4030_usb_data *pdata = dev->platform_data; |
175 | 175 | ||
@@ -178,9 +178,9 @@ static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend) | |||
178 | return 0; | 178 | return 0; |
179 | } | 179 | } |
180 | 180 | ||
181 | static int twl6030_start_srp(struct otg_transceiver *x) | 181 | static int twl6030_start_srp(struct usb_otg *otg) |
182 | { | 182 | { |
183 | struct twl6030_usb *twl = xceiv_to_twl(x); | 183 | struct twl6030_usb *twl = phy_to_twl(otg->phy); |
184 | 184 | ||
185 | twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET); | 185 | twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET); |
186 | twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET); | 186 | twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET); |
@@ -256,6 +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 | int status; | 260 | int status; |
260 | u8 vbus_state, hw_state; | 261 | u8 vbus_state, hw_state; |
261 | 262 | ||
@@ -268,18 +269,18 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | |||
268 | regulator_enable(twl->usb3v3); | 269 | regulator_enable(twl->usb3v3); |
269 | twl->asleep = 1; | 270 | twl->asleep = 1; |
270 | status = USB_EVENT_VBUS; | 271 | status = USB_EVENT_VBUS; |
271 | twl->otg.default_a = false; | 272 | otg->default_a = false; |
272 | twl->otg.state = OTG_STATE_B_IDLE; | 273 | twl->phy.state = OTG_STATE_B_IDLE; |
273 | twl->linkstat = status; | 274 | twl->linkstat = status; |
274 | twl->otg.last_event = status; | 275 | twl->phy.last_event = status; |
275 | atomic_notifier_call_chain(&twl->otg.notifier, | 276 | atomic_notifier_call_chain(&twl->phy.notifier, |
276 | status, twl->otg.gadget); | 277 | status, otg->gadget); |
277 | } else { | 278 | } else { |
278 | status = USB_EVENT_NONE; | 279 | status = USB_EVENT_NONE; |
279 | twl->linkstat = status; | 280 | twl->linkstat = status; |
280 | twl->otg.last_event = status; | 281 | twl->phy.last_event = status; |
281 | atomic_notifier_call_chain(&twl->otg.notifier, | 282 | atomic_notifier_call_chain(&twl->phy.notifier, |
282 | status, twl->otg.gadget); | 283 | status, otg->gadget); |
283 | if (twl->asleep) { | 284 | if (twl->asleep) { |
284 | regulator_disable(twl->usb3v3); | 285 | regulator_disable(twl->usb3v3); |
285 | twl->asleep = 0; | 286 | twl->asleep = 0; |
@@ -294,6 +295,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | |||
294 | static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | 295 | static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) |
295 | { | 296 | { |
296 | struct twl6030_usb *twl = _twl; | 297 | struct twl6030_usb *twl = _twl; |
298 | struct usb_otg *otg = twl->phy.otg; | ||
297 | int status = USB_EVENT_NONE; | 299 | int status = USB_EVENT_NONE; |
298 | u8 hw_state; | 300 | u8 hw_state; |
299 | 301 | ||
@@ -307,12 +309,12 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | |||
307 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, | 309 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, |
308 | 0x10); | 310 | 0x10); |
309 | status = USB_EVENT_ID; | 311 | status = USB_EVENT_ID; |
310 | twl->otg.default_a = true; | 312 | otg->default_a = true; |
311 | twl->otg.state = OTG_STATE_A_IDLE; | 313 | twl->phy.state = OTG_STATE_A_IDLE; |
312 | twl->linkstat = status; | 314 | twl->linkstat = status; |
313 | twl->otg.last_event = status; | 315 | twl->phy.last_event = status; |
314 | atomic_notifier_call_chain(&twl->otg.notifier, status, | 316 | atomic_notifier_call_chain(&twl->phy.notifier, status, |
315 | twl->otg.gadget); | 317 | otg->gadget); |
316 | } else { | 318 | } else { |
317 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, | 319 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, |
318 | 0x10); | 320 | 0x10); |
@@ -324,25 +326,22 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | |||
324 | return IRQ_HANDLED; | 326 | return IRQ_HANDLED; |
325 | } | 327 | } |
326 | 328 | ||
327 | static int twl6030_set_peripheral(struct otg_transceiver *x, | 329 | static int twl6030_set_peripheral(struct usb_otg *otg, |
328 | struct usb_gadget *gadget) | 330 | struct usb_gadget *gadget) |
329 | { | 331 | { |
330 | struct twl6030_usb *twl; | 332 | if (!otg) |
331 | |||
332 | if (!x) | ||
333 | return -ENODEV; | 333 | return -ENODEV; |
334 | 334 | ||
335 | twl = xceiv_to_twl(x); | 335 | otg->gadget = gadget; |
336 | twl->otg.gadget = gadget; | ||
337 | if (!gadget) | 336 | if (!gadget) |
338 | twl->otg.state = OTG_STATE_UNDEFINED; | 337 | otg->phy->state = OTG_STATE_UNDEFINED; |
339 | 338 | ||
340 | return 0; | 339 | return 0; |
341 | } | 340 | } |
342 | 341 | ||
343 | static int twl6030_enable_irq(struct otg_transceiver *x) | 342 | static int twl6030_enable_irq(struct usb_phy *x) |
344 | { | 343 | { |
345 | struct twl6030_usb *twl = xceiv_to_twl(x); | 344 | struct twl6030_usb *twl = phy_to_twl(x); |
346 | 345 | ||
347 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1); | 346 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1); |
348 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); | 347 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); |
@@ -376,9 +375,9 @@ static void otg_set_vbus_work(struct work_struct *data) | |||
376 | CHARGERUSB_CTRL1); | 375 | CHARGERUSB_CTRL1); |
377 | } | 376 | } |
378 | 377 | ||
379 | static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) | 378 | static int twl6030_set_vbus(struct usb_otg *otg, bool enabled) |
380 | { | 379 | { |
381 | struct twl6030_usb *twl = xceiv_to_twl(x); | 380 | struct twl6030_usb *twl = phy_to_twl(otg->phy); |
382 | 381 | ||
383 | twl->vbus_enable = enabled; | 382 | twl->vbus_enable = enabled; |
384 | schedule_work(&twl->set_vbus_work); | 383 | schedule_work(&twl->set_vbus_work); |
@@ -386,17 +385,14 @@ static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) | |||
386 | return 0; | 385 | return 0; |
387 | } | 386 | } |
388 | 387 | ||
389 | static int twl6030_set_host(struct otg_transceiver *x, struct usb_bus *host) | 388 | static int twl6030_set_host(struct usb_otg *otg, struct usb_bus *host) |
390 | { | 389 | { |
391 | struct twl6030_usb *twl; | 390 | if (!otg) |
392 | |||
393 | if (!x) | ||
394 | return -ENODEV; | 391 | return -ENODEV; |
395 | 392 | ||
396 | twl = xceiv_to_twl(x); | 393 | otg->host = host; |
397 | twl->otg.host = host; | ||
398 | if (!host) | 394 | if (!host) |
399 | twl->otg.state = OTG_STATE_UNDEFINED; | 395 | otg->phy->state = OTG_STATE_UNDEFINED; |
400 | return 0; | 396 | return 0; |
401 | } | 397 | } |
402 | 398 | ||
@@ -405,6 +401,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
405 | struct twl6030_usb *twl; | 401 | struct twl6030_usb *twl; |
406 | int status, err; | 402 | int status, err; |
407 | struct twl4030_usb_data *pdata; | 403 | struct twl4030_usb_data *pdata; |
404 | struct usb_otg *otg; | ||
408 | struct device *dev = &pdev->dev; | 405 | struct device *dev = &pdev->dev; |
409 | pdata = dev->platform_data; | 406 | pdata = dev->platform_data; |
410 | 407 | ||
@@ -412,19 +409,29 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
412 | if (!twl) | 409 | if (!twl) |
413 | return -ENOMEM; | 410 | return -ENOMEM; |
414 | 411 | ||
412 | otg = kzalloc(sizeof *otg, GFP_KERNEL); | ||
413 | if (!otg) { | ||
414 | kfree(twl); | ||
415 | return -ENOMEM; | ||
416 | } | ||
417 | |||
415 | twl->dev = &pdev->dev; | 418 | twl->dev = &pdev->dev; |
416 | twl->irq1 = platform_get_irq(pdev, 0); | 419 | twl->irq1 = platform_get_irq(pdev, 0); |
417 | twl->irq2 = platform_get_irq(pdev, 1); | 420 | twl->irq2 = platform_get_irq(pdev, 1); |
418 | twl->features = pdata->features; | 421 | twl->features = pdata->features; |
419 | twl->otg.dev = twl->dev; | 422 | |
420 | twl->otg.label = "twl6030"; | 423 | twl->phy.dev = twl->dev; |
421 | twl->otg.set_host = twl6030_set_host; | 424 | twl->phy.label = "twl6030"; |
422 | twl->otg.set_peripheral = twl6030_set_peripheral; | 425 | twl->phy.otg = otg; |
423 | twl->otg.set_vbus = twl6030_set_vbus; | 426 | twl->phy.init = twl6030_phy_init; |
424 | twl->otg.init = twl6030_phy_init; | 427 | twl->phy.shutdown = twl6030_phy_shutdown; |
425 | twl->otg.shutdown = twl6030_phy_shutdown; | 428 | twl->phy.set_suspend = twl6030_phy_suspend; |
426 | twl->otg.set_suspend = twl6030_phy_suspend; | 429 | |
427 | twl->otg.start_srp = twl6030_start_srp; | 430 | otg->phy = &twl->phy; |
431 | otg->set_host = twl6030_set_host; | ||
432 | otg->set_peripheral = twl6030_set_peripheral; | ||
433 | otg->set_vbus = twl6030_set_vbus; | ||
434 | otg->start_srp = twl6030_start_srp; | ||
428 | 435 | ||
429 | /* init spinlock for workqueue */ | 436 | /* init spinlock for workqueue */ |
430 | spin_lock_init(&twl->lock); | 437 | spin_lock_init(&twl->lock); |
@@ -432,16 +439,17 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
432 | err = twl6030_usb_ldo_init(twl); | 439 | err = twl6030_usb_ldo_init(twl); |
433 | if (err) { | 440 | if (err) { |
434 | dev_err(&pdev->dev, "ldo init failed\n"); | 441 | dev_err(&pdev->dev, "ldo init failed\n"); |
442 | kfree(otg); | ||
435 | kfree(twl); | 443 | kfree(twl); |
436 | return err; | 444 | return err; |
437 | } | 445 | } |
438 | otg_set_transceiver(&twl->otg); | 446 | usb_set_transceiver(&twl->phy); |
439 | 447 | ||
440 | platform_set_drvdata(pdev, twl); | 448 | platform_set_drvdata(pdev, twl); |
441 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | 449 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) |
442 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | 450 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
443 | 451 | ||
444 | ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier); | 452 | ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); |
445 | 453 | ||
446 | INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); | 454 | INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); |
447 | 455 | ||
@@ -453,6 +461,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
453 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | 461 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", |
454 | twl->irq1, status); | 462 | twl->irq1, status); |
455 | device_remove_file(twl->dev, &dev_attr_vbus); | 463 | device_remove_file(twl->dev, &dev_attr_vbus); |
464 | kfree(otg); | ||
456 | kfree(twl); | 465 | kfree(twl); |
457 | return status; | 466 | return status; |
458 | } | 467 | } |
@@ -465,14 +474,15 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
465 | twl->irq2, status); | 474 | twl->irq2, status); |
466 | free_irq(twl->irq1, twl); | 475 | free_irq(twl->irq1, twl); |
467 | device_remove_file(twl->dev, &dev_attr_vbus); | 476 | device_remove_file(twl->dev, &dev_attr_vbus); |
477 | kfree(otg); | ||
468 | kfree(twl); | 478 | kfree(twl); |
469 | return status; | 479 | return status; |
470 | } | 480 | } |
471 | 481 | ||
472 | twl->asleep = 0; | 482 | twl->asleep = 0; |
473 | pdata->phy_init(dev); | 483 | pdata->phy_init(dev); |
474 | twl6030_phy_suspend(&twl->otg, 0); | 484 | twl6030_phy_suspend(&twl->phy, 0); |
475 | twl6030_enable_irq(&twl->otg); | 485 | twl6030_enable_irq(&twl->phy); |
476 | dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); | 486 | dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); |
477 | 487 | ||
478 | return 0; | 488 | return 0; |
@@ -496,6 +506,7 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) | |||
496 | pdata->phy_exit(twl->dev); | 506 | pdata->phy_exit(twl->dev); |
497 | device_remove_file(twl->dev, &dev_attr_vbus); | 507 | device_remove_file(twl->dev, &dev_attr_vbus); |
498 | cancel_work_sync(&twl->set_vbus_work); | 508 | cancel_work_sync(&twl->set_vbus_work); |
509 | kfree(twl->phy.otg); | ||
499 | kfree(twl); | 510 | kfree(twl); |
500 | 511 | ||
501 | return 0; | 512 | return 0; |