7153871d21158672cbdfd2b30d44c60c65ae1739
[openwrt.git] / target / linux / brcm47xx / patches-2.6.25 / 400-arch-bcm47xx.patch
1 --- a/arch/mips/bcm47xx/irq.c
2 +++ b/arch/mips/bcm47xx/irq.c
3 @@ -1,5 +1,6 @@
4  /*
5   *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
6 + *  Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
7   *
8   *  This program is free software; you can redistribute  it and/or modify it
9   *  under  the terms of  the GNU General  Public License as published by the
10 @@ -23,10 +24,19 @@
11   */
12  
13  #include <linux/types.h>
14 +#include <linux/errno.h>
15 +#include <linux/init.h>
16  #include <linux/interrupt.h>
17  #include <linux/irq.h>
18 +#include <linux/pci.h>
19 +#include <linux/ssb/ssb.h>
20 +
21  #include <asm/irq_cpu.h>
22  
23 +
24 +extern struct ssb_bus ssb_bcm47xx;
25 +
26 +
27  void plat_irq_dispatch(void)
28  {
29         u32 cause;
30 @@ -53,3 +63,19 @@ void __init arch_init_irq(void)
31  {
32         mips_cpu_irq_init();
33  }
34 +
35 +int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
36 +{
37 +       int res;
38 +
39 +       res = ssb_pcibios_map_irq(dev, slot, pin);
40 +       if (res < 0) {
41 +               printk(KERN_ALERT "PCI: Failed to map IRQ of device %s\n",
42 +                      dev->dev.bus_id);
43 +               return 0;
44 +       }
45 +       /* IRQ-0 and IRQ-1 are software interrupts. */
46 +       WARN_ON((res == 0) || (res == 1));
47 +
48 +       return res;
49 +}
50 --- a/arch/mips/bcm47xx/setup.c
51 +++ b/arch/mips/bcm47xx/setup.c
52 @@ -2,7 +2,7 @@
53   *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
54   *  Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
55   *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
56 - *  Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
57 + *  Copyright (C) 2006-2008 Michael Buesch <mb@bu3sch.de>
58   *
59   *  This program is free software; you can redistribute  it and/or modify it
60   *  under  the terms of  the GNU General  Public License as published by the
61 @@ -25,23 +25,52 @@
62   *  675 Mass Ave, Cambridge, MA 02139, USA.
63   */
64  
65 +#include <linux/init.h>
66  #include <linux/types.h>
67 -#include <linux/ssb/ssb.h>
68 +#include <linux/tty.h>
69 +#include <linux/serial.h>
70 +#include <linux/serial_core.h>
71 +#include <linux/serial_reg.h>
72 +#include <linux/serial_8250.h>
73  #include <asm/bootinfo.h>
74 -#include <asm/reboot.h>
75  #include <asm/time.h>
76 -#include <bcm47xx.h>
77 +#include <asm/reboot.h>
78  #include <asm/fw/cfe/cfe_api.h>
79 +#include <linux/pm.h>
80 +#include <linux/ssb/ssb.h>
81 +#include <linux/ssb/ssb_embedded.h>
82 +
83 +#include "include/nvram.h"
84  
85  struct ssb_bus ssb_bcm47xx;
86  EXPORT_SYMBOL(ssb_bcm47xx);
87  
88 +extern void bcm47xx_pci_init(void);
89 +
90 +int pcibios_plat_dev_init(struct pci_dev *dev)
91 +{
92 +       int err;
93 +
94 +       err = ssb_pcibios_plat_dev_init(dev);
95 +       if (err) {
96 +               printk(KERN_ALERT "PCI: Failed to init device %s\n",
97 +                      pci_name(dev));
98 +       }
99 +
100 +       return err;
101 +}
102 +
103  static void bcm47xx_machine_restart(char *command)
104  {
105         printk(KERN_ALERT "Please stand by while rebooting the system...\n");
106         local_irq_disable();
107 +       /* CFE has a reboot callback, but that does not work.
108 +        * Oopses with: Reserved instruction in kernel code.
109 +        */
110 +
111         /* Set the watchdog timer to reset immediately */
112 -       ssb_chipco_watchdog_timer_set(&ssb_bcm47xx.chipco, 1);
113 +       if (ssb_watchdog_timer_set(&ssb_bcm47xx, 1))
114 +               printk(KERN_EMERG "SSB watchdog-triggered reboot failed!\n");
115         while (1)
116                 cpu_relax();
117  }
118 @@ -50,12 +79,13 @@ static void bcm47xx_machine_halt(void)
119  {
120         /* Disable interrupts and watchdog and spin forever */
121         local_irq_disable();
122 -       ssb_chipco_watchdog_timer_set(&ssb_bcm47xx.chipco, 0);
123 +       if (ssb_watchdog_timer_set(&ssb_bcm47xx, 0))
124 +               printk(KERN_EMERG "Failed to disable SSB watchdog!\n");
125         while (1)
126                 cpu_relax();
127  }
128  
129 -static void str2eaddr(char *str, char *dest)
130 +static void e_aton(char *str, char *dest)
131  {
132         int i = 0;
133  
134 @@ -72,52 +102,141 @@ static void str2eaddr(char *str, char *d
135         }
136  }
137  
138 -static int bcm47xx_get_invariants(struct ssb_bus *bus,
139 -                                  struct ssb_init_invariants *iv)
140 +static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
141  {
142 -       char buf[100];
143 +       char *s;
144  
145 -       /* Fill boardinfo structure */
146 -       memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
147 +       memset(sprom, 0xFF, sizeof(struct ssb_sprom));
148  
149 -       if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0)
150 -               iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
151 -       if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
152 -               iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
153 -       if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
154 -               iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
155 -
156 -       /* Fill sprom structure */
157 -       memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
158 -       iv->sprom.revision = 3;
159 -
160 -       if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
161 -               str2eaddr(buf, iv->sprom.et0mac);
162 -       if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
163 -               str2eaddr(buf, iv->sprom.et1mac);
164 -       if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
165 -               iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10);
166 -       if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
167 -               iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10);
168 -       if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
169 -               iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
170 -       if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
171 -               iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
172 +       sprom->revision = 1;
173 +       if ((s = nvram_get("il0macaddr")))
174 +               e_aton(s, sprom->il0mac);
175 +       if ((s = nvram_get("et0macaddr")))
176 +               e_aton(s, sprom->et0mac);
177 +       if ((s = nvram_get("et1macaddr")))
178 +               e_aton(s, sprom->et1mac);
179 +       if ((s = nvram_get("et0phyaddr")))
180 +               sprom->et0phyaddr = simple_strtoul(s, NULL, 0);
181 +       if ((s = nvram_get("et1phyaddr")))
182 +               sprom->et1phyaddr = simple_strtoul(s, NULL, 0);
183 +       if ((s = nvram_get("et0mdcport")))
184 +               sprom->et0mdcport = !!simple_strtoul(s, NULL, 10);
185 +       if ((s = nvram_get("et1mdcport")))
186 +               sprom->et1mdcport = !!simple_strtoul(s, NULL, 10);
187 +       if ((s = nvram_get("pa0b0")))
188 +               sprom->pa0b0 = simple_strtoul(s, NULL, 0);
189 +       if ((s = nvram_get("pa0b1")))
190 +               sprom->pa0b1 = simple_strtoul(s, NULL, 0);
191 +       if ((s = nvram_get("pa0b2")))
192 +               sprom->pa0b2 = simple_strtoul(s, NULL, 0);
193 +       if ((s = nvram_get("pa1b0")))
194 +               sprom->pa1b0 = simple_strtoul(s, NULL, 0);
195 +       if ((s = nvram_get("pa1b1")))
196 +               sprom->pa1b1 = simple_strtoul(s, NULL, 0);
197 +       if ((s = nvram_get("pa1b2")))
198 +               sprom->pa1b2 = simple_strtoul(s, NULL, 0);
199 +       if ((s = nvram_get("wl0gpio0")))
200 +               sprom->gpio0 = simple_strtoul(s, NULL, 0);
201 +       if ((s = nvram_get("wl0gpio1")))
202 +               sprom->gpio1 = simple_strtoul(s, NULL, 0);
203 +       if ((s = nvram_get("wl0gpio2")))
204 +               sprom->gpio2 = simple_strtoul(s, NULL, 0);
205 +       if ((s = nvram_get("wl0gpio3")))
206 +               sprom->gpio3 = simple_strtoul(s, NULL, 0);
207 +       if ((s = nvram_get("pa0maxpwr")))
208 +               sprom->maxpwr_bg = simple_strtoul(s, NULL, 0);
209 +       if ((s = nvram_get("pa1maxpwr")))
210 +               sprom->maxpwr_a = simple_strtoul(s, NULL, 0);
211 +       if ((s = nvram_get("pa0itssit")))
212 +               sprom->itssi_bg = simple_strtoul(s, NULL, 0);
213 +       if ((s = nvram_get("pa1itssit")))
214 +               sprom->itssi_a = simple_strtoul(s, NULL, 0);
215 +       sprom->boardflags_lo = 0;
216 +       if ((s = nvram_get("boardflags")))
217 +               sprom->boardflags_lo = simple_strtoul(s, NULL, 0);
218 +       sprom->boardflags_hi = 0;
219 +       if ((s = nvram_get("boardflags2")))
220 +               sprom->boardflags_hi = simple_strtoul(s, NULL, 0);
221 +}
222 +
223 +static int bcm47xx_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv)
224 +{
225 +       char *s;
226 +
227 +       iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
228 +       if ((s = nvram_get("boardtype")))
229 +               iv->boardinfo.type = (u16)simple_strtoul(s, NULL, 0);
230 +       if ((s = nvram_get("boardrev")))
231 +               iv->boardinfo.rev = (u16)simple_strtoul(s, NULL, 0);
232 +
233 +       bcm47xx_fill_sprom(&iv->sprom);
234 +
235 +       if ((s = nvram_get("cardbus")))
236 +               iv->has_cardbus_slot = !!simple_strtoul(s, NULL, 10);
237  
238         return 0;
239  }
240  
241  void __init plat_mem_setup(void)
242  {
243 -       int err;
244 +       int i, err;
245 +       char *s;
246 +       struct ssb_mipscore *mcore;
247 +
248 +       err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, bcm47xx_get_invariants);
249 +       if (err) {
250 +               const char *msg = "Failed to initialize SSB bus (err %d)\n";
251 +               printk(msg, err); /* Make sure the message gets out of the box. */
252 +               panic(msg, err);
253 +       }
254 +       mcore = &ssb_bcm47xx.mipscore;
255 +
256 +       s = nvram_get("kernel_args");
257 +       if (s && !strncmp(s, "console=ttyS1", 13)) {
258 +               struct ssb_serial_port port;
259 +
260 +               printk("Swapping serial ports!\n");
261 +               /* swap serial ports */
262 +               memcpy(&port, &mcore->serial_ports[0], sizeof(port));
263 +               memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], sizeof(port));
264 +               memcpy(&mcore->serial_ports[1], &port, sizeof(port));
265 +       }
266  
267 -       err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
268 -                                     bcm47xx_get_invariants);
269 -       if (err)
270 -               panic("Failed to initialize SSB bus (err %d)\n", err);
271 +       for (i = 0; i < mcore->nr_serial_ports; i++) {
272 +               struct ssb_serial_port *port = &(mcore->serial_ports[i]);
273 +               struct uart_port s;
274 +
275 +               memset(&s, 0, sizeof(s));
276 +               s.line = i;
277 +               s.membase = port->regs;
278 +               s.irq = port->irq + 2;
279 +               s.uartclk = port->baud_base;
280 +               s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
281 +               s.iotype = SERIAL_IO_MEM;
282 +               s.regshift = port->reg_shift;
283 +
284 +               early_serial_setup(&s);
285 +       }
286 +       printk("Serial init done.\n");
287  
288         _machine_restart = bcm47xx_machine_restart;
289         _machine_halt = bcm47xx_machine_halt;
290         pm_power_off = bcm47xx_machine_halt;
291  }
292  
293 +static int __init bcm47xx_register_gpiodev(void)
294 +{
295 +       static struct resource res = {
296 +               .start = 0xFFFFFFFF,
297 +       };
298 +       struct platform_device *pdev;
299 +
300 +       pdev = platform_device_register_simple("GPIODEV", 0, &res, 1);
301 +       if (!pdev) {
302 +               printk(KERN_ERR "bcm47xx: GPIODEV init failed\n");
303 +               return -ENODEV;
304 +       }
305 +
306 +       return 0;
307 +}
308 +device_initcall(bcm47xx_register_gpiodev);
309 --- a/arch/mips/bcm47xx/time.c
310 +++ b/arch/mips/bcm47xx/time.c
311 @@ -22,11 +22,17 @@
312   *  675 Mass Ave, Cambridge, MA 02139, USA.
313   */
314  
315 -
316  #include <linux/init.h>
317 +#include <linux/kernel.h>
318 +#include <linux/sched.h>
319 +#include <linux/serial_reg.h>
320 +#include <linux/interrupt.h>
321  #include <linux/ssb/ssb.h>
322 +#include <asm/addrspace.h>
323 +#include <asm/io.h>
324  #include <asm/time.h>
325 -#include <bcm47xx.h>
326 +
327 +extern struct ssb_bus ssb_bcm47xx;
328  
329  void __init plat_time_init(void)
330  {
331 --- a/arch/mips/bcm47xx/nvram.c
332 +++ b/arch/mips/bcm47xx/nvram.c
333 @@ -24,10 +24,10 @@
334  #include <asm/io.h>
335  #include <asm/uaccess.h>
336  
337 -#include <nvram.h>
338 +#include "include/nvram.h"
339  
340  #define MB * 1048576
341 -extern struct ssb_bus ssb;
342 +extern struct ssb_bus ssb_bcm47xx;
343  
344  static char nvram_buf[NVRAM_SPACE];
345  static int cfe_env;
346 @@ -36,7 +36,7 @@ extern char *cfe_env_get(char *nv_buf, c
347  /* Probe for NVRAM header */
348  static void __init early_nvram_init(void)
349  {
350 -       struct ssb_mipscore *mcore = &ssb.mipscore;
351 +       struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
352         struct nvram_header *header;
353         int i;
354         u32 base, lim, off;
355 --- a/arch/mips/bcm47xx/Makefile
356 +++ b/arch/mips/bcm47xx/Makefile
357 @@ -3,4 +3,4 @@
358  # under Linux.
359  #
360  
361 -obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o
362 +obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
363 --- a/arch/mips/Kconfig
364 +++ b/arch/mips/Kconfig
365 @@ -54,6 +54,7 @@ config BCM47XX
366         select SSB_DRIVER_MIPS
367         select SSB_DRIVER_EXTIF
368         select SSB_DRIVER_PCICORE
369 +       select SSB_B43_PCI_BRIDGE
370         select SSB_PCICORE_HOSTMODE if PCI
371         select GENERIC_GPIO
372         select SYS_HAS_EARLY_PRINTK