openwrtv3/target/linux/bcm53xx/patches-4.3/197-USB-bcma-add-USB-3.0-support.patch
Hauke Mehrtens fa4395db04 bcm53xx: add support basic for kernel 4.3
The files directory is now split up into the files which are needed for
every kernel version and the files only needed by kernel 4.1. The files
in files-4.1 are already merged into mainline kernel 4.3. This patch
only removed patches which were merged into mainline kernel 4.3.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>

SVN-Revision: 47251
2015-10-25 16:43:14 +00:00

295 lines
8.9 KiB
Diff

From 121ec6539abedbc0e975cf35f48ee044b323e4c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
Date: Tue, 16 Jun 2015 17:14:26 +0200
Subject: [PATCH v3 5/6] usb: bcma: add USB 3.0 support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/usb/host/bcma-hcd.c | 225 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 225 insertions(+)
--- a/drivers/usb/host/bcma-hcd.c
+++ b/drivers/usb/host/bcma-hcd.c
@@ -28,6 +28,7 @@
#include <linux/of_gpio.h>
#include <linux/usb/ehci_pdriver.h>
#include <linux/usb/ohci_pdriver.h>
+#include <linux/usb/xhci_pdriver.h>
MODULE_AUTHOR("Hauke Mehrtens");
MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
@@ -37,6 +38,7 @@ struct bcma_hcd_device {
struct bcma_device *core;
struct platform_device *ehci_dev;
struct platform_device *ohci_dev;
+ struct platform_device *xhci_dev;
};
/* Wait for bitmask in a register to get set or cleared.
@@ -250,6 +252,10 @@ static const struct usb_ehci_pdata ehci_
static const struct usb_ohci_pdata ohci_pdata = {
};
+static const struct usb_xhci_pdata xhci_pdata = {
+ .usb3_fake_doorbell = 1
+};
+
static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev,
const char *name, u32 addr,
const void *data,
@@ -343,6 +349,216 @@ err_unregister_ohci_dev:
return err;
}
+static bool bcma_wait_reg(struct bcma_bus *bus, void __iomem *addr, u32 mask,
+ u32 value, int timeout)
+{
+ unsigned long deadline = jiffies + timeout;
+ u32 val;
+
+ do {
+ val = readl(addr);
+ if ((val & mask) == value)
+ return true;
+ cpu_relax();
+ udelay(10);
+ } while (!time_after_eq(jiffies, deadline));
+
+ pr_err("Timeout waiting for register %p\n", addr);
+
+ return false;
+}
+
+static void bcma_hcd_usb30_phy_init(struct bcma_hcd_device *bcma_hcd)
+{
+ struct bcma_device *core = bcma_hcd->core;
+ struct bcma_bus *bus = core->bus;
+ struct bcma_chipinfo *chipinfo = &bus->chipinfo;
+ struct bcma_drv_cc_b *ccb = &bus->drv_cc_b;
+ struct bcma_device *arm_core;
+ void __iomem *dmu = NULL;
+ u32 cru_straps_ctrl;
+
+ if (chipinfo->id != BCMA_CHIP_ID_BCM4707 &&
+ chipinfo->id != BCMA_CHIP_ID_BCM53018)
+ return;
+
+ arm_core = bcma_find_core(bus, BCMA_CORE_ARMCA9);
+ if (!arm_core)
+ return;
+
+ dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000);
+ if (!dmu)
+ goto out;
+
+ /* Check strapping of PCIE/USB3 SEL */
+ cru_straps_ctrl = ioread32(dmu + 0x2a0);
+ if ((cru_straps_ctrl & 0x10) == 0)
+ goto out;
+
+ /* Perform USB3 system soft reset */
+ bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
+
+ /* Enable MDIO. Setting MDCDIV as 26 */
+ iowrite32(0x0000009a, ccb->mii + 0x000);
+ udelay(2);
+
+ switch (chipinfo->id) {
+ case BCMA_CHIP_ID_BCM4707:
+ if (chipinfo->rev == 4) {
+ /* For NS-B0, USB3 PLL Block */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x587e8000, ccb->mii + 0x004);
+
+ /* Clear ana_pllSeqStart */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x58061000, ccb->mii + 0x004);
+
+ /* CMOS Divider ratio to 25 */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x582a6400, ccb->mii + 0x004);
+
+ /* Asserting PLL Reset */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x582ec000, ccb->mii + 0x004);
+
+ /* Deaaserting PLL Reset */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x582e8000, ccb->mii + 0x004);
+
+ /* Deasserting USB3 system reset */
+ bcma_awrite32(core, BCMA_RESET_CTL, 0);
+
+ /* Set ana_pllSeqStart */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x58069000, ccb->mii + 0x004);
+
+ /* RXPMD block */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x587e8020, ccb->mii + 0x004);
+
+ /* CDR int loop locking BW to 1 */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x58120049, ccb->mii + 0x004);
+
+ /* CDR int loop acquisition BW to 1 */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x580e0049, ccb->mii + 0x004);
+
+ /* CDR prop loop BW to 1 */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x580a005c, ccb->mii + 0x004);
+
+ /* Waiting MII Mgt interface idle */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ } else {
+ /* PLL30 block */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x587e8000, ccb->mii + 0x004);
+
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x582a6400, ccb->mii + 0x004);
+
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x587e80e0, ccb->mii + 0x004);
+
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x580a009c, ccb->mii + 0x004);
+
+ /* Enable SSC */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x587e8040, ccb->mii + 0x004);
+
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x580a21d3, ccb->mii + 0x004);
+
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x58061003, ccb->mii + 0x004);
+
+ /* Waiting MII Mgt interface idle */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+
+ /* Deasserting USB3 system reset */
+ bcma_awrite32(core, BCMA_RESET_CTL, 0);
+ }
+ break;
+ case BCMA_CHIP_ID_BCM53018:
+ /* USB3 PLL Block */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x587e8000, ccb->mii + 0x004);
+
+ /* Assert Ana_Pllseq start */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x58061000, ccb->mii + 0x004);
+
+ /* Assert CML Divider ratio to 26 */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x582a6400, ccb->mii + 0x004);
+
+ /* Asserting PLL Reset */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x582ec000, ccb->mii + 0x004);
+
+ /* Deaaserting PLL Reset */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x582e8000, ccb->mii + 0x004);
+
+ /* Waiting MII Mgt interface idle */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+
+ /* Deasserting USB3 system reset */
+ bcma_awrite32(core, BCMA_RESET_CTL, 0);
+
+ /* PLL frequency monitor enable */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x58069000, ccb->mii + 0x004);
+
+ /* PIPE Block */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x587e8060, ccb->mii + 0x004);
+
+ /* CMPMAX & CMPMINTH setting */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x580af30d, ccb->mii + 0x004);
+
+ /* DEGLITCH MIN & MAX setting */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x580e6302, ccb->mii + 0x004);
+
+ /* TXPMD block */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x587e8040, ccb->mii + 0x004);
+
+ /* Enabling SSC */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+ iowrite32(0x58061003, ccb->mii + 0x004);
+
+ /* Waiting MII Mgt interface idle */
+ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
+
+ break;
+ }
+out:
+ if (dmu)
+ iounmap(dmu);
+}
+
+static int bcma_hcd_usb30_init(struct bcma_hcd_device *bcma_hcd)
+{
+ struct bcma_device *core = bcma_hcd->core;
+
+ bcma_core_enable(core, 0);
+
+ bcma_hcd_usb30_phy_init(bcma_hcd);
+
+ bcma_hcd->xhci_dev = bcma_hcd_create_pdev(core, "xhci-hcd", core->addr,
+ &xhci_pdata,
+ sizeof(xhci_pdata));
+ if (IS_ERR(bcma_hcd->ohci_dev))
+ return PTR_ERR(bcma_hcd->ohci_dev);
+
+ return 0;
+}
+
static int bcma_hcd_probe(struct bcma_device *dev)
{
int err;
@@ -365,6 +581,11 @@ static int bcma_hcd_probe(struct bcma_de
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;
}
@@ -378,11 +599,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;
+ struct platform_device *xhci_dev = usb_dev->xhci_dev;
if (ohci_dev)
platform_device_unregister(ohci_dev);
if (ehci_dev)
platform_device_unregister(ehci_dev);
+ if (xhci_dev)
+ platform_device_unregister(xhci_dev);
bcma_core_disable(dev, 0);
}
@@ -419,6 +643,7 @@ static int bcma_hcd_resume(struct bcma_d
static const struct bcma_device_id bcma_hcd_table[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB30, BCMA_ANY_REV, BCMA_ANY_CLASS),
{},
};
MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);