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