]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/libs4c/usb/lpcusb/lpcusb.c
Update of system-less architecture and board support code to actual uLAN.sf.net version.
[lincan.git] / embedded / libs4c / usb / lpcusb / lpcusb.c
1 /*****************************************************/
2 /***   Module : USB PDI                            ***/
3 /***   Author : Roman Bartosinski (C) 28.04.2002   ***/
4 /***   Modify : 08.08.2002, 16.04.2003             ***/
5 /*****************************************************/
6
7 #include <system_def.h>
8 #include <usb/usb.h>
9 #include <usb/lpcusb.h>
10
11 #ifdef MACH_LPC17XX
12  #include <LPC17xx.h>
13  #include <lpcUSB.h>
14  #ifndef PINSEL1
15   #define PINSEL1 (PINCON->PINSEL1)
16   #define PINSEL3 (PINCON->PINSEL3)
17   #define PINSEL4 (PINCON->PINSEL4)
18  #endif
19  #ifndef PCONP
20   #define PCONP (SC->PCONP)
21  #endif
22 #endif
23
24 #ifndef USB_VBUS_PIN_USED
25 #define USB_VBUS_PIN_USED 1
26 #endif
27
28 unsigned int lpc_ep2addr(unsigned int ep_num) 
29 {
30   unsigned int val;
31   val = (ep_num & 0x0F) << 1;
32   if (ep_num & 0x80) 
33     val += 1;
34   return val;
35
36
37 void lpc_wait4devint(unsigned int intrs) 
38 {
39   while ((USBDevIntSt & intrs) != intrs);
40   USBDevIntClr = intrs;  
41 }
42
43
44 void lpc_write_cmd(unsigned int cmd) 
45 {
46   USBDevIntClr = USBDevInt_CCEMTY | USBDevInt_CDFULL;
47   USBCmdCode = cmd;
48   lpc_wait4devint(USBDevInt_CCEMTY);
49 }
50
51 void lpc_write_cmd_data (unsigned int cmd, unsigned int val) 
52 {
53   lpc_write_cmd(cmd);
54   USBCmdCode = val;
55   lpc_wait4devint(USBDevInt_CCEMTY);
56 }
57
58 unsigned int lpc_read_cmd_data (unsigned int cmd)
59 {
60   lpc_write_cmd(cmd);
61   lpc_wait4devint(USBDevInt_CDFULL);
62   return USBCmdData;
63
64
65 void lpc_usb_realizeEP(unsigned int idx,unsigned int wmaxpsize)
66 {
67   USBReEp |= (1 << idx);
68   USBEpInd = idx;
69   USBMaxPSize = wmaxpsize;
70   lpc_wait4devint(USBDevInt_EP_RLZED);
71 }
72
73 void lpc_usb_configEP(unsigned int ep_num,unsigned int wmaxpsize)
74 {
75   lpc_usb_realizeEP(lpc_ep2addr(ep_num),wmaxpsize);
76   lpc_usb_enableEP(ep_num);
77 }
78
79 void lpc_usb_setstallEP(unsigned int ep_num) 
80 {
81   lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(USBC_EP_STAT_ST));
82 }
83
84 void lpc_usb_clrstallEP(unsigned int ep_num) 
85 {
86   lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(0));
87 }
88
89 void lpc_usb_enableEP(unsigned int ep_num) 
90 {
91   lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(0));
92 }
93
94 void lpc_usb_disableEP(unsigned int ep_num) 
95 {
96   lpc_write_cmd_data(USB_CMD_SET_EP_STAT(lpc_ep2addr(ep_num)),USB_DAT_WR_BYTE(USBC_EP_STAT_DA));
97 }
98
99 void lpc_usb_set_addr(unsigned int adr)
100 {
101   lpc_write_cmd_data(USB_CMD_SET_ADDR,USB_DAT_WR_BYTE(USBC_DEV_EN | adr)); /*  Setup Status Phase */
102 }
103
104 void lpc_usb_config_device(int fConfigured)
105 {
106   lpc_write_cmd_data(USB_CMD_CFG_DEV,USB_DAT_WR_BYTE(fConfigured ? USBC_CONF_DEVICE : 0)); /*  Setup Status Phase */
107 }
108
109 void lpc_usb_reset(void)
110 {
111   USBEpIntClr  = 0xFFFFFFFF;
112   USBEpIntEn   = 0xFFFFFFFF ^ USB_DMA_EP;
113   USBDevIntClr = 0xFFFFFFFF;
114   USBDevIntEn  = USBDevInt_DEV_STAT | USBDevInt_EP_SLOW;
115
116   lpc_usb_configEP(0x00, USB_MAX_PACKET0);
117   lpc_usb_configEP(0x80, USB_MAX_PACKET0);
118 }
119
120 void lpc_usb_hw_init (void) 
121 {
122
123 #if defined(INC_LPC214x_H) || defined(MACH_LPC21XX)
124   PINSEL1 &= ~0xC000C000;
125 //  PINSEL1 |=  0x40004000;                   /* Select USB Link, VBUS */
126   PINSEL1 |=  0x80000000;                   /* Select USB Link, VBUS */
127
128   PCONP |= 0x80000000;                      /* Turn On USB PCLK */
129
130   /* Configure 48MHz USB Clock;  FOsc = 12MHz, M = 4, P = 2 */
131   PLLCFG48  = 0x23;                         /* M = 4, P = 2 */
132   PLLCON48  = PLLCON_PLLE;                  /* PLL Enable */
133   PLLFEED48 = 0xAA;                         /* Feed Sequence 1 */
134   PLLFEED48 = 0x55;                         /* Feed Sequence 2 */
135
136   while ((PLLSTAT48 & PLLSTAT_LOCK) == 0);  /* Wait for PLL Lock */
137
138   PLLCON48  = PLLCON_PLLE | PLLCON_PLLC;    /* PLL Enable & Connect */
139   PLLFEED48 = 0xAA;                         /* Feed Sequence 1 */
140   PLLFEED48 = 0x55;                         /* Feed Sequence 2 */
141
142   USBDevIntEn  = USBDevInt_DEV_STAT;        /* Enable Device Status Interrupt */
143 #endif /* MACH_LPC21XX */
144
145 #if defined(MACH_LPC23XX) || defined(MACH_LPC17XX)
146   /**
147    ** ** ATTENTION **
148    ** USB clock (48MHz) should be set up externally before calling this fn
149    ** by setting USBCLKCFG (eg. USBCLKCFG = 5 for f_cco=288MHz).
150    ** If some of the pins shared with USB device are to be used for
151    ** different purpose, following PINSELs must be changed after retutn
152    ** from this fn.
153    **/
154
155   /* set up USB pins */
156   PINSEL1 = (PINSEL1 & ~(0x3<<26)) | (0x1<<26);  /* USB_D+,- @ P0.29,30 */
157   PINSEL4 = (PINSEL4 & ~(0x3<<18)) | (0x1<<18);  /* USB_CONNECT @ P2.9 */
158 #if USB_VBUS_PIN_USED
159   PINSEL3 = (PINSEL3 & ~(0x3<<28)) | (0x2<<28);  /* Vbus @ P1.30 */
160 #endif
161   /* switch USB power on */
162   PCONP |= 1<<31;
163   /* switch USB internal clock switch on */
164   USBClkCtrl = 0x12;
165   while ((USBClkSt & 0x12) != 0x12);
166
167 #endif /* MACH_LPC23XX */
168
169   /* Partial Manual Reset since Automatic Bus Reset is not working */
170   lpc_usb_reset();
171   lpc_usb_set_addr(0);
172 }
173
174 /*
175  * lpc_usb_read_endpoint: Read USB Endpoint Data
176  * @EPNum: Endpoint Number - EPNum.0..3: Address, EPNum.7: Dir
177  * @ptr: Pointer to Data Buffer
178  * @size:
179  * Return Value: Number of bytes read
180  */
181 int lpc_usb_read_endpoint( unsigned int ep_num, void *ptr, int size)
182 {
183   unsigned int cnt,i,dwData;
184   unsigned char *p=ptr;
185
186   USBCtrl = ((ep_num & 0x0F) << 2) | USBCtrl_RD_EN;
187   do {
188     cnt = USBRxPLen;
189   } while ((cnt & USBRxPLen_PKT_RDY) == 0);
190   cnt &= USBRxPLen_PKT_LNGTH;
191
192   // get data
193   while (USBCtrl & USBCtrl_RD_EN) {
194     dwData = USBRxData;
195     if (p != NULL) {
196       for (i = 0; (i < 4) && size; i++) {
197         size--;
198         *p = dwData & 0xFF;
199         p++;
200         dwData >>= 8;
201       }
202     }
203   }
204
205   lpc_write_cmd(USB_CMD_SEL_EP(lpc_ep2addr(ep_num)));
206   lpc_write_cmd(USB_CMD_CLR_BUF);
207
208   return cnt;
209 }
210
211 /*
212  * lpc_usb_write_endpoint: Write USB Endpoint Data
213  * @ep_num: Endpoint Number - ep_num.0..3: Address, ep_num.7: Dir
214  * @ptr: Pointer to Data Buffer
215  * @size:   Number of bytes to write
216  * Return Value:    Number of bytes written
217  */
218 int lpc_usb_write_endpoint( unsigned int ep_num, const void *ptr, int size)
219 {
220   unsigned int n;
221   const unsigned char *p=ptr;
222
223   USBCtrl = ((ep_num & 0x0F) << 2) | USBCtrl_WR_EN;
224   USBTxPLen = size;
225
226   for (n = 0; n < (size + 3) / 4; n++) {
227     USBTxData = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
228     p += 4;
229   }
230
231   USBCtrl=0;
232
233   lpc_write_cmd(USB_CMD_SEL_EP(lpc_ep2addr(ep_num)));
234   lpc_write_cmd(USB_CMD_VALID_BUF);
235
236   return size;
237 }