[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20220504151755.11737-8-arun.ramadoss@microchip.com>
Date: Wed, 4 May 2022 20:47:49 +0530
From: Arun Ramadoss <arun.ramadoss@...rochip.com>
To: <bpf@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
<devicetree@...r.kernel.org>, <netdev@...r.kernel.org>
CC: KP Singh <kpsingh@...nel.org>,
John Fastabend <john.fastabend@...il.com>,
Yonghong Song <yhs@...com>, Song Liu <songliubraving@...com>,
"Martin KaFai Lau" <kafai@...com>,
Andrii Nakryiko <andrii@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>,
Alexei Starovoitov <ast@...nel.org>,
Russell King <linux@...linux.org.uk>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@...aro.org>,
Woojung Huh <woojung.huh@...rochip.com>,
<UNGLinuxDriver@...rochip.com>, Andrew Lunn <andrew@...n.ch>,
Vivien Didelot <vivien.didelot@...il.com>,
Florian Fainelli <f.fainelli@...il.com>,
"Vladimir Oltean" <olteanv@...il.com>,
"David S. Miller" <davem@...emloft.net>,
"Eric Dumazet" <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
Rob Herring <robh+dt@...nel.org>
Subject: [Patch net-next v13 07/13] net: dsa: microchip: add LAN937x SPI driver
This patch add the SPI driver for the LAN937x switches. It uses the
lan937x_main.c and lan937x_dev.c functions.
Signed-off-by: Arun Ramadoss <arun.ramadoss@...rochip.com>
---
drivers/net/dsa/microchip/Makefile | 1 +
drivers/net/dsa/microchip/ksz_common.h | 1 +
drivers/net/dsa/microchip/lan937x_dev.c | 7 +
drivers/net/dsa/microchip/lan937x_spi.c | 236 ++++++++++++++++++++++++
4 files changed, 245 insertions(+)
create mode 100644 drivers/net/dsa/microchip/lan937x_spi.c
diff --git a/drivers/net/dsa/microchip/Makefile b/drivers/net/dsa/microchip/Makefile
index d32ff38dc240..28d8eb62a795 100644
--- a/drivers/net/dsa/microchip/Makefile
+++ b/drivers/net/dsa/microchip/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8863_SMI) += ksz8863_smi.o
obj-$(CONFIG_NET_DSA_MICROCHIP_LAN937X) += lan937x.o
lan937x-objs := lan937x_dev.o
lan937x-objs += lan937x_main.o
+lan937x-objs += lan937x_spi.o
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 5671f580948d..fd9e0705d2d2 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -151,6 +151,7 @@ void ksz_switch_remove(struct ksz_device *dev);
int ksz8_switch_register(struct ksz_device *dev);
int ksz9477_switch_register(struct ksz_device *dev);
int lan937x_switch_register(struct ksz_device *dev);
+int lan937x_check_device_id(struct ksz_device *dev);
void ksz_update_port_member(struct ksz_device *dev, int port);
void ksz_init_mib_timer(struct ksz_device *dev);
diff --git a/drivers/net/dsa/microchip/lan937x_dev.c b/drivers/net/dsa/microchip/lan937x_dev.c
index 3f1797cc1d16..f430a8711775 100644
--- a/drivers/net/dsa/microchip/lan937x_dev.c
+++ b/drivers/net/dsa/microchip/lan937x_dev.c
@@ -386,8 +386,15 @@ static int lan937x_mdio_register(struct ksz_device *dev)
static int lan937x_switch_init(struct ksz_device *dev)
{
+ int ret;
+
dev->ds->ops = &lan937x_switch_ops;
+ /* Check device tree */
+ ret = lan937x_check_device_id(dev);
+ if (ret < 0)
+ return ret;
+
dev->port_mask = (1 << dev->port_cnt) - 1;
dev->ports = devm_kzalloc(dev->dev,
diff --git a/drivers/net/dsa/microchip/lan937x_spi.c b/drivers/net/dsa/microchip/lan937x_spi.c
new file mode 100644
index 000000000000..a50dfcf27aff
--- /dev/null
+++ b/drivers/net/dsa/microchip/lan937x_spi.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Microchip LAN937X switch driver register access through SPI
+ * Copyright (C) 2019-2021 Microchip Technology Inc.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <linux/of_device.h>
+
+#include "ksz_common.h"
+
+#define SPI_ADDR_SHIFT 24
+#define SPI_ADDR_ALIGN 3
+#define SPI_TURNAROUND_SHIFT 5
+
+KSZ_REGMAP_TABLE(lan937x, 32, SPI_ADDR_SHIFT, SPI_TURNAROUND_SHIFT,
+ SPI_ADDR_ALIGN);
+
+struct lan937x_chip_data {
+ u32 chip_id;
+ const char *dev_name;
+ int num_vlans;
+ int num_alus;
+ int num_statics;
+ int cpu_ports;
+ int port_cnt;
+};
+
+static const struct of_device_id lan937x_dt_ids[];
+
+static const struct lan937x_chip_data lan937x_switch_chips[] = {
+ {
+ .chip_id = 0x00937010,
+ .dev_name = "LAN9370",
+ .num_vlans = 4096,
+ .num_alus = 1024,
+ .num_statics = 256,
+ /* can be configured as cpu port */
+ .cpu_ports = 0x10,
+ /* total port count */
+ .port_cnt = 5,
+ },
+ {
+ .chip_id = 0x00937110,
+ .dev_name = "LAN9371",
+ .num_vlans = 4096,
+ .num_alus = 1024,
+ .num_statics = 256,
+ /* can be configured as cpu port */
+ .cpu_ports = 0x30,
+ /* total port count */
+ .port_cnt = 6,
+ },
+ {
+ .chip_id = 0x00937210,
+ .dev_name = "LAN9372",
+ .num_vlans = 4096,
+ .num_alus = 1024,
+ .num_statics = 256,
+ /* can be configured as cpu port */
+ .cpu_ports = 0x30,
+ /* total port count */
+ .port_cnt = 8,
+ },
+ {
+ .chip_id = 0x00937310,
+ .dev_name = "LAN9373",
+ .num_vlans = 4096,
+ .num_alus = 1024,
+ .num_statics = 256,
+ /* can be configured as cpu port */
+ .cpu_ports = 0x38,
+ /* total port count */
+ .port_cnt = 5,
+ },
+ {
+ .chip_id = 0x00937410,
+ .dev_name = "LAN9374",
+ .num_vlans = 4096,
+ .num_alus = 1024,
+ .num_statics = 256,
+ /* can be configured as cpu port */
+ .cpu_ports = 0x30,
+ /* total port count */
+ .port_cnt = 8,
+ },
+};
+
+static int lan937x_spi_probe(struct spi_device *spi)
+{
+ struct regmap_config rc;
+ struct ksz_device *dev;
+ int i, ret;
+
+ dev = ksz_switch_alloc(&spi->dev, spi);
+ if (!dev)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(lan937x_regmap_config); i++) {
+ rc = lan937x_regmap_config[i];
+ rc.lock_arg = &dev->regmap_mutex;
+ dev->regmap[i] = devm_regmap_init_spi(spi, &rc);
+
+ if (IS_ERR(dev->regmap[i])) {
+ ret = PTR_ERR(dev->regmap[i]);
+ dev_err(&spi->dev,
+ "Failed to initialize regmap%i: %d\n",
+ lan937x_regmap_config[i].val_bits, ret);
+ return ret;
+ }
+ }
+
+ if (spi->dev.platform_data)
+ dev->pdata = spi->dev.platform_data;
+
+ ret = lan937x_switch_register(dev);
+ /* Main DSA driver may not be started yet. */
+ if (ret)
+ return ret;
+
+ spi_set_drvdata(spi, dev);
+
+ return 0;
+}
+
+int lan937x_check_device_id(struct ksz_device *dev)
+{
+ const struct lan937x_chip_data *dt_chip_data;
+ const struct of_device_id *match;
+ int i;
+
+ dt_chip_data = of_device_get_match_data(dev->dev);
+
+ if (!dt_chip_data)
+ return -EINVAL;
+
+ for (match = lan937x_dt_ids; match->compatible[0]; match++) {
+ const struct lan937x_chip_data *chip_data = match->data;
+
+ /* Check for chip id */
+ if (chip_data->chip_id != dev->chip_id)
+ continue;
+
+ /* Check for Device Tree and Chip ID */
+ if (dt_chip_data->chip_id != dev->chip_id) {
+ dev_err(dev->dev,
+ "Device tree specifies chip %s but found %s, please fix it!\n",
+ dt_chip_data->dev_name, chip_data->dev_name);
+ return -ENODEV;
+ }
+
+ break;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(lan937x_switch_chips); i++) {
+ const struct lan937x_chip_data *chip = &lan937x_switch_chips[i];
+
+ if (dev->chip_id == chip->chip_id) {
+ dev->name = chip->dev_name;
+ dev->num_vlans = chip->num_vlans;
+ dev->num_alus = chip->num_alus;
+ dev->num_statics = chip->num_statics;
+ dev->port_cnt = chip->port_cnt;
+ dev->cpu_ports = chip->cpu_ports;
+ break;
+ }
+ }
+
+ /* no switch found */
+ if (!dev->port_cnt)
+ return -ENODEV;
+
+ return 0;
+}
+EXPORT_SYMBOL(lan937x_check_device_id);
+
+static void lan937x_spi_remove(struct spi_device *spi)
+{
+ struct ksz_device *dev = spi_get_drvdata(spi);
+
+ if (dev)
+ ksz_switch_remove(dev);
+
+ spi_set_drvdata(spi, NULL);
+}
+
+static void lan937x_spi_shutdown(struct spi_device *spi)
+{
+ struct ksz_device *dev = spi_get_drvdata(spi);
+
+ if (dev)
+ dsa_switch_shutdown(dev->ds);
+
+ spi_set_drvdata(spi, NULL);
+}
+
+static const struct of_device_id lan937x_dt_ids[] = {
+ { .compatible = "microchip,lan9370", .data = &lan937x_switch_chips[0] },
+ { .compatible = "microchip,lan9371", .data = &lan937x_switch_chips[1] },
+ { .compatible = "microchip,lan9372", .data = &lan937x_switch_chips[2] },
+ { .compatible = "microchip,lan9373", .data = &lan937x_switch_chips[3] },
+ { .compatible = "microchip,lan9374", .data = &lan937x_switch_chips[4] },
+ {},
+};
+MODULE_DEVICE_TABLE(of, lan937x_dt_ids);
+
+static const struct spi_device_id lan937x_spi_ids[] = {
+ { .name = "lan9370" },
+ { .name = "lan9371" },
+ { .name = "lan9372" },
+ { .name = "lan9373" },
+ { .name = "lan9374" },
+ {},
+};
+MODULE_DEVICE_TABLE(spi, lan937x_spi_ids);
+
+static struct spi_driver lan937x_spi_driver = {
+ .driver = {
+ .name = "lan937x-switch",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(lan937x_dt_ids),
+ },
+ .probe = lan937x_spi_probe,
+ .remove = lan937x_spi_remove,
+ .shutdown = lan937x_spi_shutdown,
+ .id_table = lan937x_spi_ids,
+};
+
+module_spi_driver(lan937x_spi_driver);
+
+MODULE_ALIAS("spi:lan937x");
+
+MODULE_AUTHOR("Prasanna Vengateshan Varadharajan <Prasanna.Vengateshan@...rochip.com>");
+MODULE_DESCRIPTION("Microchip LAN937x Series Switch SPI access Driver");
+MODULE_LICENSE("GPL");
--
2.33.0
Powered by blists - more mailing lists