|
@@ -402,135 +402,63 @@ static bool mv88e6xxx_6065_family(struct dsa_switch *ds)
|
|
{
|
|
{
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
|
|
|
|
- switch (ps->id) {
|
|
|
|
- case PORT_SWITCH_ID_6031:
|
|
|
|
- case PORT_SWITCH_ID_6061:
|
|
|
|
- case PORT_SWITCH_ID_6035:
|
|
|
|
- case PORT_SWITCH_ID_6065:
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
|
|
+ return ps->info->family == MV88E6XXX_FAMILY_6065;
|
|
}
|
|
}
|
|
|
|
|
|
static bool mv88e6xxx_6095_family(struct dsa_switch *ds)
|
|
static bool mv88e6xxx_6095_family(struct dsa_switch *ds)
|
|
{
|
|
{
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
|
|
|
|
- switch (ps->id) {
|
|
|
|
- case PORT_SWITCH_ID_6092:
|
|
|
|
- case PORT_SWITCH_ID_6095:
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
|
|
+ return ps->info->family == MV88E6XXX_FAMILY_6095;
|
|
}
|
|
}
|
|
|
|
|
|
static bool mv88e6xxx_6097_family(struct dsa_switch *ds)
|
|
static bool mv88e6xxx_6097_family(struct dsa_switch *ds)
|
|
{
|
|
{
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
|
|
|
|
- switch (ps->id) {
|
|
|
|
- case PORT_SWITCH_ID_6046:
|
|
|
|
- case PORT_SWITCH_ID_6085:
|
|
|
|
- case PORT_SWITCH_ID_6096:
|
|
|
|
- case PORT_SWITCH_ID_6097:
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
|
|
+ return ps->info->family == MV88E6XXX_FAMILY_6097;
|
|
}
|
|
}
|
|
|
|
|
|
static bool mv88e6xxx_6165_family(struct dsa_switch *ds)
|
|
static bool mv88e6xxx_6165_family(struct dsa_switch *ds)
|
|
{
|
|
{
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
|
|
|
|
- switch (ps->id) {
|
|
|
|
- case PORT_SWITCH_ID_6123:
|
|
|
|
- case PORT_SWITCH_ID_6161:
|
|
|
|
- case PORT_SWITCH_ID_6165:
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
|
|
+ return ps->info->family == MV88E6XXX_FAMILY_6165;
|
|
}
|
|
}
|
|
|
|
|
|
static bool mv88e6xxx_6185_family(struct dsa_switch *ds)
|
|
static bool mv88e6xxx_6185_family(struct dsa_switch *ds)
|
|
{
|
|
{
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
|
|
|
|
- switch (ps->id) {
|
|
|
|
- case PORT_SWITCH_ID_6121:
|
|
|
|
- case PORT_SWITCH_ID_6122:
|
|
|
|
- case PORT_SWITCH_ID_6152:
|
|
|
|
- case PORT_SWITCH_ID_6155:
|
|
|
|
- case PORT_SWITCH_ID_6182:
|
|
|
|
- case PORT_SWITCH_ID_6185:
|
|
|
|
- case PORT_SWITCH_ID_6108:
|
|
|
|
- case PORT_SWITCH_ID_6131:
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
|
|
+ return ps->info->family == MV88E6XXX_FAMILY_6185;
|
|
}
|
|
}
|
|
|
|
|
|
static bool mv88e6xxx_6320_family(struct dsa_switch *ds)
|
|
static bool mv88e6xxx_6320_family(struct dsa_switch *ds)
|
|
{
|
|
{
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
|
|
|
|
- switch (ps->id) {
|
|
|
|
- case PORT_SWITCH_ID_6320:
|
|
|
|
- case PORT_SWITCH_ID_6321:
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
|
|
+ return ps->info->family == MV88E6XXX_FAMILY_6320;
|
|
}
|
|
}
|
|
|
|
|
|
static bool mv88e6xxx_6351_family(struct dsa_switch *ds)
|
|
static bool mv88e6xxx_6351_family(struct dsa_switch *ds)
|
|
{
|
|
{
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
|
|
|
|
- switch (ps->id) {
|
|
|
|
- case PORT_SWITCH_ID_6171:
|
|
|
|
- case PORT_SWITCH_ID_6175:
|
|
|
|
- case PORT_SWITCH_ID_6350:
|
|
|
|
- case PORT_SWITCH_ID_6351:
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
|
|
+ return ps->info->family == MV88E6XXX_FAMILY_6351;
|
|
}
|
|
}
|
|
|
|
|
|
static bool mv88e6xxx_6352_family(struct dsa_switch *ds)
|
|
static bool mv88e6xxx_6352_family(struct dsa_switch *ds)
|
|
{
|
|
{
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
|
|
|
|
- switch (ps->id) {
|
|
|
|
- case PORT_SWITCH_ID_6172:
|
|
|
|
- case PORT_SWITCH_ID_6176:
|
|
|
|
- case PORT_SWITCH_ID_6240:
|
|
|
|
- case PORT_SWITCH_ID_6352:
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
|
|
+ return ps->info->family == MV88E6XXX_FAMILY_6352;
|
|
}
|
|
}
|
|
|
|
|
|
static unsigned int mv88e6xxx_num_databases(struct dsa_switch *ds)
|
|
static unsigned int mv88e6xxx_num_databases(struct dsa_switch *ds)
|
|
{
|
|
{
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
|
|
|
|
- /* The following devices have 4-bit identifiers for 16 databases */
|
|
|
|
- if (ps->id == PORT_SWITCH_ID_6061)
|
|
|
|
- return 16;
|
|
|
|
-
|
|
|
|
- /* The following devices have 6-bit identifiers for 64 databases */
|
|
|
|
- if (ps->id == PORT_SWITCH_ID_6065)
|
|
|
|
- return 64;
|
|
|
|
-
|
|
|
|
- /* The following devices have 8-bit identifiers for 256 databases */
|
|
|
|
- if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds))
|
|
|
|
- return 256;
|
|
|
|
-
|
|
|
|
- /* The following devices have 12-bit identifiers for 4096 databases */
|
|
|
|
- if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) ||
|
|
|
|
- mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds))
|
|
|
|
- return 4096;
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
|
|
+ return ps->info->num_databases;
|
|
}
|
|
}
|
|
|
|
|
|
static bool mv88e6xxx_has_fid_reg(struct dsa_switch *ds)
|
|
static bool mv88e6xxx_has_fid_reg(struct dsa_switch *ds)
|
|
@@ -606,7 +534,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
|
|
reg |= PORT_PCS_CTRL_DUPLEX_FULL;
|
|
reg |= PORT_PCS_CTRL_DUPLEX_FULL;
|
|
|
|
|
|
if ((mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds)) &&
|
|
if ((mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds)) &&
|
|
- (port >= ps->num_ports - 2)) {
|
|
|
|
|
|
+ (port >= ps->info->num_ports - 2)) {
|
|
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
|
|
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
|
|
reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
|
|
reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
|
|
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
|
|
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
|
|
@@ -1187,7 +1115,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port)
|
|
{
|
|
{
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct net_device *bridge = ps->ports[port].bridge_dev;
|
|
struct net_device *bridge = ps->ports[port].bridge_dev;
|
|
- const u16 mask = (1 << ps->num_ports) - 1;
|
|
|
|
|
|
+ const u16 mask = (1 << ps->info->num_ports) - 1;
|
|
u16 output_ports = 0;
|
|
u16 output_ports = 0;
|
|
int reg;
|
|
int reg;
|
|
int i;
|
|
int i;
|
|
@@ -1196,7 +1124,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port)
|
|
if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
|
|
if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
|
|
output_ports = mask;
|
|
output_ports = mask;
|
|
} else {
|
|
} else {
|
|
- for (i = 0; i < ps->num_ports; ++i) {
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; ++i) {
|
|
/* allow sending frames to every group member */
|
|
/* allow sending frames to every group member */
|
|
if (bridge && ps->ports[i].bridge_dev == bridge)
|
|
if (bridge && ps->ports[i].bridge_dev == bridge)
|
|
output_ports |= BIT(i);
|
|
output_ports |= BIT(i);
|
|
@@ -1337,7 +1265,7 @@ static int _mv88e6xxx_vtu_stu_data_read(struct dsa_switch *ds,
|
|
regs[i] = ret;
|
|
regs[i] = ret;
|
|
}
|
|
}
|
|
|
|
|
|
- for (i = 0; i < ps->num_ports; ++i) {
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; ++i) {
|
|
unsigned int shift = (i % 4) * 4 + nibble_offset;
|
|
unsigned int shift = (i % 4) * 4 + nibble_offset;
|
|
u16 reg = regs[i / 4];
|
|
u16 reg = regs[i / 4];
|
|
|
|
|
|
@@ -1356,7 +1284,7 @@ static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds,
|
|
int i;
|
|
int i;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- for (i = 0; i < ps->num_ports; ++i) {
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; ++i) {
|
|
unsigned int shift = (i % 4) * 4 + nibble_offset;
|
|
unsigned int shift = (i % 4) * 4 + nibble_offset;
|
|
u8 data = entry->data[i];
|
|
u8 data = entry->data[i];
|
|
|
|
|
|
@@ -1688,7 +1616,7 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
|
|
bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
|
|
bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
|
|
|
|
|
|
/* Set every FID bit used by the (un)bridged ports */
|
|
/* Set every FID bit used by the (un)bridged ports */
|
|
- for (i = 0; i < ps->num_ports; ++i) {
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; ++i) {
|
|
err = _mv88e6xxx_port_fid_get(ds, i, fid);
|
|
err = _mv88e6xxx_port_fid_get(ds, i, fid);
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
@@ -1738,7 +1666,7 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid,
|
|
return err;
|
|
return err;
|
|
|
|
|
|
/* exclude all ports except the CPU and DSA ports */
|
|
/* exclude all ports except the CPU and DSA ports */
|
|
- for (i = 0; i < ps->num_ports; ++i)
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; ++i)
|
|
vlan.data[i] = dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)
|
|
vlan.data[i] = dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)
|
|
? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED
|
|
? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED
|
|
: GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
|
|
: GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
|
|
@@ -1827,7 +1755,7 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
|
|
if (vlan.vid > vid_end)
|
|
if (vlan.vid > vid_end)
|
|
break;
|
|
break;
|
|
|
|
|
|
- for (i = 0; i < ps->num_ports; ++i) {
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; ++i) {
|
|
if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
|
|
if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
@@ -1976,7 +1904,7 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
|
|
|
|
|
|
/* keep the VLAN unless all ports are excluded */
|
|
/* keep the VLAN unless all ports are excluded */
|
|
vlan.valid = false;
|
|
vlan.valid = false;
|
|
- for (i = 0; i < ps->num_ports; ++i) {
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; ++i) {
|
|
if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
|
|
if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
@@ -2285,11 +2213,11 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
|
|
mutex_lock(&ps->smi_mutex);
|
|
mutex_lock(&ps->smi_mutex);
|
|
|
|
|
|
/* Get or create the bridge FID and assign it to the port */
|
|
/* Get or create the bridge FID and assign it to the port */
|
|
- for (i = 0; i < ps->num_ports; ++i)
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; ++i)
|
|
if (ps->ports[i].bridge_dev == bridge)
|
|
if (ps->ports[i].bridge_dev == bridge)
|
|
break;
|
|
break;
|
|
|
|
|
|
- if (i < ps->num_ports)
|
|
|
|
|
|
+ if (i < ps->info->num_ports)
|
|
err = _mv88e6xxx_port_fid_get(ds, i, &fid);
|
|
err = _mv88e6xxx_port_fid_get(ds, i, &fid);
|
|
else
|
|
else
|
|
err = _mv88e6xxx_fid_new(ds, &fid);
|
|
err = _mv88e6xxx_fid_new(ds, &fid);
|
|
@@ -2303,7 +2231,7 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
|
|
/* Assign the bridge and remap each port's VLANTable */
|
|
/* Assign the bridge and remap each port's VLANTable */
|
|
ps->ports[port].bridge_dev = bridge;
|
|
ps->ports[port].bridge_dev = bridge;
|
|
|
|
|
|
- for (i = 0; i < ps->num_ports; ++i) {
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; ++i) {
|
|
if (ps->ports[i].bridge_dev == bridge) {
|
|
if (ps->ports[i].bridge_dev == bridge) {
|
|
err = _mv88e6xxx_port_based_vlan_map(ds, i);
|
|
err = _mv88e6xxx_port_based_vlan_map(ds, i);
|
|
if (err)
|
|
if (err)
|
|
@@ -2334,7 +2262,7 @@ void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
|
|
/* Unassign the bridge and remap each port's VLANTable */
|
|
/* Unassign the bridge and remap each port's VLANTable */
|
|
ps->ports[port].bridge_dev = NULL;
|
|
ps->ports[port].bridge_dev = NULL;
|
|
|
|
|
|
- for (i = 0; i < ps->num_ports; ++i)
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; ++i)
|
|
if (i == port || ps->ports[i].bridge_dev == bridge)
|
|
if (i == port || ps->ports[i].bridge_dev == bridge)
|
|
if (_mv88e6xxx_port_based_vlan_map(ds, i))
|
|
if (_mv88e6xxx_port_based_vlan_map(ds, i))
|
|
netdev_warn(ds->ports[i], "failed to remap\n");
|
|
netdev_warn(ds->ports[i], "failed to remap\n");
|
|
@@ -2353,7 +2281,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work)
|
|
|
|
|
|
mutex_lock(&ps->smi_mutex);
|
|
mutex_lock(&ps->smi_mutex);
|
|
|
|
|
|
- for (port = 0; port < ps->num_ports; ++port)
|
|
|
|
|
|
+ for (port = 0; port < ps->info->num_ports; ++port)
|
|
if (test_and_clear_bit(port, ps->port_state_update_mask) &&
|
|
if (test_and_clear_bit(port, ps->port_state_update_mask) &&
|
|
_mv88e6xxx_port_state(ds, port, ps->ports[port].state))
|
|
_mv88e6xxx_port_state(ds, port, ps->ports[port].state))
|
|
netdev_warn(ds->ports[port], "failed to update state to %s\n",
|
|
netdev_warn(ds->ports[port], "failed to update state to %s\n",
|
|
@@ -2685,7 +2613,7 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
|
|
int ret;
|
|
int ret;
|
|
int i;
|
|
int i;
|
|
|
|
|
|
- for (i = 0; i < ps->num_ports; i++) {
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; i++) {
|
|
ret = mv88e6xxx_setup_port(ds, i);
|
|
ret = mv88e6xxx_setup_port(ds, i);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
return ret;
|
|
return ret;
|
|
@@ -2700,10 +2628,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
|
|
ps->ds = ds;
|
|
ps->ds = ds;
|
|
mutex_init(&ps->smi_mutex);
|
|
mutex_init(&ps->smi_mutex);
|
|
|
|
|
|
- ps->id = mv88e6xxx_reg_read(ds, REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
|
|
|
|
- if (ps->id < 0)
|
|
|
|
- return ps->id;
|
|
|
|
-
|
|
|
|
INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
|
|
INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -2796,7 +2720,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
|
|
err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_TRUNK_MASK,
|
|
err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_TRUNK_MASK,
|
|
0x8000 |
|
|
0x8000 |
|
|
(i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
|
|
(i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
|
|
- ((1 << ps->num_ports) - 1));
|
|
|
|
|
|
+ ((1 << ps->info->num_ports) - 1));
|
|
if (err)
|
|
if (err)
|
|
goto unlock;
|
|
goto unlock;
|
|
}
|
|
}
|
|
@@ -2849,7 +2773,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
|
|
* ingress rate limit registers to their initial
|
|
* ingress rate limit registers to their initial
|
|
* state.
|
|
* state.
|
|
*/
|
|
*/
|
|
- for (i = 0; i < ps->num_ports; i++) {
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; i++) {
|
|
err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2,
|
|
err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2,
|
|
GLOBAL2_INGRESS_OP,
|
|
GLOBAL2_INGRESS_OP,
|
|
0x9000 | (i << 8));
|
|
0x9000 | (i << 8));
|
|
@@ -2894,7 +2818,7 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
|
|
mutex_lock(&ps->smi_mutex);
|
|
mutex_lock(&ps->smi_mutex);
|
|
|
|
|
|
/* Set all ports to the disabled state. */
|
|
/* Set all ports to the disabled state. */
|
|
- for (i = 0; i < ps->num_ports; i++) {
|
|
|
|
|
|
+ for (i = 0; i < ps->info->num_ports; i++) {
|
|
ret = _mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_CONTROL);
|
|
ret = _mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_CONTROL);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto unlock;
|
|
goto unlock;
|
|
@@ -2977,7 +2901,7 @@ static int mv88e6xxx_port_to_phy_addr(struct dsa_switch *ds, int port)
|
|
{
|
|
{
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
|
|
|
|
- if (port >= 0 && port < ps->num_ports)
|
|
|
|
|
|
+ if (port >= 0 && port < ps->info->num_ports)
|
|
return port;
|
|
return port;
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
@@ -3173,61 +3097,60 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
|
|
}
|
|
}
|
|
#endif /* CONFIG_NET_DSA_HWMON */
|
|
#endif /* CONFIG_NET_DSA_HWMON */
|
|
|
|
|
|
-static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
|
|
|
|
- const struct mv88e6xxx_switch_id *table,
|
|
|
|
- unsigned int num)
|
|
|
|
|
|
+static const struct mv88e6xxx_info *
|
|
|
|
+mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table,
|
|
|
|
+ unsigned int num)
|
|
{
|
|
{
|
|
- int i, ret;
|
|
|
|
-
|
|
|
|
- if (!bus)
|
|
|
|
- return NULL;
|
|
|
|
-
|
|
|
|
- ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
|
|
|
|
- if (ret < 0)
|
|
|
|
- return NULL;
|
|
|
|
|
|
+ int i;
|
|
|
|
|
|
- /* Look up the exact switch ID */
|
|
|
|
for (i = 0; i < num; ++i)
|
|
for (i = 0; i < num; ++i)
|
|
- if (table[i].id == ret)
|
|
|
|
- return table[i].name;
|
|
|
|
-
|
|
|
|
- /* Look up only the product number */
|
|
|
|
- for (i = 0; i < num; ++i) {
|
|
|
|
- if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) {
|
|
|
|
- dev_warn(&bus->dev,
|
|
|
|
- "unknown revision %d, using base switch 0x%x\n",
|
|
|
|
- ret & PORT_SWITCH_ID_REV_MASK,
|
|
|
|
- ret & PORT_SWITCH_ID_PROD_NUM_MASK);
|
|
|
|
- return table[i].name;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ if (table[i].prod_num == prod_num)
|
|
|
|
+ return &table[i];
|
|
|
|
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
-char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
|
|
|
|
- int sw_addr, void **priv,
|
|
|
|
- const struct mv88e6xxx_switch_id *table,
|
|
|
|
- unsigned int num)
|
|
|
|
|
|
+const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
|
|
|
|
+ int sw_addr, void **priv,
|
|
|
|
+ const struct mv88e6xxx_info *table,
|
|
|
|
+ unsigned int num)
|
|
{
|
|
{
|
|
|
|
+ const struct mv88e6xxx_info *info;
|
|
struct mv88e6xxx_priv_state *ps;
|
|
struct mv88e6xxx_priv_state *ps;
|
|
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
|
|
|
|
- char *name;
|
|
|
|
|
|
+ struct mii_bus *bus;
|
|
|
|
+ const char *name;
|
|
|
|
+ int id, prod_num, rev;
|
|
|
|
|
|
|
|
+ bus = dsa_host_dev_to_mii_bus(host_dev);
|
|
if (!bus)
|
|
if (!bus)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
- name = mv88e6xxx_lookup_name(bus, sw_addr, table, num);
|
|
|
|
- if (name) {
|
|
|
|
- ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
|
|
|
|
- if (!ps)
|
|
|
|
- return NULL;
|
|
|
|
- *priv = ps;
|
|
|
|
- ps->bus = dsa_host_dev_to_mii_bus(host_dev);
|
|
|
|
- if (!ps->bus)
|
|
|
|
- return NULL;
|
|
|
|
- ps->sw_addr = sw_addr;
|
|
|
|
- }
|
|
|
|
|
|
+ id = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
|
|
|
|
+ if (id < 0)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ prod_num = (id & 0xfff0) >> 4;
|
|
|
|
+ rev = id & 0x000f;
|
|
|
|
+
|
|
|
|
+ info = mv88e6xxx_lookup_info(prod_num, table, num);
|
|
|
|
+ if (!info)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ name = info->name;
|
|
|
|
+
|
|
|
|
+ ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
|
|
|
|
+ if (!ps)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ ps->bus = bus;
|
|
|
|
+ ps->sw_addr = sw_addr;
|
|
|
|
+ ps->info = info;
|
|
|
|
+
|
|
|
|
+ *priv = ps;
|
|
|
|
+
|
|
|
|
+ dev_info(&ps->bus->dev, "switch 0x%x probed: %s, revision %u\n",
|
|
|
|
+ prod_num, name, rev);
|
|
|
|
+
|
|
return name;
|
|
return name;
|
|
}
|
|
}
|
|
|
|
|