diff options
author | Manuel Lauss <manuel.lauss@googlemail.com> | 2011-05-08 04:42:18 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2011-05-19 04:55:46 -0400 |
commit | 40d8bc281711d188f35f035f28d94b111b735484 (patch) | |
tree | 60aec8dda708f64830cf8e49520cfa61573ee25e /arch/mips/alchemy/common/platform.c | |
parent | 80130204b43ce9c3b50924e4c2d44e9f2881f8c3 (diff) |
MIPS: Alchemy: Rewrite ethernet platform setup
Rewrite ethernet setup to use runtime cpu detection, and also clean up
the ethernet base address mess as far as possible.
Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
To: Linux-MIPS <linux-mips@linux-mips.org>
Cc: Florian Fainelli <florian@openwrt.org>
Cc: Wolfgang Grandegger <wg@grandegger.com>
Patchwork: https://patchwork.linux-mips.org/patch/2353/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org
Diffstat (limited to 'arch/mips/alchemy/common/platform.c')
-rw-r--r-- | arch/mips/alchemy/common/platform.c | 151 |
1 files changed, 101 insertions, 50 deletions
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index 36489fb184a..541fff24abe 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c | |||
@@ -13,9 +13,10 @@ | |||
13 | 13 | ||
14 | #include <linux/dma-mapping.h> | 14 | #include <linux/dma-mapping.h> |
15 | #include <linux/etherdevice.h> | 15 | #include <linux/etherdevice.h> |
16 | #include <linux/init.h> | ||
16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
17 | #include <linux/serial_8250.h> | 18 | #include <linux/serial_8250.h> |
18 | #include <linux/init.h> | 19 | #include <linux/slab.h> |
19 | 20 | ||
20 | #include <asm/mach-au1x00/au1xxx.h> | 21 | #include <asm/mach-au1x00/au1xxx.h> |
21 | #include <asm/mach-au1x00/au1xxx_dbdma.h> | 22 | #include <asm/mach-au1x00/au1xxx_dbdma.h> |
@@ -372,15 +373,16 @@ static struct platform_device pbdb_smbus_device = { | |||
372 | #endif | 373 | #endif |
373 | 374 | ||
374 | /* Macro to help defining the Ethernet MAC resources */ | 375 | /* Macro to help defining the Ethernet MAC resources */ |
376 | #define MAC_RES_COUNT 3 /* MAC regs base, MAC enable reg, MAC INT */ | ||
375 | #define MAC_RES(_base, _enable, _irq) \ | 377 | #define MAC_RES(_base, _enable, _irq) \ |
376 | { \ | 378 | { \ |
377 | .start = CPHYSADDR(_base), \ | 379 | .start = _base, \ |
378 | .end = CPHYSADDR(_base + 0xffff), \ | 380 | .end = _base + 0xffff, \ |
379 | .flags = IORESOURCE_MEM, \ | 381 | .flags = IORESOURCE_MEM, \ |
380 | }, \ | 382 | }, \ |
381 | { \ | 383 | { \ |
382 | .start = CPHYSADDR(_enable), \ | 384 | .start = _enable, \ |
383 | .end = CPHYSADDR(_enable + 0x3), \ | 385 | .end = _enable + 0x3, \ |
384 | .flags = IORESOURCE_MEM, \ | 386 | .flags = IORESOURCE_MEM, \ |
385 | }, \ | 387 | }, \ |
386 | { \ | 388 | { \ |
@@ -389,19 +391,29 @@ static struct platform_device pbdb_smbus_device = { | |||
389 | .flags = IORESOURCE_IRQ \ | 391 | .flags = IORESOURCE_IRQ \ |
390 | } | 392 | } |
391 | 393 | ||
392 | static struct resource au1xxx_eth0_resources[] = { | 394 | static struct resource au1xxx_eth0_resources[][MAC_RES_COUNT] __initdata = { |
393 | #if defined(CONFIG_SOC_AU1000) | 395 | [ALCHEMY_CPU_AU1000] = { |
394 | MAC_RES(AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT), | 396 | MAC_RES(AU1000_MAC0_PHYS_ADDR, |
395 | #elif defined(CONFIG_SOC_AU1100) | 397 | AU1000_MACEN_PHYS_ADDR, |
396 | MAC_RES(AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT), | 398 | AU1000_MAC0_DMA_INT) |
397 | #elif defined(CONFIG_SOC_AU1550) | 399 | }, |
398 | MAC_RES(AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT), | 400 | [ALCHEMY_CPU_AU1500] = { |
399 | #elif defined(CONFIG_SOC_AU1500) | 401 | MAC_RES(AU1500_MAC0_PHYS_ADDR, |
400 | MAC_RES(AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT), | 402 | AU1500_MACEN_PHYS_ADDR, |
401 | #endif | 403 | AU1500_MAC0_DMA_INT) |
404 | }, | ||
405 | [ALCHEMY_CPU_AU1100] = { | ||
406 | MAC_RES(AU1000_MAC0_PHYS_ADDR, | ||
407 | AU1000_MACEN_PHYS_ADDR, | ||
408 | AU1100_MAC0_DMA_INT) | ||
409 | }, | ||
410 | [ALCHEMY_CPU_AU1550] = { | ||
411 | MAC_RES(AU1000_MAC0_PHYS_ADDR, | ||
412 | AU1000_MACEN_PHYS_ADDR, | ||
413 | AU1550_MAC0_DMA_INT) | ||
414 | }, | ||
402 | }; | 415 | }; |
403 | 416 | ||
404 | |||
405 | static struct au1000_eth_platform_data au1xxx_eth0_platform_data = { | 417 | static struct au1000_eth_platform_data au1xxx_eth0_platform_data = { |
406 | .phy1_search_mac0 = 1, | 418 | .phy1_search_mac0 = 1, |
407 | }; | 419 | }; |
@@ -409,20 +421,26 @@ static struct au1000_eth_platform_data au1xxx_eth0_platform_data = { | |||
409 | static struct platform_device au1xxx_eth0_device = { | 421 | static struct platform_device au1xxx_eth0_device = { |
410 | .name = "au1000-eth", | 422 | .name = "au1000-eth", |
411 | .id = 0, | 423 | .id = 0, |
412 | .num_resources = ARRAY_SIZE(au1xxx_eth0_resources), | 424 | .num_resources = MAC_RES_COUNT, |
413 | .resource = au1xxx_eth0_resources, | ||
414 | .dev.platform_data = &au1xxx_eth0_platform_data, | 425 | .dev.platform_data = &au1xxx_eth0_platform_data, |
415 | }; | 426 | }; |
416 | 427 | ||
417 | #ifndef CONFIG_SOC_AU1100 | 428 | static struct resource au1xxx_eth1_resources[][MAC_RES_COUNT] __initdata = { |
418 | static struct resource au1xxx_eth1_resources[] = { | 429 | [ALCHEMY_CPU_AU1000] = { |
419 | #if defined(CONFIG_SOC_AU1000) | 430 | MAC_RES(AU1000_MAC1_PHYS_ADDR, |
420 | MAC_RES(AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT), | 431 | AU1000_MACEN_PHYS_ADDR + 4, |
421 | #elif defined(CONFIG_SOC_AU1550) | 432 | AU1000_MAC1_DMA_INT) |
422 | MAC_RES(AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT), | 433 | }, |
423 | #elif defined(CONFIG_SOC_AU1500) | 434 | [ALCHEMY_CPU_AU1500] = { |
424 | MAC_RES(AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT), | 435 | MAC_RES(AU1500_MAC1_PHYS_ADDR, |
425 | #endif | 436 | AU1500_MACEN_PHYS_ADDR + 4, |
437 | AU1500_MAC1_DMA_INT) | ||
438 | }, | ||
439 | [ALCHEMY_CPU_AU1550] = { | ||
440 | MAC_RES(AU1000_MAC1_PHYS_ADDR, | ||
441 | AU1000_MACEN_PHYS_ADDR + 4, | ||
442 | AU1550_MAC1_DMA_INT) | ||
443 | }, | ||
426 | }; | 444 | }; |
427 | 445 | ||
428 | static struct au1000_eth_platform_data au1xxx_eth1_platform_data = { | 446 | static struct au1000_eth_platform_data au1xxx_eth1_platform_data = { |
@@ -432,11 +450,9 @@ static struct au1000_eth_platform_data au1xxx_eth1_platform_data = { | |||
432 | static struct platform_device au1xxx_eth1_device = { | 450 | static struct platform_device au1xxx_eth1_device = { |
433 | .name = "au1000-eth", | 451 | .name = "au1000-eth", |
434 | .id = 1, | 452 | .id = 1, |
435 | .num_resources = ARRAY_SIZE(au1xxx_eth1_resources), | 453 | .num_resources = MAC_RES_COUNT, |
436 | .resource = au1xxx_eth1_resources, | ||
437 | .dev.platform_data = &au1xxx_eth1_platform_data, | 454 | .dev.platform_data = &au1xxx_eth1_platform_data, |
438 | }; | 455 | }; |
439 | #endif | ||
440 | 456 | ||
441 | void __init au1xxx_override_eth_cfg(unsigned int port, | 457 | void __init au1xxx_override_eth_cfg(unsigned int port, |
442 | struct au1000_eth_platform_data *eth_data) | 458 | struct au1000_eth_platform_data *eth_data) |
@@ -447,11 +463,62 @@ void __init au1xxx_override_eth_cfg(unsigned int port, | |||
447 | if (port == 0) | 463 | if (port == 0) |
448 | memcpy(&au1xxx_eth0_platform_data, eth_data, | 464 | memcpy(&au1xxx_eth0_platform_data, eth_data, |
449 | sizeof(struct au1000_eth_platform_data)); | 465 | sizeof(struct au1000_eth_platform_data)); |
450 | #ifndef CONFIG_SOC_AU1100 | ||
451 | else | 466 | else |
452 | memcpy(&au1xxx_eth1_platform_data, eth_data, | 467 | memcpy(&au1xxx_eth1_platform_data, eth_data, |
453 | sizeof(struct au1000_eth_platform_data)); | 468 | sizeof(struct au1000_eth_platform_data)); |
454 | #endif | 469 | } |
470 | |||
471 | static void __init alchemy_setup_macs(int ctype) | ||
472 | { | ||
473 | int ret, i; | ||
474 | unsigned char ethaddr[6]; | ||
475 | struct resource *macres; | ||
476 | |||
477 | /* Handle 1st MAC */ | ||
478 | if (alchemy_get_macs(ctype) < 1) | ||
479 | return; | ||
480 | |||
481 | macres = kmalloc(sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); | ||
482 | if (!macres) { | ||
483 | printk(KERN_INFO "Alchemy: no memory for MAC0 resources\n"); | ||
484 | return; | ||
485 | } | ||
486 | memcpy(macres, au1xxx_eth0_resources[ctype], | ||
487 | sizeof(struct resource) * MAC_RES_COUNT); | ||
488 | au1xxx_eth0_device.resource = macres; | ||
489 | |||
490 | i = prom_get_ethernet_addr(ethaddr); | ||
491 | if (!i && !is_valid_ether_addr(au1xxx_eth0_platform_data.mac)) | ||
492 | memcpy(au1xxx_eth0_platform_data.mac, ethaddr, 6); | ||
493 | |||
494 | ret = platform_device_register(&au1xxx_eth0_device); | ||
495 | if (!ret) | ||
496 | printk(KERN_INFO "Alchemy: failed to register MAC0\n"); | ||
497 | |||
498 | |||
499 | /* Handle 2nd MAC */ | ||
500 | if (alchemy_get_macs(ctype) < 2) | ||
501 | return; | ||
502 | |||
503 | macres = kmalloc(sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); | ||
504 | if (!macres) { | ||
505 | printk(KERN_INFO "Alchemy: no memory for MAC1 resources\n"); | ||
506 | return; | ||
507 | } | ||
508 | memcpy(macres, au1xxx_eth1_resources[ctype], | ||
509 | sizeof(struct resource) * MAC_RES_COUNT); | ||
510 | au1xxx_eth1_device.resource = macres; | ||
511 | |||
512 | ethaddr[5] += 1; /* next addr for 2nd MAC */ | ||
513 | if (!i && !is_valid_ether_addr(au1xxx_eth1_platform_data.mac)) | ||
514 | memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6); | ||
515 | |||
516 | /* Register second MAC if enabled in pinfunc */ | ||
517 | if (!(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2)) { | ||
518 | ret = platform_device_register(&au1xxx_eth1_device); | ||
519 | if (ret) | ||
520 | printk(KERN_INFO "Alchemy: failed to register MAC1\n"); | ||
521 | } | ||
455 | } | 522 | } |
456 | 523 | ||
457 | static struct platform_device *au1xxx_platform_devices[] __initdata = { | 524 | static struct platform_device *au1xxx_platform_devices[] __initdata = { |
@@ -472,33 +539,17 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = { | |||
472 | #ifdef SMBUS_PSC_BASE | 539 | #ifdef SMBUS_PSC_BASE |
473 | &pbdb_smbus_device, | 540 | &pbdb_smbus_device, |
474 | #endif | 541 | #endif |
475 | &au1xxx_eth0_device, | ||
476 | }; | 542 | }; |
477 | 543 | ||
478 | static int __init au1xxx_platform_init(void) | 544 | static int __init au1xxx_platform_init(void) |
479 | { | 545 | { |
480 | int err, i, ctype = alchemy_get_cputype(); | 546 | int err, ctype = alchemy_get_cputype(); |
481 | unsigned char ethaddr[6]; | ||
482 | 547 | ||
483 | alchemy_setup_uarts(ctype); | 548 | alchemy_setup_uarts(ctype); |
484 | 549 | alchemy_setup_macs(ctype); | |
485 | /* use firmware-provided mac addr if available and necessary */ | ||
486 | i = prom_get_ethernet_addr(ethaddr); | ||
487 | if (!i && !is_valid_ether_addr(au1xxx_eth0_platform_data.mac)) | ||
488 | memcpy(au1xxx_eth0_platform_data.mac, ethaddr, 6); | ||
489 | 550 | ||
490 | err = platform_add_devices(au1xxx_platform_devices, | 551 | err = platform_add_devices(au1xxx_platform_devices, |
491 | ARRAY_SIZE(au1xxx_platform_devices)); | 552 | ARRAY_SIZE(au1xxx_platform_devices)); |
492 | #ifndef CONFIG_SOC_AU1100 | ||
493 | ethaddr[5] += 1; /* next addr for 2nd MAC */ | ||
494 | if (!i && !is_valid_ether_addr(au1xxx_eth1_platform_data.mac)) | ||
495 | memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6); | ||
496 | |||
497 | /* Register second MAC if enabled in pinfunc */ | ||
498 | if (!err && !(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2)) | ||
499 | err = platform_device_register(&au1xxx_eth1_device); | ||
500 | #endif | ||
501 | |||
502 | return err; | 553 | return err; |
503 | } | 554 | } |
504 | 555 | ||