/*
 * Copyright (c) 2013-2014, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <linux/device.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/random.h>

#include <soc/tegra/fuse.h>

#include "fuse.h"

#define FUSE_BEGIN	0x100

/* Tegra30 and later */
#define FUSE_VENDOR_CODE	0x100
#define FUSE_FAB_CODE		0x104
#define FUSE_LOT_CODE_0		0x108
#define FUSE_LOT_CODE_1		0x10c
#define FUSE_WAFER_ID		0x110
#define FUSE_X_COORDINATE	0x114
#define FUSE_Y_COORDINATE	0x118

#define FUSE_HAS_REVISION_INFO	BIT(0)

enum speedo_idx {
	SPEEDO_TEGRA30 = 0,
	SPEEDO_TEGRA114,
	SPEEDO_TEGRA124,
};

struct tegra_fuse_info {
	int		size;
	int		spare_bit;
	enum speedo_idx	speedo_idx;
};

static void __iomem *fuse_base;
static struct clk *fuse_clk;
static struct tegra_fuse_info *fuse_info;

u32 tegra30_fuse_readl(const unsigned int offset)
{
	u32 val;

	/*
	 * early in the boot, the fuse clock will be enabled by
	 * tegra_init_fuse()
	 */

	if (fuse_clk)
		clk_prepare_enable(fuse_clk);

	val = readl_relaxed(fuse_base + FUSE_BEGIN + offset);

	if (fuse_clk)
		clk_disable_unprepare(fuse_clk);

	return val;
}

static struct tegra_fuse_info tegra30_info = {
	.size			= 0x2a4,
	.spare_bit		= 0x144,
	.speedo_idx		= SPEEDO_TEGRA30,
};

static struct tegra_fuse_info tegra114_info = {
	.size			= 0x2a0,
	.speedo_idx		= SPEEDO_TEGRA114,
};

static struct tegra_fuse_info tegra124_info = {
	.size			= 0x300,
	.speedo_idx		= SPEEDO_TEGRA124,
};

static const struct of_device_id tegra30_fuse_of_match[] = {
	{ .compatible = "nvidia,tegra30-efuse", .data = &tegra30_info },
	{ .compatible = "nvidia,tegra114-efuse", .data = &tegra114_info },
	{ .compatible = "nvidia,tegra124-efuse", .data = &tegra124_info },
	{},
};

static int tegra30_fuse_probe(struct platform_device *pdev)
{
	const struct of_device_id *of_dev_id;

	of_dev_id = of_match_device(tegra30_fuse_of_match, &pdev->dev);
	if (!of_dev_id)
		return -ENODEV;

	fuse_clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(fuse_clk)) {
		dev_err(&pdev->dev, "missing clock");
		return PTR_ERR(fuse_clk);
	}

	platform_set_drvdata(pdev, NULL);

	if (tegra_fuse_create_sysfs(&pdev->dev, fuse_info->size,
				    tegra30_fuse_readl))
		return -ENODEV;

	dev_dbg(&pdev->dev, "loaded\n");

	return 0;
}

static struct platform_driver tegra30_fuse_driver = {
	.probe = tegra30_fuse_probe,
	.driver = {
		.name = "tegra_fuse",
		.owner = THIS_MODULE,
		.of_match_table = tegra30_fuse_of_match,
	}
};

static int __init tegra30_fuse_init(void)
{
	return platform_driver_register(&tegra30_fuse_driver);
}
postcore_initcall(tegra30_fuse_init);

/* Early boot code. This code is called before the devices are created */

typedef void (*speedo_f)(struct tegra_sku_info *sku_info);

static speedo_f __initdata speedo_tbl[] = {
	[SPEEDO_TEGRA30]	= tegra30_init_speedo_data,
	[SPEEDO_TEGRA114]	= tegra114_init_speedo_data,
	[SPEEDO_TEGRA124]	= tegra124_init_speedo_data,
};

static void __init tegra30_fuse_add_randomness(void)
{
	u32 randomness[12];

	randomness[0] = tegra_sku_info.sku_id;
	randomness[1] = tegra_read_straps();
	randomness[2] = tegra_read_chipid();
	randomness[3] = tegra_sku_info.cpu_process_id << 16;
	randomness[3] |= tegra_sku_info.core_process_id;
	randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
	randomness[4] |= tegra_sku_info.soc_speedo_id;
	randomness[5] = tegra30_fuse_readl(FUSE_VENDOR_CODE);
	randomness[6] = tegra30_fuse_readl(FUSE_FAB_CODE);
	randomness[7] = tegra30_fuse_readl(FUSE_LOT_CODE_0);
	randomness[8] = tegra30_fuse_readl(FUSE_LOT_CODE_1);
	randomness[9] = tegra30_fuse_readl(FUSE_WAFER_ID);
	randomness[10] = tegra30_fuse_readl(FUSE_X_COORDINATE);
	randomness[11] = tegra30_fuse_readl(FUSE_Y_COORDINATE);

	add_device_randomness(randomness, sizeof(randomness));
}

static void __init legacy_fuse_init(void)
{
	switch (tegra_get_chip_id()) {
	case TEGRA30:
		fuse_info = &tegra30_info;
		break;
	case TEGRA114:
		fuse_info = &tegra114_info;
		break;
	case TEGRA124:
		fuse_info = &tegra124_info;
		break;
	default:
		return;
	}

	fuse_base = ioremap(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE);
}

bool __init tegra30_spare_fuse(int spare_bit)
{
	u32 offset = fuse_info->spare_bit + spare_bit * 4;

	return tegra30_fuse_readl(offset) & 1;
}

void __init tegra30_init_fuse_early(void)
{
	struct device_node *np;
	const struct of_device_id *of_match;

	np = of_find_matching_node_and_match(NULL, tegra30_fuse_of_match,
						&of_match);
	if (np) {
		fuse_base = of_iomap(np, 0);
		fuse_info = (struct tegra_fuse_info *)of_match->data;
	} else
		legacy_fuse_init();

	if (!fuse_base) {
		pr_warn("fuse DT node missing and unknown chip id: 0x%02x\n",
			tegra_get_chip_id());
		return;
	}

	tegra_init_revision();
	speedo_tbl[fuse_info->speedo_idx](&tegra_sku_info);
	tegra30_fuse_add_randomness();
}
