Kaynağa Gözat

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>
Suman Anna 6 yıl önce
ebeveyn
işleme
4022d1222e
1 değiştirilmiş dosya ile 4 ekleme ve 0 silme
  1. 4 0
      drivers/irqchip/irq-pruss-intc.c

+ 4 - 0
drivers/irqchip/irq-pruss-intc.c

@@ -201,6 +201,8 @@ int pruss_intc_configure(struct pruss *pruss,
 
 		idx = i / CMR_EVT_PER_REG;
 		val = pruss_intc_read_reg(intc, PRU_INTC_CMR(idx));
+		val &= ~(CMR_EVT_MAP_MASK <<
+			 ((i % CMR_EVT_PER_REG) * CMR_EVT_MAP_BITS));
 		val |= ch << ((i % CMR_EVT_PER_REG) * CMR_EVT_MAP_BITS);
 		pruss_intc_write_reg(intc, PRU_INTC_CMR(idx), val);
 		sysevt_mask |= BIT_ULL(i);
@@ -241,6 +243,8 @@ int pruss_intc_configure(struct pruss *pruss,
 		idx = i / HMR_CH_PER_REG;
 
 		val = pruss_intc_read_reg(intc, PRU_INTC_HMR(idx));
+		val &= ~(HMR_CH_MAP_MASK <<
+			 ((i % HMR_CH_PER_REG) * HMR_CH_MAP_BITS));
 		val |= host << ((i % HMR_CH_PER_REG) * HMR_CH_MAP_BITS);
 		pruss_intc_write_reg(intc, PRU_INTC_HMR(idx), val);