From 495551c342fe06cec9a3c1af632b26d10639b153 Mon Sep 17 00:00:00 2001 From: Ashokkumar G <0xfee1dead.sa@gmail.com> Date: Mon, 26 Jan 2015 11:28:52 -0700 Subject: [PATCH 5/9] mmp:ethernet: Adding ethernet MAC address reading for gplugd Currently Marvell's pxa168 ethernet driver uses random MAC address by default instead of reading MAC address from OTP SPI flash. Adding support to uses MAC address provided instead of random MAC address by default Signed-off-by: Ashokkumar G <0xfee1dead.sa@gmail.com> --- arch/arm/mach-mmp/gplugd.c | 132 ++++++++++++++++++++++++------ drivers/net/ethernet/marvell/pxa168_eth.c | 5 ++ include/linux/pxa168_eth.h | 3 + 3 files changed, 116 insertions(+), 24 deletions(-) diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c index 9c441e1..2981c88 100644 --- a/arch/arm/mach-mmp/gplugd.c +++ b/arch/arm/mach-mmp/gplugd.c @@ -22,6 +22,8 @@ #include #include +#include +#include #include "common.h" static unsigned long gplugd_pin_config[] __initdata = { @@ -146,27 +148,6 @@ static struct i2c_board_info gplugd_i2c_board_info[] = { } }; -/* Bring PHY out of reset by setting GPIO 104 */ -static int gplugd_eth_init(void) -{ - if (unlikely(gpio_request(104, "ETH_RESET_N"))) { - printk(KERN_ERR "Can't get hold of GPIO 104 to bring Ethernet " - "PHY out of reset\n"); - return -EIO; - } - - gpio_direction_output(104, 1); - gpio_free(104); - return 0; -} - -struct pxa168_eth_platform_data gplugd_eth_platform_data = { - .port_number = 0, - .phy_addr = 0, - .speed = 0, /* Autonagotiation */ - .init = gplugd_eth_init, -}; - static void __init select_disp_freq(void) { /* set GPIO 35 & clear GPIO 85 to set LCD External Clock to 74.25 MHz */ @@ -227,6 +208,108 @@ static inline int pxa168_add_spi(int id, struct pxa2xx_spi_master *pdata) return platform_device_add(pd); } +#ifdef CONFIG_MTD +static void gplugd_parse_enetaddr(const u8 *addr, u8 *enetaddr) +{ + char *end; + int i; + + for (i = 0; i < 6; ++i) { + enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0; + if (addr) + addr = (*end) ? end + 1 : end; + } +} + +static struct pxa168_eth_platform_data gplugd_eth_platform_data; + +static void __init read_device_serial_mac(void) +{ +#define GPLUGD_SERIAL_NUM_LENGTH 14 +#define GPLUGD_MAC_ADDR_LENGTH 18 + char otp_serial_num[GPLUGD_SERIAL_NUM_LENGTH]; + char otp_mac_addr[GPLUGD_MAC_ADDR_LENGTH]; + u8 *mac_addr = gplugd_eth_platform_data.mac_addr; + size_t retlen; + struct mtd_info *mtd = NULL; + + mtd = get_mtd_device(NULL, 0x00); + + if (!mtd) { + pr_err("%s %d: No MTD devices found", __func__, __LINE__); + return; + } + + if (mtd->_read_user_prot_reg) { + if (!mtd->_read_user_prot_reg(mtd, 0, GPLUGD_SERIAL_NUM_LENGTH, + &retlen, otp_serial_num)) { + if (!mtd->_read_user_prot_reg(mtd, + GPLUGD_SERIAL_NUM_LENGTH, + GPLUGD_MAC_ADDR_LENGTH, + &retlen, otp_mac_addr)) { + + gplugd_parse_enetaddr(otp_mac_addr, mac_addr); + } else { + pr_err("%s %d: OTP MAC Address read failed\n", + __func__, __LINE__); + } + } else { + pr_err("%s %d: OTP Serial Number read failed\n", + __func__, __LINE__); + } + } + + put_mtd_device(mtd); +} +#else +static void __init read_device_serial_mac(void) {} +#endif + +static int device_mac_address(u8 *mac_addr) +{ + pr_warn("%s %d: Entry\n", __func__, __LINE__); + read_device_serial_mac(); + if (!is_valid_ether_addr(gplugd_eth_platform_data.mac_addr)) + return -EINVAL; + memcpy(mac_addr, gplugd_eth_platform_data.mac_addr, 6); + return 0; +} + +/* Bring PHY out of reset by setting GPIO 104 */ +static int gplugd_eth_init(void) +{ + int gpio_enet_reset = 104; + int gpio_enet_coma = 102; + + if (unlikely(gpio_request(gpio_enet_reset, "ETH_RESET_N"))) { + printk(KERN_ERR "Can't get hold of GPIO %d to bring Ethernet " + "PHY out of reset\n", gpio_enet_reset); + return -EIO; + } + if (unlikely(gpio_request(gpio_enet_coma, "ETH_COMA_N"))) { + printk(KERN_ERR "Can't get hold of GPIO %d to bring Ethernet " + "PHY out of coma\n", gpio_enet_coma); + return -EIO; + } + + + gpio_direction_output(gpio_enet_reset, 1); + gpio_direction_output(gpio_enet_coma, 1); + + gpio_free(gpio_enet_reset); + gpio_free(gpio_enet_coma); + return 0; +} + +static struct pxa168_eth_platform_data gplugd_eth_platform_data = { + .port_number = 0, + .phy_addr = 0, + .speed = 0, /* Autonagotiation */ + .mac_addr = {0x00}, + .init = gplugd_eth_init, + .device_mac = device_mac_address, +}; + static void __init gplugd_init(void) { mfp_config(ARRAY_AND_SIZE(gplugd_pin_config)); @@ -243,12 +326,13 @@ static void __init gplugd_init(void) pxa168_add_twsi(0, &i2c_info, ARRAY_AND_SIZE(gplugd_i2c_board_info)); - pxa168_add_eth(&gplugd_eth_platform_data); + pxa168_add_spi(2, &pxa_ssp_master_info); + spi_register_board_info(gplugD_spi_board_info, + ARRAY_SIZE(gplugD_spi_board_info)); pxa168_add_ssp(2); - pxa168_add_spi(2, &pxa_ssp_master_info); - spi_register_board_info(gplugD_spi_board_info, ARRAY_SIZE(gplugD_spi_board_info)); + pxa168_add_eth(&gplugd_eth_platform_data); } MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform") diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index c3b209c..9cb99ab 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -1552,6 +1552,11 @@ static int pxa168_eth_probe(struct platform_device *pdev) pep->port_num = pep->pd->port_number; pep->phy_addr = pep->pd->phy_addr; + + if (pep->pd->device_mac) + pep->pd->device_mac(pep->pd->mac_addr); + if (is_valid_ether_addr(pep->pd->mac_addr)) + memcpy(dev->dev_addr, pep->pd->mac_addr, 6); } else if (pdev->dev.of_node) { of_property_read_u32(pdev->dev.of_node, "port-id", &pep->port_num); diff --git a/include/linux/pxa168_eth.h b/include/linux/pxa168_eth.h index 18d75e7..ca94155 100644 --- a/include/linux/pxa168_eth.h +++ b/include/linux/pxa168_eth.h @@ -20,11 +20,14 @@ struct pxa168_eth_platform_data { int rx_queue_size; int tx_queue_size; + u8 mac_addr[6]; /* mac address if non-zero*/ + /* * init callback is used for board specific initialization * e.g on Aspenite its used to initialize the PHY transceiver. */ int (*init)(void); + int (*device_mac)(u8 *mac_addr); }; #endif /* __LINUX_PXA168_ETH_H */ -- 2.10.2