summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/ti/am65-cpsw-nuss.h
blob: dc8d544230dc81d2f075e854825b9d4189320ccf (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
228
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
 *
 */

#ifndef AM65_CPSW_NUSS_H_
#define AM65_CPSW_NUSS_H_

#include <linux/if_ether.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phylink.h>
#include <linux/platform_device.h>
#include <linux/soc/ti/k3-ringacc.h>
#include <net/devlink.h>
#include <net/xdp.h>
#include "am65-cpsw-qos.h"

struct am65_cpts;

#define HOST_PORT_NUM		0

#define AM65_CPSW_MAX_QUEUES	8	/* both TX & RX */

#define AM65_CPSW_PORT_VLAN_REG_OFFSET	0x014

struct am65_cpsw_slave_data {
	bool				mac_only;
	struct cpsw_sl			*mac_sl;
	struct device_node		*port_np;
	phy_interface_t			phy_if;
	struct phy			*ifphy;
	struct phy			*serdes_phy;
	bool				rx_pause;
	bool				tx_pause;
	u8				mac_addr[ETH_ALEN];
	int				port_vlan;
	struct phylink			*phylink;
	struct phylink_config		phylink_config;
};

struct am65_cpsw_port {
	struct am65_cpsw_common		*common;
	struct net_device		*ndev;
	const char			*name;
	u32				port_id;
	void __iomem			*port_base;
	void __iomem			*sgmii_base;
	void __iomem			*stat_base;
	void __iomem			*fetch_ram_base;
	bool				disabled;
	struct am65_cpsw_slave_data	slave;
	bool				tx_ts_enabled;
	bool				rx_ts_enabled;
	struct am65_cpsw_qos		qos;
	struct devlink_port		devlink_port;
	struct bpf_prog			*xdp_prog;
	struct xdp_rxq_info		xdp_rxq[AM65_CPSW_MAX_QUEUES];
	/* Only for suspend resume context */
	u32				vid_context;
};

enum am65_cpsw_tx_buf_type {
	AM65_CPSW_TX_BUF_TYPE_SKB,
	AM65_CPSW_TX_BUF_TYPE_XDP_TX,
	AM65_CPSW_TX_BUF_TYPE_XDP_NDO,
};

struct am65_cpsw_host {
	struct am65_cpsw_common		*common;
	void __iomem			*port_base;
	void __iomem			*stat_base;
	/* Only for suspend resume context */
	u32				vid_context;
};

struct am65_cpsw_tx_chn {
	struct device *dma_dev;
	struct napi_struct napi_tx;
	struct am65_cpsw_common	*common;
	struct k3_cppi_desc_pool *desc_pool;
	struct k3_udma_glue_tx_channel *tx_chn;
	spinlock_t lock; /* protect TX rings in multi-port mode */
	struct hrtimer tx_hrtimer;
	unsigned long tx_pace_timeout;
	int irq;
	u32 id;
	u32 descs_num;
	unsigned char dsize_log2;
	char tx_chn_name[128];
	u32 rate_mbps;
};

struct am65_cpsw_rx_flow {
	u32 id;
	struct napi_struct napi_rx;
	struct am65_cpsw_common	*common;
	int irq;
	bool irq_disabled;
	struct hrtimer rx_hrtimer;
	unsigned long rx_pace_timeout;
	struct page_pool *page_pool;
	struct page **pages;
	char name[32];
};

struct am65_cpsw_rx_chn {
	struct device *dev;
	struct device *dma_dev;
	struct k3_cppi_desc_pool *desc_pool;
	struct k3_udma_glue_rx_channel *rx_chn;
	u32 descs_num;
	unsigned char dsize_log2;
	struct am65_cpsw_rx_flow flows[AM65_CPSW_MAX_QUEUES];
};

#define AM65_CPSW_QUIRK_I2027_NO_TX_CSUM BIT(0)
#define AM64_CPSW_QUIRK_DMA_RX_TDOWN_IRQ BIT(1)

struct am65_cpsw_pdata {
	u32	quirks;
	u64	extra_modes;
	enum k3_ring_mode fdqring_mode;
	const char	*ale_dev_id;
};

enum cpsw_devlink_param_id {
	AM65_CPSW_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
	AM65_CPSW_DL_PARAM_SWITCH_MODE,
};

struct am65_cpsw_devlink {
	struct am65_cpsw_common *common;
};

struct am65_cpsw_common {
	struct device		*dev;
	struct device		*mdio_dev;
	struct am65_cpsw_pdata	pdata;

	void __iomem		*ss_base;
	void __iomem		*cpsw_base;

	u32			port_num;
	struct am65_cpsw_host   host;
	struct am65_cpsw_port	*ports;
	u32			disabled_ports_mask;
	struct net_device	*dma_ndev;

	int			usage_count; /* number of opened ports */
	struct cpsw_ale		*ale;
	int			tx_ch_num;
	u32			tx_ch_rate_msk;
	u32			rx_flow_id_base;

	struct am65_cpsw_tx_chn	tx_chns[AM65_CPSW_MAX_QUEUES];
	struct completion	tdown_complete;
	atomic_t		tdown_cnt;

	int			rx_ch_num_flows;
	struct am65_cpsw_rx_chn	rx_chns;

	u32			nuss_ver;
	u32			cpsw_ver;
	unsigned long		bus_freq;
	bool			pf_p0_rx_ptype_rrobin;
	struct am65_cpts	*cpts;
	int			est_enabled;
	bool			iet_enabled;

	bool		is_emac_mode;
	u16			br_members;
	int			default_vlan;
	struct devlink *devlink;
	struct net_device *hw_bridge_dev;
	struct notifier_block am65_cpsw_netdevice_nb;
	unsigned char switch_id[MAX_PHYS_ITEM_ID_LEN];
	/* only for suspend/resume context restore */
	u32			*ale_context;
};

struct am65_cpsw_ndev_stats {
	u64 tx_packets;
	u64 tx_bytes;
	u64 rx_packets;
	u64 rx_bytes;
	struct u64_stats_sync syncp;
};

struct am65_cpsw_ndev_priv {
	u32			msg_enable;
	struct am65_cpsw_port	*port;
	struct am65_cpsw_ndev_stats __percpu *stats;
	bool offload_fwd_mark;
	/* Serialize access to MAC Merge state between ethtool requests
	 * and link state updates
	 */
	struct mutex		mm_lock;
};

#define am65_ndev_to_priv(ndev) \
	((struct am65_cpsw_ndev_priv *)netdev_priv(ndev))
#define am65_ndev_to_port(ndev) (am65_ndev_to_priv(ndev)->port)
#define am65_ndev_to_common(ndev) (am65_ndev_to_port(ndev)->common)
#define am65_ndev_to_slave(ndev) (&am65_ndev_to_port(ndev)->slave)

#define am65_common_get_host(common) (&(common)->host)
#define am65_common_get_port(common, id) (&(common)->ports[(id) - 1])

#define am65_cpsw_napi_to_rx_flow(pnapi) \
	container_of(pnapi, struct am65_cpsw_rx_flow, napi_rx)
#define am65_cpsw_napi_to_tx_chn(pnapi) \
	container_of(pnapi, struct am65_cpsw_tx_chn, napi_tx)

#define AM65_CPSW_DRV_NAME "am65-cpsw-nuss"

#define AM65_CPSW_IS_CPSW2G(common) ((common)->port_num == 1)

extern const struct ethtool_ops am65_cpsw_ethtool_ops_slave;

void am65_cpsw_nuss_set_p0_ptype(struct am65_cpsw_common *common);
int am65_cpsw_nuss_update_tx_rx_chns(struct am65_cpsw_common *common,
				     int num_tx, int num_rx);

bool am65_cpsw_port_dev_check(const struct net_device *dev);

#endif /* AM65_CPSW_NUSS_H_ */