1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 /* Copyright 2019 NXP */
4 #include <linux/fsl/enetc_mdio.h>
5 #include <linux/mdio.h>
6 #include <linux/of_mdio.h>
7 #include <linux/iopoll.h>
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 */
17 #define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8)
18 #define MDIO_CFG_BSY BIT(0)
19 #define MDIO_CFG_RD_ER BIT(1)
20 #define MDIO_CFG_HOLD(x) (((x) << 2) & GENMASK(4, 2))
21 #define MDIO_CFG_ENC45 BIT(6)
22 /* external MDIO only - driven on neg MDC edge */
23 #define MDIO_CFG_NEG BIT(23)
25 #define ENETC_EMDIO_CFG \
27 MDIO_CFG_CLKDIV(258) | \
30 #define MDIO_CTL_DEV_ADDR(x) ((x) & 0x1f)
31 #define MDIO_CTL_PORT_ADDR(x) (((x) & 0x1f) << 5)
32 #define MDIO_CTL_READ BIT(15)
34 static inline u32 enetc_mdio_rd(struct enetc_mdio_priv *mdio_priv, int off)
36 return enetc_port_rd_mdio(mdio_priv->hw, mdio_priv->mdio_base + off);
39 static inline void enetc_mdio_wr(struct enetc_mdio_priv *mdio_priv, int off,
42 enetc_port_wr_mdio(mdio_priv->hw, mdio_priv->mdio_base + off, val);
45 static bool enetc_mdio_is_busy(struct enetc_mdio_priv *mdio_priv)
47 return enetc_mdio_rd(mdio_priv, ENETC_MDIO_CFG) & MDIO_CFG_BSY;
50 static int enetc_mdio_wait_complete(struct enetc_mdio_priv *mdio_priv)
54 return readx_poll_timeout(enetc_mdio_is_busy, mdio_priv,
55 is_busy, !is_busy, 10, 10 * 1000);
58 int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
60 struct enetc_mdio_priv *mdio_priv = bus->priv;
61 u32 mdio_ctl, mdio_cfg;
65 mdio_cfg = ENETC_EMDIO_CFG;
66 if (regnum & MII_ADDR_C45) {
67 dev_addr = (regnum >> 16) & 0x1f;
68 mdio_cfg |= MDIO_CFG_ENC45;
70 /* clause 22 (ie 1G) */
71 dev_addr = regnum & 0x1f;
72 mdio_cfg &= ~MDIO_CFG_ENC45;
75 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
77 ret = enetc_mdio_wait_complete(mdio_priv);
81 /* set port and dev addr */
82 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
83 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
85 /* set the register address */
86 if (regnum & MII_ADDR_C45) {
87 enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
89 ret = enetc_mdio_wait_complete(mdio_priv);
95 enetc_mdio_wr(mdio_priv, ENETC_MDIO_DATA, value);
97 ret = enetc_mdio_wait_complete(mdio_priv);
103 EXPORT_SYMBOL_GPL(enetc_mdio_write);
105 int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
107 struct enetc_mdio_priv *mdio_priv = bus->priv;
108 u32 mdio_ctl, mdio_cfg;
112 mdio_cfg = ENETC_EMDIO_CFG;
113 if (regnum & MII_ADDR_C45) {
114 dev_addr = (regnum >> 16) & 0x1f;
115 mdio_cfg |= MDIO_CFG_ENC45;
117 dev_addr = regnum & 0x1f;
118 mdio_cfg &= ~MDIO_CFG_ENC45;
121 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
123 ret = enetc_mdio_wait_complete(mdio_priv);
127 /* set port and device addr */
128 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
129 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
131 /* set the register address */
132 if (regnum & MII_ADDR_C45) {
133 enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
135 ret = enetc_mdio_wait_complete(mdio_priv);
140 /* initiate the read */
141 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
143 ret = enetc_mdio_wait_complete(mdio_priv);
147 /* return all Fs if nothing was there */
148 if (enetc_mdio_rd(mdio_priv, ENETC_MDIO_CFG) & MDIO_CFG_RD_ER) {
150 "Error while reading PHY%d reg at %d.%hhu\n",
151 phy_id, dev_addr, regnum);
155 value = enetc_mdio_rd(mdio_priv, ENETC_MDIO_DATA) & 0xffff;
159 EXPORT_SYMBOL_GPL(enetc_mdio_read);
161 struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
165 hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
167 return ERR_PTR(-ENOMEM);
169 hw->port = port_regs;
173 EXPORT_SYMBOL_GPL(enetc_hw_alloc);
175 /* Lock for MDIO access errata on LS1028A */
176 DEFINE_RWLOCK(enetc_mdio_lock);
177 EXPORT_SYMBOL_GPL(enetc_mdio_lock);