163 lines
5.2 KiB
Diff
163 lines
5.2 KiB
Diff
|
From ef54f033c53bf4518f6e16e7ed815acd855e03c5 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||
|
Date: Wed, 10 Aug 2016 11:51:16 +0200
|
||
|
Subject: [PATCH] USB: bcma: support old USB 2.0 controller on Northstar
|
||
|
devices
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
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>
|
||
|
---
|
||
|
drivers/usb/host/bcma-hcd.c | 86 ++++++++++++++++++++++++++++++++++++++++--
|
||
|
include/linux/bcma/bcma_regs.h | 1 +
|
||
|
2 files changed, 83 insertions(+), 4 deletions(-)
|
||
|
|
||
|
--- a/drivers/usb/host/bcma-hcd.c
|
||
|
+++ b/drivers/usb/host/bcma-hcd.c
|
||
|
@@ -35,6 +35,9 @@ MODULE_AUTHOR("Hauke Mehrtens");
|
||
|
MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
|
||
|
MODULE_LICENSE("GPL");
|
||
|
|
||
|
+/* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */
|
||
|
+#define USB_BCMA_CLKCTLST_USB_CLK_REQ 0x00000100
|
||
|
+
|
||
|
struct bcma_hcd_device {
|
||
|
struct bcma_device *core;
|
||
|
struct platform_device *ehci_dev;
|
||
|
@@ -166,6 +169,76 @@ static void bcma_hcd_init_chip_mips(stru
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+/**
|
||
|
+ * bcma_hcd_usb20_old_arm_init - Initialize old USB 2.0 controller on ARM
|
||
|
+ *
|
||
|
+ * Old USB 2.0 core is identified as BCMA_CORE_USB20_HOST and was introduced
|
||
|
+ * long before Northstar devices. It seems some cheaper chipsets like BCM53573
|
||
|
+ * still use it.
|
||
|
+ * Initialization of this old core differs between MIPS and ARM.
|
||
|
+ */
|
||
|
+static int bcma_hcd_usb20_old_arm_init(struct bcma_hcd_device *usb_dev)
|
||
|
+{
|
||
|
+ struct bcma_device *core = usb_dev->core;
|
||
|
+ struct device *dev = &core->dev;
|
||
|
+ struct bcma_device *pmu_core;
|
||
|
+
|
||
|
+ usleep_range(10000, 20000);
|
||
|
+ if (core->id.rev < 5)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ pmu_core = bcma_find_core(core->bus, BCMA_CORE_PMU);
|
||
|
+ if (!pmu_core) {
|
||
|
+ dev_err(dev, "Could not find PMU core\n");
|
||
|
+ return -ENOENT;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Take USB core out of reset */
|
||
|
+ bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK | BCMA_IOCTL_FGC);
|
||
|
+ usleep_range(100, 200);
|
||
|
+ bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
|
||
|
+ usleep_range(100, 200);
|
||
|
+ bcma_awrite32(core, BCMA_RESET_CTL, 0);
|
||
|
+ usleep_range(100, 200);
|
||
|
+ bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK);
|
||
|
+ usleep_range(100, 200);
|
||
|
+
|
||
|
+ /* Enable Misc PLL */
|
||
|
+ bcma_write32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT |
|
||
|
+ BCMA_CLKCTLST_HQCLKREQ |
|
||
|
+ USB_BCMA_CLKCTLST_USB_CLK_REQ);
|
||
|
+ usleep_range(100, 200);
|
||
|
+
|
||
|
+ bcma_write32(core, 0x510, 0xc7f85000);
|
||
|
+ bcma_write32(core, 0x510, 0xc7f85003);
|
||
|
+ usleep_range(300, 600);
|
||
|
+
|
||
|
+ /* Program USB PHY PLL parameters */
|
||
|
+ bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x6);
|
||
|
+ bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x005360c1);
|
||
|
+ usleep_range(100, 200);
|
||
|
+ bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x7);
|
||
|
+ bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x0);
|
||
|
+ usleep_range(100, 200);
|
||
|
+ bcma_set32(pmu_core, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);
|
||
|
+ usleep_range(100, 200);
|
||
|
+
|
||
|
+ bcma_write32(core, 0x510, 0x7f8d007);
|
||
|
+ udelay(1000);
|
||
|
+
|
||
|
+ /* Take controller out of reset */
|
||
|
+ bcma_write32(core, 0x200, 0x4ff);
|
||
|
+ usleep_range(25, 50);
|
||
|
+ bcma_write32(core, 0x200, 0x6ff);
|
||
|
+ usleep_range(25, 50);
|
||
|
+ bcma_write32(core, 0x200, 0x7ff);
|
||
|
+ usleep_range(25, 50);
|
||
|
+
|
||
|
+ of_platform_default_populate(dev->of_node, NULL, dev);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev)
|
||
|
{
|
||
|
struct bcma_device *arm_core;
|
||
|
@@ -370,19 +443,24 @@ static int bcma_hcd_probe(struct bcma_de
|
||
|
|
||
|
switch (core->id.id) {
|
||
|
case BCMA_CORE_USB20_HOST:
|
||
|
+ if (IS_ENABLED(CONFIG_ARM))
|
||
|
+ err = bcma_hcd_usb20_old_arm_init(usb_dev);
|
||
|
+ else if (IS_ENABLED(CONFIG_MIPS))
|
||
|
+ err = bcma_hcd_usb20_init(usb_dev);
|
||
|
+ else
|
||
|
+ err = -ENOTSUPP;
|
||
|
+ break;
|
||
|
case BCMA_CORE_NS_USB20:
|
||
|
err = bcma_hcd_usb20_init(usb_dev);
|
||
|
- if (err)
|
||
|
- return err;
|
||
|
break;
|
||
|
case BCMA_CORE_NS_USB30:
|
||
|
err = bcma_hcd_usb30_init(usb_dev);
|
||
|
- if (err)
|
||
|
- return err;
|
||
|
break;
|
||
|
default:
|
||
|
return -ENODEV;
|
||
|
}
|
||
|
+ if (err)
|
||
|
+ return err;
|
||
|
|
||
|
bcma_set_drvdata(core, usb_dev);
|
||
|
return 0;
|
||
|
--- a/include/linux/bcma/bcma_regs.h
|
||
|
+++ b/include/linux/bcma/bcma_regs.h
|
||
|
@@ -10,6 +10,7 @@
|
||
|
#define BCMA_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */
|
||
|
#define BCMA_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
|
||
|
#define BCMA_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
|
||
|
+#define BCMA_CLKCTLST_HQCLKREQ 0x00000040 /* HQ Clock */
|
||
|
#define BCMA_CLKCTLST_EXTRESREQ 0x00000700 /* Mask of external resource requests */
|
||
|
#define BCMA_CLKCTLST_EXTRESREQ_SHIFT 8
|
||
|
#define BCMA_CLKCTLST_HAVEALP 0x00010000 /* ALP available */
|