1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * SMSC LAN9[12]1[567] Network driver
4  *
5  * (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
6  */
7 
8 #include <command.h>
9 #include <malloc.h>
10 #include <net.h>
11 #include <miiphy.h>
12 #include <linux/io.h>
13 #include <linux/delay.h>
14 #include <linux/types.h>
15 
16 #include "smc911x.h"
17 
18 struct chip_id {
19 	u16 id;
20 	char *name;
21 };
22 
23 struct smc911x_priv {
24 	phys_addr_t		iobase;
25 	const struct chip_id	*chipid;
26 	unsigned char		enetaddr[6];
27 	bool			use_32_bit_io;
28 };
29 
30 static const struct chip_id chip_ids[] =  {
31 	{ CHIP_89218, "LAN89218" },
32 	{ CHIP_9115, "LAN9115" },
33 	{ CHIP_9116, "LAN9116" },
34 	{ CHIP_9117, "LAN9117" },
35 	{ CHIP_9118, "LAN9118" },
36 	{ CHIP_9211, "LAN9211" },
37 	{ CHIP_9215, "LAN9215" },
38 	{ CHIP_9216, "LAN9216" },
39 	{ CHIP_9217, "LAN9217" },
40 	{ CHIP_9218, "LAN9218" },
41 	{ CHIP_9220, "LAN9220" },
42 	{ CHIP_9221, "LAN9221" },
43 	{ 0, NULL },
44 };
45 
46 #define DRIVERNAME "smc911x"
47 
smc911x_reg_read(struct smc911x_priv * priv,u32 offset)48 static u32 smc911x_reg_read(struct smc911x_priv *priv, u32 offset)
49 {
50 	if (priv->use_32_bit_io)
51 		return readl(priv->iobase + offset);
52 
53 	return (readw(priv->iobase + offset) & 0xffff) |
54 	       (readw(priv->iobase + offset + 2) << 16);
55 }
56 
smc911x_reg_write(struct smc911x_priv * priv,u32 offset,u32 val)57 static void smc911x_reg_write(struct smc911x_priv *priv, u32 offset, u32 val)
58 {
59 	if (priv->use_32_bit_io) {
60 		writel(val, priv->iobase + offset);
61 	} else {
62 		writew(val & 0xffff, priv->iobase + offset);
63 		writew(val >> 16, priv->iobase + offset + 2);
64 	}
65 }
66 
smc911x_get_mac_csr(struct smc911x_priv * priv,u8 reg)67 static u32 smc911x_get_mac_csr(struct smc911x_priv *priv, u8 reg)
68 {
69 	while (smc911x_reg_read(priv, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
70 		;
71 	smc911x_reg_write(priv, MAC_CSR_CMD,
72 			MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg);
73 	while (smc911x_reg_read(priv, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
74 		;
75 
76 	return smc911x_reg_read(priv, MAC_CSR_DATA);
77 }
78 
smc911x_set_mac_csr(struct smc911x_priv * priv,u8 reg,u32 data)79 static void smc911x_set_mac_csr(struct smc911x_priv *priv, u8 reg, u32 data)
80 {
81 	while (smc911x_reg_read(priv, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
82 		;
83 	smc911x_reg_write(priv, MAC_CSR_DATA, data);
84 	smc911x_reg_write(priv, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg);
85 	while (smc911x_reg_read(priv, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
86 		;
87 }
88 
smc911x_detect_chip(struct smc911x_priv * priv)89 static int smc911x_detect_chip(struct smc911x_priv *priv)
90 {
91 	unsigned long val, i;
92 
93 	val = smc911x_reg_read(priv, BYTE_TEST);
94 	if (val == 0xffffffff) {
95 		/* Special case -- no chip present */
96 		return -1;
97 	} else if (val != 0x87654321) {
98 		printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val);
99 		return -1;
100 	}
101 
102 	val = smc911x_reg_read(priv, ID_REV) >> 16;
103 	for (i = 0; chip_ids[i].id != 0; i++) {
104 		if (chip_ids[i].id == val) break;
105 	}
106 	if (!chip_ids[i].id) {
107 		printf(DRIVERNAME ": Unknown chip ID %04lx\n", val);
108 		return -1;
109 	}
110 
111 	priv->chipid = &chip_ids[i];
112 
113 	return 0;
114 }
115 
smc911x_reset(struct smc911x_priv * priv)116 static void smc911x_reset(struct smc911x_priv *priv)
117 {
118 	int timeout;
119 
120 	/*
121 	 *  Take out of PM setting first
122 	 *  Device is already wake up if PMT_CTRL_READY bit is set
123 	 */
124 	if ((smc911x_reg_read(priv, PMT_CTRL) & PMT_CTRL_READY) == 0) {
125 		/* Write to the bytetest will take out of powerdown */
126 		smc911x_reg_write(priv, BYTE_TEST, 0x0);
127 
128 		timeout = 10;
129 
130 		while (timeout-- &&
131 			!(smc911x_reg_read(priv, PMT_CTRL) & PMT_CTRL_READY))
132 			udelay(10);
133 		if (timeout < 0) {
134 			printf(DRIVERNAME
135 				": timeout waiting for PM restore\n");
136 			return;
137 		}
138 	}
139 
140 	/* Disable interrupts */
141 	smc911x_reg_write(priv, INT_EN, 0);
142 
143 	smc911x_reg_write(priv, HW_CFG, HW_CFG_SRST);
144 
145 	timeout = 1000;
146 	while (timeout-- && smc911x_reg_read(priv, E2P_CMD) & E2P_CMD_EPC_BUSY)
147 		udelay(10);
148 
149 	if (timeout < 0) {
150 		printf(DRIVERNAME ": reset timeout\n");
151 		return;
152 	}
153 
154 	/* Reset the FIFO level and flow control settings */
155 	smc911x_set_mac_csr(priv, FLOW, FLOW_FCPT | FLOW_FCEN);
156 	smc911x_reg_write(priv, AFC_CFG, 0x0050287F);
157 
158 	/* Set to LED outputs */
159 	smc911x_reg_write(priv, GPIO_CFG, 0x70070000);
160 }
161 
smc911x_handle_mac_address(struct smc911x_priv * priv)162 static void smc911x_handle_mac_address(struct smc911x_priv *priv)
163 {
164 	unsigned long addrh, addrl;
165 	unsigned char *m = priv->enetaddr;
166 
167 	addrl = m[0] | (m[1] << 8) | (m[2] << 16) | (m[3] << 24);
168 	addrh = m[4] | (m[5] << 8);
169 	smc911x_set_mac_csr(priv, ADDRL, addrl);
170 	smc911x_set_mac_csr(priv, ADDRH, addrh);
171 
172 	printf(DRIVERNAME ": MAC %pM\n", m);
173 }
174 
smc911x_read_mac_address(struct smc911x_priv * priv)175 static bool smc911x_read_mac_address(struct smc911x_priv *priv)
176 {
177 	u32 addrh, addrl;
178 
179 	/* address is obtained from optional eeprom */
180 	addrh = smc911x_get_mac_csr(priv, ADDRH);
181 	addrl = smc911x_get_mac_csr(priv, ADDRL);
182 	if (addrl == 0xffffffff && addrh == 0x0000ffff)
183 		return false;
184 
185 	priv->enetaddr[0] = addrl;
186 	priv->enetaddr[1] = addrl >>  8;
187 	priv->enetaddr[2] = addrl >> 16;
188 	priv->enetaddr[3] = addrl >> 24;
189 	priv->enetaddr[4] = addrh;
190 	priv->enetaddr[5] = addrh >> 8;
191 
192 	return true;
193 }
194 
smc911x_eth_phy_read(struct smc911x_priv * priv,u8 phy,u8 reg,u16 * val)195 static int smc911x_eth_phy_read(struct smc911x_priv *priv,
196 				u8 phy, u8 reg, u16 *val)
197 {
198 	while (smc911x_get_mac_csr(priv, MII_ACC) & MII_ACC_MII_BUSY)
199 		;
200 
201 	smc911x_set_mac_csr(priv, MII_ACC, phy << 11 | reg << 6 |
202 				MII_ACC_MII_BUSY);
203 
204 	while (smc911x_get_mac_csr(priv, MII_ACC) & MII_ACC_MII_BUSY)
205 		;
206 
207 	*val = smc911x_get_mac_csr(priv, MII_DATA);
208 
209 	return 0;
210 }
211 
smc911x_eth_phy_write(struct smc911x_priv * priv,u8 phy,u8 reg,u16 val)212 static int smc911x_eth_phy_write(struct smc911x_priv *priv,
213 				u8 phy, u8 reg, u16  val)
214 {
215 	while (smc911x_get_mac_csr(priv, MII_ACC) & MII_ACC_MII_BUSY)
216 		;
217 
218 	smc911x_set_mac_csr(priv, MII_DATA, val);
219 	smc911x_set_mac_csr(priv, MII_ACC,
220 		phy << 11 | reg << 6 | MII_ACC_MII_BUSY | MII_ACC_MII_WRITE);
221 
222 	while (smc911x_get_mac_csr(priv, MII_ACC) & MII_ACC_MII_BUSY)
223 		;
224 	return 0;
225 }
226 
smc911x_phy_reset(struct smc911x_priv * priv)227 static int smc911x_phy_reset(struct smc911x_priv *priv)
228 {
229 	u32 reg;
230 
231 	reg = smc911x_reg_read(priv, PMT_CTRL);
232 	reg &= ~0xfffff030;
233 	reg |= PMT_CTRL_PHY_RST;
234 	smc911x_reg_write(priv, PMT_CTRL, reg);
235 
236 	mdelay(100);
237 
238 	return 0;
239 }
240 
smc911x_phy_configure(struct smc911x_priv * priv)241 static void smc911x_phy_configure(struct smc911x_priv *priv)
242 {
243 	int timeout;
244 	u16 status;
245 
246 	smc911x_phy_reset(priv);
247 
248 	smc911x_eth_phy_write(priv, 1, MII_BMCR, BMCR_RESET);
249 	mdelay(1);
250 	smc911x_eth_phy_write(priv, 1, MII_ADVERTISE, 0x01e1);
251 	smc911x_eth_phy_write(priv, 1, MII_BMCR, BMCR_ANENABLE |
252 				BMCR_ANRESTART);
253 
254 	timeout = 5000;
255 	do {
256 		mdelay(1);
257 		if ((timeout--) == 0)
258 			goto err_out;
259 
260 		if (smc911x_eth_phy_read(priv, 1, MII_BMSR, &status) != 0)
261 			goto err_out;
262 	} while (!(status & BMSR_LSTATUS));
263 
264 	printf(DRIVERNAME ": phy initialized\n");
265 
266 	return;
267 
268 err_out:
269 	printf(DRIVERNAME ": autonegotiation timed out\n");
270 }
271 
smc911x_enable(struct smc911x_priv * priv)272 static void smc911x_enable(struct smc911x_priv *priv)
273 {
274 	/* Enable TX */
275 	smc911x_reg_write(priv, HW_CFG, 8 << 16 | HW_CFG_SF);
276 
277 	smc911x_reg_write(priv, GPT_CFG, GPT_CFG_TIMER_EN | 10000);
278 
279 	smc911x_reg_write(priv, TX_CFG, TX_CFG_TX_ON);
280 
281 	/* no padding to start of packets */
282 	smc911x_reg_write(priv, RX_CFG, 0);
283 
284 	smc911x_set_mac_csr(priv, MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN |
285 				MAC_CR_HBDIS);
286 }
287 
smc911x_init_common(struct smc911x_priv * priv)288 static int smc911x_init_common(struct smc911x_priv *priv)
289 {
290 	const struct chip_id *id = priv->chipid;
291 
292 	printf(DRIVERNAME ": detected %s controller\n", id->name);
293 
294 	smc911x_reset(priv);
295 
296 	/* Configure the PHY, initialize the link state */
297 	smc911x_phy_configure(priv);
298 
299 	smc911x_handle_mac_address(priv);
300 
301 	/* Turn on Tx + Rx */
302 	smc911x_enable(priv);
303 
304 	return 0;
305 }
306 
smc911x_send_common(struct smc911x_priv * priv,void * packet,int length)307 static int smc911x_send_common(struct smc911x_priv *priv,
308 			       void *packet, int length)
309 {
310 	u32 *data = (u32*)packet;
311 	u32 tmplen;
312 	u32 status;
313 
314 	smc911x_reg_write(priv, TX_DATA_FIFO, TX_CMD_A_INT_FIRST_SEG |
315 				TX_CMD_A_INT_LAST_SEG | length);
316 	smc911x_reg_write(priv, TX_DATA_FIFO, length);
317 
318 	tmplen = (length + 3) / 4;
319 
320 	while (tmplen--)
321 		smc911x_reg_write(priv, TX_DATA_FIFO, *data++);
322 
323 	/* wait for transmission */
324 	while (!((smc911x_reg_read(priv, TX_FIFO_INF) &
325 					TX_FIFO_INF_TSUSED) >> 16));
326 
327 	/* get status. Ignore 'no carrier' error, it has no meaning for
328 	 * full duplex operation
329 	 */
330 	status = smc911x_reg_read(priv, TX_STATUS_FIFO) &
331 			(TX_STS_LOC | TX_STS_LATE_COLL | TX_STS_MANY_COLL |
332 			TX_STS_MANY_DEFER | TX_STS_UNDERRUN);
333 
334 	if (!status)
335 		return 0;
336 
337 	printf(DRIVERNAME ": failed to send packet: %s%s%s%s%s\n",
338 		status & TX_STS_LOC ? "TX_STS_LOC " : "",
339 		status & TX_STS_LATE_COLL ? "TX_STS_LATE_COLL " : "",
340 		status & TX_STS_MANY_COLL ? "TX_STS_MANY_COLL " : "",
341 		status & TX_STS_MANY_DEFER ? "TX_STS_MANY_DEFER " : "",
342 		status & TX_STS_UNDERRUN ? "TX_STS_UNDERRUN" : "");
343 
344 	return -1;
345 }
346 
smc911x_halt_common(struct smc911x_priv * priv)347 static void smc911x_halt_common(struct smc911x_priv *priv)
348 {
349 	smc911x_reset(priv);
350 	smc911x_handle_mac_address(priv);
351 }
352 
smc911x_recv_common(struct smc911x_priv * priv,u32 * data)353 static int smc911x_recv_common(struct smc911x_priv *priv, u32 *data)
354 {
355 	u32 pktlen, tmplen;
356 	u32 status;
357 
358 	status = smc911x_reg_read(priv, RX_FIFO_INF);
359 	if (!(status & RX_FIFO_INF_RXSUSED))
360 		return 0;
361 
362 	status = smc911x_reg_read(priv, RX_STATUS_FIFO);
363 	pktlen = (status & RX_STS_PKT_LEN) >> 16;
364 
365 	smc911x_reg_write(priv, RX_CFG, 0);
366 
367 	tmplen = (pktlen + 3) / 4;
368 	while (tmplen--)
369 		*data++ = smc911x_reg_read(priv, RX_DATA_FIFO);
370 
371 	if (status & RX_STS_ES) {
372 		printf(DRIVERNAME
373 			": dropped bad packet. Status: 0x%08x\n",
374 			status);
375 		return 0;
376 	}
377 
378 	return pktlen;
379 }
380 
smc911x_start(struct udevice * dev)381 static int smc911x_start(struct udevice *dev)
382 {
383 	struct eth_pdata *plat = dev_get_plat(dev);
384 	struct smc911x_priv *priv = dev_get_priv(dev);
385 
386 	memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr));
387 
388 	return smc911x_init_common(priv);
389 }
390 
smc911x_stop(struct udevice * dev)391 static void smc911x_stop(struct udevice *dev)
392 {
393 	struct smc911x_priv *priv = dev_get_priv(dev);
394 
395 	smc911x_halt_common(priv);
396 }
397 
smc911x_send(struct udevice * dev,void * packet,int length)398 static int smc911x_send(struct udevice *dev, void *packet, int length)
399 {
400 	struct smc911x_priv *priv = dev_get_priv(dev);
401 	int ret;
402 
403 	ret = smc911x_send_common(priv, packet, length);
404 
405 	return ret ? -ETIMEDOUT : 0;
406 }
407 
smc911x_recv(struct udevice * dev,int flags,uchar ** packetp)408 static int smc911x_recv(struct udevice *dev, int flags, uchar **packetp)
409 {
410 	struct smc911x_priv *priv = dev_get_priv(dev);
411 	u32 *data = (u32 *)net_rx_packets[0];
412 	int ret;
413 
414 	ret = smc911x_recv_common(priv, data);
415 	if (ret)
416 		*packetp = (void *)data;
417 
418 	return ret ? ret : -EAGAIN;
419 }
420 
smc911x_read_rom_hwaddr(struct udevice * dev)421 static int smc911x_read_rom_hwaddr(struct udevice *dev)
422 {
423 	struct smc911x_priv *priv = dev_get_priv(dev);
424 	struct eth_pdata *pdata = dev_get_plat(dev);
425 
426 	if (!smc911x_read_mac_address(priv))
427 		return -ENODEV;
428 
429 	memcpy(pdata->enetaddr, priv->enetaddr, sizeof(pdata->enetaddr));
430 
431 	return 0;
432 }
433 
smc911x_bind(struct udevice * dev)434 static int smc911x_bind(struct udevice *dev)
435 {
436 	return device_set_name(dev, dev->name);
437 }
438 
smc911x_probe(struct udevice * dev)439 static int smc911x_probe(struct udevice *dev)
440 {
441 	struct smc911x_priv *priv = dev_get_priv(dev);
442 	int ret;
443 
444 	/* Try to detect chip. Will fail if not present. */
445 	ret = smc911x_detect_chip(priv);
446 	if (ret)
447 		return ret;
448 
449 	smc911x_read_rom_hwaddr(dev);
450 
451 	return 0;
452 }
453 
smc911x_of_to_plat(struct udevice * dev)454 static int smc911x_of_to_plat(struct udevice *dev)
455 {
456 	struct smc911x_priv *priv = dev_get_priv(dev);
457 	struct eth_pdata *pdata = dev_get_plat(dev);
458 	u32 io_width;
459 	int ret;
460 
461 	pdata->iobase = dev_read_addr(dev);
462 	priv->iobase = pdata->iobase;
463 
464 	ret = dev_read_u32(dev, "reg-io-width", &io_width);
465 	if (!ret)
466 		priv->use_32_bit_io = (io_width == 4);
467 	else
468 		priv->use_32_bit_io = CONFIG_IS_ENABLED(SMC911X_32_BIT);
469 
470 	return 0;
471 }
472 
473 static const struct eth_ops smc911x_ops = {
474 	.start	= smc911x_start,
475 	.send	= smc911x_send,
476 	.recv	= smc911x_recv,
477 	.stop	= smc911x_stop,
478 	.read_rom_hwaddr = smc911x_read_rom_hwaddr,
479 };
480 
481 static const struct udevice_id smc911x_ids[] = {
482 	{ .compatible = "smsc,lan9115" },
483 	{ }
484 };
485 
486 U_BOOT_DRIVER(smc911x) = {
487 	.name		= "eth_smc911x",
488 	.id		= UCLASS_ETH,
489 	.of_match	= smc911x_ids,
490 	.bind		= smc911x_bind,
491 	.of_to_plat = smc911x_of_to_plat,
492 	.probe		= smc911x_probe,
493 	.ops		= &smc911x_ops,
494 	.priv_auto	= sizeof(struct smc911x_priv),
495 	.plat_auto	= sizeof(struct eth_pdata),
496 	.flags		= DM_FLAG_ALLOC_PRIV_DMA,
497 };
498