This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DP83TD510E: Example code for this chip with RMII interface

Part Number: DP83TD510E

`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


DP83TD510.c
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