2019-05-27 09:55:01 +03:00
/* SPDX-License-Identifier: GPL-2.0-or-later */
2014-08-28 04:04:56 +04:00
/*
* Broadcom Starfighter2 private context
*
* Copyright ( C ) 2014 , Broadcom Corporation
*/
# ifndef __BCM_SF2_H
# define __BCM_SF2_H
# include <linux/platform_device.h>
# include <linux/kernel.h>
# include <linux/io.h>
# include <linux/spinlock.h>
# include <linux/mutex.h>
# include <linux/mii.h>
2014-09-25 04:05:22 +04:00
# include <linux/ethtool.h>
2015-10-23 21:38:07 +03:00
# include <linux/types.h>
# include <linux/bitops.h>
2016-06-10 03:42:08 +03:00
# include <linux/if_vlan.h>
2019-11-05 00:51:39 +03:00
# include <linux/reset.h>
2014-08-28 04:04:56 +04:00
# include <net/dsa.h>
# include "bcm_sf2_regs.h"
2016-08-26 22:18:33 +03:00
# include "b53/b53_priv.h"
2014-08-28 04:04:56 +04:00
struct bcm_sf2_hw_params {
u16 top_rev ;
u16 core_rev ;
2014-09-20 00:07:55 +04:00
u16 gphy_rev ;
2014-08-28 04:04:56 +04:00
u32 num_gphy ;
u8 num_acb_queue ;
u8 num_rgmii ;
u8 num_ports ;
u8 fcb_pause_override : 1 ;
u8 acb_packets_inflight : 1 ;
} ;
# define BCM_SF2_REGS_NAME {\
" core " , " reg " , " intrl2_0 " , " intrl2_1 " , " fcb " , " acb " \
}
# define BCM_SF2_REGS_NUM 6
struct bcm_sf2_port_status {
2021-03-12 13:41:07 +03:00
phy_interface_t mode ;
2014-08-28 04:04:56 +04:00
unsigned int link ;
2020-09-02 01:59:13 +03:00
bool enabled ;
2015-10-23 21:38:07 +03:00
} ;
2017-01-30 20:48:43 +03:00
struct bcm_sf2_cfp_priv {
/* Mutex protecting concurrent accesses to the CFP registers */
struct mutex lock ;
DECLARE_BITMAP ( used , CFP_NUM_RULES ) ;
2017-10-21 00:39:47 +03:00
DECLARE_BITMAP ( unique , CFP_NUM_RULES ) ;
2017-01-30 20:48:43 +03:00
unsigned int rules_cnt ;
2018-11-06 23:58:37 +03:00
struct list_head rules_list ;
2017-01-30 20:48:43 +03:00
} ;
2014-08-28 04:04:56 +04:00
struct bcm_sf2_priv {
/* Base registers, keep those in order with BCM_SF2_REGS_NAME */
void __iomem * core ;
void __iomem * reg ;
void __iomem * intrl2_0 ;
void __iomem * intrl2_1 ;
void __iomem * fcb ;
void __iomem * acb ;
2019-11-05 00:51:39 +03:00
struct reset_control * rcdev ;
2017-01-20 23:36:29 +03:00
/* Register offsets indirection tables */
u32 type ;
const u16 * reg_offsets ;
unsigned int core_reg_align ;
2017-08-30 22:39:33 +03:00
unsigned int num_cfp_rules ;
2021-03-12 13:41:08 +03:00
unsigned int num_crossbar_int_ports ;
2017-01-20 23:36:29 +03:00
2014-08-28 04:04:56 +04:00
/* spinlock protecting access to the indirect registers */
spinlock_t indir_lock ;
int irq0 ;
int irq1 ;
u32 irq0_stat ;
u32 irq0_mask ;
u32 irq1_stat ;
u32 irq1_mask ;
2016-08-26 22:18:33 +03:00
/* Backing b53_device */
struct b53_device * dev ;
2014-08-28 04:04:56 +04:00
struct bcm_sf2_hw_params hw_params ;
struct bcm_sf2_port_status port_sts [ DSA_MAX_PORTS ] ;
2014-09-19 04:31:25 +04:00
/* Mask of ports enabled for Wake-on-LAN */
u32 wol_ports_mask ;
2015-10-23 22:11:08 +03:00
2020-09-02 01:59:12 +03:00
struct clk * clk ;
2020-09-02 01:59:13 +03:00
struct clk * clk_mdiv ;
2020-09-02 01:59:12 +03:00
2015-10-23 22:11:08 +03:00
/* MoCA port location */
int moca_port ;
/* Bitmask of ports having an integrated PHY */
unsigned int int_phy_mask ;
2016-06-08 02:32:43 +03:00
/* Master and slave MDIO bus controller */
unsigned int indir_phy_mask ;
struct device_node * master_mii_dn ;
struct mii_bus * slave_mii_bus ;
struct mii_bus * master_mii_bus ;
2017-01-20 23:36:32 +03:00
/* Bitmask of ports needing BRCM tags */
unsigned int brcm_tag_mask ;
2017-01-30 20:48:43 +03:00
/* CFP rules context */
struct bcm_sf2_cfp_priv cfp ;
2014-08-28 04:04:56 +04:00
} ;
2016-08-26 22:18:33 +03:00
static inline struct bcm_sf2_priv * bcm_sf2_to_priv ( struct dsa_switch * ds )
{
2016-09-01 01:06:13 +03:00
struct b53_device * dev = ds - > priv ;
2016-08-26 22:18:33 +03:00
return dev - > priv ;
}
2017-01-20 23:36:29 +03:00
static inline u32 bcm_sf2_mangle_addr ( struct bcm_sf2_priv * priv , u32 off )
{
return off < < priv - > core_reg_align ;
}
2014-08-28 04:04:56 +04:00
# define SF2_IO_MACRO(name) \
static inline u32 name # # _readl ( struct bcm_sf2_priv * priv , u32 off ) \
{ \
2017-08-29 23:35:16 +03:00
return readl_relaxed ( priv - > name + off ) ; \
2014-08-28 04:04:56 +04:00
} \
static inline void name # # _writel ( struct bcm_sf2_priv * priv , \
u32 val , u32 off ) \
{ \
2017-08-29 23:35:16 +03:00
writel_relaxed ( val , priv - > name + off ) ; \
2014-08-28 04:04:56 +04:00
} \
/* Accesses to 64-bits register requires us to latch the hi/lo pairs
* using the REG_DIR_DATA_ { READ , WRITE } ancillary registers . The ' indir_lock '
* spinlock is automatically grabbed and released to provide relative
* atomiticy with latched reads / writes .
*/
# define SF2_IO64_MACRO(name) \
static inline u64 name # # _readq ( struct bcm_sf2_priv * priv , u32 off ) \
{ \
u32 indir , dir ; \
spin_lock ( & priv - > indir_lock ) ; \
2017-01-20 23:36:28 +03:00
dir = name # # _readl ( priv , off ) ; \
2015-02-19 22:09:27 +03:00
indir = reg_readl ( priv , REG_DIR_DATA_READ ) ; \
2014-08-28 04:04:56 +04:00
spin_unlock ( & priv - > indir_lock ) ; \
return ( u64 ) indir < < 32 | dir ; \
} \
2015-09-09 06:06:41 +03:00
static inline void name # # _writeq ( struct bcm_sf2_priv * priv , u64 val , \
u32 off ) \
2014-08-28 04:04:56 +04:00
{ \
spin_lock ( & priv - > indir_lock ) ; \
reg_writel ( priv , upper_32_bits ( val ) , REG_DIR_DATA_WRITE ) ; \
2017-01-20 23:36:28 +03:00
name # # _writel ( priv , lower_32_bits ( val ) , off ) ; \
2014-08-28 04:04:56 +04:00
spin_unlock ( & priv - > indir_lock ) ; \
}
# define SWITCH_INTR_L2(which) \
static inline void intrl2_ # # which # # _mask_clear ( struct bcm_sf2_priv * priv , \
u32 mask ) \
{ \
priv - > irq # # which # # _mask & = ~ ( mask ) ; \
2016-08-24 21:01:20 +03:00
intrl2_ # # which # # _writel ( priv , mask , INTRL2_CPU_MASK_CLEAR ) ; \
2014-08-28 04:04:56 +04:00
} \
static inline void intrl2_ # # which # # _mask_set ( struct bcm_sf2_priv * priv , \
u32 mask ) \
{ \
intrl2_ # # which # # _writel ( priv , mask , INTRL2_CPU_MASK_SET ) ; \
priv - > irq # # which # # _mask | = ( mask ) ; \
} \
2017-01-20 23:36:29 +03:00
static inline u32 core_readl ( struct bcm_sf2_priv * priv , u32 off )
{
u32 tmp = bcm_sf2_mangle_addr ( priv , off ) ;
2017-08-29 23:35:16 +03:00
return readl_relaxed ( priv - > core + tmp ) ;
2017-01-20 23:36:29 +03:00
}
static inline void core_writel ( struct bcm_sf2_priv * priv , u32 val , u32 off )
{
u32 tmp = bcm_sf2_mangle_addr ( priv , off ) ;
2017-08-29 23:35:16 +03:00
writel_relaxed ( val , priv - > core + tmp ) ;
2017-01-20 23:36:29 +03:00
}
static inline u32 reg_readl ( struct bcm_sf2_priv * priv , u16 off )
{
2017-08-29 23:35:16 +03:00
return readl_relaxed ( priv - > reg + priv - > reg_offsets [ off ] ) ;
2017-01-20 23:36:29 +03:00
}
static inline void reg_writel ( struct bcm_sf2_priv * priv , u32 val , u16 off )
{
2017-08-29 23:35:16 +03:00
writel_relaxed ( val , priv - > reg + priv - > reg_offsets [ off ] ) ;
2017-01-20 23:36:29 +03:00
}
2014-08-28 04:04:56 +04:00
SF2_IO64_MACRO ( core ) ;
SF2_IO_MACRO ( intrl2_0 ) ;
SF2_IO_MACRO ( intrl2_1 ) ;
SF2_IO_MACRO ( fcb ) ;
SF2_IO_MACRO ( acb ) ;
SWITCH_INTR_L2 ( 0 ) ;
SWITCH_INTR_L2 ( 1 ) ;
2021-12-29 20:16:42 +03:00
static inline u32 reg_led_readl ( struct bcm_sf2_priv * priv , u16 off , u16 reg )
{
return readl_relaxed ( priv - > reg + priv - > reg_offsets [ off ] + reg ) ;
}
static inline void reg_led_writel ( struct bcm_sf2_priv * priv , u32 val , u16 off , u16 reg )
{
writel_relaxed ( val , priv - > reg + priv - > reg_offsets [ off ] + reg ) ;
}
2017-01-30 20:48:43 +03:00
/* RXNFC */
int bcm_sf2_get_rxnfc ( struct dsa_switch * ds , int port ,
struct ethtool_rxnfc * nfc , u32 * rule_locs ) ;
int bcm_sf2_set_rxnfc ( struct dsa_switch * ds , int port ,
struct ethtool_rxnfc * nfc ) ;
int bcm_sf2_cfp_rst ( struct bcm_sf2_priv * priv ) ;
2018-11-06 23:58:37 +03:00
void bcm_sf2_cfp_exit ( struct dsa_switch * ds ) ;
2018-11-06 23:58:39 +03:00
int bcm_sf2_cfp_resume ( struct dsa_switch * ds ) ;
2019-02-06 23:45:59 +03:00
void bcm_sf2_cfp_get_strings ( struct dsa_switch * ds , int port ,
u32 stringset , uint8_t * data ) ;
void bcm_sf2_cfp_get_ethtool_stats ( struct dsa_switch * ds , int port ,
uint64_t * data ) ;
int bcm_sf2_cfp_get_sset_count ( struct dsa_switch * ds , int port , int sset ) ;
2017-01-30 20:48:43 +03:00
2014-08-28 04:04:56 +04:00
# endif /* __BCM_SF2_H */