xref: /rk3399_rockchip-uboot/drivers/net/keystone_net.c (revision 4657a2d44ed06272c1fb1d6f5b842e93ceddbbb6)
1fc9a8e8dSKaricheri, Muralidharan /*
2fc9a8e8dSKaricheri, Muralidharan  * Ethernet driver for TI K2HK EVM.
3fc9a8e8dSKaricheri, Muralidharan  *
4fc9a8e8dSKaricheri, Muralidharan  * (C) Copyright 2012-2014
5fc9a8e8dSKaricheri, Muralidharan  *     Texas Instruments Incorporated, <www.ti.com>
6fc9a8e8dSKaricheri, Muralidharan  *
7fc9a8e8dSKaricheri, Muralidharan  * SPDX-License-Identifier:     GPL-2.0+
8fc9a8e8dSKaricheri, Muralidharan  */
9fc9a8e8dSKaricheri, Muralidharan #include <common.h>
10fc9a8e8dSKaricheri, Muralidharan #include <command.h>
11fc9a8e8dSKaricheri, Muralidharan 
12fc9a8e8dSKaricheri, Muralidharan #include <net.h>
133fe93623SKhoronzhuk, Ivan #include <phy.h>
14c05d05e7SKhoronzhuk, Ivan #include <errno.h>
15fc9a8e8dSKaricheri, Muralidharan #include <miiphy.h>
16fc9a8e8dSKaricheri, Muralidharan #include <malloc.h>
17ef454717SKhoronzhuk, Ivan #include <asm/ti-common/keystone_nav.h>
180935cac6SKhoronzhuk, Ivan #include <asm/ti-common/keystone_net.h>
19a43febdeSKhoronzhuk, Ivan #include <asm/ti-common/keystone_serdes.h>
20fc9a8e8dSKaricheri, Muralidharan 
21fc9a8e8dSKaricheri, Muralidharan unsigned int emac_open;
22550c5ce6SKhoronzhuk, Ivan static struct mii_dev *mdio_bus;
23fc9a8e8dSKaricheri, Muralidharan static unsigned int sys_has_mdio = 1;
24fc9a8e8dSKaricheri, Muralidharan 
25fc9a8e8dSKaricheri, Muralidharan #ifdef KEYSTONE2_EMAC_GIG_ENABLE
26fc9a8e8dSKaricheri, Muralidharan #define emac_gigabit_enable(x)	keystone2_eth_gigabit_enable(x)
27fc9a8e8dSKaricheri, Muralidharan #else
28fc9a8e8dSKaricheri, Muralidharan #define emac_gigabit_enable(x)	/* no gigabit to enable */
29fc9a8e8dSKaricheri, Muralidharan #endif
30fc9a8e8dSKaricheri, Muralidharan 
31fc9a8e8dSKaricheri, Muralidharan #define RX_BUFF_NUMS	24
32fc9a8e8dSKaricheri, Muralidharan #define RX_BUFF_LEN	1520
33fc9a8e8dSKaricheri, Muralidharan #define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN
34c05d05e7SKhoronzhuk, Ivan #define SGMII_ANEG_TIMEOUT		4000
35fc9a8e8dSKaricheri, Muralidharan 
36fc9a8e8dSKaricheri, Muralidharan static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16);
37fc9a8e8dSKaricheri, Muralidharan 
38fc9a8e8dSKaricheri, Muralidharan struct rx_buff_desc net_rx_buffs = {
39fc9a8e8dSKaricheri, Muralidharan 	.buff_ptr	= rx_buffs,
40fc9a8e8dSKaricheri, Muralidharan 	.num_buffs	= RX_BUFF_NUMS,
41fc9a8e8dSKaricheri, Muralidharan 	.buff_len	= RX_BUFF_LEN,
42fc9a8e8dSKaricheri, Muralidharan 	.rx_flow	= 22,
43fc9a8e8dSKaricheri, Muralidharan };
44fc9a8e8dSKaricheri, Muralidharan 
45*4657a2d4SVitaly Andrianov #ifndef CONFIG_SOC_K2G
46a43febdeSKhoronzhuk, Ivan static void keystone2_net_serdes_setup(void);
47*4657a2d4SVitaly Andrianov #endif
48fc9a8e8dSKaricheri, Muralidharan 
49fc9a8e8dSKaricheri, Muralidharan int keystone2_eth_read_mac_addr(struct eth_device *dev)
50fc9a8e8dSKaricheri, Muralidharan {
51fc9a8e8dSKaricheri, Muralidharan 	struct eth_priv_t *eth_priv;
52fc9a8e8dSKaricheri, Muralidharan 	u32 maca = 0;
53fc9a8e8dSKaricheri, Muralidharan 	u32 macb = 0;
54fc9a8e8dSKaricheri, Muralidharan 
55fc9a8e8dSKaricheri, Muralidharan 	eth_priv = (struct eth_priv_t *)dev->priv;
56fc9a8e8dSKaricheri, Muralidharan 
57fc9a8e8dSKaricheri, Muralidharan 	/* Read the e-fuse mac address */
58fc9a8e8dSKaricheri, Muralidharan 	if (eth_priv->slave_port == 1) {
59fc9a8e8dSKaricheri, Muralidharan 		maca = __raw_readl(MAC_ID_BASE_ADDR);
60fc9a8e8dSKaricheri, Muralidharan 		macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
61fc9a8e8dSKaricheri, Muralidharan 	}
62fc9a8e8dSKaricheri, Muralidharan 
63fc9a8e8dSKaricheri, Muralidharan 	dev->enetaddr[0] = (macb >>  8) & 0xff;
64fc9a8e8dSKaricheri, Muralidharan 	dev->enetaddr[1] = (macb >>  0) & 0xff;
65fc9a8e8dSKaricheri, Muralidharan 	dev->enetaddr[2] = (maca >> 24) & 0xff;
66fc9a8e8dSKaricheri, Muralidharan 	dev->enetaddr[3] = (maca >> 16) & 0xff;
67fc9a8e8dSKaricheri, Muralidharan 	dev->enetaddr[4] = (maca >>  8) & 0xff;
68fc9a8e8dSKaricheri, Muralidharan 	dev->enetaddr[5] = (maca >>  0) & 0xff;
69fc9a8e8dSKaricheri, Muralidharan 
70fc9a8e8dSKaricheri, Muralidharan 	return 0;
71fc9a8e8dSKaricheri, Muralidharan }
72fc9a8e8dSKaricheri, Muralidharan 
73550c5ce6SKhoronzhuk, Ivan /* MDIO */
74550c5ce6SKhoronzhuk, Ivan 
75550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_reset(struct mii_dev *bus)
76fc9a8e8dSKaricheri, Muralidharan {
77fc9a8e8dSKaricheri, Muralidharan 	u_int32_t clkdiv;
78550c5ce6SKhoronzhuk, Ivan 	struct mdio_regs *adap_mdio = bus->priv;
79fc9a8e8dSKaricheri, Muralidharan 
80fc9a8e8dSKaricheri, Muralidharan 	clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
81fc9a8e8dSKaricheri, Muralidharan 
82550c5ce6SKhoronzhuk, Ivan 	writel((clkdiv & 0xffff) | MDIO_CONTROL_ENABLE |
83550c5ce6SKhoronzhuk, Ivan 	       MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE,
84fc9a8e8dSKaricheri, Muralidharan 	       &adap_mdio->control);
85fc9a8e8dSKaricheri, Muralidharan 
86fc9a8e8dSKaricheri, Muralidharan 	while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE)
87fc9a8e8dSKaricheri, Muralidharan 		;
88550c5ce6SKhoronzhuk, Ivan 
89550c5ce6SKhoronzhuk, Ivan 	return 0;
90fc9a8e8dSKaricheri, Muralidharan }
91fc9a8e8dSKaricheri, Muralidharan 
92550c5ce6SKhoronzhuk, Ivan /**
93550c5ce6SKhoronzhuk, Ivan  * keystone2_mdio_read - read a PHY register via MDIO interface.
94550c5ce6SKhoronzhuk, Ivan  * Blocks until operation is complete.
95550c5ce6SKhoronzhuk, Ivan  */
96550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_read(struct mii_dev *bus,
97550c5ce6SKhoronzhuk, Ivan 			       int addr, int devad, int reg)
98fc9a8e8dSKaricheri, Muralidharan {
99fc9a8e8dSKaricheri, Muralidharan 	int tmp;
100550c5ce6SKhoronzhuk, Ivan 	struct mdio_regs *adap_mdio = bus->priv;
101fc9a8e8dSKaricheri, Muralidharan 
102fc9a8e8dSKaricheri, Muralidharan 	while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
103fc9a8e8dSKaricheri, Muralidharan 		;
104fc9a8e8dSKaricheri, Muralidharan 
105550c5ce6SKhoronzhuk, Ivan 	writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ |
106550c5ce6SKhoronzhuk, Ivan 	       ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16),
107fc9a8e8dSKaricheri, Muralidharan 	       &adap_mdio->useraccess0);
108fc9a8e8dSKaricheri, Muralidharan 
109fc9a8e8dSKaricheri, Muralidharan 	/* Wait for command to complete */
110fc9a8e8dSKaricheri, Muralidharan 	while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO)
111fc9a8e8dSKaricheri, Muralidharan 		;
112fc9a8e8dSKaricheri, Muralidharan 
113550c5ce6SKhoronzhuk, Ivan 	if (tmp & MDIO_USERACCESS0_ACK)
114550c5ce6SKhoronzhuk, Ivan 		return tmp & 0xffff;
115fc9a8e8dSKaricheri, Muralidharan 
116fc9a8e8dSKaricheri, Muralidharan 	return -1;
117fc9a8e8dSKaricheri, Muralidharan }
118fc9a8e8dSKaricheri, Muralidharan 
119550c5ce6SKhoronzhuk, Ivan /**
120550c5ce6SKhoronzhuk, Ivan  * keystone2_mdio_write - write to a PHY register via MDIO interface.
121fc9a8e8dSKaricheri, Muralidharan  * Blocks until operation is complete.
122fc9a8e8dSKaricheri, Muralidharan  */
123550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_write(struct mii_dev *bus,
124550c5ce6SKhoronzhuk, Ivan 				int addr, int devad, int reg, u16 val)
125fc9a8e8dSKaricheri, Muralidharan {
126550c5ce6SKhoronzhuk, Ivan 	struct mdio_regs *adap_mdio = bus->priv;
127550c5ce6SKhoronzhuk, Ivan 
128fc9a8e8dSKaricheri, Muralidharan 	while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
129fc9a8e8dSKaricheri, Muralidharan 		;
130fc9a8e8dSKaricheri, Muralidharan 
131550c5ce6SKhoronzhuk, Ivan 	writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE |
132550c5ce6SKhoronzhuk, Ivan 	       ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16) |
133550c5ce6SKhoronzhuk, Ivan 	       (val & 0xffff), &adap_mdio->useraccess0);
134fc9a8e8dSKaricheri, Muralidharan 
135fc9a8e8dSKaricheri, Muralidharan 	/* Wait for command to complete */
136fc9a8e8dSKaricheri, Muralidharan 	while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
137fc9a8e8dSKaricheri, Muralidharan 		;
138fc9a8e8dSKaricheri, Muralidharan 
139fc9a8e8dSKaricheri, Muralidharan 	return 0;
140fc9a8e8dSKaricheri, Muralidharan }
141fc9a8e8dSKaricheri, Muralidharan 
142fc9a8e8dSKaricheri, Muralidharan static void  __attribute__((unused))
143fc9a8e8dSKaricheri, Muralidharan 	keystone2_eth_gigabit_enable(struct eth_device *dev)
144fc9a8e8dSKaricheri, Muralidharan {
145fc9a8e8dSKaricheri, Muralidharan 	u_int16_t data;
146fc9a8e8dSKaricheri, Muralidharan 	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
147fc9a8e8dSKaricheri, Muralidharan 
148fc9a8e8dSKaricheri, Muralidharan 	if (sys_has_mdio) {
149550c5ce6SKhoronzhuk, Ivan 		data = keystone2_mdio_read(mdio_bus, eth_priv->phy_addr,
150550c5ce6SKhoronzhuk, Ivan 					   MDIO_DEVAD_NONE, 0);
151550c5ce6SKhoronzhuk, Ivan 		/* speed selection MSB */
152550c5ce6SKhoronzhuk, Ivan 		if (!(data & (1 << 6)))
153fc9a8e8dSKaricheri, Muralidharan 			return;
154fc9a8e8dSKaricheri, Muralidharan 	}
155fc9a8e8dSKaricheri, Muralidharan 
156fc9a8e8dSKaricheri, Muralidharan 	/*
157fc9a8e8dSKaricheri, Muralidharan 	 * Check if link detected is giga-bit
158fc9a8e8dSKaricheri, Muralidharan 	 * If Gigabit mode detected, enable gigbit in MAC
159fc9a8e8dSKaricheri, Muralidharan 	 */
160b2cfe322SHao Zhang 	writel(readl(DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) +
161b2cfe322SHao Zhang 		     CPGMACSL_REG_CTL) |
162fc9a8e8dSKaricheri, Muralidharan 	       EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
163b2cfe322SHao Zhang 	       DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL);
164fc9a8e8dSKaricheri, Muralidharan }
165fc9a8e8dSKaricheri, Muralidharan 
166fc9a8e8dSKaricheri, Muralidharan int keystone_sgmii_link_status(int port)
167fc9a8e8dSKaricheri, Muralidharan {
168fc9a8e8dSKaricheri, Muralidharan 	u32 status = 0;
169fc9a8e8dSKaricheri, Muralidharan 
170fc9a8e8dSKaricheri, Muralidharan 	status = __raw_readl(SGMII_STATUS_REG(port));
171fc9a8e8dSKaricheri, Muralidharan 
172a4d2adeeSKhoronzhuk, Ivan 	return (status & SGMII_REG_STATUS_LOCK) &&
173a4d2adeeSKhoronzhuk, Ivan 	       (status & SGMII_REG_STATUS_LINK);
174fc9a8e8dSKaricheri, Muralidharan }
175fc9a8e8dSKaricheri, Muralidharan 
176*4657a2d4SVitaly Andrianov #ifdef CONFIG_SOC_K2G
177*4657a2d4SVitaly Andrianov int keystone_rgmii_config(struct phy_device *phy_dev)
178*4657a2d4SVitaly Andrianov {
179*4657a2d4SVitaly Andrianov 	unsigned int i, status;
180*4657a2d4SVitaly Andrianov 
181*4657a2d4SVitaly Andrianov 	i = 0;
182*4657a2d4SVitaly Andrianov 	do {
183*4657a2d4SVitaly Andrianov 		if (i > SGMII_ANEG_TIMEOUT) {
184*4657a2d4SVitaly Andrianov 			puts(" TIMEOUT !\n");
185*4657a2d4SVitaly Andrianov 			phy_dev->link = 0;
186*4657a2d4SVitaly Andrianov 			return 0;
187*4657a2d4SVitaly Andrianov 		}
188*4657a2d4SVitaly Andrianov 
189*4657a2d4SVitaly Andrianov 		if (ctrlc()) {
190*4657a2d4SVitaly Andrianov 			puts("user interrupt!\n");
191*4657a2d4SVitaly Andrianov 			phy_dev->link = 0;
192*4657a2d4SVitaly Andrianov 			return -EINTR;
193*4657a2d4SVitaly Andrianov 		}
194*4657a2d4SVitaly Andrianov 
195*4657a2d4SVitaly Andrianov 		if ((i++ % 500) == 0)
196*4657a2d4SVitaly Andrianov 			printf(".");
197*4657a2d4SVitaly Andrianov 
198*4657a2d4SVitaly Andrianov 		udelay(1000);   /* 1 ms */
199*4657a2d4SVitaly Andrianov 		status = readl(RGMII_STATUS_REG);
200*4657a2d4SVitaly Andrianov 	} while (!(status & RGMII_REG_STATUS_LINK));
201*4657a2d4SVitaly Andrianov 
202*4657a2d4SVitaly Andrianov 	puts(" done\n");
203*4657a2d4SVitaly Andrianov 
204*4657a2d4SVitaly Andrianov 	return 0;
205*4657a2d4SVitaly Andrianov }
206*4657a2d4SVitaly Andrianov #else
207c05d05e7SKhoronzhuk, Ivan int keystone_sgmii_config(struct phy_device *phy_dev, int port, int interface)
208fc9a8e8dSKaricheri, Muralidharan {
209fc9a8e8dSKaricheri, Muralidharan 	unsigned int i, status, mask;
210fc9a8e8dSKaricheri, Muralidharan 	unsigned int mr_adv_ability, control;
211fc9a8e8dSKaricheri, Muralidharan 
212fc9a8e8dSKaricheri, Muralidharan 	switch (interface) {
213fc9a8e8dSKaricheri, Muralidharan 	case SGMII_LINK_MAC_MAC_AUTONEG:
214fc9a8e8dSKaricheri, Muralidharan 		mr_adv_ability	= (SGMII_REG_MR_ADV_ENABLE |
215fc9a8e8dSKaricheri, Muralidharan 				   SGMII_REG_MR_ADV_LINK |
216fc9a8e8dSKaricheri, Muralidharan 				   SGMII_REG_MR_ADV_FULL_DUPLEX |
217fc9a8e8dSKaricheri, Muralidharan 				   SGMII_REG_MR_ADV_GIG_MODE);
218fc9a8e8dSKaricheri, Muralidharan 		control		= (SGMII_REG_CONTROL_MASTER |
219fc9a8e8dSKaricheri, Muralidharan 				   SGMII_REG_CONTROL_AUTONEG);
220fc9a8e8dSKaricheri, Muralidharan 
221fc9a8e8dSKaricheri, Muralidharan 		break;
222fc9a8e8dSKaricheri, Muralidharan 	case SGMII_LINK_MAC_PHY:
223fc9a8e8dSKaricheri, Muralidharan 	case SGMII_LINK_MAC_PHY_FORCED:
224fc9a8e8dSKaricheri, Muralidharan 		mr_adv_ability	= SGMII_REG_MR_ADV_ENABLE;
225fc9a8e8dSKaricheri, Muralidharan 		control		= SGMII_REG_CONTROL_AUTONEG;
226fc9a8e8dSKaricheri, Muralidharan 
227fc9a8e8dSKaricheri, Muralidharan 		break;
228fc9a8e8dSKaricheri, Muralidharan 	case SGMII_LINK_MAC_MAC_FORCED:
229fc9a8e8dSKaricheri, Muralidharan 		mr_adv_ability	= (SGMII_REG_MR_ADV_ENABLE |
230fc9a8e8dSKaricheri, Muralidharan 				   SGMII_REG_MR_ADV_LINK |
231fc9a8e8dSKaricheri, Muralidharan 				   SGMII_REG_MR_ADV_FULL_DUPLEX |
232fc9a8e8dSKaricheri, Muralidharan 				   SGMII_REG_MR_ADV_GIG_MODE);
233fc9a8e8dSKaricheri, Muralidharan 		control		= SGMII_REG_CONTROL_MASTER;
234fc9a8e8dSKaricheri, Muralidharan 
235fc9a8e8dSKaricheri, Muralidharan 		break;
236fc9a8e8dSKaricheri, Muralidharan 	case SGMII_LINK_MAC_FIBER:
237fc9a8e8dSKaricheri, Muralidharan 		mr_adv_ability	= 0x20;
238fc9a8e8dSKaricheri, Muralidharan 		control		= SGMII_REG_CONTROL_AUTONEG;
239fc9a8e8dSKaricheri, Muralidharan 
240fc9a8e8dSKaricheri, Muralidharan 		break;
241fc9a8e8dSKaricheri, Muralidharan 	default:
242fc9a8e8dSKaricheri, Muralidharan 		mr_adv_ability	= SGMII_REG_MR_ADV_ENABLE;
243fc9a8e8dSKaricheri, Muralidharan 		control		= SGMII_REG_CONTROL_AUTONEG;
244fc9a8e8dSKaricheri, Muralidharan 	}
245fc9a8e8dSKaricheri, Muralidharan 
246fc9a8e8dSKaricheri, Muralidharan 	__raw_writel(0, SGMII_CTL_REG(port));
247fc9a8e8dSKaricheri, Muralidharan 
248fc9a8e8dSKaricheri, Muralidharan 	/*
249fc9a8e8dSKaricheri, Muralidharan 	 * Wait for the SerDes pll to lock,
250fc9a8e8dSKaricheri, Muralidharan 	 * but don't trap if lock is never read
251fc9a8e8dSKaricheri, Muralidharan 	 */
252fc9a8e8dSKaricheri, Muralidharan 	for (i = 0; i < 1000; i++)  {
253fc9a8e8dSKaricheri, Muralidharan 		udelay(2000);
254fc9a8e8dSKaricheri, Muralidharan 		status = __raw_readl(SGMII_STATUS_REG(port));
255fc9a8e8dSKaricheri, Muralidharan 		if ((status & SGMII_REG_STATUS_LOCK) != 0)
256fc9a8e8dSKaricheri, Muralidharan 			break;
257fc9a8e8dSKaricheri, Muralidharan 	}
258fc9a8e8dSKaricheri, Muralidharan 
259fc9a8e8dSKaricheri, Muralidharan 	__raw_writel(mr_adv_ability, SGMII_MRADV_REG(port));
260fc9a8e8dSKaricheri, Muralidharan 	__raw_writel(control, SGMII_CTL_REG(port));
261fc9a8e8dSKaricheri, Muralidharan 
262fc9a8e8dSKaricheri, Muralidharan 
263fc9a8e8dSKaricheri, Muralidharan 	mask = SGMII_REG_STATUS_LINK;
264fc9a8e8dSKaricheri, Muralidharan 
265fc9a8e8dSKaricheri, Muralidharan 	if (control & SGMII_REG_CONTROL_AUTONEG)
266fc9a8e8dSKaricheri, Muralidharan 		mask |= SGMII_REG_STATUS_AUTONEG;
267fc9a8e8dSKaricheri, Muralidharan 
268fc9a8e8dSKaricheri, Muralidharan 	status = __raw_readl(SGMII_STATUS_REG(port));
269fc9a8e8dSKaricheri, Muralidharan 	if ((status & mask) == mask)
270c05d05e7SKhoronzhuk, Ivan 		return 0;
271c05d05e7SKhoronzhuk, Ivan 
272c05d05e7SKhoronzhuk, Ivan 	printf("\n%s Waiting for SGMII auto negotiation to complete",
273c05d05e7SKhoronzhuk, Ivan 	       phy_dev->dev->name);
274c05d05e7SKhoronzhuk, Ivan 	while ((status & mask) != mask) {
275c05d05e7SKhoronzhuk, Ivan 		/*
276c05d05e7SKhoronzhuk, Ivan 		 * Timeout reached ?
277c05d05e7SKhoronzhuk, Ivan 		 */
278c05d05e7SKhoronzhuk, Ivan 		if (i > SGMII_ANEG_TIMEOUT) {
279c05d05e7SKhoronzhuk, Ivan 			puts(" TIMEOUT !\n");
280c05d05e7SKhoronzhuk, Ivan 			phy_dev->link = 0;
281c05d05e7SKhoronzhuk, Ivan 			return 0;
282fc9a8e8dSKaricheri, Muralidharan 		}
283fc9a8e8dSKaricheri, Muralidharan 
284c05d05e7SKhoronzhuk, Ivan 		if (ctrlc()) {
285c05d05e7SKhoronzhuk, Ivan 			puts("user interrupt!\n");
286c05d05e7SKhoronzhuk, Ivan 			phy_dev->link = 0;
287c05d05e7SKhoronzhuk, Ivan 			return -EINTR;
288c05d05e7SKhoronzhuk, Ivan 		}
289c05d05e7SKhoronzhuk, Ivan 
290c05d05e7SKhoronzhuk, Ivan 		if ((i++ % 500) == 0)
291c05d05e7SKhoronzhuk, Ivan 			printf(".");
292c05d05e7SKhoronzhuk, Ivan 
293c05d05e7SKhoronzhuk, Ivan 		udelay(1000);   /* 1 ms */
294c05d05e7SKhoronzhuk, Ivan 		status = __raw_readl(SGMII_STATUS_REG(port));
295c05d05e7SKhoronzhuk, Ivan 	}
296c05d05e7SKhoronzhuk, Ivan 	puts(" done\n");
297c05d05e7SKhoronzhuk, Ivan 
298fc9a8e8dSKaricheri, Muralidharan 	return 0;
299fc9a8e8dSKaricheri, Muralidharan }
300*4657a2d4SVitaly Andrianov #endif
301fc9a8e8dSKaricheri, Muralidharan 
302fc9a8e8dSKaricheri, Muralidharan int mac_sl_reset(u32 port)
303fc9a8e8dSKaricheri, Muralidharan {
304fc9a8e8dSKaricheri, Muralidharan 	u32 i, v;
305fc9a8e8dSKaricheri, Muralidharan 
306fc9a8e8dSKaricheri, Muralidharan 	if (port >= DEVICE_N_GMACSL_PORTS)
307fc9a8e8dSKaricheri, Muralidharan 		return GMACSL_RET_INVALID_PORT;
308fc9a8e8dSKaricheri, Muralidharan 
309fc9a8e8dSKaricheri, Muralidharan 	/* Set the soft reset bit */
310e6c9428aSKhoronzhuk, Ivan 	writel(CPGMAC_REG_RESET_VAL_RESET,
311e6c9428aSKhoronzhuk, Ivan 	       DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET);
312fc9a8e8dSKaricheri, Muralidharan 
313fc9a8e8dSKaricheri, Muralidharan 	/* Wait for the bit to clear */
314fc9a8e8dSKaricheri, Muralidharan 	for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
315e6c9428aSKhoronzhuk, Ivan 		v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET);
316fc9a8e8dSKaricheri, Muralidharan 		if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
317fc9a8e8dSKaricheri, Muralidharan 		    CPGMAC_REG_RESET_VAL_RESET)
318fc9a8e8dSKaricheri, Muralidharan 			return GMACSL_RET_OK;
319fc9a8e8dSKaricheri, Muralidharan 	}
320fc9a8e8dSKaricheri, Muralidharan 
321fc9a8e8dSKaricheri, Muralidharan 	/* Timeout on the reset */
322fc9a8e8dSKaricheri, Muralidharan 	return GMACSL_RET_WARN_RESET_INCOMPLETE;
323fc9a8e8dSKaricheri, Muralidharan }
324fc9a8e8dSKaricheri, Muralidharan 
325fc9a8e8dSKaricheri, Muralidharan int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg)
326fc9a8e8dSKaricheri, Muralidharan {
327fc9a8e8dSKaricheri, Muralidharan 	u32 v, i;
328fc9a8e8dSKaricheri, Muralidharan 	int ret = GMACSL_RET_OK;
329fc9a8e8dSKaricheri, Muralidharan 
330fc9a8e8dSKaricheri, Muralidharan 	if (port >= DEVICE_N_GMACSL_PORTS)
331fc9a8e8dSKaricheri, Muralidharan 		return GMACSL_RET_INVALID_PORT;
332fc9a8e8dSKaricheri, Muralidharan 
333fc9a8e8dSKaricheri, Muralidharan 	if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) {
334fc9a8e8dSKaricheri, Muralidharan 		cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN;
335fc9a8e8dSKaricheri, Muralidharan 		ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG;
336fc9a8e8dSKaricheri, Muralidharan 	}
337fc9a8e8dSKaricheri, Muralidharan 
338fc9a8e8dSKaricheri, Muralidharan 	/* Must wait if the device is undergoing reset */
339fc9a8e8dSKaricheri, Muralidharan 	for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
340e6c9428aSKhoronzhuk, Ivan 		v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET);
341fc9a8e8dSKaricheri, Muralidharan 		if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
342fc9a8e8dSKaricheri, Muralidharan 		    CPGMAC_REG_RESET_VAL_RESET)
343fc9a8e8dSKaricheri, Muralidharan 			break;
344fc9a8e8dSKaricheri, Muralidharan 	}
345fc9a8e8dSKaricheri, Muralidharan 
346fc9a8e8dSKaricheri, Muralidharan 	if (i == DEVICE_EMACSL_RESET_POLL_COUNT)
347fc9a8e8dSKaricheri, Muralidharan 		return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE;
348fc9a8e8dSKaricheri, Muralidharan 
349e6c9428aSKhoronzhuk, Ivan 	writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN);
350e6c9428aSKhoronzhuk, Ivan 	writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL);
351fc9a8e8dSKaricheri, Muralidharan 
352*4657a2d4SVitaly Andrianov #ifndef CONFIG_SOC_K2HK
353ff11c769SKhoronzhuk, Ivan 	/* Map RX packet flow priority to 0 */
354ff11c769SKhoronzhuk, Ivan 	writel(0, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RX_PRI_MAP);
355ff11c769SKhoronzhuk, Ivan #endif
356ff11c769SKhoronzhuk, Ivan 
357fc9a8e8dSKaricheri, Muralidharan 	return ret;
358fc9a8e8dSKaricheri, Muralidharan }
359fc9a8e8dSKaricheri, Muralidharan 
360fc9a8e8dSKaricheri, Muralidharan int ethss_config(u32 ctl, u32 max_pkt_size)
361fc9a8e8dSKaricheri, Muralidharan {
362fc9a8e8dSKaricheri, Muralidharan 	u32 i;
363fc9a8e8dSKaricheri, Muralidharan 
364fc9a8e8dSKaricheri, Muralidharan 	/* Max length register */
365e6c9428aSKhoronzhuk, Ivan 	writel(max_pkt_size, DEVICE_CPSW_BASE + CPSW_REG_MAXLEN);
366fc9a8e8dSKaricheri, Muralidharan 
367fc9a8e8dSKaricheri, Muralidharan 	/* Control register */
368e6c9428aSKhoronzhuk, Ivan 	writel(ctl, DEVICE_CPSW_BASE + CPSW_REG_CTL);
369fc9a8e8dSKaricheri, Muralidharan 
370fc9a8e8dSKaricheri, Muralidharan 	/* All statistics enabled by default */
371e6c9428aSKhoronzhuk, Ivan 	writel(CPSW_REG_VAL_STAT_ENABLE_ALL,
372e6c9428aSKhoronzhuk, Ivan 	       DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN);
373fc9a8e8dSKaricheri, Muralidharan 
374fc9a8e8dSKaricheri, Muralidharan 	/* Reset and enable the ALE */
375e6c9428aSKhoronzhuk, Ivan 	writel(CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE |
376e6c9428aSKhoronzhuk, Ivan 	       CPSW_REG_VAL_ALE_CTL_BYPASS,
377e6c9428aSKhoronzhuk, Ivan 	       DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL);
378fc9a8e8dSKaricheri, Muralidharan 
379fc9a8e8dSKaricheri, Muralidharan 	/* All ports put into forward mode */
380fc9a8e8dSKaricheri, Muralidharan 	for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++)
381e6c9428aSKhoronzhuk, Ivan 		writel(CPSW_REG_VAL_PORTCTL_FORWARD_MODE,
382e6c9428aSKhoronzhuk, Ivan 		       DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i));
383fc9a8e8dSKaricheri, Muralidharan 
384fc9a8e8dSKaricheri, Muralidharan 	return 0;
385fc9a8e8dSKaricheri, Muralidharan }
386fc9a8e8dSKaricheri, Muralidharan 
387fc9a8e8dSKaricheri, Muralidharan int ethss_start(void)
388fc9a8e8dSKaricheri, Muralidharan {
389fc9a8e8dSKaricheri, Muralidharan 	int i;
390fc9a8e8dSKaricheri, Muralidharan 	struct mac_sl_cfg cfg;
391fc9a8e8dSKaricheri, Muralidharan 
392fc9a8e8dSKaricheri, Muralidharan 	cfg.max_rx_len	= MAX_SIZE_STREAM_BUFFER;
393fc9a8e8dSKaricheri, Muralidharan 	cfg.ctl		= GMACSL_ENABLE | GMACSL_RX_ENABLE_EXT_CTL;
394fc9a8e8dSKaricheri, Muralidharan 
395fc9a8e8dSKaricheri, Muralidharan 	for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) {
396fc9a8e8dSKaricheri, Muralidharan 		mac_sl_reset(i);
397fc9a8e8dSKaricheri, Muralidharan 		mac_sl_config(i, &cfg);
398fc9a8e8dSKaricheri, Muralidharan 	}
399fc9a8e8dSKaricheri, Muralidharan 
400fc9a8e8dSKaricheri, Muralidharan 	return 0;
401fc9a8e8dSKaricheri, Muralidharan }
402fc9a8e8dSKaricheri, Muralidharan 
403fc9a8e8dSKaricheri, Muralidharan int ethss_stop(void)
404fc9a8e8dSKaricheri, Muralidharan {
405fc9a8e8dSKaricheri, Muralidharan 	int i;
406fc9a8e8dSKaricheri, Muralidharan 
407fc9a8e8dSKaricheri, Muralidharan 	for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++)
408fc9a8e8dSKaricheri, Muralidharan 		mac_sl_reset(i);
409fc9a8e8dSKaricheri, Muralidharan 
410fc9a8e8dSKaricheri, Muralidharan 	return 0;
411fc9a8e8dSKaricheri, Muralidharan }
412fc9a8e8dSKaricheri, Muralidharan 
413fc9a8e8dSKaricheri, Muralidharan int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num)
414fc9a8e8dSKaricheri, Muralidharan {
415fc9a8e8dSKaricheri, Muralidharan 	if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE)
416fc9a8e8dSKaricheri, Muralidharan 		num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE;
417fc9a8e8dSKaricheri, Muralidharan 
4189ea9021aSKhoronzhuk, Ivan 	return ksnav_send(&netcp_pktdma, buffer,
4199ea9021aSKhoronzhuk, Ivan 			  num_bytes, (slave_port_num) << 16);
420fc9a8e8dSKaricheri, Muralidharan }
421fc9a8e8dSKaricheri, Muralidharan 
422fc9a8e8dSKaricheri, Muralidharan /* Eth device open */
423fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
424fc9a8e8dSKaricheri, Muralidharan {
425fc9a8e8dSKaricheri, Muralidharan 	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
4263fe93623SKhoronzhuk, Ivan 	struct phy_device *phy_dev = eth_priv->phy_dev;
427fc9a8e8dSKaricheri, Muralidharan 
428fc9a8e8dSKaricheri, Muralidharan 	debug("+ emac_open\n");
429fc9a8e8dSKaricheri, Muralidharan 
430fc9a8e8dSKaricheri, Muralidharan 	net_rx_buffs.rx_flow	= eth_priv->rx_flow;
431fc9a8e8dSKaricheri, Muralidharan 
432fc9a8e8dSKaricheri, Muralidharan 	sys_has_mdio =
433fc9a8e8dSKaricheri, Muralidharan 		(eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0;
434fc9a8e8dSKaricheri, Muralidharan 
4356c0fb41aSKhoronzhuk, Ivan 	if (sys_has_mdio)
4366c0fb41aSKhoronzhuk, Ivan 		keystone2_mdio_reset(mdio_bus);
4376c0fb41aSKhoronzhuk, Ivan 
438*4657a2d4SVitaly Andrianov #ifdef CONFIG_SOC_K2G
439*4657a2d4SVitaly Andrianov 	keystone_rgmii_config(phy_dev);
440*4657a2d4SVitaly Andrianov #else
441c05d05e7SKhoronzhuk, Ivan 	keystone_sgmii_config(phy_dev, eth_priv->slave_port - 1,
442fc9a8e8dSKaricheri, Muralidharan 			      eth_priv->sgmii_link_type);
443*4657a2d4SVitaly Andrianov #endif
444fc9a8e8dSKaricheri, Muralidharan 
445fc9a8e8dSKaricheri, Muralidharan 	udelay(10000);
446fc9a8e8dSKaricheri, Muralidharan 
447fc9a8e8dSKaricheri, Muralidharan 	/* On chip switch configuration */
448fc9a8e8dSKaricheri, Muralidharan 	ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE);
449fc9a8e8dSKaricheri, Muralidharan 
450fc9a8e8dSKaricheri, Muralidharan 	/* TODO: add error handling code */
451fc9a8e8dSKaricheri, Muralidharan 	if (qm_init()) {
452fc9a8e8dSKaricheri, Muralidharan 		printf("ERROR: qm_init()\n");
453fc9a8e8dSKaricheri, Muralidharan 		return -1;
454fc9a8e8dSKaricheri, Muralidharan 	}
4559ea9021aSKhoronzhuk, Ivan 	if (ksnav_init(&netcp_pktdma, &net_rx_buffs)) {
456fc9a8e8dSKaricheri, Muralidharan 		qm_close();
457fc9a8e8dSKaricheri, Muralidharan 		printf("ERROR: netcp_init()\n");
458fc9a8e8dSKaricheri, Muralidharan 		return -1;
459fc9a8e8dSKaricheri, Muralidharan 	}
460fc9a8e8dSKaricheri, Muralidharan 
461fc9a8e8dSKaricheri, Muralidharan 	/*
462fc9a8e8dSKaricheri, Muralidharan 	 * Streaming switch configuration. If not present this
463fc9a8e8dSKaricheri, Muralidharan 	 * statement is defined to void in target.h.
464fc9a8e8dSKaricheri, Muralidharan 	 * If present this is usually defined to a series of register writes
465fc9a8e8dSKaricheri, Muralidharan 	 */
466fc9a8e8dSKaricheri, Muralidharan 	hw_config_streaming_switch();
467fc9a8e8dSKaricheri, Muralidharan 
468fc9a8e8dSKaricheri, Muralidharan 	if (sys_has_mdio) {
469550c5ce6SKhoronzhuk, Ivan 		keystone2_mdio_reset(mdio_bus);
470fc9a8e8dSKaricheri, Muralidharan 
4713fe93623SKhoronzhuk, Ivan 		phy_startup(phy_dev);
4723fe93623SKhoronzhuk, Ivan 		if (phy_dev->link == 0) {
4739ea9021aSKhoronzhuk, Ivan 			ksnav_close(&netcp_pktdma);
474fc9a8e8dSKaricheri, Muralidharan 			qm_close();
475fc9a8e8dSKaricheri, Muralidharan 			return -1;
476fc9a8e8dSKaricheri, Muralidharan 		}
477fc9a8e8dSKaricheri, Muralidharan 	}
478fc9a8e8dSKaricheri, Muralidharan 
479fc9a8e8dSKaricheri, Muralidharan 	emac_gigabit_enable(dev);
480fc9a8e8dSKaricheri, Muralidharan 
481fc9a8e8dSKaricheri, Muralidharan 	ethss_start();
482fc9a8e8dSKaricheri, Muralidharan 
483fc9a8e8dSKaricheri, Muralidharan 	debug("- emac_open\n");
484fc9a8e8dSKaricheri, Muralidharan 
485fc9a8e8dSKaricheri, Muralidharan 	emac_open = 1;
486fc9a8e8dSKaricheri, Muralidharan 
487fc9a8e8dSKaricheri, Muralidharan 	return 0;
488fc9a8e8dSKaricheri, Muralidharan }
489fc9a8e8dSKaricheri, Muralidharan 
490fc9a8e8dSKaricheri, Muralidharan /* Eth device close */
491fc9a8e8dSKaricheri, Muralidharan void keystone2_eth_close(struct eth_device *dev)
492fc9a8e8dSKaricheri, Muralidharan {
4933fe93623SKhoronzhuk, Ivan 	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
4943fe93623SKhoronzhuk, Ivan 	struct phy_device *phy_dev = eth_priv->phy_dev;
4953fe93623SKhoronzhuk, Ivan 
496fc9a8e8dSKaricheri, Muralidharan 	debug("+ emac_close\n");
497fc9a8e8dSKaricheri, Muralidharan 
498fc9a8e8dSKaricheri, Muralidharan 	if (!emac_open)
499fc9a8e8dSKaricheri, Muralidharan 		return;
500fc9a8e8dSKaricheri, Muralidharan 
501fc9a8e8dSKaricheri, Muralidharan 	ethss_stop();
502fc9a8e8dSKaricheri, Muralidharan 
5039ea9021aSKhoronzhuk, Ivan 	ksnav_close(&netcp_pktdma);
504fc9a8e8dSKaricheri, Muralidharan 	qm_close();
5053fe93623SKhoronzhuk, Ivan 	phy_shutdown(phy_dev);
506fc9a8e8dSKaricheri, Muralidharan 
507fc9a8e8dSKaricheri, Muralidharan 	emac_open = 0;
508fc9a8e8dSKaricheri, Muralidharan 
509fc9a8e8dSKaricheri, Muralidharan 	debug("- emac_close\n");
510fc9a8e8dSKaricheri, Muralidharan }
511fc9a8e8dSKaricheri, Muralidharan 
512fc9a8e8dSKaricheri, Muralidharan /*
513fc9a8e8dSKaricheri, Muralidharan  * This function sends a single packet on the network and returns
514fc9a8e8dSKaricheri, Muralidharan  * positive number (number of bytes transmitted) or negative for error
515fc9a8e8dSKaricheri, Muralidharan  */
516fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_send_packet(struct eth_device *dev,
517fc9a8e8dSKaricheri, Muralidharan 					void *packet, int length)
518fc9a8e8dSKaricheri, Muralidharan {
519fc9a8e8dSKaricheri, Muralidharan 	int ret_status = -1;
520fc9a8e8dSKaricheri, Muralidharan 	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
521a4d2adeeSKhoronzhuk, Ivan 	struct phy_device *phy_dev = eth_priv->phy_dev;
522fc9a8e8dSKaricheri, Muralidharan 
523a4d2adeeSKhoronzhuk, Ivan 	genphy_update_link(phy_dev);
524a4d2adeeSKhoronzhuk, Ivan 	if (phy_dev->link == 0)
525fc9a8e8dSKaricheri, Muralidharan 		return -1;
526fc9a8e8dSKaricheri, Muralidharan 
527fc9a8e8dSKaricheri, Muralidharan 	if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0)
528fc9a8e8dSKaricheri, Muralidharan 		return ret_status;
529fc9a8e8dSKaricheri, Muralidharan 
530fc9a8e8dSKaricheri, Muralidharan 	return length;
531fc9a8e8dSKaricheri, Muralidharan }
532fc9a8e8dSKaricheri, Muralidharan 
533fc9a8e8dSKaricheri, Muralidharan /*
534fc9a8e8dSKaricheri, Muralidharan  * This function handles receipt of a packet from the network
535fc9a8e8dSKaricheri, Muralidharan  */
536fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_rcv_packet(struct eth_device *dev)
537fc9a8e8dSKaricheri, Muralidharan {
538fc9a8e8dSKaricheri, Muralidharan 	void *hd;
539fc9a8e8dSKaricheri, Muralidharan 	int  pkt_size;
540fc9a8e8dSKaricheri, Muralidharan 	u32  *pkt;
541fc9a8e8dSKaricheri, Muralidharan 
5429ea9021aSKhoronzhuk, Ivan 	hd = ksnav_recv(&netcp_pktdma, &pkt, &pkt_size);
543fc9a8e8dSKaricheri, Muralidharan 	if (hd == NULL)
544fc9a8e8dSKaricheri, Muralidharan 		return 0;
545fc9a8e8dSKaricheri, Muralidharan 
5461fd92db8SJoe Hershberger 	net_process_received_packet((uchar *)pkt, pkt_size);
547fc9a8e8dSKaricheri, Muralidharan 
5489ea9021aSKhoronzhuk, Ivan 	ksnav_release_rxhd(&netcp_pktdma, hd);
549fc9a8e8dSKaricheri, Muralidharan 
550fc9a8e8dSKaricheri, Muralidharan 	return pkt_size;
551fc9a8e8dSKaricheri, Muralidharan }
552fc9a8e8dSKaricheri, Muralidharan 
5535031ca59SVitaly Andrianov #ifdef CONFIG_MCAST_TFTP
5545031ca59SVitaly Andrianov static int keystone2_eth_bcast_addr(struct eth_device *dev, u32 ip, u8 set)
5555031ca59SVitaly Andrianov {
5565031ca59SVitaly Andrianov 	return 0;
5575031ca59SVitaly Andrianov }
5585031ca59SVitaly Andrianov #endif
5595031ca59SVitaly Andrianov 
560fc9a8e8dSKaricheri, Muralidharan /*
561fc9a8e8dSKaricheri, Muralidharan  * This function initializes the EMAC hardware.
562fc9a8e8dSKaricheri, Muralidharan  */
563fc9a8e8dSKaricheri, Muralidharan int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
564fc9a8e8dSKaricheri, Muralidharan {
565550c5ce6SKhoronzhuk, Ivan 	int res;
566fc9a8e8dSKaricheri, Muralidharan 	struct eth_device *dev;
5673fe93623SKhoronzhuk, Ivan 	struct phy_device *phy_dev;
568fc9a8e8dSKaricheri, Muralidharan 
569fc9a8e8dSKaricheri, Muralidharan 	dev = malloc(sizeof(struct eth_device));
570fc9a8e8dSKaricheri, Muralidharan 	if (dev == NULL)
571fc9a8e8dSKaricheri, Muralidharan 		return -1;
572fc9a8e8dSKaricheri, Muralidharan 
573fc9a8e8dSKaricheri, Muralidharan 	memset(dev, 0, sizeof(struct eth_device));
574fc9a8e8dSKaricheri, Muralidharan 
575fc9a8e8dSKaricheri, Muralidharan 	strcpy(dev->name, eth_priv->int_name);
576fc9a8e8dSKaricheri, Muralidharan 	dev->priv = eth_priv;
577fc9a8e8dSKaricheri, Muralidharan 
578fc9a8e8dSKaricheri, Muralidharan 	keystone2_eth_read_mac_addr(dev);
579fc9a8e8dSKaricheri, Muralidharan 
580fc9a8e8dSKaricheri, Muralidharan 	dev->iobase		= 0;
581fc9a8e8dSKaricheri, Muralidharan 	dev->init		= keystone2_eth_open;
582fc9a8e8dSKaricheri, Muralidharan 	dev->halt		= keystone2_eth_close;
583fc9a8e8dSKaricheri, Muralidharan 	dev->send		= keystone2_eth_send_packet;
584fc9a8e8dSKaricheri, Muralidharan 	dev->recv		= keystone2_eth_rcv_packet;
5855031ca59SVitaly Andrianov #ifdef CONFIG_MCAST_TFTP
5865031ca59SVitaly Andrianov 	dev->mcast		= keystone2_eth_bcast_addr;
5875031ca59SVitaly Andrianov #endif
588fc9a8e8dSKaricheri, Muralidharan 
589fc9a8e8dSKaricheri, Muralidharan 	eth_register(dev);
590fc9a8e8dSKaricheri, Muralidharan 
591550c5ce6SKhoronzhuk, Ivan 	/* Register MDIO bus if it's not registered yet */
592550c5ce6SKhoronzhuk, Ivan 	if (!mdio_bus) {
593550c5ce6SKhoronzhuk, Ivan 		mdio_bus	= mdio_alloc();
594550c5ce6SKhoronzhuk, Ivan 		mdio_bus->read	= keystone2_mdio_read;
595550c5ce6SKhoronzhuk, Ivan 		mdio_bus->write	= keystone2_mdio_write;
596550c5ce6SKhoronzhuk, Ivan 		mdio_bus->reset	= keystone2_mdio_reset;
597550c5ce6SKhoronzhuk, Ivan 		mdio_bus->priv	= (void *)EMAC_MDIO_BASE_ADDR;
598550c5ce6SKhoronzhuk, Ivan 		sprintf(mdio_bus->name, "ethernet-mdio");
599550c5ce6SKhoronzhuk, Ivan 
600550c5ce6SKhoronzhuk, Ivan 		res = mdio_register(mdio_bus);
601550c5ce6SKhoronzhuk, Ivan 		if (res)
602550c5ce6SKhoronzhuk, Ivan 			return res;
603550c5ce6SKhoronzhuk, Ivan 	}
604550c5ce6SKhoronzhuk, Ivan 
605*4657a2d4SVitaly Andrianov #ifndef CONFIG_SOC_K2G
606312aca4eSVitaly Andrianov 	keystone2_net_serdes_setup();
607*4657a2d4SVitaly Andrianov #endif
608312aca4eSVitaly Andrianov 
6093fe93623SKhoronzhuk, Ivan 	/* Create phy device and bind it with driver */
6103fe93623SKhoronzhuk, Ivan #ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE
6113fe93623SKhoronzhuk, Ivan 	phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr,
612bf7bd4e7SMugunthan V N 			      dev, eth_priv->phy_if);
6133fe93623SKhoronzhuk, Ivan 	phy_config(phy_dev);
6143fe93623SKhoronzhuk, Ivan #else
6153fe93623SKhoronzhuk, Ivan 	phy_dev = phy_find_by_mask(mdio_bus, 1 << eth_priv->phy_addr,
616bf7bd4e7SMugunthan V N 				   eth_priv->phy_if);
6173fe93623SKhoronzhuk, Ivan 	phy_dev->dev = dev;
6183fe93623SKhoronzhuk, Ivan #endif
6193fe93623SKhoronzhuk, Ivan 	eth_priv->phy_dev = phy_dev;
6203fe93623SKhoronzhuk, Ivan 
621fc9a8e8dSKaricheri, Muralidharan 	return 0;
622fc9a8e8dSKaricheri, Muralidharan }
623fc9a8e8dSKaricheri, Muralidharan 
62492a16c81SHao Zhang struct ks2_serdes ks2_serdes_sgmii_156p25mhz = {
62592a16c81SHao Zhang 	.clk = SERDES_CLOCK_156P25M,
62692a16c81SHao Zhang 	.rate = SERDES_RATE_5G,
62792a16c81SHao Zhang 	.rate_mode = SERDES_QUARTER_RATE,
62892a16c81SHao Zhang 	.intf = SERDES_PHY_SGMII,
62992a16c81SHao Zhang 	.loopback = 0,
63092a16c81SHao Zhang };
63192a16c81SHao Zhang 
632*4657a2d4SVitaly Andrianov #ifndef CONFIG_SOC_K2G
633a43febdeSKhoronzhuk, Ivan static void keystone2_net_serdes_setup(void)
634fc9a8e8dSKaricheri, Muralidharan {
63592a16c81SHao Zhang 	ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE,
63692a16c81SHao Zhang 			&ks2_serdes_sgmii_156p25mhz,
63792a16c81SHao Zhang 			CONFIG_KSNET_SERDES_LANES_PER_SGMII);
63892a16c81SHao Zhang 
63987ac27bdSKhoronzhuk, Ivan #if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L)
6403c61502aSKhoronzhuk, Ivan 	ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE,
6413c61502aSKhoronzhuk, Ivan 			&ks2_serdes_sgmii_156p25mhz,
6423c61502aSKhoronzhuk, Ivan 			CONFIG_KSNET_SERDES_LANES_PER_SGMII);
6433c61502aSKhoronzhuk, Ivan #endif
6443c61502aSKhoronzhuk, Ivan 
64592a16c81SHao Zhang 	/* wait till setup */
64692a16c81SHao Zhang 	udelay(5000);
647fc9a8e8dSKaricheri, Muralidharan }
648*4657a2d4SVitaly Andrianov #endif
649