|
1 /* Cypress West Bridge API source file (cyasusb.c) |
|
2 ## =========================== |
|
3 ## |
|
4 ## Copyright Cypress Semiconductor Corporation, 2006-2009, |
|
5 ## All Rights Reserved |
|
6 ## UNPUBLISHED, LICENSED SOFTWARE. |
|
7 ## |
|
8 ## CONFIDENTIAL AND PROPRIETARY INFORMATION |
|
9 ## WHICH IS THE PROPERTY OF CYPRESS. |
|
10 ## |
|
11 ## Use of this file is governed |
|
12 ## by the license agreement included in the file |
|
13 ## |
|
14 ## <install>/license/license.txt |
|
15 ## |
|
16 ## where <install> is the Cypress software |
|
17 ## installation root directory path. |
|
18 ## |
|
19 ## =========================== |
|
20 */ |
|
21 |
|
22 #include "cyashal.h" |
|
23 #include "cyasusb.h" |
|
24 #include "cyaserr.h" |
|
25 #include "cyaslowlevel.h" |
|
26 #include "cyasdma.h" |
|
27 |
|
28 typedef enum CyAsPhysicalEndpointState |
|
29 { |
|
30 CyAsEPFree, |
|
31 CyAsEPIn, |
|
32 CyAsEPOut, |
|
33 CyAsEPIsoIn, |
|
34 CyAsEPIsoOut |
|
35 } CyAsPhysicalEndpointState; |
|
36 |
|
37 |
|
38 /* |
|
39 * This map is used to map an index between 1 and 10 to a logical endpoint number. This |
|
40 * is used to map LEP register indexes into actual EP numbers. |
|
41 */ |
|
42 static CyAsEndPointNumber_t EndPointMap[] = { 3, 5, 7, 9, 10, 11, 12, 13, 14, 15 } ; |
|
43 |
|
44 #define CY_AS_EPCFG_1024 (1 << 3) |
|
45 #define CY_AS_EPCFG_DBL (0x02) |
|
46 #define CY_AS_EPCFG_TRIPLE (0x03) |
|
47 #define CY_AS_EPCFG_QUAD (0x00) |
|
48 |
|
49 /* |
|
50 * NB: This table contains the register values for PEP1 and PEP3. PEP2 and PEP4 only |
|
51 * have a bit to change the direction of the PEP and therefre are not represented |
|
52 * in this table. |
|
53 */ |
|
54 static uint8_t PepRegisterValues[12][4] = |
|
55 { |
|
56 /* Bit 1:0 buffering, 0 = quad, 2 = double, 3 = triple */ |
|
57 /* Bit 3 size, 0 = 512, 1 = 1024 */ |
|
58 { |
|
59 CY_AS_EPCFG_DBL, |
|
60 CY_AS_EPCFG_DBL, |
|
61 }, /* Config 1 - PEP1 (2 * 512), PEP2 (2 * 512), PEP3 (2 * 512), PEP4 (2 * 512) */ |
|
62 { |
|
63 CY_AS_EPCFG_DBL, |
|
64 CY_AS_EPCFG_QUAD, |
|
65 }, /* Config 2 - PEP1 (2 * 512), PEP2 (2 * 512), PEP3 (4 * 512), PEP4 (N/A) */ |
|
66 { |
|
67 CY_AS_EPCFG_DBL, |
|
68 CY_AS_EPCFG_DBL | CY_AS_EPCFG_1024, |
|
69 }, /* Config 3 - PEP1 (2 * 512), PEP2 (2 * 512), PEP3 (2 * 1024), PEP4(N/A) */ |
|
70 { |
|
71 CY_AS_EPCFG_QUAD, |
|
72 CY_AS_EPCFG_DBL, |
|
73 }, /* Config 4 - PEP1 (4 * 512), PEP2 (N/A), PEP3 (2 * 512), PEP4 (2 * 512) */ |
|
74 { |
|
75 CY_AS_EPCFG_QUAD, |
|
76 CY_AS_EPCFG_QUAD, |
|
77 }, /* Config 5 - PEP1 (4 * 512), PEP2 (N/A), PEP3 (4 * 512), PEP4 (N/A) */ |
|
78 { |
|
79 CY_AS_EPCFG_QUAD, |
|
80 CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, |
|
81 }, /* Config 6 - PEP1 (4 * 512), PEP2 (N/A), PEP3 (2 * 1024), PEP4 (N/A) */ |
|
82 { |
|
83 CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, |
|
84 CY_AS_EPCFG_DBL, |
|
85 }, /* Config 7 - PEP1 (2 * 1024), PEP2 (N/A), PEP3 (2 * 512), PEP4 (2 * 512) */ |
|
86 { |
|
87 CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, |
|
88 CY_AS_EPCFG_QUAD, |
|
89 }, /* Config 8 - PEP1 (2 * 1024), PEP2 (N/A), PEP3 (4 * 512), PEP4 (N/A) */ |
|
90 { |
|
91 CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, |
|
92 CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, |
|
93 }, /* Config 9 - PEP1 (2 * 1024), PEP2 (N/A), PEP3 (2 * 1024), PEP4 (N/A)*/ |
|
94 { |
|
95 CY_AS_EPCFG_TRIPLE, |
|
96 CY_AS_EPCFG_TRIPLE, |
|
97 }, /* Config 10 - PEP1 (3 * 512), PEP2 (N/A), PEP3 (3 * 512), PEP4 (2 * 512)*/ |
|
98 { |
|
99 CY_AS_EPCFG_TRIPLE | CY_AS_EPCFG_1024, |
|
100 CY_AS_EPCFG_DBL, |
|
101 }, /* Config 11 - PEP1 (3 * 1024), PEP2 (N/A), PEP3 (N/A), PEP4 (2 * 512) */ |
|
102 { |
|
103 CY_AS_EPCFG_QUAD | CY_AS_EPCFG_1024, |
|
104 CY_AS_EPCFG_DBL, |
|
105 }, /* Config 12 - PEP1 (4 * 1024), PEP2 (N/A), PEP3 (N/A), PEP4 (N/A) */ |
|
106 } ; |
|
107 |
|
108 static CyAsReturnStatus_t |
|
109 FindEndpointDirections(CyAsDevice *dev_p, CyAsPhysicalEndpointState epstate[4]) |
|
110 { |
|
111 int i ; |
|
112 CyAsPhysicalEndpointState desired ; |
|
113 |
|
114 /* |
|
115 * Note, there is no error checking here becuase ISO error checking happens when |
|
116 * the API is called. |
|
117 */ |
|
118 for(i = 0 ; i < 10 ; i++) |
|
119 { |
|
120 int epno = EndPointMap[i] ; |
|
121 if (dev_p->usb_config[epno].enabled) |
|
122 { |
|
123 int pep = dev_p->usb_config[epno].physical ; |
|
124 if (dev_p->usb_config[epno].type == CyAsUsbIso) |
|
125 { |
|
126 /* |
|
127 * Marking this as an ISO endpoint, removes the physical EP from consideration when |
|
128 * mapping the remaining EPs. |
|
129 */ |
|
130 if (dev_p->usb_config[epno].dir == CyAsUsbIn) |
|
131 desired = CyAsEPIsoIn ; |
|
132 else |
|
133 desired = CyAsEPIsoOut ; |
|
134 } |
|
135 else |
|
136 { |
|
137 if (dev_p->usb_config[epno].dir == CyAsUsbIn) |
|
138 desired = CyAsEPIn ; |
|
139 else |
|
140 desired = CyAsEPOut ; |
|
141 } |
|
142 |
|
143 /* NB: Note the API calls insure that an ISO endpoint has a physical and logical |
|
144 * EP number that are the same, therefore this condition is not enforced here. |
|
145 */ |
|
146 if (epstate[pep - 1] != CyAsEPFree && epstate[pep - 1] != desired) |
|
147 return CY_AS_ERROR_INVALID_CONFIGURATION ; |
|
148 |
|
149 epstate[pep - 1] = desired ; |
|
150 } |
|
151 } |
|
152 |
|
153 /* |
|
154 * Create the EP1 config values directly. |
|
155 * Both EP1OUT and EP1IN are invalid by default. |
|
156 */ |
|
157 dev_p->usb_ep1cfg[0] = 0 ; |
|
158 dev_p->usb_ep1cfg[1] = 0 ; |
|
159 if (dev_p->usb_config[1].enabled) |
|
160 { |
|
161 if ((dev_p->usb_config[1].dir == CyAsUsbOut) || (dev_p->usb_config[1].dir == CyAsUsbInOut)) |
|
162 { |
|
163 /* Set the valid bit and type field. */ |
|
164 dev_p->usb_ep1cfg[0] = (1 << 7) ; |
|
165 if (dev_p->usb_config[1].type == CyAsUsbBulk) |
|
166 dev_p->usb_ep1cfg[0] |= (2 << 4) ; |
|
167 else |
|
168 dev_p->usb_ep1cfg[0] |= (3 << 4) ; |
|
169 } |
|
170 |
|
171 if ((dev_p->usb_config[1].dir == CyAsUsbIn) || (dev_p->usb_config[1].dir == CyAsUsbInOut)) |
|
172 { |
|
173 /* Set the valid bit and type field. */ |
|
174 dev_p->usb_ep1cfg[1] = (1 << 7) ; |
|
175 if (dev_p->usb_config[1].type == CyAsUsbBulk) |
|
176 dev_p->usb_ep1cfg[1] |= (2 << 4) ; |
|
177 else |
|
178 dev_p->usb_ep1cfg[1] |= (3 << 4) ; |
|
179 } |
|
180 } |
|
181 |
|
182 return CY_AS_ERROR_SUCCESS ; |
|
183 } |
|
184 |
|
185 static void |
|
186 CreateRegisterSettings(CyAsDevice *dev_p, CyAsPhysicalEndpointState epstate[4]) |
|
187 { |
|
188 int i ; |
|
189 uint8_t v ; |
|
190 |
|
191 for(i = 0 ; i < 4 ; i++) |
|
192 { |
|
193 if (i == 0) |
|
194 dev_p->usb_pepcfg[i] = PepRegisterValues[dev_p->usb_phy_config - 1][0] ; /* Start with the values that specify size */ |
|
195 else if (i == 2) |
|
196 dev_p->usb_pepcfg[i] = PepRegisterValues[dev_p->usb_phy_config - 1][1] ; /* Start with the values that specify size */ |
|
197 else |
|
198 dev_p->usb_pepcfg[i] = 0 ; |
|
199 |
|
200 if (epstate[i] == CyAsEPIsoIn || epstate[i] == CyAsEPIn) |
|
201 dev_p->usb_pepcfg[i] |= (1 << 6) ; /* Adjust direction if it is in */ |
|
202 } |
|
203 |
|
204 /* Configure the logical EP registers */ |
|
205 for(i = 0 ; i < 10 ; i++) |
|
206 { |
|
207 int val ; |
|
208 int epnum = EndPointMap[i] ; |
|
209 |
|
210 v = 0x10 ; /* PEP 1, Bulk Endpoint, EP not valid */ |
|
211 if (dev_p->usb_config[epnum].enabled) |
|
212 { |
|
213 v |= (1 << 7) ; /* Enabled */ |
|
214 |
|
215 val = dev_p->usb_config[epnum].physical - 1 ; |
|
216 CyAsHalAssert(val >= 0 && val <= 3) ; |
|
217 v |= (val << 5) ; |
|
218 |
|
219 switch(dev_p->usb_config[epnum].type) |
|
220 { |
|
221 case CyAsUsbBulk: |
|
222 val = 2 ; |
|
223 break ; |
|
224 case CyAsUsbInt: |
|
225 val = 3 ; |
|
226 break ; |
|
227 case CyAsUsbIso: |
|
228 val = 1 ; |
|
229 break ; |
|
230 default: |
|
231 CyAsHalAssert(CyFalse) ; |
|
232 break ; |
|
233 } |
|
234 v |= (val << 3) ; |
|
235 } |
|
236 |
|
237 dev_p->usb_lepcfg[i] = v ; |
|
238 } |
|
239 } |
|
240 |
|
241 |
|
242 CyAsReturnStatus_t |
|
243 CyAsUsbMapLogical2Physical(CyAsDevice *dev_p) |
|
244 { |
|
245 CyAsReturnStatus_t ret ; |
|
246 |
|
247 /* Physical EPs 3 5 7 9 respectively in the array */ |
|
248 CyAsPhysicalEndpointState epstate[4] = { CyAsEPFree, CyAsEPFree, CyAsEPFree, CyAsEPFree } ; |
|
249 |
|
250 /* Find the direction for the endpoints */ |
|
251 ret = FindEndpointDirections(dev_p, epstate) ; |
|
252 if (ret != CY_AS_ERROR_SUCCESS) |
|
253 return ret ; |
|
254 |
|
255 /* |
|
256 * Now create the register settings based on the given assigned of logical EPs to |
|
257 * physical endpoints. |
|
258 */ |
|
259 CreateRegisterSettings(dev_p, epstate) ; |
|
260 |
|
261 return ret ; |
|
262 } |
|
263 |
|
264 static uint16_t |
|
265 GetMaxDmaSize(CyAsDevice *dev_p, CyAsEndPointNumber_t ep) |
|
266 { |
|
267 uint16_t size = dev_p->usb_config[ep].size ; |
|
268 |
|
269 if (size == 0) |
|
270 { |
|
271 switch(dev_p->usb_config[ep].type) |
|
272 { |
|
273 case CyAsUsbControl: |
|
274 size = 64 ; |
|
275 break ; |
|
276 |
|
277 case CyAsUsbBulk: |
|
278 size = CyAsDeviceIsUsbHighSpeed(dev_p) ? 512 : 64 ; |
|
279 break ; |
|
280 |
|
281 case CyAsUsbInt: |
|
282 size = CyAsDeviceIsUsbHighSpeed(dev_p) ? 1024 : 64 ; |
|
283 break ; |
|
284 |
|
285 case CyAsUsbIso: |
|
286 size = CyAsDeviceIsUsbHighSpeed(dev_p) ? 1024 : 1023 ; |
|
287 break ; |
|
288 } |
|
289 } |
|
290 |
|
291 return size ; |
|
292 } |
|
293 |
|
294 CyAsReturnStatus_t |
|
295 CyAsUsbSetDmaSizes(CyAsDevice *dev_p) |
|
296 { |
|
297 CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ; |
|
298 uint32_t i ; |
|
299 |
|
300 for(i = 0 ; i < 10 ; i++) |
|
301 { |
|
302 CyAsUsbEndPointConfig *config_p = &dev_p->usb_config[EndPointMap[i]] ; |
|
303 if (config_p->enabled) |
|
304 { |
|
305 ret = CyAsDmaSetMaxDmaSize(dev_p, EndPointMap[i], GetMaxDmaSize(dev_p, EndPointMap[i])) ; |
|
306 if (ret != CY_AS_ERROR_SUCCESS) |
|
307 break ; |
|
308 } |
|
309 } |
|
310 |
|
311 return ret ; |
|
312 } |
|
313 |
|
314 CyAsReturnStatus_t |
|
315 CyAsUsbSetupDma(CyAsDevice *dev_p) |
|
316 { |
|
317 CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ; |
|
318 uint32_t i ; |
|
319 |
|
320 for(i = 0 ; i < 10 ; i++) |
|
321 { |
|
322 CyAsUsbEndPointConfig *config_p = &dev_p->usb_config[EndPointMap[i]] ; |
|
323 if (config_p->enabled) |
|
324 { |
|
325 /* Map the endpoint direction to the DMA direction */ |
|
326 CyAsDmaDirection dir = CyAsDirectionOut ; |
|
327 if (config_p->dir == CyAsUsbIn) |
|
328 dir = CyAsDirectionIn ; |
|
329 |
|
330 ret = CyAsDmaEnableEndPoint(dev_p, EndPointMap[i], CyTrue, dir) ; |
|
331 if (ret != CY_AS_ERROR_SUCCESS) |
|
332 break ; |
|
333 } |
|
334 } |
|
335 |
|
336 return ret ; |
|
337 } |