2014-08-27 17:04:56 -07:00
/*
* Broadcom Starfighter2 private context
*
* Copyright ( C ) 2014 , Broadcom Corporation
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# 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-24 17:05:22 -07:00
# include <linux/ethtool.h>
2015-10-23 11:38:07 -07:00
# include <linux/types.h>
# include <linux/bitops.h>
2016-06-09 17:42:08 -07:00
# include <linux/if_vlan.h>
2014-08-27 17:04:56 -07:00
# include <net/dsa.h>
# include "bcm_sf2_regs.h"
2016-08-26 12:18:33 -07:00
# include "b53/b53_priv.h"
2014-08-27 17:04:56 -07:00
struct bcm_sf2_hw_params {
u16 top_rev ;
u16 core_rev ;
2014-09-19 13:07:55 -07:00
u16 gphy_rev ;
2014-08-27 17:04:56 -07: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 {
unsigned int link ;
2015-10-23 11:38:07 -07:00
} ;
2017-01-30 09:48:43 -08: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-20 14:39:47 -07:00
DECLARE_BITMAP ( unique , CFP_NUM_RULES ) ;
2017-01-30 09:48:43 -08:00
unsigned int rules_cnt ;
2018-11-06 12:58:37 -08:00
struct list_head rules_list ;
2017-01-30 09:48:43 -08:00
} ;
2014-08-27 17:04:56 -07: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 ;
2017-01-20 12:36:29 -08:00
/* Register offsets indirection tables */
u32 type ;
const u16 * reg_offsets ;
unsigned int core_reg_align ;
2017-08-30 12:39:33 -07:00
unsigned int num_cfp_rules ;
2017-01-20 12:36:29 -08:00
2014-08-27 17:04:56 -07: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 12:18:33 -07:00
/* Backing b53_device */
struct b53_device * dev ;
2014-08-27 17:04:56 -07:00
struct bcm_sf2_hw_params hw_params ;
struct bcm_sf2_port_status port_sts [ DSA_MAX_PORTS ] ;
2014-09-18 17:31:25 -07:00
/* Mask of ports enabled for Wake-on-LAN */
u32 wol_ports_mask ;
2015-10-23 12:11:08 -07:00
/* MoCA port location */
int moca_port ;
/* Bitmask of ports having an integrated PHY */
unsigned int int_phy_mask ;
2016-06-07 16:32:43 -07: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 12:36:32 -08:00
/* Bitmask of ports needing BRCM tags */
unsigned int brcm_tag_mask ;
2017-01-30 09:48:43 -08:00
/* CFP rules context */
struct bcm_sf2_cfp_priv cfp ;
2014-08-27 17:04:56 -07:00
} ;
2016-08-26 12:18:33 -07:00
static inline struct bcm_sf2_priv * bcm_sf2_to_priv ( struct dsa_switch * ds )
{
2016-08-31 18:06:13 -04:00
struct b53_device * dev = ds - > priv ;
2016-08-26 12:18:33 -07:00
return dev - > priv ;
}
2017-01-20 12:36:29 -08:00
static inline u32 bcm_sf2_mangle_addr ( struct bcm_sf2_priv * priv , u32 off )
{
return off < < priv - > core_reg_align ;
}
2014-08-27 17:04:56 -07:00
# define SF2_IO_MACRO(name) \
static inline u32 name # # _readl ( struct bcm_sf2_priv * priv , u32 off ) \
{ \
2017-08-29 13:35:16 -07:00
return readl_relaxed ( priv - > name + off ) ; \
2014-08-27 17:04:56 -07:00
} \
static inline void name # # _writel ( struct bcm_sf2_priv * priv , \
u32 val , u32 off ) \
{ \
2017-08-29 13:35:16 -07:00
writel_relaxed ( val , priv - > name + off ) ; \
2014-08-27 17:04:56 -07: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 12:36:28 -08:00
dir = name # # _readl ( priv , off ) ; \
2015-02-19 11:09:27 -08:00
indir = reg_readl ( priv , REG_DIR_DATA_READ ) ; \
2014-08-27 17:04:56 -07:00
spin_unlock ( & priv - > indir_lock ) ; \
return ( u64 ) indir < < 32 | dir ; \
} \
2015-09-08 20:06:41 -07:00
static inline void name # # _writeq ( struct bcm_sf2_priv * priv , u64 val , \
u32 off ) \
2014-08-27 17:04:56 -07:00
{ \
spin_lock ( & priv - > indir_lock ) ; \
reg_writel ( priv , upper_32_bits ( val ) , REG_DIR_DATA_WRITE ) ; \
2017-01-20 12:36:28 -08:00
name # # _writel ( priv , lower_32_bits ( val ) , off ) ; \
2014-08-27 17:04:56 -07: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 11:01:20 -07:00
intrl2_ # # which # # _writel ( priv , mask , INTRL2_CPU_MASK_CLEAR ) ; \
2014-08-27 17:04:56 -07: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 12:36:29 -08:00
static inline u32 core_readl ( struct bcm_sf2_priv * priv , u32 off )
{
u32 tmp = bcm_sf2_mangle_addr ( priv , off ) ;
2017-08-29 13:35:16 -07:00
return readl_relaxed ( priv - > core + tmp ) ;
2017-01-20 12:36:29 -08: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 13:35:16 -07:00
writel_relaxed ( val , priv - > core + tmp ) ;
2017-01-20 12:36:29 -08:00
}
static inline u32 reg_readl ( struct bcm_sf2_priv * priv , u16 off )
{
2017-08-29 13:35:16 -07:00
return readl_relaxed ( priv - > reg + priv - > reg_offsets [ off ] ) ;
2017-01-20 12:36:29 -08:00
}
static inline void reg_writel ( struct bcm_sf2_priv * priv , u32 val , u16 off )
{
2017-08-29 13:35:16 -07:00
writel_relaxed ( val , priv - > reg + priv - > reg_offsets [ off ] ) ;
2017-01-20 12:36:29 -08:00
}
2014-08-27 17:04:56 -07: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 ) ;
2017-01-30 09:48:43 -08: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 12:58:37 -08:00
void bcm_sf2_cfp_exit ( struct dsa_switch * ds ) ;
2018-11-06 12:58:39 -08:00
int bcm_sf2_cfp_resume ( struct dsa_switch * ds ) ;
2019-02-06 12:45:59 -08: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 09:48:43 -08:00
2014-08-27 17:04:56 -07:00
# endif /* __BCM_SF2_H */