xref: /linux/drivers/net/dsa/microchip/lan937x_main.c (revision ffaf1de2f62d2e783a169976846d9fe6c11e8b64)
155ab6ffaSArun Ramadoss // SPDX-License-Identifier: GPL-2.0
255ab6ffaSArun Ramadoss /* Microchip LAN937X switch driver main logic
355ab6ffaSArun Ramadoss  * Copyright (C) 2019-2022 Microchip Technology Inc.
455ab6ffaSArun Ramadoss  */
555ab6ffaSArun Ramadoss #include <linux/kernel.h>
655ab6ffaSArun Ramadoss #include <linux/module.h>
755ab6ffaSArun Ramadoss #include <linux/iopoll.h>
855ab6ffaSArun Ramadoss #include <linux/phy.h>
955ab6ffaSArun Ramadoss #include <linux/of_net.h>
1055ab6ffaSArun Ramadoss #include <linux/if_bridge.h>
1155ab6ffaSArun Ramadoss #include <linux/math.h>
1255ab6ffaSArun Ramadoss #include <net/dsa.h>
1355ab6ffaSArun Ramadoss #include <net/switchdev.h>
1455ab6ffaSArun Ramadoss 
1555ab6ffaSArun Ramadoss #include "lan937x_reg.h"
1655ab6ffaSArun Ramadoss #include "ksz_common.h"
1755ab6ffaSArun Ramadoss #include "lan937x.h"
1855ab6ffaSArun Ramadoss 
1955ab6ffaSArun Ramadoss static int lan937x_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
2055ab6ffaSArun Ramadoss {
2155ab6ffaSArun Ramadoss 	return regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
2255ab6ffaSArun Ramadoss }
2355ab6ffaSArun Ramadoss 
2455ab6ffaSArun Ramadoss static int lan937x_port_cfg(struct ksz_device *dev, int port, int offset,
2555ab6ffaSArun Ramadoss 			    u8 bits, bool set)
2655ab6ffaSArun Ramadoss {
2755ab6ffaSArun Ramadoss 	return regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
2855ab6ffaSArun Ramadoss 				  bits, set ? bits : 0);
2955ab6ffaSArun Ramadoss }
3055ab6ffaSArun Ramadoss 
31*ffaf1de2SArun Ramadoss static int lan937x_enable_spi_indirect_access(struct ksz_device *dev)
32*ffaf1de2SArun Ramadoss {
33*ffaf1de2SArun Ramadoss 	u16 data16;
34*ffaf1de2SArun Ramadoss 	int ret;
35*ffaf1de2SArun Ramadoss 
36*ffaf1de2SArun Ramadoss 	/* Enable Phy access through SPI */
37*ffaf1de2SArun Ramadoss 	ret = lan937x_cfg(dev, REG_GLOBAL_CTRL_0, SW_PHY_REG_BLOCK, false);
38*ffaf1de2SArun Ramadoss 	if (ret < 0)
39*ffaf1de2SArun Ramadoss 		return ret;
40*ffaf1de2SArun Ramadoss 
41*ffaf1de2SArun Ramadoss 	ret = ksz_read16(dev, REG_VPHY_SPECIAL_CTRL__2, &data16);
42*ffaf1de2SArun Ramadoss 	if (ret < 0)
43*ffaf1de2SArun Ramadoss 		return ret;
44*ffaf1de2SArun Ramadoss 
45*ffaf1de2SArun Ramadoss 	/* Allow SPI access */
46*ffaf1de2SArun Ramadoss 	data16 |= VPHY_SPI_INDIRECT_ENABLE;
47*ffaf1de2SArun Ramadoss 
48*ffaf1de2SArun Ramadoss 	return ksz_write16(dev, REG_VPHY_SPECIAL_CTRL__2, data16);
49*ffaf1de2SArun Ramadoss }
50*ffaf1de2SArun Ramadoss 
51*ffaf1de2SArun Ramadoss static int lan937x_vphy_ind_addr_wr(struct ksz_device *dev, int addr, int reg)
52*ffaf1de2SArun Ramadoss {
53*ffaf1de2SArun Ramadoss 	u16 addr_base = REG_PORT_T1_PHY_CTRL_BASE;
54*ffaf1de2SArun Ramadoss 	u16 temp;
55*ffaf1de2SArun Ramadoss 
56*ffaf1de2SArun Ramadoss 	/* get register address based on the logical port */
57*ffaf1de2SArun Ramadoss 	temp = PORT_CTRL_ADDR(addr, (addr_base + (reg << 2)));
58*ffaf1de2SArun Ramadoss 
59*ffaf1de2SArun Ramadoss 	return ksz_write16(dev, REG_VPHY_IND_ADDR__2, temp);
60*ffaf1de2SArun Ramadoss }
61*ffaf1de2SArun Ramadoss 
62*ffaf1de2SArun Ramadoss static int lan937x_internal_phy_write(struct ksz_device *dev, int addr, int reg,
63*ffaf1de2SArun Ramadoss 				      u16 val)
64*ffaf1de2SArun Ramadoss {
65*ffaf1de2SArun Ramadoss 	unsigned int value;
66*ffaf1de2SArun Ramadoss 	int ret;
67*ffaf1de2SArun Ramadoss 
68*ffaf1de2SArun Ramadoss 	/* Check for internal phy port */
69*ffaf1de2SArun Ramadoss 	if (!dev->info->internal_phy[addr])
70*ffaf1de2SArun Ramadoss 		return -EOPNOTSUPP;
71*ffaf1de2SArun Ramadoss 
72*ffaf1de2SArun Ramadoss 	ret = lan937x_vphy_ind_addr_wr(dev, addr, reg);
73*ffaf1de2SArun Ramadoss 	if (ret < 0)
74*ffaf1de2SArun Ramadoss 		return ret;
75*ffaf1de2SArun Ramadoss 
76*ffaf1de2SArun Ramadoss 	/* Write the data to be written to the VPHY reg */
77*ffaf1de2SArun Ramadoss 	ret = ksz_write16(dev, REG_VPHY_IND_DATA__2, val);
78*ffaf1de2SArun Ramadoss 	if (ret < 0)
79*ffaf1de2SArun Ramadoss 		return ret;
80*ffaf1de2SArun Ramadoss 
81*ffaf1de2SArun Ramadoss 	/* Write the Write En and Busy bit */
82*ffaf1de2SArun Ramadoss 	ret = ksz_write16(dev, REG_VPHY_IND_CTRL__2,
83*ffaf1de2SArun Ramadoss 			  (VPHY_IND_WRITE | VPHY_IND_BUSY));
84*ffaf1de2SArun Ramadoss 	if (ret < 0)
85*ffaf1de2SArun Ramadoss 		return ret;
86*ffaf1de2SArun Ramadoss 
87*ffaf1de2SArun Ramadoss 	ret = regmap_read_poll_timeout(dev->regmap[1], REG_VPHY_IND_CTRL__2,
88*ffaf1de2SArun Ramadoss 				       value, !(value & VPHY_IND_BUSY), 10,
89*ffaf1de2SArun Ramadoss 				       1000);
90*ffaf1de2SArun Ramadoss 	if (ret < 0) {
91*ffaf1de2SArun Ramadoss 		dev_err(dev->dev, "Failed to write phy register\n");
92*ffaf1de2SArun Ramadoss 		return ret;
93*ffaf1de2SArun Ramadoss 	}
94*ffaf1de2SArun Ramadoss 
95*ffaf1de2SArun Ramadoss 	return 0;
96*ffaf1de2SArun Ramadoss }
97*ffaf1de2SArun Ramadoss 
98*ffaf1de2SArun Ramadoss static int lan937x_internal_phy_read(struct ksz_device *dev, int addr, int reg,
99*ffaf1de2SArun Ramadoss 				     u16 *val)
100*ffaf1de2SArun Ramadoss {
101*ffaf1de2SArun Ramadoss 	unsigned int value;
102*ffaf1de2SArun Ramadoss 	int ret;
103*ffaf1de2SArun Ramadoss 
104*ffaf1de2SArun Ramadoss 	/* Check for internal phy port, return 0xffff for non-existent phy */
105*ffaf1de2SArun Ramadoss 	if (!dev->info->internal_phy[addr])
106*ffaf1de2SArun Ramadoss 		return 0xffff;
107*ffaf1de2SArun Ramadoss 
108*ffaf1de2SArun Ramadoss 	ret = lan937x_vphy_ind_addr_wr(dev, addr, reg);
109*ffaf1de2SArun Ramadoss 	if (ret < 0)
110*ffaf1de2SArun Ramadoss 		return ret;
111*ffaf1de2SArun Ramadoss 
112*ffaf1de2SArun Ramadoss 	/* Write Read and Busy bit to start the transaction */
113*ffaf1de2SArun Ramadoss 	ret = ksz_write16(dev, REG_VPHY_IND_CTRL__2, VPHY_IND_BUSY);
114*ffaf1de2SArun Ramadoss 	if (ret < 0)
115*ffaf1de2SArun Ramadoss 		return ret;
116*ffaf1de2SArun Ramadoss 
117*ffaf1de2SArun Ramadoss 	ret = regmap_read_poll_timeout(dev->regmap[1], REG_VPHY_IND_CTRL__2,
118*ffaf1de2SArun Ramadoss 				       value, !(value & VPHY_IND_BUSY), 10,
119*ffaf1de2SArun Ramadoss 				       1000);
120*ffaf1de2SArun Ramadoss 	if (ret < 0) {
121*ffaf1de2SArun Ramadoss 		dev_err(dev->dev, "Failed to read phy register\n");
122*ffaf1de2SArun Ramadoss 		return ret;
123*ffaf1de2SArun Ramadoss 	}
124*ffaf1de2SArun Ramadoss 
125*ffaf1de2SArun Ramadoss 	/* Read the VPHY register which has the PHY data */
126*ffaf1de2SArun Ramadoss 	return ksz_read16(dev, REG_VPHY_IND_DATA__2, val);
127*ffaf1de2SArun Ramadoss }
128*ffaf1de2SArun Ramadoss 
129*ffaf1de2SArun Ramadoss void lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
130*ffaf1de2SArun Ramadoss {
131*ffaf1de2SArun Ramadoss 	lan937x_internal_phy_read(dev, addr, reg, data);
132*ffaf1de2SArun Ramadoss }
133*ffaf1de2SArun Ramadoss 
134*ffaf1de2SArun Ramadoss void lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
135*ffaf1de2SArun Ramadoss {
136*ffaf1de2SArun Ramadoss 	lan937x_internal_phy_write(dev, addr, reg, val);
137*ffaf1de2SArun Ramadoss }
138*ffaf1de2SArun Ramadoss 
13955ab6ffaSArun Ramadoss int lan937x_reset_switch(struct ksz_device *dev)
14055ab6ffaSArun Ramadoss {
14155ab6ffaSArun Ramadoss 	u32 data32;
14255ab6ffaSArun Ramadoss 	int ret;
14355ab6ffaSArun Ramadoss 
14455ab6ffaSArun Ramadoss 	/* reset switch */
14555ab6ffaSArun Ramadoss 	ret = lan937x_cfg(dev, REG_SW_OPERATION, SW_RESET, true);
14655ab6ffaSArun Ramadoss 	if (ret < 0)
14755ab6ffaSArun Ramadoss 		return ret;
14855ab6ffaSArun Ramadoss 
14955ab6ffaSArun Ramadoss 	/* Enable Auto Aging */
15055ab6ffaSArun Ramadoss 	ret = lan937x_cfg(dev, REG_SW_LUE_CTRL_1, SW_LINK_AUTO_AGING, true);
15155ab6ffaSArun Ramadoss 	if (ret < 0)
15255ab6ffaSArun Ramadoss 		return ret;
15355ab6ffaSArun Ramadoss 
15455ab6ffaSArun Ramadoss 	/* disable interrupts */
15555ab6ffaSArun Ramadoss 	ret = ksz_write32(dev, REG_SW_INT_MASK__4, SWITCH_INT_MASK);
15655ab6ffaSArun Ramadoss 	if (ret < 0)
15755ab6ffaSArun Ramadoss 		return ret;
15855ab6ffaSArun Ramadoss 
15955ab6ffaSArun Ramadoss 	ret = ksz_write32(dev, REG_SW_PORT_INT_MASK__4, 0xFF);
16055ab6ffaSArun Ramadoss 	if (ret < 0)
16155ab6ffaSArun Ramadoss 		return ret;
16255ab6ffaSArun Ramadoss 
16355ab6ffaSArun Ramadoss 	return ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data32);
16455ab6ffaSArun Ramadoss }
16555ab6ffaSArun Ramadoss 
16655ab6ffaSArun Ramadoss void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port)
16755ab6ffaSArun Ramadoss {
16855ab6ffaSArun Ramadoss 	struct dsa_switch *ds = dev->ds;
16955ab6ffaSArun Ramadoss 	u8 member;
17055ab6ffaSArun Ramadoss 
17155ab6ffaSArun Ramadoss 	/* enable tag tail for host port */
17255ab6ffaSArun Ramadoss 	if (cpu_port)
17355ab6ffaSArun Ramadoss 		lan937x_port_cfg(dev, port, REG_PORT_CTRL_0,
17455ab6ffaSArun Ramadoss 				 PORT_TAIL_TAG_ENABLE, true);
17555ab6ffaSArun Ramadoss 
17655ab6ffaSArun Ramadoss 	/* disable frame check length field */
17755ab6ffaSArun Ramadoss 	lan937x_port_cfg(dev, port, REG_PORT_MAC_CTRL_0, PORT_CHECK_LENGTH,
17855ab6ffaSArun Ramadoss 			 false);
17955ab6ffaSArun Ramadoss 
18055ab6ffaSArun Ramadoss 	/* set back pressure for half duplex */
18155ab6ffaSArun Ramadoss 	lan937x_port_cfg(dev, port, REG_PORT_MAC_CTRL_1, PORT_BACK_PRESSURE,
18255ab6ffaSArun Ramadoss 			 true);
18355ab6ffaSArun Ramadoss 
18455ab6ffaSArun Ramadoss 	/* enable 802.1p priority */
18555ab6ffaSArun Ramadoss 	lan937x_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true);
18655ab6ffaSArun Ramadoss 
18755ab6ffaSArun Ramadoss 	if (!dev->info->internal_phy[port])
18855ab6ffaSArun Ramadoss 		lan937x_port_cfg(dev, port, REG_PORT_XMII_CTRL_0,
18955ab6ffaSArun Ramadoss 				 PORT_MII_TX_FLOW_CTRL | PORT_MII_RX_FLOW_CTRL,
19055ab6ffaSArun Ramadoss 				 true);
19155ab6ffaSArun Ramadoss 
19255ab6ffaSArun Ramadoss 	if (cpu_port)
19355ab6ffaSArun Ramadoss 		member = dsa_user_ports(ds);
19455ab6ffaSArun Ramadoss 	else
19555ab6ffaSArun Ramadoss 		member = BIT(dsa_upstream_port(ds, port));
19655ab6ffaSArun Ramadoss 
19755ab6ffaSArun Ramadoss 	dev->dev_ops->cfg_port_member(dev, port, member);
19855ab6ffaSArun Ramadoss }
19955ab6ffaSArun Ramadoss 
20055ab6ffaSArun Ramadoss void lan937x_config_cpu_port(struct dsa_switch *ds)
20155ab6ffaSArun Ramadoss {
20255ab6ffaSArun Ramadoss 	struct ksz_device *dev = ds->priv;
20355ab6ffaSArun Ramadoss 	struct dsa_port *dp;
20455ab6ffaSArun Ramadoss 
20555ab6ffaSArun Ramadoss 	dsa_switch_for_each_cpu_port(dp, ds) {
20655ab6ffaSArun Ramadoss 		if (dev->info->cpu_ports & (1 << dp->index)) {
20755ab6ffaSArun Ramadoss 			dev->cpu_port = dp->index;
20855ab6ffaSArun Ramadoss 
20955ab6ffaSArun Ramadoss 			/* enable cpu port */
21055ab6ffaSArun Ramadoss 			lan937x_port_setup(dev, dp->index, true);
21155ab6ffaSArun Ramadoss 		}
21255ab6ffaSArun Ramadoss 	}
21355ab6ffaSArun Ramadoss 
21455ab6ffaSArun Ramadoss 	dsa_switch_for_each_user_port(dp, ds) {
21555ab6ffaSArun Ramadoss 		ksz_port_stp_state_set(ds, dp->index, BR_STATE_DISABLED);
21655ab6ffaSArun Ramadoss 	}
21755ab6ffaSArun Ramadoss }
21855ab6ffaSArun Ramadoss 
21955ab6ffaSArun Ramadoss int lan937x_setup(struct dsa_switch *ds)
22055ab6ffaSArun Ramadoss {
22155ab6ffaSArun Ramadoss 	struct ksz_device *dev = ds->priv;
222*ffaf1de2SArun Ramadoss 	int ret;
223*ffaf1de2SArun Ramadoss 
224*ffaf1de2SArun Ramadoss 	/* enable Indirect Access from SPI to the VPHY registers */
225*ffaf1de2SArun Ramadoss 	ret = lan937x_enable_spi_indirect_access(dev);
226*ffaf1de2SArun Ramadoss 	if (ret < 0) {
227*ffaf1de2SArun Ramadoss 		dev_err(dev->dev, "failed to enable spi indirect access");
228*ffaf1de2SArun Ramadoss 		return ret;
229*ffaf1de2SArun Ramadoss 	}
23055ab6ffaSArun Ramadoss 
23155ab6ffaSArun Ramadoss 	/* The VLAN aware is a global setting. Mixed vlan
23255ab6ffaSArun Ramadoss 	 * filterings are not supported.
23355ab6ffaSArun Ramadoss 	 */
23455ab6ffaSArun Ramadoss 	ds->vlan_filtering_is_global = true;
23555ab6ffaSArun Ramadoss 
23655ab6ffaSArun Ramadoss 	/* Enable aggressive back off for half duplex & UNH mode */
23755ab6ffaSArun Ramadoss 	lan937x_cfg(dev, REG_SW_MAC_CTRL_0,
23855ab6ffaSArun Ramadoss 		    (SW_PAUSE_UNH_MODE | SW_NEW_BACKOFF | SW_AGGR_BACKOFF),
23955ab6ffaSArun Ramadoss 		    true);
24055ab6ffaSArun Ramadoss 
24155ab6ffaSArun Ramadoss 	/* If NO_EXC_COLLISION_DROP bit is set, the switch will not drop
24255ab6ffaSArun Ramadoss 	 * packets when 16 or more collisions occur
24355ab6ffaSArun Ramadoss 	 */
24455ab6ffaSArun Ramadoss 	lan937x_cfg(dev, REG_SW_MAC_CTRL_1, NO_EXC_COLLISION_DROP, true);
24555ab6ffaSArun Ramadoss 
24655ab6ffaSArun Ramadoss 	/* enable global MIB counter freeze function */
24755ab6ffaSArun Ramadoss 	lan937x_cfg(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FREEZE, true);
24855ab6ffaSArun Ramadoss 
24955ab6ffaSArun Ramadoss 	/* disable CLK125 & CLK25, 1: disable, 0: enable */
25055ab6ffaSArun Ramadoss 	lan937x_cfg(dev, REG_SW_GLOBAL_OUTPUT_CTRL__1,
25155ab6ffaSArun Ramadoss 		    (SW_CLK125_ENB | SW_CLK25_ENB), true);
25255ab6ffaSArun Ramadoss 
25355ab6ffaSArun Ramadoss 	return 0;
25455ab6ffaSArun Ramadoss }
25555ab6ffaSArun Ramadoss 
25655ab6ffaSArun Ramadoss int lan937x_switch_init(struct ksz_device *dev)
25755ab6ffaSArun Ramadoss {
25855ab6ffaSArun Ramadoss 	dev->port_mask = (1 << dev->info->port_cnt) - 1;
25955ab6ffaSArun Ramadoss 
26055ab6ffaSArun Ramadoss 	return 0;
26155ab6ffaSArun Ramadoss }
26255ab6ffaSArun Ramadoss 
26355ab6ffaSArun Ramadoss void lan937x_switch_exit(struct ksz_device *dev)
26455ab6ffaSArun Ramadoss {
26555ab6ffaSArun Ramadoss 	lan937x_reset_switch(dev);
26655ab6ffaSArun Ramadoss }
26755ab6ffaSArun Ramadoss 
26855ab6ffaSArun Ramadoss MODULE_AUTHOR("Arun Ramadoss <arun.ramadoss@microchip.com>");
26955ab6ffaSArun Ramadoss MODULE_DESCRIPTION("Microchip LAN937x Series Switch DSA Driver");
27055ab6ffaSArun Ramadoss MODULE_LICENSE("GPL");
271