Commit fb8d1d7e authored by David S. Miller's avatar David S. Miller

Merge branch 'net-aquantia-PTP-support-for-AQC-devices'

Igor Russkikh says:

====================
net: aquantia: PTP support for AQC devices

This patchset introduces PTP feature support in Aquantia AQC atlantic driver.

This implementation is a joined effort of aquantia developers:
Egor is the main designer and driver/firmware architect on PTP,
Sergey and Dmitry are included as co-developers.
Dmitry also helped me in the overall patchset preparations.

Feature was verified on AQC hardware with testptp tool, linuxptp,
gptp and with Motu hardware unit.

version3 updates:
- Review comments applied: error handling, various fixes

version2 updates:
- Fixing issues from Andrew's review: replacing self with
  ptp var name, making ptp_clk_offset a field in the ptp instance.
  devm_kzalloc advice is actually non applicable, because ptp object gets
  created/destroyed on each network device close/open and it should not be
  linked with dev lifecycle.
- Rearranging commit authorship, adding Egor as a ptp module main maintainer
- Fixing kbuild 32bit division issues
====================
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 337d866a 4ef511bc
...@@ -1190,6 +1190,13 @@ Q: http://patchwork.ozlabs.org/project/netdev/list/ ...@@ -1190,6 +1190,13 @@ Q: http://patchwork.ozlabs.org/project/netdev/list/
F: drivers/net/ethernet/aquantia/atlantic/ F: drivers/net/ethernet/aquantia/atlantic/
F: Documentation/networking/device_drivers/aquantia/atlantic.txt F: Documentation/networking/device_drivers/aquantia/atlantic.txt
AQUANTIA ETHERNET DRIVER PTP SUBSYSTEM
M: Egor Pomozov <epomozov@marvell.com>
L: netdev@vger.kernel.org
S: Supported
W: http://www.aquantia.com
F: drivers/net/ethernet/aquantia/atlantic/aq_ptp*
ARC FRAMEBUFFER DRIVER ARC FRAMEBUFFER DRIVER
M: Jaya Kumar <jayalk@intworks.biz> M: Jaya Kumar <jayalk@intworks.biz>
S: Maintained S: Maintained
......
...@@ -24,6 +24,8 @@ atlantic-objs := aq_main.o \ ...@@ -24,6 +24,8 @@ atlantic-objs := aq_main.o \
aq_ethtool.o \ aq_ethtool.o \
aq_drvinfo.o \ aq_drvinfo.o \
aq_filters.o \ aq_filters.o \
aq_ptp.o \
aq_phy.o \
hw_atl/hw_atl_a0.o \ hw_atl/hw_atl_a0.o \
hw_atl/hw_atl_b0.o \ hw_atl/hw_atl_b0.o \
hw_atl/hw_atl_utils.o \ hw_atl/hw_atl_utils.o \
......
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* aQuantia Corporation Network Driver * aQuantia Corporation Network Driver
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
*/ */
/* File aq_cfg.h: Definition of configuration parameters and constants. */ /* File aq_cfg.h: Definition of configuration parameters and constants. */
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#define AQ_CFG_INTERRUPT_MODERATION_USEC_MAX (0x1FF * 2) #define AQ_CFG_INTERRUPT_MODERATION_USEC_MAX (0x1FF * 2)
#define AQ_CFG_IRQ_MASK 0x1FFU #define AQ_CFG_IRQ_MASK 0x3FFU
#define AQ_CFG_VECS_MAX 8U #define AQ_CFG_VECS_MAX 8U
#define AQ_CFG_TCS_MAX 8U #define AQ_CFG_TCS_MAX 8U
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* aQuantia Corporation Network Driver * aQuantia Corporation Network Driver
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
*/ */
/* File aq_ethtool.c: Definition of ethertool related functions. */ /* File aq_ethtool.c: Definition of ethertool related functions. */
...@@ -9,8 +9,11 @@ ...@@ -9,8 +9,11 @@
#include "aq_ethtool.h" #include "aq_ethtool.h"
#include "aq_nic.h" #include "aq_nic.h"
#include "aq_vec.h" #include "aq_vec.h"
#include "aq_ptp.h"
#include "aq_filters.h" #include "aq_filters.h"
#include <linux/ptp_clock_kernel.h>
static void aq_ethtool_get_regs(struct net_device *ndev, static void aq_ethtool_get_regs(struct net_device *ndev,
struct ethtool_regs *regs, void *p) struct ethtool_regs *regs, void *p)
{ {
...@@ -377,6 +380,35 @@ static int aq_ethtool_set_wol(struct net_device *ndev, ...@@ -377,6 +380,35 @@ static int aq_ethtool_set_wol(struct net_device *ndev,
return err; return err;
} }
static int aq_ethtool_get_ts_info(struct net_device *ndev,
struct ethtool_ts_info *info)
{
struct aq_nic_s *aq_nic = netdev_priv(ndev);
ethtool_op_get_ts_info(ndev, info);
if (!aq_nic->aq_ptp)
return 0;
info->so_timestamping |=
SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
info->tx_types = BIT(HWTSTAMP_TX_OFF) |
BIT(HWTSTAMP_TX_ON);
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp));
return 0;
}
static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed) static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed)
{ {
u32 rate = 0; u32 rate = 0;
...@@ -604,4 +636,5 @@ const struct ethtool_ops aq_ethtool_ops = { ...@@ -604,4 +636,5 @@ const struct ethtool_ops aq_ethtool_ops = {
.set_link_ksettings = aq_ethtool_set_link_ksettings, .set_link_ksettings = aq_ethtool_set_link_ksettings,
.get_coalesce = aq_ethtool_get_coalesce, .get_coalesce = aq_ethtool_get_coalesce,
.set_coalesce = aq_ethtool_set_coalesce, .set_coalesce = aq_ethtool_set_coalesce,
.get_ts_info = aq_ethtool_get_ts_info,
}; };
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2014-2017 aQuantia Corporation. */ /* Copyright (C) 2014-2019 aQuantia Corporation. */
/* File aq_filters.c: RX filters related functions. */ /* File aq_filters.c: RX filters related functions. */
...@@ -89,12 +89,14 @@ static int aq_check_approve_fl3l4(struct aq_nic_s *aq_nic, ...@@ -89,12 +89,14 @@ static int aq_check_approve_fl3l4(struct aq_nic_s *aq_nic,
struct aq_hw_rx_fltrs_s *rx_fltrs, struct aq_hw_rx_fltrs_s *rx_fltrs,
struct ethtool_rx_flow_spec *fsp) struct ethtool_rx_flow_spec *fsp)
{ {
u32 last_location = AQ_RX_LAST_LOC_FL3L4 -
aq_nic->aq_hw_rx_fltrs.fl3l4.reserved_count;
if (fsp->location < AQ_RX_FIRST_LOC_FL3L4 || if (fsp->location < AQ_RX_FIRST_LOC_FL3L4 ||
fsp->location > AQ_RX_LAST_LOC_FL3L4) { fsp->location > last_location) {
netdev_err(aq_nic->ndev, netdev_err(aq_nic->ndev,
"ethtool: location must be in range [%d, %d]", "ethtool: location must be in range [%d, %d]",
AQ_RX_FIRST_LOC_FL3L4, AQ_RX_FIRST_LOC_FL3L4, last_location);
AQ_RX_LAST_LOC_FL3L4);
return -EINVAL; return -EINVAL;
} }
if (rx_fltrs->fl3l4.is_ipv6 && rx_fltrs->fl3l4.active_ipv4) { if (rx_fltrs->fl3l4.is_ipv6 && rx_fltrs->fl3l4.active_ipv4) {
...@@ -124,12 +126,15 @@ aq_check_approve_fl2(struct aq_nic_s *aq_nic, ...@@ -124,12 +126,15 @@ aq_check_approve_fl2(struct aq_nic_s *aq_nic,
struct aq_hw_rx_fltrs_s *rx_fltrs, struct aq_hw_rx_fltrs_s *rx_fltrs,
struct ethtool_rx_flow_spec *fsp) struct ethtool_rx_flow_spec *fsp)
{ {
u32 last_location = AQ_RX_LAST_LOC_FETHERT -
aq_nic->aq_hw_rx_fltrs.fet_reserved_count;
if (fsp->location < AQ_RX_FIRST_LOC_FETHERT || if (fsp->location < AQ_RX_FIRST_LOC_FETHERT ||
fsp->location > AQ_RX_LAST_LOC_FETHERT) { fsp->location > last_location) {
netdev_err(aq_nic->ndev, netdev_err(aq_nic->ndev,
"ethtool: location must be in range [%d, %d]", "ethtool: location must be in range [%d, %d]",
AQ_RX_FIRST_LOC_FETHERT, AQ_RX_FIRST_LOC_FETHERT,
AQ_RX_LAST_LOC_FETHERT); last_location);
return -EINVAL; return -EINVAL;
} }
......
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* aQuantia Corporation Network Driver * aQuantia Corporation Network Driver
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
*/ */
/* File aq_hw.h: Declaration of abstract interface for NIC hardware specific /* File aq_hw.h: Declaration of abstract interface for NIC hardware specific
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
#include "aq_rss.h" #include "aq_rss.h"
#include "hw_atl/hw_atl_utils.h" #include "hw_atl/hw_atl_utils.h"
#define AQ_HW_MAC_COUNTER_HZ 312500000ll
#define AQ_HW_PHY_COUNTER_HZ 160000000ll
#define AQ_RX_FIRST_LOC_FVLANID 0U #define AQ_RX_FIRST_LOC_FVLANID 0U
#define AQ_RX_LAST_LOC_FVLANID 15U #define AQ_RX_LAST_LOC_FVLANID 15U
#define AQ_RX_FIRST_LOC_FETHERT 16U #define AQ_RX_FIRST_LOC_FETHERT 16U
...@@ -94,6 +97,7 @@ struct aq_stats_s { ...@@ -94,6 +97,7 @@ struct aq_stats_s {
#define AQ_HW_FLAG_STOPPING 0x00000008U #define AQ_HW_FLAG_STOPPING 0x00000008U
#define AQ_HW_FLAG_RESETTING 0x00000010U #define AQ_HW_FLAG_RESETTING 0x00000010U
#define AQ_HW_FLAG_CLOSING 0x00000020U #define AQ_HW_FLAG_CLOSING 0x00000020U
#define AQ_HW_PTP_AVAILABLE 0x01000000U
#define AQ_HW_LINK_DOWN 0x04000000U #define AQ_HW_LINK_DOWN 0x04000000U
#define AQ_HW_FLAG_ERR_UNPLUG 0x40000000U #define AQ_HW_FLAG_ERR_UNPLUG 0x40000000U
#define AQ_HW_FLAG_ERR_HW 0x80000000U #define AQ_HW_FLAG_ERR_HW 0x80000000U
...@@ -135,6 +139,8 @@ struct aq_hw_s { ...@@ -135,6 +139,8 @@ struct aq_hw_s {
u32 rpc_addr; u32 rpc_addr;
u32 rpc_tid; u32 rpc_tid;
struct hw_atl_utils_fw_rpc rpc; struct hw_atl_utils_fw_rpc rpc;
s64 ptp_clk_offset;
u16 phy_id;
}; };
struct aq_ring_s; struct aq_ring_s;
...@@ -235,6 +241,40 @@ struct aq_hw_ops { ...@@ -235,6 +241,40 @@ struct aq_hw_ops {
int (*hw_set_offload)(struct aq_hw_s *self, int (*hw_set_offload)(struct aq_hw_s *self,
struct aq_nic_cfg_s *aq_nic_cfg); struct aq_nic_cfg_s *aq_nic_cfg);
int (*hw_tx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode);
int (*hw_rx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode);
int (*hw_ring_hwts_rx_fill)(struct aq_hw_s *self,
struct aq_ring_s *aq_ring);
int (*hw_ring_hwts_rx_receive)(struct aq_hw_s *self,
struct aq_ring_s *ring);
void (*hw_get_ptp_ts)(struct aq_hw_s *self, u64 *stamp);
int (*hw_adj_clock_freq)(struct aq_hw_s *self, s32 delta);
int (*hw_adj_sys_clock)(struct aq_hw_s *self, s64 delta);
int (*hw_set_sys_clock)(struct aq_hw_s *self, u64 time, u64 ts);
int (*hw_ts_to_sys_clock)(struct aq_hw_s *self, u64 ts, u64 *time);
int (*hw_gpio_pulse)(struct aq_hw_s *self, u32 index, u64 start,
u32 period);
int (*hw_extts_gpio_enable)(struct aq_hw_s *self, u32 index,
u32 enable);
int (*hw_get_sync_ts)(struct aq_hw_s *self, u64 *ts);
u16 (*rx_extract_ts)(struct aq_hw_s *self, u8 *p, unsigned int len,
u64 *timestamp);
int (*extract_hwts)(struct aq_hw_s *self, u8 *p, unsigned int len,
u64 *timestamp);
int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc); int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc);
}; };
...@@ -267,6 +307,12 @@ struct aq_fw_ops { ...@@ -267,6 +307,12 @@ struct aq_fw_ops {
int (*set_power)(struct aq_hw_s *self, unsigned int power_state, int (*set_power)(struct aq_hw_s *self, unsigned int power_state,
u8 *mac); u8 *mac);
int (*send_fw_request)(struct aq_hw_s *self,
const struct hw_fw_request_iface *fw_req,
size_t size);
void (*enable_ptp)(struct aq_hw_s *self, int enable);
int (*set_eee_rate)(struct aq_hw_s *self, u32 speed); int (*set_eee_rate)(struct aq_hw_s *self, u32 speed);
int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate, int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate,
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* aQuantia Corporation Network Driver * aQuantia Corporation Network Driver
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
*/ */
/* File aq_main.c: Main file for aQuantia Linux driver. */ /* File aq_main.c: Main file for aQuantia Linux driver. */
...@@ -10,10 +10,13 @@ ...@@ -10,10 +10,13 @@
#include "aq_nic.h" #include "aq_nic.h"
#include "aq_pci_func.h" #include "aq_pci_func.h"
#include "aq_ethtool.h" #include "aq_ethtool.h"
#include "aq_ptp.h"
#include "aq_filters.h" #include "aq_filters.h"
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/ip.h>
#include <linux/udp.h>
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_VERSION(AQ_CFG_DRV_VERSION); MODULE_VERSION(AQ_CFG_DRV_VERSION);
...@@ -93,6 +96,24 @@ static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -93,6 +96,24 @@ static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{ {
struct aq_nic_s *aq_nic = netdev_priv(ndev); struct aq_nic_s *aq_nic = netdev_priv(ndev);
if (unlikely(aq_utils_obj_test(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP))) {
/* Hardware adds the Timestamp for PTPv2 802.AS1
* and PTPv2 IPv4 UDP.
* We have to push even general 320 port messages to the ptp
* queue explicitly. This is a limitation of current firmware
* and hardware PTP design of the chip. Otherwise ptp stream
* will fail to sync
*/
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ||
unlikely((ip_hdr(skb)->version == 4) &&
(ip_hdr(skb)->protocol == IPPROTO_UDP) &&
((udp_hdr(skb)->dest == htons(319)) ||
(udp_hdr(skb)->dest == htons(320)))) ||
unlikely(eth_hdr(skb)->h_proto == htons(ETH_P_1588)))
return aq_ptp_xmit(aq_nic, skb);
}
skb_tx_timestamp(skb);
return aq_nic_xmit(aq_nic, skb); return aq_nic_xmit(aq_nic, skb);
} }
...@@ -197,6 +218,87 @@ static void aq_ndev_set_multicast_settings(struct net_device *ndev) ...@@ -197,6 +218,87 @@ static void aq_ndev_set_multicast_settings(struct net_device *ndev)
(void)aq_nic_set_multicast_list(aq_nic, ndev); (void)aq_nic_set_multicast_list(aq_nic, ndev);
} }
static int aq_ndev_config_hwtstamp(struct aq_nic_s *aq_nic,
struct hwtstamp_config *config)
{
if (config->flags)
return -EINVAL;
switch (config->tx_type) {
case HWTSTAMP_TX_OFF:
case HWTSTAMP_TX_ON:
break;
default:
return -ERANGE;
}
switch (config->rx_filter) {
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
break;
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_NONE:
break;
default:
return -ERANGE;
}
return aq_ptp_hwtstamp_config_set(aq_nic->aq_ptp, config);
}
static int aq_ndev_hwtstamp_set(struct aq_nic_s *aq_nic, struct ifreq *ifr)
{
struct hwtstamp_config config;
int ret_val;
if (!aq_nic->aq_ptp)
return -EOPNOTSUPP;
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
return -EFAULT;
ret_val = aq_ndev_config_hwtstamp(aq_nic, &config);
if (ret_val)
return ret_val;
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
-EFAULT : 0;
}
static int aq_ndev_hwtstamp_get(struct aq_nic_s *aq_nic, struct ifreq *ifr)
{
struct hwtstamp_config config;
if (!aq_nic->aq_ptp)
return -EOPNOTSUPP;
aq_ptp_hwtstamp_config_get(aq_nic->aq_ptp, &config);
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
-EFAULT : 0;
}
static int aq_ndev_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
struct aq_nic_s *aq_nic = netdev_priv(netdev);
switch (cmd) {
case SIOCSHWTSTAMP:
return aq_ndev_hwtstamp_set(aq_nic, ifr);
case SIOCGHWTSTAMP:
return aq_ndev_hwtstamp_get(aq_nic, ifr);
}
return -EOPNOTSUPP;
}
static int aq_ndo_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, static int aq_ndo_vlan_rx_add_vid(struct net_device *ndev, __be16 proto,
u16 vid) u16 vid)
{ {
...@@ -234,6 +336,7 @@ static const struct net_device_ops aq_ndev_ops = { ...@@ -234,6 +336,7 @@ static const struct net_device_ops aq_ndev_ops = {
.ndo_change_mtu = aq_ndev_change_mtu, .ndo_change_mtu = aq_ndev_change_mtu,
.ndo_set_mac_address = aq_ndev_set_mac_address, .ndo_set_mac_address = aq_ndev_set_mac_address,
.ndo_set_features = aq_ndev_set_features, .ndo_set_features = aq_ndev_set_features,
.ndo_do_ioctl = aq_ndev_ioctl,
.ndo_vlan_rx_add_vid = aq_ndo_vlan_rx_add_vid, .ndo_vlan_rx_add_vid = aq_ndo_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = aq_ndo_vlan_rx_kill_vid, .ndo_vlan_rx_kill_vid = aq_ndo_vlan_rx_kill_vid,
}; };
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* aQuantia Corporation Network Driver * aQuantia Corporation Network Driver
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
*/ */
/* File aq_nic.c: Definition of common code for NIC. */ /* File aq_nic.c: Definition of common code for NIC. */
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
#include "aq_hw.h" #include "aq_hw.h"
#include "aq_pci_func.h" #include "aq_pci_func.h"
#include "aq_main.h" #include "aq_main.h"
#include "aq_phy.h"
#include "aq_ptp.h"
#include "aq_filters.h"
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
...@@ -145,6 +148,13 @@ static int aq_nic_update_link_status(struct aq_nic_s *self) ...@@ -145,6 +148,13 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
self->aq_hw->aq_link_status.mbps); self->aq_hw->aq_link_status.mbps);
aq_nic_update_interrupt_moderation_settings(self); aq_nic_update_interrupt_moderation_settings(self);
if (self->aq_ptp) {
aq_ptp_clock_init(self);
aq_ptp_tm_offset_set(self,
self->aq_hw->aq_link_status.mbps);
aq_ptp_link_change(self);
}
/* Driver has to update flow control settings on RX block /* Driver has to update flow control settings on RX block
* on any link event. * on any link event.
* We should query FW whether it negotiated FC. * We should query FW whether it negotiated FC.
...@@ -192,6 +202,8 @@ static void aq_nic_service_task(struct work_struct *work) ...@@ -192,6 +202,8 @@ static void aq_nic_service_task(struct work_struct *work)
service_task); service_task);
int err; int err;
aq_ptp_service_task(self);
if (aq_utils_obj_test(&self->flags, AQ_NIC_FLAGS_IS_NOT_READY)) if (aq_utils_obj_test(&self->flags, AQ_NIC_FLAGS_IS_NOT_READY))
return; return;
...@@ -327,10 +339,27 @@ int aq_nic_init(struct aq_nic_s *self) ...@@ -327,10 +339,27 @@ int aq_nic_init(struct aq_nic_s *self)
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_TP) {
self->aq_hw->phy_id = HW_ATL_PHY_ID_MAX;
err = aq_phy_init(self->aq_hw);
}
for (i = 0U, aq_vec = self->aq_vec[0]; for (i = 0U, aq_vec = self->aq_vec[0];
self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
aq_vec_init(aq_vec, self->aq_hw_ops, self->aq_hw); aq_vec_init(aq_vec, self->aq_hw_ops, self->aq_hw);
err = aq_ptp_init(self, self->irqvecs - 1);
if (err < 0)
goto err_exit;
err = aq_ptp_ring_alloc(self);
if (err < 0)
goto err_exit;
err = aq_ptp_ring_init(self);
if (err < 0)
goto err_exit;
netif_carrier_off(self->ndev); netif_carrier_off(self->ndev);
err_exit: err_exit:
...@@ -361,6 +390,10 @@ int aq_nic_start(struct aq_nic_s *self) ...@@ -361,6 +390,10 @@ int aq_nic_start(struct aq_nic_s *self)
goto err_exit; goto err_exit;
} }
err = aq_ptp_ring_start(self);
if (err < 0)
goto err_exit;
err = self->aq_hw_ops->hw_start(self->aq_hw); err = self->aq_hw_ops->hw_start(self->aq_hw);
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
...@@ -388,6 +421,10 @@ int aq_nic_start(struct aq_nic_s *self) ...@@ -388,6 +421,10 @@ int aq_nic_start(struct aq_nic_s *self)
goto err_exit; goto err_exit;
} }
err = aq_ptp_irq_alloc(self);
if (err < 0)
goto err_exit;
if (self->aq_nic_cfg.link_irq_vec) { if (self->aq_nic_cfg.link_irq_vec) {
int irqvec = pci_irq_vector(self->pdev, int irqvec = pci_irq_vector(self->pdev,
self->aq_nic_cfg.link_irq_vec); self->aq_nic_cfg.link_irq_vec);
...@@ -420,8 +457,7 @@ int aq_nic_start(struct aq_nic_s *self) ...@@ -420,8 +457,7 @@ int aq_nic_start(struct aq_nic_s *self)
return err; return err;
} }
static unsigned int aq_nic_map_skb(struct aq_nic_s *self, unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb,
struct sk_buff *skb,
struct aq_ring_s *ring) struct aq_ring_s *ring)
{ {
unsigned int ret = 0U; unsigned int ret = 0U;
...@@ -953,10 +989,14 @@ int aq_nic_stop(struct aq_nic_s *self) ...@@ -953,10 +989,14 @@ int aq_nic_stop(struct aq_nic_s *self)
else else
aq_pci_func_free_irqs(self); aq_pci_func_free_irqs(self);
aq_ptp_irq_free(self);
for (i = 0U, aq_vec = self->aq_vec[0]; for (i = 0U, aq_vec = self->aq_vec[0];
self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
aq_vec_stop(aq_vec); aq_vec_stop(aq_vec);
aq_ptp_ring_stop(self);
return self->aq_hw_ops->hw_stop(self->aq_hw); return self->aq_hw_ops->hw_stop(self->aq_hw);
} }
...@@ -972,6 +1012,11 @@ void aq_nic_deinit(struct aq_nic_s *self) ...@@ -972,6 +1012,11 @@ void aq_nic_deinit(struct aq_nic_s *self)
self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
aq_vec_deinit(aq_vec); aq_vec_deinit(aq_vec);
aq_ptp_unregister(self);
aq_ptp_ring_deinit(self);
aq_ptp_ring_free(self);
aq_ptp_free(self);
if (likely(self->aq_fw_ops->deinit)) { if (likely(self->aq_fw_ops->deinit)) {
mutex_lock(&self->fwreq_mutex); mutex_lock(&self->fwreq_mutex);
self->aq_fw_ops->deinit(self->aq_hw); self->aq_fw_ops->deinit(self->aq_hw);
...@@ -1068,3 +1113,46 @@ void aq_nic_shutdown(struct aq_nic_s *self) ...@@ -1068,3 +1113,46 @@ void aq_nic_shutdown(struct aq_nic_s *self)
err_exit: err_exit:
rtnl_unlock(); rtnl_unlock();
} }
u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type)
{
u8 location = 0xFF;
u32 fltr_cnt;
u32 n_bit;
switch (type) {
case aq_rx_filter_ethertype:
location = AQ_RX_LAST_LOC_FETHERT - AQ_RX_FIRST_LOC_FETHERT -
self->aq_hw_rx_fltrs.fet_reserved_count;
self->aq_hw_rx_fltrs.fet_reserved_count++;
break;
case aq_rx_filter_l3l4:
fltr_cnt = AQ_RX_LAST_LOC_FL3L4 - AQ_RX_FIRST_LOC_FL3L4;
n_bit = fltr_cnt - self->aq_hw_rx_fltrs.fl3l4.reserved_count;
self->aq_hw_rx_fltrs.fl3l4.active_ipv4 |= BIT(n_bit);
self->aq_hw_rx_fltrs.fl3l4.reserved_count++;
location = n_bit;
break;
default:
break;
}
return location;
}
void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type,
u32 location)
{
switch (type) {
case aq_rx_filter_ethertype:
self->aq_hw_rx_fltrs.fet_reserved_count--;
break;
case aq_rx_filter_l3l4:
self->aq_hw_rx_fltrs.fl3l4.reserved_count--;
self->aq_hw_rx_fltrs.fl3l4.active_ipv4 &= ~BIT(location);
break;
default:
break;
}
}
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* aQuantia Corporation Network Driver * aQuantia Corporation Network Driver
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
*/ */
/* File aq_nic.h: Declaration of common code for NIC. */ /* File aq_nic.h: Declaration of common code for NIC. */
...@@ -17,6 +17,8 @@ struct aq_ring_s; ...@@ -17,6 +17,8 @@ struct aq_ring_s;
struct aq_hw_ops; struct aq_hw_ops;
struct aq_fw_s; struct aq_fw_s;
struct aq_vec_s; struct aq_vec_s;
struct aq_ptp_s;
enum aq_rx_filter_type;
struct aq_nic_cfg_s { struct aq_nic_cfg_s {
const struct aq_hw_caps_s *aq_hw_caps; const struct aq_hw_caps_s *aq_hw_caps;
...@@ -53,6 +55,7 @@ struct aq_nic_cfg_s { ...@@ -53,6 +55,7 @@ struct aq_nic_cfg_s {
#define AQ_NIC_FLAG_STOPPING 0x00000008U #define AQ_NIC_FLAG_STOPPING 0x00000008U
#define AQ_NIC_FLAG_RESETTING 0x00000010U #define AQ_NIC_FLAG_RESETTING 0x00000010U
#define AQ_NIC_FLAG_CLOSING 0x00000020U #define AQ_NIC_FLAG_CLOSING 0x00000020U
#define AQ_NIC_PTP_DPATH_UP 0x02000000U
#define AQ_NIC_LINK_DOWN 0x04000000U #define AQ_NIC_LINK_DOWN 0x04000000U
#define AQ_NIC_FLAG_ERR_UNPLUG 0x40000000U #define AQ_NIC_FLAG_ERR_UNPLUG 0x40000000U
#define AQ_NIC_FLAG_ERR_HW 0x80000000U #define AQ_NIC_FLAG_ERR_HW 0x80000000U
...@@ -70,6 +73,7 @@ struct aq_hw_rx_fl3l4 { ...@@ -70,6 +73,7 @@ struct aq_hw_rx_fl3l4 {
u8 active_ipv4; u8 active_ipv4;
u8 active_ipv6:2; u8 active_ipv6:2;
u8 is_ipv6; u8 is_ipv6;
u8 reserved_count;
}; };
struct aq_hw_rx_fltrs_s { struct aq_hw_rx_fltrs_s {
...@@ -77,6 +81,8 @@ struct aq_hw_rx_fltrs_s { ...@@ -77,6 +81,8 @@ struct aq_hw_rx_fltrs_s {
u16 active_filters; u16 active_filters;
struct aq_hw_rx_fl2 fl2; struct aq_hw_rx_fl2 fl2;
struct aq_hw_rx_fl3l4 fl3l4; struct aq_hw_rx_fl3l4 fl3l4;
/*filter ether type */
u8 fet_reserved_count;
}; };
struct aq_nic_s { struct aq_nic_s {
...@@ -108,6 +114,8 @@ struct aq_nic_s { ...@@ -108,6 +114,8 @@ struct aq_nic_s {
u32 irqvecs; u32 irqvecs;
/* mutex to serialize FW interface access operations */ /* mutex to serialize FW interface access operations */
struct mutex fwreq_mutex; struct mutex fwreq_mutex;
/* PTP support */
struct aq_ptp_s *aq_ptp;
struct aq_hw_rx_fltrs_s aq_hw_rx_fltrs; struct aq_hw_rx_fltrs_s aq_hw_rx_fltrs;
}; };
...@@ -126,6 +134,8 @@ void aq_nic_cfg_start(struct aq_nic_s *self); ...@@ -126,6 +134,8 @@ void aq_nic_cfg_start(struct aq_nic_s *self);
int aq_nic_ndev_register(struct aq_nic_s *self); int aq_nic_ndev_register(struct aq_nic_s *self);
void aq_nic_ndev_free(struct aq_nic_s *self); void aq_nic_ndev_free(struct aq_nic_s *self);
int aq_nic_start(struct aq_nic_s *self); int aq_nic_start(struct aq_nic_s *self);
unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb,
struct aq_ring_s *ring);
int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb); int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb);
int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p); int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p);
int aq_nic_get_regs_count(struct aq_nic_s *self); int aq_nic_get_regs_count(struct aq_nic_s *self);
...@@ -148,5 +158,7 @@ u32 aq_nic_get_fw_version(struct aq_nic_s *self); ...@@ -148,5 +158,7 @@ u32 aq_nic_get_fw_version(struct aq_nic_s *self);
int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg); int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg);
int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self); int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self);
void aq_nic_shutdown(struct aq_nic_s *self); void aq_nic_shutdown(struct aq_nic_s *self);
u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type);
void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type,
u32 location);
#endif /* AQ_NIC_H */ #endif /* AQ_NIC_H */
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* aQuantia Corporation Network Driver * aQuantia Corporation Network Driver
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
*/ */
/* File aq_pci_func.c: Definition of PCI functions. */ /* File aq_pci_func.c: Definition of PCI functions. */
...@@ -269,6 +269,9 @@ static int aq_pci_probe(struct pci_dev *pdev, ...@@ -269,6 +269,9 @@ static int aq_pci_probe(struct pci_dev *pdev,
numvecs = min((u8)AQ_CFG_VECS_DEF, numvecs = min((u8)AQ_CFG_VECS_DEF,
aq_nic_get_cfg(self)->aq_hw_caps->msix_irqs); aq_nic_get_cfg(self)->aq_hw_caps->msix_irqs);
numvecs = min(numvecs, num_online_cpus()); numvecs = min(numvecs, num_online_cpus());
/* Request IRQ vector for PTP */
numvecs += 1;
numvecs += AQ_HW_SERVICE_IRQS; numvecs += AQ_HW_SERVICE_IRQS;
/*enable interrupts */ /*enable interrupts */
#if !AQ_CFG_FORCE_LEGACY_INT #if !AQ_CFG_FORCE_LEGACY_INT
......
// SPDX-License-Identifier: GPL-2.0-only
/* aQuantia Corporation Network Driver
* Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved
*/
#include "aq_phy.h"
bool aq_mdio_busy_wait(struct aq_hw_s *aq_hw)
{
int err = 0;
u32 val;
err = readx_poll_timeout_atomic(hw_atl_mdio_busy_get, aq_hw,
val, val == 0U, 10U, 100000U);
if (err < 0)
return false;
return true;
}
u16 aq_mdio_read_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr)
{
u16 phy_addr = aq_hw->phy_id << 5 | mmd;
/* Set Address register. */
hw_atl_glb_mdio_iface4_set(aq_hw, (addr & HW_ATL_MDIO_ADDRESS_MSK) <<
HW_ATL_MDIO_ADDRESS_SHIFT);
/* Send Address command. */
hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |
(3 << HW_ATL_MDIO_OP_MODE_SHIFT) |
((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<
HW_ATL_MDIO_PHY_ADDRESS_SHIFT));
aq_mdio_busy_wait(aq_hw);
/* Send Read command. */
hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |
(1 << HW_ATL_MDIO_OP_MODE_SHIFT) |
((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<
HW_ATL_MDIO_PHY_ADDRESS_SHIFT));
/* Read result. */
aq_mdio_busy_wait(aq_hw);
return (u16)hw_atl_glb_mdio_iface5_get(aq_hw);
}
void aq_mdio_write_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr, u16 data)
{
u16 phy_addr = aq_hw->phy_id << 5 | mmd;
/* Set Address register. */
hw_atl_glb_mdio_iface4_set(aq_hw, (addr & HW_ATL_MDIO_ADDRESS_MSK) <<
HW_ATL_MDIO_ADDRESS_SHIFT);
/* Send Address command. */
hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |
(3 << HW_ATL_MDIO_OP_MODE_SHIFT) |
((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<
HW_ATL_MDIO_PHY_ADDRESS_SHIFT));
aq_mdio_busy_wait(aq_hw);
hw_atl_glb_mdio_iface3_set(aq_hw, (data & HW_ATL_MDIO_WRITE_DATA_MSK) <<
HW_ATL_MDIO_WRITE_DATA_SHIFT);
/* Send Write command. */
hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |
(2 << HW_ATL_MDIO_OP_MODE_SHIFT) |
((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<
HW_ATL_MDIO_PHY_ADDRESS_SHIFT));
aq_mdio_busy_wait(aq_hw);
}
u16 aq_phy_read_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address)
{
int err = 0;
u32 val;
err = readx_poll_timeout_atomic(hw_atl_sem_mdio_get, aq_hw,
val, val == 1U, 10U, 100000U);
if (err < 0) {
err = 0xffff;
goto err_exit;
}
err = aq_mdio_read_word(aq_hw, mmd, address);
hw_atl_reg_glb_cpu_sem_set(aq_hw, 1U, HW_ATL_FW_SM_MDIO);
err_exit:
return err;
}
void aq_phy_write_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address, u16 data)
{
int err = 0;
u32 val;
err = readx_poll_timeout_atomic(hw_atl_sem_mdio_get, aq_hw,
val, val == 1U, 10U, 100000U);
if (err < 0)
return;
aq_mdio_write_word(aq_hw, mmd, address, data);
hw_atl_reg_glb_cpu_sem_set(aq_hw, 1U, HW_ATL_FW_SM_MDIO);
}
bool aq_phy_init_phy_id(struct aq_hw_s *aq_hw)
{
u16 val;
for (aq_hw->phy_id = 0; aq_hw->phy_id < HW_ATL_PHY_ID_MAX;
++aq_hw->phy_id) {
/* PMA Standard Device Identifier 2: Address 1.3 */
val = aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 3);
if (val != 0xffff)
return true;
}
return false;
}
bool aq_phy_init(struct aq_hw_s *aq_hw)
{
u32 dev_id;
if (aq_hw->phy_id == HW_ATL_PHY_ID_MAX)
if (!aq_phy_init_phy_id(aq_hw))
return false;
/* PMA Standard Device Identifier:
* Address 1.2 = MSW,
* Address 1.3 = LSW
*/
dev_id = aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 2);
dev_id <<= 16;
dev_id |= aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 3);
if (dev_id == 0xffffffff) {
aq_hw->phy_id = HW_ATL_PHY_ID_MAX;
return false;
}
return true;
}
/* SPDX-License-Identifier: GPL-2.0-only */
/* aQuantia Corporation Network Driver
* Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved
*/
#ifndef AQ_PHY_H
#define AQ_PHY_H
#include <linux/mdio.h>
#include "hw_atl/hw_atl_llh.h"
#include "hw_atl/hw_atl_llh_internal.h"
#include "aq_hw_utils.h"
#include "aq_hw.h"
#define HW_ATL_PHY_ID_MAX 32U
bool aq_mdio_busy_wait(struct aq_hw_s *aq_hw);
u16 aq_mdio_read_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr);
void aq_mdio_write_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr, u16 data);
u16 aq_phy_read_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address);
void aq_phy_write_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address, u16 data);
bool aq_phy_init_phy_id(struct aq_hw_s *aq_hw);
bool aq_phy_init(struct aq_hw_s *aq_hw);
#endif /* AQ_PHY_H */
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/* Aquantia Corporation Network Driver
* Copyright (C) 2014-2019 Aquantia Corporation. All rights reserved
*/
/* File aq_ptp.h: Declaration of PTP functions.
*/
#ifndef AQ_PTP_H
#define AQ_PTP_H
#include <linux/net_tstamp.h>
#include <linux/version.h>
/* Common functions */
int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec);
void aq_ptp_unregister(struct aq_nic_s *aq_nic);
void aq_ptp_free(struct aq_nic_s *aq_nic);
int aq_ptp_irq_alloc(struct aq_nic_s *aq_nic);
void aq_ptp_irq_free(struct aq_nic_s *aq_nic);
int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic);
void aq_ptp_ring_free(struct aq_nic_s *aq_nic);
int aq_ptp_ring_init(struct aq_nic_s *aq_nic);
int aq_ptp_ring_start(struct aq_nic_s *aq_nic);
void aq_ptp_ring_stop(struct aq_nic_s *aq_nic);
void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic);
void aq_ptp_service_task(struct aq_nic_s *aq_nic);
void aq_ptp_tm_offset_set(struct aq_nic_s *aq_nic, unsigned int mbps);
void aq_ptp_clock_init(struct aq_nic_s *aq_nic);
/* Traffic processing functions */
int aq_ptp_xmit(struct aq_nic_s *aq_nic, struct sk_buff *skb);
void aq_ptp_tx_hwtstamp(struct aq_nic_s *aq_nic, u64 timestamp);
/* Must be to check available of PTP before call */
void aq_ptp_hwtstamp_config_get(struct aq_ptp_s *aq_ptp,
struct hwtstamp_config *config);
int aq_ptp_hwtstamp_config_set(struct aq_ptp_s *aq_ptp,
struct hwtstamp_config *config);
/* Return either ring is belong to PTP or not*/
bool aq_ptp_ring(struct aq_nic_s *aq_nic, struct aq_ring_s *ring);
u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic, struct sk_buff *skb, u8 *p,
unsigned int len);
struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp);
int aq_ptp_link_change(struct aq_nic_s *aq_nic);
#endif /* AQ_PTP_H */
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* aQuantia Corporation Network Driver * aQuantia Corporation Network Driver
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
*/ */
/* File aq_ring.c: Definition of functions for Rx/Tx rings. */ /* File aq_ring.c: Definition of functions for Rx/Tx rings. */
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "aq_nic.h" #include "aq_nic.h"
#include "aq_hw.h" #include "aq_hw.h"
#include "aq_hw_utils.h" #include "aq_hw_utils.h"
#include "aq_ptp.h"
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
...@@ -177,6 +178,30 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self, ...@@ -177,6 +178,30 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
return self; return self;
} }
struct aq_ring_s *
aq_ring_hwts_rx_alloc(struct aq_ring_s *self, struct aq_nic_s *aq_nic,
unsigned int idx, unsigned int size, unsigned int dx_size)
{
struct device *dev = aq_nic_get_dev(aq_nic);
size_t sz = size * dx_size + AQ_CFG_RXDS_DEF;
memset(self, 0, sizeof(*self));
self->aq_nic = aq_nic;
self->idx = idx;
self->size = size;
self->dx_size = dx_size;
self->dx_ring = dma_alloc_coherent(dev, sz, &self->dx_ring_pa,
GFP_KERNEL);
if (!self->dx_ring) {
aq_ring_free(self);
return NULL;
}
return self;
}
int aq_ring_init(struct aq_ring_s *self) int aq_ring_init(struct aq_ring_s *self)
{ {
self->hw_head = 0; self->hw_head = 0;
...@@ -290,6 +315,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self, ...@@ -290,6 +315,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
self->sw_head = aq_ring_next_dx(self, self->sw_head), self->sw_head = aq_ring_next_dx(self, self->sw_head),
--budget, ++(*work_done)) { --budget, ++(*work_done)) {
struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head]; struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head];
bool is_ptp_ring = aq_ptp_ring(self->aq_nic, self);
struct aq_ring_buff_s *buff_ = NULL; struct aq_ring_buff_s *buff_ = NULL;
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
unsigned int next_ = 0U; unsigned int next_ = 0U;
...@@ -354,6 +380,11 @@ int aq_ring_rx_clean(struct aq_ring_s *self, ...@@ -354,6 +380,11 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
err = -ENOMEM; err = -ENOMEM;
goto err_exit; goto err_exit;
} }
if (is_ptp_ring)
buff->len -=
aq_ptp_extract_ts(self->aq_nic, skb,
aq_buf_vaddr(&buff->rxdata),
buff->len);
skb_put(skb, buff->len); skb_put(skb, buff->len);
page_ref_inc(buff->rxdata.page); page_ref_inc(buff->rxdata.page);
} else { } else {
...@@ -362,6 +393,11 @@ int aq_ring_rx_clean(struct aq_ring_s *self, ...@@ -362,6 +393,11 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
err = -ENOMEM; err = -ENOMEM;
goto err_exit; goto err_exit;
} }
if (is_ptp_ring)
buff->len -=
aq_ptp_extract_ts(self->aq_nic, skb,
aq_buf_vaddr(&buff->rxdata),
buff->len);
hdr_len = buff->len; hdr_len = buff->len;
if (hdr_len > AQ_CFG_RX_HDR_SIZE) if (hdr_len > AQ_CFG_RX_HDR_SIZE)
...@@ -421,8 +457,8 @@ int aq_ring_rx_clean(struct aq_ring_s *self, ...@@ -421,8 +457,8 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
skb_set_hash(skb, buff->rss_hash, skb_set_hash(skb, buff->rss_hash,
buff->is_hash_l4 ? PKT_HASH_TYPE_L4 : buff->is_hash_l4 ? PKT_HASH_TYPE_L4 :
PKT_HASH_TYPE_NONE); PKT_HASH_TYPE_NONE);
/* Send all PTP traffic to 0 queue */
skb_record_rx_queue(skb, self->idx); skb_record_rx_queue(skb, is_ptp_ring ? 0 : self->idx);
++self->stats.rx.packets; ++self->stats.rx.packets;
self->stats.rx.bytes += skb->len; self->stats.rx.bytes += skb->len;
...@@ -434,6 +470,21 @@ int aq_ring_rx_clean(struct aq_ring_s *self, ...@@ -434,6 +470,21 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
return err; return err;
} }
void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic)
{
while (self->sw_head != self->hw_head) {
u64 ns;
aq_nic->aq_hw_ops->extract_hwts(aq_nic->aq_hw,
self->dx_ring +
(self->sw_head * self->dx_size),
self->dx_size, &ns);
aq_ptp_tx_hwtstamp(aq_nic, ns);
self->sw_head = aq_ring_next_dx(self, self->sw_head);
}
}
int aq_ring_rx_fill(struct aq_ring_s *self) int aq_ring_rx_fill(struct aq_ring_s *self)
{ {
unsigned int page_order = self->page_order; unsigned int page_order = self->page_order;
......
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* aQuantia Corporation Network Driver * aQuantia Corporation Network Driver
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
*/ */
/* File aq_ring.h: Declaration of functions for Rx/Tx rings. */ /* File aq_ring.h: Declaration of functions for Rx/Tx rings. */
...@@ -174,4 +174,9 @@ int aq_ring_rx_clean(struct aq_ring_s *self, ...@@ -174,4 +174,9 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
int budget); int budget);
int aq_ring_rx_fill(struct aq_ring_s *self); int aq_ring_rx_fill(struct aq_ring_s *self);
struct aq_ring_s *aq_ring_hwts_rx_alloc(struct aq_ring_s *self,
struct aq_nic_s *aq_nic, unsigned int idx,
unsigned int size, unsigned int dx_size);
void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic);
#endif /* AQ_RING_H */ #endif /* AQ_RING_H */
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* aQuantia Corporation Network Driver * 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 /* File hw_atl_b0_internal.h: Definition of Atlantic B0 chip specific
...@@ -65,7 +65,10 @@ ...@@ -65,7 +65,10 @@
#define HW_ATL_B0_MPI_SPEED_SHIFT 16U #define HW_ATL_B0_MPI_SPEED_SHIFT 16U
#define HW_ATL_B0_TXBUF_MAX 160U #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_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_MAX 64U
#define HW_ATL_B0_RSS_REDIRECTION_BITS 3U #define HW_ATL_B0_RSS_REDIRECTION_BITS 3U
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* aQuantia Corporation Network Driver * 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 /* File hw_atl_llh.c: Definitions of bitfield and register access functions for
...@@ -572,6 +572,13 @@ void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw, ...@@ -572,6 +572,13 @@ void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw,
rx_traf_class_mode); 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) 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, aq_hw_write_reg_bit(aq_hw, HW_ATL_RPB_RX_BUF_EN_ADR,
...@@ -636,8 +643,8 @@ void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, ...@@ -636,8 +643,8 @@ void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw,
rx_pkt_buff_size_per_tc); 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, void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw,
u32 buffer) u32 rx_xoff_en_per_tc, u32 buffer)
{ {
aq_hw_write_reg_bit(aq_hw, HW_ATL_RPB_RXBXOFF_EN_ADR(buffer), aq_hw_write_reg_bit(aq_hw, HW_ATL_RPB_RXBXOFF_EN_ADR(buffer),
HW_ATL_RPB_RXBXOFF_EN_MSK, HW_ATL_RPB_RXBXOFF_EN_MSK,
...@@ -1290,6 +1297,13 @@ void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en) ...@@ -1290,6 +1297,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); 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, void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw,
u32 tx_traf_class_mode) u32 tx_traf_class_mode)
{ {
...@@ -1526,6 +1540,20 @@ void hw_atl_reg_glb_cpu_scratch_scp_set(struct aq_hw_s *aq_hw, ...@@ -1526,6 +1540,20 @@ void hw_atl_reg_glb_cpu_scratch_scp_set(struct aq_hw_s *aq_hw,
glb_cpu_scratch_scp); 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) 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, aq_hw_write_reg_bit(aq_hw, HW_ATL_MCP_UP_FORCE_INTERRUPT_ADR,
...@@ -1616,6 +1644,11 @@ u32 hw_atl_sem_ram_get(struct aq_hw_s *self) ...@@ -1616,6 +1644,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); 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) u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp)
{ {
return aq_hw_read_reg(aq_hw, return aq_hw_read_reg(aq_hw,
...@@ -1631,3 +1664,60 @@ u32 hw_atl_scrpad25_get(struct aq_hw_s *self) ...@@ -1631,3 +1664,60 @@ u32 hw_atl_scrpad25_get(struct aq_hw_s *self)
{ {
return hw_atl_scrpad_get(self, 0x18); 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);
}
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* aQuantia Corporation Network Driver * 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 /* File hw_atl_llh.h: Declarations of bitfield and register access functions for
...@@ -292,6 +292,9 @@ void hw_atl_rpb_dma_sys_lbk_set(struct aq_hw_s *aq_hw, u32 dma_sys_lbk); ...@@ -292,6 +292,9 @@ void hw_atl_rpb_dma_sys_lbk_set(struct aq_hw_s *aq_hw, u32 dma_sys_lbk);
void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw, void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw,
u32 rx_traf_class_mode); 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 */ /* set rx buffer enable */
void hw_atl_rpb_rx_buff_en_set(struct aq_hw_s *aq_hw, u32 rx_buff_en); void hw_atl_rpb_rx_buff_en_set(struct aq_hw_s *aq_hw, u32 rx_buff_en);
...@@ -306,7 +309,8 @@ void hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(struct aq_hw_s *aq_hw, ...@@ -306,7 +309,8 @@ void hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(struct aq_hw_s *aq_hw,
u32 buffer); u32 buffer);
/* set rx flow control mode */ /* 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) */ /* set rx packet buffer size (per tc) */
void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw,
...@@ -320,7 +324,8 @@ void hw_atl_rdm_rx_dma_desc_cache_init_tgl(struct aq_hw_s *aq_hw); ...@@ -320,7 +324,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); u32 hw_atl_rdm_rx_dma_desc_cache_init_done_get(struct aq_hw_s *aq_hw);
/* set rx xoff enable (per tc) */ /* 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); u32 buffer);
/* rpf */ /* rpf */
...@@ -605,6 +610,9 @@ void hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(struct aq_hw_s *aq_hw, ...@@ -605,6 +610,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, void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw,
u32 tx_traf_class_mode); 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 */ /* set tx buffer enable */
void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en); void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en);
...@@ -623,7 +631,8 @@ void hw_atl_tpb_tx_dma_sys_lbk_en_set(struct aq_hw_s *aq_hw, u32 tx_dma_sys_lbk_ ...@@ -623,7 +631,8 @@ void hw_atl_tpb_tx_dma_sys_lbk_en_set(struct aq_hw_s *aq_hw, u32 tx_dma_sys_lbk_
/* set tx packet buffer size (per tc) */ /* set tx packet buffer size (per tc) */
void hw_atl_tpb_tx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, 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 */ /* 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); void hw_atl_tpb_tx_path_scp_ins_en_set(struct aq_hw_s *aq_hw, u32 tx_path_scp_ins_en);
...@@ -715,6 +724,12 @@ void hw_atl_msm_reg_wr_strobe_set(struct aq_hw_s *aq_hw, u32 reg_wr_strobe); ...@@ -715,6 +724,12 @@ void hw_atl_msm_reg_wr_strobe_set(struct aq_hw_s *aq_hw, u32 reg_wr_strobe);
/* set pci register reset disable */ /* 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); 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 */ /* set uP Force Interrupt */
void hw_atl_mcp_up_force_intr_set(struct aq_hw_s *aq_hw, u32 up_force_intr); void hw_atl_mcp_up_force_intr_set(struct aq_hw_s *aq_hw, u32 up_force_intr);
...@@ -752,9 +767,44 @@ void hw_atl_rpfl3l4_ipv6_src_addr_set(struct aq_hw_s *aq_hw, u8 location, ...@@ -752,9 +767,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, void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location,
u32 *ipv6_dest); 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 */ /* get global microprocessor ram semaphore */
u32 hw_atl_sem_ram_get(struct aq_hw_s *self); 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 */ /* get global microprocessor scratch pad register */
u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp); u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp);
......
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* aQuantia Corporation Network Driver * 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 /* File hw_atl_llh_internal.h: Preprocessor definitions
...@@ -1308,6 +1308,52 @@ ...@@ -1308,6 +1308,52 @@
/* default value of bitfield et_val{f}[f:0] */ /* default value of bitfield et_val{f}[f:0] */
#define HW_ATL_RPF_ET_VALF_DEFAULT 0x0 #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 /* RX l4_sp{D}[F:0] Bitfield Definitions
* Preprocessor definitions for the bitfield "l4_sp{D}[F:0]". * Preprocessor definitions for the bitfield "l4_sp{D}[F:0]".
* Parameter: srcport {D} | stride size 0x4 | range [0, 7] * Parameter: srcport {D} | stride size 0x4 | range [0, 7]
...@@ -2440,6 +2486,22 @@ ...@@ -2440,6 +2486,22 @@
/* default value of bitfield register write strobe */ /* default value of bitfield register write strobe */
#define HW_ATL_MSM_REG_WR_STROBE_DEFAULT 0x0 #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 /* mif soft reset bitfield definitions
* preprocessor definitions for the bitfield "soft reset". * preprocessor definitions for the bitfield "soft reset".
* port="pif_glb_res_i" * port="pif_glb_res_i"
...@@ -2532,50 +2594,121 @@ ...@@ -2532,50 +2594,121 @@
/* default value of bitfield uP Force Interrupt */ /* default value of bitfield uP Force Interrupt */
#define HW_ATL_MCP_UP_FORCE_INTERRUPT_DEFAULT 0x0 #define HW_ATL_MCP_UP_FORCE_INTERRUPT_DEFAULT 0x0
#define HW_ATL_RX_CTRL_ADDR_BEGIN_FL3L4 0x00005380 /* Preprocessor definitions for Global MDIO Interfaces
#define HW_ATL_RX_SRCA_ADDR_BEGIN_FL3L4 0x000053B0 * Address: 0x00000280 + 0x4 * Number of interface
#define HW_ATL_RX_DESTA_ADDR_BEGIN_FL3L4 0x000053D0 */
#define HW_ATL_GLB_MDIO_IFACE_ADDR_BEGIN 0x00000280u
#define HW_ATL_RPF_L3_REG_CTRL_ADR(location) (0x00005380 + (location) * 0x4)
#define HW_ATL_GLB_MDIO_IFACE_N_ADR(number) \
/* RX rpf_l3_sa{D}[1F:0] Bitfield Definitions (HW_ATL_GLB_MDIO_IFACE_ADDR_BEGIN + (((number) - 1) * 0x4))
* Preprocessor definitions for the bitfield "l3_sa{D}[1F:0]".
* Parameter: location {D} | stride size 0x4 | range [0, 7] /* MIF MDIO Busy Bitfield Definitions
* PORT="pif_rpf_l3_sa0_i[31:0]" * Preprocessor definitions for the bitfield "MDIO Busy".
*/ * PORT="mdio_pif_busy_o"
*/
/* Register address for bitfield pif_rpf_l3_sa0_i[31:0] */
#define HW_ATL_RPF_L3_SRCA_ADR(location) (0x000053B0 + (location) * 0x4) /* Register address for bitfield MDIO Busy */
/* Bitmask for bitfield l3_sa0[1F:0] */ #define HW_ATL_MDIO_BUSY_ADR 0x00000284
#define HW_ATL_RPF_L3_SRCA_MSK 0xFFFFFFFFu /* Bitmask for bitfield MDIO Busy */
/* Inverted bitmask for bitfield l3_sa0[1F:0] */ #define HW_ATL_MDIO_BUSY_MSK 0x80000000
#define HW_ATL_RPF_L3_SRCA_MSKN 0xFFFFFFFFu /* Inverted bitmask for bitfield MDIO Busy */
/* Lower bit position of bitfield l3_sa0[1F:0] */ #define HW_ATL_MDIO_BUSY_MSKN 0x7FFFFFFF
#define HW_ATL_RPF_L3_SRCA_SHIFT 0 /* Lower bit position of bitfield MDIO Busy */
/* Width of bitfield l3_sa0[1F:0] */ #define HW_ATL_MDIO_BUSY_SHIFT 31
#define HW_ATL_RPF_L3_SRCA_WIDTH 32 /* Width of bitfield MDIO Busy */
/* Default value of bitfield l3_sa0[1F:0] */ #define HW_ATL_MDIO_BUSY_WIDTH 1
#define HW_ATL_RPF_L3_SRCA_DEFAULT 0x0
/* MIF MDIO Execute Operation Bitfield Definitions
/* RX rpf_l3_da{D}[1F:0] Bitfield Definitions * Preprocessor definitions for the bitfield "MDIO Execute Operation".
* Preprocessor definitions for the bitfield "l3_da{D}[1F:0]". * PORT="pif_mdio_op_start_i"
* Parameter: location {D} | stride size 0x4 | range [0, 7] */
* PORT="pif_rpf_l3_da0_i[31:0]"
*/ /* Register address for bitfield MDIO Execute Operation */
#define HW_ATL_MDIO_EXECUTE_OPERATION_ADR 0x00000284
/* Register address for bitfield pif_rpf_l3_da0_i[31:0] */ /* Bitmask for bitfield MDIO Execute Operation */
#define HW_ATL_RPF_L3_DSTA_ADR(location) (0x000053B0 + (location) * 0x4) #define HW_ATL_MDIO_EXECUTE_OPERATION_MSK 0x00008000
/* Bitmask for bitfield l3_da0[1F:0] */ /* Inverted bitmask for bitfield MDIO Execute Operation */
#define HW_ATL_RPF_L3_DSTA_MSK 0xFFFFFFFFu #define HW_ATL_MDIO_EXECUTE_OPERATION_MSKN 0xFFFF7FFF
/* Inverted bitmask for bitfield l3_da0[1F:0] */ /* Lower bit position of bitfield MDIO Execute Operation */
#define HW_ATL_RPF_L3_DSTA_MSKN 0xFFFFFFFFu #define HW_ATL_MDIO_EXECUTE_OPERATION_SHIFT 15
/* Lower bit position of bitfield l3_da0[1F:0] */ /* Width of bitfield MDIO Execute Operation */
#define HW_ATL_RPF_L3_DSTA_SHIFT 0 #define HW_ATL_MDIO_EXECUTE_OPERATION_WIDTH 1
/* Width of bitfield l3_da0[1F:0] */ /* Default value of bitfield MDIO Execute Operation */
#define HW_ATL_RPF_L3_DSTA_WIDTH 32 #define HW_ATL_MDIO_EXECUTE_OPERATION_DEFAULT 0x0
/* Default value of bitfield l3_da0[1F:0] */
#define HW_ATL_RPF_L3_DSTA_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 #define HW_ATL_FW_SM_RAM 0x2U
#endif /* HW_ATL_LLH_INTERNAL_H */ #endif /* HW_ATL_LLH_INTERNAL_H */
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* aQuantia Corporation Network Driver * 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 /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware
...@@ -327,8 +327,7 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, ...@@ -327,8 +327,7 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
return err; return err;
} }
static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt)
u32 cnt)
{ {
u32 val; u32 val;
int err = 0; int err = 0;
...@@ -964,4 +963,6 @@ const struct aq_fw_ops aq_fw_1x_ops = { ...@@ -964,4 +963,6 @@ const struct aq_fw_ops aq_fw_1x_ops = {
.set_eee_rate = NULL, .set_eee_rate = NULL,
.get_eee_rate = NULL, .get_eee_rate = NULL,
.set_flow_control = NULL, .set_flow_control = NULL,
.send_fw_request = NULL,
.enable_ptp = NULL,
}; };
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* aQuantia Corporation Network Driver * 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 /* File hw_atl_utils.h: Declaration of common functions for Atlantic hardware
...@@ -44,6 +44,14 @@ struct __packed hw_atl_rxd_wb_s { ...@@ -44,6 +44,14 @@ struct __packed hw_atl_rxd_wb_s {
u16 vlan; u16 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 { struct __packed hw_atl_stats_s {
u32 uprc; u32 uprc;
u32 mprc; u32 mprc;
...@@ -168,6 +176,34 @@ struct __packed hw_atl_utils_mbox_header { ...@@ -168,6 +176,34 @@ struct __packed hw_atl_utils_mbox_header {
u32 error; u32 error;
}; };
struct __packed hw_aq_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;
};
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_aq_info { struct __packed hw_aq_info {
u8 reserved[6]; u8 reserved[6];
u16 phy_fault_code; u16 phy_fault_code;
...@@ -175,9 +211,23 @@ struct __packed hw_aq_info { ...@@ -175,9 +211,23 @@ struct __packed hw_aq_info {
u8 cable_len; u8 cable_len;
u8 reserved1; u8 reserved1;
u32 cable_diag_data[4]; u32 cable_diag_data[4];
u8 reserved2[32]; struct hw_aq_ptp_offset ptp_offset;
u8 reserved2[12];
u32 caps_lo; u32 caps_lo;
u32 caps_hi; 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 __packed hw_atl_utils_mbox {
...@@ -237,6 +287,42 @@ struct __packed offload_info { ...@@ -237,6 +287,42 @@ struct __packed offload_info {
u8 buf[0]; u8 buf[0];
}; };
/* 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;
};
};
enum hw_atl_rx_action_with_traffic { enum hw_atl_rx_action_with_traffic {
HW_ATL_RX_DISCARD, HW_ATL_RX_DISCARD,
HW_ATL_RX_HOST, HW_ATL_RX_HOST,
...@@ -344,91 +430,135 @@ enum hw_atl_fw2x_rate { ...@@ -344,91 +430,135 @@ enum hw_atl_fw2x_rate {
FW2X_RATE_10G = 0x800, FW2X_RATE_10G = 0x800,
}; };
/* 0x370
* Link capabilities resolution register
*/
enum hw_atl_fw2x_caps_lo { enum hw_atl_fw2x_caps_lo {
CAPS_LO_10BASET_HD = 0x00, CAPS_LO_10BASET_HD = 0,
CAPS_LO_10BASET_FD, CAPS_LO_10BASET_FD,
CAPS_LO_100BASETX_HD, CAPS_LO_100BASETX_HD,
CAPS_LO_100BASET4_HD, CAPS_LO_100BASET4_HD,
CAPS_LO_100BASET2_HD, CAPS_LO_100BASET2_HD,
CAPS_LO_100BASETX_FD, CAPS_LO_100BASETX_FD = 5,
CAPS_LO_100BASET2_FD, CAPS_LO_100BASET2_FD,
CAPS_LO_1000BASET_HD, CAPS_LO_1000BASET_HD,
CAPS_LO_1000BASET_FD, CAPS_LO_1000BASET_FD,
CAPS_LO_2P5GBASET_FD, CAPS_LO_2P5GBASET_FD,
CAPS_LO_5GBASET_FD, CAPS_LO_5GBASET_FD = 10,
CAPS_LO_10GBASET_FD, CAPS_LO_10GBASET_FD,
}; };
/* 0x374
* Status register
*/
enum hw_atl_fw2x_caps_hi { enum hw_atl_fw2x_caps_hi {
CAPS_HI_RESERVED1 = 0x00, CAPS_HI_RESERVED1 = 0,
CAPS_HI_10BASET_EEE, CAPS_HI_10BASET_EEE,
CAPS_HI_RESERVED2, CAPS_HI_RESERVED2,
CAPS_HI_PAUSE, CAPS_HI_PAUSE,
CAPS_HI_ASYMMETRIC_PAUSE, CAPS_HI_ASYMMETRIC_PAUSE,
CAPS_HI_100BASETX_EEE, CAPS_HI_100BASETX_EEE = 5,
CAPS_HI_RESERVED3, CAPS_HI_RESERVED3,
CAPS_HI_RESERVED4, CAPS_HI_RESERVED4,
CAPS_HI_1000BASET_FD_EEE, CAPS_HI_1000BASET_FD_EEE,
CAPS_HI_2P5GBASET_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_10GBASET_FD_EEE,
CAPS_HI_RESERVED5, CAPS_HI_FW_REQUEST,
CAPS_HI_RESERVED6, CAPS_HI_RESERVED6,
CAPS_HI_RESERVED7, CAPS_HI_RESERVED7,
CAPS_HI_RESERVED8, CAPS_HI_RESERVED8 = 15,
CAPS_HI_RESERVED9, CAPS_HI_RESERVED9,
CAPS_HI_CABLE_DIAG, CAPS_HI_CABLE_DIAG,
CAPS_HI_TEMPERATURE, CAPS_HI_TEMPERATURE,
CAPS_HI_DOWNSHIFT, CAPS_HI_DOWNSHIFT,
CAPS_HI_PTP_AVB_EN, CAPS_HI_PTP_AVB_EN_FW2X = 20,
CAPS_HI_MEDIA_DETECT, CAPS_HI_MEDIA_DETECT,
CAPS_HI_LINK_DROP, CAPS_HI_LINK_DROP,
CAPS_HI_SLEEP_PROXY, CAPS_HI_SLEEP_PROXY,
CAPS_HI_WOL, CAPS_HI_WOL,
CAPS_HI_MAC_STOP, CAPS_HI_MAC_STOP = 25,
CAPS_HI_EXT_LOOPBACK, CAPS_HI_EXT_LOOPBACK,
CAPS_HI_INT_LOOPBACK, CAPS_HI_INT_LOOPBACK,
CAPS_HI_EFUSE_AGENT, CAPS_HI_EFUSE_AGENT,
CAPS_HI_WOL_TIMER, CAPS_HI_WOL_TIMER,
CAPS_HI_STATISTICS, CAPS_HI_STATISTICS = 30,
CAPS_HI_TRANSACTION_ID, CAPS_HI_TRANSACTION_ID,
}; };
/* 0x36C
* Control register
*/
enum hw_atl_fw2x_ctrl { enum hw_atl_fw2x_ctrl {
CTRL_RESERVED1 = 0x00, CTRL_RESERVED1 = 0,
CTRL_RESERVED2, CTRL_RESERVED2,
CTRL_RESERVED3, CTRL_RESERVED3,
CTRL_PAUSE, CTRL_PAUSE,
CTRL_ASYMMETRIC_PAUSE, CTRL_ASYMMETRIC_PAUSE,
CTRL_RESERVED4, CTRL_RESERVED4 = 5,
CTRL_RESERVED5, CTRL_RESERVED5,
CTRL_RESERVED6, CTRL_RESERVED6,
CTRL_1GBASET_FD_EEE, CTRL_1GBASET_FD_EEE,
CTRL_2P5GBASET_FD_EEE, CTRL_2P5GBASET_FD_EEE,
CTRL_5GBASET_FD_EEE, CTRL_5GBASET_FD_EEE = 10,
CTRL_10GBASET_FD_EEE, CTRL_10GBASET_FD_EEE,
CTRL_THERMAL_SHUTDOWN, CTRL_THERMAL_SHUTDOWN,
CTRL_PHY_LOGS, CTRL_PHY_LOGS,
CTRL_EEE_AUTO_DISABLE, CTRL_EEE_AUTO_DISABLE,
CTRL_PFC, CTRL_PFC = 15,
CTRL_WAKE_ON_LINK, CTRL_WAKE_ON_LINK,
CTRL_CABLE_DIAG, CTRL_CABLE_DIAG,
CTRL_TEMPERATURE, CTRL_TEMPERATURE,
CTRL_DOWNSHIFT, CTRL_DOWNSHIFT,
CTRL_PTP_AVB, CTRL_PTP_AVB = 20,
CTRL_RESERVED7, CTRL_RESERVED7,
CTRL_LINK_DROP, CTRL_LINK_DROP,
CTRL_SLEEP_PROXY, CTRL_SLEEP_PROXY,
CTRL_WOL, CTRL_WOL,
CTRL_MAC_STOP, CTRL_MAC_STOP = 25,
CTRL_EXT_LOOPBACK, CTRL_EXT_LOOPBACK,
CTRL_INT_LOOPBACK, CTRL_INT_LOOPBACK,
CTRL_RESERVED8, CTRL_RESERVED8,
CTRL_WOL_TIMER, CTRL_WOL_TIMER,
CTRL_STATISTICS, CTRL_STATISTICS = 30,
CTRL_FORCE_RECONNECT, 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_hw_s;
struct aq_fw_ops; struct aq_fw_ops;
struct aq_hw_caps_s; struct aq_hw_caps_s;
...@@ -475,6 +605,8 @@ struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self); ...@@ -475,6 +605,8 @@ 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, int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
u32 *p, u32 cnt); u32 *p, u32 cnt);
int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, 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_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); int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size);
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* aQuantia Corporation Network Driver * 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 /* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
#define HW_ATL_FW2X_MPI_STATE_ADDR 0x370 #define HW_ATL_FW2X_MPI_STATE_ADDR 0x370
#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374 #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_PAUSE BIT(CAPS_HI_PAUSE)
#define HW_ATL_FW2X_CAP_ASYM_PAUSE BIT(CAPS_HI_ASYMMETRIC_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_SLEEP_PROXY BIT(CAPS_HI_SLEEP_PROXY)
...@@ -444,6 +447,54 @@ static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state, ...@@ -444,6 +447,54 @@ static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state,
return err; return err;
} }
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;
/* Write data to drvIface Mailbox */
dword_cnt = size / sizeof(u32);
if (size % sizeof(u32))
dword_cnt++;
err = hw_atl_utils_fw_upload_dwords(self, aq_fw2x_rpc_get(self),
(void *)fw_req, dword_cnt);
if (err < 0)
goto err_exit;
/* 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);
/* 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 void aq_fw3x_enable_ptp(struct aq_hw_s *self, int enable)
{
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 (enable)
ptp_opts |= all_ptp_features;
else
ptp_opts &= ~all_ptp_features;
aq_hw_write_reg(self, HW_ATL_FW3X_EXT_CONTROL_ADDR, ptp_opts);
}
static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed) static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed)
{ {
u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
...@@ -548,5 +599,7 @@ const struct aq_fw_ops aq_fw_2x_ops = { ...@@ -548,5 +599,7 @@ const struct aq_fw_ops aq_fw_2x_ops = {
.set_eee_rate = aq_fw2x_set_eee_rate, .set_eee_rate = aq_fw2x_set_eee_rate,
.get_eee_rate = aq_fw2x_get_eee_rate, .get_eee_rate = aq_fw2x_get_eee_rate,
.set_flow_control = aq_fw2x_set_flow_control, .set_flow_control = aq_fw2x_set_flow_control,
.get_flow_control = aq_fw2x_get_flow_control .get_flow_control = aq_fw2x_get_flow_control,
.send_fw_request = aq_fw2x_send_fw_request,
.enable_ptp = aq_fw3x_enable_ptp,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment