This source file includes following definitions.
- enetc_mdio_wait_complete
- enetc_mdio_write
- enetc_mdio_read
- enetc_mdio_probe
- enetc_mdio_remove
1
2
3
4 #include <linux/mdio.h>
5 #include <linux/of_mdio.h>
6 #include <linux/iopoll.h>
7 #include <linux/of.h>
8
9 #include "enetc_mdio.h"
10
11 #define ENETC_MDIO_REG_OFFSET 0x1c00
12 #define ENETC_MDIO_CFG 0x0
13 #define ENETC_MDIO_CTL 0x4
14 #define ENETC_MDIO_DATA 0x8
15 #define ENETC_MDIO_ADDR 0xc
16
17 #define enetc_mdio_rd(hw, off) \
18 enetc_port_rd(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET)
19 #define enetc_mdio_wr(hw, off, val) \
20 enetc_port_wr(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET, val)
21 #define enetc_mdio_rd_reg(off) enetc_mdio_rd(hw, off)
22
23 #define ENETC_MDC_DIV 258
24
25 #define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8)
26 #define MDIO_CFG_BSY BIT(0)
27 #define MDIO_CFG_RD_ER BIT(1)
28 #define MDIO_CFG_ENC45 BIT(6)
29
30 #define MDIO_CFG_NEG BIT(23)
31
32 #define MDIO_CTL_DEV_ADDR(x) ((x) & 0x1f)
33 #define MDIO_CTL_PORT_ADDR(x) (((x) & 0x1f) << 5)
34 #define MDIO_CTL_READ BIT(15)
35 #define MDIO_DATA(x) ((x) & 0xffff)
36
37 #define TIMEOUT 1000
38 static int enetc_mdio_wait_complete(struct enetc_hw *hw)
39 {
40 u32 val;
41
42 return readx_poll_timeout(enetc_mdio_rd_reg, MDIO_CFG, val,
43 !(val & MDIO_CFG_BSY), 10, 10 * TIMEOUT);
44 }
45
46 int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
47 {
48 struct enetc_mdio_priv *mdio_priv = bus->priv;
49 struct enetc_hw *hw = mdio_priv->hw;
50 u32 mdio_ctl, mdio_cfg;
51 u16 dev_addr;
52 int ret;
53
54 mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG;
55 if (regnum & MII_ADDR_C45) {
56 dev_addr = (regnum >> 16) & 0x1f;
57 mdio_cfg |= MDIO_CFG_ENC45;
58 } else {
59
60 dev_addr = regnum & 0x1f;
61 mdio_cfg &= ~MDIO_CFG_ENC45;
62 }
63
64 enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
65
66 ret = enetc_mdio_wait_complete(hw);
67 if (ret)
68 return ret;
69
70
71 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
72 enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
73
74
75 if (regnum & MII_ADDR_C45) {
76 enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
77
78 ret = enetc_mdio_wait_complete(hw);
79 if (ret)
80 return ret;
81 }
82
83
84 enetc_mdio_wr(hw, MDIO_DATA, MDIO_DATA(value));
85
86 ret = enetc_mdio_wait_complete(hw);
87 if (ret)
88 return ret;
89
90 return 0;
91 }
92
93 int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
94 {
95 struct enetc_mdio_priv *mdio_priv = bus->priv;
96 struct enetc_hw *hw = mdio_priv->hw;
97 u32 mdio_ctl, mdio_cfg;
98 u16 dev_addr, value;
99 int ret;
100
101 mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG;
102 if (regnum & MII_ADDR_C45) {
103 dev_addr = (regnum >> 16) & 0x1f;
104 mdio_cfg |= MDIO_CFG_ENC45;
105 } else {
106 dev_addr = regnum & 0x1f;
107 mdio_cfg &= ~MDIO_CFG_ENC45;
108 }
109
110 enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
111
112 ret = enetc_mdio_wait_complete(hw);
113 if (ret)
114 return ret;
115
116
117 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
118 enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
119
120
121 if (regnum & MII_ADDR_C45) {
122 enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
123
124 ret = enetc_mdio_wait_complete(hw);
125 if (ret)
126 return ret;
127 }
128
129
130 enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
131
132 ret = enetc_mdio_wait_complete(hw);
133 if (ret)
134 return ret;
135
136
137 if (enetc_mdio_rd(hw, MDIO_CFG) & MDIO_CFG_RD_ER) {
138 dev_dbg(&bus->dev,
139 "Error while reading PHY%d reg at %d.%hhu\n",
140 phy_id, dev_addr, regnum);
141 return 0xffff;
142 }
143
144 value = enetc_mdio_rd(hw, MDIO_DATA) & 0xffff;
145
146 return value;
147 }
148
149 int enetc_mdio_probe(struct enetc_pf *pf)
150 {
151 struct device *dev = &pf->si->pdev->dev;
152 struct enetc_mdio_priv *mdio_priv;
153 struct device_node *np;
154 struct mii_bus *bus;
155 int err;
156
157 bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
158 if (!bus)
159 return -ENOMEM;
160
161 bus->name = "Freescale ENETC MDIO Bus";
162 bus->read = enetc_mdio_read;
163 bus->write = enetc_mdio_write;
164 bus->parent = dev;
165 mdio_priv = bus->priv;
166 mdio_priv->hw = &pf->si->hw;
167 snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
168
169 np = of_get_child_by_name(dev->of_node, "mdio");
170 if (!np) {
171 dev_err(dev, "MDIO node missing\n");
172 return -EINVAL;
173 }
174
175 err = of_mdiobus_register(bus, np);
176 if (err) {
177 of_node_put(np);
178 dev_err(dev, "cannot register MDIO bus\n");
179 return err;
180 }
181
182 of_node_put(np);
183 pf->mdio = bus;
184
185 return 0;
186 }
187
188 void enetc_mdio_remove(struct enetc_pf *pf)
189 {
190 if (pf->mdio)
191 mdiobus_unregister(pf->mdio);
192 }