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,12 @@ 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_DEBUG
26     bool "BCMA debugging"
27     depends on BCMA
28--- a/drivers/bcma/Makefile
29+++ b/drivers/bcma/Makefile
30@@ -1,6 +1,7 @@
31-bcma-y += main.o scan.o core.o
32+bcma-y += main.o scan.o core.o sprom.o
33 bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
34 bcma-y += driver_pci.o
35+bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
36 bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
37 obj-$(CONFIG_BCMA) += bcma.o
38 
39--- a/drivers/bcma/bcma_private.h
40+++ b/drivers/bcma/bcma_private.h
41@@ -13,16 +13,23 @@
42 struct bcma_bus;
43 
44 /* main.c */
45-extern int bcma_bus_register(struct bcma_bus *bus);
46-extern void bcma_bus_unregister(struct bcma_bus *bus);
47+int bcma_bus_register(struct bcma_bus *bus);
48+void bcma_bus_unregister(struct bcma_bus *bus);
49 
50 /* scan.c */
51 int bcma_bus_scan(struct bcma_bus *bus);
52 
53+/* sprom.c */
54+int bcma_sprom_get(struct bcma_bus *bus);
55+
56 #ifdef CONFIG_BCMA_HOST_PCI
57 /* host_pci.c */
58 extern int __init bcma_host_pci_init(void);
59 extern void __exit bcma_host_pci_exit(void);
60 #endif /* CONFIG_BCMA_HOST_PCI */
61 
62+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
63+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
64+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
65+
66 #endif
67--- a/drivers/bcma/core.c
68+++ b/drivers/bcma/core.c
69@@ -19,7 +19,7 @@ bool bcma_core_is_enabled(struct bcma_de
70 }
71 EXPORT_SYMBOL_GPL(bcma_core_is_enabled);
72 
73-static void bcma_core_disable(struct bcma_device *core, u32 flags)
74+void bcma_core_disable(struct bcma_device *core, u32 flags)
75 {
76     if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
77         return;
78@@ -31,6 +31,7 @@ static void bcma_core_disable(struct bcm
79     bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
80     udelay(1);
81 }
82+EXPORT_SYMBOL_GPL(bcma_core_disable);
83 
84 int bcma_core_enable(struct bcma_device *core, u32 flags)
85 {
86@@ -49,3 +50,75 @@ int bcma_core_enable(struct bcma_device
87     return 0;
88 }
89 EXPORT_SYMBOL_GPL(bcma_core_enable);
90+
91+void bcma_core_set_clockmode(struct bcma_device *core,
92+ enum bcma_clkmode clkmode)
93+{
94+ u16 i;
95+
96+ WARN_ON(core->id.id != BCMA_CORE_CHIPCOMMON &&
97+ core->id.id != BCMA_CORE_PCIE &&
98+ core->id.id != BCMA_CORE_80211);
99+
100+ switch (clkmode) {
101+ case BCMA_CLKMODE_FAST:
102+ bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
103+ udelay(64);
104+ for (i = 0; i < 1500; i++) {
105+ if (bcma_read32(core, BCMA_CLKCTLST) &
106+ BCMA_CLKCTLST_HAVEHT) {
107+ i = 0;
108+ break;
109+ }
110+ udelay(10);
111+ }
112+ if (i)
113+ pr_err("HT force timeout\n");
114+ break;
115+ case BCMA_CLKMODE_DYNAMIC:
116+ pr_warn("Dynamic clockmode not supported yet!\n");
117+ break;
118+ }
119+}
120+EXPORT_SYMBOL_GPL(bcma_core_set_clockmode);
121+
122+void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
123+{
124+ u16 i;
125+
126+ WARN_ON(req & ~BCMA_CLKCTLST_EXTRESREQ);
127+ WARN_ON(status & ~BCMA_CLKCTLST_EXTRESST);
128+
129+ if (on) {
130+ bcma_set32(core, BCMA_CLKCTLST, req);
131+ for (i = 0; i < 10000; i++) {
132+ if ((bcma_read32(core, BCMA_CLKCTLST) & status) ==
133+ status) {
134+ i = 0;
135+ break;
136+ }
137+ udelay(10);
138+ }
139+ if (i)
140+ pr_err("PLL enable timeout\n");
141+ } else {
142+ pr_warn("Disabling PLL not supported yet!\n");
143+ }
144+}
145+EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
146+
147+u32 bcma_core_dma_translation(struct bcma_device *core)
148+{
149+ switch (core->bus->hosttype) {
150+ case BCMA_HOSTTYPE_PCI:
151+ if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
152+ return BCMA_DMA_TRANSLATION_DMA64_CMT;
153+ else
154+ return BCMA_DMA_TRANSLATION_DMA32_CMT;
155+ default:
156+ pr_err("DMA translation unknown for host %d\n",
157+ core->bus->hosttype);
158+ }
159+ return BCMA_DMA_TRANSLATION_NONE;
160+}
161+EXPORT_SYMBOL(bcma_core_dma_translation);
162--- a/drivers/bcma/driver_chipcommon_pmu.c
163+++ b/drivers/bcma/driver_chipcommon_pmu.c
164@@ -53,6 +53,7 @@ static void bcma_pmu_resources_init(stru
165         max_msk = 0xFFFF;
166         break;
167     case 43224:
168+ case 43225:
169         break;
170     default:
171         pr_err("PMU resource config unknown for device 0x%04X\n",
172@@ -74,6 +75,7 @@ void bcma_pmu_swreg_init(struct bcma_drv
173     case 0x4313:
174     case 0x4331:
175     case 43224:
176+ case 43225:
177         break;
178     default:
179         pr_err("PMU switch/regulators init unknown for device "
180@@ -96,11 +98,13 @@ void bcma_pmu_workarounds(struct bcma_dr
181         if (bus->chipinfo.rev == 0) {
182             pr_err("Workarounds for 43224 rev 0 not fully "
183                 "implemented\n");
184- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
185+ bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0);
186         } else {
187             bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
188         }
189         break;
190+ case 43225:
191+ break;
192     default:
193         pr_err("Workarounds unknown for device 0x%04X\n",
194             bus->chipinfo.id);
195--- a/drivers/bcma/driver_pci.c
196+++ b/drivers/bcma/driver_pci.c
197@@ -157,7 +157,67 @@ static void bcma_pcicore_serdes_workarou
198  * Init.
199  **************************************************/
200 
201-void bcma_core_pci_init(struct bcma_drv_pci *pc)
202+static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
203 {
204     bcma_pcicore_serdes_workaround(pc);
205 }
206+
207+static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
208+{
209+ struct bcma_bus *bus = pc->core->bus;
210+ u16 chipid_top;
211+
212+ chipid_top = (bus->chipinfo.id & 0xFF00);
213+ if (chipid_top != 0x4700 &&
214+ chipid_top != 0x5300)
215+ return false;
216+
217+ if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
218+ return false;
219+
220+#if 0
221+ /* TODO: on BCMA we use address from EROM instead of magic formula */
222+ u32 tmp;
223+ return !mips_busprobe32(tmp, (bus->mmio +
224+ (pc->core->core_index * BCMA_CORE_SIZE)));
225+#endif
226+
227+ return true;
228+}
229+
230+void bcma_core_pci_init(struct bcma_drv_pci *pc)
231+{
232+ if (bcma_core_pci_is_in_hostmode(pc)) {
233+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
234+ bcma_core_pci_hostmode_init(pc);
235+#else
236+ pr_err("Driver compiled without support for hostmode PCI\n");
237+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
238+ } else {
239+ bcma_core_pci_clientmode_init(pc);
240+ }
241+}
242+
243+int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
244+ bool enable)
245+{
246+ struct pci_dev *pdev = pc->core->bus->host_pci;
247+ u32 coremask, tmp;
248+ int err;
249+
250+ err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
251+ if (err)
252+ goto out;
253+
254+ coremask = BIT(core->core_index) << 8;
255+ if (enable)
256+ tmp |= coremask;
257+ else
258+ tmp &= ~coremask;
259+
260+ err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
261+
262+out:
263+ return err;
264+}
265+EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
266--- a/drivers/bcma/host_pci.c
267+++ b/drivers/bcma/host_pci.c
268@@ -65,6 +65,54 @@ static void bcma_host_pci_write32(struct
269     iowrite32(value, core->bus->mmio + offset);
270 }
271 
272+#ifdef CONFIG_BCMA_BLOCKIO
273+void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
274+ size_t count, u16 offset, u8 reg_width)
275+{
276+ void __iomem *addr = core->bus->mmio + offset;
277+ if (core->bus->mapped_core != core)
278+ bcma_host_pci_switch_core(core);
279+ switch (reg_width) {
280+ case sizeof(u8):
281+ ioread8_rep(addr, buffer, count);
282+ break;
283+ case sizeof(u16):
284+ WARN_ON(count & 1);
285+ ioread16_rep(addr, buffer, count >> 1);
286+ break;
287+ case sizeof(u32):
288+ WARN_ON(count & 3);
289+ ioread32_rep(addr, buffer, count >> 2);
290+ break;
291+ default:
292+ WARN_ON(1);
293+ }
294+}
295+
296+void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
297+ size_t count, u16 offset, u8 reg_width)
298+{
299+ void __iomem *addr = core->bus->mmio + offset;
300+ if (core->bus->mapped_core != core)
301+ bcma_host_pci_switch_core(core);
302+ switch (reg_width) {
303+ case sizeof(u8):
304+ iowrite8_rep(addr, buffer, count);
305+ break;
306+ case sizeof(u16):
307+ WARN_ON(count & 1);
308+ iowrite16_rep(addr, buffer, count >> 1);
309+ break;
310+ case sizeof(u32):
311+ WARN_ON(count & 3);
312+ iowrite32_rep(addr, buffer, count >> 2);
313+ break;
314+ default:
315+ WARN_ON(1);
316+ }
317+}
318+#endif
319+
320 static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
321 {
322     if (core->bus->mapped_core != core)
323@@ -87,6 +135,10 @@ const struct bcma_host_ops bcma_host_pci
324     .write8 = bcma_host_pci_write8,
325     .write16 = bcma_host_pci_write16,
326     .write32 = bcma_host_pci_write32,
327+#ifdef CONFIG_BCMA_BLOCKIO
328+ .block_read = bcma_host_pci_block_read,
329+ .block_write = bcma_host_pci_block_write,
330+#endif
331     .aread32 = bcma_host_pci_aread32,
332     .awrite32 = bcma_host_pci_awrite32,
333 };
334@@ -175,6 +227,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_
335     { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
336     { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
337     { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
338+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
339     { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
340     { 0, },
341 };
342--- a/drivers/bcma/main.c
343+++ b/drivers/bcma/main.c
344@@ -7,6 +7,7 @@
345 
346 #include "bcma_private.h"
347 #include <linux/bcma/bcma.h>
348+#include <linux/slab.h>
349 
350 MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
351 MODULE_LICENSE("GPL");
352@@ -89,6 +90,8 @@ static int bcma_register_cores(struct bc
353         switch (bus->hosttype) {
354         case BCMA_HOSTTYPE_PCI:
355             core->dev.parent = &bus->host_pci->dev;
356+ core->dma_dev = &bus->host_pci->dev;
357+ core->irq = bus->host_pci->irq;
358             break;
359         case BCMA_HOSTTYPE_NONE:
360         case BCMA_HOSTTYPE_SDIO:
361@@ -144,6 +147,15 @@ int bcma_bus_register(struct bcma_bus *b
362         bcma_core_pci_init(&bus->drv_pci);
363     }
364 
365+ /* Try to get SPROM */
366+ err = bcma_sprom_get(bus);
367+ if (err == -ENOENT) {
368+ pr_err("No SPROM available\n");
369+ } else if (err) {
370+ pr_err("Failed to get SPROM: %d\n", err);
371+ return -ENOENT;
372+ }
373+
374     /* Register found cores */
375     bcma_register_cores(bus);
376 
377@@ -151,13 +163,11 @@ int bcma_bus_register(struct bcma_bus *b
378 
379     return 0;
380 }
381-EXPORT_SYMBOL_GPL(bcma_bus_register);
382 
383 void bcma_bus_unregister(struct bcma_bus *bus)
384 {
385     bcma_unregister_cores(bus);
386 }
387-EXPORT_SYMBOL_GPL(bcma_bus_unregister);
388 
389 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
390 {
391--- /dev/null
392+++ b/drivers/bcma/sprom.c
393@@ -0,0 +1,171 @@
394+/*
395+ * Broadcom specific AMBA
396+ * SPROM reading
397+ *
398+ * Licensed under the GNU/GPL. See COPYING for details.
399+ */
400+
401+#include "bcma_private.h"
402+
403+#include <linux/bcma/bcma.h>
404+#include <linux/bcma/bcma_regs.h>
405+#include <linux/pci.h>
406+#include <linux/io.h>
407+#include <linux/dma-mapping.h>
408+#include <linux/slab.h>
409+
410+#define SPOFF(offset) ((offset) / sizeof(u16))
411+
412+/**************************************************
413+ * R/W ops.
414+ **************************************************/
415+
416+static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom)
417+{
418+ int i;
419+ for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++)
420+ sprom[i] = bcma_read16(bus->drv_cc.core,
421+ offset + (i * 2));
422+}
423+
424+/**************************************************
425+ * Validation.
426+ **************************************************/
427+
428+static inline u8 bcma_crc8(u8 crc, u8 data)
429+{
430+ /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */
431+ static const u8 t[] = {
432+ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
433+ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
434+ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
435+ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
436+ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
437+ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
438+ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
439+ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
440+ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
441+ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
442+ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
443+ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
444+ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
445+ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
446+ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
447+ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
448+ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
449+ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
450+ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
451+ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
452+ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
453+ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
454+ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
455+ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
456+ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
457+ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
458+ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
459+ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
460+ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
461+ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
462+ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
463+ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
464+ };
465+ return t[crc ^ data];
466+}
467+
468+static u8 bcma_sprom_crc(const u16 *sprom)
469+{
470+ int word;
471+ u8 crc = 0xFF;
472+
473+ for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) {
474+ crc = bcma_crc8(crc, sprom[word] & 0x00FF);
475+ crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8);
476+ }
477+ crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF);
478+ crc ^= 0xFF;
479+
480+ return crc;
481+}
482+
483+static int bcma_sprom_check_crc(const u16 *sprom)
484+{
485+ u8 crc;
486+ u8 expected_crc;
487+ u16 tmp;
488+
489+ crc = bcma_sprom_crc(sprom);
490+ tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC;
491+ expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
492+ if (crc != expected_crc)
493+ return -EPROTO;
494+
495+ return 0;
496+}
497+
498+static int bcma_sprom_valid(const u16 *sprom)
499+{
500+ u16 revision;
501+ int err;
502+
503+ err = bcma_sprom_check_crc(sprom);
504+ if (err)
505+ return err;
506+
507+ revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV;
508+ if (revision != 8 && revision != 9) {
509+ pr_err("Unsupported SPROM revision: %d\n", revision);
510+ return -ENOENT;
511+ }
512+
513+ return 0;
514+}
515+
516+/**************************************************
517+ * SPROM extraction.
518+ **************************************************/
519+
520+static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
521+{
522+ u16 v;
523+ int i;
524+
525+ for (i = 0; i < 3; i++) {
526+ v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
527+ *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
528+ }
529+}
530+
531+int bcma_sprom_get(struct bcma_bus *bus)
532+{
533+ u16 offset;
534+ u16 *sprom;
535+ int err = 0;
536+
537+ if (!bus->drv_cc.core)
538+ return -EOPNOTSUPP;
539+
540+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
541+ return -ENOENT;
542+
543+ sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
544+ GFP_KERNEL);
545+ if (!sprom)
546+ return -ENOMEM;
547+
548+ /* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
549+ * According to brcm80211 this applies to cards with PCIe rev >= 6
550+ * TODO: understand this condition and use it */
551+ offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
552+ BCMA_CC_SPROM_PCIE6;
553+ bcma_sprom_read(bus, offset, sprom);
554+
555+ err = bcma_sprom_valid(sprom);
556+ if (err)
557+ goto out;
558+
559+ bcma_sprom_extract_r8(bus, sprom);
560+
561+out:
562+ kfree(sprom);
563+ return err;
564+}
565--- a/include/linux/bcma/bcma.h
566+++ b/include/linux/bcma/bcma.h
567@@ -6,6 +6,7 @@
568 
569 #include <linux/bcma/bcma_driver_chipcommon.h>
570 #include <linux/bcma/bcma_driver_pci.h>
571+#include <linux/ssb/ssb.h> /* SPROM sharing */
572 
573 #include "bcma_regs.h"
574 
575@@ -24,6 +25,11 @@ struct bcma_chipinfo {
576     u8 pkg;
577 };
578 
579+enum bcma_clkmode {
580+ BCMA_CLKMODE_FAST,
581+ BCMA_CLKMODE_DYNAMIC,
582+};
583+
584 struct bcma_host_ops {
585     u8 (*read8)(struct bcma_device *core, u16 offset);
586     u16 (*read16)(struct bcma_device *core, u16 offset);
587@@ -31,6 +37,12 @@ struct bcma_host_ops {
588     void (*write8)(struct bcma_device *core, u16 offset, u8 value);
589     void (*write16)(struct bcma_device *core, u16 offset, u16 value);
590     void (*write32)(struct bcma_device *core, u16 offset, u32 value);
591+#ifdef CONFIG_BCMA_BLOCKIO
592+ void (*block_read)(struct bcma_device *core, void *buffer,
593+ size_t count, u16 offset, u8 reg_width);
594+ void (*block_write)(struct bcma_device *core, const void *buffer,
595+ size_t count, u16 offset, u8 reg_width);
596+#endif
597     /* Agent ops */
598     u32 (*aread32)(struct bcma_device *core, u16 offset);
599     void (*awrite32)(struct bcma_device *core, u16 offset, u32 value);
600@@ -117,6 +129,8 @@ struct bcma_device {
601     struct bcma_device_id id;
602 
603     struct device dev;
604+ struct device *dma_dev;
605+ unsigned int irq;
606     bool dev_registered;
607 
608     u8 core_index;
609@@ -179,6 +193,10 @@ struct bcma_bus {
610 
611     struct bcma_drv_cc drv_cc;
612     struct bcma_drv_pci drv_pci;
613+
614+ /* We decided to share SPROM struct with SSB as long as we do not need
615+ * any hacks for BCMA. This simplifies drivers code. */
616+ struct ssb_sprom sprom;
617 };
618 
619 extern inline u32 bcma_read8(struct bcma_device *core, u16 offset)
620@@ -208,6 +226,18 @@ void bcma_write32(struct bcma_device *co
621 {
622     core->bus->ops->write32(core, offset, value);
623 }
624+#ifdef CONFIG_BCMA_BLOCKIO
625+extern inline void bcma_block_read(struct bcma_device *core, void *buffer,
626+ size_t count, u16 offset, u8 reg_width)
627+{
628+ core->bus->ops->block_read(core, buffer, count, offset, reg_width);
629+}
630+extern inline void bcma_block_write(struct bcma_device *core, const void *buffer,
631+ size_t count, u16 offset, u8 reg_width)
632+{
633+ core->bus->ops->block_write(core, buffer, count, offset, reg_width);
634+}
635+#endif
636 extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset)
637 {
638     return core->bus->ops->aread32(core, offset);
639@@ -218,7 +248,24 @@ void bcma_awrite32(struct bcma_device *c
640     core->bus->ops->awrite32(core, offset, value);
641 }
642 
643+#define bcma_mask32(cc, offset, mask) \
644+ bcma_write32(cc, offset, bcma_read32(cc, offset) & (mask))
645+#define bcma_set32(cc, offset, set) \
646+ bcma_write32(cc, offset, bcma_read32(cc, offset) | (set))
647+#define bcma_maskset32(cc, offset, mask, set) \
648+ bcma_write32(cc, offset, (bcma_read32(cc, offset) & (mask)) | (set))
649+
650 extern bool bcma_core_is_enabled(struct bcma_device *core);
651+extern void bcma_core_disable(struct bcma_device *core, u32 flags);
652 extern int bcma_core_enable(struct bcma_device *core, u32 flags);
653+extern void bcma_core_set_clockmode(struct bcma_device *core,
654+ enum bcma_clkmode clkmode);
655+extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
656+ bool on);
657+#define BCMA_DMA_TRANSLATION_MASK 0xC0000000
658+#define BCMA_DMA_TRANSLATION_NONE 0x00000000
659+#define BCMA_DMA_TRANSLATION_DMA32_CMT 0x40000000 /* Client Mode Translation for 32-bit DMA */
660+#define BCMA_DMA_TRANSLATION_DMA64_CMT 0x80000000 /* Client Mode Translation for 64-bit DMA */
661+extern u32 bcma_core_dma_translation(struct bcma_device *core);
662 
663 #endif /* LINUX_BCMA_H_ */
664--- a/include/linux/bcma/bcma_driver_chipcommon.h
665+++ b/include/linux/bcma/bcma_driver_chipcommon.h
666@@ -179,15 +179,7 @@
667 #define BCMA_CC_PROG_WAITCNT 0x0124
668 #define BCMA_CC_FLASH_CFG 0x0128
669 #define BCMA_CC_FLASH_WAITCNT 0x012C
670-#define BCMA_CC_CLKCTLST 0x01E0 /* Clock control and status (rev >= 20) */
671-#define BCMA_CC_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */
672-#define BCMA_CC_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */
673-#define BCMA_CC_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */
674-#define BCMA_CC_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */
675-#define BCMA_CC_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
676-#define BCMA_CC_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
677-#define BCMA_CC_CLKCTLST_HAVEHT 0x00010000 /* HT available */
678-#define BCMA_CC_CLKCTLST_HAVEALP 0x00020000 /* APL available */
679+/* 0x1E0 is defined as shared BCMA_CLKCTLST */
680 #define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */
681 #define BCMA_CC_UART0_DATA 0x0300
682 #define BCMA_CC_UART0_IMR 0x0304
683@@ -244,6 +236,8 @@
684 #define BCMA_CC_REGCTL_DATA 0x065C
685 #define BCMA_CC_PLLCTL_ADDR 0x0660
686 #define BCMA_CC_PLLCTL_DATA 0x0664
687+#define BCMA_CC_SPROM 0x0800 /* SPROM beginning */
688+#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */
689 
690 /* Data for the PMU, if available.
691  * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
692--- a/include/linux/bcma/bcma_driver_pci.h
693+++ b/include/linux/bcma/bcma_driver_pci.h
694@@ -85,5 +85,7 @@ struct bcma_drv_pci {
695 #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val)
696 
697 extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
698+extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
699+ struct bcma_device *core, bool enable);
700 
701 #endif /* LINUX_BCMA_DRIVER_PCI_H_ */
702--- a/drivers/bcma/driver_chipcommon.c
703+++ b/drivers/bcma/driver_chipcommon.c
704@@ -23,6 +23,9 @@ static inline u32 bcma_cc_write32_masked
705 
706 void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
707 {
708+ u32 leddc_on = 10;
709+ u32 leddc_off = 90;
710+
711     if (cc->core->id.rev >= 11)
712         cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
713     cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
714@@ -38,6 +41,17 @@ void bcma_core_chipcommon_init(struct bc
715         bcma_pmu_init(cc);
716     if (cc->capabilities & BCMA_CC_CAP_PCTL)
717         pr_err("Power control not implemented!\n");
718+
719+ if (cc->core->id.rev >= 16) {
720+ if (cc->core->bus->sprom.leddc_on_time &&
721+ cc->core->bus->sprom.leddc_off_time) {
722+ leddc_on = cc->core->bus->sprom.leddc_on_time;
723+ leddc_off = cc->core->bus->sprom.leddc_off_time;
724+ }
725+ bcma_cc_write32(cc, BCMA_CC_GPIOTIMER,
726+ ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
727+ (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
728+ }
729 }
730 
731 /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
732--- /dev/null
733+++ b/drivers/bcma/driver_pci_host.c
734@@ -0,0 +1,14 @@
735+/*
736+ * Broadcom specific AMBA
737+ * PCI Core in hostmode
738+ *
739+ * Licensed under the GNU/GPL. See COPYING for details.
740+ */
741+
742+#include "bcma_private.h"
743+#include <linux/bcma/bcma.h>
744+
745+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
746+{
747+ pr_err("No support for PCI core in hostmode yet\n");
748+}
749--- a/include/linux/bcma/bcma_regs.h
750+++ b/include/linux/bcma/bcma_regs.h
751@@ -1,13 +1,38 @@
752 #ifndef LINUX_BCMA_REGS_H_
753 #define LINUX_BCMA_REGS_H_
754 
755+/* Some single registers are shared between many cores */
756+/* BCMA_CLKCTLST: ChipCommon (rev >= 20), PCIe, 80211 */
757+#define BCMA_CLKCTLST 0x01E0 /* Clock control and status */
758+#define BCMA_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */
759+#define BCMA_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */
760+#define BCMA_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */
761+#define BCMA_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */
762+#define BCMA_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
763+#define BCMA_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
764+#define BCMA_CLKCTLST_EXTRESREQ 0x00000700 /* Mask of external resource requests */
765+#define BCMA_CLKCTLST_HAVEALP 0x00010000 /* ALP available */
766+#define BCMA_CLKCTLST_HAVEHT 0x00020000 /* HT available */
767+#define BCMA_CLKCTLST_BP_ON_ALP 0x00040000 /* RO: running on ALP clock */
768+#define BCMA_CLKCTLST_BP_ON_HT 0x00080000 /* RO: running on HT clock */
769+#define BCMA_CLKCTLST_EXTRESST 0x07000000 /* Mask of external resource status */
770+/* Is there any BCM4328 on BCMA bus? */
771+#define BCMA_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */
772+#define BCMA_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */
773+
774 /* Agent registers (common for every core) */
775-#define BCMA_IOCTL 0x0408
776+#define BCMA_IOCTL 0x0408 /* IO control */
777 #define BCMA_IOCTL_CLK 0x0001
778 #define BCMA_IOCTL_FGC 0x0002
779 #define BCMA_IOCTL_CORE_BITS 0x3FFC
780 #define BCMA_IOCTL_PME_EN 0x4000
781 #define BCMA_IOCTL_BIST_EN 0x8000
782+#define BCMA_IOST 0x0500 /* IO status */
783+#define BCMA_IOST_CORE_BITS 0x0FFF
784+#define BCMA_IOST_DMA64 0x1000
785+#define BCMA_IOST_GATED_CLK 0x2000
786+#define BCMA_IOST_BIST_ERROR 0x4000
787+#define BCMA_IOST_BIST_DONE 0x8000
788 #define BCMA_RESET_CTL 0x0800
789 #define BCMA_RESET_CTL_RESET 0x0001
790 
791

Archive Download this file



interactive