Commit bd3980cc095af1728b994cdd8bf1ac430b6289e6
Committed by
Ben Warren
1 parent
890a02e8ee
Exists in
master
and in
55 other branches
sh: sh_eth: Change new network API
sh_eth used old network API. This patch changed new API. Signed-off-by: Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com> Signed-off-by: Ben Warren <biggerbadderben@gmail.com>
Showing 4 changed files with 240 additions and 134 deletions Side-by-side Diff
cpu/sh4/cpu.c
drivers/net/sh_eth.c
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | #include <common.h> |
25 | 25 | #include <malloc.h> |
26 | 26 | #include <net.h> |
27 | +#include <netdev.h> | |
27 | 28 | #include <asm/errno.h> |
28 | 29 | #include <asm/io.h> |
29 | 30 | |
30 | 31 | |
... | ... | @@ -36,13 +37,8 @@ |
36 | 37 | # error "Please define CONFIG_SH_ETHER_PHY_ADDR" |
37 | 38 | #endif |
38 | 39 | |
39 | -extern int eth_init(bd_t *bd); | |
40 | -extern void eth_halt(void); | |
41 | -extern int eth_rx(void); | |
42 | -extern int eth_send(volatile void *packet, int length); | |
40 | +#define SH_ETH_PHY_DELAY 50000 | |
43 | 41 | |
44 | -static struct dev_info_s *dev; | |
45 | - | |
46 | 42 | /* |
47 | 43 | * Bits are written to the PHY serially using the |
48 | 44 | * PIR register, just like a bit banger. |
... | ... | @@ -89,7 +85,7 @@ |
89 | 85 | udelay(1); |
90 | 86 | } |
91 | 87 | |
92 | -static int sh_eth_mii_read_phy_bits(int port, u32 * val, int len) | |
88 | +static void sh_eth_mii_read_phy_bits(int port, u32 *val, int len) | |
93 | 89 | { |
94 | 90 | int i; |
95 | 91 | u32 pir; |
... | ... | @@ -106,8 +102,6 @@ |
106 | 102 | outl(0, PIR(port)); |
107 | 103 | udelay(1); |
108 | 104 | } |
109 | - | |
110 | - return 0; | |
111 | 105 | } |
112 | 106 | |
113 | 107 | #define PHY_INIT 0xFFFFFFFF |
114 | 108 | |
115 | 109 | |
116 | 110 | |
117 | 111 | |
... | ... | @@ -183,26 +177,23 @@ |
183 | 177 | sh_eth_mii_ind_bus_release(port); |
184 | 178 | } |
185 | 179 | |
186 | -void eth_halt(void) | |
180 | +int sh_eth_send(struct eth_device *dev, volatile void *packet, int len) | |
187 | 181 | { |
188 | -} | |
182 | + struct sh_eth_dev *eth = dev->priv; | |
183 | + int port = eth->port, ret = 0, timeout; | |
184 | + struct sh_eth_info *port_info = ð->port_info[port]; | |
189 | 185 | |
190 | -int eth_send(volatile void *packet, int len) | |
191 | -{ | |
192 | - int port = dev->port; | |
193 | - struct port_info_s *port_info = &dev->port_info[port]; | |
194 | - int timeout; | |
195 | - int rc = 0; | |
196 | - | |
197 | 186 | if (!packet || len > 0xffff) { |
198 | - printf("eth_send: Invalid argument\n"); | |
199 | - return -EINVAL; | |
187 | + printf(SHETHER_NAME ": %s: Invalid argument\n", __func__); | |
188 | + ret = -EINVAL; | |
189 | + goto err; | |
200 | 190 | } |
201 | 191 | |
202 | 192 | /* packet must be a 4 byte boundary */ |
203 | 193 | if ((int)packet & (4 - 1)) { |
204 | - printf("eth_send: packet not 4 byte alligned\n"); | |
205 | - return -EFAULT; | |
194 | + printf(SHETHER_NAME ": %s: packet not 4 byte alligned\n", __func__); | |
195 | + ret = -EFAULT; | |
196 | + goto err; | |
206 | 197 | } |
207 | 198 | |
208 | 199 | /* Update tx descriptor */ |
209 | 200 | |
210 | 201 | |
211 | 202 | |
212 | 203 | |
... | ... | @@ -224,24 +215,25 @@ |
224 | 215 | udelay(100); |
225 | 216 | |
226 | 217 | if (timeout < 0) { |
227 | - printf("eth_send: transmit timeout\n"); | |
228 | - rc = -1; | |
218 | + printf(SHETHER_NAME ": transmit timeout\n"); | |
219 | + ret = -ETIMEDOUT; | |
229 | 220 | goto err; |
230 | 221 | } |
231 | 222 | |
232 | -err: | |
233 | 223 | port_info->tx_desc_cur++; |
234 | 224 | if (port_info->tx_desc_cur >= port_info->tx_desc_base + NUM_TX_DESC) |
235 | 225 | port_info->tx_desc_cur = port_info->tx_desc_base; |
236 | 226 | |
237 | - return rc; | |
227 | + return ret; | |
228 | +err: | |
229 | + return ret; | |
238 | 230 | } |
239 | 231 | |
240 | -int eth_rx(void) | |
232 | +int sh_eth_recv(struct eth_device *dev) | |
241 | 233 | { |
242 | - int port = dev->port; | |
243 | - struct port_info_s *port_info = &dev->port_info[port]; | |
244 | - int len = 0; | |
234 | + struct sh_eth_dev *eth = dev->priv; | |
235 | + int port = eth->port, len = 0; | |
236 | + struct sh_eth_info *port_info = ð->port_info[port]; | |
245 | 237 | volatile u8 *packet; |
246 | 238 | |
247 | 239 | /* Check if the rx descriptor is ready */ |
248 | 240 | |
... | ... | @@ -275,10 +267,10 @@ |
275 | 267 | } |
276 | 268 | |
277 | 269 | #define EDMR_INIT_CNT 1000 |
278 | -static int sh_eth_reset(struct dev_info_s *dev) | |
270 | +static int sh_eth_reset(struct sh_eth_dev *eth) | |
279 | 271 | { |
280 | - int port = dev->port; | |
281 | - int i; | |
272 | + int port = eth->port; | |
273 | + int ret = 0, i; | |
282 | 274 | |
283 | 275 | /* Start e-dmac transmitter and receiver */ |
284 | 276 | outl(EDSR_ENALL, EDSR(port)); |
285 | 277 | |
286 | 278 | |
287 | 279 | |
288 | 280 | |
289 | 281 | |
290 | 282 | |
291 | 283 | |
292 | 284 | |
293 | 285 | |
... | ... | @@ -292,33 +284,36 @@ |
292 | 284 | } |
293 | 285 | |
294 | 286 | if (i == EDMR_INIT_CNT) { |
295 | - printf("Error: Software reset timeout\n"); | |
296 | - return -1; | |
287 | + printf(SHETHER_NAME ": Software reset timeout\n"); | |
288 | + ret = -EIO; | |
297 | 289 | } |
298 | - return 0; | |
290 | + | |
291 | + return ret; | |
299 | 292 | } |
300 | 293 | |
301 | -static int sh_eth_tx_desc_init(struct dev_info_s *dev) | |
294 | +static int sh_eth_tx_desc_init(struct sh_eth_dev *eth) | |
302 | 295 | { |
303 | - int port = dev->port; | |
304 | - struct port_info_s *port_info = &dev->port_info[port]; | |
296 | + int port = eth->port, i, ret = 0; | |
305 | 297 | u32 tmp_addr; |
298 | + struct sh_eth_info *port_info = ð->port_info[port]; | |
306 | 299 | struct tx_desc_s *cur_tx_desc; |
307 | - int i; | |
308 | 300 | |
309 | - /* Allocate tx descriptors. They must be TX_DESC_SIZE bytes | |
310 | - aligned */ | |
311 | - if (!(port_info->tx_desc_malloc = malloc(NUM_TX_DESC * | |
301 | + /* | |
302 | + * Allocate tx descriptors. They must be TX_DESC_SIZE bytes aligned | |
303 | + */ | |
304 | + port_info->tx_desc_malloc = malloc(NUM_TX_DESC * | |
312 | 305 | sizeof(struct tx_desc_s) + |
313 | - TX_DESC_SIZE - 1))) { | |
314 | - printf("Error: malloc failed\n"); | |
315 | - return -ENOMEM; | |
306 | + TX_DESC_SIZE - 1); | |
307 | + if (!port_info->tx_desc_malloc) { | |
308 | + printf(SHETHER_NAME ": malloc failed\n"); | |
309 | + ret = -ENOMEM; | |
310 | + goto err; | |
316 | 311 | } |
312 | + | |
317 | 313 | tmp_addr = (u32) (((int)port_info->tx_desc_malloc + TX_DESC_SIZE - 1) & |
318 | 314 | ~(TX_DESC_SIZE - 1)); |
319 | 315 | /* Make sure we use a P2 address (non-cacheable) */ |
320 | 316 | port_info->tx_desc_base = (struct tx_desc_s *)ADDR_TO_P2(tmp_addr); |
321 | - | |
322 | 317 | port_info->tx_desc_cur = port_info->tx_desc_base; |
323 | 318 | |
324 | 319 | /* Initialize all descriptors */ |
325 | 320 | |
326 | 321 | |
327 | 322 | |
328 | 323 | |
329 | 324 | |
330 | 325 | |
331 | 326 | |
... | ... | @@ -340,26 +335,30 @@ |
340 | 335 | outl(ADDR_TO_PHY(cur_tx_desc), TDFXR(port)); |
341 | 336 | outl(0x01, TDFFR(port));/* Last discriptor bit */ |
342 | 337 | |
343 | - return 0; | |
338 | +err: | |
339 | + return ret; | |
344 | 340 | } |
345 | 341 | |
346 | -static int sh_eth_rx_desc_init(struct dev_info_s *dev) | |
342 | +static int sh_eth_rx_desc_init(struct sh_eth_dev *eth) | |
347 | 343 | { |
348 | - int port = dev->port; | |
349 | - struct port_info_s *port_info = &dev->port_info[port]; | |
350 | - u32 tmp_addr; | |
344 | + int port = eth->port, i , ret = 0; | |
345 | + struct sh_eth_info *port_info = ð->port_info[port]; | |
351 | 346 | struct rx_desc_s *cur_rx_desc; |
347 | + u32 tmp_addr; | |
352 | 348 | u8 *rx_buf; |
353 | - int i; | |
354 | 349 | |
355 | - /* Allocate rx descriptors. They must be RX_DESC_SIZE bytes | |
356 | - aligned */ | |
357 | - if (!(port_info->rx_desc_malloc = malloc(NUM_RX_DESC * | |
350 | + /* | |
351 | + * Allocate rx descriptors. They must be RX_DESC_SIZE bytes aligned | |
352 | + */ | |
353 | + port_info->rx_desc_malloc = malloc(NUM_RX_DESC * | |
358 | 354 | sizeof(struct rx_desc_s) + |
359 | - RX_DESC_SIZE - 1))) { | |
360 | - printf("Error: malloc failed\n"); | |
361 | - return -ENOMEM; | |
355 | + RX_DESC_SIZE - 1); | |
356 | + if (!port_info->rx_desc_malloc) { | |
357 | + printf(SHETHER_NAME ": malloc failed\n"); | |
358 | + ret = -ENOMEM; | |
359 | + goto err; | |
362 | 360 | } |
361 | + | |
363 | 362 | tmp_addr = (u32) (((int)port_info->rx_desc_malloc + RX_DESC_SIZE - 1) & |
364 | 363 | ~(RX_DESC_SIZE - 1)); |
365 | 364 | /* Make sure we use a P2 address (non-cacheable) */ |
366 | 365 | |
... | ... | @@ -367,15 +366,17 @@ |
367 | 366 | |
368 | 367 | port_info->rx_desc_cur = port_info->rx_desc_base; |
369 | 368 | |
370 | - /* Allocate rx data buffers. They must be 32 bytes aligned and in | |
371 | - P2 area */ | |
372 | - if (!(port_info->rx_buf_malloc = malloc(NUM_RX_DESC * MAX_BUF_SIZE + | |
373 | - 31))) { | |
374 | - printf("Error: malloc failed\n"); | |
375 | - free(port_info->rx_desc_malloc); | |
376 | - port_info->rx_desc_malloc = NULL; | |
377 | - return -ENOMEM; | |
369 | + /* | |
370 | + * Allocate rx data buffers. They must be 32 bytes aligned and in | |
371 | + * P2 area | |
372 | + */ | |
373 | + port_info->rx_buf_malloc = malloc(NUM_RX_DESC * MAX_BUF_SIZE + 31); | |
374 | + if (!port_info->rx_buf_malloc) { | |
375 | + printf(SHETHER_NAME ": malloc failed\n"); | |
376 | + ret = -ENOMEM; | |
377 | + goto err_buf_malloc; | |
378 | 378 | } |
379 | + | |
379 | 380 | tmp_addr = (u32)(((int)port_info->rx_buf_malloc + (32 - 1)) & |
380 | 381 | ~(32 - 1)); |
381 | 382 | port_info->rx_buf_base = (u8 *)ADDR_TO_P2(tmp_addr); |
382 | 383 | |
383 | 384 | |
384 | 385 | |
385 | 386 | |
... | ... | @@ -399,19 +400,32 @@ |
399 | 400 | outl(ADDR_TO_PHY(cur_rx_desc), RDFXR(port)); |
400 | 401 | outl(RDFFR_RDLF, RDFFR(port)); |
401 | 402 | |
402 | - return 0; | |
403 | + return ret; | |
404 | + | |
405 | +err_buf_malloc: | |
406 | + free(port_info->rx_desc_malloc); | |
407 | + port_info->rx_desc_malloc = NULL; | |
408 | + | |
409 | +err: | |
410 | + return ret; | |
403 | 411 | } |
404 | 412 | |
405 | -static void sh_eth_desc_free(struct dev_info_s *dev) | |
413 | +static void sh_eth_tx_desc_free(struct sh_eth_dev *eth) | |
406 | 414 | { |
407 | - int port = dev->port; | |
408 | - struct port_info_s *port_info = &dev->port_info[port]; | |
415 | + int port = eth->port; | |
416 | + struct sh_eth_info *port_info = ð->port_info[port]; | |
409 | 417 | |
410 | 418 | if (port_info->tx_desc_malloc) { |
411 | 419 | free(port_info->tx_desc_malloc); |
412 | 420 | port_info->tx_desc_malloc = NULL; |
413 | 421 | } |
422 | +} | |
414 | 423 | |
424 | +static void sh_eth_rx_desc_free(struct sh_eth_dev *eth) | |
425 | +{ | |
426 | + int port = eth->port; | |
427 | + struct sh_eth_info *port_info = ð->port_info[port]; | |
428 | + | |
415 | 429 | if (port_info->rx_desc_malloc) { |
416 | 430 | free(port_info->rx_desc_malloc); |
417 | 431 | port_info->rx_desc_malloc = NULL; |
418 | 432 | |
419 | 433 | |
420 | 434 | |
421 | 435 | |
422 | 436 | |
423 | 437 | |
424 | 438 | |
425 | 439 | |
426 | 440 | |
427 | 441 | |
428 | 442 | |
... | ... | @@ -423,36 +437,48 @@ |
423 | 437 | } |
424 | 438 | } |
425 | 439 | |
426 | -static int sh_eth_desc_init(struct dev_info_s *dev) | |
440 | +static int sh_eth_desc_init(struct sh_eth_dev *eth) | |
427 | 441 | { |
428 | - int rc; | |
442 | + int ret = 0; | |
429 | 443 | |
430 | - if ((rc = sh_eth_tx_desc_init(dev)) || (rc = sh_eth_rx_desc_init(dev))) { | |
431 | - sh_eth_desc_free(dev); | |
432 | - return rc; | |
433 | - } | |
444 | + ret = sh_eth_tx_desc_init(eth); | |
445 | + if (ret) | |
446 | + goto err_tx_init; | |
434 | 447 | |
435 | - return 0; | |
448 | + ret = sh_eth_rx_desc_init(eth); | |
449 | + if (ret) | |
450 | + goto err_rx_init; | |
451 | + | |
452 | + return ret; | |
453 | +err_rx_init: | |
454 | + sh_eth_tx_desc_free(eth); | |
455 | + | |
456 | +err_tx_init: | |
457 | + return ret; | |
436 | 458 | } |
437 | 459 | |
438 | -static int sh_eth_phy_config(struct dev_info_s *dev) | |
460 | +static int sh_eth_phy_config(struct sh_eth_dev *eth) | |
439 | 461 | { |
440 | - int port = dev->port; | |
441 | - struct port_info_s *port_info = &dev->port_info[port]; | |
442 | - int timeout; | |
462 | + int port = eth->port, timeout, ret = 0; | |
463 | + struct sh_eth_info *port_info = ð->port_info[port]; | |
443 | 464 | u32 val; |
465 | + | |
444 | 466 | /* Reset phy */ |
445 | - sh_eth_mii_write_phy_reg(port, port_info->phy_addr, PHY_CTRL, PHY_C_RESET); | |
467 | + sh_eth_mii_write_phy_reg | |
468 | + (port, port_info->phy_addr, PHY_CTRL, PHY_C_RESET); | |
446 | 469 | timeout = 10; |
447 | 470 | while (timeout--) { |
448 | - val = sh_eth_mii_read_phy_reg(port, port_info->phy_addr, PHY_CTRL); | |
471 | + val = sh_eth_mii_read_phy_reg(port, | |
472 | + port_info->phy_addr, PHY_CTRL); | |
449 | 473 | if (!(val & PHY_C_RESET)) |
450 | 474 | break; |
451 | - udelay(50000); | |
475 | + udelay(SH_ETH_PHY_DELAY); | |
452 | 476 | } |
477 | + | |
453 | 478 | if (timeout < 0) { |
454 | - printf("%s phy reset timeout\n", __func__); | |
455 | - return -1; | |
479 | + printf(SHETHER_NAME ": phy reset timeout\n"); | |
480 | + ret = -EIO; | |
481 | + goto err_tout; | |
456 | 482 | } |
457 | 483 | |
458 | 484 | /* Advertise 100/10 baseT full/half duplex */ |
459 | 485 | |
460 | 486 | |
461 | 487 | |
462 | 488 | |
463 | 489 | |
... | ... | @@ -467,23 +493,27 @@ |
467 | 493 | val = sh_eth_mii_read_phy_reg(port, port_info->phy_addr, 1); |
468 | 494 | if (val & PHY_S_ANEGC) |
469 | 495 | break; |
470 | - udelay(50000); | |
496 | + | |
497 | + udelay(SH_ETH_PHY_DELAY); | |
471 | 498 | } |
499 | + | |
472 | 500 | if (timeout < 0) { |
473 | - printf("sh_eth_phy_config() phy auto-negotiation failed\n"); | |
474 | - return -1; | |
501 | + printf(SHETHER_NAME ": phy auto-negotiation failed\n"); | |
502 | + ret = -ETIMEDOUT; | |
503 | + goto err_tout; | |
475 | 504 | } |
476 | 505 | |
477 | - return 0; | |
506 | + return ret; | |
507 | + | |
508 | +err_tout: | |
509 | + return ret; | |
478 | 510 | } |
479 | 511 | |
480 | -static int sh_eth_config(struct dev_info_s *dev, bd_t * bd) | |
512 | +static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) | |
481 | 513 | { |
482 | - int port = dev->port; | |
483 | - struct port_info_s *port_info = &dev->port_info[port]; | |
484 | - u32 val; | |
485 | - u32 phy_status; | |
486 | - int rc; | |
514 | + int port = eth->port, ret = 0; | |
515 | + u32 val, phy_status; | |
516 | + struct sh_eth_info *port_info = ð->port_info[port]; | |
487 | 517 | |
488 | 518 | /* Configure e-dmac registers */ |
489 | 519 | outl((inl(EDMR(port)) & ~EMDR_DESC_R) | EDMR_EL, EDMR(port)); |
490 | 520 | |
491 | 521 | |
492 | 522 | |
... | ... | @@ -513,20 +543,20 @@ |
513 | 543 | outl(TPAUSER_TPAUSE, TPAUSER(port)); |
514 | 544 | |
515 | 545 | /* Configure phy */ |
516 | - if ((rc = sh_eth_phy_config(dev))) | |
517 | - return rc; | |
518 | - | |
546 | + ret = sh_eth_phy_config(eth); | |
547 | + if (ret) { | |
548 | + printf(SHETHER_NAME ":i phy config timeout\n"); | |
549 | + goto err_phy_cfg; | |
550 | + } | |
519 | 551 | /* Read phy status to finish configuring the e-mac */ |
520 | - phy_status = sh_eth_mii_read_phy_reg(dev->port, | |
521 | - dev->port_info[dev->port].phy_addr, | |
522 | - 1); | |
552 | + phy_status = sh_eth_mii_read_phy_reg(port, port_info->phy_addr, 1); | |
523 | 553 | |
524 | 554 | /* Set the transfer speed */ |
525 | 555 | if (phy_status & (PHY_S_100X_F|PHY_S_100X_H)) { |
526 | - printf("100Base/"); | |
556 | + printf(SHETHER_NAME ": 100Base/"); | |
527 | 557 | outl(GECMR_100B, GECMR(port)); |
528 | 558 | } else { |
529 | - printf("10Base/"); | |
559 | + printf(SHETHER_NAME ": 10Base/"); | |
530 | 560 | outl(GECMR_10B, GECMR(port)); |
531 | 561 | } |
532 | 562 | |
533 | 563 | |
534 | 564 | |
535 | 565 | |
536 | 566 | |
537 | 567 | |
... | ... | @@ -538,27 +568,34 @@ |
538 | 568 | printf("Half\n"); |
539 | 569 | outl((ECMR_CHG_DM|ECMR_RE|ECMR_TE), ECMR(port)); |
540 | 570 | } |
541 | - return 0; | |
571 | + | |
572 | + return ret; | |
573 | + | |
574 | +err_phy_cfg: | |
575 | + return ret; | |
542 | 576 | } |
543 | 577 | |
544 | -static int sh_eth_start(struct dev_info_s *dev) | |
578 | +static void sh_eth_start(struct sh_eth_dev *eth) | |
545 | 579 | { |
546 | 580 | /* |
547 | 581 | * Enable the e-dmac receiver only. The transmitter will be enabled when |
548 | 582 | * we have something to transmit |
549 | 583 | */ |
550 | - outl(EDRRR_R, EDRRR(dev->port)); | |
584 | + outl(EDRRR_R, EDRRR(eth->port)); | |
585 | +} | |
551 | 586 | |
552 | - return 0; | |
587 | +static void sh_eth_stop(struct sh_eth_dev *eth) | |
588 | +{ | |
589 | + outl(~EDRRR_R, EDRRR(eth->port)); | |
553 | 590 | } |
554 | 591 | |
555 | 592 | static int sh_eth_get_mac(bd_t *bd) |
556 | 593 | { |
557 | 594 | char *s, *e; |
558 | - int i; | |
559 | 595 | |
560 | 596 | s = getenv("ethaddr"); |
561 | 597 | if (s != NULL) { |
598 | + int i; | |
562 | 599 | for (i = 0; i < 6; ++i) { |
563 | 600 | bd->bi_enetaddr[i] = s ? simple_strtoul(s, &e, 16) : 0; |
564 | 601 | if (s) |
565 | 602 | |
566 | 603 | |
567 | 604 | |
568 | 605 | |
569 | 606 | |
570 | 607 | |
571 | 608 | |
572 | 609 | |
573 | 610 | |
574 | 611 | |
... | ... | @@ -570,35 +607,93 @@ |
570 | 607 | return 0; |
571 | 608 | } |
572 | 609 | |
573 | -int eth_init(bd_t *bd) | |
610 | +int sh_eth_init(struct eth_device *dev, bd_t *bd) | |
574 | 611 | { |
575 | - int rc; | |
576 | - /* Allocate main device information structure */ | |
577 | - if (!(dev = malloc(sizeof(*dev)))) { | |
578 | - printf("eth_init: malloc failed\n"); | |
579 | - return -ENOMEM; | |
580 | - } | |
612 | + int ret = 0; | |
613 | + struct sh_eth_dev *eth = dev->priv; | |
581 | 614 | |
582 | - memset(dev, 0, sizeof(*dev)); | |
615 | + ret = sh_eth_reset(eth); | |
616 | + if (ret) | |
617 | + goto err; | |
583 | 618 | |
584 | - dev->port = CONFIG_SH_ETHER_USE_PORT; | |
585 | - dev->port_info[dev->port].phy_addr = CONFIG_SH_ETHER_PHY_ADDR; | |
619 | + ret = sh_eth_desc_init(eth); | |
620 | + if (ret) | |
621 | + goto err; | |
586 | 622 | |
587 | - sh_eth_get_mac(bd); | |
623 | + ret = sh_eth_config(eth, bd); | |
624 | + if (ret) | |
625 | + goto err_config; | |
588 | 626 | |
589 | - if ((rc = sh_eth_reset(dev)) || (rc = sh_eth_desc_init(dev))) | |
627 | + sh_eth_start(eth); | |
628 | + | |
629 | + return ret; | |
630 | + | |
631 | +err_config: | |
632 | + sh_eth_tx_desc_free(eth); | |
633 | + sh_eth_rx_desc_free(eth); | |
634 | + | |
635 | +err: | |
636 | + return ret; | |
637 | +} | |
638 | + | |
639 | +void sh_eth_halt(struct eth_device *dev) | |
640 | +{ | |
641 | + struct sh_eth_dev *eth = dev->priv; | |
642 | + | |
643 | + sh_eth_reset(eth); | |
644 | + sh_eth_stop(eth); | |
645 | +} | |
646 | + | |
647 | +int sh_eth_initialize(bd_t *bd) | |
648 | +{ | |
649 | + int ret = 0; | |
650 | + struct sh_eth_dev *eth = NULL; | |
651 | + struct eth_device *dev = NULL; | |
652 | + | |
653 | + eth = (struct sh_eth_dev *)malloc(sizeof(struct sh_eth_dev)); | |
654 | + if (!eth) { | |
655 | + printf(SHETHER_NAME ": %s: malloc failed\n", __func__); | |
656 | + ret = -ENOMEM; | |
590 | 657 | goto err; |
658 | + } | |
591 | 659 | |
592 | - if ((rc = sh_eth_config(dev, bd)) || (rc = sh_eth_start(dev))) | |
593 | - goto err_desc; | |
660 | + dev = (struct eth_device *)malloc(sizeof(struct eth_device)); | |
661 | + if (!dev) { | |
662 | + printf(SHETHER_NAME ": %s: malloc failed\n", __func__); | |
663 | + ret = -ENOMEM; | |
664 | + goto err; | |
665 | + } | |
666 | + memset(dev, 0, sizeof(struct eth_device)); | |
667 | + memset(eth, 0, sizeof(struct sh_eth_dev)); | |
594 | 668 | |
595 | - return 0; | |
669 | + eth->port = CONFIG_SH_ETHER_USE_PORT; | |
670 | + eth->port_info[eth->port].phy_addr = CONFIG_SH_ETHER_PHY_ADDR; | |
596 | 671 | |
597 | -err_desc: | |
598 | - sh_eth_desc_free(dev); | |
672 | + dev->priv = (void *)eth; | |
673 | + dev->iobase = 0; | |
674 | + dev->init = sh_eth_init; | |
675 | + dev->halt = sh_eth_halt; | |
676 | + dev->send = sh_eth_send; | |
677 | + dev->recv = sh_eth_recv; | |
678 | + eth->port_info[eth->port].dev = dev; | |
679 | + | |
680 | + sprintf(dev->name, SHETHER_NAME); | |
681 | + | |
682 | + /* Register Device to EtherNet subsystem */ | |
683 | + eth_register(dev); | |
684 | + | |
685 | + sh_eth_get_mac(bd); | |
686 | + | |
687 | + return ret; | |
688 | + | |
599 | 689 | err: |
600 | - free(dev); | |
601 | - printf("eth_init: Failed\n"); | |
602 | - return rc; | |
690 | + if (dev) | |
691 | + free(dev); | |
692 | + | |
693 | + if (eth) | |
694 | + free(eth); | |
695 | + | |
696 | + printf(SHETHER_NAME ": Failed\n"); | |
697 | + return ret; | |
603 | 698 | } |
drivers/net/sh_eth.h
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | 21 | */ |
22 | 22 | |
23 | +#include <netdev.h> | |
23 | 24 | #include <asm/types.h> |
24 | 25 | |
25 | 26 | #define SHETHER_NAME "sh_eth" |
... | ... | @@ -48,7 +49,7 @@ |
48 | 49 | #define TX_DESC_PADDING 4 |
49 | 50 | #define TX_DESC_SIZE (12 + TX_DESC_PADDING) |
50 | 51 | |
51 | -/* Tx descriptor. We always use 4 bytes of padding */ | |
52 | +/* Tx descriptor. We always use 3 bytes of padding */ | |
52 | 53 | struct tx_desc_s { |
53 | 54 | volatile u32 td0; |
54 | 55 | u32 td1; |
... | ... | @@ -72,7 +73,7 @@ |
72 | 73 | u32 padding; |
73 | 74 | }; |
74 | 75 | |
75 | -struct port_info_s { | |
76 | +struct sh_eth_info { | |
76 | 77 | struct tx_desc_s *tx_desc_malloc; |
77 | 78 | struct tx_desc_s *tx_desc_base; |
78 | 79 | struct tx_desc_s *tx_desc_cur; |
79 | 80 | |
80 | 81 | |
... | ... | @@ -83,11 +84,12 @@ |
83 | 84 | u8 *rx_buf_base; |
84 | 85 | u8 mac_addr[6]; |
85 | 86 | u8 phy_addr; |
87 | + struct eth_device *dev; | |
86 | 88 | }; |
87 | 89 | |
88 | -struct dev_info_s { | |
90 | +struct sh_eth_dev { | |
89 | 91 | int port; |
90 | - struct port_info_s port_info[MAX_PORT_NUM]; | |
92 | + struct sh_eth_info port_info[MAX_PORT_NUM]; | |
91 | 93 | }; |
92 | 94 | |
93 | 95 | /* Register Address */ |
include/netdev.h
... | ... | @@ -70,6 +70,7 @@ |
70 | 70 | int tsi108_eth_initialize(bd_t *bis); |
71 | 71 | int uec_initialize(int index); |
72 | 72 | int uli526x_initialize(bd_t *bis); |
73 | +int sh_eth_initialize(bd_t *bis); | |
73 | 74 | |
74 | 75 | /* Boards with PCI network controllers can call this from their board_eth_init() |
75 | 76 | * function to initialize whatever's on board. |