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