brcm47xx: add initial support for devices with bcma bus.
[openwrt.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_ */