mirror of
https://github.com/archlinuxarm/PKGBUILDs.git
synced 2024-10-29 22:43:48 +00:00
224 lines
6.4 KiB
Diff
224 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
|
||
|
|