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 
45     if (controllerId < kUSB_ControllerEhci0)
46     {
47         return NULL;
48     }
49 
50     controllerId = controllerId - kUSB_ControllerEhci0;
51 
52     for (instance = 0; instance < (sizeof(usbphy_base_temp) / sizeof(usbphy_base_temp[0])); instance++)
53     {
54         if (usbphy_base_temp[instance])
55         {
56             usbphy_base[newinstance++] = usbphy_base_temp[instance];
57         }
58     }
59     if (controllerId > newinstance)
60     {
61         return NULL;
62     }
63 
64     usbPhyBase = (void *)usbphy_base[controllerId];
65 #endif
66     return usbPhyBase;
67 }
68 
69 /*!
70  * @brief ehci phy initialization.
71  *
72  * This function initialize ehci phy IP.
73  *
74  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
75  * @param[in] freq            the external input clock.
76  *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
77  *
78  * @retval kStatus_USB_Success      cancel successfully.
79  * @retval kStatus_USB_Error        the freq value is incorrect.
80  */
USB_EhciPhyInit(uint8_t controllerId,uint32_t freq,usb_phy_config_struct_t * phyConfig)81 uint32_t USB_EhciPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
82 {
83 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
84     USBPHY_Type *usbPhyBase;
85 
86     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
87     if (NULL == usbPhyBase)
88     {
89         return kStatus_USB_Error;
90     }
91 
92 #if ((defined FSL_FEATURE_SOC_ANATOP_COUNT) && (FSL_FEATURE_SOC_ANATOP_COUNT > 0U))
93     ANATOP->HW_ANADIG_REG_3P0.RW =
94         (ANATOP->HW_ANADIG_REG_3P0.RW &
95          (~(ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x1F) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_ILIMIT_MASK))) |
96         ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x17) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_LINREG_MASK;
97     ANATOP->HW_ANADIG_USB2_CHRG_DETECT.SET =
98         ANATOP_HW_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B_MASK | ANATOP_HW_ANADIG_USB2_CHRG_DETECT_EN_B_MASK;
99 #endif
100 
101 #if (defined USB_ANALOG)
102     USB_ANALOG->INSTANCE[controllerId - kUSB_ControllerEhci0].CHRG_DETECT_SET = USB_ANALOG_CHRG_DETECT_CHK_CHRG_B(1) | USB_ANALOG_CHRG_DETECT_EN_B(1);
103 #endif
104 
105 #if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
106 
107     usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
108 #endif
109     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
110     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
111     /* PWD register provides overall control of the PHY power state */
112     usbPhyBase->PWD = 0U;
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 #endif
120 
121     return kStatus_USB_Success;
122 }
123 
124 /*!
125  * @brief ehci phy initialization for suspend and resume.
126  *
127  * This function initialize ehci phy IP for suspend and resume.
128  *
129  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
130  * @param[in] freq            the external input clock.
131  *                            for example: if the external input clock is 16M, the parameter freq should be 16000000.
132  *
133  * @retval kStatus_USB_Success      cancel successfully.
134  * @retval kStatus_USB_Error        the freq value is incorrect.
135  */
USB_EhciLowPowerPhyInit(uint8_t controllerId,uint32_t freq,usb_phy_config_struct_t * phyConfig)136 uint32_t USB_EhciLowPowerPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
137 {
138 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
139     USBPHY_Type *usbPhyBase;
140 
141     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
142     if (NULL == usbPhyBase)
143     {
144         return kStatus_USB_Error;
145     }
146 
147 #if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
148     usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
149 #endif
150 
151 #if ((defined USBPHY_CTRL_AUTORESUME_EN_MASK) && (USBPHY_CTRL_AUTORESUME_EN_MASK > 0U))
152     usbPhyBase->CTRL |= USBPHY_CTRL_AUTORESUME_EN_MASK;
153 #else
154     usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTO_PWRON_PLL_MASK;
155 #endif
156     usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK;
157     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
158     usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
159     /* PWD register provides overall control of the PHY power state */
160     usbPhyBase->PWD = 0U;
161 #if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
162     /* now the 480MHz USB clock is up, then configure fractional divider after PLL with PFD
163      * pfd clock = 480MHz*18/N, where N=18~35
164      * Please note that USB1PFDCLK has to be less than 180MHz for RUN or HSRUN mode
165      */
166     usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_FRAC(24);   /* N=24 */
167     usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_CLK_SEL(1); /* div by 4 */
168 
169     usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_DEV_PULLDOWN_MASK;
170     usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_PFD_CLKGATE_MASK;
171     while (!(usbPhyBase->ANACTRL & USBPHY_ANACTRL_PFD_STABLE_MASK))
172     {
173     }
174 #endif
175     /* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
176     usbPhyBase->TX =
177         ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
178          (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
179           USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
180 #endif
181 
182     return kStatus_USB_Success;
183 }
184 
185 /*!
186  * @brief ehci phy de-initialization.
187  *
188  * This function de-initialize ehci phy IP.
189  *
190  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
191  */
USB_EhciPhyDeinit(uint8_t controllerId)192 void USB_EhciPhyDeinit(uint8_t controllerId)
193 {
194 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
195     USBPHY_Type *usbPhyBase;
196 
197     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
198     if (NULL == usbPhyBase)
199     {
200         return;
201     }
202 #if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
203     usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_POWER_MASK;       /* power down PLL */
204     usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* disable USB clock output from USB PHY PLL */
205 #endif
206     usbPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* set to 1U to gate clocks */
207 #endif
208 }
209 
210 /*!
211  * @brief ehci phy disconnect detection enable or disable.
212  *
213  * This function enable/disable host ehci disconnect detection.
214  *
215  * @param[in] controllerId   ehci controller id, please reference to #usb_controller_index_t.
216  * @param[in] enable
217  *            1U - enable;
218  *            0U - disable;
219  */
USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId,uint8_t enable)220 void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable)
221 {
222 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
223     USBPHY_Type *usbPhyBase;
224 
225     usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
226     if (NULL == usbPhyBase)
227     {
228         return;
229     }
230 
231     if (enable)
232     {
233         usbPhyBase->CTRL |= USBPHY_CTRL_ENHOSTDISCONDETECT_MASK;
234     }
235     else
236     {
237         usbPhyBase->CTRL &= (~USBPHY_CTRL_ENHOSTDISCONDETECT_MASK);
238     }
239 #endif
240 }
241