• 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_HOST_H
9 #define HPM_USB_HOST_H
10 
11 /*---------------------------------------------------------------------
12  * Includes
13  *---------------------------------------------------------------------
14  */
15 #include "hpm_usb_drv.h"
16 #include "hpm_common.h"
17 #include "hpm_soc_feature.h"
18 
19 /*---------------------------------------------------------------------
20  * Macros
21  *---------------------------------------------------------------------
22  */
23 
24 
25 #ifndef USB_HCD_PERIODIC_ARR_COUNT
26 #define USB_HCD_PERIODIC_ARR_COUNT     (4U)
27 #endif
28 
29 #ifndef USB_HCD_MAX_CONNECTED_DEVICES
30 #define USB_HCD_MAX_CONNECTED_DEVICES  (5U)
31 #endif
32 
33 #ifndef USB_HCD_MAX_QHD_COUNT
34 #define USB_HCD_MAX_QHD_COUNT          (USB_HCD_MAX_CONNECTED_DEVICES * 16U * 2U)
35 #endif
36 
37 #ifndef USB_HCD_MAX_QTD_COUNT
38 #define USB_HCD_MAX_QTD_COUNT          (USB_HCD_MAX_QHD_COUNT * 2U)
39 #endif
40 /*---------------------------------------------------------------------
41  * Enum Declarations
42  *---------------------------------------------------------------------
43  */
44 typedef enum {
45     usb_max_itd  = 4,
46     usb_max_sitd = 16
47 } usb_max_xtd_t;
48 
49 typedef enum {
50     usb_qtype_itd = 0,
51     usb_qtype_qhd,
52     usb_qtype_sitd,
53     usb_qtype_fstn
54 } usb_qtype_t;
55 
56 typedef enum {
57     usb_pid_out = 0,
58     usb_pid_in,
59     usb_pid_setup
60 } usb_pid_t;
61 
62 typedef enum {
63     usb_speed_full = 0,
64     usb_speed_low,
65     usb_speed_high,
66     usb_speed_invalid = 0xff,
67 } usb_speed_t;
68 
69 typedef enum  {
70     usb_cmd_pos_run_stop               = 0,
71     usb_cmd_pos_framelist_szie         = 2,
72     usb_cmd_pos_period_enable          = 4,
73     usb_cmd_pos_async_enable           = 5,
74     usb_cmd_pos_framelist_size_msb     = 15,
75     usb_cmd_pos_interrupt_threshold    = 16
76 } usb_cmd_pos_t;
77 
78 typedef enum {
79     usb_portsc_mask_current_connect_status = HPM_BITSMASK(1, 0),
80     usb_portsc_mask_connect_status_change  = HPM_BITSMASK(1, 1),
81     usb_portsc_mask_port_eanbled           = HPM_BITSMASK(1, 2),
82     usb_portsc_mask_port_enable_chagne     = HPM_BITSMASK(1, 3),
83     usb_portsc_mask_over_current_change    = HPM_BITSMASK(1, 5),
84     usb_portsc_mask_port_reset             = HPM_BITSMASK(1, 8),
85 
86     usb_portsc_mask_all                    = usb_portsc_mask_connect_status_change
87                                            | usb_portsc_mask_port_enable_chagne
88                                            | usb_portsc_mask_over_current_change
89 } usb_portsc_change_mask_t;
90 
91 /* Link pointer */
92 typedef union {
93     volatile uint32_t address;
94     struct  {
95         volatile uint32_t terminate : 1;
96         volatile uint32_t type      : 2;
97     };
98 } hcd_link_t;
99 
100 /* Queue Element Transfer Descriptor */
101 /* Qtd is used to declare overlay in hcd_qhd_t */
102 typedef struct {
103     /* Word 0: Next QTD Pointer */
104     volatile hcd_link_t next;
105 
106     /* Word 1: Alternate Next QTD Pointer (not used) */
107     union{
108         volatile hcd_link_t alternate;
109         struct {
110             volatile  uint32_t                : 5;
111             volatile  uint32_t used           : 1;
112             volatile  uint32_t                : 10;
113             volatile  uint32_t expected_bytes : 16;
114         };
115     };
116 
117     /* Word 2: qTQ Token */
118     volatile uint32_t ping_err             : 1  ; /* For Highspeed: 0 Out, 1 Ping. Full/Slow used as error indicator */
119     volatile uint32_t non_hs_split_state   : 1  ; /* Used by HC to track the state of slipt transaction */
120     volatile uint32_t non_hs_missed_uframe : 1  ; /* HC misses a complete slip transaction */
121     volatile uint32_t xact_err             : 1  ; /* Error (Timeout, CRC, Bad PID ... ) */
122     volatile uint32_t babble_err           : 1  ; /* Babble detected, also set Halted bit to 1 */
123     volatile uint32_t buffer_err           : 1  ; /* Data overrun/underrun error */
124     volatile uint32_t halted               : 1  ; /* Serious error or STALL received */
125     volatile uint32_t active               : 1  ; /* Start transfer, clear by HC when complete */
126     volatile uint32_t pid                  : 2  ; /* 0: OUT, 1: IN, 2 Setup */
127     volatile uint32_t err_count            : 2  ; /* Error Counter of consecutive errors */
128     volatile uint32_t current_page         : 3  ; /* Index into the qTD buffer pointer list */
129     volatile uint32_t int_on_complete      : 1  ; /* Interrupt on complete */
130     volatile uint32_t total_bytes          : 15 ; /* Transfer bytes, decreased during transaction */
131     volatile uint32_t data_toggle          : 1  ; /* Data Toggle bit */
132 
133     /* Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page */
134     volatile uint32_t buffer[USB_SOC_HCD_QTD_BUFFER_COUNT];
135 } hcd_qtd_t;
136 
137 /* Queue Head */
138 typedef struct {
139     /* Word 0: Next QHD */
140     hcd_link_t next;
141 
142     /* Word 1: Endpoint Characteristics */
143     volatile uint32_t dev_addr              : 7  ; /* device address */
144     volatile uint32_t fl_inactive_next_xact : 1  ; /* Only valid for Periodic with Full/Slow speed */
145     volatile uint32_t ep_number             : 4  ; /* EP number */
146     volatile uint32_t ep_speed              : 2  ; /* 0: Full, 1: Low, 2: High */
147     volatile uint32_t data_toggle_control   : 1  ; /* 0: use DT in qHD, 1: use DT in qTD */
148     volatile uint32_t head_list_flag        : 1  ; /* Head of the queue */
149     volatile uint32_t max_packet_size       : 11 ; /* Max packet size */
150     volatile uint32_t fl_ctrl_ep_flag       : 1  ; /* 1 if is Full/Low speed control endpoint */
151     volatile uint32_t nak_reload            : 4  ; /* Used by HC */
152 
153     /* Word 2: Endpoint Capabilities */
154     volatile uint32_t int_smask             : 8  ; /* Interrupt Schedule Mask */
155     volatile uint32_t fl_int_cmask          : 8  ; /* Split Completion Mask for Full/Slow speed */
156     volatile uint32_t fl_hub_addr           : 7  ; /* Hub Address for Full/Slow speed */
157     volatile uint32_t fl_hub_port           : 7  ; /* Hub Port for Full/Slow speed */
158     volatile uint32_t mult                  : 2  ; /* Transaction per micro frame */
159 
160     /* Word 3: Current qTD Pointer */
161     volatile uint32_t qtd_addr;
162 
163     /* Word 4-11: Transfer Overlay */
164     volatile hcd_qtd_t qtd_overlay;
165 
166     /*--------------------------------------------------------------------
167      * Due to the fact QHD is 32 bytes aligned but occupies only 48 bytes
168      * thus there are 16 bytes padding free that we can make use of.
169      *--------------------------------------------------------------------
170      */
171     uint8_t used;
172     uint8_t removing;    /* removed from async list, waiting for async advance */
173     uint8_t pid;
174     uint8_t interval_ms; /* polling interval in frames (or millisecond) */
175 
176     uint16_t total_xferred_bytes; /* number of bytes xferred until a qtd with ioc bit set */
177     uint8_t reserved2[2];
178 
179     hcd_qtd_t * volatile p_qtd_list_head;	/* head of the scheduled TD list */
180     hcd_qtd_t * volatile p_qtd_list_tail;	/* tail of the scheduled TD list */
181 } hcd_qhd_t;
182 
183 typedef struct {
184     hcd_link_t period_framelist[USB_HOST_FRAMELIST_SIZE];
185 
186     /* for ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist)
187      * [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms
188      */
189     hcd_qhd_t period_head_arr[USB_HCD_PERIODIC_ARR_COUNT];
190 
191     /* Note control qhd of dev0 is used as head of async list */
192     struct {
193         hcd_qhd_t qhd;
194         hcd_qtd_t qtd;
195     } control[USB_HCD_MAX_CONNECTED_DEVICES + 1];
196 
197     hcd_qhd_t qhd_pool[USB_HCD_MAX_QHD_COUNT];
198     hcd_qtd_t qtd_pool[USB_HCD_MAX_QTD_COUNT];
199 
200     uint32_t uframe_number;
201 } hcd_data_t;
202 
203 typedef struct {
204     uint8_t     rhport;
205     uint8_t     ep_speed;
206     uint8_t     hub_addr;
207     uint8_t     hub_port;
208     USB_Type    *regs;
209     hcd_data_t  *hcd_data;
210     void (*hcd_vbus_ctrl_cb)(uint8_t rhport, uint8_t level);
211 } usb_host_handle_t;
212 
213 /* USB Endpoint Descriptor */
214 typedef struct __attribute__ ((packed))
215 {
216     uint8_t  bLength;
217     uint8_t  bDescriptorType;
218     uint8_t  bEndpointAddress;
219 
220     struct __attribute__ ((packed)) {
221         uint8_t xfer  : 2;
222         uint8_t sync  : 2;
223         uint8_t usage : 2;
224         uint8_t       : 2;
225     } bmAttributes;
226 
227     struct __attribute__ ((packed)) {
228         uint16_t size           : 11;
229         uint16_t hs_period_mult : 2;
230         uint16_t                : 3;
231     } wMaxPacketSize;
232 
233     uint8_t  bInterval;
234 } usb_desc_endpoint_t;
235 
236 #if defined(__cplusplus)
237 extern "C" {
238 #endif /* __cplusplus */
239 
240 /* Get direction from Endpoint address */
usb_edpt_dir(uint8_t addr)241 static inline usb_dir_t usb_edpt_dir(uint8_t addr)
242 {
243     return (addr & usb_dir_in_mask) ? usb_dir_in : usb_dir_out;
244 }
245 
246 /* Get Endpoint number from address */
usb_edpt_number(uint8_t addr)247 static inline uint8_t usb_edpt_number(uint8_t addr)
248 {
249     return (uint8_t)(addr & (~usb_dir_in_mask));
250 }
251 
252 /* Get Endpoint address */
usb_edpt_addr(uint8_t num,uint8_t dir)253 static inline uint8_t usb_edpt_addr(uint8_t num, uint8_t dir)
254 {
255     return (uint8_t)(num | (dir ? usb_dir_in_mask : 0));
256 }
257 
usb_host_align16(uint32_t value)258 static inline uint32_t usb_host_align16(uint32_t value) { return (value & 0xFFFFFFF0UL); }
usb_host_align32(uint32_t value)259 static inline uint32_t usb_host_align32(uint32_t value) { return (value & 0xFFFFFFE0UL); }
usb_host_align4k(uint32_t value)260 static inline uint32_t usb_host_align4k(uint32_t value) { return (value & 0xFFFFF000UL); }
usb_host_offset4k(uint32_t value)261 static inline uint32_t usb_host_offset4k(uint32_t value) { return (value & 0xFFFUL); }
262 
263 bool usb_host_qhd_has_xact_error(hcd_qhd_t *p_qhd);
264 bool usb_host_qhd_has_xact_error(hcd_qhd_t *p_qhd);
265 void usb_host_qtd_remove_1st_from_qhd(hcd_qhd_t *p_qhd);
266 hcd_link_t *usb_host_list_next(hcd_link_t *p_link_pointer);
267 hcd_link_t *usb_host_get_period_head(usb_host_handle_t *handle, uint8_t interval_ms);
268 hcd_qhd_t *usb_host_qhd_async_head(usb_host_handle_t *handle);
269 hcd_qhd_t *usb_host_qhd_next(hcd_qhd_t const *p_qhd);
270 hcd_qtd_t *usb_host_qtd_control(usb_host_handle_t *handle, uint8_t dev_addr);
271 uint32_t usb_host_uframe_number(usb_host_handle_t *handle);
272 uint32_t usb_host_status_flags(usb_host_handle_t *handle);
273 uint32_t usb_host_interrupts(usb_host_handle_t *handle);
274 void usb_host_clear_status_flags(usb_host_handle_t *handle, uint32_t status);
275 uint8_t  usb_host_get_port_speed(usb_host_handle_t *handle);
276 void usb_host_port_reset(usb_host_handle_t *handle);
277 bool usb_host_init(usb_host_handle_t *handle, uint32_t int_mask, uint16_t framelist_size);
278 bool usb_host_get_port_ccs(usb_host_handle_t *handle);
279 bool usb_host_port_csc(usb_host_handle_t *handle);
280 void usb_host_device_close(usb_host_handle_t *handle, uint8_t dev_addr);
281 bool usb_host_edpt_xfer(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen);
282 bool usb_host_setup_send(usb_host_handle_t *handle, uint8_t dev_addr,  const uint8_t *setup_packet);
283 bool usb_host_edpt_open(usb_host_handle_t *handle, uint8_t dev_addr, usb_desc_endpoint_t const *ep_desc);
284 bool usb_host_pipe_queue_xfer(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes);
285 bool usb_host_pipe_xfer(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete);
286 bool usb_host_edpt_busy(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr);
287 bool usb_host_edpt_stalled(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr);
288 bool usb_host_edpt_clear_stall(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr);
289 
290 #if defined(__cplusplus)
291 }
292 #endif /* __cplusplus */
293 #endif /* HPM_USB_HOST_H */
294