Revision c6488268
b/hw/etraxfs_eth.c | ||
---|---|---|
30 | 30 |
|
31 | 31 |
#define D(x) |
32 | 32 |
|
33 |
/* Advertisement control register. */ |
|
34 |
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ |
|
35 |
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ |
|
36 |
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ |
|
37 |
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ |
|
38 |
|
|
33 | 39 |
/* |
34 | 40 |
* The MDIO extensions in the TDK PHY model were reversed engineered from the |
35 | 41 |
* linux driver (PHYID and Diagnostics reg). |
... | ... | |
78 | 84 |
int speed_100 = 0; |
79 | 85 |
|
80 | 86 |
/* Are we advertising 100 half or 100 duplex ? */ |
81 |
speed_100 = !!(phy->regs[4] & 0x180); |
|
87 |
speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF); |
|
88 |
speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL); |
|
89 |
|
|
82 | 90 |
/* Are we advertising 10 duplex or 100 duplex ? */ |
83 |
duplex = !!(phy->regs[4] & 0x180); |
|
91 |
duplex = !!(phy->regs[4] & ADVERTISE_100FULL); |
|
92 |
duplex |= !!(phy->regs[4] & ADVERTISE_10FULL); |
|
84 | 93 |
r = (speed_100 << 10) | (duplex << 11); |
85 | 94 |
} |
86 | 95 |
break; |
... | ... | |
322 | 331 |
|
323 | 332 |
/* MDIO bus. */ |
324 | 333 |
struct qemu_mdio mdio_bus; |
334 |
unsigned int phyaddr; |
|
335 |
int duplex_mismatch; |
|
336 |
|
|
325 | 337 |
/* PHY. */ |
326 | 338 |
struct qemu_phy phy; |
327 | 339 |
}; |
328 | 340 |
|
341 |
static void eth_validate_duplex(struct fs_eth *eth) |
|
342 |
{ |
|
343 |
struct qemu_phy *phy; |
|
344 |
unsigned int phy_duplex; |
|
345 |
unsigned int mac_duplex; |
|
346 |
int new_mm = 0; |
|
347 |
|
|
348 |
phy = eth->mdio_bus.devs[eth->phyaddr]; |
|
349 |
phy_duplex = !!(phy->read(phy, 18) & (1 << 11)); |
|
350 |
mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128); |
|
351 |
|
|
352 |
if (mac_duplex != phy_duplex) |
|
353 |
new_mm = 1; |
|
354 |
|
|
355 |
if (eth->regs[RW_GEN_CTRL] & 1) { |
|
356 |
if (new_mm != eth->duplex_mismatch) { |
|
357 |
if (new_mm) |
|
358 |
printf("HW: WARNING " |
|
359 |
"ETH duplex mismatch MAC=%d PHY=%d\n", |
|
360 |
mac_duplex, phy_duplex); |
|
361 |
else |
|
362 |
printf("HW: ETH duplex ok.\n"); |
|
363 |
} |
|
364 |
eth->duplex_mismatch = new_mm; |
|
365 |
} |
|
366 |
} |
|
367 |
|
|
329 | 368 |
static uint32_t eth_rinvalid (void *opaque, target_phys_addr_t addr) |
330 | 369 |
{ |
331 | 370 |
struct fs_eth *eth = opaque; |
... | ... | |
418 | 457 |
/* Attach an MDIO/PHY abstraction. */ |
419 | 458 |
if (value & 2) |
420 | 459 |
eth->mdio_bus.mdio = value & 1; |
421 |
if (eth->mdio_bus.mdc != (value & 4)) |
|
460 |
if (eth->mdio_bus.mdc != (value & 4)) {
|
|
422 | 461 |
mdio_cycle(ð->mdio_bus); |
462 |
eth_validate_duplex(eth); |
|
463 |
} |
|
423 | 464 |
eth->mdio_bus.mdc = !!(value & 4); |
424 | 465 |
break; |
425 | 466 |
|
467 |
case RW_REC_CTRL: |
|
468 |
eth->regs[addr] = value; |
|
469 |
eth_validate_duplex(eth); |
|
470 |
break; |
|
471 |
|
|
426 | 472 |
default: |
427 | 473 |
eth->regs[addr] = value; |
428 | 474 |
D(printf ("%s %x %x\n", |
... | ... | |
591 | 637 |
eth->dma_in = dma + 1; |
592 | 638 |
|
593 | 639 |
/* Connect the phy. */ |
640 |
eth->phyaddr = 1; |
|
594 | 641 |
tdk_init(ð->phy); |
595 |
mdio_attach(ð->mdio_bus, ð->phy, 0x1);
|
|
642 |
mdio_attach(ð->mdio_bus, ð->phy, eth->phyaddr);
|
|
596 | 643 |
|
597 | 644 |
eth->ethregs = cpu_register_io_memory(0, eth_read, eth_write, eth); |
598 | 645 |
cpu_register_physical_memory (base, 0x5c, eth->ethregs); |
Also available in: Unified diff