aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--include/linux/bcma/bcma.h5
-rw-r--r--include/linux/bcma/bcma_soc.h16
9 files changed, 263 insertions, 8 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}
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index e31c9b462221..c70cec59d80e 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -14,9 +14,9 @@ struct bcma_device;
14struct bcma_bus; 14struct bcma_bus;
15 15
16enum bcma_hosttype { 16enum bcma_hosttype {
17 BCMA_HOSTTYPE_NONE,
18 BCMA_HOSTTYPE_PCI, 17 BCMA_HOSTTYPE_PCI,
19 BCMA_HOSTTYPE_SDIO, 18 BCMA_HOSTTYPE_SDIO,
19 BCMA_HOSTTYPE_SOC,
20}; 20};
21 21
22struct bcma_chipinfo { 22struct bcma_chipinfo {
@@ -138,6 +138,9 @@ struct bcma_device {
138 u32 addr; 138 u32 addr;
139 u32 wrap; 139 u32 wrap;
140 140
141 void __iomem *io_addr;
142 void __iomem *io_wrap;
143
141 void *drvdata; 144 void *drvdata;
142 struct list_head list; 145 struct list_head list;
143}; 146};
diff --git a/include/linux/bcma/bcma_soc.h b/include/linux/bcma/bcma_soc.h
new file mode 100644
index 000000000000..4203c5593b9f
--- /dev/null
+++ b/include/linux/bcma/bcma_soc.h
@@ -0,0 +1,16 @@
1#ifndef LINUX_BCMA_SOC_H_
2#define LINUX_BCMA_SOC_H_
3
4#include <linux/bcma/bcma.h>
5
6struct bcma_soc {
7 struct bcma_bus bus;
8 struct bcma_device core_cc;
9 struct bcma_device core_mips;
10};
11
12int __init bcma_host_soc_register(struct bcma_soc *soc);
13
14int bcma_bus_register(struct bcma_bus *bus);
15
16#endif /* LINUX_BCMA_SOC_H_ */