diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 613dbd415b91..24eafe0aa1c3 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "bus.h" #include "cadence_master.h" @@ -790,7 +791,7 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id) CDNS_MCP_INT_SLAVE_MASK, 0); int_status &= ~CDNS_MCP_INT_SLAVE_MASK; - ret = IRQ_WAKE_THREAD; + schedule_work(&cdns->work); } cdns_writel(cdns, CDNS_MCP_INTSTAT, int_status); @@ -799,13 +800,15 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id) EXPORT_SYMBOL(sdw_cdns_irq); /** - * sdw_cdns_thread() - Cadence irq thread handler - * @irq: irq number - * @dev_id: irq context + * To update slave status in a work since we will need to handle + * other interrupts eg. CDNS_MCP_INT_RX_WL during the update slave + * process. + * @work: cdns worker thread */ -irqreturn_t sdw_cdns_thread(int irq, void *dev_id) +static void cdns_update_slave_status_work(struct work_struct *work) { - struct sdw_cdns *cdns = dev_id; + struct sdw_cdns *cdns = + container_of(work, struct sdw_cdns, work); u32 slave0, slave1; dev_dbg_ratelimited(cdns->dev, "Slave status change\n"); @@ -822,9 +825,7 @@ irqreturn_t sdw_cdns_thread(int irq, void *dev_id) cdns_updatel(cdns, CDNS_MCP_INTMASK, CDNS_MCP_INT_SLAVE_MASK, CDNS_MCP_INT_SLAVE_MASK); - return IRQ_HANDLED; } -EXPORT_SYMBOL(sdw_cdns_thread); /* * init routines @@ -1427,6 +1428,7 @@ int sdw_cdns_probe(struct sdw_cdns *cdns) init_completion(&cdns->tx_complete); cdns->bus.port_ops = &cdns_port_ops; + INIT_WORK(&cdns->work, cdns_update_slave_status_work); return 0; } EXPORT_SYMBOL(sdw_cdns_probe); diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h index b410656f8194..7638858397df 100644 --- a/drivers/soundwire/cadence_master.h +++ b/drivers/soundwire/cadence_master.h @@ -129,6 +129,10 @@ struct sdw_cdns { bool link_up; unsigned int msg_count; + + struct work_struct work; + + struct list_head list; }; #define bus_to_cdns(_bus) container_of(_bus, struct sdw_cdns, bus) diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index 0a4fc7f65743..06c553d94890 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -1258,21 +1258,7 @@ static int intel_master_probe(struct platform_device *pdev) "SoundWire master %d is disabled, will be ignored\n", bus->link_id); - /* Acquire IRQ */ - ret = request_threaded_irq(sdw->link_res->irq, - sdw_cdns_irq, sdw_cdns_thread, - IRQF_SHARED, KBUILD_MODNAME, cdns); - if (ret < 0) { - dev_err(dev, "unable to grab IRQ %d, disabling device\n", - sdw->link_res->irq); - goto err_init; - } - return 0; - -err_init: - sdw_bus_master_delete(bus); - return ret; } int intel_master_startup(struct platform_device *pdev) @@ -1344,7 +1330,6 @@ static int intel_master_remove(struct platform_device *pdev) if (!bus->prop.hw_disabled) { intel_debugfs_exit(sdw); sdw_cdns_enable_interrupt(cdns, false); - free_irq(sdw->link_res->irq, sdw); snd_soc_unregister_component(dev); } sdw_bus_master_delete(bus); diff --git a/drivers/soundwire/intel.h b/drivers/soundwire/intel.h index d6bdd4d63e08..bf127c88eb51 100644 --- a/drivers/soundwire/intel.h +++ b/drivers/soundwire/intel.h @@ -17,6 +17,8 @@ * @dev: device implementing hw_params and free callbacks * @shim_lock: mutex to handle access to shared SHIM registers * @shim_mask: global pointer to check SHIM register initialization + * @cdns: Cadence master descriptor + * @list: used to walk-through all masters exposed by the same controller */ struct sdw_intel_link_res { struct platform_device *pdev; @@ -29,6 +31,8 @@ struct sdw_intel_link_res { struct device *dev; struct mutex *shim_lock; /* protect shared registers */ u32 *shim_mask; + struct sdw_cdns *cdns; + struct list_head list; }; struct sdw_intel { diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c index ad3175272e88..a97d3577eb57 100644 --- a/drivers/soundwire/intel_init.c +++ b/drivers/soundwire/intel_init.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -166,6 +167,19 @@ void sdw_intel_enable_irq(void __iomem *mmio_base, bool enable) } EXPORT_SYMBOL_NS(sdw_intel_enable_irq, SOUNDWIRE_INTEL_INIT); +irqreturn_t sdw_intel_thread(int irq, void *dev_id) +{ + struct sdw_intel_ctx *ctx = dev_id; + struct sdw_intel_link_res *link; + + list_for_each_entry(link, &ctx->link_list, list) + sdw_cdns_irq(irq, link->cdns); + + sdw_intel_enable_irq(ctx->mmio_base, true); + return IRQ_HANDLED; +} +EXPORT_SYMBOL_NS(sdw_intel_thread, SOUNDWIRE_INTEL_INIT); + static struct sdw_intel_ctx *sdw_intel_probe_controller(struct sdw_intel_res *res) { @@ -209,6 +223,8 @@ static struct sdw_intel_ctx link = ctx->links; link_mask = ctx->link_mask; + INIT_LIST_HEAD(&ctx->link_list); + /* Create SDW Master devices */ for (i = 0; i < count; i++, link++) { if (!(link_mask & BIT(i))) { @@ -246,6 +262,9 @@ static struct sdw_intel_ctx goto err; } link->pdev = pdev; + link->cdns = platform_get_drvdata(pdev); + + list_add_tail(&link->list, &ctx->link_list); } return ctx;