On 8/8/19 12:09 PM, David Lechner wrote:
Then we can provide a vendor resource hook in the remoteproc driver to handle these resources: static int ti_pru_rproc_handle_rsc(struct rproc *rproc, u32 rsc_type, void *rsc, int offset, int avail) { struct ti_pru_data *pru = rproc->priv; struct irq_fwspec fwspec; unsigned int virq; switch (rsc_type) { case TI_PRU_VENDOR_RESOURCE_IRQ: { struct ti_pru_vendor_resource_irq *rsc_irq = rsc; fwspec.fwnode = pru->intc_fwnode; fwspec.param[0] = le32_to_cpu(rsc_irq->event); fwspec.param[1] = le32_to_cpu(rsc_irq->channel); fwspec.param[2] = le32_to_cpu(rsc_irq->host); fwspec.param[3] = le32_to_cpu(rsc_irq->domain); fwspec.param_count = 4; } break; case TI_PRU_VENDOR_RESOURCE_IRQ2: { struct ti_pru_vendor_resource_irq2 *rsc_irq2 = rsc; fwspec.fwnode = pru->intc_fwnode; fwspec.param[0] = le32_to_cpu(rsc_irq2->event); fwspec.param[1] = le32_to_cpu(rsc_irq2->evt_sel); fwspec.param[2] = le32_to_cpu(rsc_irq2->channel); fwspec.param[3] = le32_to_cpu(rsc_irq2->host); fwspec.param[4] = le32_to_cpu(rsc_irq2->domain); fwspec.param_count = 5; break; } default: return RSC_IGNORED; } virq = irq_create_fwspec_mapping(&fwspec); if (!virq) return -EINVAL; /* TODO: save virq (and other metadata) for later use */ return RSC_HANDLED; } static const struct rproc_ops ti_pru_rproc_ops = { .start = ti_pru_rproc_start, .stop = ti_pru_rproc_stop, .kick = ti_pru_rproc_kick, .da_to_va = ti_pru_rproc_da_to_va, .handle_rsc = ti_pru_rproc_handle_rsc, };
After re-reading some of the previous discussions, it sounds like we wouldn't want to always map every IRQ in the firmware resource table. In that case, we could implement the rproc_ops parse_fw callback instead. All firmware nodes could be collected (from both the firmware resource table and device tree) and the remoteproc driver could decide which ones need to be mapped and which ones don't. Then it could call irq_create_fwspec_mapping() only the nodes that need to be mapped based on the current application.