aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/tusb6010.c
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-03-31 15:30:04 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:40 -0400
commit84e250ffa76dddc1bad84e04248a27f442c25986 (patch)
treeb253b1e2b030b160d2c458aece9c8122446e433f /drivers/usb/musb/tusb6010.c
parentcc835e321a9f3fa5e083436872e198095f4805b9 (diff)
musb: proper hookup to transceiver drivers
Let the otg_transceiver in MUSB be managed by an external driver; don't assume it's integrated. OMAP3 chips need it to be external, and there may be ways to interact with the transceiver which add functionality to the system. Platform init code is responsible for setting up the transeciver, probably using the NOP transceiver for integrated transceivers. External ones will use whatever the board init code provided, such as twl4030 or something more hands-off. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/musb/tusb6010.c')
-rw-r--r--drivers/usb/musb/tusb6010.c70
1 files changed, 44 insertions, 26 deletions
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 4ac1477d3569..88b587c703e9 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -259,6 +259,8 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
259 tusb_fifo_read_unaligned(fifo, buf, len); 259 tusb_fifo_read_unaligned(fifo, buf, len);
260} 260}
261 261
262static struct musb *the_musb;
263
262#ifdef CONFIG_USB_GADGET_MUSB_HDRC 264#ifdef CONFIG_USB_GADGET_MUSB_HDRC
263 265
264/* This is used by gadget drivers, and OTG transceiver logic, allowing 266/* This is used by gadget drivers, and OTG transceiver logic, allowing
@@ -269,7 +271,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
269 */ 271 */
270static int tusb_draw_power(struct otg_transceiver *x, unsigned mA) 272static int tusb_draw_power(struct otg_transceiver *x, unsigned mA)
271{ 273{
272 struct musb *musb = container_of(x, struct musb, xceiv); 274 struct musb *musb = the_musb;
273 void __iomem *tbase = musb->ctrl_base; 275 void __iomem *tbase = musb->ctrl_base;
274 u32 reg; 276 u32 reg;
275 277
@@ -419,7 +421,7 @@ static void musb_do_idle(unsigned long _musb)
419 421
420 spin_lock_irqsave(&musb->lock, flags); 422 spin_lock_irqsave(&musb->lock, flags);
421 423
422 switch (musb->xceiv.state) { 424 switch (musb->xceiv->state) {
423 case OTG_STATE_A_WAIT_BCON: 425 case OTG_STATE_A_WAIT_BCON:
424 if ((musb->a_wait_bcon != 0) 426 if ((musb->a_wait_bcon != 0)
425 && (musb->idle_timeout == 0 427 && (musb->idle_timeout == 0
@@ -483,7 +485,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
483 485
484 /* Never idle if active, or when VBUS timeout is not set as host */ 486 /* Never idle if active, or when VBUS timeout is not set as host */
485 if (musb->is_active || ((musb->a_wait_bcon == 0) 487 if (musb->is_active || ((musb->a_wait_bcon == 0)
486 && (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) { 488 && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
487 DBG(4, "%s active, deleting timer\n", otg_state_string(musb)); 489 DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
488 del_timer(&musb_idle_timer); 490 del_timer(&musb_idle_timer);
489 last_timer = jiffies; 491 last_timer = jiffies;
@@ -532,8 +534,8 @@ static void tusb_source_power(struct musb *musb, int is_on)
532 if (musb->set_clock) 534 if (musb->set_clock)
533 musb->set_clock(musb->clock, 1); 535 musb->set_clock(musb->clock, 1);
534 timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE); 536 timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE);
535 musb->xceiv.default_a = 1; 537 musb->xceiv->default_a = 1;
536 musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; 538 musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
537 devctl |= MUSB_DEVCTL_SESSION; 539 devctl |= MUSB_DEVCTL_SESSION;
538 540
539 conf |= TUSB_DEV_CONF_USB_HOST_MODE; 541 conf |= TUSB_DEV_CONF_USB_HOST_MODE;
@@ -546,24 +548,24 @@ static void tusb_source_power(struct musb *musb, int is_on)
546 /* If ID pin is grounded, we want to be a_idle */ 548 /* If ID pin is grounded, we want to be a_idle */
547 otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); 549 otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
548 if (!(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) { 550 if (!(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) {
549 switch (musb->xceiv.state) { 551 switch (musb->xceiv->state) {
550 case OTG_STATE_A_WAIT_VRISE: 552 case OTG_STATE_A_WAIT_VRISE:
551 case OTG_STATE_A_WAIT_BCON: 553 case OTG_STATE_A_WAIT_BCON:
552 musb->xceiv.state = OTG_STATE_A_WAIT_VFALL; 554 musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
553 break; 555 break;
554 case OTG_STATE_A_WAIT_VFALL: 556 case OTG_STATE_A_WAIT_VFALL:
555 musb->xceiv.state = OTG_STATE_A_IDLE; 557 musb->xceiv->state = OTG_STATE_A_IDLE;
556 break; 558 break;
557 default: 559 default:
558 musb->xceiv.state = OTG_STATE_A_IDLE; 560 musb->xceiv->state = OTG_STATE_A_IDLE;
559 } 561 }
560 musb->is_active = 0; 562 musb->is_active = 0;
561 musb->xceiv.default_a = 1; 563 musb->xceiv->default_a = 1;
562 MUSB_HST_MODE(musb); 564 MUSB_HST_MODE(musb);
563 } else { 565 } else {
564 musb->is_active = 0; 566 musb->is_active = 0;
565 musb->xceiv.default_a = 0; 567 musb->xceiv->default_a = 0;
566 musb->xceiv.state = OTG_STATE_B_IDLE; 568 musb->xceiv->state = OTG_STATE_B_IDLE;
567 MUSB_DEV_MODE(musb); 569 MUSB_DEV_MODE(musb);
568 } 570 }
569 571
@@ -674,7 +676,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
674 else 676 else
675 default_a = is_host_enabled(musb); 677 default_a = is_host_enabled(musb);
676 DBG(2, "Default-%c\n", default_a ? 'A' : 'B'); 678 DBG(2, "Default-%c\n", default_a ? 'A' : 'B');
677 musb->xceiv.default_a = default_a; 679 musb->xceiv->default_a = default_a;
678 tusb_source_power(musb, default_a); 680 tusb_source_power(musb, default_a);
679 681
680 /* Don't allow idling immediately */ 682 /* Don't allow idling immediately */
@@ -686,7 +688,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
686 if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) { 688 if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) {
687 689
688 /* B-dev state machine: no vbus ~= disconnect */ 690 /* B-dev state machine: no vbus ~= disconnect */
689 if ((is_otg_enabled(musb) && !musb->xceiv.default_a) 691 if ((is_otg_enabled(musb) && !musb->xceiv->default_a)
690 || !is_host_enabled(musb)) { 692 || !is_host_enabled(musb)) {
691#ifdef CONFIG_USB_MUSB_HDRC_HCD 693#ifdef CONFIG_USB_MUSB_HDRC_HCD
692 /* ? musb_root_disconnect(musb); */ 694 /* ? musb_root_disconnect(musb); */
@@ -701,9 +703,9 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
701 703
702 if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) { 704 if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) {
703 DBG(1, "Forcing disconnect (no interrupt)\n"); 705 DBG(1, "Forcing disconnect (no interrupt)\n");
704 if (musb->xceiv.state != OTG_STATE_B_IDLE) { 706 if (musb->xceiv->state != OTG_STATE_B_IDLE) {
705 /* INTR_DISCONNECT can hide... */ 707 /* INTR_DISCONNECT can hide... */
706 musb->xceiv.state = OTG_STATE_B_IDLE; 708 musb->xceiv->state = OTG_STATE_B_IDLE;
707 musb->int_usb |= MUSB_INTR_DISCONNECT; 709 musb->int_usb |= MUSB_INTR_DISCONNECT;
708 } 710 }
709 musb->is_active = 0; 711 musb->is_active = 0;
@@ -717,7 +719,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
717 DBG(2, "vbus change, %s, otg %03x\n", 719 DBG(2, "vbus change, %s, otg %03x\n",
718 otg_state_string(musb), otg_stat); 720 otg_state_string(musb), otg_stat);
719 721
720 switch (musb->xceiv.state) { 722 switch (musb->xceiv->state) {
721 case OTG_STATE_A_IDLE: 723 case OTG_STATE_A_IDLE:
722 DBG(2, "Got SRP, turning on VBUS\n"); 724 DBG(2, "Got SRP, turning on VBUS\n");
723 musb_set_vbus(musb, 1); 725 musb_set_vbus(musb, 1);
@@ -765,7 +767,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
765 767
766 DBG(4, "%s timer, %03x\n", otg_state_string(musb), otg_stat); 768 DBG(4, "%s timer, %03x\n", otg_state_string(musb), otg_stat);
767 769
768 switch (musb->xceiv.state) { 770 switch (musb->xceiv->state) {
769 case OTG_STATE_A_WAIT_VRISE: 771 case OTG_STATE_A_WAIT_VRISE:
770 /* VBUS has probably been valid for a while now, 772 /* VBUS has probably been valid for a while now,
771 * but may well have bounced out of range a bit 773 * but may well have bounced out of range a bit
@@ -777,7 +779,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
777 DBG(2, "devctl %02x\n", devctl); 779 DBG(2, "devctl %02x\n", devctl);
778 break; 780 break;
779 } 781 }
780 musb->xceiv.state = OTG_STATE_A_WAIT_BCON; 782 musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
781 musb->is_active = 0; 783 musb->is_active = 0;
782 idle_timeout = jiffies 784 idle_timeout = jiffies
783 + msecs_to_jiffies(musb->a_wait_bcon); 785 + msecs_to_jiffies(musb->a_wait_bcon);
@@ -1093,9 +1095,14 @@ int __init musb_platform_init(struct musb *musb)
1093{ 1095{
1094 struct platform_device *pdev; 1096 struct platform_device *pdev;
1095 struct resource *mem; 1097 struct resource *mem;
1096 void __iomem *sync; 1098 void __iomem *sync = NULL;
1097 int ret; 1099 int ret;
1098 1100
1101 usb_nop_xceiv_register();
1102 musb->xceiv = otg_get_transceiver();
1103 if (!musb->xceiv)
1104 return -ENODEV;
1105
1099 pdev = to_platform_device(musb->controller); 1106 pdev = to_platform_device(musb->controller);
1100 1107
1101 /* dma address for async dma */ 1108 /* dma address for async dma */
@@ -1106,14 +1113,16 @@ int __init musb_platform_init(struct musb *musb)
1106 mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1113 mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1107 if (!mem) { 1114 if (!mem) {
1108 pr_debug("no sync dma resource?\n"); 1115 pr_debug("no sync dma resource?\n");
1109 return -ENODEV; 1116 ret = -ENODEV;
1117 goto done;
1110 } 1118 }
1111 musb->sync = mem->start; 1119 musb->sync = mem->start;
1112 1120
1113 sync = ioremap(mem->start, mem->end - mem->start + 1); 1121 sync = ioremap(mem->start, mem->end - mem->start + 1);
1114 if (!sync) { 1122 if (!sync) {
1115 pr_debug("ioremap for sync failed\n"); 1123 pr_debug("ioremap for sync failed\n");
1116 return -ENOMEM; 1124 ret = -ENOMEM;
1125 goto done;
1117 } 1126 }
1118 musb->sync_va = sync; 1127 musb->sync_va = sync;
1119 1128
@@ -1126,28 +1135,37 @@ int __init musb_platform_init(struct musb *musb)
1126 if (ret) { 1135 if (ret) {
1127 printk(KERN_ERR "Could not start tusb6010 (%d)\n", 1136 printk(KERN_ERR "Could not start tusb6010 (%d)\n",
1128 ret); 1137 ret);
1129 return -ENODEV; 1138 goto done;
1130 } 1139 }
1131 musb->isr = tusb_interrupt; 1140 musb->isr = tusb_interrupt;
1132 1141
1133 if (is_host_enabled(musb)) 1142 if (is_host_enabled(musb))
1134 musb->board_set_vbus = tusb_source_power; 1143 musb->board_set_vbus = tusb_source_power;
1135 if (is_peripheral_enabled(musb)) 1144 if (is_peripheral_enabled(musb)) {
1136 musb->xceiv.set_power = tusb_draw_power; 1145 musb->xceiv->set_power = tusb_draw_power;
1146 the_musb = musb;
1147 }
1137 1148
1138 setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); 1149 setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
1139 1150
1151done:
1152 if (ret < 0) {
1153 if (sync)
1154 iounmap(sync);
1155 usb_nop_xceiv_unregister();
1156 }
1140 return ret; 1157 return ret;
1141} 1158}
1142 1159
1143int musb_platform_exit(struct musb *musb) 1160int musb_platform_exit(struct musb *musb)
1144{ 1161{
1145 del_timer_sync(&musb_idle_timer); 1162 del_timer_sync(&musb_idle_timer);
1163 the_musb = NULL;
1146 1164
1147 if (musb->board_set_power) 1165 if (musb->board_set_power)
1148 musb->board_set_power(0); 1166 musb->board_set_power(0);
1149 1167
1150 iounmap(musb->sync_va); 1168 iounmap(musb->sync_va);
1151 1169 usb_nop_xceiv_unregister();
1152 return 0; 1170 return 0;
1153} 1171}