drivers/dma/timb_dma.c
Source file repositories/reference/linux-study-clean/drivers/dma/timb_dma.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/dma/timb_dma.c- Extension
.c- Size
- 19328 bytes
- Lines
- 772
- Domain
- Driver Families
- Bucket
- drivers/dma
- 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/dmaengine.hlinux/dma-mapping.hlinux/init.hlinux/interrupt.hlinux/io.hlinux/module.hlinux/platform_device.hlinux/slab.hlinux/timb_dma.hdmaengine.h
Detected Declarations
struct timb_dma_descstruct timb_dma_chanstruct timb_dmafunction __td_enable_chan_irqfunction __td_dma_done_ackfunction td_fill_descfunction __td_start_dmafunction __td_finishfunction __td_ier_maskfunction __td_start_nextfunction td_tx_submitfunction td_free_descfunction td_desc_putfunction td_alloc_chan_resourcesfunction td_free_chan_resourcesfunction list_for_each_entry_safefunction td_tx_statusfunction td_issue_pendingfunction for_each_sgfunction td_terminate_allfunction td_taskletfunction td_irqfunction td_probefunction td_remove
Annotated Snippet
struct timb_dma_desc {
struct list_head desc_node;
struct dma_async_tx_descriptor txd;
u8 *desc_list;
unsigned int desc_list_len;
bool interrupt;
};
struct timb_dma_chan {
struct dma_chan chan;
void __iomem *membase;
spinlock_t lock; /* Used to protect data structures,
especially the lists and descriptors,
from races between the tasklet and calls
from above */
bool ongoing;
struct list_head active_list;
struct list_head queue;
struct list_head free_list;
unsigned int bytes_per_line;
enum dma_transfer_direction direction;
unsigned int descs; /* Descriptors to allocate */
unsigned int desc_elems; /* number of elems per descriptor */
};
struct timb_dma {
struct dma_device dma;
void __iomem *membase;
struct tasklet_struct tasklet;
struct timb_dma_chan channels[];
};
static struct device *chan2dev(struct dma_chan *chan)
{
return &chan->dev->device;
}
static struct device *chan2dmadev(struct dma_chan *chan)
{
return chan2dev(chan)->parent->parent;
}
static struct timb_dma *tdchantotd(struct timb_dma_chan *td_chan)
{
int id = td_chan->chan.chan_id;
return (struct timb_dma *)((u8 *)td_chan -
id * sizeof(struct timb_dma_chan) - sizeof(struct timb_dma));
}
/* Must be called with the spinlock held */
static void __td_enable_chan_irq(struct timb_dma_chan *td_chan)
{
int id = td_chan->chan.chan_id;
struct timb_dma *td = tdchantotd(td_chan);
u32 ier;
/* enable interrupt for this channel */
ier = ioread32(td->membase + TIMBDMA_IER);
ier |= 1 << id;
dev_dbg(chan2dev(&td_chan->chan), "Enabling irq: %d, IER: 0x%x\n", id,
ier);
iowrite32(ier, td->membase + TIMBDMA_IER);
}
/* Should be called with the spinlock held */
static bool __td_dma_done_ack(struct timb_dma_chan *td_chan)
{
int id = td_chan->chan.chan_id;
struct timb_dma *td = (struct timb_dma *)((u8 *)td_chan -
id * sizeof(struct timb_dma_chan) - sizeof(struct timb_dma));
u32 isr;
bool done = false;
dev_dbg(chan2dev(&td_chan->chan), "Checking irq: %d, td: %p\n", id, td);
isr = ioread32(td->membase + TIMBDMA_ISR) & (1 << id);
if (isr) {
iowrite32(isr, td->membase + TIMBDMA_ISR);
done = true;
}
return done;
}
static int td_fill_desc(struct timb_dma_chan *td_chan, u8 *dma_desc,
struct scatterlist *sg, bool last)
{
if (sg_dma_len(sg) > USHRT_MAX) {
dev_err(chan2dev(&td_chan->chan), "Too big sg element\n");
return -EINVAL;
}
Annotation
- Immediate include surface: `linux/dmaengine.h`, `linux/dma-mapping.h`, `linux/init.h`, `linux/interrupt.h`, `linux/io.h`, `linux/module.h`, `linux/platform_device.h`, `linux/slab.h`.
- Detected declarations: `struct timb_dma_desc`, `struct timb_dma_chan`, `struct timb_dma`, `function __td_enable_chan_irq`, `function __td_dma_done_ack`, `function td_fill_desc`, `function __td_start_dma`, `function __td_finish`, `function __td_ier_mask`, `function __td_start_next`.
- Atlas domain: Driver Families / drivers/dma.
- 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.