[PATCH 4/4] spmi: msm: correctly handle multiple mapping entries
Neil Armstrong
neil.armstrong at linaro.org
Fri Mar 28 09:53:24 CET 2025
On v5 & v7 controllers, multiple mapping for different
Execution Environment exists, if the mapping owner is for
a different Execution Environment we can only read and
not write any data.
To allow us to find a Write mapping for our Execution
Environment, we can overwritte a mapping if we encounter
a new one which we own.
Implement this logic, the result is the same mapping
table as in Linux.
Signed-off-by: Neil Armstrong <neil.armstrong at linaro.org>
---
drivers/spmi/spmi-msm.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
index ee3feaf8b5049d51665330a63110ed4949e59bd6..faae54e9fef025466787541631ce5b5171444621 100644
--- a/drivers/spmi/spmi-msm.c
+++ b/drivers/spmi/spmi-msm.c
@@ -254,16 +254,30 @@ static struct dm_spmi_ops msm_spmi_ops = {
.write = msm_spmi_write,
};
+/*
+ * In order to allow multiple EEs to write to a single PPID in arbiter
+ * version 5 and 7, there is more than one APID mapped to each PPID.
+ * The owner field for each of these mappings specifies the EE which is
+ * allowed to write to the APID.
+ */
static void msm_spmi_channel_map_v5(struct msm_spmi_priv *priv, unsigned int i,
uint8_t slave_id, uint8_t pid)
{
/* Mark channels read-only when from different owner */
uint32_t cnfg = readl(priv->spmi_cnfg + ARB_CHANNEL_OFFSET(i));
uint8_t owner = SPMI_OWNERSHIP_PERIPH2OWNER(cnfg);
-
- priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
- if (owner != priv->owner)
- priv->channel_map[slave_id][pid] |= SPMI_CHANNEL_READ_ONLY;
+ bool prev_valid = priv->channel_map[slave_id][pid] & SPMI_CHANNEL_VALID;
+ uint32_t prev_read_only = priv->channel_map[slave_id][pid] & SPMI_CHANNEL_READ_ONLY;
+
+ if (!prev_valid) {
+ /* First PPID mapping */
+ priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
+ if (owner != priv->owner)
+ priv->channel_map[slave_id][pid] |= SPMI_CHANNEL_READ_ONLY;
+ } else if ((owner == priv->owner) && prev_read_only) {
+ /* Read only and we found one we own, switch */
+ priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
+ }
}
static int msm_spmi_probe(struct udevice *dev)
--
2.34.1
More information about the U-Boot
mailing list