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