Date: Sun, 14 Sep 2014 21:21:04 +0000 (UTC) From: Ian Lepore <ian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r271601 - in head/sys/arm: arm include Message-ID: <201409142121.s8ELL4ff038610@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409142121.s8ELL4ff038610>