瀏覽代碼

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 年之前
父節點
當前提交
4022d1222e
共有 1 個文件被更改,包括 4 次插入0 次删除
  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);