hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
....@@ -5,31 +5,29 @@
55 * Copyright (c) 2009 Secret Lab Technologies, Ltd.
66 * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu>
77 * Copyright (c) 2010 - 2011 PetaLogix
8
+ * Copyright (c) 2019 SED Systems, a division of Calian Ltd.
89 * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
910 */
1011
12
+#include <linux/clk.h>
1113 #include <linux/of_address.h>
1214 #include <linux/of_mdio.h>
1315 #include <linux/jiffies.h>
16
+#include <linux/iopoll.h>
1417
1518 #include "xilinx_axienet.h"
1619
1720 #define MAX_MDIO_FREQ 2500000 /* 2.5 MHz */
18
-#define DEFAULT_CLOCK_DIVISOR XAE_MDIO_DIV_DFT
21
+#define DEFAULT_HOST_CLOCK 150000000 /* 150 MHz */
1922
2023 /* Wait till MDIO interface is ready to accept a new transaction.*/
21
-int axienet_mdio_wait_until_ready(struct axienet_local *lp)
24
+static int axienet_mdio_wait_until_ready(struct axienet_local *lp)
2225 {
23
- unsigned long end = jiffies + 2;
24
- while (!(axienet_ior(lp, XAE_MDIO_MCR_OFFSET) &
25
- XAE_MDIO_MCR_READY_MASK)) {
26
- if (time_before_eq(end, jiffies)) {
27
- WARN_ON(1);
28
- return -ETIMEDOUT;
29
- }
30
- udelay(1);
31
- }
32
- return 0;
26
+ u32 val;
27
+
28
+ return readx_poll_timeout(axinet_ior_read_mcr, lp,
29
+ val, val & XAE_MDIO_MCR_READY_MASK,
30
+ 1, 20000);
3331 }
3432
3533 /**
....@@ -116,23 +114,42 @@
116114 }
117115
118116 /**
119
- * axienet_mdio_setup - MDIO setup function
117
+ * axienet_mdio_enable - MDIO hardware setup function
120118 * @lp: Pointer to axienet local data structure.
121
- * @np: Pointer to device node
122119 *
123
- * Return: 0 on success, -ETIMEDOUT on a timeout, -ENOMEM when
124
- * mdiobus_alloc (to allocate memory for mii bus structure) fails.
120
+ * Return: 0 on success, -ETIMEDOUT on a timeout.
125121 *
126122 * Sets up the MDIO interface by initializing the MDIO clock and enabling the
127
- * MDIO interface in hardware. Register the MDIO interface.
123
+ * MDIO interface in hardware.
128124 **/
129
-int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np)
125
+int axienet_mdio_enable(struct axienet_local *lp)
130126 {
131
- int ret;
132127 u32 clk_div, host_clock;
133
- struct mii_bus *bus;
134
- struct resource res;
135
- struct device_node *np1;
128
+
129
+ if (lp->clk) {
130
+ host_clock = clk_get_rate(lp->clk);
131
+ } else {
132
+ struct device_node *np1;
133
+
134
+ /* Legacy fallback: detect CPU clock frequency and use as AXI
135
+ * bus clock frequency. This only works on certain platforms.
136
+ */
137
+ np1 = of_find_node_by_name(NULL, "cpu");
138
+ if (!np1) {
139
+ netdev_warn(lp->ndev, "Could not find CPU device node.\n");
140
+ host_clock = DEFAULT_HOST_CLOCK;
141
+ } else {
142
+ int ret = of_property_read_u32(np1, "clock-frequency",
143
+ &host_clock);
144
+ if (ret) {
145
+ netdev_warn(lp->ndev, "CPU clock-frequency property not found.\n");
146
+ host_clock = DEFAULT_HOST_CLOCK;
147
+ }
148
+ of_node_put(np1);
149
+ }
150
+ netdev_info(lp->ndev, "Setting assumed host clock to %u\n",
151
+ host_clock);
152
+ }
136153
137154 /* clk_div can be calculated by deriving it from the equation:
138155 * fMDIO = fHOST / ((1 + clk_div) * 2)
....@@ -159,25 +176,6 @@
159176 * "clock-frequency" from the CPU
160177 */
161178
162
- np1 = of_find_node_by_name(NULL, "cpu");
163
- if (!np1) {
164
- netdev_warn(lp->ndev, "Could not find CPU device node.\n");
165
- netdev_warn(lp->ndev,
166
- "Setting MDIO clock divisor to default %d\n",
167
- DEFAULT_CLOCK_DIVISOR);
168
- clk_div = DEFAULT_CLOCK_DIVISOR;
169
- goto issue;
170
- }
171
- if (of_property_read_u32(np1, "clock-frequency", &host_clock)) {
172
- netdev_warn(lp->ndev, "clock-frequency property not found.\n");
173
- netdev_warn(lp->ndev,
174
- "Setting MDIO clock divisor to default %d\n",
175
- DEFAULT_CLOCK_DIVISOR);
176
- clk_div = DEFAULT_CLOCK_DIVISOR;
177
- of_node_put(np1);
178
- goto issue;
179
- }
180
-
181179 clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1;
182180 /* If there is any remainder from the division of
183181 * fHOST / (MAX_MDIO_FREQ * 2), then we need to add
....@@ -190,12 +188,39 @@
190188 "Setting MDIO clock divisor to %u/%u Hz host clock.\n",
191189 clk_div, host_clock);
192190
193
- of_node_put(np1);
194
-issue:
195
- axienet_iow(lp, XAE_MDIO_MC_OFFSET,
196
- (((u32) clk_div) | XAE_MDIO_MC_MDIOEN_MASK));
191
+ axienet_iow(lp, XAE_MDIO_MC_OFFSET, clk_div | XAE_MDIO_MC_MDIOEN_MASK);
197192
198
- ret = axienet_mdio_wait_until_ready(lp);
193
+ return axienet_mdio_wait_until_ready(lp);
194
+}
195
+
196
+/**
197
+ * axienet_mdio_disable - MDIO hardware disable function
198
+ * @lp: Pointer to axienet local data structure.
199
+ *
200
+ * Disable the MDIO interface in hardware.
201
+ **/
202
+void axienet_mdio_disable(struct axienet_local *lp)
203
+{
204
+ axienet_iow(lp, XAE_MDIO_MC_OFFSET, 0);
205
+}
206
+
207
+/**
208
+ * axienet_mdio_setup - MDIO setup function
209
+ * @lp: Pointer to axienet local data structure.
210
+ *
211
+ * Return: 0 on success, -ETIMEDOUT on a timeout, -ENOMEM when
212
+ * mdiobus_alloc (to allocate memory for mii bus structure) fails.
213
+ *
214
+ * Sets up the MDIO interface by initializing the MDIO clock and enabling the
215
+ * MDIO interface in hardware. Register the MDIO interface.
216
+ **/
217
+int axienet_mdio_setup(struct axienet_local *lp)
218
+{
219
+ struct device_node *mdio_node;
220
+ struct mii_bus *bus;
221
+ int ret;
222
+
223
+ ret = axienet_mdio_enable(lp);
199224 if (ret < 0)
200225 return ret;
201226
....@@ -203,10 +228,8 @@
203228 if (!bus)
204229 return -ENOMEM;
205230
206
- np1 = of_get_parent(lp->phy_node);
207
- of_address_to_resource(np1, 0, &res);
208
- snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
209
- (unsigned long long) res.start);
231
+ snprintf(bus->id, MII_BUS_ID_SIZE, "axienet-%.8llx",
232
+ (unsigned long long)lp->regs_start);
210233
211234 bus->priv = lp;
212235 bus->name = "Xilinx Axi Ethernet MDIO";
....@@ -215,7 +238,9 @@
215238 bus->parent = lp->dev;
216239 lp->mii_bus = bus;
217240
218
- ret = of_mdiobus_register(bus, np1);
241
+ mdio_node = of_get_child_by_name(lp->dev->of_node, "mdio");
242
+ ret = of_mdiobus_register(bus, mdio_node);
243
+ of_node_put(mdio_node);
219244 if (ret) {
220245 mdiobus_free(bus);
221246 lp->mii_bus = NULL;