Newer
Older
/*******************************************************************************
* Public Functions
*******************************************************************************/
/*******************************************************************************
* Name: up_usbinitialize
*
* Description:
* Initialize USB hardware.
*
* Assumptions:
* - This function is called very early in the initialization sequence
* - PLL and GIO pin initialization is not performed here but should been in
* the low-level boot logic: PLL1 must be configured for operation at 48MHz
* and P0.23 and PO.31 in PINSEL1 must be configured for Vbus and USB connect
* LED.
*
*******************************************************************************/
void up_usbinitialize(void)
{
struct lpc214x_usbdev_s *priv = &g_usbdev;
uint32 reg;
usbtrace(TRACE_DEVINIT, 0);
lpc214x_putreg(0, LPC214X_USBDEV_INTST);
memset(priv, 0, sizeof(struct lpc214x_usbdev_s));
priv->usbdev.ops = &g_devops;
priv->usbdev.ep0 = &priv->eplist[LPC214X_EP0_IN].ep;
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
/* Initialize the endpoint list */
for (i = 0; i < LPC214X_NPHYSENDPOINTS; i++)
{
uint32 bit = 1 << i;
/* Set endpoint operations, reference to driver structure (not
* really necessary because there is only one controller), and
* the physical endpoint number (which is just the index to the
* endpoint).
*/
priv->eplist[i].ep.ops = &g_epops;
priv->eplist[i].dev = priv;
priv->eplist[i].epphy = i;
/* The maximum packet size may depend on the type of endpoint */
if ((LPC214X_EPCTRLSET & bit) != 0)
{
priv->eplist[i].ep.maxpacket = LPC214X_EP0MAXPACKET;
}
else if ((LPC214X_EPINTRSET & bit) != 0)
{
priv->eplist[i].ep.maxpacket = LPC214X_INTRMAXPACKET;
}
else if ((LPC214X_EPBULKSET & bit) != 0)
{
priv->eplist[i].ep.maxpacket = LPC214X_BULKMAXPACKET;
}
else /* if ((LPC214X_EPISOCSET & bit) != 0) */
{
priv->eplist[i].ep.maxpacket = LPC214X_ISOCMAXPACKET;
}
}
/* Turn on USB power and clocking */
reg = lpc214x_getreg(LPC214X_PCON_PCONP);
lpc214x_putreg(reg, LPC214X_PCON_PCONP);
/* Attach USB controller interrupt handler */
if (irq_attach(LPC214X_USB_IRQ, lpc214x_usbinterrupt) != 0)
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_IRQREGISTRATION),
(uint16)LPC214X_USB_IRQ);
/* Enable USB inerrupts at the controller -- but do not disable
* the ARM interrupt until the device is bound to the class
* driver
*/
lpc214x_putreg(USBDEV_INTST_ENUSBINTS, LPC214X_USBDEV_INTST);
/* Disconnect device */
lpc214x_pullup(&priv->usbdev, FALSE);
/* Enable EP0 for OUT (host-to-device) */
lpc214x_usbcmd(CMD_USB_DEV_SETADDRESS, CMD_USB_SETADDRESS_DEVEN|0);
lpc214x_usbcmd(CMD_USB_DEV_SETADDRESS, CMD_USB_SETADDRESS_DEVEN|0);
/* Reset/Re-initialize the USB hardware */
lpc214x_usbreset(priv);
/* Init Device state structure */
priv->devstatus = lpc214x_usbcmd(CMD_USB_DEV_GETSTATUS, 0);
return;
errout:
up_usbuninitialize();
}
/*******************************************************************************
*******************************************************************************/
{
struct lpc214x_usbdev_s *priv = &g_usbdev;
uint32 reg;
irqstate_t flags;
usbtrace(TRACE_DEVUNINIT, 0);
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_DRIVERREGISTERED), 0);
usbdev_unregister(priv->driver);
}
/* Disconnect device */
flags = irqsave();
lpc214x_pullup(&priv->usbdev, FALSE);
priv->usbdev.speed = USB_SPEED_UNKNOWN;
lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 0);
/* Disable and detach IRQs */
up_disable_irq(LPC214X_USB_IRQ);
irq_detach(LPC214X_USB_IRQ);
/* Turn off USB power and clocking */
reg = lpc214x_getreg(LPC214X_PCON_PCONP);
reg &= ~LPC214X_PCONP_PCUSB;
lpc214x_putreg(reg, LPC214X_PCON_PCONP);
irqrestore(flags);
}
/*******************************************************************************
* Name: usbdev_register
*
* Description:
* Register a USB device class driver. The class driver's bind() method will be
* called to bind it to a USB device driver.
*
*******************************************************************************/
int usbdev_register(struct usbdevclass_driver_s *driver)
{
int ret;
usbtrace(TRACE_DEVREGISTER, 0);
if (!driver || !driver->ops->bind || !driver->ops->unbind ||
!driver->ops->disconnect || !driver->ops->setup)
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDPARMS), 0);
}
if (g_usbdev.driver)
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_DRIVER), 0);
return -EBUSY;
}
#endif
/* First hook up the driver */
g_usbdev.driver = driver;
/* Then bind the class driver */
ret = CLASS_BIND(driver, &g_usbdev.usbdev);
if (ret)
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BINDFAILED), (uint16)-ret);
g_usbdev.driver = NULL;
}
else
{
/* Enable USB controller interrupts */
up_enable_irq(LPC214X_USB_IRQ);
}
return ret;
}
/*******************************************************************************
* Name: usbdev_unregister
*
* Description:
* Un-register usbdev class driver.If the USB device is connected to a USB host,
* it will first disconnect(). The driver is also requested to unbind() and clean
* up any device state, before this procedure finally returns.
*
*******************************************************************************/
int usbdev_unregister(struct usbdevclass_driver_s *driver)
{
usbtrace(TRACE_DEVUNREGISTER, 0);
#ifdef CONFIG_DEBUG
if (driver != g_usbdev.driver)
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDPARMS), 0);
return -EINVAL;
}
#endif
/* Unbind the class driver */
CLASS_UNBIND(driver, &g_usbdev.usbdev);
/* Disable USB controller interrupts */
up_disable_irq(LPC214X_USB_IRQ);