linux/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0+ */
   2/* Microchip Sparx5 Switch driver
   3 *
   4 * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries.
   5 */
   6
   7#ifndef __SPARX5_MAIN_H__
   8#define __SPARX5_MAIN_H__
   9
  10#include <linux/types.h>
  11#include <linux/phy/phy.h>
  12#include <linux/netdevice.h>
  13#include <linux/phy.h>
  14#include <linux/if_vlan.h>
  15#include <linux/bitmap.h>
  16#include <linux/phylink.h>
  17#include <linux/hrtimer.h>
  18
  19/* Target chip type */
  20enum spx5_target_chiptype {
  21        SPX5_TARGET_CT_7546    = 0x7546,  /* SparX-5-64  Enterprise */
  22        SPX5_TARGET_CT_7549    = 0x7549,  /* SparX-5-90  Enterprise */
  23        SPX5_TARGET_CT_7552    = 0x7552,  /* SparX-5-128 Enterprise */
  24        SPX5_TARGET_CT_7556    = 0x7556,  /* SparX-5-160 Enterprise */
  25        SPX5_TARGET_CT_7558    = 0x7558,  /* SparX-5-200 Enterprise */
  26        SPX5_TARGET_CT_7546TSN = 0x47546, /* SparX-5-64i Industrial */
  27        SPX5_TARGET_CT_7549TSN = 0x47549, /* SparX-5-90i Industrial */
  28        SPX5_TARGET_CT_7552TSN = 0x47552, /* SparX-5-128i Industrial */
  29        SPX5_TARGET_CT_7556TSN = 0x47556, /* SparX-5-160i Industrial */
  30        SPX5_TARGET_CT_7558TSN = 0x47558, /* SparX-5-200i Industrial */
  31};
  32
  33enum sparx5_port_max_tags {
  34        SPX5_PORT_MAX_TAGS_NONE,  /* No extra tags allowed */
  35        SPX5_PORT_MAX_TAGS_ONE,   /* Single tag allowed */
  36        SPX5_PORT_MAX_TAGS_TWO    /* Single and double tag allowed */
  37};
  38
  39enum sparx5_vlan_port_type {
  40        SPX5_VLAN_PORT_TYPE_UNAWARE, /* VLAN unaware port */
  41        SPX5_VLAN_PORT_TYPE_C,       /* C-port */
  42        SPX5_VLAN_PORT_TYPE_S,       /* S-port */
  43        SPX5_VLAN_PORT_TYPE_S_CUSTOM /* S-port using custom type */
  44};
  45
  46#define SPX5_PORTS             65
  47#define SPX5_PORT_CPU          (SPX5_PORTS)  /* Next port is CPU port */
  48#define SPX5_PORT_CPU_0        (SPX5_PORT_CPU + 0) /* CPU Port 65 */
  49#define SPX5_PORT_CPU_1        (SPX5_PORT_CPU + 1) /* CPU Port 66 */
  50#define SPX5_PORT_VD0          (SPX5_PORT_CPU + 2) /* VD0/Port 67 used for IPMC */
  51#define SPX5_PORT_VD1          (SPX5_PORT_CPU + 3) /* VD1/Port 68 used for AFI/OAM */
  52#define SPX5_PORT_VD2          (SPX5_PORT_CPU + 4) /* VD2/Port 69 used for IPinIP*/
  53#define SPX5_PORTS_ALL         (SPX5_PORT_CPU + 5) /* Total number of ports */
  54
  55#define PGID_BASE              SPX5_PORTS /* Starts after port PGIDs */
  56#define PGID_UC_FLOOD          (PGID_BASE + 0)
  57#define PGID_MC_FLOOD          (PGID_BASE + 1)
  58#define PGID_IPV4_MC_DATA      (PGID_BASE + 2)
  59#define PGID_IPV4_MC_CTRL      (PGID_BASE + 3)
  60#define PGID_IPV6_MC_DATA      (PGID_BASE + 4)
  61#define PGID_IPV6_MC_CTRL      (PGID_BASE + 5)
  62#define PGID_BCAST             (PGID_BASE + 6)
  63#define PGID_CPU               (PGID_BASE + 7)
  64
  65#define IFH_LEN                9 /* 36 bytes */
  66#define NULL_VID               0
  67#define SPX5_MACT_PULL_DELAY   (2 * HZ)
  68#define SPX5_STATS_CHECK_DELAY (1 * HZ)
  69#define SPX5_PRIOS             8     /* Number of priority queues */
  70#define SPX5_BUFFER_CELL_SZ    184   /* Cell size  */
  71#define SPX5_BUFFER_MEMORY     4194280 /* 22795 words * 184 bytes */
  72
  73#define XTR_QUEUE     0
  74#define INJ_QUEUE     0
  75
  76struct sparx5;
  77
  78struct sparx5_port_config {
  79        phy_interface_t portmode;
  80        u32 bandwidth;
  81        int speed;
  82        int duplex;
  83        enum phy_media media;
  84        bool inband;
  85        bool power_down;
  86        bool autoneg;
  87        bool serdes_reset;
  88        u32 pause;
  89        u32 pause_adv;
  90        phy_interface_t phy_mode;
  91        u32 sd_sgpio;
  92};
  93
  94struct sparx5_port {
  95        struct net_device *ndev;
  96        struct sparx5 *sparx5;
  97        struct device_node *of_node;
  98        struct phy *serdes;
  99        struct sparx5_port_config conf;
 100        struct phylink_config phylink_config;
 101        struct phylink *phylink;
 102        struct phylink_pcs phylink_pcs;
 103        u16 portno;
 104        /* Ingress default VLAN (pvid) */
 105        u16 pvid;
 106        /* Egress default VLAN (vid) */
 107        u16 vid;
 108        bool signd_internal;
 109        bool signd_active_high;
 110        bool signd_enable;
 111        bool flow_control;
 112        enum sparx5_port_max_tags max_vlan_tags;
 113        enum sparx5_vlan_port_type vlan_type;
 114        u32 custom_etype;
 115        u32 ifh[IFH_LEN];
 116        bool vlan_aware;
 117        struct hrtimer inj_timer;
 118};
 119
 120enum sparx5_core_clockfreq {
 121        SPX5_CORE_CLOCK_DEFAULT,  /* Defaults to the highest supported frequency */
 122        SPX5_CORE_CLOCK_250MHZ,   /* 250MHZ core clock frequency */
 123        SPX5_CORE_CLOCK_500MHZ,   /* 500MHZ core clock frequency */
 124        SPX5_CORE_CLOCK_625MHZ,   /* 625MHZ core clock frequency */
 125};
 126
 127struct sparx5 {
 128        struct platform_device *pdev;
 129        struct device *dev;
 130        u32 chip_id;
 131        enum spx5_target_chiptype target_ct;
 132        void __iomem *regs[NUM_TARGETS];
 133        int port_count;
 134        struct mutex lock; /* MAC reg lock */
 135        /* port structures are in net device */
 136        struct sparx5_port *ports[SPX5_PORTS];
 137        enum sparx5_core_clockfreq coreclock;
 138        /* Statistics */
 139        u32 num_stats;
 140        u32 num_ethtool_stats;
 141        const char * const *stats_layout;
 142        u64 *stats;
 143        /* Workqueue for reading stats */
 144        struct mutex queue_stats_lock;
 145        struct delayed_work stats_work;
 146        struct workqueue_struct *stats_queue;
 147        /* Notifiers */
 148        struct notifier_block netdevice_nb;
 149        struct notifier_block switchdev_nb;
 150        struct notifier_block switchdev_blocking_nb;
 151        /* Switch state */
 152        u8 base_mac[ETH_ALEN];
 153        /* Associated bridge device (when bridged) */
 154        struct net_device *hw_bridge_dev;
 155        /* Bridged interfaces */
 156        DECLARE_BITMAP(bridge_mask, SPX5_PORTS);
 157        DECLARE_BITMAP(bridge_fwd_mask, SPX5_PORTS);
 158        DECLARE_BITMAP(bridge_lrn_mask, SPX5_PORTS);
 159        DECLARE_BITMAP(vlan_mask[VLAN_N_VID], SPX5_PORTS);
 160        /* SW MAC table */
 161        struct list_head mact_entries;
 162        /* mac table list (mact_entries) mutex */
 163        struct mutex mact_lock;
 164        struct delayed_work mact_work;
 165        struct workqueue_struct *mact_queue;
 166        /* Board specifics */
 167        bool sd_sgpio_remapping;
 168        /* Register based inj/xtr */
 169        int xtr_irq;
 170};
 171
 172/* sparx5_switchdev.c */
 173int sparx5_register_notifier_blocks(struct sparx5 *sparx5);
 174void sparx5_unregister_notifier_blocks(struct sparx5 *sparx5);
 175
 176/* sparx5_packet.c */
 177irqreturn_t sparx5_xtr_handler(int irq, void *_priv);
 178int sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev);
 179int sparx5_manual_injection_mode(struct sparx5 *sparx5);
 180void sparx5_port_inj_timer_setup(struct sparx5_port *port);
 181
 182/* sparx5_mactable.c */
 183void sparx5_mact_pull_work(struct work_struct *work);
 184int sparx5_mact_learn(struct sparx5 *sparx5, int port,
 185                      const unsigned char mac[ETH_ALEN], u16 vid);
 186bool sparx5_mact_getnext(struct sparx5 *sparx5,
 187                         unsigned char mac[ETH_ALEN], u16 *vid, u32 *pcfg2);
 188int sparx5_mact_forget(struct sparx5 *sparx5,
 189                       const unsigned char mac[ETH_ALEN], u16 vid);
 190int sparx5_add_mact_entry(struct sparx5 *sparx5,
 191                          struct sparx5_port *port,
 192                          const unsigned char *addr, u16 vid);
 193int sparx5_del_mact_entry(struct sparx5 *sparx5,
 194                          const unsigned char *addr,
 195                          u16 vid);
 196int sparx5_mc_sync(struct net_device *dev, const unsigned char *addr);
 197int sparx5_mc_unsync(struct net_device *dev, const unsigned char *addr);
 198void sparx5_set_ageing(struct sparx5 *sparx5, int msecs);
 199void sparx5_mact_init(struct sparx5 *sparx5);
 200
 201/* sparx5_vlan.c */
 202void sparx5_pgid_update_mask(struct sparx5_port *port, int pgid, bool enable);
 203void sparx5_update_fwd(struct sparx5 *sparx5);
 204void sparx5_vlan_init(struct sparx5 *sparx5);
 205void sparx5_vlan_port_setup(struct sparx5 *sparx5, int portno);
 206int sparx5_vlan_vid_add(struct sparx5_port *port, u16 vid, bool pvid,
 207                        bool untagged);
 208int sparx5_vlan_vid_del(struct sparx5_port *port, u16 vid);
 209void sparx5_vlan_port_apply(struct sparx5 *sparx5, struct sparx5_port *port);
 210
 211/* sparx5_calendar.c */
 212int sparx5_config_auto_calendar(struct sparx5 *sparx5);
 213int sparx5_config_dsm_calendar(struct sparx5 *sparx5);
 214
 215/* sparx5_ethtool.c */
 216void sparx5_get_stats64(struct net_device *ndev, struct rtnl_link_stats64 *stats);
 217int sparx_stats_init(struct sparx5 *sparx5);
 218
 219/* sparx5_netdev.c */
 220bool sparx5_netdevice_check(const struct net_device *dev);
 221struct net_device *sparx5_create_netdev(struct sparx5 *sparx5, u32 portno);
 222int sparx5_register_netdevs(struct sparx5 *sparx5);
 223void sparx5_destroy_netdevs(struct sparx5 *sparx5);
 224void sparx5_unregister_netdevs(struct sparx5 *sparx5);
 225
 226/* Clock period in picoseconds */
 227static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock)
 228{
 229        switch (cclock) {
 230        case SPX5_CORE_CLOCK_250MHZ:
 231                return 4000;
 232        case SPX5_CORE_CLOCK_500MHZ:
 233                return 2000;
 234        case SPX5_CORE_CLOCK_625MHZ:
 235        default:
 236                return 1600;
 237        }
 238}
 239
 240static inline bool sparx5_is_baser(phy_interface_t interface)
 241{
 242        return interface == PHY_INTERFACE_MODE_5GBASER ||
 243                   interface == PHY_INTERFACE_MODE_10GBASER ||
 244                   interface == PHY_INTERFACE_MODE_25GBASER;
 245}
 246
 247extern const struct phylink_mac_ops sparx5_phylink_mac_ops;
 248extern const struct phylink_pcs_ops sparx5_phylink_pcs_ops;
 249extern const struct ethtool_ops sparx5_ethtool_ops;
 250
 251/* Calculate raw offset */
 252static inline __pure int spx5_offset(int id, int tinst, int tcnt,
 253                                     int gbase, int ginst,
 254                                     int gcnt, int gwidth,
 255                                     int raddr, int rinst,
 256                                     int rcnt, int rwidth)
 257{
 258        WARN_ON((tinst) >= tcnt);
 259        WARN_ON((ginst) >= gcnt);
 260        WARN_ON((rinst) >= rcnt);
 261        return gbase + ((ginst) * gwidth) +
 262                raddr + ((rinst) * rwidth);
 263}
 264
 265/* Read, Write and modify registers content.
 266 * The register definition macros start at the id
 267 */
 268static inline void __iomem *spx5_addr(void __iomem *base[],
 269                                      int id, int tinst, int tcnt,
 270                                      int gbase, int ginst,
 271                                      int gcnt, int gwidth,
 272                                      int raddr, int rinst,
 273                                      int rcnt, int rwidth)
 274{
 275        WARN_ON((tinst) >= tcnt);
 276        WARN_ON((ginst) >= gcnt);
 277        WARN_ON((rinst) >= rcnt);
 278        return base[id + (tinst)] +
 279                gbase + ((ginst) * gwidth) +
 280                raddr + ((rinst) * rwidth);
 281}
 282
 283static inline void __iomem *spx5_inst_addr(void __iomem *base,
 284                                           int gbase, int ginst,
 285                                           int gcnt, int gwidth,
 286                                           int raddr, int rinst,
 287                                           int rcnt, int rwidth)
 288{
 289        WARN_ON((ginst) >= gcnt);
 290        WARN_ON((rinst) >= rcnt);
 291        return base +
 292                gbase + ((ginst) * gwidth) +
 293                raddr + ((rinst) * rwidth);
 294}
 295
 296static inline u32 spx5_rd(struct sparx5 *sparx5, int id, int tinst, int tcnt,
 297                          int gbase, int ginst, int gcnt, int gwidth,
 298                          int raddr, int rinst, int rcnt, int rwidth)
 299{
 300        return readl(spx5_addr(sparx5->regs, id, tinst, tcnt, gbase, ginst,
 301                               gcnt, gwidth, raddr, rinst, rcnt, rwidth));
 302}
 303
 304static inline u32 spx5_inst_rd(void __iomem *iomem, int id, int tinst, int tcnt,
 305                               int gbase, int ginst, int gcnt, int gwidth,
 306                               int raddr, int rinst, int rcnt, int rwidth)
 307{
 308        return readl(spx5_inst_addr(iomem, gbase, ginst,
 309                                     gcnt, gwidth, raddr, rinst, rcnt, rwidth));
 310}
 311
 312static inline void spx5_wr(u32 val, struct sparx5 *sparx5,
 313                           int id, int tinst, int tcnt,
 314                           int gbase, int ginst, int gcnt, int gwidth,
 315                           int raddr, int rinst, int rcnt, int rwidth)
 316{
 317        writel(val, spx5_addr(sparx5->regs, id, tinst, tcnt,
 318                              gbase, ginst, gcnt, gwidth,
 319                              raddr, rinst, rcnt, rwidth));
 320}
 321
 322static inline void spx5_inst_wr(u32 val, void __iomem *iomem,
 323                                int id, int tinst, int tcnt,
 324                                int gbase, int ginst, int gcnt, int gwidth,
 325                                int raddr, int rinst, int rcnt, int rwidth)
 326{
 327        writel(val, spx5_inst_addr(iomem,
 328                                   gbase, ginst, gcnt, gwidth,
 329                                   raddr, rinst, rcnt, rwidth));
 330}
 331
 332static inline void spx5_rmw(u32 val, u32 mask, struct sparx5 *sparx5,
 333                            int id, int tinst, int tcnt,
 334                            int gbase, int ginst, int gcnt, int gwidth,
 335                            int raddr, int rinst, int rcnt, int rwidth)
 336{
 337        u32 nval;
 338
 339        nval = readl(spx5_addr(sparx5->regs, id, tinst, tcnt, gbase, ginst,
 340                               gcnt, gwidth, raddr, rinst, rcnt, rwidth));
 341        nval = (nval & ~mask) | (val & mask);
 342        writel(nval, spx5_addr(sparx5->regs, id, tinst, tcnt, gbase, ginst,
 343                               gcnt, gwidth, raddr, rinst, rcnt, rwidth));
 344}
 345
 346static inline void spx5_inst_rmw(u32 val, u32 mask, void __iomem *iomem,
 347                                 int id, int tinst, int tcnt,
 348                                 int gbase, int ginst, int gcnt, int gwidth,
 349                                 int raddr, int rinst, int rcnt, int rwidth)
 350{
 351        u32 nval;
 352
 353        nval = readl(spx5_inst_addr(iomem, gbase, ginst, gcnt, gwidth, raddr,
 354                                    rinst, rcnt, rwidth));
 355        nval = (nval & ~mask) | (val & mask);
 356        writel(nval, spx5_inst_addr(iomem, gbase, ginst, gcnt, gwidth, raddr,
 357                                    rinst, rcnt, rwidth));
 358}
 359
 360static inline void __iomem *spx5_inst_get(struct sparx5 *sparx5, int id, int tinst)
 361{
 362        return sparx5->regs[id + tinst];
 363}
 364
 365static inline void __iomem *spx5_reg_get(struct sparx5 *sparx5,
 366                                         int id, int tinst, int tcnt,
 367                                         int gbase, int ginst, int gcnt, int gwidth,
 368                                         int raddr, int rinst, int rcnt, int rwidth)
 369{
 370        return spx5_addr(sparx5->regs, id, tinst, tcnt,
 371                         gbase, ginst, gcnt, gwidth,
 372                         raddr, rinst, rcnt, rwidth);
 373}
 374
 375#endif  /* __SPARX5_MAIN_H__ */
 376