1*3cfa11baSSteen Hegelund /* SPDX-License-Identifier: GPL-2.0+ */ 2*3cfa11baSSteen Hegelund /* Microchip Sparx5 Switch driver 3*3cfa11baSSteen Hegelund * 4*3cfa11baSSteen Hegelund * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries. 5*3cfa11baSSteen Hegelund */ 6*3cfa11baSSteen Hegelund 7*3cfa11baSSteen Hegelund #ifndef __SPARX5_MAIN_H__ 8*3cfa11baSSteen Hegelund #define __SPARX5_MAIN_H__ 9*3cfa11baSSteen Hegelund 10*3cfa11baSSteen Hegelund #include <linux/types.h> 11*3cfa11baSSteen Hegelund #include <linux/phy/phy.h> 12*3cfa11baSSteen Hegelund #include <linux/netdevice.h> 13*3cfa11baSSteen Hegelund #include <linux/phy.h> 14*3cfa11baSSteen Hegelund #include <linux/if_vlan.h> 15*3cfa11baSSteen Hegelund #include <linux/bitmap.h> 16*3cfa11baSSteen Hegelund #include <linux/phylink.h> 17*3cfa11baSSteen Hegelund 18*3cfa11baSSteen Hegelund /* Target chip type */ 19*3cfa11baSSteen Hegelund enum spx5_target_chiptype { 20*3cfa11baSSteen Hegelund SPX5_TARGET_CT_7546 = 0x7546, /* SparX-5-64 Enterprise */ 21*3cfa11baSSteen Hegelund SPX5_TARGET_CT_7549 = 0x7549, /* SparX-5-90 Enterprise */ 22*3cfa11baSSteen Hegelund SPX5_TARGET_CT_7552 = 0x7552, /* SparX-5-128 Enterprise */ 23*3cfa11baSSteen Hegelund SPX5_TARGET_CT_7556 = 0x7556, /* SparX-5-160 Enterprise */ 24*3cfa11baSSteen Hegelund SPX5_TARGET_CT_7558 = 0x7558, /* SparX-5-200 Enterprise */ 25*3cfa11baSSteen Hegelund SPX5_TARGET_CT_7546TSN = 0x47546, /* SparX-5-64i Industrial */ 26*3cfa11baSSteen Hegelund SPX5_TARGET_CT_7549TSN = 0x47549, /* SparX-5-90i Industrial */ 27*3cfa11baSSteen Hegelund SPX5_TARGET_CT_7552TSN = 0x47552, /* SparX-5-128i Industrial */ 28*3cfa11baSSteen Hegelund SPX5_TARGET_CT_7556TSN = 0x47556, /* SparX-5-160i Industrial */ 29*3cfa11baSSteen Hegelund SPX5_TARGET_CT_7558TSN = 0x47558, /* SparX-5-200i Industrial */ 30*3cfa11baSSteen Hegelund }; 31*3cfa11baSSteen Hegelund 32*3cfa11baSSteen Hegelund enum sparx5_port_max_tags { 33*3cfa11baSSteen Hegelund SPX5_PORT_MAX_TAGS_NONE, /* No extra tags allowed */ 34*3cfa11baSSteen Hegelund SPX5_PORT_MAX_TAGS_ONE, /* Single tag allowed */ 35*3cfa11baSSteen Hegelund SPX5_PORT_MAX_TAGS_TWO /* Single and double tag allowed */ 36*3cfa11baSSteen Hegelund }; 37*3cfa11baSSteen Hegelund 38*3cfa11baSSteen Hegelund enum sparx5_vlan_port_type { 39*3cfa11baSSteen Hegelund SPX5_VLAN_PORT_TYPE_UNAWARE, /* VLAN unaware port */ 40*3cfa11baSSteen Hegelund SPX5_VLAN_PORT_TYPE_C, /* C-port */ 41*3cfa11baSSteen Hegelund SPX5_VLAN_PORT_TYPE_S, /* S-port */ 42*3cfa11baSSteen Hegelund SPX5_VLAN_PORT_TYPE_S_CUSTOM /* S-port using custom type */ 43*3cfa11baSSteen Hegelund }; 44*3cfa11baSSteen Hegelund 45*3cfa11baSSteen Hegelund #define SPX5_PORTS 65 46*3cfa11baSSteen Hegelund #define SPX5_PORT_CPU (SPX5_PORTS) /* Next port is CPU port */ 47*3cfa11baSSteen Hegelund #define SPX5_PORT_CPU_0 (SPX5_PORT_CPU + 0) /* CPU Port 65 */ 48*3cfa11baSSteen Hegelund #define SPX5_PORT_CPU_1 (SPX5_PORT_CPU + 1) /* CPU Port 66 */ 49*3cfa11baSSteen Hegelund #define SPX5_PORT_VD0 (SPX5_PORT_CPU + 2) /* VD0/Port 67 used for IPMC */ 50*3cfa11baSSteen Hegelund #define SPX5_PORT_VD1 (SPX5_PORT_CPU + 3) /* VD1/Port 68 used for AFI/OAM */ 51*3cfa11baSSteen Hegelund #define SPX5_PORT_VD2 (SPX5_PORT_CPU + 4) /* VD2/Port 69 used for IPinIP*/ 52*3cfa11baSSteen Hegelund #define SPX5_PORTS_ALL (SPX5_PORT_CPU + 5) /* Total number of ports */ 53*3cfa11baSSteen Hegelund 54*3cfa11baSSteen Hegelund #define PGID_BASE SPX5_PORTS /* Starts after port PGIDs */ 55*3cfa11baSSteen Hegelund #define PGID_UC_FLOOD (PGID_BASE + 0) 56*3cfa11baSSteen Hegelund #define PGID_MC_FLOOD (PGID_BASE + 1) 57*3cfa11baSSteen Hegelund #define PGID_IPV4_MC_DATA (PGID_BASE + 2) 58*3cfa11baSSteen Hegelund #define PGID_IPV4_MC_CTRL (PGID_BASE + 3) 59*3cfa11baSSteen Hegelund #define PGID_IPV6_MC_DATA (PGID_BASE + 4) 60*3cfa11baSSteen Hegelund #define PGID_IPV6_MC_CTRL (PGID_BASE + 5) 61*3cfa11baSSteen Hegelund #define PGID_BCAST (PGID_BASE + 6) 62*3cfa11baSSteen Hegelund #define PGID_CPU (PGID_BASE + 7) 63*3cfa11baSSteen Hegelund 64*3cfa11baSSteen Hegelund #define IFH_LEN 9 /* 36 bytes */ 65*3cfa11baSSteen Hegelund #define NULL_VID 0 66*3cfa11baSSteen Hegelund #define SPX5_MACT_PULL_DELAY (2 * HZ) 67*3cfa11baSSteen Hegelund #define SPX5_STATS_CHECK_DELAY (1 * HZ) 68*3cfa11baSSteen Hegelund #define SPX5_PRIOS 8 /* Number of priority queues */ 69*3cfa11baSSteen Hegelund #define SPX5_BUFFER_CELL_SZ 184 /* Cell size */ 70*3cfa11baSSteen Hegelund #define SPX5_BUFFER_MEMORY 4194280 /* 22795 words * 184 bytes */ 71*3cfa11baSSteen Hegelund 72*3cfa11baSSteen Hegelund struct sparx5; 73*3cfa11baSSteen Hegelund 74*3cfa11baSSteen Hegelund struct sparx5_port_config { 75*3cfa11baSSteen Hegelund phy_interface_t portmode; 76*3cfa11baSSteen Hegelund u32 bandwidth; 77*3cfa11baSSteen Hegelund int speed; 78*3cfa11baSSteen Hegelund int duplex; 79*3cfa11baSSteen Hegelund enum phy_media media; 80*3cfa11baSSteen Hegelund bool inband; 81*3cfa11baSSteen Hegelund bool power_down; 82*3cfa11baSSteen Hegelund bool autoneg; 83*3cfa11baSSteen Hegelund bool serdes_reset; 84*3cfa11baSSteen Hegelund u32 pause; 85*3cfa11baSSteen Hegelund u32 pause_adv; 86*3cfa11baSSteen Hegelund phy_interface_t phy_mode; 87*3cfa11baSSteen Hegelund u32 sd_sgpio; 88*3cfa11baSSteen Hegelund }; 89*3cfa11baSSteen Hegelund 90*3cfa11baSSteen Hegelund struct sparx5_port { 91*3cfa11baSSteen Hegelund struct net_device *ndev; 92*3cfa11baSSteen Hegelund struct sparx5 *sparx5; 93*3cfa11baSSteen Hegelund struct device_node *of_node; 94*3cfa11baSSteen Hegelund struct phy *serdes; 95*3cfa11baSSteen Hegelund struct sparx5_port_config conf; 96*3cfa11baSSteen Hegelund u16 portno; 97*3cfa11baSSteen Hegelund /* Ingress default VLAN (pvid) */ 98*3cfa11baSSteen Hegelund u16 pvid; 99*3cfa11baSSteen Hegelund /* Egress default VLAN (vid) */ 100*3cfa11baSSteen Hegelund u16 vid; 101*3cfa11baSSteen Hegelund bool signd_internal; 102*3cfa11baSSteen Hegelund bool signd_active_high; 103*3cfa11baSSteen Hegelund bool signd_enable; 104*3cfa11baSSteen Hegelund bool flow_control; 105*3cfa11baSSteen Hegelund enum sparx5_port_max_tags max_vlan_tags; 106*3cfa11baSSteen Hegelund enum sparx5_vlan_port_type vlan_type; 107*3cfa11baSSteen Hegelund u32 custom_etype; 108*3cfa11baSSteen Hegelund u32 ifh[IFH_LEN]; 109*3cfa11baSSteen Hegelund bool vlan_aware; 110*3cfa11baSSteen Hegelund }; 111*3cfa11baSSteen Hegelund 112*3cfa11baSSteen Hegelund enum sparx5_core_clockfreq { 113*3cfa11baSSteen Hegelund SPX5_CORE_CLOCK_DEFAULT, /* Defaults to the highest supported frequency */ 114*3cfa11baSSteen Hegelund SPX5_CORE_CLOCK_250MHZ, /* 250MHZ core clock frequency */ 115*3cfa11baSSteen Hegelund SPX5_CORE_CLOCK_500MHZ, /* 500MHZ core clock frequency */ 116*3cfa11baSSteen Hegelund SPX5_CORE_CLOCK_625MHZ, /* 625MHZ core clock frequency */ 117*3cfa11baSSteen Hegelund }; 118*3cfa11baSSteen Hegelund 119*3cfa11baSSteen Hegelund struct sparx5 { 120*3cfa11baSSteen Hegelund struct platform_device *pdev; 121*3cfa11baSSteen Hegelund struct device *dev; 122*3cfa11baSSteen Hegelund u32 chip_id; 123*3cfa11baSSteen Hegelund enum spx5_target_chiptype target_ct; 124*3cfa11baSSteen Hegelund void __iomem *regs[NUM_TARGETS]; 125*3cfa11baSSteen Hegelund int port_count; 126*3cfa11baSSteen Hegelund struct mutex lock; /* MAC reg lock */ 127*3cfa11baSSteen Hegelund /* port structures are in net device */ 128*3cfa11baSSteen Hegelund struct sparx5_port *ports[SPX5_PORTS]; 129*3cfa11baSSteen Hegelund enum sparx5_core_clockfreq coreclock; 130*3cfa11baSSteen Hegelund u8 base_mac[ETH_ALEN]; 131*3cfa11baSSteen Hegelund /* Board specifics */ 132*3cfa11baSSteen Hegelund bool sd_sgpio_remapping; 133*3cfa11baSSteen Hegelund }; 134*3cfa11baSSteen Hegelund 135*3cfa11baSSteen Hegelund /* Clock period in picoseconds */ 136*3cfa11baSSteen Hegelund static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock) 137*3cfa11baSSteen Hegelund { 138*3cfa11baSSteen Hegelund switch (cclock) { 139*3cfa11baSSteen Hegelund case SPX5_CORE_CLOCK_250MHZ: 140*3cfa11baSSteen Hegelund return 4000; 141*3cfa11baSSteen Hegelund case SPX5_CORE_CLOCK_500MHZ: 142*3cfa11baSSteen Hegelund return 2000; 143*3cfa11baSSteen Hegelund case SPX5_CORE_CLOCK_625MHZ: 144*3cfa11baSSteen Hegelund default: 145*3cfa11baSSteen Hegelund return 1600; 146*3cfa11baSSteen Hegelund } 147*3cfa11baSSteen Hegelund } 148*3cfa11baSSteen Hegelund 149*3cfa11baSSteen Hegelund /* Calculate raw offset */ 150*3cfa11baSSteen Hegelund static inline __pure int spx5_offset(int id, int tinst, int tcnt, 151*3cfa11baSSteen Hegelund int gbase, int ginst, 152*3cfa11baSSteen Hegelund int gcnt, int gwidth, 153*3cfa11baSSteen Hegelund int raddr, int rinst, 154*3cfa11baSSteen Hegelund int rcnt, int rwidth) 155*3cfa11baSSteen Hegelund { 156*3cfa11baSSteen Hegelund WARN_ON((tinst) >= tcnt); 157*3cfa11baSSteen Hegelund WARN_ON((ginst) >= gcnt); 158*3cfa11baSSteen Hegelund WARN_ON((rinst) >= rcnt); 159*3cfa11baSSteen Hegelund return gbase + ((ginst) * gwidth) + 160*3cfa11baSSteen Hegelund raddr + ((rinst) * rwidth); 161*3cfa11baSSteen Hegelund } 162*3cfa11baSSteen Hegelund 163*3cfa11baSSteen Hegelund /* Read, Write and modify registers content. 164*3cfa11baSSteen Hegelund * The register definition macros start at the id 165*3cfa11baSSteen Hegelund */ 166*3cfa11baSSteen Hegelund static inline void __iomem *spx5_addr(void __iomem *base[], 167*3cfa11baSSteen Hegelund int id, int tinst, int tcnt, 168*3cfa11baSSteen Hegelund int gbase, int ginst, 169*3cfa11baSSteen Hegelund int gcnt, int gwidth, 170*3cfa11baSSteen Hegelund int raddr, int rinst, 171*3cfa11baSSteen Hegelund int rcnt, int rwidth) 172*3cfa11baSSteen Hegelund { 173*3cfa11baSSteen Hegelund WARN_ON((tinst) >= tcnt); 174*3cfa11baSSteen Hegelund WARN_ON((ginst) >= gcnt); 175*3cfa11baSSteen Hegelund WARN_ON((rinst) >= rcnt); 176*3cfa11baSSteen Hegelund return base[id + (tinst)] + 177*3cfa11baSSteen Hegelund gbase + ((ginst) * gwidth) + 178*3cfa11baSSteen Hegelund raddr + ((rinst) * rwidth); 179*3cfa11baSSteen Hegelund } 180*3cfa11baSSteen Hegelund 181*3cfa11baSSteen Hegelund static inline void __iomem *spx5_inst_addr(void __iomem *base, 182*3cfa11baSSteen Hegelund int gbase, int ginst, 183*3cfa11baSSteen Hegelund int gcnt, int gwidth, 184*3cfa11baSSteen Hegelund int raddr, int rinst, 185*3cfa11baSSteen Hegelund int rcnt, int rwidth) 186*3cfa11baSSteen Hegelund { 187*3cfa11baSSteen Hegelund WARN_ON((ginst) >= gcnt); 188*3cfa11baSSteen Hegelund WARN_ON((rinst) >= rcnt); 189*3cfa11baSSteen Hegelund return base + 190*3cfa11baSSteen Hegelund gbase + ((ginst) * gwidth) + 191*3cfa11baSSteen Hegelund raddr + ((rinst) * rwidth); 192*3cfa11baSSteen Hegelund } 193*3cfa11baSSteen Hegelund 194*3cfa11baSSteen Hegelund static inline u32 spx5_rd(struct sparx5 *sparx5, int id, int tinst, int tcnt, 195*3cfa11baSSteen Hegelund int gbase, int ginst, int gcnt, int gwidth, 196*3cfa11baSSteen Hegelund int raddr, int rinst, int rcnt, int rwidth) 197*3cfa11baSSteen Hegelund { 198*3cfa11baSSteen Hegelund return readl(spx5_addr(sparx5->regs, id, tinst, tcnt, gbase, ginst, 199*3cfa11baSSteen Hegelund gcnt, gwidth, raddr, rinst, rcnt, rwidth)); 200*3cfa11baSSteen Hegelund } 201*3cfa11baSSteen Hegelund 202*3cfa11baSSteen Hegelund static inline u32 spx5_inst_rd(void __iomem *iomem, int id, int tinst, int tcnt, 203*3cfa11baSSteen Hegelund int gbase, int ginst, int gcnt, int gwidth, 204*3cfa11baSSteen Hegelund int raddr, int rinst, int rcnt, int rwidth) 205*3cfa11baSSteen Hegelund { 206*3cfa11baSSteen Hegelund return readl(spx5_inst_addr(iomem, gbase, ginst, 207*3cfa11baSSteen Hegelund gcnt, gwidth, raddr, rinst, rcnt, rwidth)); 208*3cfa11baSSteen Hegelund } 209*3cfa11baSSteen Hegelund 210*3cfa11baSSteen Hegelund static inline void spx5_wr(u32 val, struct sparx5 *sparx5, 211*3cfa11baSSteen Hegelund int id, int tinst, int tcnt, 212*3cfa11baSSteen Hegelund int gbase, int ginst, int gcnt, int gwidth, 213*3cfa11baSSteen Hegelund int raddr, int rinst, int rcnt, int rwidth) 214*3cfa11baSSteen Hegelund { 215*3cfa11baSSteen Hegelund writel(val, spx5_addr(sparx5->regs, id, tinst, tcnt, 216*3cfa11baSSteen Hegelund gbase, ginst, gcnt, gwidth, 217*3cfa11baSSteen Hegelund raddr, rinst, rcnt, rwidth)); 218*3cfa11baSSteen Hegelund } 219*3cfa11baSSteen Hegelund 220*3cfa11baSSteen Hegelund static inline void spx5_inst_wr(u32 val, void __iomem *iomem, 221*3cfa11baSSteen Hegelund int id, int tinst, int tcnt, 222*3cfa11baSSteen Hegelund int gbase, int ginst, int gcnt, int gwidth, 223*3cfa11baSSteen Hegelund int raddr, int rinst, int rcnt, int rwidth) 224*3cfa11baSSteen Hegelund { 225*3cfa11baSSteen Hegelund writel(val, spx5_inst_addr(iomem, 226*3cfa11baSSteen Hegelund gbase, ginst, gcnt, gwidth, 227*3cfa11baSSteen Hegelund raddr, rinst, rcnt, rwidth)); 228*3cfa11baSSteen Hegelund } 229*3cfa11baSSteen Hegelund 230*3cfa11baSSteen Hegelund static inline void spx5_rmw(u32 val, u32 mask, struct sparx5 *sparx5, 231*3cfa11baSSteen Hegelund int id, int tinst, int tcnt, 232*3cfa11baSSteen Hegelund int gbase, int ginst, int gcnt, int gwidth, 233*3cfa11baSSteen Hegelund int raddr, int rinst, int rcnt, int rwidth) 234*3cfa11baSSteen Hegelund { 235*3cfa11baSSteen Hegelund u32 nval; 236*3cfa11baSSteen Hegelund 237*3cfa11baSSteen Hegelund nval = readl(spx5_addr(sparx5->regs, id, tinst, tcnt, gbase, ginst, 238*3cfa11baSSteen Hegelund gcnt, gwidth, raddr, rinst, rcnt, rwidth)); 239*3cfa11baSSteen Hegelund nval = (nval & ~mask) | (val & mask); 240*3cfa11baSSteen Hegelund writel(nval, spx5_addr(sparx5->regs, id, tinst, tcnt, gbase, ginst, 241*3cfa11baSSteen Hegelund gcnt, gwidth, raddr, rinst, rcnt, rwidth)); 242*3cfa11baSSteen Hegelund } 243*3cfa11baSSteen Hegelund 244*3cfa11baSSteen Hegelund static inline void spx5_inst_rmw(u32 val, u32 mask, void __iomem *iomem, 245*3cfa11baSSteen Hegelund int id, int tinst, int tcnt, 246*3cfa11baSSteen Hegelund int gbase, int ginst, int gcnt, int gwidth, 247*3cfa11baSSteen Hegelund int raddr, int rinst, int rcnt, int rwidth) 248*3cfa11baSSteen Hegelund { 249*3cfa11baSSteen Hegelund u32 nval; 250*3cfa11baSSteen Hegelund 251*3cfa11baSSteen Hegelund nval = readl(spx5_inst_addr(iomem, gbase, ginst, gcnt, gwidth, raddr, 252*3cfa11baSSteen Hegelund rinst, rcnt, rwidth)); 253*3cfa11baSSteen Hegelund nval = (nval & ~mask) | (val & mask); 254*3cfa11baSSteen Hegelund writel(nval, spx5_inst_addr(iomem, gbase, ginst, gcnt, gwidth, raddr, 255*3cfa11baSSteen Hegelund rinst, rcnt, rwidth)); 256*3cfa11baSSteen Hegelund } 257*3cfa11baSSteen Hegelund 258*3cfa11baSSteen Hegelund static inline void __iomem *spx5_inst_get(struct sparx5 *sparx5, int id, int tinst) 259*3cfa11baSSteen Hegelund { 260*3cfa11baSSteen Hegelund return sparx5->regs[id + tinst]; 261*3cfa11baSSteen Hegelund } 262*3cfa11baSSteen Hegelund 263*3cfa11baSSteen Hegelund static inline void __iomem *spx5_reg_get(struct sparx5 *sparx5, 264*3cfa11baSSteen Hegelund int id, int tinst, int tcnt, 265*3cfa11baSSteen Hegelund int gbase, int ginst, int gcnt, int gwidth, 266*3cfa11baSSteen Hegelund int raddr, int rinst, int rcnt, int rwidth) 267*3cfa11baSSteen Hegelund { 268*3cfa11baSSteen Hegelund return spx5_addr(sparx5->regs, id, tinst, tcnt, 269*3cfa11baSSteen Hegelund gbase, ginst, gcnt, gwidth, 270*3cfa11baSSteen Hegelund raddr, rinst, rcnt, rwidth); 271*3cfa11baSSteen Hegelund } 272*3cfa11baSSteen Hegelund 273*3cfa11baSSteen Hegelund #endif /* __SPARX5_MAIN_H__ */ 274