diff options
Diffstat (limited to 'drivers/net/dsa/b53/b53_priv.h')
| -rw-r--r-- | drivers/net/dsa/b53/b53_priv.h | 164 |
1 files changed, 161 insertions, 3 deletions
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index 05141176daf5..bd6849e5bb93 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h @@ -45,6 +45,8 @@ struct b53_io_ops { int (*phy_write16)(struct b53_device *dev, int addr, int reg, u16 value); int (*irq_enable)(struct b53_device *dev, int port); void (*irq_disable)(struct b53_device *dev, int port); + void (*phy_enable)(struct b53_device *dev, int port); + void (*phy_disable)(struct b53_device *dev, int port); void (*phylink_get_caps)(struct b53_device *dev, int port, struct phylink_config *config); struct phylink_pcs *(*phylink_mac_select_pcs)(struct b53_device *dev, @@ -56,6 +58,17 @@ struct b53_io_ops { bool link_up); }; +struct b53_arl_entry; + +struct b53_arl_ops { + void (*arl_read_entry)(struct b53_device *dev, + struct b53_arl_entry *ent, u8 idx); + void (*arl_write_entry)(struct b53_device *dev, + const struct b53_arl_entry *ent, u8 idx); + void (*arl_search_read)(struct b53_device *dev, u8 idx, + struct b53_arl_entry *ent); +}; + #define B53_INVALID_LANE 0xff enum { @@ -66,10 +79,15 @@ enum { BCM5395_DEVICE_ID = 0x95, BCM5397_DEVICE_ID = 0x97, BCM5398_DEVICE_ID = 0x98, + BCM53101_DEVICE_ID = 0x53101, BCM53115_DEVICE_ID = 0x53115, BCM53125_DEVICE_ID = 0x53125, BCM53128_DEVICE_ID = 0x53128, BCM63XX_DEVICE_ID = 0x6300, + BCM6318_DEVICE_ID = 0x6318, + BCM6328_DEVICE_ID = 0x6328, + BCM6362_DEVICE_ID = 0x6362, + BCM6368_DEVICE_ID = 0x6368, BCM63268_DEVICE_ID = 0x63268, BCM53010_DEVICE_ID = 0x53010, BCM53011_DEVICE_ID = 0x53011, @@ -83,6 +101,12 @@ enum { BCM53134_DEVICE_ID = 0x5075, }; +enum b53_variant_id { + B53_VARIANT_NONE = 0, + B53_VARIANT_5325E, + B53_VARIANT_5325M, +}; + struct b53_pcs { struct phylink_pcs pcs; struct b53_device *dev; @@ -95,6 +119,7 @@ struct b53_pcs { struct b53_port { u16 vlan_ctl_mask; + u16 pvid; struct ethtool_keee eee; }; @@ -113,9 +138,11 @@ struct b53_device { struct mutex stats_mutex; struct mutex arl_mutex; const struct b53_io_ops *ops; + const struct b53_arl_ops *arl_ops; /* chip specific data */ u32 chip_id; + enum b53_variant_id variant_id; u8 core_rev; u8 vta_regs[3]; u8 duplex_reg; @@ -146,6 +173,7 @@ struct b53_device { unsigned int num_vlans; struct b53_vlan *vlans; bool vlan_enabled; + bool vlan_filtering; unsigned int num_ports; struct b53_port *ports; @@ -162,6 +190,18 @@ static inline int is5325(struct b53_device *dev) return dev->chip_id == BCM5325_DEVICE_ID; } +static inline int is5325e(struct b53_device *dev) +{ + return is5325(dev) && + dev->variant_id == B53_VARIANT_5325E; +} + +static inline int is5325m(struct b53_device *dev) +{ + return is5325(dev) && + dev->variant_id == B53_VARIANT_5325M; +} + static inline int is5365(struct b53_device *dev) { #ifdef CONFIG_BCM47XX @@ -188,6 +228,7 @@ static inline int is531x5(struct b53_device *dev) { return dev->chip_id == BCM53115_DEVICE_ID || dev->chip_id == BCM53125_DEVICE_ID || + dev->chip_id == BCM53101_DEVICE_ID || dev->chip_id == BCM53128_DEVICE_ID || dev->chip_id == BCM53134_DEVICE_ID; } @@ -195,12 +236,17 @@ static inline int is531x5(struct b53_device *dev) static inline int is63xx(struct b53_device *dev) { return dev->chip_id == BCM63XX_DEVICE_ID || + dev->chip_id == BCM6318_DEVICE_ID || + dev->chip_id == BCM6328_DEVICE_ID || + dev->chip_id == BCM6362_DEVICE_ID || + dev->chip_id == BCM6368_DEVICE_ID || dev->chip_id == BCM63268_DEVICE_ID; } -static inline int is63268(struct b53_device *dev) +static inline int is6318_268(struct b53_device *dev) { - return dev->chip_id == BCM63268_DEVICE_ID; + return dev->chip_id == BCM6318_DEVICE_ID || + dev->chip_id == BCM63268_DEVICE_ID; } static inline int is5301x(struct b53_device *dev) @@ -294,6 +340,33 @@ static inline void b53_arl_to_entry(struct b53_arl_entry *ent, ent->vid = mac_vid >> ARLTBL_VID_S; } +static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent, + u64 mac_vid, u8 vid_entry) +{ + memset(ent, 0, sizeof(*ent)); + ent->is_valid = !!(mac_vid & ARLTBL_VALID_25); + ent->is_age = !!(mac_vid & ARLTBL_AGE_25); + ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); + u64_to_ether_addr(mac_vid, ent->mac); + ent->port = (mac_vid & ARLTBL_DATA_PORT_ID_MASK_25) >> + ARLTBL_DATA_PORT_ID_S_25; + if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT) + ent->port = B53_CPU_PORT_25; + ent->vid = vid_entry; +} + +static inline void b53_arl_to_entry_89(struct b53_arl_entry *ent, + u64 mac_vid, u16 fwd_entry) +{ + memset(ent, 0, sizeof(*ent)); + ent->port = fwd_entry & ARLTBL_DATA_PORT_ID_MASK_89; + ent->is_valid = !!(fwd_entry & ARLTBL_VALID_89); + ent->is_age = !!(fwd_entry & ARLTBL_AGE_89); + ent->is_static = !!(fwd_entry & ARLTBL_STATIC_89); + u64_to_ether_addr(mac_vid, ent->mac); + ent->vid = mac_vid >> ARLTBL_VID_S; +} + static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry, const struct b53_arl_entry *ent) { @@ -308,6 +381,89 @@ static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry, *fwd_entry |= ARLTBL_AGE; } +static inline void b53_arl_from_entry_25(u64 *mac_vid, u8 *vid_entry, + const struct b53_arl_entry *ent) +{ + *mac_vid = ether_addr_to_u64(ent->mac); + if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT_25) + *mac_vid |= (u64)B53_CPU_PORT << ARLTBL_DATA_PORT_ID_S_25; + else + *mac_vid |= ((u64)ent->port << ARLTBL_DATA_PORT_ID_S_25) & + ARLTBL_DATA_PORT_ID_MASK_25; + if (ent->is_valid) + *mac_vid |= ARLTBL_VALID_25; + if (ent->is_static) + *mac_vid |= ARLTBL_STATIC_25; + if (ent->is_age) + *mac_vid |= ARLTBL_AGE_25; + *vid_entry = ent->vid; +} + +static inline void b53_arl_from_entry_89(u64 *mac_vid, u32 *fwd_entry, + const struct b53_arl_entry *ent) +{ + *mac_vid = ether_addr_to_u64(ent->mac); + *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK) << ARLTBL_VID_S; + *fwd_entry = ent->port & ARLTBL_DATA_PORT_ID_MASK_89; + if (ent->is_valid) + *fwd_entry |= ARLTBL_VALID_89; + if (ent->is_static) + *fwd_entry |= ARLTBL_STATIC_89; + if (ent->is_age) + *fwd_entry |= ARLTBL_AGE_89; +} + +static inline void b53_arl_search_to_entry_25(struct b53_arl_entry *ent, + u64 mac_vid, u8 ext) +{ + memset(ent, 0, sizeof(*ent)); + ent->is_valid = !!(mac_vid & ARLTBL_VALID_25); + ent->is_age = !!(mac_vid & ARLTBL_AGE_25); + ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); + u64_to_ether_addr(mac_vid, ent->mac); + ent->vid = (mac_vid & ARL_SRCH_RSLT_VID_MASK_25) >> + ARL_SRCH_RSLT_VID_S_25; + ent->port = (mac_vid & ARL_SRCH_RSLT_PORT_ID_MASK_25) >> + ARL_SRCH_RSLT_PORT_ID_S_25; + if (is_multicast_ether_addr(ent->mac) && (ext & ARL_SRCH_RSLT_EXT_MC_MII)) + ent->port |= BIT(B53_CPU_PORT_25); + else if (!is_multicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT) + ent->port = B53_CPU_PORT_25; +} + +static inline void b53_arl_search_to_entry_63xx(struct b53_arl_entry *ent, + u64 mac_vid, u16 fwd_entry) +{ + memset(ent, 0, sizeof(*ent)); + u64_to_ether_addr(mac_vid, ent->mac); + ent->vid = mac_vid >> ARLTBL_VID_S; + + ent->port = fwd_entry & ARL_SRST_PORT_ID_MASK_63XX; + ent->port >>= 1; + + ent->is_age = !!(fwd_entry & ARL_SRST_AGE_63XX); + ent->is_static = !!(fwd_entry & ARL_SRST_STATIC_63XX); + ent->is_valid = 1; +} + +static inline void b53_arl_read_entry(struct b53_device *dev, + struct b53_arl_entry *ent, u8 idx) +{ + dev->arl_ops->arl_read_entry(dev, ent, idx); +} + +static inline void b53_arl_write_entry(struct b53_device *dev, + const struct b53_arl_entry *ent, u8 idx) +{ + dev->arl_ops->arl_write_entry(dev, ent, idx); +} + +static inline void b53_arl_search_read(struct b53_device *dev, u8 idx, + struct b53_arl_entry *ent) +{ + dev->arl_ops->arl_search_read(dev, idx, ent); +} + #ifdef CONFIG_BCM47XX #include <linux/bcm47xx_nvram.h> @@ -339,6 +495,7 @@ void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset, void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data); int b53_get_sset_count(struct dsa_switch *ds, int port, int sset); void b53_get_ethtool_phy_stats(struct dsa_switch *ds, int port, uint64_t *data); +int b53_set_ageing_time(struct dsa_switch *ds, unsigned int msecs); int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge, bool *tx_fwd_offload, struct netlink_ext_ack *extack); void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge); @@ -380,11 +537,12 @@ enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port, enum dsa_tag_protocol mprot); void b53_mirror_del(struct dsa_switch *ds, int port, struct dsa_mall_mirror_tc_entry *mirror); +int b53_setup_port(struct dsa_switch *ds, int port); int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy); void b53_disable_port(struct dsa_switch *ds, int port); void b53_brcm_hdr_setup(struct dsa_switch *ds, int port); int b53_eee_init(struct dsa_switch *ds, int port, struct phy_device *phy); -int b53_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e); +bool b53_support_eee(struct dsa_switch *ds, int port); int b53_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e); #endif |
