spmi: msm: use real number of channels for v5 & v7
authorNeil Armstrong <neil.armstrong@linaro.org>
Fri, 28 Mar 2025 08:53:21 +0000 (09:53 +0100)
committerCaleb Connolly <caleb.connolly@linaro.org>
Thu, 10 Apr 2025 13:43:10 +0000 (15:43 +0200)
The SPMI_MAX_CHANNELS_Vx are only the maximum channels supported
by the controller, but the real number of channels mapped on this
system can be read from a register, so take this info.

This allows no to overlap on the second controller present on
the V7 SPMI arbiter, otherwise we would also parse the mapping
of the second SPMI bus and we would bet the wrong IDs.

Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: caleb.connolly@linaro.org # sdm845
Link: https://lore.kernel.org/r/20250328-topic-sm8x50-spmi-fix-v1-1-a7548d3aef0d@linaro.org
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
drivers/spmi/spmi-msm.c

index 5cc5a9e..08be451 100644 (file)
@@ -24,6 +24,9 @@ DECLARE_GLOBAL_DATA_PTR;
 #define PMIC_ARB_VERSION_V5_MIN 0x50000000
 #define PMIC_ARB_VERSION_V7_MIN        0x70000000
 
+#define PMIC_ARB_FEATURES              0x0004
+#define PMIC_ARB_FEATURES_PERIPH_MASK  GENMASK(10, 0)
+
 #define APID_MAP_OFFSET_V1_V2_V3 (0x800)
 #define APID_MAP_OFFSET_V5 (0x900)
 #define APID_MAP_OFFSET_V7 (0x2000)
@@ -271,13 +274,17 @@ static int msm_spmi_probe(struct udevice *dev)
        } else if (hw_ver < PMIC_ARB_VERSION_V7_MIN) {
                priv->arb_ver = V5;
                priv->arb_chnl = core_addr + APID_MAP_OFFSET_V5;
-               priv->max_channels = SPMI_MAX_CHANNELS_V5;
+               priv->max_channels = min_t(u32, readl(core_addr + PMIC_ARB_FEATURES) &
+                                               PMIC_ARB_FEATURES_PERIPH_MASK,
+                                          SPMI_MAX_CHANNELS_V5);
                priv->spmi_cnfg = dev_read_addr_name(dev, "cnfg");
        } else {
                /* TOFIX: handle second bus */
                priv->arb_ver = V7;
                priv->arb_chnl = core_addr + APID_MAP_OFFSET_V7;
-               priv->max_channels = SPMI_MAX_CHANNELS_V7;
+               priv->max_channels = min_t(u32, readl(core_addr + PMIC_ARB_FEATURES) &
+                                               PMIC_ARB_FEATURES_PERIPH_MASK,
+                                          SPMI_MAX_CHANNELS_V7);
                priv->spmi_cnfg = dev_read_addr_name(dev, "cnfg");
        }