1 /*
2 * Copyright 2019 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7 #include "usb_hsdcd.h"
8 #include "usb_hsdcd_config.h"
9 /*******************************************************************************
10 * Definitions
11 ******************************************************************************/
12 #if !(defined(FSL_FEATURE_USBPHY_HAS_DCD_ANALOG) && (FSL_FEATURE_USBPHY_HAS_DCD_ANALOG > 0U))
13 /*! @brief The sequence initiation time for the dcd module. */
14 #define USB_HSDCD_TSEQ_INIT_TIME (1000U)
15 /*! @brief Time Period to Debounce D+ Signal. */
16 #define USB_HSDCD_TDCD_DBNC (10U)
17 /*! @brief The time period comparator enabled. */
18 #define USB_HSDCD_VDPSRC_ON (200U)
19 /*! @brief The amount of time that the module waits after primary detection before start to secondary detection. */
20 #define USB_HSDCD_TWAIT_AFTER_PRD (40U)
21 /*! @brief The amount of time the module enable the Vdm_src. */
22 #define USB_HSDCD_TVDMSRC_ON (10U)
23 #endif
24 typedef enum _usb_dcd_detection_sequence_results
25 {
26 kUSB_DcdDetectionNoResults = 0x0U,
27 kUSB_DcdDetectionStandardHost = 0x01U,
28 kUSB_DcdDetectionChargingPort = 0x02U,
29 kUSB_DcdDetectionDedicatedCharger = 0x03U,
30 } usb_dcd_detection_sequence_results_t;
31 typedef enum _usb_dcd_detection_sequence_status
32 {
33 kUSB_DcdDetectionNotEnabled = 0x0U,
34 kUSB_DcdDataPinDetectionCompleted = 0x01U,
35 kUSB_DcdChargingPortDetectionCompleted = 0x02U,
36 kUSB_DcdChargerTypeDetectionCompleted = 0x03U,
37 } usb_dcd_detection_sequence_status_t;
38 typedef struct _usb_hsdcd_state_struct
39 {
40 USBHSDCD_Type *dcdRegisterBase; /*!< The base address of the dcd module */
41 usb_hsdcd_callback_t dcdCallback; /*!< DCD callback function*/
42 void *dcdCallbackParam; /*!< DCD callback parameter*/
43 #if (defined(FSL_FEATURE_USBPHY_HAS_DCD_ANALOG) && (FSL_FEATURE_USBPHY_HAS_DCD_ANALOG > 0U))
44 void *phyBase; /*!< dcd phy base address, if no phy control needed, set to NULL*/
45 #endif
46 uint8_t dcdDisable; /*!< whether enable dcd function or not*/
47 uint8_t detectResult; /*!< dcd detect result*/
48 } usb_hsdcd_state_struct_t;
49 /*******************************************************************************
50 * Prototypes
51 ******************************************************************************/
52 /*******************************************************************************
53 * Variables
54 ******************************************************************************/
55 #if defined(USBHSDCD_STACK_BASE_ADDRS)
56 static const uint32_t s_hsdcdBaseAddrs[] = USBHSDCD_STACK_BASE_ADDRS;
57 #else
58 static const uint32_t s_hsdcdBaseAddrs[] = USBHSDCD_BASE_ADDRS;
59 #endif
60
61 /* Apply for device dcd state structure */
62 static usb_hsdcd_state_struct_t s_UsbDeviceDcdHSState[FSL_FEATURE_SOC_USBHSDCD_COUNT];
63 /*******************************************************************************
64 * Code
65 ******************************************************************************/
66
USB_HSDCD_GetInstance(USBHSDCD_Type * base)67 static uint32_t USB_HSDCD_GetInstance(USBHSDCD_Type *base)
68 {
69 uint32_t i;
70 uint32_t index = 0;
71
72 for (i = 0U; i < (uint32_t)(sizeof(s_hsdcdBaseAddrs) / sizeof(s_hsdcdBaseAddrs[0])); i++)
73 {
74 if ((uint32_t)base == s_hsdcdBaseAddrs[i])
75 {
76 return index;
77 }
78 index++;
79 }
80 return 0xFF;
81 }
82
USB_HSDCD_Init(USBHSDCD_Type * base,usb_hsdcd_config_struct_t * config,usb_hsdcd_handle * dcdHandle)83 usb_hsdcd_status_t USB_HSDCD_Init(USBHSDCD_Type *base, usb_hsdcd_config_struct_t *config, usb_hsdcd_handle *dcdHandle)
84 {
85 usb_hsdcd_state_struct_t *dcdHSState;
86 uint32_t speed;
87 uint32_t index;
88 #if (defined(FSL_FEATURE_USBPHY_HAS_DCD_ANALOG) && (FSL_FEATURE_USBPHY_HAS_DCD_ANALOG > 0U))
89 #if defined(USBPHY_STACK_BASE_ADDRS)
90 uint32_t phyBase[] = USBPHY_STACK_BASE_ADDRS;
91 #else
92 uint32_t phyBase[] = USBPHY_BASE_ADDRS;
93 #endif
94 #endif
95 if (NULL == base)
96 {
97 return kStatus_hsdcd_Error;
98 }
99 index = USB_HSDCD_GetInstance(base);
100 if (0xFFU == index)
101 {
102 return kStatus_hsdcd_Error;
103 }
104
105 dcdHSState = &s_UsbDeviceDcdHSState[index];
106 *dcdHandle = dcdHSState;
107 dcdHSState->dcdRegisterBase = base;
108 if ((NULL == config) || (NULL == config->dcdCallback))
109 {
110 /* don't need init */
111 }
112 else
113 {
114 #if (defined(FSL_FEATURE_USBPHY_HAS_DCD_ANALOG) && (FSL_FEATURE_USBPHY_HAS_DCD_ANALOG > 0U))
115 dcdHSState->phyBase = (void *)(uint8_t *)phyBase[index];
116 #endif
117 dcdHSState->dcdCallbackParam = config->dcdCallbackParam;
118 /*initialize the dcd controller*/
119 dcdHSState->dcdCallback = config->dcdCallback;
120 }
121 dcdHSState->dcdDisable = 0U;
122 /*misra 14.3*/
123 #if (USB_HSDCD_CLOCK_SPEED > 1000000U)
124 /*clock speed unit is MHz*/
125 speed = USB_HSDCD_CLOCK_SPEED / 1000000U;
126 #else
127 speed = USB_HSDCD_CLOCK_SPEED / 1000U;
128 dcdHSState->dcdRegisterBase->CLOCK &= ~(USBHSDCD_CLOCK_CLOCK_UNIT_MASK);
129 #endif
130 dcdHSState->dcdRegisterBase->CLOCK &= ~USBHSDCD_CLOCK_CLOCK_SPEED_MASK;
131 dcdHSState->dcdRegisterBase->CLOCK |= USBHSDCD_CLOCK_CLOCK_SPEED(speed);
132
133 #if !(defined(FSL_FEATURE_USBPHY_HAS_DCD_ANALOG) && (FSL_FEATURE_USBPHY_HAS_DCD_ANALOG > 0U))
134 /*Valid values are 0-1023*/
135 dcdHSState->dcdRegisterBase->TIMER0 &= ~(USBHSDCD_TIMER0_TSEQ_INIT_MASK);
136 dcdHSState->dcdRegisterBase->TIMER0 |= USBHSDCD_TIMER0_TSEQ_INIT(USB_HSDCD_TSEQ_INIT_TIME);
137 /*Valid values are 1-1023*/
138 #if (USB_HSDCD_VDPSRC_ON > 0U)
139 dcdHSState->dcdRegisterBase->TIMER1 &= ~(USBHSDCD_TIMER1_TVDPSRC_ON_MASK);
140 dcdHSState->dcdRegisterBase->TIMER1 |= USBHSDCD_TIMER1_TVDPSRC_ON(USB_HSDCD_VDPSRC_ON);
141 #endif
142 /*Valid values are 1-1023*/
143 #if (USB_HSDCD_TDCD_DBNC > 0U)
144 dcdHSState->dcdRegisterBase->TIMER1 &= ~(USBHSDCD_TIMER1_TDCD_DBNC_MASK);
145 dcdHSState->dcdRegisterBase->TIMER1 |= USBHSDCD_TIMER1_TDCD_DBNC(USB_HSDCD_TDCD_DBNC);
146 #endif
147 /*Valid values are 0-40ms*/
148 dcdHSState->dcdRegisterBase->TIMER2_BC12 &= ~(USBHSDCD_TIMER2_BC12_TVDMSRC_ON_MASK);
149 dcdHSState->dcdRegisterBase->TIMER2_BC12 |= USBHSDCD_TIMER2_BC12_TVDMSRC_ON(USB_HSDCD_TVDMSRC_ON);
150
151 /*Valid values are 1-1023ms*/
152 #if (USB_HSDCD_TWAIT_AFTER_PRD > 0U)
153 dcdHSState->dcdRegisterBase->TIMER2_BC12 &= ~(USBHSDCD_TIMER2_BC12_TWAIT_AFTER_PRD_MASK);
154 dcdHSState->dcdRegisterBase->TIMER2_BC12 |= USBHSDCD_TIMER2_BC12_TWAIT_AFTER_PRD(USB_HSDCD_TWAIT_AFTER_PRD);
155 #endif
156
157 #endif
158 dcdHSState->dcdRegisterBase->CONTROL |= USBHSDCD_CONTROL_BC12_MASK;
159
160 return kStatus_hsdcd_Success;
161 }
USB_HSDCD_Deinit(usb_hsdcd_handle handle)162 usb_hsdcd_status_t USB_HSDCD_Deinit(usb_hsdcd_handle handle)
163 {
164 usb_hsdcd_state_struct_t *dcdHSState;
165 dcdHSState = (usb_hsdcd_state_struct_t *)handle;
166 if (NULL == handle)
167 {
168 return kStatus_hsdcd_Error;
169 }
170 dcdHSState->dcdRegisterBase->CONTROL |= USBHSDCD_CONTROL_SR_MASK;
171 return kStatus_hsdcd_Success;
172 }
173 #if (defined(FSL_FEATURE_USBPHY_HAS_DCD_ANALOG) && (FSL_FEATURE_USBPHY_HAS_DCD_ANALOG > 0U))
174 /*The USB PHY is shared between DCD function and USB function, but different configurations should be used
175 in these two functions. If DCD function is desired, USB_HSDCDResetEHCIPhy should be called to set the USB PHY
176 to DCD function; If USB function is desired, USB_HSDCDSetPHYToUSBMode should be called to set the USB PHY to USB
177 function*/
USB_HSDCDSetPHYtoDCDMode(void * phyBase)178 static usb_hsdcd_status_t USB_HSDCDSetPHYtoDCDMode(void *phyBase)
179 {
180 USBPHY_Type *usbPhyBase = (USBPHY_Type *)phyBase;
181
182 if (NULL == usbPhyBase)
183 {
184 return kStatus_hsdcd_Error;
185 }
186 usbPhyBase->PWD_SET |= USBPHY_PWD_TXPWDFS_MASK;
187 usbPhyBase->ANACTRL &= ~(USBPHY_ANACTRL_DEV_PULLDOWN_MASK);
188 usbPhyBase->PLL_SIC |= (USBPHY_PLL_SIC_REFBIAS_PWD_SEL_MASK);
189 usbPhyBase->PLL_SIC &= ~(USBPHY_PLL_SIC_REFBIAS_PWD_MASK);
190 usbPhyBase->USB1_CHRG_DETECT_SET = USBPHY_USB1_CHRG_DETECT_CLR_BGR_IBIAS_MASK;
191 return kStatus_hsdcd_Success;
192 }
USB_HSDCDSetPHYtoUSBMode(void * phyBase)193 static usb_hsdcd_status_t USB_HSDCDSetPHYtoUSBMode(void *phyBase)
194 {
195 USBPHY_Type *usbPhyBase = (USBPHY_Type *)phyBase;
196
197 if (NULL == usbPhyBase)
198 {
199 return kStatus_hsdcd_Error;
200 }
201 /*de-initialize phy for dcd detect*/
202 usbPhyBase->PWD &= ~(USBPHY_PWD_TXPWDFS_MASK);
203 usbPhyBase->ANACTRL |= USBPHY_ANACTRL_DEV_PULLDOWN_MASK;
204 usbPhyBase->PLL_SIC |= USBPHY_PLL_SIC_REFBIAS_PWD_MASK;
205 usbPhyBase->PLL_SIC &= ~(USBPHY_PLL_SIC_REFBIAS_PWD_SEL_MASK);
206 return kStatus_hsdcd_Success;
207 }
208 #endif
USB_HSDCD_Control(usb_hsdcd_handle handle,usb_hsdcd_control_t type,void * param)209 usb_hsdcd_status_t USB_HSDCD_Control(usb_hsdcd_handle handle, usb_hsdcd_control_t type, void *param)
210 {
211 usb_hsdcd_state_struct_t *dcdHSState;
212 dcdHSState = (usb_hsdcd_state_struct_t *)handle;
213 usb_hsdcd_status_t dcdError = kStatus_hsdcd_Success;
214 if (NULL == handle)
215 {
216 return kStatus_hsdcd_Error;
217 }
218 switch (type)
219 {
220 case kUSB_DeviceHSDcdRun:
221 if (0U == dcdHSState->dcdDisable)
222 {
223 #if (defined(FSL_FEATURE_USBPHY_HAS_DCD_ANALOG) && (FSL_FEATURE_USBPHY_HAS_DCD_ANALOG > 0U)) && \
224 ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
225 dcdError = USB_HSDCDSetPHYtoDCDMode(dcdHSState->phyBase);
226 #endif
227 dcdHSState->dcdRegisterBase->CONTROL |= USBHSDCD_CONTROL_START_MASK;
228 }
229 break;
230 case kUSB_DeviceHSDcdStop:
231 if (0U == dcdHSState->dcdDisable)
232 {
233 #if (defined(FSL_FEATURE_USBPHY_HAS_DCD_ANALOG) && (FSL_FEATURE_USBPHY_HAS_DCD_ANALOG > 0U)) && \
234 ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
235 dcdError = USB_HSDCDSetPHYtoUSBMode(dcdHSState->phyBase);
236 #endif
237 dcdHSState->dcdRegisterBase->CONTROL |= USBHSDCD_CONTROL_SR_MASK;
238 }
239 break;
240 case kUSB_DeviceHSDcdEnable:
241 dcdHSState->dcdDisable = 0U;
242 break;
243 case kUSB_DeviceHSDcdDisable:
244 dcdHSState->dcdDisable = 1U;
245 break;
246 case kUSB_HostHSDcdSetType:
247 if ((*((uint8_t *)param)) == (uint8_t)kUSB_DcdCDP)
248 {
249 dcdHSState->dcdRegisterBase->SIGNAL_OVERRIDE =
250 ((dcdHSState->dcdRegisterBase->SIGNAL_OVERRIDE &
251 (~(USBHSDCD_SIGNAL_OVERRIDE_PS_MASK << USBHSDCD_SIGNAL_OVERRIDE_PS_SHIFT))) |
252 (USBHSDCD_SIGNAL_OVERRIDE_PS(3u)));
253 }
254 else
255 {
256 dcdHSState->dcdRegisterBase->SIGNAL_OVERRIDE =
257 (dcdHSState->dcdRegisterBase->SIGNAL_OVERRIDE &
258 (~(USBHSDCD_SIGNAL_OVERRIDE_PS_MASK << USBHSDCD_SIGNAL_OVERRIDE_PS_SHIFT)));
259 }
260 break;
261 default:
262 /*no action*/
263 break;
264 }
265 return dcdError;
266 }
USB_HSDcdIsrFunction(usb_hsdcd_handle handle)267 void USB_HSDcdIsrFunction(usb_hsdcd_handle handle)
268 {
269 uint32_t status;
270 uint32_t chargerType;
271 usb_hsdcd_state_struct_t *dcdHSState;
272 dcdHSState = (usb_hsdcd_state_struct_t *)handle;
273 usb_device_charger_detect_type_t event;
274 if (NULL == handle)
275 {
276 return;
277 }
278
279 event = kUSB_DcdError;
280 status = dcdHSState->dcdRegisterBase->STATUS;
281
282 if (0U != (status & USBHSDCD_STATUS_ERR_MASK))
283 {
284 if (0U != (status & USBHSDCD_STATUS_TO_MASK))
285 {
286 event = kUSB_DcdTimeOut;
287 }
288 else
289 {
290 event = kUSB_DcdError;
291 }
292 }
293 else
294 {
295 switch (status & USBHSDCD_STATUS_SEQ_STAT_MASK)
296 {
297 case USBHSDCD_STATUS_SEQ_STAT(kUSB_DcdChargingPortDetectionCompleted):
298 chargerType = status & USBHSDCD_STATUS_SEQ_RES_MASK;
299 if (chargerType == USBHSDCD_STATUS_SEQ_RES(kUSB_DcdDetectionStandardHost))
300 {
301 event = kUSB_DcdSDP;
302 }
303 else if (chargerType == USBHSDCD_STATUS_SEQ_RES(kUSB_DcdDetectionChargingPort))
304 {
305 event = kUSB_DcdError;
306 }
307 else
308 {
309 /*no action*/
310 }
311 break;
312 case USBHSDCD_STATUS_SEQ_STAT(kUSB_DcdChargerTypeDetectionCompleted):
313 chargerType = status & USBHSDCD_STATUS_SEQ_RES_MASK;
314 if (chargerType == USBHSDCD_STATUS_SEQ_RES(kUSB_DcdDetectionChargingPort))
315 {
316 event = kUSB_DcdCDP;
317 }
318 else if (chargerType == USBHSDCD_STATUS_SEQ_RES(kUSB_DcdDetectionDedicatedCharger))
319 {
320 event = kUSB_DcdDCP;
321 }
322 else
323 {
324 /*no action*/
325 }
326 break;
327 default:
328 /*no action*/
329 break;
330 }
331 }
332
333 dcdHSState->detectResult = (uint8_t)event;
334 dcdHSState->dcdRegisterBase->CONTROL |= USBHSDCD_CONTROL_IACK_MASK;
335 dcdHSState->dcdRegisterBase->CONTROL |= USBHSDCD_CONTROL_SR_MASK;
336 (void)dcdHSState->dcdCallback(dcdHSState->dcdCallbackParam, event, (void *)&dcdHSState->detectResult);
337 (void)USB_HSDCD_Control(dcdHSState, kUSB_DeviceHSDcdStop, NULL);
338 }
339