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