aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bcma
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bcma')
-rw-r--r--drivers/bcma/Kconfig13
-rw-r--r--drivers/bcma/Makefile2
-rw-r--r--drivers/bcma/bcma_private.h16
-rw-r--r--drivers/bcma/core.c3
-rw-r--r--drivers/bcma/driver_chipcommon.c54
-rw-r--r--drivers/bcma/driver_chipcommon_pmu.c192
-rw-r--r--drivers/bcma/driver_mips.c256
-rw-r--r--drivers/bcma/driver_pci.c17
-rw-r--r--drivers/bcma/host_pci.c1
-rw-r--r--drivers/bcma/host_soc.c183
-rw-r--r--drivers/bcma/main.c71
-rw-r--r--drivers/bcma/scan.c348
-rw-r--r--drivers/bcma/sprom.c15
13 files changed, 1047 insertions, 124 deletions
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index ae0a02e1b808..c1172dafdffa 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -33,6 +33,19 @@ config BCMA_DRIVER_PCI_HOSTMODE
33 help 33 help
34 PCI core hostmode operation (external PCI bus). 34 PCI core hostmode operation (external PCI bus).
35 35
36config BCMA_HOST_SOC
37 bool
38 depends on BCMA_DRIVER_MIPS
39
40config BCMA_DRIVER_MIPS
41 bool "BCMA Broadcom MIPS core driver"
42 depends on BCMA && MIPS
43 help
44 Driver for the Broadcom MIPS core attached to Broadcom specific
45 Advanced Microcontroller Bus.
46
47 If unsure, say N
48
36config BCMA_DEBUG 49config BCMA_DEBUG
37 bool "BCMA debugging" 50 bool "BCMA debugging"
38 depends on BCMA 51 depends on BCMA
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index a2161cceafb9..82de24e5340c 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -2,7 +2,9 @@ bcma-y += main.o scan.o core.o sprom.o
2bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o 2bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
3bcma-y += driver_pci.o 3bcma-y += driver_pci.o
4bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o 4bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
5bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
5bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o 6bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
7bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
6obj-$(CONFIG_BCMA) += bcma.o 8obj-$(CONFIG_BCMA) += bcma.o
7 9
8ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG 10ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index e02ff21835c9..30a3085d3354 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -15,13 +15,29 @@ struct bcma_bus;
15/* main.c */ 15/* main.c */
16int bcma_bus_register(struct bcma_bus *bus); 16int bcma_bus_register(struct bcma_bus *bus);
17void bcma_bus_unregister(struct bcma_bus *bus); 17void bcma_bus_unregister(struct bcma_bus *bus);
18int __init bcma_bus_early_register(struct bcma_bus *bus,
19 struct bcma_device *core_cc,
20 struct bcma_device *core_mips);
18 21
19/* scan.c */ 22/* scan.c */
20int bcma_bus_scan(struct bcma_bus *bus); 23int bcma_bus_scan(struct bcma_bus *bus);
24int __init bcma_bus_scan_early(struct bcma_bus *bus,
25 struct bcma_device_id *match,
26 struct bcma_device *core);
27void bcma_init_bus(struct bcma_bus *bus);
21 28
22/* sprom.c */ 29/* sprom.c */
23int bcma_sprom_get(struct bcma_bus *bus); 30int bcma_sprom_get(struct bcma_bus *bus);
24 31
32/* driver_chipcommon.c */
33#ifdef CONFIG_BCMA_DRIVER_MIPS
34void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
35#endif /* CONFIG_BCMA_DRIVER_MIPS */
36
37/* driver_chipcommon_pmu.c */
38u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
39u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
40
25#ifdef CONFIG_BCMA_HOST_PCI 41#ifdef CONFIG_BCMA_HOST_PCI
26/* host_pci.c */ 42/* host_pci.c */
27extern int __init bcma_host_pci_init(void); 43extern int __init bcma_host_pci_init(void);
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c
index 4a04a49cc06d..893f6e0c759f 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -6,6 +6,7 @@
6 */ 6 */
7 7
8#include "bcma_private.h" 8#include "bcma_private.h"
9#include <linux/export.h>
9#include <linux/bcma/bcma.h> 10#include <linux/bcma/bcma.h>
10 11
11bool bcma_core_is_enabled(struct bcma_device *core) 12bool bcma_core_is_enabled(struct bcma_device *core)
@@ -110,6 +111,8 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
110u32 bcma_core_dma_translation(struct bcma_device *core) 111u32 bcma_core_dma_translation(struct bcma_device *core)
111{ 112{
112 switch (core->bus->hosttype) { 113 switch (core->bus->hosttype) {
114 case BCMA_HOSTTYPE_SOC:
115 return 0;
113 case BCMA_HOSTTYPE_PCI: 116 case BCMA_HOSTTYPE_PCI:
114 if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64) 117 if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
115 return BCMA_DMA_TRANSLATION_DMA64_CMT; 118 return BCMA_DMA_TRANSLATION_DMA64_CMT;
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index 851e05bc948a..e9f1b3fd252c 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include "bcma_private.h" 11#include "bcma_private.h"
12#include <linux/export.h>
12#include <linux/bcma/bcma.h> 13#include <linux/bcma/bcma.h>
13 14
14static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, 15static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
@@ -26,6 +27,9 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
26 u32 leddc_on = 10; 27 u32 leddc_on = 10;
27 u32 leddc_off = 90; 28 u32 leddc_off = 90;
28 29
30 if (cc->setup_done)
31 return;
32
29 if (cc->core->id.rev >= 11) 33 if (cc->core->id.rev >= 11)
30 cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 34 cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
31 cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); 35 cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -52,6 +56,8 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
52 ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | 56 ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
53 (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT))); 57 (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
54 } 58 }
59
60 cc->setup_done = true;
55} 61}
56 62
57/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ 63/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
@@ -101,3 +107,51 @@ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
101{ 107{
102 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); 108 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
103} 109}
110
111#ifdef CONFIG_BCMA_DRIVER_MIPS
112void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
113{
114 unsigned int irq;
115 u32 baud_base;
116 u32 i;
117 unsigned int ccrev = cc->core->id.rev;
118 struct bcma_serial_port *ports = cc->serial_ports;
119
120 if (ccrev >= 11 && ccrev != 15) {
121 /* Fixed ALP clock */
122 baud_base = bcma_pmu_alp_clock(cc);
123 if (ccrev >= 21) {
124 /* Turn off UART clock before switching clocksource. */
125 bcma_cc_write32(cc, BCMA_CC_CORECTL,
126 bcma_cc_read32(cc, BCMA_CC_CORECTL)
127 & ~BCMA_CC_CORECTL_UARTCLKEN);
128 }
129 /* Set the override bit so we don't divide it */
130 bcma_cc_write32(cc, BCMA_CC_CORECTL,
131 bcma_cc_read32(cc, BCMA_CC_CORECTL)
132 | BCMA_CC_CORECTL_UARTCLK0);
133 if (ccrev >= 21) {
134 /* Re-enable the UART clock. */
135 bcma_cc_write32(cc, BCMA_CC_CORECTL,
136 bcma_cc_read32(cc, BCMA_CC_CORECTL)
137 | BCMA_CC_CORECTL_UARTCLKEN);
138 }
139 } else {
140 pr_err("serial not supported on this device ccrev: 0x%x\n",
141 ccrev);
142 return;
143 }
144
145 irq = bcma_core_mips_irq(cc->core);
146
147 /* Determine the registers of the UARTs */
148 cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
149 for (i = 0; i < cc->nr_serial_ports; i++) {
150 ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
151 (i * 256);
152 ports[i].irq = irq;
153 ports[i].baud_base = baud_base;
154 ports[i].reg_shift = 0;
155 }
156}
157#endif /* CONFIG_BCMA_DRIVER_MIPS */
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index fcc63db0ce75..800163c8c2e7 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -9,22 +9,50 @@
9 */ 9 */
10 10
11#include "bcma_private.h" 11#include "bcma_private.h"
12#include <linux/export.h>
12#include <linux/bcma/bcma.h> 13#include <linux/bcma/bcma.h>
13 14
14static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, 15static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
15 u32 offset, u32 mask, u32 set)
16{ 16{
17 u32 value; 17 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
18 bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
19 return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
20}
18 21
19 bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); 22void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
23{
24 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
25 bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
26 bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value);
27}
28EXPORT_SYMBOL_GPL(bcma_chipco_pll_write);
29
30void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
31 u32 set)
32{
33 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
34 bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
35 bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set);
36}
37EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset);
38
39void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
40 u32 offset, u32 mask, u32 set)
41{
20 bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); 42 bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset);
21 bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); 43 bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
22 value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA); 44 bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set);
23 value &= mask; 45}
24 value |= set; 46EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset);
25 bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value); 47
26 bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA); 48void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
49 u32 set)
50{
51 bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset);
52 bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR);
53 bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set);
27} 54}
55EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
28 56
29static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) 57static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
30{ 58{
@@ -83,6 +111,24 @@ void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
83 } 111 }
84} 112}
85 113
114/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
115void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
116{
117 struct bcma_bus *bus = cc->core->bus;
118 u32 val;
119
120 val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL);
121 if (enable) {
122 val |= BCMA_CHIPCTL_4331_EXTPA_EN;
123 if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
124 val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
125 } else {
126 val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;
127 val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
128 }
129 bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
130}
131
86void bcma_pmu_workarounds(struct bcma_drv_cc *cc) 132void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
87{ 133{
88 struct bcma_bus *bus = cc->core->bus; 134 struct bcma_bus *bus = cc->core->bus;
@@ -92,7 +138,7 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
92 bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); 138 bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
93 break; 139 break;
94 case 0x4331: 140 case 0x4331:
95 pr_err("Enabling Ext PA lines not implemented\n"); 141 /* BCM4331 workaround is SPROM-related, we put it in sprom.c */
96 break; 142 break;
97 case 43224: 143 case 43224:
98 if (bus->chipinfo.rev == 0) { 144 if (bus->chipinfo.rev == 0) {
@@ -136,3 +182,129 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
136 bcma_pmu_swreg_init(cc); 182 bcma_pmu_swreg_init(cc);
137 bcma_pmu_workarounds(cc); 183 bcma_pmu_workarounds(cc);
138} 184}
185
186u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
187{
188 struct bcma_bus *bus = cc->core->bus;
189
190 switch (bus->chipinfo.id) {
191 case 0x4716:
192 case 0x4748:
193 case 47162:
194 case 0x4313:
195 case 0x5357:
196 case 0x4749:
197 case 53572:
198 /* always 20Mhz */
199 return 20000 * 1000;
200 case 0x5356:
201 case 0x5300:
202 /* always 25Mhz */
203 return 25000 * 1000;
204 default:
205 pr_warn("No ALP clock specified for %04X device, "
206 "pmu rev. %d, using default %d Hz\n",
207 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
208 }
209 return BCMA_CC_PMU_ALP_CLOCK;
210}
211
212/* Find the output of the "m" pll divider given pll controls that start with
213 * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
214 */
215static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
216{
217 u32 tmp, div, ndiv, p1, p2, fc;
218 struct bcma_bus *bus = cc->core->bus;
219
220 BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0));
221
222 BUG_ON(!m || m > 4);
223
224 if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) {
225 /* Detect failure in clock setting */
226 tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
227 if (tmp & 0x40000)
228 return 133 * 1000000;
229 }
230
231 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF);
232 p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT;
233 p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT;
234
235 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF);
236 div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) &
237 BCMA_CC_PPL_MDIV_MASK;
238
239 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF);
240 ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
241
242 /* Do calculation in Mhz */
243 fc = bcma_pmu_alp_clock(cc) / 1000000;
244 fc = (p1 * ndiv * fc) / p2;
245
246 /* Return clock in Hertz */
247 return (fc / div) * 1000000;
248}
249
250/* query bus clock frequency for PMU-enabled chipcommon */
251u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
252{
253 struct bcma_bus *bus = cc->core->bus;
254
255 switch (bus->chipinfo.id) {
256 case 0x4716:
257 case 0x4748:
258 case 47162:
259 return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
260 BCMA_CC_PMU5_MAINPLL_SSB);
261 case 0x5356:
262 return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
263 BCMA_CC_PMU5_MAINPLL_SSB);
264 case 0x5357:
265 case 0x4749:
266 return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
267 BCMA_CC_PMU5_MAINPLL_SSB);
268 case 0x5300:
269 return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
270 BCMA_CC_PMU5_MAINPLL_SSB);
271 case 53572:
272 return 75000000;
273 default:
274 pr_warn("No backplane clock specified for %04X device, "
275 "pmu rev. %d, using default %d Hz\n",
276 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
277 }
278 return BCMA_CC_PMU_HT_CLOCK;
279}
280
281/* query cpu clock frequency for PMU-enabled chipcommon */
282u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
283{
284 struct bcma_bus *bus = cc->core->bus;
285
286 if (bus->chipinfo.id == 53572)
287 return 300000000;
288
289 if (cc->pmu.rev >= 5) {
290 u32 pll;
291 switch (bus->chipinfo.id) {
292 case 0x5356:
293 pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
294 break;
295 case 0x5357:
296 case 0x4749:
297 pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
298 break;
299 default:
300 pll = BCMA_CC_PMU4716_MAINPLL_PLL0;
301 break;
302 }
303
304 /* TODO: if (bus->chipinfo.id == 0x5300)
305 return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */
306 return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
307 }
308
309 return bcma_pmu_get_clockcontrol(cc);
310}
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
new file mode 100644
index 000000000000..c3e9dff4224e
--- /dev/null
+++ b/drivers/bcma/driver_mips.c
@@ -0,0 +1,256 @@
1/*
2 * Broadcom specific AMBA
3 * Broadcom MIPS32 74K core driver
4 *
5 * Copyright 2009, Broadcom Corporation
6 * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
7 * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
8 * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
9 *
10 * Licensed under the GNU/GPL. See COPYING for details.
11 */
12
13#include "bcma_private.h"
14
15#include <linux/bcma/bcma.h>
16
17#include <linux/serial.h>
18#include <linux/serial_core.h>
19#include <linux/serial_reg.h>
20#include <linux/time.h>
21
22/* The 47162a0 hangs when reading MIPS DMP registers registers */
23static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
24{
25 return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
26 dev->id.id == BCMA_CORE_MIPS_74K;
27}
28
29/* The 5357b0 hangs when reading USB20H DMP registers */
30static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
31{
32 return (dev->bus->chipinfo.id == 0x5357 ||
33 dev->bus->chipinfo.id == 0x4749) &&
34 dev->bus->chipinfo.pkg == 11 &&
35 dev->id.id == BCMA_CORE_USB20_HOST;
36}
37
38static inline u32 mips_read32(struct bcma_drv_mips *mcore,
39 u16 offset)
40{
41 return bcma_read32(mcore->core, offset);
42}
43
44static inline void mips_write32(struct bcma_drv_mips *mcore,
45 u16 offset,
46 u32 value)
47{
48 bcma_write32(mcore->core, offset, value);
49}
50
51static const u32 ipsflag_irq_mask[] = {
52 0,
53 BCMA_MIPS_IPSFLAG_IRQ1,
54 BCMA_MIPS_IPSFLAG_IRQ2,
55 BCMA_MIPS_IPSFLAG_IRQ3,
56 BCMA_MIPS_IPSFLAG_IRQ4,
57};
58
59static const u32 ipsflag_irq_shift[] = {
60 0,
61 BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
62 BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
63 BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
64 BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
65};
66
67static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
68{
69 u32 flag;
70
71 if (bcma_core_mips_bcm47162a0_quirk(dev))
72 return dev->core_index;
73 if (bcma_core_mips_bcm5357b0_quirk(dev))
74 return dev->core_index;
75 flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
76
77 return flag & 0x1F;
78}
79
80/* Get the MIPS IRQ assignment for a specified device.
81 * If unassigned, 0 is returned.
82 */
83unsigned int bcma_core_mips_irq(struct bcma_device *dev)
84{
85 struct bcma_device *mdev = dev->bus->drv_mips.core;
86 u32 irqflag;
87 unsigned int irq;
88
89 irqflag = bcma_core_mips_irqflag(dev);
90
91 for (irq = 1; irq <= 4; irq++)
92 if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
93 (1 << irqflag))
94 return irq;
95
96 return 0;
97}
98EXPORT_SYMBOL(bcma_core_mips_irq);
99
100static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
101{
102 unsigned int oldirq = bcma_core_mips_irq(dev);
103 struct bcma_bus *bus = dev->bus;
104 struct bcma_device *mdev = bus->drv_mips.core;
105 u32 irqflag;
106
107 irqflag = bcma_core_mips_irqflag(dev);
108 BUG_ON(oldirq == 6);
109
110 dev->irq = irq + 2;
111
112 /* clear the old irq */
113 if (oldirq == 0)
114 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
115 bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
116 ~(1 << irqflag));
117 else
118 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
119
120 /* assign the new one */
121 if (irq == 0) {
122 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
123 bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
124 (1 << irqflag));
125 } else {
126 u32 oldirqflag = bcma_read32(mdev,
127 BCMA_MIPS_MIPS74K_INTMASK(irq));
128 if (oldirqflag) {
129 struct bcma_device *core;
130
131 /* backplane irq line is in use, find out who uses
132 * it and set user to irq 0
133 */
134 list_for_each_entry_reverse(core, &bus->cores, list) {
135 if ((1 << bcma_core_mips_irqflag(core)) ==
136 oldirqflag) {
137 bcma_core_mips_set_irq(core, 0);
138 break;
139 }
140 }
141 }
142 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
143 1 << irqflag);
144 }
145
146 pr_info("set_irq: core 0x%04x, irq %d => %d\n",
147 dev->id.id, oldirq + 2, irq + 2);
148}
149
150static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
151{
152 int i;
153 static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
154 printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
155 for (i = 0; i <= 6; i++)
156 printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
157 printk("\n");
158}
159
160static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
161{
162 struct bcma_device *core;
163
164 list_for_each_entry_reverse(core, &bus->cores, list) {
165 bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
166 }
167}
168
169u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
170{
171 struct bcma_bus *bus = mcore->core->bus;
172
173 if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
174 return bcma_pmu_get_clockcpu(&bus->drv_cc);
175
176 pr_err("No PMU available, need this to get the cpu clock\n");
177 return 0;
178}
179EXPORT_SYMBOL(bcma_cpu_clock);
180
181static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
182{
183 struct bcma_bus *bus = mcore->core->bus;
184
185 switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
186 case BCMA_CC_FLASHT_STSER:
187 case BCMA_CC_FLASHT_ATSER:
188 pr_err("Serial flash not supported.\n");
189 break;
190 case BCMA_CC_FLASHT_PARA:
191 pr_info("found parallel flash.\n");
192 bus->drv_cc.pflash.window = 0x1c000000;
193 bus->drv_cc.pflash.window_size = 0x02000000;
194
195 if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
196 BCMA_CC_FLASH_CFG_DS) == 0)
197 bus->drv_cc.pflash.buswidth = 1;
198 else
199 bus->drv_cc.pflash.buswidth = 2;
200 break;
201 default:
202 pr_err("flash not supported.\n");
203 }
204}
205
206void bcma_core_mips_init(struct bcma_drv_mips *mcore)
207{
208 struct bcma_bus *bus;
209 struct bcma_device *core;
210 bus = mcore->core->bus;
211
212 pr_info("Initializing MIPS core...\n");
213
214 if (!mcore->setup_done)
215 mcore->assigned_irqs = 1;
216
217 /* Assign IRQs to all cores on the bus */
218 list_for_each_entry_reverse(core, &bus->cores, list) {
219 int mips_irq;
220 if (core->irq)
221 continue;
222
223 mips_irq = bcma_core_mips_irq(core);
224 if (mips_irq > 4)
225 core->irq = 0;
226 else
227 core->irq = mips_irq + 2;
228 if (core->irq > 5)
229 continue;
230 switch (core->id.id) {
231 case BCMA_CORE_PCI:
232 case BCMA_CORE_PCIE:
233 case BCMA_CORE_ETHERNET:
234 case BCMA_CORE_ETHERNET_GBIT:
235 case BCMA_CORE_MAC_GBIT:
236 case BCMA_CORE_80211:
237 case BCMA_CORE_USB20_HOST:
238 /* These devices get their own IRQ line if available,
239 * the rest goes on IRQ0
240 */
241 if (mcore->assigned_irqs <= 4)
242 bcma_core_mips_set_irq(core,
243 mcore->assigned_irqs++);
244 break;
245 }
246 }
247 pr_info("IRQ reconfiguration done\n");
248 bcma_core_mips_dump_irq(bus);
249
250 if (mcore->setup_done)
251 return;
252
253 bcma_chipco_serial_init(&bus->drv_cc);
254 bcma_core_mips_flash_detect(mcore);
255 mcore->setup_done = true;
256}
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c
index 25f3ddf33823..4fde6254f04e 100644
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include "bcma_private.h" 11#include "bcma_private.h"
12#include <linux/export.h>
12#include <linux/bcma/bcma.h> 13#include <linux/bcma/bcma.h>
13 14
14/************************************************** 15/**************************************************
@@ -173,7 +174,7 @@ static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
173 return false; 174 return false;
174 175
175#ifdef CONFIG_SSB_DRIVER_PCICORE 176#ifdef CONFIG_SSB_DRIVER_PCICORE
176 if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI) 177 if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI)
177 return false; 178 return false;
178#endif /* CONFIG_SSB_DRIVER_PCICORE */ 179#endif /* CONFIG_SSB_DRIVER_PCICORE */
179 180
@@ -189,6 +190,9 @@ static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
189 190
190void bcma_core_pci_init(struct bcma_drv_pci *pc) 191void bcma_core_pci_init(struct bcma_drv_pci *pc)
191{ 192{
193 if (pc->setup_done)
194 return;
195
192 if (bcma_core_pci_is_in_hostmode(pc)) { 196 if (bcma_core_pci_is_in_hostmode(pc)) {
193#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE 197#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
194 bcma_core_pci_hostmode_init(pc); 198 bcma_core_pci_hostmode_init(pc);
@@ -198,6 +202,8 @@ void bcma_core_pci_init(struct bcma_drv_pci *pc)
198 } else { 202 } else {
199 bcma_core_pci_clientmode_init(pc); 203 bcma_core_pci_clientmode_init(pc);
200 } 204 }
205
206 pc->setup_done = true;
201} 207}
202 208
203int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, 209int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
@@ -205,7 +211,14 @@ int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
205{ 211{
206 struct pci_dev *pdev = pc->core->bus->host_pci; 212 struct pci_dev *pdev = pc->core->bus->host_pci;
207 u32 coremask, tmp; 213 u32 coremask, tmp;
208 int err; 214 int err = 0;
215
216 if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
217 /* This bcma device is not on a PCI host-bus. So the IRQs are
218 * not routed through the PCI core.
219 * So we must not enable routing through the PCI core. */
220 goto out;
221 }
209 222
210 err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); 223 err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
211 if (err) 224 if (err)
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index ac4bc626c149..1b51d8b7ac80 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -9,6 +9,7 @@
9#include <linux/slab.h> 9#include <linux/slab.h>
10#include <linux/bcma/bcma.h> 10#include <linux/bcma/bcma.h>
11#include <linux/pci.h> 11#include <linux/pci.h>
12#include <linux/module.h>
12 13
13static void bcma_host_pci_switch_core(struct bcma_device *core) 14static void bcma_host_pci_switch_core(struct bcma_device *core)
14{ 15{
diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c
new file mode 100644
index 000000000000..3c381fb8f9c4
--- /dev/null
+++ b/drivers/bcma/host_soc.c
@@ -0,0 +1,183 @@
1/*
2 * Broadcom specific AMBA
3 * System on Chip (SoC) Host
4 *
5 * Licensed under the GNU/GPL. See COPYING for details.
6 */
7
8#include "bcma_private.h"
9#include "scan.h"
10#include <linux/bcma/bcma.h>
11#include <linux/bcma/bcma_soc.h>
12
13static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
14{
15 return readb(core->io_addr + offset);
16}
17
18static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
19{
20 return readw(core->io_addr + offset);
21}
22
23static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
24{
25 return readl(core->io_addr + offset);
26}
27
28static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
29 u8 value)
30{
31 writeb(value, core->io_addr + offset);
32}
33
34static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
35 u16 value)
36{
37 writew(value, core->io_addr + offset);
38}
39
40static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
41 u32 value)
42{
43 writel(value, core->io_addr + offset);
44}
45
46#ifdef CONFIG_BCMA_BLOCKIO
47static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
48 size_t count, u16 offset, u8 reg_width)
49{
50 void __iomem *addr = core->io_addr + offset;
51
52 switch (reg_width) {
53 case sizeof(u8): {
54 u8 *buf = buffer;
55
56 while (count) {
57 *buf = __raw_readb(addr);
58 buf++;
59 count--;
60 }
61 break;
62 }
63 case sizeof(u16): {
64 __le16 *buf = buffer;
65
66 WARN_ON(count & 1);
67 while (count) {
68 *buf = (__force __le16)__raw_readw(addr);
69 buf++;
70 count -= 2;
71 }
72 break;
73 }
74 case sizeof(u32): {
75 __le32 *buf = buffer;
76
77 WARN_ON(count & 3);
78 while (count) {
79 *buf = (__force __le32)__raw_readl(addr);
80 buf++;
81 count -= 4;
82 }
83 break;
84 }
85 default:
86 WARN_ON(1);
87 }
88}
89
90static void bcma_host_soc_block_write(struct bcma_device *core,
91 const void *buffer,
92 size_t count, u16 offset, u8 reg_width)
93{
94 void __iomem *addr = core->io_addr + offset;
95
96 switch (reg_width) {
97 case sizeof(u8): {
98 const u8 *buf = buffer;
99
100 while (count) {
101 __raw_writeb(*buf, addr);
102 buf++;
103 count--;
104 }
105 break;
106 }
107 case sizeof(u16): {
108 const __le16 *buf = buffer;
109
110 WARN_ON(count & 1);
111 while (count) {
112 __raw_writew((__force u16)(*buf), addr);
113 buf++;
114 count -= 2;
115 }
116 break;
117 }
118 case sizeof(u32): {
119 const __le32 *buf = buffer;
120
121 WARN_ON(count & 3);
122 while (count) {
123 __raw_writel((__force u32)(*buf), addr);
124 buf++;
125 count -= 4;
126 }
127 break;
128 }
129 default:
130 WARN_ON(1);
131 }
132}
133#endif /* CONFIG_BCMA_BLOCKIO */
134
135static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
136{
137 return readl(core->io_wrap + offset);
138}
139
140static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
141 u32 value)
142{
143 writel(value, core->io_wrap + offset);
144}
145
146const struct bcma_host_ops bcma_host_soc_ops = {
147 .read8 = bcma_host_soc_read8,
148 .read16 = bcma_host_soc_read16,
149 .read32 = bcma_host_soc_read32,
150 .write8 = bcma_host_soc_write8,
151 .write16 = bcma_host_soc_write16,
152 .write32 = bcma_host_soc_write32,
153#ifdef CONFIG_BCMA_BLOCKIO
154 .block_read = bcma_host_soc_block_read,
155 .block_write = bcma_host_soc_block_write,
156#endif
157 .aread32 = bcma_host_soc_aread32,
158 .awrite32 = bcma_host_soc_awrite32,
159};
160
161int __init bcma_host_soc_register(struct bcma_soc *soc)
162{
163 struct bcma_bus *bus = &soc->bus;
164 int err;
165
166 /* iomap only first core. We have to read some register on this core
167 * to scan the bus.
168 */
169 bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
170 if (!bus->mmio)
171 return -ENOMEM;
172
173 /* Host specific */
174 bus->hosttype = BCMA_HOSTTYPE_SOC;
175 bus->ops = &bcma_host_soc_ops;
176
177 /* Register */
178 err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
179 if (err)
180 iounmap(bus->mmio);
181
182 return err;
183}
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 73b7b1a18fab..70c84b951098 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -6,6 +6,7 @@
6 */ 6 */
7 7
8#include "bcma_private.h" 8#include "bcma_private.h"
9#include <linux/module.h>
9#include <linux/bcma/bcma.h> 10#include <linux/bcma/bcma.h>
10#include <linux/slab.h> 11#include <linux/slab.h>
11 12
@@ -68,6 +69,10 @@ static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
68static void bcma_release_core_dev(struct device *dev) 69static void bcma_release_core_dev(struct device *dev)
69{ 70{
70 struct bcma_device *core = container_of(dev, struct bcma_device, dev); 71 struct bcma_device *core = container_of(dev, struct bcma_device, dev);
72 if (core->io_addr)
73 iounmap(core->io_addr);
74 if (core->io_wrap)
75 iounmap(core->io_wrap);
71 kfree(core); 76 kfree(core);
72} 77}
73 78
@@ -82,6 +87,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
82 case BCMA_CORE_CHIPCOMMON: 87 case BCMA_CORE_CHIPCOMMON:
83 case BCMA_CORE_PCI: 88 case BCMA_CORE_PCI:
84 case BCMA_CORE_PCIE: 89 case BCMA_CORE_PCIE:
90 case BCMA_CORE_MIPS_74K:
85 continue; 91 continue;
86 } 92 }
87 93
@@ -95,7 +101,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
95 core->dma_dev = &bus->host_pci->dev; 101 core->dma_dev = &bus->host_pci->dev;
96 core->irq = bus->host_pci->irq; 102 core->irq = bus->host_pci->irq;
97 break; 103 break;
98 case BCMA_HOSTTYPE_NONE: 104 case BCMA_HOSTTYPE_SOC:
105 core->dev.dma_mask = &core->dev.coherent_dma_mask;
106 core->dma_dev = &core->dev;
107 break;
99 case BCMA_HOSTTYPE_SDIO: 108 case BCMA_HOSTTYPE_SDIO:
100 break; 109 break;
101 } 110 }
@@ -142,6 +151,13 @@ int bcma_bus_register(struct bcma_bus *bus)
142 bcma_core_chipcommon_init(&bus->drv_cc); 151 bcma_core_chipcommon_init(&bus->drv_cc);
143 } 152 }
144 153
154 /* Init MIPS core */
155 core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
156 if (core) {
157 bus->drv_mips.core = core;
158 bcma_core_mips_init(&bus->drv_mips);
159 }
160
145 /* Init PCIE core */ 161 /* Init PCIE core */
146 core = bcma_find_core(bus, BCMA_CORE_PCIE); 162 core = bcma_find_core(bus, BCMA_CORE_PCIE);
147 if (core) { 163 if (core) {
@@ -171,6 +187,59 @@ void bcma_bus_unregister(struct bcma_bus *bus)
171 bcma_unregister_cores(bus); 187 bcma_unregister_cores(bus);
172} 188}
173 189
190int __init bcma_bus_early_register(struct bcma_bus *bus,
191 struct bcma_device *core_cc,
192 struct bcma_device *core_mips)
193{
194 int err;
195 struct bcma_device *core;
196 struct bcma_device_id match;
197
198 bcma_init_bus(bus);
199
200 match.manuf = BCMA_MANUF_BCM;
201 match.id = BCMA_CORE_CHIPCOMMON;
202 match.class = BCMA_CL_SIM;
203 match.rev = BCMA_ANY_REV;
204
205 /* Scan for chip common core */
206 err = bcma_bus_scan_early(bus, &match, core_cc);
207 if (err) {
208 pr_err("Failed to scan for common core: %d\n", err);
209 return -1;
210 }
211
212 match.manuf = BCMA_MANUF_MIPS;
213 match.id = BCMA_CORE_MIPS_74K;
214 match.class = BCMA_CL_SIM;
215 match.rev = BCMA_ANY_REV;
216
217 /* Scan for mips core */
218 err = bcma_bus_scan_early(bus, &match, core_mips);
219 if (err) {
220 pr_err("Failed to scan for mips core: %d\n", err);
221 return -1;
222 }
223
224 /* Init CC core */
225 core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
226 if (core) {
227 bus->drv_cc.core = core;
228 bcma_core_chipcommon_init(&bus->drv_cc);
229 }
230
231 /* Init MIPS core */
232 core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
233 if (core) {
234 bus->drv_mips.core = core;
235 bcma_core_mips_init(&bus->drv_mips);
236 }
237
238 pr_info("Early bus registered\n");
239
240 return 0;
241}
242
174int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) 243int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
175{ 244{
176 drv->drv.name = drv->name; 245 drv->drv.name = drv->name;
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 40d7dcce8933..cad994857683 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -200,18 +200,162 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
200 return addrl; 200 return addrl;
201} 201}
202 202
203int bcma_bus_scan(struct bcma_bus *bus) 203static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus,
204 u16 index)
204{ 205{
205 u32 erombase; 206 struct bcma_device *core;
206 u32 __iomem *eromptr, *eromend;
207 207
208 list_for_each_entry(core, &bus->cores, list) {
209 if (core->core_index == index)
210 return core;
211 }
212 return NULL;
213}
214
215static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
216 struct bcma_device_id *match, int core_num,
217 struct bcma_device *core)
218{
219 s32 tmp;
220 u8 i, j;
208 s32 cia, cib; 221 s32 cia, cib;
209 u8 ports[2], wrappers[2]; 222 u8 ports[2], wrappers[2];
210 223
224 /* get CIs */
225 cia = bcma_erom_get_ci(bus, eromptr);
226 if (cia < 0) {
227 bcma_erom_push_ent(eromptr);
228 if (bcma_erom_is_end(bus, eromptr))
229 return -ESPIPE;
230 return -EILSEQ;
231 }
232 cib = bcma_erom_get_ci(bus, eromptr);
233 if (cib < 0)
234 return -EILSEQ;
235
236 /* parse CIs */
237 core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
238 core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
239 core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
240 ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
241 ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
242 wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
243 wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
244 core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
245
246 if (((core->id.manuf == BCMA_MANUF_ARM) &&
247 (core->id.id == 0xFFF)) ||
248 (ports[1] == 0)) {
249 bcma_erom_skip_component(bus, eromptr);
250 return -ENXIO;
251 }
252
253 /* check if component is a core at all */
254 if (wrappers[0] + wrappers[1] == 0) {
255 /* we could save addrl of the router
256 if (cid == BCMA_CORE_OOB_ROUTER)
257 */
258 bcma_erom_skip_component(bus, eromptr);
259 return -ENXIO;
260 }
261
262 if (bcma_erom_is_bridge(bus, eromptr)) {
263 bcma_erom_skip_component(bus, eromptr);
264 return -ENXIO;
265 }
266
267 if (bcma_find_core_by_index(bus, core_num)) {
268 bcma_erom_skip_component(bus, eromptr);
269 return -ENODEV;
270 }
271
272 if (match && ((match->manuf != BCMA_ANY_MANUF &&
273 match->manuf != core->id.manuf) ||
274 (match->id != BCMA_ANY_ID && match->id != core->id.id) ||
275 (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) ||
276 (match->class != BCMA_ANY_CLASS && match->class != core->id.class)
277 )) {
278 bcma_erom_skip_component(bus, eromptr);
279 return -ENODEV;
280 }
281
282 /* get & parse master ports */
283 for (i = 0; i < ports[0]; i++) {
284 s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
285 if (mst_port_d < 0)
286 return -EILSEQ;
287 }
288
289 /* get & parse slave ports */
290 for (i = 0; i < ports[1]; i++) {
291 for (j = 0; ; j++) {
292 tmp = bcma_erom_get_addr_desc(bus, eromptr,
293 SCAN_ADDR_TYPE_SLAVE, i);
294 if (tmp < 0) {
295 /* no more entries for port _i_ */
296 /* pr_debug("erom: slave port %d "
297 * "has %d descriptors\n", i, j); */
298 break;
299 } else {
300 if (i == 0 && j == 0)
301 core->addr = tmp;
302 }
303 }
304 }
305
306 /* get & parse master wrappers */
307 for (i = 0; i < wrappers[0]; i++) {
308 for (j = 0; ; j++) {
309 tmp = bcma_erom_get_addr_desc(bus, eromptr,
310 SCAN_ADDR_TYPE_MWRAP, i);
311 if (tmp < 0) {
312 /* no more entries for port _i_ */
313 /* pr_debug("erom: master wrapper %d "
314 * "has %d descriptors\n", i, j); */
315 break;
316 } else {
317 if (i == 0 && j == 0)
318 core->wrap = tmp;
319 }
320 }
321 }
322
323 /* get & parse slave wrappers */
324 for (i = 0; i < wrappers[1]; i++) {
325 u8 hack = (ports[1] == 1) ? 0 : 1;
326 for (j = 0; ; j++) {
327 tmp = bcma_erom_get_addr_desc(bus, eromptr,
328 SCAN_ADDR_TYPE_SWRAP, i + hack);
329 if (tmp < 0) {
330 /* no more entries for port _i_ */
331 /* pr_debug("erom: master wrapper %d "
332 * has %d descriptors\n", i, j); */
333 break;
334 } else {
335 if (wrappers[0] == 0 && !i && !j)
336 core->wrap = tmp;
337 }
338 }
339 }
340 if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
341 core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE);
342 if (!core->io_addr)
343 return -ENOMEM;
344 core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE);
345 if (!core->io_wrap) {
346 iounmap(core->io_addr);
347 return -ENOMEM;
348 }
349 }
350 return 0;
351}
352
353void bcma_init_bus(struct bcma_bus *bus)
354{
211 s32 tmp; 355 s32 tmp;
212 u8 i, j;
213 356
214 int err; 357 if (bus->init_done)
358 return;
215 359
216 INIT_LIST_HEAD(&bus->cores); 360 INIT_LIST_HEAD(&bus->cores);
217 bus->nr_cores = 0; 361 bus->nr_cores = 0;
@@ -222,9 +366,27 @@ int bcma_bus_scan(struct bcma_bus *bus)
222 bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; 366 bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
223 bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; 367 bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
224 bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; 368 bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
369 bus->init_done = true;
370}
371
372int bcma_bus_scan(struct bcma_bus *bus)
373{
374 u32 erombase;
375 u32 __iomem *eromptr, *eromend;
376
377 int err, core_num = 0;
378
379 bcma_init_bus(bus);
225 380
226 erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); 381 erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
227 eromptr = bus->mmio; 382 if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
383 eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
384 if (!eromptr)
385 return -ENOMEM;
386 } else {
387 eromptr = bus->mmio;
388 }
389
228 eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); 390 eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
229 391
230 bcma_scan_switch_core(bus, erombase); 392 bcma_scan_switch_core(bus, erombase);
@@ -236,125 +398,89 @@ int bcma_bus_scan(struct bcma_bus *bus)
236 INIT_LIST_HEAD(&core->list); 398 INIT_LIST_HEAD(&core->list);
237 core->bus = bus; 399 core->bus = bus;
238 400
239 /* get CIs */ 401 err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
240 cia = bcma_erom_get_ci(bus, &eromptr); 402 if (err == -ENODEV) {
241 if (cia < 0) { 403 core_num++;
242 bcma_erom_push_ent(&eromptr);
243 if (bcma_erom_is_end(bus, &eromptr))
244 break;
245 err= -EILSEQ;
246 goto out;
247 }
248 cib = bcma_erom_get_ci(bus, &eromptr);
249 if (cib < 0) {
250 err= -EILSEQ;
251 goto out;
252 }
253
254 /* parse CIs */
255 core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
256 core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
257 core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
258 ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
259 ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
260 wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
261 wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
262 core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
263
264 if (((core->id.manuf == BCMA_MANUF_ARM) &&
265 (core->id.id == 0xFFF)) ||
266 (ports[1] == 0)) {
267 bcma_erom_skip_component(bus, &eromptr);
268 continue; 404 continue;
269 } 405 } else if (err == -ENXIO)
270
271 /* check if component is a core at all */
272 if (wrappers[0] + wrappers[1] == 0) {
273 /* we could save addrl of the router
274 if (cid == BCMA_CORE_OOB_ROUTER)
275 */
276 bcma_erom_skip_component(bus, &eromptr);
277 continue; 406 continue;
278 } 407 else if (err == -ESPIPE)
408 break;
409 else if (err < 0)
410 return err;
279 411
280 if (bcma_erom_is_bridge(bus, &eromptr)) { 412 core->core_index = core_num++;
281 bcma_erom_skip_component(bus, &eromptr); 413 bus->nr_cores++;
282 continue;
283 }
284 414
285 /* get & parse master ports */ 415 pr_info("Core %d found: %s "
286 for (i = 0; i < ports[0]; i++) { 416 "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
287 u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr); 417 core->core_index, bcma_device_name(&core->id),
288 if (mst_port_d < 0) { 418 core->id.manuf, core->id.id, core->id.rev,
289 err= -EILSEQ; 419 core->id.class);
290 goto out;
291 }
292 }
293 420
294 /* get & parse slave ports */ 421 list_add(&core->list, &bus->cores);
295 for (i = 0; i < ports[1]; i++) { 422 }
296 for (j = 0; ; j++) {
297 tmp = bcma_erom_get_addr_desc(bus, &eromptr,
298 SCAN_ADDR_TYPE_SLAVE, i);
299 if (tmp < 0) {
300 /* no more entries for port _i_ */
301 /* pr_debug("erom: slave port %d "
302 * "has %d descriptors\n", i, j); */
303 break;
304 } else {
305 if (i == 0 && j == 0)
306 core->addr = tmp;
307 }
308 }
309 }
310 423
311 /* get & parse master wrappers */ 424 if (bus->hosttype == BCMA_HOSTTYPE_SOC)
312 for (i = 0; i < wrappers[0]; i++) { 425 iounmap(eromptr);
313 for (j = 0; ; j++) {
314 tmp = bcma_erom_get_addr_desc(bus, &eromptr,
315 SCAN_ADDR_TYPE_MWRAP, i);
316 if (tmp < 0) {
317 /* no more entries for port _i_ */
318 /* pr_debug("erom: master wrapper %d "
319 * "has %d descriptors\n", i, j); */
320 break;
321 } else {
322 if (i == 0 && j == 0)
323 core->wrap = tmp;
324 }
325 }
326 }
327 426
328 /* get & parse slave wrappers */ 427 return 0;
329 for (i = 0; i < wrappers[1]; i++) { 428}
330 u8 hack = (ports[1] == 1) ? 0 : 1; 429
331 for (j = 0; ; j++) { 430int __init bcma_bus_scan_early(struct bcma_bus *bus,
332 tmp = bcma_erom_get_addr_desc(bus, &eromptr, 431 struct bcma_device_id *match,
333 SCAN_ADDR_TYPE_SWRAP, i + hack); 432 struct bcma_device *core)
334 if (tmp < 0) { 433{
335 /* no more entries for port _i_ */ 434 u32 erombase;
336 /* pr_debug("erom: master wrapper %d " 435 u32 __iomem *eromptr, *eromend;
337 * has %d descriptors\n", i, j); */ 436
338 break; 437 int err = -ENODEV;
339 } else { 438 int core_num = 0;
340 if (wrappers[0] == 0 && !i && !j) 439
341 core->wrap = tmp; 440 erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
342 } 441 if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
343 } 442 eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
344 } 443 if (!eromptr)
444 return -ENOMEM;
445 } else {
446 eromptr = bus->mmio;
447 }
448
449 eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
450
451 bcma_scan_switch_core(bus, erombase);
452
453 while (eromptr < eromend) {
454 memset(core, 0, sizeof(*core));
455 INIT_LIST_HEAD(&core->list);
456 core->bus = bus;
345 457
458 err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
459 if (err == -ENODEV) {
460 core_num++;
461 continue;
462 } else if (err == -ENXIO)
463 continue;
464 else if (err == -ESPIPE)
465 break;
466 else if (err < 0)
467 return err;
468
469 core->core_index = core_num++;
470 bus->nr_cores++;
346 pr_info("Core %d found: %s " 471 pr_info("Core %d found: %s "
347 "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", 472 "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
348 bus->nr_cores, bcma_device_name(&core->id), 473 core->core_index, bcma_device_name(&core->id),
349 core->id.manuf, core->id.id, core->id.rev, 474 core->id.manuf, core->id.id, core->id.rev,
350 core->id.class); 475 core->id.class);
351 476
352 core->core_index = bus->nr_cores++;
353 list_add(&core->list, &bus->cores); 477 list_add(&core->list, &bus->cores);
354 continue; 478 err = 0;
355out: 479 break;
356 return err;
357 } 480 }
358 481
359 return 0; 482 if (bus->hosttype == BCMA_HOSTTYPE_SOC)
483 iounmap(eromptr);
484
485 return err;
360} 486}
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index 8b5b7856abe3..d7292390d236 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -133,6 +133,15 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
133 v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; 133 v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
134 *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); 134 *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
135 } 135 }
136
137 bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)];
138
139 bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
140 bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
141 bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
142 bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
143
144 bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
136} 145}
137 146
138int bcma_sprom_get(struct bcma_bus *bus) 147int bcma_sprom_get(struct bcma_bus *bus)
@@ -152,6 +161,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
152 if (!sprom) 161 if (!sprom)
153 return -ENOMEM; 162 return -ENOMEM;
154 163
164 if (bus->chipinfo.id == 0x4331)
165 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
166
155 /* Most cards have SPROM moved by additional offset 0x30 (48 dwords). 167 /* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
156 * According to brcm80211 this applies to cards with PCIe rev >= 6 168 * According to brcm80211 this applies to cards with PCIe rev >= 6
157 * TODO: understand this condition and use it */ 169 * TODO: understand this condition and use it */
@@ -159,6 +171,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
159 BCMA_CC_SPROM_PCIE6; 171 BCMA_CC_SPROM_PCIE6;
160 bcma_sprom_read(bus, offset, sprom); 172 bcma_sprom_read(bus, offset, sprom);
161 173
174 if (bus->chipinfo.id == 0x4331)
175 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
176
162 err = bcma_sprom_valid(sprom); 177 err = bcma_sprom_valid(sprom);
163 if (err) 178 if (err)
164 goto out; 179 goto out;