|
@@ -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);
|
|
|
+}
|