e0a9c809d84813b2ef5986aca0062987d231db48
[openwrt/staging/dedeckeh.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 diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
27 index f63a432916360..d64a9af186beb 100644
28 --- a/drivers/net/dsa/qca8k.c
29 +++ b/drivers/net/dsa/qca8k.c
30 @@ -10,6 +10,7 @@
31 #include <linux/phy.h>
32 #include <linux/netdevice.h>
33 #include <linux/bitfield.h>
34 +#include <linux/regmap.h>
35 #include <net/dsa.h>
36 #include <linux/of_net.h>
37 #include <linux/of_mdio.h>
38 @@ -152,6 +153,25 @@ qca8k_set_page(struct mii_bus *bus, u16 page)
39 static int
40 qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val)
41 {
42 + return regmap_read(priv->regmap, reg, val);
43 +}
44 +
45 +static int
46 +qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
47 +{
48 + return regmap_write(priv->regmap, reg, val);
49 +}
50 +
51 +static int
52 +qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val)
53 +{
54 + return regmap_update_bits(priv->regmap, reg, mask, write_val);
55 +}
56 +
57 +static int
58 +qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
59 +{
60 + struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
61 struct mii_bus *bus = priv->bus;
62 u16 r1, r2, page;
63 int ret;
64 @@ -172,8 +192,9 @@ exit:
65 }
66
67 static int
68 -qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
69 +qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
70 {
71 + struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
72 struct mii_bus *bus = priv->bus;
73 u16 r1, r2, page;
74 int ret;
75 @@ -194,8 +215,9 @@ exit:
76 }
77
78 static int
79 -qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val)
80 +qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val)
81 {
82 + struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
83 struct mii_bus *bus = priv->bus;
84 u16 r1, r2, page;
85 u32 val;
86 @@ -223,34 +245,6 @@ exit:
87 return ret;
88 }
89
90 -static int
91 -qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val)
92 -{
93 - return qca8k_rmw(priv, reg, 0, val);
94 -}
95 -
96 -static int
97 -qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val)
98 -{
99 - return qca8k_rmw(priv, reg, val, 0);
100 -}
101 -
102 -static int
103 -qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
104 -{
105 - struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
106 -
107 - return qca8k_read(priv, reg, val);
108 -}
109 -
110 -static int
111 -qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
112 -{
113 - struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
114 -
115 - return qca8k_write(priv, reg, val);
116 -}
117 -
118 static const struct regmap_range qca8k_readable_ranges[] = {
119 regmap_reg_range(0x0000, 0x00e4), /* Global control */
120 regmap_reg_range(0x0100, 0x0168), /* EEE control */
121 @@ -282,26 +276,19 @@ static struct regmap_config qca8k_regmap_config = {
122 .max_register = 0x16ac, /* end MIB - Port6 range */
123 .reg_read = qca8k_regmap_read,
124 .reg_write = qca8k_regmap_write,
125 + .reg_update_bits = qca8k_regmap_update_bits,
126 .rd_table = &qca8k_readable_table,
127 + .disable_locking = true, /* Locking is handled by qca8k read/write */
128 + .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
129 };
130
131 static int
132 qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
133 {
134 - int ret, ret1;
135 u32 val;
136
137 - ret = read_poll_timeout(qca8k_read, ret1, !(val & mask),
138 - 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false,
139 - priv, reg, &val);
140 -
141 - /* Check if qca8k_read has failed for a different reason
142 - * before returning -ETIMEDOUT
143 - */
144 - if (ret < 0 && ret1 < 0)
145 - return ret1;
146 -
147 - return ret;
148 + return regmap_read_poll_timeout(priv->regmap, reg, val, !(val & mask), 0,
149 + QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC);
150 }
151
152 static int
153 @@ -568,7 +555,7 @@ qca8k_mib_init(struct qca8k_priv *priv)
154 int ret;
155
156 mutex_lock(&priv->reg_mutex);
157 - ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
158 + ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
159 if (ret)
160 goto exit;
161
162 @@ -576,7 +563,7 @@ qca8k_mib_init(struct qca8k_priv *priv)
163 if (ret)
164 goto exit;
165
166 - ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
167 + ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
168 if (ret)
169 goto exit;
170
171 @@ -597,9 +584,9 @@ qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
172 mask |= QCA8K_PORT_STATUS_LINK_AUTO;
173
174 if (enable)
175 - qca8k_reg_set(priv, QCA8K_REG_PORT_STATUS(port), mask);
176 + regmap_set_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
177 else
178 - qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask);
179 + regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
180 }
181
182 static u32
183 @@ -861,8 +848,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
184 * a dt-overlay and driver reload changed the configuration
185 */
186
187 - return qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
188 - QCA8K_MDIO_MASTER_EN);
189 + return regmap_clear_bits(priv->regmap, QCA8K_MDIO_MASTER_CTRL,
190 + QCA8K_MDIO_MASTER_EN);
191 }
192
193 /* Check if the devicetree declare the port:phy mapping */
194 @@ -1099,16 +1086,16 @@ qca8k_setup(struct dsa_switch *ds)
195 return ret;
196
197 /* Make sure MAC06 is disabled */
198 - ret = qca8k_reg_clear(priv, QCA8K_REG_PORT0_PAD_CTRL,
199 - QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN);
200 + ret = regmap_clear_bits(priv->regmap, QCA8K_REG_PORT0_PAD_CTRL,
201 + QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN);
202 if (ret) {
203 dev_err(priv->dev, "failed disabling MAC06 exchange");
204 return ret;
205 }
206
207 /* Enable CPU Port */
208 - ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
209 - QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
210 + ret = regmap_set_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
211 + QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
212 if (ret) {
213 dev_err(priv->dev, "failed enabling CPU port");
214 return ret;
215 @@ -1176,8 +1163,8 @@ qca8k_setup(struct dsa_switch *ds)
216 return ret;
217
218 /* Enable ARP Auto-learning by default */
219 - ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i),
220 - QCA8K_PORT_LOOKUP_LEARN);
221 + ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i),
222 + QCA8K_PORT_LOOKUP_LEARN);
223 if (ret)
224 return ret;
225
226 @@ -1741,9 +1728,9 @@ qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br)
227 /* Add this port to the portvlan mask of the other ports
228 * in the bridge
229 */
230 - ret = qca8k_reg_set(priv,
231 - QCA8K_PORT_LOOKUP_CTRL(i),
232 - BIT(port));
233 + ret = regmap_set_bits(priv->regmap,
234 + QCA8K_PORT_LOOKUP_CTRL(i),
235 + BIT(port));
236 if (ret)
237 return ret;
238 if (i != port)
239 @@ -1773,9 +1760,9 @@ qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
240 /* Remove this port to the portvlan mask of the other ports
241 * in the bridge
242 */
243 - qca8k_reg_clear(priv,
244 - QCA8K_PORT_LOOKUP_CTRL(i),
245 - BIT(port));
246 + regmap_clear_bits(priv->regmap,
247 + QCA8K_PORT_LOOKUP_CTRL(i),
248 + BIT(port));
249 }
250
251 /* Set the cpu port to be the only one in the portvlan mask of
252 --
253 cgit 1.2.3-1.el7
254