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