bcm53xx: improve USB 2.0 PHY support for BCM4709 and BCM47094
[openwrt/svn-archive/archive.git] / target / linux / bcm53xx / patches-4.4 / 811-USB-bcma-improve-USB-2.0-PHY-support-for-BCM4709-and.patch
1 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
2 Subject: [PATCH] USB: bcma: improve USB 2.0 PHY support for BCM4709 and
3 BCM47094
4 MIME-Version: 1.0
5 Content-Type: text/plain; charset=UTF-8
6 Content-Transfer-Encoding: 8bit
7
8 Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
9 ---
10 --- a/drivers/usb/host/bcma-hcd.c
11 +++ b/drivers/usb/host/bcma-hcd.c
12 @@ -31,6 +31,17 @@
13 #include <linux/usb/ohci_pdriver.h>
14 #include <linux/usb/xhci_pdriver.h>
15
16 +/* DMU (Device Management Unit) */
17 +#define BCMA_DMU_CRU_USB2_CONTROL 0x0164
18 +#define BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK 0x00000FFC
19 +#define BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT 2
20 +#define BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK 0x00007000
21 +#define BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_SHIFT 12
22 +#define BCMA_DMU_CRU_CLKSET_KEY 0x0180
23 +#define BCMA_DMU_CRU_STRAPS_CTRL 0x02A0
24 +#define BCMA_DMU_CRU_STRAPS_CTRL_USB3 0x00000010
25 +#define BCMA_DMU_CRU_STRAPS_CTRL_4BYTE 0x00008000
26 +
27 MODULE_AUTHOR("Hauke Mehrtens");
28 MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
29 MODULE_LICENSE("GPL");
30 @@ -167,10 +178,35 @@ static void bcma_hcd_init_chip_mips(struct bcma_device *dev)
31 }
32 }
33
34 +static u32 bcma_hcd_usb_ref_clk_get_rate(void __iomem *dmu)
35 +{
36 + u32 val, ndiv, pdiv, ch2_mdiv, ch2_freq;
37 +
38 + /* get divider integer from the cru_genpll_control5 */
39 + val = ioread32(dmu + 0x154);
40 + ndiv = (val >> 20) & 0x3ff;
41 + if (ndiv == 0)
42 + ndiv = 1 << 10;
43 +
44 + /* get pdiv and ch2_mdiv from the cru_genpll_control6 */
45 + val = ioread32(dmu + 0x158);
46 + pdiv = (val >> 24) & 0x7;
47 + pdiv = (pdiv == 0) ? (1 << 3) : pdiv;
48 +
49 + ch2_mdiv = val & 0xff;
50 + ch2_mdiv = (ch2_mdiv == 0) ? (1 << 8) : ch2_mdiv;
51 +
52 + /* calculate ch2_freq based on 25MHz reference clock */
53 + ch2_freq = (25000000 / (pdiv * ch2_mdiv)) * ndiv;
54 +
55 + return ch2_freq;
56 +}
57 +
58 static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev)
59 {
60 struct bcma_device *arm_core;
61 void __iomem *dmu;
62 + u32 ref_clk_rate, usb2ctl, usb_pll_ndiv, usb_pll_pdiv;
63
64 arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9);
65 if (!arm_core) {
66 @@ -184,14 +220,29 @@ static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev)
67 return;
68 }
69
70 + ref_clk_rate = bcma_hcd_usb_ref_clk_get_rate(dmu);
71 +
72 + usb2ctl = ioread32(dmu + BCMA_DMU_CRU_USB2_CONTROL);
73 +
74 + usb_pll_pdiv = usb2ctl;
75 + usb_pll_pdiv &= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK;
76 + usb_pll_pdiv >>= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_SHIFT;
77 + if (!usb_pll_pdiv)
78 + usb_pll_pdiv = 1 << 3;
79 +
80 + /* Calculate ndiv based on a solid 1920 MHz that is for USB2 PHY */
81 + usb_pll_ndiv = (1920000000 * usb_pll_pdiv) / ref_clk_rate;
82 +
83 /* Unlock DMU PLL settings */
84 - iowrite32(0x0000ea68, dmu + 0x180);
85 + iowrite32(0x0000ea68, dmu + BCMA_DMU_CRU_CLKSET_KEY);
86
87 /* Write USB 2.0 PLL control setting */
88 - iowrite32(0x00dd10c3, dmu + 0x164);
89 + usb2ctl &= ~BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK;
90 + usb2ctl |= usb_pll_ndiv << BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT;
91 + iowrite32(usb2ctl, dmu + BCMA_DMU_CRU_USB2_CONTROL);
92
93 /* Lock DMU PLL settings */
94 - iowrite32(0x00000000, dmu + 0x180);
95 + iowrite32(0x00000000, dmu + BCMA_DMU_CRU_CLKSET_KEY);
96
97 iounmap(dmu);
98 }
99 @@ -219,15 +270,17 @@ static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev)
100
101 static void bcma_hcd_init_chip_arm(struct bcma_device *dev)
102 {
103 + struct bcma_chipinfo *chipinfo = &dev->bus->chipinfo;
104 +
105 bcma_core_enable(dev, 0);
106
107 - if (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4707 ||
108 - dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM53018) {
109 - if (dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4707 ||
110 - dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4708)
111 - bcma_hcd_init_chip_arm_phy(dev);
112 + if (chipinfo->id == BCMA_CHIP_ID_BCM4707 ||
113 + chipinfo->id == BCMA_CHIP_ID_BCM47094 ||
114 + chipinfo->id == BCMA_CHIP_ID_BCM53018) {
115 + bcma_hcd_init_chip_arm_phy(dev);
116
117 - bcma_hcd_init_chip_arm_hc(dev);
118 + if (1) /* TODO: Exclude BCM53573 */
119 + bcma_hcd_init_chip_arm_hc(dev);
120 }
121 }
122