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