1 /*
2 * Copyright 2019 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7 #include "usb_phydcd.h"
8 #include "usb_phydcd_config.h"
9 /*******************************************************************************
10 * Definitions
11 ******************************************************************************/
12 #define USB_DCD_DATA_PIN_MAX_DETECTION_COUNT (100U)
13 /*time settting in ms*/
14 #define USB_DCD_DATA_PIN_DETECTION_TIME (10U)
15 #define USB_DCD_PRIMIARY_DETECTION_TIME (100U)
16 #define USB_DCD_SECONDARY_DETECTION_TIME (80U)
17 typedef enum _usb_phydcd_dev_status
18 {
19 kUSB_DCDDetectInit = 0x0U,
20 kUSB_DCDDetectIdle,
21 kUSB_DCDDetectStart,
22 kUSB_DCDDataContactDetection,
23 kUSB_DCDPrimaryDetection,
24 kUSB_DCDSecondaryDetection,
25 kUSB_DCDDectionFinished,
26 } usb_phydcd_dev_status_t;
27
28 typedef struct _usb_phydcd_state_struct
29 {
30 volatile uint64_t hwTick; /*!< Current hw tick(ms)*/
31 volatile uint64_t startTime; /*!< start time for delay*/
32 USB_ANALOG_Type *usbAnalogBase; /*!< The base address of the dcd module */
33 usb_phydcd_callback_t dcdCallback; /*!< DCD callback function*/
34 void *dcdCallbackParam; /*!< DCD callback parameter*/
35 void *phyBase; /*!< dcd phy base address, if no phy control needed, set to NULL*/
36 uint8_t dcdDisable; /*!< whether enable dcd function or not*/
37 uint8_t detectResult; /*!< dcd detect result*/
38 uint8_t index; /*!< analog instance index*/
39 volatile uint8_t dataPinCheckTimes; /*!< the check times to make sure data pin is contacted*/
40 volatile uint8_t dcdDetectState; /*!< DCD callback parameter*/
41 } usb_phydcd_state_struct_t;
42 /*******************************************************************************
43 * Prototypes
44 ******************************************************************************/
45
46 /*******************************************************************************
47 * Variables
48 ******************************************************************************/
49
50 /* Apply for device dcd state structure */
51 static usb_phydcd_state_struct_t s_UsbDeviceDcdHSState[FSL_FEATURE_SOC_USBPHY_COUNT];
52 /*******************************************************************************
53 * Code
54 ******************************************************************************/
55
USB_PHYDCD_Init(uint8_t index,usb_phydcd_config_struct_t * config,usb_phydcd_handle * dcdHandle)56 usb_phydcd_status_t USB_PHYDCD_Init(uint8_t index, usb_phydcd_config_struct_t *config, usb_phydcd_handle *dcdHandle)
57 {
58 usb_phydcd_state_struct_t *dcdState;
59 usb_phydcd_status_t dcdError = kStatus_phydcd_Success;
60 uint32_t analog_base[] = USB_ANALOG_BASE_ADDRS;
61 USB_ANALOG_Type *base;
62 uint32_t *temp;
63 base = (USB_ANALOG_Type *)analog_base[0];
64 #if defined(USBPHY_STACK_BASE_ADDRS)
65 uint32_t phyBase[] = USBPHY_STACK_BASE_ADDRS;
66 #else
67 uint32_t phyBase[] = USBPHY_BASE_ADDRS;
68 #endif
69 if ((NULL == config) || (NULL == base) || (NULL == config->dcdCallback))
70 {
71 return kStatus_phydcd_Error;
72 }
73
74 dcdState = &s_UsbDeviceDcdHSState[index];
75 dcdState->index = index;
76 temp = (uint32_t *)phyBase[index];
77 dcdState->phyBase = (void *)temp;
78 dcdState->usbAnalogBase = base;
79 dcdState->dcdCallbackParam = config->dcdCallbackParam;
80 dcdState->dcdCallback = config->dcdCallback;
81 dcdState->dcdDisable = 0U;
82 dcdState->dcdDetectState = (uint8_t)kUSB_DCDDetectInit;
83 *dcdHandle = dcdState;
84 return dcdError;
85 }
USB_PHYDCD_Deinit(usb_phydcd_handle dcdHandle)86 usb_phydcd_status_t USB_PHYDCD_Deinit(usb_phydcd_handle dcdHandle)
87 {
88 usb_phydcd_state_struct_t *dcdState;
89 dcdState = (usb_phydcd_state_struct_t *)dcdHandle;
90 usb_phydcd_status_t dcdError = kStatus_phydcd_Success;
91
92 dcdState->index = 0U;
93 dcdState->phyBase = NULL;
94 dcdState->usbAnalogBase = NULL;
95 dcdState->dcdCallbackParam = NULL;
96 dcdState->dcdCallback = NULL;
97 dcdState->dcdDisable = 0U;
98 dcdState->dcdDetectState = (uint8_t)kUSB_DCDDetectInit;
99
100 return dcdError;
101 }
USB_PHYDCD_Control(usb_phydcd_handle handle,usb_phydcd_control_t type,void * param)102 usb_phydcd_status_t USB_PHYDCD_Control(usb_phydcd_handle handle, usb_phydcd_control_t type, void *param)
103 {
104 usb_phydcd_state_struct_t *dcdState;
105 dcdState = (usb_phydcd_state_struct_t *)handle;
106 usb_phydcd_status_t dcdError = kStatus_phydcd_Success;
107 if (NULL == handle)
108 {
109 return kStatus_phydcd_Error;
110 }
111 switch (type)
112 {
113 case kUSB_DevicePHYDcdRun:
114 if (0U == dcdState->dcdDisable)
115 {
116 dcdState->dcdDetectState = (uint8_t)kUSB_DCDDetectStart;
117 }
118 break;
119 case kUSB_DevicePHYDcdStop:
120 if (0U == dcdState->dcdDisable)
121 {
122 dcdState->dcdDetectState = (uint8_t)kUSB_DCDDetectInit;
123 }
124 break;
125 case kUSB_DevicePHYDcdEnable:
126 dcdState->dcdDisable = 0U;
127 break;
128 case kUSB_DevicePHYDcdDisable:
129 dcdState->dcdDisable = 1U;
130 break;
131 default:
132 /*no action*/
133 break;
134 }
135 return dcdError;
136 }
137
USB_PHYDCD_TimerIsrFunction(usb_phydcd_handle handle)138 usb_phydcd_status_t USB_PHYDCD_TimerIsrFunction(usb_phydcd_handle handle)
139 {
140 usb_phydcd_status_t dcdError = kStatus_phydcd_Success;
141 usb_phydcd_state_struct_t *dcdState;
142 dcdState = (usb_phydcd_state_struct_t *)handle;
143 USBPHY_Type *usbPhyBase;
144 usb_phydcd_dev_status_t dcdStatus;
145 if (NULL == handle)
146 {
147 return kStatus_phydcd_Error;
148 }
149 dcdState->hwTick++;
150
151 dcdStatus = (usb_phydcd_dev_status_t)dcdState->dcdDetectState;
152 switch (dcdStatus)
153 {
154 case kUSB_DCDDetectInit:
155 break;
156 case kUSB_DCDDetectIdle:
157 break;
158 case kUSB_DCDDetectStart:
159 /*Enable the charger detector.*/
160 dcdState->dcdDetectState = (uint8_t)kUSB_DCDDataContactDetection;
161 dcdState->detectResult = (uint8_t)kUSB_DcdUnknownType;
162 dcdState->dataPinCheckTimes = 0U;
163 dcdState->usbAnalogBase->INSTANCE[dcdState->index].CHRG_DETECT_CLR |= USB_ANALOG_CHRG_DETECT_CLR_EN_B_MASK;
164 dcdState->usbAnalogBase->INSTANCE[dcdState->index].CHRG_DETECT_SET |=
165 USB_ANALOG_CHRG_DETECT_SET_CHK_CONTACT_MASK | USB_ANALOG_CHRG_DETECT_SET_CHK_CHRG_B_MASK;
166 dcdState->startTime = dcdState->hwTick;
167 break;
168 case kUSB_DCDDataContactDetection:
169 if (0U == ((dcdState->hwTick - dcdState->startTime) % USB_DCD_DATA_PIN_DETECTION_TIME))
170 {
171 if (0U != (dcdState->usbAnalogBase->INSTANCE[dcdState->index].CHRG_DETECT_STAT &
172 USB_ANALOG_CHRG_DETECT_STAT_PLUG_CONTACT_MASK))
173 {
174 dcdState->dataPinCheckTimes++;
175 if (dcdState->dataPinCheckTimes >= 5U)
176 {
177 dcdState->dcdDetectState = (uint8_t)kUSB_DCDPrimaryDetection;
178 dcdState->usbAnalogBase->INSTANCE[dcdState->index].CHRG_DETECT_CLR |=
179 USB_ANALOG_CHRG_DETECT_CLR_CHK_CONTACT_MASK | USB_ANALOG_CHRG_DETECT_CLR_CHK_CHRG_B_MASK;
180 dcdState->startTime = dcdState->hwTick;
181 }
182 }
183 else
184 {
185 dcdState->dataPinCheckTimes = 0U;
186 }
187 }
188
189 if ((dcdState->hwTick - dcdState->startTime) >=
190 USB_DCD_DATA_PIN_DETECTION_TIME * USB_DCD_DATA_PIN_MAX_DETECTION_COUNT)
191 {
192 if (((uint8_t)kUSB_DCDDataContactDetection) == dcdState->dcdDetectState)
193 {
194 dcdState->dcdDetectState = (uint8_t)kUSB_DCDDetectInit;
195 dcdState->startTime = 0U;
196 dcdState->usbAnalogBase->INSTANCE[dcdState->index].CHRG_DETECT_SET |=
197 USB_ANALOG_CHRG_DETECT_SET_EN_B_MASK | USB_ANALOG_CHRG_DETECT_SET_CHK_CHRG_B_MASK;
198 dcdState->detectResult = (uint8_t)kUSB_DcdError;
199 dcdState->dcdDetectState = (uint8_t)kUSB_DCDDectionFinished;
200 }
201 }
202 break;
203 case kUSB_DCDPrimaryDetection:
204 if (dcdState->hwTick - dcdState->startTime >= USB_DCD_PRIMIARY_DETECTION_TIME)
205 {
206 if (0U == (dcdState->usbAnalogBase->INSTANCE[dcdState->index].CHRG_DETECT_STAT &
207 USB_ANALOG_CHRG_DETECT_STAT_CHRG_DETECTED_MASK))
208 {
209 dcdState->detectResult = (uint8_t)kUSB_DcdSDP;
210 dcdState->dcdDetectState = (uint8_t)kUSB_DCDDectionFinished;
211 }
212 else
213 {
214 dcdState->dcdDetectState = (uint8_t)kUSB_DCDSecondaryDetection;
215 }
216 dcdState->usbAnalogBase->INSTANCE[dcdState->index].CHRG_DETECT_SET |=
217 USB_ANALOG_CHRG_DETECT_SET_EN_B_MASK | USB_ANALOG_CHRG_DETECT_SET_CHK_CHRG_B_MASK;
218 if (((uint8_t)kUSB_DCDSecondaryDetection) == dcdState->dcdDetectState)
219 {
220 usbPhyBase = (USBPHY_Type *)dcdState->phyBase;
221 usbPhyBase->DEBUG_CLR |= USBPHY_DEBUG_CLR_CLKGATE_MASK;
222 dcdState->usbAnalogBase->INSTANCE[dcdState->index].LOOPBACK_SET |=
223 USB_ANALOG_LOOPBACK_UTMI_TESTSTART_MASK;
224 }
225 dcdState->startTime = dcdState->hwTick;
226 }
227 break;
228 case kUSB_DCDSecondaryDetection:
229 if (dcdState->hwTick - dcdState->startTime >= USB_DCD_SECONDARY_DETECTION_TIME)
230 {
231 if (0U != (dcdState->usbAnalogBase->INSTANCE[dcdState->index].CHRG_DETECT_STAT &
232 USB_ANALOG_CHRG_DETECT_STAT_DM_STATE_MASK))
233 {
234 dcdState->detectResult = (uint8_t)kUSB_DcdDCP;
235 }
236 else
237 {
238 dcdState->detectResult = (uint8_t)kUSB_DcdCDP;
239 }
240 dcdState->usbAnalogBase->INSTANCE[dcdState->index].LOOPBACK_CLR |=
241 USB_ANALOG_LOOPBACK_UTMI_TESTSTART_MASK;
242 usbPhyBase = (USBPHY_Type *)dcdState->phyBase;
243 usbPhyBase->DEBUG_SET |= USBPHY_DEBUG_CLR_CLKGATE_MASK;
244 dcdState->dcdDetectState = (uint8_t)kUSB_DCDDectionFinished;
245 }
246 break;
247 case kUSB_DCDDectionFinished:
248 dcdState->dcdDetectState = (uint8_t)kUSB_DCDDetectIdle;
249 (void)dcdState->dcdCallback(dcdState->dcdCallbackParam, dcdState->detectResult,
250 (void *)&dcdState->detectResult);
251 break;
252 default:
253 /* no action*/
254 break;
255 }
256 return dcdError;
257 }
258