blob: 74d6adb83a5e04fed50e66a626787fbdeeae6a8c [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/* ==========================================================================
2 * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
3 * $Revision: #101 $
4 * $Date: 2012/08/10 $
5 * $Change: 2047372 $
6 *
7 * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
8 * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9 * otherwise expressly agreed to in writing between Synopsys and you.
10 *
11 * The Software IS NOT an item of Licensed Software or Licensed Product under
12 * any End User Software License Agreement or Agreement for Licensed Product
13 * with Synopsys or any supplement thereto. You are permitted to use and
14 * redistribute this Software in source and binary forms, with or without
15 * modification, provided that redistributions of source code must retain this
16 * notice. You may not view, use, disclose, copy or distribute this file or
17 * any information contained herein except pursuant to this license grant from
18 * Synopsys. If you do not agree with this notice, including the disclaimer
19 * below, then you are not authorized to use the Software.
20 *
21 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 * DAMAGE.
32 * ========================================================================== */
33#ifndef DWC_HOST_ONLY
34
35/** @file
36 * This file implements PCD Core. All code in this file is portable and doesn't
37 * use any OS specific functions.
38 * PCD Core provides Interface, defined in <code><dwc_otg_pcd_if.h></code>
39 * header file, which can be used to implement OS specific PCD interface.
40 *
41 * An important function of the PCD is managing interrupts generated
42 * by the DWC_otg controller. The implementation of the DWC_otg device
43 * mode interrupt service routines is in dwc_otg_pcd_intr.c.
44 *
45 * @todo Add Device Mode test modes (Test J mode, Test K mode, etc).
46 * @todo Does it work when the request size is greater than DEPTSIZ
47 * transfer size
48 *
49 */
50#include "global.h"
51#include "dwc_otg_pcd.h"
52
53__align(4) const dwc_device_descriptor_t device_desc =
54{
55 sizeof(dwc_device_descriptor_t),
56 DEVICE_DESCRIPTOR,
57 0x0200, // usb 2.0 //usb 1.1
58 0x00,
59 0x00,
60 0x00,
61 CONTROL_64, // ×î´ó°ü8×Ö½Ú
62 USB_VENDOR_ID,
63 USB_PRODUCT_ID,
64 PRODUCT_RELEASE_NUMBER,
65 0x01, // manufacturer descriptionË÷ÒýºÅ
66 0x02, // product descriptionË÷ÒýºÅ
67 0x03, // serial number descriptionË÷ÒýºÅ
68 0x01 // ÅäÖÃÊý
69};
70
71__align(4) const dwc_dev_qual_descriptor_t dev_qual_desc =
72{
73 sizeof(dwc_dev_qual_descriptor_t),
74 0x06,
75 0x0200, // usb 2.0
76 VERDOR_SPECIFIC,
77 0x00,
78 0x00,
79 64,
80 0x01, // ÅäÖÃÊý
81 0x0
82};
83
84
85
86__align(4) const dwc_langid_descriptor_t tLanguage=
87{
88 STRING_DESCRIPTOR_SIZE(1),
89 STRING_DESCRIPTOR,
90 LANGID_US_ENGLISH
91};
92
93__align(4) const dwc_string_descriptor_t tManufacture=
94{
95 STRING_DESCRIPTOR_SIZE(11),
96 STRING_DESCRIPTOR,
97 UNICODE('Z'), UNICODE('T'), UNICODE('E'), UNICODE(' '), UNICODE('C'),
98 UNICODE('o'), UNICODE(','), UNICODE('L'), UNICODE('t'), UNICODE('d'),
99 UNICODE('.'),
100};
101
102__align(4) const dwc_string_descriptor_t tProduct=
103{
104 STRING_DESCRIPTOR_SIZE(14),
105 STRING_DESCRIPTOR,
106 UNICODE('Z'), UNICODE('T'), UNICODE('E'), UNICODE(' '), UNICODE('B'),
107 UNICODE('o'), UNICODE('o'), UNICODE('t'), UNICODE('L'), UNICODE('o'),
108 UNICODE('a'), UNICODE('d'), UNICODE('e'), UNICODE('r')
109};
110
111__align(4) const dwc_string_descriptor_t tSN=
112{
113 STRING_DESCRIPTOR_SIZE(16),
114 STRING_DESCRIPTOR,
115 UNICODE('z'), UNICODE('t'), UNICODE('e'), UNICODE('&'), UNICODE('u'),
116 UNICODE('s'), UNICODE('b'), UNICODE('B'), UNICODE('o'), UNICODE('o'),
117 UNICODE('t'), UNICODE('l'), UNICODE('o'), UNICODE('d'), UNICODE('e'),
118 UNICODE('r')
119};
120
121__align(4) const dwc_string_descriptor_t tIfc0Name=
122 {
123 STRING_DESCRIPTOR_SIZE(9),
124 STRING_DESCRIPTOR,
125 UNICODE('B'), UNICODE('o'), UNICODE('o'), UNICODE('t'), UNICODE('l'),
126 UNICODE('o'), UNICODE('d'), UNICODE('e'), UNICODE('r')
127 };
128
129__align(4) const dwc_string_descriptor_t tIfc1Name=
130 {
131 STRING_DESCRIPTOR_SIZE(6),
132 STRING_DESCRIPTOR,
133 UNICODE('S'), UNICODE('e'), UNICODE('r'), UNICODE('i'), UNICODE('a'),
134 UNICODE('l')
135 };
136
137__align(4) const dwc_string_descriptor_t * const pStrDescIdx[]=
138{
139 (dwc_string_descriptor_t *)(&tLanguage),
140 (dwc_string_descriptor_t *)&tManufacture,
141 (dwc_string_descriptor_t *)&tProduct,
142 (dwc_string_descriptor_t *)&tSN,
143 (dwc_string_descriptor_t *)&tIfc0Name,
144 (dwc_string_descriptor_t *)&tIfc1Name,
145};
146
147
148static void do_get_descriptor(dwc_otg_pcd_t * pcd,uint32_t *buff,uint32_t len)
149{
150
151 dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
152 pcd->ep0_pending = 1;
153 ep0->dwc_ep.start_xfer_buff =(uint8_t*) buff;
154 ep0->dwc_ep.xfer_buff =(uint8_t*)buff;
155 ep0->dwc_ep.xfer_len = len;
156 ep0->dwc_ep.xfer_count = 0;
157 ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
158 dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
159
160}
161
162extern void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val);
163
164int dwc_setup(dwc_otg_pcd_t * pcd, usb_device_request_t * ctrl)
165{
166 uint8_t byIdx;
167 uint32_t len = 0;
168 uint16_t value;
169 byIdx = (uint8_t)(ctrl->wValue &0xff);
170 value = ctrl->wValue>>8;
171
172 if( USB_DT_DEVICE ==value )
173 {
174 len = MIN( sizeof(dwc_device_descriptor_t), ctrl->wLength);
175 do_get_descriptor(pcd,(uint32_t*)&device_desc,len);
176 }
177 else if( USB_DT_CONFIG==value )
178 {
179 len = MIN( sizeof(dwc_config_all_t), ctrl->wLength);
180 do_get_descriptor(pcd,(uint32_t*)&g_config_desc,len);
181 }
182
183 else if( USB_DT_STRING ==value)
184 {
185 len = MIN(((dwc_string_descriptor_t*)(pStrDescIdx[byIdx]))->bLength, ctrl->wLength);
186 do_get_descriptor(pcd,(uint32_t*)pStrDescIdx[byIdx],len);
187 }
188
189 else if( USB_DT_INTERFACE == value)
190 {
191 len = MIN(((dwc_string_descriptor_t*)(pStrDescIdx[byIdx]))->bLength, ctrl->wLength);
192 do_get_descriptor(pcd,(uint32_t*)pStrDescIdx[byIdx],len);
193 }
194 else if( ENDPOINT_DESCRIPTOR == value)
195 {
196 len = MIN(((dwc_string_descriptor_t*)(pStrDescIdx[byIdx]))->bLength, ctrl->wLength);
197 do_get_descriptor(pcd,(uint32_t*)pStrDescIdx[byIdx],len);
198 }
199 else if( USB_DT_DEVICE_QUALIFIER ==value)
200 {
201 len = MIN(sizeof(dwc_dev_qual_descriptor_t),ctrl->wLength);
202 do_get_descriptor(pcd,(uint32_t*)&dev_qual_desc,len);
203 }
204 else
205 {
206 ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
207 }
208
209 return 0;
210}
211
212
213static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
214 uint32_t is_in, uint32_t ep_num)
215{
216 /* Init EP structure */
217 pcd_ep->desc = 0;
218 pcd_ep->pcd = pcd;
219 pcd_ep->stopped = 1;
220 pcd_ep->queue_sof = 0;
221
222 /* Init DWC ep structure */
223 pcd_ep->dwc_ep.is_in = is_in;
224 pcd_ep->dwc_ep.num = ep_num;
225 pcd_ep->dwc_ep.active = 0;
226 pcd_ep->dwc_ep.tx_fifo_num = 0;
227 /* Control until ep is actvated */
228 pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_BULK;
229 pcd_ep->dwc_ep.maxpacket = 512;
230 pcd_ep->dwc_ep.maxxfer = 65536;
231
232 pcd_ep->dwc_ep.start_xfer_buff = 0;
233 pcd_ep->dwc_ep.xfer_buff = 0;
234 pcd_ep->dwc_ep.xfer_len = 0;
235 pcd_ep->dwc_ep.xfer_count = 0;
236 pcd_ep->dwc_ep.sent_zlp = 0;
237 pcd_ep->dwc_ep.total_len = 0;
238}
239
240/**
241 * Initialize ep's
242 */
243static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
244{
245 int i;
246 uint32_t hwcfg1;
247 dwc_otg_pcd_ep_t *ep;
248 int in_ep_cntr, out_ep_cntr;
249 uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
250 uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
251
252 /**
253 * Initialize the EP0 structure.
254 */
255 pcd->ep0.dwc_ep.pPara = (void*)(&global.g_in_pPara[1]);
256
257 ep = &pcd->ep0;
258 dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
259
260 in_ep_cntr = 0;
261 hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
262 for (i = 1; in_ep_cntr < num_in_eps; i++)
263 {
264 if ((hwcfg1 & 0x1) == 0)
265 {
266 pcd->in_ep[in_ep_cntr].dwc_ep.pPara = (void*)(&global.g_in_pPara[in_ep_cntr]);
267 ep = &pcd->in_ep[in_ep_cntr];
268 in_ep_cntr++;
269 /**
270 * @todo NGS: Add direction to EP, based on contents
271 * of HWCFG1. Need a copy of HWCFG1 in pcd structure?
272 * sprintf(";r
273 */
274 dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
275 }
276 hwcfg1 >>= 2;
277 }
278
279 out_ep_cntr = 0;
280 hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
281 for (i = 1; out_ep_cntr < num_out_eps; i++)
282 {
283 if ((hwcfg1 & 0x1) == 0)
284 {
285 pcd->out_ep[out_ep_cntr].dwc_ep.pPara = (void*)(&global.g_out_pPara[out_ep_cntr]);
286 ep = &pcd->out_ep[out_ep_cntr];
287 out_ep_cntr++;
288 /**
289 * @todo NGS: Add direction to EP, based on contents
290 * of HWCFG1. Need a copy of HWCFG1 in pcd structure?
291 * sprintf(";r
292 */
293 dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
294 }
295 hwcfg1 >>= 2;
296 }
297 if(NEED_ENUM == global.g_enum)
298 {
299 pcd->ep0state = EP0_DISCONNECT;
300 }
301 else
302 {
303 pcd->ep0state = EP0_IDLE;
304
305 }
306 pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
307 pcd->ep0.dwc_ep.type = 0;
308}
309
310/**
311 * This function initialized the PCD portion of the driver.
312 *
313 */
314dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
315{
316 dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)&global.g_dwc_otg_pcd_tp;
317 int i;
318 uint8_t* pt_dwc_otg_pcd_t = (uint8_t*)&global.g_dwc_otg_pcd_tp;
319 for(i = 0;i<sizeof(dwc_otg_pcd_t);i++)
320 {
321 pt_dwc_otg_pcd_t[i] = 0;
322 }
323
324 pcd->core_if = core_if;
325
326 pcd->setup_pkt = global.g_u_setup_pkt;
327 pcd->status_buf = &global.g_status_buf;
328 dwc_otg_pcd_reinit(pcd);
329
330 return pcd;
331
332
333}
334
335
336/******************************************************************************/
337
338#endif /* DWC_HOST_ONLY */