irqdomain: Add a fwnode_handle allocator
[firefly-linux-kernel-4.4.55.git] / kernel / irq / irqdomain.c
index de6d7493190b25dcda8379c3efa8dc329d2219e1..41151d394da7ea5c05b0f619f503590eefe793e4 100644 (file)
@@ -27,6 +27,57 @@ static int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
                                  irq_hw_number_t hwirq, int node);
 static void irq_domain_check_hierarchy(struct irq_domain *domain);
 
+struct irqchip_fwid {
+       struct fwnode_handle fwnode;
+       char *name;
+       void *data;
+};
+
+/**
+ * irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
+ *                           identifying an irq domain
+ * @data: optional user-provided data
+ *
+ * Allocate a struct device_node, and return a poiner to the embedded
+ * fwnode_handle (or NULL on failure).
+ */
+struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
+{
+       struct irqchip_fwid *fwid;
+       char *name;
+
+       fwid = kzalloc(sizeof(*fwid), GFP_KERNEL);
+       name = kasprintf(GFP_KERNEL, "irqchip@%p", data);
+
+       if (!fwid || !name) {
+               kfree(fwid);
+               kfree(name);
+               return NULL;
+       }
+
+       fwid->name = name;
+       fwid->data = data;
+       fwid->fwnode.type = FWNODE_IRQCHIP;
+       return &fwid->fwnode;
+}
+
+/**
+ * irq_domain_free_fwnode - Free a non-OF-backed fwnode_handle
+ *
+ * Free a fwnode_handle allocated with irq_domain_alloc_fwnode.
+ */
+void irq_domain_free_fwnode(struct fwnode_handle *fwnode)
+{
+       struct irqchip_fwid *fwid;
+
+       if (WARN_ON(fwnode->type != FWNODE_IRQCHIP))
+               return;
+
+       fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
+       kfree(fwid->name);
+       kfree(fwid);
+}
+
 /**
  * __irq_domain_add() - Allocate a new irq_domain data structure
  * @of_node: optional device-tree node of the interrupt controller