mediatek: backport upstream mediatek patches
[oweals/openwrt.git] / target / linux / mediatek / patches-4.14 / 0190-usb-xhci-mtk-supports-remote-wakeup-for-mt2712-with-.patch
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
5  two xHCI IPs
6
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
10 from mt8173.
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
15 the same time.
16
17 Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
18 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
19 ---
20  drivers/usb/host/xhci-mtk.c | 177 +++++++++++++++-----------------------------
21  drivers/usb/host/xhci-mtk.h |   6 +-
22  2 files changed, 65 insertions(+), 118 deletions(-)
23
24 diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
25 index e5caabe7eebe..8e51b3fec386 100644
26 --- a/drivers/usb/host/xhci-mtk.c
27 +++ b/drivers/usb/host/xhci-mtk.c
28 @@ -66,26 +66,21 @@
29  /* u2_phy_pll register */
30  #define CTRL_U2_FORCE_PLL_STB  BIT(28)
31  
32 -#define PERI_WK_CTRL0          0x400
33 -#define UWK_CTR0_0P_LS_PE      BIT(8)  /* posedge */
34 -#define UWK_CTR0_0P_LS_NE      BIT(7)  /* negedge for 0p linestate*/
35 -#define UWK_CTL1_1P_LS_C(x)    (((x) & 0xf) << 1)
36 -#define UWK_CTL1_1P_LS_E       BIT(0)
37 -
38 -#define PERI_WK_CTRL1          0x404
39 -#define UWK_CTL1_IS_C(x)       (((x) & 0xf) << 26)
40 -#define UWK_CTL1_IS_E          BIT(25)
41 -#define UWK_CTL1_0P_LS_C(x)    (((x) & 0xf) << 21)
42 -#define UWK_CTL1_0P_LS_E       BIT(20)
43 -#define UWK_CTL1_IDDIG_C(x)    (((x) & 0xf) << 11)  /* cycle debounce */
44 -#define UWK_CTL1_IDDIG_E       BIT(10) /* enable debounce */
45 -#define UWK_CTL1_IDDIG_P       BIT(9)  /* polarity */
46 -#define UWK_CTL1_0P_LS_P       BIT(7)
47 -#define UWK_CTL1_IS_P          BIT(6)  /* polarity for ip sleep */
48 -
49 -enum ssusb_wakeup_src {
50 -       SSUSB_WK_IP_SLEEP = 1,
51 -       SSUSB_WK_LINE_STATE = 2,
52 +/* usb remote wakeup registers in syscon */
53 +/* mt8173 etc */
54 +#define PERI_WK_CTRL1  0x4
55 +#define WC1_IS_C(x)    (((x) & 0xf) << 26)  /* cycle debounce */
56 +#define WC1_IS_EN      BIT(25)
57 +#define WC1_IS_P       BIT(6)  /* polarity for ip sleep */
58 +
59 +/* mt2712 etc */
60 +#define PERI_SSUSB_SPM_CTRL    0x0
61 +#define SSC_IP_SLEEP_EN        BIT(4)
62 +#define SSC_SPM_INT_EN         BIT(1)
63 +
64 +enum ssusb_uwk_vers {
65 +       SSUSB_UWK_V1 = 1,
66 +       SSUSB_UWK_V2,
67  };
68  
69  static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk)
70 @@ -308,112 +303,58 @@ static void xhci_mtk_clks_disable(struct xhci_hcd_mtk *mtk)
71  }
72  
73  /* only clocks can be turn off for ip-sleep wakeup mode */
74 -static void usb_wakeup_ip_sleep_en(struct xhci_hcd_mtk *mtk)
75 +static void usb_wakeup_ip_sleep_set(struct xhci_hcd_mtk *mtk, bool enable)
76  {
77 -       u32 tmp;
78 -       struct regmap *pericfg = mtk->pericfg;
79 -
80 -       regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
81 -       tmp &= ~UWK_CTL1_IS_P;
82 -       tmp &= ~(UWK_CTL1_IS_C(0xf));
83 -       tmp |= UWK_CTL1_IS_C(0x8);
84 -       regmap_write(pericfg, PERI_WK_CTRL1, tmp);
85 -       regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_IS_E);
86 -
87 -       regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
88 -       dev_dbg(mtk->dev, "%s(): WK_CTRL1[P6,E25,C26:29]=%#x\n",
89 -               __func__, tmp);
90 +       u32 reg, msk, val;
91 +
92 +       switch (mtk->uwk_vers) {
93 +       case SSUSB_UWK_V1:
94 +               reg = mtk->uwk_reg_base + PERI_WK_CTRL1;
95 +               msk = WC1_IS_EN | WC1_IS_C(0xf) | WC1_IS_P;
96 +               val = enable ? (WC1_IS_EN | WC1_IS_C(0x8)) : 0;
97 +               break;
98 +       case SSUSB_UWK_V2:
99 +               reg = mtk->uwk_reg_base + PERI_SSUSB_SPM_CTRL;
100 +               msk = SSC_IP_SLEEP_EN | SSC_SPM_INT_EN;
101 +               val = enable ? msk : 0;
102 +               break;
103 +       default:
104 +               return;
105 +       };
106 +       regmap_update_bits(mtk->uwk, reg, msk, val);
107  }
108  
109 -static void usb_wakeup_ip_sleep_dis(struct xhci_hcd_mtk *mtk)
110 +static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk,
111 +                               struct device_node *dn)
112  {
113 -       u32 tmp;
114 +       struct of_phandle_args args;
115 +       int ret;
116  
117 -       regmap_read(mtk->pericfg, PERI_WK_CTRL1, &tmp);
118 -       tmp &= ~UWK_CTL1_IS_E;
119 -       regmap_write(mtk->pericfg, PERI_WK_CTRL1, tmp);
120 -}
121 +       /* Wakeup function is optional */
122 +       mtk->uwk_en = of_property_read_bool(dn, "wakeup-source");
123 +       if (!mtk->uwk_en)
124 +               return 0;
125  
126 -/*
127 -* for line-state wakeup mode, phy's power should not power-down
128 -* and only support cable plug in/out
129 -*/
130 -static void usb_wakeup_line_state_en(struct xhci_hcd_mtk *mtk)
131 -{
132 -       u32 tmp;
133 -       struct regmap *pericfg = mtk->pericfg;
134 -
135 -       /* line-state of u2-port0 */
136 -       regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
137 -       tmp &= ~UWK_CTL1_0P_LS_P;
138 -       tmp &= ~(UWK_CTL1_0P_LS_C(0xf));
139 -       tmp |= UWK_CTL1_0P_LS_C(0x8);
140 -       regmap_write(pericfg, PERI_WK_CTRL1, tmp);
141 -       regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
142 -       regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_0P_LS_E);
143 -
144 -       /* line-state of u2-port1 */
145 -       regmap_read(pericfg, PERI_WK_CTRL0, &tmp);
146 -       tmp &= ~(UWK_CTL1_1P_LS_C(0xf));
147 -       tmp |= UWK_CTL1_1P_LS_C(0x8);
148 -       regmap_write(pericfg, PERI_WK_CTRL0, tmp);
149 -       regmap_write(pericfg, PERI_WK_CTRL0, tmp | UWK_CTL1_1P_LS_E);
150 -}
151 +       ret = of_parse_phandle_with_fixed_args(dn,
152 +                               "mediatek,syscon-wakeup", 2, 0, &args);
153 +       if (ret)
154 +               return ret;
155  
156 -static void usb_wakeup_line_state_dis(struct xhci_hcd_mtk *mtk)
157 -{
158 -       u32 tmp;
159 -       struct regmap *pericfg = mtk->pericfg;
160 -
161 -       /* line-state of u2-port0 */
162 -       regmap_read(pericfg, PERI_WK_CTRL1, &tmp);
163 -       tmp &= ~UWK_CTL1_0P_LS_E;
164 -       regmap_write(pericfg, PERI_WK_CTRL1, tmp);
165 -
166 -       /* line-state of u2-port1 */
167 -       regmap_read(pericfg, PERI_WK_CTRL0, &tmp);
168 -       tmp &= ~UWK_CTL1_1P_LS_E;
169 -       regmap_write(pericfg, PERI_WK_CTRL0, tmp);
170 -}
171 +       mtk->uwk_reg_base = args.args[0];
172 +       mtk->uwk_vers = args.args[1];
173 +       mtk->uwk = syscon_node_to_regmap(args.np);
174 +       of_node_put(args.np);
175 +       dev_info(mtk->dev, "uwk - reg:0x%x, version:%d\n",
176 +                       mtk->uwk_reg_base, mtk->uwk_vers);
177  
178 -static void usb_wakeup_enable(struct xhci_hcd_mtk *mtk)
179 -{
180 -       if (mtk->wakeup_src == SSUSB_WK_IP_SLEEP)
181 -               usb_wakeup_ip_sleep_en(mtk);
182 -       else if (mtk->wakeup_src == SSUSB_WK_LINE_STATE)
183 -               usb_wakeup_line_state_en(mtk);
184 -}
185 +       return PTR_ERR_OR_ZERO(mtk->uwk);
186  
187 -static void usb_wakeup_disable(struct xhci_hcd_mtk *mtk)
188 -{
189 -       if (mtk->wakeup_src == SSUSB_WK_IP_SLEEP)
190 -               usb_wakeup_ip_sleep_dis(mtk);
191 -       else if (mtk->wakeup_src == SSUSB_WK_LINE_STATE)
192 -               usb_wakeup_line_state_dis(mtk);
193  }
194  
195 -static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk,
196 -                               struct device_node *dn)
197 +static void usb_wakeup_set(struct xhci_hcd_mtk *mtk, bool enable)
198  {
199 -       struct device *dev = mtk->dev;
200 -
201 -       /*
202 -       * wakeup function is optional, so it is not an error if this property
203 -       * does not exist, and in such case, no need to get relative
204 -       * properties anymore.
205 -       */
206 -       of_property_read_u32(dn, "mediatek,wakeup-src", &mtk->wakeup_src);
207 -       if (!mtk->wakeup_src)
208 -               return 0;
209 -
210 -       mtk->pericfg = syscon_regmap_lookup_by_phandle(dn,
211 -                                               "mediatek,syscon-wakeup");
212 -       if (IS_ERR(mtk->pericfg)) {
213 -               dev_err(dev, "fail to get pericfg regs\n");
214 -               return PTR_ERR(mtk->pericfg);
215 -       }
216 -
217 -       return 0;
218 +       if (mtk->uwk_en)
219 +               usb_wakeup_ip_sleep_set(mtk, enable);
220  }
221  
222  static int xhci_mtk_setup(struct usb_hcd *hcd);
223 @@ -595,8 +536,10 @@ static int xhci_mtk_probe(struct platform_device *pdev)
224                              &mtk->u3p_dis_msk);
225  
226         ret = usb_wakeup_of_property_parse(mtk, node);
227 -       if (ret)
228 +       if (ret) {
229 +               dev_err(dev, "failed to parse uwk property\n");
230                 return ret;
231 +       }
232  
233         mtk->num_phys = of_count_phandle_with_args(node,
234                         "phys", "#phy-cells");
235 @@ -780,7 +723,7 @@ static int __maybe_unused xhci_mtk_suspend(struct device *dev)
236         xhci_mtk_host_disable(mtk);
237         xhci_mtk_phy_power_off(mtk);
238         xhci_mtk_clks_disable(mtk);
239 -       usb_wakeup_enable(mtk);
240 +       usb_wakeup_set(mtk, true);
241         return 0;
242  }
243  
244 @@ -790,7 +733,7 @@ static int __maybe_unused xhci_mtk_resume(struct device *dev)
245         struct usb_hcd *hcd = mtk->hcd;
246         struct xhci_hcd *xhci = hcd_to_xhci(hcd);
247  
248 -       usb_wakeup_disable(mtk);
249 +       usb_wakeup_set(mtk, false);
250         xhci_mtk_clks_enable(mtk);
251         xhci_mtk_phy_power_on(mtk);
252         xhci_mtk_host_enable(mtk);
253 diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h
254 index 45ff5c67efb5..85c007ee1f52 100644
255 --- a/drivers/usb/host/xhci-mtk.h
256 +++ b/drivers/usb/host/xhci-mtk.h
257 @@ -131,8 +131,12 @@ struct xhci_hcd_mtk {
258         struct regmap *pericfg;
259         struct phy **phys;
260         int num_phys;
261 -       int wakeup_src;
262         bool lpm_support;
263 +       /* usb remote wakeup */
264 +       bool uwk_en;
265 +       struct regmap *uwk;
266 +       u32 uwk_reg_base;
267 +       u32 uwk_vers;
268  };
269  
270  static inline struct xhci_hcd_mtk *hcd_to_mtk(struct usb_hcd *hcd)
271 -- 
272 2.11.0
273