220-enet_micrel_workaround.patch 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. @@ -326,8 +371,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. @@ -870,7 +917,8 @@ static int ar231x_open(struct net_device
  79. sp->eth_regs->mac_control |= MAC_CONTROL_RE;
  80. - phy_start(sp->phy_dev);
  81. + if (sp->phy_dev)
  82. + phy_start(sp->phy_dev);
  83. return 0;
  84. }
  85. @@ -951,7 +999,8 @@ static int ar231x_close(struct net_devic
  86. #endif
  87. - phy_stop(sp->phy_dev);
  88. + if (sp->phy_dev)
  89. + phy_stop(sp->phy_dev);
  90. return 0;
  91. }
  92. @@ -995,6 +1044,9 @@ static int ar231x_ioctl(struct net_devic
  93. {
  94. struct ar231x_private *sp = netdev_priv(dev);
  95. + if (!sp->phy_dev)
  96. + return -ENODEV;
  97. +
  98. switch (cmd) {
  99. case SIOCGMIIPHY:
  100. case SIOCGMIIREG: