diff options
author | Fabio Baltieri <fabio.baltieri@linaro.org> | 2013-03-07 21:27:07 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-03-18 08:41:32 -0400 |
commit | 0135522c48982cf1d456d863272e911fdf8a17da (patch) | |
tree | 1fcc113a2f9957e5e929b9b4b909d81a7009ada1 /drivers/usb/musb/ux500.c | |
parent | 996a9d26d37c7dca27b7e9830a49daa74a2603b7 (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.c | 42 |
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 | ||
101 | static 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 | |||
101 | static irqreturn_t ux500_musb_interrupt(int irq, void *__hci) | 132 | static 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 | ||
121 | static int ux500_musb_init(struct musb *musb) | 152 | static 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 | ||
134 | static int ux500_musb_exit(struct musb *musb) | 174 | static 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; |