xref: /OK3568_Linux_fs/u-boot/doc/README.drivers.eth (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun!!! WARNING !!!
2*4882a593Smuzhiyun
3*4882a593SmuzhiyunThis guide describes to the old way of doing things. No new Ethernet drivers
4*4882a593Smuzhiyunshould be implemented this way. All new drivers should be written against the
5*4882a593SmuzhiyunU-Boot core driver model. See doc/driver-model/README.txt
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun-----------------------
8*4882a593Smuzhiyun Ethernet Driver Guide
9*4882a593Smuzhiyun-----------------------
10*4882a593Smuzhiyun
11*4882a593SmuzhiyunThe networking stack in Das U-Boot is designed for multiple network devices
12*4882a593Smuzhiyunto be easily added and controlled at runtime.  This guide is meant for people
13*4882a593Smuzhiyunwho wish to review the net driver stack with an eye towards implementing your
14*4882a593Smuzhiyunown ethernet device driver.  Here we will describe a new pseudo 'APE' driver.
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun------------------
17*4882a593Smuzhiyun Driver Functions
18*4882a593Smuzhiyun------------------
19*4882a593Smuzhiyun
20*4882a593SmuzhiyunAll functions you will be implementing in this document have the return value
21*4882a593Smuzhiyunmeaning of 0 for success and non-zero for failure.
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun ----------
24*4882a593Smuzhiyun  Register
25*4882a593Smuzhiyun ----------
26*4882a593Smuzhiyun
27*4882a593SmuzhiyunWhen U-Boot initializes, it will call the common function eth_initialize().
28*4882a593SmuzhiyunThis will in turn call the board-specific board_eth_init() (or if that fails,
29*4882a593Smuzhiyunthe cpu-specific cpu_eth_init()).  These board-specific functions can do random
30*4882a593Smuzhiyunsystem handling, but ultimately they will call the driver-specific register
31*4882a593Smuzhiyunfunction which in turn takes care of initializing that particular instance.
32*4882a593Smuzhiyun
33*4882a593SmuzhiyunKeep in mind that you should code the driver to avoid storing state in global
34*4882a593Smuzhiyundata as someone might want to hook up two of the same devices to one board.
35*4882a593SmuzhiyunAny such information that is specific to an interface should be stored in a
36*4882a593Smuzhiyunprivate, driver-defined data structure and pointed to by eth->priv (see below).
37*4882a593Smuzhiyun
38*4882a593SmuzhiyunSo the call graph at this stage would look something like:
39*4882a593Smuzhiyunboard_init()
40*4882a593Smuzhiyun	eth_initialize()
41*4882a593Smuzhiyun		board_eth_init() / cpu_eth_init()
42*4882a593Smuzhiyun			driver_register()
43*4882a593Smuzhiyun				initialize eth_device
44*4882a593Smuzhiyun				eth_register()
45*4882a593Smuzhiyun
46*4882a593SmuzhiyunAt this point in time, the only thing you need to worry about is the driver's
47*4882a593Smuzhiyunregister function.  The pseudo code would look something like:
48*4882a593Smuzhiyunint ape_register(bd_t *bis, int iobase)
49*4882a593Smuzhiyun{
50*4882a593Smuzhiyun	struct ape_priv *priv;
51*4882a593Smuzhiyun	struct eth_device *dev;
52*4882a593Smuzhiyun	struct mii_dev *bus;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun	priv = malloc(sizeof(*priv));
55*4882a593Smuzhiyun	if (priv == NULL)
56*4882a593Smuzhiyun		return -ENOMEM;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun	dev = malloc(sizeof(*dev));
59*4882a593Smuzhiyun	if (dev == NULL) {
60*4882a593Smuzhiyun		free(priv);
61*4882a593Smuzhiyun		return -ENOMEM;
62*4882a593Smuzhiyun	}
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun	/* setup whatever private state you need */
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun	memset(dev, 0, sizeof(*dev));
67*4882a593Smuzhiyun	sprintf(dev->name, "APE");
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun	/*
70*4882a593Smuzhiyun	 * if your device has dedicated hardware storage for the
71*4882a593Smuzhiyun	 * MAC, read it and initialize dev->enetaddr with it
72*4882a593Smuzhiyun	 */
73*4882a593Smuzhiyun	ape_mac_read(dev->enetaddr);
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun	dev->iobase = iobase;
76*4882a593Smuzhiyun	dev->priv = priv;
77*4882a593Smuzhiyun	dev->init = ape_init;
78*4882a593Smuzhiyun	dev->halt = ape_halt;
79*4882a593Smuzhiyun	dev->send = ape_send;
80*4882a593Smuzhiyun	dev->recv = ape_recv;
81*4882a593Smuzhiyun	dev->write_hwaddr = ape_write_hwaddr;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun	eth_register(dev);
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun#ifdef CONFIG_PHYLIB
86*4882a593Smuzhiyun	bus = mdio_alloc();
87*4882a593Smuzhiyun	if (!bus) {
88*4882a593Smuzhiyun		free(priv);
89*4882a593Smuzhiyun		free(dev);
90*4882a593Smuzhiyun		return -ENOMEM;
91*4882a593Smuzhiyun	}
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun	bus->read = ape_mii_read;
94*4882a593Smuzhiyun	bus->write = ape_mii_write;
95*4882a593Smuzhiyun	mdio_register(bus);
96*4882a593Smuzhiyun#endif
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun	return 1;
99*4882a593Smuzhiyun}
100*4882a593Smuzhiyun
101*4882a593SmuzhiyunThe exact arguments needed to initialize your device are up to you.  If you
102*4882a593Smuzhiyunneed to pass more/less arguments, that's fine.  You should also add the
103*4882a593Smuzhiyunprototype for your new register function to include/netdev.h.
104*4882a593Smuzhiyun
105*4882a593SmuzhiyunThe return value for this function should be as follows:
106*4882a593Smuzhiyun< 0 - failure (hardware failure, not probe failure)
107*4882a593Smuzhiyun>=0 - number of interfaces detected
108*4882a593Smuzhiyun
109*4882a593SmuzhiyunYou might notice that many drivers seem to use xxx_initialize() rather than
110*4882a593Smuzhiyunxxx_register().  This is the old naming convention and should be avoided as it
111*4882a593Smuzhiyuncauses confusion with the driver-specific init function.
112*4882a593Smuzhiyun
113*4882a593SmuzhiyunOther than locating the MAC address in dedicated hardware storage, you should
114*4882a593Smuzhiyunnot touch the hardware in anyway.  That step is handled in the driver-specific
115*4882a593Smuzhiyuninit function.  Remember that we are only registering the device here, we are
116*4882a593Smuzhiyunnot checking its state or doing random probing.
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun -----------
119*4882a593Smuzhiyun  Callbacks
120*4882a593Smuzhiyun -----------
121*4882a593Smuzhiyun
122*4882a593SmuzhiyunNow that we've registered with the ethernet layer, we can start getting some
123*4882a593Smuzhiyunreal work done.  You will need five functions:
124*4882a593Smuzhiyun	int ape_init(struct eth_device *dev, bd_t *bis);
125*4882a593Smuzhiyun	int ape_send(struct eth_device *dev, volatile void *packet, int length);
126*4882a593Smuzhiyun	int ape_recv(struct eth_device *dev);
127*4882a593Smuzhiyun	int ape_halt(struct eth_device *dev);
128*4882a593Smuzhiyun	int ape_write_hwaddr(struct eth_device *dev);
129*4882a593Smuzhiyun
130*4882a593SmuzhiyunThe init function checks the hardware (probing/identifying) and gets it ready
131*4882a593Smuzhiyunfor send/recv operations.  You often do things here such as resetting the MAC
132*4882a593Smuzhiyunand/or PHY, and waiting for the link to autonegotiate.  You should also take
133*4882a593Smuzhiyunthe opportunity to program the device's MAC address with the dev->enetaddr
134*4882a593Smuzhiyunmember.  This allows the rest of U-Boot to dynamically change the MAC address
135*4882a593Smuzhiyunand have the new settings be respected.
136*4882a593Smuzhiyun
137*4882a593SmuzhiyunThe send function does what you think -- transmit the specified packet whose
138*4882a593Smuzhiyunsize is specified by length (in bytes).  You should not return until the
139*4882a593Smuzhiyuntransmission is complete, and you should leave the state such that the send
140*4882a593Smuzhiyunfunction can be called multiple times in a row.
141*4882a593Smuzhiyun
142*4882a593SmuzhiyunThe recv function should process packets as long as the hardware has them
143*4882a593Smuzhiyunreadily available before returning.  i.e. you should drain the hardware fifo.
144*4882a593SmuzhiyunFor each packet you receive, you should call the net_process_received_packet() function on it
145*4882a593Smuzhiyunalong with the packet length.  The common code sets up packet buffers for you
146*4882a593Smuzhiyunalready in the .bss (net_rx_packets), so there should be no need to allocate your
147*4882a593Smuzhiyunown.  This doesn't mean you must use the net_rx_packets array however; you're
148*4882a593Smuzhiyunfree to call the net_process_received_packet() function with any buffer you wish.  So the pseudo
149*4882a593Smuzhiyuncode here would look something like:
150*4882a593Smuzhiyunint ape_recv(struct eth_device *dev)
151*4882a593Smuzhiyun{
152*4882a593Smuzhiyun	int length, i = 0;
153*4882a593Smuzhiyun	...
154*4882a593Smuzhiyun	while (packets_are_available()) {
155*4882a593Smuzhiyun		...
156*4882a593Smuzhiyun		length = ape_get_packet(&net_rx_packets[i]);
157*4882a593Smuzhiyun		...
158*4882a593Smuzhiyun		net_process_received_packet(&net_rx_packets[i], length);
159*4882a593Smuzhiyun		...
160*4882a593Smuzhiyun		if (++i >= PKTBUFSRX)
161*4882a593Smuzhiyun			i = 0;
162*4882a593Smuzhiyun		...
163*4882a593Smuzhiyun	}
164*4882a593Smuzhiyun	...
165*4882a593Smuzhiyun	return 0;
166*4882a593Smuzhiyun}
167*4882a593Smuzhiyun
168*4882a593SmuzhiyunThe halt function should turn off / disable the hardware and place it back in
169*4882a593Smuzhiyunits reset state.  It can be called at any time (before any call to the related
170*4882a593Smuzhiyuninit function), so make sure it can handle this sort of thing.
171*4882a593Smuzhiyun
172*4882a593SmuzhiyunThe write_hwaddr function should program the MAC address stored in dev->enetaddr
173*4882a593Smuzhiyuninto the Ethernet controller.
174*4882a593Smuzhiyun
175*4882a593SmuzhiyunSo the call graph at this stage would look something like:
176*4882a593Smuzhiyunsome net operation (ping / tftp / whatever...)
177*4882a593Smuzhiyun	eth_init()
178*4882a593Smuzhiyun		dev->init()
179*4882a593Smuzhiyun	eth_send()
180*4882a593Smuzhiyun		dev->send()
181*4882a593Smuzhiyun	eth_rx()
182*4882a593Smuzhiyun		dev->recv()
183*4882a593Smuzhiyun	eth_halt()
184*4882a593Smuzhiyun		dev->halt()
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun--------------------------------
187*4882a593Smuzhiyun CONFIG_PHYLIB / CONFIG_CMD_MII
188*4882a593Smuzhiyun--------------------------------
189*4882a593Smuzhiyun
190*4882a593SmuzhiyunIf your device supports banging arbitrary values on the MII bus (pretty much
191*4882a593Smuzhiyunevery device does), you should add support for the mii command.  Doing so is
192*4882a593Smuzhiyunfairly trivial and makes debugging mii issues a lot easier at runtime.
193*4882a593Smuzhiyun
194*4882a593SmuzhiyunAfter you have called eth_register() in your driver's register function, add
195*4882a593Smuzhiyuna call to mdio_alloc() and mdio_register() like so:
196*4882a593Smuzhiyun	bus = mdio_alloc();
197*4882a593Smuzhiyun	if (!bus) {
198*4882a593Smuzhiyun		free(priv);
199*4882a593Smuzhiyun		free(dev);
200*4882a593Smuzhiyun		return -ENOMEM;
201*4882a593Smuzhiyun	}
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun	bus->read = ape_mii_read;
204*4882a593Smuzhiyun	bus->write = ape_mii_write;
205*4882a593Smuzhiyun	mdio_register(bus);
206*4882a593Smuzhiyun
207*4882a593SmuzhiyunAnd then define the mii_read and mii_write functions if you haven't already.
208*4882a593SmuzhiyunTheir syntax is straightforward:
209*4882a593Smuzhiyun	int mii_read(struct mii_dev *bus, int addr, int devad, int reg);
210*4882a593Smuzhiyun	int mii_write(struct mii_dev *bus, int addr, int devad, int reg,
211*4882a593Smuzhiyun		      u16 val);
212*4882a593Smuzhiyun
213*4882a593SmuzhiyunThe read function should read the register 'reg' from the phy at address 'addr'
214*4882a593Smuzhiyunand return the result to its caller.  The implementation for the write function
215*4882a593Smuzhiyunshould logically follow.
216