1 // SPDX-License-Identifier: GPL-2.0
3 * mtu3_dr.c - dual role switch and host glue layer
5 * Copyright (C) 2016 MediaTek Inc.
7 * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
10 #include <linux/clk.h>
11 #include <linux/irq.h>
12 #include <linux/kernel.h>
13 #include <linux/mfd/syscon.h>
15 #include <linux/of_platform.h>
16 #include <linux/regmap.h>
22 #define PERI_WK_CTRL1 0x4
23 #define WC1_IS_C(x) (((x) & 0xf) << 26) /* cycle debounce */
24 #define WC1_IS_EN BIT(25)
25 #define WC1_IS_P BIT(6) /* polarity for ip sleep */
28 #define PERI_WK_CTRL0 0x0
29 #define WC0_IS_C(x) ((u32)(((x) & 0xf) << 28)) /* cycle debounce */
30 #define WC0_IS_P BIT(12) /* polarity */
31 #define WC0_IS_EN BIT(6)
34 #define WC0_SSUSB0_CDEN BIT(6)
35 #define WC0_IS_SPM_EN BIT(1)
38 #define PERI_WK_CTRL0_8195 0x04
39 #define WC0_IS_P_95 BIT(30) /* polarity */
40 #define WC0_IS_C_95(x) ((u32)(((x) & 0x7) << 27))
41 #define WC0_IS_EN_P3_95 BIT(26)
42 #define WC0_IS_EN_P2_95 BIT(25)
44 #define PERI_WK_CTRL1_8195 0x20
45 #define WC1_IS_C_95(x) ((u32)(((x) & 0xf) << 28))
46 #define WC1_IS_P_95 BIT(12)
47 #define WC1_IS_EN_P0_95 BIT(6)
50 #define PERI_SSUSB_SPM_CTRL 0x0
51 #define SSC_IP_SLEEP_EN BIT(4)
52 #define SSC_SPM_INT_EN BIT(1)
57 SSUSB_UWK_V1_1
= 101, /* specific revision 1.01 */
58 SSUSB_UWK_V1_2
, /* specific revision 1.02 */
59 SSUSB_UWK_V1_3
, /* mt8195 IP0 */
60 SSUSB_UWK_V1_5
= 105, /* mt8195 IP2 */
61 SSUSB_UWK_V1_6
, /* mt8195 IP3 */
65 * ip-sleep wakeup mode:
66 * all clocks can be turn off, but power domain should be kept on
68 static void ssusb_wakeup_ip_sleep_set(struct ssusb_mtk
*ssusb
, bool enable
)
72 switch (ssusb
->uwk_vers
) {
74 reg
= ssusb
->uwk_reg_base
+ PERI_WK_CTRL1
;
75 msk
= WC1_IS_EN
| WC1_IS_C(0xf) | WC1_IS_P
;
76 val
= enable
? (WC1_IS_EN
| WC1_IS_C(0x8)) : 0;
79 reg
= ssusb
->uwk_reg_base
+ PERI_WK_CTRL0
;
80 msk
= WC0_IS_EN
| WC0_IS_C(0xf) | WC0_IS_P
;
81 val
= enable
? (WC0_IS_EN
| WC0_IS_C(0x1)) : 0;
84 reg
= ssusb
->uwk_reg_base
+ PERI_WK_CTRL0
;
85 msk
= WC0_SSUSB0_CDEN
| WC0_IS_SPM_EN
;
86 val
= enable
? msk
: 0;
89 reg
= ssusb
->uwk_reg_base
+ PERI_WK_CTRL1_8195
;
90 msk
= WC1_IS_EN_P0_95
| WC1_IS_C_95(0xf) | WC1_IS_P_95
;
91 val
= enable
? (WC1_IS_EN_P0_95
| WC1_IS_C_95(0x1)) : 0;
94 reg
= ssusb
->uwk_reg_base
+ PERI_WK_CTRL0_8195
;
95 msk
= WC0_IS_EN_P2_95
| WC0_IS_C_95(0x7) | WC0_IS_P_95
;
96 val
= enable
? (WC0_IS_EN_P2_95
| WC0_IS_C_95(0x1)) : 0;
99 reg
= ssusb
->uwk_reg_base
+ PERI_WK_CTRL0_8195
;
100 msk
= WC0_IS_EN_P3_95
| WC0_IS_C_95(0x7) | WC0_IS_P_95
;
101 val
= enable
? (WC0_IS_EN_P3_95
| WC0_IS_C_95(0x1)) : 0;
104 reg
= ssusb
->uwk_reg_base
+ PERI_SSUSB_SPM_CTRL
;
105 msk
= SSC_IP_SLEEP_EN
| SSC_SPM_INT_EN
;
106 val
= enable
? msk
: 0;
111 regmap_update_bits(ssusb
->uwk
, reg
, msk
, val
);
114 int ssusb_wakeup_of_property_parse(struct ssusb_mtk
*ssusb
,
115 struct device_node
*dn
)
117 struct of_phandle_args args
;
120 /* wakeup function is optional */
121 ssusb
->uwk_en
= of_property_read_bool(dn
, "wakeup-source");
125 ret
= of_parse_phandle_with_fixed_args(dn
,
126 "mediatek,syscon-wakeup", 2, 0, &args
);
130 ssusb
->uwk_reg_base
= args
.args
[0];
131 ssusb
->uwk_vers
= args
.args
[1];
132 ssusb
->uwk
= syscon_node_to_regmap(args
.np
);
133 of_node_put(args
.np
);
134 dev_info(ssusb
->dev
, "uwk - reg:0x%x, version:%d\n",
135 ssusb
->uwk_reg_base
, ssusb
->uwk_vers
);
137 return PTR_ERR_OR_ZERO(ssusb
->uwk
);
140 void ssusb_wakeup_set(struct ssusb_mtk
*ssusb
, bool enable
)
143 ssusb_wakeup_ip_sleep_set(ssusb
, enable
);
146 static void host_ports_num_get(struct ssusb_mtk
*ssusb
)
150 xhci_cap
= mtu3_readl(ssusb
->ippc_base
, U3D_SSUSB_IP_XHCI_CAP
);
151 ssusb
->u2_ports
= SSUSB_IP_XHCI_U2_PORT_NUM(xhci_cap
);
152 ssusb
->u3_ports
= SSUSB_IP_XHCI_U3_PORT_NUM(xhci_cap
);
154 dev_dbg(ssusb
->dev
, "host - u2_ports:%d, u3_ports:%d\n",
155 ssusb
->u2_ports
, ssusb
->u3_ports
);
158 /* only configure ports will be used later */
159 static int ssusb_host_enable(struct ssusb_mtk
*ssusb
)
161 void __iomem
*ibase
= ssusb
->ippc_base
;
162 int num_u3p
= ssusb
->u3_ports
;
163 int num_u2p
= ssusb
->u2_ports
;
164 int u3_ports_disabled
;
169 /* power on host ip */
170 mtu3_clrbits(ibase
, U3D_SSUSB_IP_PW_CTRL1
, SSUSB_IP_HOST_PDN
);
172 /* power on and enable u3 ports except skipped ones */
173 u3_ports_disabled
= 0;
174 for (i
= 0; i
< num_u3p
; i
++) {
175 if ((0x1 << i
) & ssusb
->u3p_dis_msk
) {
180 value
= mtu3_readl(ibase
, SSUSB_U3_CTRL(i
));
181 value
&= ~(SSUSB_U3_PORT_PDN
| SSUSB_U3_PORT_DIS
);
182 value
|= SSUSB_U3_PORT_HOST_SEL
;
183 mtu3_writel(ibase
, SSUSB_U3_CTRL(i
), value
);
186 /* power on and enable all u2 ports */
187 for (i
= 0; i
< num_u2p
; i
++) {
188 if ((0x1 << i
) & ssusb
->u2p_dis_msk
)
191 value
= mtu3_readl(ibase
, SSUSB_U2_CTRL(i
));
192 value
&= ~(SSUSB_U2_PORT_PDN
| SSUSB_U2_PORT_DIS
);
193 value
|= SSUSB_U2_PORT_HOST_SEL
;
194 mtu3_writel(ibase
, SSUSB_U2_CTRL(i
), value
);
197 check_clk
= SSUSB_XHCI_RST_B_STS
;
198 if (num_u3p
> u3_ports_disabled
)
199 check_clk
= SSUSB_U3_MAC_RST_B_STS
;
201 return ssusb_check_clocks(ssusb
, check_clk
);
204 static int ssusb_host_disable(struct ssusb_mtk
*ssusb
)
206 void __iomem
*ibase
= ssusb
->ippc_base
;
207 int num_u3p
= ssusb
->u3_ports
;
208 int num_u2p
= ssusb
->u2_ports
;
212 /* power down and disable u3 ports except skipped ones */
213 for (i
= 0; i
< num_u3p
; i
++) {
214 if ((0x1 << i
) & ssusb
->u3p_dis_msk
)
217 value
= mtu3_readl(ibase
, SSUSB_U3_CTRL(i
));
218 value
|= SSUSB_U3_PORT_PDN
| SSUSB_U3_PORT_DIS
;
219 mtu3_writel(ibase
, SSUSB_U3_CTRL(i
), value
);
222 /* power down and disable u2 ports except skipped ones */
223 for (i
= 0; i
< num_u2p
; i
++) {
224 if ((0x1 << i
) & ssusb
->u2p_dis_msk
)
227 value
= mtu3_readl(ibase
, SSUSB_U2_CTRL(i
));
228 value
|= SSUSB_U2_PORT_PDN
| SSUSB_U2_PORT_DIS
;
229 mtu3_writel(ibase
, SSUSB_U2_CTRL(i
), value
);
232 /* power down host ip */
233 mtu3_setbits(ibase
, U3D_SSUSB_IP_PW_CTRL1
, SSUSB_IP_HOST_PDN
);
238 int ssusb_host_resume(struct ssusb_mtk
*ssusb
, bool p0_skipped
)
240 void __iomem
*ibase
= ssusb
->ippc_base
;
241 int u3p_skip_msk
= ssusb
->u3p_dis_msk
;
242 int u2p_skip_msk
= ssusb
->u2p_dis_msk
;
243 int num_u3p
= ssusb
->u3_ports
;
244 int num_u2p
= ssusb
->u2_ports
;
250 if (ssusb
->otg_switch
.is_u3_drd
)
254 /* power on host ip */
255 mtu3_clrbits(ibase
, U3D_SSUSB_IP_PW_CTRL1
, SSUSB_IP_HOST_PDN
);
257 /* power on u3 ports except skipped ones */
258 for (i
= 0; i
< num_u3p
; i
++) {
259 if ((0x1 << i
) & u3p_skip_msk
)
262 value
= mtu3_readl(ibase
, SSUSB_U3_CTRL(i
));
263 value
&= ~SSUSB_U3_PORT_PDN
;
264 mtu3_writel(ibase
, SSUSB_U3_CTRL(i
), value
);
267 /* power on all u2 ports except skipped ones */
268 for (i
= 0; i
< num_u2p
; i
++) {
269 if ((0x1 << i
) & u2p_skip_msk
)
272 value
= mtu3_readl(ibase
, SSUSB_U2_CTRL(i
));
273 value
&= ~SSUSB_U2_PORT_PDN
;
274 mtu3_writel(ibase
, SSUSB_U2_CTRL(i
), value
);
280 /* here not skip port0 due to PDN can be set repeatedly */
281 int ssusb_host_suspend(struct ssusb_mtk
*ssusb
)
283 void __iomem
*ibase
= ssusb
->ippc_base
;
284 int num_u3p
= ssusb
->u3_ports
;
285 int num_u2p
= ssusb
->u2_ports
;
289 /* power down u3 ports except skipped ones */
290 for (i
= 0; i
< num_u3p
; i
++) {
291 if ((0x1 << i
) & ssusb
->u3p_dis_msk
)
294 value
= mtu3_readl(ibase
, SSUSB_U3_CTRL(i
));
295 value
|= SSUSB_U3_PORT_PDN
;
296 mtu3_writel(ibase
, SSUSB_U3_CTRL(i
), value
);
299 /* power down u2 ports except skipped ones */
300 for (i
= 0; i
< num_u2p
; i
++) {
301 if ((0x1 << i
) & ssusb
->u2p_dis_msk
)
304 value
= mtu3_readl(ibase
, SSUSB_U2_CTRL(i
));
305 value
|= SSUSB_U2_PORT_PDN
;
306 mtu3_writel(ibase
, SSUSB_U2_CTRL(i
), value
);
309 /* power down host ip */
310 mtu3_setbits(ibase
, U3D_SSUSB_IP_PW_CTRL1
, SSUSB_IP_HOST_PDN
);
315 static void ssusb_host_setup(struct ssusb_mtk
*ssusb
)
317 host_ports_num_get(ssusb
);
320 * power on host and power on/enable all ports
321 * if support OTG, gadget driver will switch port0 to device mode
323 ssusb_host_enable(ssusb
);
324 ssusb_set_force_mode(ssusb
, MTU3_DR_FORCE_HOST
);
326 /* if port0 supports dual-role, works as host mode by default */
327 ssusb_set_vbus(&ssusb
->otg_switch
, 1);
330 static void ssusb_host_cleanup(struct ssusb_mtk
*ssusb
)
333 ssusb_set_vbus(&ssusb
->otg_switch
, 0);
335 ssusb_host_disable(ssusb
);
339 * If host supports multiple ports, the VBUSes(5V) of ports except port0
340 * which supports OTG are better to be enabled by default in DTS.
341 * Because the host driver will keep link with devices attached when system
342 * enters suspend mode, so no need to control VBUSes after initialization.
344 int ssusb_host_init(struct ssusb_mtk
*ssusb
, struct device_node
*parent_dn
)
346 struct device
*parent_dev
= ssusb
->dev
;
349 ssusb_host_setup(ssusb
);
351 ret
= of_platform_populate(parent_dn
, NULL
, NULL
, parent_dev
);
353 dev_dbg(parent_dev
, "failed to create child devices at %pOF\n",
358 dev_info(parent_dev
, "xHCI platform device register success...\n");
363 void ssusb_host_exit(struct ssusb_mtk
*ssusb
)
365 of_platform_depopulate(ssusb
->dev
);
366 ssusb_host_cleanup(ssusb
);