1 /*******************************************************************************
2 * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * PolarFire SoC MSS USB Driver Stack
7 * USB Core Interface Layer (USB-CIFL)
8 * USBD-CIF driver
9 *
10 * USBD-CIF driver implementation:
11 * This file implements MSS USB core initialization in device mode and
12 * implements core interface function for the logical layer to control the
13 * MSS USB core in USB Device mode.
14 *
15 */
16 #include "mpfs_hal/mss_hal.h"
17 #include "mss_usb_device_cif.h"
18 #include "mss_usb_common_cif.h"
19 #include "mss_usb_device_reg_io.h"
20 #include "mss_usb_common_reg_io.h"
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25
26 #ifdef MSS_USB_DEVICE_ENABLED
27
28 /***************************************************************************//**
29 These pointers are used for holding the Receive transfer parameters (Buffer
30 address, length) etc. This pointer will be updated in
31 MSS_USBD_CIF_rx_ep_read_prepare() API and used in
32 MSS_USB_CIF_handle_rx_ep_irq().
33 */
34 volatile mss_usbd_cep_state_t cep_state;
35
36 /***************************************************************************//**
37 EXPORTED APIs
38 ******************************************************************************/
39
40 /***************************************************************************//**
41 This function initializes the MSS USB core in Device mode.
42 */
43 volatile uint32_t reg=0;
44 void
MSS_USBD_CIF_init(mss_usb_device_speed_t speed)45 MSS_USBD_CIF_init
46 (
47 mss_usb_device_speed_t speed
48 )
49 {
50 cep_state = MSS_USB_CTRL_EP_IDLE;
51
52 /*TODO: Avoid resetting twice in DualRole mode*/
53 MSS_USB_CIF_soft_reset();
54 MSS_USB_CIF_clr_usb_irq_reg();
55
56 /*Reset and Resume are by default enabled in INTRUSBE reg after soft reset*/
57 PLIC_EnableIRQ(USB_DMA_PLIC);
58 PLIC_EnableIRQ(USB_MC_PLIC);
59
60 MSS_USB_CIF_rx_ep_disable_irq_all();
61 MSS_USB_CIF_tx_ep_disable_irq_all();
62
63 if(MSS_USB_DEVICE_FS == speed)
64 {
65 MSS_USB_CIF_disable_hs_mode();
66 }
67
68 /*This was added during Compliance testing. Refer MUSB section 3.8.5*/
69 USB->C_T_HSBT = 0x01u;
70 }
71
72 /***************************************************************************//**
73 Provides the information about the MSS USB core configuration
74 */
75 void
MSS_USBD_CIF_get_hwcore_info(mss_usb_core_info_t * hw_core)76 MSS_USBD_CIF_get_hwcore_info
77 (
78 mss_usb_core_info_t* hw_core
79 )
80 {
81 MSS_USB_CIF_set_index_reg(MSS_USB_CEP);
82 hw_core->core_max_nbr_of_tx_ep = (USB->EP_INFO & 0x0Fu); /*lower nibble for txep*/
83 hw_core->core_max_nbr_of_rx_ep = ((USB->EP_INFO & 0xF0u) >> 4u);/*higher nibble for txep*/
84 hw_core->core_ram_bus_width = (USB->RAM_INFO & 0x0Fu);/*lower nibble for bus width*/
85 hw_core->core_max_nbr_of_dma_chan = ((USB->RAM_INFO & 0xF0u) >> 4u);/*higher nibble for dma channels*/
86 hw_core->core_WTCON = ((USB->LINK_INFO & 0xF0u) >> 4u);/*refer musb section 3 . 7 . 3*/
87 hw_core->core_WTID = (USB->LINK_INFO & 0x0Fu);/*refer musb section 3 . 7 . 3*/
88 hw_core->core_VPLEN = USB->VP_LEN;
89 hw_core->core_HS_EOF1 = USB->HS_EOF1;
90 hw_core->core_FS_EOF1 = USB->FS_EOF1;
91 hw_core->core_LS_EOF1 = USB->LS_EOF1;
92 hw_core->core_configdata = USB->INDEXED_CSR.DEVICE_EP0.CONFIG_DATA;
93 }
94
95 /***************************************************************************//**
96 Configures the registers related to TX EP for data transfer operations as
97 per the parameters provided by the upper layer.
98 */
99 void
MSS_USBD_CIF_tx_ep_configure(mss_usb_ep_t * device_ep)100 MSS_USBD_CIF_tx_ep_configure
101 (
102 mss_usb_ep_t* device_ep
103 )
104 {
105 MSS_USB_CIF_tx_ep_clr_csrreg(device_ep->num); //clear previous config, if any
106
107 MSS_USB_CIF_tx_ep_clr_underrun(device_ep->num);
108 MSS_USB_CIF_tx_ep_clr_send_stall_bit(device_ep->num);
109 MSS_USB_CIF_tx_ep_clr_stall_sent_bit(device_ep->num);
110
111 switch(device_ep->xfr_type)
112 {
113 case MSS_USB_XFR_INTERRUPT:
114 MSS_USB_CIF_tx_ep_disable_iso(device_ep->num);
115 MSS_USB_CIF_tx_ep_clr_autoset(device_ep->num);
116 break;
117
118 case MSS_USB_XFR_BULK:
119 MSS_USB_CIF_tx_ep_disable_iso(device_ep->num);
120 if(device_ep->dma_enable == DMA_ENABLE)
121 MSS_USB_CIF_tx_ep_set_autoset(device_ep->num);
122 break;
123
124 case MSS_USB_XFR_ISO:
125 /*Error check and Data toggle is ignored in ISO transfers*/
126 MSS_USB_CIF_tx_ep_enable_iso(device_ep->num);
127 MSS_USB_CIF_tx_ep_clr_autoset(device_ep->num);
128 break;
129
130 default:
131 ASSERT(0);
132 break;
133 }
134
135 /*Do the common configuration for TX EP*/
136 MSS_USB_CIF_tx_ep_configure(device_ep);
137 }
138
139 /***************************************************************************//**
140 Configures the RX EP for data transfer operations as per the parameters
141 provided by upper layer.
142 */
143 void
MSS_USBD_CIF_rx_ep_configure(mss_usb_ep_t * device_ep)144 MSS_USBD_CIF_rx_ep_configure
145 (
146 mss_usb_ep_t* device_ep
147 )
148 {
149 MSS_USB_CIF_rx_ep_clr_csrreg(device_ep->num); //clear previous config, if any
150
151 MSS_USB_CIF_rx_ep_clr_overrun(device_ep->num);
152 MSS_USB_CIF_rx_ep_clr_stall_sent_bit(device_ep->num);
153 MSS_USB_CIF_rx_ep_clr_send_stall_bit(device_ep->num);
154
155 switch(device_ep->xfr_type)
156 {
157 case MSS_USB_XFR_INTERRUPT:
158 MSS_USB_CIF_rx_ep_disable_iso(device_ep->num);
159 MSS_USB_CIF_rx_ep_disable_nyet(device_ep->num);
160 MSS_USB_CIF_rx_ep_clr_autoclr(device_ep->num);
161 break;
162
163 case MSS_USB_XFR_BULK:
164 MSS_USB_CIF_rx_ep_disable_iso(device_ep->num);
165 MSS_USB_CIF_rx_ep_enable_nyet(device_ep->num);
166 MSS_USB_CIF_rx_ep_set_autoclr(device_ep->num);
167 break;
168
169 case MSS_USB_XFR_ISO:
170 MSS_USB_CIF_rx_ep_clr_autoclr(device_ep->num);
171 MSS_USB_CIF_rx_ep_enable_iso(device_ep->num);
172 MSS_USB_CIF_rx_ep_disable_nyet(device_ep->num);
173 break;
174
175 default:
176 ASSERT(0);
177 break;
178 }
179
180 /*Do the common configuration for RX EP*/
181 MSS_USB_CIF_rx_ep_configure(device_ep);
182 }
183
184 /***************************************************************************//**
185 Configures the Control EP for data transfer operations.
186 */
187 void
MSS_USBD_CIF_cep_configure(void)188 MSS_USBD_CIF_cep_configure
189 (
190 void
191 )
192 {
193 /*Control transfers will be handled without DMA*/
194 MSS_USB_CIF_set_index_reg(MSS_USB_CEP);
195 MSS_USB_CIF_cep_reset_csr0_reg();
196 MSS_USB_CIF_cep_enable_irq();
197 }
198
199 /***************************************************************************//**
200 Prepares the Control EP for receiving data as per the parameters provided by
201 upper layer
202 */
203 void
MSS_USBD_CIF_cep_rx_prepare(mss_usb_ep_t * device_ep)204 MSS_USBD_CIF_cep_rx_prepare
205 (
206 mss_usb_ep_t* device_ep
207 )
208 {
209 if(MSS_USB_CEP_IDLE == device_ep[MSS_USB_CEP].state)
210 {
211 cep_state = MSS_USB_CTRL_EP_IDLE;
212 }
213 else if((MSS_USB_CEP_SETUP == device_ep[MSS_USB_CEP].state) ||
214 (MSS_USB_CEP_RX == device_ep[MSS_USB_CEP].state))
215 {
216 cep_state = MSS_USB_CTRL_EP_RX;
217 }
218 }
219
220 /***************************************************************************//**
221 Prepares the RX EP for receiving data as per parameters provided by upper layer
222 */
223 void
MSS_USBD_CIF_rx_ep_read_prepare(mss_usb_ep_t * device_ep)224 MSS_USBD_CIF_rx_ep_read_prepare
225 (
226 mss_usb_ep_t* device_ep
227 )
228 {
229 /*Fixed Buffer overwriting issue found with printer driver and
230 issue with interrupt transfer with DMA by moving the location
231 of interrupt enable function*/
232 if(DMA_ENABLE == device_ep->dma_enable)
233 {
234 /*Make sure that address is Modulo-4.Bits D0-D1 are read only.*/
235 ASSERT(!(((uint32_t)device_ep->buf_addr) & 0x00000002));
236
237 MSS_USB_CIF_dma_write_addr(device_ep->dma_channel,
238 (uint32_t)device_ep->buf_addr);
239
240 /*
241 DMA Count register will be loaded after receive interrupt occurs.
242 Mode need to be set every time since M1 to M0 transition might have
243 happened for "short packet".
244 */
245 if(MSS_USB_XFR_BULK == device_ep->xfr_type)
246 {
247 MSS_USB_CIF_rx_ep_set_dma_mode1(device_ep->num);
248 MSS_USB_CIF_rx_ep_set_autoclr(device_ep->num);
249 MSS_USB_CIF_rx_ep_enable_dma(device_ep->num);
250
251 MSS_USB_CIF_dma_write_count(device_ep->dma_channel,
252 device_ep->xfr_length);
253
254 MSS_USB_CIF_rx_ep_enable_irq(device_ep->num);
255
256 /*Handling single NULL packet reception*/
257 if(0u != device_ep->xfr_length )
258 {
259 MSS_USB_CIF_dma_start_xfr(device_ep->dma_channel);
260 }
261 }
262 else
263 {
264 MSS_USB_CIF_rx_ep_clr_autoclr(device_ep->num);
265 MSS_USB_CIF_rx_ep_set_dma_mode0(device_ep->num);
266
267 /*MUSB section 17.4.1*/
268 MSS_USB_CIF_rx_ep_disable_dma(device_ep->num);
269 MSS_USB_CIF_rx_ep_enable_irq(device_ep->num);
270 }
271 }
272 else
273 {
274 MSS_USB_CIF_rx_ep_enable_irq(device_ep->num);
275 }
276 }
277
278 /***************************************************************************//**
279 Writes a data packet on EP0 in device mode(control endpoint).
280 */
281 void
MSS_USBD_CIF_cep_write_pkt(mss_usb_ep_t * device_ep)282 MSS_USBD_CIF_cep_write_pkt
283 (
284 mss_usb_ep_t* device_ep
285 )
286 {
287 if(device_ep->num == MSS_USB_CEP)
288 {
289 /* null buffer, xfr type, transaction type */
290 if((0 != device_ep->buf_addr) && (MSS_USB_XFR_CONTROL == device_ep->xfr_type))
291 {
292 MSS_USB_CIF_load_tx_fifo(device_ep->num,
293 device_ep->buf_addr,
294 device_ep->txn_length);
295
296 device_ep->txn_count = device_ep->txn_length;
297 device_ep->xfr_count += device_ep->txn_length;
298 }
299
300 if(MSS_USB_CEP_TX == device_ep->state)
301 {
302 cep_state = MSS_USB_CTRL_EP_TX;
303 }
304
305 if(device_ep->xfr_count < device_ep->xfr_length)
306 {
307 MSS_USB_CIF_cep_set_txpktrdy();
308 }
309 else if(device_ep->xfr_count >= device_ep->xfr_length)
310 {
311 MSS_USBD_CIF_cep_end_rdr();
312 }
313 }
314 }
315
316 /***************************************************************************//**
317 Reads data packet arrived on EP0 in device mode(control endpoint).
318 */
319 void
MSS_USBD_CIF_cep_read_pkt(mss_usb_ep_t * device_ep)320 MSS_USBD_CIF_cep_read_pkt
321 (
322 mss_usb_ep_t* device_ep
323 )
324 {
325 volatile uint16_t received_count = 0u;
326
327 MSS_USB_CIF_set_index_reg(MSS_USB_CEP);
328
329 if((MSS_USB_CEP == device_ep->num) && (0 != device_ep->buf_addr))
330 {
331 /*TODO: check stalled, null buffer, transfer type, transaction type */
332 received_count = MSS_USB_CIF_cep_rx_byte_count();
333
334 MSS_USB_CIF_read_rx_fifo(MSS_USB_CEP,
335 device_ep->buf_addr,
336 received_count);
337
338 device_ep->xfr_count += received_count;
339 device_ep->txn_count = received_count;
340 }
341 }
342
343 #endif //MSS_USB_DEVICE_ENABLED
344
345 #ifdef __cplusplus
346 }
347 #endif
348