aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/marvell/octeontx2/bphy/otx2_rfoe.h
blob: da26a77d3cc6d6449e7e93ec9332490ef3470377 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
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