summaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/mdio-boardinfo.c
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2017-02-04 22:02:44 +0100
committerDavid S. Miller <davem@davemloft.net>2017-02-07 16:51:46 +0100
commit648ea0134069cda7d4940f397bcc6901fb88752a (patch)
tree2e898d9c56777f31708c0292170eae5d76c13882 /drivers/net/phy/mdio-boardinfo.c
parentnet: dsa: Add support for platform data (diff)
downloadlinux-648ea0134069cda7d4940f397bcc6901fb88752a.tar.xz
linux-648ea0134069cda7d4940f397bcc6901fb88752a.zip
net: phy: Allow pre-declaration of MDIO devices
Allow board support code to collect pre-declarations for MDIO devices by registering them with mdiobus_register_board_info(). SPI and I2C buses have a similar feature, we were missing this for MDIO devices, but this is particularly useful for e.g: MDIO-connected switches which need to provide their port layout (often board-specific) to a MDIO Ethernet switch driver. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy/mdio-boardinfo.c')
-rw-r--r--drivers/net/phy/mdio-boardinfo.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/drivers/net/phy/mdio-boardinfo.c b/drivers/net/phy/mdio-boardinfo.c
new file mode 100644
index 000000000000..6b988f77da08
--- /dev/null
+++ b/drivers/net/phy/mdio-boardinfo.c
@@ -0,0 +1,86 @@
+/*
+ * mdio-boardinfo - Collect pre-declarations for MDIO devices
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+
+#include "mdio-boardinfo.h"
+
+static LIST_HEAD(mdio_board_list);
+static DEFINE_MUTEX(mdio_board_lock);
+
+/**
+ * mdiobus_setup_mdiodev_from_board_info - create and setup MDIO devices
+ * from pre-collected board specific MDIO information
+ * @mdiodev: MDIO device pointer
+ * Context: can sleep
+ */
+void mdiobus_setup_mdiodev_from_board_info(struct mii_bus *bus)
+{
+ struct mdio_board_entry *be;
+ struct mdio_device *mdiodev;
+ struct mdio_board_info *bi;
+ int ret;
+
+ mutex_lock(&mdio_board_lock);
+ list_for_each_entry(be, &mdio_board_list, list) {
+ bi = &be->board_info;
+
+ if (strcmp(bus->id, bi->bus_id))
+ continue;
+
+ mdiodev = mdio_device_create(bus, bi->mdio_addr);
+ if (IS_ERR(mdiodev))
+ continue;
+
+ strncpy(mdiodev->modalias, bi->modalias,
+ sizeof(mdiodev->modalias));
+ mdiodev->bus_match = mdio_device_bus_match;
+ mdiodev->dev.platform_data = (void *)bi->platform_data;
+
+ ret = mdio_device_register(mdiodev);
+ if (ret) {
+ mdio_device_free(mdiodev);
+ continue;
+ }
+ }
+ mutex_unlock(&mdio_board_lock);
+}
+
+/**
+ * mdio_register_board_info - register MDIO devices for a given board
+ * @info: array of devices descriptors
+ * @n: number of descriptors provided
+ * Context: can sleep
+ *
+ * The board info passed can be marked with __initdata but be pointers
+ * such as platform_data etc. are copied as-is
+ */
+int mdiobus_register_board_info(const struct mdio_board_info *info,
+ unsigned int n)
+{
+ struct mdio_board_entry *be;
+ unsigned int i;
+
+ be = kcalloc(n, sizeof(*be), GFP_KERNEL);
+ if (!be)
+ return -ENOMEM;
+
+ for (i = 0; i < n; i++, be++, info++) {
+ memcpy(&be->board_info, info, sizeof(*info));
+ mutex_lock(&mdio_board_lock);
+ list_add_tail(&be->list, &mdio_board_list);
+ mutex_unlock(&mdio_board_lock);
+ }
+
+ return 0;
+}