Fix common misspellings
[linux-block.git] / drivers / staging / westbridge / astoria / api / src / cyaslep2pep.c
CommitLineData
81eb669b
DC
1/* Cypress West Bridge API source file (cyaslep2pep.c)
2## ===========================
3## Copyright (C) 2010 Cypress Semiconductor
4##
5## This program is free software; you can redistribute it and/or
6## modify it under the terms of the GNU General Public License
7## as published by the Free Software Foundation; either version 2
8## of the License, or (at your option) any later version.
9##
10## This program is distributed in the hope that it will be useful,
11## but WITHOUT ANY WARRANTY; without even the implied warranty of
12## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13## GNU General Public License for more details.
14##
15## You should have received a copy of the GNU General Public License
16## along with this program; if not, write to the Free Software
17## Foundation, Inc., 51 Franklin Street, Fifth Floor
18## Boston, MA 02110-1301, USA.
19## ===========================
20*/
21
22#include "../../include/linux/westbridge/cyashal.h"
23#include "../../include/linux/westbridge/cyasusb.h"
24#include "../../include/linux/westbridge/cyaserr.h"
25#include "../../include/linux/westbridge/cyaslowlevel.h"
26#include "../../include/linux/westbridge/cyasdma.h"
27
28typedef enum cy_as_physical_endpoint_state {
29 cy_as_e_p_free,
30 cy_as_e_p_in,
31 cy_as_e_p_out,
32 cy_as_e_p_iso_in,
33 cy_as_e_p_iso_out
34} cy_as_physical_endpoint_state;
35
36
37/*
38* This map is used to map an index between 1 and 10
39* to a logical endpoint number. This is used to map
40* LEP register indexes into actual EP numbers.
41*/
42static cy_as_end_point_number_t end_point_map[] = {
0769c38d 43 3, 5, 7, 9, 10, 11, 12, 13, 14, 15 };
81eb669b
DC
44
45#define CY_AS_EPCFG_1024 (1 << 3)
46#define CY_AS_EPCFG_DBL (0x02)
47#define CY_AS_EPCFG_TRIPLE (0x03)
48#define CY_AS_EPCFG_QUAD (0x00)
49
50/*
51 * NB: This table contains the register values for PEP1
52 * and PEP3. PEP2 and PEP4 only have a bit to change the
53 * direction of the PEP and therefre are not represented
54 * in this table.
55 */
56static uint8_t pep_register_values[12][4] = {
57 /* Bit 1:0 buffering, 0 = quad, 2 = double, 3 = triple */
58 /* Bit 3 size, 0 = 512, 1 = 1024 */
59 {
60 CY_AS_EPCFG_DBL,
61 CY_AS_EPCFG_DBL,
62 },/* Config 1 - PEP1 (2 * 512), PEP2 (2 * 512),
63 * PEP3 (2 * 512), PEP4 (2 * 512) */
64 {
65 CY_AS_EPCFG_DBL,
66 CY_AS_EPCFG_QUAD,
67 }, /* Config 2 - PEP1 (2 * 512), PEP2 (2 * 512),
68 * PEP3 (4 * 512), PEP4 (N/A) */
69 {
70 CY_AS_EPCFG_DBL,
71 CY_AS_EPCFG_DBL | CY_AS_EPCFG_1024,
72 },/* Config 3 - PEP1 (2 * 512), PEP2 (2 * 512),
73 * PEP3 (2 * 1024), PEP4(N/A) */
74 {
75 CY_AS_EPCFG_QUAD,
76 CY_AS_EPCFG_DBL,
77 },/* Config 4 - PEP1 (4 * 512), PEP2 (N/A),
78 * PEP3 (2 * 512), PEP4 (2 * 512) */
79 {
80 CY_AS_EPCFG_QUAD,
81 CY_AS_EPCFG_QUAD,
82 },/* Config 5 - PEP1 (4 * 512), PEP2 (N/A),
83 * PEP3 (4 * 512), PEP4 (N/A) */
84 {
85 CY_AS_EPCFG_QUAD,
86 CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL,
87 },/* Config 6 - PEP1 (4 * 512), PEP2 (N/A),
88 * PEP3 (2 * 1024), PEP4 (N/A) */
89 {
90 CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL,
91 CY_AS_EPCFG_DBL,
92 },/* Config 7 - PEP1 (2 * 1024), PEP2 (N/A),
93 * PEP3 (2 * 512), PEP4 (2 * 512) */
94 {
95 CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL,
96 CY_AS_EPCFG_QUAD,
97 },/* Config 8 - PEP1 (2 * 1024), PEP2 (N/A),
98 * PEP3 (4 * 512), PEP4 (N/A) */
99 {
100 CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL,
101 CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL,
102 },/* Config 9 - PEP1 (2 * 1024), PEP2 (N/A),
103 * PEP3 (2 * 1024), PEP4 (N/A)*/
104 {
105 CY_AS_EPCFG_TRIPLE,
106 CY_AS_EPCFG_TRIPLE,
107 },/* Config 10 - PEP1 (3 * 512), PEP2 (N/A),
108 * PEP3 (3 * 512), PEP4 (2 * 512)*/
109 {
110 CY_AS_EPCFG_TRIPLE | CY_AS_EPCFG_1024,
111 CY_AS_EPCFG_DBL,
112 },/* Config 11 - PEP1 (3 * 1024), PEP2 (N/A),
113 * PEP3 (N/A), PEP4 (2 * 512) */
114 {
115 CY_AS_EPCFG_QUAD | CY_AS_EPCFG_1024,
116 CY_AS_EPCFG_DBL,
117 },/* Config 12 - PEP1 (4 * 1024), PEP2 (N/A),
118 * PEP3 (N/A), PEP4 (N/A) */
0769c38d 119};
81eb669b
DC
120
121static cy_as_return_status_t
122find_endpoint_directions(cy_as_device *dev_p,
123 cy_as_physical_endpoint_state epstate[4])
124{
0769c38d
DC
125 int i;
126 cy_as_physical_endpoint_state desired;
81eb669b
DC
127
128 /*
25985edc 129 * note, there is no error checking here because
81eb669b
DC
130 * ISO error checking happens when the API is called.
131 */
0769c38d
DC
132 for (i = 0; i < 10; i++) {
133 int epno = end_point_map[i];
81eb669b 134 if (dev_p->usb_config[epno].enabled) {
0769c38d 135 int pep = dev_p->usb_config[epno].physical;
81eb669b
DC
136 if (dev_p->usb_config[epno].type == cy_as_usb_iso) {
137 /*
138 * marking this as an ISO endpoint, removes the
139 * physical EP from consideration when
140 * mapping the remaining E_ps.
141 */
142 if (dev_p->usb_config[epno].dir == cy_as_usb_in)
0769c38d 143 desired = cy_as_e_p_iso_in;
81eb669b 144 else
0769c38d 145 desired = cy_as_e_p_iso_out;
81eb669b
DC
146 } else {
147 if (dev_p->usb_config[epno].dir == cy_as_usb_in)
0769c38d 148 desired = cy_as_e_p_in;
81eb669b 149 else
0769c38d 150 desired = cy_as_e_p_out;
81eb669b
DC
151 }
152
153 /*
154 * NB: Note the API calls insure that an ISO endpoint
155 * has a physical and logical EP number that are the
156 * same, therefore this condition is not enforced here.
157 */
158 if (epstate[pep - 1] !=
159 cy_as_e_p_free && epstate[pep - 1] != desired)
0769c38d 160 return CY_AS_ERROR_INVALID_CONFIGURATION;
81eb669b 161
0769c38d 162 epstate[pep - 1] = desired;
81eb669b
DC
163 }
164 }
165
166 /*
167 * create the EP1 config values directly.
168 * both EP1OUT and EP1IN are invalid by default.
169 */
0769c38d
DC
170 dev_p->usb_ep1cfg[0] = 0;
171 dev_p->usb_ep1cfg[1] = 0;
81eb669b
DC
172 if (dev_p->usb_config[1].enabled) {
173 if ((dev_p->usb_config[1].dir == cy_as_usb_out) ||
174 (dev_p->usb_config[1].dir == cy_as_usb_in_out)) {
175 /* Set the valid bit and type field. */
0769c38d 176 dev_p->usb_ep1cfg[0] = (1 << 7);
81eb669b 177 if (dev_p->usb_config[1].type == cy_as_usb_bulk)
0769c38d 178 dev_p->usb_ep1cfg[0] |= (2 << 4);
81eb669b 179 else
0769c38d 180 dev_p->usb_ep1cfg[0] |= (3 << 4);
81eb669b
DC
181 }
182
183 if ((dev_p->usb_config[1].dir == cy_as_usb_in) ||
184 (dev_p->usb_config[1].dir == cy_as_usb_in_out)) {
185 /* Set the valid bit and type field. */
0769c38d 186 dev_p->usb_ep1cfg[1] = (1 << 7);
81eb669b 187 if (dev_p->usb_config[1].type == cy_as_usb_bulk)
0769c38d 188 dev_p->usb_ep1cfg[1] |= (2 << 4);
81eb669b 189 else
0769c38d 190 dev_p->usb_ep1cfg[1] |= (3 << 4);
81eb669b
DC
191 }
192 }
193
0769c38d 194 return CY_AS_ERROR_SUCCESS;
81eb669b
DC
195}
196
197static void
198create_register_settings(cy_as_device *dev_p,
199 cy_as_physical_endpoint_state epstate[4])
200{
0769c38d
DC
201 int i;
202 uint8_t v;
81eb669b 203
0769c38d 204 for (i = 0; i < 4; i++) {
81eb669b
DC
205 if (i == 0) {
206 /* Start with the values that specify size */
207 dev_p->usb_pepcfg[i] =
208 pep_register_values
0769c38d 209 [dev_p->usb_phy_config - 1][0];
81eb669b
DC
210 } else if (i == 2) {
211 /* Start with the values that specify size */
212 dev_p->usb_pepcfg[i] =
213 pep_register_values
0769c38d 214 [dev_p->usb_phy_config - 1][1];
81eb669b 215 } else
0769c38d 216 dev_p->usb_pepcfg[i] = 0;
81eb669b
DC
217
218 /* Adjust direction if it is in */
219 if (epstate[i] == cy_as_e_p_iso_in ||
220 epstate[i] == cy_as_e_p_in)
0769c38d 221 dev_p->usb_pepcfg[i] |= (1 << 6);
81eb669b
DC
222 }
223
224 /* Configure the logical EP registers */
0769c38d
DC
225 for (i = 0; i < 10; i++) {
226 int val;
227 int epnum = end_point_map[i];
81eb669b 228
0769c38d 229 v = 0x10; /* PEP 1, Bulk Endpoint, EP not valid */
81eb669b 230 if (dev_p->usb_config[epnum].enabled) {
0769c38d 231 v |= (1 << 7); /* Enabled */
81eb669b 232
0769c38d
DC
233 val = dev_p->usb_config[epnum].physical - 1;
234 cy_as_hal_assert(val >= 0 && val <= 3);
235 v |= (val << 5);
81eb669b
DC
236
237 switch (dev_p->usb_config[epnum].type) {
238 case cy_as_usb_bulk:
0769c38d
DC
239 val = 2;
240 break;
81eb669b 241 case cy_as_usb_int:
0769c38d
DC
242 val = 3;
243 break;
81eb669b 244 case cy_as_usb_iso:
0769c38d
DC
245 val = 1;
246 break;
81eb669b 247 default:
0769c38d
DC
248 cy_as_hal_assert(cy_false);
249 break;
81eb669b 250 }
0769c38d 251 v |= (val << 3);
81eb669b
DC
252 }
253
0769c38d 254 dev_p->usb_lepcfg[i] = v;
81eb669b
DC
255 }
256}
257
258
259cy_as_return_status_t
260cy_as_usb_map_logical2_physical(cy_as_device *dev_p)
261{
0769c38d 262 cy_as_return_status_t ret;
81eb669b
DC
263
264 /* Physical EPs 3 5 7 9 respectively in the array */
265 cy_as_physical_endpoint_state epstate[4] = {
266 cy_as_e_p_free, cy_as_e_p_free,
0769c38d 267 cy_as_e_p_free, cy_as_e_p_free };
81eb669b
DC
268
269 /* Find the direction for the endpoints */
0769c38d 270 ret = find_endpoint_directions(dev_p, epstate);
81eb669b 271 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 272 return ret;
81eb669b
DC
273
274 /*
275 * now create the register settings based on the given
276 * assigned of logical E_ps to physical endpoints.
277 */
0769c38d 278 create_register_settings(dev_p, epstate);
81eb669b 279
0769c38d 280 return ret;
81eb669b
DC
281}
282
283static uint16_t
284get_max_dma_size(cy_as_device *dev_p, cy_as_end_point_number_t ep)
285{
0769c38d 286 uint16_t size = dev_p->usb_config[ep].size;
81eb669b
DC
287
288 if (size == 0) {
289 switch (dev_p->usb_config[ep].type) {
290 case cy_as_usb_control:
0769c38d
DC
291 size = 64;
292 break;
81eb669b
DC
293
294 case cy_as_usb_bulk:
295 size = cy_as_device_is_usb_high_speed(dev_p) ?
0769c38d
DC
296 512 : 64;
297 break;
81eb669b
DC
298
299 case cy_as_usb_int:
300 size = cy_as_device_is_usb_high_speed(dev_p) ?
0769c38d
DC
301 1024 : 64;
302 break;
81eb669b
DC
303
304 case cy_as_usb_iso:
305 size = cy_as_device_is_usb_high_speed(dev_p) ?
0769c38d
DC
306 1024 : 1023;
307 break;
81eb669b
DC
308 }
309 }
310
0769c38d 311 return size;
81eb669b
DC
312}
313
314cy_as_return_status_t
315cy_as_usb_set_dma_sizes(cy_as_device *dev_p)
316{
0769c38d
DC
317 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
318 uint32_t i;
81eb669b 319
0769c38d 320 for (i = 0; i < 10; i++) {
81eb669b 321 cy_as_usb_end_point_config *config_p =
0769c38d 322 &dev_p->usb_config[end_point_map[i]];
81eb669b
DC
323 if (config_p->enabled) {
324 ret = cy_as_dma_set_max_dma_size(dev_p,
325 end_point_map[i],
0769c38d 326 get_max_dma_size(dev_p, end_point_map[i]));
81eb669b 327 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 328 break;
81eb669b
DC
329 }
330 }
331
0769c38d 332 return ret;
81eb669b
DC
333}
334
335cy_as_return_status_t
336cy_as_usb_setup_dma(cy_as_device *dev_p)
337{
0769c38d
DC
338 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
339 uint32_t i;
81eb669b 340
0769c38d 341 for (i = 0; i < 10; i++) {
81eb669b 342 cy_as_usb_end_point_config *config_p =
0769c38d 343 &dev_p->usb_config[end_point_map[i]];
81eb669b
DC
344 if (config_p->enabled) {
345 /* Map the endpoint direction to the DMA direction */
0769c38d 346 cy_as_dma_direction dir = cy_as_direction_out;
81eb669b 347 if (config_p->dir == cy_as_usb_in)
0769c38d 348 dir = cy_as_direction_in;
81eb669b
DC
349
350 ret = cy_as_dma_enable_end_point(dev_p,
0769c38d 351 end_point_map[i], cy_true, dir);
81eb669b 352 if (ret != CY_AS_ERROR_SUCCESS)
0769c38d 353 break;
81eb669b
DC
354 }
355 }
356
0769c38d 357 return ret;
81eb669b 358}