1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016 - 2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "usb.h"
10 #include "fsl_device_registers.h"
11 
12 #include "usb_phy.h"
13 
USB_EhciPhyGetBase(uint8_t controllerId)14 void *USB_EhciPhyGetBase(uint8_t controllerId)
15 {
16     void *usbPhyBase = NULL;
17 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
18 #if defined(USBPHY_STACK_BASE_ADDRS)
19     uint32_t usbphy_base[] = USBPHY_STACK_BASE_ADDRS;
20 #else
21     uint32_t usbphy_base[] = USBPHY_BASE_ADDRS;
22 #endif
23     uint32_t *temp;
24     if (controllerId < (uint8_t)kUSB_ControllerEhci0)
25     {
26         return NULL;
27     }
28 
29     if ((controllerId == (uint8_t)kUSB_ControllerEhci0) || (controllerId == (uint8_t)kUSB_ControllerEhci1))
30     {
31         controllerId = controllerId - (uint8_t)kUSB_ControllerEhci0;
32     }
33     else if ((controllerId == (uint8_t)kUSB_ControllerLpcIp3511Hs0) ||
34              (controllerId == (uint8_t)kUSB_ControllerLpcIp3511Hs1))
35     {
36         controllerId = controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0;
37     }
38     else if ((controllerId == (uint8_t)kUSB_ControllerIp3516Hs0) || (controllerId == (uint8_t)kUSB_ControllerIp3516Hs1))
39     {
40         controllerId = controllerId - (uint8_t)kUSB_ControllerIp3516Hs0;
41     }
42     else
43     {
44         return NULL;
45     }
46 
47     if (controllerId < (sizeof(usbphy_base) / sizeof(usbphy_base[0])))
48     {
49         temp       = (uint32_t *)usbphy_base[controllerId];
50         usbPhyBase = (void *)temp;
51     }
52     else
53     {
54         return NULL;
55     }
56 #endif
57     return usbPhyBase;
58 }
59 
60 /*!
61  * @brief ehci phy initialization.
62  *
63  * This function initialize ehci phy IP.
64  *
65  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
66  * @param[in] freq            the external input clock.
67  *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
68  *
69  * @retval kStatus_USB_Success      cancel successfully.
70  * @retval kStatus_USB_Error        the freq value is incorrect.
71  */
USB_EhciPhyInit(uint8_t controllerId,uint32_t freq,usb_phy_config_struct_t * phyConfig)72 uint32_t USB_EhciPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
73 {
74 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
75     USBPHY_Type *usbPhyBase;
76 
77     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
78     if (NULL == usbPhyBase)
79     {
80         return (uint8_t)kStatus_USB_Error;
81     }
82 
83 #if ((defined FSL_FEATURE_SOC_ANATOP_COUNT) && (FSL_FEATURE_SOC_ANATOP_COUNT > 0U))
84     ANATOP->HW_ANADIG_REG_3P0.RW =
85         (ANATOP->HW_ANADIG_REG_3P0.RW &
86          (~(ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x1F) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_ILIMIT_MASK))) |
87         ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x17) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_LINREG_MASK;
88     ANATOP->HW_ANADIG_USB2_CHRG_DETECT.SET =
89         ANATOP_HW_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B_MASK | ANATOP_HW_ANADIG_USB2_CHRG_DETECT_EN_B_MASK;
90 #endif
91 
92 #if (defined USB_ANALOG)
93     USB_ANALOG->INSTANCE[controllerId - (uint8_t)kUSB_ControllerEhci0].CHRG_DETECT_SET =
94         USB_ANALOG_CHRG_DETECT_CHK_CHRG_B(1) | USB_ANALOG_CHRG_DETECT_EN_B(1);
95 #endif
96 
97 #if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
98 
99     usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
100 #endif
101     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
102     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
103     /* PWD register provides overall control of the PHY power state */
104     usbPhyBase->PWD = 0U;
105     if (((uint8_t)kUSB_ControllerIp3516Hs0 == controllerId) || ((uint8_t)kUSB_ControllerIp3516Hs1 == controllerId) ||
106         ((uint8_t)kUSB_ControllerLpcIp3511Hs0 == controllerId) ||
107         ((uint8_t)kUSB_ControllerLpcIp3511Hs1 == controllerId))
108     {
109         usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_CLKGATE_MASK;
110         usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_PHY_PWD_MASK;
111     }
112     if (NULL != phyConfig)
113     {
114         /* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
115         usbPhyBase->TX =
116             ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
117              (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
118               USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
119     }
120 #endif
121 
122     return (uint8_t)kStatus_USB_Success;
123 }
124 
125 /*!
126  * @brief ehci phy initialization for suspend and resume.
127  *
128  * This function initialize ehci phy IP for suspend and resume.
129  *
130  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
131  * @param[in] freq            the external input clock.
132  *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
133  *
134  * @retval kStatus_USB_Success      cancel successfully.
135  * @retval kStatus_USB_Error        the freq value is incorrect.
136  */
USB_EhciLowPowerPhyInit(uint8_t controllerId,uint32_t freq,usb_phy_config_struct_t * phyConfig)137 uint32_t USB_EhciLowPowerPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
138 {
139 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
140     USBPHY_Type *usbPhyBase;
141 
142     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
143     if (NULL == usbPhyBase)
144     {
145         return (uint8_t)kStatus_USB_Error;
146     }
147 
148 #if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
149     usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
150 #endif
151 
152 #if ((defined USBPHY_CTRL_AUTORESUME_EN_MASK) && (USBPHY_CTRL_AUTORESUME_EN_MASK > 0U))
153     usbPhyBase->CTRL_CLR |= USBPHY_CTRL_AUTORESUME_EN_MASK;
154 #else
155     usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTO_PWRON_PLL_MASK;
156 #endif
157     usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK;
158     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
159     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
160     /* PWD register provides overall control of the PHY power state */
161     usbPhyBase->PWD = 0U;
162 #if (defined USBPHY_ANACTRL_PFD_CLKGATE_MASK)
163     /* now the 480MHz USB clock is up, then configure fractional divider after PLL with PFD
164      * pfd clock = 480MHz*18/N, where N=18~35
165      * Please note that USB1PFDCLK has to be less than 180MHz for RUN or HSRUN mode
166      */
167     usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_FRAC(24);   /* N=24 */
168     usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_CLK_SEL(1); /* div by 4 */
169 
170     usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_DEV_PULLDOWN_MASK;
171     usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_PFD_CLKGATE_MASK;
172     while (0U == (usbPhyBase->ANACTRL & USBPHY_ANACTRL_PFD_STABLE_MASK))
173     {
174     }
175 #endif
176     if (NULL != phyConfig)
177     {
178         /* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
179         usbPhyBase->TX =
180             ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
181              (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
182               USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
183     }
184 #endif
185 
186     return (uint8_t)kStatus_USB_Success;
187 }
188 
189 /*!
190  * @brief ehci phy de-initialization.
191  *
192  * This function de-initialize ehci phy IP.
193  *
194  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
195  */
USB_EhciPhyDeinit(uint8_t controllerId)196 void USB_EhciPhyDeinit(uint8_t controllerId)
197 {
198 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
199     USBPHY_Type *usbPhyBase;
200 
201     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
202     if (NULL == usbPhyBase)
203     {
204         return;
205     }
206 #if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
207     usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_POWER_MASK;       /* power down PLL */
208     usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* disable USB clock output from USB PHY PLL */
209 #endif
210     usbPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* set to 1U to gate clocks */
211 #endif
212 }
213 
214 /*!
215  * @brief ehci phy disconnect detection enable or disable.
216  *
217  * This function enable/disable host ehci disconnect detection.
218  *
219  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
220  * @param[in] enable
221  *            1U - enable;
222  *            0U - disable;
223  */
USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId,uint8_t enable)224 void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable)
225 {
226 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
227     USBPHY_Type *usbPhyBase;
228 
229     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
230     if (NULL == usbPhyBase)
231     {
232         return;
233     }
234 
235     if (0U != enable)
236     {
237         usbPhyBase->CTRL |= USBPHY_CTRL_ENHOSTDISCONDETECT_MASK;
238     }
239     else
240     {
241         usbPhyBase->CTRL &= (~USBPHY_CTRL_ENHOSTDISCONDETECT_MASK);
242     }
243 #endif
244 }
245 
246 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
247 #if ((defined FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE) && (FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE > 0U))
USB_PhyDeviceForceEnterFSMode(uint8_t controllerId,uint8_t enable)248 void USB_PhyDeviceForceEnterFSMode(uint8_t controllerId, uint8_t enable)
249 {
250     USBPHY_Type *usbPhyBase;
251 
252     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
253     if (NULL == usbPhyBase)
254     {
255         return;
256     }
257 
258     if (0U != enable)
259     {
260         uint32_t delay         = 1000000;
261         usbPhyBase->DEBUG0_CLR = USBPHY_DEBUG0_CLKGATE_MASK;
262         while ((0U != (usbPhyBase->USB1_VBUS_DET_STAT & USBPHY_USB1_VBUS_DET_STAT_VBUS_VALID_3V_MASK)) && (0U != delay))
263         {
264             delay--;
265         }
266         usbPhyBase->USB1_LOOPBACK_SET = USBPHY_USB1_LOOPBACK_UTMI_TESTSTART_MASK;
267     }
268     else
269     {
270         usbPhyBase->DEBUG0_CLR        = USBPHY_DEBUG0_CLKGATE_MASK;
271         usbPhyBase->USB1_LOOPBACK_CLR = USBPHY_USB1_LOOPBACK_UTMI_TESTSTART_MASK;
272     }
273 }
274 #endif
275 #endif
276