bcm53xx: support USB 2.0 controller on BCM53573

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
This commit is contained in:
Rafał Miłecki 2016-08-14 13:05:02 +02:00
parent 62c5f68095
commit 5b1c00e4fa
3 changed files with 171 additions and 9 deletions

View file

@ -0,0 +1,162 @@
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 */

View file

@ -22,7 +22,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
MODULE_AUTHOR("Hauke Mehrtens");
MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
@@ -39,6 +40,7 @@ struct bcma_hcd_device {
@@ -42,6 +43,7 @@ struct bcma_hcd_device {
struct bcma_device *core;
struct platform_device *ehci_dev;
struct platform_device *ohci_dev;
@ -30,7 +30,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
struct gpio_desc *gpio_desc;
};
@@ -246,6 +248,10 @@ static const struct usb_ehci_pdata ehci_
@@ -319,6 +321,10 @@ static const struct usb_ehci_pdata ehci_
static const struct usb_ohci_pdata ohci_pdata = {
};
@ -41,7 +41,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev,
const char *name, u32 addr,
const void *data,
@@ -339,6 +345,150 @@ err_unregister_ohci_dev:
@@ -412,6 +418,150 @@ err_unregister_ohci_dev:
return err;
}
@ -192,7 +192,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
static int bcma_hcd_usb30_init(struct bcma_hcd_device *bcma_hcd)
{
struct bcma_device *core = bcma_hcd->core;
@@ -346,6 +496,14 @@ static int bcma_hcd_usb30_init(struct bc
@@ -419,6 +569,14 @@ static int bcma_hcd_usb30_init(struct bc
bcma_core_enable(core, 0);
@ -207,7 +207,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
of_platform_default_populate(dev->of_node, NULL, dev);
return 0;
@@ -393,11 +551,14 @@ static void bcma_hcd_remove(struct bcma_
@@ -471,11 +629,14 @@ static void bcma_hcd_remove(struct bcma_
struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
struct platform_device *ohci_dev = usb_dev->ohci_dev;
struct platform_device *ehci_dev = usb_dev->ehci_dev;

View file

@ -27,8 +27,8 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
MODULE_AUTHOR("Hauke Mehrtens");
MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
MODULE_LICENSE("GPL");
@@ -168,10 +179,35 @@ static void bcma_hcd_init_chip_mips(stru
}
@@ -241,10 +252,35 @@ static int bcma_hcd_usb20_old_arm_init(s
return 0;
}
+static u32 bcma_hcd_usb_ref_clk_get_rate(void __iomem *dmu)
@ -63,7 +63,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9);
if (!arm_core) {
@@ -185,14 +221,29 @@ static void bcma_hcd_init_chip_arm_phy(s
@@ -258,14 +294,29 @@ static void bcma_hcd_init_chip_arm_phy(s
return;
}
@ -96,7 +96,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
iounmap(dmu);
}
@@ -220,15 +271,17 @@ static void bcma_hcd_init_chip_arm_hc(st
@@ -293,15 +344,17 @@ static void bcma_hcd_init_chip_arm_hc(st
static void bcma_hcd_init_chip_arm(struct bcma_device *dev)
{