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

1--- /dev/null
2+++ b/Documentation/ABI/testing/sysfs-bus-bcma
3@@ -0,0 +1,31 @@
4+What: /sys/bus/bcma/devices/.../manuf
5+Date: May 2011
6+KernelVersion: 2.6.40
7+Contact: Rafał Miłecki <zajec5@gmail.com>
8+Description:
9+ Each BCMA core has it's manufacturer id. See
10+ include/linux/bcma/bcma.h for possible values.
11+
12+What: /sys/bus/bcma/devices/.../id
13+Date: May 2011
14+KernelVersion: 2.6.40
15+Contact: Rafał Miłecki <zajec5@gmail.com>
16+Description:
17+ There are a few types of BCMA cores, they can be identified by
18+ id field.
19+
20+What: /sys/bus/bcma/devices/.../rev
21+Date: May 2011
22+KernelVersion: 2.6.40
23+Contact: Rafał Miłecki <zajec5@gmail.com>
24+Description:
25+ BCMA cores of the same type can still slightly differ depending
26+ on their revision. Use it for detailed programming.
27+
28+What: /sys/bus/bcma/devices/.../class
29+Date: May 2011
30+KernelVersion: 2.6.40
31+Contact: Rafał Miłecki <zajec5@gmail.com>
32+Description:
33+ Each BCMA core is identified by few fields, including class it
34+ belongs to. See include/linux/bcma/bcma.h for possible values.
35--- a/MAINTAINERS
36+++ b/MAINTAINERS
37@@ -5832,6 +5832,13 @@ S: Maintained
38 F: drivers/ssb/
39 F: include/linux/ssb/
40 
41+BROADCOM SPECIFIC AMBA DRIVER (BCMA)
42+M: Rafał Miłecki <zajec5@gmail.com>
43+L: linux-wireless@vger.kernel.org
44+S: Maintained
45+F: drivers/bcma/
46+F: include/linux/bcma/
47+
48 SONY VAIO CONTROL DEVICE DRIVER
49 M: Mattia Dongili <malattia@linux.it>
50 L: platform-driver-x86@vger.kernel.org
51--- a/drivers/Kconfig
52+++ b/drivers/Kconfig
53@@ -68,6 +68,8 @@ source "drivers/watchdog/Kconfig"
54 
55 source "drivers/ssb/Kconfig"
56 
57+source "drivers/bcma/Kconfig"
58+
59 source "drivers/mfd/Kconfig"
60 
61 source "drivers/regulator/Kconfig"
62--- a/drivers/Makefile
63+++ b/drivers/Makefile
64@@ -110,6 +110,7 @@ obj-$(CONFIG_HID) += hid/
65 obj-$(CONFIG_PPC_PS3) += ps3/
66 obj-$(CONFIG_OF) += of/
67 obj-$(CONFIG_SSB) += ssb/
68+obj-$(CONFIG_BCMA) += bcma/
69 obj-$(CONFIG_VHOST_NET) += vhost/
70 obj-$(CONFIG_VLYNQ) += vlynq/
71 obj-$(CONFIG_STAGING) += staging/
72--- /dev/null
73+++ b/drivers/bcma/Kconfig
74@@ -0,0 +1,38 @@
75+config BCMA_POSSIBLE
76+ bool
77+ depends on HAS_IOMEM && HAS_DMA
78+ default y
79+
80+menu "Broadcom specific AMBA"
81+ depends on BCMA_POSSIBLE
82+
83+config BCMA
84+ tristate "BCMA support"
85+ depends on BCMA_POSSIBLE
86+ help
87+ Bus driver for Broadcom specific Advanced Microcontroller Bus
88+ Architecture.
89+
90+# Support for Block-I/O. SELECT this from the driver that needs it.
91+config BCMA_BLOCKIO
92+ bool
93+ depends on BCMA
94+
95+config BCMA_HOST_PCI_POSSIBLE
96+ bool
97+ depends on BCMA && PCI = y
98+ default y
99+
100+config BCMA_HOST_PCI
101+ bool "Support for BCMA on PCI-host bus"
102+ depends on BCMA_HOST_PCI_POSSIBLE
103+
104+config BCMA_DEBUG
105+ bool "BCMA debugging"
106+ depends on BCMA
107+ help
108+ This turns on additional debugging messages.
109+
110+ If unsure, say N
111+
112+endmenu
113--- /dev/null
114+++ b/drivers/bcma/Makefile
115@@ -0,0 +1,7 @@
116+bcma-y += main.o scan.o core.o sprom.o
117+bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
118+bcma-y += driver_pci.o
119+bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
120+obj-$(CONFIG_BCMA) += bcma.o
121+
122+ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG
123--- /dev/null
124+++ b/drivers/bcma/README
125@@ -0,0 +1,19 @@
126+Broadcom introduced new bus as replacement for older SSB. It is based on AMBA,
127+however from programming point of view there is nothing AMBA specific we use.
128+
129+Standard AMBA drivers are platform specific, have hardcoded addresses and use
130+AMBA standard fields like CID and PID.
131+
132+In case of Broadcom's cards every device consists of:
133+1) Broadcom specific AMBA device. It is put on AMBA bus, but can not be treated
134+ as standard AMBA device. Reading it's CID or PID can cause machine lockup.
135+2) AMBA standard devices called ports or wrappers. They have CIDs (AMBA_CID)
136+ and PIDs (0x103BB369), but we do not use that info for anything. One of that
137+ devices is used for managing Broadcom specific core.
138+
139+Addresses of AMBA devices are not hardcoded in driver and have to be read from
140+EPROM.
141+
142+In this situation we decided to introduce separated bus. It can contain up to
143+16 devices identified by Broadcom specific fields: manufacturer, id, revision
144+and class.
145--- /dev/null
146+++ b/drivers/bcma/TODO
147@@ -0,0 +1,3 @@
148+- Interrupts
149+- Defines for PCI core driver
150+- Create kernel Documentation (use info from README)
151--- /dev/null
152+++ b/drivers/bcma/bcma_private.h
153@@ -0,0 +1,31 @@
154+#ifndef LINUX_BCMA_PRIVATE_H_
155+#define LINUX_BCMA_PRIVATE_H_
156+
157+#ifndef pr_fmt
158+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
159+#endif
160+
161+#include <linux/bcma/bcma.h>
162+#include <linux/delay.h>
163+
164+#define BCMA_CORE_SIZE 0x1000
165+
166+struct bcma_bus;
167+
168+/* main.c */
169+int bcma_bus_register(struct bcma_bus *bus);
170+void bcma_bus_unregister(struct bcma_bus *bus);
171+
172+/* scan.c */
173+int bcma_bus_scan(struct bcma_bus *bus);
174+
175+/* sprom.c */
176+int bcma_sprom_get(struct bcma_bus *bus);
177+
178+#ifdef CONFIG_BCMA_HOST_PCI
179+/* host_pci.c */
180+extern int __init bcma_host_pci_init(void);
181+extern void __exit bcma_host_pci_exit(void);
182+#endif /* CONFIG_BCMA_HOST_PCI */
183+
184+#endif
185--- /dev/null
186+++ b/drivers/bcma/core.c
187@@ -0,0 +1,52 @@
188+/*
189+ * Broadcom specific AMBA
190+ * Core ops
191+ *
192+ * Licensed under the GNU/GPL. See COPYING for details.
193+ */
194+
195+#include "bcma_private.h"
196+#include <linux/bcma/bcma.h>
197+
198+bool bcma_core_is_enabled(struct bcma_device *core)
199+{
200+ if ((bcma_aread32(core, BCMA_IOCTL) & (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC))
201+ != BCMA_IOCTL_CLK)
202+ return false;
203+ if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
204+ return false;
205+ return true;
206+}
207+EXPORT_SYMBOL_GPL(bcma_core_is_enabled);
208+
209+void bcma_core_disable(struct bcma_device *core, u32 flags)
210+{
211+ if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
212+ return;
213+
214+ bcma_awrite32(core, BCMA_IOCTL, flags);
215+ bcma_aread32(core, BCMA_IOCTL);
216+ udelay(10);
217+
218+ bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
219+ udelay(1);
220+}
221+EXPORT_SYMBOL_GPL(bcma_core_disable);
222+
223+int bcma_core_enable(struct bcma_device *core, u32 flags)
224+{
225+ bcma_core_disable(core, flags);
226+
227+ bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC | flags));
228+ bcma_aread32(core, BCMA_IOCTL);
229+
230+ bcma_awrite32(core, BCMA_RESET_CTL, 0);
231+ udelay(1);
232+
233+ bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags));
234+ bcma_aread32(core, BCMA_IOCTL);
235+ udelay(1);
236+
237+ return 0;
238+}
239+EXPORT_SYMBOL_GPL(bcma_core_enable);
240--- /dev/null
241+++ b/drivers/bcma/driver_chipcommon.c
242@@ -0,0 +1,89 @@
243+/*
244+ * Broadcom specific AMBA
245+ * ChipCommon core driver
246+ *
247+ * Copyright 2005, Broadcom Corporation
248+ * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
249+ *
250+ * Licensed under the GNU/GPL. See COPYING for details.
251+ */
252+
253+#include "bcma_private.h"
254+#include <linux/bcma/bcma.h>
255+
256+static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
257+ u32 mask, u32 value)
258+{
259+ value &= mask;
260+ value |= bcma_cc_read32(cc, offset) & ~mask;
261+ bcma_cc_write32(cc, offset, value);
262+
263+ return value;
264+}
265+
266+void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
267+{
268+ if (cc->core->id.rev >= 11)
269+ cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
270+ cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
271+ if (cc->core->id.rev >= 35)
272+ cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
273+
274+ if (cc->core->id.rev >= 20) {
275+ bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
276+ bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0);
277+ }
278+
279+ if (cc->capabilities & BCMA_CC_CAP_PMU)
280+ bcma_pmu_init(cc);
281+ if (cc->capabilities & BCMA_CC_CAP_PCTL)
282+ pr_err("Power control not implemented!\n");
283+}
284+
285+/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
286+void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
287+{
288+ /* instant NMI */
289+ bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
290+}
291+
292+void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value)
293+{
294+ bcma_cc_write32_masked(cc, BCMA_CC_IRQMASK, mask, value);
295+}
296+
297+u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask)
298+{
299+ return bcma_cc_read32(cc, BCMA_CC_IRQSTAT) & mask;
300+}
301+
302+u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
303+{
304+ return bcma_cc_read32(cc, BCMA_CC_GPIOIN) & mask;
305+}
306+
307+u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
308+{
309+ return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
310+}
311+
312+u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
313+{
314+ return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
315+}
316+
317+u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
318+{
319+ return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
320+}
321+EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
322+
323+u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
324+{
325+ return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
326+}
327+
328+u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
329+{
330+ return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
331+}
332--- /dev/null
333+++ b/drivers/bcma/driver_chipcommon_pmu.c
334@@ -0,0 +1,138 @@
335+/*
336+ * Broadcom specific AMBA
337+ * ChipCommon Power Management Unit driver
338+ *
339+ * Copyright 2009, Michael Buesch <mb@bu3sch.de>
340+ * Copyright 2007, Broadcom Corporation
341+ *
342+ * Licensed under the GNU/GPL. See COPYING for details.
343+ */
344+
345+#include "bcma_private.h"
346+#include <linux/bcma/bcma.h>
347+
348+static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
349+ u32 offset, u32 mask, u32 set)
350+{
351+ u32 value;
352+
353+ bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
354+ bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset);
355+ bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
356+ value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
357+ value &= mask;
358+ value |= set;
359+ bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value);
360+ bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
361+}
362+
363+static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
364+{
365+ struct bcma_bus *bus = cc->core->bus;
366+
367+ switch (bus->chipinfo.id) {
368+ case 0x4313:
369+ case 0x4331:
370+ case 43224:
371+ case 43225:
372+ break;
373+ default:
374+ pr_err("PLL init unknown for device 0x%04X\n",
375+ bus->chipinfo.id);
376+ }
377+}
378+
379+static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
380+{
381+ struct bcma_bus *bus = cc->core->bus;
382+ u32 min_msk = 0, max_msk = 0;
383+
384+ switch (bus->chipinfo.id) {
385+ case 0x4313:
386+ min_msk = 0x200D;
387+ max_msk = 0xFFFF;
388+ break;
389+ case 43224:
390+ case 43225:
391+ break;
392+ default:
393+ pr_err("PMU resource config unknown for device 0x%04X\n",
394+ bus->chipinfo.id);
395+ }
396+
397+ /* Set the resource masks. */
398+ if (min_msk)
399+ bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk);
400+ if (max_msk)
401+ bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk);
402+}
403+
404+void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
405+{
406+ struct bcma_bus *bus = cc->core->bus;
407+
408+ switch (bus->chipinfo.id) {
409+ case 0x4313:
410+ case 0x4331:
411+ case 43224:
412+ case 43225:
413+ break;
414+ default:
415+ pr_err("PMU switch/regulators init unknown for device "
416+ "0x%04X\n", bus->chipinfo.id);
417+ }
418+}
419+
420+void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
421+{
422+ struct bcma_bus *bus = cc->core->bus;
423+
424+ switch (bus->chipinfo.id) {
425+ case 0x4313:
426+ bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
427+ break;
428+ case 0x4331:
429+ pr_err("Enabling Ext PA lines not implemented\n");
430+ break;
431+ case 43224:
432+ if (bus->chipinfo.rev == 0) {
433+ pr_err("Workarounds for 43224 rev 0 not fully "
434+ "implemented\n");
435+ bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0);
436+ } else {
437+ bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
438+ }
439+ break;
440+ case 43225:
441+ break;
442+ default:
443+ pr_err("Workarounds unknown for device 0x%04X\n",
444+ bus->chipinfo.id);
445+ }
446+}
447+
448+void bcma_pmu_init(struct bcma_drv_cc *cc)
449+{
450+ u32 pmucap;
451+
452+ pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP);
453+ cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION);
454+
455+ pr_debug("Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev,
456+ pmucap);
457+
458+ if (cc->pmu.rev == 1)
459+ bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
460+ ~BCMA_CC_PMU_CTL_NOILPONW);
461+ else
462+ bcma_cc_set32(cc, BCMA_CC_PMU_CTL,
463+ BCMA_CC_PMU_CTL_NOILPONW);
464+
465+ if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2)
466+ pr_err("Fix for 4329b0 bad LPOM state not implemented!\n");
467+
468+ bcma_pmu_pll_init(cc);
469+ bcma_pmu_resources_init(cc);
470+ bcma_pmu_swreg_init(cc);
471+ bcma_pmu_workarounds(cc);
472+}
473--- /dev/null
474+++ b/drivers/bcma/driver_pci.c
475@@ -0,0 +1,187 @@
476+/*
477+ * Broadcom specific AMBA
478+ * PCI Core
479+ *
480+ * Copyright 2005, Broadcom Corporation
481+ * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
482+ *
483+ * Licensed under the GNU/GPL. See COPYING for details.
484+ */
485+
486+#include "bcma_private.h"
487+#include <linux/bcma/bcma.h>
488+
489+/**************************************************
490+ * R/W ops.
491+ **************************************************/
492+
493+static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
494+{
495+ pcicore_write32(pc, 0x130, address);
496+ pcicore_read32(pc, 0x130);
497+ return pcicore_read32(pc, 0x134);
498+}
499+
500+#if 0
501+static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
502+{
503+ pcicore_write32(pc, 0x130, address);
504+ pcicore_read32(pc, 0x130);
505+ pcicore_write32(pc, 0x134, data);
506+}
507+#endif
508+
509+static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
510+{
511+ const u16 mdio_control = 0x128;
512+ const u16 mdio_data = 0x12C;
513+ u32 v;
514+ int i;
515+
516+ v = (1 << 30); /* Start of Transaction */
517+ v |= (1 << 28); /* Write Transaction */
518+ v |= (1 << 17); /* Turnaround */
519+ v |= (0x1F << 18);
520+ v |= (phy << 4);
521+ pcicore_write32(pc, mdio_data, v);
522+
523+ udelay(10);
524+ for (i = 0; i < 200; i++) {
525+ v = pcicore_read32(pc, mdio_control);
526+ if (v & 0x100 /* Trans complete */)
527+ break;
528+ msleep(1);
529+ }
530+}
531+
532+static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
533+{
534+ const u16 mdio_control = 0x128;
535+ const u16 mdio_data = 0x12C;
536+ int max_retries = 10;
537+ u16 ret = 0;
538+ u32 v;
539+ int i;
540+
541+ v = 0x80; /* Enable Preamble Sequence */
542+ v |= 0x2; /* MDIO Clock Divisor */
543+ pcicore_write32(pc, mdio_control, v);
544+
545+ if (pc->core->id.rev >= 10) {
546+ max_retries = 200;
547+ bcma_pcie_mdio_set_phy(pc, device);
548+ }
549+
550+ v = (1 << 30); /* Start of Transaction */
551+ v |= (1 << 29); /* Read Transaction */
552+ v |= (1 << 17); /* Turnaround */
553+ if (pc->core->id.rev < 10)
554+ v |= (u32)device << 22;
555+ v |= (u32)address << 18;
556+ pcicore_write32(pc, mdio_data, v);
557+ /* Wait for the device to complete the transaction */
558+ udelay(10);
559+ for (i = 0; i < max_retries; i++) {
560+ v = pcicore_read32(pc, mdio_control);
561+ if (v & 0x100 /* Trans complete */) {
562+ udelay(10);
563+ ret = pcicore_read32(pc, mdio_data);
564+ break;
565+ }
566+ msleep(1);
567+ }
568+ pcicore_write32(pc, mdio_control, 0);
569+ return ret;
570+}
571+
572+static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
573+ u8 address, u16 data)
574+{
575+ const u16 mdio_control = 0x128;
576+ const u16 mdio_data = 0x12C;
577+ int max_retries = 10;
578+ u32 v;
579+ int i;
580+
581+ v = 0x80; /* Enable Preamble Sequence */
582+ v |= 0x2; /* MDIO Clock Divisor */
583+ pcicore_write32(pc, mdio_control, v);
584+
585+ if (pc->core->id.rev >= 10) {
586+ max_retries = 200;
587+ bcma_pcie_mdio_set_phy(pc, device);
588+ }
589+
590+ v = (1 << 30); /* Start of Transaction */
591+ v |= (1 << 28); /* Write Transaction */
592+ v |= (1 << 17); /* Turnaround */
593+ if (pc->core->id.rev < 10)
594+ v |= (u32)device << 22;
595+ v |= (u32)address << 18;
596+ v |= data;
597+ pcicore_write32(pc, mdio_data, v);
598+ /* Wait for the device to complete the transaction */
599+ udelay(10);
600+ for (i = 0; i < max_retries; i++) {
601+ v = pcicore_read32(pc, mdio_control);
602+ if (v & 0x100 /* Trans complete */)
603+ break;
604+ msleep(1);
605+ }
606+ pcicore_write32(pc, mdio_control, 0);
607+}
608+
609+/**************************************************
610+ * Workarounds.
611+ **************************************************/
612+
613+static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
614+{
615+ return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80;
616+}
617+
618+static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
619+{
620+ const u8 serdes_pll_device = 0x1D;
621+ const u8 serdes_rx_device = 0x1F;
622+ u16 tmp;
623+
624+ bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */,
625+ bcma_pcicore_polarity_workaround(pc));
626+ tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */);
627+ if (tmp & 0x4000)
628+ bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000);
629+}
630+
631+/**************************************************
632+ * Init.
633+ **************************************************/
634+
635+void bcma_core_pci_init(struct bcma_drv_pci *pc)
636+{
637+ bcma_pcicore_serdes_workaround(pc);
638+}
639+
640+int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
641+ bool enable)
642+{
643+ struct pci_dev *pdev = pc->core->bus->host_pci;
644+ u32 coremask, tmp;
645+ int err;
646+
647+ err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
648+ if (err)
649+ goto out;
650+
651+ coremask = BIT(core->core_index) << 8;
652+ if (enable)
653+ tmp |= coremask;
654+ else
655+ tmp &= ~coremask;
656+
657+ err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
658+
659+out:
660+ return err;
661+}
662+EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
663--- /dev/null
664+++ b/drivers/bcma/host_pci.c
665@@ -0,0 +1,251 @@
666+/*
667+ * Broadcom specific AMBA
668+ * PCI Host
669+ *
670+ * Licensed under the GNU/GPL. See COPYING for details.
671+ */
672+
673+#include "bcma_private.h"
674+#include <linux/slab.h>
675+#include <linux/bcma/bcma.h>
676+#include <linux/pci.h>
677+
678+static void bcma_host_pci_switch_core(struct bcma_device *core)
679+{
680+ pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN,
681+ core->addr);
682+ pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2,
683+ core->wrap);
684+ core->bus->mapped_core = core;
685+ pr_debug("Switched to core: 0x%X\n", core->id.id);
686+}
687+
688+static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
689+{
690+ if (core->bus->mapped_core != core)
691+ bcma_host_pci_switch_core(core);
692+ return ioread8(core->bus->mmio + offset);
693+}
694+
695+static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
696+{
697+ if (core->bus->mapped_core != core)
698+ bcma_host_pci_switch_core(core);
699+ return ioread16(core->bus->mmio + offset);
700+}
701+
702+static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
703+{
704+ if (core->bus->mapped_core != core)
705+ bcma_host_pci_switch_core(core);
706+ return ioread32(core->bus->mmio + offset);
707+}
708+
709+static void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
710+ u8 value)
711+{
712+ if (core->bus->mapped_core != core)
713+ bcma_host_pci_switch_core(core);
714+ iowrite8(value, core->bus->mmio + offset);
715+}
716+
717+static void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
718+ u16 value)
719+{
720+ if (core->bus->mapped_core != core)
721+ bcma_host_pci_switch_core(core);
722+ iowrite16(value, core->bus->mmio + offset);
723+}
724+
725+static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
726+ u32 value)
727+{
728+ if (core->bus->mapped_core != core)
729+ bcma_host_pci_switch_core(core);
730+ iowrite32(value, core->bus->mmio + offset);
731+}
732+
733+#ifdef CONFIG_BCMA_BLOCKIO
734+void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
735+ size_t count, u16 offset, u8 reg_width)
736+{
737+ void __iomem *addr = core->bus->mmio + offset;
738+ if (core->bus->mapped_core != core)
739+ bcma_host_pci_switch_core(core);
740+ switch (reg_width) {
741+ case sizeof(u8):
742+ ioread8_rep(addr, buffer, count);
743+ break;
744+ case sizeof(u16):
745+ WARN_ON(count & 1);
746+ ioread16_rep(addr, buffer, count >> 1);
747+ break;
748+ case sizeof(u32):
749+ WARN_ON(count & 3);
750+ ioread32_rep(addr, buffer, count >> 2);
751+ break;
752+ default:
753+ WARN_ON(1);
754+ }
755+}
756+
757+void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
758+ size_t count, u16 offset, u8 reg_width)
759+{
760+ void __iomem *addr = core->bus->mmio + offset;
761+ if (core->bus->mapped_core != core)
762+ bcma_host_pci_switch_core(core);
763+ switch (reg_width) {
764+ case sizeof(u8):
765+ iowrite8_rep(addr, buffer, count);
766+ break;
767+ case sizeof(u16):
768+ WARN_ON(count & 1);
769+ iowrite16_rep(addr, buffer, count >> 1);
770+ break;
771+ case sizeof(u32):
772+ WARN_ON(count & 3);
773+ iowrite32_rep(addr, buffer, count >> 2);
774+ break;
775+ default:
776+ WARN_ON(1);
777+ }
778+}
779+#endif
780+
781+static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
782+{
783+ if (core->bus->mapped_core != core)
784+ bcma_host_pci_switch_core(core);
785+ return ioread32(core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
786+}
787+
788+static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset,
789+ u32 value)
790+{
791+ if (core->bus->mapped_core != core)
792+ bcma_host_pci_switch_core(core);
793+ iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
794+}
795+
796+const struct bcma_host_ops bcma_host_pci_ops = {
797+ .read8 = bcma_host_pci_read8,
798+ .read16 = bcma_host_pci_read16,
799+ .read32 = bcma_host_pci_read32,
800+ .write8 = bcma_host_pci_write8,
801+ .write16 = bcma_host_pci_write16,
802+ .write32 = bcma_host_pci_write32,
803+#ifdef CONFIG_BCMA_BLOCKIO
804+ .block_read = bcma_host_pci_block_read,
805+ .block_write = bcma_host_pci_block_write,
806+#endif
807+ .aread32 = bcma_host_pci_aread32,
808+ .awrite32 = bcma_host_pci_awrite32,
809+};
810+
811+static int bcma_host_pci_probe(struct pci_dev *dev,
812+ const struct pci_device_id *id)
813+{
814+ struct bcma_bus *bus;
815+ int err = -ENOMEM;
816+ const char *name;
817+ u32 val;
818+
819+ /* Alloc */
820+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
821+ if (!bus)
822+ goto out;
823+
824+ /* Basic PCI configuration */
825+ err = pci_enable_device(dev);
826+ if (err)
827+ goto err_kfree_bus;
828+
829+ name = dev_name(&dev->dev);
830+ if (dev->driver && dev->driver->name)
831+ name = dev->driver->name;
832+ err = pci_request_regions(dev, name);
833+ if (err)
834+ goto err_pci_disable;
835+ pci_set_master(dev);
836+
837+ /* Disable the RETRY_TIMEOUT register (0x41) to keep
838+ * PCI Tx retries from interfering with C3 CPU state */
839+ pci_read_config_dword(dev, 0x40, &val);
840+ if ((val & 0x0000ff00) != 0)
841+ pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
842+
843+ /* SSB needed additional powering up, do we have any AMBA PCI cards? */
844+ if (!pci_is_pcie(dev))
845+ pr_err("PCI card detected, report problems.\n");
846+
847+ /* Map MMIO */
848+ err = -ENOMEM;
849+ bus->mmio = pci_iomap(dev, 0, ~0UL);
850+ if (!bus->mmio)
851+ goto err_pci_release_regions;
852+
853+ /* Host specific */
854+ bus->host_pci = dev;
855+ bus->hosttype = BCMA_HOSTTYPE_PCI;
856+ bus->ops = &bcma_host_pci_ops;
857+
858+ /* Register */
859+ err = bcma_bus_register(bus);
860+ if (err)
861+ goto err_pci_unmap_mmio;
862+
863+ pci_set_drvdata(dev, bus);
864+
865+out:
866+ return err;
867+
868+err_pci_unmap_mmio:
869+ pci_iounmap(dev, bus->mmio);
870+err_pci_release_regions:
871+ pci_release_regions(dev);
872+err_pci_disable:
873+ pci_disable_device(dev);
874+err_kfree_bus:
875+ kfree(bus);
876+ return err;
877+}
878+
879+static void bcma_host_pci_remove(struct pci_dev *dev)
880+{
881+ struct bcma_bus *bus = pci_get_drvdata(dev);
882+
883+ bcma_bus_unregister(bus);
884+ pci_iounmap(dev, bus->mmio);
885+ pci_release_regions(dev);
886+ pci_disable_device(dev);
887+ kfree(bus);
888+ pci_set_drvdata(dev, NULL);
889+}
890+
891+static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
892+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
893+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
894+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
895+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
896+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
897+ { 0, },
898+};
899+MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
900+
901+static struct pci_driver bcma_pci_bridge_driver = {
902+ .name = "bcma-pci-bridge",
903+ .id_table = bcma_pci_bridge_tbl,
904+ .probe = bcma_host_pci_probe,
905+ .remove = bcma_host_pci_remove,
906+};
907+
908+int __init bcma_host_pci_init(void)
909+{
910+ return pci_register_driver(&bcma_pci_bridge_driver);
911+}
912+
913+void __exit bcma_host_pci_exit(void)
914+{
915+ pci_unregister_driver(&bcma_pci_bridge_driver);
916+}
917--- /dev/null
918+++ b/drivers/bcma/main.c
919@@ -0,0 +1,255 @@
920+/*
921+ * Broadcom specific AMBA
922+ * Bus subsystem
923+ *
924+ * Licensed under the GNU/GPL. See COPYING for details.
925+ */
926+
927+#include "bcma_private.h"
928+#include <linux/bcma/bcma.h>
929+#include <linux/slab.h>
930+
931+MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
932+MODULE_LICENSE("GPL");
933+
934+static int bcma_bus_match(struct device *dev, struct device_driver *drv);
935+static int bcma_device_probe(struct device *dev);
936+static int bcma_device_remove(struct device *dev);
937+
938+static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
939+{
940+ struct bcma_device *core = container_of(dev, struct bcma_device, dev);
941+ return sprintf(buf, "0x%03X\n", core->id.manuf);
942+}
943+static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
944+{
945+ struct bcma_device *core = container_of(dev, struct bcma_device, dev);
946+ return sprintf(buf, "0x%03X\n", core->id.id);
947+}
948+static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
949+{
950+ struct bcma_device *core = container_of(dev, struct bcma_device, dev);
951+ return sprintf(buf, "0x%02X\n", core->id.rev);
952+}
953+static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
954+{
955+ struct bcma_device *core = container_of(dev, struct bcma_device, dev);
956+ return sprintf(buf, "0x%X\n", core->id.class);
957+}
958+static struct device_attribute bcma_device_attrs[] = {
959+ __ATTR_RO(manuf),
960+ __ATTR_RO(id),
961+ __ATTR_RO(rev),
962+ __ATTR_RO(class),
963+ __ATTR_NULL,
964+};
965+
966+static struct bus_type bcma_bus_type = {
967+ .name = "bcma",
968+ .match = bcma_bus_match,
969+ .probe = bcma_device_probe,
970+ .remove = bcma_device_remove,
971+ .dev_attrs = bcma_device_attrs,
972+};
973+
974+static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
975+{
976+ struct bcma_device *core;
977+
978+ list_for_each_entry(core, &bus->cores, list) {
979+ if (core->id.id == coreid)
980+ return core;
981+ }
982+ return NULL;
983+}
984+
985+static void bcma_release_core_dev(struct device *dev)
986+{
987+ struct bcma_device *core = container_of(dev, struct bcma_device, dev);
988+ kfree(core);
989+}
990+
991+static int bcma_register_cores(struct bcma_bus *bus)
992+{
993+ struct bcma_device *core;
994+ int err, dev_id = 0;
995+
996+ list_for_each_entry(core, &bus->cores, list) {
997+ /* We support that cores ourself */
998+ switch (core->id.id) {
999+ case BCMA_CORE_CHIPCOMMON:
1000+ case BCMA_CORE_PCI:
1001+ case BCMA_CORE_PCIE:
1002+ continue;
1003+ }
1004+
1005+ core->dev.release = bcma_release_core_dev;
1006+ core->dev.bus = &bcma_bus_type;
1007+ dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
1008+
1009+ switch (bus->hosttype) {
1010+ case BCMA_HOSTTYPE_PCI:
1011+ core->dev.parent = &bus->host_pci->dev;
1012+ core->dma_dev = &bus->host_pci->dev;
1013+ core->irq = bus->host_pci->irq;
1014+ break;
1015+ case BCMA_HOSTTYPE_NONE:
1016+ case BCMA_HOSTTYPE_SDIO:
1017+ break;
1018+ }
1019+
1020+ err = device_register(&core->dev);
1021+ if (err) {
1022+ pr_err("Could not register dev for core 0x%03X\n",
1023+ core->id.id);
1024+ continue;
1025+ }
1026+ core->dev_registered = true;
1027+ dev_id++;
1028+ }
1029+
1030+ return 0;
1031+}
1032+
1033+static void bcma_unregister_cores(struct bcma_bus *bus)
1034+{
1035+ struct bcma_device *core;
1036+
1037+ list_for_each_entry(core, &bus->cores, list) {
1038+ if (core->dev_registered)
1039+ device_unregister(&core->dev);
1040+ }
1041+}
1042+
1043+int bcma_bus_register(struct bcma_bus *bus)
1044+{
1045+ int err;
1046+ struct bcma_device *core;
1047+
1048+ /* Scan for devices (cores) */
1049+ err = bcma_bus_scan(bus);
1050+ if (err) {
1051+ pr_err("Failed to scan: %d\n", err);
1052+ return -1;
1053+ }
1054+
1055+ /* Init CC core */
1056+ core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
1057+ if (core) {
1058+ bus->drv_cc.core = core;
1059+ bcma_core_chipcommon_init(&bus->drv_cc);
1060+ }
1061+
1062+ /* Init PCIE core */
1063+ core = bcma_find_core(bus, BCMA_CORE_PCIE);
1064+ if (core) {
1065+ bus->drv_pci.core = core;
1066+ bcma_core_pci_init(&bus->drv_pci);
1067+ }
1068+
1069+ /* Try to get SPROM */
1070+ err = bcma_sprom_get(bus);
1071+ if (err) {
1072+ pr_err("Failed to get SPROM: %d\n", err);
1073+ return -ENOENT;
1074+ }
1075+
1076+ /* Register found cores */
1077+ bcma_register_cores(bus);
1078+
1079+ pr_info("Bus registered\n");
1080+
1081+ return 0;
1082+}
1083+
1084+void bcma_bus_unregister(struct bcma_bus *bus)
1085+{
1086+ bcma_unregister_cores(bus);
1087+}
1088+
1089+int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
1090+{
1091+ drv->drv.name = drv->name;
1092+ drv->drv.bus = &bcma_bus_type;
1093+ drv->drv.owner = owner;
1094+
1095+ return driver_register(&drv->drv);
1096+}
1097+EXPORT_SYMBOL_GPL(__bcma_driver_register);
1098+
1099+void bcma_driver_unregister(struct bcma_driver *drv)
1100+{
1101+ driver_unregister(&drv->drv);
1102+}
1103+EXPORT_SYMBOL_GPL(bcma_driver_unregister);
1104+
1105+static int bcma_bus_match(struct device *dev, struct device_driver *drv)
1106+{
1107+ struct bcma_device *core = container_of(dev, struct bcma_device, dev);
1108+ struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
1109+ const struct bcma_device_id *cid = &core->id;
1110+ const struct bcma_device_id *did;
1111+
1112+ for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) {
1113+ if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) &&
1114+ (did->id == cid->id || did->id == BCMA_ANY_ID) &&
1115+ (did->rev == cid->rev || did->rev == BCMA_ANY_REV) &&
1116+ (did->class == cid->class || did->class == BCMA_ANY_CLASS))
1117+ return 1;
1118+ }
1119+ return 0;
1120+}
1121+
1122+static int bcma_device_probe(struct device *dev)
1123+{
1124+ struct bcma_device *core = container_of(dev, struct bcma_device, dev);
1125+ struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
1126+ drv);
1127+ int err = 0;
1128+
1129+ if (adrv->probe)
1130+ err = adrv->probe(core);
1131+
1132+ return err;
1133+}
1134+
1135+static int bcma_device_remove(struct device *dev)
1136+{
1137+ struct bcma_device *core = container_of(dev, struct bcma_device, dev);
1138+ struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
1139+ drv);
1140+
1141+ if (adrv->remove)
1142+ adrv->remove(core);
1143+
1144+ return 0;
1145+}
1146+
1147+static int __init bcma_modinit(void)
1148+{
1149+ int err;
1150+
1151+ err = bus_register(&bcma_bus_type);
1152+ if (err)
1153+ return err;
1154+
1155+#ifdef CONFIG_BCMA_HOST_PCI
1156+ err = bcma_host_pci_init();
1157+ if (err) {
1158+ pr_err("PCI host initialization failed\n");
1159+ err = 0;
1160+ }
1161+#endif
1162+
1163+ return err;
1164+}
1165+fs_initcall(bcma_modinit);
1166+
1167+static void __exit bcma_modexit(void)
1168+{
1169+#ifdef CONFIG_BCMA_HOST_PCI
1170+ bcma_host_pci_exit();
1171+#endif
1172+ bus_unregister(&bcma_bus_type);
1173+}
1174+module_exit(bcma_modexit)
1175--- /dev/null
1176+++ b/drivers/bcma/scan.c
1177@@ -0,0 +1,360 @@
1178+/*
1179+ * Broadcom specific AMBA
1180+ * Bus scanning
1181+ *
1182+ * Licensed under the GNU/GPL. See COPYING for details.
1183+ */
1184+
1185+#include "scan.h"
1186+#include "bcma_private.h"
1187+
1188+#include <linux/bcma/bcma.h>
1189+#include <linux/bcma/bcma_regs.h>
1190+#include <linux/pci.h>
1191+#include <linux/io.h>
1192+#include <linux/dma-mapping.h>
1193+#include <linux/slab.h>
1194+
1195+struct bcma_device_id_name {
1196+ u16 id;
1197+ const char *name;
1198+};
1199+struct bcma_device_id_name bcma_device_names[] = {
1200+ { BCMA_CORE_OOB_ROUTER, "OOB Router" },
1201+ { BCMA_CORE_INVALID, "Invalid" },
1202+ { BCMA_CORE_CHIPCOMMON, "ChipCommon" },
1203+ { BCMA_CORE_ILINE20, "ILine 20" },
1204+ { BCMA_CORE_SRAM, "SRAM" },
1205+ { BCMA_CORE_SDRAM, "SDRAM" },
1206+ { BCMA_CORE_PCI, "PCI" },
1207+ { BCMA_CORE_MIPS, "MIPS" },
1208+ { BCMA_CORE_ETHERNET, "Fast Ethernet" },
1209+ { BCMA_CORE_V90, "V90" },
1210+ { BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
1211+ { BCMA_CORE_ADSL, "ADSL" },
1212+ { BCMA_CORE_ILINE100, "ILine 100" },
1213+ { BCMA_CORE_IPSEC, "IPSEC" },
1214+ { BCMA_CORE_UTOPIA, "UTOPIA" },
1215+ { BCMA_CORE_PCMCIA, "PCMCIA" },
1216+ { BCMA_CORE_INTERNAL_MEM, "Internal Memory" },
1217+ { BCMA_CORE_MEMC_SDRAM, "MEMC SDRAM" },
1218+ { BCMA_CORE_OFDM, "OFDM" },
1219+ { BCMA_CORE_EXTIF, "EXTIF" },
1220+ { BCMA_CORE_80211, "IEEE 802.11" },
1221+ { BCMA_CORE_PHY_A, "PHY A" },
1222+ { BCMA_CORE_PHY_B, "PHY B" },
1223+ { BCMA_CORE_PHY_G, "PHY G" },
1224+ { BCMA_CORE_MIPS_3302, "MIPS 3302" },
1225+ { BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
1226+ { BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
1227+ { BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
1228+ { BCMA_CORE_USB20_DEV, "USB 2.0 Device" },
1229+ { BCMA_CORE_SDIO_HOST, "SDIO Host" },
1230+ { BCMA_CORE_ROBOSWITCH, "Roboswitch" },
1231+ { BCMA_CORE_PARA_ATA, "PATA" },
1232+ { BCMA_CORE_SATA_XORDMA, "SATA XOR-DMA" },
1233+ { BCMA_CORE_ETHERNET_GBIT, "GBit Ethernet" },
1234+ { BCMA_CORE_PCIE, "PCIe" },
1235+ { BCMA_CORE_PHY_N, "PHY N" },
1236+ { BCMA_CORE_SRAM_CTL, "SRAM Controller" },
1237+ { BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
1238+ { BCMA_CORE_ARM_1176, "ARM 1176" },
1239+ { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
1240+ { BCMA_CORE_PHY_LP, "PHY LP" },
1241+ { BCMA_CORE_PMU, "PMU" },
1242+ { BCMA_CORE_PHY_SSN, "PHY SSN" },
1243+ { BCMA_CORE_SDIO_DEV, "SDIO Device" },
1244+ { BCMA_CORE_ARM_CM3, "ARM CM3" },
1245+ { BCMA_CORE_PHY_HT, "PHY HT" },
1246+ { BCMA_CORE_MIPS_74K, "MIPS 74K" },
1247+ { BCMA_CORE_MAC_GBIT, "GBit MAC" },
1248+ { BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
1249+ { BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
1250+ { BCMA_CORE_OCP_OCP_BRIDGE, "OCP to OCP Bridge" },
1251+ { BCMA_CORE_SHARED_COMMON, "Common Shared" },
1252+ { BCMA_CORE_OCP_AHB_BRIDGE, "OCP to AHB Bridge" },
1253+ { BCMA_CORE_SPI_HOST, "SPI Host" },
1254+ { BCMA_CORE_I2S, "I2S" },
1255+ { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" },
1256+ { BCMA_CORE_SHIM, "SHIM" },
1257+ { BCMA_CORE_DEFAULT, "Default" },
1258+};
1259+const char *bcma_device_name(struct bcma_device_id *id)
1260+{
1261+ int i;
1262+
1263+ if (id->manuf == BCMA_MANUF_BCM) {
1264+ for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) {
1265+ if (bcma_device_names[i].id == id->id)
1266+ return bcma_device_names[i].name;
1267+ }
1268+ }
1269+ return "UNKNOWN";
1270+}
1271+
1272+static u32 bcma_scan_read32(struct bcma_bus *bus, u8 current_coreidx,
1273+ u16 offset)
1274+{
1275+ return readl(bus->mmio + offset);
1276+}
1277+
1278+static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr)
1279+{
1280+ if (bus->hosttype == BCMA_HOSTTYPE_PCI)
1281+ pci_write_config_dword(bus->host_pci, BCMA_PCI_BAR0_WIN,
1282+ addr);
1283+}
1284+
1285+static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr)
1286+{
1287+ u32 ent = readl(*eromptr);
1288+ (*eromptr)++;
1289+ return ent;
1290+}
1291+
1292+static void bcma_erom_push_ent(u32 **eromptr)
1293+{
1294+ (*eromptr)--;
1295+}
1296+
1297+static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr)
1298+{
1299+ u32 ent = bcma_erom_get_ent(bus, eromptr);
1300+ if (!(ent & SCAN_ER_VALID))
1301+ return -ENOENT;
1302+ if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_CI)
1303+ return -ENOENT;
1304+ return ent;
1305+}
1306+
1307+static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr)
1308+{
1309+ u32 ent = bcma_erom_get_ent(bus, eromptr);
1310+ bcma_erom_push_ent(eromptr);
1311+ return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID));
1312+}
1313+
1314+static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr)
1315+{
1316+ u32 ent = bcma_erom_get_ent(bus, eromptr);
1317+ bcma_erom_push_ent(eromptr);
1318+ return (((ent & SCAN_ER_VALID)) &&
1319+ ((ent & SCAN_ER_TAGX) == SCAN_ER_TAG_ADDR) &&
1320+ ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE));
1321+}
1322+
1323+static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr)
1324+{
1325+ u32 ent;
1326+ while (1) {
1327+ ent = bcma_erom_get_ent(bus, eromptr);
1328+ if ((ent & SCAN_ER_VALID) &&
1329+ ((ent & SCAN_ER_TAG) == SCAN_ER_TAG_CI))
1330+ break;
1331+ if (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID))
1332+ break;
1333+ }
1334+ bcma_erom_push_ent(eromptr);
1335+}
1336+
1337+static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr)
1338+{
1339+ u32 ent = bcma_erom_get_ent(bus, eromptr);
1340+ if (!(ent & SCAN_ER_VALID))
1341+ return -ENOENT;
1342+ if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_MP)
1343+ return -ENOENT;
1344+ return ent;
1345+}
1346+
1347+static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
1348+ u32 type, u8 port)
1349+{
1350+ u32 addrl, addrh, sizel, sizeh = 0;
1351+ u32 size;
1352+
1353+ u32 ent = bcma_erom_get_ent(bus, eromptr);
1354+ if ((!(ent & SCAN_ER_VALID)) ||
1355+ ((ent & SCAN_ER_TAGX) != SCAN_ER_TAG_ADDR) ||
1356+ ((ent & SCAN_ADDR_TYPE) != type) ||
1357+ (((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) {
1358+ bcma_erom_push_ent(eromptr);
1359+ return -EINVAL;
1360+ }
1361+
1362+ addrl = ent & SCAN_ADDR_ADDR;
1363+ if (ent & SCAN_ADDR_AG32)
1364+ addrh = bcma_erom_get_ent(bus, eromptr);
1365+ else
1366+ addrh = 0;
1367+
1368+ if ((ent & SCAN_ADDR_SZ) == SCAN_ADDR_SZ_SZD) {
1369+ size = bcma_erom_get_ent(bus, eromptr);
1370+ sizel = size & SCAN_SIZE_SZ;
1371+ if (size & SCAN_SIZE_SG32)
1372+ sizeh = bcma_erom_get_ent(bus, eromptr);
1373+ } else
1374+ sizel = SCAN_ADDR_SZ_BASE <<
1375+ ((ent & SCAN_ADDR_SZ) >> SCAN_ADDR_SZ_SHIFT);
1376+
1377+ return addrl;
1378+}
1379+
1380+int bcma_bus_scan(struct bcma_bus *bus)
1381+{
1382+ u32 erombase;
1383+ u32 __iomem *eromptr, *eromend;
1384+
1385+ s32 cia, cib;
1386+ u8 ports[2], wrappers[2];
1387+
1388+ s32 tmp;
1389+ u8 i, j;
1390+
1391+ int err;
1392+
1393+ INIT_LIST_HEAD(&bus->cores);
1394+ bus->nr_cores = 0;
1395+
1396+ bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
1397+
1398+ tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
1399+ bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
1400+ bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
1401+ bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
1402+
1403+ erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
1404+ eromptr = bus->mmio;
1405+ eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
1406+
1407+ bcma_scan_switch_core(bus, erombase);
1408+
1409+ while (eromptr < eromend) {
1410+ struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
1411+ if (!core)
1412+ return -ENOMEM;
1413+ INIT_LIST_HEAD(&core->list);
1414+ core->bus = bus;
1415+
1416+ /* get CIs */
1417+ cia = bcma_erom_get_ci(bus, &eromptr);
1418+ if (cia < 0) {
1419+ bcma_erom_push_ent(&eromptr);
1420+ if (bcma_erom_is_end(bus, &eromptr))
1421+ break;
1422+ err= -EILSEQ;
1423+ goto out;
1424+ }
1425+ cib = bcma_erom_get_ci(bus, &eromptr);
1426+ if (cib < 0) {
1427+ err= -EILSEQ;
1428+ goto out;
1429+ }
1430+
1431+ /* parse CIs */
1432+ core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
1433+ core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
1434+ core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
1435+ ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
1436+ ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
1437+ wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
1438+ wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
1439+ core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
1440+
1441+ if (((core->id.manuf == BCMA_MANUF_ARM) &&
1442+ (core->id.id == 0xFFF)) ||
1443+ (ports[1] == 0)) {
1444+ bcma_erom_skip_component(bus, &eromptr);
1445+ continue;
1446+ }
1447+
1448+ /* check if component is a core at all */
1449+ if (wrappers[0] + wrappers[1] == 0) {
1450+ /* we could save addrl of the router
1451+ if (cid == BCMA_CORE_OOB_ROUTER)
1452+ */
1453+ bcma_erom_skip_component(bus, &eromptr);
1454+ continue;
1455+ }
1456+
1457+ if (bcma_erom_is_bridge(bus, &eromptr)) {
1458+ bcma_erom_skip_component(bus, &eromptr);
1459+ continue;
1460+ }
1461+
1462+ /* get & parse master ports */
1463+ for (i = 0; i < ports[0]; i++) {
1464+ u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr);
1465+ if (mst_port_d < 0) {
1466+ err= -EILSEQ;
1467+ goto out;
1468+ }
1469+ }
1470+
1471+ /* get & parse slave ports */
1472+ for (i = 0; i < ports[1]; i++) {
1473+ for (j = 0; ; j++) {
1474+ tmp = bcma_erom_get_addr_desc(bus, &eromptr,
1475+ SCAN_ADDR_TYPE_SLAVE, i);
1476+ if (tmp < 0) {
1477+ /* no more entries for port _i_ */
1478+ /* pr_debug("erom: slave port %d "
1479+ * "has %d descriptors\n", i, j); */
1480+ break;
1481+ } else {
1482+ if (i == 0 && j == 0)
1483+ core->addr = tmp;
1484+ }
1485+ }
1486+ }
1487+
1488+ /* get & parse master wrappers */
1489+ for (i = 0; i < wrappers[0]; i++) {
1490+ for (j = 0; ; j++) {
1491+ tmp = bcma_erom_get_addr_desc(bus, &eromptr,
1492+ SCAN_ADDR_TYPE_MWRAP, i);
1493+ if (tmp < 0) {
1494+ /* no more entries for port _i_ */
1495+ /* pr_debug("erom: master wrapper %d "
1496+ * "has %d descriptors\n", i, j); */
1497+ break;
1498+ } else {
1499+ if (i == 0 && j == 0)
1500+ core->wrap = tmp;
1501+ }
1502+ }
1503+ }
1504+
1505+ /* get & parse slave wrappers */
1506+ for (i = 0; i < wrappers[1]; i++) {
1507+ u8 hack = (ports[1] == 1) ? 0 : 1;
1508+ for (j = 0; ; j++) {
1509+ tmp = bcma_erom_get_addr_desc(bus, &eromptr,
1510+ SCAN_ADDR_TYPE_SWRAP, i + hack);
1511+ if (tmp < 0) {
1512+ /* no more entries for port _i_ */
1513+ /* pr_debug("erom: master wrapper %d "
1514+ * has %d descriptors\n", i, j); */
1515+ break;
1516+ } else {
1517+ if (wrappers[0] == 0 && !i && !j)
1518+ core->wrap = tmp;
1519+ }
1520+ }
1521+ }
1522+
1523+ pr_info("Core %d found: %s "
1524+ "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
1525+ bus->nr_cores, bcma_device_name(&core->id),
1526+ core->id.manuf, core->id.id, core->id.rev,
1527+ core->id.class);
1528+
1529+ core->core_index = bus->nr_cores++;
1530+ list_add(&core->list, &bus->cores);
1531+ continue;
1532+out:
1533+ return err;
1534+ }
1535+
1536+ return 0;
1537+}
1538--- /dev/null
1539+++ b/drivers/bcma/scan.h
1540@@ -0,0 +1,56 @@
1541+#ifndef BCMA_SCAN_H_
1542+#define BCMA_SCAN_H_
1543+
1544+#define BCMA_ADDR_BASE 0x18000000
1545+#define BCMA_WRAP_BASE 0x18100000
1546+
1547+#define SCAN_ER_VALID 0x00000001
1548+#define SCAN_ER_TAGX 0x00000006 /* we have to ignore 0x8 bit when checking tag for SCAN_ER_TAG_ADDR */
1549+#define SCAN_ER_TAG 0x0000000E
1550+#define SCAN_ER_TAG_CI 0x00000000
1551+#define SCAN_ER_TAG_MP 0x00000002
1552+#define SCAN_ER_TAG_ADDR 0x00000004
1553+#define SCAN_ER_TAG_END 0x0000000E
1554+#define SCAN_ER_BAD 0xFFFFFFFF
1555+
1556+#define SCAN_CIA_CLASS 0x000000F0
1557+#define SCAN_CIA_CLASS_SHIFT 4
1558+#define SCAN_CIA_ID 0x000FFF00
1559+#define SCAN_CIA_ID_SHIFT 8
1560+#define SCAN_CIA_MANUF 0xFFF00000
1561+#define SCAN_CIA_MANUF_SHIFT 20
1562+
1563+#define SCAN_CIB_NMP 0x000001F0
1564+#define SCAN_CIB_NMP_SHIFT 4
1565+#define SCAN_CIB_NSP 0x00003E00
1566+#define SCAN_CIB_NSP_SHIFT 9
1567+#define SCAN_CIB_NMW 0x0007C000
1568+#define SCAN_CIB_NMW_SHIFT 14
1569+#define SCAN_CIB_NSW 0x00F80000
1570+#define SCAN_CIB_NSW_SHIFT 17
1571+#define SCAN_CIB_REV 0xFF000000
1572+#define SCAN_CIB_REV_SHIFT 24
1573+
1574+#define SCAN_ADDR_AG32 0x00000008
1575+#define SCAN_ADDR_SZ 0x00000030
1576+#define SCAN_ADDR_SZ_SHIFT 4
1577+#define SCAN_ADDR_SZ_4K 0x00000000
1578+#define SCAN_ADDR_SZ_8K 0x00000010
1579+#define SCAN_ADDR_SZ_16K 0x00000020
1580+#define SCAN_ADDR_SZ_SZD 0x00000030
1581+#define SCAN_ADDR_TYPE 0x000000C0
1582+#define SCAN_ADDR_TYPE_SLAVE 0x00000000
1583+#define SCAN_ADDR_TYPE_BRIDGE 0x00000040
1584+#define SCAN_ADDR_TYPE_SWRAP 0x00000080
1585+#define SCAN_ADDR_TYPE_MWRAP 0x000000C0
1586+#define SCAN_ADDR_PORT 0x00000F00
1587+#define SCAN_ADDR_PORT_SHIFT 8
1588+#define SCAN_ADDR_ADDR 0xFFFFF000
1589+
1590+#define SCAN_ADDR_SZ_BASE 0x00001000 /* 4KB */
1591+
1592+#define SCAN_SIZE_SZ_ALIGN 0x00000FFF
1593+#define SCAN_SIZE_SZ 0xFFFFF000
1594+#define SCAN_SIZE_SG32 0x00000008
1595+
1596+#endif /* BCMA_SCAN_H_ */
1597--- /dev/null
1598+++ b/include/linux/bcma/bcma.h
1599@@ -0,0 +1,250 @@
1600+#ifndef LINUX_BCMA_H_
1601+#define LINUX_BCMA_H_
1602+
1603+#include <linux/pci.h>
1604+#include <linux/mod_devicetable.h>
1605+
1606+#include <linux/bcma/bcma_driver_chipcommon.h>
1607+#include <linux/bcma/bcma_driver_pci.h>
1608+#include <linux/ssb/ssb.h> /* SPROM sharing */
1609+
1610+#include "bcma_regs.h"
1611+
1612+struct bcma_device;
1613+struct bcma_bus;
1614+
1615+enum bcma_hosttype {
1616+ BCMA_HOSTTYPE_NONE,
1617+ BCMA_HOSTTYPE_PCI,
1618+ BCMA_HOSTTYPE_SDIO,
1619+};
1620+
1621+struct bcma_chipinfo {
1622+ u16 id;
1623+ u8 rev;
1624+ u8 pkg;
1625+};
1626+
1627+struct bcma_host_ops {
1628+ u8 (*read8)(struct bcma_device *core, u16 offset);
1629+ u16 (*read16)(struct bcma_device *core, u16 offset);
1630+ u32 (*read32)(struct bcma_device *core, u16 offset);
1631+ void (*write8)(struct bcma_device *core, u16 offset, u8 value);
1632+ void (*write16)(struct bcma_device *core, u16 offset, u16 value);
1633+ void (*write32)(struct bcma_device *core, u16 offset, u32 value);
1634+#ifdef CONFIG_BCMA_BLOCKIO
1635+ void (*block_read)(struct bcma_device *core, void *buffer,
1636+ size_t count, u16 offset, u8 reg_width);
1637+ void (*block_write)(struct bcma_device *core, const void *buffer,
1638+ size_t count, u16 offset, u8 reg_width);
1639+#endif
1640+ /* Agent ops */
1641+ u32 (*aread32)(struct bcma_device *core, u16 offset);
1642+ void (*awrite32)(struct bcma_device *core, u16 offset, u32 value);
1643+};
1644+
1645+/* Core manufacturers */
1646+#define BCMA_MANUF_ARM 0x43B
1647+#define BCMA_MANUF_MIPS 0x4A7
1648+#define BCMA_MANUF_BCM 0x4BF
1649+
1650+/* Core class values. */
1651+#define BCMA_CL_SIM 0x0
1652+#define BCMA_CL_EROM 0x1
1653+#define BCMA_CL_CORESIGHT 0x9
1654+#define BCMA_CL_VERIF 0xB
1655+#define BCMA_CL_OPTIMO 0xD
1656+#define BCMA_CL_GEN 0xE
1657+#define BCMA_CL_PRIMECELL 0xF
1658+
1659+/* Core-ID values. */
1660+#define BCMA_CORE_OOB_ROUTER 0x367 /* Out of band */
1661+#define BCMA_CORE_INVALID 0x700
1662+#define BCMA_CORE_CHIPCOMMON 0x800
1663+#define BCMA_CORE_ILINE20 0x801
1664+#define BCMA_CORE_SRAM 0x802
1665+#define BCMA_CORE_SDRAM 0x803
1666+#define BCMA_CORE_PCI 0x804
1667+#define BCMA_CORE_MIPS 0x805
1668+#define BCMA_CORE_ETHERNET 0x806
1669+#define BCMA_CORE_V90 0x807
1670+#define BCMA_CORE_USB11_HOSTDEV 0x808
1671+#define BCMA_CORE_ADSL 0x809
1672+#define BCMA_CORE_ILINE100 0x80A
1673+#define BCMA_CORE_IPSEC 0x80B
1674+#define BCMA_CORE_UTOPIA 0x80C
1675+#define BCMA_CORE_PCMCIA 0x80D
1676+#define BCMA_CORE_INTERNAL_MEM 0x80E
1677+#define BCMA_CORE_MEMC_SDRAM 0x80F
1678+#define BCMA_CORE_OFDM 0x810
1679+#define BCMA_CORE_EXTIF 0x811
1680+#define BCMA_CORE_80211 0x812
1681+#define BCMA_CORE_PHY_A 0x813
1682+#define BCMA_CORE_PHY_B 0x814
1683+#define BCMA_CORE_PHY_G 0x815
1684+#define BCMA_CORE_MIPS_3302 0x816
1685+#define BCMA_CORE_USB11_HOST 0x817
1686+#define BCMA_CORE_USB11_DEV 0x818
1687+#define BCMA_CORE_USB20_HOST 0x819
1688+#define BCMA_CORE_USB20_DEV 0x81A
1689+#define BCMA_CORE_SDIO_HOST 0x81B
1690+#define BCMA_CORE_ROBOSWITCH 0x81C
1691+#define BCMA_CORE_PARA_ATA 0x81D
1692+#define BCMA_CORE_SATA_XORDMA 0x81E
1693+#define BCMA_CORE_ETHERNET_GBIT 0x81F
1694+#define BCMA_CORE_PCIE 0x820
1695+#define BCMA_CORE_PHY_N 0x821
1696+#define BCMA_CORE_SRAM_CTL 0x822
1697+#define BCMA_CORE_MINI_MACPHY 0x823
1698+#define BCMA_CORE_ARM_1176 0x824
1699+#define BCMA_CORE_ARM_7TDMI 0x825
1700+#define BCMA_CORE_PHY_LP 0x826
1701+#define BCMA_CORE_PMU 0x827
1702+#define BCMA_CORE_PHY_SSN 0x828
1703+#define BCMA_CORE_SDIO_DEV 0x829
1704+#define BCMA_CORE_ARM_CM3 0x82A
1705+#define BCMA_CORE_PHY_HT 0x82B
1706+#define BCMA_CORE_MIPS_74K 0x82C
1707+#define BCMA_CORE_MAC_GBIT 0x82D
1708+#define BCMA_CORE_DDR12_MEM_CTL 0x82E
1709+#define BCMA_CORE_PCIE_RC 0x82F /* PCIe Root Complex */
1710+#define BCMA_CORE_OCP_OCP_BRIDGE 0x830
1711+#define BCMA_CORE_SHARED_COMMON 0x831
1712+#define BCMA_CORE_OCP_AHB_BRIDGE 0x832
1713+#define BCMA_CORE_SPI_HOST 0x833
1714+#define BCMA_CORE_I2S 0x834
1715+#define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */
1716+#define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */
1717+#define BCMA_CORE_DEFAULT 0xFFF
1718+
1719+#define BCMA_MAX_NR_CORES 16
1720+
1721+struct bcma_device {
1722+ struct bcma_bus *bus;
1723+ struct bcma_device_id id;
1724+
1725+ struct device dev;
1726+ struct device *dma_dev;
1727+ unsigned int irq;
1728+ bool dev_registered;
1729+
1730+ u8 core_index;
1731+
1732+ u32 addr;
1733+ u32 wrap;
1734+
1735+ void *drvdata;
1736+ struct list_head list;
1737+};
1738+
1739+static inline void *bcma_get_drvdata(struct bcma_device *core)
1740+{
1741+ return core->drvdata;
1742+}
1743+static inline void bcma_set_drvdata(struct bcma_device *core, void *drvdata)
1744+{
1745+ core->drvdata = drvdata;
1746+}
1747+
1748+struct bcma_driver {
1749+ const char *name;
1750+ const struct bcma_device_id *id_table;
1751+
1752+ int (*probe)(struct bcma_device *dev);
1753+ void (*remove)(struct bcma_device *dev);
1754+ int (*suspend)(struct bcma_device *dev, pm_message_t state);
1755+ int (*resume)(struct bcma_device *dev);
1756+ void (*shutdown)(struct bcma_device *dev);
1757+
1758+ struct device_driver drv;
1759+};
1760+extern
1761+int __bcma_driver_register(struct bcma_driver *drv, struct module *owner);
1762+static inline int bcma_driver_register(struct bcma_driver *drv)
1763+{
1764+ return __bcma_driver_register(drv, THIS_MODULE);
1765+}
1766+extern void bcma_driver_unregister(struct bcma_driver *drv);
1767+
1768+struct bcma_bus {
1769+ /* The MMIO area. */
1770+ void __iomem *mmio;
1771+
1772+ const struct bcma_host_ops *ops;
1773+
1774+ enum bcma_hosttype hosttype;
1775+ union {
1776+ /* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */
1777+ struct pci_dev *host_pci;
1778+ /* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */
1779+ struct sdio_func *host_sdio;
1780+ };
1781+
1782+ struct bcma_chipinfo chipinfo;
1783+
1784+ struct bcma_device *mapped_core;
1785+ struct list_head cores;
1786+ u8 nr_cores;
1787+
1788+ struct bcma_drv_cc drv_cc;
1789+ struct bcma_drv_pci drv_pci;
1790+
1791+ /* We decided to share SPROM struct with SSB as long as we do not need
1792+ * any hacks for BCMA. This simplifies drivers code. */
1793+ struct ssb_sprom sprom;
1794+};
1795+
1796+extern inline u32 bcma_read8(struct bcma_device *core, u16 offset)
1797+{
1798+ return core->bus->ops->read8(core, offset);
1799+}
1800+extern inline u32 bcma_read16(struct bcma_device *core, u16 offset)
1801+{
1802+ return core->bus->ops->read16(core, offset);
1803+}
1804+extern inline u32 bcma_read32(struct bcma_device *core, u16 offset)
1805+{
1806+ return core->bus->ops->read32(core, offset);
1807+}
1808+extern inline
1809+void bcma_write8(struct bcma_device *core, u16 offset, u32 value)
1810+{
1811+ core->bus->ops->write8(core, offset, value);
1812+}
1813+extern inline
1814+void bcma_write16(struct bcma_device *core, u16 offset, u32 value)
1815+{
1816+ core->bus->ops->write16(core, offset, value);
1817+}
1818+extern inline
1819+void bcma_write32(struct bcma_device *core, u16 offset, u32 value)
1820+{
1821+ core->bus->ops->write32(core, offset, value);
1822+}
1823+#ifdef CONFIG_BCMA_BLOCKIO
1824+extern inline void bcma_block_read(struct bcma_device *core, void *buffer,
1825+ size_t count, u16 offset, u8 reg_width)
1826+{
1827+ core->bus->ops->block_read(core, buffer, count, offset, reg_width);
1828+}
1829+extern inline void bcma_block_write(struct bcma_device *core, const void *buffer,
1830+ size_t count, u16 offset, u8 reg_width)
1831+{
1832+ core->bus->ops->block_write(core, buffer, count, offset, reg_width);
1833+}
1834+#endif
1835+extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset)
1836+{
1837+ return core->bus->ops->aread32(core, offset);
1838+}
1839+extern inline
1840+void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value)
1841+{
1842+ core->bus->ops->awrite32(core, offset, value);
1843+}
1844+
1845+extern bool bcma_core_is_enabled(struct bcma_device *core);
1846+extern void bcma_core_disable(struct bcma_device *core, u32 flags);
1847+extern int bcma_core_enable(struct bcma_device *core, u32 flags);
1848+
1849+#endif /* LINUX_BCMA_H_ */
1850--- /dev/null
1851+++ b/include/linux/bcma/bcma_driver_chipcommon.h
1852@@ -0,0 +1,303 @@
1853+#ifndef LINUX_BCMA_DRIVER_CC_H_
1854+#define LINUX_BCMA_DRIVER_CC_H_
1855+
1856+/** ChipCommon core registers. **/
1857+#define BCMA_CC_ID 0x0000
1858+#define BCMA_CC_ID_ID 0x0000FFFF
1859+#define BCMA_CC_ID_ID_SHIFT 0
1860+#define BCMA_CC_ID_REV 0x000F0000
1861+#define BCMA_CC_ID_REV_SHIFT 16
1862+#define BCMA_CC_ID_PKG 0x00F00000
1863+#define BCMA_CC_ID_PKG_SHIFT 20
1864+#define BCMA_CC_ID_NRCORES 0x0F000000
1865+#define BCMA_CC_ID_NRCORES_SHIFT 24
1866+#define BCMA_CC_ID_TYPE 0xF0000000
1867+#define BCMA_CC_ID_TYPE_SHIFT 28
1868+#define BCMA_CC_CAP 0x0004 /* Capabilities */
1869+#define BCMA_CC_CAP_NRUART 0x00000003 /* # of UARTs */
1870+#define BCMA_CC_CAP_MIPSEB 0x00000004 /* MIPS in BigEndian Mode */
1871+#define BCMA_CC_CAP_UARTCLK 0x00000018 /* UART clock select */
1872+#define BCMA_CC_CAP_UARTCLK_INT 0x00000008 /* UARTs are driven by internal divided clock */
1873+#define BCMA_CC_CAP_UARTGPIO 0x00000020 /* UARTs on GPIO 15-12 */
1874+#define BCMA_CC_CAP_EXTBUS 0x000000C0 /* External buses present */
1875+#define BCMA_CC_CAP_FLASHT 0x00000700 /* Flash Type */
1876+#define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */
1877+#define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */
1878+#define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */
1879+#define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */
1880+#define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */
1881+#define BCMA_PLLTYPE_NONE 0x00000000
1882+#define BCMA_PLLTYPE_1 0x00010000 /* 48Mhz base, 3 dividers */
1883+#define BCMA_PLLTYPE_2 0x00020000 /* 48Mhz, 4 dividers */
1884+#define BCMA_PLLTYPE_3 0x00030000 /* 25Mhz, 2 dividers */
1885+#define BCMA_PLLTYPE_4 0x00008000 /* 48Mhz, 4 dividers */
1886+#define BCMA_PLLTYPE_5 0x00018000 /* 25Mhz, 4 dividers */
1887+#define BCMA_PLLTYPE_6 0x00028000 /* 100/200 or 120/240 only */
1888+#define BCMA_PLLTYPE_7 0x00038000 /* 25Mhz, 4 dividers */
1889+#define BCMA_CC_CAP_PCTL 0x00040000 /* Power Control */
1890+#define BCMA_CC_CAP_OTPS 0x00380000 /* OTP size */
1891+#define BCMA_CC_CAP_OTPS_SHIFT 19
1892+#define BCMA_CC_CAP_OTPS_BASE 5
1893+#define BCMA_CC_CAP_JTAGM 0x00400000 /* JTAG master present */
1894+#define BCMA_CC_CAP_BROM 0x00800000 /* Internal boot ROM active */
1895+#define BCMA_CC_CAP_64BIT 0x08000000 /* 64-bit Backplane */
1896+#define BCMA_CC_CAP_PMU 0x10000000 /* PMU available (rev >= 20) */
1897+#define BCMA_CC_CAP_ECI 0x20000000 /* ECI available (rev >= 20) */
1898+#define BCMA_CC_CAP_SPROM 0x40000000 /* SPROM present */
1899+#define BCMA_CC_CORECTL 0x0008
1900+#define BCMA_CC_CORECTL_UARTCLK0 0x00000001 /* Drive UART with internal clock */
1901+#define BCMA_CC_CORECTL_SE 0x00000002 /* sync clk out enable (corerev >= 3) */
1902+#define BCMA_CC_CORECTL_UARTCLKEN 0x00000008 /* UART clock enable (rev >= 21) */
1903+#define BCMA_CC_BIST 0x000C
1904+#define BCMA_CC_OTPS 0x0010 /* OTP status */
1905+#define BCMA_CC_OTPS_PROGFAIL 0x80000000
1906+#define BCMA_CC_OTPS_PROTECT 0x00000007
1907+#define BCMA_CC_OTPS_HW_PROTECT 0x00000001
1908+#define BCMA_CC_OTPS_SW_PROTECT 0x00000002
1909+#define BCMA_CC_OTPS_CID_PROTECT 0x00000004
1910+#define BCMA_CC_OTPC 0x0014 /* OTP control */
1911+#define BCMA_CC_OTPC_RECWAIT 0xFF000000
1912+#define BCMA_CC_OTPC_PROGWAIT 0x00FFFF00
1913+#define BCMA_CC_OTPC_PRW_SHIFT 8
1914+#define BCMA_CC_OTPC_MAXFAIL 0x00000038
1915+#define BCMA_CC_OTPC_VSEL 0x00000006
1916+#define BCMA_CC_OTPC_SELVL 0x00000001
1917+#define BCMA_CC_OTPP 0x0018 /* OTP prog */
1918+#define BCMA_CC_OTPP_COL 0x000000FF
1919+#define BCMA_CC_OTPP_ROW 0x0000FF00
1920+#define BCMA_CC_OTPP_ROW_SHIFT 8
1921+#define BCMA_CC_OTPP_READERR 0x10000000
1922+#define BCMA_CC_OTPP_VALUE 0x20000000
1923+#define BCMA_CC_OTPP_READ 0x40000000
1924+#define BCMA_CC_OTPP_START 0x80000000
1925+#define BCMA_CC_OTPP_BUSY 0x80000000
1926+#define BCMA_CC_IRQSTAT 0x0020
1927+#define BCMA_CC_IRQMASK 0x0024
1928+#define BCMA_CC_IRQ_GPIO 0x00000001 /* gpio intr */
1929+#define BCMA_CC_IRQ_EXT 0x00000002 /* ro: ext intr pin (corerev >= 3) */
1930+#define BCMA_CC_IRQ_WDRESET 0x80000000 /* watchdog reset occurred */
1931+#define BCMA_CC_CHIPCTL 0x0028 /* Rev >= 11 only */
1932+#define BCMA_CC_CHIPSTAT 0x002C /* Rev >= 11 only */
1933+#define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */
1934+#define BCMA_CC_JCMD_START 0x80000000
1935+#define BCMA_CC_JCMD_BUSY 0x80000000
1936+#define BCMA_CC_JCMD_PAUSE 0x40000000
1937+#define BCMA_CC_JCMD0_ACC_MASK 0x0000F000
1938+#define BCMA_CC_JCMD0_ACC_IRDR 0x00000000
1939+#define BCMA_CC_JCMD0_ACC_DR 0x00001000
1940+#define BCMA_CC_JCMD0_ACC_IR 0x00002000
1941+#define BCMA_CC_JCMD0_ACC_RESET 0x00003000
1942+#define BCMA_CC_JCMD0_ACC_IRPDR 0x00004000
1943+#define BCMA_CC_JCMD0_ACC_PDR 0x00005000
1944+#define BCMA_CC_JCMD0_IRW_MASK 0x00000F00
1945+#define BCMA_CC_JCMD_ACC_MASK 0x000F0000 /* Changes for corerev 11 */
1946+#define BCMA_CC_JCMD_ACC_IRDR 0x00000000
1947+#define BCMA_CC_JCMD_ACC_DR 0x00010000
1948+#define BCMA_CC_JCMD_ACC_IR 0x00020000
1949+#define BCMA_CC_JCMD_ACC_RESET 0x00030000
1950+#define BCMA_CC_JCMD_ACC_IRPDR 0x00040000
1951+#define BCMA_CC_JCMD_ACC_PDR 0x00050000
1952+#define BCMA_CC_JCMD_IRW_MASK 0x00001F00
1953+#define BCMA_CC_JCMD_IRW_SHIFT 8
1954+#define BCMA_CC_JCMD_DRW_MASK 0x0000003F
1955+#define BCMA_CC_JIR 0x0034 /* Rev >= 10 only */
1956+#define BCMA_CC_JDR 0x0038 /* Rev >= 10 only */
1957+#define BCMA_CC_JCTL 0x003C /* Rev >= 10 only */
1958+#define BCMA_CC_JCTL_FORCE_CLK 4 /* Force clock */
1959+#define BCMA_CC_JCTL_EXT_EN 2 /* Enable external targets */
1960+#define BCMA_CC_JCTL_EN 1 /* Enable Jtag master */
1961+#define BCMA_CC_FLASHCTL 0x0040
1962+#define BCMA_CC_FLASHCTL_START 0x80000000
1963+#define BCMA_CC_FLASHCTL_BUSY BCMA_CC_FLASHCTL_START
1964+#define BCMA_CC_FLASHADDR 0x0044
1965+#define BCMA_CC_FLASHDATA 0x0048
1966+#define BCMA_CC_BCAST_ADDR 0x0050
1967+#define BCMA_CC_BCAST_DATA 0x0054
1968+#define BCMA_CC_GPIOPULLUP 0x0058 /* Rev >= 20 only */
1969+#define BCMA_CC_GPIOPULLDOWN 0x005C /* Rev >= 20 only */
1970+#define BCMA_CC_GPIOIN 0x0060
1971+#define BCMA_CC_GPIOOUT 0x0064
1972+#define BCMA_CC_GPIOOUTEN 0x0068
1973+#define BCMA_CC_GPIOCTL 0x006C
1974+#define BCMA_CC_GPIOPOL 0x0070
1975+#define BCMA_CC_GPIOIRQ 0x0074
1976+#define BCMA_CC_WATCHDOG 0x0080
1977+#define BCMA_CC_GPIOTIMER 0x0088 /* LED powersave (corerev >= 16) */
1978+#define BCMA_CC_GPIOTIMER_OFFTIME 0x0000FFFF
1979+#define BCMA_CC_GPIOTIMER_OFFTIME_SHIFT 0
1980+#define BCMA_CC_GPIOTIMER_ONTIME 0xFFFF0000
1981+#define BCMA_CC_GPIOTIMER_ONTIME_SHIFT 16
1982+#define BCMA_CC_GPIOTOUTM 0x008C /* LED powersave (corerev >= 16) */
1983+#define BCMA_CC_CLOCK_N 0x0090
1984+#define BCMA_CC_CLOCK_SB 0x0094
1985+#define BCMA_CC_CLOCK_PCI 0x0098
1986+#define BCMA_CC_CLOCK_M2 0x009C
1987+#define BCMA_CC_CLOCK_MIPS 0x00A0
1988+#define BCMA_CC_CLKDIV 0x00A4 /* Rev >= 3 only */
1989+#define BCMA_CC_CLKDIV_SFLASH 0x0F000000
1990+#define BCMA_CC_CLKDIV_SFLASH_SHIFT 24
1991+#define BCMA_CC_CLKDIV_OTP 0x000F0000
1992+#define BCMA_CC_CLKDIV_OTP_SHIFT 16
1993+#define BCMA_CC_CLKDIV_JTAG 0x00000F00
1994+#define BCMA_CC_CLKDIV_JTAG_SHIFT 8
1995+#define BCMA_CC_CLKDIV_UART 0x000000FF
1996+#define BCMA_CC_CAP_EXT 0x00AC /* Capabilities */
1997+#define BCMA_CC_PLLONDELAY 0x00B0 /* Rev >= 4 only */
1998+#define BCMA_CC_FREFSELDELAY 0x00B4 /* Rev >= 4 only */
1999+#define BCMA_CC_SLOWCLKCTL 0x00B8 /* 6 <= Rev <= 9 only */
2000+#define BCMA_CC_SLOWCLKCTL_SRC 0x00000007 /* slow clock source mask */
2001+#define BCMA_CC_SLOWCLKCTL_SRC_LPO 0x00000000 /* source of slow clock is LPO */
2002+#define BCMA_CC_SLOWCLKCTL_SRC_XTAL 0x00000001 /* source of slow clock is crystal */
2003+#define BCMA_CC_SLOECLKCTL_SRC_PCI 0x00000002 /* source of slow clock is PCI */
2004+#define BCMA_CC_SLOWCLKCTL_LPOFREQ 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */
2005+#define BCMA_CC_SLOWCLKCTL_LPOPD 0x00000400 /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */
2006+#define BCMA_CC_SLOWCLKCTL_FSLOW 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */
2007+#define BCMA_CC_SLOWCLKCTL_IPLL 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors PLL clock disable requests from core */
2008+#define BCMA_CC_SLOWCLKCTL_ENXTAL 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't disable crystal when appropriate */
2009+#define BCMA_CC_SLOWCLKCTL_XTALPU 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */
2010+#define BCMA_CC_SLOWCLKCTL_CLKDIV 0xFFFF0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */
2011+#define BCMA_CC_SLOWCLKCTL_CLKDIV_SHIFT 16
2012+#define BCMA_CC_SYSCLKCTL 0x00C0 /* Rev >= 3 only */
2013+#define BCMA_CC_SYSCLKCTL_IDLPEN 0x00000001 /* ILPen: Enable Idle Low Power */
2014+#define BCMA_CC_SYSCLKCTL_ALPEN 0x00000002 /* ALPen: Enable Active Low Power */
2015+#define BCMA_CC_SYSCLKCTL_PLLEN 0x00000004 /* ForcePLLOn */
2016+#define BCMA_CC_SYSCLKCTL_FORCEALP 0x00000008 /* Force ALP (or HT if ALPen is not set */
2017+#define BCMA_CC_SYSCLKCTL_FORCEHT 0x00000010 /* Force HT */
2018+#define BCMA_CC_SYSCLKCTL_CLKDIV 0xFFFF0000 /* ClkDiv (ILP = 1/(4+divisor)) */
2019+#define BCMA_CC_SYSCLKCTL_CLKDIV_SHIFT 16
2020+#define BCMA_CC_CLKSTSTR 0x00C4 /* Rev >= 3 only */
2021+#define BCMA_CC_EROM 0x00FC
2022+#define BCMA_CC_PCMCIA_CFG 0x0100
2023+#define BCMA_CC_PCMCIA_MEMWAIT 0x0104
2024+#define BCMA_CC_PCMCIA_ATTRWAIT 0x0108
2025+#define BCMA_CC_PCMCIA_IOWAIT 0x010C
2026+#define BCMA_CC_IDE_CFG 0x0110
2027+#define BCMA_CC_IDE_MEMWAIT 0x0114
2028+#define BCMA_CC_IDE_ATTRWAIT 0x0118
2029+#define BCMA_CC_IDE_IOWAIT 0x011C
2030+#define BCMA_CC_PROG_CFG 0x0120
2031+#define BCMA_CC_PROG_WAITCNT 0x0124
2032+#define BCMA_CC_FLASH_CFG 0x0128
2033+#define BCMA_CC_FLASH_WAITCNT 0x012C
2034+#define BCMA_CC_CLKCTLST 0x01E0 /* Clock control and status (rev >= 20) */
2035+#define BCMA_CC_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */
2036+#define BCMA_CC_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */
2037+#define BCMA_CC_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */
2038+#define BCMA_CC_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */
2039+#define BCMA_CC_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
2040+#define BCMA_CC_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
2041+#define BCMA_CC_CLKCTLST_HAVEHT 0x00010000 /* HT available */
2042+#define BCMA_CC_CLKCTLST_HAVEALP 0x00020000 /* APL available */
2043+#define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */
2044+#define BCMA_CC_UART0_DATA 0x0300
2045+#define BCMA_CC_UART0_IMR 0x0304
2046+#define BCMA_CC_UART0_FCR 0x0308
2047+#define BCMA_CC_UART0_LCR 0x030C
2048+#define BCMA_CC_UART0_MCR 0x0310
2049+#define BCMA_CC_UART0_LSR 0x0314
2050+#define BCMA_CC_UART0_MSR 0x0318
2051+#define BCMA_CC_UART0_SCRATCH 0x031C
2052+#define BCMA_CC_UART1_DATA 0x0400
2053+#define BCMA_CC_UART1_IMR 0x0404
2054+#define BCMA_CC_UART1_FCR 0x0408
2055+#define BCMA_CC_UART1_LCR 0x040C
2056+#define BCMA_CC_UART1_MCR 0x0410
2057+#define BCMA_CC_UART1_LSR 0x0414
2058+#define BCMA_CC_UART1_MSR 0x0418
2059+#define BCMA_CC_UART1_SCRATCH 0x041C
2060+/* PMU registers (rev >= 20) */
2061+#define BCMA_CC_PMU_CTL 0x0600 /* PMU control */
2062+#define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */
2063+#define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16
2064+#define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */
2065+#define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */
2066+#define BCMA_CC_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */
2067+#define BCMA_CC_PMU_CTL_XTALFREQ 0x0000007C /* Crystal freq */
2068+#define BCMA_CC_PMU_CTL_XTALFREQ_SHIFT 2
2069+#define BCMA_CC_PMU_CTL_ILPDIVEN 0x00000002 /* ILP div enable */
2070+#define BCMA_CC_PMU_CTL_LPOSEL 0x00000001 /* LPO sel */
2071+#define BCMA_CC_PMU_CAP 0x0604 /* PMU capabilities */
2072+#define BCMA_CC_PMU_CAP_REVISION 0x000000FF /* Revision mask */
2073+#define BCMA_CC_PMU_STAT 0x0608 /* PMU status */
2074+#define BCMA_CC_PMU_STAT_INTPEND 0x00000040 /* Interrupt pending */
2075+#define BCMA_CC_PMU_STAT_SBCLKST 0x00000030 /* Backplane clock status? */
2076+#define BCMA_CC_PMU_STAT_HAVEALP 0x00000008 /* ALP available */
2077+#define BCMA_CC_PMU_STAT_HAVEHT 0x00000004 /* HT available */
2078+#define BCMA_CC_PMU_STAT_RESINIT 0x00000003 /* Res init */
2079+#define BCMA_CC_PMU_RES_STAT 0x060C /* PMU res status */
2080+#define BCMA_CC_PMU_RES_PEND 0x0610 /* PMU res pending */
2081+#define BCMA_CC_PMU_TIMER 0x0614 /* PMU timer */
2082+#define BCMA_CC_PMU_MINRES_MSK 0x0618 /* PMU min res mask */
2083+#define BCMA_CC_PMU_MAXRES_MSK 0x061C /* PMU max res mask */
2084+#define BCMA_CC_PMU_RES_TABSEL 0x0620 /* PMU res table sel */
2085+#define BCMA_CC_PMU_RES_DEPMSK 0x0624 /* PMU res dep mask */
2086+#define BCMA_CC_PMU_RES_UPDNTM 0x0628 /* PMU res updown timer */
2087+#define BCMA_CC_PMU_RES_TIMER 0x062C /* PMU res timer */
2088+#define BCMA_CC_PMU_CLKSTRETCH 0x0630 /* PMU clockstretch */
2089+#define BCMA_CC_PMU_WATCHDOG 0x0634 /* PMU watchdog */
2090+#define BCMA_CC_PMU_RES_REQTS 0x0640 /* PMU res req timer sel */
2091+#define BCMA_CC_PMU_RES_REQT 0x0644 /* PMU res req timer */
2092+#define BCMA_CC_PMU_RES_REQM 0x0648 /* PMU res req mask */
2093+#define BCMA_CC_CHIPCTL_ADDR 0x0650
2094+#define BCMA_CC_CHIPCTL_DATA 0x0654
2095+#define BCMA_CC_REGCTL_ADDR 0x0658
2096+#define BCMA_CC_REGCTL_DATA 0x065C
2097+#define BCMA_CC_PLLCTL_ADDR 0x0660
2098+#define BCMA_CC_PLLCTL_DATA 0x0664
2099+#define BCMA_CC_SPROM 0x0830 /* SPROM beginning */
2100+
2101+/* Data for the PMU, if available.
2102+ * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
2103+ */
2104+struct bcma_chipcommon_pmu {
2105+ u8 rev; /* PMU revision */
2106+ u32 crystalfreq; /* The active crystal frequency (in kHz) */
2107+};
2108+
2109+struct bcma_drv_cc {
2110+ struct bcma_device *core;
2111+ u32 status;
2112+ u32 capabilities;
2113+ u32 capabilities_ext;
2114+ /* Fast Powerup Delay constant */
2115+ u16 fast_pwrup_delay;
2116+ struct bcma_chipcommon_pmu pmu;
2117+};
2118+
2119+/* Register access */
2120+#define bcma_cc_read32(cc, offset) \
2121+ bcma_read32((cc)->core, offset)
2122+#define bcma_cc_write32(cc, offset, val) \
2123+ bcma_write32((cc)->core, offset, val)
2124+
2125+#define bcma_cc_mask32(cc, offset, mask) \
2126+ bcma_cc_write32(cc, offset, bcma_cc_read32(cc, offset) & (mask))
2127+#define bcma_cc_set32(cc, offset, set) \
2128+ bcma_cc_write32(cc, offset, bcma_cc_read32(cc, offset) | (set))
2129+#define bcma_cc_maskset32(cc, offset, mask, set) \
2130+ bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set))
2131+
2132+extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
2133+
2134+extern void bcma_chipco_suspend(struct bcma_drv_cc *cc);
2135+extern void bcma_chipco_resume(struct bcma_drv_cc *cc);
2136+
2137+extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc,
2138+ u32 ticks);
2139+
2140+void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value);
2141+
2142+u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask);
2143+
2144+/* Chipcommon GPIO pin access. */
2145+u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask);
2146+u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value);
2147+u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value);
2148+u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value);
2149+u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value);
2150+u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
2151+
2152+/* PMU support */
2153+extern void bcma_pmu_init(struct bcma_drv_cc *cc);
2154+
2155+#endif /* LINUX_BCMA_DRIVER_CC_H_ */
2156--- /dev/null
2157+++ b/include/linux/bcma/bcma_driver_pci.h
2158@@ -0,0 +1,91 @@
2159+#ifndef LINUX_BCMA_DRIVER_PCI_H_
2160+#define LINUX_BCMA_DRIVER_PCI_H_
2161+
2162+#include <linux/types.h>
2163+
2164+struct pci_dev;
2165+
2166+/** PCI core registers. **/
2167+#define BCMA_CORE_PCI_CTL 0x0000 /* PCI Control */
2168+#define BCMA_CORE_PCI_CTL_RST_OE 0x00000001 /* PCI_RESET Output Enable */
2169+#define BCMA_CORE_PCI_CTL_RST 0x00000002 /* PCI_RESET driven out to pin */
2170+#define BCMA_CORE_PCI_CTL_CLK_OE 0x00000004 /* Clock gate Output Enable */
2171+#define BCMA_CORE_PCI_CTL_CLK 0x00000008 /* Gate for clock driven out to pin */
2172+#define BCMA_CORE_PCI_ARBCTL 0x0010 /* PCI Arbiter Control */
2173+#define BCMA_CORE_PCI_ARBCTL_INTERN 0x00000001 /* Use internal arbiter */
2174+#define BCMA_CORE_PCI_ARBCTL_EXTERN 0x00000002 /* Use external arbiter */
2175+#define BCMA_CORE_PCI_ARBCTL_PARKID 0x00000006 /* Mask, selects which agent is parked on an idle bus */
2176+#define BCMA_CORE_PCI_ARBCTL_PARKID_LAST 0x00000000 /* Last requestor */
2177+#define BCMA_CORE_PCI_ARBCTL_PARKID_4710 0x00000002 /* 4710 */
2178+#define BCMA_CORE_PCI_ARBCTL_PARKID_EXT0 0x00000004 /* External requestor 0 */
2179+#define BCMA_CORE_PCI_ARBCTL_PARKID_EXT1 0x00000006 /* External requestor 1 */
2180+#define BCMA_CORE_PCI_ISTAT 0x0020 /* Interrupt status */
2181+#define BCMA_CORE_PCI_ISTAT_INTA 0x00000001 /* PCI INTA# */
2182+#define BCMA_CORE_PCI_ISTAT_INTB 0x00000002 /* PCI INTB# */
2183+#define BCMA_CORE_PCI_ISTAT_SERR 0x00000004 /* PCI SERR# (write to clear) */
2184+#define BCMA_CORE_PCI_ISTAT_PERR 0x00000008 /* PCI PERR# (write to clear) */
2185+#define BCMA_CORE_PCI_ISTAT_PME 0x00000010 /* PCI PME# */
2186+#define BCMA_CORE_PCI_IMASK 0x0024 /* Interrupt mask */
2187+#define BCMA_CORE_PCI_IMASK_INTA 0x00000001 /* PCI INTA# */
2188+#define BCMA_CORE_PCI_IMASK_INTB 0x00000002 /* PCI INTB# */
2189+#define BCMA_CORE_PCI_IMASK_SERR 0x00000004 /* PCI SERR# */
2190+#define BCMA_CORE_PCI_IMASK_PERR 0x00000008 /* PCI PERR# */
2191+#define BCMA_CORE_PCI_IMASK_PME 0x00000010 /* PCI PME# */
2192+#define BCMA_CORE_PCI_MBOX 0x0028 /* Backplane to PCI Mailbox */
2193+#define BCMA_CORE_PCI_MBOX_F0_0 0x00000100 /* PCI function 0, INT 0 */
2194+#define BCMA_CORE_PCI_MBOX_F0_1 0x00000200 /* PCI function 0, INT 1 */
2195+#define BCMA_CORE_PCI_MBOX_F1_0 0x00000400 /* PCI function 1, INT 0 */
2196+#define BCMA_CORE_PCI_MBOX_F1_1 0x00000800 /* PCI function 1, INT 1 */
2197+#define BCMA_CORE_PCI_MBOX_F2_0 0x00001000 /* PCI function 2, INT 0 */
2198+#define BCMA_CORE_PCI_MBOX_F2_1 0x00002000 /* PCI function 2, INT 1 */
2199+#define BCMA_CORE_PCI_MBOX_F3_0 0x00004000 /* PCI function 3, INT 0 */
2200+#define BCMA_CORE_PCI_MBOX_F3_1 0x00008000 /* PCI function 3, INT 1 */
2201+#define BCMA_CORE_PCI_BCAST_ADDR 0x0050 /* Backplane Broadcast Address */
2202+#define BCMA_CORE_PCI_BCAST_ADDR_MASK 0x000000FF
2203+#define BCMA_CORE_PCI_BCAST_DATA 0x0054 /* Backplane Broadcast Data */
2204+#define BCMA_CORE_PCI_GPIO_IN 0x0060 /* rev >= 2 only */
2205+#define BCMA_CORE_PCI_GPIO_OUT 0x0064 /* rev >= 2 only */
2206+#define BCMA_CORE_PCI_GPIO_ENABLE 0x0068 /* rev >= 2 only */
2207+#define BCMA_CORE_PCI_GPIO_CTL 0x006C /* rev >= 2 only */
2208+#define BCMA_CORE_PCI_SBTOPCI0 0x0100 /* Backplane to PCI translation 0 (sbtopci0) */
2209+#define BCMA_CORE_PCI_SBTOPCI0_MASK 0xFC000000
2210+#define BCMA_CORE_PCI_SBTOPCI1 0x0104 /* Backplane to PCI translation 1 (sbtopci1) */
2211+#define BCMA_CORE_PCI_SBTOPCI1_MASK 0xFC000000
2212+#define BCMA_CORE_PCI_SBTOPCI2 0x0108 /* Backplane to PCI translation 2 (sbtopci2) */
2213+#define BCMA_CORE_PCI_SBTOPCI2_MASK 0xC0000000
2214+#define BCMA_CORE_PCI_PCICFG0 0x0400 /* PCI config space 0 (rev >= 8) */
2215+#define BCMA_CORE_PCI_PCICFG1 0x0500 /* PCI config space 1 (rev >= 8) */
2216+#define BCMA_CORE_PCI_PCICFG2 0x0600 /* PCI config space 2 (rev >= 8) */
2217+#define BCMA_CORE_PCI_PCICFG3 0x0700 /* PCI config space 3 (rev >= 8) */
2218+#define BCMA_CORE_PCI_SPROM(wordoffset) (0x0800 + ((wordoffset) * 2)) /* SPROM shadow area (72 bytes) */
2219+
2220+/* SBtoPCIx */
2221+#define BCMA_CORE_PCI_SBTOPCI_MEM 0x00000000
2222+#define BCMA_CORE_PCI_SBTOPCI_IO 0x00000001
2223+#define BCMA_CORE_PCI_SBTOPCI_CFG0 0x00000002
2224+#define BCMA_CORE_PCI_SBTOPCI_CFG1 0x00000003
2225+#define BCMA_CORE_PCI_SBTOPCI_PREF 0x00000004 /* Prefetch enable */
2226+#define BCMA_CORE_PCI_SBTOPCI_BURST 0x00000008 /* Burst enable */
2227+#define BCMA_CORE_PCI_SBTOPCI_MRM 0x00000020 /* Memory Read Multiple */
2228+#define BCMA_CORE_PCI_SBTOPCI_RC 0x00000030 /* Read Command mask (rev >= 11) */
2229+#define BCMA_CORE_PCI_SBTOPCI_RC_READ 0x00000000 /* Memory read */
2230+#define BCMA_CORE_PCI_SBTOPCI_RC_READL 0x00000010 /* Memory read line */
2231+#define BCMA_CORE_PCI_SBTOPCI_RC_READM 0x00000020 /* Memory read multiple */
2232+
2233+/* PCIcore specific boardflags */
2234+#define BCMA_CORE_PCI_BFL_NOPCI 0x00000400 /* Board leaves PCI floating */
2235+
2236+struct bcma_drv_pci {
2237+ struct bcma_device *core;
2238+ u8 setup_done:1;
2239+};
2240+
2241+/* Register access */
2242+#define pcicore_read32(pc, offset) bcma_read32((pc)->core, offset)
2243+#define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val)
2244+
2245+extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
2246+extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
2247+ struct bcma_device *core, bool enable);
2248+
2249+#endif /* LINUX_BCMA_DRIVER_PCI_H_ */
2250--- /dev/null
2251+++ b/include/linux/bcma/bcma_regs.h
2252@@ -0,0 +1,34 @@
2253+#ifndef LINUX_BCMA_REGS_H_
2254+#define LINUX_BCMA_REGS_H_
2255+
2256+/* Agent registers (common for every core) */
2257+#define BCMA_IOCTL 0x0408
2258+#define BCMA_IOCTL_CLK 0x0001
2259+#define BCMA_IOCTL_FGC 0x0002
2260+#define BCMA_IOCTL_CORE_BITS 0x3FFC
2261+#define BCMA_IOCTL_PME_EN 0x4000
2262+#define BCMA_IOCTL_BIST_EN 0x8000
2263+#define BCMA_RESET_CTL 0x0800
2264+#define BCMA_RESET_CTL_RESET 0x0001
2265+
2266+/* BCMA PCI config space registers. */
2267+#define BCMA_PCI_PMCSR 0x44
2268+#define BCMA_PCI_PE 0x100
2269+#define BCMA_PCI_BAR0_WIN 0x80 /* Backplane address space 0 */
2270+#define BCMA_PCI_BAR1_WIN 0x84 /* Backplane address space 1 */
2271+#define BCMA_PCI_SPROMCTL 0x88 /* SPROM control */
2272+#define BCMA_PCI_SPROMCTL_WE 0x10 /* SPROM write enable */
2273+#define BCMA_PCI_BAR1_CONTROL 0x8c /* Address space 1 burst control */
2274+#define BCMA_PCI_IRQS 0x90 /* PCI interrupts */
2275+#define BCMA_PCI_IRQMASK 0x94 /* PCI IRQ control and mask (pcirev >= 6 only) */
2276+#define BCMA_PCI_BACKPLANE_IRQS 0x98 /* Backplane Interrupts */
2277+#define BCMA_PCI_BAR0_WIN2 0xAC
2278+#define BCMA_PCI_GPIO_IN 0xB0 /* GPIO Input (pcirev >= 3 only) */
2279+#define BCMA_PCI_GPIO_OUT 0xB4 /* GPIO Output (pcirev >= 3 only) */
2280+#define BCMA_PCI_GPIO_OUT_ENABLE 0xB8 /* GPIO Output Enable/Disable (pcirev >= 3 only) */
2281+#define BCMA_PCI_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */
2282+#define BCMA_PCI_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */
2283+#define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */
2284+#define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */
2285+
2286+#endif /* LINUX_BCMA_REGS_H_ */
2287--- a/include/linux/mod_devicetable.h
2288+++ b/include/linux/mod_devicetable.h
2289@@ -382,6 +382,23 @@ struct ssb_device_id {
2290 #define SSB_ANY_ID 0xFFFF
2291 #define SSB_ANY_REV 0xFF
2292 
2293+/* Broadcom's specific AMBA core, see drivers/bcma/ */
2294+struct bcma_device_id {
2295+ __u16 manuf;
2296+ __u16 id;
2297+ __u8 rev;
2298+ __u8 class;
2299+};
2300+#define BCMA_CORE(_manuf, _id, _rev, _class) \
2301+ { .manuf = _manuf, .id = _id, .rev = _rev, .class = _class, }
2302+#define BCMA_CORETABLE_END \
2303+ { 0, },
2304+
2305+#define BCMA_ANY_MANUF 0xFFFF
2306+#define BCMA_ANY_ID 0xFFFF
2307+#define BCMA_ANY_REV 0xFF
2308+#define BCMA_ANY_CLASS 0xFF
2309+
2310 struct virtio_device_id {
2311     __u32 device;
2312     __u32 vendor;
2313--- a/scripts/mod/file2alias.c
2314+++ b/scripts/mod/file2alias.c
2315@@ -702,6 +702,24 @@ static int do_ssb_entry(const char *file
2316     return 1;
2317 }
2318 
2319+/* Looks like: bcma:mNidNrevNclN. */
2320+static int do_bcma_entry(const char *filename,
2321+ struct bcma_device_id *id, char *alias)
2322+{
2323+ id->manuf = TO_NATIVE(id->manuf);
2324+ id->id = TO_NATIVE(id->id);
2325+ id->rev = TO_NATIVE(id->rev);
2326+ id->class = TO_NATIVE(id->class);
2327+
2328+ strcpy(alias, "bcma:");
2329+ ADD(alias, "m", id->manuf != BCMA_ANY_MANUF, id->manuf);
2330+ ADD(alias, "id", id->id != BCMA_ANY_ID, id->id);
2331+ ADD(alias, "rev", id->rev != BCMA_ANY_REV, id->rev);
2332+ ADD(alias, "cl", id->class != BCMA_ANY_CLASS, id->class);
2333+ add_wildcard(alias);
2334+ return 1;
2335+}
2336+
2337 /* Looks like: virtio:dNvN */
2338 static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
2339                char *alias)
2340@@ -968,6 +986,10 @@ void handle_moddevtable(struct module *m
2341         do_table(symval, sym->st_size,
2342              sizeof(struct ssb_device_id), "ssb",
2343              do_ssb_entry, mod);
2344+ else if (sym_is(symname, "__mod_bcma_device_table"))
2345+ do_table(symval, sym->st_size,
2346+ sizeof(struct bcma_device_id), "bcma",
2347+ do_bcma_entry, mod);
2348     else if (sym_is(symname, "__mod_virtio_device_table"))
2349         do_table(symval, sym->st_size,
2350              sizeof(struct virtio_device_id), "virtio",
2351--- /dev/null
2352+++ b/drivers/bcma/sprom.c
2353@@ -0,0 +1,162 @@
2354+/*
2355+ * Broadcom specific AMBA
2356+ * SPROM reading
2357+ *
2358+ * Licensed under the GNU/GPL. See COPYING for details.
2359+ */
2360+
2361+#include "bcma_private.h"
2362+
2363+#include <linux/bcma/bcma.h>
2364+#include <linux/bcma/bcma_regs.h>
2365+#include <linux/pci.h>
2366+#include <linux/io.h>
2367+#include <linux/dma-mapping.h>
2368+#include <linux/slab.h>
2369+
2370+#define SPOFF(offset) ((offset) / sizeof(u16))
2371+
2372+/**************************************************
2373+ * R/W ops.
2374+ **************************************************/
2375+
2376+static void bcma_sprom_read(struct bcma_bus *bus, u16 *sprom)
2377+{
2378+ int i;
2379+ for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++)
2380+ sprom[i] = bcma_read16(bus->drv_cc.core,
2381+ BCMA_CC_SPROM + (i * 2));
2382+}
2383+
2384+/**************************************************
2385+ * Validation.
2386+ **************************************************/
2387+
2388+static inline u8 bcma_crc8(u8 crc, u8 data)
2389+{
2390+ /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */
2391+ static const u8 t[] = {
2392+ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
2393+ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
2394+ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
2395+ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
2396+ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
2397+ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
2398+ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
2399+ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
2400+ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
2401+ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
2402+ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
2403+ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
2404+ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
2405+ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
2406+ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
2407+ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
2408+ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
2409+ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
2410+ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
2411+ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
2412+ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
2413+ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
2414+ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
2415+ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
2416+ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
2417+ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
2418+ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
2419+ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
2420+ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
2421+ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
2422+ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
2423+ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
2424+ };
2425+ return t[crc ^ data];
2426+}
2427+
2428+static u8 bcma_sprom_crc(const u16 *sprom)
2429+{
2430+ int word;
2431+ u8 crc = 0xFF;
2432+
2433+ for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) {
2434+ crc = bcma_crc8(crc, sprom[word] & 0x00FF);
2435+ crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8);
2436+ }
2437+ crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF);
2438+ crc ^= 0xFF;
2439+
2440+ return crc;
2441+}
2442+
2443+static int bcma_sprom_check_crc(const u16 *sprom)
2444+{
2445+ u8 crc;
2446+ u8 expected_crc;
2447+ u16 tmp;
2448+
2449+ crc = bcma_sprom_crc(sprom);
2450+ tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC;
2451+ expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
2452+ if (crc != expected_crc)
2453+ return -EPROTO;
2454+
2455+ return 0;
2456+}
2457+
2458+static int bcma_sprom_valid(const u16 *sprom)
2459+{
2460+ u16 revision;
2461+ int err;
2462+
2463+ err = bcma_sprom_check_crc(sprom);
2464+ if (err)
2465+ return err;
2466+
2467+ revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV;
2468+ if (revision != 8) {
2469+ pr_err("Unsupported SPROM revision: %d\n", revision);
2470+ return -ENOENT;
2471+ }
2472+
2473+ return 0;
2474+}
2475+
2476+/**************************************************
2477+ * SPROM extraction.
2478+ **************************************************/
2479+
2480+static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
2481+{
2482+ u16 v;
2483+ int i;
2484+
2485+ for (i = 0; i < 3; i++) {
2486+ v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
2487+ *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
2488+ }
2489+}
2490+
2491+int bcma_sprom_get(struct bcma_bus *bus)
2492+{
2493+ u16 *sprom;
2494+ int err = 0;
2495+
2496+ if (!bus->drv_cc.core)
2497+ return -EOPNOTSUPP;
2498+
2499+ sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
2500+ GFP_KERNEL);
2501+ if (!sprom)
2502+ return -ENOMEM;
2503+
2504+ bcma_sprom_read(bus, sprom);
2505+
2506+ err = bcma_sprom_valid(sprom);
2507+ if (err)
2508+ goto out;
2509+
2510+ bcma_sprom_extract_r8(bus, sprom);
2511+
2512+out:
2513+ kfree(sprom);
2514+ return err;
2515+}
2516

Archive Download this file



interactive