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.c2
-rw-r--r--drivers/bcma/driver_chipcommon.c53
-rw-r--r--drivers/bcma/driver_chipcommon_pmu.c133
-rw-r--r--drivers/bcma/driver_mips.c256
-rw-r--r--drivers/bcma/driver_pci.c16
-rw-r--r--drivers/bcma/host_soc.c183
-rw-r--r--drivers/bcma/main.c70
-rw-r--r--drivers/bcma/scan.c348
11 files changed, 978 insertions, 114 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..189a97b51be9 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -110,6 +110,8 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
110u32 bcma_core_dma_translation(struct bcma_device *core) 110u32 bcma_core_dma_translation(struct bcma_device *core)
111{ 111{
112 switch (core->bus->hosttype) { 112 switch (core->bus->hosttype) {
113 case BCMA_HOSTTYPE_SOC:
114 return 0;
113 case BCMA_HOSTTYPE_PCI: 115 case BCMA_HOSTTYPE_PCI:
114 if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64) 116 if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
115 return BCMA_DMA_TRANSLATION_DMA64_CMT; 117 return BCMA_DMA_TRANSLATION_DMA64_CMT;
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index 851e05bc948a..47cce9d69630 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -26,6 +26,9 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
26 u32 leddc_on = 10; 26 u32 leddc_on = 10;
27 u32 leddc_off = 90; 27 u32 leddc_off = 90;
28 28
29 if (cc->setup_done)
30 return;
31
29 if (cc->core->id.rev >= 11) 32 if (cc->core->id.rev >= 11)
30 cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 33 cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
31 cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); 34 cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -52,6 +55,8 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
52 ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | 55 ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
53 (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT))); 56 (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
54 } 57 }
58
59 cc->setup_done = true;
55} 60}
56 61
57/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ 62/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
@@ -101,3 +106,51 @@ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
101{ 106{
102 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); 107 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
103} 108}
109
110#ifdef CONFIG_BCMA_DRIVER_MIPS
111void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
112{
113 unsigned int irq;
114 u32 baud_base;
115 u32 i;
116 unsigned int ccrev = cc->core->id.rev;
117 struct bcma_serial_port *ports = cc->serial_ports;
118
119 if (ccrev >= 11 && ccrev != 15) {
120 /* Fixed ALP clock */
121 baud_base = bcma_pmu_alp_clock(cc);
122 if (ccrev >= 21) {
123 /* Turn off UART clock before switching clocksource. */
124 bcma_cc_write32(cc, BCMA_CC_CORECTL,
125 bcma_cc_read32(cc, BCMA_CC_CORECTL)
126 & ~BCMA_CC_CORECTL_UARTCLKEN);
127 }
128 /* Set the override bit so we don't divide it */
129 bcma_cc_write32(cc, BCMA_CC_CORECTL,
130 bcma_cc_read32(cc, BCMA_CC_CORECTL)
131 | BCMA_CC_CORECTL_UARTCLK0);
132 if (ccrev >= 21) {
133 /* Re-enable the UART clock. */
134 bcma_cc_write32(cc, BCMA_CC_CORECTL,
135 bcma_cc_read32(cc, BCMA_CC_CORECTL)
136 | BCMA_CC_CORECTL_UARTCLKEN);
137 }
138 } else {
139 pr_err("serial not supported on this device ccrev: 0x%x\n",
140 ccrev);
141 return;
142 }
143
144 irq = bcma_core_mips_irq(cc->core);
145
146 /* Determine the registers of the UARTs */
147 cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
148 for (i = 0; i < cc->nr_serial_ports; i++) {
149 ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
150 (i * 256);
151 ports[i].irq = irq;
152 ports[i].baud_base = baud_base;
153 ports[i].reg_shift = 0;
154 }
155}
156#endif /* CONFIG_BCMA_DRIVER_MIPS */
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index fcc63db0ce75..5940c81e7e12 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -11,6 +11,13 @@
11#include "bcma_private.h" 11#include "bcma_private.h"
12#include <linux/bcma/bcma.h> 12#include <linux/bcma/bcma.h>
13 13
14static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
15{
16 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
17 bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
18 return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
19}
20
14static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, 21static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
15 u32 offset, u32 mask, u32 set) 22 u32 offset, u32 mask, u32 set)
16{ 23{
@@ -136,3 +143,129 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
136 bcma_pmu_swreg_init(cc); 143 bcma_pmu_swreg_init(cc);
137 bcma_pmu_workarounds(cc); 144 bcma_pmu_workarounds(cc);
138} 145}
146
147u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
148{
149 struct bcma_bus *bus = cc->core->bus;
150
151 switch (bus->chipinfo.id) {
152 case 0x4716:
153 case 0x4748:
154 case 47162:
155 case 0x4313:
156 case 0x5357:
157 case 0x4749:
158 case 53572:
159 /* always 20Mhz */
160 return 20000 * 1000;
161 case 0x5356:
162 case 0x5300:
163 /* always 25Mhz */
164 return 25000 * 1000;
165 default:
166 pr_warn("No ALP clock specified for %04X device, "
167 "pmu rev. %d, using default %d Hz\n",
168 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
169 }
170 return BCMA_CC_PMU_ALP_CLOCK;
171}
172
173/* Find the output of the "m" pll divider given pll controls that start with
174 * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
175 */
176static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
177{
178 u32 tmp, div, ndiv, p1, p2, fc;
179 struct bcma_bus *bus = cc->core->bus;
180
181 BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0));
182
183 BUG_ON(!m || m > 4);
184
185 if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) {
186 /* Detect failure in clock setting */
187 tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
188 if (tmp & 0x40000)
189 return 133 * 1000000;
190 }
191
192 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF);
193 p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT;
194 p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT;
195
196 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF);
197 div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) &
198 BCMA_CC_PPL_MDIV_MASK;
199
200 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF);
201 ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
202
203 /* Do calculation in Mhz */
204 fc = bcma_pmu_alp_clock(cc) / 1000000;
205 fc = (p1 * ndiv * fc) / p2;
206
207 /* Return clock in Hertz */
208 return (fc / div) * 1000000;
209}
210
211/* query bus clock frequency for PMU-enabled chipcommon */
212u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
213{
214 struct bcma_bus *bus = cc->core->bus;
215
216 switch (bus->chipinfo.id) {
217 case 0x4716:
218 case 0x4748:
219 case 47162:
220 return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
221 BCMA_CC_PMU5_MAINPLL_SSB);
222 case 0x5356:
223 return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
224 BCMA_CC_PMU5_MAINPLL_SSB);
225 case 0x5357:
226 case 0x4749:
227 return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
228 BCMA_CC_PMU5_MAINPLL_SSB);
229 case 0x5300:
230 return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
231 BCMA_CC_PMU5_MAINPLL_SSB);
232 case 53572:
233 return 75000000;
234 default:
235 pr_warn("No backplane clock specified for %04X device, "
236 "pmu rev. %d, using default %d Hz\n",
237 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
238 }
239 return BCMA_CC_PMU_HT_CLOCK;
240}
241
242/* query cpu clock frequency for PMU-enabled chipcommon */
243u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
244{
245 struct bcma_bus *bus = cc->core->bus;
246
247 if (bus->chipinfo.id == 53572)
248 return 300000000;
249
250 if (cc->pmu.rev >= 5) {
251 u32 pll;
252 switch (bus->chipinfo.id) {
253 case 0x5356:
254 pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
255 break;
256 case 0x5357:
257 case 0x4749:
258 pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
259 break;
260 default:
261 pll = BCMA_CC_PMU4716_MAINPLL_PLL0;
262 break;
263 }
264
265 /* TODO: if (bus->chipinfo.id == 0x5300)
266 return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */
267 return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
268 }
269
270 return bcma_pmu_get_clockcontrol(cc);
271}
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..81f3d0a4b856 100644
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -173,7 +173,7 @@ static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
173 return false; 173 return false;
174 174
175#ifdef CONFIG_SSB_DRIVER_PCICORE 175#ifdef CONFIG_SSB_DRIVER_PCICORE
176 if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI) 176 if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI)
177 return false; 177 return false;
178#endif /* CONFIG_SSB_DRIVER_PCICORE */ 178#endif /* CONFIG_SSB_DRIVER_PCICORE */
179 179
@@ -189,6 +189,9 @@ static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
189 189
190void bcma_core_pci_init(struct bcma_drv_pci *pc) 190void bcma_core_pci_init(struct bcma_drv_pci *pc)
191{ 191{
192 if (pc->setup_done)
193 return;
194
192 if (bcma_core_pci_is_in_hostmode(pc)) { 195 if (bcma_core_pci_is_in_hostmode(pc)) {
193#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE 196#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
194 bcma_core_pci_hostmode_init(pc); 197 bcma_core_pci_hostmode_init(pc);
@@ -198,6 +201,8 @@ void bcma_core_pci_init(struct bcma_drv_pci *pc)
198 } else { 201 } else {
199 bcma_core_pci_clientmode_init(pc); 202 bcma_core_pci_clientmode_init(pc);
200 } 203 }
204
205 pc->setup_done = true;
201} 206}
202 207
203int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, 208int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
@@ -205,7 +210,14 @@ int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
205{ 210{
206 struct pci_dev *pdev = pc->core->bus->host_pci; 211 struct pci_dev *pdev = pc->core->bus->host_pci;
207 u32 coremask, tmp; 212 u32 coremask, tmp;
208 int err; 213 int err = 0;
214
215 if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
216 /* This bcma device is not on a PCI host-bus. So the IRQs are
217 * not routed through the PCI core.
218 * So we must not enable routing through the PCI core. */
219 goto out;
220 }
209 221
210 err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); 222 err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
211 if (err) 223 if (err)
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 873e2e4ac55f..7072216a2a3f 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -66,6 +66,10 @@ static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
66static void bcma_release_core_dev(struct device *dev) 66static void bcma_release_core_dev(struct device *dev)
67{ 67{
68 struct bcma_device *core = container_of(dev, struct bcma_device, dev); 68 struct bcma_device *core = container_of(dev, struct bcma_device, dev);
69 if (core->io_addr)
70 iounmap(core->io_addr);
71 if (core->io_wrap)
72 iounmap(core->io_wrap);
69 kfree(core); 73 kfree(core);
70} 74}
71 75
@@ -80,6 +84,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
80 case BCMA_CORE_CHIPCOMMON: 84 case BCMA_CORE_CHIPCOMMON:
81 case BCMA_CORE_PCI: 85 case BCMA_CORE_PCI:
82 case BCMA_CORE_PCIE: 86 case BCMA_CORE_PCIE:
87 case BCMA_CORE_MIPS_74K:
83 continue; 88 continue;
84 } 89 }
85 90
@@ -93,7 +98,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
93 core->dma_dev = &bus->host_pci->dev; 98 core->dma_dev = &bus->host_pci->dev;
94 core->irq = bus->host_pci->irq; 99 core->irq = bus->host_pci->irq;
95 break; 100 break;
96 case BCMA_HOSTTYPE_NONE: 101 case BCMA_HOSTTYPE_SOC:
102 core->dev.dma_mask = &core->dev.coherent_dma_mask;
103 core->dma_dev = &core->dev;
104 break;
97 case BCMA_HOSTTYPE_SDIO: 105 case BCMA_HOSTTYPE_SDIO:
98 break; 106 break;
99 } 107 }
@@ -140,6 +148,13 @@ int bcma_bus_register(struct bcma_bus *bus)
140 bcma_core_chipcommon_init(&bus->drv_cc); 148 bcma_core_chipcommon_init(&bus->drv_cc);
141 } 149 }
142 150
151 /* Init MIPS core */
152 core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
153 if (core) {
154 bus->drv_mips.core = core;
155 bcma_core_mips_init(&bus->drv_mips);
156 }
157
143 /* Init PCIE core */ 158 /* Init PCIE core */
144 core = bcma_find_core(bus, BCMA_CORE_PCIE); 159 core = bcma_find_core(bus, BCMA_CORE_PCIE);
145 if (core) { 160 if (core) {
@@ -169,6 +184,59 @@ void bcma_bus_unregister(struct bcma_bus *bus)
169 bcma_unregister_cores(bus); 184 bcma_unregister_cores(bus);
170} 185}
171 186
187int __init bcma_bus_early_register(struct bcma_bus *bus,
188 struct bcma_device *core_cc,
189 struct bcma_device *core_mips)
190{
191 int err;
192 struct bcma_device *core;
193 struct bcma_device_id match;
194
195 bcma_init_bus(bus);
196
197 match.manuf = BCMA_MANUF_BCM;
198 match.id = BCMA_CORE_CHIPCOMMON;
199 match.class = BCMA_CL_SIM;
200 match.rev = BCMA_ANY_REV;
201
202 /* Scan for chip common core */
203 err = bcma_bus_scan_early(bus, &match, core_cc);
204 if (err) {
205 pr_err("Failed to scan for common core: %d\n", err);
206 return -1;
207 }
208
209 match.manuf = BCMA_MANUF_MIPS;
210 match.id = BCMA_CORE_MIPS_74K;
211 match.class = BCMA_CL_SIM;
212 match.rev = BCMA_ANY_REV;
213
214 /* Scan for mips core */
215 err = bcma_bus_scan_early(bus, &match, core_mips);
216 if (err) {
217 pr_err("Failed to scan for mips core: %d\n", err);
218 return -1;
219 }
220
221 /* Init CC core */
222 core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
223 if (core) {
224 bus->drv_cc.core = core;
225 bcma_core_chipcommon_init(&bus->drv_cc);
226 }
227
228 /* Init MIPS core */
229 core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
230 if (core) {
231 bus->drv_mips.core = core;
232 bcma_core_mips_init(&bus->drv_mips);
233 }
234
235 pr_info("Early bus registered\n");
236
237 return 0;
238}
239
172int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) 240int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
173{ 241{
174 drv->drv.name = drv->name; 242 drv->drv.name = drv->name;
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 40d7dcce8933..0ea390f9aa9e 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 u32 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}