#define IXP4XX_ICPR 0x00 /* Interrupt Status */ #define IXP4XX_ICMR 0x04 /* Interrupt Enable */ #define IXP4XX_ICLR 0x08 /* Interrupt IRQ/FIQ Select */ #define IXP4XX_ICIP 0x0C /* IRQ Status */ #define IXP4XX_ICFP 0x10 /* FIQ Status */ #define IXP4XX_ICHR 0x14 /* Interrupt Priority */ #define IXP4XX_ICIH 0x18 /* IRQ Highest Pri Int */ #define IXP4XX_ICFH 0x1C /* FIQ Highest Pri Int */
/* IXP43x and IXP46x-only */ #define IXP4XX_ICPR2 0x20 /* Interrupt Status 2 */ #define IXP4XX_ICMR2 0x24 /* Interrupt Enable 2 */ #define IXP4XX_ICLR2 0x28 /* Interrupt IRQ/FIQ Select 2 */ #define IXP4XX_ICIP2 0x2C /* IRQ Status */ #define IXP4XX_ICFP2 0x30 /* FIQ Status */ #define IXP4XX_ICEEN 0x34 /* Error High Pri Enable */
/** * struct ixp4xx_irq - state container for the Faraday IRQ controller * @irqbase: IRQ controller memory base in virtual memory * @is_356: if this is an IXP43x, IXP45x or IX46x SoC (with 64 IRQs) * @irqchip: irqchip for this instance * @domain: IRQ domain for this instance
*/ struct ixp4xx_irq { void __iomem *irqbase; bool is_356; struct irq_chip irqchip; struct irq_domain *domain;
};
/* Local static state container */ staticstruct ixp4xx_irq ixirq;
staticint ixp4xx_set_irq_type(struct irq_data *d, unsignedint type)
{ /* All are level active high (asserted) here */ if (type != IRQ_TYPE_LEVEL_HIGH) return -EINVAL; return 0;
}
status = __raw_readl(ixi->irqbase + IXP4XX_ICIP);
for_each_set_bit(i, &status, 32)
generic_handle_domain_irq(ixi->domain, i);
/* * IXP465/IXP435 has an upper IRQ status register
*/ if (ixi->is_356) {
status = __raw_readl(ixi->irqbase + IXP4XX_ICIP2);
for_each_set_bit(i, &status, 32)
generic_handle_domain_irq(ixi->domain, i + 32);
}
}
staticint ixp4xx_irq_domain_translate(struct irq_domain *domain, struct irq_fwspec *fwspec, unsignedlong *hwirq, unsignedint *type)
{ /* We support standard DT translation */ if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
*hwirq = fwspec->param[0];
*type = fwspec->param[1]; return 0;
}
ret = ixp4xx_irq_domain_translate(d, fwspec, &hwirq, &type); if (ret) return ret;
for (i = 0; i < nr_irqs; i++) { /* * TODO: after converting IXP4xx to only device tree, set * handle_bad_irq as default handler and assume all consumers * call .set_type() as this is provided in the second cell in * the device tree phandle.
*/
irq_domain_set_info(d,
irq + i,
hwirq + i,
&ixi->irqchip,
ixi,
handle_level_irq,
NULL, NULL);
irq_set_probe(irq + i);
}
return 0;
}
/* * This needs to be a hierarchical irqdomain to work well with the * GPIO irqchip (which is lower in the hierarchy)
*/ staticconststruct irq_domain_ops ixp4xx_irqdomain_ops = {
.translate = ixp4xx_irq_domain_translate,
.alloc = ixp4xx_irq_domain_alloc,
.free = irq_domain_free_irqs_common,
};
/** * ixp4x_irq_setup() - Common setup code for the IXP4xx interrupt controller * @ixi: State container * @irqbase: Virtual memory base for the interrupt controller * @fwnode: Corresponding fwnode abstraction for this controller * @is_356: if this is an IXP43x, IXP45x or IXP46x SoC variant
*/ staticint __init ixp4xx_irq_setup(struct ixp4xx_irq *ixi, void __iomem *irqbase, struct fwnode_handle *fwnode, bool is_356)
{ int nr_irqs;
ixi->irqbase = irqbase;
ixi->is_356 = is_356;
/* Route all sources to IRQ instead of FIQ */
__raw_writel(0x0, ixi->irqbase + IXP4XX_ICLR);
/* Disable all interrupts */
__raw_writel(0x0, ixi->irqbase + IXP4XX_ICMR);
if (is_356) { /* Route upper 32 sources to IRQ instead of FIQ */
__raw_writel(0x0, ixi->irqbase + IXP4XX_ICLR2);
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.