Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#ifndef HW_ATL2_H
#define HW_ATL2_H
#include "aq_common.h"
#define HW_ATL2_RX_TS_SIZE 8
#define HW_ATL2_PTP_OFFSET_INGRESS_100 768
#define HW_ATL2_PTP_OFFSET_EGRESS_100 336
#define HW_ATL2_PTP_OFFSET_INGRESS_1000 510
#define HW_ATL2_PTP_OFFSET_EGRESS_1000 105
#define HW_ATL2_PTP_OFFSET_INGRESS_2500 2447
#define HW_ATL2_PTP_OFFSET_EGRESS_2500 634
#define HW_ATL2_PTP_OFFSET_INGRESS_5000 1426
#define HW_ATL2_PTP_OFFSET_EGRESS_5000 361
#define HW_ATL2_PTP_OFFSET_INGRESS_10000 997
#define HW_ATL2_PTP_OFFSET_EGRESS_10000 203
extern const struct aq_hw_caps_s hw_atl2_caps_aqc113;
extern const struct aq_hw_caps_s hw_atl2_caps_aqc115c;
extern const struct aq_hw_caps_s hw_atl2_caps_aqc116c;
extern const struct aq_hw_ops hw_atl2_ops;
#endif /* HW_ATL2_H */
@@ -0,0 +1,195 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#ifndef HW_ATL2_INTERNAL_H
#define HW_ATL2_INTERNAL_H
#include "hw_atl2_utils.h"
#define HW_ATL2_MTU_JUMBO 16352U
#define HW_ATL2_MTU 1514U
#define HW_ATL2_TX_RINGS 4U
#define HW_ATL2_RX_RINGS 4U
#define HW_ATL2_RINGS_MAX 32U
#define HW_ATL2_TXD_SIZE (16U)
#define HW_ATL2_RXD_SIZE (16U)
#define HW_ATL2_MAC_UC 0U
#define HW_ATL2_MAC_MIN 1U
#define HW_ATL2_MAC_MAX 38U
/* interrupts */
#define HW_ATL2_ERR_INT 8U
#define HW_ATL2_INT_MASK (0xFFFFFFFFU)
#define HW_ATL2_TXBUF_MAX 128U
#define HW_ATL2_PTP_TXBUF_SIZE 8U
/* hw_atl2 on-chip RX packet buffer available for data TCs */
#define HW_ATL2_RXBUF_MAX 172U
#define HW_ATL2_PTP_RXBUF_SIZE 16U
#define HW_ATL2_RSS_REDIRECTION_MAX 64U
#define HW_ATL2_TC_MAX 8U
#define HW_ATL2_RSS_MAX 8U
#define HW_ATL2_INTR_MODER_MAX 0x1FF
#define HW_ATL2_INTR_MODER_MIN 0xFF
#define HW_ATL2_MIN_RXD \
(ALIGN(AQ_CFG_SKB_FRAGS_MAX + 1U, AQ_HW_RXD_MULTIPLE))
#define HW_ATL2_MIN_TXD \
(ALIGN(AQ_CFG_SKB_FRAGS_MAX + 1U, AQ_HW_TXD_MULTIPLE))
#define HW_ATL2_MAX_RXD 8184U
#define HW_ATL2_MAX_TXD 8184U
#define HW_ATL2_FW_SM_ACT_RSLVR 0x3U
#define HW_ATL2_RPF_TAG_UC_OFFSET 0x0
#define HW_ATL2_RPF_TAG_ALLMC_OFFSET 0x6
#define HW_ATL2_RPF_TAG_ET_OFFSET 0x7
#define HW_ATL2_RPF_TAG_VLAN_OFFSET 0xA
#define HW_ATL2_RPF_TAG_UNTAG_OFFSET 0xE
#define HW_ATL2_RPF_TAG_L3_V4_OFFSET 0xF
#define HW_ATL2_RPF_TAG_L3_V6_OFFSET 0x12
#define HW_ATL2_RPF_TAG_L4_OFFSET 0x15
#define HW_ATL2_RPF_TAG_L4_FLEX_OFFSET 0x18
#define HW_ATL2_RPF_TAG_FLEX_OFFSET 0x1B
#define HW_ATL2_RPF_TAG_PCP_OFFSET 0x1D
#define HW_ATL2_RPF_TAG_UC_MASK (0x0000003F << HW_ATL2_RPF_TAG_UC_OFFSET)
#define HW_ATL2_RPF_TAG_ALLMC_MASK (0x00000001 << HW_ATL2_RPF_TAG_ALLMC_OFFSET)
#define HW_ATL2_RPF_TAG_UNTAG_MASK (0x00000001 << HW_ATL2_RPF_TAG_UNTAG_OFFSET)
#define HW_ATL2_RPF_TAG_VLAN_MASK (0x0000000F << HW_ATL2_RPF_TAG_VLAN_OFFSET)
#define HW_ATL2_RPF_TAG_ET_MASK (0x00000007 << HW_ATL2_RPF_TAG_ET_OFFSET)
#define HW_ATL2_RPF_TAG_L3_V4_MASK (0x00000007 << HW_ATL2_RPF_TAG_L3_V4_OFFSET)
#define HW_ATL2_RPF_TAG_L3_V6_MASK (0x00000007 << HW_ATL2_RPF_TAG_L3_V6_OFFSET)
#define HW_ATL2_RPF_TAG_L4_MASK (0x00000007 << HW_ATL2_RPF_TAG_L4_OFFSET)
#define HW_ATL2_RPF_TAG_PCP_MASK (0x00000007 << HW_ATL2_RPF_TAG_PCP_OFFSET)
#define HW_ATL2_RPF_TAG_BASE_UC BIT(HW_ATL2_RPF_TAG_UC_OFFSET)
#define HW_ATL2_RPF_TAG_BASE_ALLMC BIT(HW_ATL2_RPF_TAG_ALLMC_OFFSET)
#define HW_ATL2_RPF_TAG_BASE_UNTAG BIT(HW_ATL2_RPF_TAG_UNTAG_OFFSET)
#define HW_ATL2_RPF_TAG_BASE_VLAN BIT(HW_ATL2_RPF_TAG_VLAN_OFFSET)
enum HW_ATL2_RPF_ART_INDEX {
HW_ATL2_RPF_L2_PROMISC_OFF_INDEX,
HW_ATL2_RPF_VLAN_PROMISC_OFF_INDEX,
HW_ATL2_RPF_L3L4_USER_INDEX = 8,
HW_ATL2_RPF_ET_PCP_USER_INDEX = HW_ATL2_RPF_L3L4_USER_INDEX + 16,
HW_ATL2_RPF_VLAN_USER_INDEX = HW_ATL2_RPF_ET_PCP_USER_INDEX + 16,
HW_ATL2_RPF_PCP_TO_TC_INDEX = HW_ATL2_RPF_VLAN_USER_INDEX +
HW_ATL_VLAN_MAX_FILTERS,
};
#define HW_ATL2_RPF_L3_CMD_EN BIT(0)
#define HW_ATL2_RPF_L3_CMD_SA_EN BIT(1)
#define HW_ATL2_RPF_L3_CMD_DA_EN BIT(2)
#define HW_ATL2_RPF_L3_CMD_PROTO_EN BIT(3)
#define HW_ATL2_RPF_L3_V6_CMD_EN BIT(0x10)
#define HW_ATL2_RPF_L3_V6_CMD_SA_EN BIT(0x11)
#define HW_ATL2_RPF_L3_V6_CMD_DA_EN BIT(0x12)
#define HW_ATL2_RPF_L3_V6_CMD_PROTO_EN BIT(0x13)
#define HW_ATL2_RPF_L4_CMD_EN BIT(0)
#define HW_ATL2_RPF_L4_CMD_DP_EN BIT(1)
#define HW_ATL2_RPF_L4_CMD_SP_EN BIT(2)
#define HW_ATL2_ART_TOTAL_ENTRIES 128
#define HW_ATL2_ACTION(ACTION, RSS, INDEX, VALID) \
((((ACTION) & 0x3U) << 8) | \
(((RSS) & 0x1U) << 7) | \
(((INDEX) & 0x3FU) << 2) | \
(((VALID) & 0x1U) << 0))
#define HW_ATL2_ACTION_DROP HW_ATL2_ACTION(0, 0, 0, 1)
#define HW_ATL2_ACTION_DISABLE HW_ATL2_ACTION(0, 0, 0, 0)
#define HW_ATL2_ACTION_ASSIGN_QUEUE(QUEUE) HW_ATL2_ACTION(1, 0, (QUEUE), 1)
#define HW_ATL2_ACTION_ASSIGN_TC(TC) HW_ATL2_ACTION(1, 1, (TC), 1)
#define HW_ATL2_RPF_L3L4_FILTERS 8
#define HW_ATL2_RPF_L3V4_FILTERS 8
#define HW_ATL2_RPF_L3V6_FILTERS 6
#define HW_ATL2_RPF_L4_FILTERS 8
#define HW_ATL2_RPF_VLAN_FILTERS 16
#define HW_ATL2_RPF_ETYPE_FILTERS 16
#define HW_ATL2_RPF_ETYPE_TAGS 7
enum HW_ATL2_RPF_RSS_HASH_TYPE {
HW_ATL2_RPF_RSS_HASH_TYPE_NONE = 0,
HW_ATL2_RPF_RSS_HASH_TYPE_IPV4 = BIT(0),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_TCP = BIT(1),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_UDP = BIT(2),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6 = BIT(3),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_TCP = BIT(4),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_UDP = BIT(5),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX = BIT(6),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_TCP = BIT(7),
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_UDP = BIT(8),
HW_ATL2_RPF_RSS_HASH_TYPE_ALL = HW_ATL2_RPF_RSS_HASH_TYPE_IPV4 |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_TCP |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_UDP |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6 |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_TCP |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_UDP |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_TCP |
HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_UDP,
};
#define HW_ATL_MCAST_FLT_ANY_TO_HOST 0x00010FFFU
struct hw_atl2_l3_filter {
u8 proto;
u8 usage;
u32 cmd;
u32 srcip[4];
u32 dstip[4];
};
struct hw_atl2_l4_filter {
u8 usage;
u32 cmd;
u16 sport;
u16 dport;
};
struct hw_atl2_l3l4_filter {
s8 l3_index;
s8 l4_index;
u8 ipv6;
};
struct hw_atl2_tag_policy {
u16 action;
u16 usage;
};
struct hw_atl2_priv {
struct hw_atl2_l3_filter l3_v4_filters[HW_ATL2_RPF_L3L4_FILTERS];
struct hw_atl2_l3_filter l3_v6_filters[HW_ATL2_RPF_L3L4_FILTERS];
struct hw_atl2_l4_filter l4_filters[HW_ATL2_RPF_L3L4_FILTERS];
struct hw_atl2_l3l4_filter l3l4_filters[HW_ATL2_RPF_L3L4_FILTERS];
struct hw_atl2_tag_policy etype_policy[HW_ATL2_RPF_ETYPE_FILTERS];
struct statistics_s last_stats;
unsigned int art_base_index;
unsigned int art_count;
unsigned int l2_filters_base_index;
unsigned int l2_filter_count;
unsigned int etype_filter_base_index;
unsigned int etype_filter_count;
unsigned int etype_filter_tag_top;
unsigned int vlan_filter_base_index;
unsigned int vlan_filter_count;
unsigned int l3_v4_filter_base_index;
unsigned int l3_v4_filter_count;
unsigned int l3_v6_filter_base_index;
unsigned int l3_v6_filter_count;
unsigned int l4_filter_base_index;
unsigned int l4_filter_count;
};
#endif /* HW_ATL2_INTERNAL_H */
@@ -0,0 +1,556 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#include "hw_atl2_llh.h"
#include "hw_atl2_llh_internal.h"
#include "aq_hw_utils.h"
u32 hw_atl2_phi_ext_tag_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg_bit(aq_hw, HW_ATL2_PHI_EXT_TAG_EN_ADR,
HW_ATL2_PHI_EXT_TAG_EN_MSK,
HW_ATL2_PHI_EXT_TAG_EN_SHIFT);
}
void hw_atl2_rpf_redirection_table2_select_set(struct aq_hw_s *aq_hw,
u32 select)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_ADR,
HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_MSK,
HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_SHIFT, select);
}
void hw_atl2_rpf_rss_hash_type_set(struct aq_hw_s *aq_hw, u32 rss_hash_type)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_ADR,
HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_MSK,
HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_SHIFT,
rss_hash_type);
}
/* rpf */
void hw_atl2_rpf_new_enable_set(struct aq_hw_s *aq_hw, u32 enable)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_NEW_EN_ADR,
HW_ATL2_RPF_NEW_EN_MSK,
HW_ATL2_RPF_NEW_EN_SHIFT,
enable);
}
void hw_atl2_rpfl2_uc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPFL2UC_TAG_ADR(filter),
HW_ATL2_RPFL2UC_TAG_MSK,
HW_ATL2_RPFL2UC_TAG_SHIFT,
tag);
}
void hw_atl2_rpfl2_bc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L2_BC_TAG_ADR,
HW_ATL2_RPF_L2_BC_TAG_MSK,
HW_ATL2_RPF_L2_BC_TAG_SHIFT,
tag);
}
void hw_atl2_new_rpf_rss_redir_set(struct aq_hw_s *aq_hw, u32 tc, u32 index,
u32 queue)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_RSS_REDIR_ADR(tc, index),
HW_ATL2_RPF_RSS_REDIR_MSK(tc),
HW_ATL2_RPF_RSS_REDIR_SHIFT(tc),
queue);
}
void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_VL_TAG_ADR(filter),
HW_ATL2_RPF_VL_TAG_MSK,
HW_ATL2_RPF_VL_TAG_SHIFT,
tag);
}
void hw_atl2_rpf_etht_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_ET_TAG_ADR(filter),
HW_ATL2_RPF_ET_TAG_MSK,
HW_ATL2_RPF_ET_TAG_SHIFT, tag);
}
u32 hw_atl2_rpf_etht_flr_tag_get(struct aq_hw_s *aq_hw, u32 filter)
{
return aq_hw_read_reg_bit(aq_hw, HW_ATL2_RPF_ET_TAG_ADR(filter),
HW_ATL2_RPF_ET_TAG_MSK,
HW_ATL2_RPF_ET_TAG_SHIFT);
}
void hw_atl2_rpf_l3_v4_dest_addr_set(struct aq_hw_s *aq_hw, u32 filter, u32 val)
{
u32 addr_set = 6 + ((filter < 4) ? 0 : 1);
u32 dword = filter % 4;
aq_hw_write_reg(aq_hw, HW_ATL2_RPF_L3_DA_DW_ADR(addr_set, dword), val);
}
void hw_atl2_rpf_l3_v4_src_addr_set(struct aq_hw_s *aq_hw, u32 filter, u32 val)
{
u32 addr_set = 6 + ((filter < 4) ? 0 : 1);
u32 dword = filter % 4;
aq_hw_write_reg(aq_hw, HW_ATL2_RPF_L3_SA_DW_ADR(addr_set, dword), val);
}
void hw_atl2_rpf_l3_v6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location,
u32 *ipv6_dst)
{
int i;
for (i = 0; i < 4; ++i)
aq_hw_write_reg(aq_hw,
HW_ATL2_RPF_L3_DA_DW_ADR(location, 3 - i),
ipv6_dst[i]);
}
void hw_atl2_rpf_l3_v6_src_addr_set(struct aq_hw_s *aq_hw, u8 location,
u32 *ipv6_src)
{
int i;
for (i = 0; i < 4; ++i)
aq_hw_write_reg(aq_hw,
HW_ATL2_RPF_L3_SA_DW_ADR(location, 3 - i),
ipv6_src[i]);
}
void hw_atl2_rpf_l3_v4_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L3_V4_CMD_ADR(filter),
HW_ATL2_RPF_L3_V4_CMD_MSK,
HW_ATL2_RPF_L3_V4_CMD_SHIFT, val);
}
void hw_atl2_rpf_l3_v6_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L3_V6_CMD_ADR(filter),
HW_ATL2_RPF_L3_V6_CMD_MSK,
HW_ATL2_RPF_L3_V6_CMD_SHIFT, val);
}
void hw_atl2_rpf_l3_v6_v4_select_set(struct aq_hw_s *aq_hw, u32 val)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L3_V6_V4_SELECT_ADR,
HW_ATL2_RPF_L3_V6_V4_SELECT_MSK,
HW_ATL2_RPF_L3_V6_V4_SELECT_SHIFT, val);
}
void hw_atl2_rpf_l3_v4_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L3_V4_TAG_ADR(filter),
HW_ATL2_RPF_L3_V4_TAG_MSK,
HW_ATL2_RPF_L3_V4_TAG_SHIFT, val);
}
void hw_atl2_rpf_l3_v6_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L3_V6_TAG_ADR(filter),
HW_ATL2_RPF_L3_V6_TAG_MSK,
HW_ATL2_RPF_L3_V6_TAG_SHIFT, val);
}
void hw_atl2_rpf_l4_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L4_TAG_ADR(filter),
HW_ATL2_RPF_L4_TAG_MSK,
HW_ATL2_RPF_L4_TAG_SHIFT, val);
}
void hw_atl2_rpf_l4_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L4_CMD_ADR(filter),
HW_ATL2_RPF_L4_CMD_MSK,
HW_ATL2_RPF_L4_CMD_SHIFT, val);
}
/* tsg */
static void hw_atl2_clock_modif_value_set(struct aq_hw_s *aq_hw,
u32 clock_sel, u64 ns)
{
aq_hw_write_reg64(aq_hw,
HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_MODIF_VAL_LSW),
ns);
}
void hw_atl2_tsg_clock_en(struct aq_hw_s *aq_hw,
u32 clock_sel, u32 clock_enable)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_CFG),
HW_ATL2_TSG_CLOCK_EN_MSK,
HW_ATL2_TSG_CLOCK_EN_SHIFT,
clock_enable);
}
void hw_atl2_tsg_clock_reset(struct aq_hw_s *aq_hw, u32 clock_sel)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_CFG),
HW_ATL2_TSG_SYNC_RESET_MSK,
HW_ATL2_TSG_SYNC_RESET_SHIFT, 1);
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_CFG),
HW_ATL2_TSG_SYNC_RESET_MSK,
HW_ATL2_TSG_SYNC_RESET_SHIFT, 0);
}
u64 hw_atl2_tsg_clock_read(struct aq_hw_s *aq_hw, u32 clock_sel)
{
return aq_hw_read_reg64(aq_hw,
HW_ATL2_TSG_REG_ADR(clock_sel,
READ_CUR_NS_LSW));
}
void hw_atl2_tsg_clock_add(struct aq_hw_s *aq_hw, u32 clock_sel, u64 ns)
{
hw_atl2_clock_modif_value_set(aq_hw, clock_sel, ns);
aq_hw_write_reg(aq_hw,
HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_MODIF_CTRL),
HW_ATL2_TSG_ADD_COUNTER_MSK);
}
void hw_atl2_tsg_clock_sub(struct aq_hw_s *aq_hw, u32 clock_sel, u64 ns)
{
hw_atl2_clock_modif_value_set(aq_hw, clock_sel, ns);
aq_hw_write_reg(aq_hw,
HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_MODIF_CTRL),
HW_ATL2_TSG_SUBTRACT_COUNTER_MSK);
}
void hw_atl2_tsg_clock_increment_set(struct aq_hw_s *aq_hw,
u32 clock_sel, u32 ns, u32 fns)
{
u32 nsfns = (ns & 0xff) | (fns & 0xffffff00);
aq_hw_write_reg(aq_hw,
HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_INC_CFG),
nsfns);
aq_hw_write_reg(aq_hw,
HW_ATL2_TSG_REG_ADR(clock_sel, CLOCK_MODIF_CTRL),
HW_ATL2_TSG_LOAD_INC_CFG_MSK);
}
void hw_atl2_tpb_tps_highest_priority_tc_enable_set(struct aq_hw_s *aq_hw,
u32 tps_highest_prio_tc_en)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_ADR,
HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_MSK,
HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_SHIFT,
tps_highest_prio_tc_en);
}
void hw_atl2_tpb_tps_highest_priority_tc_set(struct aq_hw_s *aq_hw,
u32 tps_highest_prio_tc)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPB_HIGHEST_PRIO_TC_ADR,
HW_ATL2_TPB_HIGHEST_PRIO_TC_MSK,
HW_ATL2_TPB_HIGHEST_PRIO_TC_SHIFT,
tps_highest_prio_tc);
}
void hw_atl2_tsg_gpio_isr_to_host_set(struct aq_hw_s *aq_hw,
int on, u32 clock_sel)
{
aq_hw_write_reg_bit(aq_hw,
HW_ATL2_GLOBAL_HIGH_PRIO_INTERRUPT_1_MASK_ADR,
clock_sel == 1 ? HW_ATL2_TSG_TSG1_GPIO_INTERRUPT_MSK :
HW_ATL2_TSG_TSG0_GPIO_INTERRUPT_MSK,
clock_sel == 1 ? HW_ATL2_TSG_TSG1_GPIO_INTERRUPT_SHIFT :
HW_ATL2_TSG_TSG0_GPIO_INTERRUPT_SHIFT,
!!on);
}
void hw_atl2_tsg_gpio_clear_status(struct aq_hw_s *aq_hw)
{
aq_hw_read_reg(aq_hw, HW_ATL2_GLOBAL_INTERNAL_ALARMS_1_ADR);
}
void hw_atl2_tsg_gpio_input_event_info_get(struct aq_hw_s *aq_hw,
u32 clock_sel,
u32 *event_count,
u64 *event_ts)
{
if (event_count)
*event_count = aq_hw_read_reg(aq_hw,
HW_ATL2_TSG_REG_ADR(clock_sel,
EXT_CLK_COUNT));
if (event_ts)
*event_ts = aq_hw_read_reg64(aq_hw,
HW_ATL2_TSG_REG_ADR(clock_sel,
GPIO_EVENT_TS_LSW));
}
void hw_atl2_tsg_ptp_gpio_gen_pulse(struct aq_hw_s *aq_hw, u32 clk_sel,
u64 ts, u32 period, u32 hightime)
{
u32 val = (HW_ATL2_TSG_GPIO_EVENT_MODE_SET_ON_TIME <<
(HW_ATL2_TSG_GPIO_EVENT_MODE_SHIFT -
HW_ATL2_TSG_GPIO_OUTPUT_EN_SHIFT)) |
(HW_ATL2_TSG_GPIO_GEN_OUTPUT_EN_MSK) |
(HW_ATL2_TSG_GPIO_OUTPUT_EN_MSK);
if (ts != 0) {
aq_hw_write_reg64(aq_hw,
HW_ATL2_TSG_REG_ADR(clk_sel,
GPIO_EVENT_GEN_TS_LSW),
ts);
aq_hw_write_reg64(aq_hw,
HW_ATL2_TSG_REG_ADR(clk_sel,
GPIO_EVENT_HIGH_TIME_LSW),
hightime);
aq_hw_write_reg64(aq_hw,
HW_ATL2_TSG_REG_ADR(clk_sel,
GPIO_EVENT_LOW_TIME_LSW),
(period - hightime));
}
aq_hw_write_reg_bit(aq_hw,
HW_ATL2_TSG_REG_ADR(clk_sel, GPIO_EVENT_GEN_CFG),
HW_ATL2_TSG_GPIO_EVENT_MODE_MSK |
HW_ATL2_TSG_GPIO_OUTPUT_EN_MSK |
HW_ATL2_TSG_GPIO_GEN_OUTPUT_EN_MSK,
HW_ATL2_TSG_GPIO_OUTPUT_EN_SHIFT,
(!ts ? 0 : val));
}
void hw_atl2_rpf_rx_desc_timestamp_req_set(struct aq_hw_s *aq_hw, u32 request,
u32 descriptor)
{
aq_hw_write_reg_bit(aq_hw,
HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_ADR(descriptor),
HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_MSK,
HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_SHIFT, request);
}
/* TX */
void hw_atl2_tpb_tx_tc_q_rand_map_en_set(struct aq_hw_s *aq_hw,
const u32 tc_q_rand_map_en)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_ADR,
HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_MSK,
HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_SHIFT,
tc_q_rand_map_en);
}
void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_ADR,
HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_MSK,
HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_SHIFT,
clk_gate_en);
}
void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw,
u32 tx_intr_moderation_ctl,
u32 queue)
{
aq_hw_write_reg(aq_hw, HW_ATL2_TX_INTR_MODERATION_CTL_ADR(queue),
tx_intr_moderation_ctl);
}
void hw_atl2_tdm_tx_desc_timestamp_writeback_en_set(struct aq_hw_s *aq_hw,
u32 enable, u32 descriptor)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TDM_DESCD_TS_WRB_EN_ADR(descriptor),
HW_ATL2_TDM_DESCD_TS_WRB_EN_MSK,
HW_ATL2_TDM_DESCD_TS_WRB_EN_SHIFT, enable);
}
void hw_atl2_tdm_tx_desc_timestamp_en_set(struct aq_hw_s *aq_hw, u32 enable,
u32 descriptor)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TDM_DESCD_TS_EN_ADR(descriptor),
HW_ATL2_TDM_DESCD_TS_EN_MSK,
HW_ATL2_TDM_DESCD_TS_EN_SHIFT, enable);
}
void hw_atl2_tdm_tx_desc_avb_en_set(struct aq_hw_s *aq_hw, u32 enable,
u32 descriptor)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TDM_DESCD_AVB_EN_ADR(descriptor),
HW_ATL2_TDM_DESCD_AVB_EN_MSK,
HW_ATL2_TDM_DESCD_AVB_EN_SHIFT, enable);
}
void hw_atl2_tps_tx_pkt_shed_data_arb_mode_set(struct aq_hw_s *aq_hw,
const u32 data_arb_mode)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPS_DATA_TC_ARB_MODE_ADR,
HW_ATL2_TPS_DATA_TC_ARB_MODE_MSK,
HW_ATL2_TPS_DATA_TC_ARB_MODE_SHIFT,
data_arb_mode);
}
void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw,
const u32 tc,
const u32 max_credit)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPS_DATA_TCTCREDIT_MAX_ADR(tc),
HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSK,
HW_ATL2_TPS_DATA_TCTCREDIT_MAX_SHIFT,
max_credit);
}
void hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw,
const u32 tc,
const u32 weight)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPS_DATA_TCTWEIGHT_ADR(tc),
HW_ATL2_TPS_DATA_TCTWEIGHT_MSK,
HW_ATL2_TPS_DATA_TCTWEIGHT_SHIFT,
weight);
}
void hw_atl2_tdm_tx_data_read_req_limit_set(struct aq_hw_s *aq_hw, u32 limit)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_ADR,
HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_MSK,
HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_SHIFT, limit);
}
void hw_atl2_tdm_tx_desc_read_req_limit_set(struct aq_hw_s *aq_hw, u32 limit)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_ADR,
HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_MSK,
HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_SHIFT, limit);
}
u32 hw_atl2_get_hw_version(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg(aq_hw, HW_ATL2_FPGA_VER_ADR);
}
void hw_atl2_init_launchtime(struct aq_hw_s *aq_hw)
{
u32 hw_ver = hw_atl2_get_hw_version(aq_hw);
aq_hw_write_reg_bit(aq_hw, HW_ATL2_LT_CTRL_ADR,
HW_ATL2_LT_CTRL_CLK_RATIO_MSK,
HW_ATL2_LT_CTRL_CLK_RATIO_SHIFT,
hw_ver < HW_ATL2_FPGA_VER_U32(1, 0, 0, 0) ?
HW_ATL2_LT_CTRL_CLK_RATIO_FULL_SPEED :
hw_ver >= HW_ATL2_FPGA_VER_U32(1, 0, 85, 2) ?
HW_ATL2_LT_CTRL_CLK_RATIO_HALF_SPEED :
HW_ATL2_LT_CTRL_CLK_RATIO_QUATER_SPEED);
}
/* set action resolver record */
void hw_atl2_rpf_act_rslvr_record_set(struct aq_hw_s *aq_hw, u8 location,
u32 tag, u32 mask, u32 action)
{
aq_hw_write_reg(aq_hw,
HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_ADR(location),
tag);
aq_hw_write_reg(aq_hw,
HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_ADR(location),
mask);
aq_hw_write_reg(aq_hw,
HW_ATL2_RPF_ACT_RSLVR_ACTN_ADR(location),
action);
}
void hw_atl2_rpf_act_rslvr_section_en_set(struct aq_hw_s *aq_hw, u32 sections)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_REC_TAB_EN_ADR,
HW_ATL2_RPF_REC_TAB_EN_MSK,
HW_ATL2_RPF_REC_TAB_EN_SHIFT,
sections);
}
u32 hw_atl2_rpf_act_rslvr_section_en_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg_bit(aq_hw, HW_ATL2_RPF_REC_TAB_EN_ADR,
HW_ATL2_RPF_REC_TAB_EN_MSK,
HW_ATL2_RPF_REC_TAB_EN_SHIFT);
}
void hw_atl2_mif_shared_buf_get(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len)
{
int j = 0;
int i;
for (i = offset; i < offset + len; i++, j++)
data[j] = aq_hw_read_reg(aq_hw,
HW_ATL2_MIF_SHARED_BUFFER_IN_ADR(i));
}
void hw_atl2_mif_shared_buf_write(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len)
{
int j = 0;
int i;
for (i = offset; i < offset + len; i++, j++)
aq_hw_write_reg(aq_hw, HW_ATL2_MIF_SHARED_BUFFER_IN_ADR(i),
data[j]);
}
void hw_atl2_mif_shared_buf_read(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len)
{
int j = 0;
int i;
for (i = offset; i < offset + len; i++, j++)
data[j] = aq_hw_read_reg(aq_hw,
HW_ATL2_MIF_SHARED_BUFFER_OUT_ADR(i));
}
void hw_atl2_mif_host_finished_write_set(struct aq_hw_s *aq_hw, u32 finish)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_MIF_HOST_FINISHED_WRITE_ADR,
HW_ATL2_MIF_HOST_FINISHED_WRITE_MSK,
HW_ATL2_MIF_HOST_FINISHED_WRITE_SHIFT,
finish);
}
u32 hw_atl2_mif_mcp_finished_read_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg_bit(aq_hw, HW_ATL2_MIF_MCP_FINISHED_READ_ADR,
HW_ATL2_MIF_MCP_FINISHED_READ_MSK,
HW_ATL2_MIF_MCP_FINISHED_READ_SHIFT);
}
u32 hw_atl2_mif_mcp_boot_reg_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg(aq_hw, HW_ATL2_MIF_BOOT_REG_ADR);
}
void hw_atl2_mif_mcp_boot_reg_set(struct aq_hw_s *aq_hw, u32 val)
{
return aq_hw_write_reg(aq_hw, HW_ATL2_MIF_BOOT_REG_ADR, val);
}
u32 hw_atl2_mif_host_req_int_get(struct aq_hw_s *aq_hw)
{
return aq_hw_read_reg(aq_hw, HW_ATL2_MCP_HOST_REQ_INT_ADR);
}
void hw_atl2_mif_host_req_int_clr(struct aq_hw_s *aq_hw, u32 val)
{
return aq_hw_write_reg(aq_hw, HW_ATL2_MCP_HOST_REQ_INT_CLR_ADR,
val);
}
void hw_atl2_gpio_special_mode_set(struct aq_hw_s *aq_hw,
u32 gpio_special_mode,
u32 pin)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL2_GPIO_PIN_SPEC_MODE_ADR(pin),
HW_ATL2_GPIO_PIN_SPEC_MODE_MSK,
HW_ATL2_GPIO_PIN_SPEC_MODE_SHIFT,
gpio_special_mode);
}
@@ -0,0 +1,197 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#ifndef HW_ATL2_LLH_H
#define HW_ATL2_LLH_H
#include <linux/types.h>
struct aq_hw_s;
/* Get Enable usage of extended tags from 32-255. */
u32 hw_atl2_phi_ext_tag_get(struct aq_hw_s *aq_hw);
/* Set TX Interrupt Moderation Control Register */
void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw,
u32 tx_intr_moderation_ctl,
u32 queue);
/* Set Redirection Table 2 Select */
void hw_atl2_rpf_redirection_table2_select_set(struct aq_hw_s *aq_hw,
u32 select);
/* Set RSS HASH type */
void hw_atl2_rpf_rss_hash_type_set(struct aq_hw_s *aq_hw, u32 rss_hash_type);
/* set new RPF enable */
void hw_atl2_rpf_new_enable_set(struct aq_hw_s *aq_hw, u32 enable);
/* set l2 unicast filter tag */
void hw_atl2_rpfl2_uc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter);
/* set l2 broadcast filter tag */
void hw_atl2_rpfl2_bc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag);
/* set new rss redirection table */
void hw_atl2_new_rpf_rss_redir_set(struct aq_hw_s *aq_hw, u32 tc, u32 index,
u32 queue);
/* Set VLAN filter tag */
void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter);
/* set ethertype filter tag */
void hw_atl2_rpf_etht_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter);
/* get ethertype filter tag */
u32 hw_atl2_rpf_etht_flr_tag_get(struct aq_hw_s *aq_hw, u32 filter);
/* set L3 v4 dest address */
void hw_atl2_rpf_l3_v4_dest_addr_set(struct aq_hw_s *aq_hw,
u32 filter, u32 val);
/* set L3 v4 src address */
void hw_atl2_rpf_l3_v4_src_addr_set(struct aq_hw_s *aq_hw, u32 filter, u32 val);
/* set L3 v4 cmd */
void hw_atl2_rpf_l3_v4_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
/* set L3 v6 cmd */
void hw_atl2_rpf_l3_v6_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
/* set L3 v6 dest address */
void hw_atl2_rpf_l3_v6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location,
u32 *ipv6_dst);
/* set L3 v6 src address */
void hw_atl2_rpf_l3_v6_src_addr_set(struct aq_hw_s *aq_hw, u8 location,
u32 *ipv6_src);
/* set L3 v6 v4 select */
void hw_atl2_rpf_l3_v6_v4_select_set(struct aq_hw_s *aq_hw, u32 val);
/* set L3 v4 tag */
void hw_atl2_rpf_l3_v4_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
/* set L3 v6 tag */
void hw_atl2_rpf_l3_v6_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
/* set L4 cmd */
void hw_atl2_rpf_l4_cmd_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
/* set L4 tag */
void hw_atl2_rpf_l4_tag_set(struct aq_hw_s *aq_hw, u32 val, u32 filter);
/* set tx random TC-queue mapping enable bit */
void hw_atl2_tpb_tx_tc_q_rand_map_en_set(struct aq_hw_s *aq_hw,
const u32 tc_q_rand_map_en);
void hw_atl2_tpb_tps_highest_priority_tc_enable_set(struct aq_hw_s *aq_hw,
u32 tps_highest_prio_tc_en);
void hw_atl2_tpb_tps_highest_priority_tc_set(struct aq_hw_s *aq_hw,
u32 tps_highest_prio_tc);
/* set tx buffer clock gate enable */
void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en);
/* tsg */
void hw_atl2_tsg_clock_en(struct aq_hw_s *aq_hw, u32 clock_sel,
u32 clock_enable);
void hw_atl2_tsg_clock_reset(struct aq_hw_s *aq_hw, u32 clock_sel);
u64 hw_atl2_tsg_clock_read(struct aq_hw_s *aq_hw, u32 clock_sel);
void hw_atl2_tsg_clock_add(struct aq_hw_s *aq_hw, u32 clock_sel,
u64 ns);
void hw_atl2_tsg_clock_sub(struct aq_hw_s *aq_hw, u32 clock_sel,
u64 ns);
void hw_atl2_tsg_clock_increment_set(struct aq_hw_s *aq_hw, u32 clock_sel,
u32 ns, u32 fns);
void hw_atl2_tsg_gpio_isr_to_host_set(struct aq_hw_s *aq_hw, int on,
u32 clock_sel);
void hw_atl2_tsg_gpio_clear_status(struct aq_hw_s *aq_hw);
void hw_atl2_tsg_gpio_input_event_info_get(struct aq_hw_s *aq_hw,
u32 clock_sel,
u32 *event_count,
u64 *event_ts);
/* Set Rx Descriptor0 Timestamp request */
void hw_atl2_rpf_rx_desc_timestamp_req_set(struct aq_hw_s *aq_hw, u32 request,
u32 descriptor);
/* Set Tx Descriptor Timestamp writeback Enable */
void hw_atl2_tdm_tx_desc_timestamp_writeback_en_set(struct aq_hw_s *aq_hw,
u32 enable,
u32 descriptor);
/* Set Tx Descriptor Timestamp enable */
void hw_atl2_tdm_tx_desc_timestamp_en_set(struct aq_hw_s *aq_hw, u32 enable,
u32 descriptor);
void hw_atl2_tps_tx_pkt_shed_data_arb_mode_set(struct aq_hw_s *aq_hw,
const u32 data_arb_mode);
/* set tx packet scheduler tc data max credit */
void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw,
const u32 tc,
const u32 max_credit);
/* set tx packet scheduler tc data weight */
void hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw,
const u32 tc,
const u32 weight);
/* Set Tx Descriptor AVB enable */
void hw_atl2_tdm_tx_desc_avb_en_set(struct aq_hw_s *aq_hw, u32 enable,
u32 descriptor);
void hw_atl2_tsg_ptp_gpio_gen_pulse(struct aq_hw_s *aq_hw, u32 clk_sel,
u64 ts, u32 period, u32 hightime);
void hw_atl2_tdm_tx_data_read_req_limit_set(struct aq_hw_s *aq_hw, u32 limit);
void hw_atl2_tdm_tx_desc_read_req_limit_set(struct aq_hw_s *aq_hw, u32 limit);
u32 hw_atl2_get_hw_version(struct aq_hw_s *aq_hw);
void hw_atl2_init_launchtime(struct aq_hw_s *aq_hw);
/* set action resolver record */
void hw_atl2_rpf_act_rslvr_record_set(struct aq_hw_s *aq_hw, u8 location,
u32 tag, u32 mask, u32 action);
/* set enable action resolver section */
void hw_atl2_rpf_act_rslvr_section_en_set(struct aq_hw_s *aq_hw, u32 sections);
/* get enable action resolver section */
u32 hw_atl2_rpf_act_rslvr_section_en_get(struct aq_hw_s *aq_hw);
/* get data from firmware shared input buffer */
void hw_atl2_mif_shared_buf_get(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len);
/* set data into firmware shared input buffer */
void hw_atl2_mif_shared_buf_write(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len);
/* get data from firmware shared output buffer */
void hw_atl2_mif_shared_buf_read(struct aq_hw_s *aq_hw, int offset, u32 *data,
int len);
/* set host finished write shared buffer indication */
void hw_atl2_mif_host_finished_write_set(struct aq_hw_s *aq_hw, u32 finish);
/* get mcp finished read shared buffer indication */
u32 hw_atl2_mif_mcp_finished_read_get(struct aq_hw_s *aq_hw);
/* get mcp boot register */
u32 hw_atl2_mif_mcp_boot_reg_get(struct aq_hw_s *aq_hw);
/* set mcp boot register */
void hw_atl2_mif_mcp_boot_reg_set(struct aq_hw_s *aq_hw, u32 val);
/* get host interrupt request */
u32 hw_atl2_mif_host_req_int_get(struct aq_hw_s *aq_hw);
/* clear host interrupt request */
void hw_atl2_mif_host_req_int_clr(struct aq_hw_s *aq_hw, u32 val);
/* Set GPIO Special Mode */
void hw_atl2_gpio_special_mode_set(struct aq_hw_s *aq_hw,
u32 gpio_special_mode, u32 pin);
#endif /* HW_ATL2_LLH_H */
@@ -0,0 +1,585 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#ifndef HW_ATL2_LLH_INTERNAL_H
#define HW_ATL2_LLH_INTERNAL_H
/* RX timestamp_req_desc{D} [1:0] Bitfield Definitions
*/
#define HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_ADR(descr) (0x00005B08 + (descr) * 0x20)
#define HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_MSK 0x00030000
#define HW_ATL2_RPF_TIMESTAMP_REQ_DESCD_SHIFT 16
/* RX pif_rpf_redir_2_en_i Bitfield Definitions
* PORT="pif_rpf_redir_2_en_i"
*/
#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_ADR 0x000054C8
#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_MSK 0x00001000
#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_MSKN 0xFFFFEFFF
#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_SHIFT 12
#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_WIDTH 1
#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_DEFAULT 0x0
/* RX pif_rpf_rss_hash_type_i Bitfield Definitions
*/
#define HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_ADR 0x000054C8
#define HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_MSK 0x000001FF
#define HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_MSKN 0xFFFFFE00
#define HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_SHIFT 0
#define HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_WIDTH 9
/* rx rpf_new_rpf_en bitfield definitions
* preprocessor definitions for the bitfield "rpf_new_rpf_en_i".
* port="pif_rpf_new_rpf_en_i
*/
/* register address for bitfield rpf_new_rpf_en */
#define HW_ATL2_RPF_NEW_EN_ADR 0x00005104
/* bitmask for bitfield rpf_new_rpf_en */
#define HW_ATL2_RPF_NEW_EN_MSK 0x00000800
/* inverted bitmask for bitfield rpf_new_rpf_en */
#define HW_ATL2_RPF_NEW_EN_MSKN 0xfffff7ff
/* lower bit position of bitfield rpf_new_rpf_en */
#define HW_ATL2_RPF_NEW_EN_SHIFT 11
/* width of bitfield rpf_new_rpf_en */
#define HW_ATL2_RPF_NEW_EN_WIDTH 1
/* default value of bitfield rpf_new_rpf_en */
#define HW_ATL2_RPF_NEW_EN_DEFAULT 0x0
/* rx l2_uc_req_tag0{f}[5:0] bitfield definitions
* preprocessor definitions for the bitfield "l2_uc_req_tag0{f}[7:0]".
* parameter: filter {f} | stride size 0x8 | range [0, 37]
* port="pif_rpf_l2_uc_req_tag0[5:0]"
*/
/* register address for bitfield l2_uc_req_tag0{f}[2:0] */
#define HW_ATL2_RPFL2UC_TAG_ADR(filter) (0x00005114 + (filter) * 0x8)
/* bitmask for bitfield l2_uc_req_tag0{f}[2:0] */
#define HW_ATL2_RPFL2UC_TAG_MSK 0x0FC00000
/* inverted bitmask for bitfield l2_uc_req_tag0{f}[2:0] */
#define HW_ATL2_RPFL2UC_TAG_MSKN 0xF03FFFFF
/* lower bit position of bitfield l2_uc_req_tag0{f}[2:0] */
#define HW_ATL2_RPFL2UC_TAG_SHIFT 22
/* width of bitfield l2_uc_req_tag0{f}[2:0] */
#define HW_ATL2_RPFL2UC_TAG_WIDTH 6
/* default value of bitfield l2_uc_req_tag0{f}[2:0] */
#define HW_ATL2_RPFL2UC_TAG_DEFAULT 0x0
/* rpf_l2_bc_req_tag[5:0] bitfield definitions
* preprocessor definitions for the bitfield "rpf_l2_bc_req_tag[5:0]".
* port="pifrpf_l2_bc_req_tag_i[5:0]"
*/
/* register address for bitfield rpf_l2_bc_req_tag */
#define HW_ATL2_RPF_L2_BC_TAG_ADR 0x000050F0
/* bitmask for bitfield rpf_l2_bc_req_tag */
#define HW_ATL2_RPF_L2_BC_TAG_MSK 0x0000003F
/* inverted bitmask for bitfield rpf_l2_bc_req_tag */
#define HW_ATL2_RPF_L2_BC_TAG_MSKN 0xffffffc0
/* lower bit position of bitfield rpf_l2_bc_req_tag */
#define HW_ATL2_RPF_L2_BC_TAG_SHIFT 0
/* width of bitfield rpf_l2_bc_req_tag */
#define HW_ATL2_RPF_L2_BC_TAG_WIDTH 6
/* default value of bitfield rpf_l2_bc_req_tag */
#define HW_ATL2_RPF_L2_BC_TAG_DEFAULT 0x0
/* rx rpf_rss_red1_data_[4:0] bitfield definitions
* preprocessor definitions for the bitfield "rpf_rss_red1_data[4:0]".
* port="pif_rpf_rss_red1_data_i[4:0]"
*/
/* register address for bitfield rpf_rss_red1_data[4:0] */
#define HW_ATL2_RPF_RSS_REDIR_ADR(TC, INDEX) (0x00006200 + \
(0x100 * !!((TC) > 3)) + (INDEX) * 4)
/* bitmask for bitfield rpf_rss_red1_data[4:0] */
#define HW_ATL2_RPF_RSS_REDIR_MSK(TC) (0x00000001F << (5 * ((TC) % 4)))
/* lower bit position of bitfield rpf_rss_red1_data[4:0] */
#define HW_ATL2_RPF_RSS_REDIR_SHIFT(TC) (5 * ((TC) % 4))
/* width of bitfield rpf_rss_red1_data[4:0] */
#define HW_ATL2_RPF_RSS_REDIR_WIDTH 5
/* default value of bitfield rpf_rss_red1_data[4:0] */
#define HW_ATL2_RPF_RSS_REDIR_DEFAULT 0x0
/* rx vlan_req_tag0{f}[3:0] bitfield definitions
* preprocessor definitions for the bitfield "vlan_req_tag0{f}[3:0]".
* parameter: filter {f} | stride size 0x4 | range [0, 15]
* port="pif_rpf_vlan_req_tag0[3:0]"
*/
/* register address for bitfield vlan_req_tag0{f}[3:0] */
#define HW_ATL2_RPF_VL_TAG_ADR(filter) (0x00005290 + (filter) * 0x4)
/* bitmask for bitfield vlan_req_tag0{f}[3:0] */
#define HW_ATL2_RPF_VL_TAG_MSK 0x0000F000
/* inverted bitmask for bitfield vlan_req_tag0{f}[3:0] */
#define HW_ATL2_RPF_VL_TAG_MSKN 0xFFFF0FFF
/* lower bit position of bitfield vlan_req_tag0{f}[3:0] */
#define HW_ATL2_RPF_VL_TAG_SHIFT 12
/* width of bitfield vlan_req_tag0{f}[3:0] */
#define HW_ATL2_RPF_VL_TAG_WIDTH 4
/* default value of bitfield vlan_req_tag0{f}[3:0] */
#define HW_ATL2_RPF_VL_TAG_DEFAULT 0x0
/* register address for bitfield etype_req_tag0{f}[2:0] */
#define HW_ATL2_RPF_ET_TAG_ADR(filter) (0x00005340 + (filter) * 0x4)
/* bitmask for bitfield etype_req_tag0{f}[2:0] */
#define HW_ATL2_RPF_ET_TAG_MSK 0x00000007
/* lower bit position of bitfield etype_req_tag0{f}[2:0] */
#define HW_ATL2_RPF_ET_TAG_SHIFT 0
/* Lower bit position of bitfield l3_l4_act{F}[2:0] */
#define HW_ATL2_RPF_L3_L4_ACTF_SHIFT 16
/* Bitmask for bitfield l3_l4_rxq{F}[4:0] */
#define HW_ATL2_RPF_L3_L4_RXQF_MSK 0x00001F00u
/* Lower bit position of bitfield l3_l4_rxq{F}[4:0] */
#define HW_ATL2_RPF_L3_L4_RXQF_SHIFT 8
/* Register address for bitfield rpf_l3_v6_sa{F}_dw{D}[1F:0] */
#define HW_ATL2_RPF_L3_SA_DW_ADR(filter, dword) \
(0x00006400u + (filter) * 0x10 + (dword) * 0x4)
/* Register address for bitfield rpf_l3_v6_da{F}_dw{D}[1F:0] */
#define HW_ATL2_RPF_L3_DA_DW_ADR(filter, dword) \
(0x00006480u + (filter) * 0x10 + (dword) * 0x4)
/* Register address for bitfield rpf_l3_cmd{F}[1F:0] */
#define HW_ATL2_RPF_L3_V4_CMD_ADR(filter) (0x00006500u + (filter) * 0x4)
/* Bitmask for bitfield rpf_l3_cmd{F}[F:0] */
#define HW_ATL2_RPF_L3_V4_CMD_MSK 0x0000FFFFu
/* Lower bit position of bitfield rpf_l3_cmd{F}[1F:0] */
#define HW_ATL2_RPF_L3_V4_CMD_SHIFT 0
/* Register address for bitfield rpf_l3_v6_cmd{F}[1F:0] */
#define HW_ATL2_RPF_L3_V6_CMD_ADR(filter) (0x00006500u + (filter) * 0x4)
/* Bitmask for bitfield rpf_l3_v6_cmd{F}[F:0] */
#define HW_ATL2_RPF_L3_V6_CMD_MSK 0xFF7F0000u
/* Lower bit position of bitfield rpf_l3_v6_cmd{F}[1F:0] */
#define HW_ATL2_RPF_L3_V6_CMD_SHIFT 0
/* Register address for bitfield rpf_l3_v6_cmd{F}[F:0] */
#define HW_ATL2_RPF_L3_V6_V4_SELECT_ADR 0x00006500u
/* Bitmask for bitfield pif_rpf_l3_v6_v4_select*/
#define HW_ATL2_RPF_L3_V6_V4_SELECT_MSK 0x00800000u
/* Lower bit position of bitfield pif_rpf_l3_v6_v4_select */
#define HW_ATL2_RPF_L3_V6_V4_SELECT_SHIFT 23
/* Register address for bitfield rpf_l3_v4_req_tag{F}[2:0] */
#define HW_ATL2_RPF_L3_V4_TAG_ADR(filter) (0x00006500u + (filter) * 0x4)
/* Bitmask for bitfield rpf_l3_v4_req_tag{F}[2:0] */
#define HW_ATL2_RPF_L3_V4_TAG_MSK 0x00000070u
/* Lower bit position of bitfield rpf_l3_v4_req_tag{F}[2:0] */
#define HW_ATL2_RPF_L3_V4_TAG_SHIFT 4
/* Register address for bitfield rpf_l3_v6_req_tag{F}[2:0] */
#define HW_ATL2_RPF_L3_V6_TAG_ADR(filter) (0x00006500u + (filter) * 0x4)
/* Bitmask for bitfield rpf_l3_v6_req_tag{F}[2:0] */
#define HW_ATL2_RPF_L3_V6_TAG_MSK 0x00700000
/* Lower bit position of bitfield rpf_l3_v6_req_tag{F}[2:0] */
#define HW_ATL2_RPF_L3_V6_TAG_SHIFT 20
/* Register address for bitfield rpf_l4_cmd{F}[2:0] */
#define HW_ATL2_RPF_L4_CMD_ADR(filter) (0x00006520u + (filter) * 0x4)
/* Bitmask for bitfield rpf_l4_cmd{F}[2:0] */
#define HW_ATL2_RPF_L4_CMD_MSK 0x00000007u
/* Lower bit position of bitfield rpf_l4_cmd{F}[2:0] */
#define HW_ATL2_RPF_L4_CMD_SHIFT 0
/* Register address for bitfield rpf_l4_tag{F}[2:0] */
#define HW_ATL2_RPF_L4_TAG_ADR(filter) (0x00006520u + (filter) * 0x4)
/* Bitmask for bitfield rpf_l4_tag{F}[2:0] */
#define HW_ATL2_RPF_L4_TAG_MSK 0x00000070u
/* Lower bit position of bitfield rpf_l4_tag{F}[2:0] */
#define HW_ATL2_RPF_L4_TAG_SHIFT 4
/* RX rx_q{Q}_tc_map[2:0] Bitfield Definitions
* Preprocessor definitions for the bitfield "rx_q{Q}_tc_map[2:0]".
* Parameter: Queue {Q} | bit-level stride | range [0, 31]
* PORT="pif_rx_q0_tc_map_i[2:0]"
*/
/* Register address for bitfield rx_q{Q}_tc_map[2:0] */
#define HW_ATL2_RX_Q_TC_MAP_ADR(queue) \
(((queue) < 32) ? 0x00005900 + ((queue) / 8) * 4 : 0)
/* Lower bit position of bitfield rx_q{Q}_tc_map[2:0] */
#define HW_ATL2_RX_Q_TC_MAP_SHIFT(queue) \
(((queue) < 32) ? ((queue) * 4) % 32 : 0)
/* Width of bitfield rx_q{Q}_tc_map[2:0] */
#define HW_ATL2_RX_Q_TC_MAP_WIDTH 3
/* Default value of bitfield rx_q{Q}_tc_map[2:0] */
#define HW_ATL2_RX_Q_TC_MAP_DEFAULT 0x0
/* TX desc{D}_ts_wrb_en Bitfield Definitions
*/
#define HW_ATL2_TDM_DESCD_TS_WRB_EN_ADR(descriptor) \
(0x00007C08 + (descriptor) * 0x40)
#define HW_ATL2_TDM_DESCD_TS_WRB_EN_MSK 0x00040000
#define HW_ATL2_TDM_DESCD_TS_WRB_EN_SHIFT 18
/* TX desc{D}_ts_en Bitfield Definitions
*/
#define HW_ATL2_TDM_DESCD_TS_EN_ADR(descriptor) \
(0x00007C08 + (descriptor) * 0x40)
#define HW_ATL2_TDM_DESCD_TS_EN_MSK 0x00020000
#define HW_ATL2_TDM_DESCD_TS_EN_SHIFT 17
/* TX desc{D}_avb_en Bitfield Definitions
*/
#define HW_ATL2_TDM_DESCD_AVB_EN_ADR(descriptor) \
(0x00007C08 + (descriptor) * 0x40)
#define HW_ATL2_TDM_DESCD_AVB_EN_MSK 0x00010000
#define HW_ATL2_TDM_DESCD_AVB_EN_SHIFT 16
/* tx tx_tc_q_rand_map_en bitfield definitions
* preprocessor definitions for the bitfield "tx_tc_q_rand_map_en".
* port="pif_tpb_tx_tc_q_rand_map_en_i"
*/
/* register address for bitfield tx_tc_q_rand_map_en */
#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_ADR 0x00007900
/* bitmask for bitfield tx_tc_q_rand_map_en */
#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_MSK 0x00000200
/* inverted bitmask for bitfield tx_tc_q_rand_map_en */
#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_MSKN 0xFFFFFDFF
/* lower bit position of bitfield tx_tc_q_rand_map_en */
#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_SHIFT 9
/* width of bitfield tx_tc_q_rand_map_en */
#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_WIDTH 1
/* default value of bitfield tx_tc_q_rand_map_en */
#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_DEFAULT 0x0
/* tx tx_buffer_clk_gate_en bitfield definitions
* preprocessor definitions for the bitfield "tx_buffer_clk_gate_en".
* port="pif_tpb_tx_buffer_clk_gate_en_i"
*/
/* register address for bitfield tx_buffer_clk_gate_en */
#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_ADR 0x00007900
/* bitmask for bitfield tx_buffer_clk_gate_en */
#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_MSK 0x00000020
/* inverted bitmask for bitfield tx_buffer_clk_gate_en */
#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_MSKN 0xffffffdf
/* lower bit position of bitfield tx_buffer_clk_gate_en */
#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_SHIFT 5
/* width of bitfield tx_buffer_clk_gate_en */
#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_WIDTH 1
/* default value of bitfield tx_buffer_clk_gate_en */
#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_DEFAULT 0x0
/* tx tx_q_tc_map{q} bitfield definitions
* preprocessor definitions for the bitfield "tx_q_tc_map{q}".
* parameter: queue {q} | bit-level stride | range [0, 31]
* port="pif_tpb_tx_q_tc_map0_i[2:0]"
*/
/* register address for bitfield tx_q_tc_map{q} */
#define HW_ATL2_TX_Q_TC_MAP_ADR(queue) \
(((queue) < 32) ? 0x0000799C + ((queue) / 4) * 4 : 0)
/* lower bit position of bitfield tx_q_tc_map{q} */
#define HW_ATL2_TX_Q_TC_MAP_SHIFT(queue) \
(((queue) < 32) ? ((queue) * 8) % 32 : 0)
/* width of bitfield tx_q_tc_map{q} */
#define HW_ATL2_TX_Q_TC_MAP_WIDTH 3
/* default value of bitfield tx_q_tc_map{q} */
#define HW_ATL2_TX_Q_TC_MAP_DEFAULT 0x0
/* tx data_tc_arb_mode bitfield definitions
* preprocessor definitions for the bitfield "data_tc_arb_mode".
* port="pif_tps_data_tc_arb_mode_i"
*/
/* register address for bitfield data_tc_arb_mode */
#define HW_ATL2_TPS_DATA_TC_ARB_MODE_ADR 0x00007100
/* bitmask for bitfield data_tc_arb_mode */
#define HW_ATL2_TPS_DATA_TC_ARB_MODE_MSK 0x00000003
/* inverted bitmask for bitfield data_tc_arb_mode */
#define HW_ATL2_TPS_DATA_TC_ARB_MODE_MSKN 0xfffffffc
/* lower bit position of bitfield data_tc_arb_mode */
#define HW_ATL2_TPS_DATA_TC_ARB_MODE_SHIFT 0
/* width of bitfield data_tc_arb_mode */
#define HW_ATL2_TPS_DATA_TC_ARB_MODE_WIDTH 2
/* default value of bitfield data_tc_arb_mode */
#define HW_ATL2_TPS_DATA_TC_ARB_MODE_DEFAULT 0x0
/* tx data_tc{t}_credit_max[f:0] bitfield definitions
* preprocessor definitions for the bitfield "data_tc{t}_credit_max[f:0]".
* parameter: tc {t} | stride size 0x4 | range [0, 7]
* port="pif_tps_data_tc0_credit_max_i[15:0]"
*/
/* register address for bitfield data_tc{t}_credit_max[f:0] */
#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_ADR(tc) (0x00007110 + (tc) * 0x4)
/* bitmask for bitfield data_tc{t}_credit_max[f:0] */
#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSK 0xffff0000
/* inverted bitmask for bitfield data_tc{t}_credit_max[f:0] */
#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSKN 0x0000ffff
/* lower bit position of bitfield data_tc{t}_credit_max[f:0] */
#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_SHIFT 16
/* width of bitfield data_tc{t}_credit_max[f:0] */
#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_WIDTH 16
/* default value of bitfield data_tc{t}_credit_max[f:0] */
#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_DEFAULT 0x0
/* register address for bitfield pif_tpb_highest_prio_tc_en */
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_ADR 0x00007180
/* bitmask for bitfield pif_tpb_highest_prio_tc_en */
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_MSK 0x00000100
/* lower bit position of bitfield pif_tpb_highest_prio_tc_en */
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_EN_SHIFT 8
/* register address for bitfield pif_tpb_highest_prio_tc */
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_ADR 0x00007180
/* bitmask for bitfield pif_tpb_highest_prio_tc */
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_MSK 0x00000007
/* lower bit position of bitfield pif_tpb_highest_prio_tc */
#define HW_ATL2_TPB_HIGHEST_PRIO_TC_SHIFT 0
/* tx data_tc{t}_weight[e:0] bitfield definitions
* preprocessor definitions for the bitfield "data_tc{t}_weight[e:0]".
* parameter: tc {t} | stride size 0x4 | range [0, 7]
* port="pif_tps_data_tc0_weight_i[14:0]"
*/
/* register address for bitfield data_tc{t}_weight[e:0] */
#define HW_ATL2_TPS_DATA_TCTWEIGHT_ADR(tc) (0x00007110 + (tc) * 0x4)
/* bitmask for bitfield data_tc{t}_weight[e:0] */
#define HW_ATL2_TPS_DATA_TCTWEIGHT_MSK 0x00007fff
/* inverted bitmask for bitfield data_tc{t}_weight[e:0] */
#define HW_ATL2_TPS_DATA_TCTWEIGHT_MSKN 0xffff8000
/* lower bit position of bitfield data_tc{t}_weight[e:0] */
#define HW_ATL2_TPS_DATA_TCTWEIGHT_SHIFT 0
/* width of bitfield data_tc{t}_weight[e:0] */
#define HW_ATL2_TPS_DATA_TCTWEIGHT_WIDTH 15
/* default value of bitfield data_tc{t}_weight[e:0] */
#define HW_ATL2_TPS_DATA_TCTWEIGHT_DEFAULT 0x0
/* tx interrupt moderation control register definitions
* Preprocessor definitions for TX Interrupt Moderation Control Register
* Base Address: 0x00007c28
* Parameter: queue {Q} | stride size 0x4 | range [0, 31]
*/
#define HW_ATL2_TX_INTR_MODERATION_CTL_ADR(queue) (0x00007c28u + (queue) * 0x40)
/* TX tx_data_rd_req_limit[7:0] Bitfield Definitions
*/
#define HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_ADR 0x00007B04
#define HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_MSK 0x0000FF00
#define HW_ATL2_TDM_TX_DATA_RD_REQ_LIMIT_SHIFT 8
/* TX tx_desc_rd_req_limit[4:0] Bitfield Definitions
*/
#define HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_ADR 0x00007B04
#define HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_MSK 0x0000001F
#define HW_ATL2_TDM_TX_DESC_RD_REQ_LIMIT_SHIFT 0
/* register address for bitfield uP Force Interrupt */
#define HW_ATL2_GLB_CONTROL_2_ADR 0x00000404
#define HW_ATL2_MIF_INTERRUPT_2_TO_ITR_MSK 0x00000100
/* lower bit position of bitfield MIF Interrupt to ITR */
#define HW_ATL2_MIF_INTERRUPT_TO_ITR_SHIFT 6
#define HW_ATL2_EN_INTERRUPT_MIF2_TO_ITR_MSK 0x00001000
/* lower bit position of bitfield Enable MIF Interrupt to ITR */
#define HW_ATL2_EN_INTERRUPT_TO_ITR_SHIFT 0xA
#define HW_ATL2_GLOBAL_INTERNAL_ALARMS_1_ADR 0x00000924
#define HW_ATL2_GLOBAL_HIGH_PRIO_INTERRUPT_1_MASK_ADR 0x00000964
/* bitmask for bitfield TSG PTM GPIO interrupt */
#define HW_ATL2_TSG_TSG1_GPIO_INTERRUPT_MSK 0x00000200
/* lower bit position of bitfield TSG PTM GPIO interrupt */
#define HW_ATL2_TSG_TSG1_GPIO_INTERRUPT_SHIFT 9
/* bitmask for bitfield TSG0 GPIO interrupt */
#define HW_ATL2_TSG_TSG0_GPIO_INTERRUPT_MSK 0x00000020
/* lower bit position of bitfield TSG0 GPIO interrupt */
#define HW_ATL2_TSG_TSG0_GPIO_INTERRUPT_SHIFT 5
/* TSG registers */
#define HW_ATL2_TSG_REG_ADR(clk, reg_name) \
((clk) == 0 ? HW_ATL2_CLK0_##reg_name##_ADR :\
HW_ATL2_CLK1_##reg_name##_ADR)
#define HW_ATL2_CLK0_CLOCK_CFG_ADR 0x00000CA0u
#define HW_ATL2_CLK1_CLOCK_CFG_ADR 0x00000D50u
#define HW_ATL2_TSG_SYNC_RESET_MSK 0x00000001
#define HW_ATL2_TSG_SYNC_RESET_SHIFT 0x00000000
#define HW_ATL2_TSG_CLOCK_EN_MSK 0x00000002
#define HW_ATL2_TSG_CLOCK_EN_SHIFT 0x00000001
#define HW_ATL2_CLK0_CLOCK_MODIF_CTRL_ADR 0x00000CA4u
#define HW_ATL2_CLK1_CLOCK_MODIF_CTRL_ADR 0x00000D54u
#define HW_ATL2_TSG_SUBTRACT_COUNTER_MSK 0x00000002
#define HW_ATL2_TSG_ADD_COUNTER_MSK 0x00000004
#define HW_ATL2_TSG_LOAD_INC_CFG_MSK 0x00000008
#define HW_ATL2_CLK0_CLOCK_MODIF_VAL_LSW_ADR 0x00000CA8u
#define HW_ATL2_CLK1_CLOCK_MODIF_VAL_LSW_ADR 0x00000D58u
#define HW_ATL2_CLK0_CLOCK_INC_CFG_ADR 0x00000CB0u
#define HW_ATL2_CLK1_CLOCK_INC_CFG_ADR 0x00000D60u
#define HW_ATL2_CLK0_READ_CUR_NS_LSW_ADR 0x00000CB8u
#define HW_ATL2_CLK1_READ_CUR_NS_LSW_ADR 0x00000D68u
#define HW_ATL2_CLK0_GPIO_CFG_ADR 0x00000CC4u
#define HW_ATL2_CLK1_GPIO_CFG_ADR 0x00000D74u
#define HW_ATL2_TSG_GPIO_IN_MONITOR_EN_SHIFT 0x00000000
#define HW_ATL2_TSG_GPIO_IN_MONITOR_EN_MSK 0x00000001
#define HW_ATL2_TSG_GPIO_IN_MODE_SHIFT 0x00000001
#define HW_ATL2_TSG_GPIO_IN_MODE_MSK 0x00000006
#define HW_ATL2_TSG_GPIO_IN_MODE_POSEDGE 0x00000000
#define HW_ATL2_CLK0_EXT_CLK_COUNT_ADR 0x00000CCCu
#define HW_ATL2_CLK1_EXT_CLK_COUNT_ADR 0x00000D7Cu
#define HW_ATL2_CLK0_GPIO_EVENT_TS_LSW_ADR 0x00000CD0u
#define HW_ATL2_CLK1_GPIO_EVENT_TS_LSW_ADR 0x00000D80u
#define HW_ATL2_CLK0_GPIO_EVENT_GEN_TS_LSW_ADR 0x00000CE0u
#define HW_ATL2_CLK1_GPIO_EVENT_GEN_TS_LSW_ADR 0x00000D90u
#define HW_ATL2_CLK0_GPIO_EVENT_GEN_CFG_ADR 0x00000CE8u
#define HW_ATL2_CLK1_GPIO_EVENT_GEN_CFG_ADR 0x00000D98u
#define HW_ATL2_TSG_GPIO_OUTPUT_EN_SHIFT 0x00000000
#define HW_ATL2_TSG_GPIO_OUTPUT_EN_MSK 0x00000001
#define HW_ATL2_TSG_GPIO_EVENT_MODE_SHIFT 0x00000001
#define HW_ATL2_TSG_GPIO_EVENT_MODE_MSK 0x00000006
#define HW_ATL2_TSG_GPIO_EVENT_MODE_SET_ON_TIME 0x00000003
#define HW_ATL2_TSG_GPIO_GEN_OUTPUT_EN_MSK 0x00000008
#define HW_ATL2_CLK0_GPIO_EVENT_HIGH_TIME_LSW_ADR 0x00000CF0u
#define HW_ATL2_CLK1_GPIO_EVENT_HIGH_TIME_LSW_ADR 0x00000DA0u
#define HW_ATL2_CLK0_GPIO_EVENT_LOW_TIME_LSW_ADR 0x00000CF8u
#define HW_ATL2_CLK1_GPIO_EVENT_LOW_TIME_LSW_ADR 0x00000DA8u
/* PCIE Extended tag enable Bitfield Definitions
*/
#define HW_ATL2_PHI_EXT_TAG_EN_ADR 0x00001000
#define HW_ATL2_PHI_EXT_TAG_EN_MSK 0x00000020
#define HW_ATL2_PHI_EXT_TAG_EN_SHIFT 5
/* Launch time control register */
#define HW_ATL2_LT_CTRL_ADR 0x00007a1c
#define HW_ATL2_LT_CTRL_AVB_LEN_CMP_TRSHLD_MSK 0xFFFF0000
#define HW_ATL2_LT_CTRL_AVB_LEN_CMP_TRSHLD_SHIFT 16
#define HW_ATL2_LT_CTRL_CLK_RATIO_MSK 0x0000FF00
#define HW_ATL2_LT_CTRL_CLK_RATIO_SHIFT 8
#define HW_ATL2_LT_CTRL_CLK_RATIO_QUATER_SPEED 4
#define HW_ATL2_LT_CTRL_CLK_RATIO_HALF_SPEED 2
#define HW_ATL2_LT_CTRL_CLK_RATIO_FULL_SPEED 1
#define HW_ATL2_LT_CTRL_25G_MODE_SUPPORT_MSK 0x00000008
#define HW_ATL2_LT_CTRL_25G_MODE_SUPPORT_SHIFT 3
#define HW_ATL2_LT_CTRL_LINK_SPEED_MSK 0x00000007
#define HW_ATL2_LT_CTRL_LINK_SPEED_SHIFT 0
/* FPGA VER register */
#define HW_ATL2_FPGA_VER_ADR 0x000000f4
#define HW_ATL2_FPGA_VER_U32(mj, mi, bl, rv) \
((((mj) & 0xff) << 24) | \
(((mi) & 0xff) << 16) | \
(((bl) & 0xff) << 8) | \
(((rv) & 0xff) << 0))
/* ahb_mem_addr{f}[31:0] Bitfield Definitions
* Preprocessor definitions for the bitfield "ahb_mem_addr{f}[31:0]".
* Parameter: filter {f} | stride size 0x10 | range [0, 127]
* PORT="ahb_mem_addr{f}[31:0]"
*/
/* Register address for bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_ADR(filter) \
(0x00014000u + (filter) * 0x10)
/* Bitmask for bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_MSK 0xFFFFFFFFu
/* Inverted bitmask for bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_MSKN 0x00000000u
/* Lower bit position of bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_SHIFT 0
/* Width of bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_WIDTH 31
/* Default value of bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_DEFAULT 0x0
/* Register address for bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_ADR(filter) \
(0x00014004u + (filter) * 0x10)
/* Bitmask for bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_MSK 0xFFFFFFFFu
/* Inverted bitmask for bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_MSKN 0x00000000u
/* Lower bit position of bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_SHIFT 0
/* Width of bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_WIDTH 31
/* Default value of bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_DEFAULT 0x0
/* Register address for bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_ACTN_ADR(filter) \
(0x00014008u + (filter) * 0x10)
/* Bitmask for bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_ACTN_MSK 0x000007FFu
/* Inverted bitmask for bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_ACTN_MSKN 0xFFFFF800u
/* Lower bit position of bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_ACTN_SHIFT 0
/* Width of bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_ACTN_WIDTH 10
/* Default value of bitfield ahb_mem_addr{f}[31:0] */
#define HW_ATL2_RPF_ACT_RSLVR_ACTN_DEFAULT 0x0
/* rpf_rec_tab_en[15:0] Bitfield Definitions
* Preprocessor definitions for the bitfield "rpf_rec_tab_en[15:0]".
* PORT="pif_rpf_rec_tab_en[15:0]"
*/
/* Register address for bitfield rpf_rec_tab_en[15:0] */
#define HW_ATL2_RPF_REC_TAB_EN_ADR 0x00006ff0u
/* Bitmask for bitfield rpf_rec_tab_en[15:0] */
#define HW_ATL2_RPF_REC_TAB_EN_MSK 0x0000FFFFu
/* Inverted bitmask for bitfield rpf_rec_tab_en[15:0] */
#define HW_ATL2_RPF_REC_TAB_EN_MSKN 0xFFFF0000u
/* Lower bit position of bitfield rpf_rec_tab_en[15:0] */
#define HW_ATL2_RPF_REC_TAB_EN_SHIFT 0
/* Width of bitfield rpf_rec_tab_en[15:0] */
#define HW_ATL2_RPF_REC_TAB_EN_WIDTH 16
/* Default value of bitfield rpf_rec_tab_en[15:0] */
#define HW_ATL2_RPF_REC_TAB_EN_DEFAULT 0x0
/* Register address for firmware shared input buffer */
#define HW_ATL2_MIF_SHARED_BUFFER_IN_ADR(dword) (0x00012000U + (dword) * 0x4U)
/* Register address for firmware shared output buffer */
#define HW_ATL2_MIF_SHARED_BUFFER_OUT_ADR(dword) (0x00013000U + (dword) * 0x4U)
/* pif_host_finished_buf_wr_i Bitfield Definitions
* Preprocessor definitions for the bitfield "pif_host_finished_buf_wr_i".
* PORT="pif_host_finished_buf_wr_i"
*/
/* Register address for bitfield rpif_host_finished_buf_wr_i */
#define HW_ATL2_MIF_HOST_FINISHED_WRITE_ADR 0x00000e00u
/* Bitmask for bitfield pif_host_finished_buf_wr_i */
#define HW_ATL2_MIF_HOST_FINISHED_WRITE_MSK 0x00000001u
/* Inverted bitmask for bitfield pif_host_finished_buf_wr_i */
#define HW_ATL2_MIF_HOST_FINISHED_WRITE_MSKN 0xFFFFFFFEu
/* Lower bit position of bitfield pif_host_finished_buf_wr_i */
#define HW_ATL2_MIF_HOST_FINISHED_WRITE_SHIFT 0
/* Width of bitfield pif_host_finished_buf_wr_i */
#define HW_ATL2_MIF_HOST_FINISHED_WRITE_WIDTH 1
/* Default value of bitfield pif_host_finished_buf_wr_i */
#define HW_ATL2_MIF_HOST_FINISHED_WRITE_DEFAULT 0x0
/* pif_mcp_finished_buf_rd_i Bitfield Definitions
* Preprocessor definitions for the bitfield "pif_mcp_finished_buf_rd_i".
* PORT="pif_mcp_finished_buf_rd_i"
*/
/* Register address for bitfield pif_mcp_finished_buf_rd_i */
#define HW_ATL2_MIF_MCP_FINISHED_READ_ADR 0x00000e04u
/* Bitmask for bitfield pif_mcp_finished_buf_rd_i */
#define HW_ATL2_MIF_MCP_FINISHED_READ_MSK 0x00000001u
/* Inverted bitmask for bitfield pif_mcp_finished_buf_rd_i */
#define HW_ATL2_MIF_MCP_FINISHED_READ_MSKN 0xFFFFFFFEu
/* Lower bit position of bitfield pif_mcp_finished_buf_rd_i */
#define HW_ATL2_MIF_MCP_FINISHED_READ_SHIFT 0
/* Width of bitfield pif_mcp_finished_buf_rd_i */
#define HW_ATL2_MIF_MCP_FINISHED_READ_WIDTH 1
/* Default value of bitfield pif_mcp_finished_buf_rd_i */
#define HW_ATL2_MIF_MCP_FINISHED_READ_DEFAULT 0x0
/* Register address for bitfield pif_mcp_boot_reg */
#define HW_ATL2_MIF_BOOT_REG_ADR 0x00003040u
#define HW_ATL2_MCP_HOST_REQ_INT_READY BIT(0)
#define HW_ATL2_MCP_HOST_REQ_INT_ADR 0x00000F00u
#define HW_ATL2_MCP_HOST_REQ_INT_SET_ADR 0x00000F04u
#define HW_ATL2_MCP_HOST_REQ_INT_CLR_ADR 0x00000F08u
/* Register address for bitfield PTP EXT GPIO TS SEL */
#define HW_ATL2_TSG0_EXT_GPIO_TS_INPUT_SEL_ADR 0x00003664
/* Bitmask for bitfield PTP EXT GPIO TS SEL */
#define HW_ATL2_TSG0_EXT_GPIO_TS_INPUT_SEL_MSK 0x00001F00
/* Lower bit position of bitfield PTP EXT GPIO TS SEL */
#define HW_ATL2_TSG0_EXT_GPIO_TS_INPUT_SEL_SHIFT 8
/* Register address for bitfield TSG EXT GPIO TS SEL */
#define HW_ATL2_TSG1_EXT_GPIO_TS_INPUT_SEL_ADR 0x00003660
/* Bitmask for bitfield TSG EXT GPIO TS SEL */
#define HW_ATL2_TSG1_EXT_GPIO_TS_INPUT_SEL_MSK 0x00001F00
/* Lower bit position of bitfield TSG EXT GPIO TS SEL */
#define HW_ATL2_TSG1_EXT_GPIO_TS_INPUT_SEL_SHIFT 8
/* Register address for bitfield GPIO{P} Special Mode */
#define HW_ATL2_GPIO_PIN_SPEC_MODE_ADR(pin) (0x00003698 + (pin) * 0x4)
/* Bitmask for bitfield GPIO{P} Special Mode */
#define HW_ATL2_GPIO_PIN_SPEC_MODE_MSK 0x0000000C
/* Lower bit position of bitfield GPIO{P} Special Mode */
#define HW_ATL2_GPIO_PIN_SPEC_MODE_SHIFT 2
#define HW_ATL2_GPIO_PIN_SPEC_MODE_TSG1_EVENT_OUTPUT 0
#define HW_ATL2_GPIO_PIN_SPEC_MODE_TSG0_EVENT_OUTPUT 2
#define HW_ATL2_GPIO_PIN_SPEC_MODE_GPIO 3
#endif /* HW_ATL2_LLH_INTERNAL_H */
@@ -0,0 +1,164 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#include <linux/iopoll.h>
#include "aq_hw_utils.h"
#include "hw_atl/hw_atl_utils.h"
#include "hw_atl2_utils.h"
#include "hw_atl2_llh.h"
#include "hw_atl2_llh_internal.h"
#define HW_ATL2_FW_VER_1X 0x01000000U
#define AQ_A2_BOOT_STARTED BIT(0x18)
#define AQ_A2_CRASH_INIT BIT(0x1B)
#define AQ_A2_BOOT_CODE_FAILED BIT(0x1C)
#define AQ_A2_FW_INIT_FAILED BIT(0x1D)
#define AQ_A2_FW_INIT_COMP_SUCCESS BIT(0x1F)
#define AQ_A2_FW_BOOT_FAILED_MASK (AQ_A2_CRASH_INIT | \
AQ_A2_BOOT_CODE_FAILED | \
AQ_A2_FW_INIT_FAILED)
#define AQ_A2_FW_BOOT_COMPLETE_MASK (AQ_A2_FW_BOOT_FAILED_MASK | \
AQ_A2_FW_INIT_COMP_SUCCESS)
#define AQ_A2_FW_BOOT_REQ_REBOOT BIT(0x0)
#define AQ_A2_FW_BOOT_REQ_HOST_BOOT BIT(0x8)
#define AQ_A2_FW_BOOT_REQ_MAC_FAST_BOOT BIT(0xA)
#define AQ_A2_FW_BOOT_REQ_PHY_FAST_BOOT BIT(0xB)
int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
{
int err;
self->fw_ver_actual = hw_atl2_utils_get_fw_version(self);
if (hw_atl_utils_ver_match(HW_ATL2_FW_VER_1X, self->fw_ver_actual)) {
*fw_ops = &aq_a2_fw_ops;
} else {
aq_pr_err("Bad FW version detected: %x, but continue\n",
self->fw_ver_actual);
*fw_ops = &aq_a2_fw_ops;
}
aq_pr_trace("Detect ATL2FW %x\n", self->fw_ver_actual);
self->aq_fw_ops = *fw_ops;
err = self->aq_fw_ops->init(self);
self->chip_features |= ATL_HW_CHIP_ANTIGUA;
return err;
}
static bool hw_atl2_mcp_boot_complete(struct aq_hw_s *self)
{
u32 rbl_status;
rbl_status = hw_atl2_mif_mcp_boot_reg_get(self);
if (rbl_status & AQ_A2_FW_BOOT_COMPLETE_MASK)
return true;
/* Host boot requested */
if (hw_atl2_mif_host_req_int_get(self) & HW_ATL2_MCP_HOST_REQ_INT_READY)
return true;
return false;
}
int hw_atl2_utils_soft_reset(struct aq_hw_s *self)
{
bool rbl_complete = false;
u32 rbl_status = 0;
u32 rbl_request;
int err;
hw_atl2_mif_host_req_int_clr(self, 0x01);
rbl_request = AQ_A2_FW_BOOT_REQ_REBOOT;
#ifdef AQ_CFG_FAST_START
rbl_request |= AQ_A2_FW_BOOT_REQ_MAC_FAST_BOOT;
#endif
hw_atl2_mif_mcp_boot_reg_set(self, rbl_request);
/* Wait for RBL boot */
err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_boot_reg_get, self,
rbl_status,
((rbl_status & AQ_A2_BOOT_STARTED) &&
(rbl_status != 0xFFFFFFFFu)),
10, 200000);
if (err) {
aq_pr_err("Boot code hanged");
goto err_exit;
}
err = readx_poll_timeout_atomic(hw_atl2_mcp_boot_complete, self,
rbl_complete,
rbl_complete,
10, 2000000);
if (err) {
aq_pr_err("FW Restart timed out");
goto err_exit;
}
rbl_status = hw_atl2_mif_mcp_boot_reg_get(self);
if (rbl_status & AQ_A2_FW_BOOT_FAILED_MASK) {
err = -EIO;
aq_pr_err("FW Restart failed");
goto err_exit;
}
if (hw_atl2_mif_host_req_int_get(self) &
HW_ATL2_MCP_HOST_REQ_INT_READY) {
err = -EIO;
aq_pr_err("No FW detected. Dynamic FW load not implemented");
goto err_exit;
}
if (self->aq_fw_ops) {
err = self->aq_fw_ops->init(self);
if (err) {
aq_pr_err("FW Init failed");
goto err_exit;
}
}
err_exit:
return err;
}
static const u32 hw_atl2_utils_hw_mac_regs[] = {
0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
};
int hw_atl2_utils_hw_get_regs(struct aq_hw_s *self,
const struct aq_hw_caps_s *aq_hw_caps,
u32 *regs_buff)
{
unsigned int i;
for (i = 0; i < min_t(u32, aq_hw_caps->mac_regs_count,
ARRAY_SIZE(hw_atl2_utils_hw_mac_regs)); i++)
regs_buff[i] = aq_hw_read_reg(self,
hw_atl2_utils_hw_mac_regs[i]);
return 0;
}
@@ -0,0 +1,649 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#ifndef HW_ATL2_UTILS_H
#define HW_ATL2_UTILS_H
#include "aq_hw.h"
/* Hardware tx launch time descriptor */
struct hw_atl2_txts_s {
__le64 ts;
__le32 ctrl;
u32 reserved;
};
#define HW_ATL2_TXTS_DD BIT(3)
#define HW_ATL2_TXTS_TS_VALID BIT(20)
/* F W A P I */
struct link_options_s {
u8 link_up:1;
u8 link_renegotiate:1;
u8 minimal_link_speed:1;
u8 internal_loopback:1;
u8 external_loopback:1;
u8 rate_10M_hd:1;
u8 rate_100M_hd:1;
u8 rate_1G_hd:1;
u8 rate_10M:1;
u8 rate_100M:1;
u8 rate_1G:1;
u8 rate_2P5G:1;
u8 rate_N2P5G:1;
u8 rate_5G:1;
u8 rate_N5G:1;
u8 rate_10G:1;
u8 eee_100M:1;
u8 eee_1G:1;
u8 eee_2P5G:1;
u8 eee_5G:1;
u8 eee_10G:1;
u8 rsvd3:3;
u8 pause_rx:1;
u8 pause_tx:1;
u8 rsvd4:1;
u8 downshift:1;
u8 downshift_retry:4;
};
struct link_control_s {
u8 mode:4;
u8 disable_crc_corruption:1;
u8 discard_short_frames:1;
u8 flow_control_mode:1;
u8 disable_length_check:1;
u8 discard_errored_frames:1;
u8 control_frame_enable:1;
u8 enable_tx_padding:1;
u8 enable_crc_forwarding:1;
u8 enable_frame_padding_removal_rx: 1;
u8 promiscuous_mode: 1;
u8 rsvd:2;
u16 rsvd2;
};
struct thermal_shutdown_s {
u8 enable:1;
u8 warning_enable:1;
u8 rsvd:6;
u8 shutdown_temperature;
u8 cold_temperature;
u8 warning_temperature;
};
struct mac_address_s {
u8 mac_address[6];
};
struct mac_address_aligned_s {
struct mac_address_s aligned;
u16 rsvd;
};
struct sleep_proxy_s {
struct wake_on_lan_s {
u8 wake_on_magic_packet:1;
u8 wake_on_pattern:1;
u8 wake_on_link_up:1;
u8 wake_on_link_down:1;
u8 wake_on_ping:1;
u8 wake_on_timer:1;
u8 rsvd:2;
u8 rsvd2;
u16 rsvd3;
u32 link_up_timeout;
u32 link_down_timeout;
u32 timer;
} wake_on_lan;
struct {
u32 mask[4];
u32 crc32;
} wake_up_pattern[8];
struct __packed {
u8 arp_responder:1;
u8 echo_responder:1;
u8 igmp_client:1;
u8 echo_truncate:1;
u8 address_guard:1;
u8 ignore_fragmented:1;
u8 rsvd:2;
u16 echo_max_len;
u8 rsvd2;
} ipv4_offload;
u32 ipv4_offload_addr[8];
u32 reserved[8];
struct __packed {
u8 ns_responder:1;
u8 echo_responder:1;
u8 mld_client:1;
u8 echo_truncate:1;
u8 address_guard:1;
u8 rsvd:3;
u16 echo_max_len;
u8 rsvd2;
} ipv6_offload;
u32 ipv6_offload_addr[16][4];
struct {
u16 port[16];
} tcp_port_offload;
struct {
u16 port[16];
} udp_port_offload;
struct {
u32 retry_count;
u32 retry_interval;
} ka4_offload;
struct {
u32 timeout;
u16 local_port;
u16 remote_port;
u8 remote_mac_addr[6];
u16 rsvd;
u32 rsvd2;
u32 rsvd3;
u16 rsvd4;
u16 win_size;
u32 seq_num;
u32 ack_num;
u32 local_ip;
u32 remote_ip;
} ka4_connection[16];
struct {
u32 retry_count;
u32 retry_interval;
} ka6_offload;
struct {
u32 timeout;
u16 local_port;
u16 remote_port;
u8 remote_mac_addr[6];
u16 rsvd;
u32 rsvd2;
u32 rsvd3;
u16 rsvd4;
u16 win_size;
u32 seq_num;
u32 ack_num;
u32 local_ip[4];
u32 remote_ip[4];
} ka6_connection[16];
struct {
u32 rr_count;
u32 rr_buf_len;
u32 idx_offset;
u32 rr__offset;
} mdns_offload;
};
struct pause_quanta_s {
u16 quanta_10M;
u16 threshold_10M;
u16 quanta_100M;
u16 threshold_100M;
u16 quanta_1G;
u16 threshold_1G;
u16 quanta_2P5G;
u16 threshold_2P5G;
u16 quanta_5G;
u16 threshold_5G;
u16 quanta_10G;
u16 threshold_10G;
};
struct data_buffer_status_s {
u32 data_offset;
u32 data_length;
};
struct device_caps_s {
u8 finite_flashless:1;
u8 cable_diag:1;
u8 ncsi:1;
u8 avb:1;
u8 rsvd:4;
u8 rsvd2;
u16 rsvd3;
u32 rsvd4;
};
struct version_s {
struct bundle_version_t {
u8 major;
u8 minor;
u16 build;
} bundle;
struct mac_version_t {
u8 major;
u8 minor;
u16 build;
} mac;
struct phy_version_t {
u8 major;
u8 minor;
u16 build;
} phy;
u32 drv_iface_ver:4;
u32 rsvd:28;
};
struct link_status_s {
u8 link_state:4;
u8 link_rate:4;
u8 pause_tx:1;
u8 pause_rx:1;
u8 eee:1;
u8 duplex:1;
u8 rsvd:4;
u16 rsvd2;
};
struct wol_status_s {
u8 wake_count;
u8 wake_reason;
u16 wake_up_packet_length :12;
u16 wake_up_pattern_number :3;
u16 rsvd:1;
u32 wake_up_packet[379];
};
struct mac_health_monitor_s {
u8 mac_ready:1;
u8 mac_fault:1;
u8 mac_flashless_finished:1;
u8 rsvd:5;
u8 mac_temperature;
u16 mac_heart_beat;
u16 mac_fault_code;
u16 rsvd2;
};
struct phy_health_monitor_s {
u8 phy_ready:1;
u8 phy_fault:1;
u8 phy_hot_warning:1;
u8 rsvd:5;
u8 phy_temperature;
u16 phy_heart_beat;
u16 phy_fault_code;
u16 rsvd2;
};
struct device_link_caps_s {
u8 rsvd:3;
u8 internal_loopback:1;
u8 external_loopback:1;
u8 rate_10M_hd:1;
u8 rate_100M_hd:1;
u8 rate_1G_hd:1;
u8 rate_10M:1;
u8 rate_100M:1;
u8 rate_1G:1;
u8 rate_2P5G:1;
u8 rate_N2P5G:1;
u8 rate_5G:1;
u8 rate_N5G:1;
u8 rate_10G:1;
u8 rsvd3:1;
u8 eee_100M:1;
u8 eee_1G:1;
u8 eee_2P5G:1;
u8 rsvd4:1;
u8 eee_5G:1;
u8 rsvd5:1;
u8 eee_10G:1;
u8 pause_rx:1;
u8 pause_tx:1;
u8 pfc:1;
u8 downshift:1;
u8 downshift_retry:4;
};
struct sleep_proxy_caps_s {
u8 ipv4_offload:1;
u8 ipv6_offload:1;
u8 tcp_port_offload:1;
u8 udp_port_offload:1;
u8 ka4_offload:1;
u8 ka6_offload:1;
u8 mdns_offload:1;
u8 wake_on_ping:1;
u8 wake_on_magic_packet:1;
u8 wake_on_pattern:1;
u8 wake_on_timer:1;
u8 wake_on_link:1;
u8 wake_patterns_count:4;
u8 ipv4_count;
u8 ipv6_count;
u8 tcp_port_offload_count;
u8 udp_port_offload_count;
u8 tcp4_ka_count;
u8 tcp6_ka_count;
u8 igmp_offload:1;
u8 mld_offload:1;
u8 rsvd:6;
u8 rsvd2;
u16 rsvd3;
};
struct lkp_link_caps_s {
u8 rsvd:5;
u8 rate_10M_hd:1;
u8 rate_100M_hd:1;
u8 rate_1G_hd:1;
u8 rate_10M:1;
u8 rate_100M:1;
u8 rate_1G:1;
u8 rate_2P5G:1;
u8 rate_N2P5G:1;
u8 rate_5G:1;
u8 rate_N5G:1;
u8 rate_10G:1;
u8 rsvd2:1;
u8 eee_100M:1;
u8 eee_1G:1;
u8 eee_2P5G:1;
u8 rsvd3:1;
u8 eee_5G:1;
u8 rsvd4:1;
u8 eee_10G:1;
u8 pause_rx:1;
u8 pause_tx:1;
u8 rsvd5:6;
};
struct core_dump_s {
u32 reg0;
u32 reg1;
u32 reg2;
u32 hi;
u32 lo;
u32 regs[32];
};
struct trace_s {
u32 sync_counter;
u32 mem_buffer[0x1ff];
};
struct cable_diag_control_s {
u8 toggle :1;
u8 rsvd:7;
u8 wait_timeout_sec;
u16 rsvd2;
};
struct cable_diag_lane_data_s {
u8 result_code;
u8 dist;
u8 far_dist;
u8 rsvd;
};
struct cable_diag_status_s {
struct cable_diag_lane_data_s lane_data[4];
u8 transact_id;
u8 status:4;
u8 rsvd:4;
u16 rsvd2;
};
struct statistics_a0_s {
struct {
u32 link_up;
u32 link_down;
} link;
struct {
u64 tx_unicast_octets;
u64 tx_multicast_octets;
u64 tx_broadcast_octets;
u64 rx_unicast_octets;
u64 rx_multicast_octets;
u64 rx_broadcast_octets;
u32 tx_unicast_frames;
u32 tx_multicast_frames;
u32 tx_broadcast_frames;
u32 tx_errors;
u32 rx_unicast_frames;
u32 rx_multicast_frames;
u32 rx_broadcast_frames;
u32 rx_dropped_frames;
u32 rx_error_frames;
u32 tx_good_frames;
u32 rx_good_frames;
u32 reserve_fw_gap;
} msm;
u32 main_loop_cycles;
u32 reserve_fw_gap;
};
struct __packed statistics_b0_s {
u64 rx_good_octets;
u64 rx_pause_frames;
u64 rx_good_frames;
u64 rx_errors;
u64 rx_unicast_frames;
u64 rx_multicast_frames;
u64 rx_broadcast_frames;
u64 tx_good_octets;
u64 tx_pause_frames;
u64 tx_good_frames;
u64 tx_errors;
u64 tx_unicast_frames;
u64 tx_multicast_frames;
u64 tx_broadcast_frames;
u32 main_loop_cycles;
};
struct __packed statistics_s {
union __packed {
struct statistics_a0_s a0;
struct statistics_b0_s b0;
};
};
struct filter_caps_s {
u8 l2_filters_base_index:6;
u8 flexible_filter_mask:2;
u8 l2_filter_count;
u8 ethertype_filter_base_index;
u8 ethertype_filter_count;
u8 vlan_filter_base_index;
u8 vlan_filter_count;
u8 l3_ip4_filter_base_index:4;
u8 l3_ip4_filter_count:4;
u8 l3_ip6_filter_base_index:4;
u8 l3_ip6_filter_count:4;
u8 l4_filter_base_index:4;
u8 l4_filter_count:4;
u8 l4_flex_filter_base_index:4;
u8 l4_flex_filter_count:4;
u8 rslv_tbl_base_index;
u8 rslv_tbl_count;
};
struct request_policy_s {
struct {
u8 all:1;
u8 mcast:1;
u8 rx_queue_tc_index:5;
u8 queue_or_tc:1;
} promisc;
struct {
u8 accept:1;
u8 rsvd:1;
u8 rx_queue_tc_index:5;
u8 queue_or_tc:1;
} bcast;
struct {
u8 accept:1;
u8 rsvd:1;
u8 rx_queue_tc_index:5;
u8 queue_or_tc:1;
} mcast;
u8 rsvd:8;
};
struct fw_interface_in {
u32 mtu;
u32 rsvd1;
struct mac_address_aligned_s mac_address;
struct link_control_s link_control;
u32 rsvd2;
struct link_options_s link_options;
u32 rsvd3;
struct thermal_shutdown_s thermal_shutdown;
u32 rsvd4;
struct sleep_proxy_s sleep_proxy;
u32 rsvd5;
struct pause_quanta_s pause_quanta[8];
struct cable_diag_control_s cable_diag_control;
u32 rsvd6;
struct data_buffer_status_s data_buffer_status;
u32 rsvd7;
struct request_policy_s request_policy;
};
struct transaction_counter_s {
u16 transaction_cnt_a;
u16 transaction_cnt_b;
};
struct management_status_s {
struct mac_address_s mac_address;
u16 vlan;
struct{
u32 enable : 1;
u32 rsvd:31;
} flags;
u32 rsvd1;
u32 rsvd2;
u32 rsvd3;
u32 rsvd4;
u32 rsvd5;
};
struct __packed fw_interface_out {
struct transaction_counter_s transaction_id;
struct version_s version;
struct link_status_s link_status;
struct wol_status_s wol_status;
u32 rsvd;
u32 rsvd2;
struct mac_health_monitor_s mac_health_monitor;
u32 rsvd3;
u32 rsvd4;
struct phy_health_monitor_s phy_health_monitor;
u32 rsvd5;
u32 rsvd6;
struct cable_diag_status_s cable_diag_status;
u32 rsvd7;
struct device_link_caps_s device_link_caps;
u32 rsvd8;
struct sleep_proxy_caps_s sleep_proxy_caps;
u32 rsvd9;
struct lkp_link_caps_s lkp_link_caps;
u32 rsvd10;
struct core_dump_s core_dump;
u32 rsvd11;
struct statistics_s stats;
struct filter_caps_s filter_caps;
struct device_caps_s device_caps;
u32 rsvd13;
struct management_status_s management_status;
u32 reserve[21];
struct trace_s trace;
};
#define AQ_A2_FW_LINK_RATE_INVALID 0
#define AQ_A2_FW_LINK_RATE_10M 1
#define AQ_A2_FW_LINK_RATE_100M 2
#define AQ_A2_FW_LINK_RATE_1G 3
#define AQ_A2_FW_LINK_RATE_2G5 4
#define AQ_A2_FW_LINK_RATE_5G 5
#define AQ_A2_FW_LINK_RATE_10G 6
#define AQ_HOST_MODE_INVALID 0U
#define AQ_HOST_MODE_ACTIVE 1U
#define AQ_HOST_MODE_SLEEP_PROXY 2U
#define AQ_HOST_MODE_LOW_POWER 3U
#define AQ_HOST_MODE_SHUTDOWN 4U
#define AQ_A2_FW_INTERFACE_A0 0
#define AQ_A2_FW_INTERFACE_B0 1
int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops);
int hw_atl2_utils_soft_reset(struct aq_hw_s *self);
int hw_atl2_utils_hw_get_regs(struct aq_hw_s *self,
const struct aq_hw_caps_s *aq_hw_caps,
u32 *regs_buff);
u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self);
int hw_atl2_utils_get_filter_caps(struct aq_hw_s *self);
extern const struct aq_fw_ops aq_a2_fw_ops;
#endif /* HW_ATL2_UTILS_H */
@@ -0,0 +1,718 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Atlantic Network Driver
* Copyright (C) 2020 Marvell International Ltd.
*/
#include <linux/iopoll.h>
#include "aq_hw.h"
#include "aq_hw_utils.h"
#include "aq_nic.h"
#include "hw_atl/hw_atl_llh.h"
#include "hw_atl2_utils.h"
#include "hw_atl2_llh.h"
#include "hw_atl2_internal.h"
#define AQ_A2_FW_READ_TRY_MAX 1000
#define hw_atl2_shared_buffer_write(HW, ITEM, VARIABLE) \
{\
BUILD_BUG_ON_MSG((offsetof(struct fw_interface_in, ITEM) % \
sizeof(u32)) != 0,\
"Unaligned write " # ITEM);\
BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\
"Unaligned write length " # ITEM);\
hw_atl2_mif_shared_buf_write(HW,\
(offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\
(u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32));\
}
#define hw_atl2_shared_buffer_get(HW, ITEM, VARIABLE) \
{\
BUILD_BUG_ON_MSG((offsetof(struct fw_interface_in, ITEM) % \
sizeof(u32)) != 0,\
"Unaligned get " # ITEM);\
BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\
"Unaligned get length " # ITEM);\
hw_atl2_mif_shared_buf_get(HW, \
(offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\
(u32 *)&(VARIABLE), \
sizeof(VARIABLE) / sizeof(u32));\
}
/* This should never be used on non atomic fields,
* treat any > u32 read as non atomic.
*/
#define hw_atl2_shared_buffer_read(HW, ITEM, VARIABLE) \
{\
BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \
sizeof(u32)) != 0,\
"Unaligned read " # ITEM);\
BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\
"Unaligned read length " # ITEM);\
BUILD_BUG_ON_MSG(sizeof(VARIABLE) > sizeof(u32),\
"Non atomic read " # ITEM);\
hw_atl2_mif_shared_buf_read(HW, \
(offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\
(u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32));\
}
#define hw_atl2_shared_buffer_read_safe(HW, ITEM, DATA) \
({\
BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \
sizeof(u32)) != 0,\
"Unaligned read_safe " # ITEM);\
BUILD_BUG_ON_MSG((sizeof(((struct fw_interface_out *)0)->ITEM) % \
sizeof(u32)) != 0,\
"Unaligned read_safe length " # ITEM);\
hw_atl2_shared_buffer_read_block((HW), \
(offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\
sizeof(((struct fw_interface_out *)0)->ITEM) / sizeof(u32),\
(DATA));\
})
static int hw_atl2_shared_buffer_read_block(struct aq_hw_s *self,
u32 offset, u32 dwords, void *data)
{
struct transaction_counter_s tid1, tid2;
int cnt = 0;
do {
do {
hw_atl2_shared_buffer_read(self, transaction_id, tid1);
cnt++;
if (cnt > AQ_A2_FW_READ_TRY_MAX)
return -ETIME;
if (tid1.transaction_cnt_a != tid1.transaction_cnt_b)
mdelay(1);
} while (tid1.transaction_cnt_a != tid1.transaction_cnt_b);
hw_atl2_mif_shared_buf_read(self, offset, (u32 *)data, dwords);
hw_atl2_shared_buffer_read(self, transaction_id, tid2);
cnt++;
if (cnt > AQ_A2_FW_READ_TRY_MAX)
return -ETIME;
} while (tid2.transaction_cnt_a != tid2.transaction_cnt_b ||
tid1.transaction_cnt_a != tid2.transaction_cnt_a);
return 0;
}
static inline int hw_atl2_shared_buffer_finish_ack(struct aq_hw_s *self)
{
u32 val;
int err;
hw_atl2_mif_host_finished_write_set(self, 1U);
err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get,
self, val, val == 0U,
100, 100000U);
WARN(err, "hw_atl2_shared_buffer_finish_ack");
return err;
}
static int aq_a2_fw_init(struct aq_hw_s *self)
{
struct link_control_s link_control;
u32 mtu;
u32 val;
int err;
err = hw_atl2_utils_get_filter_caps(self);
if (err)
return err;
hw_atl2_shared_buffer_get(self, link_control, link_control);
link_control.mode = AQ_HOST_MODE_ACTIVE;
hw_atl2_shared_buffer_write(self, link_control, link_control);
hw_atl2_shared_buffer_get(self, mtu, mtu);
mtu = HW_ATL2_MTU_JUMBO;
hw_atl2_shared_buffer_write(self, mtu, mtu);
hw_atl2_mif_host_finished_write_set(self, 1U);
err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get,
self, val, val == 0U,
100, 5000000U);
WARN(err, "hw_atl2_shared_buffer_finish_ack");
return err;
}
static int aq_a2_fw_deinit(struct aq_hw_s *self)
{
struct link_control_s link_control;
hw_atl2_shared_buffer_get(self, link_control, link_control);
link_control.mode = AQ_HOST_MODE_SHUTDOWN;
hw_atl2_shared_buffer_write(self, link_control, link_control);
return hw_atl2_shared_buffer_finish_ack(self);
}
static void a2_link_speed_mask2fw(u32 speed,
struct link_options_s *link_options)
{
link_options->rate_10G = !!(speed & AQ_NIC_RATE_10G);
link_options->rate_5G = !!(speed & AQ_NIC_RATE_5G);
link_options->rate_N5G = link_options->rate_5G;
link_options->rate_2P5G = !!(speed & AQ_NIC_RATE_2G5);
link_options->rate_N2P5G = link_options->rate_2P5G;
link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G);
link_options->rate_100M = !!(speed & AQ_NIC_RATE_100M);
link_options->rate_10M = !!(speed & AQ_NIC_RATE_10M);
link_options->rate_1G_hd = !!(speed & AQ_NIC_RATE_1G_HALF);
link_options->rate_100M_hd = !!(speed & AQ_NIC_RATE_100M_HALF);
link_options->rate_10M_hd = !!(speed & AQ_NIC_RATE_10M_HALF);
}
static u32 a2_fw_dev_to_eee_mask(struct device_link_caps_s *device_link_caps)
{
u32 rate = 0;
if (device_link_caps->eee_10G)
rate |= AQ_NIC_RATE_EEE_10G;
if (device_link_caps->eee_5G)
rate |= AQ_NIC_RATE_EEE_5G;
if (device_link_caps->eee_2P5G)
rate |= AQ_NIC_RATE_EEE_2G5;
if (device_link_caps->eee_1G)
rate |= AQ_NIC_RATE_EEE_1G;
if (device_link_caps->eee_100M)
rate |= AQ_NIC_RATE_EEE_100M;
return rate;
}
static u32 a2_fw_lkp_to_mask(struct lkp_link_caps_s *lkp_link_caps)
{
u32 rate = 0;
if (lkp_link_caps->rate_10G)
rate |= AQ_NIC_RATE_10G;
if (lkp_link_caps->rate_5G)
rate |= AQ_NIC_RATE_5G;
if (lkp_link_caps->rate_2P5G)
rate |= AQ_NIC_RATE_2G5;
if (lkp_link_caps->rate_1G)
rate |= AQ_NIC_RATE_1G;
if (lkp_link_caps->rate_1G_hd)
rate |= AQ_NIC_RATE_1G_HALF;
if (lkp_link_caps->rate_100M)
rate |= AQ_NIC_RATE_100M;
if (lkp_link_caps->rate_100M_hd)
rate |= AQ_NIC_RATE_100M_HALF;
if (lkp_link_caps->rate_10M)
rate |= AQ_NIC_RATE_10M;
if (lkp_link_caps->rate_10M_hd)
rate |= AQ_NIC_RATE_10M_HALF;
if (lkp_link_caps->eee_10G)
rate |= AQ_NIC_RATE_EEE_10G;
if (lkp_link_caps->eee_5G)
rate |= AQ_NIC_RATE_EEE_5G;
if (lkp_link_caps->eee_2P5G)
rate |= AQ_NIC_RATE_EEE_2G5;
if (lkp_link_caps->eee_1G)
rate |= AQ_NIC_RATE_EEE_1G;
if (lkp_link_caps->eee_100M)
rate |= AQ_NIC_RATE_EEE_100M;
return rate;
}
static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed)
{
struct link_options_s link_options;
hw_atl2_shared_buffer_get(self, link_options, link_options);
link_options.link_up = 1U;
a2_link_speed_mask2fw(speed, &link_options);
hw_atl2_shared_buffer_write(self, link_options, link_options);
return hw_atl2_shared_buffer_finish_ack(self);
}
static void aq_a2_fw_set_mpi_flow_control(struct aq_hw_s *self,
struct link_options_s *link_options)
{
u32 flow_control = self->aq_nic_cfg->fc.req;
link_options->pause_rx = !!(flow_control & AQ_NIC_FC_RX);
link_options->pause_tx = !!(flow_control & AQ_NIC_FC_TX);
}
static void aq_a2_fw_upd_eee_rate_bits(struct aq_hw_s *self,
struct link_options_s *link_options,
u32 eee_speeds)
{
link_options->eee_10G = !!(eee_speeds & AQ_NIC_RATE_EEE_10G);
link_options->eee_5G = !!(eee_speeds & AQ_NIC_RATE_EEE_5G);
link_options->eee_2P5G = !!(eee_speeds & AQ_NIC_RATE_EEE_2G5);
link_options->eee_1G = !!(eee_speeds & AQ_NIC_RATE_EEE_1G);
link_options->eee_100M = !!(eee_speeds & AQ_NIC_RATE_EEE_100M);
}
static int aq_a2_fw_set_state(struct aq_hw_s *self,
enum hal_atl_utils_fw_state_e state)
{
struct link_options_s link_options;
hw_atl2_shared_buffer_get(self, link_options, link_options);
switch (state) {
case MPI_INIT:
link_options.link_up = 1U;
aq_a2_fw_upd_eee_rate_bits(self, &link_options,
self->aq_nic_cfg->eee_speeds);
aq_a2_fw_set_mpi_flow_control(self, &link_options);
break;
case MPI_DEINIT:
link_options.link_up = 0U;
break;
case MPI_RESET:
case MPI_POWER:
/* No actions */
break;
}
hw_atl2_shared_buffer_write(self, link_options, link_options);
return hw_atl2_shared_buffer_finish_ack(self);
}
static int aq_a2_fw_update_link_status(struct aq_hw_s *self)
{
struct lkp_link_caps_s lkp_link_caps;
struct link_status_s link_status;
hw_atl2_shared_buffer_read(self, link_status, link_status);
switch (link_status.link_rate) {
case AQ_A2_FW_LINK_RATE_10G:
self->aq_link_status.mbps = 10000;
break;
case AQ_A2_FW_LINK_RATE_5G:
self->aq_link_status.mbps = 5000;
break;
case AQ_A2_FW_LINK_RATE_2G5:
self->aq_link_status.mbps = 2500;
break;
case AQ_A2_FW_LINK_RATE_1G:
self->aq_link_status.mbps = 1000;
break;
case AQ_A2_FW_LINK_RATE_100M:
self->aq_link_status.mbps = 100;
break;
case AQ_A2_FW_LINK_RATE_10M:
self->aq_link_status.mbps = 10;
break;
default:
self->aq_link_status.mbps = 0;
}
self->aq_link_status.full_duplex = link_status.duplex;
hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps);
self->aq_link_status.lp_link_speed_msk =
a2_fw_lkp_to_mask(&lkp_link_caps);
self->aq_link_status.lp_flow_control =
((lkp_link_caps.pause_rx) ? AQ_NIC_FC_RX : 0) |
((lkp_link_caps.pause_tx) ? AQ_NIC_FC_TX : 0);
return 0;
}
static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
{
struct mac_address_aligned_s mac_address;
hw_atl2_shared_buffer_get(self, mac_address, mac_address);
ether_addr_copy(mac, (u8 *)mac_address.aligned.mac_address);
return 0;
}
static void aq_a2_fill_a0_stats(struct aq_hw_s *self,
struct statistics_s *stats)
{
struct hw_atl2_priv *priv = self->priv;
struct aq_stats_s *cs = &self->curr_stats;
struct aq_stats_s curr_stats = *cs;
bool corrupted_stats = false;
#define AQ_SDELTA(_N, _F) \
do { \
if (!corrupted_stats && \
((s64)(stats->a0.msm._F - priv->last_stats.a0.msm._F)) >= 0) \
curr_stats._N += stats->a0.msm._F - priv->last_stats.a0.msm._F;\
else \
corrupted_stats = true; \
} while (0)
if (self->aq_link_status.mbps) {
AQ_SDELTA(uprc, rx_unicast_frames);
AQ_SDELTA(mprc, rx_multicast_frames);
AQ_SDELTA(bprc, rx_broadcast_frames);
AQ_SDELTA(erpr, rx_error_frames);
AQ_SDELTA(uptc, tx_unicast_frames);
AQ_SDELTA(mptc, tx_multicast_frames);
AQ_SDELTA(bptc, tx_broadcast_frames);
AQ_SDELTA(erpt, tx_errors);
AQ_SDELTA(ubrc, rx_unicast_octets);
AQ_SDELTA(ubtc, tx_unicast_octets);
AQ_SDELTA(mbrc, rx_multicast_octets);
AQ_SDELTA(mbtc, tx_multicast_octets);
AQ_SDELTA(bbrc, rx_broadcast_octets);
AQ_SDELTA(bbtc, tx_broadcast_octets);
if (!corrupted_stats)
*cs = curr_stats;
}
#undef AQ_SDELTA
}
static void aq_a2_fill_b0_stats(struct aq_hw_s *self,
struct statistics_s *stats)
{
struct hw_atl2_priv *priv = self->priv;
struct aq_stats_s *cs = &self->curr_stats;
struct aq_stats_s curr_stats = *cs;
bool corrupted_stats = false;
#define AQ_SDELTA(_N, _F) \
do { \
if (!corrupted_stats && \
((s64)(stats->b0._F - priv->last_stats.b0._F)) >= 0) \
curr_stats._N += stats->b0._F - priv->last_stats.b0._F; \
else \
corrupted_stats = true; \
} while (0)
if (self->aq_link_status.mbps) {
AQ_SDELTA(uprc, rx_unicast_frames);
AQ_SDELTA(mprc, rx_multicast_frames);
AQ_SDELTA(bprc, rx_broadcast_frames);
AQ_SDELTA(erpr, rx_errors);
AQ_SDELTA(brc, rx_good_octets);
AQ_SDELTA(uptc, tx_unicast_frames);
AQ_SDELTA(mptc, tx_multicast_frames);
AQ_SDELTA(bptc, tx_broadcast_frames);
AQ_SDELTA(erpt, tx_errors);
AQ_SDELTA(btc, tx_good_octets);
if (!corrupted_stats)
*cs = curr_stats;
}
#undef AQ_SDELTA
}
static int aq_a2_fw_update_stats(struct aq_hw_s *self)
{
struct aq_stats_s *cs = &self->curr_stats;
struct hw_atl2_priv *priv = self->priv;
struct statistics_s stats;
struct version_s version;
int err;
err = hw_atl2_shared_buffer_read_safe(self, version, &version);
if (err)
return err;
err = hw_atl2_shared_buffer_read_safe(self, stats, &stats);
if (err)
return err;
if (version.drv_iface_ver == AQ_A2_FW_INTERFACE_A0)
aq_a2_fill_a0_stats(self, &stats);
else
aq_a2_fill_b0_stats(self, &stats);
cs->dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counter_get(self);
cs->dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counter_get(self);
cs->dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counter_get(self);
cs->dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counter_get(self);
cs->dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
memcpy(&priv->last_stats, &stats, sizeof(stats));
return 0;
}
static int aq_a2_fw_get_phy_temp(struct aq_hw_s *self, int *temp)
{
struct phy_health_monitor_s phy_health_monitor;
hw_atl2_shared_buffer_read_safe(self, phy_health_monitor,
&phy_health_monitor);
*temp = (int8_t)phy_health_monitor.phy_temperature * 1000;
return 0;
}
static int aq_a2_fw_get_mac_temp(struct aq_hw_s *self, int *temp)
{
/* There's only one temperature sensor on A2, use it for
* both MAC and PHY.
*/
return aq_a2_fw_get_phy_temp(self, temp);
}
static int aq_a2_fw_set_wol_params(struct aq_hw_s *self, const u8 *mac, u32 wol)
{
struct mac_address_aligned_s mac_address;
struct link_control_s link_control;
struct wake_on_lan_s wake_on_lan;
memcpy(mac_address.aligned.mac_address, mac, ETH_ALEN);
hw_atl2_shared_buffer_write(self, mac_address, mac_address);
memset(&wake_on_lan, 0, sizeof(wake_on_lan));
if (wol & WAKE_MAGIC)
wake_on_lan.wake_on_magic_packet = 1U;
if (wol & (WAKE_PHY | AQ_FW_WAKE_ON_LINK_RTPM))
wake_on_lan.wake_on_link_up = 1U;
hw_atl2_shared_buffer_write(self, sleep_proxy, wake_on_lan);
hw_atl2_shared_buffer_get(self, link_control, link_control);
link_control.mode = AQ_HOST_MODE_SLEEP_PROXY;
hw_atl2_shared_buffer_write(self, link_control, link_control);
return hw_atl2_shared_buffer_finish_ack(self);
}
static int aq_a2_fw_set_power(struct aq_hw_s *self, unsigned int power_state,
const u8 *mac)
{
u32 wol = self->aq_nic_cfg->wol;
int err = 0;
if (wol)
err = aq_a2_fw_set_wol_params(self, mac, wol);
return err;
}
static int aq_a2_fw_set_eee_rate(struct aq_hw_s *self, u32 speed)
{
struct link_options_s link_options;
hw_atl2_shared_buffer_get(self, link_options, link_options);
aq_a2_fw_upd_eee_rate_bits(self, &link_options, speed);
hw_atl2_shared_buffer_write(self, link_options, link_options);
return hw_atl2_shared_buffer_finish_ack(self);
}
static int aq_a2_fw_get_eee_rate(struct aq_hw_s *self, u32 *rate,
u32 *supported_rates)
{
struct device_link_caps_s device_link_caps;
struct lkp_link_caps_s lkp_link_caps;
hw_atl2_shared_buffer_read(self, device_link_caps, device_link_caps);
hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps);
*supported_rates = a2_fw_dev_to_eee_mask(&device_link_caps);
*rate = a2_fw_lkp_to_mask(&lkp_link_caps);
return 0;
}
static int aq_a2_fw_renegotiate(struct aq_hw_s *self)
{
struct link_options_s link_options;
int err;
hw_atl2_shared_buffer_get(self, link_options, link_options);
link_options.link_renegotiate = 1U;
hw_atl2_shared_buffer_write(self, link_options, link_options);
err = hw_atl2_shared_buffer_finish_ack(self);
/* We should put renegotiate status back to zero
* after command completes
*/
link_options.link_renegotiate = 0U;
hw_atl2_shared_buffer_write(self, link_options, link_options);
return err;
}
static int aq_a2_fw_set_flow_control(struct aq_hw_s *self)
{
struct link_options_s link_options;
hw_atl2_shared_buffer_get(self, link_options, link_options);
aq_a2_fw_set_mpi_flow_control(self, &link_options);
hw_atl2_shared_buffer_write(self, link_options, link_options);
return hw_atl2_shared_buffer_finish_ack(self);
}
static u32 aq_a2_fw_get_flow_control(struct aq_hw_s *self, u32 *fcmode)
{
struct link_status_s link_status;
hw_atl2_shared_buffer_read(self, link_status, link_status);
*fcmode = ((link_status.pause_rx) ? AQ_NIC_FC_RX : 0) |
((link_status.pause_tx) ? AQ_NIC_FC_TX : 0);
return 0;
}
static int aq_a2_fw_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable)
{
struct link_options_s link_options;
hw_atl2_shared_buffer_get(self, link_options, link_options);
switch (mode) {
case AQ_HW_LOOPBACK_PHYINT_SYS:
link_options.internal_loopback = enable;
break;
case AQ_HW_LOOPBACK_PHYEXT_SYS:
link_options.external_loopback = enable;
break;
default:
return -EINVAL;
}
hw_atl2_shared_buffer_write(self, link_options, link_options);
return hw_atl2_shared_buffer_finish_ack(self);
}
u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self)
{
struct version_s version;
hw_atl2_shared_buffer_read_safe(self, version, &version);
/* A2 FW version is stored in reverse order */
return version.bundle.major << 24 |
version.bundle.minor << 16 |
version.bundle.build;
}
int hw_atl2_utils_get_filter_caps(struct aq_hw_s *self)
{
struct hw_atl2_priv *priv = self->priv;
struct filter_caps_s filter_caps;
u32 tag_top;
int err;
err = hw_atl2_shared_buffer_read_safe(self, filter_caps, &filter_caps);
if (err)
return err;
priv->art_base_index = filter_caps.rslv_tbl_base_index * 8;
priv->art_count = filter_caps.rslv_tbl_count * 8;
if (priv->art_count == 0)
priv->art_count = HW_ATL2_ART_TOTAL_ENTRIES;
priv->l2_filters_base_index = filter_caps.l2_filters_base_index;
if (priv->l2_filters_base_index >= HW_ATL2_MAC_MAX)
priv->l2_filters_base_index = HW_ATL2_MAC_UC;
priv->l2_filter_count = filter_caps.l2_filter_count;
priv->etype_filter_base_index = filter_caps.ethertype_filter_base_index;
priv->etype_filter_count = filter_caps.ethertype_filter_count;
priv->etype_filter_tag_top =
(priv->etype_filter_count >= HW_ATL2_RPF_ETYPE_TAGS) ?
(HW_ATL2_RPF_ETYPE_TAGS) : (HW_ATL2_RPF_ETYPE_TAGS >> 1);
priv->vlan_filter_base_index = filter_caps.vlan_filter_base_index;
/* 0 - no tag, 1 - reserved for vlan-filter-offload filters */
tag_top =
(filter_caps.vlan_filter_count == HW_ATL2_RPF_VLAN_FILTERS) ?
(HW_ATL2_RPF_VLAN_FILTERS - 2) :
(HW_ATL2_RPF_VLAN_FILTERS / 2 - 2);
if (filter_caps.vlan_filter_count > 2) {
priv->vlan_filter_count = min_t(u32,
filter_caps.vlan_filter_count - 2,
tag_top);
} else {
pr_debug("atlantic: FW vlan_filter_count=%u <= 2, no usable VLAN filters\n",
filter_caps.vlan_filter_count);
priv->vlan_filter_count = 0;
}
priv->l3_v4_filter_base_index = filter_caps.l3_ip4_filter_base_index;
if (priv->l3_v4_filter_base_index >= HW_ATL2_RPF_L3V4_FILTERS) {
priv->l3_v4_filter_base_index = 0;
priv->l3_v4_filter_count = 0;
} else {
priv->l3_v4_filter_count = min_t(u32,
filter_caps.l3_ip4_filter_count,
HW_ATL2_RPF_L3V4_FILTERS - 1);
}
priv->l3_v6_filter_base_index = filter_caps.l3_ip6_filter_base_index;
if (priv->l3_v6_filter_base_index >= HW_ATL2_RPF_L3V6_FILTERS) {
priv->l3_v6_filter_base_index = 0;
priv->l3_v6_filter_count = 0;
} else {
priv->l3_v6_filter_count = min_t(u32,
filter_caps.l3_ip6_filter_count,
HW_ATL2_RPF_L3V6_FILTERS - 1);
}
priv->l4_filter_base_index = filter_caps.l4_filter_base_index;
if (priv->l4_filter_base_index >= HW_ATL2_RPF_L4_FILTERS) {
priv->l4_filter_base_index = 0;
priv->l4_filter_count = 0;
} else {
priv->l4_filter_count = min_t(u32,
filter_caps.l4_filter_count,
HW_ATL2_RPF_L4_FILTERS - 1);
}
return 0;
}
static int aq_a2_fw_set_downshift(struct aq_hw_s *self, u32 counter)
{
struct link_options_s link_options;
hw_atl2_shared_buffer_get(self, link_options, link_options);
link_options.downshift = !!counter;
link_options.downshift_retry = counter;
hw_atl2_shared_buffer_write(self, link_options, link_options);
return hw_atl2_shared_buffer_finish_ack(self);
}
const struct aq_fw_ops aq_a2_fw_ops = {
.init = aq_a2_fw_init,
.deinit = aq_a2_fw_deinit,
.reset = NULL,
.renegotiate = aq_a2_fw_renegotiate,
.get_mac_permanent = aq_a2_fw_get_mac_permanent,
.set_link_speed = aq_a2_fw_set_link_speed,
.set_state = aq_a2_fw_set_state,
.update_link_status = aq_a2_fw_update_link_status,
.update_stats = aq_a2_fw_update_stats,
.set_power = aq_a2_fw_set_power,
.get_mac_temp = aq_a2_fw_get_mac_temp,
.get_phy_temp = aq_a2_fw_get_phy_temp,
.set_eee_rate = aq_a2_fw_set_eee_rate,
.get_eee_rate = aq_a2_fw_get_eee_rate,
.set_flow_control = aq_a2_fw_set_flow_control,
.get_flow_control = aq_a2_fw_get_flow_control,
.set_phyloopback = aq_a2_fw_set_phyloopback,
.set_downshift = aq_a2_fw_set_downshift,
};