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