Browse Source

kernel: backport GPIO LED patch for MT7530

This allows to specify and control switch LEDs on devices using mt7530
(typically mediatek and ramips targets).

Normally these LED GPIOs are 0, 3, 6, 9, and 12. wan/lan assignment is
per device. GPIO 9 is normally inverted. so GPIO_ACTIVE_HIGH instead of
GPIO_ACTIVE_LOW.

Tested on Linksys E7350.

Refreshed all patches.

Signed-off-by: Rosen Penev <[email protected]>
Rosen Penev 4 years ago
parent
commit
360c181dd7

+ 181 - 0
target/linux/generic/backport-5.10/781-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch

@@ -0,0 +1,181 @@
+From 429a0edeefd88cbfca5c417dfb8561047bb50769 Mon Sep 17 00:00:00 2001
+From: DENG Qingfang <[email protected]>
+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 <[email protected]>
+Reviewed-by: Linus Walleij <[email protected]>
+Reviewed-by: Andrew Lunn <[email protected]>
+Signed-off-by: Jakub Kicinski <[email protected]>
+---
+ 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"
+@@ -1540,6 +1541,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)
+ {
+@@ -1681,6 +1785,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

+ 3 - 3
target/linux/generic/backport-5.10/781-v5.13-net-dsa-mt7530-Add-support-for-EEE-features.patch

@@ -17,7 +17,7 @@ Signed-off-by: David S. Miller <[email protected]>
 
 --- a/drivers/net/dsa/mt7530.c
 +++ b/drivers/net/dsa/mt7530.c
-@@ -2267,6 +2267,17 @@ static void mt753x_phylink_mac_link_up(s
+@@ -2377,6 +2377,17 @@ static void mt753x_phylink_mac_link_up(s
  			mcr |= PMCR_RX_FC_EN;
  	}
  
@@ -35,7 +35,7 @@ Signed-off-by: David S. Miller <[email protected]>
  	mt7530_set(priv, MT7530_PMCR_P(port), mcr);
  }
  
-@@ -2497,6 +2508,36 @@ mt753x_phy_write(struct dsa_switch *ds,
+@@ -2607,6 +2618,36 @@ mt753x_phy_write(struct dsa_switch *ds,
  	return priv->info->phy_write(ds, port, regnum, val);
  }
  
@@ -72,7 +72,7 @@ Signed-off-by: David S. Miller <[email protected]>
  static const struct dsa_switch_ops mt7530_switch_ops = {
  	.get_tag_protocol	= mtk_get_tag_protocol,
  	.setup			= mt753x_setup,
-@@ -2525,6 +2566,8 @@ static const struct dsa_switch_ops mt753
+@@ -2635,6 +2676,8 @@ static const struct dsa_switch_ops mt753
  	.phylink_mac_an_restart	= mt753x_phylink_mac_an_restart,
  	.phylink_mac_link_down	= mt753x_phylink_mac_link_down,
  	.phylink_mac_link_up	= mt753x_phylink_mac_link_up,