diff mbox series

[4/4] spmi: msm: support controller version 7

Message ID 20240405-topic-sm8x50-spmi-fixes-v1-4-031a9e5efab4@linaro.org
State Accepted
Commit ee1d8aa5ecf77991d3bbcfea2d5b37d88bb19473
Headers show
Series smpi: msm: fix version 5 and add version 7 support | expand

Commit Message

Neil Armstrong April 5, 2024, 8:21 a.m. UTC
Add the defines and support for SPMI arbiters version 7,
which can handle up to 1024 peripherals, and can also drive
a secondary bus which is not implemented yet.

Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/spmi/spmi-msm.c | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
index 46e2e09dc26..244de69b359 100644
--- a/drivers/spmi/spmi-msm.c
+++ b/drivers/spmi/spmi-msm.c
@@ -23,13 +23,17 @@  DECLARE_GLOBAL_DATA_PTR;
 #define PMIC_ARB_VERSION_V2_MIN 0x20010000
 #define PMIC_ARB_VERSION_V3_MIN 0x30000000
 #define PMIC_ARB_VERSION_V5_MIN 0x50000000
+#define PMIC_ARB_VERSION_V7_MIN	0x70000000
 
 #define APID_MAP_OFFSET_V1_V2_V3 (0x800)
 #define APID_MAP_OFFSET_V5 (0x900)
+#define APID_MAP_OFFSET_V7 (0x2000)
 #define ARB_CHANNEL_OFFSET(n) (0x4 * (n))
 #define SPMI_CH_OFFSET(chnl) ((chnl) * 0x8000)
 #define SPMI_V5_OBS_CH_OFFSET(chnl) ((chnl) * 0x80)
+#define SPMI_V7_OBS_CH_OFFSET(chnl) ((chnl) * 0x20)
 #define SPMI_V5_RW_CH_OFFSET(chnl) ((chnl) * 0x10000)
+#define SPMI_V7_RW_CH_OFFSET(chnl) ((chnl) * 0x1000)
 
 #define SPMI_OWNERSHIP_PERIPH2OWNER(x)	((x) & 0x7)
 
@@ -52,6 +56,7 @@  DECLARE_GLOBAL_DATA_PTR;
 
 #define SPMI_MAX_CHANNELS 128
 #define SPMI_MAX_CHANNELS_V5	512
+#define SPMI_MAX_CHANNELS_V7	1024
 #define SPMI_MAX_SLAVES 16
 #define SPMI_MAX_PERIPH 256
 
@@ -62,7 +67,8 @@  enum arb_ver {
 	V1 = 1,
 	V2,
 	V3,
-	V5 = 5
+	V5 = 5,
+	V7 = 7
 };
 
 /*
@@ -133,6 +139,12 @@  static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off,
 	case V5:
 		ch_offset = SPMI_V5_RW_CH_OFFSET(channel);
 
+		reg = pmic_arb_fmt_cmd_v2(SPMI_CMD_EXT_REG_WRITE_LONG, off);
+		break;
+
+	case V7:
+		ch_offset = SPMI_V7_RW_CH_OFFSET(channel);
+
 		reg = pmic_arb_fmt_cmd_v2(SPMI_CMD_EXT_REG_WRITE_LONG, off);
 		break;
 	}
@@ -196,6 +208,13 @@  static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off)
 	case V5:
 		ch_offset = SPMI_V5_OBS_CH_OFFSET(channel);
 
+		/* Prepare read command */
+		reg = pmic_arb_fmt_cmd_v2(SPMI_CMD_EXT_REG_READ_LONG, off);
+		break;
+
+	case V7:
+		ch_offset = SPMI_V7_OBS_CH_OFFSET(channel);
+
 		/* Prepare read command */
 		reg = pmic_arb_fmt_cmd_v2(SPMI_CMD_EXT_REG_READ_LONG, off);
 		break;
@@ -250,10 +269,16 @@  static int msm_spmi_probe(struct udevice *dev)
 		priv->arb_ver = V3;
 		priv->arb_chnl = core_addr + APID_MAP_OFFSET_V1_V2_V3;
 		priv->max_channels = SPMI_MAX_CHANNELS;
-	} else {
+	} 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 = SPMI_MAX_CHANNELS;
+		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->spmi_cnfg = dev_read_addr_name(dev, "cnfg");
 	}
 
@@ -276,7 +301,7 @@  static int msm_spmi_probe(struct udevice *dev)
 		priv->channel_map[slave_id][pid] = i;
 
 		/* Mark channels read-only when from different owner */
-		if (priv->arb_ver == V5) {
+		if (priv->arb_ver == V5 || priv->arb_ver == V7) {
 			uint32_t cnfg = readl(priv->spmi_cnfg + ARB_CHANNEL_OFFSET(i));
 			uint8_t owner = SPMI_OWNERSHIP_PERIPH2OWNER(cnfg);