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