aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg
diff options
context:
space:
mode:
authorKishon Vijay Abraham I <kishon@ti.com>2012-06-22 08:10:52 -0400
committerFelipe Balbi <balbi@ti.com>2012-06-25 07:07:39 -0400
commitc9721438c009adf8e81d376839ed037c53b9b8d9 (patch)
tree3144ac8f042bd8366352e03eab530de3f9676f00 /drivers/usb/otg
parent1e5acb8d6113a0f159257845e153d5b870ca618a (diff)
usb: musb: twl: use mailbox API to send VBUS or ID events
The atomic notifier from twl4030/twl6030 to notifiy VBUS and ID events, is replaced by a direct call to omap musb blue. 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/twl4030-usb.c46
-rw-r--r--drivers/usb/otg/twl6030-usb.c47
2 files changed, 44 insertions, 49 deletions
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 25a09fabbe35..a7b809e217ea 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -33,11 +33,11 @@
33#include <linux/io.h> 33#include <linux/io.h>
34#include <linux/delay.h> 34#include <linux/delay.h>
35#include <linux/usb/otg.h> 35#include <linux/usb/otg.h>
36#include <linux/usb/musb-omap.h>
36#include <linux/usb/ulpi.h> 37#include <linux/usb/ulpi.h>
37#include <linux/i2c/twl.h> 38#include <linux/i2c/twl.h>
38#include <linux/regulator/consumer.h> 39#include <linux/regulator/consumer.h>
39#include <linux/err.h> 40#include <linux/err.h>
40#include <linux/notifier.h>
41#include <linux/slab.h> 41#include <linux/slab.h>
42 42
43/* Register defines */ 43/* Register defines */
@@ -159,7 +159,7 @@ struct twl4030_usb {
159 enum twl4030_usb_mode usb_mode; 159 enum twl4030_usb_mode usb_mode;
160 160
161 int irq; 161 int irq;
162 u8 linkstat; 162 enum omap_musb_vbus_id_status linkstat;
163 bool vbus_supplied; 163 bool vbus_supplied;
164 u8 asleep; 164 u8 asleep;
165 bool irq_enabled; 165 bool irq_enabled;
@@ -246,10 +246,11 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
246 246
247/*-------------------------------------------------------------------------*/ 247/*-------------------------------------------------------------------------*/
248 248
249static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) 249static enum omap_musb_vbus_id_status
250 twl4030_usb_linkstat(struct twl4030_usb *twl)
250{ 251{
251 int status; 252 int status;
252 int linkstat = USB_EVENT_NONE; 253 enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN;
253 struct usb_otg *otg = twl->phy.otg; 254 struct usb_otg *otg = twl->phy.otg;
254 255
255 twl->vbus_supplied = false; 256 twl->vbus_supplied = false;
@@ -273,24 +274,24 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
273 twl->vbus_supplied = true; 274 twl->vbus_supplied = true;
274 275
275 if (status & BIT(2)) 276 if (status & BIT(2))
276 linkstat = USB_EVENT_ID; 277 linkstat = OMAP_MUSB_ID_GROUND;
277 else 278 else
278 linkstat = USB_EVENT_VBUS; 279 linkstat = OMAP_MUSB_VBUS_VALID;
279 } else 280 } else {
280 linkstat = USB_EVENT_NONE; 281 if (twl->linkstat != OMAP_MUSB_UNKNOWN)
282 linkstat = OMAP_MUSB_VBUS_OFF;
283 }
281 284
282 dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", 285 dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
283 status, status, linkstat); 286 status, status, linkstat);
284 287
285 twl->phy.last_event = linkstat;
286
287 /* REVISIT this assumes host and peripheral controllers 288 /* REVISIT this assumes host and peripheral controllers
288 * are registered, and that both are active... 289 * are registered, and that both are active...
289 */ 290 */
290 291
291 spin_lock_irq(&twl->lock); 292 spin_lock_irq(&twl->lock);
292 twl->linkstat = linkstat; 293 twl->linkstat = linkstat;
293 if (linkstat == USB_EVENT_ID) { 294 if (linkstat == OMAP_MUSB_ID_GROUND) {
294 otg->default_a = true; 295 otg->default_a = true;
295 twl->phy.state = OTG_STATE_A_IDLE; 296 twl->phy.state = OTG_STATE_A_IDLE;
296 } else { 297 } else {
@@ -501,10 +502,10 @@ static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
501static irqreturn_t twl4030_usb_irq(int irq, void *_twl) 502static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
502{ 503{
503 struct twl4030_usb *twl = _twl; 504 struct twl4030_usb *twl = _twl;
504 int status; 505 enum omap_musb_vbus_id_status status;
505 506
506 status = twl4030_usb_linkstat(twl); 507 status = twl4030_usb_linkstat(twl);
507 if (status >= 0) { 508 if (status > 0) {
508 /* FIXME add a set_power() method so that B-devices can 509 /* FIXME add a set_power() method so that B-devices can
509 * configure the charger appropriately. It's not always 510 * configure the charger appropriately. It's not always
510 * correct to consume VBUS power, and how much current to 511 * correct to consume VBUS power, and how much current to
@@ -516,13 +517,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
516 * USB_LINK_VBUS state. musb_hdrc won't care until it 517 * USB_LINK_VBUS state. musb_hdrc won't care until it
517 * starts to handle softconnect right. 518 * starts to handle softconnect right.
518 */ 519 */
519 if (status == USB_EVENT_NONE) 520 if (status == OMAP_MUSB_VBUS_OFF ||
521 status == OMAP_MUSB_ID_FLOAT)
520 twl4030_phy_suspend(twl, 0); 522 twl4030_phy_suspend(twl, 0);
521 else 523 else
522 twl4030_phy_resume(twl); 524 twl4030_phy_resume(twl);
523 525
524 atomic_notifier_call_chain(&twl->phy.notifier, status, 526 omap_musb_mailbox(twl->linkstat);
525 twl->phy.otg->gadget);
526 } 527 }
527 sysfs_notify(&twl->dev->kobj, NULL, "vbus"); 528 sysfs_notify(&twl->dev->kobj, NULL, "vbus");
528 529
@@ -531,11 +532,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
531 532
532static void twl4030_usb_phy_init(struct twl4030_usb *twl) 533static void twl4030_usb_phy_init(struct twl4030_usb *twl)
533{ 534{
534 int status; 535 enum omap_musb_vbus_id_status status;
535 536
536 status = twl4030_usb_linkstat(twl); 537 status = twl4030_usb_linkstat(twl);
537 if (status >= 0) { 538 if (status > 0) {
538 if (status == USB_EVENT_NONE) { 539 if (status == OMAP_MUSB_VBUS_OFF ||
540 status == OMAP_MUSB_ID_FLOAT) {
539 __twl4030_phy_power(twl, 0); 541 __twl4030_phy_power(twl, 0);
540 twl->asleep = 1; 542 twl->asleep = 1;
541 } else { 543 } else {
@@ -543,8 +545,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl)
543 twl->asleep = 0; 545 twl->asleep = 0;
544 } 546 }
545 547
546 atomic_notifier_call_chain(&twl->phy.notifier, status, 548 omap_musb_mailbox(twl->linkstat);
547 twl->phy.otg->gadget);
548 } 549 }
549 sysfs_notify(&twl->dev->kobj, NULL, "vbus"); 550 sysfs_notify(&twl->dev->kobj, NULL, "vbus");
550} 551}
@@ -613,6 +614,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
613 twl->usb_mode = pdata->usb_mode; 614 twl->usb_mode = pdata->usb_mode;
614 twl->vbus_supplied = false; 615 twl->vbus_supplied = false;
615 twl->asleep = 1; 616 twl->asleep = 1;
617 twl->linkstat = OMAP_MUSB_UNKNOWN;
616 618
617 twl->phy.dev = twl->dev; 619 twl->phy.dev = twl->dev;
618 twl->phy.label = "twl4030"; 620 twl->phy.label = "twl4030";
@@ -639,8 +641,6 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
639 if (device_create_file(&pdev->dev, &dev_attr_vbus)) 641 if (device_create_file(&pdev->dev, &dev_attr_vbus))
640 dev_warn(&pdev->dev, "could not create sysfs file\n"); 642 dev_warn(&pdev->dev, "could not create sysfs file\n");
641 643
642 ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
643
644 /* Our job is to use irqs and status from the power module 644 /* Our job is to use irqs and status from the power module
645 * to keep the transceiver disabled when nothing's connected. 645 * to keep the transceiver disabled when nothing's connected.
646 * 646 *
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index dbee00aea755..6c758836cfb1 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:
@@ -257,7 +257,7 @@ 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 struct usb_otg *otg = twl->phy.otg;
260 int status; 260 enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
261 u8 vbus_state, hw_state; 261 u8 vbus_state, hw_state;
262 262
263 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); 263 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -268,22 +268,20 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
268 if (vbus_state & VBUS_DET) { 268 if (vbus_state & VBUS_DET) {
269 regulator_enable(twl->usb3v3); 269 regulator_enable(twl->usb3v3);
270 twl->asleep = 1; 270 twl->asleep = 1;
271 status = USB_EVENT_VBUS; 271 status = OMAP_MUSB_VBUS_VALID;
272 otg->default_a = false; 272 otg->default_a = false;
273 twl->phy.state = OTG_STATE_B_IDLE; 273 twl->phy.state = OTG_STATE_B_IDLE;
274 twl->linkstat = status; 274 twl->linkstat = status;
275 twl->phy.last_event = status; 275 omap_musb_mailbox(status);
276 atomic_notifier_call_chain(&twl->phy.notifier,
277 status, otg->gadget);
278 } else { 276 } else {
279 status = USB_EVENT_NONE; 277 if (twl->linkstat != OMAP_MUSB_UNKNOWN) {
280 twl->linkstat = status; 278 status = OMAP_MUSB_VBUS_OFF;
281 twl->phy.last_event = status; 279 twl->linkstat = status;
282 atomic_notifier_call_chain(&twl->phy.notifier, 280 omap_musb_mailbox(status);
283 status, otg->gadget); 281 if (twl->asleep) {
284 if (twl->asleep) { 282 regulator_disable(twl->usb3v3);
285 regulator_disable(twl->usb3v3); 283 twl->asleep = 0;
286 twl->asleep = 0; 284 }
287 } 285 }
288 } 286 }
289 } 287 }
@@ -296,7 +294,7 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
296{ 294{
297 struct twl6030_usb *twl = _twl; 295 struct twl6030_usb *twl = _twl;
298 struct usb_otg *otg = twl->phy.otg; 296 struct usb_otg *otg = twl->phy.otg;
299 int status = USB_EVENT_NONE; 297 enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
300 u8 hw_state; 298 u8 hw_state;
301 299
302 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); 300 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -308,13 +306,11 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
308 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1); 306 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1);
309 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 307 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
310 0x10); 308 0x10);
311 status = USB_EVENT_ID; 309 status = OMAP_MUSB_ID_GROUND;
312 otg->default_a = true; 310 otg->default_a = true;
313 twl->phy.state = OTG_STATE_A_IDLE; 311 twl->phy.state = OTG_STATE_A_IDLE;
314 twl->linkstat = status; 312 twl->linkstat = status;
315 twl->phy.last_event = status; 313 omap_musb_mailbox(status);
316 atomic_notifier_call_chain(&twl->phy.notifier, status,
317 otg->gadget);
318 } else { 314 } else {
319 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 315 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
320 0x10); 316 0x10);
@@ -419,6 +415,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
419 twl->irq1 = platform_get_irq(pdev, 0); 415 twl->irq1 = platform_get_irq(pdev, 0);
420 twl->irq2 = platform_get_irq(pdev, 1); 416 twl->irq2 = platform_get_irq(pdev, 1);
421 twl->features = pdata->features; 417 twl->features = pdata->features;
418 twl->linkstat = OMAP_MUSB_UNKNOWN;
422 419
423 twl->phy.dev = twl->dev; 420 twl->phy.dev = twl->dev;
424 twl->phy.label = "twl6030"; 421 twl->phy.label = "twl6030";
@@ -449,8 +446,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
449 if (device_create_file(&pdev->dev, &dev_attr_vbus)) 446 if (device_create_file(&pdev->dev, &dev_attr_vbus))
450 dev_warn(&pdev->dev, "could not create sysfs file\n"); 447 dev_warn(&pdev->dev, "could not create sysfs file\n");
451 448
452 ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
453
454 INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); 449 INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
455 450
456 twl->irq_enabled = true; 451 twl->irq_enabled = true;