xref: /openbmc/u-boot/doc/README.drivers.eth (revision b939689c7b87773c44275a578ffc8674a867e39d)
105c3e68fSJoe Hershberger!!! WARNING !!!
205c3e68fSJoe Hershberger
305c3e68fSJoe HershbergerThis guide describes to the old way of doing things. No new Ethernet drivers
405c3e68fSJoe Hershbergershould be implemented this way. All new drivers should be written against the
505c3e68fSJoe HershbergerU-Boot core driver model. See doc/driver-model/README.txt
605c3e68fSJoe Hershberger
71f1e774eSMike Frysinger-----------------------
81f1e774eSMike Frysinger Ethernet Driver Guide
91f1e774eSMike Frysinger-----------------------
101f1e774eSMike Frysinger
111f1e774eSMike FrysingerThe networking stack in Das U-Boot is designed for multiple network devices
121f1e774eSMike Frysingerto be easily added and controlled at runtime.  This guide is meant for people
131f1e774eSMike Frysingerwho wish to review the net driver stack with an eye towards implementing your
141f1e774eSMike Frysingerown ethernet device driver.  Here we will describe a new pseudo 'APE' driver.
151f1e774eSMike Frysinger
161f1e774eSMike Frysinger------------------
171f1e774eSMike Frysinger Driver Functions
181f1e774eSMike Frysinger------------------
191f1e774eSMike Frysinger
201f1e774eSMike FrysingerAll functions you will be implementing in this document have the return value
211f1e774eSMike Frysingermeaning of 0 for success and non-zero for failure.
221f1e774eSMike Frysinger
231f1e774eSMike Frysinger ----------
241f1e774eSMike Frysinger  Register
251f1e774eSMike Frysinger ----------
261f1e774eSMike Frysinger
271f1e774eSMike FrysingerWhen U-Boot initializes, it will call the common function eth_initialize().
281f1e774eSMike FrysingerThis will in turn call the board-specific board_eth_init() (or if that fails,
291f1e774eSMike Frysingerthe cpu-specific cpu_eth_init()).  These board-specific functions can do random
301f1e774eSMike Frysingersystem handling, but ultimately they will call the driver-specific register
311f1e774eSMike Frysingerfunction which in turn takes care of initializing that particular instance.
321f1e774eSMike Frysinger
331f1e774eSMike FrysingerKeep in mind that you should code the driver to avoid storing state in global
3499dbd4efSBen Warrendata as someone might want to hook up two of the same devices to one board.
3599dbd4efSBen WarrenAny such information that is specific to an interface should be stored in a
3699dbd4efSBen Warrenprivate, driver-defined data structure and pointed to by eth->priv (see below).
371f1e774eSMike Frysinger
381f1e774eSMike FrysingerSo the call graph at this stage would look something like:
391f1e774eSMike Frysingerboard_init()
401f1e774eSMike Frysinger	eth_initialize()
411f1e774eSMike Frysinger		board_eth_init() / cpu_eth_init()
421f1e774eSMike Frysinger			driver_register()
431f1e774eSMike Frysinger				initialize eth_device
441f1e774eSMike Frysinger				eth_register()
451f1e774eSMike Frysinger
461f1e774eSMike FrysingerAt this point in time, the only thing you need to worry about is the driver's
471f1e774eSMike Frysingerregister function.  The pseudo code would look something like:
481f1e774eSMike Frysingerint ape_register(bd_t *bis, int iobase)
491f1e774eSMike Frysinger{
501f1e774eSMike Frysinger	struct ape_priv *priv;
511f1e774eSMike Frysinger	struct eth_device *dev;
52c58ea6cbSBin Meng	struct mii_dev *bus;
531f1e774eSMike Frysinger
541f1e774eSMike Frysinger	priv = malloc(sizeof(*priv));
551f1e774eSMike Frysinger	if (priv == NULL)
56c58ea6cbSBin Meng		return -ENOMEM;
571f1e774eSMike Frysinger
581f1e774eSMike Frysinger	dev = malloc(sizeof(*dev));
591f1e774eSMike Frysinger	if (dev == NULL) {
601f1e774eSMike Frysinger		free(priv);
61c58ea6cbSBin Meng		return -ENOMEM;
621f1e774eSMike Frysinger	}
631f1e774eSMike Frysinger
641f1e774eSMike Frysinger	/* setup whatever private state you need */
651f1e774eSMike Frysinger
661f1e774eSMike Frysinger	memset(dev, 0, sizeof(*dev));
671f1e774eSMike Frysinger	sprintf(dev->name, "APE");
681f1e774eSMike Frysinger
69c58ea6cbSBin Meng	/*
70c58ea6cbSBin Meng	 * if your device has dedicated hardware storage for the
711f1e774eSMike Frysinger	 * MAC, read it and initialize dev->enetaddr with it
721f1e774eSMike Frysinger	 */
731f1e774eSMike Frysinger	ape_mac_read(dev->enetaddr);
741f1e774eSMike Frysinger
751f1e774eSMike Frysinger	dev->iobase = iobase;
761f1e774eSMike Frysinger	dev->priv = priv;
771f1e774eSMike Frysinger	dev->init = ape_init;
781f1e774eSMike Frysinger	dev->halt = ape_halt;
791f1e774eSMike Frysinger	dev->send = ape_send;
801f1e774eSMike Frysinger	dev->recv = ape_recv;
81ecee9324SBen Warren	dev->write_hwaddr = ape_write_hwaddr;
821f1e774eSMike Frysinger
831f1e774eSMike Frysinger	eth_register(dev);
841f1e774eSMike Frysinger
85c58ea6cbSBin Meng#ifdef CONFIG_PHYLIB
86c58ea6cbSBin Meng	bus = mdio_alloc();
87c58ea6cbSBin Meng	if (!bus) {
88c58ea6cbSBin Meng		free(priv);
89c58ea6cbSBin Meng		free(dev);
90c58ea6cbSBin Meng		return -ENOMEM;
91c58ea6cbSBin Meng	}
92c58ea6cbSBin Meng
93c58ea6cbSBin Meng	bus->read = ape_mii_read;
94c58ea6cbSBin Meng	bus->write = ape_mii_write;
95c58ea6cbSBin Meng	mdio_register(bus);
961f1e774eSMike Frysinger#endif
971f1e774eSMike Frysinger
9899dbd4efSBen Warren	return 1;
991f1e774eSMike Frysinger}
1001f1e774eSMike Frysinger
1011f1e774eSMike FrysingerThe exact arguments needed to initialize your device are up to you.  If you
1021f1e774eSMike Frysingerneed to pass more/less arguments, that's fine.  You should also add the
10399dbd4efSBen Warrenprototype for your new register function to include/netdev.h.
10499dbd4efSBen Warren
10599dbd4efSBen WarrenThe return value for this function should be as follows:
10699dbd4efSBen Warren< 0 - failure (hardware failure, not probe failure)
10799dbd4efSBen Warren>=0 - number of interfaces detected
10899dbd4efSBen Warren
10999dbd4efSBen WarrenYou might notice that many drivers seem to use xxx_initialize() rather than
11099dbd4efSBen Warrenxxx_register().  This is the old naming convention and should be avoided as it
11199dbd4efSBen Warrencauses confusion with the driver-specific init function.
1121f1e774eSMike Frysinger
1131f1e774eSMike FrysingerOther than locating the MAC address in dedicated hardware storage, you should
1141f1e774eSMike Frysingernot touch the hardware in anyway.  That step is handled in the driver-specific
1151f1e774eSMike Frysingerinit function.  Remember that we are only registering the device here, we are
1161f1e774eSMike Frysingernot checking its state or doing random probing.
1171f1e774eSMike Frysinger
1181f1e774eSMike Frysinger -----------
1191f1e774eSMike Frysinger  Callbacks
1201f1e774eSMike Frysinger -----------
1211f1e774eSMike Frysinger
1221f1e774eSMike FrysingerNow that we've registered with the ethernet layer, we can start getting some
123ecee9324SBen Warrenreal work done.  You will need five functions:
1241f1e774eSMike Frysinger	int ape_init(struct eth_device *dev, bd_t *bis);
1251f1e774eSMike Frysinger	int ape_send(struct eth_device *dev, volatile void *packet, int length);
1261f1e774eSMike Frysinger	int ape_recv(struct eth_device *dev);
1271f1e774eSMike Frysinger	int ape_halt(struct eth_device *dev);
128ecee9324SBen Warren	int ape_write_hwaddr(struct eth_device *dev);
1291f1e774eSMike Frysinger
1301f1e774eSMike FrysingerThe init function checks the hardware (probing/identifying) and gets it ready
1311f1e774eSMike Frysingerfor send/recv operations.  You often do things here such as resetting the MAC
1321f1e774eSMike Frysingerand/or PHY, and waiting for the link to autonegotiate.  You should also take
1331f1e774eSMike Frysingerthe opportunity to program the device's MAC address with the dev->enetaddr
1341f1e774eSMike Frysingermember.  This allows the rest of U-Boot to dynamically change the MAC address
1351f1e774eSMike Frysingerand have the new settings be respected.
1361f1e774eSMike Frysinger
1371f1e774eSMike FrysingerThe send function does what you think -- transmit the specified packet whose
1381f1e774eSMike Frysingersize is specified by length (in bytes).  You should not return until the
1391f1e774eSMike Frysingertransmission is complete, and you should leave the state such that the send
1401f1e774eSMike Frysingerfunction can be called multiple times in a row.
1411f1e774eSMike Frysinger
1421f1e774eSMike FrysingerThe recv function should process packets as long as the hardware has them
1431f1e774eSMike Frysingerreadily available before returning.  i.e. you should drain the hardware fifo.
144*1fd92db8SJoe HershbergerFor each packet you receive, you should call the net_process_received_packet() function on it
145e5c5d9e0SMike Frysingeralong with the packet length.  The common code sets up packet buffers for you
146*1fd92db8SJoe Hershbergeralready in the .bss (net_rx_packets), so there should be no need to allocate your
147*1fd92db8SJoe Hershbergerown.  This doesn't mean you must use the net_rx_packets array however; you're
148*1fd92db8SJoe Hershbergerfree to call the net_process_received_packet() function with any buffer you wish.  So the pseudo
149e5c5d9e0SMike Frysingercode here would look something like:
1501f1e774eSMike Frysingerint ape_recv(struct eth_device *dev)
1511f1e774eSMike Frysinger{
1521f1e774eSMike Frysinger	int length, i = 0;
1531f1e774eSMike Frysinger	...
1541f1e774eSMike Frysinger	while (packets_are_available()) {
1551f1e774eSMike Frysinger		...
156*1fd92db8SJoe Hershberger		length = ape_get_packet(&net_rx_packets[i]);
1571f1e774eSMike Frysinger		...
158*1fd92db8SJoe Hershberger		net_process_received_packet(&net_rx_packets[i], length);
1591f1e774eSMike Frysinger		...
1601f1e774eSMike Frysinger		if (++i >= PKTBUFSRX)
1611f1e774eSMike Frysinger			i = 0;
1621f1e774eSMike Frysinger		...
1631f1e774eSMike Frysinger	}
1641f1e774eSMike Frysinger	...
1651f1e774eSMike Frysinger	return 0;
1661f1e774eSMike Frysinger}
1671f1e774eSMike Frysinger
1681f1e774eSMike FrysingerThe halt function should turn off / disable the hardware and place it back in
169e5c5d9e0SMike Frysingerits reset state.  It can be called at any time (before any call to the related
170e5c5d9e0SMike Frysingerinit function), so make sure it can handle this sort of thing.
1711f1e774eSMike Frysinger
172ecee9324SBen WarrenThe write_hwaddr function should program the MAC address stored in dev->enetaddr
173ecee9324SBen Warreninto the Ethernet controller.
174ecee9324SBen Warren
1751f1e774eSMike FrysingerSo the call graph at this stage would look something like:
1761f1e774eSMike Frysingersome net operation (ping / tftp / whatever...)
1771f1e774eSMike Frysinger	eth_init()
1781f1e774eSMike Frysinger		dev->init()
1791f1e774eSMike Frysinger	eth_send()
1801f1e774eSMike Frysinger		dev->send()
1811f1e774eSMike Frysinger	eth_rx()
1821f1e774eSMike Frysinger		dev->recv()
1831f1e774eSMike Frysinger	eth_halt()
1841f1e774eSMike Frysinger		dev->halt()
1851f1e774eSMike Frysinger
186c58ea6cbSBin Meng--------------------------------
187c58ea6cbSBin Meng CONFIG_PHYLIB / CONFIG_CMD_MII
188c58ea6cbSBin Meng--------------------------------
1891f1e774eSMike Frysinger
1901f1e774eSMike FrysingerIf your device supports banging arbitrary values on the MII bus (pretty much
1911f1e774eSMike Frysingerevery device does), you should add support for the mii command.  Doing so is
1921f1e774eSMike Frysingerfairly trivial and makes debugging mii issues a lot easier at runtime.
1931f1e774eSMike Frysinger
1941f1e774eSMike FrysingerAfter you have called eth_register() in your driver's register function, add
195c58ea6cbSBin Menga call to mdio_alloc() and mdio_register() like so:
196c58ea6cbSBin Meng	bus = mdio_alloc();
197c58ea6cbSBin Meng	if (!bus) {
198c58ea6cbSBin Meng		free(priv);
199c58ea6cbSBin Meng		free(dev);
200c58ea6cbSBin Meng		return -ENOMEM;
201c58ea6cbSBin Meng	}
202c58ea6cbSBin Meng
203c58ea6cbSBin Meng	bus->read = ape_mii_read;
204c58ea6cbSBin Meng	bus->write = ape_mii_write;
205c58ea6cbSBin Meng	mdio_register(bus);
2061f1e774eSMike Frysinger
2071f1e774eSMike FrysingerAnd then define the mii_read and mii_write functions if you haven't already.
2081f1e774eSMike FrysingerTheir syntax is straightforward:
209c58ea6cbSBin Meng	int mii_read(struct mii_dev *bus, int addr, int devad, int reg);
210c58ea6cbSBin Meng	int mii_write(struct mii_dev *bus, int addr, int devad, int reg,
211c58ea6cbSBin Meng		      u16 val);
2121f1e774eSMike Frysinger
2131f1e774eSMike FrysingerThe read function should read the register 'reg' from the phy at address 'addr'
214c58ea6cbSBin Mengand return the result to its caller.  The implementation for the write function
215c58ea6cbSBin Mengshould logically follow.
216