diff options
-rw-r--r-- | drivers/bcma/Kconfig | 4 | ||||
-rw-r--r-- | drivers/bcma/Makefile | 1 | ||||
-rw-r--r-- | drivers/bcma/core.c | 2 | ||||
-rw-r--r-- | drivers/bcma/driver_pci.c | 9 | ||||
-rw-r--r-- | drivers/bcma/host_soc.c | 183 | ||||
-rw-r--r-- | drivers/bcma/main.c | 9 | ||||
-rw-r--r-- | drivers/bcma/scan.c | 42 | ||||
-rw-r--r-- | include/linux/bcma/bcma.h | 5 | ||||
-rw-r--r-- | include/linux/bcma/bcma_soc.h | 16 |
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 | ||
36 | config BCMA_HOST_SOC | ||
37 | bool | ||
38 | depends on BCMA && MIPS | ||
39 | |||
36 | config BCMA_DEBUG | 40 | config 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 | |||
3 | bcma-y += driver_pci.o | 3 | bcma-y += driver_pci.o |
4 | bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o | 4 | bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o |
5 | bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o | 5 | bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o |
6 | bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o | ||
6 | obj-$(CONFIG_BCMA) += bcma.o | 7 | obj-$(CONFIG_BCMA) += bcma.o |
7 | 8 | ||
8 | ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG | 9 | ccflags-$(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); | |||
110 | u32 bcma_core_dma_translation(struct bcma_device *core) | 110 | u32 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 | |||
13 | static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset) | ||
14 | { | ||
15 | return readb(core->io_addr + offset); | ||
16 | } | ||
17 | |||
18 | static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset) | ||
19 | { | ||
20 | return readw(core->io_addr + offset); | ||
21 | } | ||
22 | |||
23 | static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset) | ||
24 | { | ||
25 | return readl(core->io_addr + offset); | ||
26 | } | ||
27 | |||
28 | static void bcma_host_soc_write8(struct bcma_device *core, u16 offset, | ||
29 | u8 value) | ||
30 | { | ||
31 | writeb(value, core->io_addr + offset); | ||
32 | } | ||
33 | |||
34 | static void bcma_host_soc_write16(struct bcma_device *core, u16 offset, | ||
35 | u16 value) | ||
36 | { | ||
37 | writew(value, core->io_addr + offset); | ||
38 | } | ||
39 | |||
40 | static 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 | ||
47 | static 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 | |||
90 | static 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 | |||
135 | static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset) | ||
136 | { | ||
137 | return readl(core->io_wrap + offset); | ||
138 | } | ||
139 | |||
140 | static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset, | ||
141 | u32 value) | ||
142 | { | ||
143 | writel(value, core->io_wrap + offset); | ||
144 | } | ||
145 | |||
146 | const 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 | |||
161 | int __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) | |||
66 | static void bcma_release_core_dev(struct device *dev) | 66 | static 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; | |||
14 | struct bcma_bus; | 14 | struct bcma_bus; |
15 | 15 | ||
16 | enum bcma_hosttype { | 16 | enum 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 | ||
22 | struct bcma_chipinfo { | 22 | struct 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 | |||
6 | struct bcma_soc { | ||
7 | struct bcma_bus bus; | ||
8 | struct bcma_device core_cc; | ||
9 | struct bcma_device core_mips; | ||
10 | }; | ||
11 | |||
12 | int __init bcma_host_soc_register(struct bcma_soc *soc); | ||
13 | |||
14 | int bcma_bus_register(struct bcma_bus *bus); | ||
15 | |||
16 | #endif /* LINUX_BCMA_SOC_H_ */ | ||