brcm47xx: add initial support for devices with bcma bus.
[openwrt/staging/chunkeey.git] / target / linux / brcm47xx / patches-3.0 / 0004-bcma-add-SOC-bus.patch
1 From a807b2fb233af60028ed38ba237953bcffdf33e9 Mon Sep 17 00:00:00 2001
2 From: Hauke Mehrtens <hauke@hauke-m.de>
3 Date: Sat, 18 Jun 2011 14:31:53 +0200
4 Subject: [PATCH 04/14] bcma: add SOC bus
5
6 This patch adds support for using bcma on an embedded bus. An embedded
7 system like the bcm4716 could register this bus and it searches for the
8 bcma cores then.
9
10 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
11 ---
12 drivers/bcma/Kconfig | 5 +
13 drivers/bcma/Makefile | 1 +
14 drivers/bcma/host_soc.c | 178 +++++++++++++++++++++++++++++++++++++++++
15 drivers/bcma/main.c | 1 +
16 drivers/bcma/scan.c | 24 +++++-
17 include/linux/bcma/bcma.h | 4 +
18 include/linux/bcma/bcma_soc.h | 16 ++++
19 7 files changed, 227 insertions(+), 2 deletions(-)
20 create mode 100644 drivers/bcma/host_soc.c
21 create mode 100644 include/linux/bcma/bcma_soc.h
22
23 --- a/drivers/bcma/Kconfig
24 +++ b/drivers/bcma/Kconfig
25 @@ -27,6 +27,11 @@ config BCMA_HOST_PCI
26 bool "Support for BCMA on PCI-host bus"
27 depends on BCMA_HOST_PCI_POSSIBLE
28
29 +config BCMA_HOST_SOC
30 + bool
31 + depends on BCMA && MIPS
32 + default n
33 +
34 config BCMA_DEBUG
35 bool "BCMA debugging"
36 depends on BCMA
37 --- a/drivers/bcma/Makefile
38 +++ b/drivers/bcma/Makefile
39 @@ -2,6 +2,7 @@ bcma-y += main.o scan.o core.o sprom
40 bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
41 bcma-y += driver_pci.o
42 bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
43 +bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
44 obj-$(CONFIG_BCMA) += bcma.o
45
46 ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG
47 --- /dev/null
48 +++ b/drivers/bcma/host_soc.c
49 @@ -0,0 +1,178 @@
50 +/*
51 + * Broadcom specific AMBA
52 + * System on Chip (SoC) Host
53 + *
54 + * Licensed under the GNU/GPL. See COPYING for details.
55 + */
56 +
57 +#include "bcma_private.h"
58 +#include "scan.h"
59 +#include <linux/bcma/bcma.h>
60 +#include <linux/bcma/bcma_soc.h>
61 +
62 +static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
63 +{
64 + return readb(core->io_addr + offset);
65 +}
66 +
67 +static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
68 +{
69 + return readw(core->io_addr + offset);
70 +}
71 +
72 +static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
73 +{
74 + return readl(core->io_addr + offset);
75 +}
76 +
77 +static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
78 + u8 value)
79 +{
80 + writeb(value, core->io_addr + offset);
81 +}
82 +
83 +static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
84 + u16 value)
85 +{
86 + writew(value, core->io_addr + offset);
87 +}
88 +
89 +static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
90 + u32 value)
91 +{
92 + writel(value, core->io_addr + offset);
93 +}
94 +
95 +#ifdef CONFIG_BCMA_BLOCKIO
96 +static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
97 + size_t count, u16 offset, u8 reg_width)
98 +{
99 + void __iomem *addr = core->io_addr + offset;
100 +
101 + switch (reg_width) {
102 + case sizeof(u8): {
103 + u8 *buf = buffer;
104 +
105 + while (count) {
106 + *buf = __raw_readb(addr);
107 + buf++;
108 + count--;
109 + }
110 + break;
111 + }
112 + case sizeof(u16): {
113 + __le16 *buf = buffer;
114 +
115 + WARN_ON(count & 1);
116 + while (count) {
117 + *buf = (__force __le16)__raw_readw(addr);
118 + buf++;
119 + count -= 2;
120 + }
121 + break;
122 + }
123 + case sizeof(u32): {
124 + __le32 *buf = buffer;
125 +
126 + WARN_ON(count & 3);
127 + while (count) {
128 + *buf = (__force __le32)__raw_readl(addr);
129 + buf++;
130 + count -= 4;
131 + }
132 + break;
133 + }
134 + default:
135 + WARN_ON(1);
136 + }
137 +}
138 +
139 +static void bcma_host_soc_block_write(struct bcma_device *core,
140 + const void *buffer,
141 + size_t count, u16 offset, u8 reg_width)
142 +{
143 + void __iomem *addr = core->io_addr + offset;
144 +
145 + switch (reg_width) {
146 + case sizeof(u8): {
147 + const u8 *buf = buffer;
148 +
149 + while (count) {
150 + __raw_writeb(*buf, addr);
151 + buf++;
152 + count--;
153 + }
154 + break;
155 + }
156 + case sizeof(u16): {
157 + const __le16 *buf = buffer;
158 +
159 + WARN_ON(count & 1);
160 + while (count) {
161 + __raw_writew((__force u16)(*buf), addr);
162 + buf++;
163 + count -= 2;
164 + }
165 + break;
166 + }
167 + case sizeof(u32): {
168 + const __le32 *buf = buffer;
169 +
170 + WARN_ON(count & 3);
171 + while (count) {
172 + __raw_writel((__force u32)(*buf), addr);
173 + buf++;
174 + count -= 4;
175 + }
176 + break;
177 + }
178 + default:
179 + WARN_ON(1);
180 + }
181 +}
182 +#endif /* CONFIG_BCMA_BLOCKIO */
183 +
184 +static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
185 +{
186 + return readl(core->io_wrap + offset);
187 +}
188 +
189 +static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
190 + u32 value)
191 +{
192 + writel(value, core->io_wrap + offset);
193 +}
194 +
195 +const struct bcma_host_ops bcma_host_soc_ops = {
196 + .read8 = bcma_host_soc_read8,
197 + .read16 = bcma_host_soc_read16,
198 + .read32 = bcma_host_soc_read32,
199 + .write8 = bcma_host_soc_write8,
200 + .write16 = bcma_host_soc_write16,
201 + .write32 = bcma_host_soc_write32,
202 +#ifdef CONFIG_BCMA_BLOCKIO
203 + .block_read = bcma_host_soc_block_read,
204 + .block_write = bcma_host_soc_block_write,
205 +#endif
206 + .aread32 = bcma_host_soc_aread32,
207 + .awrite32 = bcma_host_soc_awrite32,
208 +};
209 +
210 +int __init bcma_host_soc_register(struct bcma_soc *soc)
211 +{
212 + struct bcma_bus *bus = &soc->bus;
213 +
214 + /* iomap only first core. We have to read some register on this core
215 + * to scan the bus.
216 + */
217 + bus->mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
218 + if (!bus->mmio)
219 + return -ENOMEM;
220 +
221 + /* Host specific */
222 + bus->hosttype = BCMA_HOSTTYPE_SOC;
223 + bus->ops = &bcma_host_soc_ops;
224 +
225 + /* Register */
226 + return bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
227 +}
228 --- a/drivers/bcma/main.c
229 +++ b/drivers/bcma/main.c
230 @@ -95,6 +95,7 @@ static int bcma_register_cores(struct bc
231 break;
232 case BCMA_HOSTTYPE_NONE:
233 case BCMA_HOSTTYPE_SDIO:
234 + case BCMA_HOSTTYPE_SOC:
235 break;
236 }
237
238 --- a/drivers/bcma/scan.c
239 +++ b/drivers/bcma/scan.c
240 @@ -337,6 +337,14 @@ static int bcma_get_next_core(struct bcm
241 }
242 }
243 }
244 + if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
245 + core->io_addr = ioremap(core->addr, BCMA_CORE_SIZE);
246 + if (!core->io_addr)
247 + return -ENOMEM;
248 + core->io_wrap = ioremap(core->wrap, BCMA_CORE_SIZE);
249 + if (!core->io_wrap)
250 + return -ENOMEM;
251 + }
252 return 0;
253 }
254
255 @@ -369,7 +377,13 @@ int bcma_bus_scan(struct bcma_bus *bus)
256 bcma_init_bus(bus);
257
258 erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
259 - eromptr = bus->mmio;
260 + if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
261 + eromptr = ioremap(erombase, BCMA_CORE_SIZE);
262 + if (!eromptr)
263 + return -ENOMEM;
264 + } else
265 + eromptr = bus->mmio;
266 +
267 eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
268
269 bcma_scan_switch_core(bus, erombase);
270 @@ -417,7 +431,13 @@ int __init bcma_bus_scan_early(struct bc
271 int err, core_num = 0;
272
273 erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
274 - eromptr = bus->mmio;
275 + if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
276 + eromptr = ioremap(erombase, BCMA_CORE_SIZE);
277 + if (!eromptr)
278 + return -ENOMEM;
279 + } else
280 + eromptr = bus->mmio;
281 +
282 eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
283
284 bcma_scan_switch_core(bus, erombase);
285 --- a/include/linux/bcma/bcma.h
286 +++ b/include/linux/bcma/bcma.h
287 @@ -17,6 +17,7 @@ enum bcma_hosttype {
288 BCMA_HOSTTYPE_NONE,
289 BCMA_HOSTTYPE_PCI,
290 BCMA_HOSTTYPE_SDIO,
291 + BCMA_HOSTTYPE_SOC,
292 };
293
294 struct bcma_chipinfo {
295 @@ -133,6 +134,9 @@ struct bcma_device {
296 u32 addr;
297 u32 wrap;
298
299 + void __iomem *io_addr;
300 + void __iomem *io_wrap;
301 +
302 void *drvdata;
303 struct list_head list;
304 };
305 --- /dev/null
306 +++ b/include/linux/bcma/bcma_soc.h
307 @@ -0,0 +1,16 @@
308 +#ifndef LINUX_BCMA_SOC_H_
309 +#define LINUX_BCMA_SOC_H_
310 +
311 +#include <linux/bcma/bcma.h>
312 +
313 +struct bcma_soc {
314 + struct bcma_bus bus;
315 + struct bcma_device core_cc;
316 + struct bcma_device core_mips;
317 +};
318 +
319 +int __init bcma_host_soc_register(struct bcma_soc *soc);
320 +
321 +int bcma_bus_register(struct bcma_bus *bus);
322 +
323 +#endif /* LINUX_BCMA_SOC_H_ */