1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 2 /* Copyright 2019 NXP */ 3 4 #include <linux/fsl/enetc_mdio.h> 5 #include <linux/mdio.h> 6 #include <linux/of_mdio.h> 7 #include <linux/iopoll.h> 8 #include <linux/of.h> 9 10 #include "enetc_pf.h" 11 12 #define ENETC_MDIO_CFG 0x0 /* MDIO configuration and status */ 13 #define ENETC_MDIO_CTL 0x4 /* MDIO control */ 14 #define ENETC_MDIO_DATA 0x8 /* MDIO data */ 15 #define ENETC_MDIO_ADDR 0xc /* MDIO address */ 16 17 static inline u32 _enetc_mdio_rd(struct enetc_mdio_priv *mdio_priv, int off) 18 { 19 return enetc_port_rd(mdio_priv->hw, mdio_priv->mdio_base + off); 20 } 21 22 static inline void _enetc_mdio_wr(struct enetc_mdio_priv *mdio_priv, int off, 23 u32 val) 24 { 25 enetc_port_wr(mdio_priv->hw, mdio_priv->mdio_base + off, val); 26 } 27 28 #define enetc_mdio_rd(mdio_priv, off) \ 29 _enetc_mdio_rd(mdio_priv, ENETC_##off) 30 #define enetc_mdio_wr(mdio_priv, off, val) \ 31 _enetc_mdio_wr(mdio_priv, ENETC_##off, val) 32 #define enetc_mdio_rd_reg(off) enetc_mdio_rd(mdio_priv, off) 33 34 #define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8) 35 #define MDIO_CFG_BSY BIT(0) 36 #define MDIO_CFG_RD_ER BIT(1) 37 #define MDIO_CFG_HOLD(x) (((x) << 2) & GENMASK(4, 2)) 38 #define MDIO_CFG_ENC45 BIT(6) 39 /* external MDIO only - driven on neg MDC edge */ 40 #define MDIO_CFG_NEG BIT(23) 41 42 #define ENETC_EMDIO_CFG \ 43 (MDIO_CFG_HOLD(2) | \ 44 MDIO_CFG_CLKDIV(258) | \ 45 MDIO_CFG_NEG) 46 47 #define MDIO_CTL_DEV_ADDR(x) ((x) & 0x1f) 48 #define MDIO_CTL_PORT_ADDR(x) (((x) & 0x1f) << 5) 49 #define MDIO_CTL_READ BIT(15) 50 #define MDIO_DATA(x) ((x) & 0xffff) 51 52 #define TIMEOUT 1000 53 static int enetc_mdio_wait_complete(struct enetc_mdio_priv *mdio_priv) 54 { 55 u32 val; 56 57 return readx_poll_timeout(enetc_mdio_rd_reg, MDIO_CFG, val, 58 !(val & MDIO_CFG_BSY), 10, 10 * TIMEOUT); 59 } 60 61 int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value) 62 { 63 struct enetc_mdio_priv *mdio_priv = bus->priv; 64 u32 mdio_ctl, mdio_cfg; 65 u16 dev_addr; 66 int ret; 67 68 mdio_cfg = ENETC_EMDIO_CFG; 69 if (regnum & MII_ADDR_C45) { 70 dev_addr = (regnum >> 16) & 0x1f; 71 mdio_cfg |= MDIO_CFG_ENC45; 72 } else { 73 /* clause 22 (ie 1G) */ 74 dev_addr = regnum & 0x1f; 75 mdio_cfg &= ~MDIO_CFG_ENC45; 76 } 77 78 enetc_mdio_wr(mdio_priv, MDIO_CFG, mdio_cfg); 79 80 ret = enetc_mdio_wait_complete(mdio_priv); 81 if (ret) 82 return ret; 83 84 /* set port and dev addr */ 85 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); 86 enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl); 87 88 /* set the register address */ 89 if (regnum & MII_ADDR_C45) { 90 enetc_mdio_wr(mdio_priv, MDIO_ADDR, regnum & 0xffff); 91 92 ret = enetc_mdio_wait_complete(mdio_priv); 93 if (ret) 94 return ret; 95 } 96 97 /* write the value */ 98 enetc_mdio_wr(mdio_priv, MDIO_DATA, MDIO_DATA(value)); 99 100 ret = enetc_mdio_wait_complete(mdio_priv); 101 if (ret) 102 return ret; 103 104 return 0; 105 } 106 EXPORT_SYMBOL_GPL(enetc_mdio_write); 107 108 int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) 109 { 110 struct enetc_mdio_priv *mdio_priv = bus->priv; 111 u32 mdio_ctl, mdio_cfg; 112 u16 dev_addr, value; 113 int ret; 114 115 mdio_cfg = ENETC_EMDIO_CFG; 116 if (regnum & MII_ADDR_C45) { 117 dev_addr = (regnum >> 16) & 0x1f; 118 mdio_cfg |= MDIO_CFG_ENC45; 119 } else { 120 dev_addr = regnum & 0x1f; 121 mdio_cfg &= ~MDIO_CFG_ENC45; 122 } 123 124 enetc_mdio_wr(mdio_priv, MDIO_CFG, mdio_cfg); 125 126 ret = enetc_mdio_wait_complete(mdio_priv); 127 if (ret) 128 return ret; 129 130 /* set port and device addr */ 131 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); 132 enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl); 133 134 /* set the register address */ 135 if (regnum & MII_ADDR_C45) { 136 enetc_mdio_wr(mdio_priv, MDIO_ADDR, regnum & 0xffff); 137 138 ret = enetc_mdio_wait_complete(mdio_priv); 139 if (ret) 140 return ret; 141 } 142 143 /* initiate the read */ 144 enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl | MDIO_CTL_READ); 145 146 ret = enetc_mdio_wait_complete(mdio_priv); 147 if (ret) 148 return ret; 149 150 /* return all Fs if nothing was there */ 151 if (enetc_mdio_rd(mdio_priv, MDIO_CFG) & MDIO_CFG_RD_ER) { 152 dev_dbg(&bus->dev, 153 "Error while reading PHY%d reg at %d.%hhu\n", 154 phy_id, dev_addr, regnum); 155 return 0xffff; 156 } 157 158 value = enetc_mdio_rd(mdio_priv, MDIO_DATA) & 0xffff; 159 160 return value; 161 } 162 EXPORT_SYMBOL_GPL(enetc_mdio_read); 163 164 struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs) 165 { 166 struct enetc_hw *hw; 167 168 hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); 169 if (!hw) 170 return ERR_PTR(-ENOMEM); 171 172 hw->port = port_regs; 173 174 return hw; 175 } 176 EXPORT_SYMBOL_GPL(enetc_hw_alloc); 177