4ca9c8ba41d6846502d78ab46b2777f57c31ed37
[openwrt/staging/neocturne.git] /
1 From 8b5f3f29a81a71934d004e21a1292c1148b05926 Mon Sep 17 00:00:00 2001
2 From: Ansuel Smith <ansuelsmth@gmail.com>
3 Date: Mon, 22 Nov 2021 16:23:44 +0100
4 Subject: net: dsa: qca8k: initial conversion to regmap helper
5
6 Convert any qca8k set/clear/pool to regmap helper and add
7 missing config to regmap_config struct.
8 Read/write/rmw operation are reworked to use the regmap helper
9 internally to keep the delta of this patch low. These additional
10 function will then be dropped when the code split will be proposed.
11
12 Ipq40xx SoC have the internal switch based on the qca8k regmap but use
13 mmio for read/write/rmw operation instead of mdio.
14 In preparation for the support of this internal switch, convert the
15 driver to regmap API to later split the driver to common and specific
16 code. The overhead introduced by the use of regamp API is marginal as the
17 internal mdio will bypass it by using its direct access and regmap will be
18 used only by configuration functions or fdb access.
19
20 Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
21 Signed-off-by: David S. Miller <davem@davemloft.net>
22 ---
23 drivers/net/dsa/qca8k.c | 107 +++++++++++++++++++++---------------------------
24 1 file changed, 47 insertions(+), 60 deletions(-)
25
26 --- a/drivers/net/dsa/qca8k.c
27 +++ b/drivers/net/dsa/qca8k.c
28 @@ -10,6 +10,7 @@
29 #include <linux/phy.h>
30 #include <linux/netdevice.h>
31 #include <linux/bitfield.h>
32 +#include <linux/regmap.h>
33 #include <net/dsa.h>
34 #include <linux/of_net.h>
35 #include <linux/of_mdio.h>
36 @@ -152,6 +153,25 @@ qca8k_set_page(struct mii_bus *bus, u16
37 static int
38 qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val)
39 {
40 + return regmap_read(priv->regmap, reg, val);
41 +}
42 +
43 +static int
44 +qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
45 +{
46 + return regmap_write(priv->regmap, reg, val);
47 +}
48 +
49 +static int
50 +qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val)
51 +{
52 + return regmap_update_bits(priv->regmap, reg, mask, write_val);
53 +}
54 +
55 +static int
56 +qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
57 +{
58 + struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
59 struct mii_bus *bus = priv->bus;
60 u16 r1, r2, page;
61 int ret;
62 @@ -172,8 +192,9 @@ exit:
63 }
64
65 static int
66 -qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
67 +qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
68 {
69 + struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
70 struct mii_bus *bus = priv->bus;
71 u16 r1, r2, page;
72 int ret;
73 @@ -194,8 +215,9 @@ exit:
74 }
75
76 static int
77 -qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val)
78 +qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val)
79 {
80 + struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
81 struct mii_bus *bus = priv->bus;
82 u16 r1, r2, page;
83 u32 val;
84 @@ -223,34 +245,6 @@ exit:
85 return ret;
86 }
87
88 -static int
89 -qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val)
90 -{
91 - return qca8k_rmw(priv, reg, 0, val);
92 -}
93 -
94 -static int
95 -qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val)
96 -{
97 - return qca8k_rmw(priv, reg, val, 0);
98 -}
99 -
100 -static int
101 -qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
102 -{
103 - struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
104 -
105 - return qca8k_read(priv, reg, val);
106 -}
107 -
108 -static int
109 -qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
110 -{
111 - struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
112 -
113 - return qca8k_write(priv, reg, val);
114 -}
115 -
116 static const struct regmap_range qca8k_readable_ranges[] = {
117 regmap_reg_range(0x0000, 0x00e4), /* Global control */
118 regmap_reg_range(0x0100, 0x0168), /* EEE control */
119 @@ -282,26 +276,19 @@ static struct regmap_config qca8k_regmap
120 .max_register = 0x16ac, /* end MIB - Port6 range */
121 .reg_read = qca8k_regmap_read,
122 .reg_write = qca8k_regmap_write,
123 + .reg_update_bits = qca8k_regmap_update_bits,
124 .rd_table = &qca8k_readable_table,
125 + .disable_locking = true, /* Locking is handled by qca8k read/write */
126 + .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
127 };
128
129 static int
130 qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
131 {
132 - int ret, ret1;
133 u32 val;
134
135 - ret = read_poll_timeout(qca8k_read, ret1, !(val & mask),
136 - 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false,
137 - priv, reg, &val);
138 -
139 - /* Check if qca8k_read has failed for a different reason
140 - * before returning -ETIMEDOUT
141 - */
142 - if (ret < 0 && ret1 < 0)
143 - return ret1;
144 -
145 - return ret;
146 + return regmap_read_poll_timeout(priv->regmap, reg, val, !(val & mask), 0,
147 + QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC);
148 }
149
150 static int
151 @@ -568,7 +555,7 @@ qca8k_mib_init(struct qca8k_priv *priv)
152 int ret;
153
154 mutex_lock(&priv->reg_mutex);
155 - ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
156 + ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
157 if (ret)
158 goto exit;
159
160 @@ -576,7 +563,7 @@ qca8k_mib_init(struct qca8k_priv *priv)
161 if (ret)
162 goto exit;
163
164 - ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
165 + ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
166 if (ret)
167 goto exit;
168
169 @@ -597,9 +584,9 @@ qca8k_port_set_status(struct qca8k_priv
170 mask |= QCA8K_PORT_STATUS_LINK_AUTO;
171
172 if (enable)
173 - qca8k_reg_set(priv, QCA8K_REG_PORT_STATUS(port), mask);
174 + regmap_set_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
175 else
176 - qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask);
177 + regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
178 }
179
180 static u32
181 @@ -861,8 +848,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
182 * a dt-overlay and driver reload changed the configuration
183 */
184
185 - return qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
186 - QCA8K_MDIO_MASTER_EN);
187 + return regmap_clear_bits(priv->regmap, QCA8K_MDIO_MASTER_CTRL,
188 + QCA8K_MDIO_MASTER_EN);
189 }
190
191 /* Check if the devicetree declare the port:phy mapping */
192 @@ -1099,16 +1086,16 @@ qca8k_setup(struct dsa_switch *ds)
193 return ret;
194
195 /* Make sure MAC06 is disabled */
196 - ret = qca8k_reg_clear(priv, QCA8K_REG_PORT0_PAD_CTRL,
197 - QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN);
198 + ret = regmap_clear_bits(priv->regmap, QCA8K_REG_PORT0_PAD_CTRL,
199 + QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN);
200 if (ret) {
201 dev_err(priv->dev, "failed disabling MAC06 exchange");
202 return ret;
203 }
204
205 /* Enable CPU Port */
206 - ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
207 - QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
208 + ret = regmap_set_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
209 + QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
210 if (ret) {
211 dev_err(priv->dev, "failed enabling CPU port");
212 return ret;
213 @@ -1176,8 +1163,8 @@ qca8k_setup(struct dsa_switch *ds)
214 return ret;
215
216 /* Enable ARP Auto-learning by default */
217 - ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i),
218 - QCA8K_PORT_LOOKUP_LEARN);
219 + ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i),
220 + QCA8K_PORT_LOOKUP_LEARN);
221 if (ret)
222 return ret;
223
224 @@ -1745,9 +1732,9 @@ qca8k_port_bridge_join(struct dsa_switch
225 /* Add this port to the portvlan mask of the other ports
226 * in the bridge
227 */
228 - ret = qca8k_reg_set(priv,
229 - QCA8K_PORT_LOOKUP_CTRL(i),
230 - BIT(port));
231 + ret = regmap_set_bits(priv->regmap,
232 + QCA8K_PORT_LOOKUP_CTRL(i),
233 + BIT(port));
234 if (ret)
235 return ret;
236 if (i != port)
237 @@ -1777,9 +1764,9 @@ qca8k_port_bridge_leave(struct dsa_switc
238 /* Remove this port to the portvlan mask of the other ports
239 * in the bridge
240 */
241 - qca8k_reg_clear(priv,
242 - QCA8K_PORT_LOOKUP_CTRL(i),
243 - BIT(port));
244 + regmap_clear_bits(priv->regmap,
245 + QCA8K_PORT_LOOKUP_CTRL(i),
246 + BIT(port));
247 }
248
249 /* Set the cpu port to be the only one in the portvlan mask of