mediatek: Add support for Xiaomi Redmi Router AX6S
[openwrt/staging/chunkeey.git] / target / linux / bcm4908 / patches-5.4 / 084-v5.6-0013-phy-usb-Add-support-for-wake-and-USB-low-power-mode-.patch
1 From b0c0b66c0b432d3f3a1ae5849298ba9c7f1810c5 Mon Sep 17 00:00:00 2001
2 From: Al Cooper <alcooperx@gmail.com>
3 Date: Fri, 3 Jan 2020 13:18:11 -0500
4 Subject: [PATCH] phy: usb: Add support for wake and USB low power mode for
5 7211 S2/S5
6
7 Add support for 7211 USB wake. Disable all possible 7211 USB logic
8 for S2/S5 if USB wake is not enabled.
9
10 On the 7211, the XHCI wake signal was not connected properly and
11 only goes to the USB1_USB1_CTRL_TP_DIAG1 diagonstic register.
12 The workaround is to have VPU code running that polls for the
13 proper bit in the DIAG register and to wake the system when
14 the bit is asserted.
15
16 Signed-off-by: Al Cooper <alcooperx@gmail.com>
17 Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
18 Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
19 ---
20 .../phy/broadcom/phy-brcm-usb-init-synopsys.c | 77 +++++++++++++++++--
21 drivers/phy/broadcom/phy-brcm-usb-init.c | 26 ++++---
22 drivers/phy/broadcom/phy-brcm-usb-init.h | 11 +--
23 drivers/phy/broadcom/phy-brcm-usb.c | 25 ++++--
24 4 files changed, 105 insertions(+), 34 deletions(-)
25
26 --- a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
27 +++ b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
28 @@ -26,7 +26,6 @@
29 #define PIARBCTL_MISC_CAM1_MEM_PAGE_MASK 0x00000f00
30 #define PIARBCTL_MISC_CAM0_MEM_PAGE_MASK 0x000000f0
31 #define PIARBCTL_MISC_SATA_PRIORITY_MASK 0x0000000f
32 -#define PIARBCTL_USB_M_ASB_CTRL 0x10
33
34 #define PIARBCTL_MISC_USB_ONLY_MASK \
35 (PIARBCTL_MISC_USB_SELECT_MASK | \
36 @@ -51,14 +50,27 @@
37 #define USB_CTRL_USB_PM_STATUS 0x08
38 #define USB_CTRL_USB_DEVICE_CTL1 0x10
39 #define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK 0x00000003
40 +#define USB_CTRL_TEST_PORT_CTL 0x30
41 +#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_MASK 0x000000ff
42 +#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_PME_GEN_MASK 0x0000002e
43 +#define USB_CTRL_TP_DIAG1 0x34
44 +#define USB_CTLR_TP_DIAG1_wake_MASK 0x00000002
45 +#define USB_CTRL_CTLR_CSHCR 0x50
46 +#define USB_CTRL_CTLR_CSHCR_ctl_pme_en_MASK 0x00040000
47
48 /* Register definitions for the USB_PHY block in 7211b0 */
49 +#define USB_PHY_PLL_CTL 0x00
50 +#define USB_PHY_PLL_CTL_PLL_RESETB_MASK 0x40000000
51 #define USB_PHY_PLL_LDO_CTL 0x08
52 #define USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK 0x00000004
53 +#define USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK 0x00000002
54 +#define USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK 0x00000001
55 #define USB_PHY_UTMI_CTL_1 0x04
56 #define USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK 0x00000800
57 #define USB_PHY_UTMI_CTL_1_PHY_MODE_MASK 0x0000000c
58 #define USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT 2
59 +#define USB_PHY_IDDQ 0x1c
60 +#define USB_PHY_IDDQ_phy_iddq_MASK 0x00000001
61 #define USB_PHY_STATUS 0x20
62 #define USB_PHY_STATUS_pll_lock_MASK 0x00000001
63
64 @@ -199,6 +211,17 @@ static void usb_init_common(struct brcm_
65 }
66 }
67
68 +static void usb_wake_enable_7211b0(struct brcm_usb_init_params *params,
69 + bool enable)
70 +{
71 + void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
72 +
73 + if (enable)
74 + USB_CTRL_SET(ctrl, CTLR_CSHCR, ctl_pme_en);
75 + else
76 + USB_CTRL_UNSET(ctrl, CTLR_CSHCR, ctl_pme_en);
77 +}
78 +
79 static void usb_init_common_7211b0(struct brcm_usb_init_params *params)
80 {
81 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
82 @@ -210,9 +233,27 @@ static void usb_init_common_7211b0(struc
83 if (params->syscon_piarbctl)
84 syscon_piarbctl_init(params->syscon_piarbctl);
85
86 + USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
87 +
88 + usb_wake_enable_7211b0(params, false);
89 + if (!params->wake_enabled) {
90 +
91 + /* undo possible suspend settings */
92 + brcm_usb_writel(0, usb_phy + USB_PHY_IDDQ);
93 + reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);
94 + reg |= USB_PHY_PLL_CTL_PLL_RESETB_MASK;
95 + brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);
96 +
97 + /* temporarily enable FSM so PHY comes up properly */
98 + reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1);
99 + reg |= USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK;
100 + brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);
101 + }
102 +
103 /* Init the PHY */
104 - reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_LDO_CTL);
105 - reg |= USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK;
106 + reg = USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK |
107 + USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK |
108 + USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK;
109 brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_LDO_CTL);
110
111 /* wait for lock */
112 @@ -276,12 +317,36 @@ static void usb_uninit_common(struct brc
113
114 }
115
116 +static void usb_uninit_common_7211b0(struct brcm_usb_init_params *params)
117 +{
118 + void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
119 + void __iomem *usb_phy = params->regs[BRCM_REGS_USB_PHY];
120 + u32 reg;
121 +
122 + pr_debug("%s\n", __func__);
123 +
124 + if (params->wake_enabled) {
125 + USB_CTRL_SET(ctrl, TEST_PORT_CTL, TPOUT_SEL_PME_GEN);
126 + usb_wake_enable_7211b0(params, true);
127 + } else {
128 + USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
129 + brcm_usb_writel(0, usb_phy + USB_PHY_PLL_LDO_CTL);
130 + reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);
131 + reg &= ~USB_PHY_PLL_CTL_PLL_RESETB_MASK;
132 + brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);
133 + brcm_usb_writel(USB_PHY_IDDQ_phy_iddq_MASK,
134 + usb_phy + USB_PHY_IDDQ);
135 + }
136 +
137 +}
138 +
139 static void usb_uninit_xhci(struct brcm_usb_init_params *params)
140 {
141
142 pr_debug("%s\n", __func__);
143
144 - xhci_soft_reset(params, 1);
145 + if (!params->wake_enabled)
146 + xhci_soft_reset(params, 1);
147 }
148
149 static int usb_get_dual_select(struct brcm_usb_init_params *params)
150 @@ -309,7 +374,6 @@ static void usb_set_dual_select(struct b
151 brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
152 }
153
154 -
155 static const struct brcm_usb_init_ops bcm7216_ops = {
156 .init_ipp = usb_init_ipp,
157 .init_common = usb_init_common,
158 @@ -324,7 +388,7 @@ static const struct brcm_usb_init_ops bc
159 .init_ipp = usb_init_ipp,
160 .init_common = usb_init_common_7211b0,
161 .init_xhci = usb_init_xhci,
162 - .uninit_common = usb_uninit_common,
163 + .uninit_common = usb_uninit_common_7211b0,
164 .uninit_xhci = usb_uninit_xhci,
165 .get_dual_select = usb_get_dual_select,
166 .set_dual_select = usb_set_dual_select,
167 @@ -346,4 +410,5 @@ void brcm_usb_dvr_init_7211b0(struct brc
168
169 params->family_name = "7211";
170 params->ops = &bcm7211b0_ops;
171 + params->suspend_with_clocks = true;
172 }
173 --- a/drivers/phy/broadcom/phy-brcm-usb-init.c
174 +++ b/drivers/phy/broadcom/phy-brcm-usb-init.c
175 @@ -783,12 +783,24 @@ static void usb_init_ipp(struct brcm_usb
176 msleep(50);
177 }
178
179 +static void usb_wake_enable(struct brcm_usb_init_params *params,
180 + bool enable)
181 +{
182 + void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
183 +
184 + if (enable)
185 + USB_CTRL_SET(ctrl, USB_PM, RMTWKUP_EN);
186 + else
187 + USB_CTRL_UNSET(ctrl, USB_PM, RMTWKUP_EN);
188 +}
189 +
190 static void usb_init_common(struct brcm_usb_init_params *params)
191 {
192 u32 reg;
193 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
194
195 /* Clear any pending wake conditions */
196 + usb_wake_enable(params, false);
197 reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_PM_STATUS));
198 brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_PM_STATUS));
199
200 @@ -935,6 +947,8 @@ static void usb_uninit_common(struct brc
201
202 if (USB_CTRL_MASK_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN))
203 USB_CTRL_SET_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN);
204 + if (params->wake_enabled)
205 + usb_wake_enable(params, true);
206 }
207
208 static void usb_uninit_eohci(struct brcm_usb_init_params *params)
209 @@ -978,17 +992,6 @@ static void usb_set_dual_select(struct b
210 }
211 }
212
213 -static void usb_wake_enable(struct brcm_usb_init_params *params,
214 - int enable)
215 -{
216 - void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
217 -
218 - if (enable)
219 - USB_CTRL_SET(ctrl, USB_PM, RMTWKUP_EN);
220 - else
221 - USB_CTRL_UNSET(ctrl, USB_PM, RMTWKUP_EN);
222 -}
223 -
224 static const struct brcm_usb_init_ops bcm7445_ops = {
225 .init_ipp = usb_init_ipp,
226 .init_common = usb_init_common,
227 @@ -999,7 +1002,6 @@ static const struct brcm_usb_init_ops bc
228 .uninit_xhci = usb_uninit_xhci,
229 .get_dual_select = usb_get_dual_select,
230 .set_dual_select = usb_set_dual_select,
231 - .wake_enable = usb_wake_enable,
232 };
233
234 void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params)
235 --- a/drivers/phy/broadcom/phy-brcm-usb-init.h
236 +++ b/drivers/phy/broadcom/phy-brcm-usb-init.h
237 @@ -46,8 +46,6 @@ struct brcm_usb_init_ops {
238 void (*uninit_xhci)(struct brcm_usb_init_params *params);
239 int (*get_dual_select)(struct brcm_usb_init_params *params);
240 void (*set_dual_select)(struct brcm_usb_init_params *params, int mode);
241 - void (*wake_enable)(struct brcm_usb_init_params *params,
242 - int enable);
243 };
244
245 struct brcm_usb_init_params {
246 @@ -62,6 +60,8 @@ struct brcm_usb_init_params {
247 const u32 *usb_reg_bits_map;
248 const struct brcm_usb_init_ops *ops;
249 struct regmap *syscon_piarbctl;
250 + bool wake_enabled;
251 + bool suspend_with_clocks;
252 };
253
254 void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params);
255 @@ -145,13 +145,6 @@ static inline void brcm_usb_uninit_xhci(
256 ini->ops->uninit_xhci(ini);
257 }
258
259 -static inline void brcm_usb_wake_enable(struct brcm_usb_init_params *ini,
260 - int enable)
261 -{
262 - if (ini->ops->wake_enable)
263 - ini->ops->wake_enable(ini, enable);
264 -}
265 -
266 static inline int brcm_usb_get_dual_select(struct brcm_usb_init_params *ini)
267 {
268 if (ini->ops->get_dual_select)
269 --- a/drivers/phy/broadcom/phy-brcm-usb.c
270 +++ b/drivers/phy/broadcom/phy-brcm-usb.c
271 @@ -535,16 +535,26 @@ static int brcm_usb_phy_suspend(struct d
272 struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
273
274 if (priv->init_count) {
275 + priv->ini.wake_enabled = device_may_wakeup(dev);
276 if (priv->phys[BRCM_USB_PHY_3_0].inited)
277 brcm_usb_uninit_xhci(&priv->ini);
278 if (priv->phys[BRCM_USB_PHY_2_0].inited)
279 brcm_usb_uninit_eohci(&priv->ini);
280 brcm_usb_uninit_common(&priv->ini);
281 - brcm_usb_wake_enable(&priv->ini, true);
282 - if (priv->phys[BRCM_USB_PHY_3_0].inited)
283 - clk_disable_unprepare(priv->usb_30_clk);
284 - if (priv->phys[BRCM_USB_PHY_2_0].inited || !priv->has_eohci)
285 - clk_disable_unprepare(priv->usb_20_clk);
286 +
287 + /*
288 + * Handle the clocks unless needed for wake. This has
289 + * to work for both older XHCI->3.0-clks, EOHCI->2.0-clks
290 + * and newer XHCI->2.0-clks/3.0-clks.
291 + */
292 +
293 + if (!priv->ini.suspend_with_clocks) {
294 + if (priv->phys[BRCM_USB_PHY_3_0].inited)
295 + clk_disable_unprepare(priv->usb_30_clk);
296 + if (priv->phys[BRCM_USB_PHY_2_0].inited ||
297 + !priv->has_eohci)
298 + clk_disable_unprepare(priv->usb_20_clk);
299 + }
300 if (priv->wake_irq >= 0)
301 enable_irq_wake(priv->wake_irq);
302 }
303 @@ -557,7 +567,6 @@ static int brcm_usb_phy_resume(struct de
304
305 clk_prepare_enable(priv->usb_20_clk);
306 clk_prepare_enable(priv->usb_30_clk);
307 - brcm_usb_wake_enable(&priv->ini, false);
308 brcm_usb_init_ipp(&priv->ini);
309
310 /*
311 @@ -579,6 +588,8 @@ static int brcm_usb_phy_resume(struct de
312 } else if (priv->has_xhci) {
313 brcm_usb_uninit_xhci(&priv->ini);
314 clk_disable_unprepare(priv->usb_30_clk);
315 + if (!priv->has_eohci)
316 + clk_disable_unprepare(priv->usb_20_clk);
317 }
318 } else {
319 if (priv->has_xhci)
320 @@ -589,7 +600,7 @@ static int brcm_usb_phy_resume(struct de
321 clk_disable_unprepare(priv->usb_20_clk);
322 clk_disable_unprepare(priv->usb_30_clk);
323 }
324 -
325 + priv->ini.wake_enabled = false;
326 return 0;
327 }
328 #endif /* CONFIG_PM_SLEEP */