Ver Fonte

Merge branch 'topic/4.19/am65x' of git://git.ti.com/rpmsg/remoteproc into rpmsg-ti-linux-4.19.y

Pull in the dedicated AM65x remoteproc topic branch that cleans up
the PRUSS INTC configuration code to use human-readable macros, and
a fix for an INTC mapping configuration logic bug exposed when running
different applications using different system event-to-channel and/or
channel-to-host interrupt mappings back to back.

* 'topic/4.19/am65x' of git://git.ti.com/rpmsg/remoteproc:
  irqchip/irq-pruss-intc: Fix erroneous channel/host mapping logic
  irqchip/irq-pruss-intc: Use macros for operations on CMR and HMR
  irqchip/irq-pruss-intc: Use macros for operations on CMR and HMR
  TEMP: irqchip/irq-pruss-intc: Allow setting irq affinity for PRU events
  irqchip/irq-pruss-intc: Reset chained handlers during cleanup

Signed-off-by: Suman Anna <s-anna@ti.com>
Suman Anna há 6 anos atrás
pai
commit
2e8602b1ea
1 ficheiros alterados com 29 adições e 12 exclusões
  1. 29 12
      drivers/irqchip/irq-pruss-intc.c

+ 29 - 12
drivers/irqchip/irq-pruss-intc.c

@@ -55,6 +55,16 @@
 #define PRU_INTC_HINLR(x)	(0x1100 + (x) * 4)
 #define PRU_INTC_HIER		0x1500
 
+/* CMR register bit-field macros */
+#define CMR_EVT_MAP_MASK	0xf
+#define CMR_EVT_MAP_BITS	8
+#define CMR_EVT_PER_REG		4
+
+/* HMR register bit-field macros */
+#define HMR_CH_MAP_MASK		0xf
+#define HMR_CH_MAP_BITS		8
+#define HMR_CH_PER_REG		4
+
 /* HIPIR register bit-fields */
 #define INTC_HIPIR_NONE_HINT	0x80000000
 
@@ -211,9 +221,11 @@ int pruss_intc_configure(struct pruss *pruss,
 
 		intc->config_map.sysev_to_ch[i] = ch;
 
-		idx = i / 4;
+		idx = i / CMR_EVT_PER_REG;
 		val = pruss_intc_read_reg(intc, PRU_INTC_CMR(idx));
-		val |= ch << ((i & 3) * 8);
+		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);
 		bitmap_set(sysevt_bitmap, i, 1);
 		ch_mask |= BIT(ch);
@@ -250,10 +262,12 @@ int pruss_intc_configure(struct pruss *pruss,
 
 		intc->config_map.ch_to_host[i] = host;
 
-		idx = i / 4;
+		idx = i / HMR_CH_PER_REG;
 
 		val = pruss_intc_read_reg(intc, PRU_INTC_HMR(idx));
-		val |= host << ((i & 3) * 8);
+		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);
 
 		ch_mask |= BIT(i);
@@ -376,8 +390,10 @@ EXPORT_SYMBOL_GPL(pruss_intc_unconfigure);
 static void pruss_intc_init(struct pruss_intc *intc)
 {
 	int i;
-	int num_chnl_map_regs = DIV_ROUND_UP(intc->data->num_system_events, 4);
-	int num_host_intr_regs = DIV_ROUND_UP(intc->data->num_host_intrs, 4);
+	int num_chnl_map_regs = DIV_ROUND_UP(intc->data->num_system_events,
+					     CMR_EVT_PER_REG);
+	int num_host_intr_regs = DIV_ROUND_UP(intc->data->num_host_intrs,
+					      HMR_CH_PER_REG);
 	int num_event_type_regs =
 			DIV_ROUND_UP(intc->data->num_system_events, 32);
 
@@ -468,14 +484,15 @@ static int pruss_intc_irq_set_affinity(struct irq_data *data,
 	}
 
 	/* find programmed channel */
-	ch = pruss_intc_read_reg(intc, PRU_INTC_CMR(data->hwirq / 4));
-	ch >>= (data->hwirq % 4) * 8;
-	ch &= 0xf;
+	ch = pruss_intc_read_reg(intc,
+				 PRU_INTC_CMR(data->hwirq / CMR_EVT_PER_REG));
+	ch >>= (data->hwirq % CMR_EVT_PER_REG) * CMR_EVT_MAP_BITS;
+	ch &= CMR_EVT_MAP_MASK;
 
 	/* find programmed host interrupt */
-	host = pruss_intc_read_reg(intc, PRU_INTC_HMR(ch / 4));
-	host >>= (ch % 4) * 8;
-	host &= 0xf;
+	host = pruss_intc_read_reg(intc, PRU_INTC_HMR(ch / HMR_CH_MAP_BITS));
+	host >>= (ch % HMR_CH_PER_REG) * HMR_CH_MAP_BITS;
+	host &= HMR_CH_MAP_MASK;
 
 	/* check programmed configuration for sanity */
 	if (ch != sch || host != shost) {