aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/marvell/octeontx2/bphy/otx2_rfoe.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/marvell/octeontx2/bphy/otx2_rfoe.h')
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/bphy/otx2_rfoe.h227
1 files changed, 227 insertions, 0 deletions
diff --git a/drivers/net/ethernet/marvell/octeontx2/bphy/otx2_rfoe.h b/drivers/net/ethernet/marvell/octeontx2/bphy/otx2_rfoe.h
new file mode 100644
index 000000000000..da26a77d3cc6
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/bphy/otx2_rfoe.h
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Marvell OcteonTx2 BPHY RFOE/CPRI Ethernet Driver
+ *
+ * Copyright (C) 2020 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _OTX2_RFOE_H_
+#define _OTX2_RFOE_H_
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/iommu.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_ether.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/if_vlan.h>
+
+#include "otx2_bphy.h"
+#include "rfoe_common.h"
+
+#define RFOE_RX_INTR_SHIFT(a) (32 - ((a) + 1) * 3)
+#define RFOE_RX_INTR_MASK(a) (RFOE_RX_INTR_EN << \
+ RFOE_RX_INTR_SHIFT(a))
+#define RFOE_TX_PTP_INTR_MASK(a, b) (1UL << ((a) * 4 + (b)))
+
+#define MAX_RFOE_INTF 3 /* Max RFOE instances */
+#define RFOE_MAX_INTF 10 /* 2 rfoe x 4 lmac + 1 rfoe x 2 lmac */
+#define PCI_SUBSYS_DEVID_OCTX2_95XXN 0xB400
+
+/* ethtool msg */
+#define OTX2_RFOE_MSG_DEFAULT (NETIF_MSG_DRV)
+
+/* PTP clock time operates by adding a constant increment every clock
+ * cycle. That increment is expressed (MIO_PTP_CLOCK_COMP) as a Q32.32
+ * number of nanoseconds (32 integer bits and 32 fractional bits). The
+ * value must be equal to 1/(PTP clock frequency in Hz). If the PTP clock
+ * freq is 1 GHz, there is no issue but for other input clock frequency
+ * values for example 950 MHz which is SLCK or 153.6 MHz (bcn_clk/2) the
+ * MIO_PTP_CLOCK_COMP register value can't be expressed exactly and there
+ * will be error accumulated over the time depending on the direction the
+ * PTP_CLOCK_COMP value is rounded. The accumulated error will be around
+ * -70ps or +150ps per second in case of 950 MHz.
+ *
+ * To solve this issue, the driver calculates the PTP timestamps using
+ * BCN clock as reference as per the algorithm proposed as given below.
+ *
+ * Set PTP tick (= MIO_PTP_CLOCK_COMP) to 1.0 ns
+ * Sample once, at exactly the same time, BCN and PTP to (BCN0, PTP0).
+ * Calculate (applying BCN-to-PTP epoch difference and an OAM parameter
+ * secondaryBcnOffset)
+ * PTPbase[ns] = NanoSec(BCN0) + NanoSec(315964819[s]) - secondaryBcnOffset[ns]
+ * When reading packet timestamp (tick count) PTPn, convert it to nanoseconds.
+ * PTP pkt timestamp = PTPbase[ns] + (PTPn - PTP0) / (PTP Clock in GHz)
+ *
+ * The intermediate values generated need to be of pico-second precision to
+ * achieve PTP accuracy < 1ns. The calculations should not overflow 64-bit
+ * value at anytime. Added timer to adjust the PTP and BCN base values
+ * periodically to fix the overflow issue.
+ */
+#define PTP_CLK_FREQ_GHZ 95 /* Clock freq GHz dividend */
+#define PTP_CLK_FREQ_DIV 100 /* Clock freq GHz divisor */
+#define PTP_OFF_RESAMPLE_THRESH 1800 /* resample period in seconds */
+#define PICO_SEC_PER_NSEC 1000 /* pico seconds per nano sec */
+#define UTC_GPS_EPOCH_DIFF 315964819UL /* UTC - GPS epoch secs */
+
+/* global driver context */
+struct otx2_rfoe_drv_ctx {
+ u8 rfoe_num;
+ u8 lmac_id;
+ int valid;
+ struct net_device *netdev;
+ struct rx_ft_cfg *ft_cfg;
+ int tx_gpint_bit;
+ void *debugfs;
+};
+
+extern struct otx2_rfoe_drv_ctx rfoe_drv_ctx[RFOE_MAX_INTF];
+
+/* rx flow table configuration */
+struct rx_ft_cfg {
+ enum bphy_netdev_packet_type pkt_type; /* pkt_type for psw */
+ enum bphy_netdev_rx_gpint gp_int_num;
+ u16 flow_id; /* flow id */
+ u16 mbt_idx; /* mbt index */
+ u16 buf_size; /* mbt buf size */
+ u16 num_bufs; /* mbt num bufs */
+ u64 mbt_iova_addr;
+ void __iomem *mbt_virt_addr;
+ u16 jdt_idx; /* jdt index */
+ u8 jd_size; /* jd size */
+ u16 num_jd; /* num jd's */
+ u64 jdt_iova_addr;
+ void __iomem *jdt_virt_addr;
+ u8 jd_rd_offset; /* jd rd offset */
+ u8 pkt_offset;
+ struct napi_struct napi;
+ struct otx2_rfoe_ndev_priv *priv;
+};
+
+/* PTP clk freq in GHz represented as integer numbers.
+ * This information is passed to netdev by the ODP BPHY
+ * application via ioctl. The values are used in PTP
+ * timestamp calculation algorithm.
+ *
+ * For 950MHz PTP clock =0.95GHz, the values are:
+ * clk_freq_ghz = 95
+ * clk_freq_div = 100
+ *
+ * For 153.6MHz PTP clock =0.1536GHz, the values are:
+ * clk_freq_ghz = 1536
+ * clk_freq_div = 10000
+ *
+ */
+struct ptp_clk_cfg {
+ int clk_freq_ghz; /* ptp clk freq */
+ int clk_freq_div; /* ptp clk divisor */
+};
+
+struct bcn_sec_offset_cfg {
+ u8 rfoe_num;
+ u8 lmac_id;
+ s32 sec_bcn_offset;
+};
+
+struct ptp_bcn_ref {
+ u64 ptp0_ns; /* PTP nanosec */
+ u64 bcn0_n1_ns; /* BCN N1 nanosec */
+ u64 bcn0_n2_ps; /* BCN N2 picosec */
+};
+
+struct ptp_bcn_off_cfg {
+ struct ptp_bcn_ref old_ref;
+ struct ptp_bcn_ref new_ref;
+ struct ptp_clk_cfg clk_cfg;
+ struct timer_list ptp_timer;
+ int use_ptp_alg;
+ u8 refcnt;
+ /* protection lock for updating ref */
+ spinlock_t lock;
+};
+
+/* netdev priv */
+struct otx2_rfoe_ndev_priv {
+ u8 rfoe_num;
+ u8 lmac_id;
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct otx2_bphy_cdev_priv *cdev_priv;
+ u32 msg_enable;
+ u32 ptp_ext_clk_rate;
+ void __iomem *bphy_reg_base;
+ void __iomem *psm_reg_base;
+ void __iomem *rfoe_reg_base;
+ void __iomem *bcn_reg_base;
+ void __iomem *ptp_reg_base;
+ struct iommu_domain *iommu_domain;
+ struct rx_ft_cfg rx_ft_cfg[PACKET_TYPE_MAX];
+ struct tx_job_queue_cfg tx_ptp_job_cfg;
+ struct rfoe_common_cfg *rfoe_common;
+ u8 pkt_type_mask;
+ /* priv lock */
+ spinlock_t lock;
+ int rx_hw_tstamp_en;
+ int tx_hw_tstamp_en;
+ struct sk_buff *ptp_tx_skb;
+ u16 ptp_job_tag;
+ struct timer_list tx_timer;
+ unsigned long state;
+ struct work_struct ptp_tx_work;
+ struct work_struct ptp_queue_work;
+ struct ptp_tx_skb_list ptp_skb_list;
+ struct ptp_clock *ptp_clock;
+ struct ptp_clock_info ptp_clock_info;
+ struct cyclecounter cycle_counter;
+ struct timecounter time_counter;
+
+ struct delayed_work extts_work;
+ u64 last_extts;
+ u64 thresh;
+
+ struct ptp_pin_desc extts_config;
+ /* ptp lock */
+ struct mutex ptp_lock;
+ struct otx2_rfoe_stats stats;
+ u8 mac_addr[ETH_ALEN];
+ struct ptp_bcn_off_cfg *ptp_cfg;
+ s32 sec_bcn_offset;
+ int if_type;
+ u8 link_state;
+ unsigned long last_tx_jiffies;
+ unsigned long last_tx_ptp_jiffies;
+ unsigned long last_rx_jiffies;
+ unsigned long last_rx_ptp_jiffies;
+ unsigned long last_tx_dropped_jiffies;
+ unsigned long last_tx_ptp_dropped_jiffies;
+ unsigned long last_rx_dropped_jiffies;
+ unsigned long last_rx_ptp_dropped_jiffies;
+};
+
+void otx2_rfoe_rx_napi_schedule(int rfoe_num, u32 status);
+
+int otx2_rfoe_parse_and_init_intf(struct otx2_bphy_cdev_priv *cdev,
+ struct bphy_netdev_comm_intf_cfg *cfg);
+
+void otx2_bphy_rfoe_cleanup(void);
+
+void otx2_rfoe_disable_intf(int rfoe_num);
+
+/* ethtool */
+void otx2_rfoe_set_ethtool_ops(struct net_device *netdev);
+
+/* ptp */
+void otx2_rfoe_calc_ptp_ts(struct otx2_rfoe_ndev_priv *priv, u64 *ts);
+int otx2_rfoe_ptp_init(struct otx2_rfoe_ndev_priv *priv);
+void otx2_rfoe_ptp_destroy(struct otx2_rfoe_ndev_priv *priv);
+
+/* update carrier state */
+void otx2_rfoe_set_link_state(struct net_device *netdev, u8 state);
+
+#endif