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