`HI
I have ordered this chip for our project. I could find only the attached file in the website. But this file needs various other support files (.h files).
Can you please provide example code for interfacing this chip with microcontroller using RMII interface?
Kindly let me know for clarifications if any.
Thanks
Priya
CGit Gitweb gitprojects / ti-analog-linux-kernel / dmurphy-analog.git / blob commit ? search: re summary | shortlog | log | commit | commitdiff | tree history | raw | HEAD net: phy: dp83td510: Add support for the DP83td510 Ethernet PHY [ti-analog-linux-kernel/dmurphy-analog.git] / drivers / net / phy / dp83td510.c 1 // SPDX-License-Identifier: GPL-2.0 2 /* Driver for the Texas Instruments DP83TD510 PHY 3 * Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/ 4 */ 5 6 #include <linux/ethtool.h> 7 #include <linux/etherdevice.h> 8 #include <linux/kernel.h> 9 #include <linux/mii.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/phy.h> 13 #include <linux/netdevice.h> 14 15 #define DP83TD510E_PHY_ID 0x20000180 16 #define DP83TD510_DEVADDR_AN 0x7 17 #define DP83TD510_DEVADDR 0x1f 18 19 #define DP83TD510_MII_REG 0x0 20 #define DP83TD510_PHY_STAT 0x10 21 #define DP83TD510_GEN_CFG 0x11 22 #define DP83TD510_INT_REG1 0x12 23 #define DP83TD510_INT_REG2 0x13 24 #define DP83TD510_MAC_CFG_1 0x17 25 26 #define DP83TD510_SOR_1 0x467 27 28 #define DP83TD510_HW_RESET BIT(15) 29 #define DP83TD510_SW_RESET BIT(14) 30 31 /* GEN CFG bits */ 32 #define DP83TD510_INT_OE BIT(0) 33 #define DP83TD510_INT_EN BIT(1) 34 35 /* INT REG 1 bits */ 36 #define DP83TD510_INT1_ESD_EN BIT(3) 37 #define DP83TD510_INT1_LINK_EN BIT(5) 38 #define DP83TD510_INT1_RHF_EN BIT(7) 39 #define DP83TD510_INT1_ESD BIT(11) 40 #define DP83TD510_INT1_LINK BIT(13) 41 #define DP83TD510_INT1_RHF BIT(15) 42 43 /* INT REG 2 bits */ 44 #define DP83TD510_INT2_POR_EN BIT(0) 45 #define DP83TD510_INT2_POL_EN BIT(1) 46 #define DP83TD510_INT2_PAGE_EN BIT(5) 47 #define DP83TD510_INT2_POR BIT(8) 48 #define DP83TD510_INT2_POL BIT(9) 49 #define DP83TD510_INT2_PAGE BIT(13) 50 51 /* MAC CFG bits */ 52 #define DP83TD510_RX_CLK_SHIFT BIT(12) 53 #define DP83TD510_TX_CLK_SHIFT BIT(11) 54 55 #define DP83TD510_MASTER_MODE BIT(2) 56 #define DP83TD510_2_4V BIT(7) 57 #define DP83TD510_RGMII BIT(8) 58 59 #define DP83TD510_FIFO_DEPTH_MASK GENMASK(6, 5) 60 #define DP83TD510_FIFO_DEPTH_4_B_NIB 0 61 #define DP83TD510_FIFO_DEPTH_5_B_NIB BIT(5) 62 #define DP83TD510_FIFO_DEPTH_6_B_NIB BIT(6) 63 #define DP83TD510_FIFO_DEPTH_8_B_NIB (BIT(5) | BIT(6)) 64 65 enum dp83td510_mode_config { 66 DP83TD510_AUTO_NEG = 0, 67 DP83TD510_MASTER_1 = 1, 68 DP83TD510_MASTER_24 = 2, 69 DP83TD510_SLAVE_1 = 3, 70 DP83TD510_SLAVE_24 = 4, 71 }; 72 73 struct dp83td510_private { 74 u32 forced_mode; 75 u32 tx_fifo_depth; 76 u32 rgmii_delay; 77 bool is_rgmii; 78 }; 79 80 struct dp83td510_init_reg { 81 int reg; 82 int val; 83 }; 84 85 static struct dp83td510_init_reg dp83td510_master_1_0[] = { 86 { 0x000d, 0x0007 }, /* disable auto-neg */ 87 { 0x000e, 0x0200 }, 88 { 0x000d, 0x4007 }, 89 { 0x000e, 0x0000 }, 90 { 0x000d, 0x0001 }, /* force master mode */ 91 { 0x000e, 0x0834 }, 92 { 0x000d, 0x4001 }, 93 { 0x000e, 0x4000 }, 94 { 0x000d, 0x0001 }, /* force 1.0v swing */ 95 { 0x000e, 0x08f6 }, 96 { 0x000d, 0x4001 }, 97 { 0x000e, 0x0000 }, 98 { 0x0608, 0x003b }, /* disable_0_transition */ 99 { 0x0862, 0x39f8 }, /* AGC Gain during Autoneg */ 100 { 0x081a, 0x67c0 }, /* deq offset for 1V swing */ 101 { 0x081c, 0xfb62 }, /* deq offset for 2.4V swing */ 102 { 0x0830, 0x05a3 }, /* Enable energy lost fallback */ 103 { 0x0855, 0x1b55 }, /* MSE Threshold change */ 104 { 0x0831, 0x0403 }, /* energy detect threshold */ 105 { 0x0856, 0x1800 }, /* good1 MSE threshold change */ 106 { 0x0857, 0x8fa0 }, /* Enable fallback to phase 1 on watchdog trigger */ 107 { 0x0871, 0x000c }, /* TED input changed to slicer_in without FFE */ 108 { 0x0883, 0x022e }, /* Enable Rx Filter, Change PGA threshold for Short Cable detection */ 109 { 0x0402, 0x1800 }, /* Adjusr LD swing */ 110 { 0x0878, 0x2248 }, /* Change PI up/down polarity */ 111 { 0x010c, 0x0008 }, /* tx filter coefficient */ 112 { 0x0112, 0x1212 }, /* tx filter scaling factor */ 113 { 0x0809, 0x5c80 }, /* AGC retrain */ 114 { 0x0803, 0x1529 }, /* Master Ph1 Back-off */ 115 { 0x0804, 0x1a33 }, /* Master Ph1 Back-off */ 116 { 0x0805, 0x1f3d }, /* Master Ph1 Back-off */ 117 { 0x0850, 0x045b }, /* hybrid gain & delay */ 118 { 0x0874, 0x6967 }, /* kp step 0 for master */ 119 { 0x0852, 0x7800 }, /* FAGC init gain */ 120 { 0x0806, 0x1e1e }, /* Master/Slave Ph2 Back-off */ 121 { 0x0807, 0x2525 }, /* Master/Slave Ph2 Back-off */ 122 { 0x0808, 0x2c2c }, /* Master/Slave Ph2 Back-off */ 123 { 0x0850, 0x0590 }, /* Hybrid Gain/Delay Code */ 124 { 0x0827, 0x4000 }, /* Echo Fixed Delay */ 125 { 0x0849, 0x0fe4 }, /* Hybrid Cal enable */ 126 { 0x084b, 0x04b5 }, /* Echo Score Sel */ 127 { 0x0018, 0x0043 }, /* Set CRS/RX_DV pin as RX_DV for RMII repeater mode */ 128 }; 129 130 static struct dp83td510_init_reg dp83td510_slave_1_0[] = { 131 { 0x000d, 0x0007 }, /* disable auto-neg */ 132 { 0x000e, 0x0200 }, 133 { 0x000d, 0x4007 }, 134 { 0x000e, 0x0000 }, 135 { 0x000d, 0x0001 }, /* force slave mode */ 136 { 0x000e, 0x0834 }, 137 { 0x000d, 0x4001 }, 138 { 0x000e, 0x0000 }, 139 { 0x000d, 0x0001 }, /* force 1.0v swing */ 140 { 0x000d, 0x4001 }, 141 { 0x000e, 0x0000 }, 142 { 0x0608, 0x003b }, /* disable_0_transition */ 143 { 0x0862, 0x39f8 }, /* AGC Gain during Autoneg */ 144 { 0x081a, 0x67c0 }, /* deq offset for 1V swing */ 145 { 0x081c, 0xfb62 }, /* deq offset for 2.4V swing */ 146 { 0x0830, 0x05a3 }, /* Enable energy lost fallback */ 147 { 0x0855, 0x1b55 }, /* MSE Threshold change */ 148 { 0x0831, 0x0403 }, /* energy detect threshold */ 149 { 0x0856, 0x1800 }, /* good1 MSE threshold change */ 150 { 0x0857, 0x8fa0 }, /* Enable fallback to phase 1 on watchdog trigger */ 151 { 0x0871, 0x000c }, /* TED input changed to slicer_in without FFE */ 152 { 0x0883, 0x022e }, /* Enable Rx Filter, PGA threshold for Short Cable detection */ 153 { 0x0402, 0x1800 }, /* Adjusr LD swing */ 154 { 0x0878, 0x2248 }, /* Change PI up/down polarity */ 155 { 0x010c, 0x0008 }, /* tx filter coefficient */ 156 { 0x0112, 0x1212 }, /* tx filter scaling factor */ 157 { 0x0809, 0x5c80 }, /* AGC retrain */ 158 { 0x0803, 0x1529 }, /* Master Ph1 Back-off */ 159 { 0x0804, 0x1a33 }, /* Master Ph1 Back-off */ 160 { 0x0805, 0x1f3d }, /* Master Ph1 Back-off */ 161 { 0x0850, 0x045b }, /* hybrid gain & delay */ 162 { 0x0874, 0x6967 }, /* kp step 0 for master */ 163 { 0x0852, 0x7800 }, /* FAGC init gain */ 164 { 0x0806, 0x1e1e }, /* Master/Slave Ph2 Back-off */ 165 { 0x0807, 0x2525 }, /* Master/Slave Ph2 Back-off */ 166 { 0x0808, 0x2c2c }, /* Master/Slave Ph2 Back-off */ 167 { 0x0850, 0x0590 }, /* Hybrid Gain/Delay Code */ 168 { 0x0827, 0x4000 }, /* Echo Fixed Delay */ 169 { 0x0849, 0x0fe4 }, /* Hybrid Cal enable */ 170 { 0x084b, 0x04b5 }, /* Echo Score Sel */ 171 { 0x0018, 0x0043 }, /* Set CRS/RX_DV pin as RX_DV for RMII repeater mode */ 172 }; 173 174 static struct dp83td510_init_reg dp83td510_master_2_4[] = { 175 { 0x000d, 0x0007 }, /* disable auto-neg */ 176 { 0x000e, 0x0200 }, 177 { 0x000d, 0x4007 }, 178 { 0x000e, 0x0000 }, 179 { 0x000d, 0x0001 }, /* force Master mode */ 180 { 0x000e, 0x0834 }, 181 { 0x000d, 0x4001 }, 182 { 0x000e, 0x4000 }, 183 { 0x000d, 0x0001 }, /* force 2.4v swing */ 184 { 0x000e, 0x08f6 }, 185 { 0x000d, 0x4001 }, 186 { 0x000e, 0x1000 }, 187 { 0x0608, 0x003b }, /* disable_0_transition */ 188 { 0x0862, 0x39f8 }, /* AGC Gain during Autoneg */ 189 { 0x081a, 0x67c0 }, /* deq offset for 1V swing */ 190 { 0x081c, 0xfb62 }, /* deq offset for 2.4V swing */ 191 { 0x0830, 0x05a3 }, /* Enable energy lost fallback */ 192 { 0x0855, 0x1b55 }, /* MSE Threshold change */ 193 { 0x0831, 0x0403 }, /* energy detect threshold */ 194 { 0x0856, 0x1800 }, /* good1 MSE threshold change */ 195 { 0x0857, 0x8fa0 }, /* Enable fallback to phase 1 on watchdog trigger */ 196 { 0x0871, 0x000c }, /* TED input changed to slicer_in without FFE */ 197 { 0x0883, 0x022e }, /* Enable Rx Filter, Change PGA threshold for Short Cable detection */ 198 { 0x0402, 0x1800 }, /* Adjusr LD swing */ 199 { 0x0878, 0x2248 }, /* Change PI up/down polarity */ 200 { 0x010c, 0x0008 }, /* tx filter coefficient */ 201 { 0x0112, 0x1212 }, /* tx filter scaling factor */ 202 { 0x0809, 0x5c80 }, /* AGC retrain */ 203 { 0x0803, 0x1529 }, /* Master Ph1 Back-off */ 204 { 0x0804, 0x1a33 }, /* Master Ph1 Back-off */ 205 { 0x0805, 0x1f3d }, /* Master Ph1 Back-off */ 206 { 0x0850, 0x045b }, /* hybrid gain & delay */ 207 { 0x0874, 0x6967 }, /* kp step 0 for master */ 208 { 0x0852, 0x7800 }, /* FAGC init gain */ 209 { 0x0806, 0x1e1e }, /* Master/Slave Ph2 Back-off */ 210 { 0x0807, 0x2525 }, /* Master/Slave Ph2 Back-off */ 211 { 0x0808, 0x2c2c }, /* Master/Slave Ph2 Back-off */ 212 { 0x0850, 0x0590 }, /* Hybrid Gain/Delay Code */ 213 { 0x0827, 0x4000 }, /* Echo Fixed Delay */ 214 { 0x0849, 0x0fe4 }, /* Hybrid Cal enable */ 215 { 0x084b, 0x04b5 }, /* Echo Score Sel */ 216 { 0x0018, 0x0043 }, /* Set CRS/RX_DV pin as RX_DV for RMII repeater mode */ 217 }; 218 219 static struct dp83td510_init_reg dp83td510_slave_2_4[] = { 220 { 0x000d, 0x0007}, /* disable auto-neg */ 221 { 0x000e, 0x0200}, 222 { 0x000d, 0x4007}, 223 { 0x000e, 0x0000}, 224 { 0x000d, 0x0001}, /* force slave mode */ 225 { 0x000e, 0x0834}, 226 { 0x000d, 0x4001}, 227 { 0x000e, 0x0000}, 228 { 0x000d, 0x0001}, /* force 2.4v swing */ 229 { 0x000e, 0x08f6}, 230 { 0x000d, 0x4001}, 231 { 0x000e, 0x1000}, 232 { 0x0608, 0x003b}, /* disable_0_transition */ 233 { 0x0862, 0x39f8}, /* AGC Gain during Autoneg */ 234 { 0x081a, 0x67c0}, /* deq offset for 1V swing */ 235 { 0x081c, 0xfb62}, /* deq offset for 2.4V swing */ 236 { 0x0830, 0x05a3}, /* Enable energy lost fallback */ 237 { 0x0855, 0x1b55}, /* MSE Threshold change */ 238 { 0x0831, 0x0403}, /* energy detect threshold */ 239 { 0x0856, 0x1800}, /* good1 MSE threshold change */ 240 { 0x0857, 0x8fa0}, /* Enable fallback to phase 1 on watchdog trigger */ 241 { 0x0871, 0x000c}, /* TED input changed to slicer_in without FFE */ 242 { 0x0883, 0x022e}, /* Enable Rx Filter, Change PGA threshold for Short Cable detection */ 243 { 0x0402, 0x1800}, /* Adjusr LD swing */ 244 { 0x0878, 0x2248}, /* Change PI up/down polarity */ 245 { 0x010c, 0x0008}, /* tx filter coefficient */ 246 { 0x0112, 0x1212}, /* tx filter scaling factor */ 247 { 0x0809, 0x5c80}, /* AGC retrain */ 248 { 0x0803, 0x1529}, /* Master Ph1 Back-off */ 249 { 0x0804, 0x1a33}, /* Master Ph1 Back-off */ 250 { 0x0805, 0x1f3d}, /* Master Ph1 Back-off */ 251 { 0x0850, 0x045b}, /* hybrid gain & delay */ 252 { 0x0874, 0x6967}, /* kp step 0 for master */ 253 { 0x0852, 0x7800}, /* FAGC init gain */ 254 { 0x0806, 0x1e1e}, /* Master/Slave Ph2 Back-off */ 255 { 0x0807, 0x2525}, /* Master/Slave Ph2 Back-off */ 256 { 0x0808, 0x2c2c}, /* Master/Slave Ph2 Back-off */ 257 { 0x0850, 0x0590}, /* Hybrid Gain/Delay Code */ 258 { 0x0827, 0x4000}, /* Echo Fixed Delay */ 259 { 0x0849, 0x0fe4}, /* Hybrid Cal enable */ 260 { 0x084b, 0x04b5}, /* Echo Score Sel */ 261 { 0x0018, 0x0043}, /* Set CRS/RX_DV pin as RX_DV for RMII repeater mode */ 262 }; 263 264 static struct dp83td510_init_reg dp83td510_auto_neg[] = { 265 { 0x608, 0x003b }, /* disable_0_transition */ 266 { 0x862, 0x39f8 }, /* AGC Gain during Autoneg */ 267 { 0x81a, 0x67c0 }, /* deq offset for 1V swing */ 268 { 0x81c, 0xfb62 }, /* deq offset for 2.4V swing */ 269 { 0x830, 0x05a3 }, /* Enable energy lost fallback */ 270 { 0x855, 0x1b55 }, /* MSE Threshold change */ 271 { 0x831, 0x0403 }, /* energy detect threshold */ 272 { 0x856, 0x1800 }, /* good1 MSE threshold change */ 273 { 0x857, 0x8fa0 }, /* Enable fallback to phase 1 on watchdog trigger */ 274 { 0x871, 0x000c }, /* TED input changed to slicer_in without FFE */ 275 { 0x883, 0x022e }, /* Enable Rx Filter Change PGA threshold for Short Cable detection */ 276 { 0x402, 0x1800 }, /* Adjusr LD swing */ 277 { 0x878, 0x2248 }, /* Change PI up/down polarity */ 278 { 0x10c, 0x0008 }, /* tx filter coefficient */ 279 { 0x112, 0x1212 }, /* tx filter scaling factor */ 280 { 0x809, 0x5c80 }, /* AGC retrain */ 281 { 0x803, 0x1529 }, /* Master Ph1 Back-off */ 282 { 0x804, 0x1a33 }, /* Master Ph1 Back-off */ 283 { 0x805, 0x1f3d }, /* Master Ph1 Back-off */ 284 { 0x850, 0x045b }, /* hybrid gain & delay */ 285 { 0x874, 0x6967 }, /* kp step 0 for master */ 286 { 0x852, 0x7800 }, /* FAGC init gain */ 287 { 0x806, 0x1e1e }, /* Master/Slave Ph2 Back-off */ 288 { 0x807, 0x2525 }, /* Master/Slave Ph2 Back-off */ 289 { 0x808, 0x2c2c }, /* Master/Slave Ph2 Back-off */ 290 { 0x850, 0x0590 }, /* Hybrid Gain/Delay Code */ 291 { 0x827, 0x4000 }, /* Echo Fixed Delay */ 292 { 0x849, 0x0fe4 }, /* Hybrid Cal enable */ 293 { 0x84b, 0x04b5 }, /* Echo Score Sel */ 294 { 0x018, 0x0043 }, /* Set CRS/RX_DV pin as RX_DV for RMII repeater mode */ 295 }; 296 297 static int dp83td510_ack_interrupt(struct phy_device *phydev) 298 { 299 int ret; 300 301 ret = phy_read(phydev, DP83TD510_INT_REG1); 302 if (ret < 0) 303 return ret; 304 305 ret = phy_read(phydev, DP83TD510_INT_REG2); 306 if (ret < 0) 307 return ret; 308 309 return 0; 310 } 311 312 static int dp83td510_config_intr(struct phy_device *phydev) 313 { 314 int int_status; 315 int gen_cfg_val; 316 int ret; 317 318 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 319 int_status = phy_read(phydev, DP83TD510_INT_REG1); 320 if (int_status < 0) 321 return int_status; 322 323 int_status = (DP83TD510_INT1_ESD_EN | DP83TD510_INT1_LINK_EN | 324 DP83TD510_INT1_RHF_EN); 325 326 ret = phy_write(phydev, DP83TD510_INT_REG1, int_status); 327 if (ret) 328 return ret; 329 330 int_status = phy_read(phydev, DP83TD510_INT_REG2); 331 if (int_status < 0) 332 return int_status; 333 334 int_status = (DP83TD510_INT2_POR | DP83TD510_INT2_POL | 335 DP83TD510_INT2_PAGE); 336 337 ret = phy_write(phydev, DP83TD510_INT_REG2, int_status); 338 if (ret) 339 return ret; 340 341 gen_cfg_val = phy_read(phydev, DP83TD510_GEN_CFG); 342 if (gen_cfg_val < 0) 343 return gen_cfg_val; 344 345 gen_cfg_val |= DP83TD510_INT_OE | DP83TD510_INT_EN; 346 347 } else { 348 ret = phy_write(phydev, DP83TD510_INT_REG1, 0); 349 if (ret) 350 return ret; 351 352 ret = phy_write(phydev, DP83TD510_INT_REG2, 0); 353 if (ret) 354 return ret; 355 356 gen_cfg_val = phy_read(phydev, DP83TD510_GEN_CFG); 357 if (gen_cfg_val < 0) 358 return gen_cfg_val; 359 360 gen_cfg_val &= ~DP83TD510_INT_EN; 361 } 362 363 return phy_write(phydev, DP83TD510_GEN_CFG, gen_cfg_val); 364 } 365 366 static int dp83td510_configure_mode(struct phy_device *phydev) 367 { 368 struct dp83td510_private *dp83td510 = phydev->priv; 369 struct dp83td510_init_reg *init_data; 370 int size; 371 int ret; 372 int i; 373 374 ret = phy_set_bits(phydev, DP83TD510_MII_REG, DP83TD510_HW_RESET); 375 if (ret < 0) 376 return ret; 377 378 switch (dp83td510->forced_mode) { 379 case DP83TD510_MASTER_1: 380 size = ARRAY_SIZE(dp83td510_master_1_0); 381 init_data = dp83td510_master_1_0; 382 break; 383 case DP83TD510_MASTER_24: 384 size = ARRAY_SIZE(dp83td510_master_2_4); 385 init_data = dp83td510_master_2_4; 386 break; 387 case DP83TD510_SLAVE_1: 388 size = ARRAY_SIZE(dp83td510_slave_1_0); 389 init_data = dp83td510_slave_1_0; 390 break; 391 case DP83TD510_SLAVE_24: 392 size = ARRAY_SIZE(dp83td510_slave_2_4); 393 init_data = dp83td510_slave_2_4; 394 break; 395 case DP83TD510_AUTO_NEG: 396 default: 397 size = ARRAY_SIZE(dp83td510_auto_neg); 398 init_data = dp83td510_auto_neg; 399 break; 400 }; 401 402 for (i = 0; i < size; i++) { 403 ret = phy_write_mmd(phydev, DP83TD510_DEVADDR, init_data[i].reg, 404 init_data[i].val); 405 if (ret) 406 return ret; 407 } 408 409 return phy_set_bits(phydev, DP83TD510_MII_REG, DP83TD510_SW_RESET); 410 } 411 412 static int dp83td510_config_init(struct phy_device *phydev) 413 { 414 struct dp83td510_private *dp83td510 = phydev->priv; 415 int ret = 0; 416 417 if (phy_interface_is_rgmii(phydev)) { 418 if (dp83td510->rgmii_delay) { 419 ret = phy_set_bits_mmd(phydev, DP83TD510_DEVADDR, 420 DP83TD510_MAC_CFG_1, dp83td510->rgmii_delay); 421 if (ret) 422 return ret; 423 } 424 } 425 426 if (phydev->interface == PHY_INTERFACE_MODE_RMII) 427 ret = phy_modify(phydev, DP83TD510_GEN_CFG, 428 DP83TD510_FIFO_DEPTH_MASK, 429 dp83td510->tx_fifo_depth); 430 431 linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->advertising); 432 linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->supported); 433 linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->advertising); 434 linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported); 435 linkmode_clear_bit(ETHTOOL_LINK_MODE_MII_BIT, phydev->advertising); 436 linkmode_clear_bit(ETHTOOL_LINK_MODE_MII_BIT, phydev->supported); 437 438 return dp83td510_configure_mode(phydev); 439 } 440 441 static int dp83td510_phy_reset(struct phy_device *phydev) 442 { 443 int ret; 444 445 ret = phy_set_bits(phydev, DP83TD510_MII_REG, DP83TD510_SW_RESET); 446 if (ret < 0) 447 return ret; 448 449 usleep_range(10, 20); 450 451 return dp83td510_config_init(phydev); 452 } 453 454 static int dp83td510_read_straps(struct phy_device *phydev) 455 { 456 struct dp83td510_private *dp83td510 = phydev->priv; 457 int strap; 458 459 strap = phy_read_mmd(phydev, DP83TD510_DEVADDR, DP83TD510_SOR_1); 460 if (strap < 0) 461 return strap; 462 463 if (strap & DP83TD510_RGMII) 464 dp83td510->is_rgmii = true; 465 466 return 0; 467 }; 468 469 #if IS_ENABLED(CONFIG_OF_MDIO) 470 static int dp83td510_of_init(struct phy_device *phydev) 471 { 472 struct dp83td510_private *dp83td510 = phydev->priv; 473 struct device *dev = &phydev->mdio.dev; 474 struct device_node *of_node = dev->of_node; 475 s32 rx_int_delay; 476 s32 tx_int_delay; 477 int ret; 478 479 if (!of_node) 480 return -ENODEV; 481 482 ret = dp83td510_read_straps(phydev); 483 if (ret) 484 return ret; 485 486 ret = device_property_read_u32(&phydev->mdio.dev, "ti,master-slave-mode", 487 &dp83td510->forced_mode); 488 if (ret) 489 dp83td510->forced_mode = DP83TD510_AUTO_NEG; 490 491 if (dp83td510->forced_mode < DP83TD510_AUTO_NEG || 492 dp83td510->forced_mode > DP83TD510_SLAVE_24) 493 return -EINVAL; 494 495 if (device_property_read_u32(&phydev->mdio.dev, "tx-fifo-depth", 496 &dp83td510->tx_fifo_depth)) 497 dp83td510->tx_fifo_depth = DP83TD510_FIFO_DEPTH_5_B_NIB; 498 499 switch (dp83td510->tx_fifo_depth) { 500 case 4: 501 dp83td510->tx_fifo_depth = DP83TD510_FIFO_DEPTH_4_B_NIB; 502 break; 503 case 5: 504 dp83td510->tx_fifo_depth = DP83TD510_FIFO_DEPTH_5_B_NIB; 505 break; 506 case 6: 507 dp83td510->tx_fifo_depth = DP83TD510_FIFO_DEPTH_6_B_NIB; 508 break; 509 case 8: 510 dp83td510->tx_fifo_depth = DP83TD510_FIFO_DEPTH_8_B_NIB; 511 break; 512 default: 513 return -EINVAL; 514 } 515 516 rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0, true); 517 if (rx_int_delay <= 0) 518 dp83td510->rgmii_delay = DP83TD510_RX_CLK_SHIFT; 519 else 520 dp83td510->rgmii_delay = 0; 521 522 tx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0, false); 523 if (tx_int_delay <= 0) 524 dp83td510->rgmii_delay |= DP83TD510_TX_CLK_SHIFT; 525 else 526 dp83td510->rgmii_delay &= ~DP83TD510_TX_CLK_SHIFT; 527 528 return ret; 529 } 530 #else 531 static int dp83869_of_init(struct phy_device *phydev) 532 { 533 return dp83td510_read_straps(phydev); 534 } 535 #endif /* CONFIG_OF_MDIO */ 536 537 static int dp83td510_probe(struct phy_device *phydev) 538 { 539 struct dp83td510_private *dp83td510; 540 int ret; 541 542 dp83td510 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83td510), GFP_KERNEL); 543 if (!dp83td510) 544 return -ENOMEM; 545 546 phydev->priv = dp83td510; 547 548 ret = dp83td510_of_init(phydev); 549 if (ret) 550 return ret; 551 552 return dp83td510_config_init(phydev); 553 } 554 555 static struct phy_driver dp83td510_driver[] = { 556 { 557 PHY_ID_MATCH_MODEL(DP83TD510E_PHY_ID), 558 .name = "TI DP83TD510E", 559 .probe = dp83td510_probe, 560 .config_init = dp83td510_config_init, 561 .soft_reset = dp83td510_phy_reset, 562 .features = PHY_BASIC_FEATURES, 563 564 /* IRQ related */ 565 .ack_interrupt = dp83td510_ack_interrupt, 566 .config_intr = dp83td510_config_intr, 567 568 .suspend = genphy_suspend, 569 .resume = genphy_resume, 570 }, 571 }; 572 module_phy_driver(dp83td510_driver); 573 574 static struct mdio_device_id __maybe_unused dp83td510_tbl[] = { 575 { PHY_ID_MATCH_MODEL(DP83TD510E_PHY_ID) }, 576 { } 577 }; 578 MODULE_DEVICE_TABLE(mdio, dp83td510_tbl); 579 580 MODULE_DESCRIPTION("Texas Instruments DP83TD510E PHY driver"); 581 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com"); 582 MODULE_LICENSE("GPL v2"); 583 Repository for all dmurphy work for analog device drivers.RSSAtom © Copyright 1995-2020 Texas Instruments Incorporated. All rights reserved. Trademarks | Privacy policy | Terms of use | Terms of sale