.. | .. |
---|
16 | 16 | #include <linux/mfd/core.h> |
---|
17 | 17 | #include <linux/mii.h> |
---|
18 | 18 | #include <linux/netdevice.h> |
---|
| 19 | +#include <linux/nvmem-consumer.h> |
---|
19 | 20 | #include <linux/of_irq.h> |
---|
20 | 21 | #include <linux/phy.h> |
---|
21 | 22 | #include <linux/platform_device.h> |
---|
.. | .. |
---|
24 | 25 | #define RK630_PHY_ID 0x00441400 |
---|
25 | 26 | |
---|
26 | 27 | /* PAGE 0 */ |
---|
| 28 | +#define REG_MMD_ACCESS_CONTROL 0x0d |
---|
| 29 | +#define REG_MMD_ACCESS_DATA_ADDRESS 0x0e |
---|
27 | 30 | #define REG_INTERRUPT_STATUS 0X10 |
---|
28 | 31 | #define REG_INTERRUPT_MASK 0X11 |
---|
29 | 32 | #define REG_GLOBAL_CONFIGURATION 0X13 |
---|
.. | .. |
---|
50 | 53 | #define REG_PAGE6_CP_CURRENT 0x17 |
---|
51 | 54 | #define REG_PAGE6_ADC_OP_BIAS 0x18 |
---|
52 | 55 | #define REG_PAGE6_RX_DECTOR 0x19 |
---|
| 56 | +#define REG_PAGE6_TX_MOS_DRV 0x1B |
---|
53 | 57 | #define REG_PAGE6_AFE_PDCW 0x1c |
---|
54 | 58 | |
---|
55 | 59 | /* PAGE 8 */ |
---|
.. | .. |
---|
61 | 65 | * Addr: 1 --- RK630@S40 |
---|
62 | 66 | * 2 --- RV1106@T22 |
---|
63 | 67 | */ |
---|
64 | | -#define PHY_ADDR_S40 1 |
---|
65 | | -#define PHY_ADDR_T22 2 |
---|
| 68 | +#define PHY_ADDR_S40 1 |
---|
| 69 | +#define PHY_ADDR_T22 2 |
---|
| 70 | + |
---|
| 71 | +#define T22_TX_LEVEL_100M 0x2d |
---|
| 72 | +#define T22_TX_LEVEL_10M 0x32 |
---|
66 | 73 | |
---|
67 | 74 | struct rk630_phy_priv { |
---|
68 | 75 | struct phy_device *phydev; |
---|
69 | 76 | bool ieee; |
---|
70 | 77 | int wol_irq; |
---|
71 | 78 | struct wake_lock wol_wake_lock; |
---|
| 79 | + int tx_level_100M; |
---|
| 80 | + int tx_level_10M; |
---|
72 | 81 | }; |
---|
| 82 | + |
---|
| 83 | +static void rk630_phy_t22_get_tx_level_from_efuse(struct phy_device *phydev) |
---|
| 84 | +{ |
---|
| 85 | + struct rk630_phy_priv *priv = phydev->priv; |
---|
| 86 | + unsigned int tx_level_100M = T22_TX_LEVEL_100M; |
---|
| 87 | + unsigned int tx_level_10M = T22_TX_LEVEL_10M; |
---|
| 88 | + unsigned char *efuse_buf; |
---|
| 89 | + struct nvmem_cell *cell; |
---|
| 90 | + size_t len; |
---|
| 91 | + |
---|
| 92 | + cell = nvmem_cell_get(&phydev->mdio.dev, "txlevel"); |
---|
| 93 | + if (IS_ERR(cell)) { |
---|
| 94 | + phydev_err(phydev, "failed to get txlevel cell: %ld, use default\n", |
---|
| 95 | + PTR_ERR(cell)); |
---|
| 96 | + } else { |
---|
| 97 | + efuse_buf = nvmem_cell_read(cell, &len); |
---|
| 98 | + nvmem_cell_put(cell); |
---|
| 99 | + if (!IS_ERR(efuse_buf)) { |
---|
| 100 | + if (len == 2 && efuse_buf[0] > 0 && efuse_buf[1] > 0) { |
---|
| 101 | + tx_level_100M = efuse_buf[1]; |
---|
| 102 | + tx_level_10M = efuse_buf[0]; |
---|
| 103 | + } |
---|
| 104 | + kfree(efuse_buf); |
---|
| 105 | + } else { |
---|
| 106 | + phydev_err(phydev, "failed to get efuse buf, use default\n"); |
---|
| 107 | + } |
---|
| 108 | + } |
---|
| 109 | + |
---|
| 110 | + priv->tx_level_100M = tx_level_100M; |
---|
| 111 | + priv->tx_level_10M = tx_level_10M; |
---|
| 112 | +} |
---|
73 | 113 | |
---|
74 | 114 | static void rk630_phy_wol_enable(struct phy_device *phydev) |
---|
75 | 115 | { |
---|
.. | .. |
---|
164 | 204 | |
---|
165 | 205 | static void rk630_phy_t22_config_init(struct phy_device *phydev) |
---|
166 | 206 | { |
---|
| 207 | + struct rk630_phy_priv *priv = phydev->priv; |
---|
| 208 | + |
---|
167 | 209 | /* Switch to page 1 */ |
---|
168 | 210 | phy_write(phydev, REG_PAGE_SEL, 0x0100); |
---|
169 | 211 | /* Disable APS */ |
---|
.. | .. |
---|
180 | 222 | phy_write(phydev, REG_PAGE6_GAIN_ANONTROL, 0x0400); |
---|
181 | 223 | /* PHYAFE EQ optimization */ |
---|
182 | 224 | phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, 0x1088); |
---|
| 225 | + |
---|
| 226 | + if (priv->tx_level_100M <= 0 || priv->tx_level_10M <= 0) |
---|
| 227 | + rk630_phy_t22_get_tx_level_from_efuse(phydev); |
---|
| 228 | + |
---|
183 | 229 | /* PHYAFE TX optimization */ |
---|
184 | | - phy_write(phydev, REG_PAGE6_AFE_DRIVER2, 0x3030); |
---|
| 230 | + phy_write(phydev, REG_PAGE6_AFE_DRIVER2, |
---|
| 231 | + (priv->tx_level_100M << 8) | priv->tx_level_10M); |
---|
185 | 232 | /* PHYAFE CP current optimization */ |
---|
186 | 233 | phy_write(phydev, REG_PAGE6_CP_CURRENT, 0x0575); |
---|
187 | 234 | /* ADC OP BIAS optimization */ |
---|
.. | .. |
---|
190 | 237 | phy_write(phydev, REG_PAGE6_RX_DECTOR, 0x0408); |
---|
191 | 238 | /* PHYAFE PDCW optimization */ |
---|
192 | 239 | phy_write(phydev, REG_PAGE6_AFE_PDCW, 0x8880); |
---|
| 240 | + /* Add PHY Tx mos drive, reduce power noise/jitter */ |
---|
| 241 | + phy_write(phydev, REG_PAGE6_TX_MOS_DRV, 0x888e); |
---|
193 | 242 | |
---|
194 | 243 | /* Switch to page 8 */ |
---|
195 | 244 | phy_write(phydev, REG_PAGE_SEL, 0x0800); |
---|
.. | .. |
---|
198 | 247 | |
---|
199 | 248 | /* Switch to page 0 */ |
---|
200 | 249 | phy_write(phydev, REG_PAGE_SEL, 0x0000); |
---|
| 250 | + |
---|
| 251 | + /* Disable eee mode advertised */ |
---|
| 252 | + phy_write(phydev, REG_MMD_ACCESS_CONTROL, 0x0007); |
---|
| 253 | + phy_write(phydev, REG_MMD_ACCESS_DATA_ADDRESS, 0x003c); |
---|
| 254 | + phy_write(phydev, REG_MMD_ACCESS_CONTROL, 0x4007); |
---|
| 255 | + phy_write(phydev, REG_MMD_ACCESS_DATA_ADDRESS, 0x0000); |
---|
201 | 256 | } |
---|
202 | 257 | |
---|
203 | 258 | static int rk630_phy_config_init(struct phy_device *phydev) |
---|
.. | .. |
---|
205 | 260 | switch (phydev->mdio.addr) { |
---|
206 | 261 | case PHY_ADDR_S40: |
---|
207 | 262 | rk630_phy_s40_config_init(phydev); |
---|
| 263 | + /* |
---|
| 264 | + * Ultra Auto-Power Saving Mode (UAPS) is designed to |
---|
| 265 | + * save power when cable is not plugged into PHY. |
---|
| 266 | + */ |
---|
| 267 | + rk630_phy_set_uaps(phydev); |
---|
208 | 268 | break; |
---|
209 | 269 | case PHY_ADDR_T22: |
---|
210 | 270 | rk630_phy_t22_config_init(phydev); |
---|
.. | .. |
---|
216 | 276 | } |
---|
217 | 277 | |
---|
218 | 278 | rk630_phy_ieee_set(phydev, true); |
---|
219 | | - /* |
---|
220 | | - * Ultra Auto-Power Saving Mode (UAPS) is designed to |
---|
221 | | - * save power when cable is not plugged into PHY. |
---|
222 | | - */ |
---|
223 | | - rk630_phy_set_uaps(phydev); |
---|
224 | 279 | |
---|
225 | 280 | return 0; |
---|
226 | 281 | } |
---|