2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
7 * Copyright (C) 2006 FON Technology, SL.
8 * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
9 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
13 * Platform devices for Atheros SoCs
16 #include <linux/autoconf.h>
17 #include <linux/init.h>
18 #include <linux/module.h>
19 #include <linux/types.h>
20 #include <linux/string.h>
21 #include <linux/platform_device.h>
22 #include <linux/kernel.h>
23 #include <linux/serial.h>
24 #include <linux/serial_core.h>
25 #include <linux/random.h>
26 #include <asm/bootinfo.h>
27 #include <asm/irq_cpu.h>
31 char *board_config
= NULL
;
32 char *radio_config
= NULL
;
33 int broken_boarddata
= 0;
35 extern int early_serial_setup(struct uart_port
*port
);
38 check_radio_magic(unsigned char *addr
)
40 addr
+= 0x7a; /* offset for flash magic */
41 if ((addr
[0] == 0x5a) && (addr
[1] == 0xa5)) {
48 check_board_data(unsigned char *flash_limit
, unsigned char *addr
, bool broken
)
50 /* config magic found */
51 if ( *(int *)addr
== 0x35333132)
57 if (check_radio_magic(addr
+ 0xf8))
58 radio_config
= addr
+ 0xf8;
59 if ((addr
< flash_limit
+ 0x10000) &&
60 check_radio_magic(addr
+ 0x10000))
61 radio_config
= addr
+ 0x10000;
64 /* broken board data detected, use radio data to find the offset,
65 * user will fix this */
72 static u8
*find_board_config(char *flash_limit
, bool broken
)
77 for (addr
= (char *) (flash_limit
- 0x1000);
78 addr
>= (char *) (flash_limit
- 0x30000);
81 if (check_board_data(flash_limit
, addr
, broken
)) {
93 static u8
*find_radio_config(char *flash_limit
, char *board_config
)
99 * Now find the start of Radio Configuration data, using heuristics:
100 * Search forward from Board Configuration data by 0x1000 bytes
101 * at a time until we find non-0xffffffff.
104 for (radio_config
= board_config
+ 0x1000;
105 (radio_config
< flash_limit
);
106 radio_config
+= 0x1000) {
107 if ((*(u32
*)radio_config
!= 0xffffffff) &&
108 check_radio_magic(radio_config
)) {
114 #ifdef CONFIG_ATHEROS_AR5315
115 if (!dataFound
) { /* AR2316 relocates radio config to new location */
116 for (radio_config
= board_config
+ 0xf8;
117 (radio_config
< flash_limit
- 0x1000 + 0xf8);
118 radio_config
+= 0x1000) {
119 if ((*(u32
*)radio_config
!= 0xffffffff) &&
120 check_radio_magic(radio_config
)) {
129 printk("Could not find Radio Configuration data\n");
133 return (u8
*) radio_config
;
136 int __init
ar531x_find_config(char *flash_limit
)
138 struct ar531x_boarddata
*bd
;
139 unsigned int rcfg_size
;
142 /* Copy the board and radio data to RAM, because with the new
143 * spiflash driver, accessing the mapped memory directly is no
146 bcfg
= find_board_config(flash_limit
, false);
148 bcfg
= find_board_config(flash_limit
, true);
150 printk("WARNING: No board configuration data found!\n");
154 board_config
= kzalloc(BOARD_CONFIG_BUFSZ
, GFP_KERNEL
);
155 memcpy(board_config
, bcfg
, 0x100);
156 if (broken_boarddata
) {
157 printk("WARNING: broken board data detected\n");
158 bd
= (struct ar531x_boarddata
*)board_config
;
159 if (!memcmp(bd
->enet0Mac
, "\x00\x00\x00\x00\x00\x00", 6)) {
160 printk("Fixing up empty mac addresses\n");
161 bd
->enet0Mac
[1] = 0x13;
162 bd
->enet0Mac
[2] = 0x37;
163 get_random_bytes(bd
->enet0Mac
+ 3, 3);
164 bd
->wlan0Mac
[1] = 0x13;
165 bd
->wlan0Mac
[2] = 0x37;
166 get_random_bytes(bd
->wlan0Mac
+ 3, 3);
171 /* Radio config starts 0x100 bytes after board config, regardless
172 * of what the physical layout on the flash chip looks like */
177 rcfg
= find_radio_config(flash_limit
, bcfg
);
182 radio_config
= board_config
+ 0x100 + ((rcfg
- bcfg
) & 0xfff);
183 printk("Radio config found at offset 0x%x(0x%x)\n", rcfg
- bcfg
, radio_config
- board_config
);
184 rcfg_size
= BOARD_CONFIG_BUFSZ
- (radio_config
- board_config
);
185 memcpy(radio_config
, rcfg
, rcfg_size
);
190 void __init
serial_setup(unsigned long mapbase
, unsigned int uartclk
)
194 memset(&s
, 0, sizeof(s
));
196 s
.flags
= UPF_BOOT_AUTOCONF
| UPF_SKIP_TEST
;
198 s
.irq
= AR531X_MISC_IRQ_UART0
;
202 s
.membase
= (void __iomem
*)s
.mapbase
;
204 early_serial_setup(&s
);
207 void __init
plat_mem_setup(void)
209 DO_AR5312(ar5312_plat_setup();)
210 DO_AR5315(ar5315_plat_setup();)
212 /* Disable data watchpoints */
213 write_c0_watchlo0(0);
216 const char *get_system_type(void)
218 switch (mips_machtype
) {
219 #ifdef CONFIG_ATHEROS_AR5312
220 case MACH_ATHEROS_AR5312
:
221 return "Atheros AR5312";
223 case MACH_ATHEROS_AR2312
:
224 return "Atheros AR2312";
226 case MACH_ATHEROS_AR2313
:
227 return "Atheros AR2313";
229 #ifdef CONFIG_ATHEROS_AR5315
230 case MACH_ATHEROS_AR2315
:
231 return "Atheros AR2315";
232 case MACH_ATHEROS_AR2316
:
233 return "Atheros AR2316";
234 case MACH_ATHEROS_AR2317
:
235 return "Atheros AR2317";
236 case MACH_ATHEROS_AR2318
:
237 return "Atheros AR2318";
240 return "Atheros (unknown)";
243 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
244 void __init
plat_timer_setup(struct irqaction
*irq
)
248 /* Usually irq is timer_irqaction (timer_interrupt) */
249 setup_irq(AR531X_IRQ_CPU_CLOCK
, irq
);
251 /* to generate the first CPU timer interrupt */
252 count
= read_c0_count();
253 write_c0_compare(count
+ 1000);
257 asmlinkage
void plat_irq_dispatch(void)
259 DO_AR5312(ar5312_irq_dispatch();)
260 DO_AR5315(ar5315_irq_dispatch();)
263 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
264 void (*board_time_init
)(void);
265 void __init
plat_time_init(void) {
270 void __init
arch_init_irq(void)
272 clear_c0_status(ST0_IM
);
275 /* Initialize interrupt controllers */
276 DO_AR5312(ar5312_misc_intr_init(AR531X_MISC_IRQ_BASE
);)
277 DO_AR5315(ar5315_misc_intr_init(AR531X_MISC_IRQ_BASE
);)
280 static int __init
ar531x_register_gpiodev(void)
282 static struct resource res
= {
285 struct platform_device
*pdev
;
287 printk(KERN_INFO
"ar531x: Registering GPIODEV device\n");
289 pdev
= platform_device_register_simple("GPIODEV", 0, &res
, 1);
292 printk(KERN_ERR
"ar531x: GPIODEV init failed\n");
299 device_initcall(ar531x_register_gpiodev
);
This page took 0.062266 seconds and 5 git commands to generate.