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