diff options
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx/global2_scratch.c')
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/global2_scratch.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/global2_scratch.c b/drivers/net/dsa/mv88e6xxx/global2_scratch.c index 0ff12bff9f0e..3f92b8892dc7 100644 --- a/drivers/net/dsa/mv88e6xxx/global2_scratch.c +++ b/drivers/net/dsa/mv88e6xxx/global2_scratch.c @@ -238,3 +238,54 @@ const struct mv88e6xxx_gpio_ops mv88e6352_gpio_ops = { .get_pctl = mv88e6352_g2_scratch_gpio_get_pctl, .set_pctl = mv88e6352_g2_scratch_gpio_set_pctl, }; + +/** + * mv88e6xxx_g2_gpio_set_smi - set gpio muxing for external smi + * @chip: chip private data + * @external: set mux for external smi, or free for gpio usage + * + * Some mv88e6xxx models have GPIO pins that may be configured as + * an external SMI interface, or they may be made free for other + * GPIO uses. + */ +int mv88e6xxx_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip *chip, + bool external) +{ + int misc_cfg = MV88E6352_G2_SCRATCH_MISC_CFG; + int config_data1 = MV88E6352_G2_SCRATCH_CONFIG_DATA1; + int config_data2 = MV88E6352_G2_SCRATCH_CONFIG_DATA2; + bool no_cpu; + u8 p0_mode; + int err; + u8 val; + + err = mv88e6xxx_g2_scratch_read(chip, config_data2, &val); + if (err) + return err; + + p0_mode = val & MV88E6352_G2_SCRATCH_CONFIG_DATA2_P0_MODE_MASK; + + if (p0_mode == 0x01 || p0_mode == 0x02) + return -EBUSY; + + err = mv88e6xxx_g2_scratch_read(chip, config_data1, &val); + if (err) + return err; + + no_cpu = !!(val & MV88E6352_G2_SCRATCH_CONFIG_DATA1_NO_CPU); + + err = mv88e6xxx_g2_scratch_read(chip, misc_cfg, &val); + if (err) + return err; + + /* NO_CPU being 0 inverts the meaning of the bit */ + if (!no_cpu) + external = !external; + + if (external) + val |= MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI; + else + val &= ~MV88E6352_G2_SCRATCH_MISC_CFG_NORMALSMI; + + return mv88e6xxx_g2_scratch_write(chip, misc_cfg, val); +} |