/*
 * Copyright (C) 2011 Google, Inc.
 *
 * Author:
 *	Colin Cross <ccross@android.com>
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * 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.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tegra_emc.h>

#include "tegra2_emc.h"
#include "fuse.h"

#ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE
static bool emc_enable = true;
#else
static bool emc_enable;
#endif
module_param(emc_enable, bool, 0644);

static struct platform_device *emc_pdev;
static void __iomem *emc_regbase;

static inline void emc_writel(u32 val, unsigned long addr)
{
	writel(val, emc_regbase + addr);
}

static inline u32 emc_readl(unsigned long addr)
{
	return readl(emc_regbase + addr);
}

static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
	0x2c,	/* RC */
	0x30,	/* RFC */
	0x34,	/* RAS */
	0x38,	/* RP */
	0x3c,	/* R2W */
	0x40,	/* W2R */
	0x44,	/* R2P */
	0x48,	/* W2P */
	0x4c,	/* RD_RCD */
	0x50,	/* WR_RCD */
	0x54,	/* RRD */
	0x58,	/* REXT */
	0x5c,	/* WDV */
	0x60,	/* QUSE */
	0x64,	/* QRST */
	0x68,	/* QSAFE */
	0x6c,	/* RDV */
	0x70,	/* REFRESH */
	0x74,	/* BURST_REFRESH_NUM */
	0x78,	/* PDEX2WR */
	0x7c,	/* PDEX2RD */
	0x80,	/* PCHG2PDEN */
	0x84,	/* ACT2PDEN */
	0x88,	/* AR2PDEN */
	0x8c,	/* RW2PDEN */
	0x90,	/* TXSR */
	0x94,	/* TCKE */
	0x98,	/* TFAW */
	0x9c,	/* TRPAB */
	0xa0,	/* TCLKSTABLE */
	0xa4,	/* TCLKSTOP */
	0xa8,	/* TREFBW */
	0xac,	/* QUSE_EXTRA */
	0x114,	/* FBIO_CFG6 */
	0xb0,	/* ODT_WRITE */
	0xb4,	/* ODT_READ */
	0x104,	/* FBIO_CFG5 */
	0x2bc,	/* CFG_DIG_DLL */
	0x2c0,	/* DLL_XFORM_DQS */
	0x2c4,	/* DLL_XFORM_QUSE */
	0x2e0,	/* ZCAL_REF_CNT */
	0x2e4,	/* ZCAL_WAIT_CNT */
	0x2a8,	/* AUTO_CAL_INTERVAL */
	0x2d0,	/* CFG_CLKTRIM_0 */
	0x2d4,	/* CFG_CLKTRIM_1 */
	0x2d8,	/* CFG_CLKTRIM_2 */
};

/* Select the closest EMC rate that is higher than the requested rate */
long tegra_emc_round_rate(unsigned long rate)
{
	struct tegra_emc_pdata *pdata;
	int i;
	int best = -1;
	unsigned long distance = ULONG_MAX;

	if (!emc_pdev)
		return -EINVAL;

	pdata = emc_pdev->dev.platform_data;

	pr_debug("%s: %lu\n", __func__, rate);

	/*
	 * The EMC clock rate is twice the bus rate, and the bus rate is
	 * measured in kHz
	 */
	rate = rate / 2 / 1000;

	for (i = 0; i < pdata->num_tables; i++) {
		if (pdata->tables[i].rate >= rate &&
		    (pdata->tables[i].rate - rate) < distance) {
			distance = pdata->tables[i].rate - rate;
			best = i;
		}
	}

	if (best < 0)
		return -EINVAL;

	pr_debug("%s: using %lu\n", __func__, pdata->tables[best].rate);

	return pdata->tables[best].rate * 2 * 1000;
}

/*
 * The EMC registers have shadow registers.  When the EMC clock is updated
 * in the clock controller, the shadow registers are copied to the active
 * registers, allowing glitchless memory bus frequency changes.
 * This function updates the shadow registers for a new clock frequency,
 * and relies on the clock lock on the emc clock to avoid races between
 * multiple frequency changes
 */
int tegra_emc_set_rate(unsigned long rate)
{
	struct tegra_emc_pdata *pdata;
	int i;
	int j;

	if (!emc_pdev)
		return -EINVAL;

	pdata = emc_pdev->dev.platform_data;

	/*
	 * The EMC clock rate is twice the bus rate, and the bus rate is
	 * measured in kHz
	 */
	rate = rate / 2 / 1000;

	for (i = 0; i < pdata->num_tables; i++)
		if (pdata->tables[i].rate == rate)
			break;

	if (i >= pdata->num_tables)
		return -EINVAL;

	pr_debug("%s: setting to %lu\n", __func__, rate);

	for (j = 0; j < TEGRA_EMC_NUM_REGS; j++)
		emc_writel(pdata->tables[i].regs[j], emc_reg_addr[j]);

	emc_readl(pdata->tables[i].regs[TEGRA_EMC_NUM_REGS - 1]);

	return 0;
}

#ifdef CONFIG_OF
static struct device_node *tegra_emc_ramcode_devnode(struct device_node *np)
{
	struct device_node *iter;
	u32 reg;

	for_each_child_of_node(np, iter) {
		if (of_property_read_u32(np, "nvidia,ram-code", &reg))
			continue;
		if (reg == tegra_bct_strapping)
			return of_node_get(iter);
	}

	return NULL;
}

static struct tegra_emc_pdata *tegra_emc_dt_parse_pdata(
		struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct device_node *tnp, *iter;
	struct tegra_emc_pdata *pdata;
	int ret, i, num_tables;

	if (!np)
		return NULL;

	if (of_find_property(np, "nvidia,use-ram-code", NULL)) {
		tnp = tegra_emc_ramcode_devnode(np);
		if (!tnp)
			dev_warn(&pdev->dev,
				 "can't find emc table for ram-code 0x%02x\n",
				 tegra_bct_strapping);
	} else
		tnp = of_node_get(np);

	if (!tnp)
		return NULL;

	num_tables = 0;
	for_each_child_of_node(tnp, iter)
		if (of_device_is_compatible(iter, "nvidia,tegra20-emc-table"))
			num_tables++;

	if (!num_tables) {
		pdata = NULL;
		goto out;
	}

	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
	pdata->tables = devm_kzalloc(&pdev->dev,
				     sizeof(*pdata->tables) * num_tables,
				     GFP_KERNEL);

	i = 0;
	for_each_child_of_node(tnp, iter) {
		u32 prop;

		ret = of_property_read_u32(iter, "clock-frequency", &prop);
		if (ret) {
			dev_err(&pdev->dev, "no clock-frequency in %s\n",
				iter->full_name);
			continue;
		}
		pdata->tables[i].rate = prop;

		ret = of_property_read_u32_array(iter, "nvidia,emc-registers",
						 pdata->tables[i].regs,
						 TEGRA_EMC_NUM_REGS);
		if (ret) {
			dev_err(&pdev->dev,
				"malformed emc-registers property in %s\n",
				iter->full_name);
			continue;
		}

		i++;
	}
	pdata->num_tables = i;

out:
	of_node_put(tnp);
	return pdata;
}
#else
static struct tegra_emc_pdata *tegra_emc_dt_parse_pdata(
		struct platform_device *pdev)
{
	return NULL;
}
#endif

static struct tegra_emc_pdata *tegra_emc_fill_pdata(struct platform_device *pdev)
{
	struct clk *c = clk_get_sys(NULL, "emc");
	struct tegra_emc_pdata *pdata;
	unsigned long khz;
	int i;

	WARN_ON(pdev->dev.platform_data);
	BUG_ON(IS_ERR(c));

	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
	pdata->tables = devm_kzalloc(&pdev->dev, sizeof(*pdata->tables),
				     GFP_KERNEL);

	pdata->tables[0].rate = clk_get_rate(c) / 2 / 1000;

	for (i = 0; i < TEGRA_EMC_NUM_REGS; i++)
		pdata->tables[0].regs[i] = emc_readl(emc_reg_addr[i]);

	pdata->num_tables = 1;

	khz = pdata->tables[0].rate;
	dev_info(&pdev->dev, "no tables provided, using %ld kHz emc, "
		 "%ld kHz mem\n", khz * 2, khz);

	return pdata;
}

static int tegra_emc_probe(struct platform_device *pdev)
{
	struct tegra_emc_pdata *pdata;
	struct resource *res;

	if (!emc_enable) {
		dev_err(&pdev->dev, "disabled per module parameter\n");
		return -ENODEV;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	emc_regbase = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(emc_regbase))
		return PTR_ERR(emc_regbase);

	pdata = pdev->dev.platform_data;

	if (!pdata)
		pdata = tegra_emc_dt_parse_pdata(pdev);

	if (!pdata)
		pdata = tegra_emc_fill_pdata(pdev);

	pdev->dev.platform_data = pdata;

	emc_pdev = pdev;

	return 0;
}

static struct of_device_id tegra_emc_of_match[] = {
	{ .compatible = "nvidia,tegra20-emc", },
	{ },
};

static struct platform_driver tegra_emc_driver = {
	.driver         = {
		.name   = "tegra-emc",
		.owner  = THIS_MODULE,
		.of_match_table = tegra_emc_of_match,
	},
	.probe          = tegra_emc_probe,
};

static int __init tegra_emc_init(void)
{
	return platform_driver_register(&tegra_emc_driver);
}
device_initcall(tegra_emc_init);
