bcm53xx: improve USB 2.0 PHY support for BCM4709 and BCM47094
authorRafał Miłecki <zajec5@gmail.com>
Wed, 30 Mar 2016 12:26:24 +0000 (12:26 +0000)
committerRafał Miłecki <zajec5@gmail.com>
Wed, 30 Mar 2016 12:26:24 +0000 (12:26 +0000)
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
SVN-Revision: 49094

target/linux/bcm53xx/patches-4.4/811-USB-bcma-improve-USB-2.0-PHY-support-for-BCM4709-and.patch [new file with mode: 0644]

diff --git a/target/linux/bcm53xx/patches-4.4/811-USB-bcma-improve-USB-2.0-PHY-support-for-BCM4709-and.patch b/target/linux/bcm53xx/patches-4.4/811-USB-bcma-improve-USB-2.0-PHY-support-for-BCM4709-and.patch
new file mode 100644 (file)
index 0000000..84a335b
--- /dev/null
@@ -0,0 +1,122 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Subject: [PATCH] USB: bcma: improve USB 2.0 PHY support for BCM4709 and
+ BCM47094
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -31,6 +31,17 @@
+ #include <linux/usb/ohci_pdriver.h>
+ #include <linux/usb/xhci_pdriver.h>
++/* DMU (Device Management Unit) */
++#define BCMA_DMU_CRU_USB2_CONTROL                     0x0164
++#define  BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK  0x00000FFC
++#define  BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT 2
++#define  BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK  0x00007000
++#define  BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_SHIFT 12
++#define BCMA_DMU_CRU_CLKSET_KEY                               0x0180
++#define BCMA_DMU_CRU_STRAPS_CTRL                      0x02A0
++#define  BCMA_DMU_CRU_STRAPS_CTRL_USB3                        0x00000010
++#define  BCMA_DMU_CRU_STRAPS_CTRL_4BYTE                       0x00008000
++
+ MODULE_AUTHOR("Hauke Mehrtens");
+ MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
+ MODULE_LICENSE("GPL");
+@@ -167,10 +178,35 @@ static void bcma_hcd_init_chip_mips(struct bcma_device *dev)
+       }
+ }
++static u32 bcma_hcd_usb_ref_clk_get_rate(void __iomem *dmu)
++{
++      u32 val, ndiv, pdiv, ch2_mdiv, ch2_freq;
++
++      /* get divider integer from the cru_genpll_control5 */
++      val = ioread32(dmu + 0x154);
++      ndiv = (val >> 20) & 0x3ff;
++      if (ndiv == 0)
++              ndiv = 1 << 10;
++
++      /* get pdiv and ch2_mdiv from the cru_genpll_control6 */
++      val = ioread32(dmu + 0x158);
++      pdiv = (val >> 24) & 0x7;
++      pdiv = (pdiv == 0) ? (1 << 3) : pdiv;
++
++      ch2_mdiv = val & 0xff;
++      ch2_mdiv = (ch2_mdiv == 0) ? (1 << 8) : ch2_mdiv;
++
++      /* calculate ch2_freq based on 25MHz reference clock */
++      ch2_freq = (25000000 / (pdiv * ch2_mdiv)) * ndiv;
++
++      return ch2_freq;
++}
++
+ static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev)
+ {
+       struct bcma_device *arm_core;
+       void __iomem *dmu;
++      u32 ref_clk_rate, usb2ctl, usb_pll_ndiv, usb_pll_pdiv;
+       arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9);
+       if (!arm_core) {
+@@ -184,14 +220,29 @@ static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev)
+               return;
+       }
++      ref_clk_rate = bcma_hcd_usb_ref_clk_get_rate(dmu);
++
++      usb2ctl = ioread32(dmu + BCMA_DMU_CRU_USB2_CONTROL);
++
++      usb_pll_pdiv = usb2ctl;
++      usb_pll_pdiv &= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK;
++      usb_pll_pdiv >>= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_SHIFT;
++      if (!usb_pll_pdiv)
++              usb_pll_pdiv = 1 << 3;
++
++      /* Calculate ndiv based on a solid 1920 MHz that is for USB2 PHY */
++      usb_pll_ndiv = (1920000000 * usb_pll_pdiv) / ref_clk_rate;
++
+       /* Unlock DMU PLL settings */
+-      iowrite32(0x0000ea68, dmu + 0x180);
++      iowrite32(0x0000ea68, dmu + BCMA_DMU_CRU_CLKSET_KEY);
+       /* Write USB 2.0 PLL control setting */
+-      iowrite32(0x00dd10c3, dmu + 0x164);
++      usb2ctl &= ~BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK;
++      usb2ctl |= usb_pll_ndiv << BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT;
++      iowrite32(usb2ctl, dmu + BCMA_DMU_CRU_USB2_CONTROL);
+       /* Lock DMU PLL settings */
+-      iowrite32(0x00000000, dmu + 0x180);
++      iowrite32(0x00000000, dmu + BCMA_DMU_CRU_CLKSET_KEY);
+       iounmap(dmu);
+ }
+@@ -219,15 +270,17 @@ static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev)
+ static void bcma_hcd_init_chip_arm(struct bcma_device *dev)
+ {
++      struct bcma_chipinfo *chipinfo = &dev->bus->chipinfo;
++
+       bcma_core_enable(dev, 0);
+-      if (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4707 ||
+-          dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM53018) {
+-              if (dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4707 ||
+-                  dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4708)
+-                      bcma_hcd_init_chip_arm_phy(dev);
++      if (chipinfo->id == BCMA_CHIP_ID_BCM4707 ||
++          chipinfo->id == BCMA_CHIP_ID_BCM47094 ||
++          chipinfo->id == BCMA_CHIP_ID_BCM53018) {
++              bcma_hcd_init_chip_arm_phy(dev);
+-              bcma_hcd_init_chip_arm_hc(dev);
++              if (1) /* TODO: Exclude BCM53573 */
++                      bcma_hcd_init_chip_arm_hc(dev);
+       }
+ }