drivers/mfd/cs40l50-core.c
Source file repositories/reference/linux-study-clean/drivers/mfd/cs40l50-core.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/mfd/cs40l50-core.c- Extension
.c- Size
- 14994 bytes
- Lines
- 570
- Domain
- Driver Families
- Bucket
- drivers/mfd
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/firmware/cirrus/cs_dsp.hlinux/firmware/cirrus/wmfw.hlinux/mfd/core.hlinux/mfd/cs40l50.hlinux/pm_runtime.hlinux/regulator/consumer.h
Detected Declarations
struct cs40l50_irqfunction cs40l50_dsp_writefunction cs40l50_wseq_initfunction cs40l50_dsp_configfunction cs40l50_dsp_post_runfunction cs40l50_dsp_removefunction cs40l50_dsp_initfunction cs40l50_reset_dspfunction cs40l50_dsp_power_downfunction cs40l50_dsp_stopfunction cs40l50_dsp_bringupfunction cs40l50_request_firmwarefunction cs40l50_hw_errfunction cs40l50_dsp_queuefunction cs40l50_irq_initfunction cs40l50_get_modelfunction cs40l50_pm_runtime_setupfunction cs40l50_probefunction cs40l50_removefunction cs40l50_runtime_suspendfunction cs40l50_runtime_resumeexport cs40l50_regmapexport cs40l50_dsp_writeexport cs40l50_probeexport cs40l50_remove
Annotated Snippet
struct cs40l50_irq {
const char *name;
int virq;
};
static struct cs40l50_irq cs40l50_irqs[] = {
{ "DSP", },
{ "Global", },
{ "Boost UVLO", },
{ "Boost current limit", },
{ "Boost short", },
{ "Boost undervolt", },
{ "Overtemp", },
{ "Amp short", },
};
static const struct reg_sequence cs40l50_err_rls[] = {
{ CS40L50_ERR_RLS, CS40L50_GLOBAL_ERR_RLS_SET },
{ CS40L50_ERR_RLS, CS40L50_GLOBAL_ERR_RLS_CLEAR },
};
static irqreturn_t cs40l50_hw_err(int irq, void *data)
{
struct cs40l50 *cs40l50 = data;
int ret = 0, i;
mutex_lock(&cs40l50->lock);
/* Log hardware interrupt and execute error release sequence */
for (i = 1; i < ARRAY_SIZE(cs40l50_irqs); i++) {
if (cs40l50_irqs[i].virq == irq) {
dev_err(cs40l50->dev, "%s error\n", cs40l50_irqs[i].name);
ret = regmap_multi_reg_write(cs40l50->regmap, cs40l50_err_rls,
ARRAY_SIZE(cs40l50_err_rls));
break;
}
}
mutex_unlock(&cs40l50->lock);
return IRQ_RETVAL(!ret);
}
static irqreturn_t cs40l50_dsp_queue(int irq, void *data)
{
struct cs40l50 *cs40l50 = data;
u32 rd_ptr, val, wt_ptr;
int ret = 0;
mutex_lock(&cs40l50->lock);
/* Read from DSP queue, log, and update read pointer */
while (!ret) {
ret = regmap_read(cs40l50->regmap, CS40L50_DSP_QUEUE_WT, &wt_ptr);
if (ret)
break;
ret = regmap_read(cs40l50->regmap, CS40L50_DSP_QUEUE_RD, &rd_ptr);
if (ret)
break;
/* Check if queue is empty */
if (wt_ptr == rd_ptr)
break;
ret = regmap_read(cs40l50->regmap, rd_ptr, &val);
if (ret)
break;
dev_dbg(cs40l50->dev, "DSP payload: %#X", val);
rd_ptr += sizeof(u32);
if (rd_ptr > CS40L50_DSP_QUEUE_END)
rd_ptr = CS40L50_DSP_QUEUE_BASE;
ret = regmap_write(cs40l50->regmap, CS40L50_DSP_QUEUE_RD, rd_ptr);
}
mutex_unlock(&cs40l50->lock);
return IRQ_RETVAL(!ret);
}
static int cs40l50_irq_init(struct cs40l50 *cs40l50)
{
int ret, i, virq;
ret = devm_regmap_add_irq_chip(cs40l50->dev, cs40l50->regmap, cs40l50->irq,
IRQF_ONESHOT | IRQF_SHARED, 0,
&cs40l50_irq_chip, &cs40l50->irq_data);
Annotation
- Immediate include surface: `linux/firmware/cirrus/cs_dsp.h`, `linux/firmware/cirrus/wmfw.h`, `linux/mfd/core.h`, `linux/mfd/cs40l50.h`, `linux/pm_runtime.h`, `linux/regulator/consumer.h`.
- Detected declarations: `struct cs40l50_irq`, `function cs40l50_dsp_write`, `function cs40l50_wseq_init`, `function cs40l50_dsp_config`, `function cs40l50_dsp_post_run`, `function cs40l50_dsp_remove`, `function cs40l50_dsp_init`, `function cs40l50_reset_dsp`, `function cs40l50_dsp_power_down`, `function cs40l50_dsp_stop`.
- Atlas domain: Driver Families / drivers/mfd.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.