1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * MediaTek xHCI Host Controller Driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2015 MediaTek Inc.
6*4882a593Smuzhiyun * Author:
7*4882a593Smuzhiyun * Chunfeng Yun <chunfeng.yun@mediatek.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/clk.h>
11*4882a593Smuzhiyun #include <linux/dma-mapping.h>
12*4882a593Smuzhiyun #include <linux/iopoll.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/of.h>
17*4882a593Smuzhiyun #include <linux/platform_device.h>
18*4882a593Smuzhiyun #include <linux/pm_runtime.h>
19*4882a593Smuzhiyun #include <linux/regmap.h>
20*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #include "xhci.h"
23*4882a593Smuzhiyun #include "xhci-mtk.h"
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun /* ip_pw_ctrl0 register */
26*4882a593Smuzhiyun #define CTRL0_IP_SW_RST BIT(0)
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /* ip_pw_ctrl1 register */
29*4882a593Smuzhiyun #define CTRL1_IP_HOST_PDN BIT(0)
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /* ip_pw_ctrl2 register */
32*4882a593Smuzhiyun #define CTRL2_IP_DEV_PDN BIT(0)
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun /* ip_pw_sts1 register */
35*4882a593Smuzhiyun #define STS1_IP_SLEEP_STS BIT(30)
36*4882a593Smuzhiyun #define STS1_U3_MAC_RST BIT(16)
37*4882a593Smuzhiyun #define STS1_XHCI_RST BIT(11)
38*4882a593Smuzhiyun #define STS1_SYS125_RST BIT(10)
39*4882a593Smuzhiyun #define STS1_REF_RST BIT(8)
40*4882a593Smuzhiyun #define STS1_SYSPLL_STABLE BIT(0)
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /* ip_xhci_cap register */
43*4882a593Smuzhiyun #define CAP_U3_PORT_NUM(p) ((p) & 0xff)
44*4882a593Smuzhiyun #define CAP_U2_PORT_NUM(p) (((p) >> 8) & 0xff)
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* u3_ctrl_p register */
47*4882a593Smuzhiyun #define CTRL_U3_PORT_HOST_SEL BIT(2)
48*4882a593Smuzhiyun #define CTRL_U3_PORT_PDN BIT(1)
49*4882a593Smuzhiyun #define CTRL_U3_PORT_DIS BIT(0)
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun /* u2_ctrl_p register */
52*4882a593Smuzhiyun #define CTRL_U2_PORT_HOST_SEL BIT(2)
53*4882a593Smuzhiyun #define CTRL_U2_PORT_PDN BIT(1)
54*4882a593Smuzhiyun #define CTRL_U2_PORT_DIS BIT(0)
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* u2_phy_pll register */
57*4882a593Smuzhiyun #define CTRL_U2_FORCE_PLL_STB BIT(28)
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /* usb remote wakeup registers in syscon */
60*4882a593Smuzhiyun /* mt8173 etc */
61*4882a593Smuzhiyun #define PERI_WK_CTRL1 0x4
62*4882a593Smuzhiyun #define WC1_IS_C(x) (((x) & 0xf) << 26) /* cycle debounce */
63*4882a593Smuzhiyun #define WC1_IS_EN BIT(25)
64*4882a593Smuzhiyun #define WC1_IS_P BIT(6) /* polarity for ip sleep */
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun /* mt2712 etc */
67*4882a593Smuzhiyun #define PERI_SSUSB_SPM_CTRL 0x0
68*4882a593Smuzhiyun #define SSC_IP_SLEEP_EN BIT(4)
69*4882a593Smuzhiyun #define SSC_SPM_INT_EN BIT(1)
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun enum ssusb_uwk_vers {
72*4882a593Smuzhiyun SSUSB_UWK_V1 = 1,
73*4882a593Smuzhiyun SSUSB_UWK_V2,
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun
xhci_mtk_host_enable(struct xhci_hcd_mtk * mtk)76*4882a593Smuzhiyun static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
79*4882a593Smuzhiyun u32 value, check_val;
80*4882a593Smuzhiyun int u3_ports_disabled = 0;
81*4882a593Smuzhiyun int ret;
82*4882a593Smuzhiyun int i;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun if (!mtk->has_ippc)
85*4882a593Smuzhiyun return 0;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /* power on host ip */
88*4882a593Smuzhiyun value = readl(&ippc->ip_pw_ctr1);
89*4882a593Smuzhiyun value &= ~CTRL1_IP_HOST_PDN;
90*4882a593Smuzhiyun writel(value, &ippc->ip_pw_ctr1);
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /* power on and enable u3 ports except skipped ones */
93*4882a593Smuzhiyun for (i = 0; i < mtk->num_u3_ports; i++) {
94*4882a593Smuzhiyun if ((0x1 << i) & mtk->u3p_dis_msk) {
95*4882a593Smuzhiyun u3_ports_disabled++;
96*4882a593Smuzhiyun continue;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun value = readl(&ippc->u3_ctrl_p[i]);
100*4882a593Smuzhiyun value &= ~(CTRL_U3_PORT_PDN | CTRL_U3_PORT_DIS);
101*4882a593Smuzhiyun value |= CTRL_U3_PORT_HOST_SEL;
102*4882a593Smuzhiyun writel(value, &ippc->u3_ctrl_p[i]);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun /* power on and enable all u2 ports */
106*4882a593Smuzhiyun for (i = 0; i < mtk->num_u2_ports; i++) {
107*4882a593Smuzhiyun value = readl(&ippc->u2_ctrl_p[i]);
108*4882a593Smuzhiyun value &= ~(CTRL_U2_PORT_PDN | CTRL_U2_PORT_DIS);
109*4882a593Smuzhiyun value |= CTRL_U2_PORT_HOST_SEL;
110*4882a593Smuzhiyun writel(value, &ippc->u2_ctrl_p[i]);
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /*
114*4882a593Smuzhiyun * wait for clocks to be stable, and clock domains reset to
115*4882a593Smuzhiyun * be inactive after power on and enable ports
116*4882a593Smuzhiyun */
117*4882a593Smuzhiyun check_val = STS1_SYSPLL_STABLE | STS1_REF_RST |
118*4882a593Smuzhiyun STS1_SYS125_RST | STS1_XHCI_RST;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun if (mtk->num_u3_ports > u3_ports_disabled)
121*4882a593Smuzhiyun check_val |= STS1_U3_MAC_RST;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun ret = readl_poll_timeout(&ippc->ip_pw_sts1, value,
124*4882a593Smuzhiyun (check_val == (value & check_val)), 100, 20000);
125*4882a593Smuzhiyun if (ret) {
126*4882a593Smuzhiyun dev_err(mtk->dev, "clocks are not stable (0x%x)\n", value);
127*4882a593Smuzhiyun return ret;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun return 0;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
xhci_mtk_host_disable(struct xhci_hcd_mtk * mtk)133*4882a593Smuzhiyun static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
136*4882a593Smuzhiyun u32 value;
137*4882a593Smuzhiyun int ret;
138*4882a593Smuzhiyun int i;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (!mtk->has_ippc)
141*4882a593Smuzhiyun return 0;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /* power down u3 ports except skipped ones */
144*4882a593Smuzhiyun for (i = 0; i < mtk->num_u3_ports; i++) {
145*4882a593Smuzhiyun if ((0x1 << i) & mtk->u3p_dis_msk)
146*4882a593Smuzhiyun continue;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun value = readl(&ippc->u3_ctrl_p[i]);
149*4882a593Smuzhiyun value |= CTRL_U3_PORT_PDN;
150*4882a593Smuzhiyun writel(value, &ippc->u3_ctrl_p[i]);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /* power down all u2 ports */
154*4882a593Smuzhiyun for (i = 0; i < mtk->num_u2_ports; i++) {
155*4882a593Smuzhiyun value = readl(&ippc->u2_ctrl_p[i]);
156*4882a593Smuzhiyun value |= CTRL_U2_PORT_PDN;
157*4882a593Smuzhiyun writel(value, &ippc->u2_ctrl_p[i]);
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* power down host ip */
161*4882a593Smuzhiyun value = readl(&ippc->ip_pw_ctr1);
162*4882a593Smuzhiyun value |= CTRL1_IP_HOST_PDN;
163*4882a593Smuzhiyun writel(value, &ippc->ip_pw_ctr1);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* wait for host ip to sleep */
166*4882a593Smuzhiyun ret = readl_poll_timeout(&ippc->ip_pw_sts1, value,
167*4882a593Smuzhiyun (value & STS1_IP_SLEEP_STS), 100, 100000);
168*4882a593Smuzhiyun if (ret) {
169*4882a593Smuzhiyun dev_err(mtk->dev, "ip sleep failed!!!\n");
170*4882a593Smuzhiyun return ret;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun return 0;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
xhci_mtk_ssusb_config(struct xhci_hcd_mtk * mtk)175*4882a593Smuzhiyun static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
178*4882a593Smuzhiyun u32 value;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun if (!mtk->has_ippc)
181*4882a593Smuzhiyun return 0;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun /* reset whole ip */
184*4882a593Smuzhiyun value = readl(&ippc->ip_pw_ctr0);
185*4882a593Smuzhiyun value |= CTRL0_IP_SW_RST;
186*4882a593Smuzhiyun writel(value, &ippc->ip_pw_ctr0);
187*4882a593Smuzhiyun udelay(1);
188*4882a593Smuzhiyun value = readl(&ippc->ip_pw_ctr0);
189*4882a593Smuzhiyun value &= ~CTRL0_IP_SW_RST;
190*4882a593Smuzhiyun writel(value, &ippc->ip_pw_ctr0);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun /*
193*4882a593Smuzhiyun * device ip is default power-on in fact
194*4882a593Smuzhiyun * power down device ip, otherwise ip-sleep will fail
195*4882a593Smuzhiyun */
196*4882a593Smuzhiyun value = readl(&ippc->ip_pw_ctr2);
197*4882a593Smuzhiyun value |= CTRL2_IP_DEV_PDN;
198*4882a593Smuzhiyun writel(value, &ippc->ip_pw_ctr2);
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun value = readl(&ippc->ip_xhci_cap);
201*4882a593Smuzhiyun mtk->num_u3_ports = CAP_U3_PORT_NUM(value);
202*4882a593Smuzhiyun mtk->num_u2_ports = CAP_U2_PORT_NUM(value);
203*4882a593Smuzhiyun dev_dbg(mtk->dev, "%s u2p:%d, u3p:%d\n", __func__,
204*4882a593Smuzhiyun mtk->num_u2_ports, mtk->num_u3_ports);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun return xhci_mtk_host_enable(mtk);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
xhci_mtk_clks_get(struct xhci_hcd_mtk * mtk)209*4882a593Smuzhiyun static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun struct device *dev = mtk->dev;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun mtk->sys_clk = devm_clk_get(dev, "sys_ck");
214*4882a593Smuzhiyun if (IS_ERR(mtk->sys_clk)) {
215*4882a593Smuzhiyun dev_err(dev, "fail to get sys_ck\n");
216*4882a593Smuzhiyun return PTR_ERR(mtk->sys_clk);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun mtk->xhci_clk = devm_clk_get_optional(dev, "xhci_ck");
220*4882a593Smuzhiyun if (IS_ERR(mtk->xhci_clk))
221*4882a593Smuzhiyun return PTR_ERR(mtk->xhci_clk);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun mtk->ref_clk = devm_clk_get_optional(dev, "ref_ck");
224*4882a593Smuzhiyun if (IS_ERR(mtk->ref_clk))
225*4882a593Smuzhiyun return PTR_ERR(mtk->ref_clk);
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun mtk->mcu_clk = devm_clk_get_optional(dev, "mcu_ck");
228*4882a593Smuzhiyun if (IS_ERR(mtk->mcu_clk))
229*4882a593Smuzhiyun return PTR_ERR(mtk->mcu_clk);
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun mtk->dma_clk = devm_clk_get_optional(dev, "dma_ck");
232*4882a593Smuzhiyun return PTR_ERR_OR_ZERO(mtk->dma_clk);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
xhci_mtk_clks_enable(struct xhci_hcd_mtk * mtk)235*4882a593Smuzhiyun static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun int ret;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun ret = clk_prepare_enable(mtk->ref_clk);
240*4882a593Smuzhiyun if (ret) {
241*4882a593Smuzhiyun dev_err(mtk->dev, "failed to enable ref_clk\n");
242*4882a593Smuzhiyun goto ref_clk_err;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun ret = clk_prepare_enable(mtk->sys_clk);
246*4882a593Smuzhiyun if (ret) {
247*4882a593Smuzhiyun dev_err(mtk->dev, "failed to enable sys_clk\n");
248*4882a593Smuzhiyun goto sys_clk_err;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun ret = clk_prepare_enable(mtk->xhci_clk);
252*4882a593Smuzhiyun if (ret) {
253*4882a593Smuzhiyun dev_err(mtk->dev, "failed to enable xhci_clk\n");
254*4882a593Smuzhiyun goto xhci_clk_err;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun ret = clk_prepare_enable(mtk->mcu_clk);
258*4882a593Smuzhiyun if (ret) {
259*4882a593Smuzhiyun dev_err(mtk->dev, "failed to enable mcu_clk\n");
260*4882a593Smuzhiyun goto mcu_clk_err;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun ret = clk_prepare_enable(mtk->dma_clk);
264*4882a593Smuzhiyun if (ret) {
265*4882a593Smuzhiyun dev_err(mtk->dev, "failed to enable dma_clk\n");
266*4882a593Smuzhiyun goto dma_clk_err;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun return 0;
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun dma_clk_err:
272*4882a593Smuzhiyun clk_disable_unprepare(mtk->mcu_clk);
273*4882a593Smuzhiyun mcu_clk_err:
274*4882a593Smuzhiyun clk_disable_unprepare(mtk->xhci_clk);
275*4882a593Smuzhiyun xhci_clk_err:
276*4882a593Smuzhiyun clk_disable_unprepare(mtk->sys_clk);
277*4882a593Smuzhiyun sys_clk_err:
278*4882a593Smuzhiyun clk_disable_unprepare(mtk->ref_clk);
279*4882a593Smuzhiyun ref_clk_err:
280*4882a593Smuzhiyun return ret;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
xhci_mtk_clks_disable(struct xhci_hcd_mtk * mtk)283*4882a593Smuzhiyun static void xhci_mtk_clks_disable(struct xhci_hcd_mtk *mtk)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun clk_disable_unprepare(mtk->dma_clk);
286*4882a593Smuzhiyun clk_disable_unprepare(mtk->mcu_clk);
287*4882a593Smuzhiyun clk_disable_unprepare(mtk->xhci_clk);
288*4882a593Smuzhiyun clk_disable_unprepare(mtk->sys_clk);
289*4882a593Smuzhiyun clk_disable_unprepare(mtk->ref_clk);
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun /* only clocks can be turn off for ip-sleep wakeup mode */
usb_wakeup_ip_sleep_set(struct xhci_hcd_mtk * mtk,bool enable)293*4882a593Smuzhiyun static void usb_wakeup_ip_sleep_set(struct xhci_hcd_mtk *mtk, bool enable)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun u32 reg, msk, val;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun switch (mtk->uwk_vers) {
298*4882a593Smuzhiyun case SSUSB_UWK_V1:
299*4882a593Smuzhiyun reg = mtk->uwk_reg_base + PERI_WK_CTRL1;
300*4882a593Smuzhiyun msk = WC1_IS_EN | WC1_IS_C(0xf) | WC1_IS_P;
301*4882a593Smuzhiyun val = enable ? (WC1_IS_EN | WC1_IS_C(0x8)) : 0;
302*4882a593Smuzhiyun break;
303*4882a593Smuzhiyun case SSUSB_UWK_V2:
304*4882a593Smuzhiyun reg = mtk->uwk_reg_base + PERI_SSUSB_SPM_CTRL;
305*4882a593Smuzhiyun msk = SSC_IP_SLEEP_EN | SSC_SPM_INT_EN;
306*4882a593Smuzhiyun val = enable ? msk : 0;
307*4882a593Smuzhiyun break;
308*4882a593Smuzhiyun default:
309*4882a593Smuzhiyun return;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun regmap_update_bits(mtk->uwk, reg, msk, val);
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
usb_wakeup_of_property_parse(struct xhci_hcd_mtk * mtk,struct device_node * dn)314*4882a593Smuzhiyun static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk,
315*4882a593Smuzhiyun struct device_node *dn)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun struct of_phandle_args args;
318*4882a593Smuzhiyun int ret;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun /* Wakeup function is optional */
321*4882a593Smuzhiyun mtk->uwk_en = of_property_read_bool(dn, "wakeup-source");
322*4882a593Smuzhiyun if (!mtk->uwk_en)
323*4882a593Smuzhiyun return 0;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun ret = of_parse_phandle_with_fixed_args(dn,
326*4882a593Smuzhiyun "mediatek,syscon-wakeup", 2, 0, &args);
327*4882a593Smuzhiyun if (ret)
328*4882a593Smuzhiyun return ret;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun mtk->uwk_reg_base = args.args[0];
331*4882a593Smuzhiyun mtk->uwk_vers = args.args[1];
332*4882a593Smuzhiyun mtk->uwk = syscon_node_to_regmap(args.np);
333*4882a593Smuzhiyun of_node_put(args.np);
334*4882a593Smuzhiyun dev_info(mtk->dev, "uwk - reg:0x%x, version:%d\n",
335*4882a593Smuzhiyun mtk->uwk_reg_base, mtk->uwk_vers);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun return PTR_ERR_OR_ZERO(mtk->uwk);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
usb_wakeup_set(struct xhci_hcd_mtk * mtk,bool enable)341*4882a593Smuzhiyun static void usb_wakeup_set(struct xhci_hcd_mtk *mtk, bool enable)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun if (mtk->uwk_en)
344*4882a593Smuzhiyun usb_wakeup_ip_sleep_set(mtk, enable);
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
xhci_mtk_ldos_enable(struct xhci_hcd_mtk * mtk)347*4882a593Smuzhiyun static int xhci_mtk_ldos_enable(struct xhci_hcd_mtk *mtk)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun int ret;
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun ret = regulator_enable(mtk->vbus);
352*4882a593Smuzhiyun if (ret) {
353*4882a593Smuzhiyun dev_err(mtk->dev, "failed to enable vbus\n");
354*4882a593Smuzhiyun return ret;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun ret = regulator_enable(mtk->vusb33);
358*4882a593Smuzhiyun if (ret) {
359*4882a593Smuzhiyun dev_err(mtk->dev, "failed to enable vusb33\n");
360*4882a593Smuzhiyun regulator_disable(mtk->vbus);
361*4882a593Smuzhiyun return ret;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun return 0;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
xhci_mtk_ldos_disable(struct xhci_hcd_mtk * mtk)366*4882a593Smuzhiyun static void xhci_mtk_ldos_disable(struct xhci_hcd_mtk *mtk)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun regulator_disable(mtk->vbus);
369*4882a593Smuzhiyun regulator_disable(mtk->vusb33);
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
xhci_mtk_quirks(struct device * dev,struct xhci_hcd * xhci)372*4882a593Smuzhiyun static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun struct usb_hcd *hcd = xhci_to_hcd(xhci);
375*4882a593Smuzhiyun struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun /*
378*4882a593Smuzhiyun * As of now platform drivers don't provide MSI support so we ensure
379*4882a593Smuzhiyun * here that the generic code does not try to make a pci_dev from our
380*4882a593Smuzhiyun * dev struct in order to setup MSI
381*4882a593Smuzhiyun */
382*4882a593Smuzhiyun xhci->quirks |= XHCI_PLAT;
383*4882a593Smuzhiyun xhci->quirks |= XHCI_MTK_HOST;
384*4882a593Smuzhiyun /*
385*4882a593Smuzhiyun * MTK host controller gives a spurious successful event after a
386*4882a593Smuzhiyun * short transfer. Ignore it.
387*4882a593Smuzhiyun */
388*4882a593Smuzhiyun xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
389*4882a593Smuzhiyun if (mtk->lpm_support)
390*4882a593Smuzhiyun xhci->quirks |= XHCI_LPM_SUPPORT;
391*4882a593Smuzhiyun if (mtk->u2_lpm_disable)
392*4882a593Smuzhiyun xhci->quirks |= XHCI_HW_LPM_DISABLE;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun /*
395*4882a593Smuzhiyun * MTK xHCI 0.96: PSA is 1 by default even if doesn't support stream,
396*4882a593Smuzhiyun * and it's 3 when support it.
397*4882a593Smuzhiyun */
398*4882a593Smuzhiyun if (xhci->hci_version < 0x100 && HCC_MAX_PSA(xhci->hcc_params) == 4)
399*4882a593Smuzhiyun xhci->quirks |= XHCI_BROKEN_STREAMS;
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun /* called during probe() after chip reset completes */
xhci_mtk_setup(struct usb_hcd * hcd)403*4882a593Smuzhiyun static int xhci_mtk_setup(struct usb_hcd *hcd)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
406*4882a593Smuzhiyun int ret;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun if (usb_hcd_is_primary_hcd(hcd)) {
409*4882a593Smuzhiyun ret = xhci_mtk_ssusb_config(mtk);
410*4882a593Smuzhiyun if (ret)
411*4882a593Smuzhiyun return ret;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun ret = xhci_gen_setup(hcd, xhci_mtk_quirks);
415*4882a593Smuzhiyun if (ret)
416*4882a593Smuzhiyun return ret;
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun if (usb_hcd_is_primary_hcd(hcd)) {
419*4882a593Smuzhiyun ret = xhci_mtk_sch_init(mtk);
420*4882a593Smuzhiyun if (ret)
421*4882a593Smuzhiyun return ret;
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun return ret;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun static const struct xhci_driver_overrides xhci_mtk_overrides __initconst = {
428*4882a593Smuzhiyun .reset = xhci_mtk_setup,
429*4882a593Smuzhiyun .add_endpoint = xhci_mtk_add_ep,
430*4882a593Smuzhiyun .drop_endpoint = xhci_mtk_drop_ep,
431*4882a593Smuzhiyun .check_bandwidth = xhci_mtk_check_bandwidth,
432*4882a593Smuzhiyun .reset_bandwidth = xhci_mtk_reset_bandwidth,
433*4882a593Smuzhiyun };
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun static struct hc_driver __read_mostly xhci_mtk_hc_driver;
436*4882a593Smuzhiyun
xhci_mtk_probe(struct platform_device * pdev)437*4882a593Smuzhiyun static int xhci_mtk_probe(struct platform_device *pdev)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun struct device *dev = &pdev->dev;
440*4882a593Smuzhiyun struct device_node *node = dev->of_node;
441*4882a593Smuzhiyun struct xhci_hcd_mtk *mtk;
442*4882a593Smuzhiyun const struct hc_driver *driver;
443*4882a593Smuzhiyun struct xhci_hcd *xhci;
444*4882a593Smuzhiyun struct resource *res;
445*4882a593Smuzhiyun struct usb_hcd *hcd;
446*4882a593Smuzhiyun int ret = -ENODEV;
447*4882a593Smuzhiyun int irq;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun if (usb_disabled())
450*4882a593Smuzhiyun return -ENODEV;
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun driver = &xhci_mtk_hc_driver;
453*4882a593Smuzhiyun mtk = devm_kzalloc(dev, sizeof(*mtk), GFP_KERNEL);
454*4882a593Smuzhiyun if (!mtk)
455*4882a593Smuzhiyun return -ENOMEM;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun mtk->dev = dev;
458*4882a593Smuzhiyun mtk->vbus = devm_regulator_get(dev, "vbus");
459*4882a593Smuzhiyun if (IS_ERR(mtk->vbus)) {
460*4882a593Smuzhiyun dev_err(dev, "fail to get vbus\n");
461*4882a593Smuzhiyun return PTR_ERR(mtk->vbus);
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun mtk->vusb33 = devm_regulator_get(dev, "vusb33");
465*4882a593Smuzhiyun if (IS_ERR(mtk->vusb33)) {
466*4882a593Smuzhiyun dev_err(dev, "fail to get vusb33\n");
467*4882a593Smuzhiyun return PTR_ERR(mtk->vusb33);
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun ret = xhci_mtk_clks_get(mtk);
471*4882a593Smuzhiyun if (ret)
472*4882a593Smuzhiyun return ret;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun mtk->lpm_support = of_property_read_bool(node, "usb3-lpm-capable");
475*4882a593Smuzhiyun mtk->u2_lpm_disable = of_property_read_bool(node, "usb2-lpm-disable");
476*4882a593Smuzhiyun /* optional property, ignore the error if it does not exist */
477*4882a593Smuzhiyun of_property_read_u32(node, "mediatek,u3p-dis-msk",
478*4882a593Smuzhiyun &mtk->u3p_dis_msk);
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun ret = usb_wakeup_of_property_parse(mtk, node);
481*4882a593Smuzhiyun if (ret) {
482*4882a593Smuzhiyun dev_err(dev, "failed to parse uwk property\n");
483*4882a593Smuzhiyun return ret;
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun pm_runtime_enable(dev);
487*4882a593Smuzhiyun pm_runtime_get_sync(dev);
488*4882a593Smuzhiyun device_enable_async_suspend(dev);
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun ret = xhci_mtk_ldos_enable(mtk);
491*4882a593Smuzhiyun if (ret)
492*4882a593Smuzhiyun goto disable_pm;
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun ret = xhci_mtk_clks_enable(mtk);
495*4882a593Smuzhiyun if (ret)
496*4882a593Smuzhiyun goto disable_ldos;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun irq = platform_get_irq(pdev, 0);
499*4882a593Smuzhiyun if (irq < 0) {
500*4882a593Smuzhiyun ret = irq;
501*4882a593Smuzhiyun goto disable_clk;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun hcd = usb_create_hcd(driver, dev, dev_name(dev));
505*4882a593Smuzhiyun if (!hcd) {
506*4882a593Smuzhiyun ret = -ENOMEM;
507*4882a593Smuzhiyun goto disable_clk;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun /*
511*4882a593Smuzhiyun * USB 2.0 roothub is stored in the platform_device.
512*4882a593Smuzhiyun * Swap it with mtk HCD.
513*4882a593Smuzhiyun */
514*4882a593Smuzhiyun mtk->hcd = platform_get_drvdata(pdev);
515*4882a593Smuzhiyun platform_set_drvdata(pdev, mtk);
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac");
518*4882a593Smuzhiyun hcd->regs = devm_ioremap_resource(dev, res);
519*4882a593Smuzhiyun if (IS_ERR(hcd->regs)) {
520*4882a593Smuzhiyun ret = PTR_ERR(hcd->regs);
521*4882a593Smuzhiyun goto put_usb2_hcd;
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun hcd->rsrc_start = res->start;
524*4882a593Smuzhiyun hcd->rsrc_len = resource_size(res);
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ippc");
527*4882a593Smuzhiyun if (res) { /* ippc register is optional */
528*4882a593Smuzhiyun mtk->ippc_regs = devm_ioremap_resource(dev, res);
529*4882a593Smuzhiyun if (IS_ERR(mtk->ippc_regs)) {
530*4882a593Smuzhiyun ret = PTR_ERR(mtk->ippc_regs);
531*4882a593Smuzhiyun goto put_usb2_hcd;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun mtk->has_ippc = true;
534*4882a593Smuzhiyun } else {
535*4882a593Smuzhiyun mtk->has_ippc = false;
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun device_init_wakeup(dev, true);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun xhci = hcd_to_xhci(hcd);
541*4882a593Smuzhiyun xhci->main_hcd = hcd;
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun /*
544*4882a593Smuzhiyun * imod_interval is the interrupt moderation value in nanoseconds.
545*4882a593Smuzhiyun * The increment interval is 8 times as much as that defined in
546*4882a593Smuzhiyun * the xHCI spec on MTK's controller.
547*4882a593Smuzhiyun */
548*4882a593Smuzhiyun xhci->imod_interval = 5000;
549*4882a593Smuzhiyun device_property_read_u32(dev, "imod-interval-ns", &xhci->imod_interval);
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun xhci->shared_hcd = usb_create_shared_hcd(driver, dev,
552*4882a593Smuzhiyun dev_name(dev), hcd);
553*4882a593Smuzhiyun if (!xhci->shared_hcd) {
554*4882a593Smuzhiyun ret = -ENOMEM;
555*4882a593Smuzhiyun goto disable_device_wakeup;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
559*4882a593Smuzhiyun if (ret)
560*4882a593Smuzhiyun goto put_usb3_hcd;
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun if (HCC_MAX_PSA(xhci->hcc_params) >= 4 &&
563*4882a593Smuzhiyun !(xhci->quirks & XHCI_BROKEN_STREAMS))
564*4882a593Smuzhiyun xhci->shared_hcd->can_do_streams = 1;
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
567*4882a593Smuzhiyun if (ret)
568*4882a593Smuzhiyun goto dealloc_usb2_hcd;
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun return 0;
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun dealloc_usb2_hcd:
573*4882a593Smuzhiyun usb_remove_hcd(hcd);
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun put_usb3_hcd:
576*4882a593Smuzhiyun xhci_mtk_sch_exit(mtk);
577*4882a593Smuzhiyun usb_put_hcd(xhci->shared_hcd);
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun disable_device_wakeup:
580*4882a593Smuzhiyun device_init_wakeup(dev, false);
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun put_usb2_hcd:
583*4882a593Smuzhiyun usb_put_hcd(hcd);
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun disable_clk:
586*4882a593Smuzhiyun xhci_mtk_clks_disable(mtk);
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun disable_ldos:
589*4882a593Smuzhiyun xhci_mtk_ldos_disable(mtk);
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun disable_pm:
592*4882a593Smuzhiyun pm_runtime_put_sync(dev);
593*4882a593Smuzhiyun pm_runtime_disable(dev);
594*4882a593Smuzhiyun return ret;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun
xhci_mtk_remove(struct platform_device * dev)597*4882a593Smuzhiyun static int xhci_mtk_remove(struct platform_device *dev)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun struct xhci_hcd_mtk *mtk = platform_get_drvdata(dev);
600*4882a593Smuzhiyun struct usb_hcd *hcd = mtk->hcd;
601*4882a593Smuzhiyun struct xhci_hcd *xhci = hcd_to_xhci(hcd);
602*4882a593Smuzhiyun struct usb_hcd *shared_hcd = xhci->shared_hcd;
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun pm_runtime_put_noidle(&dev->dev);
605*4882a593Smuzhiyun pm_runtime_disable(&dev->dev);
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun usb_remove_hcd(shared_hcd);
608*4882a593Smuzhiyun xhci->shared_hcd = NULL;
609*4882a593Smuzhiyun device_init_wakeup(&dev->dev, false);
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun usb_remove_hcd(hcd);
612*4882a593Smuzhiyun usb_put_hcd(shared_hcd);
613*4882a593Smuzhiyun usb_put_hcd(hcd);
614*4882a593Smuzhiyun xhci_mtk_sch_exit(mtk);
615*4882a593Smuzhiyun xhci_mtk_clks_disable(mtk);
616*4882a593Smuzhiyun xhci_mtk_ldos_disable(mtk);
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun return 0;
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun /*
622*4882a593Smuzhiyun * if ip sleep fails, and all clocks are disabled, access register will hang
623*4882a593Smuzhiyun * AHB bus, so stop polling roothubs to avoid regs access on bus suspend.
624*4882a593Smuzhiyun * and no need to check whether ip sleep failed or not; this will cause SPM
625*4882a593Smuzhiyun * to wake up system immediately after system suspend complete if ip sleep
626*4882a593Smuzhiyun * fails, it is what we wanted.
627*4882a593Smuzhiyun */
xhci_mtk_suspend(struct device * dev)628*4882a593Smuzhiyun static int __maybe_unused xhci_mtk_suspend(struct device *dev)
629*4882a593Smuzhiyun {
630*4882a593Smuzhiyun struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
631*4882a593Smuzhiyun struct usb_hcd *hcd = mtk->hcd;
632*4882a593Smuzhiyun struct xhci_hcd *xhci = hcd_to_xhci(hcd);
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun xhci_dbg(xhci, "%s: stop port polling\n", __func__);
635*4882a593Smuzhiyun clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
636*4882a593Smuzhiyun del_timer_sync(&hcd->rh_timer);
637*4882a593Smuzhiyun clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
638*4882a593Smuzhiyun del_timer_sync(&xhci->shared_hcd->rh_timer);
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun xhci_mtk_host_disable(mtk);
641*4882a593Smuzhiyun xhci_mtk_clks_disable(mtk);
642*4882a593Smuzhiyun usb_wakeup_set(mtk, true);
643*4882a593Smuzhiyun return 0;
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun
xhci_mtk_resume(struct device * dev)646*4882a593Smuzhiyun static int __maybe_unused xhci_mtk_resume(struct device *dev)
647*4882a593Smuzhiyun {
648*4882a593Smuzhiyun struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
649*4882a593Smuzhiyun struct usb_hcd *hcd = mtk->hcd;
650*4882a593Smuzhiyun struct xhci_hcd *xhci = hcd_to_xhci(hcd);
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun usb_wakeup_set(mtk, false);
653*4882a593Smuzhiyun xhci_mtk_clks_enable(mtk);
654*4882a593Smuzhiyun xhci_mtk_host_enable(mtk);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun xhci_dbg(xhci, "%s: restart port polling\n", __func__);
657*4882a593Smuzhiyun set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
658*4882a593Smuzhiyun usb_hcd_poll_rh_status(xhci->shared_hcd);
659*4882a593Smuzhiyun set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
660*4882a593Smuzhiyun usb_hcd_poll_rh_status(hcd);
661*4882a593Smuzhiyun return 0;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun static const struct dev_pm_ops xhci_mtk_pm_ops = {
665*4882a593Smuzhiyun SET_SYSTEM_SLEEP_PM_OPS(xhci_mtk_suspend, xhci_mtk_resume)
666*4882a593Smuzhiyun };
667*4882a593Smuzhiyun #define DEV_PM_OPS IS_ENABLED(CONFIG_PM) ? &xhci_mtk_pm_ops : NULL
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun #ifdef CONFIG_OF
670*4882a593Smuzhiyun static const struct of_device_id mtk_xhci_of_match[] = {
671*4882a593Smuzhiyun { .compatible = "mediatek,mt8173-xhci"},
672*4882a593Smuzhiyun { .compatible = "mediatek,mtk-xhci"},
673*4882a593Smuzhiyun { },
674*4882a593Smuzhiyun };
675*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, mtk_xhci_of_match);
676*4882a593Smuzhiyun #endif
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun static struct platform_driver mtk_xhci_driver = {
679*4882a593Smuzhiyun .probe = xhci_mtk_probe,
680*4882a593Smuzhiyun .remove = xhci_mtk_remove,
681*4882a593Smuzhiyun .driver = {
682*4882a593Smuzhiyun .name = "xhci-mtk",
683*4882a593Smuzhiyun .pm = DEV_PM_OPS,
684*4882a593Smuzhiyun .of_match_table = of_match_ptr(mtk_xhci_of_match),
685*4882a593Smuzhiyun },
686*4882a593Smuzhiyun };
687*4882a593Smuzhiyun MODULE_ALIAS("platform:xhci-mtk");
688*4882a593Smuzhiyun
xhci_mtk_init(void)689*4882a593Smuzhiyun static int __init xhci_mtk_init(void)
690*4882a593Smuzhiyun {
691*4882a593Smuzhiyun xhci_init_driver(&xhci_mtk_hc_driver, &xhci_mtk_overrides);
692*4882a593Smuzhiyun return platform_driver_register(&mtk_xhci_driver);
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun module_init(xhci_mtk_init);
695*4882a593Smuzhiyun
xhci_mtk_exit(void)696*4882a593Smuzhiyun static void __exit xhci_mtk_exit(void)
697*4882a593Smuzhiyun {
698*4882a593Smuzhiyun platform_driver_unregister(&mtk_xhci_driver);
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun module_exit(xhci_mtk_exit);
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
703*4882a593Smuzhiyun MODULE_DESCRIPTION("MediaTek xHCI Host Controller Driver");
704*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
705