220-enet_micrel_workaround.patch 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. --- a/drivers/net/ethernet/atheros/ar231x/ar231x.c
  2. +++ b/drivers/net/ethernet/atheros/ar231x/ar231x.c
  3. @@ -135,6 +135,7 @@ static int ar231x_mdiobus_write(struct m
  4. static int ar231x_mdiobus_reset(struct mii_bus *bus);
  5. static int ar231x_mdiobus_probe(struct net_device *dev);
  6. static void ar231x_adjust_link(struct net_device *dev);
  7. +static bool no_phy;
  8. #ifndef ERR
  9. #define ERR(fmt, args...) printk("%s: " fmt, __func__, ##args)
  10. @@ -167,6 +168,32 @@ static const struct net_device_ops ar231
  11. #endif
  12. };
  13. +static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
  14. +{
  15. + int phy_reg;
  16. +
  17. + /**
  18. + * Grab the bits from PHYIR1, and put them
  19. + * in the upper half.
  20. + */
  21. + phy_reg = mdiobus_read(bus, addr, MII_PHYSID1);
  22. +
  23. + if (phy_reg < 0)
  24. + return -EIO;
  25. +
  26. + *phy_id = (phy_reg & 0xffff) << 16;
  27. +
  28. + /* Grab the bits from PHYIR2, and put them in the lower half */
  29. + phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);
  30. +
  31. + if (phy_reg < 0)
  32. + return -EIO;
  33. +
  34. + *phy_id |= (phy_reg & 0xffff);
  35. +
  36. + return 0;
  37. +}
  38. +
  39. static int ar231x_probe(struct platform_device *pdev)
  40. {
  41. struct net_device *dev;
  42. @@ -273,6 +300,24 @@ static int ar231x_probe(struct platform_
  43. mdiobus_register(sp->mii_bus);
  44. + /**
  45. + * Workaround for Micrel switch, which is only available on
  46. + * one PHY and cannot be configured through MDIO.
  47. + */
  48. + if (!no_phy) {
  49. + u32 phy_id = 0;
  50. +
  51. + get_phy_id(sp->mii_bus, 1, &phy_id);
  52. + if (phy_id == 0x00221450)
  53. + no_phy = true;
  54. + }
  55. + if (no_phy) {
  56. + sp->link = 1;
  57. + netif_carrier_on(dev);
  58. + return 0;
  59. + }
  60. + no_phy = true;
  61. +
  62. if (ar231x_mdiobus_probe(dev) != 0) {
  63. printk(KERN_ERR "%s: mdiobus_probe failed\n", dev->name);
  64. rx_tasklet_cleanup(dev);
  65. @@ -329,8 +374,10 @@ static int ar231x_remove(struct platform
  66. rx_tasklet_cleanup(dev);
  67. ar231x_init_cleanup(dev);
  68. unregister_netdev(dev);
  69. - mdiobus_unregister(sp->mii_bus);
  70. - mdiobus_free(sp->mii_bus);
  71. + if (sp->mii_bus) {
  72. + mdiobus_unregister(sp->mii_bus);
  73. + mdiobus_free(sp->mii_bus);
  74. + }
  75. kfree(dev);
  76. return 0;
  77. }
  78. @@ -1079,6 +1126,9 @@ static int ar231x_ioctl(struct net_devic
  79. {
  80. struct ar231x_private *sp = netdev_priv(dev);
  81. + if (!sp->phy_dev)
  82. + return -ENODEV;
  83. +
  84. switch (cmd) {
  85. case SIOCGMIIPHY:
  86. case SIOCGMIIREG: