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.

Dependency Surface

Detected Declarations

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

Implementation Notes