ar71xx: add ethernet initialization for the AR933X SoCs
[openwrt/svn-archive/archive.git] / target / linux / ar71xx / files / arch / mips / ar71xx / devices.c
1 /*
2 * Atheros AR71xx SoC platform devices
3 *
4 * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
5 * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
6 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
7 *
8 * Parts of this file are based on Atheros 2.6.15 BSP
9 * Parts of this file are based on Atheros 2.6.31 BSP
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 as published
13 * by the Free Software Foundation.
14 */
15
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/delay.h>
19 #include <linux/etherdevice.h>
20 #include <linux/platform_device.h>
21 #include <linux/serial_8250.h>
22
23 #include <asm/mach-ar71xx/ar71xx.h>
24
25 #include "devices.h"
26
27 unsigned char ar71xx_mac_base[ETH_ALEN] __initdata;
28
29 static struct resource ar71xx_uart_resources[] = {
30 {
31 .start = AR71XX_UART_BASE,
32 .end = AR71XX_UART_BASE + AR71XX_UART_SIZE - 1,
33 .flags = IORESOURCE_MEM,
34 },
35 };
36
37 #define AR71XX_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
38 static struct plat_serial8250_port ar71xx_uart_data[] = {
39 {
40 .mapbase = AR71XX_UART_BASE,
41 .irq = AR71XX_MISC_IRQ_UART,
42 .flags = AR71XX_UART_FLAGS,
43 .iotype = UPIO_MEM32,
44 .regshift = 2,
45 }, {
46 /* terminating entry */
47 }
48 };
49
50 static struct platform_device ar71xx_uart_device = {
51 .name = "serial8250",
52 .id = PLAT8250_DEV_PLATFORM,
53 .resource = ar71xx_uart_resources,
54 .num_resources = ARRAY_SIZE(ar71xx_uart_resources),
55 .dev = {
56 .platform_data = ar71xx_uart_data
57 },
58 };
59
60 void __init ar71xx_add_device_uart(void)
61 {
62 switch (ar71xx_soc) {
63 case AR71XX_SOC_AR7130:
64 case AR71XX_SOC_AR7141:
65 case AR71XX_SOC_AR7161:
66 case AR71XX_SOC_AR7240:
67 case AR71XX_SOC_AR7241:
68 case AR71XX_SOC_AR7242:
69 case AR71XX_SOC_AR9130:
70 case AR71XX_SOC_AR9132:
71 ar71xx_uart_data[0].uartclk = ar71xx_ahb_freq;
72 break;
73
74 case AR71XX_SOC_AR9330:
75 case AR71XX_SOC_AR9331:
76 /* These SoCs are using a different UART core */
77 return;
78
79 case AR71XX_SOC_AR9341:
80 case AR71XX_SOC_AR9342:
81 case AR71XX_SOC_AR9344:
82 ar71xx_uart_data[0].uartclk = ar71xx_ref_freq;
83 break;
84
85 default:
86 BUG();
87 }
88
89 platform_device_register(&ar71xx_uart_device);
90 }
91
92 static struct resource ar71xx_mdio_resources[] = {
93 {
94 .name = "mdio_base",
95 .flags = IORESOURCE_MEM,
96 .start = AR71XX_GE0_BASE,
97 .end = AR71XX_GE0_BASE + 0x200 - 1,
98 }
99 };
100
101 static struct ag71xx_mdio_platform_data ar71xx_mdio_data;
102
103 struct platform_device ar71xx_mdio_device = {
104 .name = "ag71xx-mdio",
105 .id = -1,
106 .resource = ar71xx_mdio_resources,
107 .num_resources = ARRAY_SIZE(ar71xx_mdio_resources),
108 .dev = {
109 .platform_data = &ar71xx_mdio_data,
110 },
111 };
112
113 static void ar71xx_set_pll(u32 cfg_reg, u32 pll_reg, u32 pll_val, u32 shift)
114 {
115 void __iomem *base;
116 u32 t;
117
118 base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE);
119
120 t = __raw_readl(base + cfg_reg);
121 t &= ~(3 << shift);
122 t |= (2 << shift);
123 __raw_writel(t, base + cfg_reg);
124 udelay(100);
125
126 __raw_writel(pll_val, base + pll_reg);
127
128 t |= (3 << shift);
129 __raw_writel(t, base + cfg_reg);
130 udelay(100);
131
132 t &= ~(3 << shift);
133 __raw_writel(t, base + cfg_reg);
134 udelay(100);
135
136 printk(KERN_DEBUG "ar71xx: pll_reg %#x: %#x\n",
137 (unsigned int)(base + pll_reg), __raw_readl(base + pll_reg));
138
139 iounmap(base);
140 }
141
142 void __init ar71xx_add_device_mdio(u32 phy_mask)
143 {
144 switch (ar71xx_soc) {
145 case AR71XX_SOC_AR7240:
146 ar71xx_mdio_data.is_ar7240 = 1;
147 break;
148 case AR71XX_SOC_AR7241:
149 ar71xx_mdio_data.is_ar7240 = 1;
150 ar71xx_mdio_resources[0].start = AR71XX_GE1_BASE;
151 ar71xx_mdio_resources[0].end = AR71XX_GE1_BASE + 0x200 - 1;
152 break;
153 case AR71XX_SOC_AR7242:
154 ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG,
155 AR7242_PLL_REG_ETH0_INT_CLOCK, 0x62000000,
156 AR71XX_ETH0_PLL_SHIFT);
157 break;
158 case AR71XX_SOC_AR9330:
159 case AR71XX_SOC_AR9331:
160 ar71xx_mdio_data.is_ar7240 = 1;
161 ar71xx_mdio_resources[0].start = AR71XX_GE1_BASE;
162 ar71xx_mdio_resources[0].end = AR71XX_GE1_BASE + 0x200 - 1;
163 break;
164 default:
165 break;
166 }
167
168 ar71xx_mdio_data.phy_mask = phy_mask;
169
170 platform_device_register(&ar71xx_mdio_device);
171 }
172
173 struct ar71xx_eth_pll_data ar71xx_eth0_pll_data;
174 struct ar71xx_eth_pll_data ar71xx_eth1_pll_data;
175
176 static u32 ar71xx_get_eth_pll(unsigned int mac, int speed)
177 {
178 struct ar71xx_eth_pll_data *pll_data;
179 u32 pll_val;
180
181 switch (mac) {
182 case 0:
183 pll_data = &ar71xx_eth0_pll_data;
184 break;
185 case 1:
186 pll_data = &ar71xx_eth1_pll_data;
187 break;
188 default:
189 BUG();
190 }
191
192 switch (speed) {
193 case SPEED_10:
194 pll_val = pll_data->pll_10;
195 break;
196 case SPEED_100:
197 pll_val = pll_data->pll_100;
198 break;
199 case SPEED_1000:
200 pll_val = pll_data->pll_1000;
201 break;
202 default:
203 BUG();
204 }
205
206 return pll_val;
207 }
208
209 static void ar71xx_set_pll_ge0(int speed)
210 {
211 u32 val = ar71xx_get_eth_pll(0, speed);
212
213 ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH0_INT_CLOCK,
214 val, AR71XX_ETH0_PLL_SHIFT);
215 }
216
217 static void ar71xx_set_pll_ge1(int speed)
218 {
219 u32 val = ar71xx_get_eth_pll(1, speed);
220
221 ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH1_INT_CLOCK,
222 val, AR71XX_ETH1_PLL_SHIFT);
223 }
224
225 static void ar724x_set_pll_ge0(int speed)
226 {
227 /* TODO */
228 }
229
230 static void ar724x_set_pll_ge1(int speed)
231 {
232 /* TODO */
233 }
234
235 static void ar7242_set_pll_ge0(int speed)
236 {
237 u32 val = ar71xx_get_eth_pll(0, speed);
238
239 ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR7242_PLL_REG_ETH0_INT_CLOCK,
240 val, AR71XX_ETH0_PLL_SHIFT);
241 }
242
243 static void ar91xx_set_pll_ge0(int speed)
244 {
245 u32 val = ar71xx_get_eth_pll(0, speed);
246
247 ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH0_INT_CLOCK,
248 val, AR91XX_ETH0_PLL_SHIFT);
249 }
250
251 static void ar91xx_set_pll_ge1(int speed)
252 {
253 u32 val = ar71xx_get_eth_pll(1, speed);
254
255 ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH1_INT_CLOCK,
256 val, AR91XX_ETH1_PLL_SHIFT);
257 }
258
259 static void ar933x_set_pll_ge0(int speed)
260 {
261 /* TODO */
262 }
263
264 static void ar933x_set_pll_ge1(int speed)
265 {
266 /* TODO */
267 }
268
269 static void ar71xx_ddr_flush_ge0(void)
270 {
271 ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE0);
272 }
273
274 static void ar71xx_ddr_flush_ge1(void)
275 {
276 ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE1);
277 }
278
279 static void ar724x_ddr_flush_ge0(void)
280 {
281 ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE0);
282 }
283
284 static void ar724x_ddr_flush_ge1(void)
285 {
286 ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE1);
287 }
288
289 static void ar91xx_ddr_flush_ge0(void)
290 {
291 ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE0);
292 }
293
294 static void ar91xx_ddr_flush_ge1(void)
295 {
296 ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE1);
297 }
298
299 static void ar933x_ddr_flush_ge0(void)
300 {
301 ar71xx_ddr_flush(AR933X_DDR_REG_FLUSH_GE0);
302 }
303
304 static void ar933x_ddr_flush_ge1(void)
305 {
306 ar71xx_ddr_flush(AR933X_DDR_REG_FLUSH_GE1);
307 }
308
309 static struct resource ar71xx_eth0_resources[] = {
310 {
311 .name = "mac_base",
312 .flags = IORESOURCE_MEM,
313 .start = AR71XX_GE0_BASE,
314 .end = AR71XX_GE0_BASE + 0x200 - 1,
315 }, {
316 .name = "mii_ctrl",
317 .flags = IORESOURCE_MEM,
318 .start = AR71XX_MII_BASE + MII_REG_MII0_CTRL,
319 .end = AR71XX_MII_BASE + MII_REG_MII0_CTRL + 3,
320 }, {
321 .name = "mac_irq",
322 .flags = IORESOURCE_IRQ,
323 .start = AR71XX_CPU_IRQ_GE0,
324 .end = AR71XX_CPU_IRQ_GE0,
325 },
326 };
327
328 struct ag71xx_platform_data ar71xx_eth0_data = {
329 .reset_bit = RESET_MODULE_GE0_MAC,
330 };
331
332 struct platform_device ar71xx_eth0_device = {
333 .name = "ag71xx",
334 .id = 0,
335 .resource = ar71xx_eth0_resources,
336 .num_resources = ARRAY_SIZE(ar71xx_eth0_resources),
337 .dev = {
338 .platform_data = &ar71xx_eth0_data,
339 },
340 };
341
342 static struct resource ar71xx_eth1_resources[] = {
343 {
344 .name = "mac_base",
345 .flags = IORESOURCE_MEM,
346 .start = AR71XX_GE1_BASE,
347 .end = AR71XX_GE1_BASE + 0x200 - 1,
348 }, {
349 .name = "mii_ctrl",
350 .flags = IORESOURCE_MEM,
351 .start = AR71XX_MII_BASE + MII_REG_MII1_CTRL,
352 .end = AR71XX_MII_BASE + MII_REG_MII1_CTRL + 3,
353 }, {
354 .name = "mac_irq",
355 .flags = IORESOURCE_IRQ,
356 .start = AR71XX_CPU_IRQ_GE1,
357 .end = AR71XX_CPU_IRQ_GE1,
358 },
359 };
360
361 struct ag71xx_platform_data ar71xx_eth1_data = {
362 .reset_bit = RESET_MODULE_GE1_MAC,
363 };
364
365 struct platform_device ar71xx_eth1_device = {
366 .name = "ag71xx",
367 .id = 1,
368 .resource = ar71xx_eth1_resources,
369 .num_resources = ARRAY_SIZE(ar71xx_eth1_resources),
370 .dev = {
371 .platform_data = &ar71xx_eth1_data,
372 },
373 };
374
375 #define AR71XX_PLL_VAL_1000 0x00110000
376 #define AR71XX_PLL_VAL_100 0x00001099
377 #define AR71XX_PLL_VAL_10 0x00991099
378
379 #define AR724X_PLL_VAL_1000 0x00110000
380 #define AR724X_PLL_VAL_100 0x00001099
381 #define AR724X_PLL_VAL_10 0x00991099
382
383 #define AR7242_PLL_VAL_1000 0x1c000000
384 #define AR7242_PLL_VAL_100 0x00000101
385 #define AR7242_PLL_VAL_10 0x00001616
386
387 #define AR91XX_PLL_VAL_1000 0x1a000000
388 #define AR91XX_PLL_VAL_100 0x13000a44
389 #define AR91XX_PLL_VAL_10 0x00441099
390
391 #define AR933X_PLL_VAL_1000 0x00110000
392 #define AR933X_PLL_VAL_100 0x00001099
393 #define AR933X_PLL_VAL_10 0x00991099
394
395 static void __init ar71xx_init_eth_pll_data(unsigned int id)
396 {
397 struct ar71xx_eth_pll_data *pll_data;
398 u32 pll_10, pll_100, pll_1000;
399
400 switch (id) {
401 case 0:
402 pll_data = &ar71xx_eth0_pll_data;
403 break;
404 case 1:
405 pll_data = &ar71xx_eth1_pll_data;
406 break;
407 default:
408 BUG();
409 }
410
411 switch (ar71xx_soc) {
412 case AR71XX_SOC_AR7130:
413 case AR71XX_SOC_AR7141:
414 case AR71XX_SOC_AR7161:
415 pll_10 = AR71XX_PLL_VAL_10;
416 pll_100 = AR71XX_PLL_VAL_100;
417 pll_1000 = AR71XX_PLL_VAL_1000;
418 break;
419
420 case AR71XX_SOC_AR7240:
421 case AR71XX_SOC_AR7241:
422 pll_10 = AR724X_PLL_VAL_10;
423 pll_100 = AR724X_PLL_VAL_100;
424 pll_1000 = AR724X_PLL_VAL_1000;
425 break;
426
427 case AR71XX_SOC_AR7242:
428 pll_10 = AR7242_PLL_VAL_10;
429 pll_100 = AR7242_PLL_VAL_100;
430 pll_1000 = AR7242_PLL_VAL_1000;
431 break;
432
433 case AR71XX_SOC_AR9130:
434 case AR71XX_SOC_AR9132:
435 pll_10 = AR91XX_PLL_VAL_10;
436 pll_100 = AR91XX_PLL_VAL_100;
437 pll_1000 = AR91XX_PLL_VAL_1000;
438 break;
439
440 case AR71XX_SOC_AR9330:
441 case AR71XX_SOC_AR9331:
442 pll_10 = AR933X_PLL_VAL_10;
443 pll_100 = AR933X_PLL_VAL_100;
444 pll_1000 = AR933X_PLL_VAL_1000;
445 break;
446
447 default:
448 BUG();
449 }
450
451 if (!pll_data->pll_10)
452 pll_data->pll_10 = pll_10;
453
454 if (!pll_data->pll_100)
455 pll_data->pll_100 = pll_100;
456
457 if (!pll_data->pll_1000)
458 pll_data->pll_1000 = pll_1000;
459 }
460
461 static int ar71xx_eth_instance __initdata;
462 void __init ar71xx_add_device_eth(unsigned int id)
463 {
464 struct platform_device *pdev;
465 struct ag71xx_platform_data *pdata;
466
467 ar71xx_init_eth_pll_data(id);
468
469 switch (id) {
470 case 0:
471 switch (ar71xx_eth0_data.phy_if_mode) {
472 case PHY_INTERFACE_MODE_MII:
473 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_MII;
474 break;
475 case PHY_INTERFACE_MODE_GMII:
476 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_GMII;
477 break;
478 case PHY_INTERFACE_MODE_RGMII:
479 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_RGMII;
480 break;
481 case PHY_INTERFACE_MODE_RMII:
482 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_RMII;
483 break;
484 default:
485 printk(KERN_ERR "ar71xx: invalid PHY interface mode "
486 "for eth0\n");
487 return;
488 }
489 pdev = &ar71xx_eth0_device;
490 break;
491 case 1:
492 switch (ar71xx_eth1_data.phy_if_mode) {
493 case PHY_INTERFACE_MODE_RMII:
494 ar71xx_eth1_data.mii_if = MII1_CTRL_IF_RMII;
495 break;
496 case PHY_INTERFACE_MODE_RGMII:
497 ar71xx_eth1_data.mii_if = MII1_CTRL_IF_RGMII;
498 break;
499 default:
500 printk(KERN_ERR "ar71xx: invalid PHY interface mode "
501 "for eth1\n");
502 return;
503 }
504 pdev = &ar71xx_eth1_device;
505 break;
506 default:
507 printk(KERN_ERR "ar71xx: invalid ethernet id %d\n", id);
508 return;
509 }
510
511 pdata = pdev->dev.platform_data;
512
513 switch (ar71xx_soc) {
514 case AR71XX_SOC_AR7130:
515 pdata->ddr_flush = id ? ar71xx_ddr_flush_ge1
516 : ar71xx_ddr_flush_ge0;
517 pdata->set_pll = id ? ar71xx_set_pll_ge1
518 : ar71xx_set_pll_ge0;
519 break;
520
521 case AR71XX_SOC_AR7141:
522 case AR71XX_SOC_AR7161:
523 pdata->ddr_flush = id ? ar71xx_ddr_flush_ge1
524 : ar71xx_ddr_flush_ge0;
525 pdata->set_pll = id ? ar71xx_set_pll_ge1
526 : ar71xx_set_pll_ge0;
527 pdata->has_gbit = 1;
528 break;
529
530 case AR71XX_SOC_AR7242:
531 ar71xx_eth0_data.reset_bit |= AR724X_RESET_GE0_MDIO;
532 ar71xx_eth1_data.reset_bit |= AR724X_RESET_GE1_MDIO;
533 pdata->ddr_flush = id ? ar724x_ddr_flush_ge1
534 : ar724x_ddr_flush_ge0;
535 pdata->set_pll = id ? ar724x_set_pll_ge1
536 : ar7242_set_pll_ge0;
537 pdata->has_gbit = 1;
538 pdata->is_ar724x = 1;
539
540 if (!pdata->fifo_cfg1)
541 pdata->fifo_cfg1 = 0x0010ffff;
542 if (!pdata->fifo_cfg2)
543 pdata->fifo_cfg2 = 0x015500aa;
544 if (!pdata->fifo_cfg3)
545 pdata->fifo_cfg3 = 0x01f00140;
546 break;
547
548 case AR71XX_SOC_AR7241:
549 ar71xx_eth0_data.reset_bit |= AR724X_RESET_GE0_MDIO;
550 ar71xx_eth1_data.reset_bit |= AR724X_RESET_GE1_MDIO;
551 /* fall through */
552 case AR71XX_SOC_AR7240:
553 pdata->ddr_flush = id ? ar724x_ddr_flush_ge1
554 : ar724x_ddr_flush_ge0;
555 pdata->set_pll = id ? ar724x_set_pll_ge1
556 : ar724x_set_pll_ge0;
557 pdata->is_ar724x = 1;
558
559 if (!pdata->fifo_cfg1)
560 pdata->fifo_cfg1 = 0x0010ffff;
561 if (!pdata->fifo_cfg2)
562 pdata->fifo_cfg2 = 0x015500aa;
563 if (!pdata->fifo_cfg3)
564 pdata->fifo_cfg3 = 0x01f00140;
565 break;
566
567 case AR71XX_SOC_AR9130:
568 pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1
569 : ar91xx_ddr_flush_ge0;
570 pdata->set_pll = id ? ar91xx_set_pll_ge1
571 : ar91xx_set_pll_ge0;
572 pdata->is_ar91xx = 1;
573 break;
574
575 case AR71XX_SOC_AR9132:
576 pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1
577 : ar91xx_ddr_flush_ge0;
578 pdata->set_pll = id ? ar91xx_set_pll_ge1
579 : ar91xx_set_pll_ge0;
580 pdata->is_ar91xx = 1;
581 pdata->has_gbit = 1;
582 break;
583
584 case AR71XX_SOC_AR9330:
585 case AR71XX_SOC_AR9331:
586 ar71xx_eth0_data.reset_bit = AR933X_RESET_GE0_MAC |
587 AR933X_RESET_GE0_MDIO;
588 ar71xx_eth1_data.reset_bit = AR933X_RESET_GE1_MAC |
589 AR933X_RESET_GE1_MDIO;
590 pdata->ddr_flush = id ? ar933x_ddr_flush_ge1
591 : ar933x_ddr_flush_ge0;
592 pdata->set_pll = id ? ar933x_set_pll_ge1
593 : ar933x_set_pll_ge0;
594 pdata->has_gbit = 1;
595 pdata->is_ar724x = 1;
596
597 if (!pdata->fifo_cfg1)
598 pdata->fifo_cfg1 = 0x0010ffff;
599 if (!pdata->fifo_cfg2)
600 pdata->fifo_cfg2 = 0x015500aa;
601 if (!pdata->fifo_cfg3)
602 pdata->fifo_cfg3 = 0x01f00140;
603 break;
604
605 default:
606 BUG();
607 }
608
609 switch (pdata->phy_if_mode) {
610 case PHY_INTERFACE_MODE_GMII:
611 case PHY_INTERFACE_MODE_RGMII:
612 if (!pdata->has_gbit) {
613 printk(KERN_ERR "ar71xx: no gbit available on eth%d\n",
614 id);
615 return;
616 }
617 /* fallthrough */
618 default:
619 break;
620 }
621
622 if (!is_valid_ether_addr(pdata->mac_addr)) {
623 random_ether_addr(pdata->mac_addr);
624 printk(KERN_DEBUG
625 "ar71xx: using random MAC address for eth%d\n",
626 ar71xx_eth_instance);
627 }
628
629 if (pdata->mii_bus_dev == NULL)
630 pdata->mii_bus_dev = &ar71xx_mdio_device.dev;
631
632 /* Reset the device */
633 ar71xx_device_stop(pdata->reset_bit);
634 mdelay(100);
635
636 ar71xx_device_start(pdata->reset_bit);
637 mdelay(100);
638
639 platform_device_register(pdev);
640 ar71xx_eth_instance++;
641 }
642
643 static struct resource ar71xx_spi_resources[] = {
644 [0] = {
645 .start = AR71XX_SPI_BASE,
646 .end = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1,
647 .flags = IORESOURCE_MEM,
648 },
649 };
650
651 static struct platform_device ar71xx_spi_device = {
652 .name = "ar71xx-spi",
653 .id = -1,
654 .resource = ar71xx_spi_resources,
655 .num_resources = ARRAY_SIZE(ar71xx_spi_resources),
656 };
657
658 void __init ar71xx_add_device_spi(struct ar71xx_spi_platform_data *pdata,
659 struct spi_board_info const *info,
660 unsigned n)
661 {
662 spi_register_board_info(info, n);
663 ar71xx_spi_device.dev.platform_data = pdata;
664 platform_device_register(&ar71xx_spi_device);
665 }
666
667 void __init ar71xx_add_device_wdt(void)
668 {
669 platform_device_register_simple("ar71xx-wdt", -1, NULL, 0);
670 }
671
672 void __init ar71xx_set_mac_base(unsigned char *mac)
673 {
674 memcpy(ar71xx_mac_base, mac, ETH_ALEN);
675 }
676
677 void __init ar71xx_parse_mac_addr(char *mac_str)
678 {
679 u8 tmp[ETH_ALEN];
680 int t;
681
682 t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
683 &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
684
685 if (t != ETH_ALEN)
686 t = sscanf(mac_str, "%02hhx.%02hhx.%02hhx.%02hhx.%02hhx.%02hhx",
687 &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
688
689 if (t == ETH_ALEN)
690 ar71xx_set_mac_base(tmp);
691 else
692 printk(KERN_DEBUG "ar71xx: failed to parse mac address "
693 "\"%s\"\n", mac_str);
694 }
695
696 static int __init ar71xx_ethaddr_setup(char *str)
697 {
698 ar71xx_parse_mac_addr(str);
699 return 1;
700 }
701 __setup("ethaddr=", ar71xx_ethaddr_setup);
702
703 static int __init ar71xx_kmac_setup(char *str)
704 {
705 ar71xx_parse_mac_addr(str);
706 return 1;
707 }
708 __setup("kmac=", ar71xx_kmac_setup);
709
710 void __init ar71xx_init_mac(unsigned char *dst, const unsigned char *src,
711 unsigned offset)
712 {
713 u32 t;
714
715 if (!is_valid_ether_addr(src)) {
716 memset(dst, '\0', ETH_ALEN);
717 return;
718 }
719
720 t = (((u32) src[3]) << 16) + (((u32) src[4]) << 8) + ((u32) src[5]);
721 t += offset;
722
723 dst[0] = src[0];
724 dst[1] = src[1];
725 dst[2] = src[2];
726 dst[3] = (t >> 16) & 0xff;
727 dst[4] = (t >> 8) & 0xff;
728 dst[5] = t & 0xff;
729 }