Package: linux-image-2.6.26-1-orion5x Severity: normal Tags: patch The attached patch improves the kernel's support for the DNS-323 in a few areas:
* It reads the MAC address for the on-board NIC out of flash, and uses it in the NIC initialisation (all DNS-323 models); and * The SATA controller for the rev B1 hardware (also used in the CH3SNAS) requires PCI to be disabled, and the SATA controller to be initialised separately. * The rev B1 hardware also has different MPP mappings. A functionally-equivalent patch has been prepared for the mainline kernel, and I'm working on getting that accepted upstream at the moment. - Matt
--- dns323-setup.c.orig 2008-10-17 21:56:01.000000000 +1100 +++ dns323-setup.c 2008-10-21 09:25:42.000000000 +1100 @@ -21,6 +21,7 @@ #include <linux/gpio_keys.h> #include <linux/input.h> #include <linux/i2c.h> +#include <linux/ata_platform.h> #include <asm/mach-types.h> #include <asm/gpio.h> #include <asm/mach/arch.h> @@ -67,8 +68,18 @@ static int __init dns323_pci_init(void) { - if (machine_is_dns323()) - pci_common_init(&dns323_pci); + u32 dev, rev; + + orion5x_pcie_id(&dev, &rev); + + if (machine_is_dns323()) { + if (dev != MV88F5182_DEV_ID) { + /* The 5182 doesn't really use it's PCI bus, so + * we don't initialise it. + */ + pci_common_init(&dns323_pci); + } + } return 0; } @@ -76,15 +87,6 @@ subsys_initcall(dns323_pci_init); /**************************************************************************** - * Ethernet - */ - -static struct mv643xx_eth_platform_data dns323_eth_data = { - .phy_addr = 8, - .force_phy_addr = 1, -}; - -/**************************************************************************** * 8MiB NOR flash (Spansion S29GL064M90TFIR4) * * Layout as used by D-Link: @@ -143,6 +145,79 @@ }; /**************************************************************************** + * Ethernet + */ + +static struct mv643xx_eth_platform_data dns323_eth_data = { + .phy_addr = 8, + .force_phy_addr = 1, +}; + +/* parse_hex_*() taken from ts209-setup.c; should a common copy of these + * functions be kept somewhere? + */ +static int __init parse_hex_nibble(char n) +{ + if (n >= '0' && n <= '9') + return n - '0'; + + if (n >= 'A' && n <= 'F') + return n - 'A' + 10; + + if (n >= 'a' && n <= 'f') + return n - 'a' + 10; + + return -1; +} + +static int __init parse_hex_byte(const char *b) +{ + int hi; + int lo; + + hi = parse_hex_nibble(b[0]); + lo = parse_hex_nibble(b[1]); + + if (hi < 0 || lo < 0) + return -1; + + return (hi << 4) | lo; +} + +static int __init dns323_read_mac_addr(void) +{ + u_int8_t addr[6] = { 0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF }; + int i; + char *mac_page; + + /* MAC address is stored as a regular ol' string in /dev/mtdblock4 + * (0x007d0000-0x00800000) starting at offset 196480 (0x2ff80). + */ + mac_page = ioremap(DNS323_NOR_BOOT_BASE + 0x7d0000 + 196480, 1024); + + for (i = 0; i < 6; i++) { + int byte; + + byte = parse_hex_byte(mac_page + (i * 3)); + if (byte < 0) { + iounmap(mac_page); + return -1; + } + + addr[i] = byte; + } + + iounmap(mac_page); + printk("DNS323: Found ethernet MAC address: "); + for (i = 0; i < 6; i++) + printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n"); + + memcpy(dns323_eth_data.mac_addr, addr, 6); + + return 0; +} + +/**************************************************************************** * GPIO LEDs (simple - doesn't use hardware blinking support) */ @@ -204,6 +279,13 @@ .dev = { .platform_data = &dns323_button_data, }, }; +/***************************************************************************** + * SATA + ****************************************************************************/ +static struct mv_sata_platform_data dns323_sata_data = { + .n_ports = 2, +}; + /**************************************************************************** * General Setup */ @@ -247,6 +329,11 @@ static void __init dns323_init(void) { + u32 rev, dev; + + /* Whooooooo are we? Who who, who who? */ + orion5x_pcie_id(&dev, &rev); + /* Setup basic Orion functions. Need to be called early. */ orion5x_init(); @@ -262,11 +349,21 @@ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE, ORION5X_PCIE_WA_SIZE); - /* set MPP to 0 as D-Link's 2.6.12.6 kernel did */ - orion5x_write(MPP_0_7_CTRL, 0); - orion5x_write(MPP_8_15_CTRL, 0); - orion5x_write(MPP_16_19_CTRL, 0); - orion5x_write(MPP_DEV_CTRL, 0); + if (dev == MV88F5182_DEV_ID) { + /* The 5182 has a different MPP map, so we wire it up this way + * to let the HDD LEDs do their thing. Values taken directly + * from the D-Link kernel. + */ + orion5x_write(MPP_0_7_CTRL, 0x3); + orion5x_write(MPP_8_15_CTRL, 0x55550000); + orion5x_write(MPP_16_19_CTRL, 0x5555); + } else { + /* set MPP to 0 as D-Link's 2.6.12.6 kernel did */ + orion5x_write(MPP_0_7_CTRL, 0); + orion5x_write(MPP_8_15_CTRL, 0); + orion5x_write(MPP_16_19_CTRL, 0); + orion5x_write(MPP_DEV_CTRL, 0); + } /* Define used GPIO pins @@ -305,7 +402,15 @@ i2c_register_board_info(0, dns323_i2c_devices, ARRAY_SIZE(dns323_i2c_devices)); + if (dns323_read_mac_addr() < 0) + printk("ERROR: Failed to read MAC address\n"); + orion5x_eth_init(&dns323_eth_data); + /* The 5182 has it's SATA controller internally, and it needs it's own + * little init routine. + */ + if (dev == MV88F5182_DEV_ID) + orion5x_sata_init(&dns323_sata_data); } /* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */