aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bcma
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bcma')
-rw-r--r--drivers/bcma/driver_pci.c124
1 files changed, 70 insertions, 54 deletions
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c
index 4fde6254f04e..fc462b4a0990 100644
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright 2005, Broadcom Corporation 5 * Copyright 2005, Broadcom Corporation
6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch> 6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
7 * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
7 * 8 *
8 * Licensed under the GNU/GPL. See COPYING for details. 9 * Licensed under the GNU/GPL. See COPYING for details.
9 */ 10 */
@@ -18,38 +19,39 @@
18 19
19static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) 20static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
20{ 21{
21 pcicore_write32(pc, 0x130, address); 22 pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
22 pcicore_read32(pc, 0x130); 23 pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
23 return pcicore_read32(pc, 0x134); 24 return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA);
24} 25}
25 26
26#if 0 27#if 0
27static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) 28static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
28{ 29{
29 pcicore_write32(pc, 0x130, address); 30 pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
30 pcicore_read32(pc, 0x130); 31 pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
31 pcicore_write32(pc, 0x134, data); 32 pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
32} 33}
33#endif 34#endif
34 35
35static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) 36static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
36{ 37{
37 const u16 mdio_control = 0x128;
38 const u16 mdio_data = 0x12C;
39 u32 v; 38 u32 v;
40 int i; 39 int i;
41 40
42 v = (1 << 30); /* Start of Transaction */ 41 v = BCMA_CORE_PCI_MDIODATA_START;
43 v |= (1 << 28); /* Write Transaction */ 42 v |= BCMA_CORE_PCI_MDIODATA_WRITE;
44 v |= (1 << 17); /* Turnaround */ 43 v |= (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
45 v |= (0x1F << 18); 44 BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
45 v |= (BCMA_CORE_PCI_MDIODATA_BLK_ADDR <<
46 BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
47 v |= BCMA_CORE_PCI_MDIODATA_TA;
46 v |= (phy << 4); 48 v |= (phy << 4);
47 pcicore_write32(pc, mdio_data, v); 49 pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
48 50
49 udelay(10); 51 udelay(10);
50 for (i = 0; i < 200; i++) { 52 for (i = 0; i < 200; i++) {
51 v = pcicore_read32(pc, mdio_control); 53 v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
52 if (v & 0x100 /* Trans complete */) 54 if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
53 break; 55 break;
54 msleep(1); 56 msleep(1);
55 } 57 }
@@ -57,79 +59,84 @@ static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
57 59
58static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) 60static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
59{ 61{
60 const u16 mdio_control = 0x128;
61 const u16 mdio_data = 0x12C;
62 int max_retries = 10; 62 int max_retries = 10;
63 u16 ret = 0; 63 u16 ret = 0;
64 u32 v; 64 u32 v;
65 int i; 65 int i;
66 66
67 v = 0x80; /* Enable Preamble Sequence */ 67 /* enable mdio access to SERDES */
68 v |= 0x2; /* MDIO Clock Divisor */ 68 v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN;
69 pcicore_write32(pc, mdio_control, v); 69 v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL;
70 pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v);
70 71
71 if (pc->core->id.rev >= 10) { 72 if (pc->core->id.rev >= 10) {
72 max_retries = 200; 73 max_retries = 200;
73 bcma_pcie_mdio_set_phy(pc, device); 74 bcma_pcie_mdio_set_phy(pc, device);
75 v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
76 BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
77 v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
78 } else {
79 v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD);
80 v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
74 } 81 }
75 82
76 v = (1 << 30); /* Start of Transaction */ 83 v = BCMA_CORE_PCI_MDIODATA_START;
77 v |= (1 << 29); /* Read Transaction */ 84 v |= BCMA_CORE_PCI_MDIODATA_READ;
78 v |= (1 << 17); /* Turnaround */ 85 v |= BCMA_CORE_PCI_MDIODATA_TA;
79 if (pc->core->id.rev < 10) 86
80 v |= (u32)device << 22; 87 pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
81 v |= (u32)address << 18;
82 pcicore_write32(pc, mdio_data, v);
83 /* Wait for the device to complete the transaction */ 88 /* Wait for the device to complete the transaction */
84 udelay(10); 89 udelay(10);
85 for (i = 0; i < max_retries; i++) { 90 for (i = 0; i < max_retries; i++) {
86 v = pcicore_read32(pc, mdio_control); 91 v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
87 if (v & 0x100 /* Trans complete */) { 92 if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) {
88 udelay(10); 93 udelay(10);
89 ret = pcicore_read32(pc, mdio_data); 94 ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA);
90 break; 95 break;
91 } 96 }
92 msleep(1); 97 msleep(1);
93 } 98 }
94 pcicore_write32(pc, mdio_control, 0); 99 pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
95 return ret; 100 return ret;
96} 101}
97 102
98static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, 103static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
99 u8 address, u16 data) 104 u8 address, u16 data)
100{ 105{
101 const u16 mdio_control = 0x128;
102 const u16 mdio_data = 0x12C;
103 int max_retries = 10; 106 int max_retries = 10;
104 u32 v; 107 u32 v;
105 int i; 108 int i;
106 109
107 v = 0x80; /* Enable Preamble Sequence */ 110 /* enable mdio access to SERDES */
108 v |= 0x2; /* MDIO Clock Divisor */ 111 v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN;
109 pcicore_write32(pc, mdio_control, v); 112 v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL;
113 pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v);
110 114
111 if (pc->core->id.rev >= 10) { 115 if (pc->core->id.rev >= 10) {
112 max_retries = 200; 116 max_retries = 200;
113 bcma_pcie_mdio_set_phy(pc, device); 117 bcma_pcie_mdio_set_phy(pc, device);
118 v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
119 BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
120 v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
121 } else {
122 v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD);
123 v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
114 } 124 }
115 125
116 v = (1 << 30); /* Start of Transaction */ 126 v = BCMA_CORE_PCI_MDIODATA_START;
117 v |= (1 << 28); /* Write Transaction */ 127 v |= BCMA_CORE_PCI_MDIODATA_WRITE;
118 v |= (1 << 17); /* Turnaround */ 128 v |= BCMA_CORE_PCI_MDIODATA_TA;
119 if (pc->core->id.rev < 10)
120 v |= (u32)device << 22;
121 v |= (u32)address << 18;
122 v |= data; 129 v |= data;
123 pcicore_write32(pc, mdio_data, v); 130 pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
124 /* Wait for the device to complete the transaction */ 131 /* Wait for the device to complete the transaction */
125 udelay(10); 132 udelay(10);
126 for (i = 0; i < max_retries; i++) { 133 for (i = 0; i < max_retries; i++) {
127 v = pcicore_read32(pc, mdio_control); 134 v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
128 if (v & 0x100 /* Trans complete */) 135 if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
129 break; 136 break;
130 msleep(1); 137 msleep(1);
131 } 138 }
132 pcicore_write32(pc, mdio_control, 0); 139 pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
133} 140}
134 141
135/************************************************** 142/**************************************************
@@ -138,20 +145,29 @@ static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
138 145
139static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc) 146static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
140{ 147{
141 return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; 148 u32 tmp;
149
150 tmp = bcma_pcie_read(pc, BCMA_CORE_PCI_PLP_STATUSREG);
151 if (tmp & BCMA_CORE_PCI_PLP_POLARITYINV_STAT)
152 return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE |
153 BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY;
154 else
155 return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE;
142} 156}
143 157
144static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) 158static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
145{ 159{
146 const u8 serdes_pll_device = 0x1D;
147 const u8 serdes_rx_device = 0x1F;
148 u16 tmp; 160 u16 tmp;
149 161
150 bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, 162 bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_RX,
151 bcma_pcicore_polarity_workaround(pc)); 163 BCMA_CORE_PCI_SERDES_RX_CTRL,
152 tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); 164 bcma_pcicore_polarity_workaround(pc));
153 if (tmp & 0x4000) 165 tmp = bcma_pcie_mdio_read(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
154 bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); 166 BCMA_CORE_PCI_SERDES_PLL_CTRL);
167 if (tmp & BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN)
168 bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
169 BCMA_CORE_PCI_SERDES_PLL_CTRL,
170 tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN);
155} 171}
156 172
157/************************************************** 173/**************************************************