#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/stop_machine.h>
#include <linux/of_address.h>
#include <asm/cell-regs.h>
struct cbe_mic_tm_regs __iomem *regs;
static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
struct cell_edac_priv *priv = mci->pvt_info;
struct csrow_info *csrow = mci->csrows[0];
unsigned long address, pfn, offset, syndrome;
dev_dbg(mci->pdev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n",
address = (ar & 0xffffffffe0000000ul) >> 29;
if (priv->chanmask == 0x3)
address = (address << 1) | chan;
pfn = address >> PAGE_SHIFT;
offset = address & ~PAGE_MASK;
syndrome = (ar & 0x000000001fe00000ul) >> 21;
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
csrow->first_page + pfn, offset, syndrome,
static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
struct cell_edac_priv *priv = mci->pvt_info;
struct csrow_info *csrow = mci->csrows[0];
unsigned long address, pfn, offset;
dev_dbg(mci->pdev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n",
address = (ar & 0xffffffffe0000000ul) >> 29;
if (priv->chanmask == 0x3)
address = (address << 1) | chan;
pfn = address >> PAGE_SHIFT;
offset = address & ~PAGE_MASK;
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
csrow->first_page + pfn, offset, 0,
static void cell_edac_check(struct mem_ctl_info *mci)
struct cell_edac_priv *priv = mci->pvt_info;
u64 fir, addreg, clear = 0;
fir = in_be64(&priv->regs->mic_fir);
if (fir != priv->prev_fir) {
dev_dbg(mci->pdev, "fir change : 0x%016lx\n", fir);
if ((priv->chanmask & 0x1) && (fir & CBE_MIC_FIR_ECC_SINGLE_0_ERR)) {
addreg = in_be64(&priv->regs->mic_df_ecc_address_0);