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