1*888cdb89SClément Léger /* SPDX-License-Identifier: GPL-2.0-only */ 2*888cdb89SClément Léger /* 3*888cdb89SClément Léger * Copyright (C) 2022 Schneider Electric 4*888cdb89SClément Léger * 5*888cdb89SClément Léger * Clément Léger <clement.leger@bootlin.com> 6*888cdb89SClément Léger */ 7*888cdb89SClément Léger 8*888cdb89SClément Léger #include <linux/clk.h> 9*888cdb89SClément Léger #include <linux/debugfs.h> 10*888cdb89SClément Léger #include <linux/kernel.h> 11*888cdb89SClément Léger #include <linux/module.h> 12*888cdb89SClément Léger #include <linux/of.h> 13*888cdb89SClément Léger #include <linux/of_mdio.h> 14*888cdb89SClément Léger #include <linux/platform_device.h> 15*888cdb89SClément Léger #include <linux/pcs-rzn1-miic.h> 16*888cdb89SClément Léger #include <net/dsa.h> 17*888cdb89SClément Léger 18*888cdb89SClément Léger #define A5PSW_REVISION 0x0 19*888cdb89SClément Léger #define A5PSW_PORT_OFFSET(port) (0x400 * (port)) 20*888cdb89SClément Léger 21*888cdb89SClément Léger #define A5PSW_PORT_ENA 0x8 22*888cdb89SClément Léger #define A5PSW_PORT_ENA_RX_SHIFT 16 23*888cdb89SClément Léger #define A5PSW_PORT_ENA_TX_RX(port) (BIT((port) + A5PSW_PORT_ENA_RX_SHIFT) | \ 24*888cdb89SClément Léger BIT(port)) 25*888cdb89SClément Léger #define A5PSW_UCAST_DEF_MASK 0xC 26*888cdb89SClément Léger 27*888cdb89SClément Léger #define A5PSW_VLAN_VERIFY 0x10 28*888cdb89SClément Léger #define A5PSW_VLAN_VERI_SHIFT 0 29*888cdb89SClément Léger #define A5PSW_VLAN_DISC_SHIFT 16 30*888cdb89SClément Léger 31*888cdb89SClément Léger #define A5PSW_BCAST_DEF_MASK 0x14 32*888cdb89SClément Léger #define A5PSW_MCAST_DEF_MASK 0x18 33*888cdb89SClément Léger 34*888cdb89SClément Léger #define A5PSW_INPUT_LEARN 0x1C 35*888cdb89SClément Léger #define A5PSW_INPUT_LEARN_DIS(p) BIT((p) + 16) 36*888cdb89SClément Léger #define A5PSW_INPUT_LEARN_BLOCK(p) BIT(p) 37*888cdb89SClément Léger 38*888cdb89SClément Léger #define A5PSW_MGMT_CFG 0x20 39*888cdb89SClément Léger #define A5PSW_MGMT_CFG_DISCARD BIT(7) 40*888cdb89SClément Léger 41*888cdb89SClément Léger #define A5PSW_MODE_CFG 0x24 42*888cdb89SClément Léger #define A5PSW_MODE_STATS_RESET BIT(31) 43*888cdb89SClément Léger 44*888cdb89SClément Léger #define A5PSW_VLAN_IN_MODE 0x28 45*888cdb89SClément Léger #define A5PSW_VLAN_IN_MODE_PORT_SHIFT(port) ((port) * 2) 46*888cdb89SClément Léger #define A5PSW_VLAN_IN_MODE_PORT(port) (GENMASK(1, 0) << \ 47*888cdb89SClément Léger A5PSW_VLAN_IN_MODE_PORT_SHIFT(port)) 48*888cdb89SClément Léger #define A5PSW_VLAN_IN_MODE_SINGLE_PASSTHROUGH 0x0 49*888cdb89SClément Léger #define A5PSW_VLAN_IN_MODE_SINGLE_REPLACE 0x1 50*888cdb89SClément Léger #define A5PSW_VLAN_IN_MODE_TAG_ALWAYS 0x2 51*888cdb89SClément Léger 52*888cdb89SClément Léger #define A5PSW_VLAN_OUT_MODE 0x2C 53*888cdb89SClément Léger #define A5PSW_VLAN_OUT_MODE_PORT(port) (GENMASK(1, 0) << ((port) * 2)) 54*888cdb89SClément Léger #define A5PSW_VLAN_OUT_MODE_DIS 0x0 55*888cdb89SClément Léger #define A5PSW_VLAN_OUT_MODE_STRIP 0x1 56*888cdb89SClément Léger #define A5PSW_VLAN_OUT_MODE_TAG_THROUGH 0x2 57*888cdb89SClément Léger #define A5PSW_VLAN_OUT_MODE_TRANSPARENT 0x3 58*888cdb89SClément Léger 59*888cdb89SClément Léger #define A5PSW_VLAN_IN_MODE_ENA 0x30 60*888cdb89SClément Léger #define A5PSW_VLAN_TAG_ID 0x34 61*888cdb89SClément Léger 62*888cdb89SClément Léger #define A5PSW_SYSTEM_TAGINFO(port) (0x200 + A5PSW_PORT_OFFSET(port)) 63*888cdb89SClément Léger 64*888cdb89SClément Léger #define A5PSW_AUTH_PORT(port) (0x240 + 4 * (port)) 65*888cdb89SClément Léger #define A5PSW_AUTH_PORT_AUTHORIZED BIT(0) 66*888cdb89SClément Léger 67*888cdb89SClément Léger #define A5PSW_VLAN_RES(entry) (0x280 + 4 * (entry)) 68*888cdb89SClément Léger #define A5PSW_VLAN_RES_WR_PORTMASK BIT(30) 69*888cdb89SClément Léger #define A5PSW_VLAN_RES_WR_TAGMASK BIT(29) 70*888cdb89SClément Léger #define A5PSW_VLAN_RES_RD_TAGMASK BIT(28) 71*888cdb89SClément Léger #define A5PSW_VLAN_RES_ID GENMASK(16, 5) 72*888cdb89SClément Léger #define A5PSW_VLAN_RES_PORTMASK GENMASK(4, 0) 73*888cdb89SClément Léger 74*888cdb89SClément Léger #define A5PSW_RXMATCH_CONFIG(port) (0x3e80 + 4 * (port)) 75*888cdb89SClément Léger #define A5PSW_RXMATCH_CONFIG_PATTERN(p) BIT(p) 76*888cdb89SClément Léger 77*888cdb89SClément Léger #define A5PSW_PATTERN_CTRL(p) (0x3eb0 + 4 * (p)) 78*888cdb89SClément Léger #define A5PSW_PATTERN_CTRL_MGMTFWD BIT(1) 79*888cdb89SClément Léger 80*888cdb89SClément Léger #define A5PSW_LK_CTRL 0x400 81*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_BLOCKING BIT(0) 82*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_LEARNING BIT(1) 83*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_AGEING BIT(2) 84*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_ALLOW_MIGR BIT(3) 85*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_CLEAR_TABLE BIT(6) 86*888cdb89SClément Léger 87*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL 0x408 88*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_BUSY BIT(31) 89*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_DELETE_PORT BIT(30) 90*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_CLEAR BIT(29) 91*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_LOOKUP BIT(28) 92*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_WAIT BIT(27) 93*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_READ BIT(26) 94*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_WRITE BIT(25) 95*888cdb89SClément Léger #define A5PSW_LK_ADDR_CTRL_ADDRESS GENMASK(12, 0) 96*888cdb89SClément Léger 97*888cdb89SClément Léger #define A5PSW_LK_DATA_LO 0x40C 98*888cdb89SClément Léger #define A5PSW_LK_DATA_HI 0x410 99*888cdb89SClément Léger #define A5PSW_LK_DATA_HI_VALID BIT(16) 100*888cdb89SClément Léger #define A5PSW_LK_DATA_HI_PORT BIT(16) 101*888cdb89SClément Léger 102*888cdb89SClément Léger #define A5PSW_LK_LEARNCOUNT 0x418 103*888cdb89SClément Léger #define A5PSW_LK_LEARNCOUNT_COUNT GENMASK(13, 0) 104*888cdb89SClément Léger #define A5PSW_LK_LEARNCOUNT_MODE GENMASK(31, 30) 105*888cdb89SClément Léger #define A5PSW_LK_LEARNCOUNT_MODE_SET 0x0 106*888cdb89SClément Léger #define A5PSW_LK_LEARNCOUNT_MODE_INC 0x1 107*888cdb89SClément Léger #define A5PSW_LK_LEARNCOUNT_MODE_DEC 0x2 108*888cdb89SClément Léger 109*888cdb89SClément Léger #define A5PSW_MGMT_TAG_CFG 0x480 110*888cdb89SClément Léger #define A5PSW_MGMT_TAG_CFG_TAGFIELD GENMASK(31, 16) 111*888cdb89SClément Léger #define A5PSW_MGMT_TAG_CFG_ALL_FRAMES BIT(1) 112*888cdb89SClément Léger #define A5PSW_MGMT_TAG_CFG_ENABLE BIT(0) 113*888cdb89SClément Léger 114*888cdb89SClément Léger #define A5PSW_LK_AGETIME 0x41C 115*888cdb89SClément Léger #define A5PSW_LK_AGETIME_MASK GENMASK(23, 0) 116*888cdb89SClément Léger 117*888cdb89SClément Léger #define A5PSW_MDIO_CFG_STATUS 0x700 118*888cdb89SClément Léger #define A5PSW_MDIO_CFG_STATUS_CLKDIV GENMASK(15, 7) 119*888cdb89SClément Léger #define A5PSW_MDIO_CFG_STATUS_READERR BIT(1) 120*888cdb89SClément Léger #define A5PSW_MDIO_CFG_STATUS_BUSY BIT(0) 121*888cdb89SClément Léger 122*888cdb89SClément Léger #define A5PSW_MDIO_COMMAND 0x704 123*888cdb89SClément Léger /* Register is named TRAININIT in datasheet and should be set when reading */ 124*888cdb89SClément Léger #define A5PSW_MDIO_COMMAND_READ BIT(15) 125*888cdb89SClément Léger #define A5PSW_MDIO_COMMAND_PHY_ADDR GENMASK(9, 5) 126*888cdb89SClément Léger #define A5PSW_MDIO_COMMAND_REG_ADDR GENMASK(4, 0) 127*888cdb89SClément Léger 128*888cdb89SClément Léger #define A5PSW_MDIO_DATA 0x708 129*888cdb89SClément Léger #define A5PSW_MDIO_DATA_MASK GENMASK(15, 0) 130*888cdb89SClément Léger 131*888cdb89SClément Léger #define A5PSW_CMD_CFG(port) (0x808 + A5PSW_PORT_OFFSET(port)) 132*888cdb89SClément Léger #define A5PSW_CMD_CFG_CNTL_FRM_ENA BIT(23) 133*888cdb89SClément Léger #define A5PSW_CMD_CFG_SW_RESET BIT(13) 134*888cdb89SClément Léger #define A5PSW_CMD_CFG_TX_CRC_APPEND BIT(11) 135*888cdb89SClément Léger #define A5PSW_CMD_CFG_HD_ENA BIT(10) 136*888cdb89SClément Léger #define A5PSW_CMD_CFG_PAUSE_IGNORE BIT(8) 137*888cdb89SClément Léger #define A5PSW_CMD_CFG_CRC_FWD BIT(6) 138*888cdb89SClément Léger #define A5PSW_CMD_CFG_ETH_SPEED BIT(3) 139*888cdb89SClément Léger #define A5PSW_CMD_CFG_RX_ENA BIT(1) 140*888cdb89SClément Léger #define A5PSW_CMD_CFG_TX_ENA BIT(0) 141*888cdb89SClément Léger 142*888cdb89SClément Léger #define A5PSW_FRM_LENGTH(port) (0x814 + A5PSW_PORT_OFFSET(port)) 143*888cdb89SClément Léger #define A5PSW_FRM_LENGTH_MASK GENMASK(13, 0) 144*888cdb89SClément Léger 145*888cdb89SClément Léger #define A5PSW_STATUS(port) (0x840 + A5PSW_PORT_OFFSET(port)) 146*888cdb89SClément Léger 147*888cdb89SClément Léger #define A5PSW_STATS_HIWORD 0x900 148*888cdb89SClément Léger 149*888cdb89SClément Léger #define A5PSW_VLAN_TAG(prio, id) (((prio) << 12) | (id)) 150*888cdb89SClément Léger #define A5PSW_PORTS_NUM 5 151*888cdb89SClément Léger #define A5PSW_CPU_PORT (A5PSW_PORTS_NUM - 1) 152*888cdb89SClément Léger #define A5PSW_MDIO_DEF_FREQ 2500000 153*888cdb89SClément Léger #define A5PSW_MDIO_TIMEOUT 100 154*888cdb89SClément Léger #define A5PSW_JUMBO_LEN (10 * SZ_1K) 155*888cdb89SClément Léger #define A5PSW_MDIO_CLK_DIV_MIN 5 156*888cdb89SClément Léger #define A5PSW_TAG_LEN 8 157*888cdb89SClément Léger #define A5PSW_VLAN_COUNT 32 158*888cdb89SClément Léger 159*888cdb89SClément Léger /* Ensure enough space for 2 VLAN tags */ 160*888cdb89SClément Léger #define A5PSW_EXTRA_MTU_LEN (A5PSW_TAG_LEN + 8) 161*888cdb89SClément Léger #define A5PSW_MAX_MTU (A5PSW_JUMBO_LEN - A5PSW_EXTRA_MTU_LEN) 162*888cdb89SClément Léger 163*888cdb89SClément Léger #define A5PSW_PATTERN_MGMTFWD 0 164*888cdb89SClément Léger 165*888cdb89SClément Léger #define A5PSW_LK_BUSY_USEC_POLL 10 166*888cdb89SClément Léger #define A5PSW_CTRL_TIMEOUT 1000 167*888cdb89SClément Léger #define A5PSW_TABLE_ENTRIES 8192 168*888cdb89SClément Léger 169*888cdb89SClément Léger /** 170*888cdb89SClément Léger * struct a5psw - switch struct 171*888cdb89SClément Léger * @base: Base address of the switch 172*888cdb89SClément Léger * @hclk: hclk_switch clock 173*888cdb89SClément Léger * @clk: clk_switch clock 174*888cdb89SClément Léger * @dev: Device associated to the switch 175*888cdb89SClément Léger * @mii_bus: MDIO bus struct 176*888cdb89SClément Léger * @mdio_freq: MDIO bus frequency requested 177*888cdb89SClément Léger * @pcs: Array of PCS connected to the switch ports (not for the CPU) 178*888cdb89SClément Léger * @ds: DSA switch struct 179*888cdb89SClément Léger * @lk_lock: Lock for the lookup table 180*888cdb89SClément Léger * @reg_lock: Lock for register read-modify-write operation 181*888cdb89SClément Léger * @bridged_ports: Mask of ports that are bridged and should be flooded 182*888cdb89SClément Léger * @br_dev: Bridge net device 183*888cdb89SClément Léger */ 184*888cdb89SClément Léger struct a5psw { 185*888cdb89SClément Léger void __iomem *base; 186*888cdb89SClément Léger struct clk *hclk; 187*888cdb89SClément Léger struct clk *clk; 188*888cdb89SClément Léger struct device *dev; 189*888cdb89SClément Léger struct mii_bus *mii_bus; 190*888cdb89SClément Léger struct phylink_pcs *pcs[A5PSW_PORTS_NUM - 1]; 191*888cdb89SClément Léger struct dsa_switch ds; 192*888cdb89SClément Léger struct mutex lk_lock; 193*888cdb89SClément Léger spinlock_t reg_lock; 194*888cdb89SClément Léger u32 bridged_ports; 195*888cdb89SClément Léger struct net_device *br_dev; 196*888cdb89SClément Léger }; 197