xref: /linux/drivers/net/ethernet/ti/icssg/icssg_config.c (revision 9a95c5bfbf02a0a7f5983280fe284a0ff0836c34)
1 // SPDX-License-Identifier: GPL-2.0
2 /* ICSSG Ethernet driver
3  *
4  * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com
5  */
6 
7 #include <linux/iopoll.h>
8 #include <linux/regmap.h>
9 #include <uapi/linux/if_ether.h>
10 #include "icssg_config.h"
11 #include "icssg_prueth.h"
12 #include "icssg_switch_map.h"
13 #include "icssg_mii_rt.h"
14 
15 /* TX IPG Values to be set for 100M link speed. These values are
16  * in ocp_clk cycles. So need change if ocp_clk is changed for a specific
17  * h/w design.
18  */
19 
20 /* IPG is in core_clk cycles */
21 #define MII_RT_TX_IPG_100M	0x17
22 #define MII_RT_TX_IPG_1G	0xb
23 #define MII_RT_TX_IPG_100M_SR1	0x166
24 #define MII_RT_TX_IPG_1G_SR1	0x1a
25 
26 #define	ICSSG_QUEUES_MAX		64
27 #define	ICSSG_QUEUE_OFFSET		0xd00
28 #define	ICSSG_QUEUE_PEEK_OFFSET		0xe00
29 #define	ICSSG_QUEUE_CNT_OFFSET		0xe40
30 #define	ICSSG_QUEUE_RESET_OFFSET	0xf40
31 
32 #define	ICSSG_NUM_TX_QUEUES	8
33 
34 #define	RECYCLE_Q_SLICE0	16
35 #define	RECYCLE_Q_SLICE1	17
36 
37 #define	ICSSG_NUM_OTHER_QUEUES	5	/* port, host and special queues */
38 
39 #define	PORT_HI_Q_SLICE0	32
40 #define	PORT_LO_Q_SLICE0	33
41 #define	HOST_HI_Q_SLICE0	34
42 #define	HOST_LO_Q_SLICE0	35
43 #define	HOST_SPL_Q_SLICE0	40	/* Special Queue */
44 
45 #define	PORT_HI_Q_SLICE1	36
46 #define	PORT_LO_Q_SLICE1	37
47 #define	HOST_HI_Q_SLICE1	38
48 #define	HOST_LO_Q_SLICE1	39
49 #define	HOST_SPL_Q_SLICE1	41	/* Special Queue */
50 
51 #define MII_RXCFG_DEFAULT	(PRUSS_MII_RT_RXCFG_RX_ENABLE | \
52 				 PRUSS_MII_RT_RXCFG_RX_DATA_RDY_MODE_DIS | \
53 				 PRUSS_MII_RT_RXCFG_RX_L2_EN | \
54 				 PRUSS_MII_RT_RXCFG_RX_L2_EOF_SCLR_DIS)
55 
56 #define MII_TXCFG_DEFAULT	(PRUSS_MII_RT_TXCFG_TX_ENABLE | \
57 				 PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE | \
58 				 PRUSS_MII_RT_TXCFG_TX_32_MODE_EN | \
59 				 PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN)
60 
61 #define ICSSG_CFG_DEFAULT	(ICSSG_CFG_TX_L1_EN | \
62 				 ICSSG_CFG_TX_L2_EN | ICSSG_CFG_RX_L2_G_EN | \
63 				 ICSSG_CFG_TX_PRU_EN | \
64 				 ICSSG_CFG_SGMII_MODE)
65 
66 #define FDB_GEN_CFG1		0x60
67 #define SMEM_VLAN_OFFSET	8
68 #define SMEM_VLAN_OFFSET_MASK	GENMASK(25, 8)
69 
70 #define FDB_GEN_CFG2		0x64
71 #define FDB_VLAN_EN		BIT(6)
72 #define FDB_HOST_EN		BIT(2)
73 #define FDB_PRU1_EN		BIT(1)
74 #define FDB_PRU0_EN		BIT(0)
75 #define FDB_EN_ALL		(FDB_PRU0_EN | FDB_PRU1_EN | \
76 				 FDB_HOST_EN | FDB_VLAN_EN)
77 
78 /**
79  * struct map - ICSSG Queue Map
80  * @queue: Queue number
81  * @pd_addr_start: Packet descriptor queue reserved memory
82  * @flags: Flags
83  * @special: Indicates whether this queue is a special queue or not
84  */
85 struct map {
86 	int queue;
87 	u32 pd_addr_start;
88 	u32 flags;
89 	bool special;
90 };
91 
92 /* Hardware queue map for ICSSG */
93 static const struct map hwq_map[2][ICSSG_NUM_OTHER_QUEUES] = {
94 	{
95 		{ PORT_HI_Q_SLICE0, PORT_DESC0_HI, 0x200000, 0 },
96 		{ PORT_LO_Q_SLICE0, PORT_DESC0_LO, 0, 0 },
97 		{ HOST_HI_Q_SLICE0, HOST_DESC0_HI, 0x200000, 0 },
98 		{ HOST_LO_Q_SLICE0, HOST_DESC0_LO, 0, 0 },
99 		{ HOST_SPL_Q_SLICE0, HOST_SPPD0, 0x400000, 1 },
100 	},
101 	{
102 		{ PORT_HI_Q_SLICE1, PORT_DESC1_HI, 0xa00000, 0 },
103 		{ PORT_LO_Q_SLICE1, PORT_DESC1_LO, 0x800000, 0 },
104 		{ HOST_HI_Q_SLICE1, HOST_DESC1_HI, 0xa00000, 0 },
105 		{ HOST_LO_Q_SLICE1, HOST_DESC1_LO, 0x800000, 0 },
106 		{ HOST_SPL_Q_SLICE1, HOST_SPPD1, 0xc00000, 1 },
107 	},
108 };
109 
110 static void icssg_config_mii_init(struct prueth_emac *emac)
111 {
112 	u32 rxcfg, txcfg, rxcfg_reg, txcfg_reg, pcnt_reg;
113 	struct prueth *prueth = emac->prueth;
114 	int slice = prueth_emac_slice(emac);
115 	struct regmap *mii_rt;
116 
117 	mii_rt = prueth->mii_rt;
118 
119 	rxcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RXCFG0 :
120 				       PRUSS_MII_RT_RXCFG1;
121 	txcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_TXCFG0 :
122 				       PRUSS_MII_RT_TXCFG1;
123 	pcnt_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RX_PCNT0 :
124 				       PRUSS_MII_RT_RX_PCNT1;
125 
126 	rxcfg = MII_RXCFG_DEFAULT;
127 	txcfg = MII_TXCFG_DEFAULT;
128 
129 	if (slice == ICSS_MII1)
130 		rxcfg |= PRUSS_MII_RT_RXCFG_RX_MUX_SEL;
131 
132 	/* In MII mode TX lines swapped inside ICSSG, so TX_MUX_SEL cfg need
133 	 * to be swapped also comparing to RGMII mode.
134 	 */
135 	if (emac->phy_if == PHY_INTERFACE_MODE_MII && slice == ICSS_MII0)
136 		txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL;
137 	else if (emac->phy_if != PHY_INTERFACE_MODE_MII && slice == ICSS_MII1)
138 		txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL;
139 
140 	regmap_write(mii_rt, rxcfg_reg, rxcfg);
141 	regmap_write(mii_rt, txcfg_reg, txcfg);
142 	regmap_write(mii_rt, pcnt_reg, 0x1);
143 }
144 
145 static void icssg_miig_queues_init(struct prueth *prueth, int slice)
146 {
147 	struct regmap *miig_rt = prueth->miig_rt;
148 	void __iomem *smem = prueth->shram.va;
149 	u8 pd[ICSSG_SPECIAL_PD_SIZE];
150 	int queue = 0, i, j;
151 	u32 *pdword;
152 
153 	/* reset hwqueues */
154 	if (slice)
155 		queue = ICSSG_NUM_TX_QUEUES;
156 
157 	for (i = 0; i < ICSSG_NUM_TX_QUEUES; i++) {
158 		regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue);
159 		queue++;
160 	}
161 
162 	queue = slice ? RECYCLE_Q_SLICE1 : RECYCLE_Q_SLICE0;
163 	regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue);
164 
165 	for (i = 0; i < ICSSG_NUM_OTHER_QUEUES; i++) {
166 		regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET,
167 			     hwq_map[slice][i].queue);
168 	}
169 
170 	/* initialize packet descriptors in SMEM */
171 	/* push pakcet descriptors to hwqueues */
172 
173 	pdword = (u32 *)pd;
174 	for (j = 0; j < ICSSG_NUM_OTHER_QUEUES; j++) {
175 		const struct map *mp;
176 		int pd_size, num_pds;
177 		u32 pdaddr;
178 
179 		mp = &hwq_map[slice][j];
180 		if (mp->special) {
181 			pd_size = ICSSG_SPECIAL_PD_SIZE;
182 			num_pds = ICSSG_NUM_SPECIAL_PDS;
183 		} else	{
184 			pd_size = ICSSG_NORMAL_PD_SIZE;
185 			num_pds = ICSSG_NUM_NORMAL_PDS;
186 		}
187 
188 		for (i = 0; i < num_pds; i++) {
189 			memset(pd, 0, pd_size);
190 
191 			pdword[0] &= ICSSG_FLAG_MASK;
192 			pdword[0] |= mp->flags;
193 			pdaddr = mp->pd_addr_start + i * pd_size;
194 
195 			memcpy_toio(smem + pdaddr, pd, pd_size);
196 			queue = mp->queue;
197 			regmap_write(miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue,
198 				     pdaddr);
199 		}
200 	}
201 }
202 
203 void icssg_config_ipg(struct prueth_emac *emac)
204 {
205 	struct prueth *prueth = emac->prueth;
206 	int slice = prueth_emac_slice(emac);
207 	u32 ipg;
208 
209 	switch (emac->speed) {
210 	case SPEED_1000:
211 		ipg = emac->is_sr1 ? MII_RT_TX_IPG_1G_SR1 : MII_RT_TX_IPG_1G;
212 		break;
213 	case SPEED_100:
214 		ipg = emac->is_sr1 ? MII_RT_TX_IPG_100M_SR1 : MII_RT_TX_IPG_100M;
215 		break;
216 	case SPEED_10:
217 		/* Firmware hardcodes IPG for SR1.0 */
218 		if (emac->is_sr1)
219 			return;
220 		/* IPG for 10M is same as 100M */
221 		ipg = MII_RT_TX_IPG_100M;
222 		break;
223 	default:
224 		/* Other links speeds not supported */
225 		netdev_err(emac->ndev, "Unsupported link speed\n");
226 		return;
227 	}
228 
229 	icssg_mii_update_ipg(prueth->mii_rt, slice, ipg);
230 }
231 
232 static void emac_r30_cmd_init(struct prueth_emac *emac)
233 {
234 	struct icssg_r30_cmd __iomem *p;
235 	int i;
236 
237 	p = emac->dram.va + MGR_R30_CMD_OFFSET;
238 
239 	for (i = 0; i < 4; i++)
240 		writel(EMAC_NONE, &p->cmd[i]);
241 }
242 
243 static int emac_r30_is_done(struct prueth_emac *emac)
244 {
245 	const struct icssg_r30_cmd __iomem *p;
246 	u32 cmd;
247 	int i;
248 
249 	p = emac->dram.va + MGR_R30_CMD_OFFSET;
250 
251 	for (i = 0; i < 4; i++) {
252 		cmd = readl(&p->cmd[i]);
253 		if (cmd != EMAC_NONE)
254 			return 0;
255 	}
256 
257 	return 1;
258 }
259 
260 static int prueth_emac_buffer_setup(struct prueth_emac *emac)
261 {
262 	struct icssg_buffer_pool_cfg __iomem *bpool_cfg;
263 	struct icssg_rxq_ctx __iomem *rxq_ctx;
264 	struct prueth *prueth = emac->prueth;
265 	int slice = prueth_emac_slice(emac);
266 	u32 addr;
267 	int i;
268 
269 	/* Layout to have 64KB aligned buffer pool
270 	 * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1|
271 	 */
272 
273 	addr = lower_32_bits(prueth->msmcram.pa);
274 	if (slice)
275 		addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
276 
277 	if (addr % SZ_64K) {
278 		dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n");
279 		return -EINVAL;
280 	}
281 
282 	bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET;
283 	/* workaround for f/w bug. bpool 0 needs to be initilalized */
284 	writel(addr, &bpool_cfg[0].addr);
285 	writel(0, &bpool_cfg[0].len);
286 
287 	for (i = PRUETH_EMAC_BUF_POOL_START;
288 	     i < PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS;
289 	     i++) {
290 		writel(addr, &bpool_cfg[i].addr);
291 		writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len);
292 		addr += PRUETH_EMAC_BUF_POOL_SIZE;
293 	}
294 
295 	if (!slice)
296 		addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
297 	else
298 		addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2;
299 
300 	/* Pre-emptible RX buffer queue */
301 	rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET;
302 	for (i = 0; i < 3; i++)
303 		writel(addr, &rxq_ctx->start[i]);
304 
305 	addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
306 	writel(addr, &rxq_ctx->end);
307 
308 	/* Express RX buffer queue */
309 	rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET;
310 	for (i = 0; i < 3; i++)
311 		writel(addr, &rxq_ctx->start[i]);
312 
313 	addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
314 	writel(addr, &rxq_ctx->end);
315 
316 	return 0;
317 }
318 
319 static void icssg_init_emac_mode(struct prueth *prueth)
320 {
321 	/* When the device is configured as a bridge and it is being brought
322 	 * back to the emac mode, the host mac address has to be set as 0.
323 	 */
324 	u8 mac[ETH_ALEN] = { 0 };
325 
326 	if (prueth->emacs_initialized)
327 		return;
328 
329 	regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1,
330 			   SMEM_VLAN_OFFSET_MASK, 0);
331 	regmap_write(prueth->miig_rt, FDB_GEN_CFG2, 0);
332 	/* Clear host MAC address */
333 	icssg_class_set_host_mac_addr(prueth->miig_rt, mac);
334 }
335 
336 int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
337 {
338 	void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
339 	struct icssg_flow_cfg __iomem *flow_cfg;
340 	int ret;
341 
342 	icssg_init_emac_mode(prueth);
343 
344 	memset_io(config, 0, TAS_GATE_MASK_LIST0);
345 	icssg_miig_queues_init(prueth, slice);
346 
347 	emac->speed = SPEED_1000;
348 	emac->duplex = DUPLEX_FULL;
349 	if (!phy_interface_mode_is_rgmii(emac->phy_if)) {
350 		emac->speed = SPEED_100;
351 		emac->duplex = DUPLEX_FULL;
352 	}
353 	regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET,
354 			   ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT);
355 	icssg_miig_set_interface_mode(prueth->miig_rt, slice, emac->phy_if);
356 	icssg_config_mii_init(emac);
357 	icssg_config_ipg(emac);
358 	icssg_update_rgmii_cfg(prueth->miig_rt, emac);
359 
360 	/* set GPI mode */
361 	pruss_cfg_gpimode(prueth->pruss, prueth->pru_id[slice],
362 			  PRUSS_GPI_MODE_MII);
363 
364 	/* enable XFR shift for PRU and RTU */
365 	pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_PRU, true);
366 	pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_RTU, true);
367 
368 	/* set C28 to 0x100 */
369 	pru_rproc_set_ctable(prueth->pru[slice], PRU_C28, 0x100 << 8);
370 	pru_rproc_set_ctable(prueth->rtu[slice], PRU_C28, 0x100 << 8);
371 	pru_rproc_set_ctable(prueth->txpru[slice], PRU_C28, 0x100 << 8);
372 
373 	flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET;
374 	writew(emac->rx_flow_id_base, &flow_cfg->rx_base_flow);
375 	writew(0, &flow_cfg->mgm_base_flow);
376 	writeb(0, config + SPL_PKT_DEFAULT_PRIORITY);
377 	writeb(0, config + QUEUE_NUM_UNTAGGED);
378 
379 	ret = prueth_emac_buffer_setup(emac);
380 	if (ret)
381 		return ret;
382 
383 	emac_r30_cmd_init(emac);
384 
385 	return 0;
386 }
387 
388 /* Bitmask for ICSSG r30 commands */
389 static const struct icssg_r30_cmd emac_r32_bitmask[] = {
390 	{{0xffff0004, 0xffff0100, 0xffff0004, EMAC_NONE}},	/* EMAC_PORT_DISABLE */
391 	{{0xfffb0040, 0xfeff0200, 0xfeff0200, EMAC_NONE}},	/* EMAC_PORT_BLOCK */
392 	{{0xffbb0000, 0xfcff0000, 0xdcfb0000, EMAC_NONE}},	/* EMAC_PORT_FORWARD */
393 	{{0xffbb0000, 0xfcff0000, 0xfcff2000, EMAC_NONE}},	/* EMAC_PORT_FORWARD_WO_LEARNING */
394 	{{0xffff0001, EMAC_NONE,  EMAC_NONE, EMAC_NONE}},	/* ACCEPT ALL */
395 	{{0xfffe0002, EMAC_NONE,  EMAC_NONE, EMAC_NONE}},	/* ACCEPT TAGGED */
396 	{{0xfffc0000, EMAC_NONE,  EMAC_NONE, EMAC_NONE}},	/* ACCEPT UNTAGGED and PRIO */
397 	{{EMAC_NONE,  0xffff0020, EMAC_NONE, EMAC_NONE}},	/* TAS Trigger List change */
398 	{{EMAC_NONE,  0xdfff1000, EMAC_NONE, EMAC_NONE}},	/* TAS set state ENABLE*/
399 	{{EMAC_NONE,  0xefff2000, EMAC_NONE, EMAC_NONE}},	/* TAS set state RESET*/
400 	{{EMAC_NONE,  0xcfff0000, EMAC_NONE, EMAC_NONE}},	/* TAS set state DISABLE*/
401 	{{EMAC_NONE,  EMAC_NONE,  0xffff0400, EMAC_NONE}},	/* UC flooding ENABLE*/
402 	{{EMAC_NONE,  EMAC_NONE,  0xfbff0000, EMAC_NONE}},	/* UC flooding DISABLE*/
403 	{{EMAC_NONE,  EMAC_NONE,  0xffff0800, EMAC_NONE}},	/* MC flooding ENABLE*/
404 	{{EMAC_NONE,  EMAC_NONE,  0xf7ff0000, EMAC_NONE}},	/* MC flooding DISABLE*/
405 	{{EMAC_NONE,  0xffff4000, EMAC_NONE, EMAC_NONE}},	/* Preemption on Tx ENABLE*/
406 	{{EMAC_NONE,  0xbfff0000, EMAC_NONE, EMAC_NONE}},	/* Preemption on Tx DISABLE*/
407 	{{0xffff0010,  EMAC_NONE, 0xffff0010, EMAC_NONE}},	/* VLAN AWARE*/
408 	{{0xffef0000,  EMAC_NONE, 0xffef0000, EMAC_NONE}}	/* VLAN UNWARE*/
409 };
410 
411 int emac_set_port_state(struct prueth_emac *emac,
412 			enum icssg_port_state_cmd cmd)
413 {
414 	struct icssg_r30_cmd __iomem *p;
415 	int ret = -ETIMEDOUT;
416 	int done = 0;
417 	int i;
418 
419 	p = emac->dram.va + MGR_R30_CMD_OFFSET;
420 
421 	if (cmd >= ICSSG_EMAC_PORT_MAX_COMMANDS) {
422 		netdev_err(emac->ndev, "invalid port command\n");
423 		return -EINVAL;
424 	}
425 
426 	/* only one command at a time allowed to firmware */
427 	mutex_lock(&emac->cmd_lock);
428 
429 	for (i = 0; i < 4; i++)
430 		writel(emac_r32_bitmask[cmd].cmd[i], &p->cmd[i]);
431 
432 	/* wait for done */
433 	ret = read_poll_timeout(emac_r30_is_done, done, done == 1,
434 				1000, 10000, false, emac);
435 
436 	if (ret == -ETIMEDOUT)
437 		netdev_err(emac->ndev, "timeout waiting for command done\n");
438 
439 	mutex_unlock(&emac->cmd_lock);
440 
441 	return ret;
442 }
443 
444 void icssg_config_half_duplex(struct prueth_emac *emac)
445 {
446 	u32 val;
447 
448 	if (!emac->half_duplex)
449 		return;
450 
451 	val = get_random_u32();
452 	writel(val, emac->dram.va + HD_RAND_SEED_OFFSET);
453 }
454 
455 void icssg_config_set_speed(struct prueth_emac *emac)
456 {
457 	u8 fw_speed;
458 
459 	switch (emac->speed) {
460 	case SPEED_1000:
461 		fw_speed = FW_LINK_SPEED_1G;
462 		break;
463 	case SPEED_100:
464 		fw_speed = FW_LINK_SPEED_100M;
465 		break;
466 	case SPEED_10:
467 		fw_speed = FW_LINK_SPEED_10M;
468 		break;
469 	default:
470 		/* Other links speeds not supported */
471 		netdev_err(emac->ndev, "Unsupported link speed\n");
472 		return;
473 	}
474 
475 	if (emac->duplex == DUPLEX_HALF)
476 		fw_speed |= FW_LINK_SPEED_HD;
477 
478 	writeb(fw_speed, emac->dram.va + PORT_LINK_SPEED_OFFSET);
479 }
480