diff options
Diffstat (limited to 'drivers/net/ethernet/aquantia/atlantic/hw_atl')
9 files changed, 1453 insertions, 436 deletions
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index 359a4d387185..9b1062b8af64 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -119,10 +119,10 @@ err_exit: static int hw_atl_a0_hw_qos_set(struct aq_hw_s *self) { - u32 tc = 0U; - u32 buff_size = 0U; - unsigned int i_priority = 0U; bool is_rx_flow_control = false; + unsigned int i_priority = 0U; + u32 buff_size = 0U; + u32 tc = 0U; /* TPS Descriptor rate init */ hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U); @@ -155,7 +155,7 @@ static int hw_atl_a0_hw_qos_set(struct aq_hw_s *self) /* QoS Rx buf size per TC */ tc = 0; - is_rx_flow_control = (AQ_NIC_FC_RX & self->aq_nic_cfg->flow_control); + is_rx_flow_control = (AQ_NIC_FC_RX & self->aq_nic_cfg->fc.req); buff_size = HW_ATL_A0_RXBUF_MAX; hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, buff_size, tc); @@ -180,9 +180,9 @@ static int hw_atl_a0_hw_rss_hash_set(struct aq_hw_s *self, struct aq_rss_parameters *rss_params) { struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; - int err = 0; - unsigned int i = 0U; unsigned int addr = 0U; + unsigned int i = 0U; + int err = 0; u32 val; for (i = 10, addr = 0U; i--; ++addr) { @@ -207,12 +207,12 @@ err_exit: static int hw_atl_a0_hw_rss_set(struct aq_hw_s *self, struct aq_rss_parameters *rss_params) { - u8 *indirection_table = rss_params->indirection_table; - u32 i = 0U; u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues); - int err = 0; + u8 *indirection_table = rss_params->indirection_table; u16 bitary[1 + (HW_ATL_A0_RSS_REDIRECTION_MAX * HW_ATL_A0_RSS_REDIRECTION_BITS / 16U)]; + int err = 0; + u32 i = 0U; u32 val; memset(bitary, 0, sizeof(bitary)); @@ -321,9 +321,9 @@ static int hw_atl_a0_hw_init_rx_path(struct aq_hw_s *self) static int hw_atl_a0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) { - int err = 0; unsigned int h = 0U; unsigned int l = 0U; + int err = 0; if (!mac_addr) { err = -EINVAL; @@ -352,10 +352,9 @@ static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr) [AQ_HW_IRQ_MSI] = { 0x20000021U, 0x20000025U }, [AQ_HW_IRQ_MSIX] = { 0x20000022U, 0x20000026U }, }; - + struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg; int err = 0; - struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg; hw_atl_a0_hw_init_tx_path(self); hw_atl_a0_hw_init_rx_path(self); @@ -404,6 +403,7 @@ static int hw_atl_a0_hw_ring_tx_start(struct aq_hw_s *self, struct aq_ring_s *ring) { hw_atl_tdm_tx_desc_en_set(self, 1, ring->idx); + return aq_hw_err_from_flags(self); } @@ -411,6 +411,7 @@ static int hw_atl_a0_hw_ring_rx_start(struct aq_hw_s *self, struct aq_ring_s *ring) { hw_atl_rdm_rx_desc_en_set(self, 1, ring->idx); + return aq_hw_err_from_flags(self); } @@ -418,6 +419,7 @@ static int hw_atl_a0_hw_start(struct aq_hw_s *self) { hw_atl_tpb_tx_buff_en_set(self, 1); hw_atl_rpb_rx_buff_en_set(self, 1); + return aq_hw_err_from_flags(self); } @@ -425,6 +427,7 @@ static int hw_atl_a0_hw_tx_ring_tail_update(struct aq_hw_s *self, struct aq_ring_s *ring) { hw_atl_reg_tx_dma_desc_tail_ptr_set(self, ring->sw_tail, ring->idx); + return 0; } @@ -435,8 +438,8 @@ static int hw_atl_a0_hw_ring_tx_xmit(struct aq_hw_s *self, struct aq_ring_buff_s *buff = NULL; struct hw_atl_txd_s *txd = NULL; unsigned int buff_pa_len = 0U; - unsigned int pkt_len = 0U; unsigned int frag_count = 0U; + unsigned int pkt_len = 0U; bool is_gso = false; buff = &ring->buff_ring[ring->sw_tail]; @@ -451,7 +454,7 @@ static int hw_atl_a0_hw_ring_tx_xmit(struct aq_hw_s *self, buff = &ring->buff_ring[ring->sw_tail]; - if (buff->is_gso) { + if (buff->is_gso_tcp) { txd->ctl |= (buff->len_l3 << 31) | (buff->len_l2 << 24) | HW_ATL_A0_TXD_CTL_CMD_TCP | @@ -500,6 +503,7 @@ static int hw_atl_a0_hw_ring_tx_xmit(struct aq_hw_s *self, } hw_atl_a0_hw_tx_ring_tail_update(self, ring); + return aq_hw_err_from_flags(self); } @@ -507,8 +511,8 @@ static int hw_atl_a0_hw_ring_rx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring, struct aq_ring_param_s *aq_ring_param) { - u32 dma_desc_addr_lsw = (u32)aq_ring->dx_ring_pa; u32 dma_desc_addr_msw = (u32)(((u64)aq_ring->dx_ring_pa) >> 32); + u32 dma_desc_addr_lsw = (u32)aq_ring->dx_ring_pa; hw_atl_rdm_rx_desc_en_set(self, false, aq_ring->idx); @@ -549,8 +553,8 @@ static int hw_atl_a0_hw_ring_tx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring, struct aq_ring_param_s *aq_ring_param) { - u32 dma_desc_lsw_addr = (u32)aq_ring->dx_ring_pa; u32 dma_desc_msw_addr = (u32)(((u64)aq_ring->dx_ring_pa) >> 32); + u32 dma_desc_lsw_addr = (u32)aq_ring->dx_ring_pa; hw_atl_reg_tx_dma_desc_base_addresslswset(self, dma_desc_lsw_addr, aq_ring->idx); @@ -599,8 +603,8 @@ static int hw_atl_a0_hw_ring_rx_fill(struct aq_hw_s *self, static int hw_atl_a0_hw_ring_tx_head_update(struct aq_hw_s *self, struct aq_ring_s *ring) { - int err = 0; unsigned int hw_head = hw_atl_tdm_tx_desc_head_ptr_get(self, ring->idx); + int err = 0; if (aq_utils_obj_test(&self->flags, AQ_HW_FLAG_ERR_UNPLUG)) { err = -ENXIO; @@ -720,6 +724,7 @@ static int hw_atl_a0_hw_irq_enable(struct aq_hw_s *self, u64 mask) { hw_atl_itr_irq_msk_setlsw_set(self, LODWORD(mask) | (1U << HW_ATL_A0_ERR_INT)); + return aq_hw_err_from_flags(self); } @@ -737,6 +742,7 @@ static int hw_atl_a0_hw_irq_disable(struct aq_hw_s *self, u64 mask) static int hw_atl_a0_hw_irq_read(struct aq_hw_s *self, u64 *mask) { *mask = hw_atl_itr_irq_statuslsw_get(self); + return aq_hw_err_from_flags(self); } @@ -859,6 +865,7 @@ static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self) static int hw_atl_a0_hw_stop(struct aq_hw_s *self) { hw_atl_a0_hw_irq_disable(self, HW_ATL_A0_INT_MASK); + return aq_hw_err_from_flags(self); } @@ -866,6 +873,7 @@ static int hw_atl_a0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) { hw_atl_tdm_tx_desc_en_set(self, 0U, ring->idx); + return aq_hw_err_from_flags(self); } @@ -873,6 +881,7 @@ static int hw_atl_a0_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) { hw_atl_rdm_rx_desc_en_set(self, 0U, ring->idx); + return aq_hw_err_from_flags(self); } diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 2ad3fa6316ce..58e891af6e09 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * aQuantia Corporation Network Driver - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved + * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved */ /* File hw_atl_b0.c: Definition of Atlantic hardware specific functions. */ @@ -10,6 +10,7 @@ #include "../aq_hw_utils.h" #include "../aq_ring.h" #include "../aq_nic.h" +#include "../aq_phy.h" #include "hw_atl_b0.h" #include "hw_atl_utils.h" #include "hw_atl_llh.h" @@ -42,13 +43,17 @@ NETIF_F_NTUPLE | \ NETIF_F_HW_VLAN_CTAG_FILTER | \ NETIF_F_HW_VLAN_CTAG_RX | \ - NETIF_F_HW_VLAN_CTAG_TX, \ + NETIF_F_HW_VLAN_CTAG_TX | \ + NETIF_F_GSO_UDP_L4 | \ + NETIF_F_GSO_PARTIAL, \ .hw_priv_flags = IFF_UNICAST_FLT, \ .flow_control = true, \ .mtu = HW_ATL_B0_MTU_JUMBO, \ .mac_regs_count = 88, \ .hw_alive_check_addr = 0x10U +#define FRAC_PER_NS 0x100000000LL + const struct aq_hw_caps_s hw_atl_b0_caps_aqc100 = { DEFAULT_B0_BOARD_BASIC_CAPABILITIES, .media_type = AQ_HW_MEDIA_TYPE_FIBRE, @@ -104,14 +109,15 @@ static int hw_atl_b0_hw_reset(struct aq_hw_s *self) static int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc) { hw_atl_rpb_rx_xoff_en_per_tc_set(self, !!(fc & AQ_NIC_FC_RX), tc); + return 0; } static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) { - u32 tc = 0U; - u32 buff_size = 0U; unsigned int i_priority = 0U; + u32 buff_size = 0U; + u32 tc = 0U; /* TPS Descriptor rate init */ hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U); @@ -124,13 +130,16 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); - hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, 0U); - hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, 0U); - hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, 0U); - hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, 0U); + tc = 0; + + /* TX Packet Scheduler Data TC0 */ + hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, tc); + hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, tc); + hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc); + hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); - /* Tx buf size */ - buff_size = HW_ATL_B0_TXBUF_MAX; + /* Tx buf size TC0 */ + buff_size = HW_ATL_B0_TXBUF_MAX - HW_ATL_B0_PTP_TXBUF_SIZE; hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, buff_size, tc); hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(self, @@ -141,10 +150,15 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) (buff_size * (1024 / 32U) * 50U) / 100U, tc); + /* Init TC2 for PTP_TX */ + tc = 2; + + hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_TXBUF_SIZE, + tc); /* QoS Rx buf size per TC */ tc = 0; - buff_size = HW_ATL_B0_RXBUF_MAX; + buff_size = HW_ATL_B0_RXBUF_MAX - HW_ATL_B0_PTP_RXBUF_SIZE; hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, buff_size, tc); hw_atl_rpb_rx_buff_hi_threshold_per_tc_set(self, @@ -156,7 +170,15 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) (1024U / 32U) * 50U) / 100U, tc); - hw_atl_b0_set_fc(self, self->aq_nic_cfg->flow_control, tc); + hw_atl_b0_set_fc(self, self->aq_nic_cfg->fc.req, tc); + + /* Init TC2 for PTP_RX */ + tc = 2; + + hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_RXBUF_SIZE, + tc); + /* No flow control for PTP */ + hw_atl_rpb_rx_xoff_en_per_tc_set(self, 0U, tc); /* QoS 802.1p priority -> TC mapping */ for (i_priority = 8U; i_priority--;) @@ -169,9 +191,9 @@ static int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, struct aq_rss_parameters *rss_params) { struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; - int err = 0; - unsigned int i = 0U; unsigned int addr = 0U; + unsigned int i = 0U; + int err = 0; u32 val; for (i = 10, addr = 0U; i--; ++addr) { @@ -196,12 +218,12 @@ err_exit: static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, struct aq_rss_parameters *rss_params) { - u8 *indirection_table = rss_params->indirection_table; - u32 i = 0U; u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues); - int err = 0; + u8 *indirection_table = rss_params->indirection_table; u16 bitary[1 + (HW_ATL_B0_RSS_REDIRECTION_MAX * HW_ATL_B0_RSS_REDIRECTION_BITS / 16U)]; + int err = 0; + u32 i = 0U; u32 val; memset(bitary, 0, sizeof(bitary)); @@ -285,6 +307,7 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, hw_atl_itr_rsc_delay_set(self, 1U); } + return aq_hw_err_from_flags(self); } @@ -363,9 +386,9 @@ static int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self) static int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) { - int err = 0; unsigned int h = 0U; unsigned int l = 0U; + int err = 0; if (!mac_addr) { err = -EINVAL; @@ -394,11 +417,10 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr) [AQ_HW_IRQ_MSI] = { 0x20000021U, 0x20000025U }, [AQ_HW_IRQ_MSIX] = { 0x20000022U, 0x20000026U }, }; - + struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg; int err = 0; u32 val; - struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg; hw_atl_b0_hw_init_tx_path(self); hw_atl_b0_hw_init_rx_path(self); @@ -441,8 +463,10 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr) /* Interrupts */ hw_atl_reg_gen_irq_map_set(self, - ((HW_ATL_B0_ERR_INT << 0x18) | (1U << 0x1F)) | - ((HW_ATL_B0_ERR_INT << 0x10) | (1U << 0x17)), 0U); + ((HW_ATL_B0_ERR_INT << 0x18) | + (1U << 0x1F)) | + ((HW_ATL_B0_ERR_INT << 0x10) | + (1U << 0x17)), 0U); /* Enable link interrupt */ if (aq_nic_cfg->link_irq_vec) @@ -459,6 +483,7 @@ static int hw_atl_b0_hw_ring_tx_start(struct aq_hw_s *self, struct aq_ring_s *ring) { hw_atl_tdm_tx_desc_en_set(self, 1, ring->idx); + return aq_hw_err_from_flags(self); } @@ -466,6 +491,7 @@ static int hw_atl_b0_hw_ring_rx_start(struct aq_hw_s *self, struct aq_ring_s *ring) { hw_atl_rdm_rx_desc_en_set(self, 1, ring->idx); + return aq_hw_err_from_flags(self); } @@ -473,6 +499,7 @@ static int hw_atl_b0_hw_start(struct aq_hw_s *self) { hw_atl_tpb_tx_buff_en_set(self, 1); hw_atl_rpb_rx_buff_en_set(self, 1); + return aq_hw_err_from_flags(self); } @@ -480,6 +507,7 @@ static int hw_atl_b0_hw_tx_ring_tail_update(struct aq_hw_s *self, struct aq_ring_s *ring) { hw_atl_reg_tx_dma_desc_tail_ptr_set(self, ring->sw_tail, ring->idx); + return 0; } @@ -490,8 +518,8 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, struct aq_ring_buff_s *buff = NULL; struct hw_atl_txd_s *txd = NULL; unsigned int buff_pa_len = 0U; - unsigned int pkt_len = 0U; unsigned int frag_count = 0U; + unsigned int pkt_len = 0U; bool is_vlan = false; bool is_gso = false; @@ -507,8 +535,9 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, buff = &ring->buff_ring[ring->sw_tail]; - if (buff->is_gso) { - txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_TCP; + if (buff->is_gso_tcp || buff->is_gso_udp) { + if (buff->is_gso_tcp) + txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_TCP; txd->ctl |= HW_ATL_B0_TXD_CTL_DESC_TYPE_TXC; txd->ctl |= (buff->len_l3 << 31) | (buff->len_l2 << 24); @@ -528,7 +557,7 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, txd->ctl |= buff->vlan_tx_tag << 4; is_vlan = true; } - if (!buff->is_gso && !buff->is_vlan) { + if (!buff->is_gso_tcp && !buff->is_gso_udp && !buff->is_vlan) { buff_pa_len = buff->len; txd->buf_addr = buff->pa; @@ -567,6 +596,7 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, } hw_atl_b0_hw_tx_ring_tail_update(self, ring); + return aq_hw_err_from_flags(self); } @@ -574,9 +604,9 @@ static int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring, struct aq_ring_param_s *aq_ring_param) { - u32 dma_desc_addr_lsw = (u32)aq_ring->dx_ring_pa; u32 dma_desc_addr_msw = (u32)(((u64)aq_ring->dx_ring_pa) >> 32); u32 vlan_rx_stripping = self->aq_nic_cfg->is_vlan_rx_strip; + u32 dma_desc_addr_lsw = (u32)aq_ring->dx_ring_pa; hw_atl_rdm_rx_desc_en_set(self, false, aq_ring->idx); @@ -617,8 +647,8 @@ static int hw_atl_b0_hw_ring_tx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring, struct aq_ring_param_s *aq_ring_param) { - u32 dma_desc_lsw_addr = (u32)aq_ring->dx_ring_pa; u32 dma_desc_msw_addr = (u32)(((u64)aq_ring->dx_ring_pa) >> 32); + u32 dma_desc_lsw_addr = (u32)aq_ring->dx_ring_pa; hw_atl_reg_tx_dma_desc_base_addresslswset(self, dma_desc_lsw_addr, aq_ring->idx); @@ -664,11 +694,53 @@ static int hw_atl_b0_hw_ring_rx_fill(struct aq_hw_s *self, return aq_hw_err_from_flags(self); } +static int hw_atl_b0_hw_ring_hwts_rx_fill(struct aq_hw_s *self, + struct aq_ring_s *ring) +{ + unsigned int i; + + for (i = aq_ring_avail_dx(ring); i--; + ring->sw_tail = aq_ring_next_dx(ring, ring->sw_tail)) { + struct hw_atl_rxd_s *rxd = + (struct hw_atl_rxd_s *) + &ring->dx_ring[ring->sw_tail * HW_ATL_B0_RXD_SIZE]; + + rxd->buf_addr = ring->dx_ring_pa + ring->size * ring->dx_size; + rxd->hdr_addr = 0U; + } + /* Make sure descriptors are updated before bump tail*/ + wmb(); + + hw_atl_reg_rx_dma_desc_tail_ptr_set(self, ring->sw_tail, ring->idx); + + return aq_hw_err_from_flags(self); +} + +static int hw_atl_b0_hw_ring_hwts_rx_receive(struct aq_hw_s *self, + struct aq_ring_s *ring) +{ + while (ring->hw_head != ring->sw_tail) { + struct hw_atl_rxd_hwts_wb_s *hwts_wb = + (struct hw_atl_rxd_hwts_wb_s *) + (ring->dx_ring + (ring->hw_head * HW_ATL_B0_RXD_SIZE)); + + /* RxD is not done */ + if (!(hwts_wb->sec_lw0 & 0x1U)) + break; + + ring->hw_head = aq_ring_next_dx(ring, ring->hw_head); + } + + return aq_hw_err_from_flags(self); +} + static int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self, struct aq_ring_s *ring) { + unsigned int hw_head_; int err = 0; - unsigned int hw_head_ = hw_atl_tdm_tx_desc_head_ptr_get(self, ring->idx); + + hw_head_ = hw_atl_tdm_tx_desc_head_ptr_get(self, ring->idx); if (aq_utils_obj_test(&self->flags, AQ_HW_FLAG_ERR_UNPLUG)) { err = -ENXIO; @@ -784,6 +856,7 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, static int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask) { hw_atl_itr_irq_msk_setlsw_set(self, LODWORD(mask)); + return aq_hw_err_from_flags(self); } @@ -793,12 +866,14 @@ static int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask) hw_atl_itr_irq_status_clearlsw_set(self, LODWORD(mask)); atomic_inc(&self->dpc); + return aq_hw_err_from_flags(self); } static int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask) { *mask = hw_atl_itr_irq_statuslsw_get(self); + return aq_hw_err_from_flags(self); } @@ -807,8 +882,8 @@ static int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask) static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self, unsigned int packet_filter) { - unsigned int i = 0U; struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; + unsigned int i = 0U; hw_atl_rpfl2promiscuous_mode_en_set(self, IS_FILTER_ENABLED(IFF_PROMISC)); @@ -846,29 +921,30 @@ static int hw_atl_b0_hw_multicast_list_set(struct aq_hw_s *self, u32 count) { int err = 0; + struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; if (count > (HW_ATL_B0_MAC_MAX - HW_ATL_B0_MAC_MIN)) { err = -EBADRQC; goto err_exit; } - for (self->aq_nic_cfg->mc_list_count = 0U; - self->aq_nic_cfg->mc_list_count < count; - ++self->aq_nic_cfg->mc_list_count) { - u32 i = self->aq_nic_cfg->mc_list_count; + for (cfg->mc_list_count = 0U; + cfg->mc_list_count < count; + ++cfg->mc_list_count) { + u32 i = cfg->mc_list_count; u32 h = (ar_mac[i][0] << 8) | (ar_mac[i][1]); u32 l = (ar_mac[i][2] << 24) | (ar_mac[i][3] << 16) | (ar_mac[i][4] << 8) | ar_mac[i][5]; hw_atl_rpfl2_uc_flr_en_set(self, 0U, HW_ATL_B0_MAC_MIN + i); - hw_atl_rpfl2unicast_dest_addresslsw_set(self, - l, HW_ATL_B0_MAC_MIN + i); + hw_atl_rpfl2unicast_dest_addresslsw_set(self, l, + HW_ATL_B0_MAC_MIN + i); - hw_atl_rpfl2unicast_dest_addressmsw_set(self, - h, HW_ATL_B0_MAC_MIN + i); + hw_atl_rpfl2unicast_dest_addressmsw_set(self, h, + HW_ATL_B0_MAC_MIN + i); hw_atl_rpfl2_uc_flr_en_set(self, - (self->aq_nic_cfg->is_mc_list_enabled), + (cfg->is_mc_list_enabled), HW_ATL_B0_MAC_MIN + i); } @@ -995,6 +1071,7 @@ static int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) { hw_atl_tdm_tx_desc_en_set(self, 0U, ring->idx); + return aq_hw_err_from_flags(self); } @@ -1002,9 +1079,231 @@ static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) { hw_atl_rdm_rx_desc_en_set(self, 0U, ring->idx); + return aq_hw_err_from_flags(self); } +static int hw_atl_b0_tx_tc_mode_get(struct aq_hw_s *self, u32 *tc_mode) +{ + *tc_mode = hw_atl_rpb_tps_tx_tc_mode_get(self); + return aq_hw_err_from_flags(self); +} + +static int hw_atl_b0_rx_tc_mode_get(struct aq_hw_s *self, u32 *tc_mode) +{ + *tc_mode = hw_atl_rpb_rpf_rx_traf_class_mode_get(self); + return aq_hw_err_from_flags(self); +} + +#define get_ptp_ts_val_u64(self, indx) \ + ((u64)(hw_atl_pcs_ptp_clock_get(self, indx) & 0xffff)) + +static void hw_atl_b0_get_ptp_ts(struct aq_hw_s *self, u64 *stamp) +{ + u64 ns; + + hw_atl_pcs_ptp_clock_read_enable(self, 1); + hw_atl_pcs_ptp_clock_read_enable(self, 0); + ns = (get_ptp_ts_val_u64(self, 0) + + (get_ptp_ts_val_u64(self, 1) << 16)) * NSEC_PER_SEC + + (get_ptp_ts_val_u64(self, 3) + + (get_ptp_ts_val_u64(self, 4) << 16)); + + *stamp = ns + self->ptp_clk_offset; +} + +static void hw_atl_b0_adj_params_get(u64 freq, s64 adj, u32 *ns, u32 *fns) +{ + /* For accuracy, the digit is extended */ + s64 base_ns = ((adj + NSEC_PER_SEC) * NSEC_PER_SEC); + u64 nsi_frac = 0; + u64 nsi; + + base_ns = div64_s64(base_ns, freq); + nsi = div64_u64(base_ns, NSEC_PER_SEC); + + if (base_ns != nsi * NSEC_PER_SEC) { + s64 divisor = div64_s64((s64)NSEC_PER_SEC * NSEC_PER_SEC, + base_ns - nsi * NSEC_PER_SEC); + nsi_frac = div64_s64(FRAC_PER_NS * NSEC_PER_SEC, divisor); + } + + *ns = (u32)nsi; + *fns = (u32)nsi_frac; +} + +static void +hw_atl_b0_mac_adj_param_calc(struct hw_fw_request_ptp_adj_freq *ptp_adj_freq, + u64 phyfreq, u64 macfreq) +{ + s64 adj_fns_val; + s64 fns_in_sec_phy = phyfreq * (ptp_adj_freq->fns_phy + + FRAC_PER_NS * ptp_adj_freq->ns_phy); + s64 fns_in_sec_mac = macfreq * (ptp_adj_freq->fns_mac + + FRAC_PER_NS * ptp_adj_freq->ns_mac); + s64 fault_in_sec_phy = FRAC_PER_NS * NSEC_PER_SEC - fns_in_sec_phy; + s64 fault_in_sec_mac = FRAC_PER_NS * NSEC_PER_SEC - fns_in_sec_mac; + /* MAC MCP counter freq is macfreq / 4 */ + s64 diff_in_mcp_overflow = (fault_in_sec_mac - fault_in_sec_phy) * + 4 * FRAC_PER_NS; + + diff_in_mcp_overflow = div64_s64(diff_in_mcp_overflow, + AQ_HW_MAC_COUNTER_HZ); + adj_fns_val = (ptp_adj_freq->fns_mac + FRAC_PER_NS * + ptp_adj_freq->ns_mac) + diff_in_mcp_overflow; + + ptp_adj_freq->mac_ns_adj = div64_s64(adj_fns_val, FRAC_PER_NS); + ptp_adj_freq->mac_fns_adj = adj_fns_val - ptp_adj_freq->mac_ns_adj * + FRAC_PER_NS; +} + +static int hw_atl_b0_adj_sys_clock(struct aq_hw_s *self, s64 delta) +{ + self->ptp_clk_offset += delta; + + return 0; +} + +static int hw_atl_b0_set_sys_clock(struct aq_hw_s *self, u64 time, u64 ts) +{ + s64 delta = time - (self->ptp_clk_offset + ts); + + return hw_atl_b0_adj_sys_clock(self, delta); +} + +static int hw_atl_b0_ts_to_sys_clock(struct aq_hw_s *self, u64 ts, u64 *time) +{ + *time = self->ptp_clk_offset + ts; + return 0; +} + +static int hw_atl_b0_adj_clock_freq(struct aq_hw_s *self, s32 ppb) +{ + struct hw_fw_request_iface fwreq; + size_t size; + + memset(&fwreq, 0, sizeof(fwreq)); + + fwreq.msg_id = HW_AQ_FW_REQUEST_PTP_ADJ_FREQ; + hw_atl_b0_adj_params_get(AQ_HW_MAC_COUNTER_HZ, ppb, + &fwreq.ptp_adj_freq.ns_mac, + &fwreq.ptp_adj_freq.fns_mac); + hw_atl_b0_adj_params_get(AQ_HW_PHY_COUNTER_HZ, ppb, + &fwreq.ptp_adj_freq.ns_phy, + &fwreq.ptp_adj_freq.fns_phy); + hw_atl_b0_mac_adj_param_calc(&fwreq.ptp_adj_freq, + AQ_HW_PHY_COUNTER_HZ, + AQ_HW_MAC_COUNTER_HZ); + + size = sizeof(fwreq.msg_id) + sizeof(fwreq.ptp_adj_freq); + return self->aq_fw_ops->send_fw_request(self, &fwreq, size); +} + +static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index, + u64 start, u32 period) +{ + struct hw_fw_request_iface fwreq; + size_t size; + + memset(&fwreq, 0, sizeof(fwreq)); + + fwreq.msg_id = HW_AQ_FW_REQUEST_PTP_GPIO_CTRL; + fwreq.ptp_gpio_ctrl.index = index; + fwreq.ptp_gpio_ctrl.period = period; + /* Apply time offset */ + fwreq.ptp_gpio_ctrl.start = start - self->ptp_clk_offset; + + size = sizeof(fwreq.msg_id) + sizeof(fwreq.ptp_gpio_ctrl); + return self->aq_fw_ops->send_fw_request(self, &fwreq, size); +} + +static int hw_atl_b0_extts_gpio_enable(struct aq_hw_s *self, u32 index, + u32 enable) +{ + /* Enable/disable Sync1588 GPIO Timestamping */ + aq_phy_write_reg(self, MDIO_MMD_PCS, 0xc611, enable ? 0x71 : 0); + + return 0; +} + +static int hw_atl_b0_get_sync_ts(struct aq_hw_s *self, u64 *ts) +{ + u64 sec_l; + u64 sec_h; + u64 nsec_l; + u64 nsec_h; + + if (!ts) + return -1; + + /* PTP external GPIO clock seconds count 15:0 */ + sec_l = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc914); + /* PTP external GPIO clock seconds count 31:16 */ + sec_h = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc915); + /* PTP external GPIO clock nanoseconds count 15:0 */ + nsec_l = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc916); + /* PTP external GPIO clock nanoseconds count 31:16 */ + nsec_h = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc917); + + *ts = (nsec_h << 16) + nsec_l + ((sec_h << 16) + sec_l) * NSEC_PER_SEC; + + return 0; +} + +static u16 hw_atl_b0_rx_extract_ts(struct aq_hw_s *self, u8 *p, + unsigned int len, u64 *timestamp) +{ + unsigned int offset = 14; + struct ethhdr *eth; + __be64 sec; + __be32 ns; + u8 *ptr; + + if (len <= offset || !timestamp) + return 0; + + /* The TIMESTAMP in the end of package has following format: + * (big-endian) + * struct { + * uint64_t sec; + * uint32_t ns; + * uint16_t stream_id; + * }; + */ + ptr = p + (len - offset); + memcpy(&sec, ptr, sizeof(sec)); + ptr += sizeof(sec); + memcpy(&ns, ptr, sizeof(ns)); + + *timestamp = (be64_to_cpu(sec) & 0xffffffffffffllu) * NSEC_PER_SEC + + be32_to_cpu(ns) + self->ptp_clk_offset; + + eth = (struct ethhdr *)p; + + return (eth->h_proto == htons(ETH_P_1588)) ? 12 : 14; +} + +static int hw_atl_b0_extract_hwts(struct aq_hw_s *self, u8 *p, unsigned int len, + u64 *timestamp) +{ + struct hw_atl_rxd_hwts_wb_s *hwts_wb = (struct hw_atl_rxd_hwts_wb_s *)p; + u64 tmp, sec, ns; + + sec = 0; + tmp = (hwts_wb->sec_lw0 >> 2) & 0x3ff; + sec += tmp; + tmp = (u64)((hwts_wb->sec_lw1 >> 16) & 0xffff) << 10; + sec += tmp; + tmp = (u64)(hwts_wb->sec_hw & 0xfff) << 26; + sec += tmp; + tmp = (u64)((hwts_wb->sec_hw >> 22) & 0x3ff) << 38; + sec += tmp; + ns = sec * NSEC_PER_SEC + hwts_wb->ns; + if (timestamp) + *timestamp = ns + self->ptp_clk_offset; + return 0; +} + static int hw_atl_b0_hw_fl3l4_clear(struct aq_hw_s *self, struct aq_rx_filter_l3l4 *data) { @@ -1038,7 +1337,8 @@ static int hw_atl_b0_hw_fl3l4_set(struct aq_hw_s *self, hw_atl_b0_hw_fl3l4_clear(self, data); - if (data->cmd) { + if (data->cmd & (HW_ATL_RX_ENABLE_CMP_DEST_ADDR_L3 | + HW_ATL_RX_ENABLE_CMP_SRC_ADDR_L3)) { if (!data->is_ipv6) { hw_atl_rpfl3l4_ipv4_dest_addr_set(self, location, @@ -1055,8 +1355,13 @@ static int hw_atl_b0_hw_fl3l4_set(struct aq_hw_s *self, data->ip_src); } } - hw_atl_rpf_l4_dpd_set(self, data->p_dst, location); - hw_atl_rpf_l4_spd_set(self, data->p_src, location); + + if (data->cmd & (HW_ATL_RX_ENABLE_CMP_DEST_PORT_L4 | + HW_ATL_RX_ENABLE_CMP_SRC_PORT_L4)) { + hw_atl_rpf_l4_dpd_set(self, data->p_dst, location); + hw_atl_rpf_l4_spd_set(self, data->p_src, location); + } + hw_atl_rpfl3l4_cmd_set(self, location, data->cmd); return aq_hw_err_from_flags(self); @@ -1141,6 +1446,31 @@ static int hw_atl_b0_hw_vlan_ctrl(struct aq_hw_s *self, bool enable) return aq_hw_err_from_flags(self); } +static int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable) +{ + switch (mode) { + case AQ_HW_LOOPBACK_DMA_SYS: + hw_atl_tpb_tx_dma_sys_lbk_en_set(self, enable); + hw_atl_rpb_dma_sys_lbk_set(self, enable); + break; + case AQ_HW_LOOPBACK_PKT_SYS: + hw_atl_tpo_tx_pkt_sys_lbk_en_set(self, enable); + hw_atl_rpf_tpo_to_rpf_sys_lbk_set(self, enable); + break; + case AQ_HW_LOOPBACK_DMA_NET: + hw_atl_rpf_vlan_prom_mode_en_set(self, enable); + hw_atl_rpfl2promiscuous_mode_en_set(self, enable); + hw_atl_tpb_tx_tx_clk_gate_en_set(self, !enable); + hw_atl_tpb_tx_dma_net_lbk_en_set(self, enable); + hw_atl_rpb_dma_net_lbk_set(self, enable); + break; + default: + return -EINVAL; + } + + return 0; +} + const struct aq_hw_ops hw_atl_ops_b0 = { .hw_set_mac_address = hw_atl_b0_hw_mac_addr_set, .hw_init = hw_atl_b0_hw_init, @@ -1177,6 +1507,27 @@ const struct aq_hw_ops hw_atl_ops_b0 = { .hw_get_regs = hw_atl_utils_hw_get_regs, .hw_get_hw_stats = hw_atl_utils_get_hw_stats, .hw_get_fw_version = hw_atl_utils_get_fw_version, - .hw_set_offload = hw_atl_b0_hw_offload_set, - .hw_set_fc = hw_atl_b0_set_fc, + + .hw_tx_tc_mode_get = hw_atl_b0_tx_tc_mode_get, + .hw_rx_tc_mode_get = hw_atl_b0_rx_tc_mode_get, + + .hw_ring_hwts_rx_fill = hw_atl_b0_hw_ring_hwts_rx_fill, + .hw_ring_hwts_rx_receive = hw_atl_b0_hw_ring_hwts_rx_receive, + + .hw_get_ptp_ts = hw_atl_b0_get_ptp_ts, + .hw_adj_sys_clock = hw_atl_b0_adj_sys_clock, + .hw_set_sys_clock = hw_atl_b0_set_sys_clock, + .hw_ts_to_sys_clock = hw_atl_b0_ts_to_sys_clock, + .hw_adj_clock_freq = hw_atl_b0_adj_clock_freq, + .hw_gpio_pulse = hw_atl_b0_gpio_pulse, + .hw_extts_gpio_enable = hw_atl_b0_extts_gpio_enable, + .hw_get_sync_ts = hw_atl_b0_get_sync_ts, + .rx_extract_ts = hw_atl_b0_rx_extract_ts, + .extract_hwts = hw_atl_b0_extract_hwts, + .hw_set_offload = hw_atl_b0_hw_offload_set, + .hw_get_hw_stats = hw_atl_utils_get_hw_stats, + .hw_get_fw_version = hw_atl_utils_get_fw_version, + .hw_set_offload = hw_atl_b0_hw_offload_set, + .hw_set_loopback = hw_atl_b0_set_loopback, + .hw_set_fc = hw_atl_b0_set_fc, }; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h index 808d8cd4252a..7ab23a1751d3 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * aQuantia Corporation Network Driver - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved + * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved */ /* File hw_atl_b0_internal.h: Definition of Atlantic B0 chip specific @@ -64,8 +64,11 @@ #define HW_ATL_B0_MPI_SPEED_MSK 0xFFFFU #define HW_ATL_B0_MPI_SPEED_SHIFT 16U -#define HW_ATL_B0_TXBUF_MAX 160U -#define HW_ATL_B0_RXBUF_MAX 320U +#define HW_ATL_B0_TXBUF_MAX 160U +#define HW_ATL_B0_PTP_TXBUF_SIZE 8U + +#define HW_ATL_B0_RXBUF_MAX 320U +#define HW_ATL_B0_PTP_RXBUF_SIZE 16U #define HW_ATL_B0_RSS_REDIRECTION_MAX 64U #define HW_ATL_B0_RSS_REDIRECTION_BITS 3U diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c index 6f340695e6bd..d1f68fc16291 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * aQuantia Corporation Network Driver - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved + * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved */ /* File hw_atl_llh.c: Definitions of bitfield and register access functions for @@ -563,6 +563,13 @@ void hw_atl_rpb_dma_sys_lbk_set(struct aq_hw_s *aq_hw, u32 dma_sys_lbk) HW_ATL_RPB_DMA_SYS_LBK_SHIFT, dma_sys_lbk); } +void hw_atl_rpb_dma_net_lbk_set(struct aq_hw_s *aq_hw, u32 dma_net_lbk) +{ + aq_hw_write_reg_bit(aq_hw, HW_ATL_RPB_DMA_NET_LBK_ADR, + HW_ATL_RPB_DMA_NET_LBK_MSK, + HW_ATL_RPB_DMA_NET_LBK_SHIFT, dma_net_lbk); +} + void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw, u32 rx_traf_class_mode) { @@ -572,6 +579,13 @@ void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw, rx_traf_class_mode); } +u32 hw_atl_rpb_rpf_rx_traf_class_mode_get(struct aq_hw_s *aq_hw) +{ + return aq_hw_read_reg_bit(aq_hw, HW_ATL_RPB_RPF_RX_TC_MODE_ADR, + HW_ATL_RPB_RPF_RX_TC_MODE_MSK, + HW_ATL_RPB_RPF_RX_TC_MODE_SHIFT); +} + void hw_atl_rpb_rx_buff_en_set(struct aq_hw_s *aq_hw, u32 rx_buff_en) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPB_RX_BUF_EN_ADR, @@ -636,8 +650,8 @@ void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, rx_pkt_buff_size_per_tc); } -void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_xoff_en_per_tc, - u32 buffer) +void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, + u32 rx_xoff_en_per_tc, u32 buffer) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPB_RXBXOFF_EN_ADR(buffer), HW_ATL_RPB_RXBXOFF_EN_MSK, @@ -1290,6 +1304,13 @@ void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en) HW_ATL_TPB_TX_BUF_EN_SHIFT, tx_buff_en); } +u32 hw_atl_rpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw) +{ + return aq_hw_read_reg_bit(aq_hw, HW_ATL_TPB_TX_TC_MODE_ADDR, + HW_ATL_TPB_TX_TC_MODE_MSK, + HW_ATL_TPB_TX_TC_MODE_SHIFT); +} + void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw, u32 tx_traf_class_mode) { @@ -1327,7 +1348,26 @@ void hw_atl_tpb_tx_dma_sys_lbk_en_set(struct aq_hw_s *aq_hw, u32 tx_dma_sys_lbk_ tx_dma_sys_lbk_en); } +void hw_atl_tpb_tx_dma_net_lbk_en_set(struct aq_hw_s *aq_hw, + u32 tx_dma_net_lbk_en) +{ + aq_hw_write_reg_bit(aq_hw, HW_ATL_TPB_DMA_NET_LBK_ADR, + HW_ATL_TPB_DMA_NET_LBK_MSK, + HW_ATL_TPB_DMA_NET_LBK_SHIFT, + tx_dma_net_lbk_en); +} + +void hw_atl_tpb_tx_tx_clk_gate_en_set(struct aq_hw_s *aq_hw, + u32 tx_clk_gate_en) +{ + aq_hw_write_reg_bit(aq_hw, HW_ATL_TPB_TX_CLK_GATE_EN_ADR, + HW_ATL_TPB_TX_CLK_GATE_EN_MSK, + HW_ATL_TPB_TX_CLK_GATE_EN_SHIFT, + tx_clk_gate_en); +} + void hw_atl_tpb_tx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, + u32 tx_pkt_buff_size_per_tc, u32 buffer) { aq_hw_write_reg_bit(aq_hw, HW_ATL_TPB_TXBBUF_SIZE_ADR(buffer), @@ -1526,6 +1566,20 @@ void hw_atl_reg_glb_cpu_scratch_scp_set(struct aq_hw_s *aq_hw, glb_cpu_scratch_scp); } +void hw_atl_pcs_ptp_clock_read_enable(struct aq_hw_s *aq_hw, + u32 ptp_clock_read_enable) +{ + aq_hw_write_reg_bit(aq_hw, HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_ADR, + HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_MSK, + HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_SHIFT, + ptp_clock_read_enable); +} + +u32 hw_atl_pcs_ptp_clock_get(struct aq_hw_s *aq_hw, u32 index) +{ + return aq_hw_read_reg(aq_hw, HW_ATL_PCS_PTP_TS_VAL_ADDR(index)); +} + void hw_atl_mcp_up_force_intr_set(struct aq_hw_s *aq_hw, u32 up_force_intr) { aq_hw_write_reg_bit(aq_hw, HW_ATL_MCP_UP_FORCE_INTERRUPT_ADR, @@ -1616,6 +1670,11 @@ u32 hw_atl_sem_ram_get(struct aq_hw_s *self) return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM); } +u32 hw_atl_sem_mdio_get(struct aq_hw_s *self) +{ + return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_MDIO); +} + u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp) { return aq_hw_read_reg(aq_hw, @@ -1631,3 +1690,60 @@ u32 hw_atl_scrpad25_get(struct aq_hw_s *self) { return hw_atl_scrpad_get(self, 0x18); } + +void hw_atl_glb_mdio_iface1_set(struct aq_hw_s *aq_hw, u32 value) +{ + aq_hw_write_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(1), value); +} + +u32 hw_atl_glb_mdio_iface1_get(struct aq_hw_s *aq_hw) +{ + return aq_hw_read_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(1)); +} + +void hw_atl_glb_mdio_iface2_set(struct aq_hw_s *aq_hw, u32 value) +{ + aq_hw_write_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(2), value); +} + +u32 hw_atl_glb_mdio_iface2_get(struct aq_hw_s *aq_hw) +{ + return aq_hw_read_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(2)); +} + +void hw_atl_glb_mdio_iface3_set(struct aq_hw_s *aq_hw, u32 value) +{ + aq_hw_write_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(3), value); +} + +u32 hw_atl_glb_mdio_iface3_get(struct aq_hw_s *aq_hw) +{ + return aq_hw_read_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(3)); +} + +void hw_atl_glb_mdio_iface4_set(struct aq_hw_s *aq_hw, u32 value) +{ + aq_hw_write_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(4), value); +} + +u32 hw_atl_glb_mdio_iface4_get(struct aq_hw_s *aq_hw) +{ + return aq_hw_read_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(4)); +} + +void hw_atl_glb_mdio_iface5_set(struct aq_hw_s *aq_hw, u32 value) +{ + aq_hw_write_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(5), value); +} + +u32 hw_atl_glb_mdio_iface5_get(struct aq_hw_s *aq_hw) +{ + return aq_hw_read_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(5)); +} + +u32 hw_atl_mdio_busy_get(struct aq_hw_s *aq_hw) +{ + return aq_hw_read_reg_bit(aq_hw, HW_ATL_MDIO_BUSY_ADR, + HW_ATL_MDIO_BUSY_MSK, + HW_ATL_MDIO_BUSY_SHIFT); +} diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h index c3ee278c3747..62992b23c0e8 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * aQuantia Corporation Network Driver - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved + * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved */ /* File hw_atl_llh.h: Declarations of bitfield and register access functions for @@ -288,10 +288,16 @@ void hw_atl_reg_glb_cpu_scratch_scp_set(struct aq_hw_s *aq_hw, /* set dma system loopback */ void hw_atl_rpb_dma_sys_lbk_set(struct aq_hw_s *aq_hw, u32 dma_sys_lbk); +/* set dma network loopback */ +void hw_atl_rpb_dma_net_lbk_set(struct aq_hw_s *aq_hw, u32 dma_net_lbk); + /* set rx traffic class mode */ void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw, u32 rx_traf_class_mode); +/* get rx traffic class mode */ +u32 hw_atl_rpb_rpf_rx_traf_class_mode_get(struct aq_hw_s *aq_hw); + /* set rx buffer enable */ void hw_atl_rpb_rx_buff_en_set(struct aq_hw_s *aq_hw, u32 rx_buff_en); @@ -306,7 +312,8 @@ void hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(struct aq_hw_s *aq_hw, u32 buffer); /* set rx flow control mode */ -void hw_atl_rpb_rx_flow_ctl_mode_set(struct aq_hw_s *aq_hw, u32 rx_flow_ctl_mode); +void hw_atl_rpb_rx_flow_ctl_mode_set(struct aq_hw_s *aq_hw, + u32 rx_flow_ctl_mode); /* set rx packet buffer size (per tc) */ void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, @@ -320,7 +327,8 @@ void hw_atl_rdm_rx_dma_desc_cache_init_tgl(struct aq_hw_s *aq_hw); u32 hw_atl_rdm_rx_dma_desc_cache_init_done_get(struct aq_hw_s *aq_hw); /* set rx xoff enable (per tc) */ -void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_xoff_en_per_tc, +void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, + u32 rx_xoff_en_per_tc, u32 buffer); /* rpf */ @@ -605,6 +613,9 @@ void hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(struct aq_hw_s *aq_hw, void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw, u32 tx_traf_class_mode); +/* get TX Traffic Class Mode */ +u32 hw_atl_rpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw); + /* set tx buffer enable */ void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en); @@ -621,9 +632,18 @@ void hw_atl_tpb_tx_buff_lo_threshold_per_tc_set(struct aq_hw_s *aq_hw, /* set tx dma system loopback enable */ void hw_atl_tpb_tx_dma_sys_lbk_en_set(struct aq_hw_s *aq_hw, u32 tx_dma_sys_lbk_en); +/* set tx dma network loopback enable */ +void hw_atl_tpb_tx_dma_net_lbk_en_set(struct aq_hw_s *aq_hw, + u32 tx_dma_net_lbk_en); + +/* set tx clock gating enable */ +void hw_atl_tpb_tx_tx_clk_gate_en_set(struct aq_hw_s *aq_hw, + u32 tx_clk_gate_en); + /* set tx packet buffer size (per tc) */ void hw_atl_tpb_tx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, - u32 tx_pkt_buff_size_per_tc, u32 buffer); + u32 tx_pkt_buff_size_per_tc, + u32 buffer); /* set tx path pad insert enable */ void hw_atl_tpb_tx_path_scp_ins_en_set(struct aq_hw_s *aq_hw, u32 tx_path_scp_ins_en); @@ -715,6 +735,12 @@ void hw_atl_msm_reg_wr_strobe_set(struct aq_hw_s *aq_hw, u32 reg_wr_strobe); /* set pci register reset disable */ void hw_atl_pci_pci_reg_res_dis_set(struct aq_hw_s *aq_hw, u32 pci_reg_res_dis); +/* pcs */ +void hw_atl_pcs_ptp_clock_read_enable(struct aq_hw_s *aq_hw, + u32 ptp_clock_read_enable); + +u32 hw_atl_pcs_ptp_clock_get(struct aq_hw_s *aq_hw, u32 index); + /* set uP Force Interrupt */ void hw_atl_mcp_up_force_intr_set(struct aq_hw_s *aq_hw, u32 up_force_intr); @@ -752,9 +778,44 @@ void hw_atl_rpfl3l4_ipv6_src_addr_set(struct aq_hw_s *aq_hw, u8 location, void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location, u32 *ipv6_dest); +/* set Global MDIO Interface 1 */ +void hw_atl_glb_mdio_iface1_set(struct aq_hw_s *hw, u32 value); + +/* get Global MDIO Interface 1 */ +u32 hw_atl_glb_mdio_iface1_get(struct aq_hw_s *hw); + +/* set Global MDIO Interface 2 */ +void hw_atl_glb_mdio_iface2_set(struct aq_hw_s *hw, u32 value); + +/* get Global MDIO Interface 2 */ +u32 hw_atl_glb_mdio_iface2_get(struct aq_hw_s *hw); + +/* set Global MDIO Interface 3 */ +void hw_atl_glb_mdio_iface3_set(struct aq_hw_s *hw, u32 value); + +/* get Global MDIO Interface 3 */ +u32 hw_atl_glb_mdio_iface3_get(struct aq_hw_s *hw); + +/* set Global MDIO Interface 4 */ +void hw_atl_glb_mdio_iface4_set(struct aq_hw_s *hw, u32 value); + +/* get Global MDIO Interface 4 */ +u32 hw_atl_glb_mdio_iface4_get(struct aq_hw_s *hw); + +/* set Global MDIO Interface 5 */ +void hw_atl_glb_mdio_iface5_set(struct aq_hw_s *hw, u32 value); + +/* get Global MDIO Interface 5 */ +u32 hw_atl_glb_mdio_iface5_get(struct aq_hw_s *hw); + +u32 hw_atl_mdio_busy_get(struct aq_hw_s *aq_hw); + /* get global microprocessor ram semaphore */ u32 hw_atl_sem_ram_get(struct aq_hw_s *self); +/* get global microprocessor mdio semaphore */ +u32 hw_atl_sem_mdio_get(struct aq_hw_s *self); + /* get global microprocessor scratch pad register */ u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp); diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h index 35887ad89025..18de2f7b8959 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * aQuantia Corporation Network Driver - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved + * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved */ /* File hw_atl_llh_internal.h: Preprocessor definitions @@ -554,6 +554,24 @@ /* default value of bitfield dma_sys_loopback */ #define HW_ATL_RPB_DMA_SYS_LBK_DEFAULT 0x0 +/* rx dma_net_loopback bitfield definitions + * preprocessor definitions for the bitfield "dma_net_loopback". + * port="pif_rpb_dma_net_lbk_i" + */ + +/* register address for bitfield dma_net_loopback */ +#define HW_ATL_RPB_DMA_NET_LBK_ADR 0x00005000 +/* bitmask for bitfield dma_net_loopback */ +#define HW_ATL_RPB_DMA_NET_LBK_MSK 0x00000010 +/* inverted bitmask for bitfield dma_net_loopback */ +#define HW_ATL_RPB_DMA_NET_LBK_MSKN 0xffffffef +/* lower bit position of bitfield dma_net_loopback */ +#define HW_ATL_RPB_DMA_NET_LBK_SHIFT 4 +/* width of bitfield dma_net_loopback */ +#define HW_ATL_RPB_DMA_NET_LBK_WIDTH 1 +/* default value of bitfield dma_net_loopback */ +#define HW_ATL_RPB_DMA_NET_LBK_DEFAULT 0x0 + /* rx rx_tc_mode bitfield definitions * preprocessor definitions for the bitfield "rx_tc_mode". * port="pif_rpb_rx_tc_mode_i,pif_rpf_rx_tc_mode_i" @@ -1308,6 +1326,52 @@ /* default value of bitfield et_val{f}[f:0] */ #define HW_ATL_RPF_ET_VALF_DEFAULT 0x0 +/* RX l3_l4_en{F} Bitfield Definitions + * Preprocessor definitions for the bitfield "l3_l4_en{F}". + * Parameter: filter {F} | stride size 0x4 | range [0, 7] + * PORT="pif_rpf_l3_l4_en_i[0]" + */ + +#define HW_ATL_RPF_L3_REG_CTRL_ADR(filter) (0x00005380 + (filter) * 0x4) + +/* RX rpf_l3_sa{D}[1F:0] Bitfield Definitions + * Preprocessor definitions for the bitfield "l3_sa{D}[1F:0]". + * Parameter: location {D} | stride size 0x4 | range [0, 7] + * PORT="pif_rpf_l3_sa0_i[31:0]" + */ + +/* Register address for bitfield pif_rpf_l3_sa0_i[31:0] */ +#define HW_ATL_RPF_L3_SRCA_ADR(filter) (0x000053B0 + (filter) * 0x4) +/* Bitmask for bitfield l3_sa0[1F:0] */ +#define HW_ATL_RPF_L3_SRCA_MSK 0xFFFFFFFFu +/* Inverted bitmask for bitfield l3_sa0[1F:0] */ +#define HW_ATL_RPF_L3_SRCA_MSKN 0xFFFFFFFFu +/* Lower bit position of bitfield l3_sa0[1F:0] */ +#define HW_ATL_RPF_L3_SRCA_SHIFT 0 +/* Width of bitfield l3_sa0[1F:0] */ +#define HW_ATL_RPF_L3_SRCA_WIDTH 32 +/* Default value of bitfield l3_sa0[1F:0] */ +#define HW_ATL_RPF_L3_SRCA_DEFAULT 0x0 + +/* RX rpf_l3_da{D}[1F:0] Bitfield Definitions + * Preprocessor definitions for the bitfield "l3_da{D}[1F:0]". + * Parameter: location {D} | stride size 0x4 | range [0, 7] + * PORT="pif_rpf_l3_da0_i[31:0]" + */ + + /* Register address for bitfield pif_rpf_l3_da0_i[31:0] */ +#define HW_ATL_RPF_L3_DSTA_ADR(filter) (0x000053B0 + (filter) * 0x4) +/* Bitmask for bitfield l3_da0[1F:0] */ +#define HW_ATL_RPF_L3_DSTA_MSK 0xFFFFFFFFu +/* Inverted bitmask for bitfield l3_da0[1F:0] */ +#define HW_ATL_RPF_L3_DSTA_MSKN 0xFFFFFFFFu +/* Lower bit position of bitfield l3_da0[1F:0] */ +#define HW_ATL_RPF_L3_DSTA_SHIFT 0 +/* Width of bitfield l3_da0[1F:0] */ +#define HW_ATL_RPF_L3_DSTA_WIDTH 32 +/* Default value of bitfield l3_da0[1F:0] */ +#define HW_ATL_RPF_L3_DSTA_DEFAULT 0x0 + /* RX l4_sp{D}[F:0] Bitfield Definitions * Preprocessor definitions for the bitfield "l4_sp{D}[F:0]". * Parameter: srcport {D} | stride size 0x4 | range [0, 7] @@ -2061,6 +2125,24 @@ /* default value of bitfield dma_sys_loopback */ #define HW_ATL_TPB_DMA_SYS_LBK_DEFAULT 0x0 +/* tx dma_net_loopback bitfield definitions + * preprocessor definitions for the bitfield "dma_net_loopback". + * port="pif_tpb_dma_net_lbk_i" + */ + +/* register address for bitfield dma_net_loopback */ +#define HW_ATL_TPB_DMA_NET_LBK_ADR 0x00007000 +/* bitmask for bitfield dma_net_loopback */ +#define HW_ATL_TPB_DMA_NET_LBK_MSK 0x00000010 +/* inverted bitmask for bitfield dma_net_loopback */ +#define HW_ATL_TPB_DMA_NET_LBK_MSKN 0xffffffef +/* lower bit position of bitfield dma_net_loopback */ +#define HW_ATL_TPB_DMA_NET_LBK_SHIFT 4 +/* width of bitfield dma_net_loopback */ +#define HW_ATL_TPB_DMA_NET_LBK_WIDTH 1 +/* default value of bitfield dma_net_loopback */ +#define HW_ATL_TPB_DMA_NET_LBK_DEFAULT 0x0 + /* tx tx{b}_buf_size[7:0] bitfield definitions * preprocessor definitions for the bitfield "tx{b}_buf_size[7:0]". * parameter: buffer {b} | stride size 0x10 | range [0, 7] @@ -2098,6 +2180,24 @@ /* default value of bitfield tx_scp_ins_en */ #define HW_ATL_TPB_TX_SCP_INS_EN_DEFAULT 0x0 +/* tx tx_clk_gate_en bitfield definitions + * preprocessor definitions for the bitfield "tx_clk_gate_en". + * port="pif_tpb_clk_gate_en_i" + */ + +/* register address for bitfield tx_clk_gate_en */ +#define HW_ATL_TPB_TX_CLK_GATE_EN_ADR 0x00007900 +/* bitmask for bitfield tx_clk_gate_en */ +#define HW_ATL_TPB_TX_CLK_GATE_EN_MSK 0x00000010 +/* inverted bitmask for bitfield tx_clk_gate_en */ +#define HW_ATL_TPB_TX_CLK_GATE_EN_MSKN 0xffffffef +/* lower bit position of bitfield tx_clk_gate_en */ +#define HW_ATL_TPB_TX_CLK_GATE_EN_SHIFT 4 +/* width of bitfield tx_clk_gate_en */ +#define HW_ATL_TPB_TX_CLK_GATE_EN_WIDTH 1 +/* default value of bitfield tx_clk_gate_en */ +#define HW_ATL_TPB_TX_CLK_GATE_EN_DEFAULT 0x1 + /* tx ipv4_chk_en bitfield definitions * preprocessor definitions for the bitfield "ipv4_chk_en". * port="pif_tpo_ipv4_chk_en_i" @@ -2440,6 +2540,22 @@ /* default value of bitfield register write strobe */ #define HW_ATL_MSM_REG_WR_STROBE_DEFAULT 0x0 +/* register address for bitfield PTP Digital Clock Read Enable */ +#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_ADR 0x00004628 +/* bitmask for bitfield PTP Digital Clock Read Enable */ +#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_MSK 0x00000010 +/* inverted bitmask for bitfield PTP Digital Clock Read Enable */ +#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_MSKN 0xFFFFFFEF +/* lower bit position of bitfield PTP Digital Clock Read Enable */ +#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_SHIFT 4 +/* width of bitfield PTP Digital Clock Read Enable */ +#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_WIDTH 1 +/* default value of bitfield PTP Digital Clock Read Enable */ +#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_DEFAULT 0x0 + +/* register address for ptp counter reading */ +#define HW_ATL_PCS_PTP_TS_VAL_ADDR(index) (0x00004900 + (index) * 0x4) + /* mif soft reset bitfield definitions * preprocessor definitions for the bitfield "soft reset". * port="pif_glb_res_i" @@ -2532,50 +2648,121 @@ /* default value of bitfield uP Force Interrupt */ #define HW_ATL_MCP_UP_FORCE_INTERRUPT_DEFAULT 0x0 -#define HW_ATL_RX_CTRL_ADDR_BEGIN_FL3L4 0x00005380 -#define HW_ATL_RX_SRCA_ADDR_BEGIN_FL3L4 0x000053B0 -#define HW_ATL_RX_DESTA_ADDR_BEGIN_FL3L4 0x000053D0 - -#define HW_ATL_RPF_L3_REG_CTRL_ADR(location) (0x00005380 + (location) * 0x4) - -/* RX rpf_l3_sa{D}[1F:0] Bitfield Definitions - * Preprocessor definitions for the bitfield "l3_sa{D}[1F:0]". - * Parameter: location {D} | stride size 0x4 | range [0, 7] - * PORT="pif_rpf_l3_sa0_i[31:0]" - */ - -/* Register address for bitfield pif_rpf_l3_sa0_i[31:0] */ -#define HW_ATL_RPF_L3_SRCA_ADR(location) (0x000053B0 + (location) * 0x4) -/* Bitmask for bitfield l3_sa0[1F:0] */ -#define HW_ATL_RPF_L3_SRCA_MSK 0xFFFFFFFFu -/* Inverted bitmask for bitfield l3_sa0[1F:0] */ -#define HW_ATL_RPF_L3_SRCA_MSKN 0xFFFFFFFFu -/* Lower bit position of bitfield l3_sa0[1F:0] */ -#define HW_ATL_RPF_L3_SRCA_SHIFT 0 -/* Width of bitfield l3_sa0[1F:0] */ -#define HW_ATL_RPF_L3_SRCA_WIDTH 32 -/* Default value of bitfield l3_sa0[1F:0] */ -#define HW_ATL_RPF_L3_SRCA_DEFAULT 0x0 - -/* RX rpf_l3_da{D}[1F:0] Bitfield Definitions - * Preprocessor definitions for the bitfield "l3_da{D}[1F:0]". - * Parameter: location {D} | stride size 0x4 | range [0, 7] - * PORT="pif_rpf_l3_da0_i[31:0]" - */ - - /* Register address for bitfield pif_rpf_l3_da0_i[31:0] */ -#define HW_ATL_RPF_L3_DSTA_ADR(location) (0x000053B0 + (location) * 0x4) -/* Bitmask for bitfield l3_da0[1F:0] */ -#define HW_ATL_RPF_L3_DSTA_MSK 0xFFFFFFFFu -/* Inverted bitmask for bitfield l3_da0[1F:0] */ -#define HW_ATL_RPF_L3_DSTA_MSKN 0xFFFFFFFFu -/* Lower bit position of bitfield l3_da0[1F:0] */ -#define HW_ATL_RPF_L3_DSTA_SHIFT 0 -/* Width of bitfield l3_da0[1F:0] */ -#define HW_ATL_RPF_L3_DSTA_WIDTH 32 -/* Default value of bitfield l3_da0[1F:0] */ -#define HW_ATL_RPF_L3_DSTA_DEFAULT 0x0 - +/* Preprocessor definitions for Global MDIO Interfaces + * Address: 0x00000280 + 0x4 * Number of interface + */ +#define HW_ATL_GLB_MDIO_IFACE_ADDR_BEGIN 0x00000280u + +#define HW_ATL_GLB_MDIO_IFACE_N_ADR(number) \ + (HW_ATL_GLB_MDIO_IFACE_ADDR_BEGIN + (((number) - 1) * 0x4)) + +/* MIF MDIO Busy Bitfield Definitions + * Preprocessor definitions for the bitfield "MDIO Busy". + * PORT="mdio_pif_busy_o" + */ + +/* Register address for bitfield MDIO Busy */ +#define HW_ATL_MDIO_BUSY_ADR 0x00000284 +/* Bitmask for bitfield MDIO Busy */ +#define HW_ATL_MDIO_BUSY_MSK 0x80000000 +/* Inverted bitmask for bitfield MDIO Busy */ +#define HW_ATL_MDIO_BUSY_MSKN 0x7FFFFFFF +/* Lower bit position of bitfield MDIO Busy */ +#define HW_ATL_MDIO_BUSY_SHIFT 31 +/* Width of bitfield MDIO Busy */ +#define HW_ATL_MDIO_BUSY_WIDTH 1 + +/* MIF MDIO Execute Operation Bitfield Definitions + * Preprocessor definitions for the bitfield "MDIO Execute Operation". + * PORT="pif_mdio_op_start_i" + */ + +/* Register address for bitfield MDIO Execute Operation */ +#define HW_ATL_MDIO_EXECUTE_OPERATION_ADR 0x00000284 +/* Bitmask for bitfield MDIO Execute Operation */ +#define HW_ATL_MDIO_EXECUTE_OPERATION_MSK 0x00008000 +/* Inverted bitmask for bitfield MDIO Execute Operation */ +#define HW_ATL_MDIO_EXECUTE_OPERATION_MSKN 0xFFFF7FFF +/* Lower bit position of bitfield MDIO Execute Operation */ +#define HW_ATL_MDIO_EXECUTE_OPERATION_SHIFT 15 +/* Width of bitfield MDIO Execute Operation */ +#define HW_ATL_MDIO_EXECUTE_OPERATION_WIDTH 1 +/* Default value of bitfield MDIO Execute Operation */ +#define HW_ATL_MDIO_EXECUTE_OPERATION_DEFAULT 0x0 + +/* MIF Op Mode [1:0] Bitfield Definitions + * Preprocessor definitions for the bitfield "Op Mode [1:0]". + * PORT="pif_mdio_mode_i[1:0]" + */ + +/* Register address for bitfield Op Mode [1:0] */ +#define HW_ATL_MDIO_OP_MODE_ADR 0x00000284 +/* Bitmask for bitfield Op Mode [1:0] */ +#define HW_ATL_MDIO_OP_MODE_MSK 0x00003000 +/* Inverted bitmask for bitfield Op Mode [1:0] */ +#define HW_ATL_MDIO_OP_MODE_MSKN 0xFFFFCFFF +/* Lower bit position of bitfield Op Mode [1:0] */ +#define HW_ATL_MDIO_OP_MODE_SHIFT 12 +/* Width of bitfield Op Mode [1:0] */ +#define HW_ATL_MDIO_OP_MODE_WIDTH 2 +/* Default value of bitfield Op Mode [1:0] */ +#define HW_ATL_MDIO_OP_MODE_DEFAULT 0x0 + +/* MIF PHY address Bitfield Definitions + * Preprocessor definitions for the bitfield "PHY address". + * PORT="pif_mdio_phy_addr_i[9:0]" + */ + +/* Register address for bitfield PHY address */ +#define HW_ATL_MDIO_PHY_ADDRESS_ADR 0x00000284 +/* Bitmask for bitfield PHY address */ +#define HW_ATL_MDIO_PHY_ADDRESS_MSK 0x000003FF +/* Inverted bitmask for bitfield PHY address */ +#define HW_ATL_MDIO_PHY_ADDRESS_MSKN 0xFFFFFC00 +/* Lower bit position of bitfield PHY address */ +#define HW_ATL_MDIO_PHY_ADDRESS_SHIFT 0 +/* Width of bitfield PHY address */ +#define HW_ATL_MDIO_PHY_ADDRESS_WIDTH 10 +/* Default value of bitfield PHY address */ +#define HW_ATL_MDIO_PHY_ADDRESS_DEFAULT 0x0 + +/* MIF MDIO WriteData [F:0] Bitfield Definitions + * Preprocessor definitions for the bitfield "MDIO WriteData [F:0]". + * PORT="pif_mdio_wdata_i[15:0]" + */ + +/* Register address for bitfield MDIO WriteData [F:0] */ +#define HW_ATL_MDIO_WRITE_DATA_ADR 0x00000288 +/* Bitmask for bitfield MDIO WriteData [F:0] */ +#define HW_ATL_MDIO_WRITE_DATA_MSK 0x0000FFFF +/* Inverted bitmask for bitfield MDIO WriteData [F:0] */ +#define HW_ATL_MDIO_WRITE_DATA_MSKN 0xFFFF0000 +/* Lower bit position of bitfield MDIO WriteData [F:0] */ +#define HW_ATL_MDIO_WRITE_DATA_SHIFT 0 +/* Width of bitfield MDIO WriteData [F:0] */ +#define HW_ATL_MDIO_WRITE_DATA_WIDTH 16 +/* Default value of bitfield MDIO WriteData [F:0] */ +#define HW_ATL_MDIO_WRITE_DATA_DEFAULT 0x0 + +/* MIF MDIO Address [F:0] Bitfield Definitions + * Preprocessor definitions for the bitfield "MDIO Address [F:0]". + * PORT="pif_mdio_addr_i[15:0]" + */ + +/* Register address for bitfield MDIO Address [F:0] */ +#define HW_ATL_MDIO_ADDRESS_ADR 0x0000028C +/* Bitmask for bitfield MDIO Address [F:0] */ +#define HW_ATL_MDIO_ADDRESS_MSK 0x0000FFFF +/* Inverted bitmask for bitfield MDIO Address [F:0] */ +#define HW_ATL_MDIO_ADDRESS_MSKN 0xFFFF0000 +/* Lower bit position of bitfield MDIO Address [F:0] */ +#define HW_ATL_MDIO_ADDRESS_SHIFT 0 +/* Width of bitfield MDIO Address [F:0] */ +#define HW_ATL_MDIO_ADDRESS_WIDTH 16 +/* Default value of bitfield MDIO Address [F:0] */ +#define HW_ATL_MDIO_ADDRESS_DEFAULT 0x0 + +#define HW_ATL_FW_SM_MDIO 0x0U #define HW_ATL_FW_SM_RAM 0x2U #endif /* HW_ATL_LLH_INTERNAL_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c index 52646855495e..8910b62e67ed 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * aQuantia Corporation Network Driver - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved + * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved */ /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware @@ -47,6 +47,11 @@ #define FORCE_FLASHLESS 0 +enum mcp_area { + MCP_AREA_CONFIG = 0x80000000, + MCP_AREA_SETTINGS = 0x20000000, +}; + static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, @@ -87,6 +92,7 @@ int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) } self->aq_fw_ops = *fw_ops; err = self->aq_fw_ops->init(self); + return err; } @@ -237,9 +243,9 @@ static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self) int hw_atl_utils_soft_reset(struct aq_hw_s *self) { - int k; u32 boot_exit_code = 0; u32 val; + int k; for (k = 0; k < 1000; ++k) { u32 flb_status = aq_hw_read_reg(self, @@ -327,11 +333,75 @@ err_exit: return err; } -static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, - u32 cnt) +static int hw_atl_utils_write_b1_mbox(struct aq_hw_s *self, u32 addr, + u32 *p, u32 cnt, enum mcp_area area) { + u32 data_offset = 0; + u32 offset = addr; + int err = 0; u32 val; + + switch (area) { + case MCP_AREA_CONFIG: + offset -= self->rpc_addr; + break; + + case MCP_AREA_SETTINGS: + offset -= self->settings_addr; + break; + } + + offset = offset / sizeof(u32); + + for (; data_offset < cnt; ++data_offset, ++offset) { + aq_hw_write_reg(self, 0x328, p[data_offset]); + aq_hw_write_reg(self, 0x32C, + (area | (0xFFFF & (offset * 4)))); + hw_atl_mcp_up_force_intr_set(self, 1); + /* 1000 times by 10us = 10ms */ + err = readx_poll_timeout_atomic(hw_atl_scrpad12_get, + self, val, + (val & 0xF0000000) != + area, + 10U, 10000U); + + if (err < 0) + break; + } + + return err; +} + +static int hw_atl_utils_write_b0_mbox(struct aq_hw_s *self, u32 addr, + u32 *p, u32 cnt) +{ + u32 offset = 0; int err = 0; + u32 val; + + aq_hw_write_reg(self, 0x208, addr); + + for (; offset < cnt; ++offset) { + aq_hw_write_reg(self, 0x20C, p[offset]); + aq_hw_write_reg(self, 0x200, 0xC000); + + err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get, + self, val, + (val & 0x100) == 0U, + 10U, 10000U); + + if (err < 0) + break; + } + + return err; +} + +static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 addr, u32 *p, + u32 cnt, enum mcp_area area) +{ + int err = 0; + u32 val; err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self, val, val == 1U, @@ -339,54 +409,47 @@ static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, if (err < 0) goto err_exit; - if (IS_CHIP_FEATURE(REVISION_B1)) { - u32 offset = 0; - - for (; offset < cnt; ++offset) { - aq_hw_write_reg(self, 0x328, p[offset]); - aq_hw_write_reg(self, 0x32C, - (0x80000000 | (0xFFFF & (offset * 4)))); - hw_atl_mcp_up_force_intr_set(self, 1); - /* 1000 times by 10us = 10ms */ - err = readx_poll_timeout_atomic(hw_atl_scrpad12_get, - self, val, - (val & 0xF0000000) != - 0x80000000, - 10U, 10000U); - } - } else { - u32 offset = 0; - - aq_hw_write_reg(self, 0x208, a); + if (IS_CHIP_FEATURE(REVISION_B1)) + err = hw_atl_utils_write_b1_mbox(self, addr, p, cnt, area); + else + err = hw_atl_utils_write_b0_mbox(self, addr, p, cnt); - for (; offset < cnt; ++offset) { - aq_hw_write_reg(self, 0x20C, p[offset]); - aq_hw_write_reg(self, 0x200, 0xC000); + hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); - err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get, - self, val, - (val & 0x100) == 0, - 1000U, 10000U); - } - } + if (err < 0) + goto err_exit; - hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); + err = aq_hw_err_from_flags(self); err_exit: return err; } +int hw_atl_write_fwcfg_dwords(struct aq_hw_s *self, u32 *p, u32 cnt) +{ + return hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, p, + cnt, MCP_AREA_CONFIG); +} + +int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p, + u32 cnt) +{ + return hw_atl_utils_fw_upload_dwords(self, self->settings_addr + offset, + p, cnt, MCP_AREA_SETTINGS); +} + static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual) { - int err = 0; const u32 dw_major_mask = 0xff000000U; const u32 dw_minor_mask = 0x00ffffffU; + int err = 0; err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0; if (err < 0) goto err_exit; err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ? -EOPNOTSUPP : 0; + err_exit: return err; } @@ -431,17 +494,16 @@ struct aq_hw_atl_utils_fw_rpc_tid_s { int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size) { - int err = 0; struct aq_hw_atl_utils_fw_rpc_tid_s sw; + int err = 0; if (!IS_CHIP_FEATURE(MIPS)) { err = -1; goto err_exit; } - err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, - (u32 *)(void *)&self->rpc, - (rpc_size + sizeof(u32) - - sizeof(u8)) / sizeof(u32)); + err = hw_atl_write_fwcfg_dwords(self, (u32 *)(void *)&self->rpc, + (rpc_size + sizeof(u32) - + sizeof(u8)) / sizeof(u32)); if (err < 0) goto err_exit; @@ -456,9 +518,9 @@ err_exit: int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, struct hw_atl_utils_fw_rpc **rpc) { - int err = 0; struct aq_hw_atl_utils_fw_rpc_tid_s sw; struct aq_hw_atl_utils_fw_rpc_tid_s fw; + int err = 0; do { sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR); @@ -562,10 +624,10 @@ static int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed) static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, enum hal_atl_utils_fw_state_e state) { - int err = 0; - u32 transaction_id = 0; - struct hw_atl_utils_mbox_header mbox; u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR); + struct hw_atl_utils_mbox_header mbox; + u32 transaction_id = 0; + int err = 0; if (state == MPI_RESET) { hw_atl_utils_mpi_read_mbox(self, &mbox); @@ -593,20 +655,26 @@ static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, val |= state & HW_ATL_MPI_STATE_MSK; aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val); + err_exit: return err; } int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self) { - u32 cp0x036C = hw_atl_utils_mpi_get_state(self); - u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT; struct aq_hw_link_status_s *link_status = &self->aq_link_status; + u32 mpi_state; + u32 speed; - if (!link_speed_mask) { + mpi_state = hw_atl_utils_mpi_get_state(self); + speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G | + FW2X_RATE_2G5 | FW2X_RATE_5G | + FW2X_RATE_10G); + + if (!speed) { link_status->mbps = 0U; } else { - switch (link_speed_mask) { + switch (speed) { case HAL_ATLANTIC_RATE_10G: link_status->mbps = 10000U; break; @@ -639,14 +707,15 @@ int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self) int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self, u8 *mac) { + u32 mac_addr[2]; + u32 efuse_addr; int err = 0; u32 h = 0U; u32 l = 0U; - u32 mac_addr[2]; if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) { - unsigned int rnd = 0; unsigned int ucp_0x370 = 0; + unsigned int rnd = 0; get_random_bytes(&rnd, sizeof(unsigned int)); @@ -654,11 +723,10 @@ int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self, aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370); } - err = hw_atl_utils_fw_downld_dwords(self, - aq_hw_read_reg(self, 0x00000374U) + - (40U * 4U), - mac_addr, - ARRAY_SIZE(mac_addr)); + efuse_addr = aq_hw_read_reg(self, 0x00000374U); + + err = hw_atl_utils_fw_downld_dwords(self, efuse_addr + (40U * 4U), + mac_addr, ARRAY_SIZE(mac_addr)); if (err < 0) { mac_addr[0] = 0U; mac_addr[1] = 0U; @@ -720,14 +788,15 @@ unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps) default: break; } + return ret; } void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p) { - u32 chip_features = 0U; u32 val = hw_atl_reg_glb_mif_id_get(self); u32 mif_rev = val & 0xFFU; + u32 chip_features = 0U; if ((0xFU & mif_rev) == 1U) { chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 | @@ -754,13 +823,14 @@ static int hw_atl_fw1x_deinit(struct aq_hw_s *self) { hw_atl_utils_mpi_set_speed(self, 0); hw_atl_utils_mpi_set_state(self, MPI_DEINIT); + return 0; } int hw_atl_utils_update_stats(struct aq_hw_s *self) { - struct hw_atl_utils_mbox mbox; struct aq_stats_s *cs = &self->curr_stats; + struct hw_atl_utils_mbox mbox; hw_atl_utils_mpi_read_stats(self, &mbox); @@ -837,16 +907,19 @@ int hw_atl_utils_hw_get_regs(struct aq_hw_s *self, for (i = 0; i < aq_hw_caps->mac_regs_count; i++) regs_buff[i] = aq_hw_read_reg(self, hw_atl_utils_hw_mac_regs[i]); + return 0; } int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version) { *fw_version = aq_hw_read_reg(self, 0x18U); + return 0; } -static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac) +static int aq_fw1x_set_wake_magic(struct aq_hw_s *self, bool wol_enabled, + u8 *mac) { struct hw_atl_utils_fw_rpc *prpc = NULL; unsigned int rpc_size = 0U; @@ -859,22 +932,26 @@ static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac) memset(prpc, 0, sizeof(*prpc)); if (wol_enabled) { - rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_wol); + rpc_size = offsetof(struct hw_atl_utils_fw_rpc, msg_wol_add) + + sizeof(prpc->msg_wol_add); + prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD; - prpc->msg_wol.priority = + prpc->msg_wol_add.priority = HAL_ATLANTIC_UTILS_FW_MSG_WOL_PRIOR; - prpc->msg_wol.pattern_id = + prpc->msg_wol_add.pattern_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN; - prpc->msg_wol.wol_packet_type = + prpc->msg_wol_add.packet_type = HAL_ATLANTIC_UTILS_FW_MSG_WOL_MAG_PKT; - ether_addr_copy((u8 *)&prpc->msg_wol.wol_pattern, mac); + ether_addr_copy((u8 *)&prpc->msg_wol_add.magic_packet_pattern, + mac); } else { - rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_del_id); + rpc_size = sizeof(prpc->msg_wol_remove) + + offsetof(struct hw_atl_utils_fw_rpc, msg_wol_remove); prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL; - prpc->msg_wol.pattern_id = + prpc->msg_wol_add.pattern_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN; } @@ -891,8 +968,8 @@ static int aq_fw1x_set_power(struct aq_hw_s *self, unsigned int power_state, unsigned int rpc_size = 0U; int err = 0; - if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) { - err = aq_fw1x_set_wol(self, 1, mac); + if (self->aq_nic_cfg->wol & WAKE_MAGIC) { + err = aq_fw1x_set_wake_magic(self, 1, mac); if (err < 0) goto err_exit; @@ -964,4 +1041,7 @@ const struct aq_fw_ops aq_fw_1x_ops = { .set_eee_rate = NULL, .get_eee_rate = NULL, .set_flow_control = NULL, + .send_fw_request = NULL, + .enable_ptp = NULL, + .led_control = NULL, }; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h index 692bed70e104..42f0c5c6ec2d 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * aQuantia Corporation Network Driver - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved + * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved */ /* File hw_atl_utils.h: Declaration of common functions for Atlantic hardware @@ -41,7 +41,15 @@ struct __packed hw_atl_rxd_wb_s { u16 status; u16 pkt_len; u16 next_desc_ptr; - u16 vlan; + __le16 vlan; +}; + +/* Hardware rx HW TIMESTAMP writeback */ +struct __packed hw_atl_rxd_hwts_wb_s { + u32 sec_hw; + u32 ns; + u32 sec_lw0; + u32 sec_lw1; }; struct __packed hw_atl_stats_s { @@ -62,104 +70,41 @@ struct __packed hw_atl_stats_s { u32 dpc; }; -union __packed ip_addr { - struct { - u8 addr[16]; - } v6; - struct { - u8 padding[12]; - u8 addr[4]; - } v4; -}; - -struct __packed hw_atl_utils_fw_rpc { - u32 msg_id; - +struct __packed drv_msg_enable_wakeup { union { - struct { - u32 pong; - } msg_ping; + u32 pattern_mask; struct { - u8 mac_addr[6]; - u32 ip_addr_cnt; + u32 reason_arp_v4_pkt : 1; + u32 reason_ipv4_ping_pkt : 1; + u32 reason_ipv6_ns_pkt : 1; + u32 reason_ipv6_ping_pkt : 1; + u32 reason_link_up : 1; + u32 reason_link_down : 1; + u32 reason_maximum : 1; + }; + }; - struct { - union ip_addr addr; - union ip_addr mask; - } ip[1]; - } msg_arp; + union { + u32 offload_mask; + }; +}; - struct { - u32 len; - u8 packet[1514U]; - } msg_inject; +struct __packed magic_packet_pattern_s { + u8 mac_addr[ETH_ALEN]; +}; - struct { - u32 priority; - u32 wol_packet_type; - u32 pattern_id; - u32 next_wol_pattern_offset; - - union { - struct { - u32 flags; - u8 ipv4_source_address[4]; - u8 ipv4_dest_address[4]; - u16 tcp_source_port_number; - u16 tcp_dest_port_number; - } ipv4_tcp_syn_parameters; - - struct { - u32 flags; - u8 ipv6_source_address[16]; - u8 ipv6_dest_address[16]; - u16 tcp_source_port_number; - u16 tcp_dest_port_number; - } ipv6_tcp_syn_parameters; - - struct { - u32 flags; - } eapol_request_id_message_parameters; - - struct { - u32 flags; - u32 mask_offset; - u32 mask_size; - u32 pattern_offset; - u32 pattern_size; - } wol_bit_map_pattern; - - struct { - u8 mac_addr[ETH_ALEN]; - } wol_magic_packet_patter; - } wol_pattern; - } msg_wol; +struct __packed drv_msg_wol_add { + u32 priority; + u32 packet_type; + u32 pattern_id; + u32 next_pattern_offset; - struct { - union { - u32 pattern_mask; - - struct { - u32 reason_arp_v4_pkt : 1; - u32 reason_ipv4_ping_pkt : 1; - u32 reason_ipv6_ns_pkt : 1; - u32 reason_ipv6_ping_pkt : 1; - u32 reason_link_up : 1; - u32 reason_link_down : 1; - u32 reason_maximum : 1; - }; - }; - - union { - u32 offload_mask; - }; - } msg_enable_wakeup; + struct magic_packet_pattern_s magic_packet_pattern; +}; - struct { - u32 id; - } msg_del_id; - }; +struct __packed drv_msg_wol_remove { + u32 id; }; struct __packed hw_atl_utils_mbox_header { @@ -168,43 +113,89 @@ struct __packed hw_atl_utils_mbox_header { u32 error; }; -struct __packed hw_aq_info { +struct __packed hw_atl_ptp_offset { + u16 ingress_100; + u16 egress_100; + u16 ingress_1000; + u16 egress_1000; + u16 ingress_2500; + u16 egress_2500; + u16 ingress_5000; + u16 egress_5000; + u16 ingress_10000; + u16 egress_10000; +}; + +struct __packed hw_atl_cable_diag { + u8 fault; + u8 distance; + u8 far_distance; + u8 reserved; +}; + +enum gpio_pin_function { + GPIO_PIN_FUNCTION_NC, + GPIO_PIN_FUNCTION_VAUX_ENABLE, + GPIO_PIN_FUNCTION_EFUSE_BURN_ENABLE, + GPIO_PIN_FUNCTION_SFP_PLUS_DETECT, + GPIO_PIN_FUNCTION_TX_DISABLE, + GPIO_PIN_FUNCTION_RATE_SEL_0, + GPIO_PIN_FUNCTION_RATE_SEL_1, + GPIO_PIN_FUNCTION_TX_FAULT, + GPIO_PIN_FUNCTION_PTP0, + GPIO_PIN_FUNCTION_PTP1, + GPIO_PIN_FUNCTION_PTP2, + GPIO_PIN_FUNCTION_SIZE +}; + +struct __packed hw_atl_info { u8 reserved[6]; u16 phy_fault_code; u16 phy_temperature; u8 cable_len; u8 reserved1; - u32 cable_diag_data[4]; - u8 reserved2[32]; + struct hw_atl_cable_diag cable_diag_data[4]; + struct hw_atl_ptp_offset ptp_offset; + u8 reserved2[12]; u32 caps_lo; u32 caps_hi; + u32 reserved_datapath; + u32 reserved3[7]; + u32 reserved_simpleresp[3]; + u32 reserved_linkstat[7]; + u32 reserved_wakes_count; + u32 reserved_eee_stat[12]; + u32 tx_stuck_cnt; + u32 setting_address; + u32 setting_length; + u32 caps_ex; + enum gpio_pin_function gpio_pin[3]; + u32 pcie_aer_dump[18]; + u16 snr_margin[4]; }; struct __packed hw_atl_utils_mbox { struct hw_atl_utils_mbox_header header; struct hw_atl_stats_s stats; - struct hw_aq_info info; + struct hw_atl_info info; }; -/* fw2x */ -typedef u32 fw_offset_t; - struct __packed offload_ip_info { u8 v4_local_addr_count; u8 v4_addr_count; u8 v6_local_addr_count; u8 v6_addr_count; - fw_offset_t v4_addr; - fw_offset_t v4_prefix; - fw_offset_t v6_addr; - fw_offset_t v6_prefix; + u32 v4_addr; + u32 v4_prefix; + u32 v6_addr; + u32 v6_prefix; }; struct __packed offload_port_info { u16 udp_port_count; u16 tcp_port_count; - fw_offset_t udp_port; - fw_offset_t tcp_port; + u32 udp_port; + u32 tcp_port; }; struct __packed offload_ka_info { @@ -212,15 +203,15 @@ struct __packed offload_ka_info { u16 v6_ka_count; u32 retry_count; u32 retry_interval; - fw_offset_t v4_ka; - fw_offset_t v6_ka; + u32 v4_ka; + u32 v6_ka; }; struct __packed offload_rr_info { u32 rr_count; u32 rr_buf_len; - fw_offset_t rr_id_x; - fw_offset_t rr_buf; + u32 rr_id_x; + u32 rr_buf; }; struct __packed offload_info { @@ -237,9 +228,103 @@ struct __packed offload_info { u8 buf[0]; }; +struct __packed hw_atl_utils_fw_rpc { + u32 msg_id; + + union { + /* fw1x structures */ + struct drv_msg_wol_add msg_wol_add; + struct drv_msg_wol_remove msg_wol_remove; + struct drv_msg_enable_wakeup msg_enable_wakeup; + /* fw2x structures */ + struct offload_info fw2x_offloads; + }; +}; + +/* Mailbox FW Request interface */ +struct __packed hw_fw_request_ptp_gpio_ctrl { + u32 index; + u32 period; + u64 start; +}; + +struct __packed hw_fw_request_ptp_adj_freq { + u32 ns_mac; + u32 fns_mac; + u32 ns_phy; + u32 fns_phy; + u32 mac_ns_adj; + u32 mac_fns_adj; +}; + +struct __packed hw_fw_request_ptp_adj_clock { + u32 ns; + u32 sec; + int sign; +}; + +#define HW_AQ_FW_REQUEST_PTP_GPIO_CTRL 0x11 +#define HW_AQ_FW_REQUEST_PTP_ADJ_FREQ 0x12 +#define HW_AQ_FW_REQUEST_PTP_ADJ_CLOCK 0x13 + +struct __packed hw_fw_request_iface { + u32 msg_id; + union { + /* PTP FW Request */ + struct hw_fw_request_ptp_gpio_ctrl ptp_gpio_ctrl; + struct hw_fw_request_ptp_adj_freq ptp_adj_freq; + struct hw_fw_request_ptp_adj_clock ptp_adj_clock; + }; +}; + +struct __packed hw_atl_utils_settings { + u32 mtu; + u32 downshift_retry_count; + u32 link_pause_frame_quanta_100m; + u32 link_pause_frame_threshold_100m; + u32 link_pause_frame_quanta_1g; + u32 link_pause_frame_threshold_1g; + u32 link_pause_frame_quanta_2p5g; + u32 link_pause_frame_threshold_2p5g; + u32 link_pause_frame_quanta_5g; + u32 link_pause_frame_threshold_5g; + u32 link_pause_frame_quanta_10g; + u32 link_pause_frame_threshold_10g; + u32 pfc_quanta_class_0; + u32 pfc_threshold_class_0; + u32 pfc_quanta_class_1; + u32 pfc_threshold_class_1; + u32 pfc_quanta_class_2; + u32 pfc_threshold_class_2; + u32 pfc_quanta_class_3; + u32 pfc_threshold_class_3; + u32 pfc_quanta_class_4; + u32 pfc_threshold_class_4; + u32 pfc_quanta_class_5; + u32 pfc_threshold_class_5; + u32 pfc_quanta_class_6; + u32 pfc_threshold_class_6; + u32 pfc_quanta_class_7; + u32 pfc_threshold_class_7; + u32 eee_link_down_timeout; + u32 eee_link_up_timeout; + u32 eee_max_link_drops; + u32 eee_rates_mask; + u32 wake_timer; + u32 thermal_shutdown_off_temp; + u32 thermal_shutdown_warning_temp; + u32 thermal_shutdown_cold_temp; + u32 msm_options; + u32 dac_cable_serdes_modes; + u32 media_detect; +}; + enum hw_atl_rx_action_with_traffic { HW_ATL_RX_DISCARD, HW_ATL_RX_HOST, + HW_ATL_RX_MNGMNT, + HW_ATL_RX_HOST_AND_MNGMNT, + HW_ATL_RX_WOL }; struct aq_rx_filter_vlan { @@ -321,20 +406,12 @@ enum hal_atl_utils_fw_state_e { #define HAL_ATLANTIC_RATE_100M BIT(5) #define HAL_ATLANTIC_RATE_INVALID BIT(6) -#define HAL_ATLANTIC_UTILS_FW_MSG_PING 0x1U -#define HAL_ATLANTIC_UTILS_FW_MSG_ARP 0x2U -#define HAL_ATLANTIC_UTILS_FW_MSG_INJECT 0x3U #define HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD 0x4U #define HAL_ATLANTIC_UTILS_FW_MSG_WOL_PRIOR 0x10000000U #define HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN 0x1U #define HAL_ATLANTIC_UTILS_FW_MSG_WOL_MAG_PKT 0x2U #define HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL 0x5U #define HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP 0x6U -#define HAL_ATLANTIC_UTILS_FW_MSG_MSM_PFC 0x7U -#define HAL_ATLANTIC_UTILS_FW_MSG_PROVISIONING 0x8U -#define HAL_ATLANTIC_UTILS_FW_MSG_OFFLOAD_ADD 0x9U -#define HAL_ATLANTIC_UTILS_FW_MSG_OFFLOAD_DEL 0xAU -#define HAL_ATLANTIC_UTILS_FW_MSG_CABLE_DIAG 0xDU enum hw_atl_fw2x_rate { FW2X_RATE_100M = 0x20, @@ -344,91 +421,135 @@ enum hw_atl_fw2x_rate { FW2X_RATE_10G = 0x800, }; +/* 0x370 + * Link capabilities resolution register + */ enum hw_atl_fw2x_caps_lo { - CAPS_LO_10BASET_HD = 0x00, + CAPS_LO_10BASET_HD = 0, CAPS_LO_10BASET_FD, CAPS_LO_100BASETX_HD, CAPS_LO_100BASET4_HD, CAPS_LO_100BASET2_HD, - CAPS_LO_100BASETX_FD, + CAPS_LO_100BASETX_FD = 5, CAPS_LO_100BASET2_FD, CAPS_LO_1000BASET_HD, CAPS_LO_1000BASET_FD, CAPS_LO_2P5GBASET_FD, - CAPS_LO_5GBASET_FD, + CAPS_LO_5GBASET_FD = 10, CAPS_LO_10GBASET_FD, }; +/* 0x374 + * Status register + */ enum hw_atl_fw2x_caps_hi { - CAPS_HI_RESERVED1 = 0x00, + CAPS_HI_RESERVED1 = 0, CAPS_HI_10BASET_EEE, CAPS_HI_RESERVED2, CAPS_HI_PAUSE, CAPS_HI_ASYMMETRIC_PAUSE, - CAPS_HI_100BASETX_EEE, + CAPS_HI_100BASETX_EEE = 5, CAPS_HI_RESERVED3, CAPS_HI_RESERVED4, CAPS_HI_1000BASET_FD_EEE, CAPS_HI_2P5GBASET_FD_EEE, - CAPS_HI_5GBASET_FD_EEE, + CAPS_HI_5GBASET_FD_EEE = 10, CAPS_HI_10GBASET_FD_EEE, - CAPS_HI_RESERVED5, + CAPS_HI_FW_REQUEST, CAPS_HI_RESERVED6, CAPS_HI_RESERVED7, - CAPS_HI_RESERVED8, + CAPS_HI_RESERVED8 = 15, CAPS_HI_RESERVED9, CAPS_HI_CABLE_DIAG, CAPS_HI_TEMPERATURE, CAPS_HI_DOWNSHIFT, - CAPS_HI_PTP_AVB_EN, + CAPS_HI_PTP_AVB_EN_FW2X = 20, CAPS_HI_MEDIA_DETECT, CAPS_HI_LINK_DROP, CAPS_HI_SLEEP_PROXY, CAPS_HI_WOL, - CAPS_HI_MAC_STOP, + CAPS_HI_MAC_STOP = 25, CAPS_HI_EXT_LOOPBACK, CAPS_HI_INT_LOOPBACK, CAPS_HI_EFUSE_AGENT, CAPS_HI_WOL_TIMER, - CAPS_HI_STATISTICS, + CAPS_HI_STATISTICS = 30, CAPS_HI_TRANSACTION_ID, }; +/* 0x36C + * Control register + */ enum hw_atl_fw2x_ctrl { - CTRL_RESERVED1 = 0x00, + CTRL_RESERVED1 = 0, CTRL_RESERVED2, CTRL_RESERVED3, CTRL_PAUSE, CTRL_ASYMMETRIC_PAUSE, - CTRL_RESERVED4, + CTRL_RESERVED4 = 5, CTRL_RESERVED5, CTRL_RESERVED6, CTRL_1GBASET_FD_EEE, CTRL_2P5GBASET_FD_EEE, - CTRL_5GBASET_FD_EEE, + CTRL_5GBASET_FD_EEE = 10, CTRL_10GBASET_FD_EEE, CTRL_THERMAL_SHUTDOWN, CTRL_PHY_LOGS, CTRL_EEE_AUTO_DISABLE, - CTRL_PFC, + CTRL_PFC = 15, CTRL_WAKE_ON_LINK, CTRL_CABLE_DIAG, CTRL_TEMPERATURE, CTRL_DOWNSHIFT, - CTRL_PTP_AVB, + CTRL_PTP_AVB = 20, CTRL_RESERVED7, CTRL_LINK_DROP, CTRL_SLEEP_PROXY, CTRL_WOL, - CTRL_MAC_STOP, + CTRL_MAC_STOP = 25, CTRL_EXT_LOOPBACK, CTRL_INT_LOOPBACK, CTRL_RESERVED8, CTRL_WOL_TIMER, - CTRL_STATISTICS, + CTRL_STATISTICS = 30, CTRL_FORCE_RECONNECT, }; +enum hw_atl_caps_ex { + CAPS_EX_LED_CONTROL = 0, + CAPS_EX_LED0_MODE_LO, + CAPS_EX_LED0_MODE_HI, + CAPS_EX_LED1_MODE_LO, + CAPS_EX_LED1_MODE_HI, + CAPS_EX_LED2_MODE_LO = 5, + CAPS_EX_LED2_MODE_HI, + CAPS_EX_RESERVED07, + CAPS_EX_RESERVED08, + CAPS_EX_RESERVED09, + CAPS_EX_RESERVED10 = 10, + CAPS_EX_RESERVED11, + CAPS_EX_RESERVED12, + CAPS_EX_RESERVED13, + CAPS_EX_RESERVED14, + CAPS_EX_RESERVED15 = 15, + CAPS_EX_PHY_PTP_EN, + CAPS_EX_MAC_PTP_EN, + CAPS_EX_EXT_CLK_EN, + CAPS_EX_SCHED_DMA_EN, + CAPS_EX_PTP_GPIO_EN = 20, + CAPS_EX_UPDATE_SETTINGS, + CAPS_EX_PHY_CTRL_TS_PIN, + CAPS_EX_SNR_OPERATING_MARGIN, + CAPS_EX_RESERVED24, + CAPS_EX_RESERVED25 = 25, + CAPS_EX_RESERVED26, + CAPS_EX_RESERVED27, + CAPS_EX_RESERVED28, + CAPS_EX_RESERVED29, + CAPS_EX_RESERVED30 = 30, + CAPS_EX_RESERVED31 +}; + struct aq_hw_s; struct aq_fw_ops; struct aq_hw_caps_s; @@ -475,6 +596,11 @@ struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self); int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt); +int hw_atl_write_fwcfg_dwords(struct aq_hw_s *self, u32 *p, u32 cnt); + +int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p, + u32 cnt); + int hw_atl_utils_fw_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac); int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size); diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c index 7bc51f8d6f2f..97ebf849695f 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * aQuantia Corporation Network Driver - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved + * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved */ /* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for @@ -17,26 +17,34 @@ #include "hw_atl_utils.h" #include "hw_atl_llh.h" -#define HW_ATL_FW2X_MPI_RPC_ADDR 0x334 +#define HW_ATL_FW2X_MPI_LED_ADDR 0x31c +#define HW_ATL_FW2X_MPI_RPC_ADDR 0x334 -#define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360 -#define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364 -#define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368 -#define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C -#define HW_ATL_FW2X_MPI_STATE_ADDR 0x370 -#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374 +#define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360 +#define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364 +#define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368 +#define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C +#define HW_ATL_FW2X_MPI_STATE_ADDR 0x370 +#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374 + +#define HW_ATL_FW3X_EXT_CONTROL_ADDR 0x378 +#define HW_ATL_FW3X_EXT_STATE_ADDR 0x37c #define HW_ATL_FW2X_CAP_PAUSE BIT(CAPS_HI_PAUSE) #define HW_ATL_FW2X_CAP_ASYM_PAUSE BIT(CAPS_HI_ASYMMETRIC_PAUSE) #define HW_ATL_FW2X_CAP_SLEEP_PROXY BIT(CAPS_HI_SLEEP_PROXY) #define HW_ATL_FW2X_CAP_WOL BIT(CAPS_HI_WOL) +#define HW_ATL_FW2X_CTRL_WAKE_ON_LINK BIT(CTRL_WAKE_ON_LINK) #define HW_ATL_FW2X_CTRL_SLEEP_PROXY BIT(CTRL_SLEEP_PROXY) #define HW_ATL_FW2X_CTRL_WOL BIT(CTRL_WOL) #define HW_ATL_FW2X_CTRL_LINK_DROP BIT(CTRL_LINK_DROP) #define HW_ATL_FW2X_CTRL_PAUSE BIT(CTRL_PAUSE) #define HW_ATL_FW2X_CTRL_TEMPERATURE BIT(CTRL_TEMPERATURE) #define HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE BIT(CTRL_ASYMMETRIC_PAUSE) +#define HW_ATL_FW2X_CTRL_INT_LOOPBACK BIT(CTRL_INT_LOOPBACK) +#define HW_ATL_FW2X_CTRL_EXT_LOOPBACK BIT(CTRL_EXT_LOOPBACK) +#define HW_ATL_FW2X_CTRL_DOWNSHIFT BIT(CTRL_DOWNSHIFT) #define HW_ATL_FW2X_CTRL_FORCE_RECONNECT BIT(CTRL_FORCE_RECONNECT) #define HW_ATL_FW2X_CAP_EEE_1G_MASK BIT(CAPS_HI_1000BASET_FD_EEE) @@ -47,6 +55,9 @@ #define HAL_ATLANTIC_WOL_FILTERS_COUNT 8 #define HAL_ATLANTIC_UTILS_FW2X_MSG_WOL 0x0E +#define HW_ATL_FW_VER_LED 0x03010026U +#define HW_ATL_FW_VER_MEDIA_CONTROL 0x0301005aU + struct __packed fw2x_msg_wol_pattern { u8 mask[16]; u32 crc; @@ -71,6 +82,7 @@ static int aq_fw2x_set_state(struct aq_hw_s *self, static u32 aq_fw2x_mbox_get(struct aq_hw_s *self); static u32 aq_fw2x_rpc_get(struct aq_hw_s *self); +static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr); static u32 aq_fw2x_state2_get(struct aq_hw_s *self); static int aq_fw2x_init(struct aq_hw_s *self) @@ -88,6 +100,8 @@ static int aq_fw2x_init(struct aq_hw_s *self) self->rpc_addr != 0U, 1000U, 100000U); + err = aq_fw2x_settings_get(self, &self->settings_addr); + return err; } @@ -167,17 +181,26 @@ static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed) return 0; } -static void aq_fw2x_set_mpi_flow_control(struct aq_hw_s *self, u32 *mpi_state) +static void aq_fw2x_upd_flow_control_bits(struct aq_hw_s *self, + u32 *mpi_state, u32 fc) { - if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_RX) - *mpi_state |= BIT(CAPS_HI_PAUSE); - else - *mpi_state &= ~BIT(CAPS_HI_PAUSE); + *mpi_state &= ~(HW_ATL_FW2X_CTRL_PAUSE | + HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE); - if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_TX) - *mpi_state |= BIT(CAPS_HI_ASYMMETRIC_PAUSE); - else - *mpi_state &= ~BIT(CAPS_HI_ASYMMETRIC_PAUSE); + switch (fc) { + /* There is not explicit mode of RX only pause frames, + * thus, we join this mode with FC full. + * FC full is either Rx, either Tx, or both. + */ + case AQ_NIC_FC_FULL: + case AQ_NIC_FC_RX: + *mpi_state |= HW_ATL_FW2X_CTRL_PAUSE | + HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE; + break; + case AQ_NIC_FC_TX: + *mpi_state |= HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE; + break; + } } static void aq_fw2x_upd_eee_rate_bits(struct aq_hw_s *self, u32 *mpi_opts, @@ -201,7 +224,8 @@ static int aq_fw2x_set_state(struct aq_hw_s *self, case MPI_INIT: mpi_state &= ~BIT(CAPS_HI_LINK_DROP); aq_fw2x_upd_eee_rate_bits(self, &mpi_state, cfg->eee_speeds); - aq_fw2x_set_mpi_flow_control(self, &mpi_state); + aq_fw2x_upd_flow_control_bits(self, &mpi_state, + self->aq_nic_cfg->fc.req); break; case MPI_DEINIT: mpi_state |= BIT(CAPS_HI_LINK_DROP); @@ -212,15 +236,20 @@ static int aq_fw2x_set_state(struct aq_hw_s *self, break; } aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state); + return 0; } static int aq_fw2x_update_link_status(struct aq_hw_s *self) { - u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR); - u32 speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G | - FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G); struct aq_hw_link_status_s *link_status = &self->aq_link_status; + u32 mpi_state; + u32 speed; + + mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR); + speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G | + FW2X_RATE_2G5 | FW2X_RATE_5G | + FW2X_RATE_10G); if (speed) { if (speed & FW2X_RATE_10G) @@ -244,11 +273,11 @@ static int aq_fw2x_update_link_status(struct aq_hw_s *self) static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) { + u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR); + u32 mac_addr[2] = { 0 }; int err = 0; u32 h = 0U; u32 l = 0U; - u32 mac_addr[2] = { 0 }; - u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR); if (efuse_addr != 0) { err = hw_atl_utils_fw_downld_dwords(self, @@ -282,15 +311,16 @@ static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) h >>= 8; mac[0] = (u8)(0xFFU & h); } + return err; } static int aq_fw2x_update_stats(struct aq_hw_s *self) { - int err = 0; u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS); u32 stats_val; + int err = 0; /* Toggle statistics bit for FW to update */ mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS); @@ -317,9 +347,9 @@ static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp) int err = 0; u32 val; - phy_temp_offset = self->mbox_addr + - offsetof(struct hw_atl_utils_mbox, info) + - offsetof(struct hw_aq_info, phy_temperature); + phy_temp_offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox, + info.phy_temperature); + /* Toggle statistics bit for FW to 0x36C.18 (CTRL_TEMPERATURE) */ mpi_opts = mpi_opts ^ HW_ATL_FW2X_CTRL_TEMPERATURE; aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); @@ -342,106 +372,117 @@ static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp) return 0; } -static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac) +static int aq_fw2x_set_wol(struct aq_hw_s *self, u8 *mac) { struct hw_atl_utils_fw_rpc *rpc = NULL; - struct offload_info *cfg = NULL; - unsigned int rpc_size = 0U; - u32 mpi_opts; + struct offload_info *info = NULL; + u32 wol_bits = 0; + u32 rpc_size; int err = 0; u32 val; - rpc_size = sizeof(rpc->msg_id) + sizeof(*cfg); - - err = hw_atl_utils_fw_rpc_wait(self, &rpc); - if (err < 0) - goto err_exit; - - memset(rpc, 0, rpc_size); - cfg = (struct offload_info *)(&rpc->msg_id + 1); + if (self->aq_nic_cfg->wol & WAKE_PHY) { + aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, + HW_ATL_FW2X_CTRL_LINK_DROP); + readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val, + (val & + HW_ATL_FW2X_CTRL_LINK_DROP) != 0, + 1000, 100000); + wol_bits |= HW_ATL_FW2X_CTRL_WAKE_ON_LINK; + } - memcpy(cfg->mac_addr, mac, ETH_ALEN); - cfg->len = sizeof(*cfg); + if (self->aq_nic_cfg->wol & WAKE_MAGIC) { + wol_bits |= HW_ATL_FW2X_CTRL_SLEEP_PROXY | + HW_ATL_FW2X_CTRL_WOL; - /* Clear bit 0x36C.23 and 0x36C.22 */ - mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); - mpi_opts &= ~HW_ATL_FW2X_CTRL_SLEEP_PROXY; - mpi_opts &= ~HW_ATL_FW2X_CTRL_LINK_DROP; + err = hw_atl_utils_fw_rpc_wait(self, &rpc); + if (err < 0) + goto err_exit; - aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); + rpc_size = sizeof(*info) + + offsetof(struct hw_atl_utils_fw_rpc, fw2x_offloads); + memset(rpc, 0, rpc_size); + info = &rpc->fw2x_offloads; + memcpy(info->mac_addr, mac, ETH_ALEN); + info->len = sizeof(*info); - err = hw_atl_utils_fw_rpc_call(self, rpc_size); - if (err < 0) - goto err_exit; + err = hw_atl_utils_fw_rpc_call(self, rpc_size); + if (err < 0) + goto err_exit; + } - /* Set bit 0x36C.23 */ - mpi_opts |= HW_ATL_FW2X_CTRL_SLEEP_PROXY; - aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); - - err = readx_poll_timeout_atomic(aq_fw2x_state2_get, - self, val, - val & HW_ATL_FW2X_CTRL_SLEEP_PROXY, - 1U, 100000U); + aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, wol_bits); err_exit: return err; } -static int aq_fw2x_set_wol_params(struct aq_hw_s *self, u8 *mac) +static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state, + u8 *mac) { - struct hw_atl_utils_fw_rpc *rpc = NULL; - struct fw2x_msg_wol *msg = NULL; - u32 mpi_opts; int err = 0; - u32 val; - - err = hw_atl_utils_fw_rpc_wait(self, &rpc); - if (err < 0) - goto err_exit; - - msg = (struct fw2x_msg_wol *)rpc; - - memset(msg, 0, sizeof(*msg)); - msg->msg_id = HAL_ATLANTIC_UTILS_FW2X_MSG_WOL; - msg->magic_packet_enabled = true; - memcpy(msg->hw_addr, mac, ETH_ALEN); + if (self->aq_nic_cfg->wol) + err = aq_fw2x_set_wol(self, mac); - mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); - mpi_opts &= ~(HW_ATL_FW2X_CTRL_SLEEP_PROXY | HW_ATL_FW2X_CTRL_WOL); + return err; +} - aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); +static int aq_fw2x_send_fw_request(struct aq_hw_s *self, + const struct hw_fw_request_iface *fw_req, + size_t size) +{ + u32 ctrl2, orig_ctrl2; + u32 dword_cnt; + int err = 0; + u32 val; - err = hw_atl_utils_fw_rpc_call(self, sizeof(*msg)); + /* Write data to drvIface Mailbox */ + dword_cnt = size / sizeof(u32); + if (size % sizeof(u32)) + dword_cnt++; + err = hw_atl_write_fwcfg_dwords(self, (void *)fw_req, dword_cnt); if (err < 0) goto err_exit; - /* Set bit 0x36C.24 */ - mpi_opts |= HW_ATL_FW2X_CTRL_WOL; - aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); + /* Toggle statistics bit for FW to update */ + ctrl2 = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); + orig_ctrl2 = ctrl2 & BIT(CAPS_HI_FW_REQUEST); + ctrl2 = ctrl2 ^ BIT(CAPS_HI_FW_REQUEST); + aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, ctrl2); - err = readx_poll_timeout_atomic(aq_fw2x_state2_get, - self, val, val & HW_ATL_FW2X_CTRL_WOL, + /* Wait FW to report back */ + err = readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val, + orig_ctrl2 != (val & + BIT(CAPS_HI_FW_REQUEST)), 1U, 10000U); err_exit: return err; } -static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state, - u8 *mac) +static void aq_fw3x_enable_ptp(struct aq_hw_s *self, int enable) { - int err = 0; + u32 ptp_opts = aq_hw_read_reg(self, HW_ATL_FW3X_EXT_STATE_ADDR); + u32 all_ptp_features = BIT(CAPS_EX_PHY_PTP_EN) | + BIT(CAPS_EX_PTP_GPIO_EN); - if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) { - err = aq_fw2x_set_sleep_proxy(self, mac); - if (err < 0) - goto err_exit; - err = aq_fw2x_set_wol_params(self, mac); - } + if (enable) + ptp_opts |= all_ptp_features; + else + ptp_opts &= ~all_ptp_features; -err_exit: - return err; + aq_hw_write_reg(self, HW_ATL_FW3X_EXT_CONTROL_ADDR, ptp_opts); +} + +static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode) +{ + if (self->fw_ver_actual < HW_ATL_FW_VER_LED) + return -EOPNOTSUPP; + + aq_hw_write_reg(self, HW_ATL_FW2X_MPI_LED_ADDR, mode); + + return 0; } static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed) @@ -461,11 +502,12 @@ static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate, u32 mpi_state; u32 caps_hi; int err = 0; - u32 addr = self->mbox_addr + offsetof(struct hw_atl_utils_mbox, info) + - offsetof(struct hw_aq_info, caps_hi); + u32 offset; + + offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox, + info.caps_hi); - err = hw_atl_utils_fw_downld_dwords(self, addr, &caps_hi, - sizeof(caps_hi) / sizeof(u32)); + err = hw_atl_utils_fw_downld_dwords(self, offset, &caps_hi, 1); if (err) return err; @@ -493,7 +535,8 @@ static int aq_fw2x_set_flow_control(struct aq_hw_s *self) { u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); - aq_fw2x_set_mpi_flow_control(self, &mpi_state); + aq_fw2x_upd_flow_control_bits(self, &mpi_state, + self->aq_nic_cfg->fc.req); aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state); @@ -503,17 +546,41 @@ static int aq_fw2x_set_flow_control(struct aq_hw_s *self) static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode) { u32 mpi_state = aq_fw2x_state2_get(self); + *fcmode = 0; if (mpi_state & HW_ATL_FW2X_CAP_PAUSE) - if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE) - *fcmode = AQ_NIC_FC_RX; + *fcmode |= AQ_NIC_FC_RX; + + if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE) + *fcmode |= AQ_NIC_FC_TX; + + return 0; +} + +static int aq_fw2x_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable) +{ + u32 mpi_opts; + + switch (mode) { + case AQ_HW_LOOPBACK_PHYINT_SYS: + mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); + if (enable) + mpi_opts |= HW_ATL_FW2X_CTRL_INT_LOOPBACK; else - *fcmode = AQ_NIC_FC_RX | AQ_NIC_FC_TX; - else - if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE) - *fcmode = AQ_NIC_FC_TX; + mpi_opts &= ~HW_ATL_FW2X_CTRL_INT_LOOPBACK; + aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); + break; + case AQ_HW_LOOPBACK_PHYEXT_SYS: + mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); + if (enable) + mpi_opts |= HW_ATL_FW2X_CTRL_EXT_LOOPBACK; else - *fcmode = 0; + mpi_opts &= ~HW_ATL_FW2X_CTRL_EXT_LOOPBACK; + aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); + break; + default: + return -EINVAL; + } return 0; } @@ -528,25 +595,42 @@ static u32 aq_fw2x_rpc_get(struct aq_hw_s *self) return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR); } +static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr) +{ + int err = 0; + u32 offset; + + offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox, + info.setting_address); + + err = hw_atl_utils_fw_downld_dwords(self, offset, addr, 1); + + return err; +} + static u32 aq_fw2x_state2_get(struct aq_hw_s *self) { return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR); } const struct aq_fw_ops aq_fw_2x_ops = { - .init = aq_fw2x_init, - .deinit = aq_fw2x_deinit, - .reset = NULL, - .renegotiate = aq_fw2x_renegotiate, - .get_mac_permanent = aq_fw2x_get_mac_permanent, - .set_link_speed = aq_fw2x_set_link_speed, - .set_state = aq_fw2x_set_state, + .init = aq_fw2x_init, + .deinit = aq_fw2x_deinit, + .reset = NULL, + .renegotiate = aq_fw2x_renegotiate, + .get_mac_permanent = aq_fw2x_get_mac_permanent, + .set_link_speed = aq_fw2x_set_link_speed, + .set_state = aq_fw2x_set_state, .update_link_status = aq_fw2x_update_link_status, - .update_stats = aq_fw2x_update_stats, - .get_phy_temp = aq_fw2x_get_phy_temp, - .set_power = aq_fw2x_set_power, - .set_eee_rate = aq_fw2x_set_eee_rate, - .get_eee_rate = aq_fw2x_get_eee_rate, - .set_flow_control = aq_fw2x_set_flow_control, - .get_flow_control = aq_fw2x_get_flow_control + .update_stats = aq_fw2x_update_stats, + .get_phy_temp = aq_fw2x_get_phy_temp, + .set_power = aq_fw2x_set_power, + .set_eee_rate = aq_fw2x_set_eee_rate, + .get_eee_rate = aq_fw2x_get_eee_rate, + .set_flow_control = aq_fw2x_set_flow_control, + .get_flow_control = aq_fw2x_get_flow_control, + .send_fw_request = aq_fw2x_send_fw_request, + .enable_ptp = aq_fw3x_enable_ptp, + .led_control = aq_fw2x_led_control, + .set_phyloopback = aq_fw2x_set_phyloopback, }; |