1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_USB_DRV_H
9 #define HPM_USB_DRV_H
10 /*---------------------------------------------------------------------
11 * Includes
12 *---------------------------------------------------------------------
13 */
14 #include "hpm_common.h"
15 #include "hpm_usb_regs.h"
16 #include "hpm_soc_feature.h"
17
18 /**
19 * @brief USB driver APIs
20 * @defgroup usb_interface USB driver APIs
21 * @ingroup communication_interfaces
22 * @{
23 */
24
25 /*---------------------------------------------------------------------
26 * Macro Constant Declarations
27 *---------------------------------------------------------------------
28 */
29 #define USB_PHY_INIT_DELAY_COUNT (16U) /**< a delay count for USB phy initialization */
30 #define USB_HOST_FRAMELIST_SIZE (8U) /**< a frame list size in USB host mode */
31
32 /*---------------------------------------------------------------------
33 * Macro Enum Declarations
34 *---------------------------------------------------------------------
35 */
36 /**
37 * @brief USB transfer direction types
38 */
39 typedef enum {
40 usb_dir_out = 0,
41 usb_dir_in = 1,
42 usb_dir_in_mask = 0x80
43 } usb_dir_t;
44
45 /**
46 * @brief USB transfer types
47 */
48 typedef enum {
49 usb_xfer_control = 0,
50 usb_xfer_isochronous,
51 usb_xfer_bulk,
52 usb_xfer_interrupt
53 } usb_xfer_type_t;
54
55 /**
56 * @brief USB controller work modes
57 */
58 typedef enum {
59 usb_ctrl_mode_otg = 0,
60 usb_ctrl_mode_device = 2,
61 usb_ctrl_mode_host = 3
62 } usb_controller_mode_t;
63
64 /**
65 * @brief USB line state
66 */
67 typedef enum {
68 usb_line_state0 = 0,
69 usb_line_state1 = 1,
70 usb_line_state2 = 2
71 } usb_line_state_t;
72
73 /**
74 * @brief USB transceiver
75 */
76 typedef enum {
77 usb_tran_parallel = 0,
78 usb_tran_serial = 1
79 } usb_transceiver_t;
80 /*---------------------------------------------------------------------
81 * Structure Declarations
82 *---------------------------------------------------------------------
83 */
84 /**
85 * @brief Control request structure
86 */
87 typedef struct __attribute__ ((packed)) {
88 union {
89 struct __attribute__ ((packed)) {
90 uint8_t recipient : 5;
91 uint8_t type : 2;
92 uint8_t direction : 1;
93 } bmRequestType_bit;
94
95 uint8_t bmRequestType;
96 };
97
98 uint8_t bRequest;
99 uint16_t wValue;
100 uint16_t wIndex;
101 uint16_t wLength;
102 } usb_control_request_t;
103
104 /**
105 * @brief Endpoint config structure
106 */
107 typedef struct {
108 uint8_t xfer;
109 uint8_t ep_addr;
110 uint16_t max_packet_size;
111 } usb_endpoint_config_t;
112
113 #if defined __cplusplus
114 extern "C" {
115 #endif /* __cplusplus */
116
117 /*---------------------------------------------------------------------
118 * Common API
119 *---------------------------------------------------------------------
120 */
121
122 /**
123 * @brief Get the mask of all enabled interrupts
124 *
125 * @param[in] ptr A USB peripheral base address.
126 * @retval Mask of all enabled interrupts.
127 */
usb_get_interrupts(USB_Type * ptr)128 static inline uint32_t usb_get_interrupts(USB_Type *ptr)
129 {
130 return ptr->USBINTR;
131 }
132
133 /**
134 * @brief Enable interrupts
135 *
136 * @param[in] ptr A USB peripheral base address
137 * @param[in] mask Mask value for interrupt events
138 */
usb_enable_interrupts(USB_Type * ptr,uint32_t mask)139 static inline void usb_enable_interrupts(USB_Type *ptr, uint32_t mask)
140 {
141 ptr->USBINTR |= mask;
142 }
143
144 /**
145 * @brief Get all USB status flags
146 *
147 * @param[in] ptr A USB peripheral base address
148 * @retval The USB interrupt status flags
149 */
usb_get_status_flags(USB_Type * ptr)150 static inline uint32_t usb_get_status_flags(USB_Type *ptr)
151 {
152 return ptr->USBSTS;
153 }
154
155 /**
156 * @brief Clear status flags
157 *
158 * Only the specified flags can be cleared by writing USBSTS register.
159 *
160 * @param[in] ptr A USB peripheral base address
161 * @param[in] mask Mask value for flags to be cleared.
162 */
163
usb_clear_status_flags(USB_Type * ptr,uint32_t mask)164 static inline void usb_clear_status_flags(USB_Type *ptr, uint32_t mask)
165 {
166 ptr->USBSTS = mask;
167 }
168
169 /**
170 * @brief Get USB suspend status
171 *
172 * @param[in] ptr A USB peripheral base address
173 * @retval The USB controller suspend status
174 */
usb_get_suspend_status(USB_Type * ptr)175 static inline uint8_t usb_get_suspend_status(USB_Type *ptr)
176 {
177 return USB_PORTSC1_SUSP_GET(ptr->PORTSC1);
178 }
179
180 /**
181 * @brief Get USB reset status
182 *
183 * @param[in] ptr A USB peripheral base address
184 * @retval The USB controller reset status
185 */
usb_get_port_reset_status(USB_Type * ptr)186 static inline bool usb_get_port_reset_status(USB_Type *ptr)
187 {
188 return USB_PORTSC1_PR_GET(ptr->PORTSC1);
189 }
190
191 /**
192 * @brief Get USB current connect status
193 *
194 * @param[in] ptr A USB peripheral base address
195 * @retval The USB controller reset status
196 */
usb_get_port_ccs(USB_Type * ptr)197 static inline bool usb_get_port_ccs(USB_Type *ptr)
198 {
199 return USB_PORTSC1_CCS_GET(ptr->PORTSC1);
200 }
201
202 /**
203 * @brief Get USB port speed status
204 *
205 * @param[in] ptr A USB peripheral base address
206 * @retval The USB controller port speed status
207 */
usb_get_port_speed(USB_Type * ptr)208 static inline uint8_t usb_get_port_speed(USB_Type *ptr)
209 {
210 return USB_PORTSC1_PSPD_GET(ptr->PORTSC1);
211 }
212
213 /**
214 * @brief Initialize USB phy
215 *
216 * @param[in] ptr A USB peripheral base address
217 */
218 void usb_phy_init(USB_Type *ptr);
219
220 /**
221 * @brief USB phy using internal vbus
222 *
223 * @param[in] ptr A USB peripheral base address
224 */
usb_phy_using_internal_vbus(USB_Type * ptr)225 static inline void usb_phy_using_internal_vbus(USB_Type *ptr)
226 {
227 ptr->PHY_CTRL0 |= (USB_PHY_CTRL0_VBUS_VALID_OVERRIDE_MASK | USB_PHY_CTRL0_SESS_VALID_OVERRIDE_MASK)
228 | (USB_PHY_CTRL0_VBUS_VALID_OVERRIDE_EN_MASK | USB_PHY_CTRL0_SESS_VALID_OVERRIDE_EN_MASK);
229 }
230
231 /**
232 * @brief USB phy using external vbus
233 *
234 * @param[in] ptr A USB peripheral base address
235 */
usb_phy_using_external_vbus(USB_Type * ptr)236 static inline void usb_phy_using_external_vbus(USB_Type *ptr)
237 {
238 ptr->PHY_CTRL0 &= ~((USB_PHY_CTRL0_VBUS_VALID_OVERRIDE_MASK | USB_PHY_CTRL0_SESS_VALID_OVERRIDE_MASK)
239 | (USB_PHY_CTRL0_VBUS_VALID_OVERRIDE_EN_MASK | USB_PHY_CTRL0_SESS_VALID_OVERRIDE_EN_MASK));
240 }
241
242 /**
243 * @brief USB phy disconnect dp/dm pins pulldown resistance
244 *
245 * @param[in] ptr A USB peripheral base address
246 */
usb_phy_disable_dp_dm_pulldown(USB_Type * ptr)247 static inline void usb_phy_disable_dp_dm_pulldown(USB_Type *ptr)
248 {
249 ptr->PHY_CTRL0 |= 0x001000E0u;
250 }
251
252 /**
253 * @brief USB phy connect dp/dm pins pulldown resistance
254 *
255 * @param[in] ptr A USB peripheral base address
256 */
usb_phy_enable_dp_dm_pulldown(USB_Type * ptr)257 static inline void usb_phy_enable_dp_dm_pulldown(USB_Type *ptr)
258 {
259 ptr->PHY_CTRL0 &= ~0x001000E0u;
260 }
261
262 /*---------------------------------------------------------------------
263 * Device API
264 *---------------------------------------------------------------------
265 */
266
267 /**
268 * @brief USB device bus reset
269 *
270 * @param[in] ptr A USB peripheral base address
271 * @param[in] ep0_max_packet_size The maximum packet size of endpoint 0
272 */
273 void usb_dcd_bus_reset(USB_Type *ptr, uint16_t ep0_max_packet_size);
274
275 /**
276 * @brief Initialize controller to device mode
277 *
278 * @param[in] ptr A USB peripheral base address
279 */
280 void usb_dcd_init(USB_Type *ptr);
281
282 /**
283 * @brief Deinitialize controller to device
284 *
285 * @param[in] ptr A USB peripheral base address
286 */
287 void usb_dcd_deinit(USB_Type *ptr);
288
289 /**
290 * @brief Wakeup from host
291 *
292 * @param[in] ptr A USB peripheral base address
293 */
294 void usb_dcd_remote_wakeup(USB_Type *ptr);
295
296 /**
297 * @brief Open an endpoint
298 *
299 * @param[in] ptr A USB peripheral base address
300 * @param[in] config A pointer to the specified endpoint config struct
301 */
302 void usb_dcd_edpt_open(USB_Type *ptr, usb_endpoint_config_t *config);
303
304 /**
305 * @brief get a specified endpoint type
306 *
307 * @param[in] ptr A USB peripheral base address
308 * @param[in] ep_addr Endpoint address
309 */
310 uint8_t usb_dcd_edpt_get_type(USB_Type *ptr, uint8_t ep_addr);
311
312 /**
313 * @brief Submit a transfer
314 *
315 * @param[in] ptr A USB peripheral base address
316 * @param[in] ep_idx An index of the specified endpoint
317 */
318 void usb_dcd_edpt_xfer(USB_Type *ptr, uint8_t ep_idx);
319
320 /**
321 * @brief Stall endpoint
322 *
323 * @param[in] ptr A USB peripheral base address
324 * @param[in] ep_addr An address of the specified endpoint
325 */
326 void usb_dcd_edpt_stall(USB_Type *ptr, uint8_t ep_addr);
327
328 /**
329 * @brief Clear stall
330 *
331 * @param[in] ptr A USB peripheral base address
332 * @param[in] ep_addr An address of the specified endpoint
333 */
334 void usb_dcd_edpt_clear_stall(USB_Type *ptr, uint8_t ep_addr);
335
336 /**
337 * @brief Clear stall
338 *
339 * @param[in] ptr A USB peripheral base address
340 * @param[in] ep_addr An address of the specified endpoint
341 * @retval The status of endpoint stall, true is stall, false is not stall
342 */
343 bool usb_dcd_edpt_check_stall(USB_Type *ptr, uint8_t ep_addr);
344
345 /**
346 * @brief Close a specified endpoint
347 *
348 * @param[in] ptr A USB peripheral base address
349 * @param[in] ep_addr An address of the specified endpoint
350 */
351 void usb_dcd_edpt_close(USB_Type *ptr, uint8_t ep_addr);
352
353 /**
354 * @brief Connect by enabling internal pull-up resistor on D+/D-
355 *
356 * @param[in] ptr A USB peripheral base address
357 */
358 void usb_dcd_connect(USB_Type *ptr);
359
360 /**
361 * @brief Disconnect by disabling internal pull-up resistor on D+/D-
362 *
363 * @param[in] ptr A USB peripheral base address
364 */
365 void usb_dcd_disconnect(USB_Type *ptr);
366
367 /**
368 * @brief Get setup status of endpoint
369 *
370 * @param[in] ptr A USB peripheral base address
371 * @retval The status of setup endpoint
372 */
usb_dcd_get_edpt_setup_status(USB_Type * ptr)373 static inline uint32_t usb_dcd_get_edpt_setup_status(USB_Type *ptr)
374 {
375 return ptr->ENDPTSETUPSTAT;
376 }
377
378 /**
379 * @brief Clear the setup status of all specified endpoints
380 *
381 * @param[in] ptr A USB peripheral base address
382 * @param[in] mask A mask of all specified endpoints
383 */
usb_dcd_clear_edpt_setup_status(USB_Type * ptr,uint32_t mask)384 static inline void usb_dcd_clear_edpt_setup_status(USB_Type *ptr, uint32_t mask)
385 {
386 ptr->ENDPTSETUPSTAT = mask;
387 }
388
389 /**
390 * @brief Set address
391 *
392 * @param[in] ptr A USB peripheral base address
393 * @param[in] dev_addr An assigned endpoint address from USB host
394 */
usb_dcd_set_address(USB_Type * ptr,uint8_t dev_addr)395 static inline void usb_dcd_set_address(USB_Type *ptr, uint8_t dev_addr)
396 {
397 ptr->DEVICEADDR = USB_DEVICEADDR_USBADR_SET(dev_addr) | USB_DEVICEADDR_USBADRA_MASK;
398 }
399
400 /**
401 * @brief Set endpoint list address
402 *
403 * @param[in] ptr A USB peripheral base address
404 * @param[in] addr A start address of the endpoint qtd list
405 */
usb_dcd_set_edpt_list_addr(USB_Type * ptr,uint32_t addr)406 static inline void usb_dcd_set_edpt_list_addr(USB_Type *ptr, uint32_t addr)
407 {
408 ptr->ENDPTLISTADDR = addr & USB_ENDPTLISTADDR_EPBASE_MASK;
409 }
410
411 /**
412 * @brief Get device address
413 *
414 * @param[in] ptr A USB peripheral base address
415 * @retval The endpoint address
416 */
usb_dcd_get_device_addr(USB_Type * ptr)417 static inline uint8_t usb_dcd_get_device_addr(USB_Type *ptr)
418 {
419 return USB_DEVICEADDR_USBADR_GET(ptr->DEVICEADDR);
420 }
421
422 /**
423 * @brief Get complete status of endpoint
424 *
425 * @param[in] ptr A USB peripheral base address
426 * @retval The complete status od endpoint
427 */
usb_dcd_get_edpt_complete_status(USB_Type * ptr)428 static inline uint32_t usb_dcd_get_edpt_complete_status(USB_Type *ptr)
429 {
430 return ptr->ENDPTCOMPLETE;
431 }
432
433 /**
434 * @brief Clear complete status of endpoint
435 *
436 * @param[in] ptr A USB peripheral base address
437 * @param[in] mask A mask of the specified endpoints
438 */
usb_dcd_clear_edpt_complete_status(USB_Type * ptr,uint32_t mask)439 static inline void usb_dcd_clear_edpt_complete_status(USB_Type *ptr, uint32_t mask)
440 {
441 ptr->ENDPTCOMPLETE = mask;
442 }
443
444 /*---------------------------------------------------------------------
445 * Host API
446 *---------------------------------------------------------------------
447 */
448 /**
449 * @brief Initialize controller to host mode
450 *
451 * @param[in] ptr A USB peripheral base address
452 * @param[in] int_mask A mask of all required interrupts
453 * @param[in] framelist_size A size of the frame list
454 */
455 bool usb_hcd_init(USB_Type *ptr, uint32_t int_mask, uint16_t framelist_size);
456
457 /**
458 * @brief Initialize controller to host modeHost Reset port
459 *
460 * @param[in] ptr A USB peripheral base address
461 */
462 void usb_hcd_port_reset(USB_Type *ptr);
463
464 /**
465 * @brief Initialize controller to host modeHost set command register
466 *
467 * @param[in] ptr A USB peripheral base address
468 * @param[in] mask A mask of all required commands
469 */
usb_hcd_set_command(USB_Type * ptr,uint32_t mask)470 static inline void usb_hcd_set_command(USB_Type *ptr, uint32_t mask)
471 {
472 ptr->USBCMD |= mask;
473 }
474
475 /**
476 * @brief Get frame index
477 *
478 * @param[in] ptr A USB peripheral base address
479 * @retval A index of the current frame list
480 */
usb_hcd_get_frame_index(USB_Type * ptr)481 static inline uint32_t usb_hcd_get_frame_index(USB_Type *ptr)
482 {
483 return ptr->FRINDEX;
484 }
485
486 /**
487 * @brief Get port connect status change
488 *
489 * @param[in] ptr A USB peripheral base address
490 * @retval A connect status change
491 */
usb_hcd_get_port_csc(USB_Type * ptr)492 static inline bool usb_hcd_get_port_csc(USB_Type *ptr)
493 {
494 return USB_PORTSC1_CSC_GET(ptr->PORTSC1);
495 }
496
497 /**
498 * @brief Set power ctrl polarity
499 *
500 * @param[in] ptr A USB peripheral base address
501 * @param[in] high true - vbus high level enable, false - vbus low level enable
502 */
usb_hcd_set_power_ctrl_polarity(USB_Type * ptr,bool high)503 static inline void usb_hcd_set_power_ctrl_polarity(USB_Type *ptr, bool high)
504 {
505 if (high) {
506 ptr->OTG_CTRL0 |= USB_OTG_CTRL0_OTG_POWER_MASK_MASK;
507 } else {
508 ptr->OTG_CTRL0 &= ~USB_OTG_CTRL0_OTG_POWER_MASK_MASK;
509 }
510 }
511
512 /**
513 * @brief Enable port power
514 *
515 * @param[in] ptr A USB peripheral base address
516 */
usb_hcd_enable_port_power(USB_Type * ptr)517 static inline void usb_hcd_enable_port_power(USB_Type *ptr)
518 {
519 ptr->PORTSC1 |= USB_PORTSC1_PP_MASK;
520 }
521
522 /**
523 * @brief Get port connect status changeSet async list address
524 *
525 * @param[in] ptr A USB peripheral base address
526 * @param[in] addr An the start address of the async endpoint list
527 */
usb_hcd_set_async_list_addr(USB_Type * ptr,uint32_t addr)528 static inline void usb_hcd_set_async_list_addr(USB_Type *ptr, uint32_t addr)
529 {
530 ptr->ASYNCLISTADDR = addr & USB_ASYNCLISTADDR_ASYBASE_MASK;
531 }
532
533 /**
534 * @brief Set periodic list address
535 *
536 * @param[in] ptr A USB peripheral base address
537 * @param[in] addr An start address of the periodic endpoint list
538 */
usb_hcd_set_periodic_list_addr(USB_Type * ptr,uint32_t addr)539 static inline void usb_hcd_set_periodic_list_addr(USB_Type *ptr, uint32_t addr)
540 {
541 ptr->PERIODICLISTBASE = addr & USB_PERIODICLISTBASE_BASEADR_MASK;
542 }
543
544 /**
545 * @brief Start hcd controller
546 *
547 * @param[in] ptr A USB peripheral base address
548 */
usb_hcd_run(USB_Type * ptr)549 static inline void usb_hcd_run(USB_Type *ptr)
550 {
551 ptr->USBCMD |= USB_USBCMD_RS_MASK;
552 }
553
554 /**
555 * @brief Stop hcd controller
556 *
557 * @param[in] ptr A USB peripheral base address
558 */
usb_hcd_stop(USB_Type * ptr)559 static inline void usb_hcd_stop(USB_Type *ptr)
560 {
561 ptr->USBCMD &= ~USB_USBCMD_RS_MASK;
562 }
563
564 #if defined __cplusplus
565 }
566 #endif /* __cplusplus */
567
568 /** @} */
569 #endif /* HPM_USB_DRV_H */
570