clean up board config
[10.03/openwrt.git] / target / linux / ifxmips / files / arch / mips / ifxmips / board.c
1 /*
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.
6  *
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.
11  *
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.
15  *
16  *   Copyright (C) 2007 John Crispin <blogic@openwrt.org> 
17  */
18
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 <asm/bootinfo.h>
31 #include <asm/reboot.h>
32 #include <asm/time.h>
33 #include <asm/irq.h>
34 #include <asm/io.h>
35 #include <asm/gpio.h>
36 #include <asm/ifxmips/ifxmips.h>
37
38 #define MAX_BOARD_NAME_LEN              32
39 #define MAX_IFXMIPS_DEVS                9
40
41 #define SYSTEM_DANUBE                   "Danube"
42 #define SYSTEM_DANUBE_CHIPID1   0x10129083
43 #define SYSTEM_DANUBE_CHIPID2   0x3012B083
44
45 #define SYSTEM_TWINPASS                 "Twinpass"
46 #define SYSTEM_TWINPASS_CHIPID  0x3012D083
47
48 enum {
49         EASY50712,
50         EASY4010,
51         ARV4519,
52 };
53
54 extern int ifxmips_pci_external_clock;
55
56 static unsigned int chiprev;
57 static int cmdline_mac = 0;
58 char board_name[MAX_BOARD_NAME_LEN + 1] = { 0 };
59
60 struct ifxmips_board {
61         int type;
62         char name[32];
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;
70         int num_devs;
71 };
72
73 spinlock_t ebu_lock = SPIN_LOCK_UNLOCKED;
74 EXPORT_SYMBOL_GPL(ebu_lock);
75
76 static unsigned char ifxmips_mii_mac[6];
77 static int ifxmips_brn = 0;
78
79 static struct gpio_led_platform_data ifxmips_led_data;
80
81 static struct platform_device
82 ifxmips_led =
83 {
84         .id = 0,
85         .name = "ifxmips_led",
86         .dev = {
87                 .platform_data = (void *) &ifxmips_led_data,
88         }
89 };
90
91 static struct platform_device
92 ifxmips_gpio =
93 {
94         .id = 0,
95         .name = "ifxmips_gpio",
96         .num_resources = 1,
97 };
98
99 static struct platform_device
100 ifxmips_mii =
101 {
102         .id = 0,
103         .name = "ifxmips_mii0",
104         .dev = {
105                 .platform_data = ifxmips_mii_mac,
106         }
107 };
108
109 static struct platform_device
110 ifxmips_wdt =
111 {
112         .id = 0,
113         .name = "ifxmips_wdt",
114 };
115
116 static struct resource
117 ifxmips_mtd_resource = {
118         .start  = IFXMIPS_FLASH_START,
119         .end    = IFXMIPS_FLASH_START + IFXMIPS_FLASH_MAX - 1,
120         .flags  = IORESOURCE_MEM,
121 };
122
123 static struct platform_device
124 ifxmips_mtd =
125 {
126         .id = 0,
127         .name = "ifxmips_mtd",
128         .num_resources  = 1,
129         .resource   = &ifxmips_mtd_resource,
130 };
131
132 static struct platform_device
133 ifxmips_gpio_dev = {
134         .name     = "GPIODEV",
135         .id     = -1,
136         .num_resources    =     1,
137 };
138
139 #ifdef CONFIG_LEDS_GPIO
140 static struct gpio_led arv4519_gpio_leds[] = {
141         { .name = "ifx:green:power", .gpio = 3, .active_low = 1, },
142         { .name = "ifx:red:power", .gpio = 7, .active_low = 1, },
143         { .name = "ifx:green:adsl", .gpio = 4, .active_low = 1, },
144         { .name = "ifx:green:internet", .gpio = 5, .active_low = 1, },
145         { .name = "ifx:red:internet", .gpio = 8, .active_low = 1, },
146         { .name = "ifx:green:wlan", .gpio = 6, .active_low = 1, },
147         { .name = "ifx:green:usb", .gpio = 19, .active_low = 1, },
148 };
149
150 static struct gpio_led_platform_data ifxmips_gpio_led_data;
151
152 static struct platform_device ifxmips_gpio_leds = {
153         .name = "leds-gpio",
154         .id = -1,
155         .dev = {
156                 .platform_data = (void *) &ifxmips_gpio_led_data,
157          }
158 };
159 #endif
160
161 struct platform_device *easy50712_devs[] = {
162         &ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
163         &ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev
164 };
165
166 struct platform_device *easy4010_devs[] = {
167         &ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
168         &ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev
169 };
170
171 struct platform_device *arv5419_devs[] = {
172         &ifxmips_gpio, &ifxmips_mii, &ifxmips_mtd, &ifxmips_wdt,
173 #ifdef CONFIG_LEDS_GPIO
174         &ifxmips_gpio_leds,
175 #endif
176 };
177
178 static struct gpio_led easy50712_leds[] = {
179         { .name = "ifx:green:test0", .gpio = 0,},
180         { .name = "ifx:green:test1", .gpio = 1,},
181         { .name = "ifx:green:test2", .gpio = 2,},
182         { .name = "ifx:green:test3", .gpio = 3,},
183 };
184
185 static struct gpio_led easy4010_leds[] = {
186         { .name = "ifx:green:test0", .gpio = 0,},
187         { .name = "ifx:green:test1", .gpio = 1,},
188         { .name = "ifx:green:test2", .gpio = 2,},
189         { .name = "ifx:green:test3", .gpio = 3,},
190 };
191
192 static struct ifxmips_board boards[] =
193 {
194         {
195                 .type = EASY50712,
196                 .name = "EASY50712",
197                 .system_type = SYSTEM_DANUBE_CHIPID1,
198                 .devs = easy50712_devs,
199                 .reset_resource = {.name = "reset", .start = 1, .end = 15,},
200                 .gpiodev_resource =     {.name = "gpio", .start = (1 << 0) | (1 << 1),
201                         .end = (1 << 0) | (1 << 1)},
202                 .ifxmips_leds = easy50712_leds,
203         }, {
204                 .type = EASY4010,
205                 .name = "EASY4010",
206                 .system_type = SYSTEM_TWINPASS_CHIPID,
207                 .devs = easy4010_devs,
208                 .reset_resource = {.name = "reset", .start = 1, .end = 15},
209                 .gpiodev_resource =     {.name = "gpio", .start = (1 << 0) | (1 << 1),
210                         .end = (1 << 0) | (1 << 1)},
211                 .ifxmips_leds = easy4010_leds,
212         }, {
213                 .type = ARV4519,
214                 .name = "ARV4519",
215                 .system_type = SYSTEM_DANUBE_CHIPID2,
216                 .devs = arv5419_devs,
217                 .reset_resource = {.name = "reset", .start = 1, .end = 14},
218                 .pci_external_clock = 1,
219                 .gpio_leds = arv4519_gpio_leds,
220         },
221 };
222
223 const char*
224 get_system_type(void)
225 {
226         chiprev = ifxmips_r32(IFXMIPS_MPS_CHIPID);
227         switch(chiprev)
228         {
229         case SYSTEM_DANUBE_CHIPID1:
230         case SYSTEM_DANUBE_CHIPID2:
231                 return SYSTEM_DANUBE;
232
233         case SYSTEM_TWINPASS_CHIPID:
234                 return SYSTEM_TWINPASS;
235         }
236
237         return BOARD_SYSTEM_TYPE;
238 }
239
240 static int __init
241 ifxmips_set_board_type(char *str)
242 {
243         str = strchr(str, '=');
244         if(!str)
245                 goto out;
246         str++;
247         if(strlen(str) > MAX_BOARD_NAME_LEN)
248                 goto out;
249         strncpy(board_name, str, MAX_BOARD_NAME_LEN);
250         printk("bootloader told us, that this is a %s board\n", board_name);
251 out:
252         return 1;
253 }
254 __setup("ifxmips_board", ifxmips_set_board_type);
255
256 static int __init
257 ifxmips_set_mii0_mac(char *str)
258 {
259 #define IS_HEX(x) \
260         (((x >='0' && x <= '9') || (x >='a' && x <= 'f') || (x >='A' && x <= 'F'))?(1):(0))
261         int i;
262         str = strchr(str, '=');
263         if(!str)
264                 goto out;
265         str++;
266         if(strlen(str) != 17)
267                 goto out;
268         for(i = 0; i < 6; i++)
269         {
270                 if(!IS_HEX(str[3 * i]) || !IS_HEX(str[(3 * i) + 1]))
271                         goto out;
272                 if((i != 5) && (str[(3 * i) + 2] != ':'))
273                         goto out;
274                 ifxmips_mii_mac[i] = simple_strtoul(&str[3 * i], NULL, 16);
275         }
276         if(is_valid_ether_addr(ifxmips_mii_mac))
277                 cmdline_mac = 1;
278 out:
279         return 1;
280 }
281 __setup("mii0_mac", ifxmips_set_mii0_mac);
282
283 int
284 ifxmips_find_brn_block(void){
285         unsigned char temp[8];
286         memcpy_fromio(temp, (void*)KSEG1ADDR(IFXMIPS_FLASH_START + 0x800000 - 0x10000), 8);
287         if(memcmp(temp, "BRN-BOOT", 8) == 0)
288         {
289                 if(!cmdline_mac)
290                         memcpy_fromio(ifxmips_mii_mac, (void*)KSEG1ADDR(IFXMIPS_FLASH_START + 0x800000 - 0x10000 + 0x16), 6);
291                 cmdline_mac = 1;
292                 return 1;
293         } else {
294                 return 0;
295         }
296 }
297
298 int
299 ifxmips_has_brn_block(void)
300 {
301         return ifxmips_brn;
302 }
303 EXPORT_SYMBOL(ifxmips_has_brn_block);
304
305 struct ifxmips_board*
306 ifxmips_find_board(void)
307 {
308         int i;
309         if(!*board_name)
310                 return 0;
311         for(i = 0; i < ARRAY_SIZE(boards); i++)
312                 if((boards[i].system_type == chiprev) && (!strcmp(boards[i].name, board_name)))
313                         return &boards[i];
314         return 0;
315 }
316
317 int __init
318 ifxmips_init_devices(void)
319 {
320         struct ifxmips_board *board = ifxmips_find_board();
321
322         chiprev = ifxmips_r32(IFXMIPS_MPS_CHIPID);
323         ifxmips_brn = ifxmips_find_brn_block();
324
325         if(!cmdline_mac)
326                 random_ether_addr(ifxmips_mii_mac);
327
328         if(!board)
329         {
330                 switch(chiprev)
331                 {
332                 case SYSTEM_DANUBE_CHIPID1:
333                 case SYSTEM_DANUBE_CHIPID2:
334                         board = &boards[0];
335                         break;
336                 case SYSTEM_TWINPASS_CHIPID:
337                         board = &boards[1];
338                         break;
339                 }
340         }
341
342         switch(board->type)
343         {
344         case EASY50712:
345                 board->num_devs = ARRAY_SIZE(easy50712_devs);
346                 ifxmips_led_data.num_leds = ARRAY_SIZE(easy50712_leds);
347                 break;
348         case EASY4010:
349                 board->num_devs = ARRAY_SIZE(easy4010_devs);
350                 ifxmips_led_data.num_leds = ARRAY_SIZE(easy4010_leds);
351                 break;
352         case ARV4519:
353                 gpio_set_value(3, 0);
354                 gpio_set_value(4, 0);
355                 gpio_set_value(5, 0);
356                 gpio_set_value(6, 0);
357                 gpio_set_value(7, 1);
358                 gpio_set_value(8, 1);
359                 gpio_set_value(19, 0);
360                 board->num_devs = ARRAY_SIZE(arv5419_devs);
361 #ifdef CONFIG_LEDS_GPIO
362                 ifxmips_gpio_led_data.num_leds = ARRAY_SIZE(arv4519_gpio_leds);
363 #endif
364                 break;
365         }
366 #ifdef CONFIG_LEDS_GPIO
367         ifxmips_gpio_led_data.leds = board->gpio_leds;
368 #endif
369         ifxmips_led_data.leds = board->ifxmips_leds;
370
371         printk("%s:%s[%d]adding %d devs\n", __FILE__, __func__, __LINE__, board->num_devs);
372
373         ifxmips_gpio.resource = &board->reset_resource;
374         ifxmips_gpio_dev.resource = &board->gpiodev_resource;
375         if(board->pci_external_clock)
376                 ifxmips_pci_external_clock = 1;
377         printk("using board definition %s\n", board->name);
378         return platform_add_devices(board->devs, board->num_devs);
379 }
380
381 arch_initcall(ifxmips_init_devices);