aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorRafał Miłecki <rafal@milecki.pl>2016-08-10 05:56:46 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-08-15 10:25:59 -0400
commitd6b76c4ddb124dd22c6e910ca9332e472e7b3273 (patch)
treeeb743699e2273c7277b796d15a293c8d0b203aeb /drivers/usb
parent6e958051cb0742dd54bb61528c130bd6eaecae0d (diff)
USB: bcma: support old USB 2.0 controller on Northstar devices
Currently bcma-hcd driver handles 3 different bcma cores: 1) BCMA_CORE_USB20_HOST (0x819) 2) BCMA_CORE_NS_USB20 (0x504) 3) BCMA_CORE_NS_USB30 (0x505) The first one was introduced years ago and so far was used on MIPS devices only. All Northstar (ARM) devices were using other two cores which allowed easy implementation of separated initialization paths. It seems however Broadcom decided to reuse this old USB 2.0 controller on some recently introduced cheaper Northstar BCM53573 SoCs. I noticed this on Tenda AC9 (based on BCM47189B0 belonging to BCM53573 family). There is no difference in this old controller core identification between MIPS and ARM devices: they share the same id and revision. We need different controller initialization procedure however. To handle this add a check for architecture and implement required initialization for ARM case. Signed-off-by: Rafał Miłecki <rafal@milecki.pl> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/bcma-hcd.c86
1 files changed, 82 insertions, 4 deletions
diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c
index 422fdc295b8d..e0761d92f2b6 100644
--- a/drivers/usb/host/bcma-hcd.c
+++ b/drivers/usb/host/bcma-hcd.c
@@ -35,6 +35,9 @@ MODULE_AUTHOR("Hauke Mehrtens");
35MODULE_DESCRIPTION("Common USB driver for BCMA Bus"); 35MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
36MODULE_LICENSE("GPL"); 36MODULE_LICENSE("GPL");
37 37
38/* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */
39#define USB_BCMA_CLKCTLST_USB_CLK_REQ 0x00000100
40
38struct bcma_hcd_device { 41struct bcma_hcd_device {
39 struct bcma_device *core; 42 struct bcma_device *core;
40 struct platform_device *ehci_dev; 43 struct platform_device *ehci_dev;
@@ -166,6 +169,76 @@ static void bcma_hcd_init_chip_mips(struct bcma_device *dev)
166 } 169 }
167} 170}
168 171
172/**
173 * bcma_hcd_usb20_old_arm_init - Initialize old USB 2.0 controller on ARM
174 *
175 * Old USB 2.0 core is identified as BCMA_CORE_USB20_HOST and was introduced
176 * long before Northstar devices. It seems some cheaper chipsets like BCM53573
177 * still use it.
178 * Initialization of this old core differs between MIPS and ARM.
179 */
180static int bcma_hcd_usb20_old_arm_init(struct bcma_hcd_device *usb_dev)
181{
182 struct bcma_device *core = usb_dev->core;
183 struct device *dev = &core->dev;
184 struct bcma_device *pmu_core;
185
186 usleep_range(10000, 20000);
187 if (core->id.rev < 5)
188 return 0;
189
190 pmu_core = bcma_find_core(core->bus, BCMA_CORE_PMU);
191 if (!pmu_core) {
192 dev_err(dev, "Could not find PMU core\n");
193 return -ENOENT;
194 }
195
196 /* Take USB core out of reset */
197 bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK | BCMA_IOCTL_FGC);
198 usleep_range(100, 200);
199 bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
200 usleep_range(100, 200);
201 bcma_awrite32(core, BCMA_RESET_CTL, 0);
202 usleep_range(100, 200);
203 bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK);
204 usleep_range(100, 200);
205
206 /* Enable Misc PLL */
207 bcma_write32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT |
208 BCMA_CLKCTLST_HQCLKREQ |
209 USB_BCMA_CLKCTLST_USB_CLK_REQ);
210 usleep_range(100, 200);
211
212 bcma_write32(core, 0x510, 0xc7f85000);
213 bcma_write32(core, 0x510, 0xc7f85003);
214 usleep_range(300, 600);
215
216 /* Program USB PHY PLL parameters */
217 bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x6);
218 bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x005360c1);
219 usleep_range(100, 200);
220 bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x7);
221 bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x0);
222 usleep_range(100, 200);
223 bcma_set32(pmu_core, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);
224 usleep_range(100, 200);
225
226 bcma_write32(core, 0x510, 0x7f8d007);
227 udelay(1000);
228
229 /* Take controller out of reset */
230 bcma_write32(core, 0x200, 0x4ff);
231 usleep_range(25, 50);
232 bcma_write32(core, 0x200, 0x6ff);
233 usleep_range(25, 50);
234 bcma_write32(core, 0x200, 0x7ff);
235 usleep_range(25, 50);
236
237 of_platform_default_populate(dev->of_node, NULL, dev);
238
239 return 0;
240}
241
169static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev) 242static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev)
170{ 243{
171 struct bcma_device *arm_core; 244 struct bcma_device *arm_core;
@@ -370,19 +443,24 @@ static int bcma_hcd_probe(struct bcma_device *core)
370 443
371 switch (core->id.id) { 444 switch (core->id.id) {
372 case BCMA_CORE_USB20_HOST: 445 case BCMA_CORE_USB20_HOST:
446 if (IS_ENABLED(CONFIG_ARM))
447 err = bcma_hcd_usb20_old_arm_init(usb_dev);
448 else if (IS_ENABLED(CONFIG_MIPS))
449 err = bcma_hcd_usb20_init(usb_dev);
450 else
451 err = -ENOTSUPP;
452 break;
373 case BCMA_CORE_NS_USB20: 453 case BCMA_CORE_NS_USB20:
374 err = bcma_hcd_usb20_init(usb_dev); 454 err = bcma_hcd_usb20_init(usb_dev);
375 if (err)
376 return err;
377 break; 455 break;
378 case BCMA_CORE_NS_USB30: 456 case BCMA_CORE_NS_USB30:
379 err = bcma_hcd_usb30_init(usb_dev); 457 err = bcma_hcd_usb30_init(usb_dev);
380 if (err)
381 return err;
382 break; 458 break;
383 default: 459 default:
384 return -ENODEV; 460 return -ENODEV;
385 } 461 }
462 if (err)
463 return err;
386 464
387 bcma_set_drvdata(core, usb_dev); 465 bcma_set_drvdata(core, usb_dev);
388 return 0; 466 return 0;