Commit a199d8b6 authored by Vivien Didelot's avatar Vivien Didelot Committed by David S. Miller

net: dsa: mv88e6xxx: add PPU operations

Some Marvell chips can enable/disable the PPU on demand. This is needed
to access the PHY registers when there is no indirection mechanism.

Add two new ppu_enable and ppu_disable ops to describe this and finally
get rid of the MV88E6XXX_FLAG_PPU* flags.
Signed-off-by: default avatarVivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 17e708ba
...@@ -527,58 +527,18 @@ int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update) ...@@ -527,58 +527,18 @@ int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update)
static int mv88e6xxx_ppu_disable(struct mv88e6xxx_chip *chip) static int mv88e6xxx_ppu_disable(struct mv88e6xxx_chip *chip)
{ {
u16 val; if (!chip->info->ops->ppu_disable)
int i, err;
err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
if (err)
return err;
err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL,
val & ~GLOBAL_CONTROL_PPU_ENABLE);
if (err)
return err;
for (i = 0; i < 16; i++) {
err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val);
if (err)
return err;
usleep_range(1000, 2000);
val &= GLOBAL_STATUS_PPU_STATE_MASK;
if (val != GLOBAL_STATUS_PPU_STATE_POLLING)
return 0; return 0;
}
return -ETIMEDOUT; return chip->info->ops->ppu_disable(chip);
} }
static int mv88e6xxx_ppu_enable(struct mv88e6xxx_chip *chip) static int mv88e6xxx_ppu_enable(struct mv88e6xxx_chip *chip)
{ {
u16 val; if (!chip->info->ops->ppu_enable)
int i, err;
err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
if (err)
return err;
err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL,
val | GLOBAL_CONTROL_PPU_ENABLE);
if (err)
return err;
for (i = 0; i < 16; i++) {
err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val);
if (err)
return err;
usleep_range(1000, 2000);
val &= GLOBAL_STATUS_PPU_STATE_MASK;
if (val == GLOBAL_STATUS_PPU_STATE_POLLING)
return 0; return 0;
}
return -ETIMEDOUT; return chip->info->ops->ppu_enable(chip);
} }
static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly) static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
...@@ -2746,22 +2706,12 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip) ...@@ -2746,22 +2706,12 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
{ {
struct dsa_switch *ds = chip->ds; struct dsa_switch *ds = chip->ds;
u32 upstream_port = dsa_upstream_port(ds); u32 upstream_port = dsa_upstream_port(ds);
u16 reg;
int err; int err;
/* Enable the PHY Polling Unit if present, don't discard any packets, /* Enable the PHY Polling Unit if present, don't discard any packets,
* and mask all interrupt sources. * and mask all interrupt sources.
*/ */
err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &reg); err = mv88e6xxx_ppu_enable(chip);
if (err < 0)
return err;
reg &= ~GLOBAL_CONTROL_PPU_ENABLE;
if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU) ||
mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU_ACTIVE))
reg |= GLOBAL_CONTROL_PPU_ENABLE;
err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, reg);
if (err) if (err)
return err; return err;
...@@ -3223,6 +3173,8 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { ...@@ -3223,6 +3173,8 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
.g1_set_cpu_port = mv88e6095_g1_set_cpu_port, .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
.g1_set_egress_port = mv88e6095_g1_set_egress_port, .g1_set_egress_port = mv88e6095_g1_set_egress_port,
.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu, .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
.ppu_enable = mv88e6185_g1_ppu_enable,
.ppu_disable = mv88e6185_g1_ppu_disable,
.reset = mv88e6185_g1_reset, .reset = mv88e6185_g1_reset,
}; };
...@@ -3241,6 +3193,8 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { ...@@ -3241,6 +3193,8 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
.stats_get_strings = mv88e6095_stats_get_strings, .stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats, .stats_get_stats = mv88e6095_stats_get_stats,
.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu, .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
.ppu_enable = mv88e6185_g1_ppu_enable,
.ppu_disable = mv88e6185_g1_ppu_disable,
.reset = mv88e6185_g1_reset, .reset = mv88e6185_g1_reset,
}; };
...@@ -3311,6 +3265,8 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { ...@@ -3311,6 +3265,8 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
.g1_set_cpu_port = mv88e6095_g1_set_cpu_port, .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
.g1_set_egress_port = mv88e6095_g1_set_egress_port, .g1_set_egress_port = mv88e6095_g1_set_egress_port,
.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu, .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
.ppu_enable = mv88e6185_g1_ppu_enable,
.ppu_disable = mv88e6185_g1_ppu_disable,
.reset = mv88e6185_g1_reset, .reset = mv88e6185_g1_reset,
}; };
...@@ -3483,6 +3439,8 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { ...@@ -3483,6 +3439,8 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
.g1_set_cpu_port = mv88e6095_g1_set_cpu_port, .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
.g1_set_egress_port = mv88e6095_g1_set_egress_port, .g1_set_egress_port = mv88e6095_g1_set_egress_port,
.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu, .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
.ppu_enable = mv88e6185_g1_ppu_enable,
.ppu_disable = mv88e6185_g1_ppu_disable,
.reset = mv88e6185_g1_reset, .reset = mv88e6185_g1_reset,
}; };
...@@ -4263,13 +4221,13 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev) ...@@ -4263,13 +4221,13 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
static void mv88e6xxx_phy_init(struct mv88e6xxx_chip *chip) static void mv88e6xxx_phy_init(struct mv88e6xxx_chip *chip)
{ {
if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU)) if (chip->info->ops->ppu_enable && chip->info->ops->ppu_disable)
mv88e6xxx_ppu_state_init(chip); mv88e6xxx_ppu_state_init(chip);
} }
static void mv88e6xxx_phy_destroy(struct mv88e6xxx_chip *chip) static void mv88e6xxx_phy_destroy(struct mv88e6xxx_chip *chip)
{ {
if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU)) if (chip->info->ops->ppu_enable && chip->info->ops->ppu_disable)
mv88e6xxx_ppu_state_destroy(chip); mv88e6xxx_ppu_state_destroy(chip);
} }
......
...@@ -35,6 +35,27 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) ...@@ -35,6 +35,27 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
/* Offset 0x00: Switch Global Status Register */ /* Offset 0x00: Switch Global Status Register */
static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip)
{
u16 state;
int i, err;
for (i = 0; i < 16; i++) {
err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
if (err)
return err;
/* Check the value of the PPUState bits 15:14 */
state &= GLOBAL_STATUS_PPU_STATE_MASK;
if (state != GLOBAL_STATUS_PPU_STATE_POLLING)
return 0;
usleep_range(1000, 2000);
}
return -ETIMEDOUT;
}
static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip) static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
{ {
u16 state; u16 state;
...@@ -154,6 +175,42 @@ int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip) ...@@ -154,6 +175,42 @@ int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
return mv88e6352_g1_wait_ppu_polling(chip); return mv88e6352_g1_wait_ppu_polling(chip);
} }
int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip)
{
u16 val;
int err;
err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
if (err)
return err;
val |= GLOBAL_CONTROL_PPU_ENABLE;
err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
if (err)
return err;
return mv88e6185_g1_wait_ppu_polling(chip);
}
int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip)
{
u16 val;
int err;
err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
if (err)
return err;
val &= ~GLOBAL_CONTROL_PPU_ENABLE;
err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
if (err)
return err;
return mv88e6185_g1_wait_ppu_disabled(chip);
}
/* Offset 0x1a: Monitor Control */ /* Offset 0x1a: Monitor Control */
/* Offset 0x1a: Monitor & MGMT Control on some devices */ /* Offset 0x1a: Monitor & MGMT Control on some devices */
......
...@@ -23,6 +23,9 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask); ...@@ -23,6 +23,9 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask);
int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip);
int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip);
int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip);
int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip);
int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip); int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip);
int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port); int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port); int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
......
...@@ -490,12 +490,6 @@ enum mv88e6xxx_cap { ...@@ -490,12 +490,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_CAP_G2_PVT_DATA, /* (0x0c) Cross Chip Port VLAN Data */ MV88E6XXX_CAP_G2_PVT_DATA, /* (0x0c) Cross Chip Port VLAN Data */
MV88E6XXX_CAP_G2_POT, /* (0x0f) Priority Override Table */ MV88E6XXX_CAP_G2_POT, /* (0x0f) Priority Override Table */
/* PHY Polling Unit.
* See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
*/
MV88E6XXX_CAP_PPU,
MV88E6XXX_CAP_PPU_ACTIVE,
/* Per VLAN Spanning Tree Unit (STU). /* Per VLAN Spanning Tree Unit (STU).
* The Port State database, if present, is accessed through VTU * The Port State database, if present, is accessed through VTU
* operations and dedicated SID registers. See GLOBAL_VTU_SID. * operations and dedicated SID registers. See GLOBAL_VTU_SID.
...@@ -537,8 +531,6 @@ enum mv88e6xxx_cap { ...@@ -537,8 +531,6 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_G2_PVT_DATA BIT_ULL(MV88E6XXX_CAP_G2_PVT_DATA) #define MV88E6XXX_FLAG_G2_PVT_DATA BIT_ULL(MV88E6XXX_CAP_G2_PVT_DATA)
#define MV88E6XXX_FLAG_G2_POT BIT_ULL(MV88E6XXX_CAP_G2_POT) #define MV88E6XXX_FLAG_G2_POT BIT_ULL(MV88E6XXX_CAP_G2_POT)
#define MV88E6XXX_FLAG_PPU BIT_ULL(MV88E6XXX_CAP_PPU)
#define MV88E6XXX_FLAG_PPU_ACTIVE BIT_ULL(MV88E6XXX_CAP_PPU_ACTIVE)
#define MV88E6XXX_FLAG_STU BIT_ULL(MV88E6XXX_CAP_STU) #define MV88E6XXX_FLAG_STU BIT_ULL(MV88E6XXX_CAP_STU)
#define MV88E6XXX_FLAG_TEMP BIT_ULL(MV88E6XXX_CAP_TEMP) #define MV88E6XXX_FLAG_TEMP BIT_ULL(MV88E6XXX_CAP_TEMP)
#define MV88E6XXX_FLAG_TEMP_LIMIT BIT_ULL(MV88E6XXX_CAP_TEMP_LIMIT) #define MV88E6XXX_FLAG_TEMP_LIMIT BIT_ULL(MV88E6XXX_CAP_TEMP_LIMIT)
...@@ -567,7 +559,6 @@ enum mv88e6xxx_cap { ...@@ -567,7 +559,6 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6095 \ #define MV88E6XXX_FLAGS_FAMILY_6095 \
(MV88E6XXX_FLAG_GLOBAL2 | \ (MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_VTU | \ MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_MULTI_CHIP) MV88E6XXX_FLAGS_MULTI_CHIP)
...@@ -578,7 +569,6 @@ enum mv88e6xxx_cap { ...@@ -578,7 +569,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \ MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_STU | \ MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_VTU | \ MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_IRL | \
...@@ -605,7 +595,6 @@ enum mv88e6xxx_cap { ...@@ -605,7 +595,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_INT | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAGS_MULTI_CHIP | \ MV88E6XXX_FLAGS_MULTI_CHIP | \
MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_VTU) MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6320 \ #define MV88E6XXX_FLAGS_FAMILY_6320 \
...@@ -614,7 +603,6 @@ enum mv88e6xxx_cap { ...@@ -614,7 +603,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \ MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_PPU_ACTIVE | \
MV88E6XXX_FLAG_TEMP | \ MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_TEMP_LIMIT | \ MV88E6XXX_FLAG_TEMP_LIMIT | \
MV88E6XXX_FLAG_VTU | \ MV88E6XXX_FLAG_VTU | \
...@@ -630,7 +618,6 @@ enum mv88e6xxx_cap { ...@@ -630,7 +618,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \ MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_PPU_ACTIVE | \
MV88E6XXX_FLAG_STU | \ MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_TEMP | \ MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_VTU | \ MV88E6XXX_FLAG_VTU | \
...@@ -647,7 +634,6 @@ enum mv88e6xxx_cap { ...@@ -647,7 +634,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \ MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_PPU_ACTIVE | \
MV88E6XXX_FLAG_STU | \ MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_TEMP | \ MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_TEMP_LIMIT | \ MV88E6XXX_FLAG_TEMP_LIMIT | \
...@@ -662,7 +648,6 @@ struct mv88e6xxx_ops; ...@@ -662,7 +648,6 @@ struct mv88e6xxx_ops;
#define MV88E6XXX_FLAGS_FAMILY_6390 \ #define MV88E6XXX_FLAGS_FAMILY_6390 \
(MV88E6XXX_FLAG_EEE | \ (MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_PPU_ACTIVE | \
MV88E6XXX_FLAG_STU | \ MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_TEMP | \ MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_TEMP_LIMIT | \ MV88E6XXX_FLAG_TEMP_LIMIT | \
...@@ -792,6 +777,10 @@ struct mv88e6xxx_ops { ...@@ -792,6 +777,10 @@ struct mv88e6xxx_ops {
int (*phy_write)(struct mv88e6xxx_chip *chip, int addr, int reg, int (*phy_write)(struct mv88e6xxx_chip *chip, int addr, int reg,
u16 val); u16 val);
/* PHY Polling Unit (PPU) operations */
int (*ppu_enable)(struct mv88e6xxx_chip *chip);
int (*ppu_disable)(struct mv88e6xxx_chip *chip);
/* Switch Software Reset */ /* Switch Software Reset */
int (*reset)(struct mv88e6xxx_chip *chip); int (*reset)(struct mv88e6xxx_chip *chip);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment