mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 02:15:45 +01:00 
			
		
		
		
	net: mscc: Move ocelot_send and ocelot_recv in a different file.
This functions can be reused by other MSCC SoCs therefore, make them more generic and move them in separate files. Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
This commit is contained in:
		
				
					committed by
					
						 Daniel Schwierzeck
						Daniel Schwierzeck
					
				
			
			
				
	
			
			
			
						parent
						
							2fff4a9b59
						
					
				
				
					commit
					36d04f52ff
				
			| @@ -1,2 +1,2 @@ | ||||
|  | ||||
| obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_miim.o | ||||
| obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_miim.o mscc_xfer.o | ||||
|   | ||||
							
								
								
									
										139
									
								
								drivers/net/mscc_eswitch/mscc_xfer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								drivers/net/mscc_eswitch/mscc_xfer.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | ||||
| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) | ||||
| /* | ||||
|  * Copyright (c) 2018 Microsemi Corporation | ||||
|  */ | ||||
|  | ||||
| #include <linux/io.h> | ||||
| #include "mscc_xfer.h" | ||||
|  | ||||
| #define QS_XTR_FLUSH_FLUSH		GENMASK(1, 0) | ||||
| #define QS_INJ_CTRL_GAP_SIZE(x)		((x) << 21) | ||||
| #define QS_INJ_CTRL_EOF			BIT(19) | ||||
| #define QS_INJ_CTRL_SOF			BIT(18) | ||||
| #define QS_INJ_CTRL_VLD_BYTES(x)	((x) << 16) | ||||
|  | ||||
| #define XTR_EOF_0     ntohl(0x80000000u) | ||||
| #define XTR_EOF_1     ntohl(0x80000001u) | ||||
| #define XTR_EOF_2     ntohl(0x80000002u) | ||||
| #define XTR_EOF_3     ntohl(0x80000003u) | ||||
| #define XTR_PRUNED    ntohl(0x80000004u) | ||||
| #define XTR_ABORT     ntohl(0x80000005u) | ||||
| #define XTR_ESCAPE    ntohl(0x80000006u) | ||||
| #define XTR_NOT_READY ntohl(0x80000007u) | ||||
|  | ||||
| #define BUF_CELL_SZ		60 | ||||
| #define XTR_VALID_BYTES(x)	(4 - ((x) & 3)) | ||||
|  | ||||
| int mscc_send(void __iomem *regs, const unsigned long *mscc_qs_offset, | ||||
| 	      u32 *ifh, size_t ifh_len, u32 *buff, size_t buff_len) | ||||
| { | ||||
| 	int i, count = (buff_len + 3) / 4, last = buff_len % 4; | ||||
|  | ||||
| 	writel(QS_INJ_CTRL_GAP_SIZE(1) | QS_INJ_CTRL_SOF, | ||||
| 	       regs + mscc_qs_offset[MSCC_QS_INJ_CTRL]); | ||||
|  | ||||
| 	for (i = 0; i < ifh_len; i++) | ||||
| 		writel(ifh[i], regs + mscc_qs_offset[MSCC_QS_INJ_WR]); | ||||
|  | ||||
| 	for (i = 0; i < count; i++) | ||||
| 		writel(buff[i], regs + mscc_qs_offset[MSCC_QS_INJ_WR]); | ||||
|  | ||||
| 	/* Add padding */ | ||||
| 	while (i < (BUF_CELL_SZ / 4)) { | ||||
| 		writel(0, regs + mscc_qs_offset[MSCC_QS_INJ_WR]); | ||||
| 		i++; | ||||
| 	} | ||||
|  | ||||
| 	/* Indicate EOF and valid bytes in last word */ | ||||
| 	writel(QS_INJ_CTRL_GAP_SIZE(1) | | ||||
| 	       QS_INJ_CTRL_VLD_BYTES(buff_len < BUF_CELL_SZ ? 0 : last) | | ||||
| 	       QS_INJ_CTRL_EOF, regs + mscc_qs_offset[MSCC_QS_INJ_CTRL]); | ||||
|  | ||||
| 	/* Add dummy CRC */ | ||||
| 	writel(0, regs + mscc_qs_offset[MSCC_QS_INJ_WR]); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int mscc_recv(void __iomem *regs, const unsigned long *mscc_qs_offset, | ||||
| 	      u32 *rxbuf, size_t ifh_len, bool byte_swap) | ||||
| { | ||||
| 	u8 grp = 0; /* Recv everything on CPU group 0 */ | ||||
| 	int i, byte_cnt = 0; | ||||
| 	bool eof_flag = false, pruned_flag = false, abort_flag = false; | ||||
|  | ||||
| 	if (!(readl(regs + mscc_qs_offset[MSCC_QS_XTR_DATA_PRESENT]) & | ||||
| 	      BIT(grp))) | ||||
| 		return -EAGAIN; | ||||
|  | ||||
| 	/* skip IFH */ | ||||
| 	for (i = 0; i < ifh_len; i++) | ||||
| 		readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]); | ||||
|  | ||||
| 	while (!eof_flag) { | ||||
| 		u32 val = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]); | ||||
| 		u32 cmp = val; | ||||
|  | ||||
| 		if (byte_swap) | ||||
| 			cmp = ntohl(val); | ||||
|  | ||||
| 		switch (cmp) { | ||||
| 		case XTR_NOT_READY: | ||||
| 			debug("%d NOT_READY...?\n", byte_cnt); | ||||
| 			break; | ||||
| 		case XTR_ABORT: | ||||
| 			*rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]); | ||||
| 			abort_flag = true; | ||||
| 			eof_flag = true; | ||||
| 			debug("XTR_ABORT\n"); | ||||
| 			break; | ||||
| 		case XTR_EOF_0: | ||||
| 		case XTR_EOF_1: | ||||
| 		case XTR_EOF_2: | ||||
| 		case XTR_EOF_3: | ||||
| 			byte_cnt += XTR_VALID_BYTES(val); | ||||
| 			*rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]); | ||||
| 			eof_flag = true; | ||||
| 			debug("EOF\n"); | ||||
| 			break; | ||||
| 		case XTR_PRUNED: | ||||
| 			/* But get the last 4 bytes as well */ | ||||
| 			eof_flag = true; | ||||
| 			pruned_flag = true; | ||||
| 			debug("PRUNED\n"); | ||||
| 			/* fallthrough */ | ||||
| 		case XTR_ESCAPE: | ||||
| 			*rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]); | ||||
| 			byte_cnt += 4; | ||||
| 			rxbuf++; | ||||
| 			debug("ESCAPED\n"); | ||||
| 			break; | ||||
| 		default: | ||||
| 			*rxbuf = val; | ||||
| 			byte_cnt += 4; | ||||
| 			rxbuf++; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (abort_flag || pruned_flag || !eof_flag) { | ||||
| 		debug("Discarded frame: abort:%d pruned:%d eof:%d\n", | ||||
| 		      abort_flag, pruned_flag, eof_flag); | ||||
| 		return -EAGAIN; | ||||
| 	} | ||||
|  | ||||
| 	return byte_cnt; | ||||
| } | ||||
|  | ||||
| void mscc_flush(void __iomem *regs, const unsigned long *mscc_qs_offset) | ||||
| { | ||||
| 	/* All Queues flush */ | ||||
| 	setbits_le32(regs + mscc_qs_offset[MSCC_QS_XTR_FLUSH], | ||||
| 		     QS_XTR_FLUSH_FLUSH); | ||||
|  | ||||
| 	/* Allow to drain */ | ||||
| 	mdelay(1); | ||||
|  | ||||
| 	/* All Queues normal */ | ||||
| 	clrbits_le32(regs + mscc_qs_offset[MSCC_QS_XTR_FLUSH], | ||||
| 		     QS_XTR_FLUSH_FLUSH); | ||||
| } | ||||
							
								
								
									
										20
									
								
								drivers/net/mscc_eswitch/mscc_xfer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								drivers/net/mscc_eswitch/mscc_xfer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| /* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ | ||||
| /* | ||||
|  * Copyright (c) 2018 Microsemi Corporation | ||||
|  */ | ||||
|  | ||||
| #include <common.h> | ||||
|  | ||||
| enum mscc_regs_qs { | ||||
| 	MSCC_QS_XTR_RD, | ||||
| 	MSCC_QS_XTR_FLUSH, | ||||
| 	MSCC_QS_XTR_DATA_PRESENT, | ||||
| 	MSCC_QS_INJ_WR, | ||||
| 	MSCC_QS_INJ_CTRL, | ||||
| }; | ||||
|  | ||||
| int mscc_send(void __iomem *regs, const unsigned long *mscc_qs_offset, | ||||
| 	      u32 *ifh, size_t ifh_len, u32 *buff, size_t buff_len); | ||||
| int mscc_recv(void __iomem *regs, const unsigned long *mscc_qs_offset, | ||||
| 	      u32 *rxbuf, size_t ifh_len, bool byte_swap); | ||||
| void mscc_flush(void __iomem *regs, const unsigned long *mscc_qs_offset); | ||||
| @@ -16,6 +16,7 @@ | ||||
| #include <wait_bit.h> | ||||
|  | ||||
| #include "mscc_miim.h" | ||||
| #include "mscc_xfer.h" | ||||
|  | ||||
| #define PHY_CFG				0x0 | ||||
| #define PHY_CFG_ENA				0xF | ||||
| @@ -87,37 +88,16 @@ | ||||
| #define QS_XTR_GRP_CFG_MODE(x)			((x) << 2) | ||||
| #define		QS_XTR_GRP_CFG_STATUS_WORD_POS	BIT(1) | ||||
| #define		QS_XTR_GRP_CFG_BYTE_SWAP	BIT(0) | ||||
| #define QS_XTR_RD(x)			(0x8 + 4 * (x)) | ||||
| #define QS_XTR_FLUSH			0x18 | ||||
| #define		QS_XTR_FLUSH_FLUSH		GENMASK(1, 0) | ||||
| #define QS_XTR_DATA_PRESENT		0x1c | ||||
| #define QS_INJ_GRP_CFG(x)		(0x24 + (x) * 4) | ||||
| #define		QS_INJ_GRP_CFG_MODE(x)		((x) << 2) | ||||
| #define		QS_INJ_GRP_CFG_BYTE_SWAP	BIT(0) | ||||
| #define QS_INJ_WR(x)			(0x2c + 4 * (x)) | ||||
| #define QS_INJ_CTRL(x)			(0x34 + 4 * (x)) | ||||
| #define		QS_INJ_CTRL_GAP_SIZE(x)		((x) << 21) | ||||
| #define		QS_INJ_CTRL_EOF			BIT(19) | ||||
| #define		QS_INJ_CTRL_SOF			BIT(18) | ||||
| #define		QS_INJ_CTRL_VLD_BYTES(x)	((x) << 16) | ||||
|  | ||||
| #define XTR_EOF_0     ntohl(0x80000000u) | ||||
| #define XTR_EOF_1     ntohl(0x80000001u) | ||||
| #define XTR_EOF_2     ntohl(0x80000002u) | ||||
| #define XTR_EOF_3     ntohl(0x80000003u) | ||||
| #define XTR_PRUNED    ntohl(0x80000004u) | ||||
| #define XTR_ABORT     ntohl(0x80000005u) | ||||
| #define XTR_ESCAPE    ntohl(0x80000006u) | ||||
| #define XTR_NOT_READY ntohl(0x80000007u) | ||||
|  | ||||
| #define IFH_INJ_BYPASS		BIT(31) | ||||
| #define	IFH_TAG_TYPE_C		0 | ||||
| #define XTR_VALID_BYTES(x)	(4 - ((x) & 3)) | ||||
| #define	MAC_VID			1 | ||||
| #define CPU_PORT		11 | ||||
| #define INTERNAL_PORT_MSK	0xF | ||||
| #define IFH_LEN			4 | ||||
| #define OCELOT_BUF_CELL_SZ	60 | ||||
| #define ETH_ALEN		6 | ||||
| #define	PGID_BROADCAST		13 | ||||
| #define	PGID_UNICAST		14 | ||||
| @@ -181,6 +161,14 @@ struct ocelot_private { | ||||
| 	void *tx_adj_buf; | ||||
| }; | ||||
|  | ||||
| static const unsigned long ocelot_regs_qs[] = { | ||||
| 	[MSCC_QS_XTR_RD] = 0x8, | ||||
| 	[MSCC_QS_XTR_FLUSH] = 0x18, | ||||
| 	[MSCC_QS_XTR_DATA_PRESENT] = 0x1c, | ||||
| 	[MSCC_QS_INJ_WR] = 0x2c, | ||||
| 	[MSCC_QS_INJ_CTRL] = 0x34, | ||||
| }; | ||||
|  | ||||
| struct mscc_miim_dev miim[NUM_PHY]; | ||||
|  | ||||
| static int mscc_miim_reset(struct mii_dev *bus) | ||||
| @@ -367,16 +355,6 @@ static int ocelot_switch_init(struct ocelot_private *priv) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void ocelot_switch_flush(struct ocelot_private *priv) | ||||
| { | ||||
| 	/* All Queues flush */ | ||||
| 	setbits_le32(priv->regs[QS] + QS_XTR_FLUSH, QS_XTR_FLUSH_FLUSH); | ||||
| 	/* Allow to drain */ | ||||
| 	mdelay(1); | ||||
| 	/* All Queues normal */ | ||||
| 	clrbits_le32(priv->regs[QS] + QS_XTR_FLUSH, QS_XTR_FLUSH_FLUSH); | ||||
| } | ||||
|  | ||||
| static int ocelot_initialize(struct ocelot_private *priv) | ||||
| { | ||||
| 	int ret, i; | ||||
| @@ -394,7 +372,7 @@ static int ocelot_initialize(struct ocelot_private *priv) | ||||
| 		writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i)); | ||||
|  | ||||
| 	/* Flush queues */ | ||||
| 	ocelot_switch_flush(priv); | ||||
| 	mscc_flush(priv->regs[QS], ocelot_regs_qs); | ||||
|  | ||||
| 	/* Setup frame ageing - "2 sec" - The unit is 6.5us on Ocelot */ | ||||
| 	writel(SYS_FRM_AGING_ENA | (20000000 / 65), | ||||
| @@ -503,13 +481,8 @@ static int ocelot_send(struct udevice *dev, void *packet, int length) | ||||
| 	struct ocelot_private *priv = dev_get_priv(dev); | ||||
| 	u32 ifh[IFH_LEN]; | ||||
| 	int port = BIT(0);	/* use port 0 */ | ||||
| 	u8 grp = 0;		/* Send everything on CPU group 0 */ | ||||
| 	int i, count = (length + 3) / 4, last = length % 4; | ||||
| 	u32 *buf = packet; | ||||
|  | ||||
| 	writel(QS_INJ_CTRL_GAP_SIZE(1) | QS_INJ_CTRL_SOF, | ||||
| 	       priv->regs[QS] + QS_INJ_CTRL(grp)); | ||||
|  | ||||
| 	/* | ||||
| 	 * Generate the IFH for frame injection | ||||
| 	 * | ||||
| @@ -526,91 +499,18 @@ static int ocelot_send(struct udevice *dev, void *packet, int length) | ||||
| 	ifh[2] = (0xff & port) << 24; | ||||
| 	ifh[3] = (IFH_TAG_TYPE_C << 16); | ||||
|  | ||||
| 	for (i = 0; i < IFH_LEN; i++) | ||||
| 		writel(ifh[i], priv->regs[QS] + QS_INJ_WR(grp)); | ||||
|  | ||||
| 	for (i = 0; i < count; i++) | ||||
| 		writel(buf[i], priv->regs[QS] + QS_INJ_WR(grp)); | ||||
|  | ||||
| 	/* Add padding */ | ||||
| 	while (i < (OCELOT_BUF_CELL_SZ / 4)) { | ||||
| 		writel(0, priv->regs[QS] + QS_INJ_WR(grp)); | ||||
| 		i++; | ||||
| 	} | ||||
|  | ||||
| 	/* Indicate EOF and valid bytes in last word */ | ||||
| 	writel(QS_INJ_CTRL_GAP_SIZE(1) | | ||||
| 	       QS_INJ_CTRL_VLD_BYTES(length < OCELOT_BUF_CELL_SZ ? 0 : last) | | ||||
| 	       QS_INJ_CTRL_EOF, priv->regs[QS] + QS_INJ_CTRL(grp)); | ||||
|  | ||||
| 	/* Add dummy CRC */ | ||||
| 	writel(0, priv->regs[QS] + QS_INJ_WR(grp)); | ||||
|  | ||||
| 	return 0; | ||||
| 	return mscc_send(priv->regs[QS], ocelot_regs_qs, | ||||
| 			 ifh, IFH_LEN, buf, length); | ||||
| } | ||||
|  | ||||
| static int ocelot_recv(struct udevice *dev, int flags, uchar **packetp) | ||||
| { | ||||
| 	struct ocelot_private *priv = dev_get_priv(dev); | ||||
| 	u8 grp = 0;		/* Send everything on CPU group 0 */ | ||||
| 	u32 *rxbuf = (u32 *)net_rx_packets[0]; | ||||
| 	int i, byte_cnt = 0; | ||||
| 	bool eof_flag = false, pruned_flag = false, abort_flag = false; | ||||
| 	int byte_cnt; | ||||
|  | ||||
| 	if (!(readl(priv->regs[QS] + QS_XTR_DATA_PRESENT) & BIT(grp))) | ||||
| 		return -EAGAIN; | ||||
|  | ||||
| 	/* skip IFH */ | ||||
| 	for (i = 0; i < IFH_LEN; i++) | ||||
| 		readl(priv->regs[QS] + QS_XTR_RD(grp)); | ||||
|  | ||||
| 	while (!eof_flag) { | ||||
| 		u32 val = readl(priv->regs[QS] + QS_XTR_RD(grp)); | ||||
|  | ||||
| 		switch (val) { | ||||
| 		case XTR_NOT_READY: | ||||
| 			debug("%d NOT_READY...?\n", byte_cnt); | ||||
| 			break; | ||||
| 		case XTR_ABORT: | ||||
| 			/* really nedeed?? not done in linux */ | ||||
| 			*rxbuf = readl(priv->regs[QS] + QS_XTR_RD(grp)); | ||||
| 			abort_flag = true; | ||||
| 			eof_flag = true; | ||||
| 			debug("XTR_ABORT\n"); | ||||
| 			break; | ||||
| 		case XTR_EOF_0: | ||||
| 		case XTR_EOF_1: | ||||
| 		case XTR_EOF_2: | ||||
| 		case XTR_EOF_3: | ||||
| 			byte_cnt += XTR_VALID_BYTES(val); | ||||
| 			*rxbuf = readl(priv->regs[QS] + QS_XTR_RD(grp)); | ||||
| 			eof_flag = true; | ||||
| 			debug("EOF\n"); | ||||
| 			break; | ||||
| 		case XTR_PRUNED: | ||||
| 			/* But get the last 4 bytes as well */ | ||||
| 			eof_flag = true; | ||||
| 			pruned_flag = true; | ||||
| 			debug("PRUNED\n"); | ||||
| 			/* fallthrough */ | ||||
| 		case XTR_ESCAPE: | ||||
| 			*rxbuf = readl(priv->regs[QS] + QS_XTR_RD(grp)); | ||||
| 			byte_cnt += 4; | ||||
| 			rxbuf++; | ||||
| 			debug("ESCAPED\n"); | ||||
| 			break; | ||||
| 		default: | ||||
| 			*rxbuf = val; | ||||
| 			byte_cnt += 4; | ||||
| 			rxbuf++; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (abort_flag || pruned_flag || !eof_flag) { | ||||
| 		debug("Discarded frame: abort:%d pruned:%d eof:%d\n", | ||||
| 		      abort_flag, pruned_flag, eof_flag); | ||||
| 		return -EAGAIN; | ||||
| 	} | ||||
| 	byte_cnt = mscc_recv(priv->regs[QS], ocelot_regs_qs, rxbuf, IFH_LEN, | ||||
| 			     false); | ||||
|  | ||||
| 	*packetp = net_rx_packets[0]; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user