drivers/edac/ti_edac.c
Source file repositories/reference/linux-study-clean/drivers/edac/ti_edac.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/edac/ti_edac.c- Extension
.c- Size
- 8632 bytes
- Lines
- 337
- Domain
- Driver Families
- Bucket
- drivers/edac
- 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.
- 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/init.hlinux/edac.hlinux/io.hlinux/interrupt.hlinux/of_address.hlinux/of_device.hlinux/module.hedac_module.h
Detected Declarations
struct ti_edacfunction ti_edac_readlfunction ti_edac_writelfunction ti_edac_isrfunction ti_edac_setup_dimmfunction _emif_get_idfunction for_each_matching_nodefunction ti_edac_probefunction ti_edac_remove
Annotated Snippet
struct ti_edac {
void __iomem *reg;
};
static u32 ti_edac_readl(struct ti_edac *edac, u16 offset)
{
return readl_relaxed(edac->reg + offset);
}
static void ti_edac_writel(struct ti_edac *edac, u32 val, u16 offset)
{
writel_relaxed(val, edac->reg + offset);
}
static irqreturn_t ti_edac_isr(int irq, void *data)
{
struct mem_ctl_info *mci = data;
struct ti_edac *edac = mci->pvt_info;
u32 irq_status;
u32 err_addr;
int err_count;
irq_status = ti_edac_readl(edac, EMIF_IRQ_STATUS);
if (irq_status & EMIF_1B_ECC_ERR) {
err_addr = ti_edac_readl(edac, EMIF_1B_ECC_ERR_ADDR_LOG);
err_count = ti_edac_readl(edac, EMIF_1B_ECC_ERR_CNT);
ti_edac_writel(edac, err_count, EMIF_1B_ECC_ERR_CNT);
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, err_count,
err_addr >> PAGE_SHIFT,
err_addr & ~PAGE_MASK, -1, 0, 0, 0,
mci->ctl_name, "1B");
}
if (irq_status & EMIF_2B_ECC_ERR) {
err_addr = ti_edac_readl(edac, EMIF_2B_ECC_ERR_ADDR_LOG);
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
err_addr >> PAGE_SHIFT,
err_addr & ~PAGE_MASK, -1, 0, 0, 0,
mci->ctl_name, "2B");
}
if (irq_status & EMIF_WR_ECC_ERR)
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
0, 0, -1, 0, 0, 0,
mci->ctl_name, "WR");
ti_edac_writel(edac, irq_status, EMIF_IRQ_STATUS);
return IRQ_HANDLED;
}
static void ti_edac_setup_dimm(struct mem_ctl_info *mci, u32 type)
{
struct dimm_info *dimm;
struct ti_edac *edac = mci->pvt_info;
int bits;
u32 val;
u32 memsize;
dimm = edac_get_dimm(mci, 0, 0, 0);
val = ti_edac_readl(edac, EMIF_SDRAM_CONFIG);
if (type == EMIF_TYPE_DRA7) {
bits = ((val & SDRAM_PAGESIZE_MASK) >> SDRAM_PAGESIZE_SHIFT) + 8;
bits += ((val & SDRAM_ROWSIZE_MASK) >> SDRAM_ROWSIZE_SHIFT) + 9;
bits += (val & SDRAM_IBANK_MASK) >> SDRAM_IBANK_SHIFT;
if (val & SDRAM_NARROW_MODE_MASK) {
bits++;
dimm->dtype = DEV_X16;
} else {
bits += 2;
dimm->dtype = DEV_X32;
}
} else {
bits = 16;
bits += ((val & SDRAM_K2_PAGESIZE_MASK) >>
SDRAM_K2_PAGESIZE_SHIFT) + 8;
bits += (val & SDRAM_K2_IBANK_MASK) >> SDRAM_K2_IBANK_SHIFT;
bits += (val & SDRAM_K2_EBANK_MASK) >> SDRAM_K2_EBANK_SHIFT;
val = (val & SDRAM_K2_NARROW_MODE_MASK) >>
SDRAM_K2_NARROW_MODE_SHIFT;
switch (val) {
case 0:
bits += 3;
dimm->dtype = DEV_X64;
break;
Annotation
- Immediate include surface: `linux/init.h`, `linux/edac.h`, `linux/io.h`, `linux/interrupt.h`, `linux/of_address.h`, `linux/of_device.h`, `linux/module.h`, `edac_module.h`.
- Detected declarations: `struct ti_edac`, `function ti_edac_readl`, `function ti_edac_writel`, `function ti_edac_isr`, `function ti_edac_setup_dimm`, `function _emif_get_id`, `function for_each_matching_node`, `function ti_edac_probe`, `function ti_edac_remove`.
- Atlas domain: Driver Families / drivers/edac.
- Implementation status: source implementation candidate.
- 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.