2021-09-23 02:16:32 +00:00
|
|
|
From 429a0edeefd88cbfca5c417dfb8561047bb50769 Mon Sep 17 00:00:00 2001
|
|
|
|
From: DENG Qingfang <dqfext@gmail.com>
|
|
|
|
Date: Mon, 25 Jan 2021 12:43:22 +0800
|
|
|
|
Subject: [PATCH] net: dsa: mt7530: MT7530 optional GPIO support
|
|
|
|
|
|
|
|
MT7530's LED controller can drive up to 15 LED/GPIOs.
|
|
|
|
|
|
|
|
Add support for GPIO control and allow users to use its GPIOs by
|
|
|
|
setting gpio-controller property in device tree.
|
|
|
|
|
|
|
|
Signed-off-by: DENG Qingfang <dqfext@gmail.com>
|
|
|
|
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
|
|
|
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
|
|
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
|
---
|
|
|
|
drivers/net/dsa/mt7530.c | 110 +++++++++++++++++++++++++++++++++++++++
|
|
|
|
drivers/net/dsa/mt7530.h | 20 +++++++
|
|
|
|
2 files changed, 130 insertions(+)
|
|
|
|
|
|
|
|
--- a/drivers/net/dsa/mt7530.c
|
|
|
|
+++ b/drivers/net/dsa/mt7530.c
|
|
|
|
@@ -18,6 +18,7 @@
|
|
|
|
#include <linux/regulator/consumer.h>
|
|
|
|
#include <linux/reset.h>
|
|
|
|
#include <linux/gpio/consumer.h>
|
|
|
|
+#include <linux/gpio/driver.h>
|
|
|
|
#include <net/dsa.h>
|
|
|
|
|
|
|
|
#include "mt7530.h"
|
2021-10-27 10:10:45 +00:00
|
|
|
@@ -1534,6 +1535,109 @@ mtk_get_tag_protocol(struct dsa_switch *
|
2021-09-23 02:16:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
+static inline u32
|
|
|
|
+mt7530_gpio_to_bit(unsigned int offset)
|
|
|
|
+{
|
|
|
|
+ /* Map GPIO offset to register bit
|
|
|
|
+ * [ 2: 0] port 0 LED 0..2 as GPIO 0..2
|
|
|
|
+ * [ 6: 4] port 1 LED 0..2 as GPIO 3..5
|
|
|
|
+ * [10: 8] port 2 LED 0..2 as GPIO 6..8
|
|
|
|
+ * [14:12] port 3 LED 0..2 as GPIO 9..11
|
|
|
|
+ * [18:16] port 4 LED 0..2 as GPIO 12..14
|
|
|
|
+ */
|
|
|
|
+ return BIT(offset + offset / 3);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+mt7530_gpio_get(struct gpio_chip *gc, unsigned int offset)
|
|
|
|
+{
|
|
|
|
+ struct mt7530_priv *priv = gpiochip_get_data(gc);
|
|
|
|
+ u32 bit = mt7530_gpio_to_bit(offset);
|
|
|
|
+
|
|
|
|
+ return !!(mt7530_read(priv, MT7530_LED_GPIO_DATA) & bit);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+mt7530_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
|
|
|
|
+{
|
|
|
|
+ struct mt7530_priv *priv = gpiochip_get_data(gc);
|
|
|
|
+ u32 bit = mt7530_gpio_to_bit(offset);
|
|
|
|
+
|
|
|
|
+ if (value)
|
|
|
|
+ mt7530_set(priv, MT7530_LED_GPIO_DATA, bit);
|
|
|
|
+ else
|
|
|
|
+ mt7530_clear(priv, MT7530_LED_GPIO_DATA, bit);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+mt7530_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
|
|
|
+{
|
|
|
|
+ struct mt7530_priv *priv = gpiochip_get_data(gc);
|
|
|
|
+ u32 bit = mt7530_gpio_to_bit(offset);
|
|
|
|
+
|
|
|
|
+ return (mt7530_read(priv, MT7530_LED_GPIO_DIR) & bit) ?
|
|
|
|
+ GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+mt7530_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
|
|
|
|
+{
|
|
|
|
+ struct mt7530_priv *priv = gpiochip_get_data(gc);
|
|
|
|
+ u32 bit = mt7530_gpio_to_bit(offset);
|
|
|
|
+
|
|
|
|
+ mt7530_clear(priv, MT7530_LED_GPIO_OE, bit);
|
|
|
|
+ mt7530_clear(priv, MT7530_LED_GPIO_DIR, bit);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+mt7530_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value)
|
|
|
|
+{
|
|
|
|
+ struct mt7530_priv *priv = gpiochip_get_data(gc);
|
|
|
|
+ u32 bit = mt7530_gpio_to_bit(offset);
|
|
|
|
+
|
|
|
|
+ mt7530_set(priv, MT7530_LED_GPIO_DIR, bit);
|
|
|
|
+
|
|
|
|
+ if (value)
|
|
|
|
+ mt7530_set(priv, MT7530_LED_GPIO_DATA, bit);
|
|
|
|
+ else
|
|
|
|
+ mt7530_clear(priv, MT7530_LED_GPIO_DATA, bit);
|
|
|
|
+
|
|
|
|
+ mt7530_set(priv, MT7530_LED_GPIO_OE, bit);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+mt7530_setup_gpio(struct mt7530_priv *priv)
|
|
|
|
+{
|
|
|
|
+ struct device *dev = priv->dev;
|
|
|
|
+ struct gpio_chip *gc;
|
|
|
|
+
|
|
|
|
+ gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
|
|
|
|
+ if (!gc)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ mt7530_write(priv, MT7530_LED_GPIO_OE, 0);
|
|
|
|
+ mt7530_write(priv, MT7530_LED_GPIO_DIR, 0);
|
|
|
|
+ mt7530_write(priv, MT7530_LED_IO_MODE, 0);
|
|
|
|
+
|
|
|
|
+ gc->label = "mt7530";
|
|
|
|
+ gc->parent = dev;
|
|
|
|
+ gc->owner = THIS_MODULE;
|
|
|
|
+ gc->get_direction = mt7530_gpio_get_direction;
|
|
|
|
+ gc->direction_input = mt7530_gpio_direction_input;
|
|
|
|
+ gc->direction_output = mt7530_gpio_direction_output;
|
|
|
|
+ gc->get = mt7530_gpio_get;
|
|
|
|
+ gc->set = mt7530_gpio_set;
|
|
|
|
+ gc->base = -1;
|
|
|
|
+ gc->ngpio = 15;
|
|
|
|
+ gc->can_sleep = true;
|
|
|
|
+
|
|
|
|
+ return devm_gpiochip_add_data(dev, gc, priv);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static int
|
|
|
|
mt7530_setup(struct dsa_switch *ds)
|
|
|
|
{
|
2022-05-12 17:04:51 +00:00
|
|
|
@@ -1676,6 +1780,12 @@ mt7530_setup(struct dsa_switch *ds)
|
2021-09-23 02:16:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
+ if (of_property_read_bool(priv->dev->of_node, "gpio-controller")) {
|
|
|
|
+ ret = mt7530_setup_gpio(priv);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
mt7530_setup_port5(ds, interface);
|
|
|
|
|
|
|
|
/* Flush the FDB table */
|
|
|
|
--- a/drivers/net/dsa/mt7530.h
|
|
|
|
+++ b/drivers/net/dsa/mt7530.h
|
|
|
|
@@ -529,6 +529,26 @@ enum mt7531_clk_skew {
|
|
|
|
#define MT7531_GPIO12_RG_RXD3_MASK GENMASK(19, 16)
|
|
|
|
#define MT7531_EXT_P_MDIO_12 (2 << 16)
|
|
|
|
|
|
|
|
+/* Registers for LED GPIO control (MT7530 only)
|
|
|
|
+ * All registers follow this pattern:
|
|
|
|
+ * [ 2: 0] port 0
|
|
|
|
+ * [ 6: 4] port 1
|
|
|
|
+ * [10: 8] port 2
|
|
|
|
+ * [14:12] port 3
|
|
|
|
+ * [18:16] port 4
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+/* LED enable, 0: Disable, 1: Enable (Default) */
|
|
|
|
+#define MT7530_LED_EN 0x7d00
|
|
|
|
+/* LED mode, 0: GPIO mode, 1: PHY mode (Default) */
|
|
|
|
+#define MT7530_LED_IO_MODE 0x7d04
|
|
|
|
+/* GPIO direction, 0: Input, 1: Output */
|
|
|
|
+#define MT7530_LED_GPIO_DIR 0x7d10
|
|
|
|
+/* GPIO output enable, 0: Disable, 1: Enable */
|
|
|
|
+#define MT7530_LED_GPIO_OE 0x7d14
|
|
|
|
+/* GPIO value, 0: Low, 1: High */
|
|
|
|
+#define MT7530_LED_GPIO_DATA 0x7d18
|
|
|
|
+
|
|
|
|
#define MT7530_CREV 0x7ffc
|
|
|
|
#define CHIP_NAME_SHIFT 16
|
|
|
|
#define MT7530_ID 0x7530
|