[RFC PATCH net 1/2] net: dsa: sja1105: split out the probing code into a separate driver
From: Vladimir Oltean <vladimir.oltean@nxp.com>
Date: 2021-09-09 00:18:01
Subsystem:
networking drivers, networking [dsa], the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Andrew Lunn, Vladimir Oltean, Linus Torvalds
The tag_sja1105.ko depends on the sja1105_switch_ops being exported by
the kernel before it can be inserted as a module, but at the same time,
it must be inserted into the kernel before the sja1105 driver can probe.
Solve this circular dependency by adding a third kernel module, which is
only responsible for probing the hardware and depends on the driver
which provides sja1105_switch_ops and interacts with DSA and with the
hardware at runtime, generally speaking.
Fixes: 994d2cbb08ca ("net: dsa: tag_sja1105: be dsa_loop-safe")
Link: https://lore.kernel.org/netdev/20210908220834.d7gmtnwrorhharna@skbuf/ (local)
Suggested-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/net/dsa/sja1105/Kconfig | 4 +
drivers/net/dsa/sja1105/Makefile | 2 +
drivers/net/dsa/sja1105/sja1105_main.c | 316 -----------------
drivers/net/dsa/sja1105/sja1105_probe.c | 322 ++++++++++++++++++
drivers/net/dsa/sja1105/sja1105_spi.c | 12 +
.../net/dsa/sja1105/sja1105_static_config.c | 1 +
6 files changed, 341 insertions(+), 316 deletions(-)
create mode 100644 drivers/net/dsa/sja1105/sja1105_probe.c
diff --git a/drivers/net/dsa/sja1105/Kconfig b/drivers/net/dsa/sja1105/Kconfig
index 1291bba3f3b6..33f948d9ea18 100644
--- a/drivers/net/dsa/sja1105/Kconfig
+++ b/drivers/net/dsa/sja1105/Kconfig@@ -23,6 +23,10 @@ tristate "NXP SJA1105 Ethernet switch family support" - SJA1110C (Gen. 3, SGMII, TT-Ethernet, 100base-TX PHY, 7 ports) - SJA1110D (Gen. 3, SGMII, TT-Ethernet, no 100base-TX PHY, 7 ports) +config NET_DSA_SJA1105_PROBE +tristate "Actual driver that probes the hardware" + depends on NET_DSA_SJA1105 + config NET_DSA_SJA1105_PTP bool "Support for the PTP clock on the NXP SJA1105 Ethernet switch" depends on NET_DSA_SJA1105
diff --git a/drivers/net/dsa/sja1105/Makefile b/drivers/net/dsa/sja1105/Makefile
index 40d69e6c0bae..73b4281f8218 100644
--- a/drivers/net/dsa/sja1105/Makefile
+++ b/drivers/net/dsa/sja1105/Makefile@@ -23,3 +23,5 @@ endif ifdef CONFIG_NET_DSA_SJA1105_VL sja1105-objs += sja1105_vl.o endif + +obj-$(CONFIG_NET_DSA_SJA1105_PROBE) += sja1105_probe.o
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 2f8cc6686c38..01ef4839f631 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c@@ -10,12 +10,8 @@ #include <linux/printk.h> #include <linux/spi/spi.h> #include <linux/errno.h> -#include <linux/gpio/consumer.h> #include <linux/phylink.h> #include <linux/of.h> -#include <linux/of_net.h> -#include <linux/of_mdio.h> -#include <linux/of_device.h> #include <linux/pcs/pcs-xpcs.h> #include <linux/netdev_features.h> #include <linux/netdevice.h>
@@ -27,17 +23,6 @@ #define SJA1105_UNKNOWN_MULTICAST 0x010000000000ull -static void sja1105_hw_reset(struct gpio_desc *gpio, unsigned int pulse_len, - unsigned int startup_delay) -{ - gpiod_set_value_cansleep(gpio, 1); - /* Wait for minimum reset pulse length */ - msleep(pulse_len); - gpiod_set_value_cansleep(gpio, 0); - /* Wait until chip is ready after reset */ - msleep(startup_delay); -} - static void sja1105_port_allow_traffic(struct sja1105_l2_forwarding_entry *l2_fwd, int from, int to, bool allow)
@@ -1095,103 +1080,6 @@ static int sja1105_static_config_load(struct sja1105_private *priv) return sja1105_static_config_upload(priv); } -static int sja1105_parse_rgmii_delays(struct sja1105_private *priv) -{ - struct dsa_switch *ds = priv->ds; - int port; - - for (port = 0; port < ds->num_ports; port++) { - if (!priv->fixed_link[port]) - continue; - - if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_RXID || - priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID) - priv->rgmii_rx_delay[port] = true; - - if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_TXID || - priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID) - priv->rgmii_tx_delay[port] = true; - - if ((priv->rgmii_rx_delay[port] || priv->rgmii_tx_delay[port]) && - !priv->info->setup_rgmii_delay) - return -EINVAL; - } - return 0; -} - -static int sja1105_parse_ports_node(struct sja1105_private *priv, - struct device_node *ports_node) -{ - struct device *dev = &priv->spidev->dev; - struct device_node *child; - - for_each_available_child_of_node(ports_node, child) { - struct device_node *phy_node; - phy_interface_t phy_mode; - u32 index; - int err; - - /* Get switch port number from DT */ - if (of_property_read_u32(child, "reg", &index) < 0) { - dev_err(dev, "Port number not defined in device tree " - "(property \"reg\")\n"); - of_node_put(child); - return -ENODEV; - } - - /* Get PHY mode from DT */ - err = of_get_phy_mode(child, &phy_mode); - if (err) { - dev_err(dev, "Failed to read phy-mode or " - "phy-interface-type property for port %d\n", - index); - of_node_put(child); - return -ENODEV; - } - - phy_node = of_parse_phandle(child, "phy-handle", 0); - if (!phy_node) { - if (!of_phy_is_fixed_link(child)) { - dev_err(dev, "phy-handle or fixed-link " - "properties missing!\n"); - of_node_put(child); - return -ENODEV; - } - /* phy-handle is missing, but fixed-link isn't. - * So it's a fixed link. Default to PHY role. - */ - priv->fixed_link[index] = true; - } else { - of_node_put(phy_node); - } - - priv->phy_mode[index] = phy_mode; - } - - return 0; -} - -static int sja1105_parse_dt(struct sja1105_private *priv) -{ - struct device *dev = &priv->spidev->dev; - struct device_node *switch_node = dev->of_node; - struct device_node *ports_node; - int rc; - - ports_node = of_get_child_by_name(switch_node, "ports"); - if (!ports_node) - ports_node = of_get_child_by_name(switch_node, "ethernet-ports"); - if (!ports_node) { - dev_err(dev, "Incorrect bindings: absent \"ports\" node\n"); - return -ENODEV; - } - - rc = sja1105_parse_ports_node(priv, ports_node); - of_node_put(ports_node); - - return rc; -} - /* Convert link speed from SJA1105 to ethtool encoding */ static int sja1105_port_speed_to_ethtool(struct sja1105_private *priv, u64 speed)
@@ -3168,208 +3056,4 @@ const struct dsa_switch_ops sja1105_switch_ops = { }; EXPORT_SYMBOL_GPL(sja1105_switch_ops); -static const struct of_device_id sja1105_dt_ids[]; - -static int sja1105_check_device_id(struct sja1105_private *priv) -{ - const struct sja1105_regs *regs = priv->info->regs; - u8 prod_id[SJA1105_SIZE_DEVICE_ID] = {0}; - struct device *dev = &priv->spidev->dev; - const struct of_device_id *match; - u32 device_id; - u64 part_no; - int rc; - - rc = sja1105_xfer_u32(priv, SPI_READ, regs->device_id, &device_id, - NULL); - if (rc < 0) - return rc; - - rc = sja1105_xfer_buf(priv, SPI_READ, regs->prod_id, prod_id, - SJA1105_SIZE_DEVICE_ID); - if (rc < 0) - return rc; - - sja1105_unpack(prod_id, &part_no, 19, 4, SJA1105_SIZE_DEVICE_ID); - - for (match = sja1105_dt_ids; match->compatible[0]; match++) { - const struct sja1105_info *info = match->data; - - /* Is what's been probed in our match table at all? */ - if (info->device_id != device_id || info->part_no != part_no) - continue; - - /* But is it what's in the device tree? */ - if (priv->info->device_id != device_id || - priv->info->part_no != part_no) { - dev_warn(dev, "Device tree specifies chip %s but found %s, please fix it!\n", - priv->info->name, info->name); - /* It isn't. No problem, pick that up. */ - priv->info = info; - } - - return 0; - } - - dev_err(dev, "Unexpected {device ID, part number}: 0x%x 0x%llx\n", - device_id, part_no); - - return -ENODEV; -} - -static int sja1105_probe(struct spi_device *spi) -{ - struct device *dev = &spi->dev; - struct sja1105_private *priv; - size_t max_xfer, max_msg; - struct dsa_switch *ds; - int rc; - - if (!dev->of_node) { - dev_err(dev, "No DTS bindings for SJA1105 driver\n"); - return -EINVAL; - } - - priv = devm_kzalloc(dev, sizeof(struct sja1105_private), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - /* Configure the optional reset pin and bring up switch */ - priv->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(priv->reset_gpio)) - dev_dbg(dev, "reset-gpios not defined, ignoring\n"); - else - sja1105_hw_reset(priv->reset_gpio, 1, 1); - - /* Populate our driver private structure (priv) based on - * the device tree node that was probed (spi) - */ - priv->spidev = spi; - spi_set_drvdata(spi, priv); - - /* Configure the SPI bus */ - spi->bits_per_word = 8; - rc = spi_setup(spi); - if (rc < 0) { - dev_err(dev, "Could not init SPI\n"); - return rc; - } - - /* In sja1105_xfer, we send spi_messages composed of two spi_transfers: - * a small one for the message header and another one for the current - * chunk of the packed buffer. - * Check that the restrictions imposed by the SPI controller are - * respected: the chunk buffer is smaller than the max transfer size, - * and the total length of the chunk plus its message header is smaller - * than the max message size. - * We do that during probe time since the maximum transfer size is a - * runtime invariant. - */ - max_xfer = spi_max_transfer_size(spi); - max_msg = spi_max_message_size(spi); - - /* We need to send at least one 64-bit word of SPI payload per message - * in order to be able to make useful progress. - */ - if (max_msg < SJA1105_SIZE_SPI_MSG_HEADER + 8) { - dev_err(dev, "SPI master cannot send large enough buffers, aborting\n"); - return -EINVAL; - } - - priv->max_xfer_len = SJA1105_SIZE_SPI_MSG_MAXLEN; - if (priv->max_xfer_len > max_xfer) - priv->max_xfer_len = max_xfer; - if (priv->max_xfer_len > max_msg - SJA1105_SIZE_SPI_MSG_HEADER) - priv->max_xfer_len = max_msg - SJA1105_SIZE_SPI_MSG_HEADER; - - priv->info = of_device_get_match_data(dev); - - /* Detect hardware device */ - rc = sja1105_check_device_id(priv); - if (rc < 0) { - dev_err(dev, "Device ID check failed: %d\n", rc); - return rc; - } - - dev_info(dev, "Probed switch chip: %s\n", priv->info->name); - - ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL); - if (!ds) - return -ENOMEM; - - ds->dev = dev; - ds->num_ports = priv->info->num_ports; - ds->ops = &sja1105_switch_ops; - ds->priv = priv; - priv->ds = ds; - - mutex_init(&priv->ptp_data.lock); - mutex_init(&priv->mgmt_lock); - - rc = sja1105_parse_dt(priv); - if (rc < 0) { - dev_err(ds->dev, "Failed to parse DT: %d\n", rc); - return rc; - } - - /* Error out early if internal delays are required through DT - * and we can't apply them. - */ - rc = sja1105_parse_rgmii_delays(priv); - if (rc < 0) { - dev_err(ds->dev, "RGMII delay not supported\n"); - return rc; - } - - if (IS_ENABLED(CONFIG_NET_SCH_CBS)) { - priv->cbs = devm_kcalloc(dev, priv->info->num_cbs_shapers, - sizeof(struct sja1105_cbs_entry), - GFP_KERNEL); - if (!priv->cbs) - return -ENOMEM; - } - - return dsa_register_switch(priv->ds); -} - -static int sja1105_remove(struct spi_device *spi) -{ - struct sja1105_private *priv = spi_get_drvdata(spi); - struct dsa_switch *ds = priv->ds; - - dsa_unregister_switch(ds); - - return 0; -} - -static const struct of_device_id sja1105_dt_ids[] = { - { .compatible = "nxp,sja1105e", .data = &sja1105e_info }, - { .compatible = "nxp,sja1105t", .data = &sja1105t_info }, - { .compatible = "nxp,sja1105p", .data = &sja1105p_info }, - { .compatible = "nxp,sja1105q", .data = &sja1105q_info }, - { .compatible = "nxp,sja1105r", .data = &sja1105r_info }, - { .compatible = "nxp,sja1105s", .data = &sja1105s_info }, - { .compatible = "nxp,sja1110a", .data = &sja1110a_info }, - { .compatible = "nxp,sja1110b", .data = &sja1110b_info }, - { .compatible = "nxp,sja1110c", .data = &sja1110c_info }, - { .compatible = "nxp,sja1110d", .data = &sja1110d_info }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, sja1105_dt_ids); - -static struct spi_driver sja1105_driver = { - .driver = { - .name = "sja1105", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(sja1105_dt_ids), - }, - .probe = sja1105_probe, - .remove = sja1105_remove, -}; - -module_spi_driver(sja1105_driver); - -MODULE_AUTHOR("Vladimir Oltean <olteanv@gmail.com>"); -MODULE_AUTHOR("Georg Waibel <georg.waibel@sensor-technik.de>"); -MODULE_DESCRIPTION("SJA1105 Driver"); MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/dsa/sja1105/sja1105_probe.c b/drivers/net/dsa/sja1105/sja1105_probe.c
new file mode 100644
index 000000000000..debb9bcd788c
--- /dev/null
+++ b/drivers/net/dsa/sja1105/sja1105_probe.c@@ -0,0 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright 2021 NXP */ +#include <linux/gpio/consumer.h> +#include <linux/of_device.h> +#include <linux/of_mdio.h> +#include <linux/of_net.h> +#include <linux/spi/spi.h> +#include "sja1105.h" + +static void sja1105_hw_reset(struct gpio_desc *gpio, unsigned int pulse_len, + unsigned int startup_delay) +{ + gpiod_set_value_cansleep(gpio, 1); + /* Wait for minimum reset pulse length */ + msleep(pulse_len); + gpiod_set_value_cansleep(gpio, 0); + /* Wait until chip is ready after reset */ + msleep(startup_delay); +} + +static int sja1105_parse_rgmii_delays(struct sja1105_private *priv) +{ + struct dsa_switch *ds = priv->ds; + int port; + + for (port = 0; port < ds->num_ports; port++) { + if (!priv->fixed_link[port]) + continue; + + if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_RXID || + priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID) + priv->rgmii_rx_delay[port] = true; + + if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_TXID || + priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID) + priv->rgmii_tx_delay[port] = true; + + if ((priv->rgmii_rx_delay[port] || priv->rgmii_tx_delay[port]) && + !priv->info->setup_rgmii_delay) + return -EINVAL; + } + return 0; +} + +static int sja1105_parse_ports_node(struct sja1105_private *priv, + struct device_node *ports_node) +{ + struct device *dev = &priv->spidev->dev; + struct device_node *child; + + for_each_available_child_of_node(ports_node, child) { + struct device_node *phy_node; + phy_interface_t phy_mode; + u32 index; + int err; + + /* Get switch port number from DT */ + if (of_property_read_u32(child, "reg", &index) < 0) { + dev_err(dev, "Port number not defined in device tree " + "(property \"reg\")\n"); + of_node_put(child); + return -ENODEV; + } + + /* Get PHY mode from DT */ + err = of_get_phy_mode(child, &phy_mode); + if (err) { + dev_err(dev, "Failed to read phy-mode or " + "phy-interface-type property for port %d\n", + index); + of_node_put(child); + return -ENODEV; + } + + phy_node = of_parse_phandle(child, "phy-handle", 0); + if (!phy_node) { + if (!of_phy_is_fixed_link(child)) { + dev_err(dev, "phy-handle or fixed-link " + "properties missing!\n"); + of_node_put(child); + return -ENODEV; + } + /* phy-handle is missing, but fixed-link isn't. + * So it's a fixed link. Default to PHY role. + */ + priv->fixed_link[index] = true; + } else { + of_node_put(phy_node); + } + + priv->phy_mode[index] = phy_mode; + } + + return 0; +} + +static int sja1105_parse_dt(struct sja1105_private *priv) +{ + struct device *dev = &priv->spidev->dev; + struct device_node *switch_node = dev->of_node; + struct device_node *ports_node; + int rc; + + ports_node = of_get_child_by_name(switch_node, "ports"); + if (!ports_node) + ports_node = of_get_child_by_name(switch_node, "ethernet-ports"); + if (!ports_node) { + dev_err(dev, "Incorrect bindings: absent \"ports\" node\n"); + return -ENODEV; + } + + rc = sja1105_parse_ports_node(priv, ports_node); + of_node_put(ports_node); + + return rc; +} + +static const struct of_device_id sja1105_dt_ids[]; + +static int sja1105_check_device_id(struct sja1105_private *priv) +{ + const struct sja1105_regs *regs = priv->info->regs; + u8 prod_id[SJA1105_SIZE_DEVICE_ID] = {0}; + struct device *dev = &priv->spidev->dev; + const struct of_device_id *match; + u32 device_id; + u64 part_no; + int rc; + + rc = sja1105_xfer_u32(priv, SPI_READ, regs->device_id, &device_id, + NULL); + if (rc < 0) + return rc; + + rc = sja1105_xfer_buf(priv, SPI_READ, regs->prod_id, prod_id, + SJA1105_SIZE_DEVICE_ID); + if (rc < 0) + return rc; + + sja1105_unpack(prod_id, &part_no, 19, 4, SJA1105_SIZE_DEVICE_ID); + + for (match = sja1105_dt_ids; match->compatible[0]; match++) { + const struct sja1105_info *info = match->data; + + /* Is what's been probed in our match table at all? */ + if (info->device_id != device_id || info->part_no != part_no) + continue; + + /* But is it what's in the device tree? */ + if (priv->info->device_id != device_id || + priv->info->part_no != part_no) { + dev_warn(dev, "Device tree specifies chip %s but found %s, please fix it!\n", + priv->info->name, info->name); + /* It isn't. No problem, pick that up. */ + priv->info = info; + } + + return 0; + } + + dev_err(dev, "Unexpected {device ID, part number}: 0x%x 0x%llx\n", + device_id, part_no); + + return -ENODEV; +} + +static int sja1105_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct sja1105_private *priv; + size_t max_xfer, max_msg; + struct dsa_switch *ds; + int rc; + + if (!dev->of_node) { + dev_err(dev, "No DTS bindings for SJA1105 driver\n"); + return -EINVAL; + } + + priv = devm_kzalloc(dev, sizeof(struct sja1105_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* Configure the optional reset pin and bring up switch */ + priv->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(priv->reset_gpio)) + dev_dbg(dev, "reset-gpios not defined, ignoring\n"); + else + sja1105_hw_reset(priv->reset_gpio, 1, 1); + + /* Populate our driver private structure (priv) based on + * the device tree node that was probed (spi) + */ + priv->spidev = spi; + spi_set_drvdata(spi, priv); + + /* Configure the SPI bus */ + spi->bits_per_word = 8; + rc = spi_setup(spi); + if (rc < 0) { + dev_err(dev, "Could not init SPI\n"); + return rc; + } + + /* In sja1105_xfer, we send spi_messages composed of two spi_transfers: + * a small one for the message header and another one for the current + * chunk of the packed buffer. + * Check that the restrictions imposed by the SPI controller are + * respected: the chunk buffer is smaller than the max transfer size, + * and the total length of the chunk plus its message header is smaller + * than the max message size. + * We do that during probe time since the maximum transfer size is a + * runtime invariant. + */ + max_xfer = spi_max_transfer_size(spi); + max_msg = spi_max_message_size(spi); + + /* We need to send at least one 64-bit word of SPI payload per message + * in order to be able to make useful progress. + */ + if (max_msg < SJA1105_SIZE_SPI_MSG_HEADER + 8) { + dev_err(dev, "SPI master cannot send large enough buffers, aborting\n"); + return -EINVAL; + } + + priv->max_xfer_len = SJA1105_SIZE_SPI_MSG_MAXLEN; + if (priv->max_xfer_len > max_xfer) + priv->max_xfer_len = max_xfer; + if (priv->max_xfer_len > max_msg - SJA1105_SIZE_SPI_MSG_HEADER) + priv->max_xfer_len = max_msg - SJA1105_SIZE_SPI_MSG_HEADER; + + priv->info = of_device_get_match_data(dev); + + /* Detect hardware device */ + rc = sja1105_check_device_id(priv); + if (rc < 0) { + dev_err(dev, "Device ID check failed: %d\n", rc); + return rc; + } + + dev_info(dev, "Probed switch chip: %s\n", priv->info->name); + + ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL); + if (!ds) + return -ENOMEM; + + ds->dev = dev; + ds->num_ports = priv->info->num_ports; + ds->ops = &sja1105_switch_ops; + ds->priv = priv; + priv->ds = ds; + + mutex_init(&priv->ptp_data.lock); + mutex_init(&priv->mgmt_lock); + + rc = sja1105_parse_dt(priv); + if (rc < 0) { + dev_err(ds->dev, "Failed to parse DT: %d\n", rc); + return rc; + } + + /* Error out early if internal delays are required through DT + * and we can't apply them. + */ + rc = sja1105_parse_rgmii_delays(priv); + if (rc < 0) { + dev_err(ds->dev, "RGMII delay not supported\n"); + return rc; + } + + if (IS_ENABLED(CONFIG_NET_SCH_CBS)) { + priv->cbs = devm_kcalloc(dev, priv->info->num_cbs_shapers, + sizeof(struct sja1105_cbs_entry), + GFP_KERNEL); + if (!priv->cbs) + return -ENOMEM; + } + + return dsa_register_switch(priv->ds); +} + +static int sja1105_remove(struct spi_device *spi) +{ + struct sja1105_private *priv = spi_get_drvdata(spi); + struct dsa_switch *ds = priv->ds; + + dsa_unregister_switch(ds); + + return 0; +} + +static const struct of_device_id sja1105_dt_ids[] = { + { .compatible = "nxp,sja1105e", .data = &sja1105e_info }, + { .compatible = "nxp,sja1105t", .data = &sja1105t_info }, + { .compatible = "nxp,sja1105p", .data = &sja1105p_info }, + { .compatible = "nxp,sja1105q", .data = &sja1105q_info }, + { .compatible = "nxp,sja1105r", .data = &sja1105r_info }, + { .compatible = "nxp,sja1105s", .data = &sja1105s_info }, + { .compatible = "nxp,sja1110a", .data = &sja1110a_info }, + { .compatible = "nxp,sja1110b", .data = &sja1110b_info }, + { .compatible = "nxp,sja1110c", .data = &sja1110c_info }, + { .compatible = "nxp,sja1110d", .data = &sja1110d_info }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, sja1105_dt_ids); + +static struct spi_driver sja1105_driver = { + .driver = { + .name = "sja1105", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(sja1105_dt_ids), + }, + .probe = sja1105_probe, + .remove = sja1105_remove, +}; + +module_spi_driver(sja1105_driver); + +MODULE_AUTHOR("Vladimir Oltean <olteanv@gmail.com>"); +MODULE_AUTHOR("Georg Waibel <georg.waibel@sensor-technik.de>"); +MODULE_DESCRIPTION("SJA1105 Driver"); +MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c
index d60a530d0272..420c21bfd6b5 100644
--- a/drivers/net/dsa/sja1105/sja1105_spi.c
+++ b/drivers/net/dsa/sja1105/sja1105_spi.c@@ -118,6 +118,7 @@ int sja1105_xfer_buf(const struct sja1105_private *priv, { return sja1105_xfer(priv, rw, reg_addr, buf, len, NULL); } +EXPORT_SYMBOL_GPL(sja1105_xfer_buf); /* If @rw is: * - SPI_WRITE: creates and sends an SPI write message at absolute
@@ -172,6 +173,7 @@ int sja1105_xfer_u32(const struct sja1105_private *priv, return rc; } +EXPORT_SYMBOL_GPL(sja1105_xfer_u32); static int sja1105et_reset_cmd(struct dsa_switch *ds) {
@@ -601,6 +603,7 @@ const struct sja1105_info sja1105e_info = { .supports_rgmii = {true, true, true, true, true}, .name = "SJA1105E", }; +EXPORT_SYMBOL_GPL(sja1105e_info); const struct sja1105_info sja1105t_info = { .device_id = SJA1105T_DEVICE_ID,
@@ -633,6 +636,7 @@ const struct sja1105_info sja1105t_info = { .supports_rgmii = {true, true, true, true, true}, .name = "SJA1105T", }; +EXPORT_SYMBOL_GPL(sja1105t_info); const struct sja1105_info sja1105p_info = { .device_id = SJA1105PR_DEVICE_ID,
@@ -666,6 +670,7 @@ const struct sja1105_info sja1105p_info = { .supports_rgmii = {true, true, true, true, true}, .name = "SJA1105P", }; +EXPORT_SYMBOL_GPL(sja1105p_info); const struct sja1105_info sja1105q_info = { .device_id = SJA1105QS_DEVICE_ID,
@@ -699,6 +704,7 @@ const struct sja1105_info sja1105q_info = { .supports_rgmii = {true, true, true, true, true}, .name = "SJA1105Q", }; +EXPORT_SYMBOL_GPL(sja1105q_info); const struct sja1105_info sja1105r_info = { .device_id = SJA1105PR_DEVICE_ID,
@@ -735,6 +741,7 @@ const struct sja1105_info sja1105r_info = { .supports_sgmii = {false, false, false, false, true}, .name = "SJA1105R", }; +EXPORT_SYMBOL_GPL(sja1105r_info); const struct sja1105_info sja1105s_info = { .device_id = SJA1105QS_DEVICE_ID,
@@ -771,6 +778,7 @@ const struct sja1105_info sja1105s_info = { .supports_sgmii = {false, false, false, false, true}, .name = "SJA1105S", }; +EXPORT_SYMBOL_GPL(sja1105s_info); const struct sja1105_info sja1110a_info = { .device_id = SJA1110_DEVICE_ID,
@@ -821,6 +829,7 @@ const struct sja1105_info sja1110a_info = { SJA1105_PHY_BASE_T1}, .name = "SJA1110A", }; +EXPORT_SYMBOL_GPL(sja1110a_info); const struct sja1105_info sja1110b_info = { .device_id = SJA1110_DEVICE_ID,
@@ -871,6 +880,7 @@ const struct sja1105_info sja1110b_info = { SJA1105_NO_PHY}, .name = "SJA1110B", }; +EXPORT_SYMBOL_GPL(sja1110b_info); const struct sja1105_info sja1110c_info = { .device_id = SJA1110_DEVICE_ID,
@@ -921,6 +931,7 @@ const struct sja1105_info sja1110c_info = { SJA1105_NO_PHY}, .name = "SJA1110C", }; +EXPORT_SYMBOL_GPL(sja1110c_info); const struct sja1105_info sja1110d_info = { .device_id = SJA1110_DEVICE_ID,
@@ -971,3 +982,4 @@ const struct sja1105_info sja1110d_info = { SJA1105_NO_PHY}, .name = "SJA1110D", }; +EXPORT_SYMBOL_GPL(sja1110d_info);
diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.c b/drivers/net/dsa/sja1105/sja1105_static_config.c
index 7a422ef4deb6..d5bca0d43b21 100644
--- a/drivers/net/dsa/sja1105/sja1105_static_config.c
+++ b/drivers/net/dsa/sja1105/sja1105_static_config.c@@ -52,6 +52,7 @@ void sja1105_unpack(const void *buf, u64 *val, int start, int end, size_t len) start, end); dump_stack(); } +EXPORT_SYMBOL_GPL(sja1105_unpack); void sja1105_packing(void *buf, u64 *val, int start, int end, size_t len, enum packing_op op)
--
2.25.1