X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/fe45016635e867a8a61552ae0914a63263b64185..08bccb5ea014a173bede8f06478a35465981bd28:/embedded/libs4c/usb/lpcusb/lpcusb.c diff --git a/embedded/libs4c/usb/lpcusb/lpcusb.c b/embedded/libs4c/usb/lpcusb/lpcusb.c new file mode 100644 index 0000000..1cf130d --- /dev/null +++ b/embedded/libs4c/usb/lpcusb/lpcusb.c @@ -0,0 +1,195 @@ +/*****************************************************/ +/*** Module : USB PDI ***/ +/*** Author : Roman Bartosinski (C) 28.04.2002 ***/ +/*** Modify : 08.08.2002, 16.04.2003 ***/ +/*****************************************************/ + +#include +#include +#include + +unsigned int lpc_ep2addr(unsigned int ep_num) +{ + unsigned int val; + val = (ep_num & 0x0F) << 1; + if (ep_num & 0x80) + val += 1; + return val; +} + +void lpc_wait4devint(unsigned int intrs) +{ + while ((USBDevIntSt & intrs) != intrs); + USBDevIntClr = intrs; +} + + +void lpc_write_cmd(unsigned int cmd) +{ + USBDevIntClr = USBDevInt_CCEMTY | USBDevInt_CDFULL; + USBCmdCode = cmd; + lpc_wait4devint(USBDevInt_CCEMTY); +} + +void lpc_write_cmd_data (unsigned int cmd, unsigned int val) +{ + lpc_write_cmd(cmd); + USBCmdCode = val; + lpc_wait4devint(USBDevInt_CCEMTY); +} + +unsigned int lpc_read_cmd_data (unsigned int cmd) +{ + lpc_write_cmd(cmd); + lpc_wait4devint(USBDevInt_CDFULL); + return USBCmdData; +} + +void lpc_usb_realizeEP(unsigned int idx,unsigned int wmaxpsize) +{ + USBReEp |= (1 << idx); + USBEpInd = idx; + USBMaxPSize = wmaxpsize; + lpc_wait4devint(USBDevInt_EP_RLZED); +} + +void lpc_usb_configEP(unsigned int ep_num,unsigned int wmaxpsize) +{ + lpc_usb_realizeEP(lpc_ep2addr(ep_num),wmaxpsize); + lpc_usb_enableEP(ep_num); +} + +void lpc_usb_setstallEP(unsigned int ep_num) +{ + lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(USBC_EP_STAT_ST)); +} + +void lpc_usb_clrstallEP(unsigned int ep_num) +{ + lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(0)); +} + +void lpc_usb_enableEP(unsigned int ep_num) +{ + lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(0)); +} + +void lpc_usb_disableEP(unsigned int ep_num) +{ + lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(USBC_EP_STAT_DA)); +} + +void lpc_usb_set_addr(unsigned int adr) +{ + lpc_write_cmd_data(USB_CMD_SET_ADDR,USB_DAT_WR_BYTE(USBC_DEV_EN | adr)); /* Setup Status Phase */ +} + +void lpc_usb_config_device(int fConfigured) +{ + lpc_write_cmd_data(USB_CMD_CFG_DEV,USB_DAT_WR_BYTE(fConfigured ? USBC_CONF_DEVICE : 0)); /* Setup Status Phase */ +} + +void lpc_usb_reset(void) +{ + USBEpIntClr = 0xFFFFFFFF; + USBEpIntEn = 0xFFFFFFFF ^ USB_DMA_EP; + USBDevIntClr = 0xFFFFFFFF; + USBDevIntEn = USBDevInt_DEV_STAT | USBDevInt_EP_SLOW; + + lpc_usb_configEP(0x00, USB_MAX_PACKET0); + lpc_usb_configEP(0x80, USB_MAX_PACKET0); +} + +void lpc_usb_hw_init (void) +{ + + PINSEL1 &= ~0xC000C000; +// PINSEL1 |= 0x40004000; /* Select USB Link, VBUS */ + PINSEL1 |= 0x80000000; /* Select USB Link, VBUS */ + + PCONP |= 0x80000000; /* Turn On USB PCLK */ + + /* Configure 48MHz USB Clock; FOsc = 12MHz, M = 4, P = 2 */ + PLLCFG48 = 0x23; /* M = 4, P = 2 */ + PLLCON48 = PLLCON_PLLE; /* PLL Enable */ + PLLFEED48 = 0xAA; /* Feed Sequence 1 */ + PLLFEED48 = 0x55; /* Feed Sequence 2 */ + + while ((PLLSTAT48 & PLLSTAT_LOCK) == 0); /* Wait for PLL Lock */ + + PLLCON48 = PLLCON_PLLE | PLLCON_PLLC; /* PLL Enable & Connect */ + PLLFEED48 = 0xAA; /* Feed Sequence 1 */ + PLLFEED48 = 0x55; /* Feed Sequence 2 */ + + USBDevIntEn = USBDevInt_DEV_STAT; /* Enable Device Status Interrupt */ + + /* Partial Manual Reset since Automatic Bus Reset is not working */ + lpc_usb_reset(); + lpc_usb_set_addr(0); +} + +/* + * lpc_usb_read_endpoint: Read USB Endpoint Data + * @EPNum: Endpoint Number - EPNum.0..3: Address, EPNum.7: Dir + * @ptr: Pointer to Data Buffer + * @size: + * Return Value: Number of bytes read + */ +int lpc_usb_read_endpoint( unsigned int ep_num, void *ptr, int size) +{ + unsigned int cnt,i,dwData; + unsigned char *p=ptr; + + USBCtrl = ((ep_num & 0x0F) << 2) | USBCtrl_RD_EN; + do { + cnt = USBRxPLen; + } while ((cnt & USBRxPLen_PKT_RDY) == 0); + cnt &= USBRxPLen_PKT_LNGTH; + + // get data + while (USBCtrl & USBCtrl_RD_EN) { + dwData = USBRxData; + if (p != NULL) { + for (i = 0; i < 4; i++) { + if (size-- != 0) { + *p = dwData & 0xFF; + p++; + } + dwData >>= 8; + } + } + } + + lpc_write_cmd(USB_CMD_SEL_EP(lpc_ep2addr(ep_num))); + lpc_write_cmd(USB_CMD_CLR_BUF); + + return cnt; +} + +/* + * lpc_usb_write_endpoint: Write USB Endpoint Data + * @ep_num: Endpoint Number - ep_num.0..3: Address, ep_num.7: Dir + * @ptr: Pointer to Data Buffer + * @size: Number of bytes to write + * Return Value: Number of bytes written + */ +int lpc_usb_write_endpoint( unsigned int ep_num, const void *ptr, int size) +{ + unsigned int n; + const unsigned char *p=ptr; + + USBCtrl = ((ep_num & 0x0F) << 2) | USBCtrl_WR_EN; + USBTxPLen = size; + + for (n = 0; n < (size + 3) / 4; n++) { + USBTxData = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]; + p += 4; + } + + USBCtrl=0; + + lpc_write_cmd(USB_CMD_SEL_EP(lpc_ep2addr(ep_num))); + lpc_write_cmd(USB_CMD_VALID_BUF); + + return size; +}