• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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