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