diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 00:26:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 00:26:12 -0400 |
commit | 7a9b149212f3716c598afe973b6261fd58453b7a (patch) | |
tree | 477716d84c71da124448b72278e98da28aadbd3d /drivers/usb/musb/blackfin.c | |
parent | 3d62e3fdce8ef265a3706c52ae1ca6ab84e30f0e (diff) | |
parent | e26bcf37234c67624f62d9fc95f922b8dbda1363 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (229 commits)
USB: remove unused usb_buffer_alloc and usb_buffer_free macros
usb: musb: update gfp/slab.h includes
USB: ftdi_sio: fix legacy SIO-device header
USB: kl5usb105: reimplement using generic framework
USB: kl5usb105: minor clean ups
USB: kl5usb105: fix memory leak
USB: io_ti: use kfifo to implement write buffering
USB: io_ti: remove unsused private counter
USB: ti_usb: use kfifo to implement write buffering
USB: ir-usb: fix incorrect write-buffer length
USB: aircable: fix incorrect write-buffer length
USB: safe_serial: straighten out read processing
USB: safe_serial: reimplement read using generic framework
USB: safe_serial: reimplement write using generic framework
usb-storage: always print quirks
USB: usb-storage: trivial debug improvements
USB: oti6858: use port write fifo
USB: oti6858: use kfifo to implement write buffering
USB: cypress_m8: use kfifo to implement write buffering
USB: cypress_m8: remove unused drain define
...
Fix up conflicts (due to usb_buffer_alloc/free renaming) in
drivers/input/tablet/acecad.c
drivers/input/tablet/kbtab.c
drivers/input/tablet/wacom_sys.c
drivers/media/video/gspca/gspca.c
sound/usb/usbaudio.c
Diffstat (limited to 'drivers/usb/musb/blackfin.c')
-rw-r--r-- | drivers/usb/musb/blackfin.c | 96 |
1 files changed, 68 insertions, 28 deletions
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index ec8d324237f6..b611420a8050 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c | |||
@@ -170,6 +170,13 @@ static irqreturn_t blackfin_interrupt(int irq, void *__hci) | |||
170 | retval = musb_interrupt(musb); | 170 | retval = musb_interrupt(musb); |
171 | } | 171 | } |
172 | 172 | ||
173 | /* Start sampling ID pin, when plug is removed from MUSB */ | ||
174 | if (is_otg_enabled(musb) && (musb->xceiv->state == OTG_STATE_B_IDLE | ||
175 | || musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { | ||
176 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); | ||
177 | musb->a_wait_bcon = TIMER_DELAY; | ||
178 | } | ||
179 | |||
173 | spin_unlock_irqrestore(&musb->lock, flags); | 180 | spin_unlock_irqrestore(&musb->lock, flags); |
174 | 181 | ||
175 | return retval; | 182 | return retval; |
@@ -180,6 +187,7 @@ static void musb_conn_timer_handler(unsigned long _musb) | |||
180 | struct musb *musb = (void *)_musb; | 187 | struct musb *musb = (void *)_musb; |
181 | unsigned long flags; | 188 | unsigned long flags; |
182 | u16 val; | 189 | u16 val; |
190 | static u8 toggle; | ||
183 | 191 | ||
184 | spin_lock_irqsave(&musb->lock, flags); | 192 | spin_lock_irqsave(&musb->lock, flags); |
185 | switch (musb->xceiv->state) { | 193 | switch (musb->xceiv->state) { |
@@ -187,10 +195,44 @@ static void musb_conn_timer_handler(unsigned long _musb) | |||
187 | case OTG_STATE_A_WAIT_BCON: | 195 | case OTG_STATE_A_WAIT_BCON: |
188 | /* Start a new session */ | 196 | /* Start a new session */ |
189 | val = musb_readw(musb->mregs, MUSB_DEVCTL); | 197 | val = musb_readw(musb->mregs, MUSB_DEVCTL); |
198 | val &= ~MUSB_DEVCTL_SESSION; | ||
199 | musb_writew(musb->mregs, MUSB_DEVCTL, val); | ||
190 | val |= MUSB_DEVCTL_SESSION; | 200 | val |= MUSB_DEVCTL_SESSION; |
191 | musb_writew(musb->mregs, MUSB_DEVCTL, val); | 201 | musb_writew(musb->mregs, MUSB_DEVCTL, val); |
202 | /* Check if musb is host or peripheral. */ | ||
203 | val = musb_readw(musb->mregs, MUSB_DEVCTL); | ||
204 | |||
205 | if (!(val & MUSB_DEVCTL_BDEVICE)) { | ||
206 | gpio_set_value(musb->config->gpio_vrsel, 1); | ||
207 | musb->xceiv->state = OTG_STATE_A_WAIT_BCON; | ||
208 | } else { | ||
209 | gpio_set_value(musb->config->gpio_vrsel, 0); | ||
210 | /* Ignore VBUSERROR and SUSPEND IRQ */ | ||
211 | val = musb_readb(musb->mregs, MUSB_INTRUSBE); | ||
212 | val &= ~MUSB_INTR_VBUSERROR; | ||
213 | musb_writeb(musb->mregs, MUSB_INTRUSBE, val); | ||
192 | 214 | ||
215 | val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR; | ||
216 | musb_writeb(musb->mregs, MUSB_INTRUSB, val); | ||
217 | if (is_otg_enabled(musb)) | ||
218 | musb->xceiv->state = OTG_STATE_B_IDLE; | ||
219 | else | ||
220 | musb_writeb(musb->mregs, MUSB_POWER, MUSB_POWER_HSENAB); | ||
221 | } | ||
222 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); | ||
223 | break; | ||
224 | case OTG_STATE_B_IDLE: | ||
225 | |||
226 | if (!is_peripheral_enabled(musb)) | ||
227 | break; | ||
228 | /* Start a new session. It seems that MUSB needs taking | ||
229 | * some time to recognize the type of the plug inserted? | ||
230 | */ | ||
231 | val = musb_readw(musb->mregs, MUSB_DEVCTL); | ||
232 | val |= MUSB_DEVCTL_SESSION; | ||
233 | musb_writew(musb->mregs, MUSB_DEVCTL, val); | ||
193 | val = musb_readw(musb->mregs, MUSB_DEVCTL); | 234 | val = musb_readw(musb->mregs, MUSB_DEVCTL); |
235 | |||
194 | if (!(val & MUSB_DEVCTL_BDEVICE)) { | 236 | if (!(val & MUSB_DEVCTL_BDEVICE)) { |
195 | gpio_set_value(musb->config->gpio_vrsel, 1); | 237 | gpio_set_value(musb->config->gpio_vrsel, 1); |
196 | musb->xceiv->state = OTG_STATE_A_WAIT_BCON; | 238 | musb->xceiv->state = OTG_STATE_A_WAIT_BCON; |
@@ -205,12 +247,27 @@ static void musb_conn_timer_handler(unsigned long _musb) | |||
205 | val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR; | 247 | val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR; |
206 | musb_writeb(musb->mregs, MUSB_INTRUSB, val); | 248 | musb_writeb(musb->mregs, MUSB_INTRUSB, val); |
207 | 249 | ||
208 | val = MUSB_POWER_HSENAB; | 250 | /* Toggle the Soft Conn bit, so that we can response to |
209 | musb_writeb(musb->mregs, MUSB_POWER, val); | 251 | * the inserting of either A-plug or B-plug. |
252 | */ | ||
253 | if (toggle) { | ||
254 | val = musb_readb(musb->mregs, MUSB_POWER); | ||
255 | val &= ~MUSB_POWER_SOFTCONN; | ||
256 | musb_writeb(musb->mregs, MUSB_POWER, val); | ||
257 | toggle = 0; | ||
258 | } else { | ||
259 | val = musb_readb(musb->mregs, MUSB_POWER); | ||
260 | val |= MUSB_POWER_SOFTCONN; | ||
261 | musb_writeb(musb->mregs, MUSB_POWER, val); | ||
262 | toggle = 1; | ||
263 | } | ||
264 | /* The delay time is set to 1/4 second by default, | ||
265 | * shortening it, if accelerating A-plug detection | ||
266 | * is needed in OTG mode. | ||
267 | */ | ||
268 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY / 4); | ||
210 | } | 269 | } |
211 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); | ||
212 | break; | 270 | break; |
213 | |||
214 | default: | 271 | default: |
215 | DBG(1, "%s state not handled\n", otg_state_string(musb)); | 272 | DBG(1, "%s state not handled\n", otg_state_string(musb)); |
216 | break; | 273 | break; |
@@ -222,7 +279,7 @@ static void musb_conn_timer_handler(unsigned long _musb) | |||
222 | 279 | ||
223 | void musb_platform_enable(struct musb *musb) | 280 | void musb_platform_enable(struct musb *musb) |
224 | { | 281 | { |
225 | if (is_host_enabled(musb)) { | 282 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) { |
226 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); | 283 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); |
227 | musb->a_wait_bcon = TIMER_DELAY; | 284 | musb->a_wait_bcon = TIMER_DELAY; |
228 | } | 285 | } |
@@ -232,16 +289,12 @@ void musb_platform_disable(struct musb *musb) | |||
232 | { | 289 | { |
233 | } | 290 | } |
234 | 291 | ||
235 | static void bfin_vbus_power(struct musb *musb, int is_on, int sleeping) | ||
236 | { | ||
237 | } | ||
238 | |||
239 | static void bfin_set_vbus(struct musb *musb, int is_on) | 292 | static void bfin_set_vbus(struct musb *musb, int is_on) |
240 | { | 293 | { |
241 | if (is_on) | 294 | int value = musb->config->gpio_vrsel_active; |
242 | gpio_set_value(musb->config->gpio_vrsel, 1); | 295 | if (!is_on) |
243 | else | 296 | value = !value; |
244 | gpio_set_value(musb->config->gpio_vrsel, 0); | 297 | gpio_set_value(musb->config->gpio_vrsel, value); |
245 | 298 | ||
246 | DBG(1, "VBUS %s, devctl %02x " | 299 | DBG(1, "VBUS %s, devctl %02x " |
247 | /* otg %3x conf %08x prcm %08x */ "\n", | 300 | /* otg %3x conf %08x prcm %08x */ "\n", |
@@ -256,7 +309,7 @@ static int bfin_set_power(struct otg_transceiver *x, unsigned mA) | |||
256 | 309 | ||
257 | void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | 310 | void musb_platform_try_idle(struct musb *musb, unsigned long timeout) |
258 | { | 311 | { |
259 | if (is_host_enabled(musb)) | 312 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) |
260 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); | 313 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); |
261 | } | 314 | } |
262 | 315 | ||
@@ -270,7 +323,7 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode) | |||
270 | return -EIO; | 323 | return -EIO; |
271 | } | 324 | } |
272 | 325 | ||
273 | int __init musb_platform_init(struct musb *musb) | 326 | int __init musb_platform_init(struct musb *musb, void *board_data) |
274 | { | 327 | { |
275 | 328 | ||
276 | /* | 329 | /* |
@@ -339,23 +392,10 @@ int __init musb_platform_init(struct musb *musb) | |||
339 | return 0; | 392 | return 0; |
340 | } | 393 | } |
341 | 394 | ||
342 | int musb_platform_suspend(struct musb *musb) | ||
343 | { | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | int musb_platform_resume(struct musb *musb) | ||
348 | { | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | |||
353 | int musb_platform_exit(struct musb *musb) | 395 | int musb_platform_exit(struct musb *musb) |
354 | { | 396 | { |
355 | 397 | ||
356 | bfin_vbus_power(musb, 0 /*off*/, 1); | ||
357 | gpio_free(musb->config->gpio_vrsel); | 398 | gpio_free(musb->config->gpio_vrsel); |
358 | musb_platform_suspend(musb); | ||
359 | 399 | ||
360 | return 0; | 400 | return 0; |
361 | } | 401 | } |