aboutsummaryrefslogtreecommitdiffstats
blob: de98be1b79f918e5d1f75686b9efe3c3ad7274a7 (plain) (blame)
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
/* 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/debugfs.h>
#include <linux/if_ether.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/soc/ti/k3-ringacc.h>
#include <net/devlink.h>
#include "am65-cpsw-qos.h"

struct am65_cpts;

#define HOST_PORT_NUM		0

#define AM65_CPSW_MAX_TX_QUEUES	8
#define AM65_CPSW_MAX_RX_QUEUES	1
#define AM65_CPSW_MAX_RX_FLOWS	1

#define AM65_CPSW_PORT_VLAN_REG_OFFSET	0x014

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

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			*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 dentry			*debugfs_port;
};

struct am65_cpsw_host {
	struct am65_cpsw_common		*common;
	void __iomem			*port_base;
	void __iomem			*stat_base;
};

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 */
	int irq;
	u32 id;
	u32 descs_num;
	char tx_chn_name[128];
};

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;
	int irq;
};

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

struct am65_cpsw_pdata {
	u32	quirks;
	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			rx_flow_id_base;

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

	struct am65_cpsw_rx_chn	rx_chns;
	struct napi_struct	napi_rx;

	bool			rx_irq_disabled;

	u32			nuss_ver;
	u32			cpsw_ver;
	unsigned long		bus_freq;
	bool			pf_p0_rx_ptype_rrobin;
	struct am65_cpts	*cpts;
	int			est_enabled;
	int			iet_enabled;
	unsigned int		cut_thru_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];

	struct dentry		*debugfs_root;
};

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;
};

#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_common(pnapi) \
	container_of(pnapi, struct am65_cpsw_common, 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_adjust_link(struct net_device *ndev);
void am65_cpsw_nuss_set_p0_ptype(struct am65_cpsw_common *common);
void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common);
int am65_cpsw_nuss_update_tx_chns(struct am65_cpsw_common *common, int num_tx);

bool am65_cpsw_port_dev_check(const struct net_device *dev);

int am65_cpsw_nuss_register_port_debugfs(struct am65_cpsw_port *port);
int am65_cpsw_nuss_register_debugfs(struct am65_cpsw_common *common);
void am65_cpsw_nuss_unregister_debugfs(struct am65_cpsw_common *common);

#endif /* AM65_CPSW_NUSS_H_ */