bcm53xx: use the latest XHCI doorbell patch sent for upstream
The main difference is it supports DT binding. This allows us to use DT for specifying controller and the new standalone USB 3.0 PHY driver. Thanks to that we don't need out of tree patch adding PHY initialization to the controller driver anymore.
This commit is contained in:
parent
28974de663
commit
ba1024b9c9
5 changed files with 158 additions and 371 deletions
|
@ -73,7 +73,7 @@ DEVICE_VARS += PRODUCTID SIGNATURE NETGEAR_BOARD_ID NETGEAR_REGION
|
||||||
BRCMFMAC_43602A1 := kmod-brcmfmac brcmfmac-firmware-43602a1-pcie
|
BRCMFMAC_43602A1 := kmod-brcmfmac brcmfmac-firmware-43602a1-pcie
|
||||||
BRCMFMAC_4366B1 := kmod-brcmfmac brcmfmac-firmware-4366b1-pcie
|
BRCMFMAC_4366B1 := kmod-brcmfmac brcmfmac-firmware-4366b1-pcie
|
||||||
USB2_PACKAGES := kmod-usb-ohci kmod-usb2 kmod-phy-bcm-ns-usb2
|
USB2_PACKAGES := kmod-usb-ohci kmod-usb2 kmod-phy-bcm-ns-usb2
|
||||||
USB3_PACKAGES := kmod-usb-ohci kmod-usb2 kmod-usb3 kmod-phy-bcm-ns-usb2
|
USB3_PACKAGES := $(USB2_PACKAGES) kmod-usb3 kmod-phy-bcm-ns-usb3
|
||||||
|
|
||||||
define Device/Default
|
define Device/Default
|
||||||
# .dtb files are prefixed by SoC type, e.g. bcm4708- which is not included in device/image names
|
# .dtb files are prefixed by SoC type, e.g. bcm4708- which is not included in device/image names
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
From 37df205cdb69d17d5e815385fc1af3c97d1fe20b Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||||
|
Date: Sat, 1 Oct 2016 22:54:48 +0200
|
||||||
|
Subject: [PATCH] usb: xhci: add support for performing fake doorbell
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Broadcom's Northstar XHCI controllers seem to need a special start
|
||||||
|
procedure to work correctly. There isn't any official documentation on
|
||||||
|
this, the problem is that controller doesn't detect any connected
|
||||||
|
devices with default setup. Moreover connecting USB device to controller
|
||||||
|
that doesn't run properly can cause SoC's watchdog issues.
|
||||||
|
|
||||||
|
A workaround that was successfully tested on multiple devices is to
|
||||||
|
perform a fake doorbell. This patch adds code for doing that and a DT
|
||||||
|
binding enabling it.
|
||||||
|
|
||||||
|
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||||
|
---
|
||||||
|
Documentation/devicetree/bindings/usb/usb-xhci.txt | 2 +
|
||||||
|
drivers/usb/host/xhci-plat.c | 6 +++
|
||||||
|
drivers/usb/host/xhci.c | 63 ++++++++++++++++++++--
|
||||||
|
drivers/usb/host/xhci.h | 1 +
|
||||||
|
4 files changed, 69 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
|
||||||
|
@@ -12,6 +12,8 @@ Required properties:
|
||||||
|
Optional properties:
|
||||||
|
- clocks: reference to a clock
|
||||||
|
- usb3-lpm-capable: determines if platform is USB3 LPM capable
|
||||||
|
+ - usb3-fake-doorbell: determines if controller requires a fake doorbell when
|
||||||
|
+ starting it
|
||||||
|
|
||||||
|
Example:
|
||||||
|
usb@f0931000 {
|
||||||
|
--- a/drivers/usb/host/xhci-plat.c
|
||||||
|
+++ b/drivers/usb/host/xhci-plat.c
|
||||||
|
@@ -38,12 +38,18 @@ static const struct xhci_driver_override
|
||||||
|
|
||||||
|
static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
|
||||||
|
{
|
||||||
|
+ struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
+ struct device_node *node = pdev->dev.of_node;
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* As of now platform drivers don't provide MSI support so we ensure
|
||||||
|
* here that the generic code does not try to make a pci_dev from our
|
||||||
|
* dev struct in order to setup MSI
|
||||||
|
*/
|
||||||
|
xhci->quirks |= XHCI_PLAT;
|
||||||
|
+
|
||||||
|
+ if (node && of_property_read_bool(node, "usb3-fake-doorbell"))
|
||||||
|
+ xhci->quirks |= XHCI_FAKE_DOORBELL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* called during probe() after chip reset completes */
|
||||||
|
--- a/drivers/usb/host/xhci.c
|
||||||
|
+++ b/drivers/usb/host/xhci.c
|
||||||
|
@@ -152,6 +152,49 @@ static int xhci_start(struct xhci_hcd *x
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * xhci_fake_doorbell - Perform a fake doorbell on a specified slot
|
||||||
|
+ *
|
||||||
|
+ * Some controllers require a fake doorbell to start correctly. Without that
|
||||||
|
+ * they simply don't detect any devices.
|
||||||
|
+ */
|
||||||
|
+static int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id)
|
||||||
|
+{
|
||||||
|
+ u32 temp;
|
||||||
|
+
|
||||||
|
+ /* Alloc a virt device for that slot */
|
||||||
|
+ if (!xhci_alloc_virt_device(xhci, slot_id, NULL, GFP_NOIO)) {
|
||||||
|
+ xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Ring fake doorbell for slot_id ep 0 */
|
||||||
|
+ xhci_ring_ep_doorbell(xhci, slot_id, 0, 0);
|
||||||
|
+ usleep_range(1000, 1500);
|
||||||
|
+
|
||||||
|
+ /* Read the status to check if HSE is set or not */
|
||||||
|
+ temp = readl(&xhci->op_regs->status);
|
||||||
|
+
|
||||||
|
+ /* Clear HSE if set */
|
||||||
|
+ if (temp & STS_FATAL) {
|
||||||
|
+ xhci_dbg(xhci, "HSE problem detected, status: 0x%08x\n", temp);
|
||||||
|
+ temp &= ~0x1fff;
|
||||||
|
+ temp |= STS_FATAL;
|
||||||
|
+ writel(temp, &xhci->op_regs->status);
|
||||||
|
+ usleep_range(1000, 1500);
|
||||||
|
+ readl(&xhci->op_regs->status);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Free virt device */
|
||||||
|
+ xhci_free_virt_device(xhci, slot_id);
|
||||||
|
+
|
||||||
|
+ /* We're done if controller is already running */
|
||||||
|
+ if (readl(&xhci->op_regs->command) & CMD_RUN)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ return xhci_start(xhci);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Reset a halted HC.
|
||||||
|
*
|
||||||
|
@@ -568,10 +611,20 @@ int xhci_init(struct usb_hcd *hcd)
|
||||||
|
|
||||||
|
static int xhci_run_finished(struct xhci_hcd *xhci)
|
||||||
|
{
|
||||||
|
- if (xhci_start(xhci)) {
|
||||||
|
- xhci_halt(xhci);
|
||||||
|
- return -ENODEV;
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ err = xhci_start(xhci);
|
||||||
|
+ if (err) {
|
||||||
|
+ err = -ENODEV;
|
||||||
|
+ goto err_halt;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (xhci->quirks & XHCI_FAKE_DOORBELL) {
|
||||||
|
+ err = xhci_fake_doorbell(xhci, 1);
|
||||||
|
+ if (err)
|
||||||
|
+ goto err_halt;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
xhci->shared_hcd->state = HC_STATE_RUNNING;
|
||||||
|
xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
|
||||||
|
|
||||||
|
@@ -581,6 +634,10 @@ static int xhci_run_finished(struct xhci
|
||||||
|
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
|
||||||
|
"Finished xhci_run for USB3 roothub");
|
||||||
|
return 0;
|
||||||
|
+
|
||||||
|
+err_halt:
|
||||||
|
+ xhci_halt(xhci);
|
||||||
|
+ return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
--- a/drivers/usb/host/xhci.h
|
||||||
|
+++ b/drivers/usb/host/xhci.h
|
||||||
|
@@ -1631,6 +1631,7 @@ struct xhci_hcd {
|
||||||
|
/* For controllers with a broken beyond repair streams implementation */
|
||||||
|
#define XHCI_BROKEN_STREAMS (1 << 19)
|
||||||
|
#define XHCI_PME_STUCK_QUIRK (1 << 20)
|
||||||
|
+#define XHCI_FAKE_DOORBELL (1 << 24)
|
||||||
|
unsigned int num_active_eps;
|
||||||
|
unsigned int limit_active_eps;
|
||||||
|
/* There are two roothubs to keep track of bus suspend info for */
|
|
@ -1,145 +0,0 @@
|
||||||
From dd0e5f9a6a4aed849bdb80641c2a2350476cede7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
|
||||||
Date: Sun, 21 Jun 2015 11:10:49 +0200
|
|
||||||
Subject: [PATCH v3 2/6] usb: xhci: add Broadcom specific fake doorbell
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
This fixes problem with controller seeing devices only in some small
|
|
||||||
percentage of cold boots.
|
|
||||||
This quirk is also added to the platform data so we can activate it
|
|
||||||
when we register our platform driver.
|
|
||||||
|
|
||||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|
||||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|
||||||
---
|
|
||||||
drivers/usb/host/xhci-plat.c | 3 +++
|
|
||||||
drivers/usb/host/xhci.c | 57 +++++++++++++++++++++++++++++++++++++---
|
|
||||||
drivers/usb/host/xhci.h | 1 +
|
|
||||||
include/linux/usb/xhci_pdriver.h | 1 +
|
|
||||||
4 files changed, 59 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/usb/host/xhci-plat.c
|
|
||||||
+++ b/drivers/usb/host/xhci-plat.c
|
|
||||||
@@ -38,12 +38,19 @@ static const struct xhci_driver_override
|
|
||||||
|
|
||||||
static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
|
|
||||||
{
|
|
||||||
+ struct platform_device *pdev = to_platform_device(dev);
|
|
||||||
+ struct device_node *node = pdev->dev.of_node;
|
|
||||||
+ struct usb_xhci_pdata *pdata = dev_get_platdata(&pdev->dev);
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* As of now platform drivers don't provide MSI support so we ensure
|
|
||||||
* here that the generic code does not try to make a pci_dev from our
|
|
||||||
* dev struct in order to setup MSI
|
|
||||||
*/
|
|
||||||
xhci->quirks |= XHCI_PLAT;
|
|
||||||
+
|
|
||||||
+ if (pdata && pdata->usb3_fake_doorbell)
|
|
||||||
+ xhci->quirks |= XHCI_FAKE_DOORBELL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* called during probe() after chip reset completes */
|
|
||||||
--- a/drivers/usb/host/xhci.c
|
|
||||||
+++ b/drivers/usb/host/xhci.c
|
|
||||||
@@ -121,6 +121,39 @@ int xhci_halt(struct xhci_hcd *xhci)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id)
|
|
||||||
+{
|
|
||||||
+ u32 temp;
|
|
||||||
+
|
|
||||||
+ /* alloc a virt device for slot */
|
|
||||||
+ if (!xhci_alloc_virt_device(xhci, slot_id, NULL, GFP_NOIO)) {
|
|
||||||
+ xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* ring fake doorbell for slot_id ep 0 */
|
|
||||||
+ xhci_ring_ep_doorbell(xhci, slot_id, 0, 0);
|
|
||||||
+ usleep_range(1000, 1500);
|
|
||||||
+
|
|
||||||
+ /* read the status register to check if HSE is set or not? */
|
|
||||||
+ temp = readl(&xhci->op_regs->status);
|
|
||||||
+
|
|
||||||
+ /* clear HSE if set */
|
|
||||||
+ if (temp & STS_FATAL) {
|
|
||||||
+ xhci_dbg(xhci, "HSE problem detected, status: 0x%x\n", temp);
|
|
||||||
+ temp &= ~(0x1fff);
|
|
||||||
+ temp |= STS_FATAL;
|
|
||||||
+ writel(temp, &xhci->op_regs->status);
|
|
||||||
+ usleep_range(1000, 1500);
|
|
||||||
+ readl(&xhci->op_regs->status);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Free virt device */
|
|
||||||
+ xhci_free_virt_device(xhci, slot_id);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Set the run bit and wait for the host to be running.
|
|
||||||
*/
|
|
||||||
@@ -568,10 +601,25 @@ int xhci_init(struct usb_hcd *hcd)
|
|
||||||
|
|
||||||
static int xhci_run_finished(struct xhci_hcd *xhci)
|
|
||||||
{
|
|
||||||
- if (xhci_start(xhci)) {
|
|
||||||
- xhci_halt(xhci);
|
|
||||||
- return -ENODEV;
|
|
||||||
+ int err;
|
|
||||||
+
|
|
||||||
+ err = xhci_start(xhci);
|
|
||||||
+ if (err) {
|
|
||||||
+ err = -ENODEV;
|
|
||||||
+ goto out_err;
|
|
||||||
+ }
|
|
||||||
+ if (xhci->quirks & XHCI_FAKE_DOORBELL) {
|
|
||||||
+ err = xhci_fake_doorbell(xhci, 1);
|
|
||||||
+ if (err)
|
|
||||||
+ goto out_err;
|
|
||||||
+
|
|
||||||
+ err = xhci_start(xhci);
|
|
||||||
+ if (err) {
|
|
||||||
+ err = -ENODEV;
|
|
||||||
+ goto out_err;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
+
|
|
||||||
xhci->shared_hcd->state = HC_STATE_RUNNING;
|
|
||||||
xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
|
|
||||||
|
|
||||||
@@ -581,6 +629,9 @@ static int xhci_run_finished(struct xhci
|
|
||||||
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
|
|
||||||
"Finished xhci_run for USB3 roothub");
|
|
||||||
return 0;
|
|
||||||
+out_err:
|
|
||||||
+ xhci_halt(xhci);
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
--- a/drivers/usb/host/xhci.h
|
|
||||||
+++ b/drivers/usb/host/xhci.h
|
|
||||||
@@ -1631,6 +1631,7 @@ struct xhci_hcd {
|
|
||||||
/* For controllers with a broken beyond repair streams implementation */
|
|
||||||
#define XHCI_BROKEN_STREAMS (1 << 19)
|
|
||||||
#define XHCI_PME_STUCK_QUIRK (1 << 20)
|
|
||||||
+#define XHCI_FAKE_DOORBELL (1 << 21)
|
|
||||||
unsigned int num_active_eps;
|
|
||||||
unsigned int limit_active_eps;
|
|
||||||
/* There are two roothubs to keep track of bus suspend info for */
|
|
||||||
--- a/include/linux/usb/xhci_pdriver.h
|
|
||||||
+++ b/include/linux/usb/xhci_pdriver.h
|
|
||||||
@@ -22,6 +22,7 @@
|
|
||||||
*/
|
|
||||||
struct usb_xhci_pdata {
|
|
||||||
unsigned usb3_lpm_capable:1;
|
|
||||||
+ unsigned usb3_fake_doorbell:1;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __USB_CORE_XHCI_PDRIVER_H */
|
|
|
@ -1,224 +0,0 @@
|
||||||
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
|
|
||||||
@@ -30,6 +30,7 @@
|
|
||||||
#include <linux/of_platform.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");
|
|
||||||
@@ -42,6 +43,7 @@ struct bcma_hcd_device {
|
|
||||||
struct bcma_device *core;
|
|
||||||
struct platform_device *ehci_dev;
|
|
||||||
struct platform_device *ohci_dev;
|
|
||||||
+ struct platform_device *xhci_dev;
|
|
||||||
struct gpio_desc *gpio_desc;
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -298,6 +300,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,
|
|
||||||
@@ -382,6 +388,150 @@ 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_BCM47094 &&
|
|
||||||
+ 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);
|
|
||||||
+
|
|
||||||
+ if (chipinfo->id == BCMA_CHIP_ID_BCM53018 ||
|
|
||||||
+ (chipinfo->id == BCMA_CHIP_ID_BCM4707 && (chipinfo->rev == 4 || chipinfo->rev == 6)) ||
|
|
||||||
+ chipinfo->id == BCMA_CHIP_ID_BCM47094) {
|
|
||||||
+ /* 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);
|
|
||||||
+
|
|
||||||
+ /* 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);
|
|
||||||
+ } else if (chipinfo->id == BCMA_CHIP_ID_BCM4707) {
|
|
||||||
+ /* 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);
|
|
||||||
+ }
|
|
||||||
+out:
|
|
||||||
+ if (dmu)
|
|
||||||
+ iounmap(dmu);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int bcma_hcd_usb30_init(struct bcma_hcd_device *bcma_hcd)
|
|
||||||
{
|
|
||||||
struct bcma_device *core = bcma_hcd->core;
|
|
||||||
@@ -389,7 +539,13 @@ static int bcma_hcd_usb30_init(struct bc
|
|
||||||
|
|
||||||
bcma_core_enable(core, 0);
|
|
||||||
|
|
||||||
- of_platform_default_populate(dev->of_node, NULL, dev);
|
|
||||||
+ 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;
|
|
||||||
}
|
|
||||||
@@ -441,11 +597,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);
|
|
||||||
}
|
|
|
@ -38,7 +38,7 @@ Subject: [PATCH] ARM: BCM5301X: Specify USB controllers in DT
|
||||||
};
|
};
|
||||||
|
|
||||||
usb3: usb3@23000 {
|
usb3: usb3@23000 {
|
||||||
@@ -257,6 +278,19 @@
|
@@ -257,6 +278,20 @@
|
||||||
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
@ -52,6 +52,7 @@ Subject: [PATCH] ARM: BCM5301X: Specify USB controllers in DT
|
||||||
+ compatible = "generic-xhci";
|
+ compatible = "generic-xhci";
|
||||||
+ reg = <0x00023000 0x1000>;
|
+ reg = <0x00023000 0x1000>;
|
||||||
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
|
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
+ usb3-fake-doorbell;
|
||||||
+ phys = <&usb3_phy>;
|
+ phys = <&usb3_phy>;
|
||||||
+ phy-names = "usb";
|
+ phy-names = "usb";
|
||||||
+ };
|
+ };
|
||||||
|
|
Loading…
Reference in a new issue