aboutsummaryrefslogtreecommitdiff
path: root/eth/al_hal_eth_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'eth/al_hal_eth_main.c')
-rw-r--r--eth/al_hal_eth_main.c5260
1 files changed, 5260 insertions, 0 deletions
diff --git a/eth/al_hal_eth_main.c b/eth/al_hal_eth_main.c
new file mode 100644
index 000000000000..b3a5c70b1f04
--- /dev/null
+++ b/eth/al_hal_eth_main.c
@@ -0,0 +1,5260 @@
+/*-
+*******************************************************************************
+Copyright (C) 2015 Annapurna Labs Ltd.
+
+This file may be licensed under the terms of the Annapurna Labs Commercial
+License Agreement.
+
+Alternatively, this file can be distributed under the terms of the GNU General
+Public License V2 as published by the Free Software Foundation and can be
+found at http://www.gnu.org/licenses/gpl-2.0.html
+
+Alternatively, redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/**
+ * @{
+ * @file al_hal_eth_main.c
+ *
+ * @brief XG Ethernet unit HAL driver for main functions (initialization, data path)
+ *
+ */
+
+#include "al_hal_eth.h"
+#include <al_hal_udma_iofic.h>
+#include <al_hal_udma_config.h>
+#include <al_hal_udma.h>
+#include "al_hal_eth_ec_regs.h"
+#include "al_hal_eth_mac_regs.h"
+#include <al_hal_unit_adapter_regs.h>
+#ifdef AL_ETH_EX
+#include "al_hal_eth_ex_internal.h"
+#endif
+
+/* Number of xfi_txclk cycles that accumulate into 100ns */
+#define ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL 52
+
+#define AL_ETH_TX_PKT_UDMA_FLAGS (AL_ETH_TX_FLAGS_NO_SNOOP | \
+ AL_ETH_TX_FLAGS_INT)
+
+#define AL_ETH_TX_PKT_META_FLAGS (AL_ETH_TX_FLAGS_IPV4_L3_CSUM | \
+ AL_ETH_TX_FLAGS_L4_CSUM | \
+ AL_ETH_TX_FLAGS_L4_PARTIAL_CSUM | \
+ AL_ETH_TX_FLAGS_L2_MACSEC_PKT | \
+ AL_ETH_TX_FLAGS_L2_DIS_FCS |\
+ AL_ETH_TX_FLAGS_TSO |\
+ AL_ETH_TX_FLAGS_TS)
+
+#define AL_ETH_TX_SRC_VLAN_CNT_MASK 3
+#define AL_ETH_TX_SRC_VLAN_CNT_SHIFT 5
+#define AL_ETH_TX_L4_PROTO_IDX_MASK 0x1F
+#define AL_ETH_TX_L4_PROTO_IDX_SHIFT 8
+#define AL_ETH_TX_TUNNEL_MODE_SHIFT 18
+#define AL_ETH_TX_OUTER_L3_PROTO_SHIFT 20
+#define AL_ETH_TX_VLAN_MOD_ADD_SHIFT 22
+#define AL_ETH_TX_VLAN_MOD_DEL_SHIFT 24
+#define AL_ETH_TX_VLAN_MOD_E_SEL_SHIFT 26
+#define AL_ETH_TX_VLAN_MOD_VID_SEL_SHIFT 28
+#define AL_ETH_TX_VLAN_MOD_PBIT_SEL_SHIFT 30
+
+/* tx Meta Descriptor defines */
+#define AL_ETH_TX_META_STORE (1 << 21)
+#define AL_ETH_TX_META_L3_LEN_MASK 0xff
+#define AL_ETH_TX_META_L3_OFF_MASK 0xff
+#define AL_ETH_TX_META_L3_OFF_SHIFT 8
+#define AL_ETH_TX_META_MSS_LSB_VAL_SHIFT 22
+#define AL_ETH_TX_META_MSS_MSB_TS_VAL_SHIFT 16
+#define AL_ETH_TX_META_OUTER_L3_LEN_MASK 0x1f
+#define AL_ETH_TX_META_OUTER_L3_LEN_SHIFT 24
+#define AL_ETH_TX_META_OUTER_L3_OFF_HIGH_MASK 0x18
+#define AL_ETH_TX_META_OUTER_L3_OFF_HIGH_SHIFT 10
+#define AL_ETH_TX_META_OUTER_L3_OFF_LOW_MASK 0x07
+#define AL_ETH_TX_META_OUTER_L3_OFF_LOW_SHIFT 29
+
+/* tx Meta Descriptor defines - MacSec */
+#define AL_ETH_TX_MACSEC_SIGN_SHIFT 0 /* Sign TX pkt */
+#define AL_ETH_TX_MACSEC_ENCRYPT_SHIFT 1 /* Encrypt TX pkt */
+#define AL_ETH_TX_MACSEC_AN_LSB_SHIFT 2 /* Association Number */
+#define AL_ETH_TX_MACSEC_AN_MSB_SHIFT 3
+#define AL_ETH_TX_MACSEC_SC_LSB_SHIFT 4 /* Secured Channel */
+#define AL_ETH_TX_MACSEC_SC_MSB_SHIFT 9
+#define AL_ETH_TX_MACSEC_SECURED_PYLD_LEN_LSB_SHIFT 10 /* Secure Payload Length (0x3FFF for non-SL packets) */
+#define AL_ETH_TX_MACSEC_SECURED_PYLD_LEN_MSB_SHIFT 23
+
+/* Rx Descriptor defines */
+#define AL_ETH_RX_L3_PROTO_IDX_MASK 0x1F
+#define AL_ETH_RX_SRC_VLAN_CNT_MASK 3
+#define AL_ETH_RX_SRC_VLAN_CNT_SHIFT 5
+#define AL_ETH_RX_L4_PROTO_IDX_MASK 0x1F
+#define AL_ETH_RX_L4_PROTO_IDX_SHIFT 8
+
+#define AL_ETH_RX_L3_OFFSET_SHIFT 9
+#define AL_ETH_RX_L3_OFFSET_MASK (0x7f << AL_ETH_RX_L3_OFFSET_SHIFT)
+#define AL_ETH_RX_HASH_SHIFT 16
+#define AL_ETH_RX_HASH_MASK (0xffff << AL_ETH_RX_HASH_SHIFT)
+
+#define ETH_MAC_GEN_LED_CFG_BLINK_TIMER_VAL 5
+#define ETH_MAC_GEN_LED_CFG_ACT_TIMER_VAL 7
+
+/* Tx VID Table*/
+#define AL_ETH_TX_VLAN_TABLE_UDMA_MASK 0xF
+#define AL_ETH_TX_VLAN_TABLE_FWD_TO_MAC (1 << 4)
+
+/* tx gpd defines */
+#define AL_ETH_TX_GPD_L3_PROTO_MASK 0x1f
+#define AL_ETH_TX_GPD_L3_PROTO_SHIFT 0
+#define AL_ETH_TX_GPD_L4_PROTO_MASK 0x1f
+#define AL_ETH_TX_GPD_L4_PROTO_SHIFT 5
+#define AL_ETH_TX_GPD_TUNNEL_CTRL_MASK 0x7
+#define AL_ETH_TX_GPD_TUNNEL_CTRL_SHIFT 10
+#define AL_ETH_TX_GPD_SRC_VLAN_CNT_MASK 0x3
+#define AL_ETH_TX_GPD_SRC_VLAN_CNT_SHIFT 13
+#define AL_ETH_TX_GPD_CAM_DATA_2_SHIFT 32
+#define AL_ETH_TX_GPD_CAM_MASK_2_SHIFT 32
+#define AL_ETH_TX_GPD_CAM_CTRL_VALID_SHIFT 31
+
+/* tx gcp defines */
+#define AL_ETH_TX_GCP_POLY_SEL_MASK 0x1
+#define AL_ETH_TX_GCP_POLY_SEL_SHIFT 0
+#define AL_ETH_TX_GCP_CRC32_BIT_COMP_MASK 0x1
+#define AL_ETH_TX_GCP_CRC32_BIT_COMP_SHIFT 1
+#define AL_ETH_TX_GCP_CRC32_BIT_SWAP_MASK 0x1
+#define AL_ETH_TX_GCP_CRC32_BIT_SWAP_SHIFT 2
+#define AL_ETH_TX_GCP_CRC32_BYTE_SWAP_MASK 0x1
+#define AL_ETH_TX_GCP_CRC32_BYTE_SWAP_SHIFT 3
+#define AL_ETH_TX_GCP_DATA_BIT_SWAP_MASK 0x1
+#define AL_ETH_TX_GCP_DATA_BIT_SWAP_SHIFT 4
+#define AL_ETH_TX_GCP_DATA_BYTE_SWAP_MASK 0x1
+#define AL_ETH_TX_GCP_DATA_BYTE_SWAP_SHIFT 5
+#define AL_ETH_TX_GCP_TRAIL_SIZE_MASK 0xF
+#define AL_ETH_TX_GCP_TRAIL_SIZE_SHIFT 6
+#define AL_ETH_TX_GCP_HEAD_SIZE_MASK 0xFF
+#define AL_ETH_TX_GCP_HEAD_SIZE_SHIFT 16
+#define AL_ETH_TX_GCP_HEAD_CALC_MASK 0x1
+#define AL_ETH_TX_GCP_HEAD_CALC_SHIFT 24
+#define AL_ETH_TX_GCP_MASK_POLARITY_MASK 0x1
+#define AL_ETH_TX_GCP_MASK_POLARITY_SHIFT 25
+
+#define AL_ETH_TX_GCP_OPCODE_1_MASK 0x3F
+#define AL_ETH_TX_GCP_OPCODE_1_SHIFT 0
+#define AL_ETH_TX_GCP_OPCODE_2_MASK 0x3F
+#define AL_ETH_TX_GCP_OPCODE_2_SHIFT 6
+#define AL_ETH_TX_GCP_OPCODE_3_MASK 0x3F
+#define AL_ETH_TX_GCP_OPCODE_3_SHIFT 12
+#define AL_ETH_TX_GCP_OPSEL_1_MASK 0xF
+#define AL_ETH_TX_GCP_OPSEL_1_SHIFT 0
+#define AL_ETH_TX_GCP_OPSEL_2_MASK 0xF
+#define AL_ETH_TX_GCP_OPSEL_2_SHIFT 4
+#define AL_ETH_TX_GCP_OPSEL_3_MASK 0xF
+#define AL_ETH_TX_GCP_OPSEL_3_SHIFT 8
+#define AL_ETH_TX_GCP_OPSEL_4_MASK 0xF
+#define AL_ETH_TX_GCP_OPSEL_4_SHIFT 12
+
+/* Tx crc_chksum_replace defines */
+#define L4_CHECKSUM_DIS_AND_L3_CHECKSUM_DIS 0x00
+#define L4_CHECKSUM_DIS_AND_L3_CHECKSUM_EN 0x20
+#define L4_CHECKSUM_EN_AND_L3_CHECKSUM_DIS 0x40
+#define L4_CHECKSUM_EN_AND_L3_CHECKSUM_EN 0x60
+
+/* rx gpd defines */
+#define AL_ETH_RX_GPD_OUTER_L3_PROTO_MASK 0x1f
+#define AL_ETH_RX_GPD_OUTER_L3_PROTO_SHIFT (3 + 0)
+#define AL_ETH_RX_GPD_OUTER_L4_PROTO_MASK 0x1f
+#define AL_ETH_RX_GPD_OUTER_L4_PROTO_SHIFT (3 + 8)
+#define AL_ETH_RX_GPD_INNER_L3_PROTO_MASK 0x1f
+#define AL_ETH_RX_GPD_INNER_L3_PROTO_SHIFT (3 + 16)
+#define AL_ETH_RX_GPD_INNER_L4_PROTO_MASK 0x1f
+#define AL_ETH_RX_GPD_INNER_L4_PROTO_SHIFT (3 + 24)
+#define AL_ETH_RX_GPD_OUTER_PARSE_CTRL_MASK 0xFF
+#define AL_ETH_RX_GPD_OUTER_PARSE_CTRL_SHIFT 32
+#define AL_ETH_RX_GPD_INNER_PARSE_CTRL_MASK 0xFF
+#define AL_ETH_RX_GPD_INNER_PARSE_CTRL_SHIFT 40
+#define AL_ETH_RX_GPD_L3_PRIORITY_MASK 0xFF
+#define AL_ETH_RX_GPD_L3_PRIORITY_SHIFT 48
+#define AL_ETH_RX_GPD_L4_DST_PORT_LSB_MASK 0xFF
+#define AL_ETH_RX_GPD_L4_DST_PORT_LSB_SHIFT 56
+#define AL_ETH_RX_GPD_CAM_DATA_2_SHIFT 32
+#define AL_ETH_RX_GPD_CAM_MASK_2_SHIFT 32
+#define AL_ETH_RX_GPD_CAM_CTRL_VALID_SHIFT 31
+
+#define AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L3_PROTO_IDX_OFFSET (106 + 5)
+#define AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L4_PROTO_IDX_OFFSET (106 + 10)
+#define AL_ETH_RX_GPD_PARSE_RESULT_INNER_L3_PROTO_IDX_OFFSET (0 + 5)
+#define AL_ETH_RX_GPD_PARSE_RESULT_INNER_L4_PROTO_IDX_OFFSET (0 + 10)
+#define AL_ETH_RX_GPD_PARSE_RESULT_OUTER_PARSE_CTRL (106 + 4)
+#define AL_ETH_RX_GPD_PARSE_RESULT_INNER_PARSE_CTRL 4
+#define AL_ETH_RX_GPD_PARSE_RESULT_L3_PRIORITY (106 + 13)
+#define AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L4_DST_PORT_LSB (106 + 65)
+
+/* rx gcp defines */
+#define AL_ETH_RX_GCP_POLY_SEL_MASK 0x1
+#define AL_ETH_RX_GCP_POLY_SEL_SHIFT 0
+#define AL_ETH_RX_GCP_CRC32_BIT_COMP_MASK 0x1
+#define AL_ETH_RX_GCP_CRC32_BIT_COMP_SHIFT 1
+#define AL_ETH_RX_GCP_CRC32_BIT_SWAP_MASK 0x1
+#define AL_ETH_RX_GCP_CRC32_BIT_SWAP_SHIFT 2
+#define AL_ETH_RX_GCP_CRC32_BYTE_SWAP_MASK 0x1
+#define AL_ETH_RX_GCP_CRC32_BYTE_SWAP_SHIFT 3
+#define AL_ETH_RX_GCP_DATA_BIT_SWAP_MASK 0x1
+#define AL_ETH_RX_GCP_DATA_BIT_SWAP_SHIFT 4
+#define AL_ETH_RX_GCP_DATA_BYTE_SWAP_MASK 0x1
+#define AL_ETH_RX_GCP_DATA_BYTE_SWAP_SHIFT 5
+#define AL_ETH_RX_GCP_TRAIL_SIZE_MASK 0xF
+#define AL_ETH_RX_GCP_TRAIL_SIZE_SHIFT 6
+#define AL_ETH_RX_GCP_HEAD_SIZE_MASK 0xFF
+#define AL_ETH_RX_GCP_HEAD_SIZE_SHIFT 16
+#define AL_ETH_RX_GCP_HEAD_CALC_MASK 0x1
+#define AL_ETH_RX_GCP_HEAD_CALC_SHIFT 24
+#define AL_ETH_RX_GCP_MASK_POLARITY_MASK 0x1
+#define AL_ETH_RX_GCP_MASK_POLARITY_SHIFT 25
+
+#define AL_ETH_RX_GCP_OPCODE_1_MASK 0x3F
+#define AL_ETH_RX_GCP_OPCODE_1_SHIFT 0
+#define AL_ETH_RX_GCP_OPCODE_2_MASK 0x3F
+#define AL_ETH_RX_GCP_OPCODE_2_SHIFT 6
+#define AL_ETH_RX_GCP_OPCODE_3_MASK 0x3F
+#define AL_ETH_RX_GCP_OPCODE_3_SHIFT 12
+#define AL_ETH_RX_GCP_OPSEL_1_MASK 0xF
+#define AL_ETH_RX_GCP_OPSEL_1_SHIFT 0
+#define AL_ETH_RX_GCP_OPSEL_2_MASK 0xF
+#define AL_ETH_RX_GCP_OPSEL_2_SHIFT 4
+#define AL_ETH_RX_GCP_OPSEL_3_MASK 0xF
+#define AL_ETH_RX_GCP_OPSEL_3_SHIFT 8
+#define AL_ETH_RX_GCP_OPSEL_4_MASK 0xF
+#define AL_ETH_RX_GCP_OPSEL_4_SHIFT 12
+
+#define AL_ETH_MDIO_DELAY_PERIOD 1 /* micro seconds to wait when polling mdio status */
+#define AL_ETH_MDIO_DELAY_COUNT 150 /* number of times to poll */
+#define AL_ETH_S2M_UDMA_COMP_COAL_TIMEOUT 200 /* Rx descriptors coalescing timeout in SB clocks */
+
+#define AL_ETH_EPE_ENTRIES_NUM 26
+static struct al_eth_epe_p_reg_entry al_eth_epe_p_regs[AL_ETH_EPE_ENTRIES_NUM] = {
+ { 0x0, 0x0, 0x0 },
+ { 0x0, 0x0, 0x1 },
+ { 0x0, 0x0, 0x2 },
+ { 0x0, 0x0, 0x3 },
+ { 0x18100, 0xFFFFF, 0x80000004 },
+ { 0x188A8, 0xFFFFF, 0x80000005 },
+ { 0x99100, 0xFFFFF, 0x80000006 },
+ { 0x98100, 0xFFFFF, 0x80000007 },
+ { 0x10800, 0x7FFFF, 0x80000008 },
+ { 0x20000, 0x73FFF, 0x80000009 },
+ { 0x20000, 0x70000, 0x8000000A },
+ { 0x186DD, 0x7FFFF, 0x8000000B },
+ { 0x30600, 0x7FF00, 0x8000000C },
+ { 0x31100, 0x7FF00, 0x8000000D },
+ { 0x32F00, 0x7FF00, 0x8000000E },
+ { 0x32900, 0x7FF00, 0x8000000F },
+ { 0x105DC, 0x7FFFF, 0x80010010 },
+ { 0x188E5, 0x7FFFF, 0x80000011 },
+ { 0x72000, 0x72000, 0x80000012 },
+ { 0x70000, 0x72000, 0x80000013 },
+ { 0x46558, 0x7FFFF, 0x80000001 },
+ { 0x18906, 0x7FFFF, 0x80000015 },
+ { 0x18915, 0x7FFFF, 0x80000016 },
+ { 0x31B00, 0x7FF00, 0x80000017 },
+ { 0x30400, 0x7FF00, 0x80000018 },
+ { 0x0, 0x0, 0x8000001F }
+};
+
+
+static struct al_eth_epe_control_entry al_eth_epe_control_table[AL_ETH_EPE_ENTRIES_NUM] = {
+ {{ 0x2800000, 0x0, 0x0, 0x0, 0x1, 0x400000 }},
+ {{ 0x280004C, 0x746000, 0xA46030, 0xE00000, 0x2, 0x400000 }},
+ {{ 0x2800054, 0x746000, 0xA46030, 0x1600000, 0x2, 0x400000 }},
+ {{ 0x280005C, 0x746000, 0xA46030, 0x1E00000, 0x2, 0x400000 }},
+ {{ 0x2800042, 0xD42000, 0x0, 0x400000, 0x1010412, 0x400000 }},
+ {{ 0x2800042, 0xD42000, 0x0, 0x400000, 0x1010412, 0x400000 }},
+ {{ 0x2800042, 0xE42000, 0x0, 0x400000, 0x2020002, 0x400000 }},
+ {{ 0x2800042, 0xE42000, 0x0, 0x400000, 0x2020002, 0x400000 }},
+ {{ 0x280B046, 0x0, 0x6C1008, 0x0, 0x4, 0x406800 }},
+ {{ 0x2800049, 0xF44060, 0x1744080, 0x14404, 0x6, 0x400011 }},
+ {{ 0x2015049, 0xF44060, 0x1744080, 0x14404, 0x8080007, 0x400011 }},
+ {{ 0x280B046, 0xF60040, 0x6C1004, 0x2800000, 0x6, 0x406811 }},
+ {{ 0x2815042, 0x1F42000, 0x2042010, 0x1414460, 0x10100009, 0x40B800 }},
+ {{ 0x2815042, 0x1F42000, 0x2042010, 0x800000, 0x10100009, 0x40B800 }},
+ {{ 0x280B042, 0x0, 0x0, 0x430400, 0x4040009, 0x0 }},
+ {{ 0x2815580, 0x0, 0x0, 0x0, 0x4040005, 0x0 }},
+ {{ 0x280B000, 0x0, 0x0, 0x0, 0x1, 0x400000 }},
+ {{ 0x2800040, 0x174E000, 0x0, 0x0, 0xE, 0x406800 }},
+ {{ 0x280B000, 0x0, 0x0, 0x600000, 0x1, 0x406800 }},
+ {{ 0x280B000, 0x0, 0x0, 0xE00000, 0x1, 0x406800 }},
+ {{ 0x2800000, 0x0, 0x0, 0x0, 0x1, 0x400000 }},
+ {{ 0x280B046, 0x0, 0x0, 0x2800000, 0x7, 0x400000 }},
+ {{ 0x280B046, 0xF60040, 0x6C1004, 0x2800000, 0x6, 0x406811 }},
+ {{ 0x2815042, 0x1F43028, 0x2000000, 0xC00000, 0x10100009, 0x40B800 }},
+ {{ 0x2815400, 0x0, 0x0, 0x0, 0x4040005, 0x0 }},
+ {{ 0x2800000, 0x0, 0x0, 0x0, 0x1, 0x400000 }}
+};
+
+
+#define AL_ETH_IS_1G_MAC(mac_mode) (((mac_mode) == AL_ETH_MAC_MODE_RGMII) || ((mac_mode) == AL_ETH_MAC_MODE_SGMII))
+#define AL_ETH_IS_10G_MAC(mac_mode) (((mac_mode) == AL_ETH_MAC_MODE_10GbE_Serial) || \
+ ((mac_mode) == AL_ETH_MAC_MODE_10G_SGMII) || \
+ ((mac_mode) == AL_ETH_MAC_MODE_SGMII_2_5G))
+#define AL_ETH_IS_25G_MAC(mac_mode) ((mac_mode) == AL_ETH_MAC_MODE_KR_LL_25G)
+
+static const char *al_eth_mac_mode_str(enum al_eth_mac_mode mode)
+{
+ switch(mode) {
+ case AL_ETH_MAC_MODE_RGMII:
+ return "RGMII";
+ case AL_ETH_MAC_MODE_SGMII:
+ return "SGMII";
+ case AL_ETH_MAC_MODE_SGMII_2_5G:
+ return "SGMII_2_5G";
+ case AL_ETH_MAC_MODE_10GbE_Serial:
+ return "KR";
+ case AL_ETH_MAC_MODE_KR_LL_25G:
+ return "KR_LL_25G";
+ case AL_ETH_MAC_MODE_10G_SGMII:
+ return "10G_SGMII";
+ case AL_ETH_MAC_MODE_XLG_LL_40G:
+ return "40G_LL";
+ case AL_ETH_MAC_MODE_XLG_LL_50G:
+ return "50G_LL";
+ default:
+ return "N/A";
+ }
+}
+
+/**
+ * change and wait udma state
+ *
+ * @param dma the udma to change its state
+ * @param new_state
+ *
+ * @return 0 on success. otherwise on failure.
+ */
+static int al_udma_state_set_wait(struct al_udma *dma, enum al_udma_state new_state)
+{
+ enum al_udma_state state;
+ enum al_udma_state expected_state = new_state;
+ int count = 1000;
+ int rc;
+
+ rc = al_udma_state_set(dma, new_state);
+ if (rc != 0) {
+ al_warn("[%s] warn: failed to change state, error %d\n", dma->name, rc);
+ return rc;
+ }
+
+ if ((new_state == UDMA_NORMAL) || (new_state == UDMA_DISABLE))
+ expected_state = UDMA_IDLE;
+
+ do {
+ state = al_udma_state_get(dma);
+ if (state == expected_state)
+ break;
+ al_udelay(1);
+ if (count-- == 0) {
+ al_warn("[%s] warn: dma state didn't change to %s\n",
+ dma->name, al_udma_states_name[new_state]);
+ return -ETIMEDOUT;
+ }
+ } while (1);
+ return 0;
+}
+
+static void al_eth_epe_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ struct al_eth_epe_p_reg_entry *reg_entry,
+ struct al_eth_epe_control_entry *control_entry)
+{
+ al_reg_write32(&adapter->ec_regs_base->epe_p[idx].comp_data, reg_entry->data);
+ al_reg_write32(&adapter->ec_regs_base->epe_p[idx].comp_mask, reg_entry->mask);
+ al_reg_write32(&adapter->ec_regs_base->epe_p[idx].comp_ctrl, reg_entry->ctrl);
+
+ al_reg_write32(&adapter->ec_regs_base->msp_c[idx].p_comp_data, reg_entry->data);
+ al_reg_write32(&adapter->ec_regs_base->msp_c[idx].p_comp_mask, reg_entry->mask);
+ al_reg_write32(&adapter->ec_regs_base->msp_c[idx].p_comp_ctrl, reg_entry->ctrl);
+
+ /*control table 0*/
+ al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_6,
+ control_entry->data[5]);
+ al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_2,
+ control_entry->data[1]);
+ al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_3,
+ control_entry->data[2]);
+ al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_4,
+ control_entry->data[3]);
+ al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_5,
+ control_entry->data[4]);
+ al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_1,
+ control_entry->data[0]);
+
+ /*control table 1*/
+ al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_6,
+ control_entry->data[5]);
+ al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_2,
+ control_entry->data[1]);
+ al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_3,
+ control_entry->data[2]);
+ al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_4,
+ control_entry->data[3]);
+ al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_5,
+ control_entry->data[4]);
+ al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_1,
+ control_entry->data[0]);
+}
+
+static void al_eth_epe_init(struct al_hal_eth_adapter *adapter)
+{
+ int idx;
+
+ if (adapter->enable_rx_parser == 0) {
+ al_dbg("eth [%s]: disable rx parser\n", adapter->name);
+
+ al_reg_write32(&adapter->ec_regs_base->epe[0].res_def, 0x08000000);
+ al_reg_write32(&adapter->ec_regs_base->epe[0].res_in, 0x7);
+
+ al_reg_write32(&adapter->ec_regs_base->epe[1].res_def, 0x08000000);
+ al_reg_write32(&adapter->ec_regs_base->epe[1].res_in, 0x7);
+
+ return;
+ }
+ al_dbg("eth [%s]: enable rx parser\n", adapter->name);
+ for (idx = 0; idx < AL_ETH_EPE_ENTRIES_NUM; idx++)
+ al_eth_epe_entry_set(adapter, idx, &al_eth_epe_p_regs[idx], &al_eth_epe_control_table[idx]);
+
+ al_reg_write32(&adapter->ec_regs_base->epe[0].res_def, 0x08000080);
+ al_reg_write32(&adapter->ec_regs_base->epe[0].res_in, 0x7);
+
+ al_reg_write32(&adapter->ec_regs_base->epe[1].res_def, 0x08000080);
+ al_reg_write32(&adapter->ec_regs_base->epe[1].res_in, 0);
+
+ /* header length as function of 4 bits value, for GRE, when C bit is set, the header len should be increase by 4*/
+ al_reg_write32(&adapter->ec_regs_base->epe_h[8].hdr_len, (4 << 16) | 4);
+
+ /* select the outer information when writing the rx descriptor (l3 protocol index etc) */
+ al_reg_write32(&adapter->ec_regs_base->rfw.meta, EC_RFW_META_L3_LEN_CALC);
+
+ al_reg_write32(&adapter->ec_regs_base->rfw.checksum, EC_RFW_CHECKSUM_HDR_SEL);
+}
+
+/**
+ * read 40G MAC registers (indirect access)
+ *
+ * @param adapter pointer to the private structure
+ * @param reg_addr address in the an registers
+ *
+ * @return the register value
+ */
+static uint32_t al_eth_40g_mac_reg_read(
+ struct al_hal_eth_adapter *adapter,
+ uint32_t reg_addr)
+{
+ uint32_t val;
+
+ /* indirect access */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_addr, reg_addr);
+ val = al_reg_read32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_data);
+
+ al_dbg("[%s]: %s - reg %d. val 0x%x",
+ adapter->name, __func__, reg_addr, val);
+
+ return val;
+}
+
+/**
+ * write 40G MAC registers (indirect access)
+ *
+ * @param adapter pointer to the private structure
+ * @param reg_addr address in the an registers
+ * @param reg_data value to write to the register
+ *
+ */
+static void al_eth_40g_mac_reg_write(
+ struct al_hal_eth_adapter *adapter,
+ uint32_t reg_addr,
+ uint32_t reg_data)
+{
+ /* indirect access */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_addr, reg_addr);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_data, reg_data);
+
+ al_dbg("[%s]: %s - reg %d. val 0x%x",
+ adapter->name, __func__, reg_addr, reg_data);
+}
+
+/**
+ * read 40G PCS registers (indirect access)
+ *
+ * @param adapter pointer to the private structure
+ * @param reg_addr address in the an registers
+ *
+ * @return the register value
+ */
+static uint32_t al_eth_40g_pcs_reg_read(
+ struct al_hal_eth_adapter *adapter,
+ uint32_t reg_addr)
+{
+ uint32_t val;
+
+ /* indirect access */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_addr, reg_addr);
+ val = al_reg_read32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_data);
+
+ al_dbg("[%s]: %s - reg %d. val 0x%x",
+ adapter->name, __func__, reg_addr, val);
+
+ return val;
+}
+
+/**
+ * write 40G PCS registers (indirect access)
+ *
+ * @param adapter pointer to the private structure
+ * @param reg_addr address in the an registers
+ * @param reg_data value to write to the register
+ *
+ */
+static void al_eth_40g_pcs_reg_write(
+ struct al_hal_eth_adapter *adapter,
+ uint32_t reg_addr,
+ uint32_t reg_data)
+{
+ /* indirect access */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_addr, reg_addr);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_data, reg_data);
+
+ al_dbg("[%s]: %s - reg %d. val 0x%x",
+ adapter->name, __func__, reg_addr, reg_data);
+}
+
+/*****************************API Functions **********************************/
+/*adapter management */
+/**
+ * initialize the ethernet adapter's DMA
+ */
+int al_eth_adapter_init(struct al_hal_eth_adapter *adapter, struct al_eth_adapter_params *params)
+{
+ struct al_udma_params udma_params;
+ struct al_udma_m2s_pkt_len_conf conf;
+ int i;
+ uint32_t reg;
+ int rc;
+
+ al_dbg("eth [%s]: initialize controller's UDMA. id = %d\n", params->name, params->udma_id);
+ al_dbg("eth [%s]: UDMA base regs: %p\n", params->name, params->udma_regs_base);
+ al_dbg("eth [%s]: EC base regs: %p\n", params->name, params->ec_regs_base);
+ al_dbg("eth [%s]: MAC base regs: %p\n", params->name, params->mac_regs_base);
+ al_dbg("eth [%s]: enable_rx_parser: %x\n", params->name, params->enable_rx_parser);
+
+ adapter->name = params->name;
+ adapter->rev_id = params->rev_id;
+ adapter->udma_id = params->udma_id;
+ adapter->udma_regs_base = params->udma_regs_base;
+ adapter->ec_regs_base = (struct al_ec_regs __iomem*)params->ec_regs_base;
+ adapter->mac_regs_base = (struct al_eth_mac_regs __iomem*)params->mac_regs_base;
+ adapter->unit_regs = (struct unit_regs __iomem *)params->udma_regs_base;
+ adapter->enable_rx_parser = params->enable_rx_parser;
+ adapter->ec_ints_base = (void __iomem *)((uint32_t)adapter->ec_regs_base + 0x1c00);
+ adapter->mac_ints_base = (void __iomem *)((uint32_t)adapter->mac_regs_base + 0x800);
+
+ /* initialize Tx udma */
+ udma_params.udma_regs_base = adapter->unit_regs;
+ udma_params.type = UDMA_TX;
+ udma_params.num_of_queues = AL_ETH_UDMA_TX_QUEUES;
+ udma_params.name = "eth tx";
+ rc = al_udma_init(&adapter->tx_udma, &udma_params);
+
+ if (rc != 0) {
+ al_err("failed to initialize %s, error %d\n",
+ udma_params.name, rc);
+ return rc;
+ }
+ rc = al_udma_state_set_wait(&adapter->tx_udma, UDMA_NORMAL);
+ if (rc != 0) {
+ al_err("[%s]: failed to change state, error %d\n",
+ udma_params.name, rc);
+ return rc;
+ }
+ /* initialize Rx udma */
+ udma_params.udma_regs_base = adapter->unit_regs;
+ udma_params.type = UDMA_RX;
+ udma_params.num_of_queues = AL_ETH_UDMA_RX_QUEUES;
+ udma_params.name = "eth rx";
+ rc = al_udma_init(&adapter->rx_udma, &udma_params);
+
+ if (rc != 0) {
+ al_err("failed to initialize %s, error %d\n",
+ udma_params.name, rc);
+ return rc;
+ }
+
+ rc = al_udma_state_set_wait(&adapter->rx_udma, UDMA_NORMAL);
+ if (rc != 0) {
+ al_err("[%s]: failed to change state, error %d\n",
+ udma_params.name, rc);
+ return rc;
+ }
+ al_dbg("eth [%s]: controller's UDMA successfully initialized\n",
+ params->name);
+
+ /* set max packet size to 1M (for TSO) */
+ conf.encode_64k_as_zero = AL_TRUE;
+ conf.max_pkt_size = 0xfffff;
+ al_udma_m2s_packet_size_cfg_set(&adapter->tx_udma, &conf);
+
+ /* set m2s (tx) max descriptors to max data buffers number and one for
+ * meta descriptor
+ */
+ al_udma_m2s_max_descs_set(&adapter->tx_udma, AL_ETH_PKT_MAX_BUFS + 1);
+
+ /* set s2m (rx) max descriptors to max data buffers */
+ al_udma_s2m_max_descs_set(&adapter->rx_udma, AL_ETH_PKT_MAX_BUFS);
+
+ /* set s2m burst lenght when writing completion descriptors to 64 bytes
+ */
+ al_udma_s2m_compl_desc_burst_config(&adapter->rx_udma, 64);
+
+ /* if pointer to ec regs provided, then init the tx meta cache of this udma*/
+ if (adapter->ec_regs_base != NULL) {
+ // INIT TX CACHE TABLE:
+ for (i = 0; i < 4; i++) {
+ al_reg_write32(&adapter->ec_regs_base->tso.cache_table_addr, i + (adapter->udma_id * 4));
+ al_reg_write32(&adapter->ec_regs_base->tso.cache_table_data_1, 0x00000000);
+ al_reg_write32(&adapter->ec_regs_base->tso.cache_table_data_2, 0x00000000);
+ al_reg_write32(&adapter->ec_regs_base->tso.cache_table_data_3, 0x00000000);
+ al_reg_write32(&adapter->ec_regs_base->tso.cache_table_data_4, 0x00000000);
+ }
+ }
+ // only udma 0 allowed to init ec
+ if (adapter->udma_id != 0) {
+ return 0;
+ }
+ /* enable Ethernet controller: */
+ /* enable internal machines*/
+ al_reg_write32(&adapter->ec_regs_base->gen.en, 0xffffffff);
+ al_reg_write32(&adapter->ec_regs_base->gen.fifo_en, 0xffffffff);
+
+ if (adapter->rev_id > AL_ETH_REV_ID_0) {
+ /* enable A0 descriptor structure */
+ al_reg_write32_masked(&adapter->ec_regs_base->gen.en_ext,
+ EC_GEN_EN_EXT_CACHE_WORD_SPLIT,
+ EC_GEN_EN_EXT_CACHE_WORD_SPLIT);
+
+ /* use mss value in the descriptor */
+ al_reg_write32(&adapter->ec_regs_base->tso.cfg_add_0,
+ EC_TSO_CFG_ADD_0_MSS_SEL);
+
+ /* enable tunnel TSO */
+ al_reg_write32(&adapter->ec_regs_base->tso.cfg_tunnel,
+ (EC_TSO_CFG_TUNNEL_EN_TUNNEL_TSO |
+ EC_TSO_CFG_TUNNEL_EN_UDP_CHKSUM |
+ EC_TSO_CFG_TUNNEL_EN_UDP_LEN |
+ EC_TSO_CFG_TUNNEL_EN_IPV6_PLEN |
+ EC_TSO_CFG_TUNNEL_EN_IPV4_CHKSUM |
+ EC_TSO_CFG_TUNNEL_EN_IPV4_IDEN |
+ EC_TSO_CFG_TUNNEL_EN_IPV4_TLEN));
+ }
+
+ /* swap input byts from MAC RX */
+ al_reg_write32(&adapter->ec_regs_base->mac.gen, 0x00000001);
+ /* swap output bytes to MAC TX*/
+ al_reg_write32(&adapter->ec_regs_base->tmi.tx_cfg, EC_TMI_TX_CFG_EN_FWD_TO_RX|EC_TMI_TX_CFG_SWAP_BYTES);
+
+ /* TODO: check if we need this line*/
+ al_reg_write32(&adapter->ec_regs_base->tfw_udma[0].fwd_dec, 0x000003fb);
+
+ /* RFW configuration: default 0 */
+ al_reg_write32(&adapter->ec_regs_base->rfw_default[0].opt_1, 0x00000001);
+
+ /* VLAN table address*/
+ al_reg_write32(&adapter->ec_regs_base->rfw.vid_table_addr, 0x00000000);
+ /* VLAN table data*/
+ al_reg_write32(&adapter->ec_regs_base->rfw.vid_table_data, 0x00000000);
+ /* HASH config (select toeplitz and bits 7:0 of the thash result, enable
+ * symmetric hash) */
+ al_reg_write32(&adapter->ec_regs_base->rfw.thash_cfg_1,
+ EC_RFW_THASH_CFG_1_ENABLE_IP_SWAP |
+ EC_RFW_THASH_CFG_1_ENABLE_PORT_SWAP);
+
+ al_eth_epe_init(adapter);
+
+ /* disable TSO padding and use mac padding instead */
+ reg = al_reg_read32(&adapter->ec_regs_base->tso.in_cfg);
+ reg &= ~0x7F00; /*clear bits 14:8 */
+ al_reg_write32(&adapter->ec_regs_base->tso.in_cfg, reg);
+
+ return 0;
+}
+
+/*****************************API Functions **********************************/
+/*adapter management */
+/**
+ * enable the ec and mac interrupts
+ */
+int al_eth_ec_mac_ints_config(struct al_hal_eth_adapter *adapter)
+{
+
+ al_dbg("eth [%s]: enable ethernet and mac interrupts\n", adapter->name);
+
+ // only udma 0 allowed to init ec
+ if (adapter->udma_id != 0)
+ return -EPERM;
+
+ /* enable mac ints */
+ al_iofic_config(adapter->ec_ints_base, AL_INT_GROUP_A,
+ INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ);
+ al_iofic_config(adapter->ec_ints_base, AL_INT_GROUP_B,
+ INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ);
+ al_iofic_config(adapter->ec_ints_base, AL_INT_GROUP_C,
+ INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ);
+ al_iofic_config(adapter->ec_ints_base, AL_INT_GROUP_D,
+ INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ);
+
+ /* unmask MAC int */
+ al_iofic_unmask(adapter->ec_ints_base, AL_INT_GROUP_A, 8);
+
+ /* enable ec interrupts */
+ al_iofic_config(adapter->mac_ints_base, AL_INT_GROUP_A,
+ INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ);
+ al_iofic_config(adapter->mac_ints_base, AL_INT_GROUP_B,
+ INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ);
+ al_iofic_config(adapter->mac_ints_base, AL_INT_GROUP_C,
+ INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ);
+ al_iofic_config(adapter->mac_ints_base, AL_INT_GROUP_D,
+ INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ);
+
+ /* eee active */
+ al_iofic_unmask(adapter->mac_ints_base, AL_INT_GROUP_B, AL_BIT(14));
+
+ al_iofic_unmask(adapter->unit_regs, AL_INT_GROUP_D, AL_BIT(11));
+ return 0;
+}
+
+/**
+ * ec and mac interrupt service routine
+ * read and print asserted interrupts
+ *
+ * @param adapter pointer to the private structure
+ *
+ * @return 0 on success. otherwise on failure.
+ */
+int al_eth_ec_mac_isr(struct al_hal_eth_adapter *adapter)
+{
+ uint32_t cause;
+ al_dbg("[%s]: ethernet interrupts handler\n", adapter->name);
+
+ // only udma 0 allowed to init ec
+ if (adapter->udma_id != 0)
+ return -EPERM;
+
+ /* read ec cause */
+ cause = al_iofic_read_cause(adapter->ec_ints_base, AL_INT_GROUP_A);
+ al_dbg("[%s]: ethernet group A cause 0x%08x\n", adapter->name, cause);
+ if (cause & 1)
+ {
+ cause = al_iofic_read_cause(adapter->mac_ints_base, AL_INT_GROUP_A);
+ al_dbg("[%s]: mac group A cause 0x%08x\n", adapter->name, cause);
+
+ cause = al_iofic_read_cause(adapter->mac_ints_base, AL_INT_GROUP_B);
+ al_dbg("[%s]: mac group B cause 0x%08x\n", adapter->name, cause);
+
+ cause = al_iofic_read_cause(adapter->mac_ints_base, AL_INT_GROUP_C);
+ al_dbg("[%s]: mac group C cause 0x%08x\n", adapter->name, cause);
+
+ cause = al_iofic_read_cause(adapter->mac_ints_base, AL_INT_GROUP_D);
+ al_dbg("[%s]: mac group D cause 0x%08x\n", adapter->name, cause);
+ }
+ cause = al_iofic_read_cause(adapter->ec_ints_base, AL_INT_GROUP_B);
+ al_dbg("[%s]: ethernet group B cause 0x%08x\n", adapter->name, cause);
+ cause = al_iofic_read_cause(adapter->ec_ints_base, AL_INT_GROUP_C);
+ al_dbg("[%s]: ethernet group C cause 0x%08x\n", adapter->name, cause);
+ cause = al_iofic_read_cause(adapter->ec_ints_base, AL_INT_GROUP_D);
+ al_dbg("[%s]: ethernet group D cause 0x%08x\n", adapter->name, cause);
+
+ return 0;
+}
+
+/**
+ * stop the DMA of the ethernet adapter
+ */
+int al_eth_adapter_stop(struct al_hal_eth_adapter *adapter)
+{
+ int rc;
+
+ al_dbg("eth [%s]: stop controller's UDMA\n", adapter->name);
+
+ /* disable Tx dma*/
+ rc = al_udma_state_set_wait(&adapter->tx_udma, UDMA_DISABLE);
+ if (rc != 0) {
+ al_warn("[%s] warn: failed to change state, error %d\n",
+ adapter->tx_udma.name, rc);
+ return rc;
+ }
+
+ al_dbg("eth [%s]: controller's TX UDMA stopped\n",
+ adapter->name);
+ /* disable Rx dma*/
+ rc = al_udma_state_set_wait(&adapter->rx_udma, UDMA_DISABLE);
+ if (rc != 0) {
+ al_warn("[%s] warn: failed to change state, error %d\n",
+ adapter->rx_udma.name, rc);
+ return rc;
+ }
+
+ al_dbg("eth [%s]: controller's RX UDMA stopped\n",
+ adapter->name);
+ return 0;
+}
+
+int al_eth_adapter_reset(struct al_hal_eth_adapter *adapter)
+{
+ al_dbg("eth [%s]: reset controller's UDMA\n", adapter->name);
+
+ return -EPERM;
+}
+
+/* Q management */
+/**
+ * Configure and enable a queue ring
+ */
+int al_eth_queue_config(struct al_hal_eth_adapter *adapter, enum al_udma_type type, uint32_t qid,
+ struct al_udma_q_params *q_params)
+{
+ struct al_udma *udma;
+ int rc;
+
+ al_dbg("eth [%s]: config UDMA %s queue %d\n", adapter->name,
+ type == UDMA_TX ? "Tx" : "Rx", qid);
+
+ if (type == UDMA_TX) {
+ udma = &adapter->tx_udma;
+ } else {
+ udma = &adapter->rx_udma;
+ }
+
+ q_params->adapter_rev_id = adapter->rev_id;
+
+ rc = al_udma_q_init(udma, qid, q_params);
+
+ if (rc)
+ return rc;
+
+ if (type == UDMA_RX) {
+ rc = al_udma_s2m_q_compl_coal_config(&udma->udma_q[qid],
+ AL_TRUE, AL_ETH_S2M_UDMA_COMP_COAL_TIMEOUT);
+
+ al_assert(q_params->cdesc_size <= 32);
+
+ if (q_params->cdesc_size > 16)
+ al_reg_write32_masked(&adapter->ec_regs_base->rfw.out_cfg,
+ EC_RFW_OUT_CFG_META_CNT_MASK, 2);
+ }
+ return rc;
+}
+
+int al_eth_queue_enable(struct al_hal_eth_adapter *adapter __attribute__((__unused__)),
+ enum al_udma_type type __attribute__((__unused__)),
+ uint32_t qid __attribute__((__unused__)))
+{
+ return -EPERM;
+}
+int al_eth_queue_disable(struct al_hal_eth_adapter *adapter __attribute__((__unused__)),
+ enum al_udma_type type __attribute__((__unused__)),
+ uint32_t qid __attribute__((__unused__)))
+{
+ return -EPERM;
+}
+
+/* MAC layer */
+int al_eth_rx_pkt_limit_config(struct al_hal_eth_adapter *adapter, uint32_t min_rx_len, uint32_t max_rx_len)
+{
+ al_assert(max_rx_len <= AL_ETH_MAX_FRAME_LEN);
+
+ /* EC minimum packet length [bytes] in RX */
+ al_reg_write32(&adapter->ec_regs_base->mac.min_pkt, min_rx_len);
+ /* EC maximum packet length [bytes] in RX */
+ al_reg_write32(&adapter->ec_regs_base->mac.max_pkt, max_rx_len);
+
+ if (adapter->rev_id > AL_ETH_REV_ID_2) {
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, min_rx_len);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, max_rx_len);
+ }
+
+ /* configure the MAC's max rx length, add 16 bytes so the packet get
+ * trimmed by the EC/Async_fifo rather by the MAC
+ */
+ if (AL_ETH_IS_1G_MAC(adapter->mac_mode))
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.frm_len, max_rx_len + 16);
+ else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode))
+ /* 10G MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.frm_len, (max_rx_len + 16));
+ else
+ al_eth_40g_mac_reg_write(adapter, ETH_MAC_GEN_V3_MAC_40G_FRM_LENGTH_ADDR, (max_rx_len + 16));
+
+ return 0;
+}
+
+/* configure the mac media type. */
+int al_eth_mac_config(struct al_hal_eth_adapter *adapter, enum al_eth_mac_mode mode)
+{
+ switch(mode) {
+ case AL_ETH_MAC_MODE_RGMII:
+ al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x40003210);
+
+ /* 1G MAC control register */
+ /* bit[0] - TX_ENA - zeroed by default. Should be asserted by al_eth_mac_start
+ * bit[1] - RX_ENA - zeroed by default. Should be asserted by al_eth_mac_start
+ * bit[3] - ETH_SPEED - zeroed to enable 10/100 Mbps Ethernet
+ * bit[4] - PROMIS_EN - asserted to enable MAC promiscuous mode
+ * bit[23] - CNTL_FRM-ENA - asserted to enable control frames
+ * bit[24] - NO_LGTH_CHECK - asserted to disable length checks, which is done in the controller
+ */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, 0x01800010);
+
+ /* RX_SECTION_EMPTY, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_section_empty, 0x00000000);
+ /* RX_SECTION_FULL, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_section_full, 0x0000000c); /* must be larger than almost empty */
+ /* RX_ALMOST_EMPTY, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_almost_empty, 0x00000008);
+ /* RX_ALMOST_FULL, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_almost_full, 0x00000008);
+
+
+ /* TX_SECTION_EMPTY, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_section_empty, 0x00000008); /* 8 ? */
+ /* TX_SECTION_FULL, 0 - store and forward, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_section_full, 0x0000000c);
+ /* TX_ALMOST_EMPTY, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_almost_empty, 0x00000008);
+ /* TX_ALMOST_FULL, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_almost_full, 0x00000008);
+
+ /* XAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000000);
+
+ /* 1G MACSET 1G */
+ /* taking sel_1000/sel_10 inputs from rgmii PHY, and not from register.
+ * disabling magic_packets detection in mac */
+ al_reg_write32(&adapter->mac_regs_base->gen.mac_1g_cfg, 0x00000002);
+ /* RGMII set 1G */
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00063910);
+ al_reg_write32(&adapter->mac_regs_base->gen.rgmii_sel, 0xF);
+ break;
+ case AL_ETH_MAC_MODE_SGMII:
+ if (adapter->rev_id > AL_ETH_REV_ID_2) {
+ /* configure and enable the ASYNC FIFO between the MACs and the EC */
+ /* TX min packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037);
+ /* TX max packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800);
+ /* TX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080);
+ /* TX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00030020);
+ /* TX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000121);
+ /* RX min packet size */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, 0x00000040); */
+ /* RX max packet size */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, 0x00002800); */
+ /* RX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00030020);
+ /* RX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080);
+ /* RX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000212);
+ /* V3 additional MAC selection */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000001);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x00000000);
+ /* ASYNC FIFO ENABLE */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333);
+ /* Timestamp_configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.spare,
+ ETH_MAC_GEN_V3_SPARE_CHICKEN_DISABLE_TIMESTAMP_STRETCH);
+ }
+
+ al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x40053210);
+
+ /* 1G MAC control register */
+ /* bit[0] - TX_ENA - zeroed by default. Should be asserted by al_eth_mac_start
+ * bit[1] - RX_ENA - zeroed by default. Should be asserted by al_eth_mac_start
+ * bit[3] - ETH_SPEED - zeroed to enable 10/100 Mbps Ethernet
+ * bit[4] - PROMIS_EN - asserted to enable MAC promiscuous mode
+ * bit[23] - CNTL_FRM-ENA - asserted to enable control frames
+ * bit[24] - NO_LGTH_CHECK - asserted to disable length checks, which is done in the controller
+ */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, 0x01800010);
+
+ /* RX_SECTION_EMPTY, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_section_empty, 0x00000000);
+ /* RX_SECTION_FULL, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_section_full, 0x0000000c); /* must be larger than almost empty */
+ /* RX_ALMOST_EMPTY, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_almost_empty, 0x00000008);
+ /* RX_ALMOST_FULL, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_almost_full, 0x00000008);
+
+
+ /* TX_SECTION_EMPTY, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_section_empty, 0x00000008); /* 8 ? */
+ /* TX_SECTION_FULL, 0 - store and forward, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_section_full, 0x0000000c);
+ /* TX_ALMOST_EMPTY, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_almost_empty, 0x00000008);
+ /* TX_ALMOST_FULL, */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_almost_full, 0x00000008);
+
+ /* XAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x000000c0);
+
+ /* 1G MACSET 1G */
+ /* taking sel_1000/sel_10 inputs from rgmii_converter, and not from register.
+ * disabling magic_packets detection in mac */
+ al_reg_write32(&adapter->mac_regs_base->gen.mac_1g_cfg, 0x00000002);
+ /* SerDes configuration */
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00063910);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401);
+
+ // FAST AN -- Testing only
+#ifdef AL_HAL_ETH_FAST_AN
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, 0x00000012);
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data, 0x00000040);
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, 0x00000013);
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data, 0x00000000);
+#endif
+
+ /* Setting PCS i/f mode to SGMII (instead of default 1000Base-X) */
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, 0x00000014);
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data, 0x0000000b);
+ /* setting dev_ability to have speed of 1000Mb, [11:10] = 2'b10 */
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, 0x00000004);
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data, 0x000009A0);
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg,
+ ETH_MAC_GEN_LED_CFG_SEL_MASK,
+ ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG);
+ break;
+
+ case AL_ETH_MAC_MODE_SGMII_2_5G:
+ if (adapter->rev_id > AL_ETH_REV_ID_2) {
+ /* configure and enable the ASYNC FIFO between the MACs and the EC */
+ /* TX min packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037);
+ /* TX max packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800);
+ /* TX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080);
+ /* TX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00030020);
+ /* TX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000023);
+ /* RX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00030020);
+ /* RX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080);
+ /* RX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000012);
+ /* V3 additional MAC selection */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x00000050);
+ /* ASYNC FIFO ENABLE */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333);
+ }
+
+ /* MAC register file */
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022830);
+ /* XAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000001);
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.if_mode, 0x00000028);
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.control, 0x00001140);
+ /* RXAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel,
+ ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00063910);
+ al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x40003210);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401);
+
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg,
+ ETH_MAC_GEN_LED_CFG_SEL_MASK,
+ ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG);
+ break;
+
+ case AL_ETH_MAC_MODE_10GbE_Serial:
+ if (adapter->rev_id > AL_ETH_REV_ID_2) {
+ /* configure and enable the ASYNC FIFO between the MACs and the EC */
+ /* TX min packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037);
+ /* TX max packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800);
+ /* TX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080);
+ /* TX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00030020);
+ /* TX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000023);
+ /* RX min packet size */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, 0x00000040); */
+ /* RX max packet size */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, 0x00002800); */
+ /* RX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00030020);
+ /* RX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080);
+ /* RX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000012);
+ /* V3 additional MAC selection */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x00000050);
+ /* ASYNC FIFO ENABLE */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333);
+ }
+
+ /* MAC register file */
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022810);
+ /* XAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000005);
+ /* RXAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.rxaui_cfg, 0x00000007);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_cfg, 0x000001F1);
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel,
+ ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00073910);
+ al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10003210);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401);
+
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg,
+ ETH_MAC_GEN_LED_CFG_SEL_MASK,
+ ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG);
+ break;
+
+ case AL_ETH_MAC_MODE_KR_LL_25G:
+ /* select 25G SERDES lane 0 and lane 1 */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.ext_serdes_ctrl, 0x03821101);
+ if (adapter->rev_id > AL_ETH_REV_ID_2) {
+ /* configure and enable the ASYNC FIFO between the MACs and the EC */
+ /* TX min packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037);
+ /* TX max packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800);
+ /* TX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080);
+ /* TX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00030020);
+ /* TX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000023);
+ /* RX min packet size */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, 0x00000040); */
+ /* RX max packet size */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, 0x00002800); */
+ /* RX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00030020);
+ /* RX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080);
+ /* RX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000012);
+ /* V3 additional MAC selection */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x000000a0);
+ /* ASYNC FIFO ENABLE */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333);
+ }
+
+ /* MAC register file */
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022810);
+ /* XAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000005);
+ /* RXAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.rxaui_cfg, 0x00000007);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_cfg, 0x000001F1);
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel,
+ ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00073910);
+ al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10003210);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401);
+
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg,
+ ETH_MAC_GEN_LED_CFG_SEL_MASK,
+ ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG);
+ break;
+
+ case AL_ETH_MAC_MODE_10G_SGMII:
+ /* MAC register file */
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022810);
+
+ /* XAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000001);
+
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.if_mode, 0x0000002b);
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.control, 0x00009140);
+ // FAST AN -- Testing only
+#ifdef AL_HAL_ETH_FAST_AN
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.link_timer_lo, 0x00000040);
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.link_timer_hi, 0x00000000);
+#endif
+
+ /* RXAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.rxaui_cfg, 0x00000007);
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel,
+ ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00063910);
+ al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x40003210);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401);
+
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg,
+ ETH_MAC_GEN_LED_CFG_SEL_MASK,
+ ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG);
+ break;
+
+ case AL_ETH_MAC_MODE_XLG_LL_40G:
+ /* configure and enable the ASYNC FIFO between the MACs and the EC */
+ /* TX min packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037);
+ /* TX max packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800);
+ /* TX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080);
+ /* TX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00010040);
+ /* TX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000023);
+ /* RX min packet size */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, 0x00000040); */
+ /* RX max packet size */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, 0x00002800); */
+ /* RX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00010040);
+ /* RX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080);
+ /* RX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000112);
+ /* V3 additional MAC selection */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000010);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x00000000);
+ /* ASYNC FIFO ENABLE */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333);
+
+ /* cmd_cfg */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_addr, 0x00000008);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_data, 0x01022810);
+ /* speed_ability //Read-Only */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_addr, 0x00000008); */
+ /* 40G capable */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_data, 0x00000002); */
+
+#ifdef AL_HAL_ETH_FAST_AN
+ al_eth_40g_pcs_reg_write(adapter, 0x00010004, 1023);
+ al_eth_40g_pcs_reg_write(adapter, 0x00000000, 0xA04c);
+ al_eth_40g_pcs_reg_write(adapter, 0x00000000, 0x204c);
+
+#endif
+
+ /* XAUI MAC control register */
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel,
+ ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x06883910);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x0000040f);
+
+ /* MAC register file */
+/* al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022810); */
+ /* XAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000005);
+ /* RXAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.rxaui_cfg, 0x00000007);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_cfg, 0x000001F1);
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */
+/* al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00073910); *//* XLG_LL_40G change */
+ al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10003210);
+/* al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0); *//* XLG_LL_40G change */
+/* al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401); *//* XLG_LL_40G change */
+
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg,
+ ETH_MAC_GEN_LED_CFG_SEL_MASK,
+ ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG);
+ break;
+
+ case AL_ETH_MAC_MODE_XLG_LL_50G:
+
+ /* configure and enable the ASYNC FIFO between the MACs and the EC */
+ /* TX min packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037);
+ /* TX max packet size */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800);
+ /* TX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080);
+ /* TX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00010040);
+ /* TX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000023);
+ /* RX min packet size */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, 0x00000040); */
+ /* RX max packet size */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, 0x00002800); */
+ /* RX input bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00010040);
+ /* RX output bus configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080);
+ /* RX Valid/ready configuration */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000112);
+ /* V3 additional MAC selection */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000010);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x00000000);
+ /* ASYNC FIFO ENABLE */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333);
+
+ /* cmd_cfg */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_addr, 0x00000008);
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_data, 0x01022810);
+ /* speed_ability //Read-Only */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_addr, 0x00000008); */
+ /* 40G capable */
+ /* al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_data, 0x00000002); */
+
+ /* select the 25G serdes for lanes 0/1 */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.ext_serdes_ctrl, 0x0382110F);
+ /* configure the PCS to work with 2 lanes */
+ /* configure which two of the 4 PCS Lanes (VL) are combined to one RXLAUI lane */
+ /* use VL 0-2 for RXLAUI lane 0, use VL 1-3 for RXLAUI lane 1 */
+ al_eth_40g_pcs_reg_write(adapter, 0x00010008, 0x0d81);
+ /* configure the PCS to work 32 bit interface */
+ al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_cfg, 0x00440000);
+
+
+#ifdef AL_HAL_ETH_FAST_AN
+ al_eth_40g_pcs_reg_write(adapter, 0x00010004, 1023);
+ al_eth_40g_pcs_reg_write(adapter, 0x00000000, 0xA04c);
+ al_eth_40g_pcs_reg_write(adapter, 0x00000000, 0x204c);
+#endif
+
+ /* XAUI MAC control register */
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x06883910);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x0000040f);
+
+ /* MAC register file */
+/* al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022810); */
+ /* XAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000005);
+ /* RXAUI MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->gen.rxaui_cfg, 0x00000007);
+ al_reg_write32(&adapter->mac_regs_base->gen.sd_cfg, 0x000001F1);
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */
+ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401);
+/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */
+/* al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00073910); *//* XLG_LL_40G change */
+ al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10003210);
+/* al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0); *//* XLG_LL_40G change */
+/* al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401); *//* XLG_LL_40G change */
+
+ al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg,
+ ETH_MAC_GEN_LED_CFG_SEL_MASK,
+ ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG);
+ break;
+
+
+ default:
+ al_err("Eth: unsupported MAC mode %d", mode);
+ return -EPERM;
+ }
+ adapter->mac_mode = mode;
+ al_info("configured MAC to %s mode:\n", al_eth_mac_mode_str(mode));
+
+ return 0;
+}
+
+/* start the mac */
+int al_eth_mac_start(struct al_hal_eth_adapter *adapter)
+{
+ if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) {
+ /* 1G MAC control register */
+ al_reg_write32_masked(&adapter->mac_regs_base->mac_1g.cmd_cfg, 0x3, 0x3);
+ } else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) {
+ /* 10G MAC control register */
+ al_reg_write32_masked(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x3, 0x3);
+ } else {
+ uint32_t cmd_cfg;
+
+ cmd_cfg = al_eth_40g_mac_reg_read(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR);
+
+ cmd_cfg |= (ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_TX_ENA |
+ ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_RX_ENA);
+
+ al_eth_40g_mac_reg_write(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR, cmd_cfg);
+ }
+
+ return 0;
+}
+
+/* stop the mac */
+int al_eth_mac_stop(struct al_hal_eth_adapter *adapter)
+{
+ if (AL_ETH_IS_1G_MAC(adapter->mac_mode))
+ /* 1G MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, 0x0);
+ else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode))
+ /* 10G MAC control register */
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x0);
+ else
+ al_eth_40g_mac_reg_write(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR, 0);
+
+ return 0;
+}
+
+int al_eth_capabilities_get(struct al_hal_eth_adapter *adapter, struct al_eth_capabilities *caps)
+{
+ al_assert(caps);
+
+ caps->speed_10_HD = AL_FALSE;
+ caps->speed_10_FD = AL_FALSE;
+ caps->speed_100_HD = AL_FALSE;
+ caps->speed_100_FD = AL_FALSE;
+ caps->speed_1000_HD = AL_FALSE;
+ caps->speed_1000_FD = AL_FALSE;
+ caps->speed_10000_HD = AL_FALSE;
+ caps->speed_10000_FD = AL_FALSE;
+ caps->pfc = AL_FALSE;
+ caps->eee = AL_FALSE;
+
+ switch (adapter->mac_mode) {
+ case AL_ETH_MAC_MODE_RGMII:
+ case AL_ETH_MAC_MODE_SGMII:
+ caps->speed_10_HD = AL_TRUE;
+ caps->speed_10_FD = AL_TRUE;
+ caps->speed_100_HD = AL_TRUE;
+ caps->speed_100_FD = AL_TRUE;
+ caps->speed_1000_FD = AL_TRUE;
+ caps->eee = AL_TRUE;
+ break;
+ case AL_ETH_MAC_MODE_10GbE_Serial:
+ caps->speed_10000_FD = AL_TRUE;
+ caps->pfc = AL_TRUE;
+ break;
+ default:
+ al_err("Eth: unsupported MAC mode %d", adapter->mac_mode);
+ return -EPERM;
+ }
+ return 0;
+}
+
+/* update link speed and duplex mode */
+int al_eth_mac_link_config(struct al_hal_eth_adapter *adapter,
+ al_bool force_1000_base_x,
+ al_bool an_enable,
+ uint32_t speed,
+ al_bool full_duplex)
+{
+ uint32_t mac_ctrl;
+ uint32_t sgmii_ctrl = 0;
+ uint32_t sgmii_if_mode = 0;
+ uint32_t rgmii_ctrl = 0;
+
+ if (!AL_ETH_IS_1G_MAC(adapter->mac_mode)) {
+ al_err("eth [%s]: this function not supported in this mac mode.\n",
+ adapter->name);
+ return -EINVAL;
+ }
+
+ if ((adapter->mac_mode != AL_ETH_MAC_MODE_RGMII) && (an_enable)) {
+ /*
+ * an_enable is not relevant to RGMII mode.
+ * in AN mode speed and duplex aren't relevant.
+ */
+ al_info("eth [%s]: set auto negotiation to enable\n", adapter->name);
+ } else {
+ al_info("eth [%s]: set link speed to %dMbps. %s duplex.\n", adapter->name,
+ speed, full_duplex == AL_TRUE ? "full" : "half");
+
+ if ((speed != 10) && (speed != 100) && (speed != 1000)) {
+ al_err("eth [%s]: bad speed parameter (%d).\n",
+ adapter->name, speed);
+ return -EINVAL;
+ }
+ if ((speed == 1000) && (full_duplex == AL_FALSE)) {
+ al_err("eth [%s]: half duplex in 1Gbps is not supported.\n",
+ adapter->name);
+ return -EINVAL;
+ }
+ }
+
+ mac_ctrl = al_reg_read32(&adapter->mac_regs_base->mac_1g.cmd_cfg);
+
+ if (adapter->mac_mode == AL_ETH_MAC_MODE_SGMII) {
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr,
+ ETH_MAC_SGMII_REG_ADDR_CTRL_REG);
+ sgmii_ctrl = al_reg_read32(&adapter->mac_regs_base->sgmii.reg_data);
+ /*
+ * in case bit 0 is off in sgmii_if_mode register all the other
+ * bits are ignored.
+ */
+ if (force_1000_base_x == AL_FALSE)
+ sgmii_if_mode = ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_EN;
+
+ if (an_enable == AL_TRUE) {
+ sgmii_if_mode |= ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_AN;
+ sgmii_ctrl |= ETH_MAC_SGMII_REG_DATA_CTRL_AN_ENABLE;
+ } else {
+ sgmii_ctrl &= ~(ETH_MAC_SGMII_REG_DATA_CTRL_AN_ENABLE);
+ }
+ }
+
+ if (adapter->mac_mode == AL_ETH_MAC_MODE_RGMII) {
+ /*
+ * Use the speed provided by the MAC instead of the PHY
+ */
+ rgmii_ctrl = al_reg_read32(&adapter->mac_regs_base->gen.rgmii_cfg);
+
+ AL_REG_MASK_CLEAR(rgmii_ctrl, ETH_MAC_GEN_RGMII_CFG_ENA_AUTO);
+ AL_REG_MASK_CLEAR(rgmii_ctrl, ETH_MAC_GEN_RGMII_CFG_SET_1000_SEL);
+ AL_REG_MASK_CLEAR(rgmii_ctrl, ETH_MAC_GEN_RGMII_CFG_SET_10_SEL);
+
+ al_reg_write32(&adapter->mac_regs_base->gen.rgmii_cfg, rgmii_ctrl);
+ }
+
+ if (full_duplex == AL_TRUE) {
+ AL_REG_MASK_CLEAR(mac_ctrl, AL_ETH_1G_MAC_CTRL_HD_EN);
+ } else {
+ AL_REG_MASK_SET(mac_ctrl, AL_ETH_1G_MAC_CTRL_HD_EN);
+ sgmii_if_mode |= ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_DUPLEX;
+ }
+
+ if (speed == 1000) {
+ AL_REG_MASK_SET(mac_ctrl, AL_ETH_1G_MAC_CTRL_1G_SPD);
+ sgmii_if_mode |= ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_SPEED_1000;
+ } else {
+ AL_REG_MASK_CLEAR(mac_ctrl, AL_ETH_1G_MAC_CTRL_1G_SPD);
+ if (speed == 10) {
+ AL_REG_MASK_SET(mac_ctrl, AL_ETH_1G_MAC_CTRL_10M_SPD);
+ } else {
+ sgmii_if_mode |= ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_SPEED_100;
+ AL_REG_MASK_CLEAR(mac_ctrl, AL_ETH_1G_MAC_CTRL_10M_SPD);
+ }
+ }
+
+ if (adapter->mac_mode == AL_ETH_MAC_MODE_SGMII) {
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr,
+ ETH_MAC_SGMII_REG_ADDR_IF_MODE_REG);
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data,
+ sgmii_if_mode);
+
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr,
+ ETH_MAC_SGMII_REG_ADDR_CTRL_REG);
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data,
+ sgmii_ctrl);
+ }
+
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, mac_ctrl);
+
+ return 0;
+}
+
+int al_eth_mac_loopback_config(struct al_hal_eth_adapter *adapter, int enable)
+{
+ const char *state = (enable) ? "enable" : "disable";
+
+ al_dbg("eth [%s]: loopback %s\n", adapter->name, state);
+ if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) {
+ uint32_t reg;
+ reg = al_reg_read32(&adapter->mac_regs_base->mac_1g.cmd_cfg);
+ if (enable)
+ reg |= AL_BIT(15);
+ else
+ reg &= ~AL_BIT(15);
+ al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, reg);
+ } else if ((AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode))
+ && (adapter->rev_id == AL_ETH_REV_ID_3)) {
+ uint32_t reg;
+ al_reg_write16(
+ (uint16_t *)&adapter->mac_regs_base->kr.pcs_addr, ETH_MAC_KR_PCS_CONTROL_1_ADDR);
+ reg = al_reg_read16(
+ (uint16_t *)&adapter->mac_regs_base->kr.pcs_data);
+ if (enable)
+ reg |= AL_BIT(14);
+ else
+ reg &= ~AL_BIT(14);
+ al_reg_write16(
+ (uint16_t *)&adapter->mac_regs_base->kr.pcs_addr, ETH_MAC_KR_PCS_CONTROL_1_ADDR);
+ al_reg_write16(
+ (uint16_t *)&adapter->mac_regs_base->kr.pcs_data, reg);
+ } else if (adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_40G ||
+ (adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_50G)) {
+ uint32_t reg;
+ reg = al_eth_40g_pcs_reg_read(adapter, ETH_MAC_GEN_V3_PCS_40G_CONTROL_STATUS_ADDR);
+ if (enable)
+ reg |= AL_BIT(14);
+ else
+ reg &= ~AL_BIT(14);
+ al_eth_40g_pcs_reg_write(adapter, ETH_MAC_GEN_V3_PCS_40G_CONTROL_STATUS_ADDR, reg);
+ } else {
+ al_err("Eth: mac loopback not supported in this mode %d", adapter->mac_mode);
+ return -EPERM;
+ }
+ return 0;
+}
+
+/* MDIO */
+int al_eth_mdio_config(
+ struct al_hal_eth_adapter *adapter,
+ enum al_eth_mdio_type mdio_type,
+ al_bool shared_mdio_if,
+ enum al_eth_ref_clk_freq ref_clk_freq,
+ unsigned int mdio_clk_freq_khz)
+{
+ enum al_eth_mdio_if mdio_if = AL_ETH_MDIO_IF_10G_MAC;
+ const char *if_name = (mdio_if == AL_ETH_MDIO_IF_1G_MAC) ? "10/100/1G MAC" : "10G MAC";
+ const char *type_name = (mdio_type == AL_ETH_MDIO_TYPE_CLAUSE_22) ? "Clause 22" : "Clause 45";
+ const char *shared_name = (shared_mdio_if == AL_TRUE) ? "Yes" : "No";
+
+ unsigned int ref_clk_freq_khz;
+ uint32_t val;
+
+ al_dbg("eth [%s]: mdio config: interface %s. type %s. shared: %s\n", adapter->name, if_name, type_name, shared_name);
+ adapter->shared_mdio_if = shared_mdio_if;
+
+ val = al_reg_read32(&adapter->mac_regs_base->gen.cfg);
+ al_dbg("eth [%s]: mdio config: 10G mac \n", adapter->name);
+
+ switch(mdio_if)
+ {
+ case AL_ETH_MDIO_IF_1G_MAC:
+ val &= ~AL_BIT(10);
+ break;
+ case AL_ETH_MDIO_IF_10G_MAC:
+ val |= AL_BIT(10);
+ break;
+ }
+ al_reg_write32(&adapter->mac_regs_base->gen.cfg, val);
+ adapter->mdio_if = mdio_if;
+
+
+ if (mdio_if == AL_ETH_MDIO_IF_10G_MAC)
+ {
+ val = al_reg_read32(&adapter->mac_regs_base->mac_10g.mdio_cfg_status);
+ switch(mdio_type)
+ {
+ case AL_ETH_MDIO_TYPE_CLAUSE_22:
+ val &= ~AL_BIT(6);
+ break;
+ case AL_ETH_MDIO_TYPE_CLAUSE_45:
+ val |= AL_BIT(6);
+ break;
+ }
+
+ /* set clock div to get 'mdio_clk_freq_khz' */
+ switch (ref_clk_freq) {
+ default:
+ al_err("eth [%s]: %s: invalid reference clock frequency"
+ " (%d)\n",
+ adapter->name, __func__, ref_clk_freq);
+ case AL_ETH_REF_FREQ_375_MHZ:
+ ref_clk_freq_khz = 375000;
+ break;
+ case AL_ETH_REF_FREQ_187_5_MHZ:
+ ref_clk_freq_khz = 187500;
+ break;
+ case AL_ETH_REF_FREQ_250_MHZ:
+ ref_clk_freq_khz = 250000;
+ break;
+ case AL_ETH_REF_FREQ_500_MHZ:
+ ref_clk_freq_khz = 500000;
+ break;
+ case AL_ETH_REF_FREQ_428_MHZ:
+ ref_clk_freq_khz = 428000;
+ break;
+ };
+
+ val &= ~(0x1FF << 7);
+ val |= (ref_clk_freq_khz / (2 * mdio_clk_freq_khz)) << 7;
+ AL_REG_FIELD_SET(val, ETH_10G_MAC_MDIO_CFG_HOLD_TIME_MASK,
+ ETH_10G_MAC_MDIO_CFG_HOLD_TIME_SHIFT,
+ ETH_10G_MAC_MDIO_CFG_HOLD_TIME_7_CLK);
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.mdio_cfg_status, val);
+ }else{
+ if(mdio_type != AL_ETH_MDIO_TYPE_CLAUSE_22) {
+ al_err("eth [%s] mdio type not supported for this interface\n",
+ adapter->name);
+ return -EINVAL;
+ }
+ }
+ adapter->mdio_type = mdio_type;
+
+ return 0;
+}
+
+static int al_eth_mdio_1g_mac_read(struct al_hal_eth_adapter *adapter,
+ uint32_t phy_addr __attribute__((__unused__)),
+ uint32_t reg, uint16_t *val)
+{
+ *val = al_reg_read32(
+ &adapter->mac_regs_base->mac_1g.phy_regs_base + reg);
+ return 0;
+}
+
+static int al_eth_mdio_1g_mac_write(struct al_hal_eth_adapter *adapter,
+ uint32_t phy_addr __attribute__((__unused__)),
+ uint32_t reg, uint16_t val)
+{
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_1g.phy_regs_base + reg, val);
+ return 0;
+}
+
+static int al_eth_mdio_10g_mac_wait_busy(struct al_hal_eth_adapter *adapter)
+{
+ int count = 0;
+ uint32_t mdio_cfg_status;
+
+ do {
+ mdio_cfg_status = al_reg_read32(&adapter->mac_regs_base->mac_10g.mdio_cfg_status);
+/*
+ if (mdio_cfg_status & AL_BIT(1)){ //error
+ al_err(" %s mdio read failed on error. phy_addr 0x%x reg 0x%x\n",
+ udma_params.name, phy_addr, reg);
+ return -EIO;
+ }*/
+ if (mdio_cfg_status & AL_BIT(0)){
+ if (count > 0)
+ al_dbg("eth [%s] mdio: still busy!\n", adapter->name);
+ }else{
+ return 0;
+ }
+ al_udelay(AL_ETH_MDIO_DELAY_PERIOD);
+ }while(count++ < AL_ETH_MDIO_DELAY_COUNT);
+
+ return -ETIMEDOUT;
+}
+
+static int al_eth_mdio_10g_mac_type22(
+ struct al_hal_eth_adapter *adapter,
+ int read, uint32_t phy_addr, uint32_t reg, uint16_t *val)
+{
+ int rc;
+ const char *op = (read == 1) ? "read":"write";
+ uint32_t mdio_cfg_status;
+ uint16_t mdio_cmd;
+
+ //wait if the HW is busy
+ rc = al_eth_mdio_10g_mac_wait_busy(adapter);
+ if (rc) {
+ al_err(" eth [%s] mdio %s failed. HW is busy\n", adapter->name, op);
+ return rc;
+ }
+
+ mdio_cmd = (uint16_t)(0x1F & reg);
+ mdio_cmd |= (0x1F & phy_addr) << 5;
+
+ if (read)
+ mdio_cmd |= AL_BIT(15); //READ command
+
+ al_reg_write16(&adapter->mac_regs_base->mac_10g.mdio_cmd,
+ mdio_cmd);
+ if (!read)
+ al_reg_write16(&adapter->mac_regs_base->mac_10g.mdio_data,
+ *val);
+
+ //wait for the busy to clear
+ rc = al_eth_mdio_10g_mac_wait_busy(adapter);
+ if (rc != 0) {
+ al_err(" %s mdio %s failed on timeout\n", adapter->name, op);
+ return -ETIMEDOUT;
+ }
+
+ mdio_cfg_status = al_reg_read32(&adapter->mac_regs_base->mac_10g.mdio_cfg_status);
+
+ if (mdio_cfg_status & AL_BIT(1)){ //error
+ al_err(" %s mdio %s failed on error. phy_addr 0x%x reg 0x%x\n",
+ adapter->name, op, phy_addr, reg);
+ return -EIO;
+ }
+ if (read)
+ *val = al_reg_read16(
+ (uint16_t *)&adapter->mac_regs_base->mac_10g.mdio_data);
+ return 0;
+}
+
+static int al_eth_mdio_10g_mac_type45(
+ struct al_hal_eth_adapter *adapter,
+ int read, uint32_t port_addr, uint32_t device, uint32_t reg, uint16_t *val)
+{
+ int rc;
+ const char *op = (read == 1) ? "read":"write";
+ uint32_t mdio_cfg_status;
+ uint16_t mdio_cmd;
+
+ //wait if the HW is busy
+ rc = al_eth_mdio_10g_mac_wait_busy(adapter);
+ if (rc) {
+ al_err(" %s mdio %s failed. HW is busy\n", adapter->name, op);
+ return rc;
+ }
+ // set command register
+ mdio_cmd = (uint16_t)(0x1F & device);
+ mdio_cmd |= (0x1F & port_addr) << 5;
+ al_reg_write16(&adapter->mac_regs_base->mac_10g.mdio_cmd,
+ mdio_cmd);
+
+ // send address frame
+ al_reg_write16(&adapter->mac_regs_base->mac_10g.mdio_regaddr, reg);
+ //wait for the busy to clear
+ rc = al_eth_mdio_10g_mac_wait_busy(adapter);
+ if (rc) {
+ al_err(" %s mdio %s (address frame) failed on timeout\n", adapter->name, op);
+ return rc;
+ }
+
+ // if read, write again to the command register with READ bit set
+ if (read) {
+ mdio_cmd |= AL_BIT(15); //READ command
+ al_reg_write16(
+ (uint16_t *)&adapter->mac_regs_base->mac_10g.mdio_cmd,
+ mdio_cmd);
+ } else {
+ al_reg_write16(
+ (uint16_t *)&adapter->mac_regs_base->mac_10g.mdio_data,
+ *val);
+ }
+ //wait for the busy to clear
+ rc = al_eth_mdio_10g_mac_wait_busy(adapter);
+ if (rc) {
+ al_err(" %s mdio %s failed on timeout\n", adapter->name, op);
+ return rc;
+ }
+
+ mdio_cfg_status = al_reg_read32(&adapter->mac_regs_base->mac_10g.mdio_cfg_status);
+
+ if (mdio_cfg_status & AL_BIT(1)){ //error
+ al_err(" %s mdio %s failed on error. port 0x%x, device 0x%x reg 0x%x\n",
+ adapter->name, op, port_addr, device, reg);
+ return -EIO;
+ }
+ if (read)
+ *val = al_reg_read16(
+ (uint16_t *)&adapter->mac_regs_base->mac_10g.mdio_data);
+ return 0;
+}
+
+/**
+ * acquire mdio interface ownership
+ * when mdio interface shared between multiple eth controllers, this function waits until the ownership granted for this controller.
+ * this function does nothing when the mdio interface is used only by this controller.
+ *
+ * @param adapter
+ * @return 0 on success, -ETIMEDOUT on timeout.
+ */
+static int al_eth_mdio_lock(struct al_hal_eth_adapter *adapter)
+{
+ int count = 0;
+ uint32_t mdio_ctrl_1;
+
+ if (adapter->shared_mdio_if == AL_FALSE)
+ return 0; /* nothing to do when interface is not shared */
+
+ do {
+ mdio_ctrl_1 = al_reg_read32(&adapter->mac_regs_base->gen.mdio_ctrl_1);
+/*
+ if (mdio_cfg_status & AL_BIT(1)){ //error
+ al_err(" %s mdio read failed on error. phy_addr 0x%x reg 0x%x\n",
+ udma_params.name, phy_addr, reg);
+ return -EIO;
+ }*/
+ if (mdio_ctrl_1 & AL_BIT(0)){
+ if (count > 0)
+ al_dbg("eth %s mdio interface still busy!\n", adapter->name);
+ }else{
+ return 0;
+ }
+ al_udelay(AL_ETH_MDIO_DELAY_PERIOD);
+ }while(count++ < (AL_ETH_MDIO_DELAY_COUNT * 4));
+ al_err(" %s mdio failed to take ownership. MDIO info reg: 0x%08x\n",
+ adapter->name, al_reg_read32(&adapter->mac_regs_base->gen.mdio_1));
+
+ return -ETIMEDOUT;
+}
+
+/**
+ * free mdio interface ownership
+ * when mdio interface shared between multiple eth controllers, this function releases the ownership granted for this controller.
+ * this function does nothing when the mdio interface is used only by this controller.
+ *
+ * @param adapter
+ * @return 0.
+ */
+static int al_eth_mdio_free(struct al_hal_eth_adapter *adapter)
+{
+ if (adapter->shared_mdio_if == AL_FALSE)
+ return 0; /* nothing to do when interface is not shared */
+
+ al_reg_write32(&adapter->mac_regs_base->gen.mdio_ctrl_1, 0);
+
+ /*
+ * Addressing RMN: 2917
+ *
+ * RMN description:
+ * The HW spin-lock is stateless and doesn't maintain any scheduling
+ * policy.
+ *
+ * Software flow:
+ * After getting the lock wait 2 times the delay period in order to give
+ * the other port chance to take the lock and prevent starvation.
+ * This is not scalable to more than two ports.
+ */
+ al_udelay(2 * AL_ETH_MDIO_DELAY_PERIOD);
+
+ return 0;
+}
+
+int al_eth_mdio_read(struct al_hal_eth_adapter *adapter, uint32_t phy_addr, uint32_t device, uint32_t reg, uint16_t *val)
+{
+ int rc;
+ rc = al_eth_mdio_lock(adapter);
+
+ /*"interface ownership taken"*/
+ if (rc)
+ return rc;
+
+ if (adapter->mdio_if == AL_ETH_MDIO_IF_1G_MAC)
+ rc = al_eth_mdio_1g_mac_read(adapter, phy_addr, reg, val);
+ else
+ if (adapter->mdio_type == AL_ETH_MDIO_TYPE_CLAUSE_22)
+ rc = al_eth_mdio_10g_mac_type22(adapter, 1, phy_addr, reg, val);
+ else
+ rc = al_eth_mdio_10g_mac_type45(adapter, 1, phy_addr, device, reg, val);
+
+ al_eth_mdio_free(adapter);
+ al_dbg("eth mdio read: phy_addr %x, device %x, reg %x val %x\n", phy_addr, device, reg, *val);
+ return rc;
+}
+
+int al_eth_mdio_write(struct al_hal_eth_adapter *adapter, uint32_t phy_addr, uint32_t device, uint32_t reg, uint16_t val)
+{
+ int rc;
+ al_dbg("eth mdio write: phy_addr %x, device %x, reg %x, val %x\n", phy_addr, device, reg, val);
+ rc = al_eth_mdio_lock(adapter);
+ /* interface ownership taken */
+ if (rc)
+ return rc;
+
+ if (adapter->mdio_if == AL_ETH_MDIO_IF_1G_MAC)
+ rc = al_eth_mdio_1g_mac_write(adapter, phy_addr, reg, val);
+ else
+ if (adapter->mdio_type == AL_ETH_MDIO_TYPE_CLAUSE_22)
+ rc = al_eth_mdio_10g_mac_type22(adapter, 0, phy_addr, reg, &val);
+ else
+ rc = al_eth_mdio_10g_mac_type45(adapter, 0, phy_addr, device, reg, &val);
+
+ al_eth_mdio_free(adapter);
+ return rc;
+}
+
+static void al_dump_tx_desc(union al_udma_desc *tx_desc)
+{
+ uint32_t *ptr = (uint32_t *)tx_desc;
+ al_dbg("eth tx desc:\n");
+ al_dbg("0x%08x\n", *(ptr++));
+ al_dbg("0x%08x\n", *(ptr++));
+ al_dbg("0x%08x\n", *(ptr++));
+ al_dbg("0x%08x\n", *(ptr++));
+}
+
+static void
+al_dump_tx_pkt(struct al_udma_q *tx_dma_q, struct al_eth_pkt *pkt)
+{
+ const char *tso = (pkt->flags & AL_ETH_TX_FLAGS_TSO) ? "TSO" : "";
+ const char *l3_csum = (pkt->flags & AL_ETH_TX_FLAGS_IPV4_L3_CSUM) ? "L3 CSUM" : "";
+ const char *l4_csum = (pkt->flags & AL_ETH_TX_FLAGS_L4_CSUM) ?
+ ((pkt->flags & AL_ETH_TX_FLAGS_L4_PARTIAL_CSUM) ? "L4 PARTIAL CSUM" : "L4 FULL CSUM") : "";
+ const char *fcs = (pkt->flags & AL_ETH_TX_FLAGS_L2_DIS_FCS) ? "Disable FCS" : "";
+ const char *ptp = (pkt->flags & AL_ETH_TX_FLAGS_TS) ? "TX_PTP" : "";
+ const char *l3_proto_name = "unknown";
+ const char *l4_proto_name = "unknown";
+ const char *outer_l3_proto_name = "N/A";
+ const char *tunnel_mode = ((pkt->tunnel_mode & AL_ETH_TUNNEL_WITH_UDP) ==
+ AL_ETH_TUNNEL_WITH_UDP) ?
+ "TUNNEL_WITH_UDP" :
+ ((pkt->tunnel_mode & AL_ETH_TUNNEL_NO_UDP) ==
+ AL_ETH_TUNNEL_NO_UDP) ?
+ "TUNNEL_NO_UDP" : "";
+ uint32_t total_len = 0;
+ int i;
+
+ al_dbg("[%s %d]: flags: %s %s %s %s %s %s\n", tx_dma_q->udma->name, tx_dma_q->qid,
+ tso, l3_csum, l4_csum, fcs, ptp, tunnel_mode);
+
+ switch (pkt->l3_proto_idx) {
+ case AL_ETH_PROTO_ID_IPv4:
+ l3_proto_name = "IPv4";
+ break;
+ case AL_ETH_PROTO_ID_IPv6:
+ l3_proto_name = "IPv6";
+ break;
+ default:
+ l3_proto_name = "unknown";
+ break;
+ }
+
+ switch (pkt->l4_proto_idx) {
+ case AL_ETH_PROTO_ID_TCP:
+ l4_proto_name = "TCP";
+ break;
+ case AL_ETH_PROTO_ID_UDP:
+ l4_proto_name = "UDP";
+ break;
+ default:
+ l4_proto_name = "unknown";
+ break;
+ }
+
+ switch (pkt->outer_l3_proto_idx) {
+ case AL_ETH_PROTO_ID_IPv4:
+ outer_l3_proto_name = "IPv4";
+ break;
+ case AL_ETH_PROTO_ID_IPv6:
+ outer_l3_proto_name = "IPv6";
+ break;
+ default:
+ outer_l3_proto_name = "N/A";
+ break;
+ }
+
+ al_dbg("[%s %d]: L3 proto: %d (%s). L4 proto: %d (%s). Outer_L3 proto: %d (%s). vlan source count %d. mod add %d. mod del %d\n",
+ tx_dma_q->udma->name, tx_dma_q->qid, pkt->l3_proto_idx,
+ l3_proto_name, pkt->l4_proto_idx, l4_proto_name,
+ pkt->outer_l3_proto_idx, outer_l3_proto_name,
+ pkt->source_vlan_count, pkt->vlan_mod_add_count,
+ pkt->vlan_mod_del_count);
+
+ if (pkt->meta) {
+ const char * store = pkt->meta->store ? "Yes" : "No";
+
+ al_dbg("[%s %d]: tx pkt with meta data. words valid %x\n",
+ tx_dma_q->udma->name, tx_dma_q->qid,
+ pkt->meta->words_valid);
+ if (tx_dma_q->adapter_rev_id == AL_ETH_REV_ID_0)
+ al_dbg("[%s %d]: meta: store to cache %s. l3 hdr len %d. l3 hdr offset %d. l4 hdr len %d. mss sel %d\n"
+ , tx_dma_q->udma->name, tx_dma_q->qid, store,
+ pkt->meta->l3_header_len, pkt->meta->l3_header_offset,
+ pkt->meta->l4_header_len,
+ pkt->meta->mss_idx_sel);
+ else {
+ const char *ptp_val = (pkt->flags & AL_ETH_TX_FLAGS_TS) ? "Yes" : "No";
+ al_dbg("[%s %d]: meta: store to cache %s. l3 hdr len %d. l3 hdr offset %d. l4 hdr len %d. mss val %d ts_index %d ts_val:%s\n"
+ , tx_dma_q->udma->name, tx_dma_q->qid, store,
+ pkt->meta->l3_header_len, pkt->meta->l3_header_offset,
+ pkt->meta->l4_header_len, pkt->meta->mss_val,
+ pkt->meta->ts_index, ptp_val);
+ al_dbg("outer_l3_hdr_offset %d. outer_l3_len %d.\n",
+ pkt->meta->outer_l3_offset, pkt->meta->outer_l3_len);
+ }
+ }
+
+ al_dbg("[%s %d]: num of bufs: %d\n", tx_dma_q->udma->name, tx_dma_q->qid,
+ pkt->num_of_bufs);
+ for (i = 0; i < pkt->num_of_bufs; i++) {
+ al_dbg("eth [%s %d]: buf[%d]: len 0x%08x. address 0x%016llx\n", tx_dma_q->udma->name, tx_dma_q->qid,
+ i, pkt->bufs[i].len, (unsigned long long)pkt->bufs[i].addr);
+ total_len += pkt->bufs[i].len;
+ }
+ al_dbg("[%s %d]: total len: 0x%08x\n", tx_dma_q->udma->name, tx_dma_q->qid, total_len);
+
+}
+
+/* TX */
+/**
+ * add packet to transmission queue
+ */
+int al_eth_tx_pkt_prepare(struct al_udma_q *tx_dma_q, struct al_eth_pkt *pkt)
+{
+ union al_udma_desc *tx_desc;
+ uint32_t tx_descs;
+ uint32_t flags = AL_M2S_DESC_FIRST |
+ AL_M2S_DESC_CONCAT |
+ (pkt->flags & AL_ETH_TX_FLAGS_INT);
+ uint64_t vmid = ((uint64_t)pkt->vmid) << AL_UDMA_DESC_VMID_SHIFT;
+ uint32_t meta_ctrl;
+ uint32_t ring_id;
+ int buf_idx;
+
+ al_dbg("[%s %d]: new tx pkt\n", tx_dma_q->udma->name, tx_dma_q->qid);
+
+ al_dump_tx_pkt(tx_dma_q, pkt);
+
+ tx_descs = pkt->num_of_bufs;
+ if (pkt->meta) {
+ tx_descs += 1;
+ }
+#ifdef AL_ETH_EX
+ al_assert((pkt->ext_meta_data == NULL) || (tx_dma_q->adapter_rev_id > AL_ETH_REV_ID_2));
+
+ tx_descs += al_eth_ext_metadata_needed_descs(pkt->ext_meta_data);
+ al_dbg("[%s %d]: %d Descriptors: ext_meta (%d). meta (%d). buffer (%d) ",
+ tx_dma_q->udma->name, tx_dma_q->qid, tx_descs,
+ al_eth_ext_metadata_needed_descs(pkt->ext_meta_data),
+ (pkt->meta != NULL), pkt->num_of_bufs);
+#endif
+
+ if (unlikely(al_udma_available_get(tx_dma_q) < tx_descs)) {
+ al_dbg("[%s %d]: failed to allocate (%d) descriptors",
+ tx_dma_q->udma->name, tx_dma_q->qid, tx_descs);
+ return 0;
+ }
+
+#ifdef AL_ETH_EX
+ if (pkt->ext_meta_data != NULL) {
+ al_eth_ext_metadata_create(tx_dma_q, &flags, pkt->ext_meta_data);
+ flags &= ~(AL_M2S_DESC_FIRST | AL_ETH_TX_FLAGS_INT);
+ }
+#endif
+
+ if (pkt->meta) {
+ uint32_t meta_word_0 = 0;
+ uint32_t meta_word_1 = 0;
+ uint32_t meta_word_2 = 0;
+ uint32_t meta_word_3 = 0;
+
+ meta_word_0 |= flags | AL_M2S_DESC_META_DATA;
+ meta_word_0 &= ~AL_M2S_DESC_CONCAT;
+ flags &= ~(AL_M2S_DESC_FIRST | AL_ETH_TX_FLAGS_INT);
+
+ tx_desc = al_udma_desc_get(tx_dma_q);
+ /* get ring id, and clear FIRST and Int flags */
+ ring_id = al_udma_ring_id_get(tx_dma_q) <<
+ AL_M2S_DESC_RING_ID_SHIFT;
+
+ meta_word_0 |= ring_id;
+ meta_word_0 |= pkt->meta->words_valid << 12;
+
+ if (pkt->meta->store)
+ meta_word_0 |= AL_ETH_TX_META_STORE;
+
+ if (pkt->meta->words_valid & 1) {
+ meta_word_0 |= pkt->meta->vlan1_cfi_sel;
+ meta_word_0 |= pkt->meta->vlan2_vid_sel << 2;
+ meta_word_0 |= pkt->meta->vlan2_cfi_sel << 4;
+ meta_word_0 |= pkt->meta->vlan2_pbits_sel << 6;
+ meta_word_0 |= pkt->meta->vlan2_ether_sel << 8;
+ }
+
+ if (pkt->meta->words_valid & 2) {
+ meta_word_1 = pkt->meta->vlan1_new_vid;
+ meta_word_1 |= pkt->meta->vlan1_new_cfi << 12;
+ meta_word_1 |= pkt->meta->vlan1_new_pbits << 13;
+ meta_word_1 |= pkt->meta->vlan2_new_vid << 16;
+ meta_word_1 |= pkt->meta->vlan2_new_cfi << 28;
+ meta_word_1 |= pkt->meta->vlan2_new_pbits << 29;
+ }
+
+ if (pkt->meta->words_valid & 4) {
+ meta_word_2 = pkt->meta->l3_header_len & AL_ETH_TX_META_L3_LEN_MASK;
+ meta_word_2 |= (pkt->meta->l3_header_offset & AL_ETH_TX_META_L3_OFF_MASK) <<
+ AL_ETH_TX_META_L3_OFF_SHIFT;
+ meta_word_2 |= (pkt->meta->l4_header_len & 0x3f) << 16;
+
+ if (tx_dma_q->adapter_rev_id == AL_ETH_REV_ID_0) {
+ meta_word_2 |= (pkt->meta->mss_idx_sel & 7) << 24;
+ } else {
+ uint32_t l3_offset;
+
+ if (unlikely(pkt->flags & AL_ETH_TX_FLAGS_TS))
+ meta_word_0 |= pkt->meta->ts_index << AL_ETH_TX_META_MSS_MSB_TS_VAL_SHIFT;
+ else
+ meta_word_0 |= (((pkt->meta->mss_val & 0x3c00) >> 10)
+ << AL_ETH_TX_META_MSS_MSB_TS_VAL_SHIFT);
+ meta_word_2 |= ((pkt->meta->mss_val & 0x03ff)
+ << AL_ETH_TX_META_MSS_LSB_VAL_SHIFT);
+
+ /*
+ * move from bytes to multiplication of 2 as the HW
+ * expect to get it
+ */
+ l3_offset = (pkt->meta->outer_l3_offset >> 1);
+
+ meta_word_0 |=
+ (((l3_offset &
+ AL_ETH_TX_META_OUTER_L3_OFF_HIGH_MASK) >> 3)
+ << AL_ETH_TX_META_OUTER_L3_OFF_HIGH_SHIFT);
+
+ meta_word_3 |=
+ ((l3_offset &
+ AL_ETH_TX_META_OUTER_L3_OFF_LOW_MASK)
+ << AL_ETH_TX_META_OUTER_L3_OFF_LOW_SHIFT);
+
+ /*
+ * shift right 2 bits to work in multiplication of 4
+ * as the HW expect to get it
+ */
+ meta_word_3 |=
+ (((pkt->meta->outer_l3_len >> 2) &
+ AL_ETH_TX_META_OUTER_L3_LEN_MASK)
+ << AL_ETH_TX_META_OUTER_L3_LEN_SHIFT);
+ }
+ }
+
+ tx_desc->tx_meta.len_ctrl = swap32_to_le(meta_word_0);
+ tx_desc->tx_meta.meta_ctrl = swap32_to_le(meta_word_1);
+ tx_desc->tx_meta.meta1 = swap32_to_le(meta_word_2);
+ tx_desc->tx_meta.meta2 = swap32_to_le(meta_word_3);
+ al_dump_tx_desc(tx_desc);
+ }
+
+ meta_ctrl = pkt->flags & AL_ETH_TX_PKT_META_FLAGS;
+
+ /* L4_PARTIAL_CSUM without L4_CSUM is invalid option */
+ al_assert((pkt->flags & (AL_ETH_TX_FLAGS_L4_CSUM|AL_ETH_TX_FLAGS_L4_PARTIAL_CSUM)) !=
+ AL_ETH_TX_FLAGS_L4_PARTIAL_CSUM);
+
+ /* TSO packets can't have Timestamp enabled */
+ al_assert((pkt->flags & (AL_ETH_TX_FLAGS_TSO|AL_ETH_TX_FLAGS_TS)) !=
+ (AL_ETH_TX_FLAGS_TSO|AL_ETH_TX_FLAGS_TS));
+
+ meta_ctrl |= pkt->l3_proto_idx;
+ meta_ctrl |= pkt->l4_proto_idx << AL_ETH_TX_L4_PROTO_IDX_SHIFT;
+ meta_ctrl |= pkt->source_vlan_count << AL_ETH_TX_SRC_VLAN_CNT_SHIFT;
+ meta_ctrl |= pkt->vlan_mod_add_count << AL_ETH_TX_VLAN_MOD_ADD_SHIFT;
+ meta_ctrl |= pkt->vlan_mod_del_count << AL_ETH_TX_VLAN_MOD_DEL_SHIFT;
+ meta_ctrl |= pkt->vlan_mod_v1_ether_sel << AL_ETH_TX_VLAN_MOD_E_SEL_SHIFT;
+ meta_ctrl |= pkt->vlan_mod_v1_vid_sel << AL_ETH_TX_VLAN_MOD_VID_SEL_SHIFT;
+ meta_ctrl |= pkt->vlan_mod_v1_pbits_sel << AL_ETH_TX_VLAN_MOD_PBIT_SEL_SHIFT;
+
+#ifdef AL_ETH_EX
+ if ((pkt->ext_meta_data != NULL) && (pkt->ext_meta_data->tx_crypto_data != NULL))
+ meta_ctrl |= AL_ETH_TX_FLAGS_ENCRYPT;
+#endif
+
+ if (tx_dma_q->adapter_rev_id > AL_ETH_REV_ID_0) {
+ meta_ctrl |= pkt->tunnel_mode << AL_ETH_TX_TUNNEL_MODE_SHIFT;
+ if (pkt->outer_l3_proto_idx == AL_ETH_PROTO_ID_IPv4)
+ meta_ctrl |= 1 << AL_ETH_TX_OUTER_L3_PROTO_SHIFT;
+ }
+
+ flags |= pkt->flags & AL_ETH_TX_PKT_UDMA_FLAGS;
+ for(buf_idx = 0; buf_idx < pkt->num_of_bufs; buf_idx++ ) {
+ uint32_t flags_len = flags;
+
+ tx_desc = al_udma_desc_get(tx_dma_q);
+ /* get ring id, and clear FIRST and Int flags */
+ ring_id = al_udma_ring_id_get(tx_dma_q) <<
+ AL_M2S_DESC_RING_ID_SHIFT;
+
+ flags_len |= ring_id;
+
+ if (buf_idx == (pkt->num_of_bufs - 1))
+ flags_len |= AL_M2S_DESC_LAST;
+
+ /* clear First and Int flags */
+ flags &= AL_ETH_TX_FLAGS_NO_SNOOP;
+ flags |= AL_M2S_DESC_CONCAT;
+
+ flags_len |= pkt->bufs[buf_idx].len & AL_M2S_DESC_LEN_MASK;
+ tx_desc->tx.len_ctrl = swap32_to_le(flags_len);
+ if (buf_idx == 0)
+ tx_desc->tx.meta_ctrl = swap32_to_le(meta_ctrl);
+ tx_desc->tx.buf_ptr = swap64_to_le(
+ pkt->bufs[buf_idx].addr | vmid);
+ al_dump_tx_desc(tx_desc);
+ }
+
+ al_dbg("[%s %d]: pkt descriptors written into the tx queue. descs num (%d)\n",
+ tx_dma_q->udma->name, tx_dma_q->qid, tx_descs);
+
+ return tx_descs;
+}
+
+
+void al_eth_tx_dma_action(struct al_udma_q *tx_dma_q, uint32_t tx_descs)
+{
+ /* add tx descriptors */
+ al_udma_desc_action_add(tx_dma_q, tx_descs);
+}
+
+/**
+ * get number of completed tx descriptors, upper layer should derive from
+ */
+int al_eth_comp_tx_get(struct al_udma_q *tx_dma_q)
+{
+ int rc;
+
+ rc = al_udma_cdesc_get_all(tx_dma_q, NULL);
+ if (rc != 0) {
+ al_udma_cdesc_ack(tx_dma_q, rc);
+ al_dbg("[%s %d]: tx completion: descs (%d)\n",
+ tx_dma_q->udma->name, tx_dma_q->qid, rc);
+ }
+
+ return rc;
+}
+
+/**
+ * configure the TSO MSS val
+ */
+int al_eth_tso_mss_config(struct al_hal_eth_adapter *adapter, uint8_t idx, uint32_t mss_val)
+{
+
+ al_assert(idx <= 8); /*valid MSS index*/
+ al_assert(mss_val <= AL_ETH_TSO_MSS_MAX_VAL); /*valid MSS val*/
+ al_assert(mss_val >= AL_ETH_TSO_MSS_MIN_VAL); /*valid MSS val*/
+
+ al_reg_write32(&adapter->ec_regs_base->tso_sel[idx].mss, mss_val);
+ return 0;
+}
+
+
+/* RX */
+/**
+ * config the rx descriptor fields
+ */
+void al_eth_rx_desc_config(
+ struct al_hal_eth_adapter *adapter,
+ enum al_eth_rx_desc_lro_context_val_res lro_sel,
+ enum al_eth_rx_desc_l4_offset_sel l4_offset_sel,
+ enum al_eth_rx_desc_l3_offset_sel l3_offset_sel,
+ enum al_eth_rx_desc_l4_chk_res_sel l4_sel,
+ enum al_eth_rx_desc_l3_chk_res_sel l3_sel,
+ enum al_eth_rx_desc_l3_proto_idx_sel l3_proto_sel,
+ enum al_eth_rx_desc_l4_proto_idx_sel l4_proto_sel,
+ enum al_eth_rx_desc_frag_sel frag_sel)
+{
+ uint32_t reg_val = 0;
+
+ reg_val |= (lro_sel == AL_ETH_L4_OFFSET) ?
+ EC_RFW_CFG_A_0_LRO_CONTEXT_SEL : 0;
+
+ reg_val |= (l4_sel == AL_ETH_L4_INNER_OUTER_CHK) ?
+ EC_RFW_CFG_A_0_META_L4_CHK_RES_SEL : 0;
+
+ reg_val |= l3_sel << EC_RFW_CFG_A_0_META_L3_CHK_RES_SEL_SHIFT;
+
+ al_reg_write32(&adapter->ec_regs_base->rfw.cfg_a_0, reg_val);
+
+ reg_val = al_reg_read32(&adapter->ec_regs_base->rfw.meta);
+ if (l3_proto_sel == AL_ETH_L3_PROTO_IDX_INNER)
+ reg_val |= EC_RFW_META_L3_PROT_SEL;
+ else
+ reg_val &= ~EC_RFW_META_L3_PROT_SEL;
+
+ if (l4_proto_sel == AL_ETH_L4_PROTO_IDX_INNER)
+ reg_val |= EC_RFW_META_L4_PROT_SEL;
+ else
+ reg_val &= ~EC_RFW_META_L4_PROT_SEL;
+
+ if (l4_offset_sel == AL_ETH_L4_OFFSET_INNER)
+ reg_val |= EC_RFW_META_L4_OFFSET_SEL;
+ else
+ reg_val &= ~EC_RFW_META_L4_OFFSET_SEL;
+
+ if (l3_offset_sel == AL_ETH_L3_OFFSET_INNER)
+ reg_val |= EC_RFW_META_L3_OFFSET_SEL;
+ else
+ reg_val &= ~EC_RFW_META_L3_OFFSET_SEL;
+
+ if (frag_sel == AL_ETH_FRAG_INNER)
+ reg_val |= EC_RFW_META_FRAG_SEL;
+ else
+ reg_val &= ~EC_RFW_META_FRAG_SEL;
+
+
+ al_reg_write32(&adapter->ec_regs_base->rfw.meta, reg_val);
+}
+
+/**
+ * Configure RX header split
+ */
+int al_eth_rx_header_split_config(struct al_hal_eth_adapter *adapter, al_bool enable, uint32_t header_len)
+{
+ uint32_t reg;
+
+ if (adapter->rev_id < AL_ETH_REV_ID_1) {
+ al_err("[%s]: header split feature not supported by this revision\n", adapter->name);
+ return -EINVAL;
+ }
+ reg = al_reg_read32(&adapter->ec_regs_base->rfw.hdr_split);
+ if (enable == AL_TRUE)
+ reg |= EC_RFW_HDR_SPLIT_EN;
+ else
+ reg &= ~EC_RFW_HDR_SPLIT_EN;
+
+ AL_REG_FIELD_SET(reg, EC_RFW_HDR_SPLIT_DEF_LEN_MASK, EC_RFW_HDR_SPLIT_DEF_LEN_SHIFT, header_len);
+ al_reg_write32(&adapter->ec_regs_base->rfw.hdr_split, reg);
+ return 0;
+}
+
+
+/**
+ * enable / disable header split in the udma queue.
+ * length will be taken from the udma configuration to enable different length per queue.
+ */
+int al_eth_rx_header_split_force_len_config(struct al_hal_eth_adapter *adapter,
+ al_bool enable,
+ uint32_t qid,
+ uint32_t header_len)
+{
+ al_udma_s2m_q_compl_hdr_split_config(&(adapter->rx_udma.udma_q[qid]), enable,
+ AL_TRUE, header_len);
+
+ return 0;
+}
+
+
+/**
+ * add buffer to receive queue
+ */
+int al_eth_rx_buffer_add(struct al_udma_q *rx_dma_q,
+ struct al_buf *buf, uint32_t flags,
+ struct al_buf *header_buf)
+{
+ uint64_t vmid = ((uint64_t)flags & AL_ETH_RX_FLAGS_VMID_MASK) <<
+ AL_UDMA_DESC_VMID_SHIFT;
+ uint32_t flags_len = flags & ~AL_ETH_RX_FLAGS_VMID_MASK;
+ union al_udma_desc *rx_desc;
+
+ al_dbg("[%s %d]: add rx buffer.\n", rx_dma_q->udma->name, rx_dma_q->qid);
+
+#if 1
+ if (unlikely(al_udma_available_get(rx_dma_q) < 1)) {
+ al_dbg("[%s]: rx q (%d) has no enough free descriptor",
+ rx_dma_q->udma->name, rx_dma_q->qid);
+ return -ENOSPC;
+ }
+#endif
+ rx_desc = al_udma_desc_get(rx_dma_q);
+
+ flags_len |= al_udma_ring_id_get(rx_dma_q) << AL_S2M_DESC_RING_ID_SHIFT;
+ flags_len |= buf->len & AL_S2M_DESC_LEN_MASK;
+
+ if (flags & AL_S2M_DESC_DUAL_BUF) {
+ al_assert(header_buf != NULL); /*header valid in dual buf */
+ al_assert((rx_dma_q->udma->rev_id >= AL_UDMA_REV_ID_2) ||
+ (AL_ADDR_HIGH(buf->addr) == AL_ADDR_HIGH(header_buf->addr)));
+
+ flags_len |= ((header_buf->len >> AL_S2M_DESC_LEN2_GRANULARITY_SHIFT)
+ << AL_S2M_DESC_LEN2_SHIFT) & AL_S2M_DESC_LEN2_MASK;
+ rx_desc->rx.buf2_ptr_lo = swap32_to_le(AL_ADDR_LOW(header_buf->addr));
+ }
+ rx_desc->rx.len_ctrl = swap32_to_le(flags_len);
+ rx_desc->rx.buf1_ptr = swap64_to_le(buf->addr | vmid);
+
+ return 0;
+}
+
+/**
+ * notify the hw engine about rx descriptors that were added to the receive queue
+ */
+void al_eth_rx_buffer_action(struct al_udma_q *rx_dma_q, uint32_t descs_num)
+{
+ al_dbg("[%s]: update the rx engine tail pointer: queue %d. descs %d\n",
+ rx_dma_q->udma->name, rx_dma_q->qid, descs_num);
+
+ /* add rx descriptor */
+ al_udma_desc_action_add(rx_dma_q, descs_num);
+}
+
+/**
+ * get packet from RX completion ring
+ */
+uint32_t al_eth_pkt_rx(struct al_udma_q *rx_dma_q,
+ struct al_eth_pkt *pkt)
+{
+ volatile union al_udma_cdesc *cdesc;
+ volatile al_eth_rx_cdesc *rx_desc;
+ uint32_t i;
+ uint32_t rc;
+
+ rc = al_udma_cdesc_packet_get(rx_dma_q, &cdesc);
+ if (rc == 0)
+ return 0;
+
+ al_assert(rc <= AL_ETH_PKT_MAX_BUFS);
+
+ al_dbg("[%s]: fetch rx packet: queue %d.\n",
+ rx_dma_q->udma->name, rx_dma_q->qid);
+
+ pkt->rx_header_len = 0;
+ for (i = 0; i < rc; i++) {
+ uint32_t buf1_len, buf2_len;
+
+ /* get next descriptor */
+ rx_desc = (volatile al_eth_rx_cdesc *)al_cdesc_next(rx_dma_q, cdesc, i);
+
+ buf1_len = swap32_from_le(rx_desc->len);
+
+ if ((i == 0) && (swap32_from_le(rx_desc->word2) &
+ AL_UDMA_CDESC_BUF2_USED)) {
+ buf2_len = swap32_from_le(rx_desc->word2);
+ pkt->rx_header_len = (buf2_len & AL_S2M_DESC_LEN2_MASK) >>
+ AL_S2M_DESC_LEN2_SHIFT;
+ }
+ if ((swap32_from_le(rx_desc->ctrl_meta) & AL_UDMA_CDESC_BUF1_USED) &&
+ ((swap32_from_le(rx_desc->ctrl_meta) & AL_UDMA_CDESC_DDP) == 0))
+ pkt->bufs[i].len = buf1_len & AL_S2M_DESC_LEN_MASK;
+ else
+ pkt->bufs[i].len = 0;
+ }
+ /* get flags from last desc */
+ pkt->flags = swap32_from_le(rx_desc->ctrl_meta);
+#ifdef AL_ETH_RX_DESC_RAW_GET
+ pkt->rx_desc_raw[0] = pkt->flags;
+ pkt->rx_desc_raw[1] = swap32_from_le(rx_desc->len);
+ pkt->rx_desc_raw[2] = swap32_from_le(rx_desc->word2);
+ pkt->rx_desc_raw[3] = swap32_from_le(rx_desc->word3);
+#endif
+ /* update L3/L4 proto index */
+ pkt->l3_proto_idx = pkt->flags & AL_ETH_RX_L3_PROTO_IDX_MASK;
+ pkt->l4_proto_idx = (pkt->flags >> AL_ETH_RX_L4_PROTO_IDX_SHIFT) &
+ AL_ETH_RX_L4_PROTO_IDX_MASK;
+ pkt->rxhash = (swap32_from_le(rx_desc->len) & AL_ETH_RX_HASH_MASK) >>
+ AL_ETH_RX_HASH_SHIFT;
+ pkt->l3_offset = (swap32_from_le(rx_desc->word2) & AL_ETH_RX_L3_OFFSET_MASK) >> AL_ETH_RX_L3_OFFSET_SHIFT;
+
+ al_udma_cdesc_ack(rx_dma_q, rc);
+ return rc;
+}
+
+
+int al_eth_rx_parser_entry_update(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ struct al_eth_epe_p_reg_entry *reg_entry,
+ struct al_eth_epe_control_entry *control_entry)
+{
+ al_eth_epe_entry_set(adapter, idx, reg_entry, control_entry);
+ return 0;
+}
+
+#define AL_ETH_THASH_UDMA_SHIFT 0
+#define AL_ETH_THASH_UDMA_MASK (0xF << AL_ETH_THASH_UDMA_SHIFT)
+
+#define AL_ETH_THASH_Q_SHIFT 4
+#define AL_ETH_THASH_Q_MASK (0x3 << AL_ETH_THASH_Q_SHIFT)
+
+int al_eth_thash_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t udma, uint32_t queue)
+{
+ uint32_t entry;
+ al_assert(idx < AL_ETH_RX_THASH_TABLE_SIZE); /*valid THASH index*/
+
+ entry = (udma << AL_ETH_THASH_UDMA_SHIFT) & AL_ETH_THASH_UDMA_MASK;
+ entry |= (queue << AL_ETH_THASH_Q_SHIFT) & AL_ETH_THASH_Q_MASK;
+
+ al_reg_write32(&adapter->ec_regs_base->rfw.thash_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->rfw.thash_table_data, entry);
+ return 0;
+}
+
+int al_eth_fsm_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t entry)
+{
+
+ al_assert(idx < AL_ETH_RX_FSM_TABLE_SIZE); /*valid FSM index*/
+
+
+ al_reg_write32(&adapter->ec_regs_base->rfw.fsm_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->rfw.fsm_table_data, entry);
+ return 0;
+}
+
+static uint32_t al_eth_fwd_ctrl_entry_to_val(struct al_eth_fwd_ctrl_table_entry *entry)
+{
+ uint32_t val = 0;
+ AL_REG_FIELD_SET(val, AL_FIELD_MASK(3,0), 0, entry->prio_sel);
+ AL_REG_FIELD_SET(val, AL_FIELD_MASK(7,4), 4, entry->queue_sel_1);
+ AL_REG_FIELD_SET(val, AL_FIELD_MASK(9,8), 8, entry->queue_sel_2);
+ AL_REG_FIELD_SET(val, AL_FIELD_MASK(13,10), 10, entry->udma_sel);
+ AL_REG_FIELD_SET(val, AL_FIELD_MASK(17,15), 15, entry->hdr_split_len_sel);
+ if (entry->hdr_split_len_sel != AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL_0)
+ val |= AL_BIT(18);
+ AL_REG_BIT_VAL_SET(val, 19, !!(entry->filter == AL_TRUE));
+
+ return val;
+}
+
+static int al_eth_ctrl_index_match(struct al_eth_fwd_ctrl_table_index *index, uint32_t i) {
+ if ((index->vlan_table_out != AL_ETH_FWD_CTRL_IDX_VLAN_TABLE_OUT_ANY)
+ && (index->vlan_table_out != AL_REG_BIT_GET(i, 0)))
+ return 0;
+ if ((index->tunnel_exist != AL_ETH_FWD_CTRL_IDX_TUNNEL_ANY)
+ && (index->tunnel_exist != AL_REG_BIT_GET(i, 1)))
+ return 0;
+ if ((index->vlan_exist != AL_ETH_FWD_CTRL_IDX_VLAN_ANY)
+ && (index->vlan_exist != AL_REG_BIT_GET(i, 2)))
+ return 0;
+ if ((index->mac_table_match != AL_ETH_FWD_CTRL_IDX_MAC_TABLE_ANY)
+ && (index->mac_table_match != AL_REG_BIT_GET(i, 3)))
+ return 0;
+ if ((index->protocol_id != AL_ETH_PROTO_ID_ANY)
+ && (index->protocol_id != AL_REG_FIELD_GET(i, AL_FIELD_MASK(8,4),4)))
+ return 0;
+ if ((index->mac_type != AL_ETH_FWD_CTRL_IDX_MAC_DA_TYPE_ANY)
+ && (index->mac_type != AL_REG_FIELD_GET(i, AL_FIELD_MASK(10,9),9)))
+ return 0;
+ return 1;
+}
+
+int al_eth_ctrl_table_set(struct al_hal_eth_adapter *adapter,
+ struct al_eth_fwd_ctrl_table_index *index,
+ struct al_eth_fwd_ctrl_table_entry *entry)
+{
+ uint32_t val = al_eth_fwd_ctrl_entry_to_val(entry);
+ uint32_t i;
+
+ for (i = 0; i < AL_ETH_RX_CTRL_TABLE_SIZE; i++) {
+ if (al_eth_ctrl_index_match(index, i)) {
+ al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_addr, i);
+ al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_data, val);
+ }
+ }
+ return 0;
+}
+
+int al_eth_ctrl_table_def_set(struct al_hal_eth_adapter *adapter,
+ al_bool use_table,
+ struct al_eth_fwd_ctrl_table_entry *entry)
+{
+ uint32_t val = al_eth_fwd_ctrl_entry_to_val(entry);
+
+ if (use_table)
+ val |= EC_RFW_CTRL_TABLE_DEF_SEL;
+
+ al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_def, val);
+
+ return 0;
+}
+
+int al_eth_ctrl_table_raw_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t entry)
+{
+
+ al_assert(idx < AL_ETH_RX_CTRL_TABLE_SIZE); /* valid CTRL index */
+
+
+ al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_data, entry);
+ return 0;
+}
+
+int al_eth_ctrl_table_def_raw_set(struct al_hal_eth_adapter *adapter, uint32_t val)
+{
+ al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_def, val);
+
+ return 0;
+}
+
+int al_eth_hash_key_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t val)
+{
+
+ al_assert(idx < AL_ETH_RX_HASH_KEY_NUM); /*valid CTRL index*/
+
+ al_reg_write32(&adapter->ec_regs_base->rfw_hash[idx].key, val);
+
+ return 0;
+}
+
+static uint32_t al_eth_fwd_mac_table_entry_to_val(struct al_eth_fwd_mac_table_entry *entry)
+{
+ uint32_t val = 0;
+
+ val |= (entry->filter == AL_TRUE) ? EC_FWD_MAC_CTRL_RX_VAL_DROP : 0;
+ val |= ((entry->udma_mask << EC_FWD_MAC_CTRL_RX_VAL_UDMA_SHIFT) &
+ EC_FWD_MAC_CTRL_RX_VAL_UDMA_MASK);
+
+ val |= ((entry->qid << EC_FWD_MAC_CTRL_RX_VAL_QID_SHIFT) &
+ EC_FWD_MAC_CTRL_RX_VAL_QID_MASK);
+
+ val |= (entry->rx_valid == AL_TRUE) ? EC_FWD_MAC_CTRL_RX_VALID : 0;
+
+ val |= ((entry->tx_target << EC_FWD_MAC_CTRL_TX_VAL_SHIFT) &
+ EC_FWD_MAC_CTRL_TX_VAL_MASK);
+
+ val |= (entry->tx_valid == AL_TRUE) ? EC_FWD_MAC_CTRL_TX_VALID : 0;
+
+ return val;
+}
+
+int al_eth_fwd_mac_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ struct al_eth_fwd_mac_table_entry *entry)
+{
+ uint32_t val;
+
+ al_assert(idx < AL_ETH_FWD_MAC_NUM); /*valid FWD MAC index */
+
+ val = (entry->addr[2] << 24) | (entry->addr[3] << 16) |
+ (entry->addr[4] << 8) | entry->addr[5];
+ al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].data_l, val);
+ val = (entry->addr[0] << 8) | entry->addr[1];
+ al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].data_h, val);
+ val = (entry->mask[2] << 24) | (entry->mask[3] << 16) |
+ (entry->mask[4] << 8) | entry->mask[5];
+ al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].mask_l, val);
+ val = (entry->mask[0] << 8) | entry->mask[1];
+ al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].mask_h, val);
+
+ val = al_eth_fwd_mac_table_entry_to_val(entry);
+ al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].ctrl, val);
+ return 0;
+}
+
+
+
+int al_eth_fwd_mac_addr_raw_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t addr_lo, uint32_t addr_hi, uint32_t mask_lo, uint32_t mask_hi)
+{
+ al_assert(idx < AL_ETH_FWD_MAC_NUM); /*valid FWD MAC index */
+
+ al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].data_l, addr_lo);
+ al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].data_h, addr_hi);
+ al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].mask_l, mask_lo);
+ al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].mask_h, mask_hi);
+
+ return 0;
+}
+
+int al_eth_fwd_mac_ctrl_raw_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t ctrl)
+{
+ al_assert(idx < AL_ETH_FWD_MAC_NUM); /*valid FWD MAC index */
+
+ al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].ctrl, ctrl);
+
+ return 0;
+}
+
+int al_eth_mac_addr_store(void * __iomem ec_base, uint32_t idx, uint8_t *addr)
+{
+ struct al_ec_regs __iomem *ec_regs_base = (struct al_ec_regs __iomem*)ec_base;
+ uint32_t val;
+
+ al_assert(idx < AL_ETH_FWD_MAC_NUM); /*valid FWD MAC index */
+
+ val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5];
+ al_reg_write32(&ec_regs_base->fwd_mac[idx].data_l, val);
+ val = (addr[0] << 8) | addr[1];
+ al_reg_write32(&ec_regs_base->fwd_mac[idx].data_h, val);
+ return 0;
+}
+
+int al_eth_mac_addr_read(void * __iomem ec_base, uint32_t idx, uint8_t *addr)
+{
+ struct al_ec_regs __iomem *ec_regs_base = (struct al_ec_regs __iomem*)ec_base;
+ uint32_t addr_lo = al_reg_read32(&ec_regs_base->fwd_mac[idx].data_l);
+ uint16_t addr_hi = al_reg_read32(&ec_regs_base->fwd_mac[idx].data_h);
+
+ addr[5] = addr_lo & 0xff;
+ addr[4] = (addr_lo >> 8) & 0xff;
+ addr[3] = (addr_lo >> 16) & 0xff;
+ addr[2] = (addr_lo >> 24) & 0xff;
+ addr[1] = addr_hi & 0xff;
+ addr[0] = (addr_hi >> 8) & 0xff;
+ return 0;
+}
+
+int al_eth_fwd_mhash_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t udma_mask, uint8_t qid)
+{
+ uint32_t val = 0;
+ al_assert(idx < AL_ETH_FWD_MAC_HASH_NUM); /* valid MHASH index */
+
+ AL_REG_FIELD_SET(val, AL_FIELD_MASK(3,0), 0, udma_mask);
+ AL_REG_FIELD_SET(val, AL_FIELD_MASK(5,4), 4, qid);
+
+ al_reg_write32(&adapter->ec_regs_base->rfw.mhash_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->rfw.mhash_table_data, val);
+ return 0;
+}
+static uint32_t al_eth_fwd_vid_entry_to_val(struct al_eth_fwd_vid_table_entry *entry)
+{
+ uint32_t val = 0;
+ AL_REG_BIT_VAL_SET(val, 0, entry->control);
+ AL_REG_BIT_VAL_SET(val, 1, entry->filter);
+ AL_REG_FIELD_SET(val, AL_FIELD_MASK(5,2), 2, entry->udma_mask);
+
+ return val;
+}
+
+int al_eth_fwd_vid_config_set(struct al_hal_eth_adapter *adapter, al_bool use_table,
+ struct al_eth_fwd_vid_table_entry *default_entry,
+ uint32_t default_vlan)
+{
+ uint32_t reg;
+
+ reg = al_eth_fwd_vid_entry_to_val(default_entry);
+ if (use_table)
+ reg |= EC_RFW_VID_TABLE_DEF_SEL;
+ else
+ reg &= ~EC_RFW_VID_TABLE_DEF_SEL;
+ al_reg_write32(&adapter->ec_regs_base->rfw.vid_table_def, reg);
+ al_reg_write32(&adapter->ec_regs_base->rfw.default_vlan, default_vlan);
+
+ return 0;
+}
+
+int al_eth_fwd_vid_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ struct al_eth_fwd_vid_table_entry *entry)
+{
+ uint32_t val;
+ al_assert(idx < AL_ETH_FWD_VID_TABLE_NUM); /* valid VID index */
+
+ val = al_eth_fwd_vid_entry_to_val(entry);
+ al_reg_write32(&adapter->ec_regs_base->rfw.vid_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->rfw.vid_table_data, val);
+ return 0;
+}
+
+int al_eth_fwd_pbits_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t prio)
+{
+
+ al_assert(idx < AL_ETH_FWD_PBITS_TABLE_NUM); /* valid PBIT index */
+ al_assert(prio < AL_ETH_FWD_PRIO_TABLE_NUM); /* valid PRIO index */
+ al_reg_write32(&adapter->ec_regs_base->rfw.pbits_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->rfw.pbits_table_data, prio);
+ return 0;
+}
+
+int al_eth_fwd_priority_table_set(struct al_hal_eth_adapter *adapter, uint8_t prio, uint8_t qid)
+{
+ al_assert(prio < AL_ETH_FWD_PRIO_TABLE_NUM); /* valid PRIO index */
+
+ al_reg_write32(&adapter->ec_regs_base->rfw_priority[prio].queue, qid);
+ return 0;
+}
+
+
+int al_eth_fwd_dscp_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t prio)
+{
+
+ al_assert(idx < AL_ETH_FWD_DSCP_TABLE_NUM); /* valid DSCP index */
+
+
+ al_reg_write32(&adapter->ec_regs_base->rfw.dscp_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->rfw.dscp_table_data, prio);
+ return 0;
+}
+
+int al_eth_fwd_tc_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t prio)
+{
+
+ al_assert(idx < AL_ETH_FWD_TC_TABLE_NUM); /* valid TC index */
+
+
+ al_reg_write32(&adapter->ec_regs_base->rfw.tc_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->rfw.tc_table_data, prio);
+ return 0;
+}
+
+/** Configure default UDMA register */
+int al_eth_fwd_default_udma_config(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ uint8_t udma_mask)
+{
+ al_reg_write32_masked(&adapter->ec_regs_base->rfw_default[idx].opt_1,
+ EC_RFW_DEFAULT_OPT_1_UDMA_MASK,
+ udma_mask << EC_RFW_DEFAULT_OPT_1_UDMA_SHIFT);
+ return 0;
+}
+
+/** Configure default queue register */
+int al_eth_fwd_default_queue_config(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ uint8_t qid)
+{
+ al_reg_write32_masked(&adapter->ec_regs_base->rfw_default[idx].opt_1,
+ EC_RFW_DEFAULT_OPT_1_QUEUE_MASK,
+ qid << EC_RFW_DEFAULT_OPT_1_QUEUE_SHIFT);
+ return 0;
+}
+
+/** Configure default priority register */
+int al_eth_fwd_default_priority_config(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ uint8_t prio)
+{
+ al_reg_write32_masked(&adapter->ec_regs_base->rfw_default[idx].opt_1,
+ EC_RFW_DEFAULT_OPT_1_PRIORITY_MASK,
+ prio << EC_RFW_DEFAULT_OPT_1_PRIORITY_SHIFT);
+ return 0;
+}
+
+int al_eth_switching_config_set(struct al_hal_eth_adapter *adapter, uint8_t udma_id, uint8_t forward_all_to_mac, uint8_t enable_int_switching,
+ enum al_eth_tx_switch_vid_sel_type vid_sel_type,
+ enum al_eth_tx_switch_dec_type uc_dec,
+ enum al_eth_tx_switch_dec_type mc_dec,
+ enum al_eth_tx_switch_dec_type bc_dec)
+{
+ uint32_t reg;
+
+ if (udma_id == 0) {
+ reg = al_reg_read32(&adapter->ec_regs_base->tfw.tx_gen);
+ if (forward_all_to_mac)
+ reg |= EC_TFW_TX_GEN_FWD_ALL_TO_MAC;
+ else
+ reg &= ~EC_TFW_TX_GEN_FWD_ALL_TO_MAC;
+ al_reg_write32(&adapter->ec_regs_base->tfw.tx_gen, reg);
+ }
+
+ reg = enable_int_switching;
+ reg |= (vid_sel_type & 7) << 1;
+ reg |= (bc_dec & 3) << 4;
+ reg |= (mc_dec & 3) << 6;
+ reg |= (uc_dec & 3) << 8;
+ al_reg_write32(&adapter->ec_regs_base->tfw_udma[udma_id].fwd_dec, reg);
+
+ return 0;
+}
+
+#define AL_ETH_RFW_FILTER_SUPPORTED(rev_id) \
+ (AL_ETH_RFW_FILTER_UNDET_MAC | \
+ AL_ETH_RFW_FILTER_DET_MAC | \
+ AL_ETH_RFW_FILTER_TAGGED | \
+ AL_ETH_RFW_FILTER_UNTAGGED | \
+ AL_ETH_RFW_FILTER_BC | \
+ AL_ETH_RFW_FILTER_MC | \
+ AL_ETH_RFW_FILTER_VLAN_VID | \
+ AL_ETH_RFW_FILTER_CTRL_TABLE | \
+ AL_ETH_RFW_FILTER_PROT_INDEX | \
+ ((rev_id > AL_ETH_REV_ID_0) ? ((AL_ETH_RFW_FILTER_WOL) | (AL_ETH_RFW_FILTER_PARSE)) : 0))
+
+/* Configure the receive filters */
+int al_eth_filter_config(struct al_hal_eth_adapter *adapter, struct al_eth_filter_params *params)
+{
+ uint32_t reg;
+
+ al_assert(params); /* valid params pointer */
+
+ if (params->filters & ~(AL_ETH_RFW_FILTER_SUPPORTED(adapter->rev_id))) {
+ al_err("[%s]: unsupported filter options (0x%08x)\n", adapter->name, params->filters);
+ return -EINVAL;
+ }
+
+ reg = al_reg_read32(&adapter->ec_regs_base->rfw.out_cfg);
+ if (params->enable == AL_TRUE)
+ AL_REG_MASK_SET(reg, EC_RFW_OUT_CFG_DROP_EN);
+ else
+ AL_REG_MASK_CLEAR(reg, EC_RFW_OUT_CFG_DROP_EN);
+ al_reg_write32(&adapter->ec_regs_base->rfw.out_cfg, reg);
+
+ al_reg_write32_masked(
+ &adapter->ec_regs_base->rfw.filter,
+ AL_ETH_RFW_FILTER_SUPPORTED(adapter->rev_id),
+ params->filters);
+ if (params->filters & AL_ETH_RFW_FILTER_PROT_INDEX) {
+ int i;
+ for (i = 0; i < AL_ETH_PROTOCOLS_NUM; i++) {
+ reg = al_reg_read32(&adapter->ec_regs_base->epe_a[i].prot_act);
+ if (params->filter_proto[i] == AL_TRUE)
+ AL_REG_MASK_SET(reg, EC_EPE_A_PROT_ACT_DROP);
+ else
+ AL_REG_MASK_CLEAR(reg, EC_EPE_A_PROT_ACT_DROP);
+ al_reg_write32(&adapter->ec_regs_base->epe_a[i].prot_act, reg);
+ }
+ }
+ return 0;
+}
+
+/* Configure the receive override filters */
+int al_eth_filter_override_config(struct al_hal_eth_adapter *adapter,
+ struct al_eth_filter_override_params *params)
+{
+ uint32_t reg;
+
+ al_assert(params); /* valid params pointer */
+
+ if (params->filters & ~(AL_ETH_RFW_FILTER_SUPPORTED(adapter->rev_id))) {
+ al_err("[%s]: unsupported override filter options (0x%08x)\n", adapter->name, params->filters);
+ return -EINVAL;
+ }
+
+ al_reg_write32_masked(
+ &adapter->ec_regs_base->rfw.filter,
+ AL_ETH_RFW_FILTER_SUPPORTED(adapter->rev_id) << 16,
+ params->filters << 16);
+
+ reg = al_reg_read32(&adapter->ec_regs_base->rfw.default_or);
+ AL_REG_FIELD_SET(reg, EC_RFW_DEFAULT_OR_UDMA_MASK, EC_RFW_DEFAULT_OR_UDMA_SHIFT, params->udma);
+ AL_REG_FIELD_SET(reg, EC_RFW_DEFAULT_OR_QUEUE_MASK, EC_RFW_DEFAULT_OR_QUEUE_SHIFT, params->qid);
+ al_reg_write32(&adapter->ec_regs_base->rfw.default_or, reg);
+ return 0;
+}
+
+
+
+int al_eth_switching_default_bitmap_set(struct al_hal_eth_adapter *adapter, uint8_t udma_id, uint8_t udma_uc_bitmask,
+ uint8_t udma_mc_bitmask,uint8_t udma_bc_bitmask)
+{
+ al_reg_write32(&adapter->ec_regs_base->tfw_udma[udma_id].uc_udma, udma_uc_bitmask);
+ al_reg_write32(&adapter->ec_regs_base->tfw_udma[udma_id].mc_udma, udma_mc_bitmask);
+ al_reg_write32(&adapter->ec_regs_base->tfw_udma[udma_id].bc_udma, udma_bc_bitmask);
+
+ return 0;
+}
+
+int al_eth_flow_control_config(struct al_hal_eth_adapter *adapter, struct al_eth_flow_control_params *params)
+{
+ uint32_t reg;
+ int i;
+ al_assert(params); /* valid params pointer */
+
+ switch(params->type){
+ case AL_ETH_FLOW_CONTROL_TYPE_LINK_PAUSE:
+ al_dbg("[%s]: config flow control to link pause mode.\n", adapter->name);
+
+ /* config the mac */
+ if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) {
+ /* set quanta value */
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_1g.pause_quant,
+ params->quanta);
+ al_reg_write32(
+ &adapter->ec_regs_base->efc.xoff_timer_1g,
+ params->quanta_th);
+
+ } else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) {
+ /* set quanta value */
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_10g.cl01_pause_quanta,
+ params->quanta);
+ /* set quanta threshold value */
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_10g.cl01_quanta_thresh,
+ params->quanta_th);
+ } else {
+ /* set quanta value */
+ al_eth_40g_mac_reg_write(adapter,
+ ETH_MAC_GEN_V3_MAC_40G_CL01_PAUSE_QUANTA_ADDR,
+ params->quanta);
+ /* set quanta threshold value */
+ al_eth_40g_mac_reg_write(adapter,
+ ETH_MAC_GEN_V3_MAC_40G_CL01_QUANTA_THRESH_ADDR,
+ params->quanta_th);
+ }
+
+ if (params->obay_enable == AL_TRUE)
+ /* Tx path FIFO, unmask pause_on from MAC when PAUSE packet received */
+ al_reg_write32(&adapter->ec_regs_base->efc.ec_pause, 1);
+ else
+ al_reg_write32(&adapter->ec_regs_base->efc.ec_pause, 0);
+
+
+ /* Rx path */
+ if (params->gen_enable == AL_TRUE)
+ /* enable generating xoff from ec fifo almost full indication in hysteresis mode */
+ al_reg_write32(&adapter->ec_regs_base->efc.ec_xoff, 1 << EC_EFC_EC_XOFF_MASK_2_SHIFT);
+ else
+ al_reg_write32(&adapter->ec_regs_base->efc.ec_xoff, 0);
+
+ if (AL_ETH_IS_1G_MAC(adapter->mac_mode))
+ /* in 1G mode, enable generating xon from ec fifo in hysteresis mode*/
+ al_reg_write32(&adapter->ec_regs_base->efc.xon, EC_EFC_XON_MASK_2 | EC_EFC_XON_MASK_1);
+
+ /* set hysteresis mode thresholds */
+ al_reg_write32(&adapter->ec_regs_base->efc.rx_fifo_hyst, params->rx_fifo_th_low | (params->rx_fifo_th_high << EC_EFC_RX_FIFO_HYST_TH_HIGH_SHIFT));
+
+ for (i = 0; i < 4; i++) {
+ if (params->obay_enable == AL_TRUE)
+ /* Tx path UDMA, unmask pause_on for all queues */
+ al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_pause_0,
+ params->prio_q_map[i][0]);
+ else
+ al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_pause_0, 0);
+
+ if (params->gen_enable == AL_TRUE)
+ /* Rx path UDMA, enable generating xoff from UDMA queue almost full indication */
+ al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_xoff_0, params->prio_q_map[i][0]);
+ else
+ al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_xoff_0, 0);
+ }
+ break;
+ case AL_ETH_FLOW_CONTROL_TYPE_PFC:
+ al_dbg("[%s]: config flow control to PFC mode.\n", adapter->name);
+ al_assert(!AL_ETH_IS_1G_MAC(adapter->mac_mode)); /* pfc not available for RGMII mode */;
+
+ for (i = 0; i < 4; i++) {
+ int prio;
+ for (prio = 0; prio < 8; prio++) {
+ if (params->obay_enable == AL_TRUE)
+ /* Tx path UDMA, unmask pause_on for all queues */
+ al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_pause_0 + prio,
+ params->prio_q_map[i][prio]);
+ else
+ al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_pause_0 + prio,
+ 0);
+
+ if (params->gen_enable == AL_TRUE)
+ al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_xoff_0 + prio,
+ params->prio_q_map[i][prio]);
+ else
+ al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_xoff_0 + prio,
+ 0);
+ }
+ }
+
+ /* Rx path */
+ /* enable generating xoff from ec fifo almost full indication in hysteresis mode */
+ if (params->gen_enable == AL_TRUE)
+ al_reg_write32(&adapter->ec_regs_base->efc.ec_xoff, 0xFF << EC_EFC_EC_XOFF_MASK_2_SHIFT);
+ else
+ al_reg_write32(&adapter->ec_regs_base->efc.ec_xoff, 0);
+
+ /* set hysteresis mode thresholds */
+ al_reg_write32(&adapter->ec_regs_base->efc.rx_fifo_hyst, params->rx_fifo_th_low | (params->rx_fifo_th_high << EC_EFC_RX_FIFO_HYST_TH_HIGH_SHIFT));
+
+ if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) {
+ /* config the 10g_mac */
+ /* set quanta value (same value for all prios) */
+ reg = params->quanta | (params->quanta << 16);
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_10g.cl01_pause_quanta, reg);
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_10g.cl23_pause_quanta, reg);
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_10g.cl45_pause_quanta, reg);
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_10g.cl67_pause_quanta, reg);
+ /* set quanta threshold value (same value for all prios) */
+ reg = params->quanta_th | (params->quanta_th << 16);
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_10g.cl01_quanta_thresh, reg);
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_10g.cl23_quanta_thresh, reg);
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_10g.cl45_quanta_thresh, reg);
+ al_reg_write32(
+ &adapter->mac_regs_base->mac_10g.cl67_quanta_thresh, reg);
+
+ /* enable PFC in the 10g_MAC */
+ reg = al_reg_read32(&adapter->mac_regs_base->mac_10g.cmd_cfg);
+ reg |= 1 << 19;
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, reg);
+ } else {
+ /* config the 40g_mac */
+ /* set quanta value (same value for all prios) */
+ reg = params->quanta | (params->quanta << 16);
+ al_eth_40g_mac_reg_write(adapter,
+ ETH_MAC_GEN_V3_MAC_40G_CL01_PAUSE_QUANTA_ADDR, reg);
+ al_eth_40g_mac_reg_write(adapter,
+ ETH_MAC_GEN_V3_MAC_40G_CL23_PAUSE_QUANTA_ADDR, reg);
+ al_eth_40g_mac_reg_write(adapter,
+ ETH_MAC_GEN_V3_MAC_40G_CL45_PAUSE_QUANTA_ADDR, reg);
+ al_eth_40g_mac_reg_write(adapter,
+ ETH_MAC_GEN_V3_MAC_40G_CL67_PAUSE_QUANTA_ADDR, reg);
+ /* set quanta threshold value (same value for all prios) */
+ reg = params->quanta_th | (params->quanta_th << 16);
+ al_eth_40g_mac_reg_write(adapter,
+ ETH_MAC_GEN_V3_MAC_40G_CL01_QUANTA_THRESH_ADDR, reg);
+ al_eth_40g_mac_reg_write(adapter,
+ ETH_MAC_GEN_V3_MAC_40G_CL23_QUANTA_THRESH_ADDR, reg);
+ al_eth_40g_mac_reg_write(adapter,
+ ETH_MAC_GEN_V3_MAC_40G_CL45_QUANTA_THRESH_ADDR, reg);
+ al_eth_40g_mac_reg_write(adapter,
+ ETH_MAC_GEN_V3_MAC_40G_CL67_QUANTA_THRESH_ADDR, reg);
+
+ /* enable PFC in the 40g_MAC */
+ reg = al_reg_read32(&adapter->mac_regs_base->mac_10g.cmd_cfg);
+ reg |= 1 << 19;
+ al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, reg);
+ reg = al_eth_40g_mac_reg_read(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR);
+
+ reg |= ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_PFC_MODE;
+
+ al_eth_40g_mac_reg_write(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR, reg);
+ }
+
+ break;
+ default:
+ al_err("[%s]: unsupported flow control type %d\n", adapter->name, params->type);
+ return -EINVAL;
+
+ }
+ return 0;
+}
+
+int al_eth_vlan_mod_config(struct al_hal_eth_adapter *adapter, uint8_t udma_id, uint16_t udma_etype, uint16_t vlan1_data, uint16_t vlan2_data)
+{
+ al_dbg("[%s]: config vlan modification registers. udma id %d.\n", adapter->name, udma_id);
+
+ al_reg_write32(&adapter->ec_regs_base->tpm_sel[udma_id].etype, udma_etype);
+ al_reg_write32(&adapter->ec_regs_base->tpm_udma[udma_id].vlan_data, vlan1_data | (vlan2_data << 16));
+
+ return 0;
+}
+
+int al_eth_eee_get(struct al_hal_eth_adapter *adapter, struct al_eth_eee_params *params)
+{
+ uint32_t reg;
+
+ al_dbg("[%s]: getting eee.\n", adapter->name);
+
+ reg = al_reg_read32(&adapter->ec_regs_base->eee.cfg_e);
+ params->enable = (reg & EC_EEE_CFG_E_ENABLE) ? AL_TRUE : AL_FALSE;
+
+ params->tx_eee_timer = al_reg_read32(&adapter->ec_regs_base->eee.pre_cnt);
+ params->min_interval = al_reg_read32(&adapter->ec_regs_base->eee.post_cnt);
+ params->stop_cnt = al_reg_read32(&adapter->ec_regs_base->eee.stop_cnt);
+
+ return 0;
+}
+
+
+int al_eth_eee_config(struct al_hal_eth_adapter *adapter, struct al_eth_eee_params *params)
+{
+ uint32_t reg;
+ al_dbg("[%s]: config eee.\n", adapter->name);
+
+ if (params->enable == 0) {
+ al_dbg("[%s]: disable eee.\n", adapter->name);
+ al_reg_write32(&adapter->ec_regs_base->eee.cfg_e, 0);
+ return 0;
+ }
+ if (AL_ETH_IS_10G_MAC(adapter->mac_mode)) {
+ reg = ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL << ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL_SHIFT;
+ al_reg_write32_masked(
+ &adapter->mac_regs_base->kr.pcs_cfg,
+ ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL_MASK, reg);
+ }
+
+ al_reg_write32(&adapter->ec_regs_base->eee.pre_cnt, params->tx_eee_timer);
+ al_reg_write32(&adapter->ec_regs_base->eee.post_cnt, params->min_interval);
+ al_reg_write32(&adapter->ec_regs_base->eee.stop_cnt, params->stop_cnt);
+
+ reg = EC_EEE_CFG_E_MASK_EC_TMI_STOP | EC_EEE_CFG_E_MASK_MAC_EEE |
+ EC_EEE_CFG_E_ENABLE |
+ EC_EEE_CFG_E_USE_EC_TX_FIFO | EC_EEE_CFG_E_USE_EC_RX_FIFO;
+
+ /*
+ * Addressing RMN: 3732
+ *
+ * RMN description:
+ * When the HW get into eee mode, it can't transmit any pause packet
+ * (when flow control policy is enabled).
+ * In such case, the HW has no way to handle extreme pushback from
+ * the Rx_path fifos.
+ *
+ * Software flow:
+ * Configure RX_FIFO empty as eee mode term.
+ * That way, nothing will prevent pause packet transmittion in
+ * case of extreme pushback from the Rx_path fifos.
+ *
+ */
+
+ al_reg_write32(&adapter->ec_regs_base->eee.cfg_e, reg);
+
+ return 0;
+}
+
+/* Timestamp */
+/* prepare the adapter for doing Timestamps for Rx packets. */
+int al_eth_ts_init(struct al_hal_eth_adapter *adapter)
+{
+ uint32_t reg;
+
+ /*TODO:
+ * return error when:
+ * - working in 1G mode and MACSEC enabled
+ * - RX completion descriptor is not 8 words
+ */
+ reg = al_reg_read32(&adapter->ec_regs_base->gen.en_ext);
+ if (AL_ETH_IS_1G_MAC(adapter->mac_mode))
+ reg &= ~EC_GEN_EN_EXT_PTH_1_10_SEL;
+ else
+ reg |= EC_GEN_EN_EXT_PTH_1_10_SEL;
+ /*
+ * set completion bypass so tx timestamps won't be inserted to tx cmpl
+ * (in order to disable unverified flow)
+ */
+ reg |= EC_GEN_EN_EXT_PTH_COMPLETION_BYPASS;
+ al_reg_write32(&adapter->ec_regs_base->gen.en_ext, reg);
+
+ /*TODO: add the following when we have updated regs file:
+ * reg_rfw_out_cfg_timestamp_sample_out
+ 0 (default) – use the timestamp from the SOP info (10G MAC)
+ 1 – use the timestamp from the EOP (1G MAC) (noly when MACSEC is disabled)
+ */
+ return 0;
+}
+
+/* read Timestamp sample value of previously transmitted packet. */
+int al_eth_tx_ts_val_get(struct al_hal_eth_adapter *adapter, uint8_t ts_index,
+ uint32_t *timestamp)
+{
+ al_assert(ts_index < AL_ETH_PTH_TX_SAMPLES_NUM);
+
+ /* in 1G mode, only indexes 1-7 are allowed*/
+ if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) {
+ al_assert(ts_index <= 7);
+ al_assert(ts_index >= 1);
+ }
+
+ /*TODO: check if sample is valid */
+ *timestamp = al_reg_read32(&adapter->ec_regs_base->pth_db[ts_index].ts);
+ return 0;
+}
+
+/* Read the systime value */
+int al_eth_pth_systime_read(struct al_hal_eth_adapter *adapter,
+ struct al_eth_pth_time *systime)
+{
+ uint32_t reg;
+
+ /* first we must read the subseconds MSB so the seconds register will be
+ * shadowed
+ */
+ reg = al_reg_read32(&adapter->ec_regs_base->pth.system_time_subseconds_msb);
+ systime->femto = (uint64_t)reg << 18;
+ reg = al_reg_read32(&adapter->ec_regs_base->pth.system_time_seconds);
+ systime->seconds = reg;
+
+ return 0;
+}
+
+/* Set the clock period to a given value. */
+int al_eth_pth_clk_period_write(struct al_hal_eth_adapter *adapter,
+ uint64_t clk_period)
+{
+ uint32_t reg;
+ /* first write the LSB so it will be shadowed */
+ /* bits 31:14 of the clock period lsb register contains bits 17:0 of the
+ * period.
+ */
+ reg = (clk_period & AL_BIT_MASK(18)) << EC_PTH_CLOCK_PERIOD_LSB_VAL_SHIFT;
+ al_reg_write32(&adapter->ec_regs_base->pth.clock_period_lsb, reg);
+ reg = clk_period >> 18;
+ al_reg_write32(&adapter->ec_regs_base->pth.clock_period_msb, reg);
+
+ return 0;
+}
+
+/* Configure the systime internal update */
+int al_eth_pth_int_update_config(struct al_hal_eth_adapter *adapter,
+ struct al_eth_pth_int_update_params *params)
+{
+ uint32_t reg;
+
+ reg = al_reg_read32(&adapter->ec_regs_base->pth.int_update_ctrl);
+ if (params->enable == AL_FALSE) {
+ reg &= ~EC_PTH_INT_UPDATE_CTRL_INT_TRIG_EN;
+ } else {
+ reg |= EC_PTH_INT_UPDATE_CTRL_INT_TRIG_EN;
+ AL_REG_FIELD_SET(reg, EC_PTH_INT_UPDATE_CTRL_UPDATE_METHOD_MASK,
+ EC_PTH_INT_UPDATE_CTRL_UPDATE_METHOD_SHIFT,
+ params->method);
+ if (params->trigger == AL_ETH_PTH_INT_TRIG_REG_WRITE)
+ reg |= EC_PTH_INT_UPDATE_CTRL_UPDATE_TRIG;
+ else
+ reg &= ~EC_PTH_INT_UPDATE_CTRL_UPDATE_TRIG;
+ }
+ al_reg_write32(&adapter->ec_regs_base->pth.int_update_ctrl, reg);
+ return 0;
+}
+/* set internal update time */
+int al_eth_pth_int_update_time_set(struct al_hal_eth_adapter *adapter,
+ struct al_eth_pth_time *time)
+{
+ uint32_t reg;
+
+ al_reg_write32(&adapter->ec_regs_base->pth.int_update_seconds,
+ time->seconds);
+ reg = time->femto & AL_BIT_MASK(18);
+ reg = reg << EC_PTH_INT_UPDATE_SUBSECONDS_LSB_VAL_SHIFT;
+ al_reg_write32(&adapter->ec_regs_base->pth.int_update_subseconds_lsb,
+ reg);
+ reg = time->femto >> 18;
+ al_reg_write32(&adapter->ec_regs_base->pth.int_update_subseconds_msb,
+ reg);
+
+ return 0;
+}
+
+/* Configure the systime external update */
+int al_eth_pth_ext_update_config(struct al_hal_eth_adapter *adapter,
+ struct al_eth_pth_ext_update_params * params)
+{
+ uint32_t reg;
+
+ reg = al_reg_read32(&adapter->ec_regs_base->pth.int_update_ctrl);
+ AL_REG_FIELD_SET(reg, EC_PTH_INT_UPDATE_CTRL_UPDATE_METHOD_MASK,
+ EC_PTH_INT_UPDATE_CTRL_UPDATE_METHOD_SHIFT,
+ params->method);
+
+ AL_REG_FIELD_SET(reg, EC_PTH_EXT_UPDATE_CTRL_EXT_TRIG_EN_MASK,
+ EC_PTH_EXT_UPDATE_CTRL_EXT_TRIG_EN_SHIFT,
+ params->triggers);
+ al_reg_write32(&adapter->ec_regs_base->pth.int_update_ctrl, reg);
+ return 0;
+}
+
+/* set external update time */
+int al_eth_pth_ext_update_time_set(struct al_hal_eth_adapter *adapter,
+ struct al_eth_pth_time *time)
+{
+ uint32_t reg;
+
+ al_reg_write32(&adapter->ec_regs_base->pth.ext_update_seconds,
+ time->seconds);
+ reg = time->femto & AL_BIT_MASK(18);
+ reg = reg << EC_PTH_EXT_UPDATE_SUBSECONDS_LSB_VAL_SHIFT;
+ al_reg_write32(&adapter->ec_regs_base->pth.ext_update_subseconds_lsb,
+ reg);
+ reg = time->femto >> 18;
+ al_reg_write32(&adapter->ec_regs_base->pth.ext_update_subseconds_msb,
+ reg);
+
+ return 0;
+};
+
+/* set the read compensation delay */
+int al_eth_pth_read_compensation_set(struct al_hal_eth_adapter *adapter,
+ uint64_t subseconds)
+{
+ uint32_t reg;
+
+ /* first write to lsb to ensure atomicity */
+ reg = (subseconds & AL_BIT_MASK(18)) << EC_PTH_READ_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT;
+ al_reg_write32(&adapter->ec_regs_base->pth.read_compensation_subseconds_lsb, reg);
+
+ reg = subseconds >> 18;
+ al_reg_write32(&adapter->ec_regs_base->pth.read_compensation_subseconds_msb, reg);
+ return 0;
+}
+
+/* set the internal write compensation delay */
+int al_eth_pth_int_write_compensation_set(struct al_hal_eth_adapter *adapter,
+ uint64_t subseconds)
+{
+ uint32_t reg;
+
+ /* first write to lsb to ensure atomicity */
+ reg = (subseconds & AL_BIT_MASK(18)) << EC_PTH_INT_WRITE_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT;
+ al_reg_write32(&adapter->ec_regs_base->pth.int_write_compensation_subseconds_lsb, reg);
+
+ reg = subseconds >> 18;
+ al_reg_write32(&adapter->ec_regs_base->pth.int_write_compensation_subseconds_msb, reg);
+ return 0;
+}
+
+/* set the external write compensation delay */
+int al_eth_pth_ext_write_compensation_set(struct al_hal_eth_adapter *adapter,
+ uint64_t subseconds)
+{
+ uint32_t reg;
+
+ /* first write to lsb to ensure atomicity */
+ reg = (subseconds & AL_BIT_MASK(18)) << EC_PTH_EXT_WRITE_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT;
+ al_reg_write32(&adapter->ec_regs_base->pth.ext_write_compensation_subseconds_lsb, reg);
+
+ reg = subseconds >> 18;
+ al_reg_write32(&adapter->ec_regs_base->pth.ext_write_compensation_subseconds_msb, reg);
+ return 0;
+}
+
+/* set the sync compensation delay */
+int al_eth_pth_sync_compensation_set(struct al_hal_eth_adapter *adapter,
+ uint64_t subseconds)
+{
+ uint32_t reg;
+
+ /* first write to lsb to ensure atomicity */
+ reg = (subseconds & AL_BIT_MASK(18)) << EC_PTH_SYNC_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT;
+ al_reg_write32(&adapter->ec_regs_base->pth.sync_compensation_subseconds_lsb, reg);
+
+ reg = subseconds >> 18;
+ al_reg_write32(&adapter->ec_regs_base->pth.sync_compensation_subseconds_msb, reg);
+ return 0;
+}
+
+/* Configure an output pulse */
+int al_eth_pth_pulse_out_config(struct al_hal_eth_adapter *adapter,
+ struct al_eth_pth_pulse_out_params *params)
+{
+ uint32_t reg;
+
+ if (params->index >= AL_ETH_PTH_PULSE_OUT_NUM) {
+ al_err("eth [%s] PTH out pulse index out of range\n",
+ adapter->name);
+ return -EINVAL;
+ }
+ reg = al_reg_read32(&adapter->ec_regs_base->pth_egress[params->index].trigger_ctrl);
+ if (params->enable == AL_FALSE) {
+ reg &= ~EC_PTH_EGRESS_TRIGGER_CTRL_EN;
+ } else {
+ reg |= EC_PTH_EGRESS_TRIGGER_CTRL_EN;
+ if (params->periodic == AL_FALSE)
+ reg &= ~EC_PTH_EGRESS_TRIGGER_CTRL_PERIODIC;
+ else
+ reg |= EC_PTH_EGRESS_TRIGGER_CTRL_PERIODIC;
+
+ AL_REG_FIELD_SET(reg, EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SUBSEC_MASK,
+ EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SUBSEC_SHIFT,
+ params->period_us);
+ AL_REG_FIELD_SET(reg, EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SEC_MASK,
+ EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SEC_SHIFT,
+ params->period_sec);
+ }
+ al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].trigger_ctrl, reg);
+
+ /* set trigger time */
+ al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].trigger_seconds,
+ params->start_time.seconds);
+ reg = params->start_time.femto & AL_BIT_MASK(18);
+ reg = reg << EC_PTH_EGRESS_TRIGGER_SUBSECONDS_LSB_VAL_SHIFT;
+ al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].trigger_subseconds_lsb,
+ reg);
+ reg = params->start_time.femto >> 18;
+ al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].trigger_subseconds_msb,
+ reg);
+
+ /* set pulse width */
+ reg = params->pulse_width & AL_BIT_MASK(18);
+ reg = reg << EC_PTH_EGRESS_PULSE_WIDTH_SUBSECONDS_LSB_VAL_SHIFT;
+ al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].pulse_width_subseconds_lsb, reg);
+
+ reg = params->pulse_width >> 18;
+ al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].pulse_width_subseconds_msb, reg);
+
+ return 0;
+}
+
+/** get link status */
+int al_eth_link_status_get(struct al_hal_eth_adapter *adapter,
+ struct al_eth_link_status *status)
+{
+ uint32_t reg;
+
+ if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) {
+ reg = al_reg_read32(&adapter->mac_regs_base->gen.mac_10g_stat);
+
+ status->link_up = AL_TRUE;
+
+ if (reg & (ETH_MAC_GEN_MAC_10G_STAT_LOC_FAULT |
+ ETH_MAC_GEN_MAC_10G_STAT_REM_FAULT))
+ status->link_up = AL_FALSE;
+
+ } else if (adapter->mac_mode == AL_ETH_MAC_MODE_SGMII) {
+ al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, 1);
+ /*
+ * This register is latched low so need to read twice to get
+ * the current link status
+ */
+ reg = al_reg_read32(&adapter->mac_regs_base->sgmii.reg_data);
+ reg = al_reg_read32(&adapter->mac_regs_base->sgmii.reg_data);
+
+ status->link_up = AL_FALSE;
+
+ if (reg & AL_BIT(2))
+ status->link_up = AL_TRUE;
+
+ reg = al_reg_read32(&adapter->mac_regs_base->sgmii.link_stat);
+
+ if ((reg & AL_BIT(3)) == 0)
+ status->link_up = AL_FALSE;
+
+ } else if (adapter->mac_mode == AL_ETH_MAC_MODE_RGMII) {
+ reg = al_reg_read32(&adapter->mac_regs_base->gen.rgmii_stat);
+
+ status->link_up = AL_FALSE;
+
+ if (reg & AL_BIT(4))
+ status->link_up = AL_TRUE;
+
+ } else if ((adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_40G) ||
+ (adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_50G)) {
+ reg = al_reg_read32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_status);
+
+ status->link_up = AL_FALSE;
+
+ if ((reg & 0x1F) == 0x1F) {
+ reg = al_reg_read32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_status);
+ if ((reg & (ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_REM_FAULT |
+ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_LOC_FAULT)) == 0)
+ status->link_up = AL_TRUE;
+ }
+
+ } else {
+ /* not implemented yet */
+ return -EPERM;
+ }
+
+ al_dbg("[%s]: mac %s port. link_status: %s.\n", adapter->name,
+ al_eth_mac_mode_str(adapter->mac_mode),
+ (status->link_up == AL_TRUE) ? "LINK_UP" : "LINK_DOWN");
+
+ return 0;
+}
+
+/** set LED mode and value */
+int al_eth_led_set(struct al_hal_eth_adapter *adapter, al_bool link_is_up)
+{
+ uint32_t reg = 0;
+ uint32_t mode = ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG;
+
+ if (link_is_up)
+ mode = ETH_MAC_GEN_LED_CFG_SEL_LINK_ACTIVITY;
+
+ AL_REG_FIELD_SET(reg, ETH_MAC_GEN_LED_CFG_SEL_MASK,
+ ETH_MAC_GEN_LED_CFG_SEL_SHIFT, mode);
+
+ AL_REG_FIELD_SET(reg, ETH_MAC_GEN_LED_CFG_BLINK_TIMER_MASK,
+ ETH_MAC_GEN_LED_CFG_BLINK_TIMER_SHIFT,
+ ETH_MAC_GEN_LED_CFG_BLINK_TIMER_VAL);
+
+ AL_REG_FIELD_SET(reg, ETH_MAC_GEN_LED_CFG_ACT_TIMER_MASK,
+ ETH_MAC_GEN_LED_CFG_ACT_TIMER_SHIFT,
+ ETH_MAC_GEN_LED_CFG_ACT_TIMER_VAL);
+
+ al_reg_write32(&adapter->mac_regs_base->gen.led_cfg, reg);
+
+ return 0;
+}
+
+/* get statistics */
+int al_eth_mac_stats_get(struct al_hal_eth_adapter *adapter, struct al_eth_mac_stats *stats)
+{
+ al_assert(stats);
+
+ if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) {
+ void __iomem *mac_1g_regs_base = &adapter->mac_regs_base->mac_1g;
+
+ stats->ifInUcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x90));
+ stats->ifInMulticastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x94));
+ stats->ifInBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x98));
+ stats->etherStatsPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xb4));
+ stats->ifOutUcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xa0));
+ stats->ifOutMulticastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xa4));
+ stats->ifOutBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xa8));
+ stats->ifInErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x88));
+ stats->ifOutErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x8c));
+
+ stats->aFramesReceivedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x6c));
+ stats->aFramesTransmittedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x68));
+
+ stats->aOctetsReceivedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x7c));
+ stats->aOctetsTransmittedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x78));
+
+ stats->etherStatsUndersizePkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xB8));
+ stats->etherStatsFragments = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xE0));
+ stats->etherStatsJabbers = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xDC));
+ stats->etherStatsOversizePkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xBC));
+
+ stats->aFrameCheckSequenceErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x70));
+ stats->aAlignmentErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x74));
+ stats->etherStatsDropEvents = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xAC));
+
+ stats->aPAUSEMACCtrlFramesTransmitted = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x80));
+ stats->aPAUSEMACCtrlFramesReceived = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x84));
+ stats->aFrameTooLongErrors = 0; /* N/A */
+ stats->aInRangeLengthErrors = 0; /* N/A */
+ stats->VLANTransmittedOK = 0; /* N/A */
+ stats->VLANReceivedOK = 0; /* N/A */
+ stats->etherStatsOctets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xB0));
+
+ stats->etherStatsPkts64Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xC0));
+ stats->etherStatsPkts65to127Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xC4));
+ stats->etherStatsPkts128to255Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xC8));
+ stats->etherStatsPkts256to511Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xCC));
+ stats->etherStatsPkts512to1023Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xD0));
+ stats->etherStatsPkts1024to1518Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xD4));
+ stats->etherStatsPkts1519toX = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xD8));
+ } else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) {
+ if (adapter->rev_id < AL_ETH_REV_ID_3) {
+ void __iomem *mac_10g_regs_base = &adapter->mac_regs_base->mac_10g;
+ uint64_t octets;
+
+ stats->ifInUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xE0));
+ stats->ifInMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xE8));
+ stats->ifInBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xF0));
+ stats->etherStatsPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x130));
+ stats->ifOutUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x108));
+ stats->ifOutMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x110));
+ stats->ifOutBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x118));
+ stats->ifInErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x190));
+ stats->ifOutErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xf8));
+
+ stats->aFramesReceivedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x88));
+ stats->aFramesTransmittedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x80));
+ /* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */
+ octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xD8));
+ octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xDC))) << 32;
+ octets -= 18 * stats->aFramesReceivedOK;
+ octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC8));
+ stats->aOctetsReceivedOK = octets;
+
+ /* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */
+ octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xD0));
+ octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xD4))) << 32;
+ octets -= 18 * stats->aFramesTransmittedOK;
+ octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC0));
+ stats->aOctetsTransmittedOK = octets;
+
+ stats->etherStatsUndersizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x138));
+ stats->etherStatsFragments = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x188));
+ stats->etherStatsJabbers = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x180));
+ stats->etherStatsOversizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x178));
+
+ stats->aFrameCheckSequenceErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x90));
+ stats->aAlignmentErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x98));
+ stats->etherStatsDropEvents = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x120));
+
+ stats->aPAUSEMACCtrlFramesTransmitted = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xA0));
+ stats->aPAUSEMACCtrlFramesReceived = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xA8));
+ stats->aFrameTooLongErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xB0));
+ stats->aInRangeLengthErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xB8));
+ stats->VLANTransmittedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC0));
+ stats->VLANReceivedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC8));
+ stats->etherStatsOctets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x128));
+
+ stats->etherStatsPkts64Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x140));
+ stats->etherStatsPkts65to127Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x148));
+ stats->etherStatsPkts128to255Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x150));
+ stats->etherStatsPkts256to511Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x158));
+ stats->etherStatsPkts512to1023Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x160));
+ stats->etherStatsPkts1024to1518Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x168));
+ stats->etherStatsPkts1519toX = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x170));
+ } else {
+ void __iomem *mac_10g_regs_base = &adapter->mac_regs_base->mac_10g;
+ uint64_t octets;
+ /* TODO - change to 64 bit */
+ stats->ifInUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x140));
+ stats->ifInMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x148));
+ stats->ifInBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x150));
+ stats->etherStatsPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x160));
+ stats->ifOutUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x240));
+ stats->ifOutMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x248));
+ stats->ifOutBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x250));
+ stats->ifInErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x138));
+ stats->ifOutErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x238));
+
+ stats->aFramesReceivedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x120)); /*frames_ok*/
+ stats->aFramesTransmittedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x220)); /*frames_ok*/
+ /* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */
+ octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x108)); /*OctetsOK*/
+ octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x10C))) << 32;
+ octets -= 18 * stats->aFramesReceivedOK;
+ octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x130)); /*VLANOK*/
+ stats->aOctetsReceivedOK = octets;
+
+ /* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */
+ octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x208)); /*OctetsOK*/
+ octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x20c))) << 32;
+ octets -= 18 * stats->aFramesTransmittedOK;
+ octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x230)); /*VLANOK*/
+ stats->aOctetsTransmittedOK = octets;
+
+ stats->etherStatsUndersizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x168));
+ stats->etherStatsFragments = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x1b8));
+ stats->etherStatsJabbers = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x1b0));
+ stats->etherStatsOversizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x1a8));
+
+ stats->aFrameCheckSequenceErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x128)); /* CRCErrors */
+ /* stats->aAlignmentErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x98)); */ /* not implemented */
+ stats->etherStatsDropEvents = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x158));
+ }
+ } else {
+ uint64_t octets;
+ /* TODO - change to 64 bit */
+ stats->ifInUcastPkts = al_eth_40g_mac_reg_read(adapter, 0x140);
+ stats->ifInMulticastPkts = al_eth_40g_mac_reg_read(adapter, 0x148);
+ stats->ifInBroadcastPkts = al_eth_40g_mac_reg_read(adapter, 0x150);
+ stats->etherStatsPkts = al_eth_40g_mac_reg_read(adapter, 0x160);
+ stats->ifOutUcastPkts = al_eth_40g_mac_reg_read(adapter, 0x240);
+ stats->ifOutMulticastPkts = al_eth_40g_mac_reg_read(adapter, 0x248);
+ stats->ifOutBroadcastPkts = al_eth_40g_mac_reg_read(adapter, 0x250);
+ stats->ifInErrors = al_eth_40g_mac_reg_read(adapter, 0x138);
+ stats->ifOutErrors = al_eth_40g_mac_reg_read(adapter, 0x238);
+ stats->aFramesReceivedOK = al_eth_40g_mac_reg_read(adapter, 0x120);
+ stats->aFramesTransmittedOK = al_eth_40g_mac_reg_read(adapter, 0x220);
+
+ /* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */
+ octets = al_eth_40g_mac_reg_read(adapter, 0x100);
+ octets |= (uint64_t)(al_eth_40g_mac_reg_read(adapter, 0x104)) << 32;
+ octets -= 18 * stats->aFramesReceivedOK;
+ octets -= 4 * al_eth_40g_mac_reg_read(adapter, 0x130); /*VLANOK*/
+ stats->aOctetsTransmittedOK = octets;
+
+ /* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */
+ octets = al_eth_40g_mac_reg_read(adapter, 0x200);
+ octets |= (uint64_t)(al_eth_40g_mac_reg_read(adapter, 0x204)) << 32;
+ octets -= 18 * stats->aFramesReceivedOK;
+ octets -= 4 * al_eth_40g_mac_reg_read(adapter, 0x230); /*VLANOK*/
+ stats->aOctetsReceivedOK = octets;
+
+ stats->etherStatsUndersizePkts = al_eth_40g_mac_reg_read(adapter, 0x168);
+ stats->etherStatsFragments = al_eth_40g_mac_reg_read(adapter, 0x1b8);
+ stats->etherStatsJabbers = al_eth_40g_mac_reg_read(adapter, 0x1b0);
+ stats->etherStatsOversizePkts = al_eth_40g_mac_reg_read(adapter, 0x1a8);
+ stats->aFrameCheckSequenceErrors = al_eth_40g_mac_reg_read(adapter, 0x128);
+ stats->aAlignmentErrors = al_eth_40g_mac_reg_read(adapter, 0x110);
+ stats->etherStatsDropEvents = al_eth_40g_mac_reg_read(adapter, 0x158);
+ }
+
+ stats->eee_in = al_reg_read32(&adapter->mac_regs_base->stat.eee_in);
+ stats->eee_out = al_reg_read32(&adapter->mac_regs_base->stat.eee_out);
+
+/* stats->etherStatsPkts = 1; */
+ return 0;
+}
+
+/**
+* read ec_stat_counters
+*/
+int al_eth_ec_stats_get(struct al_hal_eth_adapter *adapter, struct al_eth_ec_stats *stats)
+{
+ al_assert(stats);
+ stats->faf_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.faf_in_rx_pkt);
+ stats->faf_in_rx_short = al_reg_read32(&adapter->ec_regs_base->stat.faf_in_rx_short);
+ stats->faf_in_rx_long = al_reg_read32(&adapter->ec_regs_base->stat.faf_in_rx_long);
+ stats->faf_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.faf_out_rx_pkt);
+ stats->faf_out_rx_short = al_reg_read32(&adapter->ec_regs_base->stat.faf_out_rx_short);
+ stats->faf_out_rx_long = al_reg_read32(&adapter->ec_regs_base->stat.faf_out_rx_long);
+ stats->faf_out_drop = al_reg_read32(&adapter->ec_regs_base->stat.faf_out_drop);
+ stats->rxf_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rxf_in_rx_pkt);
+ stats->rxf_in_fifo_err = al_reg_read32(&adapter->ec_regs_base->stat.rxf_in_fifo_err);
+ stats->lbf_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.lbf_in_rx_pkt);
+ stats->lbf_in_fifo_err = al_reg_read32(&adapter->ec_regs_base->stat.lbf_in_fifo_err);
+ stats->rxf_out_rx_1_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rxf_out_rx_1_pkt);
+ stats->rxf_out_rx_2_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rxf_out_rx_2_pkt);
+ stats->rxf_out_drop_1_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rxf_out_drop_1_pkt);
+ stats->rxf_out_drop_2_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rxf_out_drop_2_pkt);
+ stats->rpe_1_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_1_in_rx_pkt);
+ stats->rpe_1_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_1_out_rx_pkt);
+ stats->rpe_2_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_2_in_rx_pkt);
+ stats->rpe_2_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_2_out_rx_pkt);
+ stats->rpe_3_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_3_in_rx_pkt);
+ stats->rpe_3_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_3_out_rx_pkt);
+ stats->tpe_in_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.tpe_in_tx_pkt);
+ stats->tpe_out_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.tpe_out_tx_pkt);
+ stats->tpm_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.tpm_tx_pkt);
+ stats->tfw_in_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.tfw_in_tx_pkt);
+ stats->tfw_out_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.tfw_out_tx_pkt);
+ stats->rfw_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_rx_pkt);
+ stats->rfw_in_vlan_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_vlan_drop);
+ stats->rfw_in_parse_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_parse_drop);
+ stats->rfw_in_mc = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_mc);
+ stats->rfw_in_bc = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_bc);
+ stats->rfw_in_vlan_exist = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_vlan_exist);
+ stats->rfw_in_vlan_nexist = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_vlan_nexist);
+ stats->rfw_in_mac_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_mac_drop);
+ stats->rfw_in_mac_ndet_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_mac_ndet_drop);
+ stats->rfw_in_ctrl_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_ctrl_drop);
+ stats->rfw_in_prot_i_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_prot_i_drop);
+ stats->eee_in = al_reg_read32(&adapter->ec_regs_base->stat.eee_in);
+ return 0;
+}
+
+/**
+ * read per_udma_counters
+ */
+int al_eth_ec_stat_udma_get(struct al_hal_eth_adapter *adapter, uint8_t idx, struct al_eth_ec_stat_udma *stats)
+{
+
+ al_assert(idx <= 3); /*valid udma_id*/
+ al_assert(stats);
+ stats->rfw_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].rfw_out_rx_pkt);
+ stats->rfw_out_drop = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].rfw_out_drop);
+ stats->msw_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_in_rx_pkt);
+ stats->msw_drop_q_full = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_drop_q_full);
+ stats->msw_drop_sop = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_drop_sop);
+ stats->msw_drop_eop = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_drop_eop);
+ stats->msw_wr_eop = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_wr_eop);
+ stats->msw_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_out_rx_pkt);
+ stats->tso_no_tso_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tso_no_tso_pkt);
+ stats->tso_tso_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tso_tso_pkt);
+ stats->tso_seg_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tso_seg_pkt);
+ stats->tso_pad_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tso_pad_pkt);
+ stats->tpm_tx_spoof = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tpm_tx_spoof);
+ stats->tmi_in_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tmi_in_tx_pkt);
+ stats->tmi_out_to_mac = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tmi_out_to_mac);
+ stats->tmi_out_to_rx = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tmi_out_to_rx);
+ stats->tx_q0_bytes = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q0_bytes);
+ stats->tx_q1_bytes = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q1_bytes);
+ stats->tx_q2_bytes = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q2_bytes);
+ stats->tx_q3_bytes = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q3_bytes);
+ stats->tx_q0_pkts = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q0_pkts);
+ stats->tx_q1_pkts = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q1_pkts);
+ stats->tx_q2_pkts = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q2_pkts);
+ stats->tx_q3_pkts = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q3_pkts);
+ return 0;
+}
+
+/* Traffic control */
+
+
+int al_eth_flr_rmn(int (* pci_read_config_u32)(void *handle, int where, uint32_t *val),
+ int (* pci_write_config_u32)(void *handle, int where, uint32_t val),
+ void *handle,
+ void __iomem *mac_base)
+{
+ struct al_eth_mac_regs __iomem *mac_regs_base =
+ (struct al_eth_mac_regs __iomem *)mac_base;
+ uint32_t cfg_reg_store[6];
+ uint32_t reg;
+ uint32_t mux_sel;
+ int i = 0;
+
+ (*pci_read_config_u32)(handle, AL_ADAPTER_GENERIC_CONTROL_0, &reg);
+
+ /* reset 1G mac */
+ AL_REG_MASK_SET(reg, AL_ADAPTER_GENERIC_CONTROL_0_ETH_RESET_1GMAC);
+ (*pci_write_config_u32)(handle, AL_ADAPTER_GENERIC_CONTROL_0, reg);
+ al_udelay(1000);
+ /* don't reset 1G mac */
+ AL_REG_MASK_CLEAR(reg, AL_ADAPTER_GENERIC_CONTROL_0_ETH_RESET_1GMAC);
+ /* prevent 1G mac reset on FLR */
+ AL_REG_MASK_CLEAR(reg, AL_ADAPTER_GENERIC_CONTROL_0_ETH_RESET_1GMAC_ON_FLR);
+ /* prevent adapter reset */
+ (*pci_write_config_u32)(handle, AL_ADAPTER_GENERIC_CONTROL_0, reg);
+
+ mux_sel = al_reg_read32(&mac_regs_base->gen.mux_sel);
+
+ /* save pci register that get reset due to flr*/
+ (*pci_read_config_u32)(handle, AL_PCI_COMMAND, &cfg_reg_store[i++]);
+ (*pci_read_config_u32)(handle, 0xC, &cfg_reg_store[i++]);
+ (*pci_read_config_u32)(handle, 0x10, &cfg_reg_store[i++]);
+ (*pci_read_config_u32)(handle, 0x18, &cfg_reg_store[i++]);
+ (*pci_read_config_u32)(handle, 0x20, &cfg_reg_store[i++]);
+ (*pci_read_config_u32)(handle, 0x110, &cfg_reg_store[i++]);
+
+ /* do flr */
+ (*pci_write_config_u32)(handle, AL_PCI_EXP_CAP_BASE + AL_PCI_EXP_DEVCTL, AL_PCI_EXP_DEVCTL_BCR_FLR);
+ al_udelay(1000);
+ /* restore command */
+ i = 0;
+ (*pci_write_config_u32)(handle, AL_PCI_COMMAND, cfg_reg_store[i++]);
+ (*pci_write_config_u32)(handle, 0xC, cfg_reg_store[i++]);
+ (*pci_write_config_u32)(handle, 0x10, cfg_reg_store[i++]);
+ (*pci_write_config_u32)(handle, 0x18, cfg_reg_store[i++]);
+ (*pci_write_config_u32)(handle, 0x20, cfg_reg_store[i++]);
+ (*pci_write_config_u32)(handle, 0x110, cfg_reg_store[i++]);
+
+ al_reg_write32_masked(&mac_regs_base->gen.mux_sel, ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, mux_sel);
+
+ /* set SGMII clock to 125MHz */
+ al_reg_write32(mac_base + 0xB08, 0x03320501);
+
+ /* reset 1G mac */
+ AL_REG_MASK_SET(reg, AL_ADAPTER_GENERIC_CONTROL_0_ETH_RESET_1GMAC);
+ (*pci_write_config_u32)(handle, AL_ADAPTER_GENERIC_CONTROL_0, reg);
+
+ al_udelay(1000);
+
+ /* clear 1G mac reset */
+ AL_REG_MASK_CLEAR(reg, AL_ADAPTER_GENERIC_CONTROL_0_ETH_RESET_1GMAC);
+ (*pci_write_config_u32)(handle, AL_ADAPTER_GENERIC_CONTROL_0, reg);
+
+ /* reset SGMII mac clock to default */
+ al_reg_write32(mac_base + 0xB08, 0x00320501);
+ al_udelay(1000);
+ /* reset async fifo */
+ reg = al_reg_read32((void*)((uint32_t)mac_base + 0x95c));
+ AL_REG_MASK_SET(reg, 0xF0);
+ al_reg_write32((void*)((uint32_t)mac_base + 0x95c), reg);
+ reg = al_reg_read32((void*)((uint32_t)mac_base + 0x95c));
+ AL_REG_MASK_CLEAR(reg, 0xF0);
+ al_reg_write32((void*)((uint32_t)mac_base + 0x95c), reg);
+
+ return 0;
+}
+
+int al_eth_flr_rmn_restore_params(int (* pci_read_config_u32)(void *handle, int where, uint32_t *val),
+ int (* pci_write_config_u32)(void *handle, int where, uint32_t val),
+ void *handle,
+ void __iomem *mac_base,
+ void __iomem *ec_base,
+ int mac_addresses_num
+ )
+{
+ struct al_eth_board_params params = { .media_type = 0 };
+ uint8_t mac_addr[6];
+ int rc;
+
+ /* not implemented yet */
+ if (mac_addresses_num > 1)
+ return -EPERM;
+
+ /* save board params so we restore it after reset */
+ al_eth_board_params_get(mac_base, &params);
+ al_eth_mac_addr_read(ec_base, 0, mac_addr);
+
+ rc = al_eth_flr_rmn(pci_read_config_u32, pci_write_config_u32, handle, mac_base);
+ al_eth_board_params_set(mac_base, &params);
+ al_eth_mac_addr_store(ec_base, 0, mac_addr);
+
+ return rc;
+}
+
+/* board params register 1 */
+#define AL_HAL_ETH_MEDIA_TYPE_MASK (AL_FIELD_MASK(3, 0))
+#define AL_HAL_ETH_MEDIA_TYPE_SHIFT 0
+#define AL_HAL_ETH_EXT_PHY_SHIFT 4
+#define AL_HAL_ETH_PHY_ADDR_MASK (AL_FIELD_MASK(9, 5))
+#define AL_HAL_ETH_PHY_ADDR_SHIFT 5
+#define AL_HAL_ETH_SFP_EXIST_SHIFT 10
+#define AL_HAL_ETH_AN_ENABLE_SHIFT 11
+#define AL_HAL_ETH_KR_LT_ENABLE_SHIFT 12
+#define AL_HAL_ETH_KR_FEC_ENABLE_SHIFT 13
+#define AL_HAL_ETH_MDIO_FREQ_MASK (AL_FIELD_MASK(15, 14))
+#define AL_HAL_ETH_MDIO_FREQ_SHIFT 14
+#define AL_HAL_ETH_I2C_ADAPTER_ID_MASK (AL_FIELD_MASK(19, 16))
+#define AL_HAL_ETH_I2C_ADAPTER_ID_SHIFT 16
+#define AL_HAL_ETH_EXT_PHY_IF_MASK (AL_FIELD_MASK(21, 20))
+#define AL_HAL_ETH_EXT_PHY_IF_SHIFT 20
+#define AL_HAL_ETH_AUTO_NEG_MODE_SHIFT 22
+#define AL_HAL_ETH_SERDES_GRP_MASK (AL_FIELD_MASK(26, 25))
+#define AL_HAL_ETH_SERDES_GRP_SHIFT 25
+#define AL_HAL_ETH_SERDES_LANE_MASK (AL_FIELD_MASK(28, 27))
+#define AL_HAL_ETH_SERDES_LANE_SHIFT 27
+#define AL_HAL_ETH_REF_CLK_FREQ_MASK (AL_FIELD_MASK(31, 29))
+#define AL_HAL_ETH_REF_CLK_FREQ_SHIFT 29
+
+/* board params register 2 */
+#define AL_HAL_ETH_DONT_OVERRIDE_SERDES_SHIFT 0
+#define AL_HAL_ETH_1000_BASE_X_SHIFT 1
+#define AL_HAL_ETH_1G_AN_DISABLE_SHIFT 2
+#define AL_HAL_ETH_1G_SPEED_MASK (AL_FIELD_MASK(4, 3))
+#define AL_HAL_ETH_1G_SPEED_SHIFT 3
+#define AL_HAL_ETH_1G_HALF_DUPLEX_SHIFT 5
+#define AL_HAL_ETH_1G_FC_DISABLE_SHIFT 6
+#define AL_HAL_ETH_RETIMER_EXIST_SHIFT 7
+#define AL_HAL_ETH_RETIMER_BUS_ID_MASK (AL_FIELD_MASK(11, 8))
+#define AL_HAL_ETH_RETIMER_BUS_ID_SHIFT 8
+#define AL_HAL_ETH_RETIMER_I2C_ADDR_MASK (AL_FIELD_MASK(18, 12))
+#define AL_HAL_ETH_RETIMER_I2C_ADDR_SHIFT 12
+#define AL_HAL_ETH_RETIMER_CHANNEL_SHIFT 19
+#define AL_HAL_ETH_DAC_LENGTH_MASK (AL_FIELD_MASK(23, 20))
+#define AL_HAL_ETH_DAC_LENGTH_SHIFT 20
+#define AL_HAL_ETH_DAC_SHIFT 24
+#define AL_HAL_ETH_RETIMER_TYPE_MASK (AL_FIELD_MASK(26, 25))
+#define AL_HAL_ETH_RETIMER_TYPE_SHIFT 25
+#define AL_HAL_ETH_RETIMER_CHANNEL_2_SHIFT 27
+
+int al_eth_board_params_set(void * __iomem mac_base, struct al_eth_board_params *params){
+ uint32_t reg = 0;
+
+ /* ************* Setting Board params register 1 **************** */
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_MEDIA_TYPE_MASK,
+ AL_HAL_ETH_MEDIA_TYPE_SHIFT, params->media_type);
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_EXT_PHY_SHIFT, params->phy_exist == AL_TRUE);
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_PHY_ADDR_MASK,
+ AL_HAL_ETH_PHY_ADDR_SHIFT, params->phy_mdio_addr);
+
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_SFP_EXIST_SHIFT, params->sfp_plus_module_exist == AL_TRUE);
+
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_AN_ENABLE_SHIFT, params->autoneg_enable == AL_TRUE);
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_KR_LT_ENABLE_SHIFT, params->kr_lt_enable == AL_TRUE);
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_KR_FEC_ENABLE_SHIFT, params->kr_fec_enable == AL_TRUE);
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_MDIO_FREQ_MASK,
+ AL_HAL_ETH_MDIO_FREQ_SHIFT, params->mdio_freq);
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_I2C_ADAPTER_ID_MASK,
+ AL_HAL_ETH_I2C_ADAPTER_ID_SHIFT, params->i2c_adapter_id);
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_EXT_PHY_IF_MASK,
+ AL_HAL_ETH_EXT_PHY_IF_SHIFT, params->phy_if);
+
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_AUTO_NEG_MODE_SHIFT,
+ params->an_mode == AL_ETH_BOARD_AUTONEG_IN_BAND);
+
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_SERDES_GRP_MASK,
+ AL_HAL_ETH_SERDES_GRP_SHIFT, params->serdes_grp);
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_SERDES_LANE_MASK,
+ AL_HAL_ETH_SERDES_LANE_SHIFT, params->serdes_lane);
+
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_REF_CLK_FREQ_MASK,
+ AL_HAL_ETH_REF_CLK_FREQ_SHIFT, params->ref_clk_freq);
+
+ al_assert(reg != 0);
+
+ al_reg_write32(mac_base + 0x4, reg);
+
+ /* ************* Setting Board params register 2 **************** */
+ reg = 0;
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_DONT_OVERRIDE_SERDES_SHIFT,
+ params->dont_override_serdes == AL_TRUE);
+
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_1000_BASE_X_SHIFT,
+ params->force_1000_base_x == AL_TRUE);
+
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_1G_AN_DISABLE_SHIFT,
+ params->an_disable == AL_TRUE);
+
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_1G_SPEED_MASK,
+ AL_HAL_ETH_1G_SPEED_SHIFT, params->speed);
+
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_1G_HALF_DUPLEX_SHIFT,
+ params->half_duplex == AL_TRUE);
+
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_1G_FC_DISABLE_SHIFT,
+ params->fc_disable == AL_TRUE);
+
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_RETIMER_EXIST_SHIFT, params->retimer_exist == AL_TRUE);
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_RETIMER_BUS_ID_MASK,
+ AL_HAL_ETH_RETIMER_BUS_ID_SHIFT, params->retimer_bus_id);
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_RETIMER_I2C_ADDR_MASK,
+ AL_HAL_ETH_RETIMER_I2C_ADDR_SHIFT, params->retimer_i2c_addr);
+
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_RETIMER_CHANNEL_SHIFT,
+ ((params->retimer_channel == AL_ETH_RETIMER_CHANNEL_B) ||
+ (params->retimer_channel == AL_ETH_RETIMER_CHANNEL_D)));
+
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_RETIMER_CHANNEL_2_SHIFT,
+ ((params->retimer_channel == AL_ETH_RETIMER_CHANNEL_C) ||
+ (params->retimer_channel == AL_ETH_RETIMER_CHANNEL_D)));
+
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_DAC_LENGTH_MASK,
+ AL_HAL_ETH_DAC_LENGTH_SHIFT, params->dac_len);
+ AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_DAC_SHIFT, params->dac);
+
+ AL_REG_FIELD_SET(reg, AL_HAL_ETH_RETIMER_TYPE_MASK,
+ AL_HAL_ETH_RETIMER_TYPE_SHIFT, params->retimer_type);
+
+ al_reg_write32(mac_base + 0x404, reg);
+ return 0;
+}
+
+int al_eth_board_params_get(void * __iomem mac_base, struct al_eth_board_params *params){
+ uint32_t reg = al_reg_read32((void*)((uint32_t)mac_base + 0x4));
+
+ /* check if the register was initialized, 0 is not a valid value */
+ if (reg == 0)
+ return -ENOENT;
+
+ /* ************* Getting Board params register 1 **************** */
+ params->media_type = AL_REG_FIELD_GET(reg, AL_HAL_ETH_MEDIA_TYPE_MASK,
+ AL_HAL_ETH_MEDIA_TYPE_SHIFT);
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_EXT_PHY_SHIFT))
+ params->phy_exist = AL_TRUE;
+ else
+ params->phy_exist = AL_FALSE;
+
+ params->phy_mdio_addr = AL_REG_FIELD_GET(reg, AL_HAL_ETH_PHY_ADDR_MASK,
+ AL_HAL_ETH_PHY_ADDR_SHIFT);
+
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_SFP_EXIST_SHIFT))
+ params->sfp_plus_module_exist = AL_TRUE;
+ else
+ params->sfp_plus_module_exist = AL_FALSE;
+
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_AN_ENABLE_SHIFT))
+ params->autoneg_enable = AL_TRUE;
+ else
+ params->autoneg_enable = AL_FALSE;
+
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_KR_LT_ENABLE_SHIFT))
+ params->kr_lt_enable = AL_TRUE;
+ else
+ params->kr_lt_enable = AL_FALSE;
+
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_KR_FEC_ENABLE_SHIFT))
+ params->kr_fec_enable = AL_TRUE;
+ else
+ params->kr_fec_enable = AL_FALSE;
+
+ params->mdio_freq = AL_REG_FIELD_GET(reg,
+ AL_HAL_ETH_MDIO_FREQ_MASK,
+ AL_HAL_ETH_MDIO_FREQ_SHIFT);
+
+ params->i2c_adapter_id = AL_REG_FIELD_GET(reg,
+ AL_HAL_ETH_I2C_ADAPTER_ID_MASK,
+ AL_HAL_ETH_I2C_ADAPTER_ID_SHIFT);
+
+ params->phy_if = AL_REG_FIELD_GET(reg,
+ AL_HAL_ETH_EXT_PHY_IF_MASK,
+ AL_HAL_ETH_EXT_PHY_IF_SHIFT);
+
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_AUTO_NEG_MODE_SHIFT))
+ params->an_mode = AL_TRUE;
+ else
+ params->an_mode = AL_FALSE;
+
+ params->serdes_grp = AL_REG_FIELD_GET(reg,
+ AL_HAL_ETH_SERDES_GRP_MASK,
+ AL_HAL_ETH_SERDES_GRP_SHIFT);
+
+ params->serdes_lane = AL_REG_FIELD_GET(reg,
+ AL_HAL_ETH_SERDES_LANE_MASK,
+ AL_HAL_ETH_SERDES_LANE_SHIFT);
+
+ params->ref_clk_freq = AL_REG_FIELD_GET(reg,
+ AL_HAL_ETH_REF_CLK_FREQ_MASK,
+ AL_HAL_ETH_REF_CLK_FREQ_SHIFT);
+
+ /* ************* Getting Board params register 2 **************** */
+ reg = al_reg_read32((void*)((uint32_t)mac_base + 0x404));
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_DONT_OVERRIDE_SERDES_SHIFT))
+ params->dont_override_serdes = AL_TRUE;
+ else
+ params->dont_override_serdes = AL_FALSE;
+
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_1000_BASE_X_SHIFT))
+ params->force_1000_base_x = AL_TRUE;
+ else
+ params->force_1000_base_x = AL_FALSE;
+
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_1G_AN_DISABLE_SHIFT))
+ params->an_disable = AL_TRUE;
+ else
+ params->an_disable = AL_FALSE;
+
+ params->speed = AL_REG_FIELD_GET(reg,
+ AL_HAL_ETH_1G_SPEED_MASK,
+ AL_HAL_ETH_1G_SPEED_SHIFT);
+
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_1G_HALF_DUPLEX_SHIFT))
+ params->half_duplex = AL_TRUE;
+ else
+ params->half_duplex = AL_FALSE;
+
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_1G_FC_DISABLE_SHIFT))
+ params->fc_disable = AL_TRUE;
+ else
+ params->fc_disable = AL_FALSE;
+
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_RETIMER_EXIST_SHIFT))
+ params->retimer_exist = AL_TRUE;
+ else
+ params->retimer_exist = AL_FALSE;
+
+ params->retimer_bus_id = AL_REG_FIELD_GET(reg,
+ AL_HAL_ETH_RETIMER_BUS_ID_MASK,
+ AL_HAL_ETH_RETIMER_BUS_ID_SHIFT);
+ params->retimer_i2c_addr = AL_REG_FIELD_GET(reg,
+ AL_HAL_ETH_RETIMER_I2C_ADDR_MASK,
+ AL_HAL_ETH_RETIMER_I2C_ADDR_SHIFT);
+
+ params->retimer_channel =
+ ((AL_REG_BIT_GET(reg, AL_HAL_ETH_RETIMER_CHANNEL_SHIFT)) |
+ (AL_REG_BIT_GET(reg, AL_HAL_ETH_RETIMER_CHANNEL_2_SHIFT) << 1));
+
+ params->dac_len = AL_REG_FIELD_GET(reg,
+ AL_HAL_ETH_DAC_LENGTH_MASK,
+ AL_HAL_ETH_DAC_LENGTH_SHIFT);
+
+ if (AL_REG_BIT_GET(reg, AL_HAL_ETH_DAC_SHIFT))
+ params->dac = AL_TRUE;
+ else
+ params->dac = AL_FALSE;
+
+ params->retimer_type = AL_REG_FIELD_GET(reg,
+ AL_HAL_ETH_RETIMER_TYPE_MASK,
+ AL_HAL_ETH_RETIMER_TYPE_SHIFT);
+
+ return 0;
+}
+
+/* Wake-On-Lan (WoL) */
+static inline void al_eth_byte_arr_to_reg(
+ uint32_t *reg, uint8_t *arr, unsigned int num_bytes)
+{
+ uint32_t mask = 0xff;
+ unsigned int i;
+
+ al_assert(num_bytes <= 4);
+
+ *reg = 0;
+
+ for (i = 0 ; i < num_bytes ; i++) {
+ AL_REG_FIELD_SET(*reg, mask, (sizeof(uint8_t) * i), arr[i]);
+ mask = mask << sizeof(uint8_t);
+ }
+}
+
+int al_eth_wol_enable(
+ struct al_hal_eth_adapter *adapter,
+ struct al_eth_wol_params *wol)
+{
+ uint32_t reg = 0;
+
+ if (wol->int_mask & AL_ETH_WOL_INT_MAGIC_PSWD) {
+ al_assert(wol->pswd != NULL);
+
+ al_eth_byte_arr_to_reg(&reg, &wol->pswd[0], 4);
+ al_reg_write32(&adapter->ec_regs_base->wol.magic_pswd_l, reg);
+
+ al_eth_byte_arr_to_reg(&reg, &wol->pswd[4], 2);
+ al_reg_write32(&adapter->ec_regs_base->wol.magic_pswd_h, reg);
+ }
+
+ if (wol->int_mask & AL_ETH_WOL_INT_IPV4) {
+ al_assert(wol->ipv4 != NULL);
+
+ al_eth_byte_arr_to_reg(&reg, &wol->ipv4[0], 4);
+ al_reg_write32(&adapter->ec_regs_base->wol.ipv4_dip, reg);
+ }
+
+ if (wol->int_mask & AL_ETH_WOL_INT_IPV6) {
+ al_assert(wol->ipv6 != NULL);
+
+ al_eth_byte_arr_to_reg(&reg, &wol->ipv6[0], 4);
+ al_reg_write32(&adapter->ec_regs_base->wol.ipv6_dip_word0, reg);
+
+ al_eth_byte_arr_to_reg(&reg, &wol->ipv6[4], 4);
+ al_reg_write32(&adapter->ec_regs_base->wol.ipv6_dip_word1, reg);
+
+ al_eth_byte_arr_to_reg(&reg, &wol->ipv6[8], 4);
+ al_reg_write32(&adapter->ec_regs_base->wol.ipv6_dip_word2, reg);
+
+ al_eth_byte_arr_to_reg(&reg, &wol->ipv6[12], 4);
+ al_reg_write32(&adapter->ec_regs_base->wol.ipv6_dip_word3, reg);
+ }
+
+ if (wol->int_mask &
+ (AL_ETH_WOL_INT_ETHERTYPE_BC | AL_ETH_WOL_INT_ETHERTYPE_DA)) {
+
+ reg = ((uint32_t)wol->ethr_type2 << 16);
+ reg |= wol->ethr_type1;
+
+ al_reg_write32(&adapter->ec_regs_base->wol.ethertype, reg);
+ }
+
+ /* make sure we dont forwarding packets without interrupt */
+ al_assert((wol->forward_mask | wol->int_mask) == wol->int_mask);
+
+ reg = ((uint32_t)wol->forward_mask << 16);
+ reg |= wol->int_mask;
+ al_reg_write32(&adapter->ec_regs_base->wol.wol_en, reg);
+
+ return 0;
+}
+
+int al_eth_wol_disable(
+ struct al_hal_eth_adapter *adapter)
+{
+ al_reg_write32(&adapter->ec_regs_base->wol.wol_en, 0);
+
+ return 0;
+}
+
+int al_eth_tx_fwd_vid_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ uint8_t udma_mask, al_bool fwd_to_mac)
+{
+ uint32_t val = 0;
+ al_assert(idx < AL_ETH_FWD_VID_TABLE_NUM); /* valid VID index */
+ AL_REG_FIELD_SET(val, AL_ETH_TX_VLAN_TABLE_UDMA_MASK, 0, udma_mask);
+ AL_REG_FIELD_SET(val, AL_ETH_TX_VLAN_TABLE_FWD_TO_MAC, 4, fwd_to_mac);
+
+ al_reg_write32(&adapter->ec_regs_base->tfw.tx_vid_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->tfw.tx_vid_table_data, val);
+ return 0;
+}
+
+int al_eth_tx_protocol_detect_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ struct al_eth_tx_gpd_cam_entry *tx_gpd_entry)
+{
+ uint64_t gpd_data;
+ uint64_t gpd_mask;
+
+ gpd_data = ((uint64_t)tx_gpd_entry->l3_proto_idx & AL_ETH_TX_GPD_L3_PROTO_MASK) <<
+ AL_ETH_TX_GPD_L3_PROTO_SHIFT;
+ gpd_data |= ((uint64_t)tx_gpd_entry->l4_proto_idx & AL_ETH_TX_GPD_L4_PROTO_MASK) <<
+ AL_ETH_TX_GPD_L4_PROTO_SHIFT;
+ gpd_data |= ((uint64_t)tx_gpd_entry->tunnel_control & AL_ETH_TX_GPD_TUNNEL_CTRL_MASK) <<
+ AL_ETH_TX_GPD_TUNNEL_CTRL_SHIFT;
+ gpd_data |= ((uint64_t)tx_gpd_entry->source_vlan_count & AL_ETH_TX_GPD_SRC_VLAN_CNT_MASK) <<
+ AL_ETH_TX_GPD_SRC_VLAN_CNT_SHIFT;
+ gpd_mask = ((uint64_t)tx_gpd_entry->l3_proto_idx_mask & AL_ETH_TX_GPD_L3_PROTO_MASK) <<
+ AL_ETH_TX_GPD_L3_PROTO_SHIFT;
+ gpd_mask |= ((uint64_t)tx_gpd_entry->l4_proto_idx_mask & AL_ETH_TX_GPD_L4_PROTO_MASK) <<
+ AL_ETH_TX_GPD_L4_PROTO_SHIFT;
+ gpd_mask |= ((uint64_t)tx_gpd_entry->tunnel_control_mask & AL_ETH_TX_GPD_TUNNEL_CTRL_MASK) <<
+ AL_ETH_TX_GPD_TUNNEL_CTRL_SHIFT;
+ gpd_mask |= ((uint64_t)tx_gpd_entry->source_vlan_count_mask & AL_ETH_TX_GPD_SRC_VLAN_CNT_MASK) <<
+ AL_ETH_TX_GPD_SRC_VLAN_CNT_SHIFT;
+
+ /* Tx Generic protocol detect Cam compare table */
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_ctrl,
+ (uint32_t)((tx_gpd_entry->tx_gpd_cam_ctrl) << AL_ETH_TX_GPD_CAM_CTRL_VALID_SHIFT));
+ al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], tx_gpd_cam_ctrl: %#x", idx, tx_gpd_entry->tx_gpd_cam_ctrl);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_mask_2,
+ (uint32_t)(gpd_mask >> AL_ETH_TX_GPD_CAM_MASK_2_SHIFT));
+ al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], tx_gpd_cam_mask_2: %#x", idx, (uint32_t)(gpd_mask >> AL_ETH_TX_GPD_CAM_MASK_2_SHIFT));
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_mask_1,
+ (uint32_t)(gpd_mask));
+ al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], tx_gpd_cam_mask_1: %#x", idx, (uint32_t)(gpd_mask));
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_data_2,
+ (uint32_t)(gpd_data >> AL_ETH_TX_GPD_CAM_DATA_2_SHIFT));
+ al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], tx_gpd_cam_data_2: %#x", idx, (uint32_t)(gpd_data >> AL_ETH_TX_GPD_CAM_DATA_2_SHIFT));
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_data_1,
+ (uint32_t)(gpd_data));
+ al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], tx_gpd_cam_data_1: %#x", idx, (uint32_t)(gpd_data));
+ return 0;
+}
+
+int al_eth_tx_generic_crc_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ struct al_eth_tx_gcp_table_entry *tx_gcp_entry)
+{
+ uint32_t gcp_table_gen;
+ uint32_t tx_alu_opcode;
+ uint32_t tx_alu_opsel;
+
+ gcp_table_gen = (tx_gcp_entry->poly_sel & AL_ETH_TX_GCP_POLY_SEL_MASK) <<
+ AL_ETH_TX_GCP_POLY_SEL_SHIFT;
+ gcp_table_gen |= (tx_gcp_entry->crc32_bit_comp & AL_ETH_TX_GCP_CRC32_BIT_COMP_MASK) <<
+ AL_ETH_TX_GCP_CRC32_BIT_COMP_SHIFT;
+ gcp_table_gen |= (tx_gcp_entry->crc32_bit_swap & AL_ETH_TX_GCP_CRC32_BIT_SWAP_MASK) <<
+ AL_ETH_TX_GCP_CRC32_BIT_SWAP_SHIFT;
+ gcp_table_gen |= (tx_gcp_entry->crc32_byte_swap & AL_ETH_TX_GCP_CRC32_BYTE_SWAP_MASK) <<
+ AL_ETH_TX_GCP_CRC32_BYTE_SWAP_SHIFT;
+ gcp_table_gen |= (tx_gcp_entry->data_bit_swap & AL_ETH_TX_GCP_DATA_BIT_SWAP_MASK) <<
+ AL_ETH_TX_GCP_DATA_BIT_SWAP_SHIFT;
+ gcp_table_gen |= (tx_gcp_entry->data_byte_swap & AL_ETH_TX_GCP_DATA_BYTE_SWAP_MASK) <<
+ AL_ETH_TX_GCP_DATA_BYTE_SWAP_SHIFT;
+ gcp_table_gen |= (tx_gcp_entry->trail_size & AL_ETH_TX_GCP_TRAIL_SIZE_MASK) <<
+ AL_ETH_TX_GCP_TRAIL_SIZE_SHIFT;
+ gcp_table_gen |= (tx_gcp_entry->head_size & AL_ETH_TX_GCP_HEAD_SIZE_MASK) <<
+ AL_ETH_TX_GCP_HEAD_SIZE_SHIFT;
+ gcp_table_gen |= (tx_gcp_entry->head_calc & AL_ETH_TX_GCP_HEAD_CALC_MASK) <<
+ AL_ETH_TX_GCP_HEAD_CALC_SHIFT;
+ gcp_table_gen |= (tx_gcp_entry->mask_polarity & AL_ETH_TX_GCP_MASK_POLARITY_MASK) <<
+ AL_ETH_TX_GCP_MASK_POLARITY_SHIFT;
+ al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], gcp_table_gen: %#x", idx, gcp_table_gen);
+
+ tx_alu_opcode = (tx_gcp_entry->tx_alu_opcode_1 & AL_ETH_TX_GCP_OPCODE_1_MASK) <<
+ AL_ETH_TX_GCP_OPCODE_1_SHIFT;
+ tx_alu_opcode |= (tx_gcp_entry->tx_alu_opcode_2 & AL_ETH_TX_GCP_OPCODE_2_MASK) <<
+ AL_ETH_TX_GCP_OPCODE_2_SHIFT;
+ tx_alu_opcode |= (tx_gcp_entry->tx_alu_opcode_3 & AL_ETH_TX_GCP_OPCODE_3_MASK) <<
+ AL_ETH_TX_GCP_OPCODE_3_SHIFT;
+ tx_alu_opsel = (tx_gcp_entry->tx_alu_opsel_1 & AL_ETH_TX_GCP_OPSEL_1_MASK) <<
+ AL_ETH_TX_GCP_OPSEL_1_SHIFT;
+ tx_alu_opsel |= (tx_gcp_entry->tx_alu_opsel_2 & AL_ETH_TX_GCP_OPSEL_2_MASK) <<
+ AL_ETH_TX_GCP_OPSEL_2_SHIFT;
+ tx_alu_opsel |= (tx_gcp_entry->tx_alu_opsel_3 & AL_ETH_TX_GCP_OPSEL_3_MASK) <<
+ AL_ETH_TX_GCP_OPSEL_3_SHIFT;
+ tx_alu_opsel |= (tx_gcp_entry->tx_alu_opsel_4 & AL_ETH_TX_GCP_OPSEL_4_MASK) <<
+ AL_ETH_TX_GCP_OPSEL_4_SHIFT;
+
+ /* Tx Generic crc prameters table general */
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_gen,
+ gcp_table_gen);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_1,
+ tx_gcp_entry->gcp_mask[0]);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_2,
+ tx_gcp_entry->gcp_mask[1]);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_3,
+ tx_gcp_entry->gcp_mask[2]);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_4,
+ tx_gcp_entry->gcp_mask[3]);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_5,
+ tx_gcp_entry->gcp_mask[4]);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_6,
+ tx_gcp_entry->gcp_mask[5]);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_crc_init,
+ tx_gcp_entry->crc_init);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_res,
+ tx_gcp_entry->gcp_table_res);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_alu_opcode,
+ tx_alu_opcode);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_alu_opsel,
+ tx_alu_opsel);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_alu_val,
+ tx_gcp_entry->alu_val);
+ return 0;
+}
+
+int al_eth_tx_crc_chksum_replace_cmd_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ struct al_eth_tx_crc_chksum_replace_cmd_for_protocol_num_entry *tx_replace_entry)
+{
+ uint32_t replace_table_address;
+ uint32_t tx_replace_cmd;
+
+ /* Tx crc_chksum_replace_cmd */
+ replace_table_address = L4_CHECKSUM_DIS_AND_L3_CHECKSUM_DIS | idx;
+ tx_replace_cmd = (uint32_t)(tx_replace_entry->l3_csum_en_00) << 0;
+ tx_replace_cmd |= (uint32_t)(tx_replace_entry->l4_csum_en_00) << 1;
+ tx_replace_cmd |= (uint32_t)(tx_replace_entry->crc_en_00) << 2;
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table_addr, replace_table_address);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table,
+ tx_replace_cmd);
+ replace_table_address = L4_CHECKSUM_DIS_AND_L3_CHECKSUM_EN | idx;
+ tx_replace_cmd = (uint32_t)(tx_replace_entry->l3_csum_en_01) << 0;
+ tx_replace_cmd |= (uint32_t)(tx_replace_entry->l4_csum_en_01) << 1;
+ tx_replace_cmd |= (uint32_t)(tx_replace_entry->crc_en_01) << 2;
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table_addr, replace_table_address);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table,
+ tx_replace_cmd);
+ replace_table_address = L4_CHECKSUM_EN_AND_L3_CHECKSUM_DIS | idx;
+ tx_replace_cmd = (uint32_t)(tx_replace_entry->l3_csum_en_10) << 0;
+ tx_replace_cmd |= (uint32_t)(tx_replace_entry->l4_csum_en_10) << 1;
+ tx_replace_cmd |= (uint32_t)(tx_replace_entry->crc_en_10) << 2;
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table_addr, replace_table_address);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table,
+ tx_replace_cmd);
+ replace_table_address = L4_CHECKSUM_EN_AND_L3_CHECKSUM_EN | idx;
+ tx_replace_cmd = (uint32_t)(tx_replace_entry->l3_csum_en_11) << 0;
+ tx_replace_cmd |= (uint32_t)(tx_replace_entry->l4_csum_en_11) << 1;
+ tx_replace_cmd |= (uint32_t)(tx_replace_entry->crc_en_11) << 2;
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table_addr, replace_table_address);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table,
+ tx_replace_cmd);
+
+ return 0;
+}
+
+int al_eth_rx_protocol_detect_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ struct al_eth_rx_gpd_cam_entry *rx_gpd_entry)
+{
+ uint64_t gpd_data;
+ uint64_t gpd_mask;
+
+ gpd_data = ((uint64_t)rx_gpd_entry->outer_l3_proto_idx & AL_ETH_RX_GPD_OUTER_L3_PROTO_MASK) <<
+ AL_ETH_RX_GPD_OUTER_L3_PROTO_SHIFT;
+ gpd_data |= ((uint64_t)rx_gpd_entry->outer_l4_proto_idx & AL_ETH_RX_GPD_OUTER_L4_PROTO_MASK) <<
+ AL_ETH_RX_GPD_OUTER_L4_PROTO_SHIFT;
+ gpd_data |= ((uint64_t)rx_gpd_entry->inner_l3_proto_idx & AL_ETH_RX_GPD_INNER_L3_PROTO_MASK) <<
+ AL_ETH_RX_GPD_INNER_L3_PROTO_SHIFT;
+ gpd_data |= ((uint64_t)rx_gpd_entry->inner_l4_proto_idx & AL_ETH_RX_GPD_INNER_L4_PROTO_MASK) <<
+ AL_ETH_RX_GPD_INNER_L4_PROTO_SHIFT;
+ gpd_data |= ((uint64_t)rx_gpd_entry->parse_ctrl & AL_ETH_RX_GPD_OUTER_PARSE_CTRL_MASK) <<
+ AL_ETH_RX_GPD_OUTER_PARSE_CTRL_SHIFT;
+ gpd_data |= ((uint64_t)rx_gpd_entry->outer_l3_len & AL_ETH_RX_GPD_INNER_PARSE_CTRL_MASK) <<
+ AL_ETH_RX_GPD_INNER_PARSE_CTRL_SHIFT;
+ gpd_data |= ((uint64_t)rx_gpd_entry->l3_priority & AL_ETH_RX_GPD_L3_PRIORITY_MASK) <<
+ AL_ETH_RX_GPD_L3_PRIORITY_SHIFT;
+ gpd_data |= ((uint64_t)rx_gpd_entry->l4_dst_port_lsb & AL_ETH_RX_GPD_L4_DST_PORT_LSB_MASK) <<
+ AL_ETH_RX_GPD_L4_DST_PORT_LSB_SHIFT;
+
+ gpd_mask = ((uint64_t)rx_gpd_entry->outer_l3_proto_idx_mask & AL_ETH_RX_GPD_OUTER_L3_PROTO_MASK) <<
+ AL_ETH_RX_GPD_OUTER_L3_PROTO_SHIFT;
+ gpd_mask |= ((uint64_t)rx_gpd_entry->outer_l4_proto_idx_mask & AL_ETH_RX_GPD_OUTER_L4_PROTO_MASK) <<
+ AL_ETH_RX_GPD_OUTER_L4_PROTO_SHIFT;
+ gpd_mask |= ((uint64_t)rx_gpd_entry->inner_l3_proto_idx_mask & AL_ETH_RX_GPD_INNER_L3_PROTO_MASK) <<
+ AL_ETH_RX_GPD_INNER_L3_PROTO_SHIFT;
+ gpd_mask |= ((uint64_t)rx_gpd_entry->inner_l4_proto_idx_mask & AL_ETH_RX_GPD_INNER_L4_PROTO_MASK) <<
+ AL_ETH_RX_GPD_INNER_L4_PROTO_SHIFT;
+ gpd_mask |= ((uint64_t)rx_gpd_entry->parse_ctrl_mask & AL_ETH_RX_GPD_OUTER_PARSE_CTRL_MASK) <<
+ AL_ETH_RX_GPD_OUTER_PARSE_CTRL_SHIFT;
+ gpd_mask |= ((uint64_t)rx_gpd_entry->outer_l3_len_mask & AL_ETH_RX_GPD_INNER_PARSE_CTRL_MASK) <<
+ AL_ETH_RX_GPD_INNER_PARSE_CTRL_SHIFT;
+ gpd_mask |= ((uint64_t)rx_gpd_entry->l3_priority_mask & AL_ETH_RX_GPD_L3_PRIORITY_MASK) <<
+ AL_ETH_RX_GPD_L3_PRIORITY_SHIFT;
+ gpd_mask |= ((uint64_t)rx_gpd_entry->l4_dst_port_lsb_mask & AL_ETH_RX_GPD_L4_DST_PORT_LSB_MASK) <<
+ AL_ETH_RX_GPD_L4_DST_PORT_LSB_SHIFT;
+
+ /* Rx Generic protocol detect Cam compare table */
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_ctrl,
+ (uint32_t)((rx_gpd_entry->rx_gpd_cam_ctrl) << AL_ETH_RX_GPD_CAM_CTRL_VALID_SHIFT));
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_mask_2,
+ (uint32_t)(gpd_mask >> AL_ETH_RX_GPD_CAM_MASK_2_SHIFT));
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_mask_1,
+ (uint32_t)(gpd_mask));
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_data_2,
+ (uint32_t)(gpd_data >> AL_ETH_RX_GPD_CAM_DATA_2_SHIFT));
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_data_1,
+ (uint32_t)(gpd_data));
+ return 0;
+}
+
+int al_eth_rx_generic_crc_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx,
+ struct al_eth_rx_gcp_table_entry *rx_gcp_entry)
+{
+ uint32_t gcp_table_gen;
+ uint32_t rx_alu_opcode;
+ uint32_t rx_alu_opsel;
+
+ gcp_table_gen = (rx_gcp_entry->poly_sel & AL_ETH_RX_GCP_POLY_SEL_MASK) <<
+ AL_ETH_RX_GCP_POLY_SEL_SHIFT;
+ gcp_table_gen |= (rx_gcp_entry->crc32_bit_comp & AL_ETH_RX_GCP_CRC32_BIT_COMP_MASK) <<
+ AL_ETH_RX_GCP_CRC32_BIT_COMP_SHIFT;
+ gcp_table_gen |= (rx_gcp_entry->crc32_bit_swap & AL_ETH_RX_GCP_CRC32_BIT_SWAP_MASK) <<
+ AL_ETH_RX_GCP_CRC32_BIT_SWAP_SHIFT;
+ gcp_table_gen |= (rx_gcp_entry->crc32_byte_swap & AL_ETH_RX_GCP_CRC32_BYTE_SWAP_MASK) <<
+ AL_ETH_RX_GCP_CRC32_BYTE_SWAP_SHIFT;
+ gcp_table_gen |= (rx_gcp_entry->data_bit_swap & AL_ETH_RX_GCP_DATA_BIT_SWAP_MASK) <<
+ AL_ETH_RX_GCP_DATA_BIT_SWAP_SHIFT;
+ gcp_table_gen |= (rx_gcp_entry->data_byte_swap & AL_ETH_RX_GCP_DATA_BYTE_SWAP_MASK) <<
+ AL_ETH_RX_GCP_DATA_BYTE_SWAP_SHIFT;
+ gcp_table_gen |= (rx_gcp_entry->trail_size & AL_ETH_RX_GCP_TRAIL_SIZE_MASK) <<
+ AL_ETH_RX_GCP_TRAIL_SIZE_SHIFT;
+ gcp_table_gen |= (rx_gcp_entry->head_size & AL_ETH_RX_GCP_HEAD_SIZE_MASK) <<
+ AL_ETH_RX_GCP_HEAD_SIZE_SHIFT;
+ gcp_table_gen |= (rx_gcp_entry->head_calc & AL_ETH_RX_GCP_HEAD_CALC_MASK) <<
+ AL_ETH_RX_GCP_HEAD_CALC_SHIFT;
+ gcp_table_gen |= (rx_gcp_entry->mask_polarity & AL_ETH_RX_GCP_MASK_POLARITY_MASK) <<
+ AL_ETH_RX_GCP_MASK_POLARITY_SHIFT;
+
+ rx_alu_opcode = (rx_gcp_entry->rx_alu_opcode_1 & AL_ETH_RX_GCP_OPCODE_1_MASK) <<
+ AL_ETH_RX_GCP_OPCODE_1_SHIFT;
+ rx_alu_opcode |= (rx_gcp_entry->rx_alu_opcode_2 & AL_ETH_RX_GCP_OPCODE_2_MASK) <<
+ AL_ETH_RX_GCP_OPCODE_2_SHIFT;
+ rx_alu_opcode |= (rx_gcp_entry->rx_alu_opcode_3 & AL_ETH_RX_GCP_OPCODE_3_MASK) <<
+ AL_ETH_RX_GCP_OPCODE_3_SHIFT;
+ rx_alu_opsel = (rx_gcp_entry->rx_alu_opsel_1 & AL_ETH_RX_GCP_OPSEL_1_MASK) <<
+ AL_ETH_RX_GCP_OPSEL_1_SHIFT;
+ rx_alu_opsel |= (rx_gcp_entry->rx_alu_opsel_2 & AL_ETH_RX_GCP_OPSEL_2_MASK) <<
+ AL_ETH_RX_GCP_OPSEL_2_SHIFT;
+ rx_alu_opsel |= (rx_gcp_entry->rx_alu_opsel_3 & AL_ETH_RX_GCP_OPSEL_3_MASK) <<
+ AL_ETH_RX_GCP_OPSEL_3_SHIFT;
+ rx_alu_opsel |= (rx_gcp_entry->rx_alu_opsel_4 & AL_ETH_RX_GCP_OPSEL_4_MASK) <<
+ AL_ETH_RX_GCP_OPSEL_4_SHIFT;
+
+ /* Rx Generic crc prameters table general */
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_addr, idx);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_gen,
+ gcp_table_gen);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_1,
+ rx_gcp_entry->gcp_mask[0]);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_2,
+ rx_gcp_entry->gcp_mask[1]);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_3,
+ rx_gcp_entry->gcp_mask[2]);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_4,
+ rx_gcp_entry->gcp_mask[3]);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_5,
+ rx_gcp_entry->gcp_mask[4]);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_6,
+ rx_gcp_entry->gcp_mask[5]);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_crc_init,
+ rx_gcp_entry->crc_init);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_res,
+ rx_gcp_entry->gcp_table_res);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_alu_opcode,
+ rx_alu_opcode);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_alu_opsel,
+ rx_alu_opsel);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_alu_val,
+ rx_gcp_entry->alu_val);
+ return 0;
+}
+
+
+#define AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM 9
+#define AL_ETH_RX_PROTOCOL_DETECT_ENTRIES_NUM 32
+
+static struct al_eth_tx_gpd_cam_entry
+al_eth_generic_tx_crc_gpd[AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM] = {
+
+ /* [0] roce (with grh, bth) */
+ {22, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x0, 0x0, },
+ /* [1] fcoe */
+ {21, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x0, 0x0, },
+ /* [2] routable_roce that is refered as l4_protocol, over IPV4 (and udp) */
+ {8, 23, 0, 0, 1,
+ 0x1f, 0x1f, 0x0, 0x0, },
+ /* [3] routable_roce that is refered as l4_protocol, over IPV6 (and udp) */
+ {11, 23, 0, 0, 1,
+ 0x1f, 0x1f, 0x0, 0x0, },
+ /* [4] routable_roce that is refered as tunneled_packet, over outer IPV4 and udp */
+ {23, 0, 5, 0, 1,
+ 0x1f, 0x0, 0x5, 0x0, },
+ /* [5] routable_roce that is refered as tunneled_packet, over outer IPV6 and udp */
+ {23, 0, 3, 0, 1,
+ 0x1f, 0x0, 0x5, 0x0 },
+ /* [6] GENERIC_STORAGE_READ over IPV4 (and udp) */
+ {8, 2, 0, 0, 1,
+ 0x1f, 0x1f, 0x0, 0x0, },
+ /* [7] GENERIC_STORAGE_READ over IPV6 (and udp) */
+ {11, 2, 0, 0, 1,
+ 0x1f, 0x1f, 0x0, 0x0, },
+ /* [8] default match */
+ {0, 0, 0, 0, 1,
+ 0x0, 0x0, 0x0, 0x0 }
+};
+
+static struct al_eth_tx_gcp_table_entry
+al_eth_generic_tx_crc_gcp[AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM] = {
+
+ /* [0] roce (with grh, bth) */
+ {0, 1, 1, 0, 1,
+ 0, 4, 8, 0, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0xffff7f03, 0x00000000, 0x00000000,
+ 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x0,
+ 0},
+ /* [1] fcoe */
+ {0, 1, 0, 0, 1,
+ 0, 8, 14, 1, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0,
+ 0},
+ /* [2] routable_roce that is refered as l4_protocol, over IPV4 (and udp) */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0,
+ 0},
+ /* [3] routable_roce that is refered as l4_protocol, over IPV6 (and udp) */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x7f030000, 0x00000000, 0x00000003,
+ 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x0,
+ 0},
+ /* [4] routable_roce that is refered as tunneled_packet, over outer IPV4 and udp */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 2, 0, 0, 0, 10,
+ 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0,
+ 28},
+ /* [5] routable_roce that is refered as tunneled_packet, over outer IPV6 and udp */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 2, 0, 0, 0, 10,
+ 0, 0, {0x7f030000, 0x00000000, 0x00000003,
+ 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x0,
+ 48},
+ /* [6] GENERIC_STORAGE_READ over IPV4 (and udp) */
+ {1, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 1, 0, 1, 0, 2,
+ 10, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0,
+ 8},
+ /* [7] GENERIC_STORAGE_READ over IPV6 (and udp) */
+ {1, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 1, 0, 1, 0, 2,
+ 10, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0,
+ 8},
+ /* [8] default match */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x0,
+ 0}
+};
+
+static struct al_eth_tx_crc_chksum_replace_cmd_for_protocol_num_entry
+al_eth_tx_crc_chksum_replace_cmd[AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM] = {
+
+ /* [0] roce (with grh, bth) */
+ {0,1,0,1, 0,0,0,0, 0,0,0,0},
+ /* [1] fcoe */
+ {0,1,0,1, 0,0,0,0, 0,0,0,0},
+ /* [2] routable_roce that is refered as l4_protocol, over IPV4 (and udp) */
+ {0,0,1,1, 0,0,0,0, 0,1,0,1},
+ /* [3] routable_roce that is refered as l4_protocol, over IPV6 (and udp) */
+ {0,0,1,1, 0,0,0,0, 0,0,0,0},
+ /* [4] routable_roce that is refered as tunneled_packet, over outer IPV4 and udp */
+ {0,1,0,1, 0,0,0,0, 0,0,0,0},
+ /* [5] routable_roce that is refered as tunneled_packet, over outer IPV6 and udp */
+ {0,1,0,1, 0,0,0,0, 0,0,0,0},
+ /* [6] GENERIC_STORAGE_READ over IPV4 (and udp) */
+ {0,0,1,1, 0,0,0,0, 0,1,0,1},
+ /* [7] GENERIC_STORAGE_READ over IPV6 (and udp) */
+ {0,0,1,1, 0,0,0,0, 0,0,0,0},
+ /* [8] default match */
+ {0,0,0,0, 0,0,1,1, 0,1,0,1}
+};
+
+static struct al_eth_rx_gpd_cam_entry
+al_eth_generic_rx_crc_gpd[AL_ETH_RX_PROTOCOL_DETECT_ENTRIES_NUM] = {
+
+ /* [0] roce (with grh, bth) */
+ {22, 0, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x0, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [1] fcoe */
+ {21, 0, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x0, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [2] routable_roce that is refered as l4_protocol, over IPV4 (and udp) */
+ {8, 23, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x1f, 0x0, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [3] routable_roce that is refered as l4_protocol, over IPV6 (and udp) */
+ {11, 23, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x1f, 0x0, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [4] routable_roce that is refered as tunneled_packet, over outer IPV4 and udp */
+ {8, 13, 23, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x1f, 0x1f, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [5] routable_roce that is refered as tunneled_packet, over outer IPV6 and udp */
+ {11, 13, 23, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x1f, 0x1f, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [6] tunneled roce (with grh, bth) over GRE over IPV4 */
+ {8, 0, 22, 0,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [7] tunneled roce (with grh, bth) over GRE over IPV6 */
+ {11, 0, 22, 0,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [8] tunneled fcoe over IPV4 */
+ {8, 0, 21, 0,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [9] tunneled fcoe over IPV6 */
+ {11, 0, 21, 0,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [10] tunneled routable_roce that is refered as l4_protocol, over IPV4 (and udp) over IPV4 */
+ {8, 0, 8, 23,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1f,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [11] tunneled routable_roce that is refered as l4_protocol, over IPV4 (and udp) over IPV6 */
+ {11, 0, 8, 23,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1f,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [12] tunneled routable_roce that is refered as l4_protocol, over IPV6 (and udp) over IPV4 */
+ {8, 0, 11, 23,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1f,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [13] tunneled routable_roce that is refered as l4_protocol, over IPV6 (and udp) over IPV6 */
+ {11, 0, 11, 23,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1f,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [14] l3_pkt - IPV4 */
+ {8, 0, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x1f, 0x0, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [15] l4_hdr over IPV4 */
+ {8, 12, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x1e, 0x0, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [16] l3_pkt - IPV6 */
+ {11, 0, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x1f, 0x0, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [17] l4_hdr over IPV6 */
+ {11, 12, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x1e, 0x0, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [18] IPV4 over IPV4 */
+ {8, 0, 8, 0,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1f,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [19] l4_hdr over IPV4 over IPV4 */
+ {8, 0, 8, 12,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1e,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [20] IPV4 over IPV6 */
+ {11, 0, 8, 0,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1f,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [21] l4_hdr over IPV4 over IPV6 */
+ {11, 0, 8, 12,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1e,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [22] IPV6 over IPV4 */
+ {8, 0, 11, 0,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1f,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [23] l4_hdr over IPV6 over IPV4 */
+ {8, 0, 11, 12,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1e,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [24] IPV6 over IPV6 */
+ {11, 0, 11, 0,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1f,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [25] l4_hdr over IPV6 over IPV6 */
+ {11, 0, 11, 12,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x1e,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [26] GENERIC_STORAGE_READ, over IPV4 (and udp) */
+ {8, 2, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x1f, 0x0, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [27] GENERIC_STORAGE_READ, over IPV6 (and udp) */
+ {11, 2, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0x1f, 0x1f, 0x0, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [28] tunneled GENERIC_STORAGE_READ over IPV4 (and udp) over IPV4/IPV6 */
+ {8, 0, 8, 2,
+ 4, 0, 0, 0, 1,
+ 0x18, 0x0, 0x1f, 0x1f,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [29] tunneled GENERIC_STORAGE_READ over IPV6 (and udp) over IPV4/IPV6 */
+ {8, 0, 11, 2,
+ 4, 0, 0, 0, 1,
+ 0x18, 0x0, 0x1f, 0x1f,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [30] tunneled L2 over GRE over IPV4 */
+ {8, 0, 0, 0,
+ 4, 0, 0, 0, 1,
+ 0x1f, 0x0, 0x1f, 0x0,
+ 0x4, 0x0, 0x0, 0x0},
+ /* [31] default match */
+ {0, 0, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0}
+};
+
+static struct al_eth_rx_gcp_table_entry
+al_eth_generic_rx_crc_gcp[AL_ETH_RX_PROTOCOL_DETECT_ENTRIES_NUM] = {
+
+ /* [0] roce (with grh, bth) */
+ {0, 1, 1, 0, 1,
+ 0, 4, 8, 0, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0xffff7f03, 0x00000000, 0x00000000,
+ 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010,
+ 0},
+ /* [1] fcoe */
+ {0, 1, 0, 0, 1,
+ 0, 8, 14, 1, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010,
+ 0},
+ /* [2] routable_roce that is refered as l4_protocol, over IPV4 (and udp) */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000011,
+ 0},
+ /* [3] routable_roce that is refered as l4_protocol, over IPV6 (and udp) */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x7f030000, 0x00000000, 0x00000003,
+ 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010,
+ 0},
+ /* [4] routable_roce that is refered as tunneled_packet, over outer IPV4 and udp */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 2, 0, 0, 0, 10,
+ 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0302201c,
+ 28},
+ /* [5] routable_roce that is refered as tunneled_packet, over outer IPV6 and udp */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 2, 0, 0, 0, 10,
+ 0, 0, {0x7f030000, 0x00000000, 0x00000003,
+ 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03002018,
+ 48},
+ /* [6] tunneled roce (with grh, bth) over IPV4 */
+ {0, 1, 1, 0, 1,
+ 0, 4, 8, 0, 1,
+ 0, 0, 0, 1, 0,
+ 0, 0, {0xffff7f03, 0x00000000, 0x00000000,
+ 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03020014,
+ 0},
+ /* [7] tunneled roce (with grh, bth) over IPV6 */
+ {0, 1, 1, 0, 1,
+ 0, 4, 8, 0, 1,
+ 0, 0, 0, 1, 0,
+ 0, 0, {0xffff7f03, 0x00000000, 0x00000000,
+ 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010,
+ 0},
+ /* [8] tunneled fcoe over IPV4 */
+ {0, 1, 0, 0, 1,
+ 0, 8, 14, 1, 1,
+ 0, 0, 0, 1, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03020014,
+ 0},
+ /* [9] tunneled fcoe over IPV6 */
+ {0, 1, 0, 0, 1,
+ 0, 8, 14, 1, 1,
+ 0, 0, 0, 1, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010,
+ 0},
+ /* [10] tunneled routable_roce that is refered as l4_protocol, over IPV4 (and udp) over IPV4 */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 1, 0,
+ 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03020015,
+ 0},
+ /* [11] tunneled routable_roce that is refered as l4_protocol, over IPV4 (and udp) over IPV6 */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 1, 0,
+ 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000011,
+ 0},
+ /* [12] tunneled routable_roce that is refered as l4_protocol, over IPV6 (and udp) over IPV4 */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 1, 0,
+ 0, 0, {0x7f030000, 0x00000000, 0x00000003,
+ 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03020014,
+ 0},
+ /* [13] tunneled routable_roce that is refered as l4_protocol, over IPV6 (and udp) over IPV6 */
+ {0, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 1, 0,
+ 0, 0, {0x7f030000, 0x00000000, 0x00000003,
+ 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010,
+ 0},
+ /* [14] l3_pkt - IPV4 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000001,
+ 0},
+ /* [15] l4_hdr over IPV4 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000003,
+ 0},
+ /* [16] l3_pkt - IPV6 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000000,
+ 0},
+ /* [17] l4_hdr over IPV6 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000002,
+ 0},
+ /* [18] IPV4 over IPV4 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00020005,
+ 0},
+ /* [19] l4_hdr over IPV4 over IPV4 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00020007,
+ 0},
+ /* [20] IPV4 over IPV6 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000001,
+ 0},
+ /* [21] l4_hdr over IPV4 over IPV6 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000003,
+ 0},
+ /* [22] IPV6 over IPV4 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00020004,
+ 0},
+ /* [23] l4_hdr over IPV6 over IPV4 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00020006,
+ 0},
+ /* [24] IPV6 over IPV6 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000000,
+ 0},
+ /* [25] l4_hdr over IPV6 over IPV6 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000002,
+ 0},
+ /* [26] GENERIC_STORAGE_READ, over IPV4 (and udp) */
+ {1, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 2, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000011,
+ 0},
+ /* [27] GENERIC_STORAGE_READ, over IPV6 (and udp) */
+ {1, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 2, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010,
+ 0},
+ /* [28] tunneled GENERIC_STORAGE_READ over IPV4 (and udp) over IPV4/IPV6 */
+ {1, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 3, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000011,
+ 0},
+ /* [29] tunneled GENERIC_STORAGE_READ over IPV6 (and udp) over IPV4/IPV6 */
+ {1, 1, 1, 0, 1,
+ 0, 4, 0, 0, 1,
+ 0, 0, 0, 3, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010,
+ 0},
+ /* [30] tunneled L2 over GRE over IPV4 */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00020004,
+ 0},
+ /* [31] default match */
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, {0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x0,
+ 0}
+};
+
+int al_eth_tx_protocol_detect_table_init(struct al_hal_eth_adapter *adapter)
+{
+ int idx;
+ al_assert((adapter->rev_id > AL_ETH_REV_ID_2));
+
+ for (idx = 0; idx < AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM; idx++)
+ al_eth_tx_protocol_detect_table_entry_set(adapter, idx,
+ &al_eth_generic_tx_crc_gpd[idx]);
+
+ return 0;
+}
+
+int al_eth_tx_generic_crc_table_init(struct al_hal_eth_adapter *adapter)
+{
+ int idx;
+ al_assert((adapter->rev_id > AL_ETH_REV_ID_2));
+
+ al_dbg("eth [%s]: enable tx_generic_crc\n", adapter->name);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_legacy, 0x0);
+ al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace, 0x0);
+ for (idx = 0; idx < AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM; idx++)
+ al_eth_tx_generic_crc_table_entry_set(adapter, idx,
+ &al_eth_generic_tx_crc_gcp[idx]);
+
+ return 0;
+}
+
+int al_eth_tx_crc_chksum_replace_cmd_init(struct al_hal_eth_adapter *adapter)
+{
+ int idx;
+ al_assert((adapter->rev_id > AL_ETH_REV_ID_2));
+
+ for (idx = 0; idx < AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM; idx++)
+ al_eth_tx_crc_chksum_replace_cmd_entry_set(adapter, idx,
+ &al_eth_tx_crc_chksum_replace_cmd[idx]);
+
+ return 0;
+}
+
+int al_eth_rx_protocol_detect_table_init(struct al_hal_eth_adapter *adapter)
+{
+ int idx;
+ al_assert((adapter->rev_id > AL_ETH_REV_ID_2));
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p1,
+ AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L3_PROTO_IDX_OFFSET);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p2,
+ AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L4_PROTO_IDX_OFFSET);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p3,
+ AL_ETH_RX_GPD_PARSE_RESULT_INNER_L3_PROTO_IDX_OFFSET);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p4,
+ AL_ETH_RX_GPD_PARSE_RESULT_INNER_L4_PROTO_IDX_OFFSET);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p5,
+ AL_ETH_RX_GPD_PARSE_RESULT_OUTER_PARSE_CTRL);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p6,
+ AL_ETH_RX_GPD_PARSE_RESULT_INNER_PARSE_CTRL);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p7,
+ AL_ETH_RX_GPD_PARSE_RESULT_L3_PRIORITY);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p8,
+ AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L4_DST_PORT_LSB);
+
+ for (idx = 0; idx < AL_ETH_RX_PROTOCOL_DETECT_ENTRIES_NUM; idx++)
+ al_eth_rx_protocol_detect_table_entry_set(adapter, idx,
+ &al_eth_generic_rx_crc_gpd[idx]);
+ return 0;
+}
+
+int al_eth_rx_generic_crc_table_init(struct al_hal_eth_adapter *adapter)
+ {
+ int idx;
+ uint32_t val;
+
+ al_assert((adapter->rev_id > AL_ETH_REV_ID_2));
+
+ al_dbg("eth [%s]: enable rx_generic_crc\n", adapter->name);
+ al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_legacy, 0x0);
+
+ for (idx = 0; idx < AL_ETH_RX_PROTOCOL_DETECT_ENTRIES_NUM; idx++)
+ al_eth_rx_generic_crc_table_entry_set(adapter, idx,
+ &al_eth_generic_rx_crc_gcp[idx]);
+
+ val = EC_GEN_V3_RX_COMP_DESC_W3_DEC_STAT_15_CRC_RES_SEL |
+ EC_GEN_V3_RX_COMP_DESC_W3_DEC_STAT_14_L3_CKS_RES_SEL |
+ EC_GEN_V3_RX_COMP_DESC_W3_DEC_STAT_13_L4_CKS_RES_SEL |
+ EC_GEN_V3_RX_COMP_DESC_W0_L3_CKS_RES_SEL;
+ al_reg_write32_masked(&adapter->ec_regs_base->gen_v3.rx_comp_desc,
+ val, val);
+ return 0;
+}
+
+/** @} end of Ethernet group */
+