The existing Xilinx INTC driver does not have mechanism to remove the driver when it is being used as a module. For example, if the Xilinx INTC IP is part of a removable fpga partition and a user intends to replace the removable partition with a new one, the existing implementation will not support the same. The enhancement is done by adding a new remove API and making other necessary changes. Signed-off-by: Anirudha Sarangi <anirudha.sarangi@xxxxxxxxxx> --- drivers/irqchip/irq-xilinx-intc.c | 49 +++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-xilinx-intc.c b/drivers/irqchip/irq-xilinx-intc.c index 642733a6cbdf..2c5b76efabf6 100644 --- a/drivers/irqchip/irq-xilinx-intc.c +++ b/drivers/irqchip/irq-xilinx-intc.c @@ -39,6 +39,7 @@ struct xintc_irq_chip { struct irq_domain *root_domain; u32 intr_mask; u32 nr_irq; + int irq; }; static struct xintc_irq_chip *primary_intc; @@ -234,6 +235,8 @@ static int xilinx_intc_of_init(struct device_node *intc, if (parent) { irq = irq_of_parse_and_map(intc, 0); + irqc->irq = irq; + intc->data = irqc; if (irq) { irq_set_chained_handler_and_data(irq, xil_intc_irq_handler, @@ -257,5 +260,47 @@ static int xilinx_intc_of_init(struct device_node *intc, } -IRQCHIP_DECLARE(xilinx_intc_xps, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init); -IRQCHIP_DECLARE(xilinx_intc_opb, "xlnx,opb-intc-1.00.c", xilinx_intc_of_init); +static int xilinx_intc_of_remove(struct device_node *intc, + struct device_node *parent) +{ + int irq; + struct xintc_irq_chip *irqc; + + if (!parent) + return 0; + + irqc = intc->data; + irq = irqc->irq; + irq_set_chained_handler_and_data(irq, NULL, NULL); + if (irqc->domain) { + irq_dispose_mapping(irq); + irq_domain_remove(irqc->domain); + } + /* + * Disable all external interrupts until they are + * explicity requested. + */ + xintc_write(irqc, IER, 0); + /* Acknowledge any pending interrupts just in case. */ + xintc_write(irqc, IAR, 0xffffffff); + /* Turn off the Master Enable. */ + xintc_write(irqc, MER, 0x0); + + iounmap(irqc->base); + kfree(irqc); + + return 0; +} + +static struct irqc_init_remove_funps intc_funps = { + .irqchip_initp = xilinx_intc_of_init, + .irqchip_removep = xilinx_intc_of_remove, +}; + +IRQCHIP_PLATFORM_DRIVER_BEGIN(xilinx_intc_xps) +IRQCHIP_MATCH("xlnx,xps-intc-1.00.a", &intc_funps) +IRQCHIP_PLATFORM_DRIVER_END(xilinx_intc_xps) + +IRQCHIP_PLATFORM_DRIVER_BEGIN(xilinx_intc_opb) +IRQCHIP_MATCH("xlnx,opb-intc-1.00.c", &intc_funps) +IRQCHIP_PLATFORM_DRIVER_END(xilinx_intc_opb) -- 2.17.1