#define VIC_VECT_ADDR0 0x100 /* 0 to 15 (0..31 PL192) */ #define VIC_VECT_CNTL0 0x200 /* 0 to 15 (0..31 PL192) */ #define VIC_ITCR 0x300 /* VIC test control register */
#define VIC_VECT_CNTL_ENABLE (1 << 5)
#define VIC_PL192_VECT_ADDR 0xF00
/** * struct vic_device - VIC PM device * @base: The register base for the VIC. * @irq: The IRQ number for the base of the VIC. * @valid_sources: A bitmask of valid interrupts * @resume_sources: A bitmask of interrupts for resume. * @resume_irqs: The IRQs enabled for resume. * @int_select: Save for VIC_INT_SELECT. * @int_enable: Save for VIC_INT_ENABLE. * @soft_int: Save for VIC_INT_SOFT. * @protect: Save for VIC_PROTECT. * @domain: The IRQ domain for the VIC.
*/ struct vic_device { void __iomem *base; int irq;
u32 valid_sources;
u32 resume_sources;
u32 resume_irqs;
u32 int_select;
u32 int_enable;
u32 soft_int;
u32 protect; struct irq_domain *domain;
};
/* we cannot allocate memory when VICs are initially registered */ staticstruct vic_device vic_devices[CONFIG_ARM_VIC_NR];
staticint vic_id;
staticvoid vic_handle_irq(struct pt_regs *regs);
/** * vic_init2 - common initialisation code * @base: Base of the VIC. * * Common initialisation code for registration * and resume.
*/ staticvoid vic_init2(void __iomem *base)
{ int i;
for (i = 0; i < 16; i++) { void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
writel(VIC_VECT_CNTL_ENABLE | i, reg);
}
writel(vic->int_select, base + VIC_INT_SELECT);
writel(vic->protect, base + VIC_PROTECT);
/* set the enabled ints and then clear the non-enabled */
writel(vic->int_enable, base + VIC_INT_ENABLE);
writel(~vic->int_enable, base + VIC_INT_ENABLE_CLEAR);
/* and the same for the soft-int register */
writel(vic->soft_int, base + VIC_INT_SOFT);
writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR);
}
staticvoid vic_resume(void)
{ int id;
for (id = vic_id - 1; id >= 0; id--)
resume_one_vic(vic_devices + id);
}
/** * vic_pm_init - initcall to register VIC pm * * This is called via late_initcall() to register * the resources for the VICs due to the early * nature of the VIC's registration.
*/ staticint __init vic_pm_init(void)
{ if (vic_id > 0)
register_syscore_ops(&vic_syscore_ops);
/* Skip invalid IRQs, only register handlers for the real ones */ if (!(v->valid_sources & (1 << hwirq))) return -EPERM;
irq_set_chip_and_handler(irq, &vic_chip, handle_level_irq);
irq_set_chip_data(irq, v->base);
irq_set_probe(irq); return 0;
}
/* * Handle each interrupt in a single VIC. Returns non-zero if we've * handled at least one interrupt. This reads the status register * before handling each interrupt, which is necessary given that * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
*/ staticint handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
{
u32 stat, irq; int handled = 0;
/* * Keep iterating over all registered VIC's until there are no pending * interrupts.
*/ staticvoid __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
{ int i, handled;
do { for (i = 0, handled = 0; i < vic_id; ++i)
handled |= handle_one_vic(&vic_devices[i], regs);
} while (handled);
}
/** * vic_register() - Register a VIC. * @base: The base address of the VIC. * @parent_irq: The parent IRQ if cascaded, else 0. * @irq: The base IRQ for the VIC. * @valid_sources: bitmask of valid interrupts * @resume_sources: bitmask of interrupts allowed for resume sources. * @node: The device tree node associated with the VIC. * * Register the VIC with the system device tree so that it can be notified * of suspend and resume requests and ensure that the correct actions are * taken to re-instate the settings on resume. * * This also configures the IRQ domain for the VIC.
*/ staticvoid __init vic_register(void __iomem *base, unsignedint parent_irq, unsignedint irq,
u32 valid_sources, u32 resume_sources, struct device_node *node)
{ struct vic_device *v; int i;
if (vic_id >= ARRAY_SIZE(vic_devices)) {
printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__); return;
}
if (parent_irq) {
irq_set_chained_handler_and_data(parent_irq,
vic_handle_irq_cascaded, v);
}
v->domain = irq_domain_create_simple(of_fwnode_handle(node),
fls(valid_sources), irq,
&vic_irqdomain_ops, v); /* create an IRQ mapping for each valid IRQ */ for (i = 0; i < fls(valid_sources); i++) if (valid_sources & (1 << i))
irq_create_mapping(v->domain, i); /* If no base IRQ was passed, figure out our allocated base */ if (irq)
v->irq = irq; else
v->irq = irq_find_mapping(v->domain, 0);
}
staticvoid vic_ack_irq(struct irq_data *d)
{ void __iomem *base = irq_data_get_irq_chip_data(d); unsignedint irq = d->hwirq;
writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); /* moreover, clear the soft-triggered, in case it was the reason */
writel(1 << irq, base + VIC_INT_SOFT_CLEAR);
}
writel(0, base + VIC_PL190_VECT_ADDR); for (i = 0; i < 19; i++) { unsignedint value;
value = readl(base + VIC_PL190_VECT_ADDR);
writel(value, base + VIC_PL190_VECT_ADDR);
}
}
/* * The PL190 cell from ARM has been modified by ST to handle 64 interrupts. * The original cell has 32 interrupts, while the modified one has 64, * replicating two blocks 0x00..0x1f in 0x20..0x3f. In that case * the probe function is called twice, with base set to offset 000 * and 020 within the page. We call this "second block".
*/ staticvoid __init vic_init_st(void __iomem *base, unsignedint irq_start,
u32 vic_sources, struct device_node *node)
{ unsignedint i; int vic_2nd_block = ((unsignedlong)base & ~PAGE_MASK) != 0;
/* Disable all interrupts initially. */
vic_disable(base);
/* * Make sure we clear all existing interrupts. The vector registers * in this cell are after the second block of general registers, * so we can address them using standard offsets, but only from * the second base address, which is 0x20 in the page
*/ if (vic_2nd_block) {
vic_clear_interrupts(base);
/* ST has 16 vectors as well, but we don't enable them by now */ for (i = 0; i < 16; i++) { void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
writel(0, reg);
}
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.