|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
/*
|
|
|
|
|
* Marvell 88E6171 switch driver
|
|
|
|
|
* Marvell 88E61xx switch driver
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
|
|
|
|
|
*
|
|
|
|
@ -23,12 +23,12 @@
|
|
|
|
|
#include <linux/device.h>
|
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
|
|
|
|
|
|
#include "mvsw6171.h"
|
|
|
|
|
#include "mvsw61xx.h"
|
|
|
|
|
|
|
|
|
|
MODULE_DESCRIPTION("Marvell 88E6171 Switch driver");
|
|
|
|
|
MODULE_DESCRIPTION("Marvell 88E61xx Switch driver");
|
|
|
|
|
MODULE_AUTHOR("Claudio Leite <leitec@staticky.com>");
|
|
|
|
|
MODULE_LICENSE("GPL v2");
|
|
|
|
|
MODULE_ALIAS("platform:mvsw6171");
|
|
|
|
|
MODULE_ALIAS("platform:mvsw61xx");
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Register access is done through direct or indirect addressing,
|
|
|
|
@ -43,7 +43,7 @@ MODULE_ALIAS("platform:mvsw6171");
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mvsw6171_wait_mask_raw(struct mii_bus *bus, int addr,
|
|
|
|
|
mvsw61xx_wait_mask_raw(struct mii_bus *bus, int addr,
|
|
|
|
|
int reg, u16 mask, u16 val)
|
|
|
|
|
{
|
|
|
|
|
int i = 100;
|
|
|
|
@ -67,7 +67,7 @@ r16(struct mii_bus *bus, bool indirect, int base_addr, int addr, int reg)
|
|
|
|
|
return bus->read(bus, addr, reg);
|
|
|
|
|
|
|
|
|
|
/* Indirect read: First, make sure switch is free */
|
|
|
|
|
mvsw6171_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
|
|
|
|
|
mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
|
|
|
|
|
MV_INDIRECT_INPROGRESS, 0);
|
|
|
|
|
|
|
|
|
|
/* Load address and request read */
|
|
|
|
@ -76,7 +76,7 @@ r16(struct mii_bus *bus, bool indirect, int base_addr, int addr, int reg)
|
|
|
|
|
ind_addr);
|
|
|
|
|
|
|
|
|
|
/* Wait until it's ready */
|
|
|
|
|
mvsw6171_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
|
|
|
|
|
mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
|
|
|
|
|
MV_INDIRECT_INPROGRESS, 0);
|
|
|
|
|
|
|
|
|
|
/* Read the requested data */
|
|
|
|
@ -95,14 +95,14 @@ w16(struct mii_bus *bus, bool indirect, int base_addr, int addr,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Indirect write: First, make sure switch is free */
|
|
|
|
|
mvsw6171_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
|
|
|
|
|
mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
|
|
|
|
|
MV_INDIRECT_INPROGRESS, 0);
|
|
|
|
|
|
|
|
|
|
/* Load the data to be written */
|
|
|
|
|
bus->write(bus, base_addr, MV_INDIRECT_REG_DATA, val);
|
|
|
|
|
|
|
|
|
|
/* Wait again for switch to be free */
|
|
|
|
|
mvsw6171_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
|
|
|
|
|
mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
|
|
|
|
|
MV_INDIRECT_INPROGRESS, 0);
|
|
|
|
|
|
|
|
|
|
/* Load address, and issue write command */
|
|
|
|
@ -116,7 +116,7 @@ w16(struct mii_bus *bus, bool indirect, int base_addr, int addr,
|
|
|
|
|
static inline u16
|
|
|
|
|
sr16(struct switch_dev *dev, int addr, int reg)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
|
|
|
|
|
return r16(state->bus, state->is_indirect, state->base_addr, addr, reg);
|
|
|
|
|
}
|
|
|
|
@ -124,13 +124,13 @@ sr16(struct switch_dev *dev, int addr, int reg)
|
|
|
|
|
static inline void
|
|
|
|
|
sw16(struct switch_dev *dev, int addr, int reg, u16 val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
|
|
|
|
|
w16(state->bus, state->is_indirect, state->base_addr, addr, reg, val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mvsw6171_wait_mask_s(struct switch_dev *dev, int addr,
|
|
|
|
|
mvsw61xx_wait_mask_s(struct switch_dev *dev, int addr,
|
|
|
|
|
int reg, u16 mask, u16 val)
|
|
|
|
|
{
|
|
|
|
|
int i = 100;
|
|
|
|
@ -146,10 +146,10 @@ mvsw6171_wait_mask_s(struct switch_dev *dev, int addr,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mvsw6171_get_port_mask(struct switch_dev *dev,
|
|
|
|
|
mvsw61xx_get_port_mask(struct switch_dev *dev,
|
|
|
|
|
const struct switch_attr *attr, struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
char *buf = state->buf;
|
|
|
|
|
int port, len, i;
|
|
|
|
|
u16 reg;
|
|
|
|
@ -172,10 +172,10 @@ mvsw6171_get_port_mask(struct switch_dev *dev,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mvsw6171_get_port_qmode(struct switch_dev *dev,
|
|
|
|
|
mvsw61xx_get_port_qmode(struct switch_dev *dev,
|
|
|
|
|
const struct switch_attr *attr, struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
|
|
|
|
|
val->value.i = state->ports[val->port_vlan].qmode;
|
|
|
|
|
|
|
|
|
@ -183,10 +183,10 @@ mvsw6171_get_port_qmode(struct switch_dev *dev,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mvsw6171_set_port_qmode(struct switch_dev *dev,
|
|
|
|
|
mvsw61xx_set_port_qmode(struct switch_dev *dev,
|
|
|
|
|
const struct switch_attr *attr, struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
|
|
|
|
|
state->ports[val->port_vlan].qmode = val->value.i;
|
|
|
|
|
|
|
|
|
@ -194,9 +194,9 @@ mvsw6171_set_port_qmode(struct switch_dev *dev,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mvsw6171_get_pvid(struct switch_dev *dev, int port, int *val)
|
|
|
|
|
mvsw61xx_get_pvid(struct switch_dev *dev, int port, int *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
|
|
|
|
|
*val = state->ports[port].pvid;
|
|
|
|
|
|
|
|
|
@ -204,9 +204,9 @@ mvsw6171_get_pvid(struct switch_dev *dev, int port, int *val)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mvsw6171_set_pvid(struct switch_dev *dev, int port, int val)
|
|
|
|
|
mvsw61xx_set_pvid(struct switch_dev *dev, int port, int val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
|
|
|
|
|
if (val < 0 || val >= MV_VLANS)
|
|
|
|
|
return -EINVAL;
|
|
|
|
@ -217,10 +217,10 @@ mvsw6171_set_pvid(struct switch_dev *dev, int port, int val)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mvsw6171_get_port_status(struct switch_dev *dev,
|
|
|
|
|
mvsw61xx_get_port_status(struct switch_dev *dev,
|
|
|
|
|
const struct switch_attr *attr, struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
char *buf = state->buf;
|
|
|
|
|
u16 status, speed;
|
|
|
|
|
int len;
|
|
|
|
@ -261,7 +261,7 @@ mvsw6171_get_port_status(struct switch_dev *dev,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mvsw6171_get_port_speed(struct switch_dev *dev,
|
|
|
|
|
mvsw61xx_get_port_speed(struct switch_dev *dev,
|
|
|
|
|
const struct switch_attr *attr, struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
u16 status, speed;
|
|
|
|
@ -289,10 +289,10 @@ mvsw6171_get_port_speed(struct switch_dev *dev,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_get_vlan_ports(struct switch_dev *dev,
|
|
|
|
|
static int mvsw61xx_get_vlan_ports(struct switch_dev *dev,
|
|
|
|
|
struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
int i, j, mode, vno;
|
|
|
|
|
|
|
|
|
|
vno = val->port_vlan;
|
|
|
|
@ -320,10 +320,10 @@ static int mvsw6171_get_vlan_ports(struct switch_dev *dev,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_set_vlan_ports(struct switch_dev *dev,
|
|
|
|
|
static int mvsw61xx_set_vlan_ports(struct switch_dev *dev,
|
|
|
|
|
struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
int i, mode, pno, vno;
|
|
|
|
|
|
|
|
|
|
vno = val->port_vlan;
|
|
|
|
@ -362,10 +362,10 @@ static int mvsw6171_set_vlan_ports(struct switch_dev *dev,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_get_vlan_port_based(struct switch_dev *dev,
|
|
|
|
|
static int mvsw61xx_get_vlan_port_based(struct switch_dev *dev,
|
|
|
|
|
const struct switch_attr *attr, struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
int vno = val->port_vlan;
|
|
|
|
|
|
|
|
|
|
if (vno <= 0 || vno >= dev->vlans)
|
|
|
|
@ -379,10 +379,10 @@ static int mvsw6171_get_vlan_port_based(struct switch_dev *dev,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_set_vlan_port_based(struct switch_dev *dev,
|
|
|
|
|
static int mvsw61xx_set_vlan_port_based(struct switch_dev *dev,
|
|
|
|
|
const struct switch_attr *attr, struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
int vno = val->port_vlan;
|
|
|
|
|
|
|
|
|
|
if (vno <= 0 || vno >= dev->vlans)
|
|
|
|
@ -396,10 +396,10 @@ static int mvsw6171_set_vlan_port_based(struct switch_dev *dev,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_get_vid(struct switch_dev *dev,
|
|
|
|
|
static int mvsw61xx_get_vid(struct switch_dev *dev,
|
|
|
|
|
const struct switch_attr *attr, struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
int vno = val->port_vlan;
|
|
|
|
|
|
|
|
|
|
if (vno <= 0 || vno >= dev->vlans)
|
|
|
|
@ -410,10 +410,10 @@ static int mvsw6171_get_vid(struct switch_dev *dev,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_set_vid(struct switch_dev *dev,
|
|
|
|
|
static int mvsw61xx_set_vid(struct switch_dev *dev,
|
|
|
|
|
const struct switch_attr *attr, struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
int vno = val->port_vlan;
|
|
|
|
|
|
|
|
|
|
if (vno <= 0 || vno >= dev->vlans)
|
|
|
|
@ -424,34 +424,34 @@ static int mvsw6171_set_vid(struct switch_dev *dev,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_get_enable_vlan(struct switch_dev *dev,
|
|
|
|
|
static int mvsw61xx_get_enable_vlan(struct switch_dev *dev,
|
|
|
|
|
const struct switch_attr *attr, struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
|
|
|
|
|
val->value.i = state->vlan_enabled;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_set_enable_vlan(struct switch_dev *dev,
|
|
|
|
|
static int mvsw61xx_set_enable_vlan(struct switch_dev *dev,
|
|
|
|
|
const struct switch_attr *attr, struct switch_val *val)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
|
|
|
|
|
state->vlan_enabled = val->value.i;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_vtu_program(struct switch_dev *dev)
|
|
|
|
|
static int mvsw61xx_vtu_program(struct switch_dev *dev)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
u16 v1, v2;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* Flush */
|
|
|
|
|
mvsw6171_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
|
|
|
|
|
mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
|
|
|
|
|
MV_VTUOP_INPROGRESS, 0);
|
|
|
|
|
sw16(dev, MV_GLOBALREG(VTU_OP),
|
|
|
|
|
MV_VTUOP_INPROGRESS | MV_VTUOP_VALID);
|
|
|
|
@ -463,7 +463,7 @@ static int mvsw6171_vtu_program(struct switch_dev *dev)
|
|
|
|
|
state->vlans[i].port_based == true)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
mvsw6171_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
|
|
|
|
|
mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
|
|
|
|
|
MV_VTUOP_INPROGRESS, 0);
|
|
|
|
|
|
|
|
|
|
sw16(dev, MV_GLOBALREG(VTU_VID),
|
|
|
|
@ -477,16 +477,16 @@ static int mvsw6171_vtu_program(struct switch_dev *dev)
|
|
|
|
|
|
|
|
|
|
sw16(dev, MV_GLOBALREG(VTU_OP),
|
|
|
|
|
MV_VTUOP_INPROGRESS | MV_VTUOP_LOAD);
|
|
|
|
|
mvsw6171_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
|
|
|
|
|
mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
|
|
|
|
|
MV_VTUOP_INPROGRESS, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void mvsw6171_vlan_port_config(struct switch_dev *dev, int vno)
|
|
|
|
|
static void mvsw61xx_vlan_port_config(struct switch_dev *dev, int vno)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
int i, mode;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < dev->ports; i++) {
|
|
|
|
@ -505,16 +505,16 @@ static void mvsw6171_vlan_port_config(struct switch_dev *dev, int vno)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_update_state(struct switch_dev *dev)
|
|
|
|
|
static int mvsw61xx_update_state(struct switch_dev *dev)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
int i;
|
|
|
|
|
u16 reg;
|
|
|
|
|
|
|
|
|
|
if (!state->registered)
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
|
|
mvsw6171_vtu_program(dev);
|
|
|
|
|
mvsw61xx_vtu_program(dev);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set 802.1q-only mode if vlan_enabled is true.
|
|
|
|
@ -549,7 +549,7 @@ static int mvsw6171_update_state(struct switch_dev *dev)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < dev->vlans; i++)
|
|
|
|
|
mvsw6171_vlan_port_config(dev, i);
|
|
|
|
|
mvsw61xx_vlan_port_config(dev, i);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < dev->ports; i++) {
|
|
|
|
|
reg = sr16(dev, MV_PORTREG(VLANID, i)) & ~MV_PVID_MASK;
|
|
|
|
@ -571,14 +571,14 @@ static int mvsw6171_update_state(struct switch_dev *dev)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_apply(struct switch_dev *dev)
|
|
|
|
|
static int mvsw61xx_apply(struct switch_dev *dev)
|
|
|
|
|
{
|
|
|
|
|
return mvsw6171_update_state(dev);
|
|
|
|
|
return mvsw61xx_update_state(dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_reset(struct switch_dev *dev)
|
|
|
|
|
static int mvsw61xx_reset(struct switch_dev *dev)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = get_state(dev);
|
|
|
|
|
struct mvsw61xx_state *state = get_state(dev);
|
|
|
|
|
int i;
|
|
|
|
|
u16 reg;
|
|
|
|
|
|
|
|
|
@ -592,7 +592,7 @@ static int mvsw6171_reset(struct switch_dev *dev)
|
|
|
|
|
reg = sr16(dev, MV_GLOBALREG(CONTROL)) | MV_CONTROL_RESET;
|
|
|
|
|
|
|
|
|
|
sw16(dev, MV_GLOBALREG(CONTROL), reg);
|
|
|
|
|
if (mvsw6171_wait_mask_s(dev, MV_GLOBALREG(CONTROL),
|
|
|
|
|
if (mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(CONTROL),
|
|
|
|
|
MV_CONTROL_RESET, 0) < 0)
|
|
|
|
|
return -ETIMEDOUT;
|
|
|
|
|
|
|
|
|
@ -619,7 +619,7 @@ static int mvsw6171_reset(struct switch_dev *dev)
|
|
|
|
|
|
|
|
|
|
state->vlan_enabled = 0;
|
|
|
|
|
|
|
|
|
|
mvsw6171_update_state(dev);
|
|
|
|
|
mvsw61xx_update_state(dev);
|
|
|
|
|
|
|
|
|
|
/* Re-enable ports */
|
|
|
|
|
for (i = 0; i < dev->ports; i++) {
|
|
|
|
@ -632,112 +632,112 @@ static int mvsw6171_reset(struct switch_dev *dev)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
MVSW6171_ENABLE_VLAN,
|
|
|
|
|
MVSW61XX_ENABLE_VLAN,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
MVSW6171_VLAN_PORT_BASED,
|
|
|
|
|
MVSW6171_VLAN_ID,
|
|
|
|
|
MVSW61XX_VLAN_PORT_BASED,
|
|
|
|
|
MVSW61XX_VLAN_ID,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
MVSW6171_PORT_MASK,
|
|
|
|
|
MVSW6171_PORT_QMODE,
|
|
|
|
|
MVSW6171_PORT_STATUS,
|
|
|
|
|
MVSW6171_PORT_LINK,
|
|
|
|
|
MVSW61XX_PORT_MASK,
|
|
|
|
|
MVSW61XX_PORT_QMODE,
|
|
|
|
|
MVSW61XX_PORT_STATUS,
|
|
|
|
|
MVSW61XX_PORT_LINK,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct switch_attr mvsw6171_global[] = {
|
|
|
|
|
[MVSW6171_ENABLE_VLAN] = {
|
|
|
|
|
.id = MVSW6171_ENABLE_VLAN,
|
|
|
|
|
static const struct switch_attr mvsw61xx_global[] = {
|
|
|
|
|
[MVSW61XX_ENABLE_VLAN] = {
|
|
|
|
|
.id = MVSW61XX_ENABLE_VLAN,
|
|
|
|
|
.type = SWITCH_TYPE_INT,
|
|
|
|
|
.name = "enable_vlan",
|
|
|
|
|
.description = "Enable 802.1q VLAN support",
|
|
|
|
|
.get = mvsw6171_get_enable_vlan,
|
|
|
|
|
.set = mvsw6171_set_enable_vlan,
|
|
|
|
|
.get = mvsw61xx_get_enable_vlan,
|
|
|
|
|
.set = mvsw61xx_set_enable_vlan,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct switch_attr mvsw6171_vlan[] = {
|
|
|
|
|
[MVSW6171_VLAN_PORT_BASED] = {
|
|
|
|
|
.id = MVSW6171_VLAN_PORT_BASED,
|
|
|
|
|
static const struct switch_attr mvsw61xx_vlan[] = {
|
|
|
|
|
[MVSW61XX_VLAN_PORT_BASED] = {
|
|
|
|
|
.id = MVSW61XX_VLAN_PORT_BASED,
|
|
|
|
|
.type = SWITCH_TYPE_INT,
|
|
|
|
|
.name = "port_based",
|
|
|
|
|
.description = "Use port-based (non-802.1q) VLAN only",
|
|
|
|
|
.get = mvsw6171_get_vlan_port_based,
|
|
|
|
|
.set = mvsw6171_set_vlan_port_based,
|
|
|
|
|
.get = mvsw61xx_get_vlan_port_based,
|
|
|
|
|
.set = mvsw61xx_set_vlan_port_based,
|
|
|
|
|
},
|
|
|
|
|
[MVSW6171_VLAN_ID] = {
|
|
|
|
|
.id = MVSW6171_VLAN_ID,
|
|
|
|
|
[MVSW61XX_VLAN_ID] = {
|
|
|
|
|
.id = MVSW61XX_VLAN_ID,
|
|
|
|
|
.type = SWITCH_TYPE_INT,
|
|
|
|
|
.name = "vid",
|
|
|
|
|
.description = "Get/set VLAN ID",
|
|
|
|
|
.get = mvsw6171_get_vid,
|
|
|
|
|
.set = mvsw6171_set_vid,
|
|
|
|
|
.get = mvsw61xx_get_vid,
|
|
|
|
|
.set = mvsw61xx_set_vid,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct switch_attr mvsw6171_port[] = {
|
|
|
|
|
[MVSW6171_PORT_MASK] = {
|
|
|
|
|
.id = MVSW6171_PORT_MASK,
|
|
|
|
|
static const struct switch_attr mvsw61xx_port[] = {
|
|
|
|
|
[MVSW61XX_PORT_MASK] = {
|
|
|
|
|
.id = MVSW61XX_PORT_MASK,
|
|
|
|
|
.type = SWITCH_TYPE_STRING,
|
|
|
|
|
.description = "Port-based VLAN mask",
|
|
|
|
|
.name = "mask",
|
|
|
|
|
.get = mvsw6171_get_port_mask,
|
|
|
|
|
.get = mvsw61xx_get_port_mask,
|
|
|
|
|
.set = NULL,
|
|
|
|
|
},
|
|
|
|
|
[MVSW6171_PORT_QMODE] = {
|
|
|
|
|
.id = MVSW6171_PORT_QMODE,
|
|
|
|
|
[MVSW61XX_PORT_QMODE] = {
|
|
|
|
|
.id = MVSW61XX_PORT_QMODE,
|
|
|
|
|
.type = SWITCH_TYPE_INT,
|
|
|
|
|
.description = "802.1q mode: 0=off/1=fallback/2=check/3=secure",
|
|
|
|
|
.name = "qmode",
|
|
|
|
|
.get = mvsw6171_get_port_qmode,
|
|
|
|
|
.set = mvsw6171_set_port_qmode,
|
|
|
|
|
.get = mvsw61xx_get_port_qmode,
|
|
|
|
|
.set = mvsw61xx_set_port_qmode,
|
|
|
|
|
},
|
|
|
|
|
[MVSW6171_PORT_STATUS] = {
|
|
|
|
|
.id = MVSW6171_PORT_STATUS,
|
|
|
|
|
[MVSW61XX_PORT_STATUS] = {
|
|
|
|
|
.id = MVSW61XX_PORT_STATUS,
|
|
|
|
|
.type = SWITCH_TYPE_STRING,
|
|
|
|
|
.description = "Return port status",
|
|
|
|
|
.name = "status",
|
|
|
|
|
.get = mvsw6171_get_port_status,
|
|
|
|
|
.get = mvsw61xx_get_port_status,
|
|
|
|
|
.set = NULL,
|
|
|
|
|
},
|
|
|
|
|
[MVSW6171_PORT_LINK] = {
|
|
|
|
|
.id = MVSW6171_PORT_LINK,
|
|
|
|
|
[MVSW61XX_PORT_LINK] = {
|
|
|
|
|
.id = MVSW61XX_PORT_LINK,
|
|
|
|
|
.type = SWITCH_TYPE_INT,
|
|
|
|
|
.description = "Get link speed",
|
|
|
|
|
.name = "link",
|
|
|
|
|
.get = mvsw6171_get_port_speed,
|
|
|
|
|
.get = mvsw61xx_get_port_speed,
|
|
|
|
|
.set = NULL,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct switch_dev_ops mvsw6171_ops = {
|
|
|
|
|
static const struct switch_dev_ops mvsw61xx_ops = {
|
|
|
|
|
.attr_global = {
|
|
|
|
|
.attr = mvsw6171_global,
|
|
|
|
|
.n_attr = ARRAY_SIZE(mvsw6171_global),
|
|
|
|
|
.attr = mvsw61xx_global,
|
|
|
|
|
.n_attr = ARRAY_SIZE(mvsw61xx_global),
|
|
|
|
|
},
|
|
|
|
|
.attr_vlan = {
|
|
|
|
|
.attr = mvsw6171_vlan,
|
|
|
|
|
.n_attr = ARRAY_SIZE(mvsw6171_vlan),
|
|
|
|
|
.attr = mvsw61xx_vlan,
|
|
|
|
|
.n_attr = ARRAY_SIZE(mvsw61xx_vlan),
|
|
|
|
|
},
|
|
|
|
|
.attr_port = {
|
|
|
|
|
.attr = mvsw6171_port,
|
|
|
|
|
.n_attr = ARRAY_SIZE(mvsw6171_port),
|
|
|
|
|
.attr = mvsw61xx_port,
|
|
|
|
|
.n_attr = ARRAY_SIZE(mvsw61xx_port),
|
|
|
|
|
},
|
|
|
|
|
.get_port_pvid = mvsw6171_get_pvid,
|
|
|
|
|
.set_port_pvid = mvsw6171_set_pvid,
|
|
|
|
|
.get_vlan_ports = mvsw6171_get_vlan_ports,
|
|
|
|
|
.set_vlan_ports = mvsw6171_set_vlan_ports,
|
|
|
|
|
.apply_config = mvsw6171_apply,
|
|
|
|
|
.reset_switch = mvsw6171_reset,
|
|
|
|
|
.get_port_pvid = mvsw61xx_get_pvid,
|
|
|
|
|
.set_port_pvid = mvsw61xx_set_pvid,
|
|
|
|
|
.get_vlan_ports = mvsw61xx_get_vlan_ports,
|
|
|
|
|
.set_vlan_ports = mvsw61xx_set_vlan_ports,
|
|
|
|
|
.apply_config = mvsw61xx_apply,
|
|
|
|
|
.reset_switch = mvsw61xx_reset,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* end swconfig stuff */
|
|
|
|
|
|
|
|
|
|
static int mvsw6171_probe(struct platform_device *pdev)
|
|
|
|
|
static int mvsw61xx_probe(struct platform_device *pdev)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state;
|
|
|
|
|
struct mvsw61xx_state *state;
|
|
|
|
|
struct device_node *np = pdev->dev.of_node;
|
|
|
|
|
struct device_node *mdio;
|
|
|
|
|
u32 val;
|
|
|
|
@ -809,7 +809,7 @@ static int mvsw6171_probe(struct platform_device *pdev)
|
|
|
|
|
state->dev.cpu_port = state->cpu_port0;
|
|
|
|
|
state->dev.ports = MV_PORTS;
|
|
|
|
|
state->dev.name = MV_IDENT_STR;
|
|
|
|
|
state->dev.ops = &mvsw6171_ops;
|
|
|
|
|
state->dev.ops = &mvsw61xx_ops;
|
|
|
|
|
state->dev.alias = dev_name(&pdev->dev);
|
|
|
|
|
|
|
|
|
|
err = register_switch(&state->dev, NULL);
|
|
|
|
@ -825,9 +825,9 @@ out_err:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mvsw6171_remove(struct platform_device *pdev)
|
|
|
|
|
mvsw61xx_remove(struct platform_device *pdev)
|
|
|
|
|
{
|
|
|
|
|
struct mvsw6171_state *state = platform_get_drvdata(pdev);
|
|
|
|
|
struct mvsw61xx_state *state = platform_get_drvdata(pdev);
|
|
|
|
|
|
|
|
|
|
if (state->registered)
|
|
|
|
|
unregister_switch(&state->dev);
|
|
|
|
@ -837,30 +837,30 @@ mvsw6171_remove(struct platform_device *pdev)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct of_device_id mvsw6171_match[] = {
|
|
|
|
|
static const struct of_device_id mvsw61xx_match[] = {
|
|
|
|
|
{ .compatible = "marvell,88e6171" },
|
|
|
|
|
{ }
|
|
|
|
|
};
|
|
|
|
|
MODULE_DEVICE_TABLE(of, mvsw6171_match);
|
|
|
|
|
MODULE_DEVICE_TABLE(of, mvsw61xx_match);
|
|
|
|
|
|
|
|
|
|
static struct platform_driver mvsw6171_driver = {
|
|
|
|
|
.probe = mvsw6171_probe,
|
|
|
|
|
.remove = mvsw6171_remove,
|
|
|
|
|
static struct platform_driver mvsw61xx_driver = {
|
|
|
|
|
.probe = mvsw61xx_probe,
|
|
|
|
|
.remove = mvsw61xx_remove,
|
|
|
|
|
.driver = {
|
|
|
|
|
.name = "mvsw6171",
|
|
|
|
|
.of_match_table = of_match_ptr(mvsw6171_match),
|
|
|
|
|
.name = "mvsw61xx",
|
|
|
|
|
.of_match_table = of_match_ptr(mvsw61xx_match),
|
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int __init mvsw6171_module_init(void)
|
|
|
|
|
static int __init mvsw61xx_module_init(void)
|
|
|
|
|
{
|
|
|
|
|
return platform_driver_register(&mvsw6171_driver);
|
|
|
|
|
return platform_driver_register(&mvsw61xx_driver);
|
|
|
|
|
}
|
|
|
|
|
late_initcall(mvsw6171_module_init);
|
|
|
|
|
late_initcall(mvsw61xx_module_init);
|
|
|
|
|
|
|
|
|
|
static void __exit mvsw6171_module_exit(void)
|
|
|
|
|
static void __exit mvsw61xx_module_exit(void)
|
|
|
|
|
{
|
|
|
|
|
platform_driver_unregister(&mvsw6171_driver);
|
|
|
|
|
platform_driver_unregister(&mvsw61xx_driver);
|
|
|
|
|
}
|
|
|
|
|
module_exit(mvsw6171_module_exit);
|
|
|
|
|
module_exit(mvsw61xx_module_exit);
|