musb_dsps.c (768330756d9bbfee6eca573b96c828adb1ba9058) musb_dsps.c (e47d92545c2972bcf3711e7db80f481e402163c7)
1/*
2 * Texas Instruments DSPS platforms "glue layer"
3 *
4 * Copyright (C) 2012, by Texas Instruments
5 *
6 * Based on the am35x "glue layer" code.
7 *
8 * This file is part of the Inventra Controller Driver for Linux.

--- 165 unchanged lines hidden (view full) ---

174 struct device *dev = musb->controller;
175 struct dsps_glue *glue = dev_get_drvdata(dev->parent);
176
177 if (timeout == 0)
178 timeout = jiffies + msecs_to_jiffies(3);
179
180 /* Never idle if active, or when VBUS timeout is not set as host */
181 if (musb->is_active || (musb->a_wait_bcon == 0 &&
1/*
2 * Texas Instruments DSPS platforms "glue layer"
3 *
4 * Copyright (C) 2012, by Texas Instruments
5 *
6 * Based on the am35x "glue layer" code.
7 *
8 * This file is part of the Inventra Controller Driver for Linux.

--- 165 unchanged lines hidden (view full) ---

174 struct device *dev = musb->controller;
175 struct dsps_glue *glue = dev_get_drvdata(dev->parent);
176
177 if (timeout == 0)
178 timeout = jiffies + msecs_to_jiffies(3);
179
180 /* Never idle if active, or when VBUS timeout is not set as host */
181 if (musb->is_active || (musb->a_wait_bcon == 0 &&
182 musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
182 musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON)) {
183 dev_dbg(musb->controller, "%s active, deleting timer\n",
183 dev_dbg(musb->controller, "%s active, deleting timer\n",
184 usb_otg_state_string(musb->xceiv->state));
184 usb_otg_state_string(musb->xceiv->otg->state));
185 del_timer(&glue->timer);
186 glue->last_timer = jiffies;
187 return;
188 }
189 if (musb->port_mode != MUSB_PORT_MODE_DUAL_ROLE)
190 return;
191
192 if (!musb->g.dev.driver)
193 return;
194
195 if (time_after(glue->last_timer, timeout) &&
196 timer_pending(&glue->timer)) {
197 dev_dbg(musb->controller,
198 "Longer idle timer already pending, ignoring...\n");
199 return;
200 }
201 glue->last_timer = timeout;
202
203 dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
185 del_timer(&glue->timer);
186 glue->last_timer = jiffies;
187 return;
188 }
189 if (musb->port_mode != MUSB_PORT_MODE_DUAL_ROLE)
190 return;
191
192 if (!musb->g.dev.driver)
193 return;
194
195 if (time_after(glue->last_timer, timeout) &&
196 timer_pending(&glue->timer)) {
197 dev_dbg(musb->controller,
198 "Longer idle timer already pending, ignoring...\n");
199 return;
200 }
201 glue->last_timer = timeout;
202
203 dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
204 usb_otg_state_string(musb->xceiv->state),
204 usb_otg_state_string(musb->xceiv->otg->state),
205 jiffies_to_msecs(timeout - jiffies));
206 mod_timer(&glue->timer, timeout);
207}
208
209/**
210 * dsps_musb_enable - enable interrupts
211 */
212static void dsps_musb_enable(struct musb *musb)

--- 47 unchanged lines hidden (view full) ---

260 int skip_session = 0;
261
262 /*
263 * We poll because DSPS IP's won't expose several OTG-critical
264 * status change events (from the transceiver) otherwise.
265 */
266 devctl = dsps_readb(mregs, MUSB_DEVCTL);
267 dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
205 jiffies_to_msecs(timeout - jiffies));
206 mod_timer(&glue->timer, timeout);
207}
208
209/**
210 * dsps_musb_enable - enable interrupts
211 */
212static void dsps_musb_enable(struct musb *musb)

--- 47 unchanged lines hidden (view full) ---

260 int skip_session = 0;
261
262 /*
263 * We poll because DSPS IP's won't expose several OTG-critical
264 * status change events (from the transceiver) otherwise.
265 */
266 devctl = dsps_readb(mregs, MUSB_DEVCTL);
267 dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
268 usb_otg_state_string(musb->xceiv->state));
268 usb_otg_state_string(musb->xceiv->otg->state));
269
270 spin_lock_irqsave(&musb->lock, flags);
269
270 spin_lock_irqsave(&musb->lock, flags);
271 switch (musb->xceiv->state) {
271 switch (musb->xceiv->otg->state) {
272 case OTG_STATE_A_WAIT_BCON:
273 dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
274 skip_session = 1;
275 /* fall */
276
277 case OTG_STATE_A_IDLE:
278 case OTG_STATE_B_IDLE:
279 if (devctl & MUSB_DEVCTL_BDEVICE) {
272 case OTG_STATE_A_WAIT_BCON:
273 dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
274 skip_session = 1;
275 /* fall */
276
277 case OTG_STATE_A_IDLE:
278 case OTG_STATE_B_IDLE:
279 if (devctl & MUSB_DEVCTL_BDEVICE) {
280 musb->xceiv->state = OTG_STATE_B_IDLE;
280 musb->xceiv->otg->state = OTG_STATE_B_IDLE;
281 MUSB_DEV_MODE(musb);
282 } else {
281 MUSB_DEV_MODE(musb);
282 } else {
283 musb->xceiv->state = OTG_STATE_A_IDLE;
283 musb->xceiv->otg->state = OTG_STATE_A_IDLE;
284 MUSB_HST_MODE(musb);
285 }
286 if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session)
287 dsps_writeb(mregs, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
288 mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
289 break;
290 case OTG_STATE_A_WAIT_VFALL:
284 MUSB_HST_MODE(musb);
285 }
286 if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session)
287 dsps_writeb(mregs, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
288 mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
289 break;
290 case OTG_STATE_A_WAIT_VFALL:
291 musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
291 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
292 dsps_writel(musb->ctrl_base, wrp->coreintr_set,
293 MUSB_INTR_VBUSERROR << wrp->usb_shift);
294 break;
295 default:
296 break;
297 }
298 spin_unlock_irqrestore(&musb->lock, flags);
299}

--- 68 unchanged lines hidden (view full) ---

368 * to get VBUS errors during enumeration.
369 *
370 * This is a workaround, but newer RTL from Mentor
371 * seems to allow a better one: "re"-starting sessions
372 * without waiting for VBUS to stop registering in
373 * devctl.
374 */
375 musb->int_usb &= ~MUSB_INTR_VBUSERROR;
292 dsps_writel(musb->ctrl_base, wrp->coreintr_set,
293 MUSB_INTR_VBUSERROR << wrp->usb_shift);
294 break;
295 default:
296 break;
297 }
298 spin_unlock_irqrestore(&musb->lock, flags);
299}

--- 68 unchanged lines hidden (view full) ---

368 * to get VBUS errors during enumeration.
369 *
370 * This is a workaround, but newer RTL from Mentor
371 * seems to allow a better one: "re"-starting sessions
372 * without waiting for VBUS to stop registering in
373 * devctl.
374 */
375 musb->int_usb &= ~MUSB_INTR_VBUSERROR;
376 musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
376 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
377 mod_timer(&glue->timer,
378 jiffies + wrp->poll_seconds * HZ);
379 WARNING("VBUS error workaround (delay coming)\n");
380 } else if (drvvbus) {
381 MUSB_HST_MODE(musb);
382 musb->xceiv->otg->default_a = 1;
377 mod_timer(&glue->timer,
378 jiffies + wrp->poll_seconds * HZ);
379 WARNING("VBUS error workaround (delay coming)\n");
380 } else if (drvvbus) {
381 MUSB_HST_MODE(musb);
382 musb->xceiv->otg->default_a = 1;
383 musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
383 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
384 del_timer(&glue->timer);
385 } else {
386 musb->is_active = 0;
387 MUSB_DEV_MODE(musb);
388 musb->xceiv->otg->default_a = 0;
384 del_timer(&glue->timer);
385 } else {
386 musb->is_active = 0;
387 MUSB_DEV_MODE(musb);
388 musb->xceiv->otg->default_a = 0;
389 musb->xceiv->state = OTG_STATE_B_IDLE;
389 musb->xceiv->otg->state = OTG_STATE_B_IDLE;
390 }
391
392 /* NOTE: this must complete power-on within 100 ms. */
393 dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
394 drvvbus ? "on" : "off",
390 }
391
392 /* NOTE: this must complete power-on within 100 ms. */
393 dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
394 drvvbus ? "on" : "off",
395 usb_otg_state_string(musb->xceiv->state),
395 usb_otg_state_string(musb->xceiv->otg->state),
396 err ? " ERROR" : "",
397 devctl);
398 ret = IRQ_HANDLED;
399 }
400
401 if (musb->int_tx || musb->int_rx || musb->int_usb)
402 ret |= musb_interrupt(musb);
403
404 /* Poll for ID change in OTG port mode */
396 err ? " ERROR" : "",
397 devctl);
398 ret = IRQ_HANDLED;
399 }
400
401 if (musb->int_tx || musb->int_rx || musb->int_usb)
402 ret |= musb_interrupt(musb);
403
404 /* Poll for ID change in OTG port mode */
405 if (musb->xceiv->state == OTG_STATE_B_IDLE &&
405 if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
406 musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
407 mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
408out:
409 spin_unlock_irqrestore(&musb->lock, flags);
410
411 return ret;
412}
413

--- 481 unchanged lines hidden (view full) ---

895 mbase = musb->ctrl_base;
896 dsps_writel(mbase, wrp->control, glue->context.control);
897 dsps_writel(mbase, wrp->epintr_set, glue->context.epintr);
898 dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
899 dsps_writel(mbase, wrp->phy_utmi, glue->context.phy_utmi);
900 dsps_writel(mbase, wrp->mode, glue->context.mode);
901 dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
902 dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
406 musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
407 mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
408out:
409 spin_unlock_irqrestore(&musb->lock, flags);
410
411 return ret;
412}
413

--- 481 unchanged lines hidden (view full) ---

895 mbase = musb->ctrl_base;
896 dsps_writel(mbase, wrp->control, glue->context.control);
897 dsps_writel(mbase, wrp->epintr_set, glue->context.epintr);
898 dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
899 dsps_writel(mbase, wrp->phy_utmi, glue->context.phy_utmi);
900 dsps_writel(mbase, wrp->mode, glue->context.mode);
901 dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
902 dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
903 if (musb->xceiv->state == OTG_STATE_B_IDLE &&
903 if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
904 musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
905 mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
906
907 return 0;
908}
909#endif
910
911static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);

--- 17 unchanged lines hidden ---
904 musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
905 mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
906
907 return 0;
908}
909#endif
910
911static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);

--- 17 unchanged lines hidden ---