2 * Lantiq PSB6970 (Tantos) Switch driver
4 * Copyright (c) 2009,2010 Team Embedded.
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.
10 * The switch programming done in this driver follows the
11 * "Ethernet Traffic Separation using VLAN" Application Note as
12 * published by Lantiq.
15 #include <linux/module.h>
16 #include <linux/netdevice.h>
17 #include <linux/switch.h>
18 #include <linux/phy.h>
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)
25 #define PHYADDR(_reg) ((_reg >> 5) & 0xff), (_reg & 0x1f)
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
34 /* --- VLAN filter table --- */
35 #define PSB6970_VFxL(i) ((i)*2+0x10) /* VLAN Filter Low */
36 #define PSB6970_VFxL_VV (1 << 15) /* VLAN_Valid */
38 #define PSB6970_VFxH(i) ((i)*2+0x11) /* VLAN Filter High */
39 #define PSB6970_VFxH_TM_SHIFT 7 /* Tagged Member */
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 */
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 */
52 #define PSB6970_DVID(p) ((p)*0x20+4) /* Default VLAN ID & Priority */
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;
61 /* all fields below are cleared on reset */
63 u16 vlan_id[PSB6970_MAX_VLANS];
64 u8 vlan_table[PSB6970_MAX_VLANS];
66 u16 pvid[PSB6970_NUM_PORTS];
69 #define to_psb6970(_dev) container_of(_dev, struct psb6970_priv, dev)
71 static u16 psb6970_mii_read(struct phy_device *phydev, int reg)
73 struct mii_bus *bus = phydev->mdio.bus;
75 return bus->read(bus, PHYADDR(reg));
78 static void psb6970_mii_write(struct phy_device *phydev, int reg, u16 val)
80 struct mii_bus *bus = phydev->mdio.bus;
82 bus->write(bus, PHYADDR(reg), val);
86 psb6970_set_vlan(struct switch_dev *dev, const struct switch_attr *attr,
87 struct switch_val *val)
89 struct psb6970_priv *priv = to_psb6970(dev);
90 priv->vlan = !!val->value.i;
95 psb6970_get_vlan(struct switch_dev *dev, const struct switch_attr *attr,
96 struct switch_val *val)
98 struct psb6970_priv *priv = to_psb6970(dev);
99 val->value.i = priv->vlan;
103 static int psb6970_set_pvid(struct switch_dev *dev, int port, int vlan)
105 struct psb6970_priv *priv = to_psb6970(dev);
107 /* make sure no invalid PVIDs get set */
108 if (vlan >= dev->vlans)
111 priv->pvid[port] = vlan;
115 static int psb6970_get_pvid(struct switch_dev *dev, int port, int *vlan)
117 struct psb6970_priv *priv = to_psb6970(dev);
118 *vlan = priv->pvid[port];
123 psb6970_set_vid(struct switch_dev *dev, const struct switch_attr *attr,
124 struct switch_val *val)
126 struct psb6970_priv *priv = to_psb6970(dev);
127 priv->vlan_id[val->port_vlan] = val->value.i;
132 psb6970_get_vid(struct switch_dev *dev, const struct switch_attr *attr,
133 struct switch_val *val)
135 struct psb6970_priv *priv = to_psb6970(dev);
136 val->value.i = priv->vlan_id[val->port_vlan];
140 static struct switch_attr psb6970_globals[] = {
142 .type = SWITCH_TYPE_INT,
143 .name = "enable_vlan",
144 .description = "Enable VLAN mode",
145 .set = psb6970_set_vlan,
146 .get = psb6970_get_vlan,
150 static struct switch_attr psb6970_port[] = {
153 static struct switch_attr psb6970_vlan[] = {
155 .type = SWITCH_TYPE_INT,
157 .description = "VLAN ID (0-4094)",
158 .set = psb6970_set_vid,
159 .get = psb6970_get_vid,
164 static int psb6970_get_ports(struct switch_dev *dev, struct switch_val *val)
166 struct psb6970_priv *priv = to_psb6970(dev);
167 u8 ports = priv->vlan_table[val->port_vlan];
171 for (i = 0; i < PSB6970_NUM_PORTS; i++) {
172 struct switch_port *p;
174 if (!(ports & (1 << i)))
177 p = &val->value.ports[val->len++];
179 if (priv->vlan_tagged & (1 << i))
180 p->flags = (1 << SWITCH_PORT_FLAG_TAGGED);
187 static int psb6970_set_ports(struct switch_dev *dev, struct switch_val *val)
189 struct psb6970_priv *priv = to_psb6970(dev);
190 u8 *vt = &priv->vlan_table[val->port_vlan];
194 for (i = 0; i < val->len; i++) {
195 struct switch_port *p = &val->value.ports[i];
197 if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED))
198 priv->vlan_tagged |= (1 << p->id);
200 priv->vlan_tagged &= ~(1 << p->id);
201 priv->pvid[p->id] = val->port_vlan;
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)
208 priv->vlan_table[j] &= ~(1 << p->id);
217 static int psb6970_hw_apply(struct switch_dev *dev)
219 struct psb6970_priv *priv = to_psb6970(dev);
222 mutex_lock(&priv->reg_mutex);
225 /* into the vlan translation unit */
226 for (j = 0; j < PSB6970_MAX_VLANS; j++) {
227 u8 vp = priv->vlan_table[j];
230 priv->write(priv->phy, PSB6970_VFxL(j),
231 PSB6970_VFxL_VV | priv->vlan_id[j]);
232 priv->write(priv->phy, PSB6970_VFxH(j),
235 PSB6970_VFxH_TM_SHIFT) | vp);
236 } else /* clear VLAN Valid flag for unused vlans */
237 priv->write(priv->phy, PSB6970_VFxL(j), 0);
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;
247 ec = PSB6970_EC_IFNTE;
248 dvid = priv->vlan_id[priv->pvid[i]];
249 pbvm |= PSB6970_PBVM_TBVE | PSB6970_PBVM_VMCE;
251 if ((i << 1) & priv->vlan_tagged)
252 pbvm |= PSB6970_PBVM_AOVTP | PSB6970_PBVM_VC;
255 priv->write(priv->phy, PSB6970_PBVM(i), pbvm);
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);
263 mutex_unlock(&priv->reg_mutex);
267 static int psb6970_reset_switch(struct switch_dev *dev)
269 struct psb6970_priv *priv = to_psb6970(dev);
272 mutex_lock(&priv->reg_mutex);
274 memset(&priv->vlan, 0, sizeof(struct psb6970_priv) -
275 offsetof(struct psb6970_priv, vlan));
277 for (i = 0; i < PSB6970_MAX_VLANS; i++)
278 priv->vlan_id[i] = i;
280 mutex_unlock(&priv->reg_mutex);
282 return psb6970_hw_apply(dev);
285 static const struct switch_dev_ops psb6970_ops = {
287 .attr = psb6970_globals,
288 .n_attr = ARRAY_SIZE(psb6970_globals),
291 .attr = psb6970_port,
292 .n_attr = ARRAY_SIZE(psb6970_port),
295 .attr = psb6970_vlan,
296 .n_attr = ARRAY_SIZE(psb6970_vlan),
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,
306 static int psb6970_config_init(struct phy_device *pdev)
308 struct psb6970_priv *priv;
309 struct net_device *dev = pdev->attached_dev;
310 struct switch_dev *swdev;
313 priv = kzalloc(sizeof(struct psb6970_priv), GFP_KERNEL);
319 if (pdev->mdio.addr == 0)
320 printk(KERN_INFO "%s: psb6970 switch driver attached.\n",
321 pdev->attached_dev->name);
323 if (pdev->mdio.addr != 0) {
328 pdev->supported = pdev->advertising = SUPPORTED_100baseT_Full;
330 mutex_init(&priv->reg_mutex);
331 priv->read = psb6970_mii_read;
332 priv->write = psb6970_mii_write;
337 swdev->cpu_port = PSB6970_DEFAULT_PORT_CPU;
338 swdev->ops = &psb6970_ops;
340 swdev->name = "Lantiq PSB6970";
341 swdev->vlans = PSB6970_MAX_VLANS;
342 swdev->ports = PSB6970_NUM_PORTS;
344 if ((ret = register_switch(&priv->dev, pdev->attached_dev)) < 0) {
349 ret = psb6970_reset_switch(&priv->dev);
361 static int psb6970_read_status(struct phy_device *phydev)
363 phydev->speed = SPEED_100;
364 phydev->duplex = DUPLEX_FULL;
367 phydev->state = PHY_RUNNING;
368 netif_carrier_on(phydev->attached_dev);
369 phydev->adjust_link(phydev->attached_dev);
374 static int psb6970_config_aneg(struct phy_device *phydev)
379 static int psb6970_probe(struct phy_device *pdev)
384 static void psb6970_remove(struct phy_device *pdev)
386 struct psb6970_priv *priv = pdev->priv;
391 if (pdev->mdio.addr == 0)
392 unregister_switch(&priv->dev);
396 static int psb6970_fixup(struct phy_device *dev)
398 struct mii_bus *bus = dev->mdio.bus;
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)
406 dev->phy_id = (reg << 16);
407 dev->phy_id |= bus->read(bus, PHYADDR(PSB6970_CI0)) & PSB6970_CI0_MASK;
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,
424 int __init psb6970_init(void)
426 phy_register_fixup_for_id(PHY_ANY_ID, psb6970_fixup);
427 return phy_driver_register(&psb6970_driver, THIS_MODULE);
430 module_init(psb6970_init);
432 void __exit psb6970_exit(void)
434 phy_driver_unregister(&psb6970_driver);
437 module_exit(psb6970_exit);
439 MODULE_DESCRIPTION("Lantiq PSB6970 Switch");
440 MODULE_AUTHOR("Ithamar R. Adema <ithamar.adema@team-embedded.nl>");
441 MODULE_LICENSE("GPL");