Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'mv88e6171_indirect_phy'

Andrew Lunn says:

====================
Indirect phy access for mv88e6171

These two patches allow the mv88e6171 driver to access the port phys
using indirect addressing. Depending on pin strapping, the switch
either uses a single address on the host MDIO bus, requiring the port
phys are accessed indirectly, or the switch uses a number of addresses
on the host bus and the phys can be directly accessed.

The 370RD, the first supported platform to use the 6171 uses multiple
addresses, so this indirect mode was not required. However the
WRT1900AC has the switch configured to use a single address, and so
indirect access is needed.

The mv88e6352 already has all the needed code. Refactor it into the
shared mv88e6xxx and then use it in the mv88e6171 driver.

Tested on the 370RD and WRT1900AC.

It would be good if Guenter Roeck could test on his platform to ensure
i've not broken anything for the mv88e6352.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+81 -73
+10 -8
drivers/net/dsa/mv88e6171.c
··· 51 51 /* Wait for transmit queues to drain. */ 52 52 usleep_range(2000, 4000); 53 53 54 - /* Reset the switch. */ 55 - REG_WRITE(REG_GLOBAL, 0x04, 0xc400); 54 + /* Reset the switch. Keep PPU active. The PPU needs to be 55 + * active to support indirect phy register accesses through 56 + * global registers 0x18 and 0x19. 57 + */ 58 + REG_WRITE(REG_GLOBAL, 0x04, 0xc000); 56 59 57 60 /* Wait up to one second for reset to complete. */ 58 61 timeout = jiffies + 1 * HZ; ··· 86 83 int ret; 87 84 int i; 88 85 89 - /* Disable the PHY polling unit (since there won't be any 90 - * external PHYs to poll), don't discard packets with 91 - * excessive collisions, and mask all interrupt sources. 86 + /* Discard packets with excessive collisions, mask all 87 + * interrupt sources, enable PPU. 92 88 */ 93 - REG_WRITE(REG_GLOBAL, 0x04, 0x0000); 89 + REG_WRITE(REG_GLOBAL, 0x04, 0x6000); 94 90 95 91 /* Set the default address aging time to 5 minutes, and 96 92 * enable address learn messages to be sent to all message ··· 338 336 int ret; 339 337 340 338 mutex_lock(&ps->phy_mutex); 341 - ret = mv88e6xxx_phy_read(ds, addr, regnum); 339 + ret = mv88e6xxx_phy_read_indirect(ds, addr, regnum); 342 340 mutex_unlock(&ps->phy_mutex); 343 341 return ret; 344 342 } ··· 352 350 int ret; 353 351 354 352 mutex_lock(&ps->phy_mutex); 355 - ret = mv88e6xxx_phy_write(ds, addr, regnum, val); 353 + ret = mv88e6xxx_phy_write_indirect(ds, addr, regnum, val); 356 354 mutex_unlock(&ps->phy_mutex); 357 355 return ret; 358 356 }
+12 -65
drivers/net/dsa/mv88e6352.c
··· 22 22 #include <net/dsa.h> 23 23 #include "mv88e6xxx.h" 24 24 25 - static int mv88e6352_wait(struct dsa_switch *ds, int reg, int offset, u16 mask) 26 - { 27 - unsigned long timeout = jiffies + HZ / 10; 28 - 29 - while (time_before(jiffies, timeout)) { 30 - int ret; 31 - 32 - ret = REG_READ(reg, offset); 33 - if (!(ret & mask)) 34 - return 0; 35 - 36 - usleep_range(1000, 2000); 37 - } 38 - return -ETIMEDOUT; 39 - } 40 - 41 - static inline int mv88e6352_phy_wait(struct dsa_switch *ds) 42 - { 43 - return mv88e6352_wait(ds, REG_GLOBAL2, 0x18, 0x8000); 44 - } 45 - 46 - static inline int mv88e6352_eeprom_load_wait(struct dsa_switch *ds) 47 - { 48 - return mv88e6352_wait(ds, REG_GLOBAL2, 0x14, 0x0800); 49 - } 50 - 51 - static inline int mv88e6352_eeprom_busy_wait(struct dsa_switch *ds) 52 - { 53 - return mv88e6352_wait(ds, REG_GLOBAL2, 0x14, 0x8000); 54 - } 55 - 56 - static int __mv88e6352_phy_read(struct dsa_switch *ds, int addr, int regnum) 57 - { 58 - int ret; 59 - 60 - REG_WRITE(REG_GLOBAL2, 0x18, 0x9800 | (addr << 5) | regnum); 61 - 62 - ret = mv88e6352_phy_wait(ds); 63 - if (ret < 0) 64 - return ret; 65 - 66 - return REG_READ(REG_GLOBAL2, 0x19); 67 - } 68 - 69 - static int __mv88e6352_phy_write(struct dsa_switch *ds, int addr, int regnum, 70 - u16 val) 71 - { 72 - REG_WRITE(REG_GLOBAL2, 0x19, val); 73 - REG_WRITE(REG_GLOBAL2, 0x18, 0x9400 | (addr << 5) | regnum); 74 - 75 - return mv88e6352_phy_wait(ds); 76 - } 77 - 78 25 static char *mv88e6352_probe(struct device *host_dev, int sw_addr) 79 26 { 80 27 struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); ··· 293 346 int ret; 294 347 295 348 mutex_lock(&ps->phy_mutex); 296 - ret = __mv88e6352_phy_write(ds, port, 0x16, page); 349 + ret = mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); 297 350 if (ret < 0) 298 351 goto error; 299 - ret = __mv88e6352_phy_read(ds, port, reg); 352 + ret = mv88e6xxx_phy_read_indirect(ds, port, reg); 300 353 error: 301 - __mv88e6352_phy_write(ds, port, 0x16, 0x0); 354 + mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); 302 355 mutex_unlock(&ps->phy_mutex); 303 356 return ret; 304 357 } ··· 310 363 int ret; 311 364 312 365 mutex_lock(&ps->phy_mutex); 313 - ret = __mv88e6352_phy_write(ds, port, 0x16, page); 366 + ret = mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); 314 367 if (ret < 0) 315 368 goto error; 316 369 317 - ret = __mv88e6352_phy_write(ds, port, reg, val); 370 + ret = mv88e6xxx_phy_write_indirect(ds, port, reg, val); 318 371 error: 319 - __mv88e6352_phy_write(ds, port, 0x16, 0x0); 372 + mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); 320 373 mutex_unlock(&ps->phy_mutex); 321 374 return ret; 322 375 } ··· 429 482 return addr; 430 483 431 484 mutex_lock(&ps->phy_mutex); 432 - ret = __mv88e6352_phy_read(ds, addr, regnum); 485 + ret = mv88e6xxx_phy_read_indirect(ds, addr, regnum); 433 486 mutex_unlock(&ps->phy_mutex); 434 487 435 488 return ret; ··· 446 499 return addr; 447 500 448 501 mutex_lock(&ps->phy_mutex); 449 - ret = __mv88e6352_phy_write(ds, addr, regnum, val); 502 + ret = mv88e6xxx_phy_write_indirect(ds, addr, regnum, val); 450 503 mutex_unlock(&ps->phy_mutex); 451 504 452 505 return ret; ··· 500 553 if (ret < 0) 501 554 goto error; 502 555 503 - ret = mv88e6352_eeprom_busy_wait(ds); 556 + ret = mv88e6xxx_eeprom_busy_wait(ds); 504 557 if (ret < 0) 505 558 goto error; 506 559 ··· 523 576 524 577 eeprom->magic = 0xc3ec4951; 525 578 526 - ret = mv88e6352_eeprom_load_wait(ds); 579 + ret = mv88e6xxx_eeprom_load_wait(ds); 527 580 if (ret < 0) 528 581 return ret; 529 582 ··· 604 657 if (ret < 0) 605 658 goto error; 606 659 607 - ret = mv88e6352_eeprom_busy_wait(ds); 660 + ret = mv88e6xxx_eeprom_busy_wait(ds); 608 661 error: 609 662 mutex_unlock(&ps->eeprom_mutex); 610 663 return ret; ··· 628 681 len = eeprom->len; 629 682 eeprom->len = 0; 630 683 631 - ret = mv88e6352_eeprom_load_wait(ds); 684 + ret = mv88e6xxx_eeprom_load_wait(ds); 632 685 if (ret < 0) 633 686 return ret; 634 687
+53
drivers/net/dsa/mv88e6xxx.c
··· 596 596 } 597 597 #endif /* CONFIG_NET_DSA_HWMON */ 598 598 599 + static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask) 600 + { 601 + unsigned long timeout = jiffies + HZ / 10; 602 + 603 + while (time_before(jiffies, timeout)) { 604 + int ret; 605 + 606 + ret = REG_READ(reg, offset); 607 + if (!(ret & mask)) 608 + return 0; 609 + 610 + usleep_range(1000, 2000); 611 + } 612 + return -ETIMEDOUT; 613 + } 614 + 615 + int mv88e6xxx_phy_wait(struct dsa_switch *ds) 616 + { 617 + return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x18, 0x8000); 618 + } 619 + 620 + int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds) 621 + { 622 + return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x14, 0x0800); 623 + } 624 + 625 + int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds) 626 + { 627 + return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x14, 0x8000); 628 + } 629 + 630 + int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum) 631 + { 632 + int ret; 633 + 634 + REG_WRITE(REG_GLOBAL2, 0x18, 0x9800 | (addr << 5) | regnum); 635 + 636 + ret = mv88e6xxx_phy_wait(ds); 637 + if (ret < 0) 638 + return ret; 639 + 640 + return REG_READ(REG_GLOBAL2, 0x19); 641 + } 642 + 643 + int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum, 644 + u16 val) 645 + { 646 + REG_WRITE(REG_GLOBAL2, 0x19, val); 647 + REG_WRITE(REG_GLOBAL2, 0x18, 0x9400 | (addr << 5) | regnum); 648 + 649 + return mv88e6xxx_phy_wait(ds); 650 + } 651 + 599 652 static int __init mv88e6xxx_init(void) 600 653 { 601 654 #if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
+6
drivers/net/dsa/mv88e6xxx.h
··· 82 82 void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, 83 83 struct ethtool_regs *regs, void *_p); 84 84 int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp); 85 + int mv88e6xxx_phy_wait(struct dsa_switch *ds); 86 + int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds); 87 + int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds); 88 + int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum); 89 + int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum, 90 + u16 val); 85 91 86 92 extern struct dsa_switch_driver mv88e6131_switch_driver; 87 93 extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;