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,
|
.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,
|
static void msm_spmi_channel_map_v5(struct msm_spmi_priv *priv, unsigned int i,
|
||||||
uint8_t slave_id, uint8_t pid)
|
uint8_t slave_id, uint8_t pid)
|
||||||
{
|
{
|
||||||
/* Mark channels read-only when from different owner */
|
/* Mark channels read-only when from different owner */
|
||||||
uint32_t cnfg = readl(priv->spmi_cnfg + ARB_CHANNEL_OFFSET(i));
|
uint32_t cnfg = readl(priv->spmi_cnfg + ARB_CHANNEL_OFFSET(i));
|
||||||
uint8_t owner = SPMI_OWNERSHIP_PERIPH2OWNER(cnfg);
|
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;
|
||||||
|
|
||||||
|
if (!prev_valid) {
|
||||||
|
/* First PPID mapping */
|
||||||
priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
|
priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
|
||||||
if (owner != priv->owner)
|
if (owner != priv->owner)
|
||||||
priv->channel_map[slave_id][pid] |= SPMI_CHANNEL_READ_ONLY;
|
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)
|
static int msm_spmi_probe(struct udevice *dev)
|
||||||
|
Reference in New Issue
Block a user