svn commit: r271601 - in head/sys/arm: arm include

Ian Lepore ian at FreeBSD.org
Sun Sep 14 21:21:04 UTC 2014


Author: ian
Date: Sun Sep 14 21:21:03 2014
New Revision: 271601
URL: http://svnweb.freebsd.org/changeset/base/271601

Log:
  Add a common routine for parsing FDT data describing an ARM GIC interrupt.
  
  In the fdt data we've written for ourselves, the interrupt properties
  for GIC interrupts have just been a bare interrupt number.  In standard
  data that conforms to the published bindings, GIC interrupt properties
  contain 3-tuples that describe the interrupt as shared vs private, the
  interrupt number within the shared/private address space, and configuration
  info such as level vs edge triggered.
  
  The new gic_decode_fdt() function parses both types of data, based on the
  #interrupt-cells property.  Previously, each platform implemented a decode
  routine and put a pointer to it into fdt_pic_table.  Now they can just
  list this function in their table instead if they use arm/gic.c.

Modified:
  head/sys/arm/arm/gic.c
  head/sys/arm/include/intr.h

Modified: head/sys/arm/arm/gic.c
==============================================================================
--- head/sys/arm/arm/gic.c	Sun Sep 14 20:13:07 2014	(r271600)
+++ head/sys/arm/arm/gic.c	Sun Sep 14 21:21:03 2014	(r271601)
@@ -185,6 +185,51 @@ gic_init_secondary(void)
 	gic_d_write_4(GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F)));
 }
 
+int
+gic_decode_fdt(uint32_t iparent, uint32_t *intr, int *interrupt,
+    int *trig, int *pol)
+{
+	static u_int num_intr_cells;
+
+	if (num_intr_cells == 0) {
+		if (OF_searchencprop(OF_node_from_xref(iparent), 
+		    "#interrupt-cells", &num_intr_cells, 
+		    sizeof(num_intr_cells)) == -1) {
+			num_intr_cells = 1;
+		}
+	}
+
+	if (num_intr_cells == 1) {
+		*interrupt = fdt32_to_cpu(intr[0]);
+		*trig = INTR_TRIGGER_CONFORM;
+		*pol = INTR_POLARITY_CONFORM;
+	} else {
+		if (intr[0] == 0)
+			*interrupt = fdt32_to_cpu(intr[1]) + 32;
+		else
+			*interrupt = fdt32_to_cpu(intr[1]);
+		/*
+		 * In intr[2], bits[3:0] are trigger type and level flags.
+		 *   1 = low-to-high edge triggered
+		 *   2 = high-to-low edge triggered
+		 *   4 = active high level-sensitive
+		 *   8 = active low level-sensitive
+		 * The hardware only supports active-high-level or rising-edge.
+		 */
+		if (intr[2] & 0x0a) {
+			printf("unsupported trigger/polarity configuration "
+			    "0x%2x\n", intr[2] & 0x0f);
+			return (ENOTSUP);
+		}
+		*pol  = INTR_POLARITY_CONFORM;
+		if (intr[2] & 0x01)
+			*trig = INTR_TRIGGER_EDGE;
+		else
+			*trig = INTR_TRIGGER_LEVEL;
+	}
+	return (0);
+}
+
 static int
 arm_gic_attach(device_t dev)
 {

Modified: head/sys/arm/include/intr.h
==============================================================================
--- head/sys/arm/include/intr.h	Sun Sep 14 20:13:07 2014	(r271600)
+++ head/sys/arm/include/intr.h	Sun Sep 14 21:21:03 2014	(r271601)
@@ -82,5 +82,7 @@ extern int (*arm_config_irq)(int irq, en
 void arm_irq_memory_barrier(uintptr_t);
 
 void gic_init_secondary(void);
+int  gic_decode_fdt(uint32_t iparentnode, uint32_t *intrcells, int *interrupt,
+    int *trig, int *pol);
 
 #endif	/* _MACHINE_INTR_H */


More information about the svn-src-all mailing list