Root/target/linux/generic/patches-3.0/025-bcma_backport.patch

1--- a/drivers/bcma/Kconfig
2+++ b/drivers/bcma/Kconfig
3@@ -13,6 +13,11 @@ config BCMA
4       Bus driver for Broadcom specific Advanced Microcontroller Bus
5       Architecture.
6 
7+# Support for Block-I/O. SELECT this from the driver that needs it.
8+config BCMA_BLOCKIO
9+ bool
10+ depends on BCMA
11+
12 config BCMA_HOST_PCI_POSSIBLE
13     bool
14     depends on BCMA && PCI = y
15@@ -22,6 +27,25 @@ config BCMA_HOST_PCI
16     bool "Support for BCMA on PCI-host bus"
17     depends on BCMA_HOST_PCI_POSSIBLE
18 
19+config BCMA_DRIVER_PCI_HOSTMODE
20+ bool "Driver for PCI core working in hostmode"
21+ depends on BCMA && MIPS
22+ help
23+ PCI core hostmode operation (external PCI bus).
24+
25+config BCMA_HOST_SOC
26+ bool
27+ depends on BCMA_DRIVER_MIPS
28+
29+config BCMA_DRIVER_MIPS
30+ bool "BCMA Broadcom MIPS core driver"
31+ depends on BCMA && MIPS
32+ help
33+ Driver for the Broadcom MIPS core attached to Broadcom specific
34+ Advanced Microcontroller Bus.
35+
36+ If unsure, say N
37+
38 config BCMA_DEBUG
39     bool "BCMA debugging"
40     depends on BCMA
41--- a/drivers/bcma/Makefile
42+++ b/drivers/bcma/Makefile
43@@ -1,7 +1,10 @@
44-bcma-y += main.o scan.o core.o
45+bcma-y += main.o scan.o core.o sprom.o
46 bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
47 bcma-y += driver_pci.o
48+bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
49+bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
50 bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
51+bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
52 obj-$(CONFIG_BCMA) += bcma.o
53 
54 ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG
55--- a/drivers/bcma/bcma_private.h
56+++ b/drivers/bcma/bcma_private.h
57@@ -13,11 +13,33 @@
58 struct bcma_bus;
59 
60 /* main.c */
61-extern int bcma_bus_register(struct bcma_bus *bus);
62-extern void bcma_bus_unregister(struct bcma_bus *bus);
63+int bcma_bus_register(struct bcma_bus *bus);
64+void bcma_bus_unregister(struct bcma_bus *bus);
65+int __init bcma_bus_early_register(struct bcma_bus *bus,
66+ struct bcma_device *core_cc,
67+ struct bcma_device *core_mips);
68+#ifdef CONFIG_PM
69+int bcma_bus_resume(struct bcma_bus *bus);
70+#endif
71 
72 /* scan.c */
73 int bcma_bus_scan(struct bcma_bus *bus);
74+int __init bcma_bus_scan_early(struct bcma_bus *bus,
75+ struct bcma_device_id *match,
76+ struct bcma_device *core);
77+void bcma_init_bus(struct bcma_bus *bus);
78+
79+/* sprom.c */
80+int bcma_sprom_get(struct bcma_bus *bus);
81+
82+/* driver_chipcommon.c */
83+#ifdef CONFIG_BCMA_DRIVER_MIPS
84+void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
85+#endif /* CONFIG_BCMA_DRIVER_MIPS */
86+
87+/* driver_chipcommon_pmu.c */
88+u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
89+u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
90 
91 #ifdef CONFIG_BCMA_HOST_PCI
92 /* host_pci.c */
93@@ -25,4 +47,8 @@ extern int __init bcma_host_pci_init(voi
94 extern void __exit bcma_host_pci_exit(void);
95 #endif /* CONFIG_BCMA_HOST_PCI */
96 
97+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
98+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
99+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
100+
101 #endif
102--- a/drivers/bcma/core.c
103+++ b/drivers/bcma/core.c
104@@ -19,7 +19,7 @@ bool bcma_core_is_enabled(struct bcma_de
105 }
106 EXPORT_SYMBOL_GPL(bcma_core_is_enabled);
107 
108-static void bcma_core_disable(struct bcma_device *core, u32 flags)
109+void bcma_core_disable(struct bcma_device *core, u32 flags)
110 {
111     if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
112         return;
113@@ -31,6 +31,7 @@ static void bcma_core_disable(struct bcm
114     bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
115     udelay(1);
116 }
117+EXPORT_SYMBOL_GPL(bcma_core_disable);
118 
119 int bcma_core_enable(struct bcma_device *core, u32 flags)
120 {
121@@ -49,3 +50,77 @@ int bcma_core_enable(struct bcma_device
122     return 0;
123 }
124 EXPORT_SYMBOL_GPL(bcma_core_enable);
125+
126+void bcma_core_set_clockmode(struct bcma_device *core,
127+ enum bcma_clkmode clkmode)
128+{
129+ u16 i;
130+
131+ WARN_ON(core->id.id != BCMA_CORE_CHIPCOMMON &&
132+ core->id.id != BCMA_CORE_PCIE &&
133+ core->id.id != BCMA_CORE_80211);
134+
135+ switch (clkmode) {
136+ case BCMA_CLKMODE_FAST:
137+ bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
138+ udelay(64);
139+ for (i = 0; i < 1500; i++) {
140+ if (bcma_read32(core, BCMA_CLKCTLST) &
141+ BCMA_CLKCTLST_HAVEHT) {
142+ i = 0;
143+ break;
144+ }
145+ udelay(10);
146+ }
147+ if (i)
148+ pr_err("HT force timeout\n");
149+ break;
150+ case BCMA_CLKMODE_DYNAMIC:
151+ pr_warn("Dynamic clockmode not supported yet!\n");
152+ break;
153+ }
154+}
155+EXPORT_SYMBOL_GPL(bcma_core_set_clockmode);
156+
157+void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
158+{
159+ u16 i;
160+
161+ WARN_ON(req & ~BCMA_CLKCTLST_EXTRESREQ);
162+ WARN_ON(status & ~BCMA_CLKCTLST_EXTRESST);
163+
164+ if (on) {
165+ bcma_set32(core, BCMA_CLKCTLST, req);
166+ for (i = 0; i < 10000; i++) {
167+ if ((bcma_read32(core, BCMA_CLKCTLST) & status) ==
168+ status) {
169+ i = 0;
170+ break;
171+ }
172+ udelay(10);
173+ }
174+ if (i)
175+ pr_err("PLL enable timeout\n");
176+ } else {
177+ pr_warn("Disabling PLL not supported yet!\n");
178+ }
179+}
180+EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
181+
182+u32 bcma_core_dma_translation(struct bcma_device *core)
183+{
184+ switch (core->bus->hosttype) {
185+ case BCMA_HOSTTYPE_SOC:
186+ return 0;
187+ case BCMA_HOSTTYPE_PCI:
188+ if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
189+ return BCMA_DMA_TRANSLATION_DMA64_CMT;
190+ else
191+ return BCMA_DMA_TRANSLATION_DMA32_CMT;
192+ default:
193+ pr_err("DMA translation unknown for host %d\n",
194+ core->bus->hosttype);
195+ }
196+ return BCMA_DMA_TRANSLATION_NONE;
197+}
198+EXPORT_SYMBOL(bcma_core_dma_translation);
199--- a/drivers/bcma/driver_chipcommon.c
200+++ b/drivers/bcma/driver_chipcommon.c
201@@ -3,7 +3,7 @@
202  * ChipCommon core driver
203  *
204  * Copyright 2005, Broadcom Corporation
205- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
206+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
207  *
208  * Licensed under the GNU/GPL. See COPYING for details.
209  */
210@@ -23,6 +23,12 @@ static inline u32 bcma_cc_write32_masked
211 
212 void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
213 {
214+ u32 leddc_on = 10;
215+ u32 leddc_off = 90;
216+
217+ if (cc->setup_done)
218+ return;
219+
220     if (cc->core->id.rev >= 11)
221         cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
222     cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
223@@ -38,6 +44,19 @@ void bcma_core_chipcommon_init(struct bc
224         bcma_pmu_init(cc);
225     if (cc->capabilities & BCMA_CC_CAP_PCTL)
226         pr_err("Power control not implemented!\n");
227+
228+ if (cc->core->id.rev >= 16) {
229+ if (cc->core->bus->sprom.leddc_on_time &&
230+ cc->core->bus->sprom.leddc_off_time) {
231+ leddc_on = cc->core->bus->sprom.leddc_on_time;
232+ leddc_off = cc->core->bus->sprom.leddc_off_time;
233+ }
234+ bcma_cc_write32(cc, BCMA_CC_GPIOTIMER,
235+ ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
236+ (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
237+ }
238+
239+ cc->setup_done = true;
240 }
241 
242 /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
243@@ -87,3 +106,51 @@ u32 bcma_chipco_gpio_polarity(struct bcm
244 {
245     return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
246 }
247+
248+#ifdef CONFIG_BCMA_DRIVER_MIPS
249+void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
250+{
251+ unsigned int irq;
252+ u32 baud_base;
253+ u32 i;
254+ unsigned int ccrev = cc->core->id.rev;
255+ struct bcma_serial_port *ports = cc->serial_ports;
256+
257+ if (ccrev >= 11 && ccrev != 15) {
258+ /* Fixed ALP clock */
259+ baud_base = bcma_pmu_alp_clock(cc);
260+ if (ccrev >= 21) {
261+ /* Turn off UART clock before switching clocksource. */
262+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
263+ bcma_cc_read32(cc, BCMA_CC_CORECTL)
264+ & ~BCMA_CC_CORECTL_UARTCLKEN);
265+ }
266+ /* Set the override bit so we don't divide it */
267+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
268+ bcma_cc_read32(cc, BCMA_CC_CORECTL)
269+ | BCMA_CC_CORECTL_UARTCLK0);
270+ if (ccrev >= 21) {
271+ /* Re-enable the UART clock. */
272+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
273+ bcma_cc_read32(cc, BCMA_CC_CORECTL)
274+ | BCMA_CC_CORECTL_UARTCLKEN);
275+ }
276+ } else {
277+ pr_err("serial not supported on this device ccrev: 0x%x\n",
278+ ccrev);
279+ return;
280+ }
281+
282+ irq = bcma_core_mips_irq(cc->core);
283+
284+ /* Determine the registers of the UARTs */
285+ cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
286+ for (i = 0; i < cc->nr_serial_ports; i++) {
287+ ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
288+ (i * 256);
289+ ports[i].irq = irq;
290+ ports[i].baud_base = baud_base;
291+ ports[i].reg_shift = 0;
292+ }
293+}
294+#endif /* CONFIG_BCMA_DRIVER_MIPS */
295--- a/drivers/bcma/driver_chipcommon_pmu.c
296+++ b/drivers/bcma/driver_chipcommon_pmu.c
297@@ -2,7 +2,7 @@
298  * Broadcom specific AMBA
299  * ChipCommon Power Management Unit driver
300  *
301- * Copyright 2009, Michael Buesch <mb@bu3sch.de>
302+ * Copyright 2009, Michael Buesch <m@bues.ch>
303  * Copyright 2007, Broadcom Corporation
304  *
305  * Licensed under the GNU/GPL. See COPYING for details.
306@@ -11,20 +11,47 @@
307 #include "bcma_private.h"
308 #include <linux/bcma/bcma.h>
309 
310-static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
311- u32 offset, u32 mask, u32 set)
312+static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
313 {
314- u32 value;
315+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
316+ bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
317+ return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
318+}
319 
320- bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
321+void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
322+{
323+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
324+ bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
325+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value);
326+}
327+EXPORT_SYMBOL_GPL(bcma_chipco_pll_write);
328+
329+void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
330+ u32 set)
331+{
332+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
333+ bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
334+ bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set);
335+}
336+EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset);
337+
338+void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
339+ u32 offset, u32 mask, u32 set)
340+{
341     bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset);
342     bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
343- value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
344- value &= mask;
345- value |= set;
346- bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value);
347- bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
348+ bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set);
349+}
350+EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset);
351+
352+void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
353+ u32 set)
354+{
355+ bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset);
356+ bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR);
357+ bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set);
358 }
359+EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
360 
361 static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
362 {
363@@ -53,6 +80,7 @@ static void bcma_pmu_resources_init(stru
364         max_msk = 0xFFFF;
365         break;
366     case 43224:
367+ case 43225:
368         break;
369     default:
370         pr_err("PMU resource config unknown for device 0x%04X\n",
371@@ -74,6 +102,7 @@ void bcma_pmu_swreg_init(struct bcma_drv
372     case 0x4313:
373     case 0x4331:
374     case 43224:
375+ case 43225:
376         break;
377     default:
378         pr_err("PMU switch/regulators init unknown for device "
379@@ -81,6 +110,24 @@ void bcma_pmu_swreg_init(struct bcma_drv
380     }
381 }
382 
383+/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
384+void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
385+{
386+ struct bcma_bus *bus = cc->core->bus;
387+ u32 val;
388+
389+ val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL);
390+ if (enable) {
391+ val |= BCMA_CHIPCTL_4331_EXTPA_EN;
392+ if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
393+ val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
394+ } else {
395+ val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;
396+ val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
397+ }
398+ bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
399+}
400+
401 void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
402 {
403     struct bcma_bus *bus = cc->core->bus;
404@@ -90,17 +137,19 @@ void bcma_pmu_workarounds(struct bcma_dr
405         bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
406         break;
407     case 0x4331:
408- pr_err("Enabling Ext PA lines not implemented\n");
409+ /* BCM4331 workaround is SPROM-related, we put it in sprom.c */
410         break;
411     case 43224:
412         if (bus->chipinfo.rev == 0) {
413             pr_err("Workarounds for 43224 rev 0 not fully "
414                 "implemented\n");
415- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
416+ bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0);
417         } else {
418             bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
419         }
420         break;
421+ case 43225:
422+ break;
423     default:
424         pr_err("Workarounds unknown for device 0x%04X\n",
425             bus->chipinfo.id);
426@@ -132,3 +181,129 @@ void bcma_pmu_init(struct bcma_drv_cc *c
427     bcma_pmu_swreg_init(cc);
428     bcma_pmu_workarounds(cc);
429 }
430+
431+u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
432+{
433+ struct bcma_bus *bus = cc->core->bus;
434+
435+ switch (bus->chipinfo.id) {
436+ case 0x4716:
437+ case 0x4748:
438+ case 47162:
439+ case 0x4313:
440+ case 0x5357:
441+ case 0x4749:
442+ case 53572:
443+ /* always 20Mhz */
444+ return 20000 * 1000;
445+ case 0x5356:
446+ case 0x5300:
447+ /* always 25Mhz */
448+ return 25000 * 1000;
449+ default:
450+ pr_warn("No ALP clock specified for %04X device, "
451+ "pmu rev. %d, using default %d Hz\n",
452+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
453+ }
454+ return BCMA_CC_PMU_ALP_CLOCK;
455+}
456+
457+/* Find the output of the "m" pll divider given pll controls that start with
458+ * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
459+ */
460+static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
461+{
462+ u32 tmp, div, ndiv, p1, p2, fc;
463+ struct bcma_bus *bus = cc->core->bus;
464+
465+ BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0));
466+
467+ BUG_ON(!m || m > 4);
468+
469+ if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) {
470+ /* Detect failure in clock setting */
471+ tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
472+ if (tmp & 0x40000)
473+ return 133 * 1000000;
474+ }
475+
476+ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF);
477+ p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT;
478+ p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT;
479+
480+ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF);
481+ div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) &
482+ BCMA_CC_PPL_MDIV_MASK;
483+
484+ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF);
485+ ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
486+
487+ /* Do calculation in Mhz */
488+ fc = bcma_pmu_alp_clock(cc) / 1000000;
489+ fc = (p1 * ndiv * fc) / p2;
490+
491+ /* Return clock in Hertz */
492+ return (fc / div) * 1000000;
493+}
494+
495+/* query bus clock frequency for PMU-enabled chipcommon */
496+u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
497+{
498+ struct bcma_bus *bus = cc->core->bus;
499+
500+ switch (bus->chipinfo.id) {
501+ case 0x4716:
502+ case 0x4748:
503+ case 47162:
504+ return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
505+ BCMA_CC_PMU5_MAINPLL_SSB);
506+ case 0x5356:
507+ return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
508+ BCMA_CC_PMU5_MAINPLL_SSB);
509+ case 0x5357:
510+ case 0x4749:
511+ return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
512+ BCMA_CC_PMU5_MAINPLL_SSB);
513+ case 0x5300:
514+ return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
515+ BCMA_CC_PMU5_MAINPLL_SSB);
516+ case 53572:
517+ return 75000000;
518+ default:
519+ pr_warn("No backplane clock specified for %04X device, "
520+ "pmu rev. %d, using default %d Hz\n",
521+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
522+ }
523+ return BCMA_CC_PMU_HT_CLOCK;
524+}
525+
526+/* query cpu clock frequency for PMU-enabled chipcommon */
527+u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
528+{
529+ struct bcma_bus *bus = cc->core->bus;
530+
531+ if (bus->chipinfo.id == 53572)
532+ return 300000000;
533+
534+ if (cc->pmu.rev >= 5) {
535+ u32 pll;
536+ switch (bus->chipinfo.id) {
537+ case 0x5356:
538+ pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
539+ break;
540+ case 0x5357:
541+ case 0x4749:
542+ pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
543+ break;
544+ default:
545+ pll = BCMA_CC_PMU4716_MAINPLL_PLL0;
546+ break;
547+ }
548+
549+ /* TODO: if (bus->chipinfo.id == 0x5300)
550+ return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */
551+ return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
552+ }
553+
554+ return bcma_pmu_get_clockcontrol(cc);
555+}
556--- /dev/null
557+++ b/drivers/bcma/driver_mips.c
558@@ -0,0 +1,256 @@
559+/*
560+ * Broadcom specific AMBA
561+ * Broadcom MIPS32 74K core driver
562+ *
563+ * Copyright 2009, Broadcom Corporation
564+ * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
565+ * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
566+ * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
567+ *
568+ * Licensed under the GNU/GPL. See COPYING for details.
569+ */
570+
571+#include "bcma_private.h"
572+
573+#include <linux/bcma/bcma.h>
574+
575+#include <linux/serial.h>
576+#include <linux/serial_core.h>
577+#include <linux/serial_reg.h>
578+#include <linux/time.h>
579+
580+/* The 47162a0 hangs when reading MIPS DMP registers registers */
581+static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
582+{
583+ return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
584+ dev->id.id == BCMA_CORE_MIPS_74K;
585+}
586+
587+/* The 5357b0 hangs when reading USB20H DMP registers */
588+static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
589+{
590+ return (dev->bus->chipinfo.id == 0x5357 ||
591+ dev->bus->chipinfo.id == 0x4749) &&
592+ dev->bus->chipinfo.pkg == 11 &&
593+ dev->id.id == BCMA_CORE_USB20_HOST;
594+}
595+
596+static inline u32 mips_read32(struct bcma_drv_mips *mcore,
597+ u16 offset)
598+{
599+ return bcma_read32(mcore->core, offset);
600+}
601+
602+static inline void mips_write32(struct bcma_drv_mips *mcore,
603+ u16 offset,
604+ u32 value)
605+{
606+ bcma_write32(mcore->core, offset, value);
607+}
608+
609+static const u32 ipsflag_irq_mask[] = {
610+ 0,
611+ BCMA_MIPS_IPSFLAG_IRQ1,
612+ BCMA_MIPS_IPSFLAG_IRQ2,
613+ BCMA_MIPS_IPSFLAG_IRQ3,
614+ BCMA_MIPS_IPSFLAG_IRQ4,
615+};
616+
617+static const u32 ipsflag_irq_shift[] = {
618+ 0,
619+ BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
620+ BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
621+ BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
622+ BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
623+};
624+
625+static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
626+{
627+ u32 flag;
628+
629+ if (bcma_core_mips_bcm47162a0_quirk(dev))
630+ return dev->core_index;
631+ if (bcma_core_mips_bcm5357b0_quirk(dev))
632+ return dev->core_index;
633+ flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
634+
635+ return flag & 0x1F;
636+}
637+
638+/* Get the MIPS IRQ assignment for a specified device.
639+ * If unassigned, 0 is returned.
640+ */
641+unsigned int bcma_core_mips_irq(struct bcma_device *dev)
642+{
643+ struct bcma_device *mdev = dev->bus->drv_mips.core;
644+ u32 irqflag;
645+ unsigned int irq;
646+
647+ irqflag = bcma_core_mips_irqflag(dev);
648+
649+ for (irq = 1; irq <= 4; irq++)
650+ if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
651+ (1 << irqflag))
652+ return irq;
653+
654+ return 0;
655+}
656+EXPORT_SYMBOL(bcma_core_mips_irq);
657+
658+static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
659+{
660+ unsigned int oldirq = bcma_core_mips_irq(dev);
661+ struct bcma_bus *bus = dev->bus;
662+ struct bcma_device *mdev = bus->drv_mips.core;
663+ u32 irqflag;
664+
665+ irqflag = bcma_core_mips_irqflag(dev);
666+ BUG_ON(oldirq == 6);
667+
668+ dev->irq = irq + 2;
669+
670+ /* clear the old irq */
671+ if (oldirq == 0)
672+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
673+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
674+ ~(1 << irqflag));
675+ else
676+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
677+
678+ /* assign the new one */
679+ if (irq == 0) {
680+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
681+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
682+ (1 << irqflag));
683+ } else {
684+ u32 oldirqflag = bcma_read32(mdev,
685+ BCMA_MIPS_MIPS74K_INTMASK(irq));
686+ if (oldirqflag) {
687+ struct bcma_device *core;
688+
689+ /* backplane irq line is in use, find out who uses
690+ * it and set user to irq 0
691+ */
692+ list_for_each_entry_reverse(core, &bus->cores, list) {
693+ if ((1 << bcma_core_mips_irqflag(core)) ==
694+ oldirqflag) {
695+ bcma_core_mips_set_irq(core, 0);
696+ break;
697+ }
698+ }
699+ }
700+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
701+ 1 << irqflag);
702+ }
703+
704+ pr_info("set_irq: core 0x%04x, irq %d => %d\n",
705+ dev->id.id, oldirq + 2, irq + 2);
706+}
707+
708+static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
709+{
710+ int i;
711+ static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
712+ printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
713+ for (i = 0; i <= 6; i++)
714+ printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
715+ printk("\n");
716+}
717+
718+static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
719+{
720+ struct bcma_device *core;
721+
722+ list_for_each_entry_reverse(core, &bus->cores, list) {
723+ bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
724+ }
725+}
726+
727+u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
728+{
729+ struct bcma_bus *bus = mcore->core->bus;
730+
731+ if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
732+ return bcma_pmu_get_clockcpu(&bus->drv_cc);
733+
734+ pr_err("No PMU available, need this to get the cpu clock\n");
735+ return 0;
736+}
737+EXPORT_SYMBOL(bcma_cpu_clock);
738+
739+static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
740+{
741+ struct bcma_bus *bus = mcore->core->bus;
742+
743+ switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
744+ case BCMA_CC_FLASHT_STSER:
745+ case BCMA_CC_FLASHT_ATSER:
746+ pr_err("Serial flash not supported.\n");
747+ break;
748+ case BCMA_CC_FLASHT_PARA:
749+ pr_info("found parallel flash.\n");
750+ bus->drv_cc.pflash.window = 0x1c000000;
751+ bus->drv_cc.pflash.window_size = 0x02000000;
752+
753+ if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
754+ BCMA_CC_FLASH_CFG_DS) == 0)
755+ bus->drv_cc.pflash.buswidth = 1;
756+ else
757+ bus->drv_cc.pflash.buswidth = 2;
758+ break;
759+ default:
760+ pr_err("flash not supported.\n");
761+ }
762+}
763+
764+void bcma_core_mips_init(struct bcma_drv_mips *mcore)
765+{
766+ struct bcma_bus *bus;
767+ struct bcma_device *core;
768+ bus = mcore->core->bus;
769+
770+ pr_info("Initializing MIPS core...\n");
771+
772+ if (!mcore->setup_done)
773+ mcore->assigned_irqs = 1;
774+
775+ /* Assign IRQs to all cores on the bus */
776+ list_for_each_entry_reverse(core, &bus->cores, list) {
777+ int mips_irq;
778+ if (core->irq)
779+ continue;
780+
781+ mips_irq = bcma_core_mips_irq(core);
782+ if (mips_irq > 4)
783+ core->irq = 0;
784+ else
785+ core->irq = mips_irq + 2;
786+ if (core->irq > 5)
787+ continue;
788+ switch (core->id.id) {
789+ case BCMA_CORE_PCI:
790+ case BCMA_CORE_PCIE:
791+ case BCMA_CORE_ETHERNET:
792+ case BCMA_CORE_ETHERNET_GBIT:
793+ case BCMA_CORE_MAC_GBIT:
794+ case BCMA_CORE_80211:
795+ case BCMA_CORE_USB20_HOST:
796+ /* These devices get their own IRQ line if available,
797+ * the rest goes on IRQ0
798+ */
799+ if (mcore->assigned_irqs <= 4)
800+ bcma_core_mips_set_irq(core,
801+ mcore->assigned_irqs++);
802+ break;
803+ }
804+ }
805+ pr_info("IRQ reconfiguration done\n");
806+ bcma_core_mips_dump_irq(bus);
807+
808+ if (mcore->setup_done)
809+ return;
810+
811+ bcma_chipco_serial_init(&bus->drv_cc);
812+ bcma_core_mips_flash_detect(mcore);
813+ mcore->setup_done = true;
814+}
815--- a/drivers/bcma/driver_pci.c
816+++ b/drivers/bcma/driver_pci.c
817@@ -3,7 +3,7 @@
818  * PCI Core
819  *
820  * Copyright 2005, Broadcom Corporation
821- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
822+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
823  *
824  * Licensed under the GNU/GPL. See COPYING for details.
825  */
826@@ -157,7 +157,81 @@ static void bcma_pcicore_serdes_workarou
827  * Init.
828  **************************************************/
829 
830-void bcma_core_pci_init(struct bcma_drv_pci *pc)
831+static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
832 {
833     bcma_pcicore_serdes_workaround(pc);
834 }
835+
836+static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
837+{
838+ struct bcma_bus *bus = pc->core->bus;
839+ u16 chipid_top;
840+
841+ chipid_top = (bus->chipinfo.id & 0xFF00);
842+ if (chipid_top != 0x4700 &&
843+ chipid_top != 0x5300)
844+ return false;
845+
846+#ifdef CONFIG_SSB_DRIVER_PCICORE
847+ if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI)
848+ return false;
849+#endif /* CONFIG_SSB_DRIVER_PCICORE */
850+
851+#if 0
852+ /* TODO: on BCMA we use address from EROM instead of magic formula */
853+ u32 tmp;
854+ return !mips_busprobe32(tmp, (bus->mmio +
855+ (pc->core->core_index * BCMA_CORE_SIZE)));
856+#endif
857+
858+ return true;
859+}
860+
861+void bcma_core_pci_init(struct bcma_drv_pci *pc)
862+{
863+ if (pc->setup_done)
864+ return;
865+
866+ if (bcma_core_pci_is_in_hostmode(pc)) {
867+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
868+ bcma_core_pci_hostmode_init(pc);
869+#else
870+ pr_err("Driver compiled without support for hostmode PCI\n");
871+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
872+ } else {
873+ bcma_core_pci_clientmode_init(pc);
874+ }
875+
876+ pc->setup_done = true;
877+}
878+
879+int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
880+ bool enable)
881+{
882+ struct pci_dev *pdev = pc->core->bus->host_pci;
883+ u32 coremask, tmp;
884+ int err = 0;
885+
886+ if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
887+ /* This bcma device is not on a PCI host-bus. So the IRQs are
888+ * not routed through the PCI core.
889+ * So we must not enable routing through the PCI core. */
890+ goto out;
891+ }
892+
893+ err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
894+ if (err)
895+ goto out;
896+
897+ coremask = BIT(core->core_index) << 8;
898+ if (enable)
899+ tmp |= coremask;
900+ else
901+ tmp &= ~coremask;
902+
903+ err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
904+
905+out:
906+ return err;
907+}
908+EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
909--- /dev/null
910+++ b/drivers/bcma/driver_pci_host.c
911@@ -0,0 +1,14 @@
912+/*
913+ * Broadcom specific AMBA
914+ * PCI Core in hostmode
915+ *
916+ * Licensed under the GNU/GPL. See COPYING for details.
917+ */
918+
919+#include "bcma_private.h"
920+#include <linux/bcma/bcma.h>
921+
922+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
923+{
924+ pr_err("No support for PCI core in hostmode yet\n");
925+}
926--- a/drivers/bcma/host_pci.c
927+++ b/drivers/bcma/host_pci.c
928@@ -9,6 +9,7 @@
929 #include <linux/slab.h>
930 #include <linux/bcma/bcma.h>
931 #include <linux/pci.h>
932+#include <linux/module.h>
933 
934 static void bcma_host_pci_switch_core(struct bcma_device *core)
935 {
936@@ -20,50 +21,108 @@ static void bcma_host_pci_switch_core(st
937     pr_debug("Switched to core: 0x%X\n", core->id.id);
938 }
939 
940-static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
941-{
942+/* Provides access to the requested core. Returns base offset that has to be
943+ * used. It makes use of fixed windows when possible. */
944+static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core)
945+{
946+ switch (core->id.id) {
947+ case BCMA_CORE_CHIPCOMMON:
948+ return 3 * BCMA_CORE_SIZE;
949+ case BCMA_CORE_PCIE:
950+ return 2 * BCMA_CORE_SIZE;
951+ }
952+
953     if (core->bus->mapped_core != core)
954         bcma_host_pci_switch_core(core);
955+ return 0;
956+}
957+
958+static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
959+{
960+ offset += bcma_host_pci_provide_access_to_core(core);
961     return ioread8(core->bus->mmio + offset);
962 }
963 
964 static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
965 {
966- if (core->bus->mapped_core != core)
967- bcma_host_pci_switch_core(core);
968+ offset += bcma_host_pci_provide_access_to_core(core);
969     return ioread16(core->bus->mmio + offset);
970 }
971 
972 static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
973 {
974- if (core->bus->mapped_core != core)
975- bcma_host_pci_switch_core(core);
976+ offset += bcma_host_pci_provide_access_to_core(core);
977     return ioread32(core->bus->mmio + offset);
978 }
979 
980 static void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
981                  u8 value)
982 {
983- if (core->bus->mapped_core != core)
984- bcma_host_pci_switch_core(core);
985+ offset += bcma_host_pci_provide_access_to_core(core);
986     iowrite8(value, core->bus->mmio + offset);
987 }
988 
989 static void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
990                  u16 value)
991 {
992- if (core->bus->mapped_core != core)
993- bcma_host_pci_switch_core(core);
994+ offset += bcma_host_pci_provide_access_to_core(core);
995     iowrite16(value, core->bus->mmio + offset);
996 }
997 
998 static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
999                  u32 value)
1000 {
1001+ offset += bcma_host_pci_provide_access_to_core(core);
1002+ iowrite32(value, core->bus->mmio + offset);
1003+}
1004+
1005+#ifdef CONFIG_BCMA_BLOCKIO
1006+void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
1007+ size_t count, u16 offset, u8 reg_width)
1008+{
1009+ void __iomem *addr = core->bus->mmio + offset;
1010     if (core->bus->mapped_core != core)
1011         bcma_host_pci_switch_core(core);
1012- iowrite32(value, core->bus->mmio + offset);
1013+ switch (reg_width) {
1014+ case sizeof(u8):
1015+ ioread8_rep(addr, buffer, count);
1016+ break;
1017+ case sizeof(u16):
1018+ WARN_ON(count & 1);
1019+ ioread16_rep(addr, buffer, count >> 1);
1020+ break;
1021+ case sizeof(u32):
1022+ WARN_ON(count & 3);
1023+ ioread32_rep(addr, buffer, count >> 2);
1024+ break;
1025+ default:
1026+ WARN_ON(1);
1027+ }
1028+}
1029+
1030+void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
1031+ size_t count, u16 offset, u8 reg_width)
1032+{
1033+ void __iomem *addr = core->bus->mmio + offset;
1034+ if (core->bus->mapped_core != core)
1035+ bcma_host_pci_switch_core(core);
1036+ switch (reg_width) {
1037+ case sizeof(u8):
1038+ iowrite8_rep(addr, buffer, count);
1039+ break;
1040+ case sizeof(u16):
1041+ WARN_ON(count & 1);
1042+ iowrite16_rep(addr, buffer, count >> 1);
1043+ break;
1044+ case sizeof(u32):
1045+ WARN_ON(count & 3);
1046+ iowrite32_rep(addr, buffer, count >> 2);
1047+ break;
1048+ default:
1049+ WARN_ON(1);
1050+ }
1051 }
1052+#endif
1053 
1054 static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
1055 {
1056@@ -87,6 +146,10 @@ const struct bcma_host_ops bcma_host_pci
1057     .write8 = bcma_host_pci_write8,
1058     .write16 = bcma_host_pci_write16,
1059     .write32 = bcma_host_pci_write32,
1060+#ifdef CONFIG_BCMA_BLOCKIO
1061+ .block_read = bcma_host_pci_block_read,
1062+ .block_write = bcma_host_pci_block_write,
1063+#endif
1064     .aread32 = bcma_host_pci_aread32,
1065     .awrite32 = bcma_host_pci_awrite32,
1066 };
1067@@ -171,10 +234,46 @@ static void bcma_host_pci_remove(struct
1068     pci_set_drvdata(dev, NULL);
1069 }
1070 
1071+#ifdef CONFIG_PM
1072+static int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state)
1073+{
1074+ /* Host specific */
1075+ pci_save_state(dev);
1076+ pci_disable_device(dev);
1077+ pci_set_power_state(dev, pci_choose_state(dev, state));
1078+
1079+ return 0;
1080+}
1081+
1082+static int bcma_host_pci_resume(struct pci_dev *dev)
1083+{
1084+ struct bcma_bus *bus = pci_get_drvdata(dev);
1085+ int err;
1086+
1087+ /* Host specific */
1088+ pci_set_power_state(dev, 0);
1089+ err = pci_enable_device(dev);
1090+ if (err)
1091+ return err;
1092+ pci_restore_state(dev);
1093+
1094+ /* Bus specific */
1095+ err = bcma_bus_resume(bus);
1096+ if (err)
1097+ return err;
1098+
1099+ return 0;
1100+}
1101+#else /* CONFIG_PM */
1102+# define bcma_host_pci_suspend NULL
1103+# define bcma_host_pci_resume NULL
1104+#endif /* CONFIG_PM */
1105+
1106 static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
1107     { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
1108     { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
1109     { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
1110+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
1111     { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
1112     { 0, },
1113 };
1114@@ -185,6 +284,8 @@ static struct pci_driver bcma_pci_bridge
1115     .id_table = bcma_pci_bridge_tbl,
1116     .probe = bcma_host_pci_probe,
1117     .remove = bcma_host_pci_remove,
1118+ .suspend = bcma_host_pci_suspend,
1119+ .resume = bcma_host_pci_resume,
1120 };
1121 
1122 int __init bcma_host_pci_init(void)
1123--- /dev/null
1124+++ b/drivers/bcma/host_soc.c
1125@@ -0,0 +1,183 @@
1126+/*
1127+ * Broadcom specific AMBA
1128+ * System on Chip (SoC) Host
1129+ *
1130+ * Licensed under the GNU/GPL. See COPYING for details.
1131+ */
1132+
1133+#include "bcma_private.h"
1134+#include "scan.h"
1135+#include <linux/bcma/bcma.h>
1136+#include <linux/bcma/bcma_soc.h>
1137+
1138+static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
1139+{
1140+ return readb(core->io_addr + offset);
1141+}
1142+
1143+static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
1144+{
1145+ return readw(core->io_addr + offset);
1146+}
1147+
1148+static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
1149+{
1150+ return readl(core->io_addr + offset);
1151+}
1152+
1153+static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
1154+ u8 value)
1155+{
1156+ writeb(value, core->io_addr + offset);
1157+}
1158+
1159+static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
1160+ u16 value)
1161+{
1162+ writew(value, core->io_addr + offset);
1163+}
1164+
1165+static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
1166+ u32 value)
1167+{
1168+ writel(value, core->io_addr + offset);
1169+}
1170+
1171+#ifdef CONFIG_BCMA_BLOCKIO
1172+static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
1173+ size_t count, u16 offset, u8 reg_width)
1174+{
1175+ void __iomem *addr = core->io_addr + offset;
1176+
1177+ switch (reg_width) {
1178+ case sizeof(u8): {
1179+ u8 *buf = buffer;
1180+
1181+ while (count) {
1182+ *buf = __raw_readb(addr);
1183+ buf++;
1184+ count--;
1185+ }
1186+ break;
1187+ }
1188+ case sizeof(u16): {
1189+ __le16 *buf = buffer;
1190+
1191+ WARN_ON(count & 1);
1192+ while (count) {
1193+ *buf = (__force __le16)__raw_readw(addr);
1194+ buf++;
1195+ count -= 2;
1196+ }
1197+ break;
1198+ }
1199+ case sizeof(u32): {
1200+ __le32 *buf = buffer;
1201+
1202+ WARN_ON(count & 3);
1203+ while (count) {
1204+ *buf = (__force __le32)__raw_readl(addr);
1205+ buf++;
1206+ count -= 4;
1207+ }
1208+ break;
1209+ }
1210+ default:
1211+ WARN_ON(1);
1212+ }
1213+}
1214+
1215+static void bcma_host_soc_block_write(struct bcma_device *core,
1216+ const void *buffer,
1217+ size_t count, u16 offset, u8 reg_width)
1218+{
1219+ void __iomem *addr = core->io_addr + offset;
1220+
1221+ switch (reg_width) {
1222+ case sizeof(u8): {
1223+ const u8 *buf = buffer;
1224+
1225+ while (count) {
1226+ __raw_writeb(*buf, addr);
1227+ buf++;
1228+ count--;
1229+ }
1230+ break;
1231+ }
1232+ case sizeof(u16): {
1233+ const __le16 *buf = buffer;
1234+
1235+ WARN_ON(count & 1);
1236+ while (count) {
1237+ __raw_writew((__force u16)(*buf), addr);
1238+ buf++;
1239+ count -= 2;
1240+ }
1241+ break;
1242+ }
1243+ case sizeof(u32): {
1244+ const __le32 *buf = buffer;
1245+
1246+ WARN_ON(count & 3);
1247+ while (count) {
1248+ __raw_writel((__force u32)(*buf), addr);
1249+ buf++;
1250+ count -= 4;
1251+ }
1252+ break;
1253+ }
1254+ default:
1255+ WARN_ON(1);
1256+ }
1257+}
1258+#endif /* CONFIG_BCMA_BLOCKIO */
1259+
1260+static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
1261+{
1262+ return readl(core->io_wrap + offset);
1263+}
1264+
1265+static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
1266+ u32 value)
1267+{
1268+ writel(value, core->io_wrap + offset);
1269+}
1270+
1271+const struct bcma_host_ops bcma_host_soc_ops = {
1272+ .read8 = bcma_host_soc_read8,
1273+ .read16 = bcma_host_soc_read16,
1274+ .read32 = bcma_host_soc_read32,
1275+ .write8 = bcma_host_soc_write8,
1276+ .write16 = bcma_host_soc_write16,
1277+ .write32 = bcma_host_soc_write32,
1278+#ifdef CONFIG_BCMA_BLOCKIO
1279+ .block_read = bcma_host_soc_block_read,
1280+ .block_write = bcma_host_soc_block_write,
1281+#endif
1282+ .aread32 = bcma_host_soc_aread32,
1283+ .awrite32 = bcma_host_soc_awrite32,
1284+};
1285+
1286+int __init bcma_host_soc_register(struct bcma_soc *soc)
1287+{
1288+ struct bcma_bus *bus = &soc->bus;
1289+ int err;
1290+
1291+ /* iomap only first core. We have to read some register on this core
1292+ * to scan the bus.
1293+ */
1294+ bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
1295+ if (!bus->mmio)
1296+ return -ENOMEM;
1297+
1298+ /* Host specific */
1299+ bus->hosttype = BCMA_HOSTTYPE_SOC;
1300+ bus->ops = &bcma_host_soc_ops;
1301+
1302+ /* Register */
1303+ err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
1304+ if (err)
1305+ iounmap(bus->mmio);
1306+
1307+ return err;
1308+}
1309--- a/drivers/bcma/main.c
1310+++ b/drivers/bcma/main.c
1311@@ -6,7 +6,9 @@
1312  */
1313 
1314 #include "bcma_private.h"
1315+#include <linux/module.h>
1316 #include <linux/bcma/bcma.h>
1317+#include <linux/slab.h>
1318 
1319 MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
1320 MODULE_LICENSE("GPL");
1321@@ -14,6 +16,7 @@ MODULE_LICENSE("GPL");
1322 static int bcma_bus_match(struct device *dev, struct device_driver *drv);
1323 static int bcma_device_probe(struct device *dev);
1324 static int bcma_device_remove(struct device *dev);
1325+static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env);
1326 
1327 static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
1328 {
1329@@ -48,6 +51,7 @@ static struct bus_type bcma_bus_type = {
1330     .match = bcma_bus_match,
1331     .probe = bcma_device_probe,
1332     .remove = bcma_device_remove,
1333+ .uevent = bcma_device_uevent,
1334     .dev_attrs = bcma_device_attrs,
1335 };
1336 
1337@@ -65,6 +69,10 @@ static struct bcma_device *bcma_find_cor
1338 static void bcma_release_core_dev(struct device *dev)
1339 {
1340     struct bcma_device *core = container_of(dev, struct bcma_device, dev);
1341+ if (core->io_addr)
1342+ iounmap(core->io_addr);
1343+ if (core->io_wrap)
1344+ iounmap(core->io_wrap);
1345     kfree(core);
1346 }
1347 
1348@@ -79,6 +87,7 @@ static int bcma_register_cores(struct bc
1349         case BCMA_CORE_CHIPCOMMON:
1350         case BCMA_CORE_PCI:
1351         case BCMA_CORE_PCIE:
1352+ case BCMA_CORE_MIPS_74K:
1353             continue;
1354         }
1355 
1356@@ -89,8 +98,13 @@ static int bcma_register_cores(struct bc
1357         switch (bus->hosttype) {
1358         case BCMA_HOSTTYPE_PCI:
1359             core->dev.parent = &bus->host_pci->dev;
1360+ core->dma_dev = &bus->host_pci->dev;
1361+ core->irq = bus->host_pci->irq;
1362+ break;
1363+ case BCMA_HOSTTYPE_SOC:
1364+ core->dev.dma_mask = &core->dev.coherent_dma_mask;
1365+ core->dma_dev = &core->dev;
1366             break;
1367- case BCMA_HOSTTYPE_NONE:
1368         case BCMA_HOSTTYPE_SDIO:
1369             break;
1370         }
1371@@ -137,6 +151,13 @@ int bcma_bus_register(struct bcma_bus *b
1372         bcma_core_chipcommon_init(&bus->drv_cc);
1373     }
1374 
1375+ /* Init MIPS core */
1376+ core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
1377+ if (core) {
1378+ bus->drv_mips.core = core;
1379+ bcma_core_mips_init(&bus->drv_mips);
1380+ }
1381+
1382     /* Init PCIE core */
1383     core = bcma_find_core(bus, BCMA_CORE_PCIE);
1384     if (core) {
1385@@ -144,6 +165,15 @@ int bcma_bus_register(struct bcma_bus *b
1386         bcma_core_pci_init(&bus->drv_pci);
1387     }
1388 
1389+ /* Try to get SPROM */
1390+ err = bcma_sprom_get(bus);
1391+ if (err == -ENOENT) {
1392+ pr_err("No SPROM available\n");
1393+ } else if (err) {
1394+ pr_err("Failed to get SPROM: %d\n", err);
1395+ return -ENOENT;
1396+ }
1397+
1398     /* Register found cores */
1399     bcma_register_cores(bus);
1400 
1401@@ -151,13 +181,80 @@ int bcma_bus_register(struct bcma_bus *b
1402 
1403     return 0;
1404 }
1405-EXPORT_SYMBOL_GPL(bcma_bus_register);
1406 
1407 void bcma_bus_unregister(struct bcma_bus *bus)
1408 {
1409     bcma_unregister_cores(bus);
1410 }
1411-EXPORT_SYMBOL_GPL(bcma_bus_unregister);
1412+
1413+int __init bcma_bus_early_register(struct bcma_bus *bus,
1414+ struct bcma_device *core_cc,
1415+ struct bcma_device *core_mips)
1416+{
1417+ int err;
1418+ struct bcma_device *core;
1419+ struct bcma_device_id match;
1420+
1421+ bcma_init_bus(bus);
1422+
1423+ match.manuf = BCMA_MANUF_BCM;
1424+ match.id = BCMA_CORE_CHIPCOMMON;
1425+ match.class = BCMA_CL_SIM;
1426+ match.rev = BCMA_ANY_REV;
1427+
1428+ /* Scan for chip common core */
1429+ err = bcma_bus_scan_early(bus, &match, core_cc);
1430+ if (err) {
1431+ pr_err("Failed to scan for common core: %d\n", err);
1432+ return -1;
1433+ }
1434+
1435+ match.manuf = BCMA_MANUF_MIPS;
1436+ match.id = BCMA_CORE_MIPS_74K;
1437+ match.class = BCMA_CL_SIM;
1438+ match.rev = BCMA_ANY_REV;
1439+
1440+ /* Scan for mips core */
1441+ err = bcma_bus_scan_early(bus, &match, core_mips);
1442+ if (err) {
1443+ pr_err("Failed to scan for mips core: %d\n", err);
1444+ return -1;
1445+ }
1446+
1447+ /* Init CC core */
1448+ core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
1449+ if (core) {
1450+ bus->drv_cc.core = core;
1451+ bcma_core_chipcommon_init(&bus->drv_cc);
1452+ }
1453+
1454+ /* Init MIPS core */
1455+ core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
1456+ if (core) {
1457+ bus->drv_mips.core = core;
1458+ bcma_core_mips_init(&bus->drv_mips);
1459+ }
1460+
1461+ pr_info("Early bus registered\n");
1462+
1463+ return 0;
1464+}
1465+
1466+#ifdef CONFIG_PM
1467+int bcma_bus_resume(struct bcma_bus *bus)
1468+{
1469+ struct bcma_device *core;
1470+
1471+ /* Init CC core */
1472+ core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
1473+ if (core) {
1474+ bus->drv_cc.setup_done = false;
1475+ bcma_core_chipcommon_init(&bus->drv_cc);
1476+ }
1477+
1478+ return 0;
1479+}
1480+#endif
1481 
1482 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
1483 {
1484@@ -217,6 +314,16 @@ static int bcma_device_remove(struct dev
1485     return 0;
1486 }
1487 
1488+static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
1489+{
1490+ struct bcma_device *core = container_of(dev, struct bcma_device, dev);
1491+
1492+ return add_uevent_var(env,
1493+ "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X",
1494+ core->id.manuf, core->id.id,
1495+ core->id.rev, core->id.class);
1496+}
1497+
1498 static int __init bcma_modinit(void)
1499 {
1500     int err;
1501--- a/drivers/bcma/scan.c
1502+++ b/drivers/bcma/scan.c
1503@@ -200,18 +200,162 @@ static s32 bcma_erom_get_addr_desc(struc
1504     return addrl;
1505 }
1506 
1507-int bcma_bus_scan(struct bcma_bus *bus)
1508+static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus,
1509+ u16 index)
1510 {
1511- u32 erombase;
1512- u32 __iomem *eromptr, *eromend;
1513+ struct bcma_device *core;
1514 
1515+ list_for_each_entry(core, &bus->cores, list) {
1516+ if (core->core_index == index)
1517+ return core;
1518+ }
1519+ return NULL;
1520+}
1521+
1522+static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
1523+ struct bcma_device_id *match, int core_num,
1524+ struct bcma_device *core)
1525+{
1526+ s32 tmp;
1527+ u8 i, j;
1528     s32 cia, cib;
1529     u8 ports[2], wrappers[2];
1530 
1531+ /* get CIs */
1532+ cia = bcma_erom_get_ci(bus, eromptr);
1533+ if (cia < 0) {
1534+ bcma_erom_push_ent(eromptr);
1535+ if (bcma_erom_is_end(bus, eromptr))
1536+ return -ESPIPE;
1537+ return -EILSEQ;
1538+ }
1539+ cib = bcma_erom_get_ci(bus, eromptr);
1540+ if (cib < 0)
1541+ return -EILSEQ;
1542+
1543+ /* parse CIs */
1544+ core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
1545+ core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
1546+ core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
1547+ ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
1548+ ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
1549+ wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
1550+ wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
1551+ core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
1552+
1553+ if (((core->id.manuf == BCMA_MANUF_ARM) &&
1554+ (core->id.id == 0xFFF)) ||
1555+ (ports[1] == 0)) {
1556+ bcma_erom_skip_component(bus, eromptr);
1557+ return -ENXIO;
1558+ }
1559+
1560+ /* check if component is a core at all */
1561+ if (wrappers[0] + wrappers[1] == 0) {
1562+ /* we could save addrl of the router
1563+ if (cid == BCMA_CORE_OOB_ROUTER)
1564+ */
1565+ bcma_erom_skip_component(bus, eromptr);
1566+ return -ENXIO;
1567+ }
1568+
1569+ if (bcma_erom_is_bridge(bus, eromptr)) {
1570+ bcma_erom_skip_component(bus, eromptr);
1571+ return -ENXIO;
1572+ }
1573+
1574+ if (bcma_find_core_by_index(bus, core_num)) {
1575+ bcma_erom_skip_component(bus, eromptr);
1576+ return -ENODEV;
1577+ }
1578+
1579+ if (match && ((match->manuf != BCMA_ANY_MANUF &&
1580+ match->manuf != core->id.manuf) ||
1581+ (match->id != BCMA_ANY_ID && match->id != core->id.id) ||
1582+ (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) ||
1583+ (match->class != BCMA_ANY_CLASS && match->class != core->id.class)
1584+ )) {
1585+ bcma_erom_skip_component(bus, eromptr);
1586+ return -ENODEV;
1587+ }
1588+
1589+ /* get & parse master ports */
1590+ for (i = 0; i < ports[0]; i++) {
1591+ s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
1592+ if (mst_port_d < 0)
1593+ return -EILSEQ;
1594+ }
1595+
1596+ /* get & parse slave ports */
1597+ for (i = 0; i < ports[1]; i++) {
1598+ for (j = 0; ; j++) {
1599+ tmp = bcma_erom_get_addr_desc(bus, eromptr,
1600+ SCAN_ADDR_TYPE_SLAVE, i);
1601+ if (tmp < 0) {
1602+ /* no more entries for port _i_ */
1603+ /* pr_debug("erom: slave port %d "
1604+ * "has %d descriptors\n", i, j); */
1605+ break;
1606+ } else {
1607+ if (i == 0 && j == 0)
1608+ core->addr = tmp;
1609+ }
1610+ }
1611+ }
1612+
1613+ /* get & parse master wrappers */
1614+ for (i = 0; i < wrappers[0]; i++) {
1615+ for (j = 0; ; j++) {
1616+ tmp = bcma_erom_get_addr_desc(bus, eromptr,
1617+ SCAN_ADDR_TYPE_MWRAP, i);
1618+ if (tmp < 0) {
1619+ /* no more entries for port _i_ */
1620+ /* pr_debug("erom: master wrapper %d "
1621+ * "has %d descriptors\n", i, j); */
1622+ break;
1623+ } else {
1624+ if (i == 0 && j == 0)
1625+ core->wrap = tmp;
1626+ }
1627+ }
1628+ }
1629+
1630+ /* get & parse slave wrappers */
1631+ for (i = 0; i < wrappers[1]; i++) {
1632+ u8 hack = (ports[1] == 1) ? 0 : 1;
1633+ for (j = 0; ; j++) {
1634+ tmp = bcma_erom_get_addr_desc(bus, eromptr,
1635+ SCAN_ADDR_TYPE_SWRAP, i + hack);
1636+ if (tmp < 0) {
1637+ /* no more entries for port _i_ */
1638+ /* pr_debug("erom: master wrapper %d "
1639+ * has %d descriptors\n", i, j); */
1640+ break;
1641+ } else {
1642+ if (wrappers[0] == 0 && !i && !j)
1643+ core->wrap = tmp;
1644+ }
1645+ }
1646+ }
1647+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
1648+ core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE);
1649+ if (!core->io_addr)
1650+ return -ENOMEM;
1651+ core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE);
1652+ if (!core->io_wrap) {
1653+ iounmap(core->io_addr);
1654+ return -ENOMEM;
1655+ }
1656+ }
1657+ return 0;
1658+}
1659+
1660+void bcma_init_bus(struct bcma_bus *bus)
1661+{
1662     s32 tmp;
1663- u8 i, j;
1664 
1665- int err;
1666+ if (bus->init_done)
1667+ return;
1668 
1669     INIT_LIST_HEAD(&bus->cores);
1670     bus->nr_cores = 0;
1671@@ -222,9 +366,27 @@ int bcma_bus_scan(struct bcma_bus *bus)
1672     bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
1673     bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
1674     bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
1675+ bus->init_done = true;
1676+}
1677+
1678+int bcma_bus_scan(struct bcma_bus *bus)
1679+{
1680+ u32 erombase;
1681+ u32 __iomem *eromptr, *eromend;
1682+
1683+ int err, core_num = 0;
1684+
1685+ bcma_init_bus(bus);
1686 
1687     erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
1688- eromptr = bus->mmio;
1689+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
1690+ eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
1691+ if (!eromptr)
1692+ return -ENOMEM;
1693+ } else {
1694+ eromptr = bus->mmio;
1695+ }
1696+
1697     eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
1698 
1699     bcma_scan_switch_core(bus, erombase);
1700@@ -236,125 +398,89 @@ int bcma_bus_scan(struct bcma_bus *bus)
1701         INIT_LIST_HEAD(&core->list);
1702         core->bus = bus;
1703 
1704- /* get CIs */
1705- cia = bcma_erom_get_ci(bus, &eromptr);
1706- if (cia < 0) {
1707- bcma_erom_push_ent(&eromptr);
1708- if (bcma_erom_is_end(bus, &eromptr))
1709- break;
1710- err= -EILSEQ;
1711- goto out;
1712- }
1713- cib = bcma_erom_get_ci(bus, &eromptr);
1714- if (cib < 0) {
1715- err= -EILSEQ;
1716- goto out;
1717- }
1718-
1719- /* parse CIs */
1720- core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
1721- core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
1722- core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
1723- ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
1724- ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
1725- wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
1726- wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
1727- core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
1728-
1729- if (((core->id.manuf == BCMA_MANUF_ARM) &&
1730- (core->id.id == 0xFFF)) ||
1731- (ports[1] == 0)) {
1732- bcma_erom_skip_component(bus, &eromptr);
1733+ err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
1734+ if (err == -ENODEV) {
1735+ core_num++;
1736             continue;
1737- }
1738-
1739- /* check if component is a core at all */
1740- if (wrappers[0] + wrappers[1] == 0) {
1741- /* we could save addrl of the router
1742- if (cid == BCMA_CORE_OOB_ROUTER)
1743- */
1744- bcma_erom_skip_component(bus, &eromptr);
1745+ } else if (err == -ENXIO)
1746             continue;
1747- }
1748+ else if (err == -ESPIPE)
1749+ break;
1750+ else if (err < 0)
1751+ return err;
1752 
1753- if (bcma_erom_is_bridge(bus, &eromptr)) {
1754- bcma_erom_skip_component(bus, &eromptr);
1755- continue;
1756- }
1757+ core->core_index = core_num++;
1758+ bus->nr_cores++;
1759 
1760- /* get & parse master ports */
1761- for (i = 0; i < ports[0]; i++) {
1762- u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr);
1763- if (mst_port_d < 0) {
1764- err= -EILSEQ;
1765- goto out;
1766- }
1767- }
1768+ pr_info("Core %d found: %s "
1769+ "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
1770+ core->core_index, bcma_device_name(&core->id),
1771+ core->id.manuf, core->id.id, core->id.rev,
1772+ core->id.class);
1773 
1774- /* get & parse slave ports */
1775- for (i = 0; i < ports[1]; i++) {
1776- for (j = 0; ; j++) {
1777- tmp = bcma_erom_get_addr_desc(bus, &eromptr,
1778- SCAN_ADDR_TYPE_SLAVE, i);
1779- if (tmp < 0) {
1780- /* no more entries for port _i_ */
1781- /* pr_debug("erom: slave port %d "
1782- * "has %d descriptors\n", i, j); */
1783- break;
1784- } else {
1785- if (i == 0 && j == 0)
1786- core->addr = tmp;
1787- }
1788- }
1789- }
1790+ list_add(&core->list, &bus->cores);
1791+ }
1792 
1793- /* get & parse master wrappers */
1794- for (i = 0; i < wrappers[0]; i++) {
1795- for (j = 0; ; j++) {
1796- tmp = bcma_erom_get_addr_desc(bus, &eromptr,
1797- SCAN_ADDR_TYPE_MWRAP, i);
1798- if (tmp < 0) {
1799- /* no more entries for port _i_ */
1800- /* pr_debug("erom: master wrapper %d "
1801- * "has %d descriptors\n", i, j); */
1802- break;
1803- } else {
1804- if (i == 0 && j == 0)
1805- core->wrap = tmp;
1806- }
1807- }
1808- }
1809+ if (bus->hosttype == BCMA_HOSTTYPE_SOC)
1810+ iounmap(eromptr);
1811 
1812- /* get & parse slave wrappers */
1813- for (i = 0; i < wrappers[1]; i++) {
1814- u8 hack = (ports[1] == 1) ? 0 : 1;
1815- for (j = 0; ; j++) {
1816- tmp = bcma_erom_get_addr_desc(bus, &eromptr,
1817- SCAN_ADDR_TYPE_SWRAP, i + hack);
1818- if (tmp < 0) {
1819- /* no more entries for port _i_ */
1820- /* pr_debug("erom: master wrapper %d "
1821- * has %d descriptors\n", i, j); */
1822- break;
1823- } else {
1824- if (wrappers[0] == 0 && !i && !j)
1825- core->wrap = tmp;
1826- }
1827- }
1828- }
1829+ return 0;
1830+}
1831+
1832+int __init bcma_bus_scan_early(struct bcma_bus *bus,
1833+ struct bcma_device_id *match,
1834+ struct bcma_device *core)
1835+{
1836+ u32 erombase;
1837+ u32 __iomem *eromptr, *eromend;
1838 
1839+ int err = -ENODEV;
1840+ int core_num = 0;
1841+
1842+ erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
1843+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
1844+ eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
1845+ if (!eromptr)
1846+ return -ENOMEM;
1847+ } else {
1848+ eromptr = bus->mmio;
1849+ }
1850+
1851+ eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
1852+
1853+ bcma_scan_switch_core(bus, erombase);
1854+
1855+ while (eromptr < eromend) {
1856+ memset(core, 0, sizeof(*core));
1857+ INIT_LIST_HEAD(&core->list);
1858+ core->bus = bus;
1859+
1860+ err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
1861+ if (err == -ENODEV) {
1862+ core_num++;
1863+ continue;
1864+ } else if (err == -ENXIO)
1865+ continue;
1866+ else if (err == -ESPIPE)
1867+ break;
1868+ else if (err < 0)
1869+ return err;
1870+
1871+ core->core_index = core_num++;
1872+ bus->nr_cores++;
1873         pr_info("Core %d found: %s "
1874             "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
1875- bus->nr_cores, bcma_device_name(&core->id),
1876+ core->core_index, bcma_device_name(&core->id),
1877             core->id.manuf, core->id.id, core->id.rev,
1878             core->id.class);
1879 
1880- core->core_index = bus->nr_cores++;
1881         list_add(&core->list, &bus->cores);
1882- continue;
1883-out:
1884- return err;
1885+ err = 0;
1886+ break;
1887     }
1888 
1889- return 0;
1890+ if (bus->hosttype == BCMA_HOSTTYPE_SOC)
1891+ iounmap(eromptr);
1892+
1893+ return err;
1894 }
1895--- /dev/null
1896+++ b/drivers/bcma/sprom.c
1897@@ -0,0 +1,247 @@
1898+/*
1899+ * Broadcom specific AMBA
1900+ * SPROM reading
1901+ *
1902+ * Licensed under the GNU/GPL. See COPYING for details.
1903+ */
1904+
1905+#include "bcma_private.h"
1906+
1907+#include <linux/bcma/bcma.h>
1908+#include <linux/bcma/bcma_regs.h>
1909+#include <linux/pci.h>
1910+#include <linux/io.h>
1911+#include <linux/dma-mapping.h>
1912+#include <linux/slab.h>
1913+
1914+#define SPOFF(offset) ((offset) / sizeof(u16))
1915+
1916+/**************************************************
1917+ * R/W ops.
1918+ **************************************************/
1919+
1920+static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom)
1921+{
1922+ int i;
1923+ for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++)
1924+ sprom[i] = bcma_read16(bus->drv_cc.core,
1925+ offset + (i * 2));
1926+}
1927+
1928+/**************************************************
1929+ * Validation.
1930+ **************************************************/
1931+
1932+static inline u8 bcma_crc8(u8 crc, u8 data)
1933+{
1934+ /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */
1935+ static const u8 t[] = {
1936+ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
1937+ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
1938+ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
1939+ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
1940+ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
1941+ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
1942+ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
1943+ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
1944+ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
1945+ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
1946+ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
1947+ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
1948+ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
1949+ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
1950+ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
1951+ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
1952+ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
1953+ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
1954+ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
1955+ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
1956+ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
1957+ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
1958+ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
1959+ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
1960+ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
1961+ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
1962+ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
1963+ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
1964+ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
1965+ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
1966+ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
1967+ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
1968+ };
1969+ return t[crc ^ data];
1970+}
1971+
1972+static u8 bcma_sprom_crc(const u16 *sprom)
1973+{
1974+ int word;
1975+ u8 crc = 0xFF;
1976+
1977+ for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) {
1978+ crc = bcma_crc8(crc, sprom[word] & 0x00FF);
1979+ crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8);
1980+ }
1981+ crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF);
1982+ crc ^= 0xFF;
1983+
1984+ return crc;
1985+}
1986+
1987+static int bcma_sprom_check_crc(const u16 *sprom)
1988+{
1989+ u8 crc;
1990+ u8 expected_crc;
1991+ u16 tmp;
1992+
1993+ crc = bcma_sprom_crc(sprom);
1994+ tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC;
1995+ expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
1996+ if (crc != expected_crc)
1997+ return -EPROTO;
1998+
1999+ return 0;
2000+}
2001+
2002+static int bcma_sprom_valid(const u16 *sprom)
2003+{
2004+ u16 revision;
2005+ int err;
2006+
2007+ err = bcma_sprom_check_crc(sprom);
2008+ if (err)
2009+ return err;
2010+
2011+ revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV;
2012+ if (revision != 8 && revision != 9) {
2013+ pr_err("Unsupported SPROM revision: %d\n", revision);
2014+ return -ENOENT;
2015+ }
2016+
2017+ return 0;
2018+}
2019+
2020+/**************************************************
2021+ * SPROM extraction.
2022+ **************************************************/
2023+
2024+static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
2025+{
2026+ u16 v;
2027+ int i;
2028+
2029+ bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] &
2030+ SSB_SPROM_REVISION_REV;
2031+
2032+ for (i = 0; i < 3; i++) {
2033+ v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
2034+ *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
2035+ }
2036+
2037+ bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)];
2038+
2039+ bus->sprom.txpid2g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
2040+ SSB_SPROM4_TXPID2G0) >> SSB_SPROM4_TXPID2G0_SHIFT;
2041+ bus->sprom.txpid2g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
2042+ SSB_SPROM4_TXPID2G1) >> SSB_SPROM4_TXPID2G1_SHIFT;
2043+ bus->sprom.txpid2g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
2044+ SSB_SPROM4_TXPID2G2) >> SSB_SPROM4_TXPID2G2_SHIFT;
2045+ bus->sprom.txpid2g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
2046+ SSB_SPROM4_TXPID2G3) >> SSB_SPROM4_TXPID2G3_SHIFT;
2047+
2048+ bus->sprom.txpid5gl[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
2049+ SSB_SPROM4_TXPID5GL0) >> SSB_SPROM4_TXPID5GL0_SHIFT;
2050+ bus->sprom.txpid5gl[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
2051+ SSB_SPROM4_TXPID5GL1) >> SSB_SPROM4_TXPID5GL1_SHIFT;
2052+ bus->sprom.txpid5gl[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
2053+ SSB_SPROM4_TXPID5GL2) >> SSB_SPROM4_TXPID5GL2_SHIFT;
2054+ bus->sprom.txpid5gl[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
2055+ SSB_SPROM4_TXPID5GL3) >> SSB_SPROM4_TXPID5GL3_SHIFT;
2056+
2057+ bus->sprom.txpid5g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
2058+ SSB_SPROM4_TXPID5G0) >> SSB_SPROM4_TXPID5G0_SHIFT;
2059+ bus->sprom.txpid5g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
2060+ SSB_SPROM4_TXPID5G1) >> SSB_SPROM4_TXPID5G1_SHIFT;
2061+ bus->sprom.txpid5g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
2062+ SSB_SPROM4_TXPID5G2) >> SSB_SPROM4_TXPID5G2_SHIFT;
2063+ bus->sprom.txpid5g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
2064+ SSB_SPROM4_TXPID5G3) >> SSB_SPROM4_TXPID5G3_SHIFT;
2065+
2066+ bus->sprom.txpid5gh[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
2067+ SSB_SPROM4_TXPID5GH0) >> SSB_SPROM4_TXPID5GH0_SHIFT;
2068+ bus->sprom.txpid5gh[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
2069+ SSB_SPROM4_TXPID5GH1) >> SSB_SPROM4_TXPID5GH1_SHIFT;
2070+ bus->sprom.txpid5gh[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
2071+ SSB_SPROM4_TXPID5GH2) >> SSB_SPROM4_TXPID5GH2_SHIFT;
2072+ bus->sprom.txpid5gh[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
2073+ SSB_SPROM4_TXPID5GH3) >> SSB_SPROM4_TXPID5GH3_SHIFT;
2074+
2075+ bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
2076+ bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
2077+ bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
2078+ bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
2079+
2080+ bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
2081+
2082+ bus->sprom.fem.ghz2.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
2083+ SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
2084+ bus->sprom.fem.ghz2.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
2085+ SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
2086+ bus->sprom.fem.ghz2.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
2087+ SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
2088+ bus->sprom.fem.ghz2.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
2089+ SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
2090+ bus->sprom.fem.ghz2.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
2091+ SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
2092+
2093+ bus->sprom.fem.ghz5.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
2094+ SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
2095+ bus->sprom.fem.ghz5.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
2096+ SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
2097+ bus->sprom.fem.ghz5.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
2098+ SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
2099+ bus->sprom.fem.ghz5.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
2100+ SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
2101+ bus->sprom.fem.ghz5.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
2102+ SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
2103+}
2104+
2105+int bcma_sprom_get(struct bcma_bus *bus)
2106+{
2107+ u16 offset;
2108+ u16 *sprom;
2109+ int err = 0;
2110+
2111+ if (!bus->drv_cc.core)
2112+ return -EOPNOTSUPP;
2113+
2114+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
2115+ return -ENOENT;
2116+
2117+ sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
2118+ GFP_KERNEL);
2119+ if (!sprom)
2120+ return -ENOMEM;
2121+
2122+ if (bus->chipinfo.id == 0x4331)
2123+ bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
2124+
2125+ /* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
2126+ * According to brcm80211 this applies to cards with PCIe rev >= 6
2127+ * TODO: understand this condition and use it */
2128+ offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
2129+ BCMA_CC_SPROM_PCIE6;
2130+ bcma_sprom_read(bus, offset, sprom);
2131+
2132+ if (bus->chipinfo.id == 0x4331)
2133+ bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
2134+
2135+ err = bcma_sprom_valid(sprom);
2136+ if (err)
2137+ goto out;
2138+
2139+ bcma_sprom_extract_r8(bus, sprom);
2140+
2141+out:
2142+ kfree(sprom);
2143+ return err;
2144+}
2145--- a/include/linux/bcma/bcma.h
2146+++ b/include/linux/bcma/bcma.h
2147@@ -6,6 +6,8 @@
2148 
2149 #include <linux/bcma/bcma_driver_chipcommon.h>
2150 #include <linux/bcma/bcma_driver_pci.h>
2151+#include <linux/bcma/bcma_driver_mips.h>
2152+#include <linux/ssb/ssb.h> /* SPROM sharing */
2153 
2154 #include "bcma_regs.h"
2155 
2156@@ -13,9 +15,9 @@ struct bcma_device;
2157 struct bcma_bus;
2158 
2159 enum bcma_hosttype {
2160- BCMA_HOSTTYPE_NONE,
2161     BCMA_HOSTTYPE_PCI,
2162     BCMA_HOSTTYPE_SDIO,
2163+ BCMA_HOSTTYPE_SOC,
2164 };
2165 
2166 struct bcma_chipinfo {
2167@@ -24,6 +26,11 @@ struct bcma_chipinfo {
2168     u8 pkg;
2169 };
2170 
2171+enum bcma_clkmode {
2172+ BCMA_CLKMODE_FAST,
2173+ BCMA_CLKMODE_DYNAMIC,
2174+};
2175+
2176 struct bcma_host_ops {
2177     u8 (*read8)(struct bcma_device *core, u16 offset);
2178     u16 (*read16)(struct bcma_device *core, u16 offset);
2179@@ -31,6 +38,12 @@ struct bcma_host_ops {
2180     void (*write8)(struct bcma_device *core, u16 offset, u8 value);
2181     void (*write16)(struct bcma_device *core, u16 offset, u16 value);
2182     void (*write32)(struct bcma_device *core, u16 offset, u32 value);
2183+#ifdef CONFIG_BCMA_BLOCKIO
2184+ void (*block_read)(struct bcma_device *core, void *buffer,
2185+ size_t count, u16 offset, u8 reg_width);
2186+ void (*block_write)(struct bcma_device *core, const void *buffer,
2187+ size_t count, u16 offset, u8 reg_width);
2188+#endif
2189     /* Agent ops */
2190     u32 (*aread32)(struct bcma_device *core, u16 offset);
2191     void (*awrite32)(struct bcma_device *core, u16 offset, u32 value);
2192@@ -117,6 +130,9 @@ struct bcma_device {
2193     struct bcma_device_id id;
2194 
2195     struct device dev;
2196+ struct device *dma_dev;
2197+
2198+ unsigned int irq;
2199     bool dev_registered;
2200 
2201     u8 core_index;
2202@@ -124,6 +140,9 @@ struct bcma_device {
2203     u32 addr;
2204     u32 wrap;
2205 
2206+ void __iomem *io_addr;
2207+ void __iomem *io_wrap;
2208+
2209     void *drvdata;
2210     struct list_head list;
2211 };
2212@@ -151,10 +170,9 @@ struct bcma_driver {
2213 };
2214 extern
2215 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner);
2216-static inline int bcma_driver_register(struct bcma_driver *drv)
2217-{
2218- return __bcma_driver_register(drv, THIS_MODULE);
2219-}
2220+#define bcma_driver_register(drv) \
2221+ __bcma_driver_register(drv, THIS_MODULE)
2222+
2223 extern void bcma_driver_unregister(struct bcma_driver *drv);
2224 
2225 struct bcma_bus {
2226@@ -176,49 +194,105 @@ struct bcma_bus {
2227     struct bcma_device *mapped_core;
2228     struct list_head cores;
2229     u8 nr_cores;
2230+ u8 init_done:1;
2231 
2232     struct bcma_drv_cc drv_cc;
2233     struct bcma_drv_pci drv_pci;
2234+ struct bcma_drv_mips drv_mips;
2235+
2236+ /* We decided to share SPROM struct with SSB as long as we do not need
2237+ * any hacks for BCMA. This simplifies drivers code. */
2238+ struct ssb_sprom sprom;
2239 };
2240 
2241-extern inline u32 bcma_read8(struct bcma_device *core, u16 offset)
2242+static inline u32 bcma_read8(struct bcma_device *core, u16 offset)
2243 {
2244     return core->bus->ops->read8(core, offset);
2245 }
2246-extern inline u32 bcma_read16(struct bcma_device *core, u16 offset)
2247+static inline u32 bcma_read16(struct bcma_device *core, u16 offset)
2248 {
2249     return core->bus->ops->read16(core, offset);
2250 }
2251-extern inline u32 bcma_read32(struct bcma_device *core, u16 offset)
2252+static inline u32 bcma_read32(struct bcma_device *core, u16 offset)
2253 {
2254     return core->bus->ops->read32(core, offset);
2255 }
2256-extern inline
2257+static inline
2258 void bcma_write8(struct bcma_device *core, u16 offset, u32 value)
2259 {
2260     core->bus->ops->write8(core, offset, value);
2261 }
2262-extern inline
2263+static inline
2264 void bcma_write16(struct bcma_device *core, u16 offset, u32 value)
2265 {
2266     core->bus->ops->write16(core, offset, value);
2267 }
2268-extern inline
2269+static inline
2270 void bcma_write32(struct bcma_device *core, u16 offset, u32 value)
2271 {
2272     core->bus->ops->write32(core, offset, value);
2273 }
2274-extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset)
2275+#ifdef CONFIG_BCMA_BLOCKIO
2276+static inline void bcma_block_read(struct bcma_device *core, void *buffer,
2277+ size_t count, u16 offset, u8 reg_width)
2278+{
2279+ core->bus->ops->block_read(core, buffer, count, offset, reg_width);
2280+}
2281+static inline void bcma_block_write(struct bcma_device *core,
2282+ const void *buffer, size_t count,
2283+ u16 offset, u8 reg_width)
2284+{
2285+ core->bus->ops->block_write(core, buffer, count, offset, reg_width);
2286+}
2287+#endif
2288+static inline u32 bcma_aread32(struct bcma_device *core, u16 offset)
2289 {
2290     return core->bus->ops->aread32(core, offset);
2291 }
2292-extern inline
2293+static inline
2294 void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value)
2295 {
2296     core->bus->ops->awrite32(core, offset, value);
2297 }
2298 
2299+static inline void bcma_mask32(struct bcma_device *cc, u16 offset, u32 mask)
2300+{
2301+ bcma_write32(cc, offset, bcma_read32(cc, offset) & mask);
2302+}
2303+static inline void bcma_set32(struct bcma_device *cc, u16 offset, u32 set)
2304+{
2305+ bcma_write32(cc, offset, bcma_read32(cc, offset) | set);
2306+}
2307+static inline void bcma_maskset32(struct bcma_device *cc,
2308+ u16 offset, u32 mask, u32 set)
2309+{
2310+ bcma_write32(cc, offset, (bcma_read32(cc, offset) & mask) | set);
2311+}
2312+static inline void bcma_mask16(struct bcma_device *cc, u16 offset, u16 mask)
2313+{
2314+ bcma_write16(cc, offset, bcma_read16(cc, offset) & mask);
2315+}
2316+static inline void bcma_set16(struct bcma_device *cc, u16 offset, u16 set)
2317+{
2318+ bcma_write16(cc, offset, bcma_read16(cc, offset) | set);
2319+}
2320+static inline void bcma_maskset16(struct bcma_device *cc,
2321+ u16 offset, u16 mask, u16 set)
2322+{
2323+ bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
2324+}
2325+
2326 extern bool bcma_core_is_enabled(struct bcma_device *core);
2327+extern void bcma_core_disable(struct bcma_device *core, u32 flags);
2328 extern int bcma_core_enable(struct bcma_device *core, u32 flags);
2329+extern void bcma_core_set_clockmode(struct bcma_device *core,
2330+ enum bcma_clkmode clkmode);
2331+extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
2332+ bool on);
2333+#define BCMA_DMA_TRANSLATION_MASK 0xC0000000
2334+#define BCMA_DMA_TRANSLATION_NONE 0x00000000
2335+#define BCMA_DMA_TRANSLATION_DMA32_CMT 0x40000000 /* Client Mode Translation for 32-bit DMA */
2336+#define BCMA_DMA_TRANSLATION_DMA64_CMT 0x80000000 /* Client Mode Translation for 64-bit DMA */
2337+extern u32 bcma_core_dma_translation(struct bcma_device *core);
2338 
2339 #endif /* LINUX_BCMA_H_ */
2340--- a/include/linux/bcma/bcma_driver_chipcommon.h
2341+++ b/include/linux/bcma/bcma_driver_chipcommon.h
2342@@ -24,6 +24,7 @@
2343 #define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */
2344 #define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */
2345 #define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */
2346+#define BCMA_CC_FLASHT_NFLASH 0x00000200
2347 #define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */
2348 #define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */
2349 #define BCMA_PLLTYPE_NONE 0x00000000
2350@@ -178,16 +179,9 @@
2351 #define BCMA_CC_PROG_CFG 0x0120
2352 #define BCMA_CC_PROG_WAITCNT 0x0124
2353 #define BCMA_CC_FLASH_CFG 0x0128
2354+#define BCMA_CC_FLASH_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */
2355 #define BCMA_CC_FLASH_WAITCNT 0x012C
2356-#define BCMA_CC_CLKCTLST 0x01E0 /* Clock control and status (rev >= 20) */
2357-#define BCMA_CC_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */
2358-#define BCMA_CC_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */
2359-#define BCMA_CC_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */
2360-#define BCMA_CC_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */
2361-#define BCMA_CC_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
2362-#define BCMA_CC_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
2363-#define BCMA_CC_CLKCTLST_HAVEHT 0x00010000 /* HT available */
2364-#define BCMA_CC_CLKCTLST_HAVEALP 0x00020000 /* APL available */
2365+/* 0x1E0 is defined as shared BCMA_CLKCTLST */
2366 #define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */
2367 #define BCMA_CC_UART0_DATA 0x0300
2368 #define BCMA_CC_UART0_IMR 0x0304
2369@@ -209,6 +203,7 @@
2370 #define BCMA_CC_PMU_CTL 0x0600 /* PMU control */
2371 #define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */
2372 #define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16
2373+#define BCMA_CC_PMU_CTL_PLL_UPD 0x00000400
2374 #define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */
2375 #define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */
2376 #define BCMA_CC_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */
2377@@ -244,6 +239,66 @@
2378 #define BCMA_CC_REGCTL_DATA 0x065C
2379 #define BCMA_CC_PLLCTL_ADDR 0x0660
2380 #define BCMA_CC_PLLCTL_DATA 0x0664
2381+#define BCMA_CC_SPROM 0x0800 /* SPROM beginning */
2382+#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */
2383+
2384+/* Divider allocation in 4716/47162/5356 */
2385+#define BCMA_CC_PMU5_MAINPLL_CPU 1
2386+#define BCMA_CC_PMU5_MAINPLL_MEM 2
2387+#define BCMA_CC_PMU5_MAINPLL_SSB 3
2388+
2389+/* PLL usage in 4716/47162 */
2390+#define BCMA_CC_PMU4716_MAINPLL_PLL0 12
2391+
2392+/* PLL usage in 5356/5357 */
2393+#define BCMA_CC_PMU5356_MAINPLL_PLL0 0
2394+#define BCMA_CC_PMU5357_MAINPLL_PLL0 0
2395+
2396+/* 4706 PMU */
2397+#define BCMA_CC_PMU4706_MAINPLL_PLL0 0
2398+
2399+/* ALP clock on pre-PMU chips */
2400+#define BCMA_CC_PMU_ALP_CLOCK 20000000
2401+/* HT clock for systems with PMU-enabled chipcommon */
2402+#define BCMA_CC_PMU_HT_CLOCK 80000000
2403+
2404+/* PMU rev 5 (& 6) */
2405+#define BCMA_CC_PPL_P1P2_OFF 0
2406+#define BCMA_CC_PPL_P1_MASK 0x0f000000
2407+#define BCMA_CC_PPL_P1_SHIFT 24
2408+#define BCMA_CC_PPL_P2_MASK 0x00f00000
2409+#define BCMA_CC_PPL_P2_SHIFT 20
2410+#define BCMA_CC_PPL_M14_OFF 1
2411+#define BCMA_CC_PPL_MDIV_MASK 0x000000ff
2412+#define BCMA_CC_PPL_MDIV_WIDTH 8
2413+#define BCMA_CC_PPL_NM5_OFF 2
2414+#define BCMA_CC_PPL_NDIV_MASK 0xfff00000
2415+#define BCMA_CC_PPL_NDIV_SHIFT 20
2416+#define BCMA_CC_PPL_FMAB_OFF 3
2417+#define BCMA_CC_PPL_MRAT_MASK 0xf0000000
2418+#define BCMA_CC_PPL_MRAT_SHIFT 28
2419+#define BCMA_CC_PPL_ABRAT_MASK 0x08000000
2420+#define BCMA_CC_PPL_ABRAT_SHIFT 27
2421+#define BCMA_CC_PPL_FDIV_MASK 0x07ffffff
2422+#define BCMA_CC_PPL_PLLCTL_OFF 4
2423+#define BCMA_CC_PPL_PCHI_OFF 5
2424+#define BCMA_CC_PPL_PCHI_MASK 0x0000003f
2425+
2426+/* BCM4331 ChipControl numbers. */
2427+#define BCMA_CHIPCTL_4331_BT_COEXIST BIT(0) /* 0 disable */
2428+#define BCMA_CHIPCTL_4331_SECI BIT(1) /* 0 SECI is disabled (JATG functional) */
2429+#define BCMA_CHIPCTL_4331_EXT_LNA BIT(2) /* 0 disable */
2430+#define BCMA_CHIPCTL_4331_SPROM_GPIO13_15 BIT(3) /* sprom/gpio13-15 mux */
2431+#define BCMA_CHIPCTL_4331_EXTPA_EN BIT(4) /* 0 ext pa disable, 1 ext pa enabled */
2432+#define BCMA_CHIPCTL_4331_GPIOCLK_ON_SPROMCS BIT(5) /* set drive out GPIO_CLK on sprom_cs pin */
2433+#define BCMA_CHIPCTL_4331_PCIE_MDIO_ON_SPROMCS BIT(6) /* use sprom_cs pin as PCIE mdio interface */
2434+#define BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5 BIT(7) /* aband extpa will be at gpio2/5 and sprom_dout */
2435+#define BCMA_CHIPCTL_4331_OVR_PIPEAUXCLKEN BIT(8) /* override core control on pipe_AuxClkEnable */
2436+#define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN BIT(9) /* override core control on pipe_AuxPowerDown */
2437+#define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN BIT(10) /* pcie_auxclkenable */
2438+#define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN BIT(11) /* pcie_pipe_pllpowerdown */
2439+#define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4 BIT(16) /* enable bt_shd0 at gpio4 */
2440+#define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5 BIT(17) /* enable bt_shd1 at gpio5 */
2441 
2442 /* Data for the PMU, if available.
2443  * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
2444@@ -253,14 +308,37 @@ struct bcma_chipcommon_pmu {
2445     u32 crystalfreq; /* The active crystal frequency (in kHz) */
2446 };
2447 
2448+#ifdef CONFIG_BCMA_DRIVER_MIPS
2449+struct bcma_pflash {
2450+ u8 buswidth;
2451+ u32 window;
2452+ u32 window_size;
2453+};
2454+
2455+struct bcma_serial_port {
2456+ void *regs;
2457+ unsigned long clockspeed;
2458+ unsigned int irq;
2459+ unsigned int baud_base;
2460+ unsigned int reg_shift;
2461+};
2462+#endif /* CONFIG_BCMA_DRIVER_MIPS */
2463+
2464 struct bcma_drv_cc {
2465     struct bcma_device *core;
2466     u32 status;
2467     u32 capabilities;
2468     u32 capabilities_ext;
2469+ u8 setup_done:1;
2470     /* Fast Powerup Delay constant */
2471     u16 fast_pwrup_delay;
2472     struct bcma_chipcommon_pmu pmu;
2473+#ifdef CONFIG_BCMA_DRIVER_MIPS
2474+ struct bcma_pflash pflash;
2475+
2476+ int nr_serial_ports;
2477+ struct bcma_serial_port serial_ports[4];
2478+#endif /* CONFIG_BCMA_DRIVER_MIPS */
2479 };
2480 
2481 /* Register access */
2482@@ -281,6 +359,8 @@ extern void bcma_core_chipcommon_init(st
2483 extern void bcma_chipco_suspend(struct bcma_drv_cc *cc);
2484 extern void bcma_chipco_resume(struct bcma_drv_cc *cc);
2485 
2486+void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
2487+
2488 extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc,
2489                       u32 ticks);
2490 
2491@@ -299,4 +379,13 @@ u32 bcma_chipco_gpio_polarity(struct bcm
2492 /* PMU support */
2493 extern void bcma_pmu_init(struct bcma_drv_cc *cc);
2494 
2495+extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset,
2496+ u32 value);
2497+extern void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset,
2498+ u32 mask, u32 set);
2499+extern void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
2500+ u32 offset, u32 mask, u32 set);
2501+extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc,
2502+ u32 offset, u32 mask, u32 set);
2503+
2504 #endif /* LINUX_BCMA_DRIVER_CC_H_ */
2505--- /dev/null
2506+++ b/include/linux/bcma/bcma_driver_mips.h
2507@@ -0,0 +1,51 @@
2508+#ifndef LINUX_BCMA_DRIVER_MIPS_H_
2509+#define LINUX_BCMA_DRIVER_MIPS_H_
2510+
2511+#define BCMA_MIPS_IPSFLAG 0x0F08
2512+/* which sbflags get routed to mips interrupt 1 */
2513+#define BCMA_MIPS_IPSFLAG_IRQ1 0x0000003F
2514+#define BCMA_MIPS_IPSFLAG_IRQ1_SHIFT 0
2515+/* which sbflags get routed to mips interrupt 2 */
2516+#define BCMA_MIPS_IPSFLAG_IRQ2 0x00003F00
2517+#define BCMA_MIPS_IPSFLAG_IRQ2_SHIFT 8
2518+/* which sbflags get routed to mips interrupt 3 */
2519+#define BCMA_MIPS_IPSFLAG_IRQ3 0x003F0000
2520+#define BCMA_MIPS_IPSFLAG_IRQ3_SHIFT 16
2521+/* which sbflags get routed to mips interrupt 4 */
2522+#define BCMA_MIPS_IPSFLAG_IRQ4 0x3F000000
2523+#define BCMA_MIPS_IPSFLAG_IRQ4_SHIFT 24
2524+
2525+/* MIPS 74K core registers */
2526+#define BCMA_MIPS_MIPS74K_CORECTL 0x0000
2527+#define BCMA_MIPS_MIPS74K_EXCEPTBASE 0x0004
2528+#define BCMA_MIPS_MIPS74K_BIST 0x000C
2529+#define BCMA_MIPS_MIPS74K_INTMASK_INT0 0x0014
2530+#define BCMA_MIPS_MIPS74K_INTMASK(int) \
2531+ ((int) * 4 + BCMA_MIPS_MIPS74K_INTMASK_INT0)
2532+#define BCMA_MIPS_MIPS74K_NMIMASK 0x002C
2533+#define BCMA_MIPS_MIPS74K_GPIOSEL 0x0040
2534+#define BCMA_MIPS_MIPS74K_GPIOOUT 0x0044
2535+#define BCMA_MIPS_MIPS74K_GPIOEN 0x0048
2536+#define BCMA_MIPS_MIPS74K_CLKCTLST 0x01E0
2537+
2538+#define BCMA_MIPS_OOBSELOUTA30 0x100
2539+
2540+struct bcma_device;
2541+
2542+struct bcma_drv_mips {
2543+ struct bcma_device *core;
2544+ u8 setup_done:1;
2545+ unsigned int assigned_irqs;
2546+};
2547+
2548+#ifdef CONFIG_BCMA_DRIVER_MIPS
2549+extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
2550+#else
2551+static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
2552+#endif
2553+
2554+extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
2555+
2556+extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
2557+
2558+#endif /* LINUX_BCMA_DRIVER_MIPS_H_ */
2559--- a/include/linux/bcma/bcma_driver_pci.h
2560+++ b/include/linux/bcma/bcma_driver_pci.h
2561@@ -85,5 +85,7 @@ struct bcma_drv_pci {
2562 #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val)
2563 
2564 extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
2565+extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
2566+ struct bcma_device *core, bool enable);
2567 
2568 #endif /* LINUX_BCMA_DRIVER_PCI_H_ */
2569--- a/include/linux/bcma/bcma_regs.h
2570+++ b/include/linux/bcma/bcma_regs.h
2571@@ -1,13 +1,38 @@
2572 #ifndef LINUX_BCMA_REGS_H_
2573 #define LINUX_BCMA_REGS_H_
2574 
2575+/* Some single registers are shared between many cores */
2576+/* BCMA_CLKCTLST: ChipCommon (rev >= 20), PCIe, 80211 */
2577+#define BCMA_CLKCTLST 0x01E0 /* Clock control and status */
2578+#define BCMA_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */
2579+#define BCMA_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */
2580+#define BCMA_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */
2581+#define BCMA_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */
2582+#define BCMA_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
2583+#define BCMA_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
2584+#define BCMA_CLKCTLST_EXTRESREQ 0x00000700 /* Mask of external resource requests */
2585+#define BCMA_CLKCTLST_HAVEALP 0x00010000 /* ALP available */
2586+#define BCMA_CLKCTLST_HAVEHT 0x00020000 /* HT available */
2587+#define BCMA_CLKCTLST_BP_ON_ALP 0x00040000 /* RO: running on ALP clock */
2588+#define BCMA_CLKCTLST_BP_ON_HT 0x00080000 /* RO: running on HT clock */
2589+#define BCMA_CLKCTLST_EXTRESST 0x07000000 /* Mask of external resource status */
2590+/* Is there any BCM4328 on BCMA bus? */
2591+#define BCMA_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */
2592+#define BCMA_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */
2593+
2594 /* Agent registers (common for every core) */
2595-#define BCMA_IOCTL 0x0408
2596+#define BCMA_IOCTL 0x0408 /* IO control */
2597 #define BCMA_IOCTL_CLK 0x0001
2598 #define BCMA_IOCTL_FGC 0x0002
2599 #define BCMA_IOCTL_CORE_BITS 0x3FFC
2600 #define BCMA_IOCTL_PME_EN 0x4000
2601 #define BCMA_IOCTL_BIST_EN 0x8000
2602+#define BCMA_IOST 0x0500 /* IO status */
2603+#define BCMA_IOST_CORE_BITS 0x0FFF
2604+#define BCMA_IOST_DMA64 0x1000
2605+#define BCMA_IOST_GATED_CLK 0x2000
2606+#define BCMA_IOST_BIST_ERROR 0x4000
2607+#define BCMA_IOST_BIST_DONE 0x8000
2608 #define BCMA_RESET_CTL 0x0800
2609 #define BCMA_RESET_CTL_RESET 0x0001
2610 
2611--- /dev/null
2612+++ b/include/linux/bcma/bcma_soc.h
2613@@ -0,0 +1,16 @@
2614+#ifndef LINUX_BCMA_SOC_H_
2615+#define LINUX_BCMA_SOC_H_
2616+
2617+#include <linux/bcma/bcma.h>
2618+
2619+struct bcma_soc {
2620+ struct bcma_bus bus;
2621+ struct bcma_device core_cc;
2622+ struct bcma_device core_mips;
2623+};
2624+
2625+int __init bcma_host_soc_register(struct bcma_soc *soc);
2626+
2627+int bcma_bus_register(struct bcma_bus *bus);
2628+
2629+#endif /* LINUX_BCMA_SOC_H_ */
2630

Archive Download this file



interactive