]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mfd: bcm590xx: Add PMU ID/revision parsing function
authorArtur Weber <aweber.kernel@gmail.com>
Thu, 15 May 2025 14:16:31 +0000 (16:16 +0200)
committerLee Jones <lee@kernel.org>
Thu, 22 May 2025 09:57:00 +0000 (10:57 +0100)
The BCM590xx PMUs have two I2C registers for reading the PMU ID
and revision. The revision is useful for subdevice drivers, since
different revisions may have slight differences in behavior (for
example - BCM59054 has different regulator configurations for
revision A0 and A1).

Check the PMU ID register and make sure it matches the DT compatible.
Fetch the digital and analog revision from the PMUREV register
so that it can be used in subdevice drivers.

Also add some known revision values to bcm590xx.h, for convenience
when writing subdevice drivers.

Signed-off-by: Artur Weber <aweber.kernel@gmail.com>
Reviewed-by: Stanislav Jakubek <stano.jakubek@gmail.com>
Link: https://lore.kernel.org/r/20250515-bcm59054-v9-4-14ba0ea2ea5b@gmail.com
Signed-off-by: Lee Jones <lee@kernel.org>
drivers/mfd/bcm590xx.c
include/linux/mfd/bcm590xx.h

index 4620eed0066fbf1dd691a2e392e967747b4d125b..5a8456bbd63f65b9260f05ef6546c026bf822bae 100644 (file)
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
+/* Under primary I2C address: */
+#define BCM590XX_REG_PMUID             0x1e
+
+#define BCM590XX_REG_PMUREV            0x1f
+#define BCM590XX_PMUREV_DIG_MASK       0xF
+#define BCM590XX_PMUREV_DIG_SHIFT      0
+#define BCM590XX_PMUREV_ANA_MASK       0xF0
+#define BCM590XX_PMUREV_ANA_SHIFT      4
+
 static const struct mfd_cell bcm590xx_devs[] = {
        {
                .name = "bcm590xx-vregs",
@@ -37,6 +46,47 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
        .cache_type     = REGCACHE_MAPLE,
 };
 
+/* Map PMU ID value to model name string */
+static const char * const bcm590xx_names[] = {
+       [BCM590XX_PMUID_BCM59054] = "BCM59054",
+       [BCM590XX_PMUID_BCM59056] = "BCM59056",
+};
+
+static int bcm590xx_parse_version(struct bcm590xx *bcm590xx)
+{
+       unsigned int id, rev;
+       int ret;
+
+       /* Get PMU ID and verify that it matches compatible */
+       ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUID, &id);
+       if (ret) {
+               dev_err(bcm590xx->dev, "failed to read PMU ID: %d\n", ret);
+               return ret;
+       }
+
+       if (id != bcm590xx->pmu_id) {
+               dev_err(bcm590xx->dev, "Incorrect ID for %s: expected %x, got %x.\n",
+                       bcm590xx_names[bcm590xx->pmu_id], bcm590xx->pmu_id, id);
+               return -ENODEV;
+       }
+
+       /* Get PMU revision and store it in the info struct */
+       ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUREV, &rev);
+       if (ret) {
+               dev_err(bcm590xx->dev, "failed to read PMU revision: %d\n", ret);
+               return ret;
+       }
+
+       bcm590xx->rev_digital = (rev & BCM590XX_PMUREV_DIG_MASK) >> BCM590XX_PMUREV_DIG_SHIFT;
+
+       bcm590xx->rev_analog = (rev & BCM590XX_PMUREV_ANA_MASK) >> BCM590XX_PMUREV_ANA_SHIFT;
+
+       dev_dbg(bcm590xx->dev, "PMU ID 0x%x (%s), revision: digital %d, analog %d",
+                id, bcm590xx_names[id], bcm590xx->rev_digital, bcm590xx->rev_analog);
+
+       return 0;
+}
+
 static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
 {
        struct bcm590xx *bcm590xx;
@@ -78,6 +128,10 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
                goto err;
        }
 
+       ret = bcm590xx_parse_version(bcm590xx);
+       if (ret)
+               goto err;
+
        ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,
                                   ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
        if (ret < 0) {
index 76c30e6293338fa6dae8baa00768492af81aae4f..a54c50b2d2c8f389fcabed4c79d0477f66142ac5 100644 (file)
 #define BCM590XX_PMUID_BCM59054                0x54
 #define BCM590XX_PMUID_BCM59056                0x56
 
+/* Known chip revision IDs */
+#define BCM59054_REV_DIGITAL_A1                1
+#define BCM59054_REV_ANALOG_A1         2
+
+#define BCM59056_REV_DIGITAL_A0                1
+#define BCM59056_REV_ANALOG_A0         1
+
+#define BCM59056_REV_DIGITAL_B0                2
+#define BCM59056_REV_ANALOG_B0         2
+
 /* max register address */
 #define BCM590XX_MAX_REGISTER_PRI      0xe7
 #define BCM590XX_MAX_REGISTER_SEC      0xf0
@@ -31,6 +41,10 @@ struct bcm590xx {
 
        /* PMU ID value; also used as device type */
        u8 pmu_id;
+
+       /* Chip revision, read from PMUREV reg */
+       u8 rev_digital;
+       u8 rev_analog;
 };
 
 #endif /*  __LINUX_MFD_BCM590XX_H */