ixp4xx: add support for linux 3.3.1
[openwrt.git] / target / linux / brcm47xx / patches-3.0 / 0008-bcm47xx-prepare-to-support-different-buses.patch
1 From 18fe82b600f9563e59e28746211a2ce3176a81de Mon Sep 17 00:00:00 2001
2 From: Hauke Mehrtens <hauke@hauke-m.de>
3 Date: Mon, 6 Jun 2011 00:07:36 +0200
4 Subject: [PATCH 08/26] bcm47xx: prepare to support different buses
5
6 Prepare bcm47xx to support different System buses. Before adding
7 support for bcma it should be possible to build bcm47xx without the
8 need of ssb. With this patch bcm47xx does not directly contain a
9 ssb_bus, but a union contain all the supported system buses. As a SoC
10 just uses one system bus a union is a good choice.
11
12 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
13 ---
14  arch/mips/bcm47xx/gpio.c                     |   56 ++++++++++++++++----------
15  arch/mips/bcm47xx/nvram.c                    |   15 +++++--
16  arch/mips/bcm47xx/serial.c                   |   13 +++++-
17  arch/mips/bcm47xx/setup.c                    |   33 ++++++++++++---
18  arch/mips/bcm47xx/time.c                     |    9 +++-
19  arch/mips/bcm47xx/wgt634u.c                  |   14 ++++--
20  arch/mips/include/asm/mach-bcm47xx/bcm47xx.h |   14 ++++++-
21  arch/mips/include/asm/mach-bcm47xx/gpio.h    |   55 ++++++++++++++++++-------
22  drivers/watchdog/bcm47xx_wdt.c               |   12 +++++-
23  9 files changed, 160 insertions(+), 61 deletions(-)
24
25 --- a/arch/mips/bcm47xx/gpio.c
26 +++ b/arch/mips/bcm47xx/gpio.c
27 @@ -20,42 +20,54 @@ static DECLARE_BITMAP(gpio_in_use, BCM47
28  
29  int gpio_request(unsigned gpio, const char *tag)
30  {
31 -       if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
32 -           ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
33 -               return -EINVAL;
34 -
35 -       if (ssb_extif_available(&ssb_bcm47xx.extif) &&
36 -           ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
37 -               return -EINVAL;
38 -
39 -       if (test_and_set_bit(gpio, gpio_in_use))
40 -               return -EBUSY;
41 -
42 -       return 0;
43 +       switch (bcm47xx_bus_type) {
44 +       case BCM47XX_BUS_TYPE_SSB:
45 +               if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
46 +                   ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
47 +                       return -EINVAL;
48 +
49 +               if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
50 +                   ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
51 +                       return -EINVAL;
52 +
53 +               if (test_and_set_bit(gpio, gpio_in_use))
54 +                       return -EBUSY;
55 +
56 +               return 0;
57 +       }
58 +       return -EINVAL;
59  }
60  EXPORT_SYMBOL(gpio_request);
61  
62  void gpio_free(unsigned gpio)
63  {
64 -       if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
65 -           ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
66 -               return;
67 +       switch (bcm47xx_bus_type) {
68 +       case BCM47XX_BUS_TYPE_SSB:
69 +               if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
70 +                   ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
71 +                       return;
72 +
73 +               if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
74 +                   ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
75 +                       return;
76  
77 -       if (ssb_extif_available(&ssb_bcm47xx.extif) &&
78 -           ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
79 +               clear_bit(gpio, gpio_in_use);
80                 return;
81 -
82 -       clear_bit(gpio, gpio_in_use);
83 +       }
84  }
85  EXPORT_SYMBOL(gpio_free);
86  
87  int gpio_to_irq(unsigned gpio)
88  {
89 -       if (ssb_chipco_available(&ssb_bcm47xx.chipco))
90 -               return ssb_mips_irq(ssb_bcm47xx.chipco.dev) + 2;
91 -       else if (ssb_extif_available(&ssb_bcm47xx.extif))
92 -               return ssb_mips_irq(ssb_bcm47xx.extif.dev) + 2;
93 -       else
94 -               return -EINVAL;
95 +       switch (bcm47xx_bus_type) {
96 +       case BCM47XX_BUS_TYPE_SSB:
97 +               if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
98 +                       return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
99 +               else if (ssb_extif_available(&bcm47xx_bus.ssb.extif))
100 +                       return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
101 +               else
102 +                       return -EINVAL;
103 +       }
104 +       return -EINVAL;
105  }
106  EXPORT_SYMBOL_GPL(gpio_to_irq);
107 --- a/arch/mips/bcm47xx/nvram.c
108 +++ b/arch/mips/bcm47xx/nvram.c
109 @@ -26,14 +26,21 @@ static char nvram_buf[NVRAM_SPACE];
110  /* Probe for NVRAM header */
111  static void early_nvram_init(void)
112  {
113 -       struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
114 +       struct ssb_mipscore *mcore_ssb;
115         struct nvram_header *header;
116         int i;
117 -       u32 base, lim, off;
118 +       u32 base = 0;
119 +       u32 lim = 0;
120 +       u32 off;
121         u32 *src, *dst;
122  
123 -       base = mcore->flash_window;
124 -       lim = mcore->flash_window_size;
125 +       switch (bcm47xx_bus_type) {
126 +       case BCM47XX_BUS_TYPE_SSB:
127 +               mcore_ssb = &bcm47xx_bus.ssb.mipscore;
128 +               base = mcore_ssb->flash_window;
129 +               lim = mcore_ssb->flash_window_size;
130 +               break;
131 +       }
132  
133         off = FLASH_MIN;
134         while (off <= lim) {
135 --- a/arch/mips/bcm47xx/serial.c
136 +++ b/arch/mips/bcm47xx/serial.c
137 @@ -23,10 +23,10 @@ static struct platform_device uart8250_d
138         },
139  };
140  
141 -static int __init uart8250_init(void)
142 +static int __init uart8250_init_ssb(void)
143  {
144         int i;
145 -       struct ssb_mipscore *mcore = &(ssb_bcm47xx.mipscore);
146 +       struct ssb_mipscore *mcore = &(bcm47xx_bus.ssb.mipscore);
147  
148         memset(&uart8250_data, 0,  sizeof(uart8250_data));
149  
150 @@ -45,6 +45,15 @@ static int __init uart8250_init(void)
151         return platform_device_register(&uart8250_device);
152  }
153  
154 +static int __init uart8250_init(void)
155 +{
156 +       switch (bcm47xx_bus_type) {
157 +       case BCM47XX_BUS_TYPE_SSB:
158 +               return uart8250_init_ssb();
159 +       }
160 +       return -EINVAL;
161 +}
162 +
163  module_init(uart8250_init);
164  
165  MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
166 --- a/arch/mips/bcm47xx/setup.c
167 +++ b/arch/mips/bcm47xx/setup.c
168 @@ -35,15 +35,22 @@
169  #include <bcm47xx.h>
170  #include <asm/mach-bcm47xx/nvram.h>
171  
172 -struct ssb_bus ssb_bcm47xx;
173 -EXPORT_SYMBOL(ssb_bcm47xx);
174 +union bcm47xx_bus bcm47xx_bus;
175 +EXPORT_SYMBOL(bcm47xx_bus);
176 +
177 +enum bcm47xx_bus_type bcm47xx_bus_type;
178 +EXPORT_SYMBOL(bcm47xx_bus_type);
179  
180  static void bcm47xx_machine_restart(char *command)
181  {
182         printk(KERN_ALERT "Please stand by while rebooting the system...\n");
183         local_irq_disable();
184         /* Set the watchdog timer to reset immediately */
185 -       ssb_watchdog_timer_set(&ssb_bcm47xx, 1);
186 +       switch (bcm47xx_bus_type) {
187 +       case BCM47XX_BUS_TYPE_SSB:
188 +               ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
189 +               break;
190 +       }
191         while (1)
192                 cpu_relax();
193  }
194 @@ -52,7 +59,11 @@ static void bcm47xx_machine_halt(void)
195  {
196         /* Disable interrupts and watchdog and spin forever */
197         local_irq_disable();
198 -       ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
199 +       switch (bcm47xx_bus_type) {
200 +       case BCM47XX_BUS_TYPE_SSB:
201 +               ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
202 +               break;
203 +       }
204         while (1)
205                 cpu_relax();
206  }
207 @@ -247,7 +258,7 @@ static int bcm47xx_get_invariants(struct
208         return 0;
209  }
210  
211 -void __init plat_mem_setup(void)
212 +static void __init bcm47xx_register_ssb(void)
213  {
214         int err;
215         char buf[100];
216 @@ -258,12 +269,12 @@ void __init plat_mem_setup(void)
217                 printk(KERN_WARNING "bcm47xx: someone else already registered"
218                         " a ssb SPROM callback handler (err %d)\n", err);
219  
220 -       err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
221 +       err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE,
222                                       bcm47xx_get_invariants);
223         if (err)
224                 panic("Failed to initialize SSB bus (err %d)\n", err);
225  
226 -       mcore = &ssb_bcm47xx.mipscore;
227 +       mcore = &bcm47xx_bus.ssb.mipscore;
228         if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
229                 if (strstr(buf, "console=ttyS1")) {
230                         struct ssb_serial_port port;
231 @@ -276,6 +287,14 @@ void __init plat_mem_setup(void)
232                         memcpy(&mcore->serial_ports[1], &port, sizeof(port));
233                 }
234         }
235 +}
236 +
237 +void __init plat_mem_setup(void)
238 +{
239 +       struct cpuinfo_mips *c = &current_cpu_data;
240 +
241 +       bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB;
242 +       bcm47xx_register_ssb();
243  
244         _machine_restart = bcm47xx_machine_restart;
245         _machine_halt = bcm47xx_machine_halt;
246 --- a/arch/mips/bcm47xx/time.c
247 +++ b/arch/mips/bcm47xx/time.c
248 @@ -30,7 +30,7 @@
249  
250  void __init plat_time_init(void)
251  {
252 -       unsigned long hz;
253 +       unsigned long hz = 0;
254  
255         /*
256          * Use deterministic values for initial counter interrupt
257 @@ -39,7 +39,12 @@ void __init plat_time_init(void)
258         write_c0_count(0);
259         write_c0_compare(0xffff);
260  
261 -       hz = ssb_cpu_clock(&ssb_bcm47xx.mipscore) / 2;
262 +       switch (bcm47xx_bus_type) {
263 +       case BCM47XX_BUS_TYPE_SSB:
264 +               hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
265 +               break;
266 +       }
267 +
268         if (!hz)
269                 hz = 100000000;
270  
271 --- a/arch/mips/bcm47xx/wgt634u.c
272 +++ b/arch/mips/bcm47xx/wgt634u.c
273 @@ -108,7 +108,7 @@ static irqreturn_t gpio_interrupt(int ir
274  
275         /* Interrupts are shared, check if the current one is
276            a GPIO interrupt. */
277 -       if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco,
278 +       if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco,
279                                    SSB_CHIPCO_IRQ_GPIO))
280                 return IRQ_NONE;
281  
282 @@ -132,22 +132,26 @@ static int __init wgt634u_init(void)
283          * machine. Use the MAC address as an heuristic. Netgear Inc. has
284          * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
285          */
286 +       u8 *et0mac;
287  
288 -       u8 *et0mac = ssb_bcm47xx.sprom.et0mac;
289 +       if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
290 +               return -ENODEV;
291 +
292 +       et0mac = bcm47xx_bus.ssb.sprom.et0mac;
293  
294         if (et0mac[0] == 0x00 &&
295             ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
296              (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
297 -               struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
298 +               struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
299  
300                 printk(KERN_INFO "WGT634U machine detected.\n");
301  
302                 if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
303                                  gpio_interrupt, IRQF_SHARED,
304 -                                "WGT634U GPIO", &ssb_bcm47xx.chipco)) {
305 +                                "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
306                         gpio_direction_input(WGT634U_GPIO_RESET);
307                         gpio_intmask(WGT634U_GPIO_RESET, 1);
308 -                       ssb_chipco_irq_mask(&ssb_bcm47xx.chipco,
309 +                       ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
310                                             SSB_CHIPCO_IRQ_GPIO,
311                                             SSB_CHIPCO_IRQ_GPIO);
312                 }
313 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
314 +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
315 @@ -19,7 +19,17 @@
316  #ifndef __ASM_BCM47XX_H
317  #define __ASM_BCM47XX_H
318  
319 -/* SSB bus */
320 -extern struct ssb_bus ssb_bcm47xx;
321 +#include <linux/ssb/ssb.h>
322 +
323 +enum bcm47xx_bus_type {
324 +       BCM47XX_BUS_TYPE_SSB,
325 +};
326 +
327 +union bcm47xx_bus {
328 +       struct ssb_bus ssb;
329 +};
330 +
331 +extern union bcm47xx_bus bcm47xx_bus;
332 +extern enum bcm47xx_bus_type bcm47xx_bus_type;
333  
334  #endif /* __ASM_BCM47XX_H */
335 --- a/arch/mips/include/asm/mach-bcm47xx/gpio.h
336 +++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h
337 @@ -21,41 +21,66 @@ extern int gpio_to_irq(unsigned gpio);
338  
339  static inline int gpio_get_value(unsigned gpio)
340  {
341 -       return ssb_gpio_in(&ssb_bcm47xx, 1 << gpio);
342 +       switch (bcm47xx_bus_type) {
343 +       case BCM47XX_BUS_TYPE_SSB:
344 +               return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
345 +       }
346 +       return -EINVAL;
347  }
348  
349  static inline void gpio_set_value(unsigned gpio, int value)
350  {
351 -       ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
352 +       switch (bcm47xx_bus_type) {
353 +       case BCM47XX_BUS_TYPE_SSB:
354 +               ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
355 +                            value ? 1 << gpio : 0);
356 +       }
357  }
358  
359  static inline int gpio_direction_input(unsigned gpio)
360  {
361 -       ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0);
362 -       return 0;
363 +       switch (bcm47xx_bus_type) {
364 +       case BCM47XX_BUS_TYPE_SSB:
365 +               ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
366 +               return 0;
367 +       }
368 +       return -EINVAL;
369  }
370  
371  static inline int gpio_direction_output(unsigned gpio, int value)
372  {
373 -       /* first set the gpio out value */
374 -       ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
375 -       /* then set the gpio mode */
376 -       ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio);
377 -       return 0;
378 +       switch (bcm47xx_bus_type) {
379 +       case BCM47XX_BUS_TYPE_SSB:
380 +               /* first set the gpio out value */
381 +               ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
382 +                            value ? 1 << gpio : 0);
383 +               /* then set the gpio mode */
384 +               ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
385 +               return 0;
386 +       }
387 +       return -EINVAL;
388  }
389  
390  static inline int gpio_intmask(unsigned gpio, int value)
391  {
392 -       ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio,
393 -                        value ? 1 << gpio : 0);
394 -       return 0;
395 +       switch (bcm47xx_bus_type) {
396 +       case BCM47XX_BUS_TYPE_SSB:
397 +               ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
398 +                                value ? 1 << gpio : 0);
399 +               return 0;
400 +       }
401 +       return -EINVAL;
402  }
403  
404  static inline int gpio_polarity(unsigned gpio, int value)
405  {
406 -       ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio,
407 -                         value ? 1 << gpio : 0);
408 -       return 0;
409 +       switch (bcm47xx_bus_type) {
410 +       case BCM47XX_BUS_TYPE_SSB:
411 +               ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
412 +                                 value ? 1 << gpio : 0);
413 +               return 0;
414 +       }
415 +       return -EINVAL;
416  }
417  
418  
419 --- a/drivers/watchdog/bcm47xx_wdt.c
420 +++ b/drivers/watchdog/bcm47xx_wdt.c
421 @@ -54,12 +54,20 @@ static atomic_t ticks;
422  static inline void bcm47xx_wdt_hw_start(void)
423  {
424         /* this is 2,5s on 100Mhz clock  and 2s on 133 Mhz */
425 -       ssb_watchdog_timer_set(&ssb_bcm47xx, 0xfffffff);
426 +       switch (bcm47xx_bus_type) {
427 +       case BCM47XX_BUS_TYPE_SSB:
428 +               ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff);
429 +               break;
430 +       }
431  }
432  
433  static inline int bcm47xx_wdt_hw_stop(void)
434  {
435 -       return ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
436 +       switch (bcm47xx_bus_type) {
437 +       case BCM47XX_BUS_TYPE_SSB:
438 +               return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
439 +       }
440 +       return -EINVAL;
441  }
442  
443  static void bcm47xx_timer_tick(unsigned long unused)