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