1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18 /** @page USBHW
19 *
20 * Introduction
21 * ===============
22 * USB hard ware .
23 *
24 * API Reference
25 * ===============
26 * Header File: usbhw.h
27 */
28
29 #pragma once
30
31 #include "analog.h"
32 #include "gpio.h"
33 #include "reg_include/register_b91.h"
34
35 typedef enum {
36 USB_IRQ_RESET_MASK = BIT(0),
37 USB_IRQ_250US_MASK = BIT(1),
38 USB_IRQ_SUSPEND_MASK = BIT(2),
39 } usb_irq_mask_e;
40
41 typedef enum {
42 USB_IRQ_RESET_STATUS = BIT(5),
43 USB_IRQ_250US_STATUS = BIT(6),
44 USB_IRQ_SUSPEND_STATUS = BIT(7),
45 } usb_irq_status_e;
46
47 /**
48 * @brief This function servers to set ed8 to fifo mode.
49 * @return none.
50 */
usbhw_set_ep8_fifo_mode(void)51 static inline void usbhw_set_ep8_fifo_mode(void)
52 {
53 BM_SET(reg_usb_ep8_fifo_mode, FLD_USB_ENP8_FIFO_MODE);
54 }
55
56 /**
57 * @brief This function servers to reset the pointer of control Endpoint.
58 * @return none.
59 */
usbhw_reset_ctrl_ep_ptr(void)60 static inline void usbhw_reset_ctrl_ep_ptr(void)
61 {
62 reg_ctrl_ep_ptr = 0;
63 }
64
65 /**
66 * @brief This function servers to get the irq status of control Endpoint.
67 * @return none.
68 */
usbhw_get_ctrl_ep_irq(void)69 static inline unsigned int usbhw_get_ctrl_ep_irq(void)
70 {
71 return reg_ctrl_ep_irq_sta;
72 }
73
74 /**
75 * @brief This function servers to clear the irq status of control Endpoint.
76 * @param[in] ep - selected the Endpoint
77 * @return none.
78 */
usbhw_clr_ctrl_ep_irq(int ep)79 static inline void usbhw_clr_ctrl_ep_irq(int ep)
80 {
81 #ifdef WIN32
82 BM_CLR(reg_ctrl_ep_irq_sta, ep);
83 #else
84 reg_ctrl_ep_irq_sta = ep;
85 #endif
86 }
87
88 /**
89 * @brief This function servers to set the value of control Endpoint.
90 * @param[in] data - the value of control Endpoint
91 * @return none.
92 */
usbhw_write_ctrl_ep_ctrl(unsigned char data)93 static inline void usbhw_write_ctrl_ep_ctrl(unsigned char data)
94 {
95 reg_ctrl_ep_ctrl = data;
96 }
97
98 /**
99 * @brief This function servers to read the data of control Endpoint.
100 * @return the value of control Endpoint data
101 */
usbhw_read_ctrl_ep_data(void)102 static inline unsigned char usbhw_read_ctrl_ep_data(void)
103 {
104 return reg_ctrl_ep_dat;
105 }
106
107 /**
108 * @brief This function servers to write the data of control Endpoint.
109 * @param[in] data - the data of control Endpoint to write
110 * @return none
111 */
usbhw_write_ctrl_ep_data(unsigned char data)112 static inline void usbhw_write_ctrl_ep_data(unsigned char data)
113 {
114 reg_ctrl_ep_dat = data;
115 }
116
117 /**
118 * @brief This function servers to determine whether control Endpoint is busy.
119 * @return 1: busy; 0: not busy.
120 */
usbhw_is_ctrl_ep_busy(void)121 static inline int usbhw_is_ctrl_ep_busy(void)
122 {
123 return reg_ctrl_ep_irq_sta & FLD_USB_EP_BUSY;
124 }
125
126 /**
127 * @brief This function servers to reset the pointer of Endpoint.
128 * @param[in] ep - select the Endpoint
129 * @return none.
130 */
usbhw_reset_ep_ptr(unsigned int ep)131 static inline void usbhw_reset_ep_ptr(unsigned int ep)
132 {
133 reg_usb_ep_ptr(ep) = 0;
134 }
135
136 /**
137 * @brief This function servers to set the irq mask of Endpoint.
138 * @return none.
139 */
usbhw_set_eps_irq_mask(usb_ep_irq_e mask)140 static inline void usbhw_set_eps_irq_mask(usb_ep_irq_e mask)
141 {
142 reg_usb_ep_irq_mask |= mask;
143 }
144
145 /**
146 * @brief This function servers to clr the irq mask of Endpoint.
147 * @return none.
148 */
usbhw_clr_eps_irq_mask(usb_ep_irq_e mask)149 static inline void usbhw_clr_eps_irq_mask(usb_ep_irq_e mask)
150 {
151 reg_usb_ep_irq_mask &= (~mask);
152 }
153
154 /**
155 * @brief This function servers to get the irq status of Endpoint.
156 * @return none.
157 */
usbhw_get_eps_irq(void)158 static inline unsigned int usbhw_get_eps_irq(void)
159 {
160 return reg_usb_ep_irq_status;
161 }
162
163 /**
164 * @brief This function servers to clear the irq status of Endpoint.
165 * @param[in] ep - selected the Endpoint
166 * @return none.
167 */
usbhw_clr_eps_irq(int ep)168 static inline void usbhw_clr_eps_irq(int ep)
169 {
170 reg_usb_ep_irq_status = ep;
171 }
172
173 /**
174 * @brief This function servers to set usb irq mask.
175 * @param[in] mask -the irq mask of usb.
176 * @return none.
177 */
usbhw_set_irq_mask(usb_irq_mask_e mask)178 static inline void usbhw_set_irq_mask(usb_irq_mask_e mask)
179 {
180 reg_usb_irq_mask |= mask;
181 }
182
183 /**
184 * @brief This function servers to clr usb irq mask.
185 * @param[in] mask -the irq mask of usb.
186 * @return none.
187 */
usbhw_clr_irq_mask(usb_irq_mask_e mask)188 static inline void usbhw_clr_irq_mask(usb_irq_mask_e mask)
189 {
190 reg_usb_irq_mask &= (~mask);
191 }
192
193 /**
194 * @brief This function servers to get usb irq status.
195 * @param[in] status -the irq status of usb.
196 * @return the status of irq.
197 */
usbhw_get_irq_status(usb_irq_status_e status)198 static inline unsigned char usbhw_get_irq_status(usb_irq_status_e status)
199 {
200 return reg_usb_irq_mask & status;
201 }
202
203 /**
204 * @brief This function servers to clr usb irq status.
205 * @param[in] status -the irq status of usb.
206 * @return none.
207 */
usbhw_clr_irq_status(usb_irq_status_e status)208 static inline void usbhw_clr_irq_status(usb_irq_status_e status)
209 {
210 reg_usb_irq_mask |= status;
211 }
212
213 /**
214 * @brief This function servers to enable Endpoint.
215 * @param[in] ep - selected the Endpoint
216 * @return none.
217 */
usbhw_set_eps_en(usb_ep_en_e ep)218 static inline void usbhw_set_eps_en(usb_ep_en_e ep)
219 {
220 reg_usb_edp_en = ep;
221 }
222
223 /**
224 * @brief This function servers to enable Endpoint.
225 * @param[in] ep - selected the Endpoint
226 * @return none.
227 */
usbhw_set_eps_dis(usb_ep_en_e ep)228 static inline void usbhw_set_eps_dis(usb_ep_en_e ep)
229 {
230 reg_usb_edp_en &= (~ep);
231 }
232
233 /**
234 * @brief This function servers to read the data of Endpoint.
235 * @param[in] ep - selected the Endpoint
236 * @return the value of Endpoint
237 */
usbhw_read_ep_data(unsigned int ep)238 static inline unsigned char usbhw_read_ep_data(unsigned int ep)
239 {
240 return reg_usb_ep_dat(ep);
241 }
242
243 /**
244 * @brief This function servers to write the data of Endpoint.
245 * @param[in] ep - selected the Endpoint
246 * @param[in] data - the value of Endpoint
247 * @return none
248 */
usbhw_write_ep_data(unsigned int ep,unsigned char data)249 static inline void usbhw_write_ep_data(unsigned int ep, unsigned char data)
250 {
251 reg_usb_ep_dat(ep) = data;
252 }
253
254 /**
255 * @brief This function servers to enable the specified Endpoint.
256 * @param[in] ep - selected the Endpoint
257 * @param[in] en - 1:enable,0:disable
258 * @return none
259 */
usbhw_set_ep_en(unsigned int ep,unsigned char en)260 static inline void usbhw_set_ep_en(unsigned int ep, unsigned char en)
261 {
262 if (en) {
263 reg_usb_edp_en |= ep;
264 } else {
265 reg_usb_edp_en &= ~(ep);
266 }
267 }
268
269 /**
270 * @brief This function servers to determine whether Endpoint is busy.
271 * @param[in] ep - selected the Endpoint
272 * @return 1: busy; 0: not busy.
273 */
usbhw_is_ep_busy(unsigned int ep)274 static inline unsigned int usbhw_is_ep_busy(unsigned int ep)
275 {
276 return reg_usb_ep_ctrl(ep) & FLD_USB_EP_BUSY;
277 }
278
279 /**
280 * @brief This function servers to set the specified data EndPoint to ack.
281 * @param[in] ep - select the data EndPoint.
282 * @return none.
283 */
usbhw_data_ep_ack(unsigned int ep)284 static inline void usbhw_data_ep_ack(unsigned int ep)
285 {
286 reg_usb_ep_ctrl(ep) = FLD_USB_EP_BUSY;
287 }
288
289 /**
290 * @brief This function servers to set the specified data EndPoint to stall.
291 * @param[in] ep - select the data EndPoint.
292 * @return none.
293 */
usbhw_data_ep_stall(unsigned int ep)294 static inline void usbhw_data_ep_stall(unsigned int ep)
295 {
296 reg_usb_ep_ctrl(ep) = FLD_USB_EP_STALL;
297 }
298
299 /**
300 * @brief This function servers to set the threshold of printer.
301 * @param[in] th - set the threshold for printer
302 * @return none.
303 */
usbhw_set_printer_threshold(unsigned char th)304 static inline void usbhw_set_printer_threshold(unsigned char th)
305 {
306 reg_usb_ep8_send_thre = th;
307 }
308
309 enum {
310 USB_EDP_PRINTER_IN = 8, // default hw buf len = 64
311 USB_EDP_MOUSE = 2, // default hw buf len = 8
312 USB_EDP_KEYBOARD_IN = 1, // default hw buf len = 8
313 USB_EDP_IN = 3, // default hw buf len = 16
314 USB_EDP_AUDIO_IN = 4, // default hw buf len = 64
315 USB_EDP_PRINTER_OUT = 5, // default hw buf len = 64
316 USB_EDP_SPEAKER = 6, // default hw buf len = 16
317 USB_EDP_MIC = 7, // default hw buf len = 16
318 USB_EDP_MS_IN = USB_EDP_PRINTER_IN, // mass storage
319 USB_EDP_MS_OUT = USB_EDP_PRINTER_OUT,
320 USB_EDP_SOMATIC_IN = USB_EDP_AUDIO_IN, // when USB_SOMATIC_ENABLE, USB_EDP_PRINTER_OUT disable
321 USB_EDP_SOMATIC_OUT = USB_EDP_PRINTER_OUT,
322 USB_EDP_CDC_IN = 4,
323 USB_EDP_CDC_OUT = 5,
324 };
325
326 // #defined in the standard spec
327 enum {
328 USB_HID_AUDIO = 2,
329 USB_HID_MOUSE = 1,
330 USB_HID_KB_MEDIA = 3, // media
331 USB_HID_KB_SYS = 4, // system : power,sleep,wakeup
332 USB_HID_SOMATIC = 5, // somatic sensor, may have many report ids
333 };
334
335 /**
336 * @brief This function disables the manual interrupt
337 * (Endpont8 is the alias of endpoint0)
338 * @param[in] m - the irq mode needs to set
339 * @return none
340 */
341 void usbhw_disable_manual_interrupt(int m);
342
343 /**
344 * @brief This function enable the manual interrupt
345 * @param[in] m - the irq mode needs to set
346 * @return none
347 */
348 void usbhw_enable_manual_interrupt(int m);
349
350 /**
351 * @brief This function sends a bulk of data to host via the specified endpoint
352 * @param[in] ep - the number of the endpoint
353 * @param[in] data - pointer to the data need to send
354 * @param[in] len - length in byte of the data need to send
355 * @return none
356 */
357 void usbhw_write_ep(unsigned int ep, unsigned char *data, int len);
358
359 /**
360 * @brief This function sends two bytes data to host via the control endpoint
361 * (handy help function)
362 * @param[in] v - the two bytes data need to send
363 * @return none
364 */
365 void usbhw_write_ctrl_ep_u16(unsigned short v);
366
367 /**
368 * @brief This function reads two bytes data from host via the control endpoint
369 * @return the two bytes data read from the control endpoint
370 */
371 unsigned short usbhw_read_ctrl_ep_u16(void);
372
373 /**
374 * @brief This function enables or disables the internal pull-up resistor of DP pin of USB interface
375 * @param[in] en - enables or disables the internal pull-up resistor(1: enable 0: disable)
376 * @return none
377 */
usb_dp_pullup_en(int en)378 static inline void usb_dp_pullup_en(int en)
379 {
380 unsigned char dat = analog_read_reg8(0x0b);
381 if (en) {
382 dat = dat | BIT(7);
383 } else {
384 dat = dat & 0x7f;
385 }
386
387 analog_write_reg8(0x0b, dat);
388 }
389
390 /**
391 * @brief This function serves to power on or down USB module
392 * @param[in] en - 1: power on 0: power down
393 * @return none
394 */
usb_power_on(unsigned char en)395 static inline void usb_power_on(unsigned char en)
396 {
397 if (en) {
398 analog_write_reg8(0x7d, analog_read_reg8(0x7d) & 0xfd);
399 } else {
400 analog_write_reg8(0x7d, analog_read_reg8(0x7d) | 0x02);
401 }
402 }
403
404 /**
405 * @brief This function serves to set GPIO MUX function as DP and DM pin of USB
406 * @return none.
407 */
usb_set_pin_en(void)408 static inline void usb_set_pin_en(void)
409 {
410 reg_gpio_func_mux(GPIO_PA5) = reg_gpio_func_mux(GPIO_PA5) & (~BIT_RNG(2, 3));
411 gpio_function_dis(GPIO_PA5);
412 reg_gpio_func_mux(GPIO_PA6) = reg_gpio_func_mux(GPIO_PA6) & (~BIT_RNG(4, 5));
413 gpio_function_dis(GPIO_PA6);
414 gpio_input_en(GPIO_PA5 | GPIO_PA6); // DP/DM must set input enable
415 usb_dp_pullup_en(1);
416 }
417