[ifxmips] cleanup sources and prepare for 2.6.27
[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 <linux/reboot.h>
31 #include <linux/time.h>
32 #include <linux/io.h>
33 #include <linux/gpio.h>
34 #include <asm/bootinfo.h>
35 #include <asm/irq.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   0x00129083
43 #define SYSTEM_DANUBE_CHIPID2   0x0012B083
44
45 #define SYSTEM_TWINPASS                 "Twinpass"
46 #define SYSTEM_TWINPASS_CHIPID  0x0012D083
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;
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 DEFINE_SPINLOCK(ebu_lock);
74 EXPORT_SYMBOL_GPL(ebu_lock);
75
76 static unsigned char ifxmips_ethaddr[6];
77 static int ifxmips_brn;
78
79 static struct gpio_led_platform_data ifxmips_led_data;
80
81 static struct platform_device ifxmips_led = {
82         .id = 0,
83         .name = "ifxmips_led",
84         .dev = {
85                 .platform_data = (void *) &ifxmips_led_data,
86         }
87 };
88
89 static struct platform_device ifxmips_gpio = {
90         .id = 0,
91         .name = "ifxmips_gpio",
92         .num_resources = 1,
93 };
94
95 static struct platform_device ifxmips_mii = {
96         .id = 0,
97         .name = "ifxmips_mii0",
98         .dev = {
99                 .platform_data = ifxmips_ethaddr,
100         }
101 };
102
103 static struct platform_device ifxmips_wdt = {
104         .id = 0,
105         .name = "ifxmips_wdt",
106 };
107
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,
112 };
113
114 static struct platform_device ifxmips_mtd = {
115         .id = 0,
116         .name = "ifxmips_mtd",
117         .num_resources  = 1,
118         .resource   = &ifxmips_mtd_resource,
119 };
120
121 static struct platform_device ifxmips_gpio_dev = {
122         .name     = "GPIODEV",
123         .id     = -1,
124         .num_resources    =     1,
125 };
126
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, },
136 };
137
138 static struct gpio_led_platform_data ifxmips_gpio_led_data;
139
140 static struct platform_device ifxmips_gpio_leds = {
141         .name = "leds-gpio",
142         .id = -1,
143         .dev = {
144                 .platform_data = (void *) &ifxmips_gpio_led_data,
145         }
146 };
147 #endif
148
149 struct platform_device *easy50712_devs[] = {
150         &ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
151         &ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev
152 };
153
154 struct platform_device *easy4010_devs[] = {
155         &ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
156         &ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev
157 };
158
159 struct platform_device *arv5419_devs[] = {
160         &ifxmips_gpio, &ifxmips_mii, &ifxmips_mtd, &ifxmips_wdt,
161 #ifdef CONFIG_LEDS_GPIO
162         &ifxmips_gpio_leds,
163 #endif
164 };
165
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,},
171 };
172
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,},
178 };
179
180 static struct ifxmips_board boards[] = {
181         {
182                 .type = EASY50712,
183                 .name = "EASY50712",
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,
191         }, {
192                 .type = EASY4010,
193                 .name = "EASY4010",
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,
201         }, {
202                 .type = ARV4519,
203                 .name = "ARV4519",
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,
209         },
210 };
211
212 const char *get_system_type(void)
213 {
214         chiprev = (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0x0FFFFFFF);
215
216         switch (chiprev) {
217         case SYSTEM_DANUBE_CHIPID1:
218         case SYSTEM_DANUBE_CHIPID2:
219                 return SYSTEM_DANUBE;
220
221         case SYSTEM_TWINPASS_CHIPID:
222                 return SYSTEM_TWINPASS;
223         }
224
225         return BOARD_SYSTEM_TYPE;
226 }
227
228 static int __init ifxmips_set_board_type(char *str)
229 {
230         str = strchr(str, '=');
231         if (!str)
232                 goto out;
233         str++;
234         if (strlen(str) > MAX_BOARD_NAME_LEN)
235                 goto out;
236         strncpy(board_name, str, MAX_BOARD_NAME_LEN);
237         printk(KERN_INFO "bootloader told us, that this is a %s board\n",
238                 board_name);
239 out:
240         return 1;
241 }
242 __setup("ifxmips_board", ifxmips_set_board_type);
243
244 static int __init ifxmips_set_ethaddr(char *str)
245 {
246 #define IS_HEX(x) \
247         (((x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') \
248                 || (x >= 'A' && x <= 'F')) ? (1) : (0))
249         int i;
250         str = strchr(str, '=');
251         if (!str)
252                 goto out;
253         str++;
254         if (strlen(str) != 17)
255                 goto out;
256         for (i = 0; i < 6; i++) {
257                 if (!IS_HEX(str[3 * i]) || !IS_HEX(str[(3 * i) + 1]))
258                         goto out;
259                 if ((i != 5) && (str[(3 * i) + 2] != ':'))
260                         goto out;
261                 ifxmips_ethaddr[i] = simple_strtoul(&str[3 * i], NULL, 16);
262         }
263         if (is_valid_ether_addr(ifxmips_ethaddr))
264                 cmdline_mac = 1;
265 out:
266         return 1;
267 }
268 __setup("ethaddr", ifxmips_set_ethaddr);
269
270 int ifxmips_find_brn_block(void)
271 {
272         unsigned char temp[8];
273         memcpy_fromio(temp,
274                 (void *)KSEG1ADDR(IFXMIPS_FLASH_START + 0x800000 - 0x10000), 8);
275         if (memcmp(temp, "BRN-BOOT", 8) == 0) {
276                 if (!cmdline_mac)
277                         memcpy_fromio(ifxmips_ethaddr,
278                                 (void *)KSEG1ADDR(IFXMIPS_FLASH_START +
279                                         0x800000 - 0x10000 + 0x16), 6);
280                 if (is_valid_ether_addr(ifxmips_ethaddr))
281                         cmdline_mac = 1;
282                 return 1;
283         } else {
284                 return 0;
285         }
286 }
287
288 int ifxmips_has_brn_block(void)
289 {
290         return ifxmips_brn;
291 }
292 EXPORT_SYMBOL(ifxmips_has_brn_block);
293
294 struct ifxmips_board *ifxmips_find_board(void)
295 {
296         int i;
297         if (!*board_name)
298                 return 0;
299         for (i = 0; i < ARRAY_SIZE(boards); i++)
300                 if ((boards[i].system_type == chiprev) &&
301                     (!strcmp(boards[i].name, board_name)))
302                         return &boards[i];
303         return 0;
304 }
305
306 int __init ifxmips_init_devices(void)
307 {
308         struct ifxmips_board *board = ifxmips_find_board();
309
310         chiprev = (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0x0FFFFFFF);
311         ifxmips_brn = ifxmips_find_brn_block();
312
313         if (!cmdline_mac)
314                 random_ether_addr(ifxmips_ethaddr);
315
316         if (!board) {
317                 switch (chiprev) {
318                 case SYSTEM_DANUBE_CHIPID1:
319                 case SYSTEM_DANUBE_CHIPID2:
320                 default:
321                         board = &boards[0];
322                         break;
323                 case SYSTEM_TWINPASS_CHIPID:
324                         board = &boards[1];
325                         break;
326                 }
327         }
328
329         switch (board->type) {
330         case EASY50712:
331                 board->num_devs = ARRAY_SIZE(easy50712_devs);
332                 ifxmips_led_data.num_leds = ARRAY_SIZE(easy50712_leds);
333                 break;
334         case EASY4010:
335                 board->num_devs = ARRAY_SIZE(easy4010_devs);
336                 ifxmips_led_data.num_leds = ARRAY_SIZE(easy4010_leds);
337                 break;
338         case ARV4519:
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);
349 #endif
350                 break;
351         }
352 #ifdef CONFIG_LEDS_GPIO
353         ifxmips_gpio_led_data.leds = board->gpio_leds;
354 #endif
355         ifxmips_led_data.leds = board->ifxmips_leds;
356
357         printk(KERN_INFO "%s: adding %d devs\n",
358                 __func__, board->num_devs);
359
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);
366 }
367
368 arch_initcall(ifxmips_init_devices);