2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
16 * Copyright (C) 2007 John Crispin <blogic@openwrt.org>
19 #include <linux/autoconf.h>
20 #include <linux/init.h>
21 #include <linux/module.h>
22 #include <linux/types.h>
23 #include <linux/string.h>
24 #include <linux/mtd/physmap.h>
25 #include <linux/kernel.h>
26 #include <linux/reboot.h>
27 #include <linux/platform_device.h>
28 #include <linux/leds.h>
29 #include <linux/etherdevice.h>
30 #include <linux/reboot.h>
31 #include <linux/time.h>
33 #include <linux/gpio.h>
34 #include <asm/bootinfo.h>
36 #include <asm/ifxmips/ifxmips.h>
38 #define MAX_BOARD_NAME_LEN 32
39 #define MAX_IFXMIPS_DEVS 9
41 #define SYSTEM_DANUBE "Danube"
42 #define SYSTEM_DANUBE_CHIPID1 0x00129083
43 #define SYSTEM_DANUBE_CHIPID2 0x0012B083
45 #define SYSTEM_TWINPASS "Twinpass"
46 #define SYSTEM_TWINPASS_CHIPID 0x0012D083
54 extern int ifxmips_pci_external_clock;
56 static unsigned int chiprev;
57 static int cmdline_mac;
58 char board_name[MAX_BOARD_NAME_LEN + 1] = { 0 };
60 struct ifxmips_board {
63 unsigned int system_type;
64 struct platform_device **devs;
65 struct resource reset_resource;
66 struct resource gpiodev_resource;
67 struct gpio_led *ifxmips_leds;
68 struct gpio_led *gpio_leds;
69 int pci_external_clock;
73 DEFINE_SPINLOCK(ebu_lock);
74 EXPORT_SYMBOL_GPL(ebu_lock);
76 static unsigned char ifxmips_ethaddr[6];
77 static int ifxmips_brn;
79 static struct gpio_led_platform_data ifxmips_led_data;
81 static struct platform_device ifxmips_led = {
83 .name = "ifxmips_led",
85 .platform_data = (void *) &ifxmips_led_data,
89 static struct platform_device ifxmips_gpio = {
91 .name = "ifxmips_gpio",
95 static struct platform_device ifxmips_mii = {
97 .name = "ifxmips_mii0",
99 .platform_data = ifxmips_ethaddr,
103 static struct platform_device ifxmips_wdt = {
105 .name = "ifxmips_wdt",
108 static struct resource ifxmips_mtd_resource = {
109 .start = IFXMIPS_FLASH_START,
110 .end = IFXMIPS_FLASH_START + IFXMIPS_FLASH_MAX - 1,
111 .flags = IORESOURCE_MEM,
114 static struct platform_device ifxmips_mtd = {
116 .name = "ifxmips_mtd",
118 .resource = &ifxmips_mtd_resource,
121 static struct platform_device ifxmips_gpio_dev = {
127 #ifdef CONFIG_LEDS_GPIO
128 static struct gpio_led arv4519_gpio_leds[] = {
129 { .name = "ifx:green:power", .gpio = 3, .active_low = 1, },
130 { .name = "ifx:red:power", .gpio = 7, .active_low = 1, },
131 { .name = "ifx:green:adsl", .gpio = 4, .active_low = 1, },
132 { .name = "ifx:green:internet", .gpio = 5, .active_low = 1, },
133 { .name = "ifx:red:internet", .gpio = 8, .active_low = 1, },
134 { .name = "ifx:green:wlan", .gpio = 6, .active_low = 1, },
135 { .name = "ifx:green:usb", .gpio = 19, .active_low = 1, },
138 static struct gpio_led_platform_data ifxmips_gpio_led_data;
140 static struct platform_device ifxmips_gpio_leds = {
144 .platform_data = (void *) &ifxmips_gpio_led_data,
149 struct platform_device *easy50712_devs[] = {
150 &ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
151 &ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev
154 struct platform_device *easy4010_devs[] = {
155 &ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
156 &ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev
159 struct platform_device *arv5419_devs[] = {
160 &ifxmips_gpio, &ifxmips_mii, &ifxmips_mtd, &ifxmips_wdt,
161 #ifdef CONFIG_LEDS_GPIO
166 static struct gpio_led easy50712_leds[] = {
167 { .name = "ifx:green:test0", .gpio = 0,},
168 { .name = "ifx:green:test1", .gpio = 1,},
169 { .name = "ifx:green:test2", .gpio = 2,},
170 { .name = "ifx:green:test3", .gpio = 3,},
173 static struct gpio_led easy4010_leds[] = {
174 { .name = "ifx:green:test0", .gpio = 0,},
175 { .name = "ifx:green:test1", .gpio = 1,},
176 { .name = "ifx:green:test2", .gpio = 2,},
177 { .name = "ifx:green:test3", .gpio = 3,},
180 static struct ifxmips_board boards[] = {
184 .system_type = SYSTEM_DANUBE_CHIPID1,
185 .devs = easy50712_devs,
186 .reset_resource = {.name = "reset", .start = 1, .end = 15,},
187 .gpiodev_resource = { .name = "gpio",
188 .start = (1 << 0) | (1 << 1),
189 .end = (1 << 0) | (1 << 1)},
190 .ifxmips_leds = easy50712_leds,
194 .system_type = SYSTEM_TWINPASS_CHIPID,
195 .devs = easy4010_devs,
196 .reset_resource = {.name = "reset", .start = 1, .end = 15},
197 .gpiodev_resource = { .name = "gpio",
198 .start = (1 << 0) | (1 << 1),
199 .end = (1 << 0) | (1 << 1)},
200 .ifxmips_leds = easy4010_leds,
204 .system_type = SYSTEM_DANUBE_CHIPID2,
205 .devs = arv5419_devs,
206 .reset_resource = {.name = "reset", .start = 1, .end = 14},
207 .pci_external_clock = 1,
208 .gpio_leds = arv4519_gpio_leds,
212 const char *get_system_type(void)
214 chiprev = (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0x0FFFFFFF);
217 case SYSTEM_DANUBE_CHIPID1:
218 case SYSTEM_DANUBE_CHIPID2:
219 return SYSTEM_DANUBE;
221 case SYSTEM_TWINPASS_CHIPID:
222 return SYSTEM_TWINPASS;
225 return BOARD_SYSTEM_TYPE;
228 static int __init ifxmips_set_board_type(char *str)
230 str = strchr(str, '=');
234 if (strlen(str) > MAX_BOARD_NAME_LEN)
236 strncpy(board_name, str, MAX_BOARD_NAME_LEN);
237 printk(KERN_INFO "bootloader told us, that this is a %s board\n",
242 __setup("ifxmips_board", ifxmips_set_board_type);
244 static int __init ifxmips_set_ethaddr(char *str)
247 (((x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') \
248 || (x >= 'A' && x <= 'F')) ? (1) : (0))
250 str = strchr(str, '=');
254 if (strlen(str) != 17)
256 for (i = 0; i < 6; i++) {
257 if (!IS_HEX(str[3 * i]) || !IS_HEX(str[(3 * i) + 1]))
259 if ((i != 5) && (str[(3 * i) + 2] != ':'))
261 ifxmips_ethaddr[i] = simple_strtoul(&str[3 * i], NULL, 16);
263 if (is_valid_ether_addr(ifxmips_ethaddr))
268 __setup("ethaddr", ifxmips_set_ethaddr);
270 int ifxmips_find_brn_block(void)
272 unsigned char temp[8];
274 (void *)KSEG1ADDR(IFXMIPS_FLASH_START + 0x800000 - 0x10000), 8);
275 if (memcmp(temp, "BRN-BOOT", 8) == 0) {
277 memcpy_fromio(ifxmips_ethaddr,
278 (void *)KSEG1ADDR(IFXMIPS_FLASH_START +
279 0x800000 - 0x10000 + 0x16), 6);
280 if (is_valid_ether_addr(ifxmips_ethaddr))
288 int ifxmips_has_brn_block(void)
292 EXPORT_SYMBOL(ifxmips_has_brn_block);
294 struct ifxmips_board *ifxmips_find_board(void)
299 for (i = 0; i < ARRAY_SIZE(boards); i++)
300 if ((boards[i].system_type == chiprev) &&
301 (!strcmp(boards[i].name, board_name)))
306 int __init ifxmips_init_devices(void)
308 struct ifxmips_board *board = ifxmips_find_board();
310 chiprev = (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0x0FFFFFFF);
311 ifxmips_brn = ifxmips_find_brn_block();
314 random_ether_addr(ifxmips_ethaddr);
318 case SYSTEM_DANUBE_CHIPID1:
319 case SYSTEM_DANUBE_CHIPID2:
323 case SYSTEM_TWINPASS_CHIPID:
329 switch (board->type) {
331 board->num_devs = ARRAY_SIZE(easy50712_devs);
332 ifxmips_led_data.num_leds = ARRAY_SIZE(easy50712_leds);
335 board->num_devs = ARRAY_SIZE(easy4010_devs);
336 ifxmips_led_data.num_leds = ARRAY_SIZE(easy4010_leds);
339 gpio_set_value(3, 0);
340 gpio_set_value(4, 0);
341 gpio_set_value(5, 0);
342 gpio_set_value(6, 0);
343 gpio_set_value(7, 1);
344 gpio_set_value(8, 1);
345 gpio_set_value(19, 0);
346 board->num_devs = ARRAY_SIZE(arv5419_devs);
347 #ifdef CONFIG_LEDS_GPIO
348 ifxmips_gpio_led_data.num_leds = ARRAY_SIZE(arv4519_gpio_leds);
352 #ifdef CONFIG_LEDS_GPIO
353 ifxmips_gpio_led_data.leds = board->gpio_leds;
355 ifxmips_led_data.leds = board->ifxmips_leds;
357 printk(KERN_INFO "%s: adding %d devs\n",
358 __func__, board->num_devs);
360 ifxmips_gpio.resource = &board->reset_resource;
361 ifxmips_gpio_dev.resource = &board->gpiodev_resource;
362 if (board->pci_external_clock)
363 ifxmips_pci_external_clock = 1;
364 printk(KERN_INFO "using board definition %s\n", board->name);
365 return platform_add_devices(board->devs, board->num_devs);
368 arch_initcall(ifxmips_init_devices);