1 /* 2 * TI PHY drivers 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 * 6 */ 7 #include <common.h> 8 #include <phy.h> 9 #include <linux/compat.h> 10 #include <malloc.h> 11 12 #include <fdtdec.h> 13 #include <dm.h> 14 #include <dt-bindings/net/ti-dp83867.h> 15 16 DECLARE_GLOBAL_DATA_PTR; 17 18 /* TI DP83867 */ 19 #define DP83867_DEVADDR 0x1f 20 21 #define MII_DP83867_PHYCTRL 0x10 22 #define MII_DP83867_MICR 0x12 23 #define MII_DP83867_CFG2 0x14 24 #define MII_DP83867_BISCR 0x16 25 #define DP83867_CTRL 0x1f 26 27 /* Extended Registers */ 28 #define DP83867_RGMIICTL 0x0032 29 #define DP83867_RGMIIDCTL 0x0086 30 #define DP83867_IO_MUX_CFG 0x0170 31 32 #define DP83867_SW_RESET BIT(15) 33 #define DP83867_SW_RESTART BIT(14) 34 35 /* MICR Interrupt bits */ 36 #define MII_DP83867_MICR_AN_ERR_INT_EN BIT(15) 37 #define MII_DP83867_MICR_SPEED_CHNG_INT_EN BIT(14) 38 #define MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN BIT(13) 39 #define MII_DP83867_MICR_PAGE_RXD_INT_EN BIT(12) 40 #define MII_DP83867_MICR_AUTONEG_COMP_INT_EN BIT(11) 41 #define MII_DP83867_MICR_LINK_STS_CHNG_INT_EN BIT(10) 42 #define MII_DP83867_MICR_FALSE_CARRIER_INT_EN BIT(8) 43 #define MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN BIT(4) 44 #define MII_DP83867_MICR_WOL_INT_EN BIT(3) 45 #define MII_DP83867_MICR_XGMII_ERR_INT_EN BIT(2) 46 #define MII_DP83867_MICR_POL_CHNG_INT_EN BIT(1) 47 #define MII_DP83867_MICR_JABBER_INT_EN BIT(0) 48 49 /* RGMIICTL bits */ 50 #define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1) 51 #define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0) 52 53 /* PHY CTRL bits */ 54 #define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14 55 #define DP83867_MDI_CROSSOVER 5 56 #define DP83867_MDI_CROSSOVER_AUTO 2 57 #define DP83867_MDI_CROSSOVER_MDIX 2 58 #define DP83867_PHYCTRL_SGMIIEN 0x0800 59 #define DP83867_PHYCTRL_RXFIFO_SHIFT 12 60 #define DP83867_PHYCTRL_TXFIFO_SHIFT 14 61 62 /* RGMIIDCTL bits */ 63 #define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4 64 65 /* CFG2 bits */ 66 #define MII_DP83867_CFG2_SPEEDOPT_10EN 0x0040 67 #define MII_DP83867_CFG2_SGMII_AUTONEGEN 0x0080 68 #define MII_DP83867_CFG2_SPEEDOPT_ENH 0x0100 69 #define MII_DP83867_CFG2_SPEEDOPT_CNT 0x0800 70 #define MII_DP83867_CFG2_SPEEDOPT_INTLOW 0x2000 71 #define MII_DP83867_CFG2_MASK 0x003F 72 73 #define MII_MMD_CTRL 0x0d /* MMD Access Control Register */ 74 #define MII_MMD_DATA 0x0e /* MMD Access Data Register */ 75 76 /* MMD Access Control register fields */ 77 #define MII_MMD_CTRL_DEVAD_MASK 0x1f /* Mask MMD DEVAD*/ 78 #define MII_MMD_CTRL_ADDR 0x0000 /* Address */ 79 #define MII_MMD_CTRL_NOINCR 0x4000 /* no post increment */ 80 #define MII_MMD_CTRL_INCR_RDWT 0x8000 /* post increment on reads & writes */ 81 #define MII_MMD_CTRL_INCR_ON_WT 0xC000 /* post increment on writes only */ 82 83 /* User setting - can be taken from DTS */ 84 #define DEFAULT_RX_ID_DELAY DP83867_RGMIIDCTL_2_25_NS 85 #define DEFAULT_TX_ID_DELAY DP83867_RGMIIDCTL_2_75_NS 86 #define DEFAULT_FIFO_DEPTH DP83867_PHYCR_FIFO_DEPTH_4_B_NIB 87 88 /* IO_MUX_CFG bits */ 89 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL 0x1f 90 91 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0 92 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f 93 94 struct dp83867_private { 95 int rx_id_delay; 96 int tx_id_delay; 97 int fifo_depth; 98 int io_impedance; 99 }; 100 101 /** 102 * phy_read_mmd_indirect - reads data from the MMD registers 103 * @phydev: The PHY device bus 104 * @prtad: MMD Address 105 * @devad: MMD DEVAD 106 * @addr: PHY address on the MII bus 107 * 108 * Description: it reads data from the MMD registers (clause 22 to access to 109 * clause 45) of the specified phy address. 110 * To read these registers we have: 111 * 1) Write reg 13 // DEVAD 112 * 2) Write reg 14 // MMD Address 113 * 3) Write reg 13 // MMD Data Command for MMD DEVAD 114 * 3) Read reg 14 // Read MMD data 115 */ 116 int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, 117 int devad, int addr) 118 { 119 int value = -1; 120 121 /* Write the desired MMD Devad */ 122 phy_write(phydev, addr, MII_MMD_CTRL, devad); 123 124 /* Write the desired MMD register address */ 125 phy_write(phydev, addr, MII_MMD_DATA, prtad); 126 127 /* Select the Function : DATA with no post increment */ 128 phy_write(phydev, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR)); 129 130 /* Read the content of the MMD's selected register */ 131 value = phy_read(phydev, addr, MII_MMD_DATA); 132 return value; 133 } 134 135 /** 136 * phy_write_mmd_indirect - writes data to the MMD registers 137 * @phydev: The PHY device 138 * @prtad: MMD Address 139 * @devad: MMD DEVAD 140 * @addr: PHY address on the MII bus 141 * @data: data to write in the MMD register 142 * 143 * Description: Write data from the MMD registers of the specified 144 * phy address. 145 * To write these registers we have: 146 * 1) Write reg 13 // DEVAD 147 * 2) Write reg 14 // MMD Address 148 * 3) Write reg 13 // MMD Data Command for MMD DEVAD 149 * 3) Write reg 14 // Write MMD data 150 */ 151 void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, 152 int devad, int addr, u32 data) 153 { 154 /* Write the desired MMD Devad */ 155 phy_write(phydev, addr, MII_MMD_CTRL, devad); 156 157 /* Write the desired MMD register address */ 158 phy_write(phydev, addr, MII_MMD_DATA, prtad); 159 160 /* Select the Function : DATA with no post increment */ 161 phy_write(phydev, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR)); 162 163 /* Write the data into MMD's selected register */ 164 phy_write(phydev, addr, MII_MMD_DATA, data); 165 } 166 167 #if defined(CONFIG_DM_ETH) 168 /** 169 * dp83867_data_init - Convenience function for setting PHY specific data 170 * 171 * @phydev: the phy_device struct 172 */ 173 static int dp83867_of_init(struct phy_device *phydev) 174 { 175 struct dp83867_private *dp83867 = phydev->priv; 176 struct udevice *dev = phydev->dev; 177 int node = dev->of_offset; 178 const void *fdt = gd->fdt_blob; 179 180 if (fdtdec_get_bool(fdt, node, "ti,max-output-impedance")) 181 dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX; 182 else if (fdtdec_get_bool(fdt, node, "ti,min-output-impedance")) 183 dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN; 184 else 185 dp83867->io_impedance = -EINVAL; 186 187 dp83867->rx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), 188 "ti,rx-internal-delay", -1); 189 190 dp83867->tx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), 191 "ti,tx-internal-delay", -1); 192 193 dp83867->fifo_depth = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), 194 "ti,fifo-depth", -1); 195 196 return 0; 197 } 198 #else 199 static int dp83867_of_init(struct phy_device *phydev) 200 { 201 struct dp83867_private *dp83867 = phydev->priv; 202 203 dp83867->rx_id_delay = DEFAULT_RX_ID_DELAY; 204 dp83867->tx_id_delay = DEFAULT_TX_ID_DELAY; 205 dp83867->fifo_depth = DEFAULT_FIFO_DEPTH; 206 dp83867->io_impedance = -EINVAL; 207 208 return 0; 209 } 210 #endif 211 212 static int dp83867_config(struct phy_device *phydev) 213 { 214 struct dp83867_private *dp83867; 215 unsigned int val, delay, cfg2; 216 int ret; 217 218 if (!phydev->priv) { 219 dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL); 220 if (!dp83867) 221 return -ENOMEM; 222 223 phydev->priv = dp83867; 224 ret = dp83867_of_init(phydev); 225 if (ret) 226 goto err_out; 227 } else { 228 dp83867 = (struct dp83867_private *)phydev->priv; 229 } 230 231 /* Restart the PHY. */ 232 val = phy_read(phydev, MDIO_DEVAD_NONE, DP83867_CTRL); 233 phy_write(phydev, MDIO_DEVAD_NONE, DP83867_CTRL, 234 val | DP83867_SW_RESTART); 235 236 if (phy_interface_is_rgmii(phydev)) { 237 ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL, 238 (DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER) | 239 (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT)); 240 if (ret) 241 goto err_out; 242 } else if (phy_interface_is_sgmii(phydev)) { 243 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, 244 (BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000)); 245 246 cfg2 = phy_read(phydev, phydev->addr, MII_DP83867_CFG2); 247 cfg2 &= MII_DP83867_CFG2_MASK; 248 cfg2 |= (MII_DP83867_CFG2_SPEEDOPT_10EN | 249 MII_DP83867_CFG2_SGMII_AUTONEGEN | 250 MII_DP83867_CFG2_SPEEDOPT_ENH | 251 MII_DP83867_CFG2_SPEEDOPT_CNT | 252 MII_DP83867_CFG2_SPEEDOPT_INTLOW); 253 phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_CFG2, cfg2); 254 255 phy_write_mmd_indirect(phydev, DP83867_RGMIICTL, 256 DP83867_DEVADDR, phydev->addr, 0x0); 257 258 phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL, 259 DP83867_PHYCTRL_SGMIIEN | 260 (DP83867_MDI_CROSSOVER_MDIX << 261 DP83867_MDI_CROSSOVER) | 262 (dp83867->fifo_depth << DP83867_PHYCTRL_RXFIFO_SHIFT) | 263 (dp83867->fifo_depth << DP83867_PHYCTRL_TXFIFO_SHIFT)); 264 phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_BISCR, 0x0); 265 } 266 267 if (phy_interface_is_rgmii(phydev)) { 268 val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL, 269 DP83867_DEVADDR, phydev->addr); 270 271 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 272 val |= (DP83867_RGMII_TX_CLK_DELAY_EN | 273 DP83867_RGMII_RX_CLK_DELAY_EN); 274 275 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) 276 val |= DP83867_RGMII_TX_CLK_DELAY_EN; 277 278 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) 279 val |= DP83867_RGMII_RX_CLK_DELAY_EN; 280 281 phy_write_mmd_indirect(phydev, DP83867_RGMIICTL, 282 DP83867_DEVADDR, phydev->addr, val); 283 284 delay = (dp83867->rx_id_delay | 285 (dp83867->tx_id_delay << DP83867_RGMII_TX_CLK_DELAY_SHIFT)); 286 287 phy_write_mmd_indirect(phydev, DP83867_RGMIIDCTL, 288 DP83867_DEVADDR, phydev->addr, delay); 289 290 if (dp83867->io_impedance >= 0) { 291 val = phy_read_mmd_indirect(phydev, 292 DP83867_IO_MUX_CFG, 293 DP83867_DEVADDR, 294 phydev->addr); 295 val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; 296 val |= dp83867->io_impedance & 297 DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; 298 phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG, 299 DP83867_DEVADDR, phydev->addr, 300 val); 301 } 302 } 303 304 genphy_config_aneg(phydev); 305 return 0; 306 307 err_out: 308 kfree(dp83867); 309 return ret; 310 } 311 312 static struct phy_driver DP83867_driver = { 313 .name = "TI DP83867", 314 .uid = 0x2000a231, 315 .mask = 0xfffffff0, 316 .features = PHY_GBIT_FEATURES, 317 .config = &dp83867_config, 318 .startup = &genphy_startup, 319 .shutdown = &genphy_shutdown, 320 }; 321 322 int phy_ti_init(void) 323 { 324 phy_register(&DP83867_driver); 325 return 0; 326 } 327