aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg/twl6030-usb.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-05 18:35:41 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-05 18:35:41 -0400
commitff9cce82772a78983b529e044d85884d3ec95fda (patch)
tree6491adac0538739a415f7b776d1865ce7ae5d1f7 /drivers/usb/otg/twl6030-usb.c
parent933141509cefd64102a943d61d154c5c53bad889 (diff)
parentf8ecf829481b2cc7301a811da9d2df53ef174977 (diff)
Merge tag 'xceiv-for-v3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
usb: phy: patches for v3.6 merge window We are starting to support multiple USB phys as we should thanks for Kishon's work. DeviceTree support for USB PHYs won't come until discussion with DeviceTree maintainer is finished. Together with that series, we have one fix for twl4030 which missed a IRQF_ONESHOT annotation when requesting a threaded IRQ without a top half handler, and removal of an unused variable compilation warning to isp1301_omap.
Diffstat (limited to 'drivers/usb/otg/twl6030-usb.c')
-rw-r--r--drivers/usb/otg/twl6030-usb.c69
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);
256static irqreturn_t twl6030_usb_irq(int irq, void *_twl) 256static 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)
295static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) 290static 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}