734-net-phy-at803x-allow-to-configure-via-pdata.patch 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. --- a/drivers/net/phy/at803x.c
  2. +++ b/drivers/net/phy/at803x.c
  3. @@ -12,12 +12,14 @@
  4. */
  5. #include <linux/phy.h>
  6. +#include <linux/mdio.h>
  7. #include <linux/module.h>
  8. #include <linux/string.h>
  9. #include <linux/netdevice.h>
  10. #include <linux/etherdevice.h>
  11. #include <linux/of_gpio.h>
  12. #include <linux/gpio/consumer.h>
  13. +#include <linux/platform_data/phy-at803x.h>
  14. #define AT803X_INTR_ENABLE 0x12
  15. #define AT803X_INTR_STATUS 0x13
  16. @@ -34,8 +36,16 @@
  17. #define AT803X_INER 0x0012
  18. #define AT803X_INER_INIT 0xec00
  19. #define AT803X_INSR 0x0013
  20. +
  21. +#define AT803X_PCS_SMART_EEE_CTRL3 0x805D
  22. +#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK 0x3
  23. +#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT 12
  24. +#define AT803X_SMART_EEE_CTRL3_LPI_EN BIT(8)
  25. +
  26. #define AT803X_DEBUG_ADDR 0x1D
  27. #define AT803X_DEBUG_DATA 0x1E
  28. +#define AT803X_DBG0_REG 0x00
  29. +#define AT803X_DEBUG_RGMII_RX_CLK_DLY BIT(8)
  30. #define AT803X_DEBUG_SYSTEM_MODE_CTRL 0x05
  31. #define AT803X_DEBUG_RGMII_TX_CLK_DLY BIT(8)
  32. @@ -50,6 +60,7 @@ MODULE_LICENSE("GPL");
  33. struct at803x_priv {
  34. bool phy_reset:1;
  35. struct gpio_desc *gpiod_reset;
  36. + int prev_speed;
  37. };
  38. struct at803x_context {
  39. @@ -61,6 +72,43 @@ struct at803x_context {
  40. u16 led_control;
  41. };
  42. +static u16
  43. +at803x_dbg_reg_rmw(struct phy_device *phydev, u16 reg, u16 clear, u16 set)
  44. +{
  45. + struct mii_bus *bus = phydev->bus;
  46. + int val;
  47. +
  48. + mutex_lock(&bus->mdio_lock);
  49. +
  50. + bus->write(bus, phydev->addr, AT803X_DEBUG_ADDR, reg);
  51. + val = bus->read(bus, phydev->addr, AT803X_DEBUG_DATA);
  52. + if (val < 0) {
  53. + val = 0xffff;
  54. + goto out;
  55. + }
  56. +
  57. + val &= ~clear;
  58. + val |= set;
  59. + bus->write(bus, phydev->addr, AT803X_DEBUG_DATA, val);
  60. +
  61. +out:
  62. + mutex_unlock(&bus->mdio_lock);
  63. + return val;
  64. +}
  65. +
  66. +static inline void
  67. +at803x_dbg_reg_set(struct phy_device *phydev, u16 reg, u16 set)
  68. +{
  69. + at803x_dbg_reg_rmw(phydev, reg, 0, set);
  70. +}
  71. +
  72. +static inline void
  73. +at803x_dbg_reg_clr(struct phy_device *phydev, u16 reg, u16 clear)
  74. +{
  75. + at803x_dbg_reg_rmw(phydev, reg, clear, 0);
  76. +}
  77. +
  78. +
  79. /* save relevant PHY registers to private copy */
  80. static void at803x_context_save(struct phy_device *phydev,
  81. struct at803x_context *context)
  82. @@ -209,8 +257,16 @@ static int at803x_probe(struct phy_devic
  83. return 0;
  84. }
  85. +static void at803x_disable_smarteee(struct phy_device *phydev)
  86. +{
  87. + phy_write_mmd(phydev, MDIO_MMD_PCS, AT803X_PCS_SMART_EEE_CTRL3,
  88. + 1 << AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT);
  89. + phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
  90. +}
  91. +
  92. static int at803x_config_init(struct phy_device *phydev)
  93. {
  94. + struct at803x_platform_data *pdata;
  95. int ret;
  96. ret = genphy_config_init(phydev);
  97. @@ -228,6 +284,26 @@ static int at803x_config_init(struct phy
  98. return ret;
  99. }
  100. + pdata = dev_get_platdata(&phydev->dev);
  101. + if (pdata) {
  102. + if (pdata->disable_smarteee)
  103. + at803x_disable_smarteee(phydev);
  104. +
  105. + if (pdata->enable_rgmii_rx_delay)
  106. + at803x_dbg_reg_set(phydev, AT803X_DBG0_REG,
  107. + AT803X_DEBUG_RGMII_RX_CLK_DLY);
  108. + else
  109. + at803x_dbg_reg_clr(phydev, AT803X_DBG0_REG,
  110. + AT803X_DEBUG_RGMII_RX_CLK_DLY);
  111. +
  112. + if (pdata->enable_rgmii_tx_delay)
  113. + at803x_dbg_reg_set(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
  114. + AT803X_DEBUG_RGMII_TX_CLK_DLY);
  115. + else
  116. + at803x_dbg_reg_clr(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
  117. + AT803X_DEBUG_RGMII_TX_CLK_DLY);
  118. + }
  119. +
  120. return 0;
  121. }
  122. @@ -259,6 +335,8 @@ static int at803x_config_intr(struct phy
  123. static void at803x_link_change_notify(struct phy_device *phydev)
  124. {
  125. struct at803x_priv *priv = phydev->priv;
  126. + struct at803x_platform_data *pdata;
  127. + pdata = dev_get_platdata(&phydev->dev);
  128. /*
  129. * Conduct a hardware reset for AT8030 every time a link loss is
  130. @@ -289,6 +367,26 @@ static void at803x_link_change_notify(st
  131. priv->phy_reset = false;
  132. }
  133. }
  134. + if (pdata && pdata->fixup_rgmii_tx_delay &&
  135. + phydev->speed != priv->prev_speed) {
  136. + switch (phydev->speed) {
  137. + case SPEED_10:
  138. + case SPEED_100:
  139. + at803x_dbg_reg_set(phydev,
  140. + AT803X_DEBUG_SYSTEM_MODE_CTRL,
  141. + AT803X_DEBUG_RGMII_TX_CLK_DLY);
  142. + break;
  143. + case SPEED_1000:
  144. + at803x_dbg_reg_clr(phydev,
  145. + AT803X_DEBUG_SYSTEM_MODE_CTRL,
  146. + AT803X_DEBUG_RGMII_TX_CLK_DLY);
  147. + break;
  148. + default:
  149. + break;
  150. + }
  151. +
  152. + priv->prev_speed = phydev->speed;
  153. + }
  154. }
  155. static struct phy_driver at803x_driver[] = {
  156. --- /dev/null
  157. +++ b/include/linux/platform_data/phy-at803x.h
  158. @@ -0,0 +1,11 @@
  159. +#ifndef _PHY_AT803X_PDATA_H
  160. +#define _PHY_AT803X_PDATA_H
  161. +
  162. +struct at803x_platform_data {
  163. + int disable_smarteee:1;
  164. + int enable_rgmii_tx_delay:1;
  165. + int enable_rgmii_rx_delay:1;
  166. + int fixup_rgmii_tx_delay:1;
  167. +};
  168. +
  169. +#endif /* _PHY_AT803X_PDATA_H */