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