aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/blackfin.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 00:26:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 00:26:12 -0400
commit7a9b149212f3716c598afe973b6261fd58453b7a (patch)
tree477716d84c71da124448b72278e98da28aadbd3d /drivers/usb/musb/blackfin.c
parent3d62e3fdce8ef265a3706c52ae1ca6ab84e30f0e (diff)
parente26bcf37234c67624f62d9fc95f922b8dbda1363 (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.c96
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
223void musb_platform_enable(struct musb *musb) 280void 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
235static void bfin_vbus_power(struct musb *musb, int is_on, int sleeping)
236{
237}
238
239static void bfin_set_vbus(struct musb *musb, int is_on) 292static 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
257void musb_platform_try_idle(struct musb *musb, unsigned long timeout) 310void 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
273int __init musb_platform_init(struct musb *musb) 326int __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
342int musb_platform_suspend(struct musb *musb)
343{
344 return 0;
345}
346
347int musb_platform_resume(struct musb *musb)
348{
349 return 0;
350}
351
352
353int musb_platform_exit(struct musb *musb) 395int 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}