/** * struct irq_fwspec - generic IRQ specifier structure * * @fwnode: Pointer to a firmware-specific descriptor * @param_count: Number of device-specific parameters * @param: Device-specific parameters * * This structure, directly modeled after of_phandle_args, is used to * pass a device-specific description of an interrupt.
*/ struct irq_fwspec { struct fwnode_handle *fwnode; int param_count;
u32 param[IRQ_DOMAIN_IRQ_SPEC_PARAMS];
};
/* Conversion function from of_phandle_args fields to fwspec */ void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, unsignedint count, struct irq_fwspec *fwspec);
/** * struct irq_domain_ops - Methods for irq_domain objects * @match: Match an interrupt controller device node to a domain, returns * 1 on a match * @select: Match an interrupt controller fw specification. It is more generic * than @match as it receives a complete struct irq_fwspec. Therefore, * @select is preferred if provided. Returns 1 on a match. * @map: Create or update a mapping between a virtual irq number and a hw * irq number. This is called only once for a given mapping. * @unmap: Dispose of such a mapping * @xlate: Given a device tree node and interrupt specifier, decode * the hardware irq number and linux irq type value. * @alloc: Allocate @nr_irqs interrupts starting from @virq. * @free: Free @nr_irqs interrupts starting from @virq. * @activate: Activate one interrupt in HW (@irqd). If @reserve is set, only * reserve the vector. If unset, assign the vector (called from * request_irq()). * @deactivate: Disarm one interrupt (@irqd). * @translate: Given @fwspec, decode the hardware irq number (@out_hwirq) and * linux irq type value (@out_type). This is a generalised @xlate * (over struct irq_fwspec) and is preferred if provided. * @debug_show: For domains to show specific data for an interrupt in debugfs. * * Functions below are provided by the driver and called whenever a new mapping * is created or an old mapping is disposed. The driver can then proceed to * whatever internal data structures management is required. It also needs * to setup the irq_desc when returning from map().
*/ struct irq_domain_ops { int (*match)(struct irq_domain *d, struct device_node *node, enum irq_domain_bus_token bus_token); int (*select)(struct irq_domain *d, struct irq_fwspec *fwspec, enum irq_domain_bus_token bus_token); int (*map)(struct irq_domain *d, unsignedint virq, irq_hw_number_t hw); void (*unmap)(struct irq_domain *d, unsignedint virq); int (*xlate)(struct irq_domain *d, struct device_node *node, const u32 *intspec, unsignedint intsize, unsignedlong *out_hwirq, unsignedint *out_type); #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY /* extended V2 interfaces to support hierarchy irq_domains */ int (*alloc)(struct irq_domain *d, unsignedint virq, unsignedint nr_irqs, void *arg); void (*free)(struct irq_domain *d, unsignedint virq, unsignedint nr_irqs); int (*activate)(struct irq_domain *d, struct irq_data *irqd, bool reserve); void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data); int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec, unsignedlong *out_hwirq, unsignedint *out_type); #endif #ifdef CONFIG_GENERIC_IRQ_DEBUGFS void (*debug_show)(struct seq_file *m, struct irq_domain *d, struct irq_data *irqd, int ind); #endif
};
/** * struct irq_domain - Hardware interrupt number translation object * @link: Element in global irq_domain list. * @name: Name of interrupt domain * @ops: Pointer to irq_domain methods * @host_data: Private data pointer for use by owner. Not touched by irq_domain * core code. * @flags: Per irq_domain flags * @mapcount: The number of mapped interrupts * @mutex: Domain lock, hierarchical domains use root domain's lock * @root: Pointer to root domain, or containing structure if non-hierarchical * * Optional elements: * @fwnode: Pointer to firmware node associated with the irq_domain. Pretty easy * to swap it for the of_node via the irq_domain_get_of_node accessor * @bus_token: @fwnode's device_node might be used for several irq domains. But * in connection with @bus_token, the pair shall be unique in a * system. * @gc: Pointer to a list of generic chips. There is a helper function for * setting up one or more generic chips for interrupt controllers * drivers using the generic chip library which uses this pointer. * @dev: Pointer to the device which instantiated the irqdomain * With per device irq domains this is not necessarily the same * as @pm_dev. * @pm_dev: Pointer to a device that can be utilized for power management * purposes related to the irq domain. * @parent: Pointer to parent irq_domain to support hierarchy irq_domains * @msi_parent_ops: Pointer to MSI parent domain methods for per device domain init * @exit: Function called when the domain is destroyed * * Revmap data, used internally by the irq domain code: * @hwirq_max: Top limit for the HW irq number. Especially to avoid * conflicts/failures with reserved HW irqs. Can be ~0. * @revmap_size: Size of the linear map table @revmap * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map * @revmap: Linear table of irq_data pointers
*/ struct irq_domain { struct list_head link; constchar *name; conststruct irq_domain_ops *ops; void *host_data; unsignedint flags; unsignedint mapcount; struct mutex mutex; struct irq_domain *root;
/* * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved * for implementation specific purposes and ignored by the * core code.
*/
IRQ_DOMAIN_FLAG_NONCORE = (1 << 16),
};
DEFINE_FREE(irq_domain_free_fwnode, struct fwnode_handle *, if (_T) irq_domain_free_fwnode(_T))
struct irq_domain_chip_generic_info;
/** * struct irq_domain_info - Domain information structure * @fwnode: firmware node for the interrupt controller * @domain_flags: Additional flags to add to the domain flags * @size: Size of linear map; 0 for radix mapping only * @hwirq_max: Maximum number of interrupts supported by controller * @direct_max: Maximum value of direct maps; * Use ~0 for no limit; 0 for no direct mapping * @hwirq_base: The first hardware interrupt number (legacy domains only) * @virq_base: The first Linux interrupt number for legacy domains to * immediately associate the interrupts after domain creation * @bus_token: Domain bus token * @name_suffix: Optional name suffix to avoid collisions when multiple * domains are added using same fwnode * @ops: Domain operation callbacks * @host_data: Controller private data pointer * @dev: Device which creates the domain * @dgc_info: Geneneric chip information structure pointer used to * create generic chips for the domain if not NULL. * @init: Function called when the domain is created. * Allow to do some additional domain initialisation. * @exit: Function called when the domain is destroyed. * Allow to do some additional cleanup operation.
*/ struct irq_domain_info { struct fwnode_handle *fwnode; unsignedint domain_flags; unsignedint size;
irq_hw_number_t hwirq_max; int direct_max; unsignedint hwirq_base; unsignedint virq_base; enum irq_domain_bus_token bus_token; constchar *name_suffix; conststruct irq_domain_ops *ops; void *host_data; struct device *dev; #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY /** * @parent: Pointer to the parent irq domain used in a hierarchy domain
*/ struct irq_domain *parent; #endif struct irq_domain_chip_generic_info *dgc_info; int (*init)(struct irq_domain *d); void (*exit)(struct irq_domain *d);
};
/** * irq_create_mapping - Map a hardware interrupt into linux irq space * @domain: domain owning this hardware interrupt or NULL for default domain * @hwirq: hardware irq number in that domain space * * Only one mapping per hardware interrupt is permitted. * * If the sense/trigger is to be specified, set_irq_type() should be called * on the number returned from that call. * * Returns: Linux irq number or 0 on error
*/ staticinlineunsignedint irq_create_mapping(struct irq_domain *domain, irq_hw_number_t hwirq)
{ return irq_create_mapping_affinity(domain, hwirq, NULL);
}
/** * irq_resolve_mapping - Find a linux irq from a hw irq number. * @domain: domain owning this hardware interrupt * @hwirq: hardware irq number in that domain space * * Returns: Interrupt descriptor
*/ staticinlinestruct irq_desc *irq_resolve_mapping(struct irq_domain *domain,
irq_hw_number_t hwirq)
{ return __irq_resolve_mapping(domain, hwirq, NULL);
}
/** * irq_find_mapping() - Find a linux irq from a hw irq number. * @domain: domain owning this hardware interrupt * @hwirq: hardware irq number in that domain space * * Returns: Linux irq number or 0 if not found
*/ staticinlineunsignedint irq_find_mapping(struct irq_domain *domain,
irq_hw_number_t hwirq)
{ unsignedint irq;
if (__irq_resolve_mapping(domain, hwirq, &irq)) return irq;
/* IPI functions */ int irq_reserve_ipi(struct irq_domain *domain, conststruct cpumask *dest); int irq_destroy_ipi(unsignedint irq, conststruct cpumask *dest);
/* V2 interfaces to support hierarchy IRQ domains. */ struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain, unsignedint virq); void irq_domain_set_info(struct irq_domain *domain, unsignedint virq, irq_hw_number_t hwirq, conststruct irq_chip *chip, void *chip_data, irq_flow_handler_t handler, void *handler_data, constchar *handler_name); void irq_domain_reset_irq_data(struct irq_data *irq_data); #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY /** * irq_domain_create_hierarchy - Add a irqdomain into the hierarchy * @parent: Parent irq domain to associate with the new domain * @flags: Irq domain flags associated to the domain * @size: Size of the domain. See below * @fwnode: Optional fwnode of the interrupt controller * @ops: Pointer to the interrupt domain callbacks * @host_data: Controller private data pointer * * If @size is 0 a tree domain is created, otherwise a linear domain. * * If successful the parent is associated to the new domain and the * domain flags are set. * * Returns: A pointer to IRQ domain, or %NULL on failure.
*/ staticinlinestruct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent, unsignedint flags, unsignedint size, struct fwnode_handle *fwnode, conststruct irq_domain_ops *ops, void *host_data)
{ conststruct irq_domain_info info = {
.fwnode = fwnode,
.size = size,
.hwirq_max = size ? : ~0U,
.ops = ops,
.host_data = host_data,
.domain_flags = flags,
.parent = parent,
}; struct irq_domain *d = irq_domain_instantiate(&info);
return IS_ERR(d) ? NULL : d;
}
int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, unsignedint nr_irqs, int node, void *arg, bool realloc, conststruct irq_affinity_desc *affinity); void irq_domain_free_irqs(unsignedint virq, unsignedint nr_irqs); int irq_domain_activate_irq(struct irq_data *irq_data, bool early); void irq_domain_deactivate_irq(struct irq_data *irq_data);
/** * irq_domain_alloc_irqs - Allocate IRQs from domain * @domain: domain to allocate from * @nr_irqs: number of IRQs to allocate * @node: NUMA node id for memory allocation * @arg: domain specific argument * * See __irq_domain_alloc_irqs()' documentation.
*/ staticinlineint irq_domain_alloc_irqs(struct irq_domain *domain, unsignedint nr_irqs, int node, void *arg)
{ return __irq_domain_alloc_irqs(domain, -1, nr_irqs, node, arg, false, NULL);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.