Root/target/linux/generic/files/drivers/net/phy/adm6996.c

1/*
2 * ADM6996 switch driver
3 *
4 * swconfig interface based on ar8216.c
5 *
6 * Copyright (c) 2008 Felix Fietkau <nbd@openwrt.org>
7 * VLAN support Copyright (c) 2010, 2011 Peter Lebbing <peter@digitalbrains.com>
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 v2 as published by the
11 * Free Software Foundation
12 */
13
14/*#define DEBUG 1*/
15#include <linux/kernel.h>
16#include <linux/string.h>
17#include <linux/errno.h>
18#include <linux/unistd.h>
19#include <linux/slab.h>
20#include <linux/interrupt.h>
21#include <linux/init.h>
22#include <linux/delay.h>
23#include <linux/netdevice.h>
24#include <linux/etherdevice.h>
25#include <linux/skbuff.h>
26#include <linux/spinlock.h>
27#include <linux/mm.h>
28#include <linux/module.h>
29#include <linux/mii.h>
30#include <linux/ethtool.h>
31#include <linux/phy.h>
32#include <linux/switch.h>
33
34#include <asm/io.h>
35#include <asm/irq.h>
36#include <asm/uaccess.h>
37#include "adm6996.h"
38
39MODULE_DESCRIPTION("Infineon ADM6996 Switch");
40MODULE_AUTHOR("Felix Fietkau, Peter Lebbing <peter@digitalbrains.com>");
41MODULE_LICENSE("GPL");
42
43enum adm6996_model {
44    ADM6996FC,
45    ADM6996M
46};
47
48static const char * const adm6996_model_name[] =
49{
50    "ADM6996FC",
51    "ADM6996M"
52};
53
54struct adm6996_priv {
55    struct switch_dev dev;
56    struct phy_device *phydev;
57
58    enum adm6996_model model;
59
60    bool enable_vlan;
61    bool vlan_enabled; /* Current hardware state */
62
63#ifdef DEBUG
64    u16 addr; /* Debugging: register address to operate on */
65#endif
66
67    u16 pvid[ADM_NUM_PORTS]; /* Primary VLAN ID */
68
69    u16 vlan_id[ADM_NUM_VLANS];
70    u8 vlan_table[ADM_NUM_VLANS]; /* bitmap, 1 = port is member */
71    u8 vlan_tagged[ADM_NUM_VLANS]; /* bitmap, 1 = tagged member */
72
73    struct mutex reg_mutex;
74
75    /* use abstraction for regops, we want to add gpio support in the future */
76    u16 (*read)(struct phy_device *phydev, enum admreg reg);
77    void (*write)(struct phy_device *phydev, enum admreg reg, u16 val);
78};
79
80#define to_adm(_dev) container_of(_dev, struct adm6996_priv, dev)
81#define phy_to_adm(_phy) ((struct adm6996_priv *) (_phy)->priv)
82
83static inline u16
84r16(struct phy_device *pdev, enum admreg reg)
85{
86    return phy_to_adm(pdev)->read(pdev, reg);
87}
88
89static inline void
90w16(struct phy_device *pdev, enum admreg reg, u16 val)
91{
92    phy_to_adm(pdev)->write(pdev, reg, val);
93}
94
95
96static u16
97adm6996_read_mii_reg(struct phy_device *phydev, enum admreg reg)
98{
99    return phydev->bus->read(phydev->bus, PHYADDR(reg));
100}
101
102static void
103adm6996_write_mii_reg(struct phy_device *phydev, enum admreg reg, u16 val)
104{
105    phydev->bus->write(phydev->bus, PHYADDR(reg), val);
106}
107
108static int
109adm6996_set_enable_vlan(struct switch_dev *dev, const struct switch_attr *attr,
110            struct switch_val *val)
111{
112    struct adm6996_priv *priv = to_adm(dev);
113
114    if (val->value.i > 1)
115        return -EINVAL;
116
117    priv->enable_vlan = val->value.i;
118
119    return 0;
120};
121
122static int
123adm6996_get_enable_vlan(struct switch_dev *dev, const struct switch_attr *attr,
124            struct switch_val *val)
125{
126    struct adm6996_priv *priv = to_adm(dev);
127
128    val->value.i = priv->enable_vlan;
129
130    return 0;
131};
132
133#ifdef DEBUG
134
135static int
136adm6996_set_addr(struct switch_dev *dev, const struct switch_attr *attr,
137         struct switch_val *val)
138{
139    struct adm6996_priv *priv = to_adm(dev);
140
141    if (val->value.i > 1023)
142        return -EINVAL;
143
144    priv->addr = val->value.i;
145
146    return 0;
147};
148
149static int
150adm6996_get_addr(struct switch_dev *dev, const struct switch_attr *attr,
151         struct switch_val *val)
152{
153    struct adm6996_priv *priv = to_adm(dev);
154
155    val->value.i = priv->addr;
156
157    return 0;
158};
159
160static int
161adm6996_set_data(struct switch_dev *dev, const struct switch_attr *attr,
162         struct switch_val *val)
163{
164    struct adm6996_priv *priv = to_adm(dev);
165
166    if (val->value.i > 65535)
167        return -EINVAL;
168
169    w16(priv->phydev, priv->addr, val->value.i);
170
171    return 0;
172};
173
174static int
175adm6996_get_data(struct switch_dev *dev, const struct switch_attr *attr,
176         struct switch_val *val)
177{
178    struct adm6996_priv *priv = to_adm(dev);
179
180    val->value.i = r16(priv->phydev, priv->addr);
181
182    return 0;
183};
184
185#endif /* def DEBUG */
186
187static int
188adm6996_set_pvid(struct switch_dev *dev, int port, int vlan)
189{
190    struct adm6996_priv *priv = to_adm(dev);
191
192    dev_dbg (&priv->phydev->dev, "set_pvid port %d vlan %d\n", port
193            , vlan);
194
195    if (vlan > ADM_VLAN_MAX_ID)
196        return -EINVAL;
197
198    priv->pvid[port] = vlan;
199
200    return 0;
201}
202
203static int
204adm6996_get_pvid(struct switch_dev *dev, int port, int *vlan)
205{
206    struct adm6996_priv *priv = to_adm(dev);
207
208    dev_dbg (&priv->phydev->dev, "get_pvid port %d\n", port);
209    *vlan = priv->pvid[port];
210
211    return 0;
212}
213
214static int
215adm6996_set_vid(struct switch_dev *dev, const struct switch_attr *attr,
216        struct switch_val *val)
217{
218    struct adm6996_priv *priv = to_adm(dev);
219
220    dev_dbg (&priv->phydev->dev, "set_vid port %d vid %d\n", val->port_vlan,
221            val->value.i);
222
223    if (val->value.i > ADM_VLAN_MAX_ID)
224        return -EINVAL;
225
226    priv->vlan_id[val->port_vlan] = val->value.i;
227
228    return 0;
229};
230
231static int
232adm6996_get_vid(struct switch_dev *dev, const struct switch_attr *attr,
233        struct switch_val *val)
234{
235    struct adm6996_priv *priv = to_adm(dev);
236
237    dev_dbg (&priv->phydev->dev, "get_vid port %d\n", val->port_vlan);
238
239    val->value.i = priv->vlan_id[val->port_vlan];
240
241    return 0;
242};
243
244static int
245adm6996_get_ports(struct switch_dev *dev, struct switch_val *val)
246{
247    struct adm6996_priv *priv = to_adm(dev);
248    u8 ports = priv->vlan_table[val->port_vlan];
249    u8 tagged = priv->vlan_tagged[val->port_vlan];
250    int i;
251
252    dev_dbg (&priv->phydev->dev, "get_ports port_vlan %d\n",
253            val->port_vlan);
254
255    val->len = 0;
256
257    for (i = 0; i < ADM_NUM_PORTS; i++) {
258        struct switch_port *p;
259
260        if (!(ports & (1 << i)))
261            continue;
262
263        p = &val->value.ports[val->len++];
264        p->id = i;
265        if (tagged & (1 << i))
266            p->flags = (1 << SWITCH_PORT_FLAG_TAGGED);
267        else
268            p->flags = 0;
269    }
270
271    return 0;
272};
273
274static int
275adm6996_set_ports(struct switch_dev *dev, struct switch_val *val)
276{
277    struct adm6996_priv *priv = to_adm(dev);
278    u8 *ports = &priv->vlan_table[val->port_vlan];
279    u8 *tagged = &priv->vlan_tagged[val->port_vlan];
280    int i;
281
282    dev_dbg (&priv->phydev->dev, "set_ports port_vlan %d ports",
283            val->port_vlan);
284
285    *ports = 0;
286    *tagged = 0;
287
288    for (i = 0; i < val->len; i++) {
289        struct switch_port *p = &val->value.ports[i];
290
291#ifdef DEBUG
292        pr_cont(" %d%s", p->id,
293               ((p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) ? "T" :
294            ""));
295#endif
296
297        if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED))
298            *tagged |= (1 << p->id);
299
300        *ports |= (1 << p->id);
301    }
302
303#ifdef DEBUG
304    pr_cont("\n");
305#endif
306
307    return 0;
308};
309
310/*
311 * Precondition: reg_mutex must be held
312 */
313static void
314adm6996_enable_vlan(struct adm6996_priv *priv)
315{
316    u16 reg;
317
318    reg = r16(priv->phydev, ADM_OTBE_P2_PVID);
319    reg &= ~(ADM_OTBE_MASK);
320    w16(priv->phydev, ADM_OTBE_P2_PVID, reg);
321    reg = r16(priv->phydev, ADM_IFNTE);
322    reg &= ~(ADM_IFNTE_MASK);
323    w16(priv->phydev, ADM_IFNTE, reg);
324    reg = r16(priv->phydev, ADM_VID_CHECK);
325    reg |= ADM_VID_CHECK_MASK;
326    w16(priv->phydev, ADM_VID_CHECK, reg);
327    reg = r16(priv->phydev, ADM_SYSC0);
328    reg |= ADM_NTTE;
329    reg &= ~(ADM_RVID1);
330    w16(priv->phydev, ADM_SYSC0, reg);
331    reg = r16(priv->phydev, ADM_SYSC3);
332    reg |= ADM_TBV;
333    w16(priv->phydev, ADM_SYSC3, reg);
334
335};
336
337/*
338 * Disable VLANs
339 *
340 * Sets VLAN mapping for port-based VLAN with all ports connected to
341 * eachother (this is also the power-on default).
342 *
343 * Precondition: reg_mutex must be held
344 */
345static void
346adm6996_disable_vlan(struct adm6996_priv *priv)
347{
348    u16 reg;
349    int i;
350
351    for (i = 0; i < ADM_NUM_PORTS; i++) {
352        reg = ADM_VLAN_FILT_MEMBER_MASK;
353        w16(priv->phydev, ADM_VLAN_FILT_L(i), reg);
354        reg = ADM_VLAN_FILT_VALID | ADM_VLAN_FILT_VID(1);
355        w16(priv->phydev, ADM_VLAN_FILT_H(i), reg);
356    }
357
358    reg = r16(priv->phydev, ADM_OTBE_P2_PVID);
359    reg |= ADM_OTBE_MASK;
360    w16(priv->phydev, ADM_OTBE_P2_PVID, reg);
361    reg = r16(priv->phydev, ADM_IFNTE);
362    reg |= ADM_IFNTE_MASK;
363    w16(priv->phydev, ADM_IFNTE, reg);
364    reg = r16(priv->phydev, ADM_VID_CHECK);
365    reg &= ~(ADM_VID_CHECK_MASK);
366    w16(priv->phydev, ADM_VID_CHECK, reg);
367    reg = r16(priv->phydev, ADM_SYSC0);
368    reg &= ~(ADM_NTTE);
369    reg |= ADM_RVID1;
370    w16(priv->phydev, ADM_SYSC0, reg);
371    reg = r16(priv->phydev, ADM_SYSC3);
372    reg &= ~(ADM_TBV);
373    w16(priv->phydev, ADM_SYSC3, reg);
374}
375
376/*
377 * Precondition: reg_mutex must be held
378 */
379static void
380adm6996_apply_port_pvids(struct adm6996_priv *priv)
381{
382    u16 reg;
383    int i;
384
385    for (i = 0; i < ADM_NUM_PORTS; i++) {
386        reg = r16(priv->phydev, adm_portcfg[i]);
387        reg &= ~(ADM_PORTCFG_PVID_MASK);
388        reg |= ADM_PORTCFG_PVID(priv->pvid[i]);
389        w16(priv->phydev, adm_portcfg[i], reg);
390    }
391
392    w16(priv->phydev, ADM_P0_PVID, ADM_P0_PVID_VAL(priv->pvid[0]));
393    w16(priv->phydev, ADM_P1_PVID, ADM_P1_PVID_VAL(priv->pvid[1]));
394    reg = r16(priv->phydev, ADM_OTBE_P2_PVID);
395    reg &= ~(ADM_P2_PVID_MASK);
396    reg |= ADM_P2_PVID_VAL(priv->pvid[2]);
397    w16(priv->phydev, ADM_OTBE_P2_PVID, reg);
398    reg = ADM_P3_PVID_VAL(priv->pvid[3]);
399    reg |= ADM_P4_PVID_VAL(priv->pvid[4]);
400    w16(priv->phydev, ADM_P3_P4_PVID, reg);
401    w16(priv->phydev, ADM_P5_PVID, ADM_P5_PVID_VAL(priv->pvid[5]));
402}
403
404/*
405 * Precondition: reg_mutex must be held
406 */
407static void
408adm6996_apply_vlan_filters(struct adm6996_priv *priv)
409{
410    u8 ports, tagged;
411    u16 vid, reg;
412    int i;
413
414    for (i = 0; i < ADM_NUM_VLANS; i++) {
415        vid = priv->vlan_id[i];
416        ports = priv->vlan_table[i];
417        tagged = priv->vlan_tagged[i];
418
419        if (ports == 0) {
420            /* Disable VLAN entry */
421            w16(priv->phydev, ADM_VLAN_FILT_H(i), 0);
422            w16(priv->phydev, ADM_VLAN_FILT_L(i), 0);
423            continue;
424        }
425
426        reg = ADM_VLAN_FILT_MEMBER(ports);
427        reg |= ADM_VLAN_FILT_TAGGED(tagged);
428        w16(priv->phydev, ADM_VLAN_FILT_L(i), reg);
429        reg = ADM_VLAN_FILT_VALID | ADM_VLAN_FILT_VID(vid);
430        w16(priv->phydev, ADM_VLAN_FILT_H(i), reg);
431    }
432}
433
434static int
435adm6996_hw_apply(struct switch_dev *dev)
436{
437    struct adm6996_priv *priv = to_adm(dev);
438
439    dev_dbg(&priv->phydev->dev, "hw_apply\n");
440
441    mutex_lock(&priv->reg_mutex);
442
443    if (!priv->enable_vlan) {
444        if (priv->vlan_enabled) {
445            adm6996_disable_vlan(priv);
446            priv->vlan_enabled = 0;
447        }
448        goto out;
449    }
450
451    if (!priv->vlan_enabled) {
452        adm6996_enable_vlan(priv);
453        priv->vlan_enabled = 1;
454    }
455
456    adm6996_apply_port_pvids(priv);
457    adm6996_apply_vlan_filters(priv);
458
459out:
460    mutex_unlock(&priv->reg_mutex);
461
462    return 0;
463}
464
465/*
466 * Reset the switch
467 *
468 * The ADM6996 can't do a software-initiated reset, so we just initialise the
469 * registers we support in this driver.
470 *
471 * Precondition: reg_mutex must be held
472 */
473static void
474adm6996_perform_reset (struct adm6996_priv *priv)
475{
476    int i;
477
478    /* initialize port and vlan settings */
479    for (i = 0; i < ADM_NUM_PORTS - 1; i++) {
480        w16(priv->phydev, adm_portcfg[i], ADM_PORTCFG_INIT |
481            ADM_PORTCFG_PVID(0));
482    }
483    w16(priv->phydev, adm_portcfg[5], ADM_PORTCFG_CPU);
484
485    /* reset all PHY ports */
486    for (i = 0; i < ADM_PHY_PORTS; i++) {
487        w16(priv->phydev, ADM_PHY_PORT(i), ADM_PHYCFG_INIT);
488    }
489
490    priv->enable_vlan = 0;
491    priv->vlan_enabled = 0;
492
493    for (i = 0; i < ADM_NUM_PORTS; i++) {
494        priv->pvid[i] = 0;
495    }
496
497    for (i = 0; i < ADM_NUM_VLANS; i++) {
498        priv->vlan_id[i] = i;
499        priv->vlan_table[i] = 0;
500        priv->vlan_tagged[i] = 0;
501    }
502
503    if (priv->model == ADM6996M) {
504        /* Clear VLAN priority map so prio's are unused */
505        w16 (priv->phydev, ADM_VLAN_PRIOMAP, 0);
506
507        adm6996_disable_vlan(priv);
508        adm6996_apply_port_pvids(priv);
509    }
510}
511
512static int
513adm6996_reset_switch(struct switch_dev *dev)
514{
515    struct adm6996_priv *priv = to_adm(dev);
516
517    dev_dbg (&priv->phydev->dev, "reset\n");
518    mutex_lock(&priv->reg_mutex);
519    adm6996_perform_reset (priv);
520    mutex_unlock(&priv->reg_mutex);
521    return 0;
522}
523
524static struct switch_attr adm6996_globals[] = {
525    {
526     .type = SWITCH_TYPE_INT,
527     .name = "enable_vlan",
528     .description = "Enable VLANs",
529     .set = adm6996_set_enable_vlan,
530     .get = adm6996_get_enable_vlan,
531    },
532#ifdef DEBUG
533    {
534     .type = SWITCH_TYPE_INT,
535     .name = "addr",
536     .description =
537     "Direct register access: set register address (0 - 1023)",
538     .set = adm6996_set_addr,
539     .get = adm6996_get_addr,
540     },
541    {
542     .type = SWITCH_TYPE_INT,
543     .name = "data",
544     .description =
545     "Direct register access: read/write to register (0 - 65535)",
546     .set = adm6996_set_data,
547     .get = adm6996_get_data,
548     },
549#endif /* def DEBUG */
550};
551
552static struct switch_attr adm6996_port[] = {
553};
554
555static struct switch_attr adm6996_vlan[] = {
556    {
557     .type = SWITCH_TYPE_INT,
558     .name = "vid",
559     .description = "VLAN ID",
560     .set = adm6996_set_vid,
561     .get = adm6996_get_vid,
562     },
563};
564
565static const struct switch_dev_ops adm6996_ops = {
566    .attr_global = {
567            .attr = adm6996_globals,
568            .n_attr = ARRAY_SIZE(adm6996_globals),
569            },
570    .attr_port = {
571              .attr = adm6996_port,
572              .n_attr = ARRAY_SIZE(adm6996_port),
573              },
574    .attr_vlan = {
575              .attr = adm6996_vlan,
576              .n_attr = ARRAY_SIZE(adm6996_vlan),
577              },
578    .get_port_pvid = adm6996_get_pvid,
579    .set_port_pvid = adm6996_set_pvid,
580    .get_vlan_ports = adm6996_get_ports,
581    .set_vlan_ports = adm6996_set_ports,
582    .apply_config = adm6996_hw_apply,
583    .reset_switch = adm6996_reset_switch,
584};
585
586static int adm6996_config_init(struct phy_device *pdev)
587{
588    struct adm6996_priv *priv;
589    struct switch_dev *swdev;
590
591    int ret;
592    u16 test, old;
593
594    pdev->supported = ADVERTISED_100baseT_Full;
595    pdev->advertising = ADVERTISED_100baseT_Full;
596
597    if (pdev->addr != 0) {
598        pr_info ("%s: PHY overlaps ADM6996, providing fixed PHY 0x%x.\n"
599                , pdev->attached_dev->name, pdev->addr);
600        return 0;
601    }
602
603    priv = kzalloc(sizeof(struct adm6996_priv), GFP_KERNEL);
604    if (priv == NULL)
605        return -ENOMEM;
606
607    mutex_init(&priv->reg_mutex);
608    priv->phydev = pdev;
609    priv->read = adm6996_read_mii_reg;
610    priv->write = adm6996_write_mii_reg;
611    pdev->priv = priv;
612
613    /* Detect type of chip */
614    old = r16(pdev, ADM_VID_CHECK);
615    test = old ^ (1 << 12);
616    w16(pdev, ADM_VID_CHECK, test);
617    test ^= r16(pdev, ADM_VID_CHECK);
618    if (test & (1 << 12)) {
619        /*
620         * Bit 12 of this register is read-only.
621         * This is the FC model.
622         */
623        priv->model = ADM6996FC;
624    } else {
625        /* Bit 12 is read-write. This is the M model. */
626        priv->model = ADM6996M;
627        w16(pdev, ADM_VID_CHECK, old);
628    }
629
630    swdev = &priv->dev;
631    swdev->name = (adm6996_model_name[priv->model]);
632    swdev->cpu_port = ADM_CPU_PORT;
633    swdev->ports = ADM_NUM_PORTS;
634    swdev->vlans = ADM_NUM_VLANS;
635    swdev->ops = &adm6996_ops;
636
637    pr_info ("%s: %s model PHY found.\n", pdev->attached_dev->name,
638            swdev->name);
639
640    mutex_lock(&priv->reg_mutex);
641    adm6996_perform_reset (priv);
642    mutex_unlock(&priv->reg_mutex);
643
644    if (priv->model == ADM6996M) {
645        if ((ret = register_switch(swdev, pdev->attached_dev)) < 0) {
646            kfree(priv);
647            return ret;
648        }
649    }
650
651    return 0;
652}
653
654/*
655 * Warning: phydev->priv is NULL if phydev->addr != 0
656 */
657static int adm6996_read_status(struct phy_device *phydev)
658{
659    phydev->speed = SPEED_100;
660    phydev->duplex = DUPLEX_FULL;
661    phydev->link = 1;
662    return 0;
663}
664
665/*
666 * Warning: phydev->priv is NULL if phydev->addr != 0
667 */
668static int adm6996_config_aneg(struct phy_device *phydev)
669{
670    return 0;
671}
672
673static int adm6996_fixup(struct phy_device *dev)
674{
675    struct mii_bus *bus = dev->bus;
676    u16 reg;
677
678    /* Our custom registers are at PHY addresses 0-10. Claim those. */
679    if (dev->addr > 10)
680        return 0;
681
682    /* look for the switch on the bus */
683    reg = bus->read(bus, PHYADDR(ADM_SIG0)) & ADM_SIG0_MASK;
684    if (reg != ADM_SIG0_VAL)
685        return 0;
686
687    reg = bus->read(bus, PHYADDR(ADM_SIG1)) & ADM_SIG1_MASK;
688    if (reg != ADM_SIG1_VAL)
689        return 0;
690
691    dev->phy_id = (ADM_SIG0_VAL << 16) | ADM_SIG1_VAL;
692
693    return 0;
694}
695
696static int adm6996_probe(struct phy_device *pdev)
697{
698    return 0;
699}
700
701static void adm6996_remove(struct phy_device *pdev)
702{
703    struct adm6996_priv *priv = phy_to_adm(pdev);
704
705    if (priv != NULL && priv->model == ADM6996M)
706        unregister_switch(&priv->dev);
707
708    kfree(priv);
709}
710
711
712static struct phy_driver adm6996_driver = {
713    .name = "Infineon ADM6996",
714    .phy_id = (ADM_SIG0_VAL << 16) | ADM_SIG1_VAL,
715    .phy_id_mask = 0xffffffff,
716    .features = PHY_BASIC_FEATURES,
717    .probe = adm6996_probe,
718    .remove = adm6996_remove,
719    .config_init = &adm6996_config_init,
720    .config_aneg = &adm6996_config_aneg,
721    .read_status = &adm6996_read_status,
722    .driver = { .owner = THIS_MODULE,},
723};
724
725static int __init adm6996_init(void)
726{
727    phy_register_fixup_for_id(PHY_ANY_ID, adm6996_fixup);
728    return phy_driver_register(&adm6996_driver);
729}
730
731static void __exit adm6996_exit(void)
732{
733    phy_driver_unregister(&adm6996_driver);
734}
735
736module_init(adm6996_init);
737module_exit(adm6996_exit);
738

Archive Download this file



interactive