kernel: bump 5.10 to 5.10.141
[openwrt/openwrt.git] / target / linux / generic / backport-5.10 / 731-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch
1 From 429a0edeefd88cbfca5c417dfb8561047bb50769 Mon Sep 17 00:00:00 2001
2 From: DENG Qingfang <dqfext@gmail.com>
3 Date: Mon, 25 Jan 2021 12:43:22 +0800
4 Subject: [PATCH] net: dsa: mt7530: MT7530 optional GPIO support
5
6 MT7530's LED controller can drive up to 15 LED/GPIOs.
7
8 Add support for GPIO control and allow users to use its GPIOs by
9 setting gpio-controller property in device tree.
10
11 Signed-off-by: DENG Qingfang <dqfext@gmail.com>
12 Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
13 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
14 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
15 ---
16 drivers/net/dsa/mt7530.c | 110 +++++++++++++++++++++++++++++++++++++++
17 drivers/net/dsa/mt7530.h | 20 +++++++
18 2 files changed, 130 insertions(+)
19
20 --- a/drivers/net/dsa/mt7530.c
21 +++ b/drivers/net/dsa/mt7530.c
22 @@ -18,6 +18,7 @@
23 #include <linux/regulator/consumer.h>
24 #include <linux/reset.h>
25 #include <linux/gpio/consumer.h>
26 +#include <linux/gpio/driver.h>
27 #include <net/dsa.h>
28
29 #include "mt7530.h"
30 @@ -1534,6 +1535,109 @@ mtk_get_tag_protocol(struct dsa_switch *
31 }
32 }
33
34 +static inline u32
35 +mt7530_gpio_to_bit(unsigned int offset)
36 +{
37 + /* Map GPIO offset to register bit
38 + * [ 2: 0] port 0 LED 0..2 as GPIO 0..2
39 + * [ 6: 4] port 1 LED 0..2 as GPIO 3..5
40 + * [10: 8] port 2 LED 0..2 as GPIO 6..8
41 + * [14:12] port 3 LED 0..2 as GPIO 9..11
42 + * [18:16] port 4 LED 0..2 as GPIO 12..14
43 + */
44 + return BIT(offset + offset / 3);
45 +}
46 +
47 +static int
48 +mt7530_gpio_get(struct gpio_chip *gc, unsigned int offset)
49 +{
50 + struct mt7530_priv *priv = gpiochip_get_data(gc);
51 + u32 bit = mt7530_gpio_to_bit(offset);
52 +
53 + return !!(mt7530_read(priv, MT7530_LED_GPIO_DATA) & bit);
54 +}
55 +
56 +static void
57 +mt7530_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
58 +{
59 + struct mt7530_priv *priv = gpiochip_get_data(gc);
60 + u32 bit = mt7530_gpio_to_bit(offset);
61 +
62 + if (value)
63 + mt7530_set(priv, MT7530_LED_GPIO_DATA, bit);
64 + else
65 + mt7530_clear(priv, MT7530_LED_GPIO_DATA, bit);
66 +}
67 +
68 +static int
69 +mt7530_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
70 +{
71 + struct mt7530_priv *priv = gpiochip_get_data(gc);
72 + u32 bit = mt7530_gpio_to_bit(offset);
73 +
74 + return (mt7530_read(priv, MT7530_LED_GPIO_DIR) & bit) ?
75 + GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
76 +}
77 +
78 +static int
79 +mt7530_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
80 +{
81 + struct mt7530_priv *priv = gpiochip_get_data(gc);
82 + u32 bit = mt7530_gpio_to_bit(offset);
83 +
84 + mt7530_clear(priv, MT7530_LED_GPIO_OE, bit);
85 + mt7530_clear(priv, MT7530_LED_GPIO_DIR, bit);
86 +
87 + return 0;
88 +}
89 +
90 +static int
91 +mt7530_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value)
92 +{
93 + struct mt7530_priv *priv = gpiochip_get_data(gc);
94 + u32 bit = mt7530_gpio_to_bit(offset);
95 +
96 + mt7530_set(priv, MT7530_LED_GPIO_DIR, bit);
97 +
98 + if (value)
99 + mt7530_set(priv, MT7530_LED_GPIO_DATA, bit);
100 + else
101 + mt7530_clear(priv, MT7530_LED_GPIO_DATA, bit);
102 +
103 + mt7530_set(priv, MT7530_LED_GPIO_OE, bit);
104 +
105 + return 0;
106 +}
107 +
108 +static int
109 +mt7530_setup_gpio(struct mt7530_priv *priv)
110 +{
111 + struct device *dev = priv->dev;
112 + struct gpio_chip *gc;
113 +
114 + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
115 + if (!gc)
116 + return -ENOMEM;
117 +
118 + mt7530_write(priv, MT7530_LED_GPIO_OE, 0);
119 + mt7530_write(priv, MT7530_LED_GPIO_DIR, 0);
120 + mt7530_write(priv, MT7530_LED_IO_MODE, 0);
121 +
122 + gc->label = "mt7530";
123 + gc->parent = dev;
124 + gc->owner = THIS_MODULE;
125 + gc->get_direction = mt7530_gpio_get_direction;
126 + gc->direction_input = mt7530_gpio_direction_input;
127 + gc->direction_output = mt7530_gpio_direction_output;
128 + gc->get = mt7530_gpio_get;
129 + gc->set = mt7530_gpio_set;
130 + gc->base = -1;
131 + gc->ngpio = 15;
132 + gc->can_sleep = true;
133 +
134 + return devm_gpiochip_add_data(dev, gc, priv);
135 +}
136 +
137 static int
138 mt7530_setup(struct dsa_switch *ds)
139 {
140 @@ -1676,6 +1780,12 @@ mt7530_setup(struct dsa_switch *ds)
141 }
142 }
143
144 + if (of_property_read_bool(priv->dev->of_node, "gpio-controller")) {
145 + ret = mt7530_setup_gpio(priv);
146 + if (ret)
147 + return ret;
148 + }
149 +
150 mt7530_setup_port5(ds, interface);
151
152 /* Flush the FDB table */
153 --- a/drivers/net/dsa/mt7530.h
154 +++ b/drivers/net/dsa/mt7530.h
155 @@ -529,6 +529,26 @@ enum mt7531_clk_skew {
156 #define MT7531_GPIO12_RG_RXD3_MASK GENMASK(19, 16)
157 #define MT7531_EXT_P_MDIO_12 (2 << 16)
158
159 +/* Registers for LED GPIO control (MT7530 only)
160 + * All registers follow this pattern:
161 + * [ 2: 0] port 0
162 + * [ 6: 4] port 1
163 + * [10: 8] port 2
164 + * [14:12] port 3
165 + * [18:16] port 4
166 + */
167 +
168 +/* LED enable, 0: Disable, 1: Enable (Default) */
169 +#define MT7530_LED_EN 0x7d00
170 +/* LED mode, 0: GPIO mode, 1: PHY mode (Default) */
171 +#define MT7530_LED_IO_MODE 0x7d04
172 +/* GPIO direction, 0: Input, 1: Output */
173 +#define MT7530_LED_GPIO_DIR 0x7d10
174 +/* GPIO output enable, 0: Disable, 1: Enable */
175 +#define MT7530_LED_GPIO_OE 0x7d14
176 +/* GPIO value, 0: Low, 1: High */
177 +#define MT7530_LED_GPIO_DATA 0x7d18
178 +
179 #define MT7530_CREV 0x7ffc
180 #define CHIP_NAME_SHIFT 16
181 #define MT7530_ID 0x7530