These changes are a raw update to a vanilla kernel 4.1.10, with the
[kvmfornfv.git] / kernel / drivers / net / phy / fixed_phy.c
1 /*
2  * Fixed MDIO bus (MDIO bus emulation with fixed PHYs)
3  *
4  * Author: Vitaly Bordug <vbordug@ru.mvista.com>
5  *         Anton Vorontsov <avorontsov@ru.mvista.com>
6  *
7  * Copyright (c) 2006-2007 MontaVista Software, Inc.
8  *
9  * This program is free software; you can redistribute  it and/or modify it
10  * under  the terms of  the GNU General  Public License as published by the
11  * Free Software Foundation;  either version 2 of the  License, or (at your
12  * option) any later version.
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
18 #include <linux/list.h>
19 #include <linux/mii.h>
20 #include <linux/phy.h>
21 #include <linux/phy_fixed.h>
22 #include <linux/err.h>
23 #include <linux/slab.h>
24 #include <linux/of.h>
25
26 #define MII_REGS_NUM 29
27
28 struct fixed_mdio_bus {
29         int irqs[PHY_MAX_ADDR];
30         struct mii_bus *mii_bus;
31         struct list_head phys;
32 };
33
34 struct fixed_phy {
35         int addr;
36         u16 regs[MII_REGS_NUM];
37         struct phy_device *phydev;
38         struct fixed_phy_status status;
39         int (*link_update)(struct net_device *, struct fixed_phy_status *);
40         struct list_head node;
41 };
42
43 static struct platform_device *pdev;
44 static struct fixed_mdio_bus platform_fmb = {
45         .phys = LIST_HEAD_INIT(platform_fmb.phys),
46 };
47
48 static int fixed_phy_update_regs(struct fixed_phy *fp)
49 {
50         u16 bmsr = BMSR_ANEGCAPABLE;
51         u16 bmcr = 0;
52         u16 lpagb = 0;
53         u16 lpa = 0;
54
55         if (!fp->status.link)
56                 goto done;
57         bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;
58
59         if (fp->status.duplex) {
60                 bmcr |= BMCR_FULLDPLX;
61
62                 switch (fp->status.speed) {
63                 case 1000:
64                         bmsr |= BMSR_ESTATEN;
65                         bmcr |= BMCR_SPEED1000;
66                         lpagb |= LPA_1000FULL;
67                         break;
68                 case 100:
69                         bmsr |= BMSR_100FULL;
70                         bmcr |= BMCR_SPEED100;
71                         lpa |= LPA_100FULL;
72                         break;
73                 case 10:
74                         bmsr |= BMSR_10FULL;
75                         lpa |= LPA_10FULL;
76                         break;
77                 default:
78                         pr_warn("fixed phy: unknown speed\n");
79                         return -EINVAL;
80                 }
81         } else {
82                 switch (fp->status.speed) {
83                 case 1000:
84                         bmsr |= BMSR_ESTATEN;
85                         bmcr |= BMCR_SPEED1000;
86                         lpagb |= LPA_1000HALF;
87                         break;
88                 case 100:
89                         bmsr |= BMSR_100HALF;
90                         bmcr |= BMCR_SPEED100;
91                         lpa |= LPA_100HALF;
92                         break;
93                 case 10:
94                         bmsr |= BMSR_10HALF;
95                         lpa |= LPA_10HALF;
96                         break;
97                 default:
98                         pr_warn("fixed phy: unknown speed\n");
99                         return -EINVAL;
100                 }
101         }
102
103         if (fp->status.pause)
104                 lpa |= LPA_PAUSE_CAP;
105
106         if (fp->status.asym_pause)
107                 lpa |= LPA_PAUSE_ASYM;
108
109 done:
110         fp->regs[MII_PHYSID1] = 0;
111         fp->regs[MII_PHYSID2] = 0;
112
113         fp->regs[MII_BMSR] = bmsr;
114         fp->regs[MII_BMCR] = bmcr;
115         fp->regs[MII_LPA] = lpa;
116         fp->regs[MII_STAT1000] = lpagb;
117
118         return 0;
119 }
120
121 static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num)
122 {
123         struct fixed_mdio_bus *fmb = bus->priv;
124         struct fixed_phy *fp;
125
126         if (reg_num >= MII_REGS_NUM)
127                 return -1;
128
129         /* We do not support emulating Clause 45 over Clause 22 register reads
130          * return an error instead of bogus data.
131          */
132         switch (reg_num) {
133         case MII_MMD_CTRL:
134         case MII_MMD_DATA:
135                 return -1;
136         default:
137                 break;
138         }
139
140         list_for_each_entry(fp, &fmb->phys, node) {
141                 if (fp->addr == phy_addr) {
142                         /* Issue callback if user registered it. */
143                         if (fp->link_update) {
144                                 fp->link_update(fp->phydev->attached_dev,
145                                                 &fp->status);
146                                 fixed_phy_update_regs(fp);
147                         }
148                         return fp->regs[reg_num];
149                 }
150         }
151
152         return 0xFFFF;
153 }
154
155 static int fixed_mdio_write(struct mii_bus *bus, int phy_addr, int reg_num,
156                             u16 val)
157 {
158         return 0;
159 }
160
161 /*
162  * If something weird is required to be done with link/speed,
163  * network driver is able to assign a function to implement this.
164  * May be useful for PHY's that need to be software-driven.
165  */
166 int fixed_phy_set_link_update(struct phy_device *phydev,
167                               int (*link_update)(struct net_device *,
168                                                  struct fixed_phy_status *))
169 {
170         struct fixed_mdio_bus *fmb = &platform_fmb;
171         struct fixed_phy *fp;
172
173         if (!phydev || !phydev->bus)
174                 return -EINVAL;
175
176         list_for_each_entry(fp, &fmb->phys, node) {
177                 if (fp->addr == phydev->addr) {
178                         fp->link_update = link_update;
179                         fp->phydev = phydev;
180                         return 0;
181                 }
182         }
183
184         return -ENOENT;
185 }
186 EXPORT_SYMBOL_GPL(fixed_phy_set_link_update);
187
188 int fixed_phy_update_state(struct phy_device *phydev,
189                            const struct fixed_phy_status *status,
190                            const struct fixed_phy_status *changed)
191 {
192         struct fixed_mdio_bus *fmb = &platform_fmb;
193         struct fixed_phy *fp;
194
195         if (!phydev || !phydev->bus)
196                 return -EINVAL;
197
198         list_for_each_entry(fp, &fmb->phys, node) {
199                 if (fp->addr == phydev->addr) {
200 #define _UPD(x) if (changed->x) \
201         fp->status.x = status->x
202                         _UPD(link);
203                         _UPD(speed);
204                         _UPD(duplex);
205                         _UPD(pause);
206                         _UPD(asym_pause);
207 #undef _UPD
208                         fixed_phy_update_regs(fp);
209                         return 0;
210                 }
211         }
212
213         return -ENOENT;
214 }
215 EXPORT_SYMBOL(fixed_phy_update_state);
216
217 int fixed_phy_add(unsigned int irq, int phy_addr,
218                   struct fixed_phy_status *status)
219 {
220         int ret;
221         struct fixed_mdio_bus *fmb = &platform_fmb;
222         struct fixed_phy *fp;
223
224         fp = kzalloc(sizeof(*fp), GFP_KERNEL);
225         if (!fp)
226                 return -ENOMEM;
227
228         memset(fp->regs, 0xFF,  sizeof(fp->regs[0]) * MII_REGS_NUM);
229
230         fmb->irqs[phy_addr] = irq;
231
232         fp->addr = phy_addr;
233         fp->status = *status;
234
235         ret = fixed_phy_update_regs(fp);
236         if (ret)
237                 goto err_regs;
238
239         list_add_tail(&fp->node, &fmb->phys);
240
241         return 0;
242
243 err_regs:
244         kfree(fp);
245         return ret;
246 }
247 EXPORT_SYMBOL_GPL(fixed_phy_add);
248
249 void fixed_phy_del(int phy_addr)
250 {
251         struct fixed_mdio_bus *fmb = &platform_fmb;
252         struct fixed_phy *fp, *tmp;
253
254         list_for_each_entry_safe(fp, tmp, &fmb->phys, node) {
255                 if (fp->addr == phy_addr) {
256                         list_del(&fp->node);
257                         kfree(fp);
258                         return;
259                 }
260         }
261 }
262 EXPORT_SYMBOL_GPL(fixed_phy_del);
263
264 static int phy_fixed_addr;
265 static DEFINE_SPINLOCK(phy_fixed_addr_lock);
266
267 struct phy_device *fixed_phy_register(unsigned int irq,
268                                       struct fixed_phy_status *status,
269                                       struct device_node *np)
270 {
271         struct fixed_mdio_bus *fmb = &platform_fmb;
272         struct phy_device *phy;
273         int phy_addr;
274         int ret;
275
276         /* Get the next available PHY address, up to PHY_MAX_ADDR */
277         spin_lock(&phy_fixed_addr_lock);
278         if (phy_fixed_addr == PHY_MAX_ADDR) {
279                 spin_unlock(&phy_fixed_addr_lock);
280                 return ERR_PTR(-ENOSPC);
281         }
282         phy_addr = phy_fixed_addr++;
283         spin_unlock(&phy_fixed_addr_lock);
284
285         ret = fixed_phy_add(PHY_POLL, phy_addr, status);
286         if (ret < 0)
287                 return ERR_PTR(ret);
288
289         phy = get_phy_device(fmb->mii_bus, phy_addr, false);
290         if (!phy || IS_ERR(phy)) {
291                 fixed_phy_del(phy_addr);
292                 return ERR_PTR(-EINVAL);
293         }
294
295         of_node_get(np);
296         phy->dev.of_node = np;
297
298         ret = phy_device_register(phy);
299         if (ret) {
300                 phy_device_free(phy);
301                 of_node_put(np);
302                 fixed_phy_del(phy_addr);
303                 return ERR_PTR(ret);
304         }
305
306         return phy;
307 }
308 EXPORT_SYMBOL_GPL(fixed_phy_register);
309
310 static int __init fixed_mdio_bus_init(void)
311 {
312         struct fixed_mdio_bus *fmb = &platform_fmb;
313         int ret;
314
315         pdev = platform_device_register_simple("Fixed MDIO bus", 0, NULL, 0);
316         if (IS_ERR(pdev)) {
317                 ret = PTR_ERR(pdev);
318                 goto err_pdev;
319         }
320
321         fmb->mii_bus = mdiobus_alloc();
322         if (fmb->mii_bus == NULL) {
323                 ret = -ENOMEM;
324                 goto err_mdiobus_reg;
325         }
326
327         snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "fixed-0");
328         fmb->mii_bus->name = "Fixed MDIO Bus";
329         fmb->mii_bus->priv = fmb;
330         fmb->mii_bus->parent = &pdev->dev;
331         fmb->mii_bus->read = &fixed_mdio_read;
332         fmb->mii_bus->write = &fixed_mdio_write;
333         fmb->mii_bus->irq = fmb->irqs;
334
335         ret = mdiobus_register(fmb->mii_bus);
336         if (ret)
337                 goto err_mdiobus_alloc;
338
339         return 0;
340
341 err_mdiobus_alloc:
342         mdiobus_free(fmb->mii_bus);
343 err_mdiobus_reg:
344         platform_device_unregister(pdev);
345 err_pdev:
346         return ret;
347 }
348 module_init(fixed_mdio_bus_init);
349
350 static void __exit fixed_mdio_bus_exit(void)
351 {
352         struct fixed_mdio_bus *fmb = &platform_fmb;
353         struct fixed_phy *fp, *tmp;
354
355         mdiobus_unregister(fmb->mii_bus);
356         mdiobus_free(fmb->mii_bus);
357         platform_device_unregister(pdev);
358
359         list_for_each_entry_safe(fp, tmp, &fmb->phys, node) {
360                 list_del(&fp->node);
361                 kfree(fp);
362         }
363 }
364 module_exit(fixed_mdio_bus_exit);
365
366 MODULE_DESCRIPTION("Fixed MDIO bus (MDIO bus emulation with fixed PHYs)");
367 MODULE_AUTHOR("Vitaly Bordug");
368 MODULE_LICENSE("GPL");