GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / net / dsa / qca / qca8k-common.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
4  * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
5  * Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved.
6  * Copyright (c) 2016 John Crispin <john@phrozen.org>
7  */
8
9 #include <linux/netdevice.h>
10 #include <net/dsa.h>
11 #include <linux/if_bridge.h>
12
13 #include "qca8k.h"
14
15 #define MIB_DESC(_s, _o, _n)    \
16         {                       \
17                 .size = (_s),   \
18                 .offset = (_o), \
19                 .name = (_n),   \
20         }
21
22 const struct qca8k_mib_desc ar8327_mib[] = {
23         MIB_DESC(1, 0x00, "RxBroad"),
24         MIB_DESC(1, 0x04, "RxPause"),
25         MIB_DESC(1, 0x08, "RxMulti"),
26         MIB_DESC(1, 0x0c, "RxFcsErr"),
27         MIB_DESC(1, 0x10, "RxAlignErr"),
28         MIB_DESC(1, 0x14, "RxRunt"),
29         MIB_DESC(1, 0x18, "RxFragment"),
30         MIB_DESC(1, 0x1c, "Rx64Byte"),
31         MIB_DESC(1, 0x20, "Rx128Byte"),
32         MIB_DESC(1, 0x24, "Rx256Byte"),
33         MIB_DESC(1, 0x28, "Rx512Byte"),
34         MIB_DESC(1, 0x2c, "Rx1024Byte"),
35         MIB_DESC(1, 0x30, "Rx1518Byte"),
36         MIB_DESC(1, 0x34, "RxMaxByte"),
37         MIB_DESC(1, 0x38, "RxTooLong"),
38         MIB_DESC(2, 0x3c, "RxGoodByte"),
39         MIB_DESC(2, 0x44, "RxBadByte"),
40         MIB_DESC(1, 0x4c, "RxOverFlow"),
41         MIB_DESC(1, 0x50, "Filtered"),
42         MIB_DESC(1, 0x54, "TxBroad"),
43         MIB_DESC(1, 0x58, "TxPause"),
44         MIB_DESC(1, 0x5c, "TxMulti"),
45         MIB_DESC(1, 0x60, "TxUnderRun"),
46         MIB_DESC(1, 0x64, "Tx64Byte"),
47         MIB_DESC(1, 0x68, "Tx128Byte"),
48         MIB_DESC(1, 0x6c, "Tx256Byte"),
49         MIB_DESC(1, 0x70, "Tx512Byte"),
50         MIB_DESC(1, 0x74, "Tx1024Byte"),
51         MIB_DESC(1, 0x78, "Tx1518Byte"),
52         MIB_DESC(1, 0x7c, "TxMaxByte"),
53         MIB_DESC(1, 0x80, "TxOverSize"),
54         MIB_DESC(2, 0x84, "TxByte"),
55         MIB_DESC(1, 0x8c, "TxCollision"),
56         MIB_DESC(1, 0x90, "TxAbortCol"),
57         MIB_DESC(1, 0x94, "TxMultiCol"),
58         MIB_DESC(1, 0x98, "TxSingleCol"),
59         MIB_DESC(1, 0x9c, "TxExcDefer"),
60         MIB_DESC(1, 0xa0, "TxDefer"),
61         MIB_DESC(1, 0xa4, "TxLateCol"),
62         MIB_DESC(1, 0xa8, "RXUnicast"),
63         MIB_DESC(1, 0xac, "TXUnicast"),
64 };
65
66 int qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val)
67 {
68         return regmap_read(priv->regmap, reg, val);
69 }
70
71 int qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
72 {
73         return regmap_write(priv->regmap, reg, val);
74 }
75
76 int qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val)
77 {
78         return regmap_update_bits(priv->regmap, reg, mask, write_val);
79 }
80
81 static const struct regmap_range qca8k_readable_ranges[] = {
82         regmap_reg_range(0x0000, 0x00e4), /* Global control */
83         regmap_reg_range(0x0100, 0x0168), /* EEE control */
84         regmap_reg_range(0x0200, 0x0270), /* Parser control */
85         regmap_reg_range(0x0400, 0x0454), /* ACL */
86         regmap_reg_range(0x0600, 0x0718), /* Lookup */
87         regmap_reg_range(0x0800, 0x0b70), /* QM */
88         regmap_reg_range(0x0c00, 0x0c80), /* PKT */
89         regmap_reg_range(0x0e00, 0x0e98), /* L3 */
90         regmap_reg_range(0x1000, 0x10ac), /* MIB - Port0 */
91         regmap_reg_range(0x1100, 0x11ac), /* MIB - Port1 */
92         regmap_reg_range(0x1200, 0x12ac), /* MIB - Port2 */
93         regmap_reg_range(0x1300, 0x13ac), /* MIB - Port3 */
94         regmap_reg_range(0x1400, 0x14ac), /* MIB - Port4 */
95         regmap_reg_range(0x1500, 0x15ac), /* MIB - Port5 */
96         regmap_reg_range(0x1600, 0x16ac), /* MIB - Port6 */
97 };
98
99 const struct regmap_access_table qca8k_readable_table = {
100         .yes_ranges = qca8k_readable_ranges,
101         .n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges),
102 };
103
104 static int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
105 {
106         u32 val;
107
108         return regmap_read_poll_timeout(priv->regmap, reg, val, !(val & mask), 0,
109                                        QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC);
110 }
111
112 static int qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb)
113 {
114         u32 reg[QCA8K_ATU_TABLE_SIZE];
115         int ret;
116
117         /* load the ARL table into an array */
118         ret = regmap_bulk_read(priv->regmap, QCA8K_REG_ATU_DATA0, reg,
119                                QCA8K_ATU_TABLE_SIZE);
120         if (ret)
121                 return ret;
122
123         /* vid - 83:72 */
124         fdb->vid = FIELD_GET(QCA8K_ATU_VID_MASK, reg[2]);
125         /* aging - 67:64 */
126         fdb->aging = FIELD_GET(QCA8K_ATU_STATUS_MASK, reg[2]);
127         /* portmask - 54:48 */
128         fdb->port_mask = FIELD_GET(QCA8K_ATU_PORT_MASK, reg[1]);
129         /* mac - 47:0 */
130         fdb->mac[0] = FIELD_GET(QCA8K_ATU_ADDR0_MASK, reg[1]);
131         fdb->mac[1] = FIELD_GET(QCA8K_ATU_ADDR1_MASK, reg[1]);
132         fdb->mac[2] = FIELD_GET(QCA8K_ATU_ADDR2_MASK, reg[0]);
133         fdb->mac[3] = FIELD_GET(QCA8K_ATU_ADDR3_MASK, reg[0]);
134         fdb->mac[4] = FIELD_GET(QCA8K_ATU_ADDR4_MASK, reg[0]);
135         fdb->mac[5] = FIELD_GET(QCA8K_ATU_ADDR5_MASK, reg[0]);
136
137         return 0;
138 }
139
140 static void qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask,
141                             const u8 *mac, u8 aging)
142 {
143         u32 reg[QCA8K_ATU_TABLE_SIZE] = { 0 };
144
145         /* vid - 83:72 */
146         reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid);
147         /* aging - 67:64 */
148         reg[2] |= FIELD_PREP(QCA8K_ATU_STATUS_MASK, aging);
149         /* portmask - 54:48 */
150         reg[1] = FIELD_PREP(QCA8K_ATU_PORT_MASK, port_mask);
151         /* mac - 47:0 */
152         reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR0_MASK, mac[0]);
153         reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR1_MASK, mac[1]);
154         reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR2_MASK, mac[2]);
155         reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR3_MASK, mac[3]);
156         reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR4_MASK, mac[4]);
157         reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]);
158
159         /* load the array into the ARL table */
160         regmap_bulk_write(priv->regmap, QCA8K_REG_ATU_DATA0, reg,
161                           QCA8K_ATU_TABLE_SIZE);
162 }
163
164 static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd,
165                             int port)
166 {
167         u32 reg;
168         int ret;
169
170         /* Set the command and FDB index */
171         reg = QCA8K_ATU_FUNC_BUSY;
172         reg |= cmd;
173         if (port >= 0) {
174                 reg |= QCA8K_ATU_FUNC_PORT_EN;
175                 reg |= FIELD_PREP(QCA8K_ATU_FUNC_PORT_MASK, port);
176         }
177
178         /* Write the function register triggering the table access */
179         ret = qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg);
180         if (ret)
181                 return ret;
182
183         /* wait for completion */
184         ret = qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY);
185         if (ret)
186                 return ret;
187
188         /* Check for table full violation when adding an entry */
189         if (cmd == QCA8K_FDB_LOAD) {
190                 ret = qca8k_read(priv, QCA8K_REG_ATU_FUNC, &reg);
191                 if (ret < 0)
192                         return ret;
193                 if (reg & QCA8K_ATU_FUNC_FULL)
194                         return -1;
195         }
196
197         return 0;
198 }
199
200 static int qca8k_fdb_next(struct qca8k_priv *priv, struct qca8k_fdb *fdb,
201                           int port)
202 {
203         int ret;
204
205         qca8k_fdb_write(priv, fdb->vid, fdb->port_mask, fdb->mac, fdb->aging);
206         ret = qca8k_fdb_access(priv, QCA8K_FDB_NEXT, port);
207         if (ret < 0)
208                 return ret;
209
210         return qca8k_fdb_read(priv, fdb);
211 }
212
213 static int qca8k_fdb_add(struct qca8k_priv *priv, const u8 *mac,
214                          u16 port_mask, u16 vid, u8 aging)
215 {
216         int ret;
217
218         mutex_lock(&priv->reg_mutex);
219         qca8k_fdb_write(priv, vid, port_mask, mac, aging);
220         ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
221         mutex_unlock(&priv->reg_mutex);
222
223         return ret;
224 }
225
226 static int qca8k_fdb_del(struct qca8k_priv *priv, const u8 *mac,
227                          u16 port_mask, u16 vid)
228 {
229         int ret;
230
231         mutex_lock(&priv->reg_mutex);
232         qca8k_fdb_write(priv, vid, port_mask, mac, 0);
233         ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
234         mutex_unlock(&priv->reg_mutex);
235
236         return ret;
237 }
238
239 void qca8k_fdb_flush(struct qca8k_priv *priv)
240 {
241         mutex_lock(&priv->reg_mutex);
242         qca8k_fdb_access(priv, QCA8K_FDB_FLUSH, -1);
243         mutex_unlock(&priv->reg_mutex);
244 }
245
246 static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
247                                        const u8 *mac, u16 vid, u8 aging)
248 {
249         struct qca8k_fdb fdb = { 0 };
250         int ret;
251
252         mutex_lock(&priv->reg_mutex);
253
254         qca8k_fdb_write(priv, vid, 0, mac, 0);
255         ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
256         if (ret < 0)
257                 goto exit;
258
259         ret = qca8k_fdb_read(priv, &fdb);
260         if (ret < 0)
261                 goto exit;
262
263         /* Rule exist. Delete first */
264         if (fdb.aging) {
265                 ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
266                 if (ret)
267                         goto exit;
268         } else {
269                 fdb.aging = aging;
270         }
271
272         /* Add port to fdb portmask */
273         fdb.port_mask |= port_mask;
274
275         qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
276         ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
277
278 exit:
279         mutex_unlock(&priv->reg_mutex);
280         return ret;
281 }
282
283 static int qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask,
284                                     const u8 *mac, u16 vid)
285 {
286         struct qca8k_fdb fdb = { 0 };
287         int ret;
288
289         mutex_lock(&priv->reg_mutex);
290
291         qca8k_fdb_write(priv, vid, 0, mac, 0);
292         ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
293         if (ret < 0)
294                 goto exit;
295
296         ret = qca8k_fdb_read(priv, &fdb);
297         if (ret < 0)
298                 goto exit;
299
300         /* Rule doesn't exist. Why delete? */
301         if (!fdb.aging) {
302                 ret = -EINVAL;
303                 goto exit;
304         }
305
306         ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
307         if (ret)
308                 goto exit;
309
310         /* Only port in the rule is this port. Don't re insert */
311         if (fdb.port_mask == port_mask)
312                 goto exit;
313
314         /* Remove port from port mask */
315         fdb.port_mask &= ~port_mask;
316
317         qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
318         ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
319
320 exit:
321         mutex_unlock(&priv->reg_mutex);
322         return ret;
323 }
324
325 static int qca8k_vlan_access(struct qca8k_priv *priv,
326                              enum qca8k_vlan_cmd cmd, u16 vid)
327 {
328         u32 reg;
329         int ret;
330
331         /* Set the command and VLAN index */
332         reg = QCA8K_VTU_FUNC1_BUSY;
333         reg |= cmd;
334         reg |= FIELD_PREP(QCA8K_VTU_FUNC1_VID_MASK, vid);
335
336         /* Write the function register triggering the table access */
337         ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg);
338         if (ret)
339                 return ret;
340
341         /* wait for completion */
342         ret = qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY);
343         if (ret)
344                 return ret;
345
346         /* Check for table full violation when adding an entry */
347         if (cmd == QCA8K_VLAN_LOAD) {
348                 ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC1, &reg);
349                 if (ret < 0)
350                         return ret;
351                 if (reg & QCA8K_VTU_FUNC1_FULL)
352                         return -ENOMEM;
353         }
354
355         return 0;
356 }
357
358 static int qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid,
359                           bool untagged)
360 {
361         u32 reg;
362         int ret;
363
364         /* We do the right thing with VLAN 0 and treat it as untagged while
365          * preserving the tag on egress.
366          */
367         if (vid == 0)
368                 return 0;
369
370         mutex_lock(&priv->reg_mutex);
371         ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid);
372         if (ret < 0)
373                 goto out;
374
375         ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, &reg);
376         if (ret < 0)
377                 goto out;
378         reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN;
379         reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port);
380         if (untagged)
381                 reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_UNTAG(port);
382         else
383                 reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_TAG(port);
384
385         ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
386         if (ret)
387                 goto out;
388         ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
389
390 out:
391         mutex_unlock(&priv->reg_mutex);
392
393         return ret;
394 }
395
396 static int qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid)
397 {
398         u32 reg, mask;
399         int ret, i;
400         bool del;
401
402         mutex_lock(&priv->reg_mutex);
403         ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid);
404         if (ret < 0)
405                 goto out;
406
407         ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, &reg);
408         if (ret < 0)
409                 goto out;
410         reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port);
411         reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(port);
412
413         /* Check if we're the last member to be removed */
414         del = true;
415         for (i = 0; i < QCA8K_NUM_PORTS; i++) {
416                 mask = QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(i);
417
418                 if ((reg & mask) != mask) {
419                         del = false;
420                         break;
421                 }
422         }
423
424         if (del) {
425                 ret = qca8k_vlan_access(priv, QCA8K_VLAN_PURGE, vid);
426         } else {
427                 ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
428                 if (ret)
429                         goto out;
430                 ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
431         }
432
433 out:
434         mutex_unlock(&priv->reg_mutex);
435
436         return ret;
437 }
438
439 int qca8k_mib_init(struct qca8k_priv *priv)
440 {
441         int ret;
442
443         mutex_lock(&priv->reg_mutex);
444         ret = regmap_update_bits(priv->regmap, QCA8K_REG_MIB,
445                                  QCA8K_MIB_FUNC | QCA8K_MIB_BUSY,
446                                  FIELD_PREP(QCA8K_MIB_FUNC, QCA8K_MIB_FLUSH) |
447                                  QCA8K_MIB_BUSY);
448         if (ret)
449                 goto exit;
450
451         ret = qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY);
452         if (ret)
453                 goto exit;
454
455         ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
456         if (ret)
457                 goto exit;
458
459         ret = qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB);
460
461 exit:
462         mutex_unlock(&priv->reg_mutex);
463         return ret;
464 }
465
466 void qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
467 {
468         u32 mask = QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC;
469
470         /* Port 0 and 6 have no internal PHY */
471         if (port > 0 && port < 6)
472                 mask |= QCA8K_PORT_STATUS_LINK_AUTO;
473
474         if (enable)
475                 regmap_set_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
476         else
477                 regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
478 }
479
480 void qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset,
481                        uint8_t *data)
482 {
483         struct qca8k_priv *priv = ds->priv;
484         int i;
485
486         if (stringset != ETH_SS_STATS)
487                 return;
488
489         for (i = 0; i < priv->info->mib_count; i++)
490                 ethtool_puts(&data, ar8327_mib[i].name);
491 }
492
493 void qca8k_get_ethtool_stats(struct dsa_switch *ds, int port,
494                              uint64_t *data)
495 {
496         struct qca8k_priv *priv = ds->priv;
497         const struct qca8k_mib_desc *mib;
498         u32 reg, i, val;
499         u32 hi = 0;
500         int ret;
501
502         if (priv->mgmt_conduit && priv->info->ops->autocast_mib &&
503             priv->info->ops->autocast_mib(ds, port, data) > 0)
504                 return;
505
506         for (i = 0; i < priv->info->mib_count; i++) {
507                 mib = &ar8327_mib[i];
508                 reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset;
509
510                 ret = qca8k_read(priv, reg, &val);
511                 if (ret < 0)
512                         continue;
513
514                 if (mib->size == 2) {
515                         ret = qca8k_read(priv, reg + 4, &hi);
516                         if (ret < 0)
517                                 continue;
518                 }
519
520                 data[i] = val;
521                 if (mib->size == 2)
522                         data[i] |= (u64)hi << 32;
523         }
524 }
525
526 int qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset)
527 {
528         struct qca8k_priv *priv = ds->priv;
529
530         if (sset != ETH_SS_STATS)
531                 return 0;
532
533         return priv->info->mib_count;
534 }
535
536 int qca8k_set_mac_eee(struct dsa_switch *ds, int port,
537                       struct ethtool_eee *eee)
538 {
539         u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port);
540         struct qca8k_priv *priv = ds->priv;
541         u32 reg;
542         int ret;
543
544         mutex_lock(&priv->reg_mutex);
545         ret = qca8k_read(priv, QCA8K_REG_EEE_CTRL, &reg);
546         if (ret < 0)
547                 goto exit;
548
549         if (eee->eee_enabled)
550                 reg |= lpi_en;
551         else
552                 reg &= ~lpi_en;
553         ret = qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg);
554
555 exit:
556         mutex_unlock(&priv->reg_mutex);
557         return ret;
558 }
559
560 int qca8k_get_mac_eee(struct dsa_switch *ds, int port,
561                       struct ethtool_eee *e)
562 {
563         /* Nothing to do on the port's MAC */
564         return 0;
565 }
566
567 static int qca8k_port_configure_learning(struct dsa_switch *ds, int port,
568                                          bool learning)
569 {
570         struct qca8k_priv *priv = ds->priv;
571
572         if (learning)
573                 return regmap_set_bits(priv->regmap,
574                                        QCA8K_PORT_LOOKUP_CTRL(port),
575                                        QCA8K_PORT_LOOKUP_LEARN);
576         else
577                 return regmap_clear_bits(priv->regmap,
578                                          QCA8K_PORT_LOOKUP_CTRL(port),
579                                          QCA8K_PORT_LOOKUP_LEARN);
580 }
581
582 void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
583 {
584         struct dsa_port *dp = dsa_to_port(ds, port);
585         struct qca8k_priv *priv = ds->priv;
586         bool learning = false;
587         u32 stp_state;
588
589         switch (state) {
590         case BR_STATE_DISABLED:
591                 stp_state = QCA8K_PORT_LOOKUP_STATE_DISABLED;
592                 break;
593         case BR_STATE_BLOCKING:
594                 stp_state = QCA8K_PORT_LOOKUP_STATE_BLOCKING;
595                 break;
596         case BR_STATE_LISTENING:
597                 stp_state = QCA8K_PORT_LOOKUP_STATE_LISTENING;
598                 break;
599         case BR_STATE_LEARNING:
600                 stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING;
601                 learning = dp->learning;
602                 break;
603         case BR_STATE_FORWARDING:
604                 learning = dp->learning;
605                 fallthrough;
606         default:
607                 stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD;
608                 break;
609         }
610
611         qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
612                   QCA8K_PORT_LOOKUP_STATE_MASK, stp_state);
613
614         qca8k_port_configure_learning(ds, port, learning);
615 }
616
617 int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port,
618                                 struct switchdev_brport_flags flags,
619                                 struct netlink_ext_ack *extack)
620 {
621         if (flags.mask & ~BR_LEARNING)
622                 return -EINVAL;
623
624         return 0;
625 }
626
627 int qca8k_port_bridge_flags(struct dsa_switch *ds, int port,
628                             struct switchdev_brport_flags flags,
629                             struct netlink_ext_ack *extack)
630 {
631         int ret;
632
633         if (flags.mask & BR_LEARNING) {
634                 ret = qca8k_port_configure_learning(ds, port,
635                                                     flags.val & BR_LEARNING);
636                 if (ret)
637                         return ret;
638         }
639
640         return 0;
641 }
642
643 int qca8k_port_bridge_join(struct dsa_switch *ds, int port,
644                            struct dsa_bridge bridge,
645                            bool *tx_fwd_offload,
646                            struct netlink_ext_ack *extack)
647 {
648         struct qca8k_priv *priv = ds->priv;
649         int port_mask, cpu_port;
650         int i, ret;
651
652         cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
653         port_mask = BIT(cpu_port);
654
655         for (i = 0; i < QCA8K_NUM_PORTS; i++) {
656                 if (dsa_is_cpu_port(ds, i))
657                         continue;
658                 if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
659                         continue;
660                 /* Add this port to the portvlan mask of the other ports
661                  * in the bridge
662                  */
663                 ret = regmap_set_bits(priv->regmap,
664                                       QCA8K_PORT_LOOKUP_CTRL(i),
665                                       BIT(port));
666                 if (ret)
667                         return ret;
668                 if (i != port)
669                         port_mask |= BIT(i);
670         }
671
672         /* Add all other ports to this ports portvlan mask */
673         ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
674                         QCA8K_PORT_LOOKUP_MEMBER, port_mask);
675
676         return ret;
677 }
678
679 void qca8k_port_bridge_leave(struct dsa_switch *ds, int port,
680                              struct dsa_bridge bridge)
681 {
682         struct qca8k_priv *priv = ds->priv;
683         int cpu_port, i;
684
685         cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
686
687         for (i = 0; i < QCA8K_NUM_PORTS; i++) {
688                 if (dsa_is_cpu_port(ds, i))
689                         continue;
690                 if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
691                         continue;
692                 /* Remove this port to the portvlan mask of the other ports
693                  * in the bridge
694                  */
695                 regmap_clear_bits(priv->regmap,
696                                   QCA8K_PORT_LOOKUP_CTRL(i),
697                                   BIT(port));
698         }
699
700         /* Set the cpu port to be the only one in the portvlan mask of
701          * this port
702          */
703         qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
704                   QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
705 }
706
707 void qca8k_port_fast_age(struct dsa_switch *ds, int port)
708 {
709         struct qca8k_priv *priv = ds->priv;
710
711         mutex_lock(&priv->reg_mutex);
712         qca8k_fdb_access(priv, QCA8K_FDB_FLUSH_PORT, port);
713         mutex_unlock(&priv->reg_mutex);
714 }
715
716 int qca8k_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
717 {
718         struct qca8k_priv *priv = ds->priv;
719         unsigned int secs = msecs / 1000;
720         u32 val;
721
722         /* AGE_TIME reg is set in 7s step */
723         val = secs / 7;
724
725         /* Handle case with 0 as val to NOT disable
726          * learning
727          */
728         if (!val)
729                 val = 1;
730
731         return regmap_update_bits(priv->regmap, QCA8K_REG_ATU_CTRL,
732                                   QCA8K_ATU_AGE_TIME_MASK,
733                                   QCA8K_ATU_AGE_TIME(val));
734 }
735
736 int qca8k_port_enable(struct dsa_switch *ds, int port,
737                       struct phy_device *phy)
738 {
739         struct qca8k_priv *priv = ds->priv;
740
741         qca8k_port_set_status(priv, port, 1);
742         priv->port_enabled_map |= BIT(port);
743
744         if (dsa_is_user_port(ds, port))
745                 phy_support_asym_pause(phy);
746
747         return 0;
748 }
749
750 void qca8k_port_disable(struct dsa_switch *ds, int port)
751 {
752         struct qca8k_priv *priv = ds->priv;
753
754         qca8k_port_set_status(priv, port, 0);
755         priv->port_enabled_map &= ~BIT(port);
756 }
757
758 int qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
759 {
760         struct qca8k_priv *priv = ds->priv;
761         int ret;
762
763         /* We have only have a general MTU setting.
764          * DSA always set the CPU port's MTU to the largest MTU of the user
765          * ports.
766          * Setting MTU just for the CPU port is sufficient to correctly set a
767          * value for every port.
768          */
769         if (!dsa_is_cpu_port(ds, port))
770                 return 0;
771
772         /* To change the MAX_FRAME_SIZE the cpu ports must be off or
773          * the switch panics.
774          * Turn off both cpu ports before applying the new value to prevent
775          * this.
776          */
777         if (priv->port_enabled_map & BIT(0))
778                 qca8k_port_set_status(priv, 0, 0);
779
780         if (priv->port_enabled_map & BIT(6))
781                 qca8k_port_set_status(priv, 6, 0);
782
783         /* Include L2 header / FCS length */
784         ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, new_mtu +
785                           ETH_HLEN + ETH_FCS_LEN);
786
787         if (priv->port_enabled_map & BIT(0))
788                 qca8k_port_set_status(priv, 0, 1);
789
790         if (priv->port_enabled_map & BIT(6))
791                 qca8k_port_set_status(priv, 6, 1);
792
793         return ret;
794 }
795
796 int qca8k_port_max_mtu(struct dsa_switch *ds, int port)
797 {
798         return QCA8K_MAX_MTU;
799 }
800
801 int qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr,
802                           u16 port_mask, u16 vid)
803 {
804         /* Set the vid to the port vlan id if no vid is set */
805         if (!vid)
806                 vid = QCA8K_PORT_VID_DEF;
807
808         return qca8k_fdb_add(priv, addr, port_mask, vid,
809                              QCA8K_ATU_STATUS_STATIC);
810 }
811
812 int qca8k_port_fdb_add(struct dsa_switch *ds, int port,
813                        const unsigned char *addr, u16 vid,
814                        struct dsa_db db)
815 {
816         struct qca8k_priv *priv = ds->priv;
817         u16 port_mask = BIT(port);
818
819         return qca8k_port_fdb_insert(priv, addr, port_mask, vid);
820 }
821
822 int qca8k_port_fdb_del(struct dsa_switch *ds, int port,
823                        const unsigned char *addr, u16 vid,
824                        struct dsa_db db)
825 {
826         struct qca8k_priv *priv = ds->priv;
827         u16 port_mask = BIT(port);
828
829         if (!vid)
830                 vid = QCA8K_PORT_VID_DEF;
831
832         return qca8k_fdb_del(priv, addr, port_mask, vid);
833 }
834
835 int qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
836                         dsa_fdb_dump_cb_t *cb, void *data)
837 {
838         struct qca8k_priv *priv = ds->priv;
839         struct qca8k_fdb _fdb = { 0 };
840         int cnt = QCA8K_NUM_FDB_RECORDS;
841         bool is_static;
842         int ret = 0;
843
844         mutex_lock(&priv->reg_mutex);
845         while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) {
846                 if (!_fdb.aging)
847                         break;
848                 is_static = (_fdb.aging == QCA8K_ATU_STATUS_STATIC);
849                 ret = cb(_fdb.mac, _fdb.vid, is_static, data);
850                 if (ret)
851                         break;
852         }
853         mutex_unlock(&priv->reg_mutex);
854
855         return 0;
856 }
857
858 int qca8k_port_mdb_add(struct dsa_switch *ds, int port,
859                        const struct switchdev_obj_port_mdb *mdb,
860                        struct dsa_db db)
861 {
862         struct qca8k_priv *priv = ds->priv;
863         const u8 *addr = mdb->addr;
864         u16 vid = mdb->vid;
865
866         if (!vid)
867                 vid = QCA8K_PORT_VID_DEF;
868
869         return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid,
870                                            QCA8K_ATU_STATUS_STATIC);
871 }
872
873 int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
874                        const struct switchdev_obj_port_mdb *mdb,
875                        struct dsa_db db)
876 {
877         struct qca8k_priv *priv = ds->priv;
878         const u8 *addr = mdb->addr;
879         u16 vid = mdb->vid;
880
881         if (!vid)
882                 vid = QCA8K_PORT_VID_DEF;
883
884         return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
885 }
886
887 int qca8k_port_mirror_add(struct dsa_switch *ds, int port,
888                           struct dsa_mall_mirror_tc_entry *mirror,
889                           bool ingress, struct netlink_ext_ack *extack)
890 {
891         struct qca8k_priv *priv = ds->priv;
892         int monitor_port, ret;
893         u32 reg, val;
894
895         /* Check for existent entry */
896         if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port))
897                 return -EEXIST;
898
899         ret = regmap_read(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, &val);
900         if (ret)
901                 return ret;
902
903         /* QCA83xx can have only one port set to mirror mode.
904          * Check that the correct port is requested and return error otherwise.
905          * When no mirror port is set, the values is set to 0xF
906          */
907         monitor_port = FIELD_GET(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
908         if (monitor_port != 0xF && monitor_port != mirror->to_local_port)
909                 return -EEXIST;
910
911         /* Set the monitor port */
912         val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM,
913                          mirror->to_local_port);
914         ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
915                                  QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
916         if (ret)
917                 return ret;
918
919         if (ingress) {
920                 reg = QCA8K_PORT_LOOKUP_CTRL(port);
921                 val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
922         } else {
923                 reg = QCA8K_REG_PORT_HOL_CTRL1(port);
924                 val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
925         }
926
927         ret = regmap_update_bits(priv->regmap, reg, val, val);
928         if (ret)
929                 return ret;
930
931         /* Track mirror port for tx and rx to decide when the
932          * mirror port has to be disabled.
933          */
934         if (ingress)
935                 priv->mirror_rx |= BIT(port);
936         else
937                 priv->mirror_tx |= BIT(port);
938
939         return 0;
940 }
941
942 void qca8k_port_mirror_del(struct dsa_switch *ds, int port,
943                            struct dsa_mall_mirror_tc_entry *mirror)
944 {
945         struct qca8k_priv *priv = ds->priv;
946         u32 reg, val;
947         int ret;
948
949         if (mirror->ingress) {
950                 reg = QCA8K_PORT_LOOKUP_CTRL(port);
951                 val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
952         } else {
953                 reg = QCA8K_REG_PORT_HOL_CTRL1(port);
954                 val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
955         }
956
957         ret = regmap_clear_bits(priv->regmap, reg, val);
958         if (ret)
959                 goto err;
960
961         if (mirror->ingress)
962                 priv->mirror_rx &= ~BIT(port);
963         else
964                 priv->mirror_tx &= ~BIT(port);
965
966         /* No port set to send packet to mirror port. Disable mirror port */
967         if (!priv->mirror_rx && !priv->mirror_tx) {
968                 val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, 0xF);
969                 ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
970                                          QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
971                 if (ret)
972                         goto err;
973         }
974 err:
975         dev_err(priv->dev, "Failed to del mirror port from %d", port);
976 }
977
978 int qca8k_port_vlan_filtering(struct dsa_switch *ds, int port,
979                               bool vlan_filtering,
980                               struct netlink_ext_ack *extack)
981 {
982         struct qca8k_priv *priv = ds->priv;
983         int ret;
984
985         if (vlan_filtering) {
986                 ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
987                                 QCA8K_PORT_LOOKUP_VLAN_MODE_MASK,
988                                 QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE);
989         } else {
990                 ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
991                                 QCA8K_PORT_LOOKUP_VLAN_MODE_MASK,
992                                 QCA8K_PORT_LOOKUP_VLAN_MODE_NONE);
993         }
994
995         return ret;
996 }
997
998 int qca8k_port_vlan_add(struct dsa_switch *ds, int port,
999                         const struct switchdev_obj_port_vlan *vlan,
1000                         struct netlink_ext_ack *extack)
1001 {
1002         bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
1003         bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
1004         struct qca8k_priv *priv = ds->priv;
1005         int ret;
1006
1007         ret = qca8k_vlan_add(priv, port, vlan->vid, untagged);
1008         if (ret) {
1009                 dev_err(priv->dev, "Failed to add VLAN to port %d (%d)", port, ret);
1010                 return ret;
1011         }
1012
1013         if (pvid) {
1014                 ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port),
1015                                 QCA8K_EGREES_VLAN_PORT_MASK(port),
1016                                 QCA8K_EGREES_VLAN_PORT(port, vlan->vid));
1017                 if (ret)
1018                         return ret;
1019
1020                 ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port),
1021                                   QCA8K_PORT_VLAN_CVID(vlan->vid) |
1022                                   QCA8K_PORT_VLAN_SVID(vlan->vid));
1023         }
1024
1025         return ret;
1026 }
1027
1028 int qca8k_port_vlan_del(struct dsa_switch *ds, int port,
1029                         const struct switchdev_obj_port_vlan *vlan)
1030 {
1031         struct qca8k_priv *priv = ds->priv;
1032         int ret;
1033
1034         ret = qca8k_vlan_del(priv, port, vlan->vid);
1035         if (ret)
1036                 dev_err(priv->dev, "Failed to delete VLAN from port %d (%d)", port, ret);
1037
1038         return ret;
1039 }
1040
1041 static bool qca8k_lag_can_offload(struct dsa_switch *ds,
1042                                   struct dsa_lag lag,
1043                                   struct netdev_lag_upper_info *info,
1044                                   struct netlink_ext_ack *extack)
1045 {
1046         struct dsa_port *dp;
1047         int members = 0;
1048
1049         if (!lag.id)
1050                 return false;
1051
1052         dsa_lag_foreach_port(dp, ds->dst, &lag)
1053                 /* Includes the port joining the LAG */
1054                 members++;
1055
1056         if (members > QCA8K_NUM_PORTS_FOR_LAG) {
1057                 NL_SET_ERR_MSG_MOD(extack,
1058                                    "Cannot offload more than 4 LAG ports");
1059                 return false;
1060         }
1061
1062         if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
1063                 NL_SET_ERR_MSG_MOD(extack,
1064                                    "Can only offload LAG using hash TX type");
1065                 return false;
1066         }
1067
1068         if (info->hash_type != NETDEV_LAG_HASH_L2 &&
1069             info->hash_type != NETDEV_LAG_HASH_L23) {
1070                 NL_SET_ERR_MSG_MOD(extack,
1071                                    "Can only offload L2 or L2+L3 TX hash");
1072                 return false;
1073         }
1074
1075         return true;
1076 }
1077
1078 static int qca8k_lag_setup_hash(struct dsa_switch *ds,
1079                                 struct dsa_lag lag,
1080                                 struct netdev_lag_upper_info *info)
1081 {
1082         struct net_device *lag_dev = lag.dev;
1083         struct qca8k_priv *priv = ds->priv;
1084         bool unique_lag = true;
1085         unsigned int i;
1086         u32 hash = 0;
1087
1088         switch (info->hash_type) {
1089         case NETDEV_LAG_HASH_L23:
1090                 hash |= QCA8K_TRUNK_HASH_SIP_EN;
1091                 hash |= QCA8K_TRUNK_HASH_DIP_EN;
1092                 fallthrough;
1093         case NETDEV_LAG_HASH_L2:
1094                 hash |= QCA8K_TRUNK_HASH_SA_EN;
1095                 hash |= QCA8K_TRUNK_HASH_DA_EN;
1096                 break;
1097         default: /* We should NEVER reach this */
1098                 return -EOPNOTSUPP;
1099         }
1100
1101         /* Check if we are the unique configured LAG */
1102         dsa_lags_foreach_id(i, ds->dst)
1103                 if (i != lag.id && dsa_lag_by_id(ds->dst, i)) {
1104                         unique_lag = false;
1105                         break;
1106                 }
1107
1108         /* Hash Mode is global. Make sure the same Hash Mode
1109          * is set to all the 4 possible lag.
1110          * If we are the unique LAG we can set whatever hash
1111          * mode we want.
1112          * To change hash mode it's needed to remove all LAG
1113          * and change the mode with the latest.
1114          */
1115         if (unique_lag) {
1116                 priv->lag_hash_mode = hash;
1117         } else if (priv->lag_hash_mode != hash) {
1118                 netdev_err(lag_dev, "Error: Mismatched Hash Mode across different lag is not supported\n");
1119                 return -EOPNOTSUPP;
1120         }
1121
1122         return regmap_update_bits(priv->regmap, QCA8K_TRUNK_HASH_EN_CTRL,
1123                                   QCA8K_TRUNK_HASH_MASK, hash);
1124 }
1125
1126 static int qca8k_lag_refresh_portmap(struct dsa_switch *ds, int port,
1127                                      struct dsa_lag lag, bool delete)
1128 {
1129         struct qca8k_priv *priv = ds->priv;
1130         int ret, id, i;
1131         u32 val;
1132
1133         /* DSA LAG IDs are one-based, hardware is zero-based */
1134         id = lag.id - 1;
1135
1136         /* Read current port member */
1137         ret = regmap_read(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL0, &val);
1138         if (ret)
1139                 return ret;
1140
1141         /* Shift val to the correct trunk */
1142         val >>= QCA8K_REG_GOL_TRUNK_SHIFT(id);
1143         val &= QCA8K_REG_GOL_TRUNK_MEMBER_MASK;
1144         if (delete)
1145                 val &= ~BIT(port);
1146         else
1147                 val |= BIT(port);
1148
1149         /* Update port member. With empty portmap disable trunk */
1150         ret = regmap_update_bits(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL0,
1151                                  QCA8K_REG_GOL_TRUNK_MEMBER(id) |
1152                                  QCA8K_REG_GOL_TRUNK_EN(id),
1153                                  !val << QCA8K_REG_GOL_TRUNK_SHIFT(id) |
1154                                  val << QCA8K_REG_GOL_TRUNK_SHIFT(id));
1155
1156         /* Search empty member if adding or port on deleting */
1157         for (i = 0; i < QCA8K_NUM_PORTS_FOR_LAG; i++) {
1158                 ret = regmap_read(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL(id), &val);
1159                 if (ret)
1160                         return ret;
1161
1162                 val >>= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i);
1163                 val &= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_MASK;
1164
1165                 if (delete) {
1166                         /* If port flagged to be disabled assume this member is
1167                          * empty
1168                          */
1169                         if (val != QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK)
1170                                 continue;
1171
1172                         val &= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT_MASK;
1173                         if (val != port)
1174                                 continue;
1175                 } else {
1176                         /* If port flagged to be enabled assume this member is
1177                          * already set
1178                          */
1179                         if (val == QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK)
1180                                 continue;
1181                 }
1182
1183                 /* We have found the member to add/remove */
1184                 break;
1185         }
1186
1187         /* Set port in the correct port mask or disable port if in delete mode */
1188         return regmap_update_bits(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL(id),
1189                                   QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN(id, i) |
1190                                   QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT(id, i),
1191                                   !delete << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i) |
1192                                   port << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i));
1193 }
1194
1195 int qca8k_port_lag_join(struct dsa_switch *ds, int port, struct dsa_lag lag,
1196                         struct netdev_lag_upper_info *info,
1197                         struct netlink_ext_ack *extack)
1198 {
1199         int ret;
1200
1201         if (!qca8k_lag_can_offload(ds, lag, info, extack))
1202                 return -EOPNOTSUPP;
1203
1204         ret = qca8k_lag_setup_hash(ds, lag, info);
1205         if (ret)
1206                 return ret;
1207
1208         return qca8k_lag_refresh_portmap(ds, port, lag, false);
1209 }
1210
1211 int qca8k_port_lag_leave(struct dsa_switch *ds, int port,
1212                          struct dsa_lag lag)
1213 {
1214         return qca8k_lag_refresh_portmap(ds, port, lag, true);
1215 }
1216
1217 int qca8k_read_switch_id(struct qca8k_priv *priv)
1218 {
1219         u32 val;
1220         u8 id;
1221         int ret;
1222
1223         if (!priv->info)
1224                 return -ENODEV;
1225
1226         ret = qca8k_read(priv, QCA8K_REG_MASK_CTRL, &val);
1227         if (ret < 0)
1228                 return -ENODEV;
1229
1230         id = QCA8K_MASK_CTRL_DEVICE_ID(val);
1231         if (id != priv->info->id) {
1232                 dev_err(priv->dev,
1233                         "Switch id detected %x but expected %x",
1234                         id, priv->info->id);
1235                 return -ENODEV;
1236         }
1237
1238         priv->switch_id = id;
1239
1240         /* Save revision to communicate to the internal PHY driver */
1241         priv->switch_revision = QCA8K_MASK_CTRL_REV_ID(val);
1242
1243         return 0;
1244 }