237 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2/*3 * Broadcom Starfighter2 private context4 *5 * Copyright (C) 2014, Broadcom Corporation6 */7 8#ifndef __BCM_SF2_H9#define __BCM_SF2_H10 11#include <linux/platform_device.h>12#include <linux/kernel.h>13#include <linux/io.h>14#include <linux/spinlock.h>15#include <linux/mutex.h>16#include <linux/mii.h>17#include <linux/ethtool.h>18#include <linux/types.h>19#include <linux/bitops.h>20#include <linux/if_vlan.h>21#include <linux/reset.h>22 23#include <net/dsa.h>24 25#include "bcm_sf2_regs.h"26#include "b53/b53_priv.h"27 28struct bcm_sf2_hw_params {29 u16 top_rev;30 u16 core_rev;31 u16 gphy_rev;32 u32 num_gphy;33 u8 num_acb_queue;34 u8 num_rgmii;35 u8 num_ports;36 u8 fcb_pause_override:1;37 u8 acb_packets_inflight:1;38};39 40#define BCM_SF2_REGS_NAME {\41 "core", "reg", "intrl2_0", "intrl2_1", "fcb", "acb" \42}43 44#define BCM_SF2_REGS_NUM 645 46struct bcm_sf2_port_status {47 phy_interface_t mode;48 unsigned int link;49 bool enabled;50};51 52struct bcm_sf2_cfp_priv {53 /* Mutex protecting concurrent accesses to the CFP registers */54 struct mutex lock;55 DECLARE_BITMAP(used, CFP_NUM_RULES);56 DECLARE_BITMAP(unique, CFP_NUM_RULES);57 unsigned int rules_cnt;58 struct list_head rules_list;59};60 61struct bcm_sf2_priv {62 /* Base registers, keep those in order with BCM_SF2_REGS_NAME */63 void __iomem *core;64 void __iomem *reg;65 void __iomem *intrl2_0;66 void __iomem *intrl2_1;67 void __iomem *fcb;68 void __iomem *acb;69 70 struct reset_control *rcdev;71 72 /* Register offsets indirection tables */73 u32 type;74 const u16 *reg_offsets;75 unsigned int core_reg_align;76 unsigned int num_cfp_rules;77 unsigned int num_crossbar_int_ports;78 79 /* spinlock protecting access to the indirect registers */80 spinlock_t indir_lock;81 82 int irq0;83 int irq1;84 u32 irq0_stat;85 u32 irq0_mask;86 u32 irq1_stat;87 u32 irq1_mask;88 89 /* Backing b53_device */90 struct b53_device *dev;91 92 struct bcm_sf2_hw_params hw_params;93 94 struct bcm_sf2_port_status port_sts[DSA_MAX_PORTS];95 96 /* Mask of ports enabled for Wake-on-LAN */97 u32 wol_ports_mask;98 99 struct clk *clk;100 struct clk *clk_mdiv;101 102 /* MoCA port location */103 int moca_port;104 105 /* Bitmask of ports having an integrated PHY */106 unsigned int int_phy_mask;107 108 /* Master and slave MDIO bus controller */109 unsigned int indir_phy_mask;110 struct mii_bus *user_mii_bus;111 struct mii_bus *master_mii_bus;112 113 /* Bitmask of ports needing BRCM tags */114 unsigned int brcm_tag_mask;115 116 /* CFP rules context */117 struct bcm_sf2_cfp_priv cfp;118};119 120static inline struct bcm_sf2_priv *bcm_sf2_to_priv(struct dsa_switch *ds)121{122 struct b53_device *dev = ds->priv;123 124 return dev->priv;125}126 127static inline u32 bcm_sf2_mangle_addr(struct bcm_sf2_priv *priv, u32 off)128{129 return off << priv->core_reg_align;130}131 132#define SF2_IO_MACRO(name) \133static inline u32 name##_readl(struct bcm_sf2_priv *priv, u32 off) \134{ \135 return readl_relaxed(priv->name + off); \136} \137static inline void name##_writel(struct bcm_sf2_priv *priv, \138 u32 val, u32 off) \139{ \140 writel_relaxed(val, priv->name + off); \141} \142 143/* Accesses to 64-bits register requires us to latch the hi/lo pairs144 * using the REG_DIR_DATA_{READ,WRITE} ancillary registers. The 'indir_lock'145 * spinlock is automatically grabbed and released to provide relative146 * atomiticy with latched reads/writes.147 */148#define SF2_IO64_MACRO(name) \149static inline u64 name##_readq(struct bcm_sf2_priv *priv, u32 off) \150{ \151 u32 indir, dir; \152 spin_lock(&priv->indir_lock); \153 dir = name##_readl(priv, off); \154 indir = reg_readl(priv, REG_DIR_DATA_READ); \155 spin_unlock(&priv->indir_lock); \156 return (u64)indir << 32 | dir; \157} \158static inline void name##_writeq(struct bcm_sf2_priv *priv, u64 val, \159 u32 off) \160{ \161 spin_lock(&priv->indir_lock); \162 reg_writel(priv, upper_32_bits(val), REG_DIR_DATA_WRITE); \163 name##_writel(priv, lower_32_bits(val), off); \164 spin_unlock(&priv->indir_lock); \165}166 167#define SWITCH_INTR_L2(which) \168static inline void intrl2_##which##_mask_clear(struct bcm_sf2_priv *priv, \169 u32 mask) \170{ \171 priv->irq##which##_mask &= ~(mask); \172 intrl2_##which##_writel(priv, mask, INTRL2_CPU_MASK_CLEAR); \173} \174static inline void intrl2_##which##_mask_set(struct bcm_sf2_priv *priv, \175 u32 mask) \176{ \177 intrl2_## which##_writel(priv, mask, INTRL2_CPU_MASK_SET); \178 priv->irq##which##_mask |= (mask); \179} \180 181static inline u32 core_readl(struct bcm_sf2_priv *priv, u32 off)182{183 u32 tmp = bcm_sf2_mangle_addr(priv, off);184 return readl_relaxed(priv->core + tmp);185}186 187static inline void core_writel(struct bcm_sf2_priv *priv, u32 val, u32 off)188{189 u32 tmp = bcm_sf2_mangle_addr(priv, off);190 writel_relaxed(val, priv->core + tmp);191}192 193static inline u32 reg_readl(struct bcm_sf2_priv *priv, u16 off)194{195 return readl_relaxed(priv->reg + priv->reg_offsets[off]);196}197 198static inline void reg_writel(struct bcm_sf2_priv *priv, u32 val, u16 off)199{200 writel_relaxed(val, priv->reg + priv->reg_offsets[off]);201}202 203SF2_IO64_MACRO(core);204SF2_IO_MACRO(intrl2_0);205SF2_IO_MACRO(intrl2_1);206SF2_IO_MACRO(fcb);207SF2_IO_MACRO(acb);208 209SWITCH_INTR_L2(0);210SWITCH_INTR_L2(1);211 212static inline u32 reg_led_readl(struct bcm_sf2_priv *priv, u16 off, u16 reg)213{214 return readl_relaxed(priv->reg + priv->reg_offsets[off] + reg);215}216 217static inline void reg_led_writel(struct bcm_sf2_priv *priv, u32 val, u16 off, u16 reg)218{219 writel_relaxed(val, priv->reg + priv->reg_offsets[off] + reg);220}221 222/* RXNFC */223int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port,224 struct ethtool_rxnfc *nfc, u32 *rule_locs);225int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,226 struct ethtool_rxnfc *nfc);227int bcm_sf2_cfp_rst(struct bcm_sf2_priv *priv);228void bcm_sf2_cfp_exit(struct dsa_switch *ds);229int bcm_sf2_cfp_resume(struct dsa_switch *ds);230void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port,231 u32 stringset, uint8_t *data);232void bcm_sf2_cfp_get_ethtool_stats(struct dsa_switch *ds, int port,233 uint64_t *data);234int bcm_sf2_cfp_get_sset_count(struct dsa_switch *ds, int port, int sset);235 236#endif /* __BCM_SF2_H */237