Removed upstreamed: backport-5.10/850-v5.17-0004-PCI-aardvark-Clear-all-MSIs-at-setup.patch pending-5.10/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch All other patches automatically rebased. Build system: x86_64 Build-tested: bcm2711/RPi4B Signed-off-by: John Audia <therealgraysky@proton.me>
		
			
				
	
	
		
			182 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
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"
 | 
						|
@@ -1534,6 +1535,109 @@ mtk_get_tag_protocol(struct dsa_switch *
 | 
						|
 	}
 | 
						|
 }
 | 
						|
 
 | 
						|
+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)
 | 
						|
 {
 | 
						|
@@ -1676,6 +1780,12 @@ mt7530_setup(struct dsa_switch *ds)
 | 
						|
 		}
 | 
						|
 	}
 | 
						|
 
 | 
						|
+	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
 |