spmi: msm: correctly handle multiple mapping entries
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@linaro.org> Tested-by: caleb.connolly@linaro.org # sdm845 Link: https://lore.kernel.org/r/20250328-topic-sm8x50-spmi-fix-v1-4-a7548d3aef0d@linaro.org Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
This commit is contained in:

committed by
Caleb Connolly

parent
69400a696c
commit
5b233442af
@@ -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);
|
||||
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;
|
||||
|
||||
priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
|
||||
if (owner != priv->owner)
|
||||
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)
|
||||
|
Reference in New Issue
Block a user