/*
 * Copyright 2011 Tilera Corporation. All Rights Reserved.
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation, version 2.
 *
 *   This program is distributed in the hope that it will be useful, but
 *   WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 *   NON INFRINGEMENT.  See the GNU General Public License for
 *   more details.
 * Tilera-specific EDAC driver.
 *
 * This source code is derived from the following driver:
 *
 * Cell MIC driver for ECC counting
 *
 * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
 *                <benh@kernel.crashing.org>
 *
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/edac.h>
#include <hv/hypervisor.h>
#include <hv/drv_mshim_intf.h>

#include "edac_core.h"

#define DRV_NAME	"tile-edac"

/* Number of cs_rows needed per memory controller on TILEPro. */
#define TILE_EDAC_NR_CSROWS	1

/* Number of channels per memory controller on TILEPro. */
#define TILE_EDAC_NR_CHANS	1

/* Granularity of reported error in bytes on TILEPro. */
#define TILE_EDAC_ERROR_GRAIN	8

/* TILE processor has multiple independent memory controllers. */
struct platform_device *mshim_pdev[TILE_MAX_MSHIMS];

struct tile_edac_priv {
	int		hv_devhdl;	/* Hypervisor device handle. */
	int		node;		/* Memory controller instance #. */
	unsigned int	ce_count;	/*
					 * Correctable-error counter
					 * kept by the driver.
					 */
};

static void tile_edac_check(struct mem_ctl_info *mci)
{
	struct tile_edac_priv	*priv = mci->pvt_info;
	struct mshim_mem_error	mem_error;

	if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_error,
		sizeof(struct mshim_mem_error), MSHIM_MEM_ERROR_OFF) !=
		sizeof(struct mshim_mem_error)) {
		pr_err(DRV_NAME ": MSHIM_MEM_ERROR_OFF pread failure.\n");
		return;
	}

	/* Check if the current error count is different from the saved one. */
	if (mem_error.sbe_count != priv->ce_count) {
		dev_dbg(mci->pdev, "ECC CE err on node %d\n", priv->node);
		priv->ce_count = mem_error.sbe_count;
		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
				     0, 0, 0,
				     0, 0, -1,
				     mci->ctl_name, "");
	}
}

/*
 * Initialize the 'csrows' table within the mci control structure with the
 * addressing of memory.
 */
static int tile_edac_init_csrows(struct mem_ctl_info *mci)
{
	struct csrow_info	*csrow = mci->csrows[0];
	struct tile_edac_priv	*priv = mci->pvt_info;
	struct mshim_mem_info	mem_info;
	struct dimm_info *dimm = csrow->channels[0]->dimm;

	if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info,
		sizeof(struct mshim_mem_info), MSHIM_MEM_INFO_OFF) !=
		sizeof(struct mshim_mem_info)) {
		pr_err(DRV_NAME ": MSHIM_MEM_INFO_OFF pread failure.\n");
		return -1;
	}

	if (mem_info.mem_ecc)
		dimm->edac_mode = EDAC_SECDED;
	else
		dimm->edac_mode = EDAC_NONE;
	switch (mem_info.mem_type) {
	case DDR2:
		dimm->mtype = MEM_DDR2;
		break;

	case DDR3:
		dimm->mtype = MEM_DDR3;
		break;

	default:
		return -1;
	}

	dimm->nr_pages = mem_info.mem_size >> PAGE_SHIFT;
	dimm->grain = TILE_EDAC_ERROR_GRAIN;
	dimm->dtype = DEV_UNKNOWN;

	return 0;
}

static int tile_edac_mc_probe(struct platform_device *pdev)
{
	char			hv_file[32];
	int			hv_devhdl;
	struct mem_ctl_info	*mci;
	struct edac_mc_layer	layers[2];
	struct tile_edac_priv	*priv;
	int			rc;

	sprintf(hv_file, "mshim/%d", pdev->id);
	hv_devhdl = hv_dev_open((HV_VirtAddr)hv_file, 0);
	if (hv_devhdl < 0)
		return -EINVAL;

	/* A TILE MC has a single channel and one chip-select row. */
	layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
	layers[0].size = TILE_EDAC_NR_CSROWS;
	layers[0].is_virt_csrow = true;
	layers[1].type = EDAC_MC_LAYER_CHANNEL;
	layers[1].size = TILE_EDAC_NR_CHANS;
	layers[1].is_virt_csrow = false;
	mci = edac_mc_alloc(pdev->id, ARRAY_SIZE(layers), layers,
			    sizeof(struct tile_edac_priv));
	if (mci == NULL)
		return -ENOMEM;
	priv = mci->pvt_info;
	priv->node = pdev->id;
	priv->hv_devhdl = hv_devhdl;

	mci->pdev = &pdev->dev;
	mci->mtype_cap = MEM_FLAG_DDR2;
	mci->edac_ctl_cap = EDAC_FLAG_SECDED;

	mci->mod_name = DRV_NAME;
#ifdef __tilegx__
	mci->ctl_name = "TILEGx_Memory_Controller";
#else
	mci->ctl_name = "TILEPro_Memory_Controller";
#endif
	mci->dev_name = dev_name(&pdev->dev);
	mci->edac_check = tile_edac_check;

	/*
	 * Initialize the MC control structure 'csrows' table
	 * with the mapping and control information.
	 */
	if (tile_edac_init_csrows(mci)) {
		/* No csrows found. */
		mci->edac_cap = EDAC_FLAG_NONE;
	} else {
		mci->edac_cap = EDAC_FLAG_SECDED;
	}

	platform_set_drvdata(pdev, mci);

	/* Register with EDAC core */
	rc = edac_mc_add_mc(mci);
	if (rc) {
		dev_err(&pdev->dev, "failed to register with EDAC core\n");
		edac_mc_free(mci);
		return rc;
	}

	return 0;
}

static int tile_edac_mc_remove(struct platform_device *pdev)
{
	struct mem_ctl_info *mci = platform_get_drvdata(pdev);

	edac_mc_del_mc(&pdev->dev);
	if (mci)
		edac_mc_free(mci);
	return 0;
}

static struct platform_driver tile_edac_mc_driver = {
	.driver		= {
		.name	= DRV_NAME,
	},
	.probe		= tile_edac_mc_probe,
	.remove		= tile_edac_mc_remove,
};

/*
 * Driver init routine.
 */
static int __init tile_edac_init(void)
{
	char	hv_file[32];
	struct platform_device *pdev;
	int i, err, num = 0;

	/* Only support POLL mode. */
	edac_op_state = EDAC_OPSTATE_POLL;

	err = platform_driver_register(&tile_edac_mc_driver);
	if (err)
		return err;

	for (i = 0; i < TILE_MAX_MSHIMS; i++) {
		/*
		 * Not all memory controllers are configured such as in the
		 * case of a simulator. So we register only those mshims
		 * that are configured by the hypervisor.
		 */
		sprintf(hv_file, "mshim/%d", i);
		if (hv_dev_open((HV_VirtAddr)hv_file, 0) < 0)
			continue;

		pdev = platform_device_register_simple(DRV_NAME, i, NULL, 0);
		if (IS_ERR(pdev))
			continue;
		mshim_pdev[i] = pdev;
		num++;
	}

	if (num == 0) {
		platform_driver_unregister(&tile_edac_mc_driver);
		return -ENODEV;
	}
	return 0;
}

/*
 * Driver cleanup routine.
 */
static void __exit tile_edac_exit(void)
{
	int i;

	for (i = 0; i < TILE_MAX_MSHIMS; i++) {
		struct platform_device *pdev = mshim_pdev[i];
		if (!pdev)
			continue;

		platform_device_unregister(pdev);
	}
	platform_driver_unregister(&tile_edac_mc_driver);
}

module_init(tile_edac_init);
module_exit(tile_edac_exit);
