1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016 - 2017 NXP
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  *   of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  *   list of conditions and the following disclaimer in the documentation and/or
13  *   other materials provided with the distribution.
14  *
15  * o Neither the name of the copyright holder nor the names of its
16  *   contributors may be used to endorse or promote products derived from this
17  *   software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <usb/include/usb.h>
32 #include "fsl_device_registers.h"
33 
34 #include <usb/phy/usb_phy.h>
35 
USB_EhciPhyGetBase(uint8_t controllerId)36 void *USB_EhciPhyGetBase(uint8_t controllerId)
37 {
38     void *usbPhyBase = NULL;
39 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
40     uint32_t instance;
41     uint32_t newinstance        = 0;
42     uint32_t usbphy_base_temp[] = USBPHY_BASE_ADDRS;
43     uint32_t usbphy_base[]      = USBPHY_BASE_ADDRS;
44     uint32_t *temp;
45     if (controllerId < (uint8_t)kUSB_ControllerEhci0)
46     {
47         return NULL;
48     }
49 
50     if ((controllerId == (uint8_t)kUSB_ControllerEhci0) || (controllerId == (uint8_t)kUSB_ControllerEhci1))
51     {
52         controllerId = controllerId - (uint8_t)kUSB_ControllerEhci0;
53     }
54     else if ((controllerId == (uint8_t)kUSB_ControllerLpcIp3511Hs0) ||
55              (controllerId == (uint8_t)kUSB_ControllerLpcIp3511Hs1))
56     {
57         controllerId = controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0;
58     }
59     else if ((controllerId == (uint8_t)kUSB_ControllerIp3516Hs0) || (controllerId == (uint8_t)kUSB_ControllerIp3516Hs1))
60     {
61         controllerId = controllerId - (uint8_t)kUSB_ControllerIp3516Hs0;
62     }
63     else
64     {
65         /*no action*/
66     }
67 
68     for (instance = 0; instance < (sizeof(usbphy_base_temp) / sizeof(usbphy_base_temp[0])); instance++)
69     {
70         if (0U != usbphy_base_temp[instance])
71         {
72             usbphy_base[newinstance++] = usbphy_base_temp[instance];
73         }
74     }
75     if (controllerId > newinstance)
76     {
77         return NULL;
78     }
79     temp       = (uint32_t *)usbphy_base[controllerId];
80     usbPhyBase = (void *)temp;
81 #endif
82     return usbPhyBase;
83 }
84 
85 /*!
86  * @brief ehci phy initialization.
87  *
88  * This function initialize ehci phy IP.
89  *
90  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
91  * @param[in] freq            the external input clock.
92  *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
93  *
94  * @retval kStatus_USB_Success      cancel successfully.
95  * @retval kStatus_USB_Error        the freq value is incorrect.
96  */
USB_EhciPhyInit(uint8_t controllerId,uint32_t freq,usb_phy_config_struct_t * phyConfig)97 uint32_t USB_EhciPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
98 {
99 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
100     USBPHY_Type *usbPhyBase;
101 
102     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
103     if (NULL == usbPhyBase)
104     {
105         return (uint8_t)kStatus_USB_Error;
106     }
107 
108 #if ((defined FSL_FEATURE_SOC_ANATOP_COUNT) && (FSL_FEATURE_SOC_ANATOP_COUNT > 0U))
109     ANATOP->HW_ANADIG_REG_3P0.RW =
110         (ANATOP->HW_ANADIG_REG_3P0.RW &
111          (~(ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x1F) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_ILIMIT_MASK))) |
112         ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x17) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_LINREG_MASK;
113     ANATOP->HW_ANADIG_USB2_CHRG_DETECT.SET =
114         ANATOP_HW_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B_MASK | ANATOP_HW_ANADIG_USB2_CHRG_DETECT_EN_B_MASK;
115 #endif
116 
117 #if (defined USB_ANALOG)
118     USB_ANALOG->INSTANCE[controllerId - (uint8_t)kUSB_ControllerEhci0].CHRG_DETECT_SET =
119         USB_ANALOG_CHRG_DETECT_CHK_CHRG_B(1) | USB_ANALOG_CHRG_DETECT_EN_B(1);
120 #endif
121 
122 #if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
123 
124     usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
125 #endif
126     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
127     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
128     /* PWD register provides overall control of the PHY power state */
129     usbPhyBase->PWD = 0U;
130     if (((uint8_t)kUSB_ControllerIp3516Hs0 == controllerId) || ((uint8_t)kUSB_ControllerIp3516Hs1 == controllerId) ||
131         ((uint8_t)kUSB_ControllerLpcIp3511Hs0 == controllerId) ||
132         ((uint8_t)kUSB_ControllerLpcIp3511Hs1 == controllerId))
133     {
134         usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_CLKGATE_MASK;
135         usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_PHY_PWD_MASK;
136     }
137     if (NULL != phyConfig)
138     {
139         /* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
140         usbPhyBase->TX =
141             ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
142              (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
143               USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
144     }
145 #endif
146 
147     return (uint8_t)kStatus_USB_Success;
148 }
149 
150 /*!
151  * @brief ehci phy initialization for suspend and resume.
152  *
153  * This function initialize ehci phy IP for suspend and resume.
154  *
155  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
156  * @param[in] freq            the external input clock.
157  *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
158  *
159  * @retval kStatus_USB_Success      cancel successfully.
160  * @retval kStatus_USB_Error        the freq value is incorrect.
161  */
USB_EhciLowPowerPhyInit(uint8_t controllerId,uint32_t freq,usb_phy_config_struct_t * phyConfig)162 uint32_t USB_EhciLowPowerPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
163 {
164 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
165     USBPHY_Type *usbPhyBase;
166 
167     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
168     if (NULL == usbPhyBase)
169     {
170         return (uint8_t)kStatus_USB_Error;
171     }
172 
173 #if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
174     usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
175 #endif
176 
177 #if ((defined USBPHY_CTRL_AUTORESUME_EN_MASK) && (USBPHY_CTRL_AUTORESUME_EN_MASK > 0U))
178     usbPhyBase->CTRL_CLR |= USBPHY_CTRL_AUTORESUME_EN_MASK;
179 #else
180     usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTO_PWRON_PLL_MASK;
181 #endif
182     usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK;
183     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
184     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
185     /* PWD register provides overall control of the PHY power state */
186     usbPhyBase->PWD = 0U;
187 #if (defined USBPHY_ANACTRL_PFD_CLKGATE_MASK)
188     /* now the 480MHz USB clock is up, then configure fractional divider after PLL with PFD
189      * pfd clock = 480MHz*18/N, where N=18~35
190      * Please note that USB1PFDCLK has to be less than 180MHz for RUN or HSRUN mode
191      */
192     usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_FRAC(24);   /* N=24 */
193     usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_CLK_SEL(1); /* div by 4 */
194 
195     usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_DEV_PULLDOWN_MASK;
196     usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_PFD_CLKGATE_MASK;
197     while (0U == (usbPhyBase->ANACTRL & USBPHY_ANACTRL_PFD_STABLE_MASK))
198     {
199     }
200 #endif
201     if (NULL != phyConfig)
202     {
203         /* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
204         usbPhyBase->TX =
205             ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
206              (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
207               USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
208     }
209 #endif
210 
211     return (uint8_t)kStatus_USB_Success;
212 }
213 
214 /*!
215  * @brief ehci phy de-initialization.
216  *
217  * This function de-initialize ehci phy IP.
218  *
219  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
220  */
USB_EhciPhyDeinit(uint8_t controllerId)221 void USB_EhciPhyDeinit(uint8_t controllerId)
222 {
223 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
224     USBPHY_Type *usbPhyBase;
225 
226     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
227     if (NULL == usbPhyBase)
228     {
229         return;
230     }
231 #if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
232     usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_POWER_MASK;       /* power down PLL */
233     usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* disable USB clock output from USB PHY PLL */
234 #endif
235     usbPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* set to 1U to gate clocks */
236 #endif
237 }
238 
239 /*!
240  * @brief ehci phy disconnect detection enable or disable.
241  *
242  * This function enable/disable host ehci disconnect detection.
243  *
244  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
245  * @param[in] enable
246  *            1U - enable;
247  *            0U - disable;
248  */
USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId,uint8_t enable)249 void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable)
250 {
251 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
252     USBPHY_Type *usbPhyBase;
253 
254     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
255     if (NULL == usbPhyBase)
256     {
257         return;
258     }
259 
260     if (0U != enable)
261     {
262         usbPhyBase->CTRL |= USBPHY_CTRL_ENHOSTDISCONDETECT_MASK;
263     }
264     else
265     {
266         usbPhyBase->CTRL &= (~USBPHY_CTRL_ENHOSTDISCONDETECT_MASK);
267     }
268 #endif
269 }
270 
271 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
272 #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)273 void USB_PhyDeviceForceEnterFSMode(uint8_t controllerId, uint8_t enable)
274 {
275     USBPHY_Type *usbPhyBase;
276 
277     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
278     if (NULL == usbPhyBase)
279     {
280         return;
281     }
282 
283     if (0U != enable)
284     {
285         uint32_t delay         = 1000000;
286         usbPhyBase->DEBUG0_CLR = USBPHY_DEBUG0_CLKGATE_MASK;
287         while ((0U != (usbPhyBase->USB1_VBUS_DET_STAT & USBPHY_USB1_VBUS_DET_STAT_VBUS_VALID_3V_MASK)) && (0U != delay))
288         {
289             delay--;
290         }
291         usbPhyBase->USB1_LOOPBACK_SET = USBPHY_USB1_LOOPBACK_UTMI_TESTSTART_MASK;
292     }
293     else
294     {
295         usbPhyBase->DEBUG0_CLR        = USBPHY_DEBUG0_CLKGATE_MASK;
296         usbPhyBase->USB1_LOOPBACK_CLR = USBPHY_USB1_LOOPBACK_UTMI_TESTSTART_MASK;
297     }
298 }
299 #endif
300 #endif
301 
302