Loading...
Note: File does not exist in v5.4.
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2018, Broadcom */
3
4/*
5 * This module contains USB PHY initialization for power up and S3 resume
6 * for newer Synopsys based USB hardware first used on the bcm7216.
7 */
8
9#include <linux/delay.h>
10#include <linux/io.h>
11
12#include <linux/soc/brcmstb/brcmstb.h>
13#include "phy-brcm-usb-init.h"
14
15#define PHY_LOCK_TIMEOUT_MS 200
16
17/* Register definitions for syscon piarbctl registers */
18#define PIARBCTL_CAM 0x00
19#define PIARBCTL_SPLITTER 0x04
20#define PIARBCTL_MISC 0x08
21#define PIARBCTL_MISC_SATA_PRIORITY_MASK GENMASK(3, 0)
22#define PIARBCTL_MISC_CAM0_MEM_PAGE_MASK GENMASK(7, 4)
23#define PIARBCTL_MISC_CAM1_MEM_PAGE_MASK GENMASK(11, 8)
24#define PIARBCTL_MISC_USB_MEM_PAGE_MASK GENMASK(15, 12)
25#define PIARBCTL_MISC_USB_PRIORITY_MASK GENMASK(19, 16)
26#define PIARBCTL_MISC_USB_4G_SDRAM_MASK BIT(29)
27#define PIARBCTL_MISC_USB_SELECT_MASK BIT(30)
28#define PIARBCTL_MISC_SECURE_MASK BIT(31)
29
30#define PIARBCTL_MISC_USB_ONLY_MASK \
31 (PIARBCTL_MISC_USB_SELECT_MASK | \
32 PIARBCTL_MISC_USB_4G_SDRAM_MASK | \
33 PIARBCTL_MISC_USB_PRIORITY_MASK | \
34 PIARBCTL_MISC_USB_MEM_PAGE_MASK)
35
36/* Register definitions for the USB CTRL block */
37#define USB_CTRL_SETUP 0x00
38#define USB_CTRL_SETUP_IOC_MASK BIT(4)
39#define USB_CTRL_SETUP_IPP_MASK BIT(5)
40#define USB_CTRL_SETUP_SOFT_SHUTDOWN_MASK BIT(9)
41#define USB_CTRL_SETUP_SCB1_EN_MASK BIT(14)
42#define USB_CTRL_SETUP_SCB2_EN_MASK BIT(15)
43#define USB_CTRL_SETUP_tca_drv_sel_MASK BIT(24)
44#define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK BIT(25)
45#define USB_CTRL_USB_PM 0x04
46#define USB_CTRL_USB_PM_XHC_S2_CLK_SWITCH_EN_MASK BIT(3)
47#define USB_CTRL_USB_PM_XHC_PME_EN_MASK BIT(4)
48#define USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK BIT(22)
49#define USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK BIT(23)
50#define USB_CTRL_USB_PM_SOFT_RESET_MASK BIT(30)
51#define USB_CTRL_USB_PM_USB_PWRDN_MASK BIT(31)
52#define USB_CTRL_USB_PM_STATUS 0x08
53#define USB_CTRL_USB_DEVICE_CTL1 0x10
54#define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK GENMASK(1, 0)
55#define USB_CTRL_TEST_PORT_CTL 0x30
56#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_MASK GENMASK(7, 0)
57#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_PME_GEN_MASK 0x0000002e
58#define USB_CTRL_TP_DIAG1 0x34
59#define USB_CTLR_TP_DIAG1_wake_MASK BIT(1)
60#define USB_CTRL_CTLR_CSHCR 0x50
61#define USB_CTRL_CTLR_CSHCR_ctl_pme_en_MASK BIT(18)
62
63/* Register definitions for the USB_PHY block in 7211b0 */
64#define USB_PHY_PLL_CTL 0x00
65#define USB_PHY_PLL_CTL_PLL_SUSPEND_MASK BIT(27)
66#define USB_PHY_PLL_CTL_PLL_RESETB_MASK BIT(30)
67#define USB_PHY_PLL_LDO_CTL 0x08
68#define USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK BIT(0)
69#define USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK BIT(1)
70#define USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK BIT(2)
71#define USB_PHY_UTMI_CTL_1 0x04
72#define USB_PHY_UTMI_CTL_1_PHY_MODE_MASK GENMASK(3, 2)
73#define USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT 2
74#define USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK BIT(11)
75#define USB_PHY_IDDQ 0x1c
76#define USB_PHY_IDDQ_phy_iddq_MASK BIT(0)
77#define USB_PHY_STATUS 0x20
78#define USB_PHY_STATUS_pll_lock_MASK BIT(0)
79
80/* Register definitions for the MDIO registers in the DWC2 block of
81 * the 7211b0.
82 * NOTE: The PHY's MDIO registers are only accessible through the
83 * legacy DesignWare USB controller even though it's not being used.
84 */
85#define USB_GMDIOCSR 0
86#define USB_GMDIOGEN 4
87
88/* Register definitions for the BDC EC block in 7211b0 */
89#define BDC_EC_AXIRDA 0x0c
90#define BDC_EC_AXIRDA_RTS_MASK GENMASK(31, 28)
91#define BDC_EC_AXIRDA_RTS_SHIFT 28
92
93
94static void usb_mdio_write_7211b0(struct brcm_usb_init_params *params,
95 uint8_t addr, uint16_t data)
96{
97 void __iomem *usb_mdio = params->regs[BRCM_REGS_USB_MDIO];
98
99 addr &= 0x1f; /* 5-bit address */
100 brcm_usb_writel(0xffffffff, usb_mdio + USB_GMDIOGEN);
101 while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
102 ;
103 brcm_usb_writel(0x59020000 | (addr << 18) | data,
104 usb_mdio + USB_GMDIOGEN);
105 while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
106 ;
107 brcm_usb_writel(0x00000000, usb_mdio + USB_GMDIOGEN);
108 while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
109 ;
110}
111
112static uint16_t __maybe_unused usb_mdio_read_7211b0(
113 struct brcm_usb_init_params *params, uint8_t addr)
114{
115 void __iomem *usb_mdio = params->regs[BRCM_REGS_USB_MDIO];
116
117 addr &= 0x1f; /* 5-bit address */
118 brcm_usb_writel(0xffffffff, usb_mdio + USB_GMDIOGEN);
119 while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
120 ;
121 brcm_usb_writel(0x69020000 | (addr << 18), usb_mdio + USB_GMDIOGEN);
122 while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
123 ;
124 brcm_usb_writel(0x00000000, usb_mdio + USB_GMDIOGEN);
125 while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
126 ;
127 return brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & 0xffff;
128}
129
130static void usb2_eye_fix_7211b0(struct brcm_usb_init_params *params)
131{
132 /* select bank */
133 usb_mdio_write_7211b0(params, 0x1f, 0x80a0);
134
135 /* Set the eye */
136 usb_mdio_write_7211b0(params, 0x0a, 0xc6a0);
137}
138
139static void xhci_soft_reset(struct brcm_usb_init_params *params,
140 int on_off)
141{
142 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
143
144 /* Assert reset */
145 if (on_off)
146 USB_CTRL_UNSET(ctrl, USB_PM, XHC_SOFT_RESETB);
147 /* De-assert reset */
148 else
149 USB_CTRL_SET(ctrl, USB_PM, XHC_SOFT_RESETB);
150}
151
152static void usb_init_ipp(struct brcm_usb_init_params *params)
153{
154 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
155 u32 reg;
156 u32 orig_reg;
157
158 pr_debug("%s\n", __func__);
159
160 orig_reg = reg = brcm_usb_readl(USB_CTRL_REG(ctrl, SETUP));
161 if (params->ipp != 2)
162 /* override ipp strap pin (if it exits) */
163 reg &= ~(USB_CTRL_MASK(SETUP, STRAP_IPP_SEL));
164
165 /* Override the default OC and PP polarity */
166 reg &= ~(USB_CTRL_MASK(SETUP, IPP) | USB_CTRL_MASK(SETUP, IOC));
167 if (params->ioc)
168 reg |= USB_CTRL_MASK(SETUP, IOC);
169 if (params->ipp == 1)
170 reg |= USB_CTRL_MASK(SETUP, IPP);
171 brcm_usb_writel(reg, USB_CTRL_REG(ctrl, SETUP));
172
173 /*
174 * If we're changing IPP, make sure power is off long enough
175 * to turn off any connected devices.
176 */
177 if ((reg ^ orig_reg) & USB_CTRL_MASK(SETUP, IPP))
178 msleep(50);
179}
180
181static void syscon_piarbctl_init(struct regmap *rmap)
182{
183 /* Switch from legacy USB OTG controller to new STB USB controller */
184 regmap_update_bits(rmap, PIARBCTL_MISC, PIARBCTL_MISC_USB_ONLY_MASK,
185 PIARBCTL_MISC_USB_SELECT_MASK |
186 PIARBCTL_MISC_USB_4G_SDRAM_MASK);
187}
188
189static void usb_init_common(struct brcm_usb_init_params *params)
190{
191 u32 reg;
192 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
193
194 pr_debug("%s\n", __func__);
195
196 if (USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE)) {
197 reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
198 reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
199 reg |= params->port_mode;
200 brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
201 }
202 switch (params->supported_port_modes) {
203 case USB_CTLR_MODE_HOST:
204 USB_CTRL_UNSET(ctrl, USB_PM, BDC_SOFT_RESETB);
205 break;
206 default:
207 USB_CTRL_UNSET(ctrl, USB_PM, BDC_SOFT_RESETB);
208 USB_CTRL_SET(ctrl, USB_PM, BDC_SOFT_RESETB);
209 break;
210 }
211}
212
213static void usb_wake_enable_7211b0(struct brcm_usb_init_params *params,
214 bool enable)
215{
216 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
217
218 if (enable)
219 USB_CTRL_SET(ctrl, CTLR_CSHCR, ctl_pme_en);
220 else
221 USB_CTRL_UNSET(ctrl, CTLR_CSHCR, ctl_pme_en);
222}
223
224static void usb_wake_enable_7216(struct brcm_usb_init_params *params,
225 bool enable)
226{
227 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
228
229 if (enable)
230 USB_CTRL_SET(ctrl, USB_PM, XHC_PME_EN);
231 else
232 USB_CTRL_UNSET(ctrl, USB_PM, XHC_PME_EN);
233}
234
235static void usb_init_common_7211b0(struct brcm_usb_init_params *params)
236{
237 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
238 void __iomem *usb_phy = params->regs[BRCM_REGS_USB_PHY];
239 void __iomem *bdc_ec = params->regs[BRCM_REGS_BDC_EC];
240 int timeout_ms = PHY_LOCK_TIMEOUT_MS;
241 u32 reg;
242
243 if (params->syscon_piarbctl)
244 syscon_piarbctl_init(params->syscon_piarbctl);
245
246 USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
247
248 usb_wake_enable_7211b0(params, false);
249 if (!params->wake_enabled) {
250
251 /* undo possible suspend settings */
252 brcm_usb_writel(0, usb_phy + USB_PHY_IDDQ);
253 reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);
254 reg |= USB_PHY_PLL_CTL_PLL_RESETB_MASK;
255 brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);
256
257 /* temporarily enable FSM so PHY comes up properly */
258 reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1);
259 reg |= USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK;
260 brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);
261 }
262
263 /* Disable PLL auto suspend */
264 reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);
265 reg |= USB_PHY_PLL_CTL_PLL_SUSPEND_MASK;
266 brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);
267
268 /* Init the PHY */
269 reg = USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK |
270 USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK |
271 USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK;
272 brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_LDO_CTL);
273
274 /* wait for lock */
275 while (timeout_ms-- > 0) {
276 reg = brcm_usb_readl(usb_phy + USB_PHY_STATUS);
277 if (reg & USB_PHY_STATUS_pll_lock_MASK)
278 break;
279 usleep_range(1000, 2000);
280 }
281
282 /* Set the PHY_MODE */
283 reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1);
284 reg &= ~USB_PHY_UTMI_CTL_1_PHY_MODE_MASK;
285 reg |= params->supported_port_modes << USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT;
286 brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);
287
288 usb_init_common(params);
289
290 /*
291 * The BDC controller will get occasional failures with
292 * the default "Read Transaction Size" of 6 (1024 bytes).
293 * Set it to 4 (256 bytes).
294 */
295 if ((params->supported_port_modes != USB_CTLR_MODE_HOST) && bdc_ec) {
296 reg = brcm_usb_readl(bdc_ec + BDC_EC_AXIRDA);
297 reg &= ~BDC_EC_AXIRDA_RTS_MASK;
298 reg |= (0x4 << BDC_EC_AXIRDA_RTS_SHIFT);
299 brcm_usb_writel(reg, bdc_ec + BDC_EC_AXIRDA);
300 }
301
302 /*
303 * Disable FSM, otherwise the PHY will auto suspend when no
304 * device is connected and will be reset on resume.
305 */
306 reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1);
307 reg &= ~USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK;
308 brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);
309
310 usb2_eye_fix_7211b0(params);
311}
312
313static void usb_init_common_7216(struct brcm_usb_init_params *params)
314{
315 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
316
317 USB_CTRL_UNSET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN);
318 USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
319
320 /* 1 millisecond - for USB clocks to settle down */
321 usleep_range(1000, 2000);
322
323 usb_wake_enable_7216(params, false);
324 usb_init_common(params);
325}
326
327static void usb_init_xhci(struct brcm_usb_init_params *params)
328{
329 pr_debug("%s\n", __func__);
330
331 xhci_soft_reset(params, 0);
332}
333
334static void usb_uninit_common_7216(struct brcm_usb_init_params *params)
335{
336 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
337
338 pr_debug("%s\n", __func__);
339
340 if (params->wake_enabled) {
341 /* Switch to using slower clock during suspend to save power */
342 USB_CTRL_SET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN);
343 usb_wake_enable_7216(params, true);
344 } else {
345 USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
346 }
347}
348
349static void usb_uninit_common_7211b0(struct brcm_usb_init_params *params)
350{
351 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
352 void __iomem *usb_phy = params->regs[BRCM_REGS_USB_PHY];
353 u32 reg;
354
355 pr_debug("%s\n", __func__);
356
357 if (params->wake_enabled) {
358 USB_CTRL_SET(ctrl, TEST_PORT_CTL, TPOUT_SEL_PME_GEN);
359 usb_wake_enable_7211b0(params, true);
360 } else {
361 USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
362 brcm_usb_writel(0, usb_phy + USB_PHY_PLL_LDO_CTL);
363 reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);
364 reg &= ~USB_PHY_PLL_CTL_PLL_RESETB_MASK;
365 brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);
366 brcm_usb_writel(USB_PHY_IDDQ_phy_iddq_MASK,
367 usb_phy + USB_PHY_IDDQ);
368 }
369
370}
371
372static void usb_uninit_xhci(struct brcm_usb_init_params *params)
373{
374
375 pr_debug("%s\n", __func__);
376
377 if (!params->wake_enabled)
378 xhci_soft_reset(params, 1);
379}
380
381static int usb_get_dual_select(struct brcm_usb_init_params *params)
382{
383 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
384 u32 reg = 0;
385
386 pr_debug("%s\n", __func__);
387
388 reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
389 reg &= USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
390 return reg;
391}
392
393static void usb_set_dual_select(struct brcm_usb_init_params *params)
394{
395 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
396 u32 reg;
397
398 pr_debug("%s\n", __func__);
399
400 reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
401 reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
402 reg |= params->port_mode;
403 brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
404}
405
406static const struct brcm_usb_init_ops bcm7216_ops = {
407 .init_ipp = usb_init_ipp,
408 .init_common = usb_init_common_7216,
409 .init_xhci = usb_init_xhci,
410 .uninit_common = usb_uninit_common_7216,
411 .uninit_xhci = usb_uninit_xhci,
412 .get_dual_select = usb_get_dual_select,
413 .set_dual_select = usb_set_dual_select,
414};
415
416static const struct brcm_usb_init_ops bcm7211b0_ops = {
417 .init_ipp = usb_init_ipp,
418 .init_common = usb_init_common_7211b0,
419 .init_xhci = usb_init_xhci,
420 .uninit_common = usb_uninit_common_7211b0,
421 .uninit_xhci = usb_uninit_xhci,
422 .get_dual_select = usb_get_dual_select,
423 .set_dual_select = usb_set_dual_select,
424};
425
426void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params)
427{
428
429 pr_debug("%s\n", __func__);
430
431 params->family_name = "7216";
432 params->ops = &bcm7216_ops;
433}
434
435void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params)
436{
437
438 pr_debug("%s\n", __func__);
439
440 params->family_name = "7211";
441 params->ops = &bcm7211b0_ops;
442}