use boards mac on boards with brn loader, on ifxmips
[oweals/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 <asm/bootinfo.h>
29 #include <asm/reboot.h>
30 #include <asm/time.h>
31 #include <asm/irq.h>
32 #include <asm/io.h>
33 #include <linux/etherdevice.h>
34 #include <asm/ifxmips/ifxmips.h>
35
36 #define MAX_BOARD_NAME_LEN              32
37 #define MAX_IFXMIPS_DEVS                9
38
39 #define SYSTEM_DANUBE                   "Danube"
40 #define SYSTEM_DANUBE_CHIPID1   0x10129083
41 #define SYSTEM_DANUBE_CHIPID2   0x3012B083
42
43 #define SYSTEM_TWINPASS                 "Twinpass"
44 #define SYSTEM_TWINPASS_CHIPID  0x3012D083
45
46 extern int ifxmips_pci_external_clock;
47
48 static unsigned int chiprev;
49 static int cmdline_mac = 0;
50 char board_name[MAX_BOARD_NAME_LEN + 1] = { 0 };
51
52 struct ifxmips_board {
53         char name[32];
54         unsigned int system_type;
55         struct platform_device *devs[MAX_IFXMIPS_DEVS];
56         struct resource reset_resource;
57         struct resource gpiodev_resource;
58         int pci_external_clock;
59         int num_devs;
60 };
61
62 spinlock_t ebu_lock = SPIN_LOCK_UNLOCKED;
63 EXPORT_SYMBOL_GPL(ebu_lock);
64
65 static unsigned char ifxmips_mii_mac[6];
66 static int ifxmips_brn = 0;
67
68 static struct platform_device
69 ifxmips_led =
70 {
71         .id = 0,
72         .name = "ifxmips_led",
73 };
74
75 static struct platform_device
76 ifxmips_gpio =
77 {
78         .id = 0,
79         .name = "ifxmips_gpio",
80         .num_resources = 1,
81 };
82
83 static struct platform_device
84 ifxmips_mii =
85 {
86         .id = 0,
87         .name = "ifxmips_mii0",
88         .dev = {
89                 .platform_data = ifxmips_mii_mac,
90         }
91 };
92
93 static struct platform_device
94 ifxmips_wdt =
95 {
96         .id = 0,
97         .name = "ifxmips_wdt",
98 };
99
100 static struct resource
101 ifxmips_mtd_resource = {
102         .start  = IFXMIPS_FLASH_START,
103         .end    = IFXMIPS_FLASH_START + IFXMIPS_FLASH_MAX - 1,
104         .flags  = IORESOURCE_MEM,
105 };
106
107 static struct platform_device
108 ifxmips_mtd =
109 {
110         .id = 0,
111         .name = "ifxmips_mtd",
112         .num_resources  = 1,
113         .resource   = &ifxmips_mtd_resource,
114 };
115
116 static struct platform_device
117 ifxmips_gpio_dev = {
118         .name     = "GPIODEV",
119         .id     = -1,
120         .num_resources    =     1,
121 };
122
123 const char*
124 get_system_type(void)
125 {
126         chiprev = ifxmips_r32(IFXMIPS_MPS_CHIPID);
127         switch(chiprev)
128         {
129         case SYSTEM_DANUBE_CHIPID1:
130         case SYSTEM_DANUBE_CHIPID2:
131                 return SYSTEM_DANUBE;
132
133         case SYSTEM_TWINPASS_CHIPID:
134                 return SYSTEM_TWINPASS;
135         }
136
137         return BOARD_SYSTEM_TYPE;
138 }
139
140 static int __init
141 ifxmips_set_board_type(char *str)
142 {
143         str = strchr(str, '=');
144         if(!str)
145                 goto out;
146         str++;
147         if(strlen(str) > MAX_BOARD_NAME_LEN)
148                 goto out;
149         strncpy(board_name, str, MAX_BOARD_NAME_LEN);
150         printk("bootloader told us, that this is a %s board\n", board_name);
151 out:
152         return 1;
153 }
154 __setup("ifxmips_board", ifxmips_set_board_type);
155
156 #define IS_HEX(x) \
157         (((x >='0' && x <= '9') || (x >='a' && x <= 'f') || (x >='A' && x <= 'F'))?(1):(0))
158
159 static int __init
160 ifxmips_set_mii0_mac(char *str)
161 {
162         int i;
163         str = strchr(str, '=');
164         if(!str)
165                 goto out;
166         str++;
167         if(strlen(str) != 17)
168                 goto out;
169         for(i = 0; i < 6; i++)
170         {
171                 if(!IS_HEX(str[3 * i]) || !IS_HEX(str[(3 * i) + 1]))
172                         goto out;
173                 if((i != 5) && (str[(3 * i) + 2] != ':'))
174                         goto out;
175                 ifxmips_mii_mac[i] = simple_strtoul(&str[3 * i], NULL, 16);
176         }
177         if(is_valid_ether_addr(ifxmips_mii_mac))
178                 cmdline_mac = 1;
179 out:
180         return 1;
181 }
182 __setup("mii0_mac", ifxmips_set_mii0_mac);
183
184
185 static struct ifxmips_board boards[] =
186 {
187         {
188                 .name = "EASY50712",
189                 .system_type = SYSTEM_DANUBE_CHIPID1,
190                 .devs =
191                 {
192                         &ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
193                         &ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev,
194                 },
195                 .reset_resource =
196                 {
197                         .name = "reset",
198                         .start = 1,
199                         .end = 15,
200                 },
201                 .gpiodev_resource =
202                 {
203                         .name = "gpio",
204                         .start = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) |
205                                         (1 << 4) | (1 << 5) | (1 << 8) | (1 << 9) | (1 << 12),
206                         .end = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) |
207                                         (1 << 4) | (1 << 5) | (1 << 8) | (1 << 9) | (1 << 12),
208                 },
209                 .num_devs = 6,
210         }, {
211                 .name = "EASY4010",
212                 .system_type = SYSTEM_TWINPASS_CHIPID,
213                 .devs =
214                 {
215                         &ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
216                         &ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev,
217                 },
218                 .reset_resource =
219                 {
220                         .name = "reset",
221                         .start = 1,
222                         .end = 15,
223                 },
224                 .gpiodev_resource =
225                 {
226                         .name = "gpio",
227                         .start = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) |
228                                         (1 << 4) | (1 << 5) | (1 << 8) | (1 << 9) | (1 << 12),
229                         .end = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) |
230                                         (1 << 4) | (1 << 5) | (1 << 8) | (1 << 9) | (1 << 12),
231                 },
232                 .num_devs = 6,
233         }, {
234                 .name = "ARV4519",
235                 .system_type = SYSTEM_DANUBE_CHIPID2,
236                 .devs =
237                 {
238                         &ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
239                         &ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev,
240                 },
241                 .reset_resource =
242                 {
243                         .name = "reset",
244                         .start = 1,
245                         .end = 12,
246                 },
247                 .gpiodev_resource =
248                 {
249                         .name = "gpio",
250                         .start = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) |
251                                         (1 << 4) | (1 << 5) | (1 << 8) | (1 << 9) | (1 << 12),
252                         .end = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) |
253                                         (1 << 4) | (1 << 5) | (1 << 8) | (1 << 9) | (1 << 12),
254                 },
255                 .pci_external_clock = 1,
256                 .num_devs = 6,
257         },
258 };
259
260 int
261 ifxmips_find_brn_block(void){
262         unsigned char temp[8];
263         memcpy_fromio(temp, (void*)KSEG1ADDR(IFXMIPS_FLASH_START + 0x800000 - 0x10000), 8);
264         if(memcmp(temp, "BRN-BOOT", 8) == 0)
265         {
266                 if(!cmdline_mac)
267                         memcpy_fromio(ifxmips_mii_mac, (void*)KSEG1ADDR(IFXMIPS_FLASH_START + 0x800000 - 0x10000 + 0x16), 6);
268                 cmdline_mac = 1;
269                 return 1;
270         } else {
271                 return 0;
272         }
273 }
274
275 int
276 ifxmips_has_brn_block(void)
277 {
278         return ifxmips_brn;
279 }
280
281 struct ifxmips_board*
282 ifxmips_find_board(void)
283 {
284         int i;
285         if(!*board_name)
286                 return 0;
287         for(i = 0; i < ARRAY_SIZE(boards); i++)
288                 if((boards[i].system_type == chiprev) && (!strcmp(boards[i].name, board_name)))
289                         return &boards[i];
290         return 0;
291 }
292
293 int __init
294 ifxmips_init_devices(void)
295 {
296         struct ifxmips_board *board = ifxmips_find_board();
297
298         chiprev = ifxmips_r32(IFXMIPS_MPS_CHIPID);
299         ifxmips_brn = ifxmips_find_brn_block();
300
301         if(!cmdline_mac)
302                 random_ether_addr(ifxmips_mii_mac);
303
304         if(!board)
305         {
306                 switch(chiprev)
307                 {
308                 case SYSTEM_DANUBE_CHIPID1:
309                 case SYSTEM_DANUBE_CHIPID2:
310                         board = &boards[0];
311                         break;
312                 case SYSTEM_TWINPASS_CHIPID:
313                         board = &boards[1];
314                         break;
315                 }
316         }
317         ifxmips_gpio.resource = &board->reset_resource;
318         ifxmips_gpio_dev.resource = &board->gpiodev_resource;
319         if(board->pci_external_clock)
320                 ifxmips_pci_external_clock = 1;
321         printk("using board definition %s\n", board->name);
322         return platform_add_devices(board->devs, board->num_devs);
323 }
324
325 arch_initcall(ifxmips_init_devices);