drivers/hsi/controllers/omap_ssi_port.c
Source file repositories/reference/linux-study-clean/drivers/hsi/controllers/omap_ssi_port.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/hsi/controllers/omap_ssi_port.c- Extension
.c- Size
- 41418 bytes
- Lines
- 1381
- Domain
- Driver Families
- Bucket
- drivers/hsi
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/mod_devicetable.hlinux/platform_device.hlinux/dma-mapping.hlinux/pm_runtime.hlinux/delay.hlinux/gpio/consumer.hlinux/pinctrl/consumer.hlinux/debugfs.homap_ssi_regs.homap_ssi.h
Detected Declarations
function Copyrightfunction hsi_dummy_clfunction ssi_wakeinfunction ssi_debug_remove_portfunction ssi_port_regs_showfunction ssi_div_getfunction ssi_div_setfunction ssi_debug_add_portfunction ssi_process_errqueuefunction list_for_each_safefunction ssi_claim_lchfunction ssi_start_dmafunction ssi_start_piofunction ssi_start_transferfunction ssi_async_breakfunction ssi_asyncfunction ssi_calculate_divfunction ssi_flush_queuefunction list_for_each_safefunction ssi_setupfunction ssi_flushfunction start_tx_workfunction ssi_start_txfunction ssi_stop_txfunction ssi_transferfunction ssi_cleanup_queuesfunction ssi_cleanup_gddfunction ssi_set_port_modefunction ssi_releasefunction ssi_errorfunction ssi_break_completefunction list_for_each_entry_safefunction ssi_pio_completefunction ssi_pio_threadfunction ssi_wake_threadfunction ssi_port_irqfunction ssi_wake_irqfunction ssi_queues_initfunction ssi_port_get_iomemfunction ssi_port_probefunction ssi_port_removefunction ssi_restore_divisorfunction omap_ssi_port_update_fclkfunction ssi_save_port_ctxfunction ssi_restore_port_ctxfunction ssi_restore_port_modefunction omap_ssi_port_runtime_suspendfunction omap_ssi_port_runtime_resume
Annotated Snippet
if (!omap_ssi->gdd_trn[lch].msg) {
omap_ssi->gdd_trn[lch].msg = msg;
omap_ssi->gdd_trn[lch].sg = msg->sgt.sgl;
return lch;
}
return -EBUSY;
}
static int ssi_start_dma(struct hsi_msg *msg, int lch)
{
struct hsi_port *port = hsi_get_port(msg->cl);
struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
void __iomem *gdd = omap_ssi->gdd;
int err;
u16 csdp;
u16 ccr;
u32 s_addr;
u32 d_addr;
u32 tmp;
/* Hold clocks during the transfer */
pm_runtime_get(omap_port->pdev);
if (!pm_runtime_active(omap_port->pdev)) {
dev_warn(&port->device, "ssi_start_dma called without runtime PM!\n");
pm_runtime_put_autosuspend(omap_port->pdev);
return -EREMOTEIO;
}
if (msg->ttype == HSI_MSG_READ) {
err = dma_map_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents,
DMA_FROM_DEVICE);
if (!err) {
dev_dbg(&ssi->device, "DMA map SG failed !\n");
pm_runtime_put_autosuspend(omap_port->pdev);
return -EIO;
}
csdp = SSI_DST_BURST_4x32_BIT | SSI_DST_MEMORY_PORT |
SSI_SRC_SINGLE_ACCESS0 | SSI_SRC_PERIPHERAL_PORT |
SSI_DATA_TYPE_S32;
ccr = msg->channel + 0x10 + (port->num * 8); /* Sync */
ccr |= SSI_DST_AMODE_POSTINC | SSI_SRC_AMODE_CONST |
SSI_CCR_ENABLE;
s_addr = omap_port->ssr_dma +
SSI_SSR_BUFFER_CH_REG(msg->channel);
d_addr = sg_dma_address(msg->sgt.sgl);
} else {
err = dma_map_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents,
DMA_TO_DEVICE);
if (!err) {
dev_dbg(&ssi->device, "DMA map SG failed !\n");
pm_runtime_put_autosuspend(omap_port->pdev);
return -EIO;
}
csdp = SSI_SRC_BURST_4x32_BIT | SSI_SRC_MEMORY_PORT |
SSI_DST_SINGLE_ACCESS0 | SSI_DST_PERIPHERAL_PORT |
SSI_DATA_TYPE_S32;
ccr = (msg->channel + 1 + (port->num * 8)) & 0xf; /* Sync */
ccr |= SSI_SRC_AMODE_POSTINC | SSI_DST_AMODE_CONST |
SSI_CCR_ENABLE;
s_addr = sg_dma_address(msg->sgt.sgl);
d_addr = omap_port->sst_dma +
SSI_SST_BUFFER_CH_REG(msg->channel);
}
dev_dbg(&ssi->device, "lch %d cdsp %08x ccr %04x s_addr %08x d_addr %08x\n",
lch, csdp, ccr, s_addr, d_addr);
writew_relaxed(csdp, gdd + SSI_GDD_CSDP_REG(lch));
writew_relaxed(SSI_BLOCK_IE | SSI_TOUT_IE, gdd + SSI_GDD_CICR_REG(lch));
writel_relaxed(d_addr, gdd + SSI_GDD_CDSA_REG(lch));
writel_relaxed(s_addr, gdd + SSI_GDD_CSSA_REG(lch));
writew_relaxed(SSI_BYTES_TO_FRAMES(msg->sgt.sgl->length),
gdd + SSI_GDD_CEN_REG(lch));
spin_lock_bh(&omap_ssi->lock);
tmp = readl(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
tmp |= SSI_GDD_LCH(lch);
writel_relaxed(tmp, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
spin_unlock_bh(&omap_ssi->lock);
writew(ccr, gdd + SSI_GDD_CCR_REG(lch));
msg->status = HSI_STATUS_PROCEEDING;
return 0;
}
static int ssi_start_pio(struct hsi_msg *msg)
{
Annotation
- Immediate include surface: `linux/mod_devicetable.h`, `linux/platform_device.h`, `linux/dma-mapping.h`, `linux/pm_runtime.h`, `linux/delay.h`, `linux/gpio/consumer.h`, `linux/pinctrl/consumer.h`, `linux/debugfs.h`.
- Detected declarations: `function Copyright`, `function hsi_dummy_cl`, `function ssi_wakein`, `function ssi_debug_remove_port`, `function ssi_port_regs_show`, `function ssi_div_get`, `function ssi_div_set`, `function ssi_debug_add_port`, `function ssi_process_errqueue`, `function list_for_each_safe`.
- Atlas domain: Driver Families / drivers/hsi.
- Implementation status: source 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.