static void axp_mc_check()

in armada_xp_edac.c [125:217]


static void axp_mc_check(struct mem_ctl_info *mci)
{
	struct axp_mc_drvdata *drvdata = mci->pvt_info;
	uint32_t data_h, data_l, recv_ecc, calc_ecc, addr;
	uint32_t cnt_sbe, cnt_dbe, cause_err, cause_msg;
	uint32_t row_val, col_val, bank_val, addr_val;
	uint8_t syndrome_val, cs_val;
	char *msg = drvdata->msg;

	data_h    = readl(drvdata->base + SDRAM_ERR_DATA_H_REG);
	data_l    = readl(drvdata->base + SDRAM_ERR_DATA_L_REG);
	recv_ecc  = readl(drvdata->base + SDRAM_ERR_RECV_ECC_REG);
	calc_ecc  = readl(drvdata->base + SDRAM_ERR_CALC_ECC_REG);
	addr      = readl(drvdata->base + SDRAM_ERR_ADDR_REG);
	cnt_sbe   = readl(drvdata->base + SDRAM_ERR_SBE_COUNT_REG);
	cnt_dbe   = readl(drvdata->base + SDRAM_ERR_DBE_COUNT_REG);
	cause_err = readl(drvdata->base + SDRAM_ERR_CAUSE_ERR_REG);
	cause_msg = readl(drvdata->base + SDRAM_ERR_CAUSE_MSG_REG);

	/* clear cause registers */
	writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK),
	       drvdata->base + SDRAM_ERR_CAUSE_ERR_REG);
	writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK),
	       drvdata->base + SDRAM_ERR_CAUSE_MSG_REG);

	/* clear error counter registers */
	if (cnt_sbe)
		writel(0, drvdata->base + SDRAM_ERR_SBE_COUNT_REG);
	if (cnt_dbe)
		writel(0, drvdata->base + SDRAM_ERR_DBE_COUNT_REG);

	if (!cnt_sbe && !cnt_dbe)
		return;

	if (!(addr & SDRAM_ERR_ADDR_TYPE_MASK)) {
		if (cnt_sbe)
			cnt_sbe--;
		else
			dev_warn(mci->pdev, "inconsistent SBE count detected\n");
	} else {
		if (cnt_dbe)
			cnt_dbe--;
		else
			dev_warn(mci->pdev, "inconsistent DBE count detected\n");
	}

	/* report earlier errors */
	if (cnt_sbe)
		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
				     cnt_sbe, /* error count */
				     0, 0, 0, /* pfn, offset, syndrome */
				     -1, -1, -1, /* top, mid, low layer */
				     mci->ctl_name,
				     "details unavailable (multiple errors)");
	if (cnt_dbe)
		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
				     cnt_dbe, /* error count */
				     0, 0, 0, /* pfn, offset, syndrome */
				     -1, -1, -1, /* top, mid, low layer */
				     mci->ctl_name,
				     "details unavailable (multiple errors)");

	/* report details for most recent error */
	cs_val   = (addr & SDRAM_ERR_ADDR_CS_MASK) >> SDRAM_ERR_ADDR_CS_OFFSET;
	bank_val = (addr & SDRAM_ERR_ADDR_BANK_MASK) >> SDRAM_ERR_ADDR_BANK_OFFSET;
	row_val  = (calc_ecc & SDRAM_ERR_CALC_ECC_ROW_MASK) >> SDRAM_ERR_CALC_ECC_ROW_OFFSET;
	col_val  = (addr & SDRAM_ERR_ADDR_COL_MASK) >> SDRAM_ERR_ADDR_COL_OFFSET;
	syndrome_val = (recv_ecc ^ calc_ecc) & 0xff;
	addr_val = axp_mc_calc_address(drvdata, cs_val, bank_val, row_val,
				       col_val);
	msg += sprintf(msg, "row=0x%04x ", row_val); /* 11 chars */
	msg += sprintf(msg, "bank=0x%x ", bank_val); /*  9 chars */
	msg += sprintf(msg, "col=0x%04x ", col_val); /* 11 chars */
	msg += sprintf(msg, "cs=%d", cs_val);	     /*  4 chars */

	if (!(addr & SDRAM_ERR_ADDR_TYPE_MASK)) {
		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
				     1,	/* error count */
				     addr_val >> PAGE_SHIFT,
				     addr_val & ~PAGE_MASK,
				     syndrome_val,
				     cs_val, -1, -1, /* top, mid, low layer */
				     mci->ctl_name, drvdata->msg);
	} else {
		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
				     1,	/* error count */
				     addr_val >> PAGE_SHIFT,
				     addr_val & ~PAGE_MASK,
				     syndrome_val,
				     cs_val, -1, -1, /* top, mid, low layer */
				     mci->ctl_name, drvdata->msg);
	}
}