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