1 From e6fe50ef22071fe87ce48f79ab4fe21cbec2081b Mon Sep 17 00:00:00 2001
2 From: Chunfeng Yun <chunfeng.yun@mediatek.com>
3 Date: Wed, 3 Jan 2018 16:53:20 +0800
4 Subject: [PATCH 190/224] usb: xhci-mtk: supports remote wakeup for mt2712 with
7 The old way of usb wakeup only supports platform with single xHCI IP,
8 such as mt8173, but mt2712 has two xHCI IPs, so rebuild its flow and
9 supports the new glue layer of usb wakeup on mt2712 which is different
11 Due to there is a hardware bug with the LINE STATE wakeup mode on
12 mt8173 which causes wakeup failure by low speed devices, and also
13 because IP SLEEP mode can cover all functions of LINE STATE mode,
14 it is unused in fact, and will not support it later, so remove it at
17 Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
18 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
20 drivers/usb/host/xhci-mtk.c | 177 +++++++++++++++-----------------------------
21 drivers/usb/host/xhci-mtk.h | 6 +-
22 2 files changed, 65 insertions(+), 118 deletions(-)
24 --- a/drivers/usb/host/xhci-mtk.c
25 +++ b/drivers/usb/host/xhci-mtk.c
27 /* u2_phy_pll register */
28 #define CTRL_U2_FORCE_PLL_STB BIT(28)
30 -#define PERI_WK_CTRL0 0x400
31 -#define UWK_CTR0_0P_LS_PE BIT(8) /* posedge */
32 -#define UWK_CTR0_0P_LS_NE BIT(7) /* negedge for 0p linestate*/
33 -#define UWK_CTL1_1P_LS_C(x) (((x) & 0xf) << 1)
34 -#define UWK_CTL1_1P_LS_E BIT(0)
36 -#define PERI_WK_CTRL1 0x404
37 -#define UWK_CTL1_IS_C(x) (((x) & 0xf) << 26)
38 -#define UWK_CTL1_IS_E BIT(25)
39 -#define UWK_CTL1_0P_LS_C(x) (((x) & 0xf) << 21)
40 -#define UWK_CTL1_0P_LS_E BIT(20)
41 -#define UWK_CTL1_IDDIG_C(x) (((x) & 0xf) << 11) /* cycle debounce */
42 -#define UWK_CTL1_IDDIG_E BIT(10) /* enable debounce */
43 -#define UWK_CTL1_IDDIG_P BIT(9) /* polarity */
44 -#define UWK_CTL1_0P_LS_P BIT(7)
45 -#define UWK_CTL1_IS_P BIT(6) /* polarity for ip sleep */
47 -enum ssusb_wakeup_src {
48 - SSUSB_WK_IP_SLEEP = 1,
49 - SSUSB_WK_LINE_STATE = 2,
50 +/* usb remote wakeup registers in syscon */
52 +#define PERI_WK_CTRL1 0x4
53 +#define WC1_IS_C(x) (((x) & 0xf) << 26) /* cycle debounce */
54 +#define WC1_IS_EN BIT(25)
55 +#define WC1_IS_P BIT(6) /* polarity for ip sleep */
58 +#define PERI_SSUSB_SPM_CTRL 0x0
59 +#define SSC_IP_SLEEP_EN BIT(4)
60 +#define SSC_SPM_INT_EN BIT(1)
62 +enum ssusb_uwk_vers {
67 static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk)
68 @@ -308,112 +303,58 @@ static void xhci_mtk_clks_disable(struct
71 /* only clocks can be turn off for ip-sleep wakeup mode */
72 -static void usb_wakeup_ip_sleep_en(struct xhci_hcd_mtk *mtk)
73 +static void usb_wakeup_ip_sleep_set(struct xhci_hcd_mtk *mtk, bool enable)
76 - struct regmap *pericfg = mtk->pericfg;
79 - regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
80 - tmp &= ~UWK_CTL1_IS_P;
81 - tmp &= ~(UWK_CTL1_IS_C(0xf));
82 - tmp |= UWK_CTL1_IS_C(0x8);
83 - regmap_write(pericfg, PERI_WK_CTRL1, tmp);
84 - regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_IS_E);
86 - regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
87 - dev_dbg(mtk->dev, "%s(): WK_CTRL1[P6,E25,C26:29]=%#x\n",
91 -static void usb_wakeup_ip_sleep_dis(struct xhci_hcd_mtk *mtk)
95 - regmap_read(mtk->pericfg, PERI_WK_CTRL1, &tmp);
96 - tmp &= ~UWK_CTL1_IS_E;
97 - regmap_write(mtk->pericfg, PERI_WK_CTRL1, tmp);
98 + switch (mtk->uwk_vers) {
100 + reg = mtk->uwk_reg_base + PERI_WK_CTRL1;
101 + msk = WC1_IS_EN | WC1_IS_C(0xf) | WC1_IS_P;
102 + val = enable ? (WC1_IS_EN | WC1_IS_C(0x8)) : 0;
105 + reg = mtk->uwk_reg_base + PERI_SSUSB_SPM_CTRL;
106 + msk = SSC_IP_SLEEP_EN | SSC_SPM_INT_EN;
107 + val = enable ? msk : 0;
112 + regmap_update_bits(mtk->uwk, reg, msk, val);
116 -* for line-state wakeup mode, phy's power should not power-down
117 -* and only support cable plug in/out
119 -static void usb_wakeup_line_state_en(struct xhci_hcd_mtk *mtk)
120 +static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk,
121 + struct device_node *dn)
124 - struct regmap *pericfg = mtk->pericfg;
126 - /* line-state of u2-port0 */
127 - regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
128 - tmp &= ~UWK_CTL1_0P_LS_P;
129 - tmp &= ~(UWK_CTL1_0P_LS_C(0xf));
130 - tmp |= UWK_CTL1_0P_LS_C(0x8);
131 - regmap_write(pericfg, PERI_WK_CTRL1, tmp);
132 - regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
133 - regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_0P_LS_E);
134 + struct of_phandle_args args;
137 - /* line-state of u2-port1 */
138 - regmap_read(pericfg, PERI_WK_CTRL0, &tmp);
139 - tmp &= ~(UWK_CTL1_1P_LS_C(0xf));
140 - tmp |= UWK_CTL1_1P_LS_C(0x8);
141 - regmap_write(pericfg, PERI_WK_CTRL0, tmp);
142 - regmap_write(pericfg, PERI_WK_CTRL0, tmp | UWK_CTL1_1P_LS_E);
144 + /* Wakeup function is optional */
145 + mtk->uwk_en = of_property_read_bool(dn, "wakeup-source");
149 -static void usb_wakeup_line_state_dis(struct xhci_hcd_mtk *mtk)
152 - struct regmap *pericfg = mtk->pericfg;
153 + ret = of_parse_phandle_with_fixed_args(dn,
154 + "mediatek,syscon-wakeup", 2, 0, &args);
158 - /* line-state of u2-port0 */
159 - regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
160 - tmp &= ~UWK_CTL1_0P_LS_E;
161 - regmap_write(pericfg, PERI_WK_CTRL1, tmp);
162 + mtk->uwk_reg_base = args.args[0];
163 + mtk->uwk_vers = args.args[1];
164 + mtk->uwk = syscon_node_to_regmap(args.np);
165 + of_node_put(args.np);
166 + dev_info(mtk->dev, "uwk - reg:0x%x, version:%d\n",
167 + mtk->uwk_reg_base, mtk->uwk_vers);
169 - /* line-state of u2-port1 */
170 - regmap_read(pericfg, PERI_WK_CTRL0, &tmp);
171 - tmp &= ~UWK_CTL1_1P_LS_E;
172 - regmap_write(pericfg, PERI_WK_CTRL0, tmp);
174 + return PTR_ERR_OR_ZERO(mtk->uwk);
176 -static void usb_wakeup_enable(struct xhci_hcd_mtk *mtk)
178 - if (mtk->wakeup_src == SSUSB_WK_IP_SLEEP)
179 - usb_wakeup_ip_sleep_en(mtk);
180 - else if (mtk->wakeup_src == SSUSB_WK_LINE_STATE)
181 - usb_wakeup_line_state_en(mtk);
184 -static void usb_wakeup_disable(struct xhci_hcd_mtk *mtk)
185 +static void usb_wakeup_set(struct xhci_hcd_mtk *mtk, bool enable)
187 - if (mtk->wakeup_src == SSUSB_WK_IP_SLEEP)
188 - usb_wakeup_ip_sleep_dis(mtk);
189 - else if (mtk->wakeup_src == SSUSB_WK_LINE_STATE)
190 - usb_wakeup_line_state_dis(mtk);
193 -static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk,
194 - struct device_node *dn)
196 - struct device *dev = mtk->dev;
199 - * wakeup function is optional, so it is not an error if this property
200 - * does not exist, and in such case, no need to get relative
201 - * properties anymore.
203 - of_property_read_u32(dn, "mediatek,wakeup-src", &mtk->wakeup_src);
204 - if (!mtk->wakeup_src)
207 - mtk->pericfg = syscon_regmap_lookup_by_phandle(dn,
208 - "mediatek,syscon-wakeup");
209 - if (IS_ERR(mtk->pericfg)) {
210 - dev_err(dev, "fail to get pericfg regs\n");
211 - return PTR_ERR(mtk->pericfg);
216 + usb_wakeup_ip_sleep_set(mtk, enable);
219 static int xhci_mtk_setup(struct usb_hcd *hcd);
220 @@ -595,8 +536,10 @@ static int xhci_mtk_probe(struct platfor
223 ret = usb_wakeup_of_property_parse(mtk, node);
226 + dev_err(dev, "failed to parse uwk property\n");
230 mtk->num_phys = of_count_phandle_with_args(node,
231 "phys", "#phy-cells");
232 @@ -780,7 +723,7 @@ static int __maybe_unused xhci_mtk_suspe
233 xhci_mtk_host_disable(mtk);
234 xhci_mtk_phy_power_off(mtk);
235 xhci_mtk_clks_disable(mtk);
236 - usb_wakeup_enable(mtk);
237 + usb_wakeup_set(mtk, true);
241 @@ -790,7 +733,7 @@ static int __maybe_unused xhci_mtk_resum
242 struct usb_hcd *hcd = mtk->hcd;
243 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
245 - usb_wakeup_disable(mtk);
246 + usb_wakeup_set(mtk, false);
247 xhci_mtk_clks_enable(mtk);
248 xhci_mtk_phy_power_on(mtk);
249 xhci_mtk_host_enable(mtk);
250 --- a/drivers/usb/host/xhci-mtk.h
251 +++ b/drivers/usb/host/xhci-mtk.h
252 @@ -131,8 +131,12 @@ struct xhci_hcd_mtk {
253 struct regmap *pericfg;
258 + /* usb remote wakeup */
260 + struct regmap *uwk;
265 static inline struct xhci_hcd_mtk *hcd_to_mtk(struct usb_hcd *hcd)