1 /*
2  * Copyright (c) 2016, 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_LPC3511IP_H__
10 #define __USB_DEVICE_LPC3511IP_H__
11 
12 #include "fsl_device_registers.h"
13 
14 /*!
15  * @addtogroup usb_device_controller_lpcip3511_driver
16  * @{
17  */
18 
19 /*******************************************************************************
20  * Definitions
21  ******************************************************************************/
22 
23 /* For bulk out endpoint in high speed mode, use long length data transfer to decrease the Ping packet count to increase
24  * bulk bandwidth */
25 /* The bigger this macro's value is, the higher bandwidth bulk out endpoint has. However, you need to set a reasonable
26  * value for this macro based on RAM size of Soc. If this macro's value is too big, link may be failed. */
27 /* Note that please set this value as integral multiple of 512U. When using USB RAM, you also can decrease the
28  * USB_DEVICE_IP3511_USB_RAM_IN_USE_SIZE within a reasonable range to use more USB RAM */
29 #if (((defined(USB_DEVICE_CONFIG_MSC)) && (USB_DEVICE_CONFIG_MSC > 0U)) && \
30      ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
31 #define USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX (0U)
32 #endif
33 
34 /* During enumeration for high speed, IP3511HS responds NYET to the host(HUAWEI smartphone P20,  Kirin 970 platform) for
35    OUT transaction in the status stage of control transfer. \ The host can not handle NYET respond in this case. Then
36    this leads to enumeration failure. This workaround is used to fix this issue, which force the prime length is 65
37    bytes. This workaround is disabled by default */
38 #if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
39 #define USB_DEVICE_IP3511HS_CONTROL_OUT_NYET_WORKAROUND (0U)
40 #endif
41 
42 /*! @brief Prime all the double endpoint buffer at the same time, if the transfer length is larger than max packet size.
43  */
44 #define USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE (1U)
45 #if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
46 #define USB_LPC3511IP_Type              USBHSD_Type
47 #define USB_DEVICE_IP3511_ENDPOINTS_NUM FSL_FEATURE_USBHSD_EP_NUM
48 #define USB_DEVICE_IP3511_USB_RAM_SIZE  FSL_FEATURE_USBHSD_USB_RAM
49 #else
50 #define USB_LPC3511IP_Type              USB_Type
51 #define USB_DEVICE_IP3511_ENDPOINTS_NUM FSL_FEATURE_USB_EP_NUM
52 #if ((defined(FSL_FEATURE_USB_USB_RAM)) && (FSL_FEATURE_USB_USB_RAM > 0U))
53 #define USB_DEVICE_IP3511_USB_RAM_SIZE FSL_FEATURE_USB_USB_RAM
54 #endif
55 #endif
56 
57 /*! @brief Use the macro to represent the USB RAM that has been used. The remaining USB RAM will be used by the
58      controller driver. If application needs to allocate variables into the USB RAM, please increase the macro or link
59      may fail. Likewise, if requiring to assign more USB RAM to the controller driver, please decrease the macro.
60      When USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX is used, USB_DEVICE_IP3511_USB_RAM_IN_USE_SIZE can be
61    decreased within a reasonable range to use more USB RAM. */
62 #define USB_DEVICE_IP3511_USB_RAM_IN_USE_SIZE (3U * 1024U)
63 /*! @brief The reserved buffer size, the buffer is for the memory copy if the application transfer buffer is
64      ((not 64 bytes alignment) || (not in the USB RAM) || (HS && OUT && not multiple of the maximum packet size)) */
65 #if ((defined(USB_DEVICE_IP3511_USB_RAM_SIZE)) && (USB_DEVICE_IP3511_USB_RAM_SIZE > 0U))
66 #define USB_DEVICE_IP3511_ENDPOINT_RESERVED_BUFFER_SIZE \
67     ((uint32_t)USB_DEVICE_IP3511_USB_RAM_SIZE - USB_DEVICE_IP3511_USB_RAM_IN_USE_SIZE)
68 #else
69 #if ((defined(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX)) && \
70      (USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX > 0U))
71 /* if use USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX (>0U), need to increase the reserved buffer size */
72 #define USB_DEVICE_IP3511_ENDPOINT_RESERVED_BUFFER_SIZE \
73     ((5U * 1024U) + (USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX / 512U) * 512U)
74 #else
75 #define USB_DEVICE_IP3511_ENDPOINT_RESERVED_BUFFER_SIZE (5U * 1024U)
76 #endif
77 #endif
78 
79 /*! @brief Use one bit to represent one reserved 64 bytes to allocate the buffer by uint of 64 bytes. */
80 #define USB_DEVICE_IP3511_BITS_FOR_RESERVED_BUFFER ((USB_DEVICE_IP3511_ENDPOINT_RESERVED_BUFFER_SIZE + 63U) / 64U)
81 /*! @brief How many IPs support the reserved buffer */
82 #define USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY (USB_DEVICE_CONFIG_LPCIP3511FS + USB_DEVICE_CONFIG_LPCIP3511HS)
83 
84 /* for out endpoint,only use buffer toggle, disable prime double buffer at the same time*/
85 /*host send data less than maxpacket size and in endpoint prime length more more than maxpacketsize, there will be state
86  * mismtach*/
87 #if USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE
88 #define USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER (1U)
89 #else
90 #define USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER (0U)
91 #endif
92 
93 #define USB_DEVICE_IP3511HS_LPM_ADPPROBE_ATTACH_DEBOUNCE_COUNT (3)
94 
95 /* if FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE is true:
96  * Enable this macro to exit HS mode automatically if the user case is:
97  *   host and device keep cable connected, and host turn off vbus to simulate detachment.
98  * If user disconnects the cable, there is no issue and don't need enable this macro.
99  * There is one delay in the isr if enable this macro.
100  */
101 #define USB_DEVICE_IP3511HS_FORCE_EXIT_HS_MODE_ENABLE (0u)
102 
103 /*! @brief Endpoint state structure */
104 typedef struct _usb_device_lpc3511ip_endpoint_state_struct
105 {
106     uint8_t *transferBuffer;       /*!< Address of buffer containing the data to be transmitted */
107     uint32_t transferLength;       /*!< Length of data to transmit. */
108     uint32_t transferDone;         /*!< The data length has been transferred*/
109     uint32_t transferPrimedLength; /*!< it may larger than transferLength, because the primed length may larger than the
110                                       transaction length. */
111     uint8_t *epPacketBuffer;       /*!< The max packet buffer for copying*/
112     union
113     {
114         uint32_t state; /*!< The state of the endpoint */
115         struct
116         {
117             uint32_t maxPacketSize : 12U; /*!< The maximum packet size of the endpoint */
118             uint32_t stalled : 1U;        /*!< The endpoint is stalled or not */
119             uint32_t transferring : 1U;   /*!< The endpoint is transferring */
120             uint32_t zlt : 1U;            /*!< zlt flag */
121             uint32_t stallPrimed : 1U;
122             uint32_t epPacketCopyed : 1U;   /*!< whether use the copy buffer */
123             uint32_t epControlDefault : 5u; /*!< The EP command/status 26~30 bits */
124             uint32_t doubleBufferBusy : 2U; /*!< How many buffers are primed, for control endpoint it is not used */
125             uint32_t producerOdd : 1U;      /*!< When priming one transaction, prime to this endpoint buffer */
126             uint32_t consumerOdd : 1U;      /*!< When transaction is done, read result from this endpoint buffer */
127             uint32_t endpointType : 2U;
128 #if (defined(USB_DEVICE_CONFIG_ROOT2_TEST) && (USB_DEVICE_CONFIG_ROOT2_TEST > 0U))
129             uint32_t isOpened : 1U; /*!< whether the endpoint is initialized */
130             uint32_t reserved1 : 3U;
131 #else
132             uint32_t reserved1 : 4U;
133 #endif
134         } stateBitField;
135     } stateUnion;
136     union
137     {
138         uint16_t epBufferStatus;
139         /* If double buff is disable, only epBufferStatusUnion[0] is used;
140            For control endpoint, only epBufferStatusUnion[0] is used. */
141         struct
142         {
143             uint16_t transactionLength : 15U;
144             uint16_t epPacketCopyed : 1U;
145         } epBufferStatusField;
146     } epBufferStatusUnion[2];
147 } usb_device_lpc3511ip_endpoint_state_struct_t;
148 
149 /*! @brief LPC USB controller (IP3511) state structure */
150 typedef struct _usb_device_lpc3511ip_state_struct
151 {
152     /*!< control data buffer, must align with 64 */
153     uint8_t *controlData;
154     /*!< 8 bytes' setup data, must align with 64 */
155     uint8_t *setupData;
156     /*!< 4 bytes for zero length transaction, must align with 64 */
157     uint8_t *zeroTransactionData;
158     /* Endpoint state structures */
159     usb_device_lpc3511ip_endpoint_state_struct_t endpointState[(USB_DEVICE_IP3511_ENDPOINTS_NUM * 2)];
160     usb_device_handle deviceHandle;   /*!< (4 bytes) Device handle used to identify the device object belongs to */
161     USB_LPC3511IP_Type *registerBase; /*!< (4 bytes) ip base address */
162     volatile uint32_t *epCommandStatusList; /* endpoint list */
163 #if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
164     (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
165     void *dcdHandle; /*!< Dcd handle used to identify the device object belongs to */
166 #endif
167     uint8_t controllerId; /*!< Controller ID */
168     uint8_t isResetting;  /*!< Is doing device reset or not */
169     uint8_t deviceSpeed;  /*!< some controller support the HS */
170 #if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
171     uint8_t controllerSpeed;
172 #endif
173 #if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE))
174     uint8_t deviceState; /*!< Is device attached,1 attached,0 detached */
175 #endif
176 #if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
177 #if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
178     uint8_t lpmRemoteWakeUp;
179 #endif
180 #endif
181 #if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
182 #if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
183      (FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
184     uint8_t hsInterruptIssue;
185 #endif
186 #endif
187 } usb_device_lpc3511ip_state_struct_t;
188 
189 /*!
190  * @name USB device controller (IP3511) functions
191  * @{
192  */
193 
194 /*******************************************************************************
195  * API
196  ******************************************************************************/
197 
198 #if defined(__cplusplus)
199 extern "C" {
200 #endif
201 
202 /*!
203  * @brief Initializes the USB device controller instance.
204  *
205  * This function initializes the USB device controller module specified by the controllerId.
206  *
207  * @param[in] controllerId      The controller ID of the USB IP. See the enumeration type usb_controller_index_t.
208  * @param[in] handle            Pointer of the device handle used to identify the device object belongs to.
209  * @param[out] controllerHandle An out parameter used to return the pointer of the device controller handle to the
210  * caller.
211  *
212  * @return A USB error code or kStatus_USB_Success.
213  */
214 usb_status_t USB_DeviceLpc3511IpInit(uint8_t controllerId,
215                                      usb_device_handle handle,
216                                      usb_device_controller_handle *controllerHandle);
217 
218 /*!
219  * @brief Deinitializes the USB device controller instance.
220  *
221  * This function deinitializes the USB device controller module.
222  *
223  * @param[in] controllerHandle   Pointer of the device controller handle.
224  *
225  * @return A USB error code or kStatus_USB_Success.
226  */
227 usb_status_t USB_DeviceLpc3511IpDeinit(usb_device_controller_handle controllerHandle);
228 
229 /*!
230  * @brief Sends data through a specified endpoint.
231  *
232  * This function sends data through a specified endpoint.
233  *
234  * @param[in] controllerHandle Pointer of the device controller handle.
235  * @param[in] endpointAddress  Endpoint index.
236  * @param[in] buffer           The memory address to hold the data need to be sent.
237  * @param[in] length           The data length need to be sent.
238  *
239  * @return A USB error code or kStatus_USB_Success.
240  *
241  * @note The return value indicates whether the sending request is successful or not. The transfer completion is
242  * notified by the
243  * corresponding callback function.
244  * Currently, only one transfer request can be supported for a specific endpoint.
245  * If there is a specific requirement to support multiple transfer requests for a specific endpoint, the application
246  * should implement a queue in the application level.
247  * The subsequent transfer can begin only when the previous transfer is done (a notification is obtained through the
248  * endpoint
249  * callback).
250  */
251 usb_status_t USB_DeviceLpc3511IpSend(usb_device_controller_handle controllerHandle,
252                                      uint8_t endpointAddress,
253                                      uint8_t *buffer,
254                                      uint32_t length);
255 
256 /*!
257  * @brief Receives data through a specified endpoint.
258  *
259  * This function receives data through a specified endpoint.
260  *
261  * @param[in] controllerHandle Pointer of the device controller handle.
262  * @param[in] endpointAddress  Endpoint index.
263  * @param[in] buffer           The memory address to save the received data.
264  * @param[in] length           The data length to be received.
265  *
266  * @return A USB error code or kStatus_USB_Success.
267  *
268  * @note The return value indicates whether the receiving request is successful or not. The transfer completion is
269  * notified by the
270  * corresponding callback function.
271  * Currently, only one transfer request can be supported for a specific endpoint.
272  * If there is a specific requirement to support multiple transfer requests for a specific endpoint, the application
273  * should implement a queue in the application level.
274  * The subsequent transfer can begin only when the previous transfer is done (a notification is obtained through the
275  * endpoint
276  * callback).
277  */
278 usb_status_t USB_DeviceLpc3511IpRecv(usb_device_controller_handle controllerHandle,
279                                      uint8_t endpointAddress,
280                                      uint8_t *buffer,
281                                      uint32_t length);
282 
283 /*!
284  * @brief Cancels the pending transfer in a specified endpoint.
285  *
286  * The function is used to cancel the pending transfer in a specified endpoint.
287  *
288  * @param[in] controllerHandle  ointer of the device controller handle.
289  * @param[in] ep                Endpoint address, bit7 is the direction of endpoint, 1U - IN, abd 0U - OUT.
290  *
291  * @return A USB error code or kStatus_USB_Success.
292  */
293 usb_status_t USB_DeviceLpc3511IpCancel(usb_device_controller_handle controllerHandle, uint8_t ep);
294 
295 /*!
296  * @brief Controls the status of the selected item.
297  *
298  * The function is used to control the status of the selected item.
299  *
300  * @param[in] controllerHandle      Pointer of the device controller handle.
301  * @param[in] type             The selected item. Please refer to enumeration type usb_device_control_type_t.
302  * @param[in,out] param            The parameter type is determined by the selected item.
303  *
304  * @return A USB error code or kStatus_USB_Success.
305  */
306 usb_status_t USB_DeviceLpc3511IpControl(usb_device_controller_handle controllerHandle,
307                                         usb_device_control_type_t type,
308                                         void *param);
309 
310 /*! @} */
311 
312 #if defined(__cplusplus)
313 }
314 #endif
315 
316 /*! @} */
317 
318 #endif /* __USB_DEVICE_LPC3511IP_H__ */
319