1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #ifndef __USB_DEVICE_KHCI_H__
10 #define __USB_DEVICE_KHCI_H__
11 
12 /*!
13  * @addtogroup usb_device_controller_khci_driver
14  * @{
15  */
16 
17 /*******************************************************************************
18  * Definitions
19  ******************************************************************************/
20 
21 /*! @brief The maximum value of ISO maximum packet size for FS in USB specification 2.0 */
22 #define USB_DEVICE_MAX_FS_ISO_MAX_PACKET_SIZE (1023U)
23 
24 /*! @brief The maximum value of non-ISO maximum packet size for FS in USB specification 2.0 */
25 #define USB_DEVICE_MAX_FS_NONE_ISO_MAX_PACKET_SIZE (64U)
26 
27 #define USB_KHCI_BDT_DEVICE_OUT_TOKEN   (0x01U)
28 #define USB_KHCI_BDT_DEVICE_IN_TOKEN    (0x09U)
29 #define USB_KHCI_BDT_DEVICE_SETUP_TOKEN (0x0DU)
30 
31 #define USB_KHCI_BDT_OWN       (0x80U)
32 #define USB_KHCI_BDT_DATA01(x) ((((uint32_t)(x)) & 0x01U) << 0x06U)
33 #define USB_KHCI_BDT_BC(x)     ((((uint32_t)(x)) & 0x3FFU) << 0x10U)
34 #define UBS_KHCI_BDT_KEEP      (0x20U)
35 #define UBS_KHCI_BDT_NINC      (0x10U)
36 #define USB_KHCI_BDT_DTS       (0x08U)
37 #define USB_KHCI_BDT_STALL     (0x04U)
38 
39 #if defined(__DSC__) || defined(__CW__)
40 /*! @brief Set BDT buffer address */
41 #define USB_KHCI_BDT_SET_ADDRESS(bdt_base, ep, direction, odd, address)                            \
42     *((volatile uint32_t *)((((bdt_base)&0xfffffe00U) | (((uint32_t)(ep)&0x0fU) << 5U) |           \
43                              (((uint32_t)(direction)&1U) << 4U) | (((uint32_t)(odd)&1U) << 3U)) >> \
44                             1U) +                                                                  \
45       1U) = (address)
46 
47 /*! @brief Set BDT control fields*/
48 #define USB_KHCI_BDT_SET_CONTROL(bdt_base, ep, direction, odd, control)                           \
49     *(volatile uint32_t *)((((bdt_base)&0xfffffe00U) | (((uint32_t)(ep)&0x0fU) << 5U) |           \
50                             (((uint32_t)(direction)&1U) << 4U) | (((uint32_t)(odd)&1U) << 3U)) >> \
51                            1U) = (control)
52 
53 /*! @brief Get BDT buffer address*/
54 #define USB_KHCI_BDT_GET_ADDRESS(bdt_base, ep, direction, odd)                                      \
55     (*((volatile uint32_t *)((((bdt_base)&0xfffffe00U) | (((uint32_t)(ep)&0x0fU) << 5U) |           \
56                               (((uint32_t)(direction)&1U) << 4U) | (((uint32_t)(odd)&1U) << 3U)) >> \
57                              1U) +                                                                  \
58        1U))
59 
60 /*! @brief Get BDT control fields*/
61 #define USB_KHCI_BDT_GET_CONTROL(bdt_base, ep, direction, odd)                                     \
62     (*(volatile uint32_t *)((((bdt_base)&0xfffffe00U) | (((uint32_t)(ep)&0x0fU) << 5U) |           \
63                              (((uint32_t)(direction)&1U) << 4U) | (((uint32_t)(odd)&1U) << 3U)) >> \
64                             1U))
65 #else
66 /*! @brief Set BDT buffer address */
67 #define USB_KHCI_BDT_SET_ADDRESS(bdt_base, ep, direction, odd, address)                          \
68     *((volatile uint32_t *)(((bdt_base)&0xfffffe00U) | (((uint32_t)(ep)&0x0fU) << 5U) |          \
69                             (((uint32_t)(direction)&1U) << 4U) | (((uint32_t)(odd)&1U) << 3U)) + \
70       1U) = (address)
71 
72 /*! @brief Set BDT control fields*/
73 #define USB_KHCI_BDT_SET_CONTROL(bdt_base, ep, direction, odd, control)                \
74     *(volatile uint32_t *)(((bdt_base)&0xfffffe00U) | (((uint32_t)(ep)&0x0fU) << 5U) | \
75                            (((uint32_t)(direction)&1U) << 4U) | (((uint32_t)(odd)&1U) << 3U)) = (control)
76 
77 /*! @brief Get BDT buffer address*/
78 #define USB_KHCI_BDT_GET_ADDRESS(bdt_base, ep, direction, odd)                                    \
79     (*((volatile uint32_t *)(((bdt_base)&0xfffffe00U) | (((uint32_t)(ep)&0x0fU) << 5U) |          \
80                              (((uint32_t)(direction)&1U) << 4U) | (((uint32_t)(odd)&1U) << 3U)) + \
81        1U))
82 
83 /*! @brief Get BDT control fields*/
84 #define USB_KHCI_BDT_GET_CONTROL(bdt_base, ep, direction, odd)                          \
85     (*(volatile uint32_t *)(((bdt_base)&0xfffffe00U) | (((uint32_t)(ep)&0x0fU) << 5U) | \
86                             (((uint32_t)(direction)&1U) << 4U) | (((uint32_t)(odd)&1U) << 3U)))
87 #endif
88 
89 /*! @brief Endpoint state structure */
90 typedef struct _usb_device_khci_endpoint_state_struct
91 {
92     uint8_t *transferBuffer; /*!< Address of buffer containing the data to be transmitted */
93     uint32_t transferLength; /*!< Length of data to transmit. */
94     uint32_t transferDone;   /*!< The data length has been transferred*/
95     union
96     {
97         uint32_t state; /*!< The state of the endpoint */
98         struct
99         {
100             uint32_t maxPacketSize : 10U; /*!< The maximum packet size of the endpoint */
101             uint32_t stalled : 1U;        /*!< The endpoint is stalled or not */
102             uint32_t data0 : 1U;          /*!< The data toggle of the transaction */
103             uint32_t bdtOdd : 1U;         /*!< The BDT toggle of the endpoint */
104             uint32_t dmaAlign : 1U;       /*!< Whether the transferBuffer is DMA aligned or not */
105             uint32_t transferring : 1U;   /*!< The endpoint is transferring */
106             uint32_t zlt : 1U;            /*!< zlt flag */
107         } stateBitField;
108     } stateUnion;
109 } usb_device_khci_endpoint_state_struct_t;
110 
111 /*! @brief KHCI state structure */
112 typedef struct _usb_device_khci_state_struct
113 {
114     usb_device_struct_t *deviceHandle; /*!< Device handle used to identify the device object belongs to */
115 #if defined(__DSC__) || defined(__CW__)
116     uint8_t *bdt; /*!< BDT buffer address */
117 #else
118     uint32_t *bdt; /*!< BDT buffer address */
119 #endif
120     USB_Type *registerBase;                               /*!< The base address of the register */
121     uint8_t setupPacketBuffer[USB_SETUP_PACKET_SIZE * 2]; /*!< The setup request buffer */
122     uint8_t *dmaAlignBuffer; /*!< This buffer is used to fix the transferBuffer or transferLength does
123                                not align to 4-bytes when the function USB_DeviceKhciRecv is called.
124                                The macro USB_DEVICE_CONFIG_KHCI_DMA_ALIGN is used to enable or disable this feature.
125                                If the feature is enabled, when the transferBuffer or transferLength does not align to
126                                4-bytes,
127                                the transferLength is not more than USB_DEVICE_CONFIG_KHCI_DMA_ALIGN_BUFFER_LENGTH, and
128                                the flag isDmaAlignBufferInusing is zero, the dmaAlignBuffer is used to receive data
129                                and the flag isDmaAlignBufferInusing is set to 1.
130                                When the transfer is done, the received data, kept in dmaAlignBuffer, is copied
131                                to the transferBuffer, and the flag isDmaAlignBufferInusing is cleared.
132                                 */
133     usb_device_khci_endpoint_state_struct_t
134         endpointState[USB_DEVICE_CONFIG_ENDPOINTS * 2]; /*!< Endpoint state structures */
135     uint8_t isDmaAlignBufferInusing;                    /*!< The dmaAlignBuffer is used or not */
136     uint8_t isResetting;                                /*!< Is doing device reset or not */
137     uint8_t controllerId;                               /*!< Controller ID */
138     uint8_t setupBufferIndex;                           /*!< A valid setup buffer flag */
139 #if (defined(USB_DEVICE_CONFIG_OTG) && (USB_DEVICE_CONFIG_OTG))
140     uint8_t otgStatus;
141 #endif
142 } usb_device_khci_state_struct_t;
143 
144 #if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
145     (defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U))
146 typedef struct _usb_device_dcd_state_struct
147 {
148     usb_device_struct_t *deviceHandle; /*!< Device handle used to identify the device object belongs to */
149     USBDCD_Type *dcdRegisterBase;      /*!< The base address of the dcd module */
150     uint8_t controllerId;              /*!< Controller ID */
151 } usb_device_dcd_state_struct_t;
152 #endif
153 
154 #if defined(__cplusplus)
155 extern "C" {
156 #endif
157 
158 /*!
159  * @name USB device KHCI functions
160  * @{
161  */
162 
163 /*******************************************************************************
164  * API
165  ******************************************************************************/
166 
167 /*!
168  * @brief Initializes the USB device KHCI instance.
169  *
170  * This function initializes the USB device KHCI module specified by the controllerId.
171  *
172  * @param[in] controllerId The controller ID of the USB IP. See the enumeration type usb_controller_index_t.
173  * @param[in] handle        Pointer of the device handle used to identify the device object belongs to.
174  * @param[out] khciHandle   An out parameter used to return the pointer of the device KHCI handle to the caller.
175  *
176  * @return A USB error code or kStatus_USB_Success.
177  */
178 usb_status_t USB_DeviceKhciInit(uint8_t controllerId,
179                                 usb_device_handle handle,
180                                 usb_device_controller_handle *khciHandle);
181 
182 /*!
183  * @brief Deinitializes the USB device KHCI instance.
184  *
185  * This function deinitializes the USB device KHCI module.
186  *
187  * @param[in] khciHandle   Pointer of the device KHCI handle.
188  *
189  * @return A USB error code or kStatus_USB_Success.
190  */
191 usb_status_t USB_DeviceKhciDeinit(usb_device_controller_handle khciHandle);
192 
193 /*!
194  * @brief Sends data through a specified endpoint.
195  *
196  * This function sends data through a specified endpoint.
197  *
198  * @param[in] khciHandle      Pointer of the device KHCI handle.
199  * @param[in] endpointAddress Endpoint index.
200  * @param[in] buffer           The memory address to hold the data need to be sent.
201  * @param[in] length           The data length need to be sent.
202  *
203  * @return A USB error code or kStatus_USB_Success.
204  *
205  * @note The return value indicates whether the sending request is successful or not. The transfer completion is
206  * notified by the
207  * corresponding callback function.
208  * Currently, only one transfer request can be supported for a specific endpoint.
209  * If there is a specific requirement to support multiple transfer requests for a specific endpoint, the application
210  * should implement a queue in the application level.
211  * The subsequent transfer can begin only when the previous transfer is done (a notification is obtained through the
212  * endpoint
213  * callback).
214  */
215 usb_status_t USB_DeviceKhciSend(usb_device_controller_handle khciHandle,
216                                 uint8_t endpointAddress,
217                                 uint8_t *buffer,
218                                 uint32_t length);
219 
220 /*!
221  * @brief Receives data through a specified endpoint.
222  *
223  * This function receives data through a specified endpoint.
224  *
225  * @param[in] khciHandle      Pointer of the device KHCI handle.
226  * @param[in] endpointAddress Endpoint index.
227  * @param[in] buffer           The memory address to save the received data.
228  * @param[in] length           The data length to be received.
229  *
230  * @return A USB error code or kStatus_USB_Success.
231  *
232  * @note The return value indicates whether the receiving request is successful or not. The transfer completion is
233  * notified by the
234  * corresponding callback function.
235  * Currently, only one transfer request can be supported for a specific endpoint.
236  * If there is a specific requirement to support multiple transfer requests for a specific endpoint, the application
237  * should implement a queue in the application level.
238  * The subsequent transfer can begin only when the previous transfer is done (a notification is obtained through the
239  * endpoint
240  * callback).
241  */
242 usb_status_t USB_DeviceKhciRecv(usb_device_controller_handle khciHandle,
243                                 uint8_t endpointAddress,
244                                 uint8_t *buffer,
245                                 uint32_t length);
246 
247 /*!
248  * @brief Cancels the pending transfer in a specified endpoint.
249  *
250  * The function is used to cancel the pending transfer in a specified endpoint.
251  *
252  * @param[in] khciHandle      Pointer of the device KHCI handle.
253  * @param[in] ep               Endpoint address, bit7 is the direction of endpoint, 1U - IN, abd 0U - OUT.
254  *
255  * @return A USB error code or kStatus_USB_Success.
256  */
257 usb_status_t USB_DeviceKhciCancel(usb_device_controller_handle khciHandle, uint8_t ep);
258 
259 /*!
260  * @brief Controls the status of the selected item.
261  *
262  * The function is used to control the status of the selected item.
263  *
264  * @param[in] khciHandle      Pointer of the device KHCI handle.
265  * @param[in] type             The selected item. See enumeration type usb_device_control_type_t.
266  * @param[in,out] param            The parameter type is determined by the selected item.
267  *
268  * @return A USB error code or kStatus_USB_Success.
269  */
270 usb_status_t USB_DeviceKhciControl(usb_device_controller_handle khciHandle,
271                                    usb_device_control_type_t type,
272                                    void *param);
273 
274 /*! @} */
275 
276 #if defined(__cplusplus)
277 }
278 #endif
279 
280 /*! @} */
281 
282 #endif /* __USB_DEVICE_KHCI_H__ */
283