1 From: Gabor Juhos <juhosg@openwrt.org>
2 Subject: net: phy: allow to configure AR803x PHYs via platform data
4 Add a patch for the at803x phy driver, in order to be able
5 to configure some register settings via platform data.
7 Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
9 drivers/net/phy/at803x.c | 56 ++++++++++++++++++++++++++++++++
10 include/linux/platform_data/phy-at803x.h | 11 +++++++
11 2 files changed, 67 insertions(+)
12 create mode 100644 include/linux/platform_data/phy-at803x.h
14 --- a/drivers/net/phy/at803x.c
15 +++ b/drivers/net/phy/at803x.c
19 #include <linux/phy.h>
20 +#include <linux/mdio.h>
21 #include <linux/module.h>
22 #include <linux/string.h>
23 #include <linux/netdevice.h>
24 #include <linux/etherdevice.h>
25 #include <linux/of_gpio.h>
26 #include <linux/gpio/consumer.h>
27 +#include <linux/platform_data/phy-at803x.h>
29 #define AT803X_INTR_ENABLE 0x12
30 #define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15)
32 #define AT803X_REG_CHIP_CONFIG 0x1f
33 #define AT803X_BT_BX_REG_SEL 0x8000
35 +#define AT803X_PCS_SMART_EEE_CTRL3 0x805D
36 +#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK 0x3
37 +#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT 12
38 +#define AT803X_SMART_EEE_CTRL3_LPI_EN BIT(8)
40 #define AT803X_DEBUG_ADDR 0x1D
41 #define AT803X_DEBUG_DATA 0x1E
43 @@ -72,6 +79,7 @@ MODULE_LICENSE("GPL");
46 struct gpio_desc *gpiod_reset;
50 struct at803x_context {
51 @@ -276,8 +284,16 @@ does_not_require_reset_workaround:
55 +static void at803x_disable_smarteee(struct phy_device *phydev)
57 + phy_write_mmd(phydev, MDIO_MMD_PCS, AT803X_PCS_SMART_EEE_CTRL3,
58 + 1 << AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT);
59 + phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
62 static int at803x_config_init(struct phy_device *phydev)
64 + struct at803x_platform_data *pdata;
67 ret = genphy_config_init(phydev);
68 @@ -298,6 +314,26 @@ static int at803x_config_init(struct phy
72 + pdata = dev_get_platdata(&phydev->mdio.dev);
74 + if (pdata->disable_smarteee)
75 + at803x_disable_smarteee(phydev);
77 + if (pdata->enable_rgmii_rx_delay)
78 + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0,
79 + AT803X_DEBUG_RX_CLK_DLY_EN);
81 + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0,
82 + AT803X_DEBUG_RX_CLK_DLY_EN, 0);
84 + if (pdata->enable_rgmii_tx_delay)
85 + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0,
86 + AT803X_DEBUG_TX_CLK_DLY_EN);
88 + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5,
89 + AT803X_DEBUG_TX_CLK_DLY_EN, 0);
95 @@ -335,6 +371,8 @@ static int at803x_config_intr(struct phy
96 static void at803x_link_change_notify(struct phy_device *phydev)
98 struct at803x_priv *priv = phydev->priv;
99 + struct at803x_platform_data *pdata;
100 + pdata = dev_get_platdata(&phydev->mdio.dev);
103 * Conduct a hardware reset for AT8030/2 every time a link loss is
104 @@ -363,6 +401,24 @@ static void at803x_link_change_notify(st
106 priv->phy_reset = false;
108 + if (pdata && pdata->fixup_rgmii_tx_delay &&
109 + phydev->speed != priv->prev_speed) {
110 + switch (phydev->speed) {
113 + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0,
114 + AT803X_DEBUG_TX_CLK_DLY_EN);
117 + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5,
118 + AT803X_DEBUG_TX_CLK_DLY_EN, 0);
124 + priv->prev_speed = phydev->speed;
128 static int at803x_aneg_done(struct phy_device *phydev)
130 +++ b/include/linux/platform_data/phy-at803x.h
132 +#ifndef _PHY_AT803X_PDATA_H
133 +#define _PHY_AT803X_PDATA_H
135 +struct at803x_platform_data {
136 + int disable_smarteee:1;
137 + int enable_rgmii_tx_delay:1;
138 + int enable_rgmii_rx_delay:1;
139 + int fixup_rgmii_tx_delay:1;
142 +#endif /* _PHY_AT803X_PDATA_H */