// SPDX-License-Identifier: GPL-2.0
/*
* Driver for Intel client SoC with integrated memory controller using IBECC
*
* Copyright (C) 2020 Intel Corporation
*
* The In-Band ECC (IBECC) IP provides ECC protection to all or specific
* regions of the physical memory space. It's used for memory controllers
* that don't support the out-of-band ECC which often needs an additional
* storage device to each channel for storing ECC data.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/irq_work.h>
#include <linux/llist.h>
#include <linux/genalloc.h>
#include <linux/edac.h>
#include <linux/bits.h>
#include <linux/io.h>
#include <asm/mach_traps.h>
#include <asm/nmi.h>
#include <asm/mce.h>
#include "edac_mc.h"
#include "edac_module.h"
#define IGEN6_REVISION "v2.5.1"
#define EDAC_MOD_STR "igen6_edac"
#define IGEN6_NMI_NAME "igen6_ibecc"
/* Debug macros */
#define igen6_printk(level, fmt, arg...) \
edac_printk(level, "igen6", fmt, ##arg)
#define igen6_mc_printk(mci, level, fmt, arg...) \
edac_mc_chipset_printk(mci, level, "igen6", fmt, ##arg)
#define GET_BITFIELD(v, lo, hi) (((v) & GENMASK_ULL(hi, lo)) >> (lo))
#define NUM_IMC 2 /* Max memory controllers */
#define NUM_CHANNELS 2 /* Max channels */
#define NUM_DIMMS 2 /* Max DIMMs per channel */
#define _4GB BIT_ULL(32)
/* Size of physical memory */
#define TOM_OFFSET 0xa0
/* Top of low usable DRAM */
#define TOLUD_OFFSET 0xbc
/* Capability register C */
#define CAPID_C_OFFSET 0xec
#define CAPID_C_IBECC BIT(15)
/* Capability register E */
#define CAPID_E_OFFSET 0xf0
#define CAPID_E_IBECC BIT(12)
#define CAPID_E_IBECC_BIT18 BIT(18)
/* Error Status */
#define ERRSTS_OFFSET 0xc8
#define ERRSTS_CE BIT_ULL(6)
#define ERRSTS_UE BIT_ULL(7)
/* Error Command */
#define ERRCMD_OFFSET 0xca
#define ERRCMD_CE BIT_ULL(6)
#define ERRCMD_UE BIT_ULL(7)
/* IBECC MMIO base address */
#define IBECC_BASE (res_cfg->ibecc_base)
#define IBECC_ACTIVATE_OFFSET IBECC_BASE
#define IBECC_ACTIVATE_EN BIT(0)
/* IBECC error log */
#define ECC_ERROR_LOG_OFFSET (IBECC_BASE + res_cfg->ibecc_error_log_offset)
#define ECC_ERROR_LOG_CE BIT_ULL(62)
#define ECC_ERROR_LOG_UE BIT_ULL(63)
#define ECC_ERROR_LOG_ADDR_SHIFT 5
#define ECC_ERROR_LOG_ADDR(v) GET_BITFIELD(v, 5, 38)
#define ECC_ERROR_LOG_ADDR45(v) GET_BITFIELD(v, 5, 45)
#define ECC_ERROR_LOG_SYND(v) GET_BITFIELD(v, 46, 61)
/* Host MMIO base address */
#define MCHBAR_OFFSET 0x48
#define MCHBAR_EN BIT_ULL(0)
#define MCHBAR_BASE(v) (GET_BITFIELD(v, 16, 38) << 16)
#define MCHBAR_SIZE 0x10000
/* Parameters for the channel decode stage */
#define IMC_BASE (res_cfg->imc_base)