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 #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)
24
25 #define ENETC_EMDIO_CFG \
26 (MDIO_CFG_HOLD(2) | \
27 MDIO_CFG_CLKDIV(258) | \
28 MDIO_CFG_NEG)
29
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)
33
enetc_mdio_rd(struct enetc_mdio_priv * mdio_priv,int off)34 static inline u32 enetc_mdio_rd(struct enetc_mdio_priv *mdio_priv, int off)
35 {
36 return enetc_port_rd_mdio(mdio_priv->hw, mdio_priv->mdio_base + off);
37 }
38
enetc_mdio_wr(struct enetc_mdio_priv * mdio_priv,int off,u32 val)39 static inline void enetc_mdio_wr(struct enetc_mdio_priv *mdio_priv, int off,
40 u32 val)
41 {
42 enetc_port_wr_mdio(mdio_priv->hw, mdio_priv->mdio_base + off, val);
43 }
44
enetc_mdio_is_busy(struct enetc_mdio_priv * mdio_priv)45 static bool enetc_mdio_is_busy(struct enetc_mdio_priv *mdio_priv)
46 {
47 return enetc_mdio_rd(mdio_priv, ENETC_MDIO_CFG) & MDIO_CFG_BSY;
48 }
49
enetc_mdio_wait_complete(struct enetc_mdio_priv * mdio_priv)50 static int enetc_mdio_wait_complete(struct enetc_mdio_priv *mdio_priv)
51 {
52 bool is_busy;
53
54 return readx_poll_timeout(enetc_mdio_is_busy, mdio_priv,
55 is_busy, !is_busy, 10, 10 * 1000);
56 }
57
enetc_mdio_write(struct mii_bus * bus,int phy_id,int regnum,u16 value)58 int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
59 {
60 struct enetc_mdio_priv *mdio_priv = bus->priv;
61 u32 mdio_ctl, mdio_cfg;
62 u16 dev_addr;
63 int ret;
64
65 mdio_cfg = ENETC_EMDIO_CFG;
66 if (regnum & MII_ADDR_C45) {
67 dev_addr = (regnum >> 16) & 0x1f;
68 mdio_cfg |= MDIO_CFG_ENC45;
69 } else {
70 /* clause 22 (ie 1G) */
71 dev_addr = regnum & 0x1f;
72 mdio_cfg &= ~MDIO_CFG_ENC45;
73 }
74
75 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
76
77 ret = enetc_mdio_wait_complete(mdio_priv);
78 if (ret)
79 return ret;
80
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);
84
85 /* set the register address */
86 if (regnum & MII_ADDR_C45) {
87 enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
88
89 ret = enetc_mdio_wait_complete(mdio_priv);
90 if (ret)
91 return ret;
92 }
93
94 /* write the value */
95 enetc_mdio_wr(mdio_priv, ENETC_MDIO_DATA, value);
96
97 ret = enetc_mdio_wait_complete(mdio_priv);
98 if (ret)
99 return ret;
100
101 return 0;
102 }
103 EXPORT_SYMBOL_GPL(enetc_mdio_write);
104
enetc_mdio_read(struct mii_bus * bus,int phy_id,int regnum)105 int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
106 {
107 struct enetc_mdio_priv *mdio_priv = bus->priv;
108 u32 mdio_ctl, mdio_cfg;
109 u16 dev_addr, value;
110 int ret;
111
112 mdio_cfg = ENETC_EMDIO_CFG;
113 if (regnum & MII_ADDR_C45) {
114 dev_addr = (regnum >> 16) & 0x1f;
115 mdio_cfg |= MDIO_CFG_ENC45;
116 } else {
117 dev_addr = regnum & 0x1f;
118 mdio_cfg &= ~MDIO_CFG_ENC45;
119 }
120
121 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
122
123 ret = enetc_mdio_wait_complete(mdio_priv);
124 if (ret)
125 return ret;
126
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);
130
131 /* set the register address */
132 if (regnum & MII_ADDR_C45) {
133 enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
134
135 ret = enetc_mdio_wait_complete(mdio_priv);
136 if (ret)
137 return ret;
138 }
139
140 /* initiate the read */
141 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
142
143 ret = enetc_mdio_wait_complete(mdio_priv);
144 if (ret)
145 return ret;
146
147 /* return all Fs if nothing was there */
148 if (enetc_mdio_rd(mdio_priv, ENETC_MDIO_CFG) & MDIO_CFG_RD_ER) {
149 dev_dbg(&bus->dev,
150 "Error while reading PHY%d reg at %d.%d\n",
151 phy_id, dev_addr, regnum);
152 return 0xffff;
153 }
154
155 value = enetc_mdio_rd(mdio_priv, ENETC_MDIO_DATA) & 0xffff;
156
157 return value;
158 }
159 EXPORT_SYMBOL_GPL(enetc_mdio_read);
160
enetc_hw_alloc(struct device * dev,void __iomem * port_regs)161 struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
162 {
163 struct enetc_hw *hw;
164
165 hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
166 if (!hw)
167 return ERR_PTR(-ENOMEM);
168
169 hw->port = port_regs;
170
171 return hw;
172 }
173 EXPORT_SYMBOL_GPL(enetc_hw_alloc);
174
175 /* Lock for MDIO access errata on LS1028A */
176 DEFINE_RWLOCK(enetc_mdio_lock);
177 EXPORT_SYMBOL_GPL(enetc_mdio_lock);
178