mediatek: add support for the new MT7623 Arm SoC
[openwrt.git] / target / linux / mediatek / patches / 0046-usb-phy-add-usb3.0-phy-driver-for-mt65xx-SoCs.patch
1 From cee7c5a343bdecf407c876289327c567bfd34fd4 Mon Sep 17 00:00:00 2001
2 From: Chunfeng Yun <chunfeng.yun@mediatek.com>
3 Date: Wed, 27 May 2015 19:48:01 +0800
4 Subject: [PATCH 46/76] usb: phy: add usb3.0 phy driver for mt65xx SoCs
5
6 Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
7 ---
8  drivers/usb/phy/Kconfig           |   10 +
9  drivers/usb/phy/Makefile          |    1 +
10  drivers/usb/phy/phy-mt65xx-usb3.c |  724 +++++++++++++++++++++++++++++++++++++
11  3 files changed, 735 insertions(+)
12  create mode 100644 drivers/usb/phy/phy-mt65xx-usb3.c
13
14 diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
15 index 2175678..dfca566 100644
16 --- a/drivers/usb/phy/Kconfig
17 +++ b/drivers/usb/phy/Kconfig
18 @@ -151,6 +151,16 @@ config USB_MSM_OTG
19           This driver is not supported on boards like trout which
20           has an external PHY.
21  
22 +config USB_MT65XX_USB3_PHY
23 +       tristate "Mediatek USB3.0 PHY controller Driver"
24 +       depends on ARCH_MEDIATEK || COMPILE_TEST
25 +       select USB_PHY
26 +       help
27 +         Say 'Y' here to add support for Mediatek USB3.0 PHY driver
28 +         for mt65xx SoCs. it supports two usb2.0 ports and
29 +         one usb3.0 port.
30 +         To compile this driver as a module, choose M here
31 +
32  config USB_MV_OTG
33         tristate "Marvell USB OTG support"
34         depends on USB_EHCI_MV && USB_MV_UDC && PM
35 diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
36 index 75f2bba..d6113a4 100644
37 --- a/drivers/usb/phy/Makefile
38 +++ b/drivers/usb/phy/Makefile
39 @@ -20,6 +20,7 @@ obj-$(CONFIG_USB_EHCI_TEGRA)          += phy-tegra-usb.o
40  obj-$(CONFIG_USB_GPIO_VBUS)            += phy-gpio-vbus-usb.o
41  obj-$(CONFIG_USB_ISP1301)              += phy-isp1301.o
42  obj-$(CONFIG_USB_MSM_OTG)              += phy-msm-usb.o
43 +obj-$(CONFIG_USB_MT65XX_USB3_PHY)      += phy-mt65xx-usb3.o
44  obj-$(CONFIG_USB_MV_OTG)               += phy-mv-usb.o
45  obj-$(CONFIG_USB_MXS_PHY)              += phy-mxs-usb.o
46  obj-$(CONFIG_USB_RCAR_PHY)             += phy-rcar-usb.o
47 diff --git a/drivers/usb/phy/phy-mt65xx-usb3.c b/drivers/usb/phy/phy-mt65xx-usb3.c
48 new file mode 100644
49 index 0000000..ec5cf24
50 --- /dev/null
51 +++ b/drivers/usb/phy/phy-mt65xx-usb3.c
52 @@ -0,0 +1,724 @@
53 +/*
54 + * Copyright (c) 2015 MediaTek Inc.
55 + * Author: Chunfeng.Yun <chunfeng.yun@mediatek.com>
56 + *
57 + * This software is licensed under the terms of the GNU General Public
58 + * License version 2, as published by the Free Software Foundation, and
59 + * may be copied, distributed, and modified under those terms.
60 + *
61 + * This program is distributed in the hope that it will be useful,
62 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
63 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
64 + * GNU General Public License for more details.
65 + *
66 + */
67 +
68 +#include <linux/resource.h>
69 +#include <linux/delay.h>
70 +#include <linux/slab.h>
71 +#include <linux/err.h>
72 +#include <linux/export.h>
73 +#include <linux/module.h>
74 +#include <linux/platform_device.h>
75 +#include <linux/regulator/consumer.h>
76 +#include <linux/pm_runtime.h>
77 +#include <linux/io.h>
78 +#include <linux/gpio.h>
79 +#include <linux/of.h>
80 +#include <linux/of_device.h>
81 +#include <linux/of_gpio.h>
82 +#include <linux/of_address.h>
83 +#include <linux/usb/otg.h>
84 +#include <linux/usb/of.h>
85 +#include <linux/usb/phy.h>
86 +#include <linux/clk.h>
87 +#include <linux/iopoll.h>
88 +
89 +/*
90 + * relative to MAC base address
91 + */
92 +#define SSUSB_USB3_MAC_CSR_BASE        (0x1400)
93 +#define SSUSB_USB3_SYS_CSR_BASE        (0x1400)
94 +#define SSUSB_USB2_CSR_BASE            (0x2400)
95 +
96 +/*
97 + * for sifslv1 register
98 + * relative to USB3_SIF_BASE base address
99 + */
100 +#define SSUSB_SIFSLV_IPPC_BASE         (0x700)
101 +
102 +/*
103 + * for sifslv2 register
104 + * relative to USB3_SIF_BASE base address
105 + */
106 +#define SSUSB_SIFSLV_U2PHY_COM_BASE    (0x10800)
107 +#define SSUSB_SIFSLV_U3PHYD_BASE       (0x10900)
108 +#define SSUSB_SIFSLV_U2FREQ_BASE       (0x10f00)
109 +#define SSUSB_USB30_PHYA_SIV_B_BASE            (0x10b00)
110 +#define SSUSB_SIFSLV_U3PHYA_DA_BASE            (0x10c00)
111 +#define SSUSB_SIFSLV_SPLLC             (0x10000)
112 +
113 +/*port1 refs. +0x800(refer to port0)*/
114 +#define U3P_PORT_OFFSET (0x800)        /*based on port0 */
115 +#define U3P_PHY_BASE(index) ((U3P_PORT_OFFSET) * (index))
116 +
117 +#define U3P_IP_PW_CTRL0        (SSUSB_SIFSLV_IPPC_BASE+0x0000)
118 +#define CTRL0_IP_SW_RST                        (0x1<<0)
119 +
120 +#define U3P_IP_PW_CTRL1        (SSUSB_SIFSLV_IPPC_BASE+0x0004)
121 +#define CTRL1_IP_HOST_PDN              (0x1<<0)
122 +
123 +#define U3P_IP_PW_STS1         (SSUSB_SIFSLV_IPPC_BASE+0x0010)
124 +#define STS1_U3_MAC_RST                (0x1 << 16)
125 +#define STS1_SYS125_RST                (0x1 << 10)
126 +#define STS1_REF_RST           (0x1 << 8)
127 +#define STS1_SYSPLL_STABLE     (0x1 << 0)
128 +
129 +#define U3P_IP_PW_STS2 (SSUSB_SIFSLV_IPPC_BASE+0x0014)
130 +#define STS2_U2_MAC_RST        (0x1 << 0)
131 +
132 +#define U3P_IP_XHCI_CAP        (SSUSB_SIFSLV_IPPC_BASE + 0x24)
133 +#define CAP_U3_PORT_NUM(p)     ((p) & 0xff)
134 +#define CAP_U2_PORT_NUM(p)     (((p) >> 8) & 0xff)
135 +
136 +#define U3P_U3_CTRL_0P (SSUSB_SIFSLV_IPPC_BASE+0x0030)
137 +#define CTRL_U3_PORT_HOST_SEL  (0x1<<2)
138 +#define CTRL_U3_PORT_PDN               (0x1<<1)
139 +#define CTRL_U3_PORT_DIS               (0x1<<0)
140 +
141 +#define U3P_U2_CTRL_0P (SSUSB_SIFSLV_IPPC_BASE+0x0050)
142 +#define CTRL_U2_PORT_HOST_SEL  (0x1<<2)
143 +#define CTRL_U2_PORT_PDN               (0x1<<1)
144 +#define CTRL_U2_PORT_DIS               (0x1<<0)
145 +
146 +#define U3P_U3_CTRL(p) (U3P_U3_CTRL_0P + ((p) * 0x08))
147 +#define U3P_U2_CTRL(p) (U3P_U2_CTRL_0P + ((p) * 0x08))
148 +
149 +#define U3P_USBPHYACR5      (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0014)
150 +#define PA5_RG_U2_HSTX_SRCTRL                  (0x7<<12)
151 +#define PA5_RG_U2_HSTX_SRCTRL_VAL(x)   ((0x7 & (x)) << 12)
152 +#define PA5_RG_U2_HS_100U_U3_EN                        (0x1<<11)
153 +
154 +#define U3P_USBPHYACR6      (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0018)
155 +#define PA6_RG_U2_ISO_EN                       (0x1<<31)
156 +#define PA6_RG_U2_BC11_SW_EN           (0x1<<23)
157 +#define PA6_RG_U2_OTG_VBUSCMP_EN       (0x1<<20)
158 +
159 +#define U3P_U2PHYACR4       (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0020)
160 +#define P2C_RG_USB20_GPIO_CTL  (0x1<<9)
161 +#define P2C_USB20_GPIO_MODE            (0x1<<8)
162 +#define P2C_U2_GPIO_CTR_MSK  (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE)
163 +
164 +#define U3P_U2PHYDTM0       (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0068)
165 +#define P2C_FORCE_UART_EN              (0x1<<26)
166 +#define P2C_FORCE_DATAIN               (0x1<<23)
167 +#define P2C_FORCE_DM_PULLDOWN  (0x1<<21)
168 +#define P2C_FORCE_DP_PULLDOWN  (0x1<<20)
169 +#define P2C_FORCE_XCVRSEL              (0x1<<19)
170 +#define P2C_FORCE_SUSPENDM             (0x1<<18)
171 +#define P2C_FORCE_TERMSEL              (0x1<<17)
172 +#define P2C_RG_DATAIN                  (0xf<<10)
173 +#define P2C_RG_DATAIN_VAL(x)   ((0xf & (x)) << 10)
174 +#define P2C_RG_DMPULLDOWN              (0x1<<7)
175 +#define P2C_RG_DPPULLDOWN              (0x1<<6)
176 +#define P2C_RG_XCVRSEL                 (0x3<<4)
177 +#define P2C_RG_XCVRSEL_VAL(x)  ((0x3 & (x)) << 4)
178 +#define P2C_RG_SUSPENDM                        (0x1<<3)
179 +#define P2C_RG_TERMSEL                 (0x1<<2)
180 +#define P2C_DTM0_PART_MASK \
181 +               (P2C_FORCE_DATAIN | P2C_FORCE_DM_PULLDOWN | \
182 +               P2C_FORCE_DP_PULLDOWN | P2C_FORCE_XCVRSEL | \
183 +               P2C_FORCE_TERMSEL | P2C_RG_DMPULLDOWN | \
184 +               P2C_RG_TERMSEL)
185 +
186 +#define U3P_U2PHYDTM1       (SSUSB_SIFSLV_U2PHY_COM_BASE+0x006C)
187 +#define P2C_RG_UART_EN         (0x1<<16)
188 +#define P2C_RG_VBUSVALID       (0x1<<5)
189 +#define P2C_RG_SESSEND         (0x1<<4)
190 +#define P2C_RG_AVALID          (0x1<<2)
191 +
192 +#define U3P_U3_PHYA_REG0       (SSUSB_USB30_PHYA_SIV_B_BASE+0x0000)
193 +#define P3A_RG_U3_VUSB10_ON                    (1<<5)
194 +
195 +#define U3P_U3_PHYA_REG6       (SSUSB_USB30_PHYA_SIV_B_BASE+0x0018)
196 +#define P3A_RG_TX_EIDLE_CM                     (0xf<<28)
197 +#define P3A_RG_TX_EIDLE_CM_VAL(x)      ((0xf & (x)) << 28)
198 +
199 +#define U3P_U3_PHYA_REG9       (SSUSB_USB30_PHYA_SIV_B_BASE+0x0024)
200 +#define P3A_RG_RX_DAC_MUX                      (0x1f<<1)
201 +#define P3A_RG_RX_DAC_MUX_VAL(x)       ((0x1f & (x)) << 1)
202 +
203 +#define U3P_U3PHYA_DA_REG0     (SSUSB_SIFSLV_U3PHYA_DA_BASE + 0x0)
204 +#define P3A_RG_XTAL_EXT_EN_U3                  (0x3<<10)
205 +#define P3A_RG_XTAL_EXT_EN_U3_VAL(x)   ((0x3 & (x)) << 10)
206 +
207 +#define U3P_PHYD_CDR1          (SSUSB_SIFSLV_U3PHYD_BASE+0x5c)
208 +#define P3D_RG_CDR_BIR_LTD1                            (0x1f<<24)
209 +#define P3D_RG_CDR_BIR_LTD1_VAL(x)             ((0x1f & (x)) << 24)
210 +#define P3D_RG_CDR_BIR_LTD0                            (0x1f<<8)
211 +#define P3D_RG_CDR_BIR_LTD0_VAL(x)             ((0x1f & (x)) << 8)
212 +
213 +#define U3P_XTALCTL3           (SSUSB_SIFSLV_SPLLC + 0x18)
214 +#define XC3_RG_U3_XTAL_RX_PWD                  (0x1<<9)
215 +#define XC3_RG_U3_FRC_XTAL_RX_PWD              (0x1<<8)
216 +
217 +#define U3P_UX_EXIT_LFPS_PARAM (SSUSB_USB3_MAC_CSR_BASE+0x00A0)
218 +#define RX_UX_EXIT_REF         (0xff<<8)
219 +#define RX_UX_EXIT_REF_VAL     (0x3 << 8)
220 +
221 +#define U3P_REF_CLK_PARAM      (SSUSB_USB3_MAC_CSR_BASE+0x00B0)
222 +#define REF_CLK_1000NS         (0xff << 0)
223 +#define REF_CLK_VAL_DEF                (0xa << 0)
224 +
225 +#define U3P_LINK_PM_TIMER                      (SSUSB_USB3_SYS_CSR_BASE+0x0208)
226 +#define PM_LC_TIMEOUT                  (0xf<<0)
227 +#define PM_LC_TIMEOUT_VAL              (0x3 << 0)
228 +
229 +#define U3P_TIMING_PULSE_CTRL  (SSUSB_USB3_SYS_CSR_BASE+0x02B4)
230 +#define U3T_CNT_1US                    (0xff << 0)
231 +#define U3T_CNT_1US_VAL                (0x3f << 0)     /* 62.5MHz: 63 */
232 +
233 +#define U3P_U2_TIMING_PARAM            (SSUSB_USB2_CSR_BASE+0x0040)
234 +#define U2T_VAL_1US                    (0xff<<0)
235 +#define U2T_VAL_1US_VAL                (0x3f << 0)     /* 62.5MHz: 63 */
236 +
237 +
238 +struct mt65xx_u3phy {
239 +       struct usb_phy phy;
240 +       struct device *dev;
241 +       struct regulator *vusb33;
242 +       struct regulator *p1_vbus;
243 +       void __iomem *mac_base; /* only device-mac regs, exclude xhci's */
244 +       void __iomem *sif_base; /* include sif & sif2 */
245 +       struct clk *wk_deb_p0;  /* port0's wakeup debounce clock */
246 +       struct clk *wk_deb_p1;
247 +       struct clk *sys_mac;    /* sys and mac clock */
248 +       struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
249 +       bool enable_usb2_p1;
250 +};
251 +
252 +
253 +static void u3p_writel(void __iomem *base, u32 offset, u32 data)
254 +{
255 +       writel(data, base + offset);
256 +}
257 +
258 +static u32 u3p_readl(void __iomem *base, u32 offset)
259 +{
260 +       return readl(base + offset);
261 +}
262 +
263 +static void u3p_setmsk(void __iomem *base, u32 offset, u32 msk)
264 +{
265 +       void __iomem *addr = base + offset;
266 +
267 +       writel((readl(addr) | msk), addr);
268 +}
269 +
270 +static void u3p_clrmsk(void __iomem *base, u32 offset, u32 msk)
271 +{
272 +       void __iomem *addr = base + offset;
273 +
274 +       writel((readl(addr) & ~msk), addr);
275 +}
276 +
277 +static void u3p_setval(void __iomem *base, u32 offset,
278 +       u32 mask, u32 value)
279 +{
280 +       void __iomem *addr = base + offset;
281 +       unsigned int new_value;
282 +
283 +       new_value = (readl(addr) & ~mask) | value;
284 +       writel(new_value, addr);
285 +}
286 +
287 +static void phy_index_power_on(struct mt65xx_u3phy *u3phy, int index)
288 +{
289 +       void __iomem *sif_base = u3phy->sif_base + U3P_PHY_BASE(index);
290 +
291 +       if (!index) {
292 +               /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */
293 +               u3p_setmsk(sif_base, U3P_U3_PHYA_REG0, P3A_RG_U3_VUSB10_ON);
294 +               /* power domain iso disable */
295 +               u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_ISO_EN);
296 +       }
297 +
298 +       /* switch to USB function. (system register, force ip into usb mode) */
299 +       u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_UART_EN);
300 +       u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_UART_EN);
301 +       if (!index)
302 +               u3p_clrmsk(sif_base, U3P_U2PHYACR4, P2C_U2_GPIO_CTR_MSK);
303 +
304 +       /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */
305 +       u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_SUSPENDM);
306 +       u3p_clrmsk(sif_base, U3P_U2PHYDTM0,
307 +                       P2C_RG_XCVRSEL | P2C_RG_DATAIN | P2C_DTM0_PART_MASK);
308 +
309 +       /* DP/DM BC1.1 path Disable */
310 +       u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_BC11_SW_EN);
311 +       /* OTG Enable */
312 +       u3p_setmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_OTG_VBUSCMP_EN);
313 +       u3p_setval(sif_base, U3P_U3PHYA_DA_REG0, P3A_RG_XTAL_EXT_EN_U3,
314 +                       P3A_RG_XTAL_EXT_EN_U3_VAL(2));
315 +       u3p_setval(sif_base, U3P_U3_PHYA_REG9, P3A_RG_RX_DAC_MUX,
316 +                       P3A_RG_RX_DAC_MUX_VAL(4));
317 +
318 +       if (!index) {
319 +               u3p_setmsk(sif_base, U3P_XTALCTL3, XC3_RG_U3_XTAL_RX_PWD);
320 +               u3p_setmsk(sif_base, U3P_XTALCTL3, XC3_RG_U3_FRC_XTAL_RX_PWD);
321 +               /* [mt8173]disable Change 100uA current from SSUSB */
322 +               u3p_clrmsk(sif_base, U3P_USBPHYACR5, PA5_RG_U2_HS_100U_U3_EN);
323 +       }
324 +       u3p_setval(sif_base, U3P_U3_PHYA_REG6, P3A_RG_TX_EIDLE_CM,
325 +                       P3A_RG_TX_EIDLE_CM_VAL(0xe));
326 +       u3p_setval(sif_base, U3P_PHYD_CDR1, P3D_RG_CDR_BIR_LTD0,
327 +                       P3D_RG_CDR_BIR_LTD0_VAL(0xc));
328 +       u3p_setval(sif_base, U3P_PHYD_CDR1, P3D_RG_CDR_BIR_LTD1,
329 +                       P3D_RG_CDR_BIR_LTD1_VAL(0x3));
330 +
331 +       udelay(800);
332 +       u3p_setmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_VBUSVALID | P2C_RG_AVALID);
333 +       u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_SESSEND);
334 +
335 +       /* USB 2.0 slew rate calibration */
336 +       u3p_setval(sif_base, U3P_USBPHYACR5, PA5_RG_U2_HSTX_SRCTRL,
337 +                       PA5_RG_U2_HSTX_SRCTRL_VAL(4));
338 +
339 +       dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
340 +}
341 +
342 +
343 +static void phy_index_power_off(struct mt65xx_u3phy *u3phy, int index)
344 +{
345 +       void __iomem *sif_base = u3phy->sif_base + U3P_PHY_BASE(index);
346 +
347 +       /* switch to USB function. (system register, force ip into usb mode) */
348 +       u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_UART_EN);
349 +       u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_UART_EN);
350 +       if (!index)
351 +               u3p_clrmsk(sif_base, U3P_U2PHYACR4, P2C_U2_GPIO_CTR_MSK);
352 +
353 +       u3p_setmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_SUSPENDM);
354 +       u3p_setval(sif_base, U3P_U2PHYDTM0,
355 +                       P2C_RG_XCVRSEL, P2C_RG_XCVRSEL_VAL(1));
356 +       u3p_setval(sif_base, U3P_U2PHYDTM0,
357 +                       P2C_RG_DATAIN, P2C_RG_DATAIN_VAL(0));
358 +       u3p_setmsk(sif_base, U3P_U2PHYDTM0, P2C_DTM0_PART_MASK);
359 +       /* DP/DM BC1.1 path Disable */
360 +       u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_BC11_SW_EN);
361 +       /* OTG Disable */
362 +       u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_OTG_VBUSCMP_EN);
363 +       if (!index) {
364 +               /* Change 100uA current switch to USB2.0 */
365 +               u3p_clrmsk(sif_base, U3P_USBPHYACR5, PA5_RG_U2_HS_100U_U3_EN);
366 +       }
367 +       udelay(800);
368 +
369 +       /* let suspendm=0, set utmi into analog power down */
370 +       u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_RG_SUSPENDM);
371 +       udelay(1);
372 +
373 +       u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_VBUSVALID | P2C_RG_AVALID);
374 +       u3p_setmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_SESSEND);
375 +       if (!index) {
376 +               /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */
377 +               u3p_clrmsk(sif_base, U3P_U3_PHYA_REG0, P3A_RG_U3_VUSB10_ON);
378 +       }
379 +       dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
380 +}
381 +
382 +
383 +static int check_ip_clk_status(struct mt65xx_u3phy *u3phy)
384 +{
385 +       int ret;
386 +       int u3_port_num;
387 +       int u2_port_num;
388 +       u32 xhci_cap;
389 +       u32 val;
390 +       void __iomem *sif_base = u3phy->sif_base;
391 +
392 +       xhci_cap = u3p_readl(sif_base, U3P_IP_XHCI_CAP);
393 +       u3_port_num = CAP_U3_PORT_NUM(xhci_cap);
394 +       u2_port_num = CAP_U2_PORT_NUM(xhci_cap);
395 +
396 +       ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
397 +                         (val & STS1_SYSPLL_STABLE), 100, 10000);
398 +       if (ret) {
399 +               dev_err(u3phy->dev, "sypll is not stable!!!\n");
400 +               return ret;
401 +       }
402 +
403 +       ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
404 +                         (val & STS1_REF_RST), 100, 10000);
405 +       if (ret) {
406 +               dev_err(u3phy->dev, "ref_clk is still active!!!\n");
407 +               return ret;
408 +       }
409 +
410 +       ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
411 +                          (val & STS1_SYS125_RST), 100, 10000);
412 +       if (ret) {
413 +               dev_err(u3phy->dev, "sys125_ck is still active!!!\n");
414 +               return ret;
415 +       }
416 +
417 +       if (u3_port_num) {
418 +               ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
419 +                                  (val & STS1_U3_MAC_RST), 100, 10000);
420 +               if (ret) {
421 +                       dev_err(u3phy->dev, "mac3_mac_ck is still active!!!\n");
422 +                       return ret;
423 +               }
424 +       }
425 +
426 +       if (u2_port_num) {
427 +               ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS2, val,
428 +                                  (val & STS2_U2_MAC_RST), 100, 10000);
429 +               if (ret) {
430 +                       dev_err(u3phy->dev, "mac2_sys_ck is still active!!!\n");
431 +                       return ret;
432 +               }
433 +       }
434 +
435 +       return 0;
436 +}
437 +
438 +static int u3phy_ports_enable(struct mt65xx_u3phy *u3phy)
439 +{
440 +       int i;
441 +       u32 temp;
442 +       int u3_port_num;
443 +       int u2_port_num;
444 +       void __iomem *sif_base = u3phy->sif_base;
445 +
446 +       temp = u3p_readl(sif_base, U3P_IP_XHCI_CAP);
447 +       u3_port_num = CAP_U3_PORT_NUM(temp);
448 +       u2_port_num = CAP_U2_PORT_NUM(temp);
449 +       dev_dbg(u3phy->dev, "%s u2p:%d, u3p:%d\n",
450 +               __func__, u2_port_num, u3_port_num);
451 +
452 +       /* power on host ip */
453 +       u3p_clrmsk(sif_base, U3P_IP_PW_CTRL1, CTRL1_IP_HOST_PDN);
454 +
455 +       /* power on and enable all u3 ports */
456 +       for (i = 0; i < u3_port_num; i++) {
457 +               temp = u3p_readl(sif_base, U3P_U3_CTRL(i));
458 +               temp &= ~(CTRL_U3_PORT_PDN | CTRL_U3_PORT_DIS);
459 +               temp |= CTRL_U3_PORT_HOST_SEL;
460 +               u3p_writel(sif_base, U3P_U3_CTRL(i), temp);
461 +       }
462 +
463 +       /* power on and enable all u2 ports */
464 +       for (i = 0; i < u2_port_num; i++) {
465 +               temp = u3p_readl(sif_base, U3P_U2_CTRL(i));
466 +               temp &= ~(CTRL_U2_PORT_PDN | CTRL_U2_PORT_DIS);
467 +               temp |= CTRL_U2_PORT_HOST_SEL;
468 +               u3p_writel(sif_base, U3P_U2_CTRL(i), temp);
469 +       }
470 +       return check_ip_clk_status(u3phy);
471 +}
472 +
473 +
474 +static void u3phy_timing_init(struct mt65xx_u3phy *u3phy)
475 +{
476 +       void __iomem *mbase = u3phy->mac_base;
477 +       int u3_port_num;
478 +       u32 temp;
479 +
480 +       temp = u3p_readl(u3phy->sif_base, U3P_IP_XHCI_CAP);
481 +       u3_port_num = CAP_U3_PORT_NUM(temp);
482 +
483 +       if (u3_port_num) {
484 +               /* set MAC reference clock speed */
485 +               u3p_setval(mbase, U3P_UX_EXIT_LFPS_PARAM,
486 +                               RX_UX_EXIT_REF, RX_UX_EXIT_REF_VAL);
487 +               /* set REF_CLK */
488 +               u3p_setval(mbase, U3P_REF_CLK_PARAM,
489 +                               REF_CLK_1000NS, REF_CLK_VAL_DEF);
490 +               /* set SYS_CLK */
491 +               u3p_setval(mbase, U3P_TIMING_PULSE_CTRL,
492 +                               U3T_CNT_1US, U3T_CNT_1US_VAL);
493 +               /* set LINK_PM_TIMER=3 */
494 +               u3p_setval(mbase, U3P_LINK_PM_TIMER,
495 +                               PM_LC_TIMEOUT, PM_LC_TIMEOUT_VAL);
496 +       }
497 +       u3p_setval(mbase, U3P_U2_TIMING_PARAM, U2T_VAL_1US, U2T_VAL_1US_VAL);
498 +}
499 +
500 +
501 +static int u3phy_clks_enable(struct mt65xx_u3phy *u3phy)
502 +{
503 +       int ret;
504 +
505 +       ret = clk_prepare_enable(u3phy->sys_mac);
506 +       if (ret) {
507 +               dev_err(u3phy->dev, "failed to enable sys_mac\n");
508 +               goto sys_mac_err;
509 +       }
510 +
511 +       ret = clk_prepare_enable(u3phy->u3phya_ref);
512 +       if (ret) {
513 +               dev_err(u3phy->dev, "failed to enable u3phya_ref\n");
514 +               goto u3phya_ref_err;
515 +       }
516 +       ret = clk_prepare_enable(u3phy->wk_deb_p0);
517 +       if (ret) {
518 +               dev_err(u3phy->dev, "failed to enable wk_deb_p0\n");
519 +               goto usb_p0_err;
520 +       }
521 +       if (u3phy->enable_usb2_p1) {
522 +               ret = clk_prepare_enable(u3phy->wk_deb_p1);
523 +               if (ret) {
524 +                       dev_err(u3phy->dev, "failed to enable wk_deb_p1\n");
525 +                       goto usb_p1_err;
526 +               }
527 +       }
528 +       udelay(50);
529 +
530 +       return 0;
531 +
532 +usb_p1_err:
533 +       clk_disable_unprepare(u3phy->wk_deb_p0);
534 +usb_p0_err:
535 +       clk_disable_unprepare(u3phy->u3phya_ref);
536 +u3phya_ref_err:
537 +       clk_disable_unprepare(u3phy->sys_mac);
538 +sys_mac_err:
539 +       return -EINVAL;
540 +}
541 +
542 +static void u3phy_clks_disable(struct mt65xx_u3phy *u3phy)
543 +{
544 +       if (u3phy->enable_usb2_p1)
545 +               clk_disable_unprepare(u3phy->wk_deb_p1);
546 +       clk_disable_unprepare(u3phy->wk_deb_p0);
547 +       clk_disable_unprepare(u3phy->u3phya_ref);
548 +       clk_disable_unprepare(u3phy->sys_mac);
549 +}
550 +
551 +
552 +static int mt65xx_u3phy_init(struct usb_phy *phy)
553 +{
554 +       struct mt65xx_u3phy *u3phy;
555 +       int ret;
556 +
557 +       u3phy = container_of(phy, struct mt65xx_u3phy, phy);
558 +       dev_dbg(u3phy->dev, "%s+\n", __func__);
559 +
560 +       if (u3phy->enable_usb2_p1) {
561 +               ret = regulator_enable(u3phy->p1_vbus);
562 +               if (ret) {
563 +                       dev_err(u3phy->dev, "failed to enable p1-vbus\n");
564 +                       goto reg_p1_err;
565 +               }
566 +       }
567 +
568 +       ret = regulator_enable(u3phy->vusb33);
569 +       if (ret) {
570 +               dev_err(u3phy->dev, "failed to enable vusb33\n");
571 +               goto reg_err;
572 +       }
573 +
574 +       ret = pm_runtime_get_sync(u3phy->dev);
575 +       if (ret < 0)
576 +               goto pm_err;
577 +
578 +       ret = u3phy_clks_enable(u3phy);
579 +       if (ret) {
580 +               dev_err(u3phy->dev, "failed to enable clks\n");
581 +               goto clks_err;
582 +       }
583 +
584 +       /* reset whole ip */
585 +       u3p_setmsk(u3phy->sif_base, U3P_IP_PW_CTRL0, CTRL0_IP_SW_RST);
586 +       u3p_clrmsk(u3phy->sif_base, U3P_IP_PW_CTRL0, CTRL0_IP_SW_RST);
587 +
588 +       ret = u3phy_ports_enable(u3phy);
589 +       if (ret) {
590 +               dev_err(u3phy->dev, "failed to enable ports\n");
591 +               goto port_err;
592 +       }
593 +       u3phy_timing_init(u3phy);
594 +       phy_index_power_on(u3phy, 0);
595 +       if (u3phy->enable_usb2_p1)
596 +               phy_index_power_on(u3phy, 1);
597 +
598 +       return 0;
599 +
600 +port_err:
601 +       u3phy_clks_disable(u3phy);
602 +clks_err:
603 +       pm_runtime_put_sync(u3phy->dev);
604 +pm_err:
605 +       regulator_disable(u3phy->vusb33);
606 +reg_err:
607 +       if (u3phy->enable_usb2_p1)
608 +               regulator_disable(u3phy->p1_vbus);
609 +reg_p1_err:
610 +       return ret;
611 +}
612 +
613 +
614 +static void mt65xx_u3phy_shutdown(struct usb_phy *phy)
615 +{
616 +       struct mt65xx_u3phy *u3phy;
617 +
618 +       u3phy = container_of(phy, struct mt65xx_u3phy, phy);
619 +       dev_dbg(u3phy->dev, "%s+\n", __func__);
620 +
621 +       phy_index_power_off(u3phy, 0);
622 +       if (u3phy->enable_usb2_p1) {
623 +               phy_index_power_off(u3phy, 1);
624 +               regulator_disable(u3phy->p1_vbus);
625 +       }
626 +       u3phy_clks_disable(u3phy);
627 +       pm_runtime_put_sync(u3phy->dev);
628 +       regulator_disable(u3phy->vusb33);
629 +}
630 +
631 +
632 +static int mt65xx_u3phy_suspend(struct usb_phy *x, int suspend)
633 +{
634 +       struct mt65xx_u3phy *u3phy = container_of(x, struct mt65xx_u3phy, phy);
635 +
636 +       if (suspend) {
637 +               mt65xx_u3phy_shutdown(&u3phy->phy);
638 +               return 0;
639 +       } else {
640 +               return mt65xx_u3phy_init(&u3phy->phy);
641 +       }
642 +}
643 +
644 +
645 +static const struct of_device_id mt65xx_u3phy_id_table[] = {
646 +       { .compatible = "mediatek,mt8173-u3phy",},
647 +       { },
648 +};
649 +MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table);
650 +
651 +
652 +static int mt65xx_u3phy_probe(struct platform_device *pdev)
653 +{
654 +       struct device *dev = &pdev->dev;
655 +       struct device_node *np = dev->of_node;
656 +       struct resource *mac_res;
657 +       struct resource *sif_res;
658 +       struct mt65xx_u3phy *u3phy;
659 +       int retval = -ENOMEM;
660 +
661 +       u3phy = devm_kzalloc(&pdev->dev, sizeof(*u3phy), GFP_KERNEL);
662 +       if (!u3phy)
663 +               goto err;
664 +
665 +       u3phy->dev = &pdev->dev;
666 +
667 +       mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
668 +       u3phy->mac_base = devm_ioremap_resource(dev, mac_res);
669 +       if (IS_ERR(u3phy->mac_base)) {
670 +               dev_err(dev, "failed to remap mac regs\n");
671 +               retval = PTR_ERR(u3phy->mac_base);
672 +               goto err;
673 +       }
674 +
675 +       sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
676 +       u3phy->sif_base = devm_ioremap_resource(dev, sif_res);
677 +       if (IS_ERR(u3phy->sif_base)) {
678 +               dev_err(dev, "failed to remap sif regs\n");
679 +               retval = PTR_ERR(u3phy->sif_base);
680 +               goto err;
681 +       }
682 +
683 +       u3phy->enable_usb2_p1 = !of_property_read_bool(np, "disable-usb2-p1");
684 +       dev_dbg(dev, "enable_usb2_p1 - %d\n", u3phy->enable_usb2_p1);
685 +
686 +       u3phy->sys_mac = devm_clk_get(u3phy->dev, "sys_mac");
687 +       if (IS_ERR(u3phy->sys_mac)) {
688 +               dev_err(dev, "error to get sys_mac\n");
689 +               retval = PTR_ERR(u3phy->sys_mac);
690 +               goto err;
691 +       }
692 +
693 +       u3phy->u3phya_ref = devm_clk_get(u3phy->dev, "u3phya_ref");
694 +       if (IS_ERR(u3phy->u3phya_ref)) {
695 +               dev_err(dev, "error to get u3phya_ref\n");
696 +               retval = PTR_ERR(u3phy->u3phya_ref);
697 +               goto err;
698 +       }
699 +
700 +       u3phy->wk_deb_p0 = devm_clk_get(u3phy->dev, "wakeup_deb_p0");
701 +       if (IS_ERR(u3phy->wk_deb_p0)) {
702 +               dev_err(dev, "error to get wakeup_deb_p0\n");
703 +               retval = PTR_ERR(u3phy->wk_deb_p0);
704 +               goto err;
705 +       }
706 +
707 +       if (u3phy->enable_usb2_p1) {
708 +               u3phy->wk_deb_p1 = devm_clk_get(u3phy->dev, "wakeup_deb_p1");
709 +               if (IS_ERR(u3phy->wk_deb_p1)) {
710 +                       dev_err(dev, "error to get wakeup_deb_p1\n");
711 +                       retval = PTR_ERR(u3phy->wk_deb_p1);
712 +                       goto err;
713 +               }
714 +
715 +               u3phy->p1_vbus = devm_regulator_get(u3phy->dev, "reg-p1-vbus");
716 +               if (IS_ERR_OR_NULL(u3phy->p1_vbus)) {
717 +                       dev_err(dev, "fail to get p1-vbus\n");
718 +                       retval = PTR_ERR(u3phy->p1_vbus);
719 +                       goto err;
720 +               }
721 +       }
722 +
723 +       u3phy->vusb33 = devm_regulator_get(u3phy->dev, "reg-vusb33");
724 +       if (IS_ERR_OR_NULL(u3phy->vusb33)) {
725 +               dev_err(dev, "fail to get vusb33\n");
726 +               retval = PTR_ERR(u3phy->vusb33);
727 +               goto err;
728 +       }
729 +
730 +       pm_runtime_enable(dev);
731 +       u3phy->phy.dev = u3phy->dev;
732 +       u3phy->phy.label = "mt65xx-usb3phy";
733 +       u3phy->phy.type = USB_PHY_TYPE_USB3;
734 +       u3phy->phy.init = mt65xx_u3phy_init;
735 +       u3phy->phy.shutdown = mt65xx_u3phy_shutdown;
736 +       u3phy->phy.set_suspend = mt65xx_u3phy_suspend;
737 +
738 +       platform_set_drvdata(pdev, u3phy);
739 +       retval = usb_add_phy_dev(&u3phy->phy);
740 +       if (retval) {
741 +               dev_err(dev, "failed to add phy\n");
742 +               goto add_phy_err;
743 +       }
744 +
745 +       return 0;
746 +
747 +add_phy_err:
748 +       pm_runtime_disable(dev);
749 +err:
750 +       return retval;
751 +}
752 +
753 +static int mt65xx_u3phy_remove(struct platform_device *pdev)
754 +{
755 +       struct mt65xx_u3phy *u3phy = platform_get_drvdata(pdev);
756 +
757 +       mt65xx_u3phy_shutdown(&u3phy->phy);
758 +       pm_runtime_disable(&pdev->dev);
759 +       usb_remove_phy(&u3phy->phy);
760 +
761 +       return 0;
762 +}
763 +
764 +static struct platform_driver mt65xx_u3phy_driver = {
765 +       .probe          = mt65xx_u3phy_probe,
766 +       .remove         = mt65xx_u3phy_remove,
767 +       .driver         = {
768 +               .name   = "mt65xx-u3phy",
769 +               .of_match_table = mt65xx_u3phy_id_table,
770 +       },
771 +};
772 +
773 +module_platform_driver(mt65xx_u3phy_driver);
774 +
775 +MODULE_DESCRIPTION("Mt65xx USB PHY driver");
776 +MODULE_LICENSE("GPL v2");
777 -- 
778 1.7.10.4
779