1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
4 * Copyright (C) 2011-2012, 2020-2021 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 * Copyright (c) 2021 Robert Marko <robert.marko@sartura.hr>
10 #include <linux/version.h>
11 #include <linux/etherdevice.h>
12 #include <linux/if_bridge.h>
13 #include <linux/mdio.h>
14 #include <linux/mfd/syscon.h>
15 #include <linux/module.h>
16 #include <linux/netdevice.h>
17 #include <linux/of_mdio.h>
18 #include <linux/of_net.h>
19 #include <linux/of_platform.h>
20 #include <linux/phy.h>
21 #include <linux/phylink.h>
22 #include <linux/reset.h>
25 #include "qca8k-ipq4019.h"
27 #define MIB_DESC(_s, _o, _n) \
34 static const struct qca8k_mib_desc ar8327_mib
[] = {
35 MIB_DESC(1, 0x00, "RxBroad"),
36 MIB_DESC(1, 0x04, "RxPause"),
37 MIB_DESC(1, 0x08, "RxMulti"),
38 MIB_DESC(1, 0x0c, "RxFcsErr"),
39 MIB_DESC(1, 0x10, "RxAlignErr"),
40 MIB_DESC(1, 0x14, "RxRunt"),
41 MIB_DESC(1, 0x18, "RxFragment"),
42 MIB_DESC(1, 0x1c, "Rx64Byte"),
43 MIB_DESC(1, 0x20, "Rx128Byte"),
44 MIB_DESC(1, 0x24, "Rx256Byte"),
45 MIB_DESC(1, 0x28, "Rx512Byte"),
46 MIB_DESC(1, 0x2c, "Rx1024Byte"),
47 MIB_DESC(1, 0x30, "Rx1518Byte"),
48 MIB_DESC(1, 0x34, "RxMaxByte"),
49 MIB_DESC(1, 0x38, "RxTooLong"),
50 MIB_DESC(2, 0x3c, "RxGoodByte"),
51 MIB_DESC(2, 0x44, "RxBadByte"),
52 MIB_DESC(1, 0x4c, "RxOverFlow"),
53 MIB_DESC(1, 0x50, "Filtered"),
54 MIB_DESC(1, 0x54, "TxBroad"),
55 MIB_DESC(1, 0x58, "TxPause"),
56 MIB_DESC(1, 0x5c, "TxMulti"),
57 MIB_DESC(1, 0x60, "TxUnderRun"),
58 MIB_DESC(1, 0x64, "Tx64Byte"),
59 MIB_DESC(1, 0x68, "Tx128Byte"),
60 MIB_DESC(1, 0x6c, "Tx256Byte"),
61 MIB_DESC(1, 0x70, "Tx512Byte"),
62 MIB_DESC(1, 0x74, "Tx1024Byte"),
63 MIB_DESC(1, 0x78, "Tx1518Byte"),
64 MIB_DESC(1, 0x7c, "TxMaxByte"),
65 MIB_DESC(1, 0x80, "TxOverSize"),
66 MIB_DESC(2, 0x84, "TxByte"),
67 MIB_DESC(1, 0x8c, "TxCollision"),
68 MIB_DESC(1, 0x90, "TxAbortCol"),
69 MIB_DESC(1, 0x94, "TxMultiCol"),
70 MIB_DESC(1, 0x98, "TxSingleCol"),
71 MIB_DESC(1, 0x9c, "TxExcDefer"),
72 MIB_DESC(1, 0xa0, "TxDefer"),
73 MIB_DESC(1, 0xa4, "TxLateCol"),
74 MIB_DESC(1, 0xa8, "RXUnicast"),
75 MIB_DESC(1, 0xac, "TXunicast"),
79 qca8k_read(struct qca8k_priv
*priv
, u32 reg
, u32
*val
)
81 return regmap_read(priv
->regmap
, reg
, val
);
85 qca8k_write(struct qca8k_priv
*priv
, u32 reg
, u32 val
)
87 return regmap_write(priv
->regmap
, reg
, val
);
91 qca8k_rmw(struct qca8k_priv
*priv
, u32 reg
, u32 mask
, u32 write_val
)
93 return regmap_update_bits(priv
->regmap
, reg
, mask
, write_val
);
97 qca8k_reg_set(struct qca8k_priv
*priv
, u32 reg
, u32 val
)
99 return regmap_set_bits(priv
->regmap
, reg
, val
);
103 qca8k_reg_clear(struct qca8k_priv
*priv
, u32 reg
, u32 val
)
105 return regmap_clear_bits(priv
->regmap
, reg
, val
);
108 static const struct regmap_range qca8k_readable_ranges
[] = {
109 regmap_reg_range(0x0000, 0x00e4), /* Global control */
110 regmap_reg_range(0x0100, 0x0168), /* EEE control */
111 regmap_reg_range(0x0200, 0x0270), /* Parser control */
112 regmap_reg_range(0x0400, 0x0454), /* ACL */
113 regmap_reg_range(0x0600, 0x0718), /* Lookup */
114 regmap_reg_range(0x0800, 0x0b70), /* QM */
115 regmap_reg_range(0x0c00, 0x0c80), /* PKT */
116 regmap_reg_range(0x0e00, 0x0e98), /* L3 */
117 regmap_reg_range(0x1000, 0x10ac), /* MIB - Port0 */
118 regmap_reg_range(0x1100, 0x11ac), /* MIB - Port1 */
119 regmap_reg_range(0x1200, 0x12ac), /* MIB - Port2 */
120 regmap_reg_range(0x1300, 0x13ac), /* MIB - Port3 */
121 regmap_reg_range(0x1400, 0x14ac), /* MIB - Port4 */
122 regmap_reg_range(0x1500, 0x15ac), /* MIB - Port5 */
123 regmap_reg_range(0x1600, 0x16ac), /* MIB - Port6 */
127 static const struct regmap_access_table qca8k_readable_table
= {
128 .yes_ranges
= qca8k_readable_ranges
,
129 .n_yes_ranges
= ARRAY_SIZE(qca8k_readable_ranges
),
132 static struct regmap_config qca8k_ipq4019_regmap_config
= {
136 .max_register
= 0x16ac, /* end MIB - Port6 range */
137 .rd_table
= &qca8k_readable_table
,
140 static struct regmap_config qca8k_ipq4019_psgmii_phy_regmap_config
= {
141 .name
= "psgmii-phy",
145 .max_register
= 0x7fc,
149 qca8k_busy_wait(struct qca8k_priv
*priv
, u32 reg
, u32 mask
)
153 return regmap_read_poll_timeout(priv
->regmap
, reg
, val
,
156 QCA8K_BUSY_WAIT_TIMEOUT
);
160 qca8k_fdb_read(struct qca8k_priv
*priv
, struct qca8k_fdb
*fdb
)
165 /* load the ARL table into an array */
166 for (i
= 0; i
< 4; i
++) {
167 ret
= qca8k_read(priv
, QCA8K_REG_ATU_DATA0
+ (i
* 4), &val
);
175 fdb
->vid
= (reg
[2] >> QCA8K_ATU_VID_S
) & QCA8K_ATU_VID_M
;
177 fdb
->aging
= reg
[2] & QCA8K_ATU_STATUS_M
;
178 /* portmask - 54:48 */
179 fdb
->port_mask
= (reg
[1] >> QCA8K_ATU_PORT_S
) & QCA8K_ATU_PORT_M
;
181 fdb
->mac
[0] = (reg
[1] >> QCA8K_ATU_ADDR0_S
) & 0xff;
182 fdb
->mac
[1] = reg
[1] & 0xff;
183 fdb
->mac
[2] = (reg
[0] >> QCA8K_ATU_ADDR2_S
) & 0xff;
184 fdb
->mac
[3] = (reg
[0] >> QCA8K_ATU_ADDR3_S
) & 0xff;
185 fdb
->mac
[4] = (reg
[0] >> QCA8K_ATU_ADDR4_S
) & 0xff;
186 fdb
->mac
[5] = reg
[0] & 0xff;
192 qca8k_fdb_write(struct qca8k_priv
*priv
, u16 vid
, u8 port_mask
, const u8
*mac
,
199 reg
[2] = (vid
& QCA8K_ATU_VID_M
) << QCA8K_ATU_VID_S
;
201 reg
[2] |= aging
& QCA8K_ATU_STATUS_M
;
202 /* portmask - 54:48 */
203 reg
[1] = (port_mask
& QCA8K_ATU_PORT_M
) << QCA8K_ATU_PORT_S
;
205 reg
[1] |= mac
[0] << QCA8K_ATU_ADDR0_S
;
207 reg
[0] |= mac
[2] << QCA8K_ATU_ADDR2_S
;
208 reg
[0] |= mac
[3] << QCA8K_ATU_ADDR3_S
;
209 reg
[0] |= mac
[4] << QCA8K_ATU_ADDR4_S
;
212 /* load the array into the ARL table */
213 for (i
= 0; i
< 3; i
++)
214 qca8k_write(priv
, QCA8K_REG_ATU_DATA0
+ (i
* 4), reg
[i
]);
218 qca8k_fdb_access(struct qca8k_priv
*priv
, enum qca8k_fdb_cmd cmd
, int port
)
223 /* Set the command and FDB index */
224 reg
= QCA8K_ATU_FUNC_BUSY
;
227 reg
|= QCA8K_ATU_FUNC_PORT_EN
;
228 reg
|= (port
& QCA8K_ATU_FUNC_PORT_M
) << QCA8K_ATU_FUNC_PORT_S
;
231 /* Write the function register triggering the table access */
232 ret
= qca8k_write(priv
, QCA8K_REG_ATU_FUNC
, reg
);
236 /* wait for completion */
237 ret
= qca8k_busy_wait(priv
, QCA8K_REG_ATU_FUNC
, QCA8K_ATU_FUNC_BUSY
);
241 /* Check for table full violation when adding an entry */
242 if (cmd
== QCA8K_FDB_LOAD
) {
243 ret
= qca8k_read(priv
, QCA8K_REG_ATU_FUNC
, ®
);
246 if (reg
& QCA8K_ATU_FUNC_FULL
)
254 qca8k_fdb_next(struct qca8k_priv
*priv
, struct qca8k_fdb
*fdb
, int port
)
258 qca8k_fdb_write(priv
, fdb
->vid
, fdb
->port_mask
, fdb
->mac
, fdb
->aging
);
259 ret
= qca8k_fdb_access(priv
, QCA8K_FDB_NEXT
, port
);
263 return qca8k_fdb_read(priv
, fdb
);
267 qca8k_fdb_add(struct qca8k_priv
*priv
, const u8
*mac
, u16 port_mask
,
272 mutex_lock(&priv
->reg_mutex
);
273 qca8k_fdb_write(priv
, vid
, port_mask
, mac
, aging
);
274 ret
= qca8k_fdb_access(priv
, QCA8K_FDB_LOAD
, -1);
275 mutex_unlock(&priv
->reg_mutex
);
281 qca8k_fdb_del(struct qca8k_priv
*priv
, const u8
*mac
, u16 port_mask
, u16 vid
)
285 mutex_lock(&priv
->reg_mutex
);
286 qca8k_fdb_write(priv
, vid
, port_mask
, mac
, 0);
287 ret
= qca8k_fdb_access(priv
, QCA8K_FDB_PURGE
, -1);
288 mutex_unlock(&priv
->reg_mutex
);
294 qca8k_fdb_flush(struct qca8k_priv
*priv
)
296 mutex_lock(&priv
->reg_mutex
);
297 qca8k_fdb_access(priv
, QCA8K_FDB_FLUSH
, -1);
298 mutex_unlock(&priv
->reg_mutex
);
302 qca8k_vlan_access(struct qca8k_priv
*priv
, enum qca8k_vlan_cmd cmd
, u16 vid
)
307 /* Set the command and VLAN index */
308 reg
= QCA8K_VTU_FUNC1_BUSY
;
310 reg
|= vid
<< QCA8K_VTU_FUNC1_VID_S
;
312 /* Write the function register triggering the table access */
313 ret
= qca8k_write(priv
, QCA8K_REG_VTU_FUNC1
, reg
);
317 /* wait for completion */
318 ret
= qca8k_busy_wait(priv
, QCA8K_REG_VTU_FUNC1
, QCA8K_VTU_FUNC1_BUSY
);
322 /* Check for table full violation when adding an entry */
323 if (cmd
== QCA8K_VLAN_LOAD
) {
324 ret
= qca8k_read(priv
, QCA8K_REG_VTU_FUNC1
, ®
);
327 if (reg
& QCA8K_VTU_FUNC1_FULL
)
335 qca8k_vlan_add(struct qca8k_priv
*priv
, u8 port
, u16 vid
, bool untagged
)
341 We do the right thing with VLAN 0 and treat it as untagged while
342 preserving the tag on egress.
347 mutex_lock(&priv
->reg_mutex
);
348 ret
= qca8k_vlan_access(priv
, QCA8K_VLAN_READ
, vid
);
352 ret
= qca8k_read(priv
, QCA8K_REG_VTU_FUNC0
, ®
);
355 reg
|= QCA8K_VTU_FUNC0_VALID
| QCA8K_VTU_FUNC0_IVL_EN
;
356 reg
&= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK
<< QCA8K_VTU_FUNC0_EG_MODE_S(port
));
358 reg
|= QCA8K_VTU_FUNC0_EG_MODE_UNTAG
<<
359 QCA8K_VTU_FUNC0_EG_MODE_S(port
);
361 reg
|= QCA8K_VTU_FUNC0_EG_MODE_TAG
<<
362 QCA8K_VTU_FUNC0_EG_MODE_S(port
);
364 ret
= qca8k_write(priv
, QCA8K_REG_VTU_FUNC0
, reg
);
367 ret
= qca8k_vlan_access(priv
, QCA8K_VLAN_LOAD
, vid
);
370 mutex_unlock(&priv
->reg_mutex
);
376 qca8k_vlan_del(struct qca8k_priv
*priv
, u8 port
, u16 vid
)
382 mutex_lock(&priv
->reg_mutex
);
383 ret
= qca8k_vlan_access(priv
, QCA8K_VLAN_READ
, vid
);
387 ret
= qca8k_read(priv
, QCA8K_REG_VTU_FUNC0
, ®
);
390 reg
&= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port
));
391 reg
|= QCA8K_VTU_FUNC0_EG_MODE_NOT
<<
392 QCA8K_VTU_FUNC0_EG_MODE_S(port
);
394 /* Check if we're the last member to be removed */
396 for (i
= 0; i
< QCA8K_NUM_PORTS
; i
++) {
397 mask
= QCA8K_VTU_FUNC0_EG_MODE_NOT
;
398 mask
<<= QCA8K_VTU_FUNC0_EG_MODE_S(i
);
400 if ((reg
& mask
) != mask
) {
407 ret
= qca8k_vlan_access(priv
, QCA8K_VLAN_PURGE
, vid
);
409 ret
= qca8k_write(priv
, QCA8K_REG_VTU_FUNC0
, reg
);
412 ret
= qca8k_vlan_access(priv
, QCA8K_VLAN_LOAD
, vid
);
416 mutex_unlock(&priv
->reg_mutex
);
422 qca8k_mib_init(struct qca8k_priv
*priv
)
426 mutex_lock(&priv
->reg_mutex
);
427 ret
= qca8k_reg_set(priv
, QCA8K_REG_MIB
, QCA8K_MIB_FLUSH
| QCA8K_MIB_BUSY
);
431 ret
= qca8k_busy_wait(priv
, QCA8K_REG_MIB
, QCA8K_MIB_BUSY
);
435 ret
= qca8k_reg_set(priv
, QCA8K_REG_MIB
, QCA8K_MIB_CPU_KEEP
);
439 ret
= qca8k_write(priv
, QCA8K_REG_MODULE_EN
, QCA8K_MODULE_EN_MIB
);
442 mutex_unlock(&priv
->reg_mutex
);
447 qca8k_port_set_status(struct qca8k_priv
*priv
, int port
, int enable
)
449 u32 mask
= QCA8K_PORT_STATUS_TXMAC
| QCA8K_PORT_STATUS_RXMAC
;
451 /* Port 0 is internally connected to the CPU
452 * TODO: Probably check for RGMII as well if it doesnt work
455 if (port
> QCA8K_CPU_PORT
)
456 mask
|= QCA8K_PORT_STATUS_LINK_AUTO
;
459 qca8k_reg_set(priv
, QCA8K_REG_PORT_STATUS(port
), mask
);
461 qca8k_reg_clear(priv
, QCA8K_REG_PORT_STATUS(port
), mask
);
465 qca8k_setup_port(struct dsa_switch
*ds
, int port
)
467 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
470 /* CPU port gets connected to all user ports of the switch */
471 if (dsa_is_cpu_port(ds
, port
)) {
472 ret
= qca8k_rmw(priv
, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT
),
473 QCA8K_PORT_LOOKUP_MEMBER
, dsa_user_ports(ds
));
477 /* Disable CPU ARP Auto-learning by default */
478 ret
= qca8k_reg_clear(priv
, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT
),
479 QCA8K_PORT_LOOKUP_LEARN
);
484 /* Individual user ports get connected to CPU port only */
485 if (dsa_is_user_port(ds
, port
)) {
486 int shift
= 16 * (port
% 2);
488 ret
= qca8k_rmw(priv
, QCA8K_PORT_LOOKUP_CTRL(port
),
489 QCA8K_PORT_LOOKUP_MEMBER
,
490 BIT(QCA8K_CPU_PORT
));
494 /* Enable ARP Auto-learning by default */
495 ret
= qca8k_reg_set(priv
, QCA8K_PORT_LOOKUP_CTRL(port
),
496 QCA8K_PORT_LOOKUP_LEARN
);
500 /* For port based vlans to work we need to set the
503 ret
= qca8k_rmw(priv
, QCA8K_EGRESS_VLAN(port
),
505 QCA8K_PORT_VID_DEF
<< shift
);
509 ret
= qca8k_write(priv
, QCA8K_REG_PORT_VLAN_CTRL0(port
),
510 QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF
) |
511 QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF
));
520 qca8k_setup(struct dsa_switch
*ds
)
522 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
525 /* Make sure that port 0 is the cpu port */
526 if (!dsa_is_cpu_port(ds
, 0)) {
527 dev_err(priv
->dev
, "port 0 is not the CPU port");
531 /* Enable CPU Port */
532 ret
= qca8k_reg_set(priv
, QCA8K_REG_GLOBAL_FW_CTRL0
,
533 QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN
);
535 dev_err(priv
->dev
, "failed enabling CPU port");
539 /* Enable MIB counters */
540 ret
= qca8k_mib_init(priv
);
542 dev_warn(priv
->dev
, "MIB init failed");
544 /* Enable QCA header mode on the cpu port */
545 ret
= qca8k_write(priv
, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT
),
546 QCA8K_PORT_HDR_CTRL_ALL
<< QCA8K_PORT_HDR_CTRL_TX_S
|
547 QCA8K_PORT_HDR_CTRL_ALL
<< QCA8K_PORT_HDR_CTRL_RX_S
);
549 dev_err(priv
->dev
, "failed enabling QCA header mode");
553 /* Disable forwarding by default on all ports */
554 for (i
= 0; i
< QCA8K_NUM_PORTS
; i
++) {
555 ret
= qca8k_rmw(priv
, QCA8K_PORT_LOOKUP_CTRL(i
),
556 QCA8K_PORT_LOOKUP_MEMBER
, 0);
561 /* Disable MAC by default on all ports */
562 for (i
= 1; i
< QCA8K_NUM_PORTS
; i
++)
563 qca8k_port_set_status(priv
, i
, 0);
565 /* Forward all unknown frames to CPU port for Linux processing */
566 ret
= qca8k_write(priv
, QCA8K_REG_GLOBAL_FW_CTRL1
,
567 BIT(QCA8K_CPU_PORT
) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S
|
568 BIT(QCA8K_CPU_PORT
) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S
|
569 BIT(QCA8K_CPU_PORT
) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S
|
570 BIT(QCA8K_CPU_PORT
) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S
);
574 /* Setup connection between CPU port & user ports */
575 for (i
= 0; i
< QCA8K_NUM_PORTS
; i
++) {
576 ret
= qca8k_setup_port(ds
, i
);
581 /* Setup our port MTUs to match power on defaults */
582 for (i
= 0; i
< QCA8K_NUM_PORTS
; i
++)
583 /* Set per port MTU to 1500 as the MTU change function
584 * will add the overhead and if its set to 1518 then it
585 * will apply the overhead again and we will end up with
586 * MTU of 1536 instead of 1518
588 priv
->port_mtu
[i
] = ETH_DATA_LEN
;
589 ret
= qca8k_write(priv
, QCA8K_MAX_FRAME_SIZE
, ETH_FRAME_LEN
+ ETH_FCS_LEN
);
591 dev_warn(priv
->dev
, "failed setting MTU settings");
593 /* Flush the FDB table */
594 qca8k_fdb_flush(priv
);
596 /* We don't have interrupts for link changes, so we need to poll */
599 /* CPU port HW learning doesnt work correctly, so let DSA handle it */
600 ds
->assisted_learning_on_cpu_port
= true;
605 static int psgmii_vco_calibrate(struct dsa_switch
*ds
)
607 struct qca8k_priv
*priv
= ds
->priv
;
610 if (!priv
->psgmii_ethphy
) {
611 dev_err(ds
->dev
, "PSGMII eth PHY missing, calibration failed!\n");
615 /* Fix PSGMII RX 20bit */
616 ret
= phy_write(priv
->psgmii_ethphy
, MII_BMCR
, 0x5b);
617 /* Reset PSGMII PHY */
618 ret
= phy_write(priv
->psgmii_ethphy
, MII_BMCR
, 0x1b);
620 ret
= phy_write(priv
->psgmii_ethphy
, MII_BMCR
, 0x5b);
622 /* Poll for VCO PLL calibration finish */
623 ret
= phy_read_mmd_poll_timeout(priv
->psgmii_ethphy
,
630 dev_err(ds
->dev
, "QCA807x PSGMII VCO calibration PLL not ready\n");
634 /* Freeze PSGMII RX CDR */
635 ret
= phy_write(priv
->psgmii_ethphy
, MII_RESV2
, 0x2230);
637 /* Start PSGMIIPHY VCO PLL calibration */
638 ret
= regmap_set_bits(priv
->psgmii
,
639 PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_1
,
640 PSGMIIPHY_REG_PLL_VCO_CALIB_RESTART
);
642 /* Poll for PSGMIIPHY PLL calibration finish */
643 ret
= regmap_read_poll_timeout(priv
->psgmii
,
644 PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_2
,
645 val
, val
& PSGMIIPHY_REG_PLL_VCO_CALIB_READY
,
648 dev_err(ds
->dev
, "PSGMIIPHY VCO calibration PLL not ready\n");
652 /* Release PSGMII RX CDR */
653 ret
= phy_write(priv
->psgmii_ethphy
, MII_RESV2
, 0x3230);
655 /* Release PSGMII RX 20bit */
656 ret
= phy_write(priv
->psgmii_ethphy
, MII_BMCR
, 0x5f);
661 static int ipq4019_psgmii_configure(struct dsa_switch
*ds
)
663 struct qca8k_priv
*priv
= ds
->priv
;
666 if (!priv
->psgmii_calibrated
) {
667 ret
= psgmii_vco_calibrate(ds
);
669 ret
= regmap_clear_bits(priv
->psgmii
, PSGMIIPHY_MODE_CONTROL
,
670 PSGMIIPHY_MODE_ATHR_CSCO_MODE_25M
);
671 ret
= regmap_write(priv
->psgmii
, PSGMIIPHY_TX_CONTROL
,
672 PSGMIIPHY_TX_CONTROL_MAGIC_VALUE
);
674 priv
->psgmii_calibrated
= true;
683 qca8k_phylink_mac_config(struct dsa_switch
*ds
, int port
, unsigned int mode
,
684 const struct phylink_link_state
*state
)
686 struct qca8k_priv
*priv
= ds
->priv
;
690 /* CPU port, no configuration needed */
695 if (state
->interface
== PHY_INTERFACE_MODE_PSGMII
)
696 if (ipq4019_psgmii_configure(ds
))
697 dev_err(ds
->dev
, "PSGMII configuration failed!\n");
701 if (state
->interface
== PHY_INTERFACE_MODE_RGMII
||
702 state
->interface
== PHY_INTERFACE_MODE_RGMII_ID
||
703 state
->interface
== PHY_INTERFACE_MODE_RGMII_RXID
||
704 state
->interface
== PHY_INTERFACE_MODE_RGMII_TXID
) {
705 qca8k_reg_set(priv
, QCA8K_REG_RGMII_CTRL
, QCA8K_RGMII_CTRL_CLK
);
708 if (state
->interface
== PHY_INTERFACE_MODE_PSGMII
)
709 if (ipq4019_psgmii_configure(ds
))
710 dev_err(ds
->dev
, "PSGMII configuration failed!\n");
713 dev_err(ds
->dev
, "%s: unsupported port: %i\n", __func__
, port
);
719 qca8k_phylink_validate(struct dsa_switch
*ds
, int port
,
720 unsigned long *supported
,
721 struct phylink_link_state
*state
)
723 __ETHTOOL_DECLARE_LINK_MODE_MASK(mask
) = { 0, };
726 case 0: /* CPU port */
727 if (state
->interface
!= PHY_INTERFACE_MODE_INTERNAL
)
733 /* Only PSGMII mode is supported */
734 if (state
->interface
!= PHY_INTERFACE_MODE_PSGMII
)
739 /* PSGMII and RGMII modes are supported */
740 if (state
->interface
!= PHY_INTERFACE_MODE_PSGMII
&&
741 state
->interface
!= PHY_INTERFACE_MODE_RGMII
&&
742 state
->interface
!= PHY_INTERFACE_MODE_RGMII_ID
&&
743 state
->interface
!= PHY_INTERFACE_MODE_RGMII_RXID
&&
744 state
->interface
!= PHY_INTERFACE_MODE_RGMII_TXID
)
749 dev_warn(ds
->dev
, "interface '%s' (%d) on port %d is not supported\n",
750 phy_modes(state
->interface
), state
->interface
, port
);
751 linkmode_zero(supported
);
756 phylink_set_port_modes(mask
);
758 phylink_set(mask
, 1000baseT_Full
);
760 phylink_set(mask
, Pause
);
761 phylink_set(mask
, Asym_Pause
);
763 linkmode_and(supported
, supported
, mask
);
764 linkmode_and(state
->advertising
, state
->advertising
, mask
);
766 /* Simply copy what PHYs tell us */
767 linkmode_copy(state
->advertising
, supported
);
772 qca8k_phylink_mac_link_state(struct dsa_switch
*ds
, int port
,
773 struct phylink_link_state
*state
)
775 struct qca8k_priv
*priv
= ds
->priv
;
779 ret
= qca8k_read(priv
, QCA8K_REG_PORT_STATUS(port
), ®
);
783 state
->link
= !!(reg
& QCA8K_PORT_STATUS_LINK_UP
);
784 state
->an_complete
= state
->link
;
785 state
->an_enabled
= !!(reg
& QCA8K_PORT_STATUS_LINK_AUTO
);
786 state
->duplex
= (reg
& QCA8K_PORT_STATUS_DUPLEX
) ? DUPLEX_FULL
:
789 switch (reg
& QCA8K_PORT_STATUS_SPEED
) {
790 case QCA8K_PORT_STATUS_SPEED_10
:
791 state
->speed
= SPEED_10
;
793 case QCA8K_PORT_STATUS_SPEED_100
:
794 state
->speed
= SPEED_100
;
796 case QCA8K_PORT_STATUS_SPEED_1000
:
797 state
->speed
= SPEED_1000
;
800 state
->speed
= SPEED_UNKNOWN
;
804 state
->pause
= MLO_PAUSE_NONE
;
805 if (reg
& QCA8K_PORT_STATUS_RXFLOW
)
806 state
->pause
|= MLO_PAUSE_RX
;
807 if (reg
& QCA8K_PORT_STATUS_TXFLOW
)
808 state
->pause
|= MLO_PAUSE_TX
;
814 qca8k_phylink_mac_link_down(struct dsa_switch
*ds
, int port
, unsigned int mode
,
815 phy_interface_t interface
)
817 struct qca8k_priv
*priv
= ds
->priv
;
819 qca8k_port_set_status(priv
, port
, 0);
823 qca8k_phylink_mac_link_up(struct dsa_switch
*ds
, int port
, unsigned int mode
,
824 phy_interface_t interface
, struct phy_device
*phydev
,
825 int speed
, int duplex
, bool tx_pause
, bool rx_pause
)
827 struct qca8k_priv
*priv
= ds
->priv
;
830 if (phylink_autoneg_inband(mode
)) {
831 reg
= QCA8K_PORT_STATUS_LINK_AUTO
;
835 reg
= QCA8K_PORT_STATUS_SPEED_10
;
838 reg
= QCA8K_PORT_STATUS_SPEED_100
;
841 reg
= QCA8K_PORT_STATUS_SPEED_1000
;
844 reg
= QCA8K_PORT_STATUS_LINK_AUTO
;
848 if (duplex
== DUPLEX_FULL
)
849 reg
|= QCA8K_PORT_STATUS_DUPLEX
;
851 if (rx_pause
|| dsa_is_cpu_port(ds
, port
))
852 reg
|= QCA8K_PORT_STATUS_RXFLOW
;
854 if (tx_pause
|| dsa_is_cpu_port(ds
, port
))
855 reg
|= QCA8K_PORT_STATUS_TXFLOW
;
858 reg
|= QCA8K_PORT_STATUS_TXMAC
| QCA8K_PORT_STATUS_RXMAC
;
860 qca8k_write(priv
, QCA8K_REG_PORT_STATUS(port
), reg
);
864 qca8k_get_strings(struct dsa_switch
*ds
, int port
, u32 stringset
, uint8_t *data
)
868 if (stringset
!= ETH_SS_STATS
)
871 for (i
= 0; i
< ARRAY_SIZE(ar8327_mib
); i
++)
872 strncpy(data
+ i
* ETH_GSTRING_LEN
, ar8327_mib
[i
].name
,
877 qca8k_get_ethtool_stats(struct dsa_switch
*ds
, int port
,
880 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
881 const struct qca8k_mib_desc
*mib
;
886 for (i
= 0; i
< ARRAY_SIZE(ar8327_mib
); i
++) {
887 mib
= &ar8327_mib
[i
];
888 reg
= QCA8K_PORT_MIB_COUNTER(port
) + mib
->offset
;
890 ret
= qca8k_read(priv
, reg
, &val
);
894 if (mib
->size
== 2) {
895 ret
= qca8k_read(priv
, reg
+ 4, &hi
);
902 data
[i
] |= (u64
)hi
<< 32;
907 qca8k_get_sset_count(struct dsa_switch
*ds
, int port
, int sset
)
909 if (sset
!= ETH_SS_STATS
)
912 return ARRAY_SIZE(ar8327_mib
);
916 qca8k_set_mac_eee(struct dsa_switch
*ds
, int port
, struct ethtool_eee
*eee
)
918 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
919 u32 lpi_en
= QCA8K_REG_EEE_CTRL_LPI_EN(port
);
923 mutex_lock(&priv
->reg_mutex
);
924 ret
= qca8k_read(priv
, QCA8K_REG_EEE_CTRL
, ®
);
928 if (eee
->eee_enabled
)
932 ret
= qca8k_write(priv
, QCA8K_REG_EEE_CTRL
, reg
);
935 mutex_unlock(&priv
->reg_mutex
);
940 qca8k_get_mac_eee(struct dsa_switch
*ds
, int port
, struct ethtool_eee
*e
)
942 /* Nothing to do on the port's MAC */
947 qca8k_port_stp_state_set(struct dsa_switch
*ds
, int port
, u8 state
)
949 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
953 case BR_STATE_DISABLED
:
954 stp_state
= QCA8K_PORT_LOOKUP_STATE_DISABLED
;
956 case BR_STATE_BLOCKING
:
957 stp_state
= QCA8K_PORT_LOOKUP_STATE_BLOCKING
;
959 case BR_STATE_LISTENING
:
960 stp_state
= QCA8K_PORT_LOOKUP_STATE_LISTENING
;
962 case BR_STATE_LEARNING
:
963 stp_state
= QCA8K_PORT_LOOKUP_STATE_LEARNING
;
965 case BR_STATE_FORWARDING
:
967 stp_state
= QCA8K_PORT_LOOKUP_STATE_FORWARD
;
971 qca8k_rmw(priv
, QCA8K_PORT_LOOKUP_CTRL(port
),
972 QCA8K_PORT_LOOKUP_STATE_MASK
, stp_state
);
976 qca8k_port_bridge_join(struct dsa_switch
*ds
, int port
, struct net_device
*br
)
978 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
979 int port_mask
, cpu_port
;
982 cpu_port
= dsa_to_port(ds
, port
)->cpu_dp
->index
;
983 port_mask
= BIT(cpu_port
);
985 for (i
= 0; i
< QCA8K_NUM_PORTS
; i
++) {
986 if (dsa_is_cpu_port(ds
, i
))
988 if (dsa_to_port(ds
, i
)->bridge_dev
!= br
)
990 /* Add this port to the portvlan mask of the other ports
993 ret
= qca8k_reg_set(priv
,
994 QCA8K_PORT_LOOKUP_CTRL(i
),
1002 /* Add all other ports to this ports portvlan mask */
1003 ret
= qca8k_rmw(priv
, QCA8K_PORT_LOOKUP_CTRL(port
),
1004 QCA8K_PORT_LOOKUP_MEMBER
, port_mask
);
1010 qca8k_port_bridge_leave(struct dsa_switch
*ds
, int port
, struct net_device
*br
)
1012 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
1015 cpu_port
= dsa_to_port(ds
, port
)->cpu_dp
->index
;
1017 for (i
= 0; i
< QCA8K_NUM_PORTS
; i
++) {
1018 if (dsa_is_cpu_port(ds
, i
))
1020 if (dsa_to_port(ds
, i
)->bridge_dev
!= br
)
1022 /* Remove this port to the portvlan mask of the other ports
1025 qca8k_reg_clear(priv
,
1026 QCA8K_PORT_LOOKUP_CTRL(i
),
1030 /* Set the cpu port to be the only one in the portvlan mask of
1033 qca8k_rmw(priv
, QCA8K_PORT_LOOKUP_CTRL(port
),
1034 QCA8K_PORT_LOOKUP_MEMBER
, BIT(cpu_port
));
1038 qca8k_port_enable(struct dsa_switch
*ds
, int port
,
1039 struct phy_device
*phy
)
1041 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
1043 qca8k_port_set_status(priv
, port
, 1);
1044 priv
->port_sts
[port
].enabled
= 1;
1046 if (dsa_is_user_port(ds
, port
))
1047 phy_support_asym_pause(phy
);
1053 qca8k_port_disable(struct dsa_switch
*ds
, int port
)
1055 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
1057 qca8k_port_set_status(priv
, port
, 0);
1058 priv
->port_sts
[port
].enabled
= 0;
1062 qca8k_port_change_mtu(struct dsa_switch
*ds
, int port
, int new_mtu
)
1064 struct qca8k_priv
*priv
= ds
->priv
;
1067 priv
->port_mtu
[port
] = new_mtu
;
1069 for (i
= 0; i
< QCA8K_NUM_PORTS
; i
++)
1070 if (priv
->port_mtu
[i
] > mtu
)
1071 mtu
= priv
->port_mtu
[i
];
1073 /* Include L2 header / FCS length */
1074 return qca8k_write(priv
, QCA8K_MAX_FRAME_SIZE
, mtu
+ ETH_HLEN
+ ETH_FCS_LEN
);
1078 qca8k_port_max_mtu(struct dsa_switch
*ds
, int port
)
1080 return QCA8K_MAX_MTU
;
1084 qca8k_port_fdb_insert(struct qca8k_priv
*priv
, const u8
*addr
,
1085 u16 port_mask
, u16 vid
)
1087 /* Set the vid to the port vlan id if no vid is set */
1089 vid
= QCA8K_PORT_VID_DEF
;
1091 return qca8k_fdb_add(priv
, addr
, port_mask
, vid
,
1092 QCA8K_ATU_STATUS_STATIC
);
1096 qca8k_port_fdb_add(struct dsa_switch
*ds
, int port
,
1097 const unsigned char *addr
, u16 vid
)
1099 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
1100 u16 port_mask
= BIT(port
);
1102 return qca8k_port_fdb_insert(priv
, addr
, port_mask
, vid
);
1106 qca8k_port_fdb_del(struct dsa_switch
*ds
, int port
,
1107 const unsigned char *addr
, u16 vid
)
1109 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
1110 u16 port_mask
= BIT(port
);
1113 vid
= QCA8K_PORT_VID_DEF
;
1115 return qca8k_fdb_del(priv
, addr
, port_mask
, vid
);
1119 qca8k_port_fdb_dump(struct dsa_switch
*ds
, int port
,
1120 dsa_fdb_dump_cb_t
*cb
, void *data
)
1122 struct qca8k_priv
*priv
= (struct qca8k_priv
*)ds
->priv
;
1123 struct qca8k_fdb _fdb
= { 0 };
1124 int cnt
= QCA8K_NUM_FDB_RECORDS
;
1128 mutex_lock(&priv
->reg_mutex
);
1129 while (cnt
-- && !qca8k_fdb_next(priv
, &_fdb
, port
)) {
1132 is_static
= (_fdb
.aging
== QCA8K_ATU_STATUS_STATIC
);
1133 ret
= cb(_fdb
.mac
, _fdb
.vid
, is_static
, data
);
1137 mutex_unlock(&priv
->reg_mutex
);
1142 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
1144 qca8k_port_vlan_filtering(struct dsa_switch
*ds
, int port
, bool vlan_filtering
,
1145 struct switchdev_trans
*trans
)
1148 qca8k_port_vlan_filtering(struct dsa_switch
*ds
, int port
, bool vlan_filtering
,
1149 struct netlink_ext_ack
*extack
)
1152 struct qca8k_priv
*priv
= ds
->priv
;
1154 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
1155 if (switchdev_trans_ph_prepare(trans
))
1159 if (vlan_filtering
) {
1160 qca8k_rmw(priv
, QCA8K_PORT_LOOKUP_CTRL(port
),
1161 QCA8K_PORT_LOOKUP_VLAN_MODE
,
1162 QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE
);
1164 qca8k_rmw(priv
, QCA8K_PORT_LOOKUP_CTRL(port
),
1165 QCA8K_PORT_LOOKUP_VLAN_MODE
,
1166 QCA8K_PORT_LOOKUP_VLAN_MODE_NONE
);
1172 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
1174 qca8k_port_vlan_prepare(struct dsa_switch
*ds
, int port
,
1175 const struct switchdev_obj_port_vlan
*vlan
)
1181 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
1183 qca8k_port_vlan_add(struct dsa_switch
*ds
, int port
,
1184 const struct switchdev_obj_port_vlan
*vlan
)
1187 qca8k_port_vlan_add(struct dsa_switch
*ds
, int port
,
1188 const struct switchdev_obj_port_vlan
*vlan
,
1189 struct netlink_ext_ack
*extack
)
1192 bool untagged
= vlan
->flags
& BRIDGE_VLAN_INFO_UNTAGGED
;
1193 bool pvid
= vlan
->flags
& BRIDGE_VLAN_INFO_PVID
;
1194 struct qca8k_priv
*priv
= ds
->priv
;
1196 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
1199 for (vid
= vlan
->vid_begin
; vid
<= vlan
->vid_end
&& !ret
; ++vid
)
1200 ret
= qca8k_vlan_add(priv
, port
, vid
, untagged
);
1202 ret
= qca8k_vlan_add(priv
, port
, vlan
->vid
, untagged
);
1204 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
1206 dev_err(priv
->dev
, "Failed to add VLAN to port %d (%d)", port
, ret
);
1209 dev_err(priv
->dev
, "Failed to add VLAN to port %d (%d)", port
, ret
);
1215 int shift
= 16 * (port
% 2);
1217 qca8k_rmw(priv
, QCA8K_EGRESS_VLAN(port
),
1218 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
1220 vlan
->vid_end
<< shift
);
1222 0xfff << shift
, vlan
->vid
<< shift
);
1224 qca8k_write(priv
, QCA8K_REG_PORT_VLAN_CTRL0(port
),
1225 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
1226 QCA8K_PORT_VLAN_CVID(vlan
->vid_end
) |
1227 QCA8K_PORT_VLAN_SVID(vlan
->vid_end
));
1229 QCA8K_PORT_VLAN_CVID(vlan
->vid
) |
1230 QCA8K_PORT_VLAN_SVID(vlan
->vid
));
1233 #if LINUX_VERSION_CODE > KERNEL_VERSION(5,12,0)
1239 qca8k_port_vlan_del(struct dsa_switch
*ds
, int port
,
1240 const struct switchdev_obj_port_vlan
*vlan
)
1242 struct qca8k_priv
*priv
= ds
->priv
;
1244 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
1247 for (vid
= vlan
->vid_begin
; vid
<= vlan
->vid_end
&& !ret
; ++vid
)
1248 ret
= qca8k_vlan_del(priv
, port
, vid
);
1250 ret
= qca8k_vlan_del(priv
, port
, vlan
->vid
);
1253 dev_err(priv
->dev
, "Failed to delete VLAN from port %d (%d)", port
, ret
);
1258 static enum dsa_tag_protocol
1259 qca8k_get_tag_protocol(struct dsa_switch
*ds
, int port
,
1260 enum dsa_tag_protocol mp
)
1262 return DSA_TAG_PROTO_IPQ4019
;
1265 static const struct dsa_switch_ops qca8k_switch_ops
= {
1266 .get_tag_protocol
= qca8k_get_tag_protocol
,
1267 .setup
= qca8k_setup
,
1268 .get_strings
= qca8k_get_strings
,
1269 .get_ethtool_stats
= qca8k_get_ethtool_stats
,
1270 .get_sset_count
= qca8k_get_sset_count
,
1271 .get_mac_eee
= qca8k_get_mac_eee
,
1272 .set_mac_eee
= qca8k_set_mac_eee
,
1273 .port_enable
= qca8k_port_enable
,
1274 .port_disable
= qca8k_port_disable
,
1275 .port_change_mtu
= qca8k_port_change_mtu
,
1276 .port_max_mtu
= qca8k_port_max_mtu
,
1277 .port_stp_state_set
= qca8k_port_stp_state_set
,
1278 .port_bridge_join
= qca8k_port_bridge_join
,
1279 .port_bridge_leave
= qca8k_port_bridge_leave
,
1280 .port_fdb_add
= qca8k_port_fdb_add
,
1281 .port_fdb_del
= qca8k_port_fdb_del
,
1282 .port_fdb_dump
= qca8k_port_fdb_dump
,
1283 .port_vlan_filtering
= qca8k_port_vlan_filtering
,
1284 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
1285 .port_vlan_prepare
= qca8k_port_vlan_prepare
,
1287 .port_vlan_add
= qca8k_port_vlan_add
,
1288 .port_vlan_del
= qca8k_port_vlan_del
,
1289 .phylink_validate
= qca8k_phylink_validate
,
1290 .phylink_mac_link_state
= qca8k_phylink_mac_link_state
,
1291 .phylink_mac_config
= qca8k_phylink_mac_config
,
1292 .phylink_mac_link_down
= qca8k_phylink_mac_link_down
,
1293 .phylink_mac_link_up
= qca8k_phylink_mac_link_up
,
1297 qca8k_ipq4019_probe(struct platform_device
*pdev
)
1299 struct qca8k_priv
*priv
;
1300 void __iomem
*base
, *psgmii
;
1301 struct device_node
*np
= pdev
->dev
.of_node
, *mdio_np
, *psgmii_ethphy_np
;
1304 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
1308 priv
->dev
= &pdev
->dev
;
1310 base
= devm_platform_ioremap_resource_byname(pdev
, "base");
1312 return PTR_ERR(base
);
1314 priv
->regmap
= devm_regmap_init_mmio(priv
->dev
, base
,
1315 &qca8k_ipq4019_regmap_config
);
1316 if (IS_ERR(priv
->regmap
)) {
1317 ret
= PTR_ERR(priv
->regmap
);
1318 dev_err(priv
->dev
, "base regmap initialization failed, %d\n", ret
);
1322 psgmii
= devm_platform_ioremap_resource_byname(pdev
, "psgmii_phy");
1324 return PTR_ERR(psgmii
);
1326 priv
->psgmii
= devm_regmap_init_mmio(priv
->dev
, psgmii
,
1327 &qca8k_ipq4019_psgmii_phy_regmap_config
);
1328 if (IS_ERR(priv
->psgmii
)) {
1329 ret
= PTR_ERR(priv
->psgmii
);
1330 dev_err(priv
->dev
, "PSGMII regmap initialization failed, %d\n", ret
);
1334 mdio_np
= of_parse_phandle(np
, "mdio", 0);
1336 dev_err(&pdev
->dev
, "unable to get MDIO bus phandle\n");
1337 of_node_put(mdio_np
);
1341 priv
->bus
= of_mdio_find_bus(mdio_np
);
1342 of_node_put(mdio_np
);
1344 dev_err(&pdev
->dev
, "unable to find MDIO bus\n");
1345 return -EPROBE_DEFER
;
1348 psgmii_ethphy_np
= of_parse_phandle(np
, "psgmii-ethphy", 0);
1349 if (!psgmii_ethphy_np
) {
1350 dev_dbg(&pdev
->dev
, "unable to get PSGMII eth PHY phandle\n");
1351 of_node_put(psgmii_ethphy_np
);
1354 if (psgmii_ethphy_np
) {
1355 priv
->psgmii_ethphy
= of_phy_find_device(psgmii_ethphy_np
);
1356 of_node_put(psgmii_ethphy_np
);
1357 if (!priv
->psgmii_ethphy
) {
1358 dev_err(&pdev
->dev
, "unable to get PSGMII eth PHY\n");
1363 priv
->ds
= devm_kzalloc(priv
->dev
, sizeof(*priv
->ds
), GFP_KERNEL
);
1367 priv
->ds
->dev
= priv
->dev
;
1368 priv
->ds
->num_ports
= QCA8K_NUM_PORTS
;
1369 priv
->ds
->priv
= priv
;
1370 priv
->ops
= qca8k_switch_ops
;
1371 priv
->ds
->ops
= &priv
->ops
;
1373 mutex_init(&priv
->reg_mutex
);
1374 platform_set_drvdata(pdev
, priv
);
1376 return dsa_register_switch(priv
->ds
);
1380 qca8k_ipq4019_remove(struct platform_device
*pdev
)
1382 struct qca8k_priv
*priv
= dev_get_drvdata(&pdev
->dev
);
1388 for (i
= 0; i
< QCA8K_NUM_PORTS
; i
++)
1389 qca8k_port_set_status(priv
, i
, 0);
1391 dsa_unregister_switch(priv
->ds
);
1393 dev_set_drvdata(&pdev
->dev
, NULL
);
1398 static const struct of_device_id qca8k_ipq4019_of_match
[] = {
1399 { .compatible
= "qca,ipq4019-qca8337n" },
1403 static struct platform_driver qca8k_ipq4019_driver
= {
1404 .probe
= qca8k_ipq4019_probe
,
1405 .remove
= qca8k_ipq4019_remove
,
1407 .name
= "qca8k-ipq4019",
1408 .of_match_table
= qca8k_ipq4019_of_match
,
1412 module_platform_driver(qca8k_ipq4019_driver
);
1414 MODULE_AUTHOR("Mathieu Olivari, John Crispin <john@phrozen.org>");
1415 MODULE_AUTHOR("Gabor Juhos <j4g8y7@gmail.com>, Robert Marko <robert.marko@sartura.hr>");
1416 MODULE_DESCRIPTION("Qualcomm IPQ4019 built-in switch driver");
1417 MODULE_LICENSE("GPL v2");