xref: /rk3399_rockchip-uboot/drivers/net/bcm-sf2-eth.c (revision 799e125cca9f75a6e3bc87676266f8da4ebefcfd)
1*799e125cSJiandong Zheng /*
2*799e125cSJiandong Zheng  * Copyright 2014 Broadcom Corporation.
3*799e125cSJiandong Zheng  *
4*799e125cSJiandong Zheng  * SPDX-License-Identifier:	GPL-2.0+
5*799e125cSJiandong Zheng  */
6*799e125cSJiandong Zheng 
7*799e125cSJiandong Zheng #include <common.h>
8*799e125cSJiandong Zheng #include <malloc.h>
9*799e125cSJiandong Zheng #include <net.h>
10*799e125cSJiandong Zheng #include <config.h>
11*799e125cSJiandong Zheng 
12*799e125cSJiandong Zheng #include <phy.h>
13*799e125cSJiandong Zheng #include <miiphy.h>
14*799e125cSJiandong Zheng 
15*799e125cSJiandong Zheng #include <asm/io.h>
16*799e125cSJiandong Zheng 
17*799e125cSJiandong Zheng #include <netdev.h>
18*799e125cSJiandong Zheng #include "bcm-sf2-eth.h"
19*799e125cSJiandong Zheng 
20*799e125cSJiandong Zheng #if defined(CONFIG_BCM_SF2_ETH_GMAC)
21*799e125cSJiandong Zheng #include "bcm-sf2-eth-gmac.h"
22*799e125cSJiandong Zheng #else
23*799e125cSJiandong Zheng #error "bcm_sf2_eth: NEED to define a MAC!"
24*799e125cSJiandong Zheng #endif
25*799e125cSJiandong Zheng 
26*799e125cSJiandong Zheng #define BCM_NET_MODULE_DESCRIPTION	"Broadcom Starfighter2 Ethernet driver"
27*799e125cSJiandong Zheng #define BCM_NET_MODULE_VERSION		"0.1"
28*799e125cSJiandong Zheng #define BCM_SF2_ETH_DEV_NAME		"bcm_sf2"
29*799e125cSJiandong Zheng 
30*799e125cSJiandong Zheng static const char banner[] =
31*799e125cSJiandong Zheng 	BCM_NET_MODULE_DESCRIPTION " " BCM_NET_MODULE_VERSION "\n";
32*799e125cSJiandong Zheng 
33*799e125cSJiandong Zheng static int bcm_sf2_eth_init(struct eth_device *dev)
34*799e125cSJiandong Zheng {
35*799e125cSJiandong Zheng 	struct eth_info *eth = (struct eth_info *)(dev->priv);
36*799e125cSJiandong Zheng 	struct eth_dma *dma = &(eth->dma);
37*799e125cSJiandong Zheng 	struct phy_device *phydev;
38*799e125cSJiandong Zheng 	int rc = 0;
39*799e125cSJiandong Zheng 	int i;
40*799e125cSJiandong Zheng 
41*799e125cSJiandong Zheng 	rc = eth->mac_init(dev);
42*799e125cSJiandong Zheng 	if (rc) {
43*799e125cSJiandong Zheng 		error("%s: Couldn't cofigure MAC!\n", __func__);
44*799e125cSJiandong Zheng 		return rc;
45*799e125cSJiandong Zheng 	}
46*799e125cSJiandong Zheng 
47*799e125cSJiandong Zheng 	/* disable DMA */
48*799e125cSJiandong Zheng 	dma->disable_dma(dma, MAC_DMA_RX);
49*799e125cSJiandong Zheng 	dma->disable_dma(dma, MAC_DMA_TX);
50*799e125cSJiandong Zheng 
51*799e125cSJiandong Zheng 	eth->port_num = 0;
52*799e125cSJiandong Zheng 	debug("Connecting PHY 0...\n");
53*799e125cSJiandong Zheng 	phydev = phy_connect(miiphy_get_dev_by_name(dev->name),
54*799e125cSJiandong Zheng 			     0, dev, eth->phy_interface);
55*799e125cSJiandong Zheng 	if (phydev != NULL) {
56*799e125cSJiandong Zheng 		eth->port[0] = phydev;
57*799e125cSJiandong Zheng 		eth->port_num += 1;
58*799e125cSJiandong Zheng 	} else {
59*799e125cSJiandong Zheng 		debug("No PHY found for port 0\n");
60*799e125cSJiandong Zheng 	}
61*799e125cSJiandong Zheng 
62*799e125cSJiandong Zheng 	for (i = 0; i < eth->port_num; i++)
63*799e125cSJiandong Zheng 		phy_config(eth->port[i]);
64*799e125cSJiandong Zheng 
65*799e125cSJiandong Zheng 	return rc;
66*799e125cSJiandong Zheng }
67*799e125cSJiandong Zheng 
68*799e125cSJiandong Zheng /*
69*799e125cSJiandong Zheng  * u-boot net functions
70*799e125cSJiandong Zheng  */
71*799e125cSJiandong Zheng 
72*799e125cSJiandong Zheng static int bcm_sf2_eth_send(struct eth_device *dev, void *packet, int length)
73*799e125cSJiandong Zheng {
74*799e125cSJiandong Zheng 	struct eth_dma *dma = &(((struct eth_info *)(dev->priv))->dma);
75*799e125cSJiandong Zheng 	uint8_t *buf = (uint8_t *)packet;
76*799e125cSJiandong Zheng 	int rc = 0;
77*799e125cSJiandong Zheng 	int i = 0;
78*799e125cSJiandong Zheng 
79*799e125cSJiandong Zheng 	debug("%s enter\n", __func__);
80*799e125cSJiandong Zheng 
81*799e125cSJiandong Zheng 	/* load buf and start transmit */
82*799e125cSJiandong Zheng 	rc = dma->tx_packet(dma, buf, length);
83*799e125cSJiandong Zheng 	if (rc) {
84*799e125cSJiandong Zheng 		debug("ERROR - Tx failed\n");
85*799e125cSJiandong Zheng 		return rc;
86*799e125cSJiandong Zheng 	}
87*799e125cSJiandong Zheng 
88*799e125cSJiandong Zheng 	while (!(dma->check_tx_done(dma))) {
89*799e125cSJiandong Zheng 		udelay(100);
90*799e125cSJiandong Zheng 		debug(".");
91*799e125cSJiandong Zheng 		i++;
92*799e125cSJiandong Zheng 		if (i > 20) {
93*799e125cSJiandong Zheng 			error("%s: Tx timeout: retried 20 times\n", __func__);
94*799e125cSJiandong Zheng 			rc = -1;
95*799e125cSJiandong Zheng 			break;
96*799e125cSJiandong Zheng 		}
97*799e125cSJiandong Zheng 	}
98*799e125cSJiandong Zheng 
99*799e125cSJiandong Zheng 	debug("%s exit rc(0x%x)\n", __func__, rc);
100*799e125cSJiandong Zheng 	return rc;
101*799e125cSJiandong Zheng }
102*799e125cSJiandong Zheng 
103*799e125cSJiandong Zheng static int bcm_sf2_eth_receive(struct eth_device *dev)
104*799e125cSJiandong Zheng {
105*799e125cSJiandong Zheng 	struct eth_dma *dma = &(((struct eth_info *)(dev->priv))->dma);
106*799e125cSJiandong Zheng 	uint8_t *buf = (uint8_t *)NetRxPackets[0];
107*799e125cSJiandong Zheng 	int rcvlen;
108*799e125cSJiandong Zheng 	int rc = 0;
109*799e125cSJiandong Zheng 	int i = 0;
110*799e125cSJiandong Zheng 
111*799e125cSJiandong Zheng 	while (1) {
112*799e125cSJiandong Zheng 		/* Poll Rx queue to get a packet */
113*799e125cSJiandong Zheng 		rcvlen = dma->check_rx_done(dma, buf);
114*799e125cSJiandong Zheng 		if (rcvlen < 0) {
115*799e125cSJiandong Zheng 			/* No packet received */
116*799e125cSJiandong Zheng 			rc = -1;
117*799e125cSJiandong Zheng 			debug("\nNO More Rx\n");
118*799e125cSJiandong Zheng 			break;
119*799e125cSJiandong Zheng 		} else if ((rcvlen == 0) || (rcvlen > RX_BUF_SIZE)) {
120*799e125cSJiandong Zheng 			error("%s: Wrong Ethernet packet size (%d B), skip!\n",
121*799e125cSJiandong Zheng 			      __func__, rcvlen);
122*799e125cSJiandong Zheng 			break;
123*799e125cSJiandong Zheng 		} else {
124*799e125cSJiandong Zheng 			debug("recieved\n");
125*799e125cSJiandong Zheng 
126*799e125cSJiandong Zheng 			/* Forward received packet to uboot network handler */
127*799e125cSJiandong Zheng 			NetReceive(buf, rcvlen);
128*799e125cSJiandong Zheng 
129*799e125cSJiandong Zheng 			if (++i >= PKTBUFSRX)
130*799e125cSJiandong Zheng 				i = 0;
131*799e125cSJiandong Zheng 			buf = NetRxPackets[i];
132*799e125cSJiandong Zheng 		}
133*799e125cSJiandong Zheng 	}
134*799e125cSJiandong Zheng 
135*799e125cSJiandong Zheng 	return rc;
136*799e125cSJiandong Zheng }
137*799e125cSJiandong Zheng 
138*799e125cSJiandong Zheng static int bcm_sf2_eth_write_hwaddr(struct eth_device *dev)
139*799e125cSJiandong Zheng {
140*799e125cSJiandong Zheng 	struct eth_info *eth = (struct eth_info *)(dev->priv);
141*799e125cSJiandong Zheng 
142*799e125cSJiandong Zheng 	printf(" ETH MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
143*799e125cSJiandong Zheng 	       dev->enetaddr[0], dev->enetaddr[1], dev->enetaddr[2],
144*799e125cSJiandong Zheng 	       dev->enetaddr[3], dev->enetaddr[4], dev->enetaddr[5]);
145*799e125cSJiandong Zheng 
146*799e125cSJiandong Zheng 	return eth->set_mac_addr(dev->enetaddr);
147*799e125cSJiandong Zheng }
148*799e125cSJiandong Zheng 
149*799e125cSJiandong Zheng static int bcm_sf2_eth_open(struct eth_device *dev, bd_t *bt)
150*799e125cSJiandong Zheng {
151*799e125cSJiandong Zheng 	struct eth_info *eth = (struct eth_info *)(dev->priv);
152*799e125cSJiandong Zheng 	struct eth_dma *dma = &(eth->dma);
153*799e125cSJiandong Zheng 	int i;
154*799e125cSJiandong Zheng 
155*799e125cSJiandong Zheng 	debug("Enabling BCM SF2 Ethernet.\n");
156*799e125cSJiandong Zheng 
157*799e125cSJiandong Zheng 	/* Set MAC address from env */
158*799e125cSJiandong Zheng 	if (bcm_sf2_eth_write_hwaddr(dev) != 0) {
159*799e125cSJiandong Zheng 		error("%s: MAC set error when opening !\n", __func__);
160*799e125cSJiandong Zheng 		return -1;
161*799e125cSJiandong Zheng 	}
162*799e125cSJiandong Zheng 
163*799e125cSJiandong Zheng 	eth->enable_mac();
164*799e125cSJiandong Zheng 
165*799e125cSJiandong Zheng 	/* enable tx and rx DMA */
166*799e125cSJiandong Zheng 	dma->enable_dma(dma, MAC_DMA_RX);
167*799e125cSJiandong Zheng 	dma->enable_dma(dma, MAC_DMA_TX);
168*799e125cSJiandong Zheng 
169*799e125cSJiandong Zheng 	/*
170*799e125cSJiandong Zheng 	 * Need to start PHY here because link speed can change
171*799e125cSJiandong Zheng 	 * before each ethernet operation
172*799e125cSJiandong Zheng 	 */
173*799e125cSJiandong Zheng 	for (i = 0; i < eth->port_num; i++) {
174*799e125cSJiandong Zheng 		if (phy_startup(eth->port[i])) {
175*799e125cSJiandong Zheng 			error("%s: PHY %d startup failed!\n", __func__, i);
176*799e125cSJiandong Zheng 			if (i == CONFIG_BCM_SF2_ETH_DEFAULT_PORT) {
177*799e125cSJiandong Zheng 				error("%s: No default port %d!\n", __func__, i);
178*799e125cSJiandong Zheng 				return -1;
179*799e125cSJiandong Zheng 			}
180*799e125cSJiandong Zheng 		}
181*799e125cSJiandong Zheng 	}
182*799e125cSJiandong Zheng 
183*799e125cSJiandong Zheng 	/* Set MAC speed using default port */
184*799e125cSJiandong Zheng 	i = CONFIG_BCM_SF2_ETH_DEFAULT_PORT;
185*799e125cSJiandong Zheng 	debug("PHY %d: speed:%d, duplex:%d, link:%d\n", i,
186*799e125cSJiandong Zheng 	      eth->port[i]->speed, eth->port[i]->duplex, eth->port[i]->link);
187*799e125cSJiandong Zheng 	eth->set_mac_speed(eth->port[i]->speed, eth->port[i]->duplex);
188*799e125cSJiandong Zheng 
189*799e125cSJiandong Zheng 	debug("Enable Ethernet Done.\n");
190*799e125cSJiandong Zheng 
191*799e125cSJiandong Zheng 	return 0;
192*799e125cSJiandong Zheng }
193*799e125cSJiandong Zheng 
194*799e125cSJiandong Zheng static void bcm_sf2_eth_close(struct eth_device *dev)
195*799e125cSJiandong Zheng {
196*799e125cSJiandong Zheng 	struct eth_info *eth = (struct eth_info *)(dev->priv);
197*799e125cSJiandong Zheng 	struct eth_dma *dma = &(eth->dma);
198*799e125cSJiandong Zheng 
199*799e125cSJiandong Zheng 	/* disable DMA */
200*799e125cSJiandong Zheng 	dma->disable_dma(dma, MAC_DMA_RX);
201*799e125cSJiandong Zheng 	dma->disable_dma(dma, MAC_DMA_TX);
202*799e125cSJiandong Zheng 
203*799e125cSJiandong Zheng 	eth->disable_mac();
204*799e125cSJiandong Zheng }
205*799e125cSJiandong Zheng 
206*799e125cSJiandong Zheng int bcm_sf2_eth_register(bd_t *bis, u8 dev_num)
207*799e125cSJiandong Zheng {
208*799e125cSJiandong Zheng 	struct eth_device *dev;
209*799e125cSJiandong Zheng 	struct eth_info *eth;
210*799e125cSJiandong Zheng 	int rc;
211*799e125cSJiandong Zheng 
212*799e125cSJiandong Zheng 	dev = (struct eth_device *)malloc(sizeof(struct eth_device));
213*799e125cSJiandong Zheng 	if (dev == NULL) {
214*799e125cSJiandong Zheng 		error("%s: Not enough memory!\n", __func__);
215*799e125cSJiandong Zheng 		return -1;
216*799e125cSJiandong Zheng 	}
217*799e125cSJiandong Zheng 
218*799e125cSJiandong Zheng 	eth = (struct eth_info *)malloc(sizeof(struct eth_info));
219*799e125cSJiandong Zheng 	if (eth == NULL) {
220*799e125cSJiandong Zheng 		error("%s: Not enough memory!\n", __func__);
221*799e125cSJiandong Zheng 		return -1;
222*799e125cSJiandong Zheng 	}
223*799e125cSJiandong Zheng 
224*799e125cSJiandong Zheng 	printf(banner);
225*799e125cSJiandong Zheng 
226*799e125cSJiandong Zheng 	memset(dev, 0, sizeof(*dev));
227*799e125cSJiandong Zheng 	sprintf(dev->name, "%s_%s-%hu", BCM_SF2_ETH_DEV_NAME,
228*799e125cSJiandong Zheng 		BCM_SF2_ETH_MAC_NAME, dev_num);
229*799e125cSJiandong Zheng 
230*799e125cSJiandong Zheng 	dev->priv = (void *)eth;
231*799e125cSJiandong Zheng 	dev->iobase = 0;
232*799e125cSJiandong Zheng 
233*799e125cSJiandong Zheng 	dev->init = bcm_sf2_eth_open;
234*799e125cSJiandong Zheng 	dev->halt = bcm_sf2_eth_close;
235*799e125cSJiandong Zheng 	dev->send = bcm_sf2_eth_send;
236*799e125cSJiandong Zheng 	dev->recv = bcm_sf2_eth_receive;
237*799e125cSJiandong Zheng 	dev->write_hwaddr = bcm_sf2_eth_write_hwaddr;
238*799e125cSJiandong Zheng 
239*799e125cSJiandong Zheng #ifdef CONFIG_BCM_SF2_ETH_GMAC
240*799e125cSJiandong Zheng 	if (gmac_add(dev)) {
241*799e125cSJiandong Zheng 		free(eth);
242*799e125cSJiandong Zheng 		free(dev);
243*799e125cSJiandong Zheng 		error("%s: Adding GMAC failed!\n", __func__);
244*799e125cSJiandong Zheng 		return -1;
245*799e125cSJiandong Zheng 	}
246*799e125cSJiandong Zheng #else
247*799e125cSJiandong Zheng #error "bcm_sf2_eth: NEED to register a MAC!"
248*799e125cSJiandong Zheng #endif
249*799e125cSJiandong Zheng 
250*799e125cSJiandong Zheng 	eth_register(dev);
251*799e125cSJiandong Zheng 
252*799e125cSJiandong Zheng #ifdef CONFIG_CMD_MII
253*799e125cSJiandong Zheng 	miiphy_register(dev->name, eth->miiphy_read, eth->miiphy_write);
254*799e125cSJiandong Zheng #endif
255*799e125cSJiandong Zheng 
256*799e125cSJiandong Zheng 	/* Initialization */
257*799e125cSJiandong Zheng 	debug("Ethernet initialization ...");
258*799e125cSJiandong Zheng 
259*799e125cSJiandong Zheng 	rc = bcm_sf2_eth_init(dev);
260*799e125cSJiandong Zheng 	if (rc != 0) {
261*799e125cSJiandong Zheng 		error("%s: configuration failed!\n", __func__);
262*799e125cSJiandong Zheng 		return -1;
263*799e125cSJiandong Zheng 	}
264*799e125cSJiandong Zheng 
265*799e125cSJiandong Zheng 	printf("Basic ethernet functionality initialized\n");
266*799e125cSJiandong Zheng 
267*799e125cSJiandong Zheng 	return 0;
268*799e125cSJiandong Zheng }
269