aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/phy/fixed.c61
-rw-r--r--include/linux/phy_fixed.h11
2 files changed, 72 insertions, 0 deletions
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index e41546da105e..d60d875cb445 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -21,6 +21,7 @@
21#include <linux/phy_fixed.h> 21#include <linux/phy_fixed.h>
22#include <linux/err.h> 22#include <linux/err.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/of.h>
24 25
25#define MII_REGS_NUM 29 26#define MII_REGS_NUM 29
26 27
@@ -203,6 +204,66 @@ err_regs:
203} 204}
204EXPORT_SYMBOL_GPL(fixed_phy_add); 205EXPORT_SYMBOL_GPL(fixed_phy_add);
205 206
207void fixed_phy_del(int phy_addr)
208{
209 struct fixed_mdio_bus *fmb = &platform_fmb;
210 struct fixed_phy *fp, *tmp;
211
212 list_for_each_entry_safe(fp, tmp, &fmb->phys, node) {
213 if (fp->addr == phy_addr) {
214 list_del(&fp->node);
215 kfree(fp);
216 return;
217 }
218 }
219}
220EXPORT_SYMBOL_GPL(fixed_phy_del);
221
222static int phy_fixed_addr;
223static DEFINE_SPINLOCK(phy_fixed_addr_lock);
224
225int fixed_phy_register(unsigned int irq,
226 struct fixed_phy_status *status,
227 struct device_node *np)
228{
229 struct fixed_mdio_bus *fmb = &platform_fmb;
230 struct phy_device *phy;
231 int phy_addr;
232 int ret;
233
234 /* Get the next available PHY address, up to PHY_MAX_ADDR */
235 spin_lock(&phy_fixed_addr_lock);
236 if (phy_fixed_addr == PHY_MAX_ADDR) {
237 spin_unlock(&phy_fixed_addr_lock);
238 return -ENOSPC;
239 }
240 phy_addr = phy_fixed_addr++;
241 spin_unlock(&phy_fixed_addr_lock);
242
243 ret = fixed_phy_add(PHY_POLL, phy_addr, status);
244 if (ret < 0)
245 return ret;
246
247 phy = get_phy_device(fmb->mii_bus, phy_addr, false);
248 if (!phy || IS_ERR(phy)) {
249 fixed_phy_del(phy_addr);
250 return -EINVAL;
251 }
252
253 of_node_get(np);
254 phy->dev.of_node = np;
255
256 ret = phy_device_register(phy);
257 if (ret) {
258 phy_device_free(phy);
259 of_node_put(np);
260 fixed_phy_del(phy_addr);
261 return ret;
262 }
263
264 return 0;
265}
266
206static int __init fixed_mdio_bus_init(void) 267static int __init fixed_mdio_bus_init(void)
207{ 268{
208 struct fixed_mdio_bus *fmb = &platform_fmb; 269 struct fixed_mdio_bus *fmb = &platform_fmb;
diff --git a/include/linux/phy_fixed.h b/include/linux/phy_fixed.h
index 509d8f5f984e..4f2478b47136 100644
--- a/include/linux/phy_fixed.h
+++ b/include/linux/phy_fixed.h
@@ -9,15 +9,26 @@ struct fixed_phy_status {
9 int asym_pause; 9 int asym_pause;
10}; 10};
11 11
12struct device_node;
13
12#ifdef CONFIG_FIXED_PHY 14#ifdef CONFIG_FIXED_PHY
13extern int fixed_phy_add(unsigned int irq, int phy_id, 15extern int fixed_phy_add(unsigned int irq, int phy_id,
14 struct fixed_phy_status *status); 16 struct fixed_phy_status *status);
17extern int fixed_phy_register(unsigned int irq,
18 struct fixed_phy_status *status,
19 struct device_node *np);
15#else 20#else
16static inline int fixed_phy_add(unsigned int irq, int phy_id, 21static inline int fixed_phy_add(unsigned int irq, int phy_id,
17 struct fixed_phy_status *status) 22 struct fixed_phy_status *status)
18{ 23{
19 return -ENODEV; 24 return -ENODEV;
20} 25}
26static inline int fixed_phy_register(unsigned int irq,
27 struct fixed_phy_status *status,
28 struct device_node *np)
29{
30 return -ENODEV;
31}
21#endif /* CONFIG_FIXED_PHY */ 32#endif /* CONFIG_FIXED_PHY */
22 33
23/* 34/*