staticint imx_irqsteer_get_hwirq_base(struct irqsteer_data *data, u32 irq)
{ int i;
for (i = 0; i < data->irq_count; i++) { if (data->irq[i] == irq) return i * 64;
}
return -EINVAL;
}
staticvoid imx_irqsteer_irq_handler(struct irq_desc *desc)
{ struct irqsteer_data *data = irq_desc_get_handler_data(desc); int hwirq; int irq, i;
chained_irq_enter(irq_desc_get_chip(desc), desc);
irq = irq_desc_get_irq(desc);
hwirq = imx_irqsteer_get_hwirq_base(data, irq); if (hwirq < 0) {
pr_warn("%s: unable to get hwirq base for irq %d\n",
__func__, irq); return;
}
for (i = 0; i < 2; i++, hwirq += 32) { int idx = imx_irqsteer_get_reg_index(data, hwirq); unsignedlong irqmap; int pos;
staticint imx_irqsteer_probe(struct platform_device *pdev)
{ struct device_node *np = pdev->dev.of_node; struct irqsteer_data *data;
u32 irqs_num; int i, ret;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM;
data->dev = &pdev->dev;
data->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(data->regs)) {
dev_err(&pdev->dev, "failed to initialize reg\n"); return PTR_ERR(data->regs);
}
data->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(data->ipg_clk)) return dev_err_probe(&pdev->dev, PTR_ERR(data->ipg_clk), "failed to get ipg clk\n");
raw_spin_lock_init(&data->lock);
ret = of_property_read_u32(np, "fsl,num-irqs", &irqs_num); if (ret) return ret;
ret = of_property_read_u32(np, "fsl,channel", &data->channel); if (ret) return ret;
/* * There is one output irq for each group of 64 inputs. * One register bit map can represent 32 input interrupts.
*/
data->irq_count = DIV_ROUND_UP(irqs_num, 64);
data->reg_num = irqs_num / 32;
if (IS_ENABLED(CONFIG_PM)) {
data->saved_reg = devm_kzalloc(&pdev->dev, sizeof(u32) * data->reg_num,
GFP_KERNEL); if (!data->saved_reg) return -ENOMEM;
}
ret = clk_prepare_enable(data->ipg_clk); if (ret) {
dev_err(&pdev->dev, "failed to enable ipg clk: %d\n", ret); return ret;
}
/* steer all IRQs into configured channel */
writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
data->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), data->reg_num * 32,
&imx_irqsteer_domain_ops, data); if (!data->domain) {
dev_err(&pdev->dev, "failed to create IRQ domain\n");
ret = -ENOMEM; goto out;
}
irq_domain_set_pm_device(data->domain, &pdev->dev);
if (!data->irq_count || data->irq_count > CHAN_MAX_OUTPUT_INT) {
ret = -EINVAL; goto out;
}
for (i = 0; i < data->irq_count; i++) {
data->irq[i] = irq_of_parse_and_map(np, i); if (!data->irq[i]) break;
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.