PKGBUILDs/core/linux-mmp/0005-mmp-ethernet-Adding-ethernet-MAC-address-reading-for.patch
2016-05-02 01:47:12 +00:00

223 lines
6.4 KiB
Diff

From 0301652be6fa93f3f0cd6de523cfc896c868d312 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/8] 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 <mach/pxa168.h>
#include <mach/mfp-pxa168.h>
+#include <uapi/linux/ethtool.h>
+#include <linux/etherdevice.h>
#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.8.0