drivers/mmc/host/cavium.c
Source file repositories/reference/linux-study-clean/drivers/mmc/host/cavium.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/mmc/host/cavium.c- Extension
.c- Size
- 28366 bytes
- Lines
- 1077
- Domain
- Driver Families
- Bucket
- drivers/mmc
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bitfield.hlinux/delay.hlinux/dma-direction.hlinux/dma-mapping.hlinux/gpio/consumer.hlinux/interrupt.hlinux/mmc/mmc.hlinux/mmc/slot-gpio.hlinux/module.hlinux/regulator/consumer.hlinux/scatterlist.hlinux/time.hcavium.h
Detected Declarations
function cvm_mmc_get_cr_modsfunction check_switch_errorsfunction clear_bus_idfunction set_bus_idfunction get_bus_idfunction do_switchfunction switch_val_changedfunction set_wdogfunction cvm_mmc_reset_busfunction cvm_mmc_switch_tofunction do_readfunction do_writefunction set_cmd_responsefunction get_dma_dirfunction finish_dma_singlefunction finish_dma_sgfunction finish_dmafunction check_statusfunction cleanup_dmafunction cvm_mmc_interruptfunction prepare_dma_singlefunction prepare_dma_sgfunction for_each_sgfunction prepare_dmafunction prepare_ext_dmafunction cvm_mmc_dma_requestfunction do_read_requestfunction do_write_requestfunction cvm_mmc_requestfunction cvm_mmc_set_iosfunction cvm_mmc_set_clockfunction cvm_mmc_init_lowlevelfunction cvm_mmc_of_parsefunction cvm_mmc_of_slot_probefunction cvm_mmc_of_slot_remove
Annotated Snippet
if (smi->consumed >= smi->length) {
if (!sg_miter_next(smi))
break;
smi->consumed = 0;
}
if (shift < 0) {
dat = readq(host->base + MIO_EMM_BUF_DAT(host));
shift = 56;
}
while (smi->consumed < smi->length && shift >= 0) {
((u8 *)smi->addr)[smi->consumed] = (dat >> shift) & 0xff;
bytes_xfered++;
smi->consumed++;
shift -= 8;
}
}
sg_miter_stop(smi);
req->data->bytes_xfered = bytes_xfered;
req->data->error = 0;
}
static void do_write(struct mmc_request *req)
{
req->data->bytes_xfered = req->data->blocks * req->data->blksz;
req->data->error = 0;
}
static void set_cmd_response(struct cvm_mmc_host *host, struct mmc_request *req,
u64 rsp_sts)
{
u64 rsp_hi, rsp_lo;
if (!(rsp_sts & MIO_EMM_RSP_STS_RSP_VAL))
return;
rsp_lo = readq(host->base + MIO_EMM_RSP_LO(host));
switch (FIELD_GET(MIO_EMM_RSP_STS_RSP_TYPE, rsp_sts)) {
case 1:
case 3:
req->cmd->resp[0] = (rsp_lo >> 8) & 0xffffffff;
req->cmd->resp[1] = 0;
req->cmd->resp[2] = 0;
req->cmd->resp[3] = 0;
break;
case 2:
req->cmd->resp[3] = rsp_lo & 0xffffffff;
req->cmd->resp[2] = (rsp_lo >> 32) & 0xffffffff;
rsp_hi = readq(host->base + MIO_EMM_RSP_HI(host));
req->cmd->resp[1] = rsp_hi & 0xffffffff;
req->cmd->resp[0] = (rsp_hi >> 32) & 0xffffffff;
break;
}
}
static int get_dma_dir(struct mmc_data *data)
{
return (data->flags & MMC_DATA_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
}
static int finish_dma_single(struct cvm_mmc_host *host, struct mmc_data *data)
{
data->bytes_xfered = data->blocks * data->blksz;
data->error = 0;
dma_unmap_sg(host->dev, data->sg, data->sg_len, get_dma_dir(data));
return 1;
}
static int finish_dma_sg(struct cvm_mmc_host *host, struct mmc_data *data)
{
u64 fifo_cfg;
int count;
/* Check if there are any pending requests left */
fifo_cfg = readq(host->dma_base + MIO_EMM_DMA_FIFO_CFG(host));
count = FIELD_GET(MIO_EMM_DMA_FIFO_CFG_COUNT, fifo_cfg);
if (count)
dev_err(host->dev, "%u requests still pending\n", count);
data->bytes_xfered = data->blocks * data->blksz;
data->error = 0;
/* Clear and disable FIFO */
writeq(BIT_ULL(16), host->dma_base + MIO_EMM_DMA_FIFO_CFG(host));
dma_unmap_sg(host->dev, data->sg, data->sg_len, get_dma_dir(data));
return 1;
}
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/delay.h`, `linux/dma-direction.h`, `linux/dma-mapping.h`, `linux/gpio/consumer.h`, `linux/interrupt.h`, `linux/mmc/mmc.h`, `linux/mmc/slot-gpio.h`.
- Detected declarations: `function cvm_mmc_get_cr_mods`, `function check_switch_errors`, `function clear_bus_id`, `function set_bus_id`, `function get_bus_id`, `function do_switch`, `function switch_val_changed`, `function set_wdog`, `function cvm_mmc_reset_bus`, `function cvm_mmc_switch_to`.
- Atlas domain: Driver Families / drivers/mmc.
- 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.