v1.5 branch refresh based upon upstream master @ c8677ca89e53e3be7988d54280fce166cc894a7e
[librecmc/librecmc.git] / target / linux / generic / files / drivers / net / phy / psb6970.c
1 /*
2  * Lantiq PSB6970 (Tantos) Switch driver
3  *
4  * Copyright (c) 2009,2010 Team Embedded.
5  *
6  * This program is free software; you can redistribute  it and/or modify it
7  * under  the terms of the GNU General Public License v2 as published by the
8  * Free Software Foundation.
9  *
10  * The switch programming done in this driver follows the 
11  * "Ethernet Traffic Separation using VLAN" Application Note as
12  * published by Lantiq.
13  */
14
15 #include <linux/module.h>
16 #include <linux/netdevice.h>
17 #include <linux/switch.h>
18 #include <linux/phy.h>
19
20 #define PSB6970_MAX_VLANS               16
21 #define PSB6970_NUM_PORTS               7
22 #define PSB6970_DEFAULT_PORT_CPU        6
23 #define PSB6970_IS_CPU_PORT(x)          ((x) > 4)
24
25 #define PHYADDR(_reg)           ((_reg >> 5) & 0xff), (_reg & 0x1f)
26
27 /* --- Identification --- */
28 #define PSB6970_CI0             0x0100
29 #define PSB6970_CI0_MASK        0x000f
30 #define PSB6970_CI1             0x0101
31 #define PSB6970_CI1_VAL         0x2599
32 #define PSB6970_CI1_MASK        0xffff
33
34 /* --- VLAN filter table --- */
35 #define PSB6970_VFxL(i)         ((i)*2+0x10)    /* VLAN Filter Low */
36 #define PSB6970_VFxL_VV         (1 << 15)       /* VLAN_Valid */
37
38 #define PSB6970_VFxH(i)         ((i)*2+0x11)    /* VLAN Filter High */
39 #define PSB6970_VFxH_TM_SHIFT   7               /* Tagged Member */
40
41 /* --- Port registers --- */
42 #define PSB6970_EC(p)           ((p)*0x20+2)    /* Extended Control */
43 #define PSB6970_EC_IFNTE        (1 << 1)        /* Input Force No Tag Enable */
44
45 #define PSB6970_PBVM(p)         ((p)*0x20+3)    /* Port Base VLAN Map */
46 #define PSB6970_PBVM_VMCE       (1 << 8)
47 #define PSB6970_PBVM_AOVTP      (1 << 9)
48 #define PSB6970_PBVM_VSD        (1 << 10)
49 #define PSB6970_PBVM_VC         (1 << 11)       /* VID Check with VID table */
50 #define PSB6970_PBVM_TBVE       (1 << 13)       /* Tag-Based VLAN enable */
51
52 #define PSB6970_DVID(p)         ((p)*0x20+4)    /* Default VLAN ID & Priority */
53
54 struct psb6970_priv {
55         struct switch_dev dev;
56         struct phy_device *phy;
57         u16 (*read) (struct phy_device* phydev, int reg);
58         void (*write) (struct phy_device* phydev, int reg, u16 val);
59         struct mutex reg_mutex;
60
61         /* all fields below are cleared on reset */
62         bool vlan;
63         u16 vlan_id[PSB6970_MAX_VLANS];
64         u8 vlan_table[PSB6970_MAX_VLANS];
65         u8 vlan_tagged;
66         u16 pvid[PSB6970_NUM_PORTS];
67 };
68
69 #define to_psb6970(_dev) container_of(_dev, struct psb6970_priv, dev)
70
71 static u16 psb6970_mii_read(struct phy_device *phydev, int reg)
72 {
73         struct mii_bus *bus = phydev->mdio.bus;
74
75         return bus->read(bus, PHYADDR(reg));
76 }
77
78 static void psb6970_mii_write(struct phy_device *phydev, int reg, u16 val)
79 {
80         struct mii_bus *bus = phydev->mdio.bus;
81
82         bus->write(bus, PHYADDR(reg), val);
83 }
84
85 static int
86 psb6970_set_vlan(struct switch_dev *dev, const struct switch_attr *attr,
87                  struct switch_val *val)
88 {
89         struct psb6970_priv *priv = to_psb6970(dev);
90         priv->vlan = !!val->value.i;
91         return 0;
92 }
93
94 static int
95 psb6970_get_vlan(struct switch_dev *dev, const struct switch_attr *attr,
96                  struct switch_val *val)
97 {
98         struct psb6970_priv *priv = to_psb6970(dev);
99         val->value.i = priv->vlan;
100         return 0;
101 }
102
103 static int psb6970_set_pvid(struct switch_dev *dev, int port, int vlan)
104 {
105         struct psb6970_priv *priv = to_psb6970(dev);
106
107         /* make sure no invalid PVIDs get set */
108         if (vlan >= dev->vlans)
109                 return -EINVAL;
110
111         priv->pvid[port] = vlan;
112         return 0;
113 }
114
115 static int psb6970_get_pvid(struct switch_dev *dev, int port, int *vlan)
116 {
117         struct psb6970_priv *priv = to_psb6970(dev);
118         *vlan = priv->pvid[port];
119         return 0;
120 }
121
122 static int
123 psb6970_set_vid(struct switch_dev *dev, const struct switch_attr *attr,
124                 struct switch_val *val)
125 {
126         struct psb6970_priv *priv = to_psb6970(dev);
127         priv->vlan_id[val->port_vlan] = val->value.i;
128         return 0;
129 }
130
131 static int
132 psb6970_get_vid(struct switch_dev *dev, const struct switch_attr *attr,
133                 struct switch_val *val)
134 {
135         struct psb6970_priv *priv = to_psb6970(dev);
136         val->value.i = priv->vlan_id[val->port_vlan];
137         return 0;
138 }
139
140 static struct switch_attr psb6970_globals[] = {
141         {
142          .type = SWITCH_TYPE_INT,
143          .name = "enable_vlan",
144          .description = "Enable VLAN mode",
145          .set = psb6970_set_vlan,
146          .get = psb6970_get_vlan,
147          .max = 1},
148 };
149
150 static struct switch_attr psb6970_port[] = {
151 };
152
153 static struct switch_attr psb6970_vlan[] = {
154         {
155          .type = SWITCH_TYPE_INT,
156          .name = "vid",
157          .description = "VLAN ID (0-4094)",
158          .set = psb6970_set_vid,
159          .get = psb6970_get_vid,
160          .max = 4094,
161          },
162 };
163
164 static int psb6970_get_ports(struct switch_dev *dev, struct switch_val *val)
165 {
166         struct psb6970_priv *priv = to_psb6970(dev);
167         u8 ports = priv->vlan_table[val->port_vlan];
168         int i;
169
170         val->len = 0;
171         for (i = 0; i < PSB6970_NUM_PORTS; i++) {
172                 struct switch_port *p;
173
174                 if (!(ports & (1 << i)))
175                         continue;
176
177                 p = &val->value.ports[val->len++];
178                 p->id = i;
179                 if (priv->vlan_tagged & (1 << i))
180                         p->flags = (1 << SWITCH_PORT_FLAG_TAGGED);
181                 else
182                         p->flags = 0;
183         }
184         return 0;
185 }
186
187 static int psb6970_set_ports(struct switch_dev *dev, struct switch_val *val)
188 {
189         struct psb6970_priv *priv = to_psb6970(dev);
190         u8 *vt = &priv->vlan_table[val->port_vlan];
191         int i, j;
192
193         *vt = 0;
194         for (i = 0; i < val->len; i++) {
195                 struct switch_port *p = &val->value.ports[i];
196
197                 if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED))
198                         priv->vlan_tagged |= (1 << p->id);
199                 else {
200                         priv->vlan_tagged &= ~(1 << p->id);
201                         priv->pvid[p->id] = val->port_vlan;
202
203                         /* make sure that an untagged port does not
204                          * appear in other vlans */
205                         for (j = 0; j < PSB6970_MAX_VLANS; j++) {
206                                 if (j == val->port_vlan)
207                                         continue;
208                                 priv->vlan_table[j] &= ~(1 << p->id);
209                         }
210                 }
211
212                 *vt |= 1 << p->id;
213         }
214         return 0;
215 }
216
217 static int psb6970_hw_apply(struct switch_dev *dev)
218 {
219         struct psb6970_priv *priv = to_psb6970(dev);
220         int i, j;
221
222         mutex_lock(&priv->reg_mutex);
223
224         if (priv->vlan) {
225                 /* into the vlan translation unit */
226                 for (j = 0; j < PSB6970_MAX_VLANS; j++) {
227                         u8 vp = priv->vlan_table[j];
228
229                         if (vp) {
230                                 priv->write(priv->phy, PSB6970_VFxL(j),
231                                             PSB6970_VFxL_VV | priv->vlan_id[j]);
232                                 priv->write(priv->phy, PSB6970_VFxH(j),
233                                             ((vp & priv->
234                                               vlan_tagged) <<
235                                              PSB6970_VFxH_TM_SHIFT) | vp);
236                         } else  /* clear VLAN Valid flag for unused vlans */
237                                 priv->write(priv->phy, PSB6970_VFxL(j), 0);
238
239                 }
240         }
241
242         /* update the port destination mask registers and tag settings */
243         for (i = 0; i < PSB6970_NUM_PORTS; i++) {
244                 int dvid = 1, pbvm = 0x7f | PSB6970_PBVM_VSD, ec = 0;
245
246                 if (priv->vlan) {
247                         ec = PSB6970_EC_IFNTE;
248                         dvid = priv->vlan_id[priv->pvid[i]];
249                         pbvm |= PSB6970_PBVM_TBVE | PSB6970_PBVM_VMCE;
250
251                         if ((i << 1) & priv->vlan_tagged)
252                                 pbvm |= PSB6970_PBVM_AOVTP | PSB6970_PBVM_VC;
253                 }
254
255                 priv->write(priv->phy, PSB6970_PBVM(i), pbvm);
256
257                 if (!PSB6970_IS_CPU_PORT(i)) {
258                         priv->write(priv->phy, PSB6970_EC(i), ec);
259                         priv->write(priv->phy, PSB6970_DVID(i), dvid);
260                 }
261         }
262
263         mutex_unlock(&priv->reg_mutex);
264         return 0;
265 }
266
267 static int psb6970_reset_switch(struct switch_dev *dev)
268 {
269         struct psb6970_priv *priv = to_psb6970(dev);
270         int i;
271
272         mutex_lock(&priv->reg_mutex);
273
274         memset(&priv->vlan, 0, sizeof(struct psb6970_priv) -
275                offsetof(struct psb6970_priv, vlan));
276
277         for (i = 0; i < PSB6970_MAX_VLANS; i++)
278                 priv->vlan_id[i] = i;
279
280         mutex_unlock(&priv->reg_mutex);
281
282         return psb6970_hw_apply(dev);
283 }
284
285 static const struct switch_dev_ops psb6970_ops = {
286         .attr_global = {
287                         .attr = psb6970_globals,
288                         .n_attr = ARRAY_SIZE(psb6970_globals),
289                         },
290         .attr_port = {
291                       .attr = psb6970_port,
292                       .n_attr = ARRAY_SIZE(psb6970_port),
293                       },
294         .attr_vlan = {
295                       .attr = psb6970_vlan,
296                       .n_attr = ARRAY_SIZE(psb6970_vlan),
297                       },
298         .get_port_pvid = psb6970_get_pvid,
299         .set_port_pvid = psb6970_set_pvid,
300         .get_vlan_ports = psb6970_get_ports,
301         .set_vlan_ports = psb6970_set_ports,
302         .apply_config = psb6970_hw_apply,
303         .reset_switch = psb6970_reset_switch,
304 };
305
306 static int psb6970_config_init(struct phy_device *pdev)
307 {
308         struct psb6970_priv *priv;
309         struct net_device *dev = pdev->attached_dev;
310         struct switch_dev *swdev;
311         int ret;
312
313         priv = kzalloc(sizeof(struct psb6970_priv), GFP_KERNEL);
314         if (priv == NULL)
315                 return -ENOMEM;
316
317         priv->phy = pdev;
318
319         if (pdev->mdio.addr == 0)
320                 printk(KERN_INFO "%s: psb6970 switch driver attached.\n",
321                        pdev->attached_dev->name);
322
323         if (pdev->mdio.addr != 0) {
324                 kfree(priv);
325                 return 0;
326         }
327
328         pdev->supported = pdev->advertising = SUPPORTED_100baseT_Full;
329
330         mutex_init(&priv->reg_mutex);
331         priv->read = psb6970_mii_read;
332         priv->write = psb6970_mii_write;
333
334         pdev->priv = priv;
335
336         swdev = &priv->dev;
337         swdev->cpu_port = PSB6970_DEFAULT_PORT_CPU;
338         swdev->ops = &psb6970_ops;
339
340         swdev->name = "Lantiq PSB6970";
341         swdev->vlans = PSB6970_MAX_VLANS;
342         swdev->ports = PSB6970_NUM_PORTS;
343
344         if ((ret = register_switch(&priv->dev, pdev->attached_dev)) < 0) {
345                 kfree(priv);
346                 goto done;
347         }
348
349         ret = psb6970_reset_switch(&priv->dev);
350         if (ret) {
351                 kfree(priv);
352                 goto done;
353         }
354
355         dev->phy_ptr = priv;
356
357 done:
358         return ret;
359 }
360
361 static int psb6970_read_status(struct phy_device *phydev)
362 {
363         phydev->speed = SPEED_100;
364         phydev->duplex = DUPLEX_FULL;
365         phydev->link = 1;
366
367         phydev->state = PHY_RUNNING;
368         netif_carrier_on(phydev->attached_dev);
369         phydev->adjust_link(phydev->attached_dev);
370
371         return 0;
372 }
373
374 static int psb6970_config_aneg(struct phy_device *phydev)
375 {
376         return 0;
377 }
378
379 static int psb6970_probe(struct phy_device *pdev)
380 {
381         return 0;
382 }
383
384 static void psb6970_remove(struct phy_device *pdev)
385 {
386         struct psb6970_priv *priv = pdev->priv;
387
388         if (!priv)
389                 return;
390
391         if (pdev->mdio.addr == 0)
392                 unregister_switch(&priv->dev);
393         kfree(priv);
394 }
395
396 static int psb6970_fixup(struct phy_device *dev)
397 {
398         struct mii_bus *bus = dev->mdio.bus;
399         u16 reg;
400
401         /* look for the switch on the bus */
402         reg = bus->read(bus, PHYADDR(PSB6970_CI1)) & PSB6970_CI1_MASK;
403         if (reg != PSB6970_CI1_VAL)
404                 return 0;
405
406         dev->phy_id = (reg << 16);
407         dev->phy_id |= bus->read(bus, PHYADDR(PSB6970_CI0)) & PSB6970_CI0_MASK;
408
409         return 0;
410 }
411
412 static struct phy_driver psb6970_driver = {
413         .name = "Lantiq PSB6970",
414         .phy_id = PSB6970_CI1_VAL << 16,
415         .phy_id_mask = 0xffff0000,
416         .features = PHY_BASIC_FEATURES,
417         .probe = psb6970_probe,
418         .remove = psb6970_remove,
419         .config_init = &psb6970_config_init,
420         .config_aneg = &psb6970_config_aneg,
421         .read_status = &psb6970_read_status,
422 };
423
424 int __init psb6970_init(void)
425 {
426         phy_register_fixup_for_id(PHY_ANY_ID, psb6970_fixup);
427         return phy_driver_register(&psb6970_driver, THIS_MODULE);
428 }
429
430 module_init(psb6970_init);
431
432 void __exit psb6970_exit(void)
433 {
434         phy_driver_unregister(&psb6970_driver);
435 }
436
437 module_exit(psb6970_exit);
438
439 MODULE_DESCRIPTION("Lantiq PSB6970 Switch");
440 MODULE_AUTHOR("Ithamar R. Adema <ithamar.adema@team-embedded.nl>");
441 MODULE_LICENSE("GPL");