aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/ux500.c
diff options
context:
space:
mode:
authorFabio Baltieri <fabio.baltieri@linaro.org>2013-03-07 21:27:07 -0500
committerFelipe Balbi <balbi@ti.com>2013-03-18 08:41:32 -0400
commit0135522c48982cf1d456d863272e911fdf8a17da (patch)
tree1fcc113a2f9957e5e929b9b4b909d81a7009ada1 /drivers/usb/musb/ux500.c
parent996a9d26d37c7dca27b7e9830a49daa74a2603b7 (diff)
usb: musb: ux500: add otg notifier support
Add transceiver notifier event handling to the ux500 driver to set vbus on specific transceiver events. Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org> [ balbi@ti.com: fix build error due to missing otg_state_string() ] Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/musb/ux500.c')
-rw-r--r--drivers/usb/musb/ux500.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index 0332fcd286f7..0ae9472a68a8 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -98,6 +98,37 @@ static void ux500_musb_set_vbus(struct musb *musb, int is_on)
98 musb_readb(musb->mregs, MUSB_DEVCTL)); 98 musb_readb(musb->mregs, MUSB_DEVCTL));
99} 99}
100 100
101static int musb_otg_notifications(struct notifier_block *nb,
102 unsigned long event, void *unused)
103{
104 struct musb *musb = container_of(nb, struct musb, nb);
105
106 dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n",
107 event, usb_otg_state_string(musb->xceiv->state));
108
109 switch (event) {
110 case USB_EVENT_ID:
111 dev_dbg(musb->controller, "ID GND\n");
112 ux500_musb_set_vbus(musb, 1);
113 break;
114 case USB_EVENT_VBUS:
115 dev_dbg(musb->controller, "VBUS Connect\n");
116 ux500_musb_set_vbus(musb, 0);
117 break;
118 case USB_EVENT_NONE:
119 dev_dbg(musb->controller, "VBUS Disconnect\n");
120 if (is_host_active(musb))
121 ux500_musb_set_vbus(musb, 0);
122 else
123 musb->xceiv->state = OTG_STATE_B_IDLE;
124 break;
125 default:
126 dev_dbg(musb->controller, "ID float\n");
127 return NOTIFY_DONE;
128 }
129 return NOTIFY_OK;
130}
131
101static irqreturn_t ux500_musb_interrupt(int irq, void *__hci) 132static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
102{ 133{
103 unsigned long flags; 134 unsigned long flags;
@@ -120,12 +151,21 @@ static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
120 151
121static int ux500_musb_init(struct musb *musb) 152static int ux500_musb_init(struct musb *musb)
122{ 153{
154 int status;
155
123 musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); 156 musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
124 if (IS_ERR_OR_NULL(musb->xceiv)) { 157 if (IS_ERR_OR_NULL(musb->xceiv)) {
125 pr_err("HS USB OTG: no transceiver configured\n"); 158 pr_err("HS USB OTG: no transceiver configured\n");
126 return -EPROBE_DEFER; 159 return -EPROBE_DEFER;
127 } 160 }
128 161
162 musb->nb.notifier_call = musb_otg_notifications;
163 status = usb_register_notifier(musb->xceiv, &musb->nb);
164 if (status < 0) {
165 dev_dbg(musb->controller, "notification register failed\n");
166 return status;
167 }
168
129 musb->isr = ux500_musb_interrupt; 169 musb->isr = ux500_musb_interrupt;
130 170
131 return 0; 171 return 0;
@@ -133,6 +173,8 @@ static int ux500_musb_init(struct musb *musb)
133 173
134static int ux500_musb_exit(struct musb *musb) 174static int ux500_musb_exit(struct musb *musb)
135{ 175{
176 usb_unregister_notifier(musb->xceiv, &musb->nb);
177
136 usb_put_phy(musb->xceiv); 178 usb_put_phy(musb->xceiv);
137 179
138 return 0; 180 return 0;