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 */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to