Răsfoiți Sursa

bcm53xx: improve USB 2.0 PHY support for BCM4709 and BCM47094

Signed-off-by: Rafał Miłecki <[email protected]>

SVN-Revision: 49094
Rafał Miłecki 9 ani în urmă
părinte
comite
e3e8a85c4f

+ 122 - 0
target/linux/bcm53xx/patches-4.4/811-USB-bcma-improve-USB-2.0-PHY-support-for-BCM4709-and.patch

@@ -0,0 +1,122 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
+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 <[email protected]>
+---
+--- 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);
+ 	}
+ }
+