aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bcma
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2011-07-22 19:20:08 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-08 14:29:25 -0400
commitecd177c21640e92b059a71139f5850243a8f0942 (patch)
tree70ed92f7b63087bec0a6036dca1c81403d65c86d /drivers/bcma
parent517f43e5a922d51ac960424de4f72676fe6a7390 (diff)
bcma: add SOC bus
This patch adds support for using bcma on a Broadcom SoC as the system bus. An SoC like the bcm4716 could register this bus and use it to searches for the bcma cores and register the devices on this bus. BCMA_HOSTTYPE_NONE was intended for SoCs at first but BCMA_HOSTTYPE_SOC is a better name. Acked-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> Acked-by: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/bcma')
-rw-r--r--drivers/bcma/Kconfig4
-rw-r--r--drivers/bcma/Makefile1
-rw-r--r--drivers/bcma/core.c2
-rw-r--r--drivers/bcma/driver_pci.c9
-rw-r--r--drivers/bcma/host_soc.c183
-rw-r--r--drivers/bcma/main.c9
-rw-r--r--drivers/bcma/scan.c42
7 files changed, 243 insertions, 7 deletions
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index ae0a02e1b808..4a062f858e7a 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -33,6 +33,10 @@ config BCMA_DRIVER_PCI_HOSTMODE
33 help 33 help
34 PCI core hostmode operation (external PCI bus). 34 PCI core hostmode operation (external PCI bus).
35 35
36config BCMA_HOST_SOC
37 bool
38 depends on BCMA && MIPS
39
36config BCMA_DEBUG 40config BCMA_DEBUG
37 bool "BCMA debugging" 41 bool "BCMA debugging"
38 depends on BCMA 42 depends on BCMA
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index a2161cceafb9..8dc730de7786 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -3,6 +3,7 @@ bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
3bcma-y += driver_pci.o 3bcma-y += driver_pci.o
4bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o 4bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
5bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o 5bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
6bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
6obj-$(CONFIG_BCMA) += bcma.o 7obj-$(CONFIG_BCMA) += bcma.o
7 8
8ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG 9ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c
index 4a04a49cc06d..189a97b51be9 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -110,6 +110,8 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
110u32 bcma_core_dma_translation(struct bcma_device *core) 110u32 bcma_core_dma_translation(struct bcma_device *core)
111{ 111{
112 switch (core->bus->hosttype) { 112 switch (core->bus->hosttype) {
113 case BCMA_HOSTTYPE_SOC:
114 return 0;
113 case BCMA_HOSTTYPE_PCI: 115 case BCMA_HOSTTYPE_PCI:
114 if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64) 116 if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
115 return BCMA_DMA_TRANSLATION_DMA64_CMT; 117 return BCMA_DMA_TRANSLATION_DMA64_CMT;
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c
index 4e082100fa9b..405537662392 100644
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -210,7 +210,14 @@ int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
210{ 210{
211 struct pci_dev *pdev = pc->core->bus->host_pci; 211 struct pci_dev *pdev = pc->core->bus->host_pci;
212 u32 coremask, tmp; 212 u32 coremask, tmp;
213 int err; 213 int err = 0;
214
215 if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
216 /* This bcma device is not on a PCI host-bus. So the IRQs are
217 * not routed through the PCI core.
218 * So we must not enable routing through the PCI core. */
219 goto out;
220 }
214 221
215 err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); 222 err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
216 if (err) 223 if (err)
diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c
new file mode 100644
index 000000000000..3c381fb8f9c4
--- /dev/null
+++ b/drivers/bcma/host_soc.c
@@ -0,0 +1,183 @@
1/*
2 * Broadcom specific AMBA
3 * System on Chip (SoC) Host
4 *
5 * Licensed under the GNU/GPL. See COPYING for details.
6 */
7
8#include "bcma_private.h"
9#include "scan.h"
10#include <linux/bcma/bcma.h>
11#include <linux/bcma/bcma_soc.h>
12
13static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
14{
15 return readb(core->io_addr + offset);
16}
17
18static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
19{
20 return readw(core->io_addr + offset);
21}
22
23static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
24{
25 return readl(core->io_addr + offset);
26}
27
28static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
29 u8 value)
30{
31 writeb(value, core->io_addr + offset);
32}
33
34static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
35 u16 value)
36{
37 writew(value, core->io_addr + offset);
38}
39
40static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
41 u32 value)
42{
43 writel(value, core->io_addr + offset);
44}
45
46#ifdef CONFIG_BCMA_BLOCKIO
47static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
48 size_t count, u16 offset, u8 reg_width)
49{
50 void __iomem *addr = core->io_addr + offset;
51
52 switch (reg_width) {
53 case sizeof(u8): {
54 u8 *buf = buffer;
55
56 while (count) {
57 *buf = __raw_readb(addr);
58 buf++;
59 count--;
60 }
61 break;
62 }
63 case sizeof(u16): {
64 __le16 *buf = buffer;
65
66 WARN_ON(count & 1);
67 while (count) {
68 *buf = (__force __le16)__raw_readw(addr);
69 buf++;
70 count -= 2;
71 }
72 break;
73 }
74 case sizeof(u32): {
75 __le32 *buf = buffer;
76
77 WARN_ON(count & 3);
78 while (count) {
79 *buf = (__force __le32)__raw_readl(addr);
80 buf++;
81 count -= 4;
82 }
83 break;
84 }
85 default:
86 WARN_ON(1);
87 }
88}
89
90static void bcma_host_soc_block_write(struct bcma_device *core,
91 const void *buffer,
92 size_t count, u16 offset, u8 reg_width)
93{
94 void __iomem *addr = core->io_addr + offset;
95
96 switch (reg_width) {
97 case sizeof(u8): {
98 const u8 *buf = buffer;
99
100 while (count) {
101 __raw_writeb(*buf, addr);
102 buf++;
103 count--;
104 }
105 break;
106 }
107 case sizeof(u16): {
108 const __le16 *buf = buffer;
109
110 WARN_ON(count & 1);
111 while (count) {
112 __raw_writew((__force u16)(*buf), addr);
113 buf++;
114 count -= 2;
115 }
116 break;
117 }
118 case sizeof(u32): {
119 const __le32 *buf = buffer;
120
121 WARN_ON(count & 3);
122 while (count) {
123 __raw_writel((__force u32)(*buf), addr);
124 buf++;
125 count -= 4;
126 }
127 break;
128 }
129 default:
130 WARN_ON(1);
131 }
132}
133#endif /* CONFIG_BCMA_BLOCKIO */
134
135static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
136{
137 return readl(core->io_wrap + offset);
138}
139
140static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
141 u32 value)
142{
143 writel(value, core->io_wrap + offset);
144}
145
146const struct bcma_host_ops bcma_host_soc_ops = {
147 .read8 = bcma_host_soc_read8,
148 .read16 = bcma_host_soc_read16,
149 .read32 = bcma_host_soc_read32,
150 .write8 = bcma_host_soc_write8,
151 .write16 = bcma_host_soc_write16,
152 .write32 = bcma_host_soc_write32,
153#ifdef CONFIG_BCMA_BLOCKIO
154 .block_read = bcma_host_soc_block_read,
155 .block_write = bcma_host_soc_block_write,
156#endif
157 .aread32 = bcma_host_soc_aread32,
158 .awrite32 = bcma_host_soc_awrite32,
159};
160
161int __init bcma_host_soc_register(struct bcma_soc *soc)
162{
163 struct bcma_bus *bus = &soc->bus;
164 int err;
165
166 /* iomap only first core. We have to read some register on this core
167 * to scan the bus.
168 */
169 bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
170 if (!bus->mmio)
171 return -ENOMEM;
172
173 /* Host specific */
174 bus->hosttype = BCMA_HOSTTYPE_SOC;
175 bus->ops = &bcma_host_soc_ops;
176
177 /* Register */
178 err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
179 if (err)
180 iounmap(bus->mmio);
181
182 return err;
183}
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 360a289738fc..2648522432be 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -66,6 +66,10 @@ static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
66static void bcma_release_core_dev(struct device *dev) 66static void bcma_release_core_dev(struct device *dev)
67{ 67{
68 struct bcma_device *core = container_of(dev, struct bcma_device, dev); 68 struct bcma_device *core = container_of(dev, struct bcma_device, dev);
69 if (core->io_addr)
70 iounmap(core->io_addr);
71 if (core->io_wrap)
72 iounmap(core->io_wrap);
69 kfree(core); 73 kfree(core);
70} 74}
71 75
@@ -93,7 +97,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
93 core->dma_dev = &bus->host_pci->dev; 97 core->dma_dev = &bus->host_pci->dev;
94 core->irq = bus->host_pci->irq; 98 core->irq = bus->host_pci->irq;
95 break; 99 break;
96 case BCMA_HOSTTYPE_NONE: 100 case BCMA_HOSTTYPE_SOC:
101 core->dev.dma_mask = &core->dev.coherent_dma_mask;
102 core->dma_dev = &core->dev;
103 break;
97 case BCMA_HOSTTYPE_SDIO: 104 case BCMA_HOSTTYPE_SDIO:
98 break; 105 break;
99 } 106 }
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index bf9f80652773..0ea390f9aa9e 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -337,6 +337,16 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
337 } 337 }
338 } 338 }
339 } 339 }
340 if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
341 core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE);
342 if (!core->io_addr)
343 return -ENOMEM;
344 core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE);
345 if (!core->io_wrap) {
346 iounmap(core->io_addr);
347 return -ENOMEM;
348 }
349 }
340 return 0; 350 return 0;
341} 351}
342 352
@@ -369,7 +379,14 @@ int bcma_bus_scan(struct bcma_bus *bus)
369 bcma_init_bus(bus); 379 bcma_init_bus(bus);
370 380
371 erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); 381 erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
372 eromptr = bus->mmio; 382 if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
383 eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
384 if (!eromptr)
385 return -ENOMEM;
386 } else {
387 eromptr = bus->mmio;
388 }
389
373 eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); 390 eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
374 391
375 bcma_scan_switch_core(bus, erombase); 392 bcma_scan_switch_core(bus, erombase);
@@ -404,6 +421,9 @@ int bcma_bus_scan(struct bcma_bus *bus)
404 list_add(&core->list, &bus->cores); 421 list_add(&core->list, &bus->cores);
405 } 422 }
406 423
424 if (bus->hosttype == BCMA_HOSTTYPE_SOC)
425 iounmap(eromptr);
426
407 return 0; 427 return 0;
408} 428}
409 429
@@ -414,10 +434,18 @@ int __init bcma_bus_scan_early(struct bcma_bus *bus,
414 u32 erombase; 434 u32 erombase;
415 u32 __iomem *eromptr, *eromend; 435 u32 __iomem *eromptr, *eromend;
416 436
417 int err, core_num = 0; 437 int err = -ENODEV;
438 int core_num = 0;
418 439
419 erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); 440 erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
420 eromptr = bus->mmio; 441 if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
442 eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
443 if (!eromptr)
444 return -ENOMEM;
445 } else {
446 eromptr = bus->mmio;
447 }
448
421 eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); 449 eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
422 450
423 bcma_scan_switch_core(bus, erombase); 451 bcma_scan_switch_core(bus, erombase);
@@ -447,8 +475,12 @@ int __init bcma_bus_scan_early(struct bcma_bus *bus,
447 core->id.class); 475 core->id.class);
448 476
449 list_add(&core->list, &bus->cores); 477 list_add(&core->list, &bus->cores);
450 return 0; 478 err = 0;
479 break;
451 } 480 }
452 481
453 return -ENODEV; 482 if (bus->hosttype == BCMA_HOSTTYPE_SOC)
483 iounmap(eromptr);
484
485 return err;
454} 486}