]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - embedded/libs4c/usb/lpcusb/lpcusb.c
Included ARM LPC21xx related code from uLan project. The snapshot date is 2008-07-05
[lincan.git] / 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 (file)
index 0000000..1cf130d
--- /dev/null
@@ -0,0 +1,195 @@
+/*****************************************************/
+/***   Module : USB PDI                            ***/
+/***   Author : Roman Bartosinski (C) 28.04.2002   ***/
+/***   Modify : 08.08.2002, 16.04.2003             ***/
+/*****************************************************/
+
+#include <system_def.h>
+#include <usb/usb.h>
+#include <usb/lpcusb.h>
+
+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;
+}