1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* Texas Instruments ICSSG Ethernet driver |
3 | * |
4 | * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ |
5 | * |
6 | */ |
7 | |
8 | #ifndef __NET_TI_ICSSG_PRUETH_H |
9 | #define __NET_TI_ICSSG_PRUETH_H |
10 | |
11 | #include <linux/etherdevice.h> |
12 | #include <linux/genalloc.h> |
13 | #include <linux/if_vlan.h> |
14 | #include <linux/interrupt.h> |
15 | #include <linux/kernel.h> |
16 | #include <linux/mfd/syscon.h> |
17 | #include <linux/module.h> |
18 | #include <linux/mutex.h> |
19 | #include <linux/net_tstamp.h> |
20 | #include <linux/of.h> |
21 | #include <linux/of_irq.h> |
22 | #include <linux/of_mdio.h> |
23 | #include <linux/of_net.h> |
24 | #include <linux/of_platform.h> |
25 | #include <linux/phy.h> |
26 | #include <linux/remoteproc/pruss.h> |
27 | #include <linux/pruss_driver.h> |
28 | #include <linux/ptp_clock_kernel.h> |
29 | #include <linux/remoteproc.h> |
30 | |
31 | #include <linux/dma-mapping.h> |
32 | #include <linux/dma/ti-cppi5.h> |
33 | #include <linux/dma/k3-udma-glue.h> |
34 | |
35 | #include <net/devlink.h> |
36 | |
37 | #include "icssg_config.h" |
38 | #include "icss_iep.h" |
39 | #include "icssg_switch_map.h" |
40 | |
41 | #define PRUETH_MAX_MTU (2000 - ETH_HLEN - ETH_FCS_LEN) |
42 | #define PRUETH_MIN_PKT_SIZE (VLAN_ETH_ZLEN) |
43 | #define PRUETH_MAX_PKT_SIZE (PRUETH_MAX_MTU + ETH_HLEN + ETH_FCS_LEN) |
44 | |
45 | #define ICSS_SLICE0 0 |
46 | #define ICSS_SLICE1 1 |
47 | |
48 | #define ICSS_FW_PRU 0 |
49 | #define ICSS_FW_RTU 1 |
50 | |
51 | #define ICSSG_MAX_RFLOWS 8 /* per slice */ |
52 | |
53 | /* Number of ICSSG related stats */ |
54 | #define ICSSG_NUM_STATS 60 |
55 | #define ICSSG_NUM_STANDARD_STATS 31 |
56 | #define ICSSG_NUM_ETHTOOL_STATS (ICSSG_NUM_STATS - ICSSG_NUM_STANDARD_STATS) |
57 | |
58 | /* Firmware status codes */ |
59 | #define ICSS_HS_FW_READY 0x55555555 |
60 | #define ICSS_HS_FW_DEAD 0xDEAD0000 /* lower 16 bits contain error code */ |
61 | |
62 | /* Firmware command codes */ |
63 | #define ICSS_HS_CMD_BUSY 0x40000000 |
64 | #define ICSS_HS_CMD_DONE 0x80000000 |
65 | #define ICSS_HS_CMD_CANCEL 0x10000000 |
66 | |
67 | /* Firmware commands */ |
68 | #define ICSS_CMD_SPAD 0x20 |
69 | #define ICSS_CMD_RXTX 0x10 |
70 | #define ICSS_CMD_ADD_FDB 0x1 |
71 | #define ICSS_CMD_DEL_FDB 0x2 |
72 | #define ICSS_CMD_SET_RUN 0x4 |
73 | #define ICSS_CMD_GET_FDB_SLOT 0x5 |
74 | #define ICSS_CMD_ENABLE_VLAN 0x5 |
75 | #define ICSS_CMD_DISABLE_VLAN 0x6 |
76 | #define ICSS_CMD_ADD_FILTER 0x7 |
77 | #define ICSS_CMD_ADD_MAC 0x8 |
78 | |
79 | /* In switch mode there are 3 real ports i.e. 3 mac addrs. |
80 | * however Linux sees only the host side port. The other 2 ports |
81 | * are the switch ports. |
82 | * In emac mode there are 2 real ports i.e. 2 mac addrs. |
83 | * Linux sees both the ports. |
84 | */ |
85 | enum prueth_port { |
86 | PRUETH_PORT_HOST = 0, /* host side port */ |
87 | PRUETH_PORT_MII0, /* physical port RG/SG MII 0 */ |
88 | PRUETH_PORT_MII1, /* physical port RG/SG MII 1 */ |
89 | PRUETH_PORT_INVALID, /* Invalid prueth port */ |
90 | }; |
91 | |
92 | enum prueth_mac { |
93 | PRUETH_MAC0 = 0, |
94 | PRUETH_MAC1, |
95 | PRUETH_NUM_MACS, |
96 | PRUETH_MAC_INVALID, |
97 | }; |
98 | |
99 | struct prueth_tx_chn { |
100 | struct device *dma_dev; |
101 | struct napi_struct napi_tx; |
102 | struct k3_cppi_desc_pool *desc_pool; |
103 | struct k3_udma_glue_tx_channel *tx_chn; |
104 | struct prueth_emac *emac; |
105 | u32 id; |
106 | u32 descs_num; |
107 | unsigned int irq; |
108 | char name[32]; |
109 | }; |
110 | |
111 | struct prueth_rx_chn { |
112 | struct device *dev; |
113 | struct device *dma_dev; |
114 | struct k3_cppi_desc_pool *desc_pool; |
115 | struct k3_udma_glue_rx_channel *rx_chn; |
116 | u32 descs_num; |
117 | unsigned int irq[ICSSG_MAX_RFLOWS]; /* separate irq per flow */ |
118 | char name[32]; |
119 | }; |
120 | |
121 | /* There are 4 Tx DMA channels, but the highest priority is CH3 (thread 3) |
122 | * and lower three are lower priority channels or threads. |
123 | */ |
124 | #define PRUETH_MAX_TX_QUEUES 4 |
125 | |
126 | #define PRUETH_MAX_TX_TS_REQUESTS 50 /* Max simultaneous TX_TS requests */ |
127 | |
128 | /* data for each emac port */ |
129 | struct prueth_emac { |
130 | bool fw_running; |
131 | struct prueth *prueth; |
132 | struct net_device *ndev; |
133 | u8 mac_addr[6]; |
134 | struct napi_struct napi_rx; |
135 | u32 msg_enable; |
136 | |
137 | int link; |
138 | int speed; |
139 | int duplex; |
140 | |
141 | const char *phy_id; |
142 | struct device_node *phy_node; |
143 | phy_interface_t phy_if; |
144 | enum prueth_port port_id; |
145 | struct icss_iep *iep; |
146 | unsigned int rx_ts_enabled : 1; |
147 | unsigned int tx_ts_enabled : 1; |
148 | unsigned int half_duplex : 1; |
149 | |
150 | /* DMA related */ |
151 | struct prueth_tx_chn tx_chns[PRUETH_MAX_TX_QUEUES]; |
152 | struct completion tdown_complete; |
153 | atomic_t tdown_cnt; |
154 | struct prueth_rx_chn rx_chns; |
155 | int rx_flow_id_base; |
156 | int tx_ch_num; |
157 | |
158 | spinlock_t lock; /* serialize access */ |
159 | |
160 | /* TX HW Timestamping */ |
161 | /* TX TS cookie will be index to the tx_ts_skb array */ |
162 | struct sk_buff *tx_ts_skb[PRUETH_MAX_TX_TS_REQUESTS]; |
163 | atomic_t tx_ts_pending; |
164 | int tx_ts_irq; |
165 | |
166 | u8 cmd_seq; |
167 | /* shutdown related */ |
168 | u32 cmd_data[4]; |
169 | struct completion cmd_complete; |
170 | /* Mutex to serialize access to firmware command interface */ |
171 | struct mutex cmd_lock; |
172 | struct work_struct rx_mode_work; |
173 | struct workqueue_struct *cmd_wq; |
174 | |
175 | struct pruss_mem_region dram; |
176 | |
177 | struct delayed_work stats_work; |
178 | u64 stats[ICSSG_NUM_STATS]; |
179 | }; |
180 | |
181 | /** |
182 | * struct prueth_pdata - PRUeth platform data |
183 | * @fdqring_mode: Free desc queue mode |
184 | * @quirk_10m_link_issue: 10M link detect errata |
185 | */ |
186 | struct prueth_pdata { |
187 | enum k3_ring_mode fdqring_mode; |
188 | u32 quirk_10m_link_issue:1; |
189 | }; |
190 | |
191 | /** |
192 | * struct prueth - PRUeth structure |
193 | * @dev: device |
194 | * @pruss: pruss handle |
195 | * @pru: rproc instances of PRUs |
196 | * @rtu: rproc instances of RTUs |
197 | * @txpru: rproc instances of TX_PRUs |
198 | * @shram: PRUSS shared RAM region |
199 | * @sram_pool: MSMC RAM pool for buffers |
200 | * @msmcram: MSMC RAM region |
201 | * @eth_node: DT node for the port |
202 | * @emac: private EMAC data structure |
203 | * @registered_netdevs: list of registered netdevs |
204 | * @miig_rt: regmap to mii_g_rt block |
205 | * @mii_rt: regmap to mii_rt block |
206 | * @pru_id: ID for each of the PRUs |
207 | * @pdev: pointer to ICSSG platform device |
208 | * @pdata: pointer to platform data for ICSSG driver |
209 | * @icssg_hwcmdseq: seq counter or HWQ messages |
210 | * @emacs_initialized: num of EMACs/ext ports that are up/running |
211 | * @iep0: pointer to IEP0 device |
212 | * @iep1: pointer to IEP1 device |
213 | */ |
214 | struct prueth { |
215 | struct device *dev; |
216 | struct pruss *pruss; |
217 | struct rproc *pru[PRUSS_NUM_PRUS]; |
218 | struct rproc *rtu[PRUSS_NUM_PRUS]; |
219 | struct rproc *txpru[PRUSS_NUM_PRUS]; |
220 | struct pruss_mem_region shram; |
221 | struct gen_pool *sram_pool; |
222 | struct pruss_mem_region msmcram; |
223 | |
224 | struct device_node *eth_node[PRUETH_NUM_MACS]; |
225 | struct prueth_emac *emac[PRUETH_NUM_MACS]; |
226 | struct net_device *registered_netdevs[PRUETH_NUM_MACS]; |
227 | struct regmap *miig_rt; |
228 | struct regmap *mii_rt; |
229 | |
230 | enum pruss_pru_id pru_id[PRUSS_NUM_PRUS]; |
231 | struct platform_device *pdev; |
232 | struct prueth_pdata pdata; |
233 | u8 icssg_hwcmdseq; |
234 | int emacs_initialized; |
235 | struct icss_iep *iep0; |
236 | struct icss_iep *iep1; |
237 | }; |
238 | |
239 | struct emac_tx_ts_response { |
240 | u32 reserved[2]; |
241 | u32 cookie; |
242 | u32 lo_ts; |
243 | u32 hi_ts; |
244 | }; |
245 | |
246 | /* get PRUSS SLICE number from prueth_emac */ |
247 | static inline int prueth_emac_slice(struct prueth_emac *emac) |
248 | { |
249 | switch (emac->port_id) { |
250 | case PRUETH_PORT_MII0: |
251 | return ICSS_SLICE0; |
252 | case PRUETH_PORT_MII1: |
253 | return ICSS_SLICE1; |
254 | default: |
255 | return -EINVAL; |
256 | } |
257 | } |
258 | |
259 | extern const struct ethtool_ops icssg_ethtool_ops; |
260 | |
261 | /* Classifier helpers */ |
262 | void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac); |
263 | void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac); |
264 | void icssg_class_disable(struct regmap *miig_rt, int slice); |
265 | void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti); |
266 | void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr); |
267 | |
268 | /* config helpers */ |
269 | void icssg_config_ipg(struct prueth_emac *emac); |
270 | int icssg_config(struct prueth *prueth, struct prueth_emac *emac, |
271 | int slice); |
272 | int emac_set_port_state(struct prueth_emac *emac, |
273 | enum icssg_port_state_cmd state); |
274 | void icssg_config_set_speed(struct prueth_emac *emac); |
275 | void icssg_config_half_duplex(struct prueth_emac *emac); |
276 | |
277 | /* Buffer queue helpers */ |
278 | int icssg_queue_pop(struct prueth *prueth, u8 queue); |
279 | void icssg_queue_push(struct prueth *prueth, int queue, u16 addr); |
280 | u32 icssg_queue_level(struct prueth *prueth, int queue); |
281 | |
282 | #define prueth_napi_to_tx_chn(pnapi) \ |
283 | container_of(pnapi, struct prueth_tx_chn, napi_tx) |
284 | |
285 | void emac_stats_work_handler(struct work_struct *work); |
286 | void emac_update_hardware_stats(struct prueth_emac *emac); |
287 | int emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name); |
288 | #endif /* __NET_TI_ICSSG_PRUETH_H */ |
289 | |