kernel: backport GPIO LED patch for MT7530
authorRosen Penev <rosenp@gmail.com>
Thu, 23 Sep 2021 02:16:32 +0000 (19:16 -0700)
committerChristian Lamparter <chunkeey@gmail.com>
Sat, 23 Oct 2021 16:50:31 +0000 (18:50 +0200)
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 <rosenp@gmail.com>
target/linux/generic/backport-5.10/781-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch [new file with mode: 0644]
target/linux/generic/backport-5.10/781-v5.13-net-dsa-mt7530-Add-support-for-EEE-features.patch

diff --git a/target/linux/generic/backport-5.10/781-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch b/target/linux/generic/backport-5.10/781-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch
new file mode 100644 (file)
index 0000000..6931500
--- /dev/null
@@ -0,0 +1,181 @@
+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"
+@@ -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
index ae4270391d526eade179120c2abb04229b7cd086..4952abdb1eddf05172a37d022b14c17daf4985b5 100644 (file)
@@ -17,7 +17,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
 
 --- 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 <davem@davemloft.net>
        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 <davem@davemloft.net>
  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,