[RFC 1/2] misc: Add MAC address mapper "driver"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add Barebox specific device tree provisions to allow specifying MAC
addresses for network interfaces via device tree.

Signed-off-by: Andrey Smirnov <andrew.smirnov@xxxxxxxxx>
---
 .../bindings/barebox/barebox,mac-address-map.rst   |  27 ++++
 drivers/misc/Makefile                              |   1 +
 drivers/misc/mac-address-map.c                     | 142 +++++++++++++++++++++
 3 files changed, 170 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/barebox/barebox,mac-address-map.rst
 create mode 100644 drivers/misc/mac-address-map.c

diff --git a/Documentation/devicetree/bindings/barebox/barebox,mac-address-map.rst b/Documentation/devicetree/bindings/barebox/barebox,mac-address-map.rst
new file mode 100644
index 0000000..1ac3062
--- /dev/null
+++ b/Documentation/devicetree/bindings/barebox/barebox,mac-address-map.rst
@@ -0,0 +1,27 @@
+barebox MAC address map
+=======================
+
+This driver allows to specify each network adapter's source of MAC address from the devicetree.
+
+Required properties:
+
+* ``compatible``: should be ``barebox,mac-address-map``
+
+Besides ``compatible`` property the node is expected to contain a
+number of children nodes each specifing a single "MAC source ->
+interface" mapping.
+
+Child node's required properties:
+* ``network-interface``: phandle corresponding to network interface
+* ``mac-location``: a pair of phandle to 'cdev' containing MAC address
+  and offset withing that 'cdev'
+
+Example::
+
+  mac-address-map {
+	compatible = "barebox,mac-address-map";
+	nic@0 {
+		network-interface = <&fec>;
+		mac-location = <&ocotp 0x88>;
+	};
+  };
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 487e4b8..94d2a4f 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_JTAG)		+= jtag.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-$(CONFIG_STATE_DRV)		+= state.o
+obj-y += mac-address-map.o
diff --git a/drivers/misc/mac-address-map.c b/drivers/misc/mac-address-map.c
new file mode 100644
index 0000000..2161dc3
--- /dev/null
+++ b/drivers/misc/mac-address-map.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 Zodiac Inflight Innovation
+ * Author: Andrey Smirnov <andrew.smirnov@xxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <of.h>
+#include <state.h>
+#include <io.h>
+#include <fcntl.h>
+#include <net.h>
+
+#include <linux/err.h>
+
+/*
+ * a single MAC address reference has the form
+ * <&phandle regoffset>
+ */
+#define MAC_ADDRESS_PROPLEN	(2 * sizeof(__be32))
+#define MAC_ADDRESS_SIZE	8 /* FIXME ocotp driver is broken and
+				   * can't read non multiple of 4
+				   * quantities of data */
+
+static int mac_address_map_read_cdev(struct device_d *dev,
+				     struct cdev *cdev,
+				     size_t offset,
+				     uint8_t *addr)
+{
+	int ret;
+
+	ret = cdev_do_open(cdev, O_RDONLY);
+	if (ret < 0) {
+		dev_err(dev, "Failed to open %s\n", cdev->name);
+		return ret;
+	}
+
+	ret = cdev_read(cdev, addr, MAC_ADDRESS_SIZE, offset, 0);
+	cdev_close(cdev);
+
+	if (ret != MAC_ADDRESS_SIZE) {
+		dev_err(dev, "Failed to read MAC address\n");
+		return (ret < 0) ? ret : -EIO;
+	}
+
+	return 0;
+}
+
+static int mac_address_map_probe(struct device_d *dev)
+{
+	int ret;
+	struct device_node *np = dev->device_node;
+	struct device_node *child;
+
+	if (!np || !of_get_next_child(np, NULL))
+		return -EINVAL;
+
+	for_each_child_of_node(np, child) {
+		uint8_t addr[MAC_ADDRESS_SIZE];
+
+		struct {
+			const __be32 *prop;
+			int plen;
+			uint32_t phandle;
+			size_t offset;
+			struct cdev *cdev;
+			struct device_node *node;
+		} nvm;
+
+		struct device_node *nic_node;
+
+		nvm.prop = of_get_property(child, "mac-location", &nvm.plen);
+
+		if (!nvm.prop || nvm.plen != MAC_ADDRESS_PROPLEN) {
+			dev_err(dev, "'mac-location' lookup failed\n");
+			return -EINVAL;
+		}
+
+		nvm.phandle = be32_to_cpup(nvm.prop);
+		nvm.offset  = be32_to_cpup(++nvm.prop);
+
+		nvm.node = of_find_node_by_phandle(nvm.phandle);
+		if (!nvm.node) {
+			dev_err(dev, "'mac-location' lookup failed\n");
+			return -EINVAL;
+		}
+
+		nvm.cdev = cdev_by_device_node(nvm.node);
+		if (!nvm.cdev) {
+			dev_err(dev, "no OCOTP character device\n");
+			return -ENODEV;
+		}
+
+		nic_node = of_parse_phandle(child, "network-interface", 0);
+		if (!nic_node) {
+			dev_err(dev, "'network-interface' lookup failed\n");
+			return -EINVAL;
+		}
+
+		ret = mac_address_map_read_cdev(dev,
+						nvm.cdev, nvm.offset,
+						addr);
+		if (ret < 0)
+			return ret;
+
+		if (is_valid_ether_addr(addr))
+			of_eth_register_ethaddr(nic_node, addr);
+		else
+			dev_warn(dev,
+				 "%s @ 0x%x does not contain a vaild MAC address\n",
+				 nvm.node->name, nvm.offset);
+	}
+
+	return 0;
+}
+
+static __maybe_unused struct of_device_id mac_address_map_ids[] = {
+	{
+		.compatible = "barebox,mac-address-map",
+	}, {
+		/* sentinel */
+	}
+};
+
+static struct driver_d mac_address_map_driver = {
+	.name = "mac-address-map",
+	.probe = mac_address_map_probe,
+	.of_compatible = DRV_OF_COMPAT(mac_address_map_ids),
+};
+device_platform_driver(mac_address_map_driver);
-- 
2.5.0


_______________________________________________
barebox mailing list
barebox@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/barebox



[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux