2762785f79c13b7f7d012307d83d23d5b2ed5cf0
[openwrt/staging/aparcar.git] /
1 From d6b76c4ddb124dd22c6e910ca9332e472e7b3273 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
3 Date: Wed, 10 Aug 2016 11:56:46 +0200
4 Subject: [PATCH] USB: bcma: support old USB 2.0 controller on Northstar
5 devices
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 Currently bcma-hcd driver handles 3 different bcma cores:
11 1) BCMA_CORE_USB20_HOST (0x819)
12 2) BCMA_CORE_NS_USB20 (0x504)
13 3) BCMA_CORE_NS_USB30 (0x505)
14
15 The first one was introduced years ago and so far was used on MIPS
16 devices only. All Northstar (ARM) devices were using other two cores
17 which allowed easy implementation of separated initialization paths.
18
19 It seems however Broadcom decided to reuse this old USB 2.0 controller
20 on some recently introduced cheaper Northstar BCM53573 SoCs. I noticed
21 this on Tenda AC9 (based on BCM47189B0 belonging to BCM53573 family).
22
23 There is no difference in this old controller core identification
24 between MIPS and ARM devices: they share the same id and revision. We
25 need different controller initialization procedure however.
26 To handle this add a check for architecture and implement required
27 initialization for ARM case.
28
29 Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
30 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
31 ---
32 drivers/usb/host/bcma-hcd.c | 86 ++++++++++++++++++++++++++++++++++++++++--
33 include/linux/bcma/bcma_regs.h | 1 +
34 2 files changed, 83 insertions(+), 4 deletions(-)
35
36 --- a/drivers/usb/host/bcma-hcd.c
37 +++ b/drivers/usb/host/bcma-hcd.c
38 @@ -35,6 +35,9 @@ MODULE_AUTHOR("Hauke Mehrtens");
39 MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
40 MODULE_LICENSE("GPL");
41
42 +/* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */
43 +#define USB_BCMA_CLKCTLST_USB_CLK_REQ 0x00000100
44 +
45 struct bcma_hcd_device {
46 struct bcma_device *core;
47 struct platform_device *ehci_dev;
48 @@ -166,6 +169,76 @@ static void bcma_hcd_init_chip_mips(stru
49 }
50 }
51
52 +/**
53 + * bcma_hcd_usb20_old_arm_init - Initialize old USB 2.0 controller on ARM
54 + *
55 + * Old USB 2.0 core is identified as BCMA_CORE_USB20_HOST and was introduced
56 + * long before Northstar devices. It seems some cheaper chipsets like BCM53573
57 + * still use it.
58 + * Initialization of this old core differs between MIPS and ARM.
59 + */
60 +static int bcma_hcd_usb20_old_arm_init(struct bcma_hcd_device *usb_dev)
61 +{
62 + struct bcma_device *core = usb_dev->core;
63 + struct device *dev = &core->dev;
64 + struct bcma_device *pmu_core;
65 +
66 + usleep_range(10000, 20000);
67 + if (core->id.rev < 5)
68 + return 0;
69 +
70 + pmu_core = bcma_find_core(core->bus, BCMA_CORE_PMU);
71 + if (!pmu_core) {
72 + dev_err(dev, "Could not find PMU core\n");
73 + return -ENOENT;
74 + }
75 +
76 + /* Take USB core out of reset */
77 + bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK | BCMA_IOCTL_FGC);
78 + usleep_range(100, 200);
79 + bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
80 + usleep_range(100, 200);
81 + bcma_awrite32(core, BCMA_RESET_CTL, 0);
82 + usleep_range(100, 200);
83 + bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK);
84 + usleep_range(100, 200);
85 +
86 + /* Enable Misc PLL */
87 + bcma_write32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT |
88 + BCMA_CLKCTLST_HQCLKREQ |
89 + USB_BCMA_CLKCTLST_USB_CLK_REQ);
90 + usleep_range(100, 200);
91 +
92 + bcma_write32(core, 0x510, 0xc7f85000);
93 + bcma_write32(core, 0x510, 0xc7f85003);
94 + usleep_range(300, 600);
95 +
96 + /* Program USB PHY PLL parameters */
97 + bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x6);
98 + bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x005360c1);
99 + usleep_range(100, 200);
100 + bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x7);
101 + bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x0);
102 + usleep_range(100, 200);
103 + bcma_set32(pmu_core, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);
104 + usleep_range(100, 200);
105 +
106 + bcma_write32(core, 0x510, 0x7f8d007);
107 + udelay(1000);
108 +
109 + /* Take controller out of reset */
110 + bcma_write32(core, 0x200, 0x4ff);
111 + usleep_range(25, 50);
112 + bcma_write32(core, 0x200, 0x6ff);
113 + usleep_range(25, 50);
114 + bcma_write32(core, 0x200, 0x7ff);
115 + usleep_range(25, 50);
116 +
117 + of_platform_default_populate(dev->of_node, NULL, dev);
118 +
119 + return 0;
120 +}
121 +
122 static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev)
123 {
124 struct bcma_device *arm_core;
125 @@ -370,19 +443,24 @@ static int bcma_hcd_probe(struct bcma_de
126
127 switch (core->id.id) {
128 case BCMA_CORE_USB20_HOST:
129 + if (IS_ENABLED(CONFIG_ARM))
130 + err = bcma_hcd_usb20_old_arm_init(usb_dev);
131 + else if (IS_ENABLED(CONFIG_MIPS))
132 + err = bcma_hcd_usb20_init(usb_dev);
133 + else
134 + err = -ENOTSUPP;
135 + break;
136 case BCMA_CORE_NS_USB20:
137 err = bcma_hcd_usb20_init(usb_dev);
138 - if (err)
139 - return err;
140 break;
141 case BCMA_CORE_NS_USB30:
142 err = bcma_hcd_usb30_init(usb_dev);
143 - if (err)
144 - return err;
145 break;
146 default:
147 return -ENODEV;
148 }
149 + if (err)
150 + return err;
151
152 bcma_set_drvdata(core, usb_dev);
153 return 0;
154 --- a/include/linux/bcma/bcma_regs.h
155 +++ b/include/linux/bcma/bcma_regs.h
156 @@ -10,6 +10,7 @@
157 #define BCMA_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */
158 #define BCMA_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
159 #define BCMA_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
160 +#define BCMA_CLKCTLST_HQCLKREQ 0x00000040 /* HQ Clock */
161 #define BCMA_CLKCTLST_EXTRESREQ 0x00000700 /* Mask of external resource requests */
162 #define BCMA_CLKCTLST_EXTRESREQ_SHIFT 8
163 #define BCMA_CLKCTLST_HAVEALP 0x00010000 /* ALP available */