aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuman Anna2019-06-28 20:52:09 -0500
committerSuman Anna2019-07-01 11:48:05 -0500
commit4022d1222efe82fb17ccf271af352b1206b012e0 (patch)
treeee94c5ad0efda2f8a7d06bd7a5c60192d8681fe0
parent57c76b3f28042138bf92c203a3db576a66aab5cc (diff)
downloadremoteproc-4022d1222efe82fb17ccf271af352b1206b012e0.tar.gz
remoteproc-4022d1222efe82fb17ccf271af352b1206b012e0.tar.xz
remoteproc-4022d1222efe82fb17ccf271af352b1206b012e0.zip
irqchip/irq-pruss-intc: Fix erroneous channel/host mapping logic
The PRUSS INTC uses two-levels of many-to-one mappings to route various PRU System Events to a limited number of output interrupt lines connected to various processors on the SoC. This event mapping configuration logic is optimized to program the associated Channel Map Registers (CMRx) and Host Interrupt Map Registers (HMRx) only when a new program is being loaded/started and simply disables the same events and interrupt channels without zeroing out the corresponding map registers when stopping a PRU. The map logic currently does not zero out the previous field value before programming the new value, and thereby potentially mapping a completely different value in the CMR and HMR registers (if previous values are not zero) and resulting in non-functional interrupts. Fix this erroneous bitwise logic. Reported-by: Nick Saulnier <nsaulnier@ti.com> Signed-off-by: Suman Anna <s-anna@ti.com> Acked-by: Roger Quadros <rogerq@ti.com>
-rw-r--r--drivers/irqchip/irq-pruss-intc.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-pruss-intc.c b/drivers/irqchip/irq-pruss-intc.c
index 2bd2498ac389..fe4dc776fb2a 100644
--- a/drivers/irqchip/irq-pruss-intc.c
+++ b/drivers/irqchip/irq-pruss-intc.c
@@ -201,6 +201,8 @@ int pruss_intc_configure(struct pruss *pruss,
201 201
202 idx = i / CMR_EVT_PER_REG; 202 idx = i / CMR_EVT_PER_REG;
203 val = pruss_intc_read_reg(intc, PRU_INTC_CMR(idx)); 203 val = pruss_intc_read_reg(intc, PRU_INTC_CMR(idx));
204 val &= ~(CMR_EVT_MAP_MASK <<
205 ((i % CMR_EVT_PER_REG) * CMR_EVT_MAP_BITS));
204 val |= ch << ((i % CMR_EVT_PER_REG) * CMR_EVT_MAP_BITS); 206 val |= ch << ((i % CMR_EVT_PER_REG) * CMR_EVT_MAP_BITS);
205 pruss_intc_write_reg(intc, PRU_INTC_CMR(idx), val); 207 pruss_intc_write_reg(intc, PRU_INTC_CMR(idx), val);
206 sysevt_mask |= BIT_ULL(i); 208 sysevt_mask |= BIT_ULL(i);
@@ -241,6 +243,8 @@ int pruss_intc_configure(struct pruss *pruss,
241 idx = i / HMR_CH_PER_REG; 243 idx = i / HMR_CH_PER_REG;
242 244
243 val = pruss_intc_read_reg(intc, PRU_INTC_HMR(idx)); 245 val = pruss_intc_read_reg(intc, PRU_INTC_HMR(idx));
246 val &= ~(HMR_CH_MAP_MASK <<
247 ((i % HMR_CH_PER_REG) * HMR_CH_MAP_BITS));
244 val |= host << ((i % HMR_CH_PER_REG) * HMR_CH_MAP_BITS); 248 val |= host << ((i % HMR_CH_PER_REG) * HMR_CH_MAP_BITS);
245 pruss_intc_write_reg(intc, PRU_INTC_HMR(idx), val); 249 pruss_intc_write_reg(intc, PRU_INTC_HMR(idx), val);
246 250