risc-v/mpfs: usb: fix usb restart
Issuing the following commands doesn't succeed: - conn - disconn - conn This USB driver doesn't even disconnect without this patch. If the USB driver has been started from another hart, closing it will not disable the PLIC interrupt. This means it's possible many harts get the USB interrupt and thus make the USB look very unstable. Fix these problems by disconnecting the USB via the USB_POWER register at shutdown and disabling the interrupt at shutdown. Also clear the software internals via the mpfs_sw_setup() for the conn / disconect loop to succeed. Signed-off-by: Eero Nurkkala <eero.nurkkala@offcode.fi>
This commit is contained in:
parent
0322a61510
commit
5cedf1ef2a
1 changed files with 42 additions and 0 deletions
|
|
@ -307,6 +307,40 @@ static void mpfs_modifyreg16(uintptr_t addr, uint16_t clearbits,
|
|||
spin_unlock_irqrestore(NULL, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mpfs_modifyreg8
|
||||
*
|
||||
* Description:
|
||||
* Atomically modify the specified bits in the memory mapped register.
|
||||
* This also checks the addr range is valid.
|
||||
*
|
||||
* Input Parameters:
|
||||
* addr - Address to access
|
||||
* clearbits - Bits to clear
|
||||
* setbits - Bits to set
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void mpfs_modifyreg8(uintptr_t addr, uint8_t clearbits,
|
||||
uint8_t setbits)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uint8_t regval;
|
||||
|
||||
DEBUGASSERT((addr >= MPFS_USB_BASE) && addr < (MPFS_USB_BASE +
|
||||
MPFS_USB_REG_MAX));
|
||||
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
regval = getreg8(addr);
|
||||
regval &= ~clearbits;
|
||||
regval |= setbits;
|
||||
putreg8(regval, addr);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Register Operations
|
||||
****************************************************************************/
|
||||
|
|
@ -3691,9 +3725,15 @@ static void mpfs_hw_shutdown(struct mpfs_usbdev_s *priv)
|
|||
{
|
||||
priv->usbdev.speed = USB_SPEED_UNKNOWN;
|
||||
|
||||
/* Force disconnect and give some time to finish it up */
|
||||
|
||||
mpfs_modifyreg8(MPFS_USB_POWER, POWER_REG_SOFT_CONN_MASK, 0);
|
||||
nxsig_usleep(1000);
|
||||
|
||||
/* Disable all interrupts */
|
||||
|
||||
mpfs_putreg8(0, MPFS_USB_ENABLE);
|
||||
up_disable_irq(MPFS_IRQ_USB_MC);
|
||||
|
||||
/* Disable clocking to the peripheral */
|
||||
|
||||
|
|
@ -3818,6 +3858,8 @@ int usbdev_register(struct usbdevclass_driver_s *driver)
|
|||
|
||||
DEBUGASSERT(driver != NULL);
|
||||
|
||||
mpfs_sw_setup(priv);
|
||||
|
||||
/* First hook up the driver */
|
||||
|
||||
priv->driver = driver;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue