cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dmc520_edac.c (16753B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3/*
      4 * EDAC driver for DMC-520 memory controller.
      5 *
      6 * The driver supports 10 interrupt lines,
      7 * though only dram_ecc_errc and dram_ecc_errd are currently handled.
      8 *
      9 * Authors:	Rui Zhao <ruizhao@microsoft.com>
     10 *		Lei Wang <lewan@microsoft.com>
     11 *		Shiping Ji <shji@microsoft.com>
     12 */
     13
     14#include <linux/bitfield.h>
     15#include <linux/edac.h>
     16#include <linux/interrupt.h>
     17#include <linux/io.h>
     18#include <linux/module.h>
     19#include <linux/of.h>
     20#include <linux/platform_device.h>
     21#include <linux/slab.h>
     22#include <linux/spinlock.h>
     23#include "edac_mc.h"
     24
     25/* DMC-520 registers */
     26#define REG_OFFSET_FEATURE_CONFIG			0x130
     27#define REG_OFFSET_ECC_ERRC_COUNT_31_00		0x158
     28#define REG_OFFSET_ECC_ERRC_COUNT_63_32		0x15C
     29#define REG_OFFSET_ECC_ERRD_COUNT_31_00		0x160
     30#define REG_OFFSET_ECC_ERRD_COUNT_63_32		0x164
     31#define REG_OFFSET_INTERRUPT_CONTROL			0x500
     32#define REG_OFFSET_INTERRUPT_CLR			0x508
     33#define REG_OFFSET_INTERRUPT_STATUS			0x510
     34#define REG_OFFSET_DRAM_ECC_ERRC_INT_INFO_31_00	0x528
     35#define REG_OFFSET_DRAM_ECC_ERRC_INT_INFO_63_32	0x52C
     36#define REG_OFFSET_DRAM_ECC_ERRD_INT_INFO_31_00	0x530
     37#define REG_OFFSET_DRAM_ECC_ERRD_INT_INFO_63_32	0x534
     38#define REG_OFFSET_ADDRESS_CONTROL_NOW			0x1010
     39#define REG_OFFSET_MEMORY_TYPE_NOW			0x1128
     40#define REG_OFFSET_SCRUB_CONTROL0_NOW			0x1170
     41#define REG_OFFSET_FORMAT_CONTROL			0x18
     42
     43/* DMC-520 types, masks and bitfields */
     44#define RAM_ECC_INT_CE_BIT			BIT(0)
     45#define RAM_ECC_INT_UE_BIT			BIT(1)
     46#define DRAM_ECC_INT_CE_BIT			BIT(2)
     47#define DRAM_ECC_INT_UE_BIT			BIT(3)
     48#define FAILED_ACCESS_INT_BIT			BIT(4)
     49#define FAILED_PROG_INT_BIT			BIT(5)
     50#define LINK_ERR_INT_BIT			BIT(6)
     51#define TEMPERATURE_EVENT_INT_BIT		BIT(7)
     52#define ARCH_FSM_INT_BIT			BIT(8)
     53#define PHY_REQUEST_INT_BIT			BIT(9)
     54#define MEMORY_WIDTH_MASK			GENMASK(1, 0)
     55#define SCRUB_TRIGGER0_NEXT_MASK		GENMASK(1, 0)
     56#define REG_FIELD_DRAM_ECC_ENABLED		GENMASK(1, 0)
     57#define REG_FIELD_MEMORY_TYPE			GENMASK(2, 0)
     58#define REG_FIELD_DEVICE_WIDTH			GENMASK(9, 8)
     59#define REG_FIELD_ADDRESS_CONTROL_COL		GENMASK(2,  0)
     60#define REG_FIELD_ADDRESS_CONTROL_ROW		GENMASK(10, 8)
     61#define REG_FIELD_ADDRESS_CONTROL_BANK		GENMASK(18, 16)
     62#define REG_FIELD_ADDRESS_CONTROL_RANK		GENMASK(25, 24)
     63#define REG_FIELD_ERR_INFO_LOW_VALID		BIT(0)
     64#define REG_FIELD_ERR_INFO_LOW_COL		GENMASK(10, 1)
     65#define REG_FIELD_ERR_INFO_LOW_ROW		GENMASK(28, 11)
     66#define REG_FIELD_ERR_INFO_LOW_RANK		GENMASK(31, 29)
     67#define REG_FIELD_ERR_INFO_HIGH_BANK		GENMASK(3, 0)
     68#define REG_FIELD_ERR_INFO_HIGH_VALID		BIT(31)
     69
     70#define DRAM_ADDRESS_CONTROL_MIN_COL_BITS	8
     71#define DRAM_ADDRESS_CONTROL_MIN_ROW_BITS	11
     72
     73#define DMC520_SCRUB_TRIGGER_ERR_DETECT	2
     74#define DMC520_SCRUB_TRIGGER_IDLE		3
     75
     76/* Driver settings */
     77/*
     78 * The max-length message would be: "rank:7 bank:15 row:262143 col:1023".
     79 * Max length is 34. Using a 40-size buffer is enough.
     80 */
     81#define DMC520_MSG_BUF_SIZE			40
     82#define EDAC_MOD_NAME				"dmc520-edac"
     83#define EDAC_CTL_NAME				"dmc520"
     84
     85/* the data bus width for the attached memory chips. */
     86enum dmc520_mem_width {
     87	MEM_WIDTH_X32 = 2,
     88	MEM_WIDTH_X64 = 3
     89};
     90
     91/* memory type */
     92enum dmc520_mem_type {
     93	MEM_TYPE_DDR3 = 1,
     94	MEM_TYPE_DDR4 = 2
     95};
     96
     97/* memory device width */
     98enum dmc520_dev_width {
     99	DEV_WIDTH_X4 = 0,
    100	DEV_WIDTH_X8 = 1,
    101	DEV_WIDTH_X16 = 2
    102};
    103
    104struct ecc_error_info {
    105	u32 col;
    106	u32 row;
    107	u32 bank;
    108	u32 rank;
    109};
    110
    111/* The interrupt config */
    112struct dmc520_irq_config {
    113	char *name;
    114	int mask;
    115};
    116
    117/* The interrupt mappings */
    118static struct dmc520_irq_config dmc520_irq_configs[] = {
    119	{
    120		.name = "ram_ecc_errc",
    121		.mask = RAM_ECC_INT_CE_BIT
    122	},
    123	{
    124		.name = "ram_ecc_errd",
    125		.mask = RAM_ECC_INT_UE_BIT
    126	},
    127	{
    128		.name = "dram_ecc_errc",
    129		.mask = DRAM_ECC_INT_CE_BIT
    130	},
    131	{
    132		.name = "dram_ecc_errd",
    133		.mask = DRAM_ECC_INT_UE_BIT
    134	},
    135	{
    136		.name = "failed_access",
    137		.mask = FAILED_ACCESS_INT_BIT
    138	},
    139	{
    140		.name = "failed_prog",
    141		.mask = FAILED_PROG_INT_BIT
    142	},
    143	{
    144		.name = "link_err",
    145		.mask = LINK_ERR_INT_BIT
    146	},
    147	{
    148		.name = "temperature_event",
    149		.mask = TEMPERATURE_EVENT_INT_BIT
    150	},
    151	{
    152		.name = "arch_fsm",
    153		.mask = ARCH_FSM_INT_BIT
    154	},
    155	{
    156		.name = "phy_request",
    157		.mask = PHY_REQUEST_INT_BIT
    158	}
    159};
    160
    161#define NUMBER_OF_IRQS				ARRAY_SIZE(dmc520_irq_configs)
    162
    163/*
    164 * The EDAC driver private data.
    165 * error_lock is to protect concurrent writes to the mci->error_desc through
    166 * edac_mc_handle_error().
    167 */
    168struct dmc520_edac {
    169	void __iomem *reg_base;
    170	spinlock_t error_lock;
    171	u32 mem_width_in_bytes;
    172	int irqs[NUMBER_OF_IRQS];
    173	int masks[NUMBER_OF_IRQS];
    174};
    175
    176static int dmc520_mc_idx;
    177
    178static u32 dmc520_read_reg(struct dmc520_edac *pvt, u32 offset)
    179{
    180	return readl(pvt->reg_base + offset);
    181}
    182
    183static void dmc520_write_reg(struct dmc520_edac *pvt, u32 val, u32 offset)
    184{
    185	writel(val, pvt->reg_base + offset);
    186}
    187
    188static u32 dmc520_calc_dram_ecc_error(u32 value)
    189{
    190	u32 total = 0;
    191
    192	/* Each rank's error counter takes one byte. */
    193	while (value > 0) {
    194		total += (value & 0xFF);
    195		value >>= 8;
    196	}
    197	return total;
    198}
    199
    200static u32 dmc520_get_dram_ecc_error_count(struct dmc520_edac *pvt,
    201					    bool is_ce)
    202{
    203	u32 reg_offset_low, reg_offset_high;
    204	u32 err_low, err_high;
    205	u32 err_count;
    206
    207	reg_offset_low = is_ce ? REG_OFFSET_ECC_ERRC_COUNT_31_00 :
    208				 REG_OFFSET_ECC_ERRD_COUNT_31_00;
    209	reg_offset_high = is_ce ? REG_OFFSET_ECC_ERRC_COUNT_63_32 :
    210				  REG_OFFSET_ECC_ERRD_COUNT_63_32;
    211
    212	err_low = dmc520_read_reg(pvt, reg_offset_low);
    213	err_high = dmc520_read_reg(pvt, reg_offset_high);
    214	/* Reset error counters */
    215	dmc520_write_reg(pvt, 0, reg_offset_low);
    216	dmc520_write_reg(pvt, 0, reg_offset_high);
    217
    218	err_count = dmc520_calc_dram_ecc_error(err_low) +
    219		   dmc520_calc_dram_ecc_error(err_high);
    220
    221	return err_count;
    222}
    223
    224static void dmc520_get_dram_ecc_error_info(struct dmc520_edac *pvt,
    225					    bool is_ce,
    226					    struct ecc_error_info *info)
    227{
    228	u32 reg_offset_low, reg_offset_high;
    229	u32 reg_val_low, reg_val_high;
    230	bool valid;
    231
    232	reg_offset_low = is_ce ? REG_OFFSET_DRAM_ECC_ERRC_INT_INFO_31_00 :
    233				 REG_OFFSET_DRAM_ECC_ERRD_INT_INFO_31_00;
    234	reg_offset_high = is_ce ? REG_OFFSET_DRAM_ECC_ERRC_INT_INFO_63_32 :
    235				  REG_OFFSET_DRAM_ECC_ERRD_INT_INFO_63_32;
    236
    237	reg_val_low = dmc520_read_reg(pvt, reg_offset_low);
    238	reg_val_high = dmc520_read_reg(pvt, reg_offset_high);
    239
    240	valid = (FIELD_GET(REG_FIELD_ERR_INFO_LOW_VALID, reg_val_low) != 0) &&
    241		(FIELD_GET(REG_FIELD_ERR_INFO_HIGH_VALID, reg_val_high) != 0);
    242
    243	if (valid) {
    244		info->col = FIELD_GET(REG_FIELD_ERR_INFO_LOW_COL, reg_val_low);
    245		info->row = FIELD_GET(REG_FIELD_ERR_INFO_LOW_ROW, reg_val_low);
    246		info->rank = FIELD_GET(REG_FIELD_ERR_INFO_LOW_RANK, reg_val_low);
    247		info->bank = FIELD_GET(REG_FIELD_ERR_INFO_HIGH_BANK, reg_val_high);
    248	} else {
    249		memset(info, 0, sizeof(*info));
    250	}
    251}
    252
    253static bool dmc520_is_ecc_enabled(void __iomem *reg_base)
    254{
    255	u32 reg_val = readl(reg_base + REG_OFFSET_FEATURE_CONFIG);
    256
    257	return FIELD_GET(REG_FIELD_DRAM_ECC_ENABLED, reg_val);
    258}
    259
    260static enum scrub_type dmc520_get_scrub_type(struct dmc520_edac *pvt)
    261{
    262	enum scrub_type type = SCRUB_NONE;
    263	u32 reg_val, scrub_cfg;
    264
    265	reg_val = dmc520_read_reg(pvt, REG_OFFSET_SCRUB_CONTROL0_NOW);
    266	scrub_cfg = FIELD_GET(SCRUB_TRIGGER0_NEXT_MASK, reg_val);
    267
    268	if (scrub_cfg == DMC520_SCRUB_TRIGGER_ERR_DETECT ||
    269	    scrub_cfg == DMC520_SCRUB_TRIGGER_IDLE)
    270		type = SCRUB_HW_PROG;
    271
    272	return type;
    273}
    274
    275/* Get the memory data bus width, in number of bytes. */
    276static u32 dmc520_get_memory_width(struct dmc520_edac *pvt)
    277{
    278	enum dmc520_mem_width mem_width_field;
    279	u32 mem_width_in_bytes = 0;
    280	u32 reg_val;
    281
    282	reg_val = dmc520_read_reg(pvt, REG_OFFSET_FORMAT_CONTROL);
    283	mem_width_field = FIELD_GET(MEMORY_WIDTH_MASK, reg_val);
    284
    285	if (mem_width_field == MEM_WIDTH_X32)
    286		mem_width_in_bytes = 4;
    287	else if (mem_width_field == MEM_WIDTH_X64)
    288		mem_width_in_bytes = 8;
    289	return mem_width_in_bytes;
    290}
    291
    292static enum mem_type dmc520_get_mtype(struct dmc520_edac *pvt)
    293{
    294	enum mem_type mt = MEM_UNKNOWN;
    295	enum dmc520_mem_type type;
    296	u32 reg_val;
    297
    298	reg_val = dmc520_read_reg(pvt, REG_OFFSET_MEMORY_TYPE_NOW);
    299	type = FIELD_GET(REG_FIELD_MEMORY_TYPE, reg_val);
    300
    301	switch (type) {
    302	case MEM_TYPE_DDR3:
    303		mt = MEM_DDR3;
    304		break;
    305
    306	case MEM_TYPE_DDR4:
    307		mt = MEM_DDR4;
    308		break;
    309	}
    310
    311	return mt;
    312}
    313
    314static enum dev_type dmc520_get_dtype(struct dmc520_edac *pvt)
    315{
    316	enum dmc520_dev_width device_width;
    317	enum dev_type dt = DEV_UNKNOWN;
    318	u32 reg_val;
    319
    320	reg_val = dmc520_read_reg(pvt, REG_OFFSET_MEMORY_TYPE_NOW);
    321	device_width = FIELD_GET(REG_FIELD_DEVICE_WIDTH, reg_val);
    322
    323	switch (device_width) {
    324	case DEV_WIDTH_X4:
    325		dt = DEV_X4;
    326		break;
    327
    328	case DEV_WIDTH_X8:
    329		dt = DEV_X8;
    330		break;
    331
    332	case DEV_WIDTH_X16:
    333		dt = DEV_X16;
    334		break;
    335	}
    336
    337	return dt;
    338}
    339
    340static u32 dmc520_get_rank_count(void __iomem *reg_base)
    341{
    342	u32 reg_val, rank_bits;
    343
    344	reg_val = readl(reg_base + REG_OFFSET_ADDRESS_CONTROL_NOW);
    345	rank_bits = FIELD_GET(REG_FIELD_ADDRESS_CONTROL_RANK, reg_val);
    346
    347	return BIT(rank_bits);
    348}
    349
    350static u64 dmc520_get_rank_size(struct dmc520_edac *pvt)
    351{
    352	u32 reg_val, col_bits, row_bits, bank_bits;
    353
    354	reg_val = dmc520_read_reg(pvt, REG_OFFSET_ADDRESS_CONTROL_NOW);
    355
    356	col_bits = FIELD_GET(REG_FIELD_ADDRESS_CONTROL_COL, reg_val) +
    357		   DRAM_ADDRESS_CONTROL_MIN_COL_BITS;
    358	row_bits = FIELD_GET(REG_FIELD_ADDRESS_CONTROL_ROW, reg_val) +
    359		   DRAM_ADDRESS_CONTROL_MIN_ROW_BITS;
    360	bank_bits = FIELD_GET(REG_FIELD_ADDRESS_CONTROL_BANK, reg_val);
    361
    362	return (u64)pvt->mem_width_in_bytes << (col_bits + row_bits + bank_bits);
    363}
    364
    365static void dmc520_handle_dram_ecc_errors(struct mem_ctl_info *mci,
    366					   bool is_ce)
    367{
    368	struct dmc520_edac *pvt = mci->pvt_info;
    369	char message[DMC520_MSG_BUF_SIZE];
    370	struct ecc_error_info info;
    371	u32 cnt;
    372
    373	dmc520_get_dram_ecc_error_info(pvt, is_ce, &info);
    374
    375	cnt = dmc520_get_dram_ecc_error_count(pvt, is_ce);
    376	if (!cnt)
    377		return;
    378
    379	snprintf(message, ARRAY_SIZE(message),
    380		 "rank:%d bank:%d row:%d col:%d",
    381		 info.rank, info.bank,
    382		 info.row, info.col);
    383
    384	spin_lock(&pvt->error_lock);
    385	edac_mc_handle_error((is_ce ? HW_EVENT_ERR_CORRECTED :
    386			     HW_EVENT_ERR_UNCORRECTED),
    387			     mci, cnt, 0, 0, 0, info.rank, -1, -1,
    388			     message, "");
    389	spin_unlock(&pvt->error_lock);
    390}
    391
    392static irqreturn_t dmc520_edac_dram_ecc_isr(int irq, struct mem_ctl_info *mci,
    393					     bool is_ce)
    394{
    395	struct dmc520_edac *pvt = mci->pvt_info;
    396	u32 i_mask;
    397
    398	i_mask = is_ce ? DRAM_ECC_INT_CE_BIT : DRAM_ECC_INT_UE_BIT;
    399
    400	dmc520_handle_dram_ecc_errors(mci, is_ce);
    401
    402	dmc520_write_reg(pvt, i_mask, REG_OFFSET_INTERRUPT_CLR);
    403
    404	return IRQ_HANDLED;
    405}
    406
    407static irqreturn_t dmc520_edac_dram_all_isr(int irq, struct mem_ctl_info *mci,
    408					     u32 irq_mask)
    409{
    410	struct dmc520_edac *pvt = mci->pvt_info;
    411	irqreturn_t irq_ret = IRQ_NONE;
    412	u32 status;
    413
    414	status = dmc520_read_reg(pvt, REG_OFFSET_INTERRUPT_STATUS);
    415
    416	if ((irq_mask & DRAM_ECC_INT_CE_BIT) &&
    417		(status & DRAM_ECC_INT_CE_BIT))
    418		irq_ret = dmc520_edac_dram_ecc_isr(irq, mci, true);
    419
    420	if ((irq_mask & DRAM_ECC_INT_UE_BIT) &&
    421		(status & DRAM_ECC_INT_UE_BIT))
    422		irq_ret = dmc520_edac_dram_ecc_isr(irq, mci, false);
    423
    424	return irq_ret;
    425}
    426
    427static irqreturn_t dmc520_isr(int irq, void *data)
    428{
    429	struct mem_ctl_info *mci = data;
    430	struct dmc520_edac *pvt = mci->pvt_info;
    431	u32 mask = 0;
    432	int idx;
    433
    434	for (idx = 0; idx < NUMBER_OF_IRQS; idx++) {
    435		if (pvt->irqs[idx] == irq) {
    436			mask = pvt->masks[idx];
    437			break;
    438		}
    439	}
    440	return dmc520_edac_dram_all_isr(irq, mci, mask);
    441}
    442
    443static void dmc520_init_csrow(struct mem_ctl_info *mci)
    444{
    445	struct dmc520_edac *pvt = mci->pvt_info;
    446	struct csrow_info *csi;
    447	struct dimm_info *dimm;
    448	u32 pages_per_rank;
    449	enum dev_type dt;
    450	enum mem_type mt;
    451	int row, ch;
    452	u64 rs;
    453
    454	dt = dmc520_get_dtype(pvt);
    455	mt = dmc520_get_mtype(pvt);
    456	rs = dmc520_get_rank_size(pvt);
    457	pages_per_rank = rs >> PAGE_SHIFT;
    458
    459	for (row = 0; row < mci->nr_csrows; row++) {
    460		csi = mci->csrows[row];
    461
    462		for (ch = 0; ch < csi->nr_channels; ch++) {
    463			dimm		= csi->channels[ch]->dimm;
    464			dimm->grain	= pvt->mem_width_in_bytes;
    465			dimm->dtype	= dt;
    466			dimm->mtype	= mt;
    467			dimm->edac_mode	= EDAC_SECDED;
    468			dimm->nr_pages	= pages_per_rank / csi->nr_channels;
    469		}
    470	}
    471}
    472
    473static int dmc520_edac_probe(struct platform_device *pdev)
    474{
    475	bool registered[NUMBER_OF_IRQS] = { false };
    476	int irqs[NUMBER_OF_IRQS] = { -ENXIO };
    477	int masks[NUMBER_OF_IRQS] = { 0 };
    478	struct edac_mc_layer layers[1];
    479	struct dmc520_edac *pvt = NULL;
    480	struct mem_ctl_info *mci;
    481	void __iomem *reg_base;
    482	u32 irq_mask_all = 0;
    483	struct resource *res;
    484	struct device *dev;
    485	int ret, idx, irq;
    486	u32 reg_val;
    487
    488	/* Parse the device node */
    489	dev = &pdev->dev;
    490
    491	for (idx = 0; idx < NUMBER_OF_IRQS; idx++) {
    492		irq = platform_get_irq_byname_optional(pdev, dmc520_irq_configs[idx].name);
    493		irqs[idx] = irq;
    494		masks[idx] = dmc520_irq_configs[idx].mask;
    495		if (irq >= 0) {
    496			irq_mask_all |= dmc520_irq_configs[idx].mask;
    497			edac_dbg(0, "Discovered %s, irq: %d.\n", dmc520_irq_configs[idx].name, irq);
    498		}
    499	}
    500
    501	if (!irq_mask_all) {
    502		edac_printk(KERN_ERR, EDAC_MOD_NAME,
    503			    "At least one valid interrupt line is expected.\n");
    504		return -EINVAL;
    505	}
    506
    507	/* Initialize dmc520 edac */
    508	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    509	reg_base = devm_ioremap_resource(dev, res);
    510	if (IS_ERR(reg_base))
    511		return PTR_ERR(reg_base);
    512
    513	if (!dmc520_is_ecc_enabled(reg_base))
    514		return -ENXIO;
    515
    516	layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
    517	layers[0].size = dmc520_get_rank_count(reg_base);
    518	layers[0].is_virt_csrow = true;
    519
    520	mci = edac_mc_alloc(dmc520_mc_idx++, ARRAY_SIZE(layers), layers, sizeof(*pvt));
    521	if (!mci) {
    522		edac_printk(KERN_ERR, EDAC_MOD_NAME,
    523			    "Failed to allocate memory for mc instance\n");
    524		ret = -ENOMEM;
    525		goto err;
    526	}
    527
    528	pvt = mci->pvt_info;
    529
    530	pvt->reg_base = reg_base;
    531	spin_lock_init(&pvt->error_lock);
    532	memcpy(pvt->irqs, irqs, sizeof(irqs));
    533	memcpy(pvt->masks, masks, sizeof(masks));
    534
    535	platform_set_drvdata(pdev, mci);
    536
    537	mci->pdev = dev;
    538	mci->mtype_cap		= MEM_FLAG_DDR3 | MEM_FLAG_DDR4;
    539	mci->edac_ctl_cap	= EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
    540	mci->edac_cap		= EDAC_FLAG_SECDED;
    541	mci->scrub_cap		= SCRUB_FLAG_HW_SRC;
    542	mci->scrub_mode		= dmc520_get_scrub_type(pvt);
    543	mci->ctl_name		= EDAC_CTL_NAME;
    544	mci->dev_name		= dev_name(mci->pdev);
    545	mci->mod_name		= EDAC_MOD_NAME;
    546
    547	edac_op_state = EDAC_OPSTATE_INT;
    548
    549	pvt->mem_width_in_bytes = dmc520_get_memory_width(pvt);
    550
    551	dmc520_init_csrow(mci);
    552
    553	/* Clear interrupts, not affecting other unrelated interrupts */
    554	reg_val = dmc520_read_reg(pvt, REG_OFFSET_INTERRUPT_CONTROL);
    555	dmc520_write_reg(pvt, reg_val & (~irq_mask_all),
    556			 REG_OFFSET_INTERRUPT_CONTROL);
    557	dmc520_write_reg(pvt, irq_mask_all, REG_OFFSET_INTERRUPT_CLR);
    558
    559	for (idx = 0; idx < NUMBER_OF_IRQS; idx++) {
    560		irq = irqs[idx];
    561		if (irq >= 0) {
    562			ret = devm_request_irq(&pdev->dev, irq,
    563					       dmc520_isr, IRQF_SHARED,
    564					       dev_name(&pdev->dev), mci);
    565			if (ret < 0) {
    566				edac_printk(KERN_ERR, EDAC_MC,
    567					    "Failed to request irq %d\n", irq);
    568				goto err;
    569			}
    570			registered[idx] = true;
    571		}
    572	}
    573
    574	/* Reset DRAM CE/UE counters */
    575	if (irq_mask_all & DRAM_ECC_INT_CE_BIT)
    576		dmc520_get_dram_ecc_error_count(pvt, true);
    577
    578	if (irq_mask_all & DRAM_ECC_INT_UE_BIT)
    579		dmc520_get_dram_ecc_error_count(pvt, false);
    580
    581	ret = edac_mc_add_mc(mci);
    582	if (ret) {
    583		edac_printk(KERN_ERR, EDAC_MOD_NAME,
    584			    "Failed to register with EDAC core\n");
    585		goto err;
    586	}
    587
    588	/* Enable interrupts, not affecting other unrelated interrupts */
    589	dmc520_write_reg(pvt, reg_val | irq_mask_all,
    590			 REG_OFFSET_INTERRUPT_CONTROL);
    591
    592	return 0;
    593
    594err:
    595	for (idx = 0; idx < NUMBER_OF_IRQS; idx++) {
    596		if (registered[idx])
    597			devm_free_irq(&pdev->dev, pvt->irqs[idx], mci);
    598	}
    599	if (mci)
    600		edac_mc_free(mci);
    601
    602	return ret;
    603}
    604
    605static int dmc520_edac_remove(struct platform_device *pdev)
    606{
    607	u32 reg_val, idx, irq_mask_all = 0;
    608	struct mem_ctl_info *mci;
    609	struct dmc520_edac *pvt;
    610
    611	mci = platform_get_drvdata(pdev);
    612	pvt = mci->pvt_info;
    613
    614	/* Disable interrupts */
    615	reg_val = dmc520_read_reg(pvt, REG_OFFSET_INTERRUPT_CONTROL);
    616	dmc520_write_reg(pvt, reg_val & (~irq_mask_all),
    617			 REG_OFFSET_INTERRUPT_CONTROL);
    618
    619	/* free irq's */
    620	for (idx = 0; idx < NUMBER_OF_IRQS; idx++) {
    621		if (pvt->irqs[idx] >= 0) {
    622			irq_mask_all |= pvt->masks[idx];
    623			devm_free_irq(&pdev->dev, pvt->irqs[idx], mci);
    624		}
    625	}
    626
    627	edac_mc_del_mc(&pdev->dev);
    628	edac_mc_free(mci);
    629
    630	return 0;
    631}
    632
    633static const struct of_device_id dmc520_edac_driver_id[] = {
    634	{ .compatible = "arm,dmc-520", },
    635	{ /* end of table */ }
    636};
    637
    638MODULE_DEVICE_TABLE(of, dmc520_edac_driver_id);
    639
    640static struct platform_driver dmc520_edac_driver = {
    641	.driver = {
    642		.name = "dmc520",
    643		.of_match_table = dmc520_edac_driver_id,
    644	},
    645
    646	.probe = dmc520_edac_probe,
    647	.remove = dmc520_edac_remove
    648};
    649
    650module_platform_driver(dmc520_edac_driver);
    651
    652MODULE_AUTHOR("Rui Zhao <ruizhao@microsoft.com>");
    653MODULE_AUTHOR("Lei Wang <lewan@microsoft.com>");
    654MODULE_AUTHOR("Shiping Ji <shji@microsoft.com>");
    655MODULE_DESCRIPTION("DMC-520 ECC driver");
    656MODULE_LICENSE("GPL v2");