/*
 * TI keystone reboot driver
 *
 * Copyright (C) 2014 Texas Instruments Incorporated. http://www.ti.com/
 *
 * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/io.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/of_platform.h>

#define RSTYPE_RG			0x0
#define RSCTRL_RG			0x4
#define RSCFG_RG			0x8
#define RSISO_RG			0xc

#define RSCTRL_KEY_MASK			0x0000ffff
#define RSCTRL_RESET_MASK		BIT(16)
#define RSCTRL_KEY			0x5a69

#define RSMUX_OMODE_MASK		0xe
#define RSMUX_OMODE_RESET_ON		0xa
#define RSMUX_OMODE_RESET_OFF		0x0
#define RSMUX_LOCK_MASK			0x1
#define RSMUX_LOCK_SET			0x1

#define RSCFG_RSTYPE_SOFT		0x300f
#define RSCFG_RSTYPE_HARD		0x0

#define WDT_MUX_NUMBER			0x4

static int rspll_offset;
static struct regmap *pllctrl_regs;

/**
 * rsctrl_enable_rspll_write - enable access to RSCTRL, RSCFG
 * To be able to access to RSCTRL, RSCFG registers
 * we have to write a key before
 */
static inline int rsctrl_enable_rspll_write(void)
{
	return regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG,
				  RSCTRL_KEY_MASK, RSCTRL_KEY);
}

static int rsctrl_restart_handler(struct notifier_block *this,
				  unsigned long mode, void *cmd)
{
	/* enable write access to RSTCTRL */
	rsctrl_enable_rspll_write();

	/* reset the SOC */
	regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG,
			   RSCTRL_RESET_MASK, 0);

	return NOTIFY_DONE;
}

static struct notifier_block rsctrl_restart_nb = {
	.notifier_call = rsctrl_restart_handler,
	.priority = 128,
};

static const struct of_device_id rsctrl_of_match[] = {
	{.compatible = "ti,keystone-reset", },
	{},
};

static int rsctrl_probe(struct platform_device *pdev)
{
	int i;
	int ret;
	u32 val;
	unsigned int rg;
	u32 rsmux_offset;
	struct regmap *devctrl_regs;
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;

	if (!np)
		return -ENODEV;

	/* get regmaps */
	pllctrl_regs = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pll");
	if (IS_ERR(pllctrl_regs))
		return PTR_ERR(pllctrl_regs);

	devctrl_regs = syscon_regmap_lookup_by_phandle(np, "ti,syscon-dev");
	if (IS_ERR(devctrl_regs))
		return PTR_ERR(devctrl_regs);

	ret = of_property_read_u32_index(np, "ti,syscon-pll", 1, &rspll_offset);
	if (ret) {
		dev_err(dev, "couldn't read the reset pll offset!\n");
		return -EINVAL;
	}

	ret = of_property_read_u32_index(np, "ti,syscon-dev", 1, &rsmux_offset);
	if (ret) {
		dev_err(dev, "couldn't read the rsmux offset!\n");
		return -EINVAL;
	}

	/* set soft/hard reset */
	val = of_property_read_bool(np, "ti,soft-reset");
	val = val ? RSCFG_RSTYPE_SOFT : RSCFG_RSTYPE_HARD;

	ret = rsctrl_enable_rspll_write();
	if (ret)
		return ret;

	ret = regmap_write(pllctrl_regs, rspll_offset + RSCFG_RG, val);
	if (ret)
		return ret;

	/* disable a reset isolation for all module clocks */
	ret = regmap_write(pllctrl_regs, rspll_offset + RSISO_RG, 0);
	if (ret)
		return ret;

	/* enable a reset for watchdogs from wdt-list */
	for (i = 0; i < WDT_MUX_NUMBER; i++) {
		ret = of_property_read_u32_index(np, "ti,wdt-list", i, &val);
		if (ret == -EOVERFLOW && !i) {
			dev_err(dev, "ti,wdt-list property has to contain at"
				"least one entry\n");
			return -EINVAL;
		} else if (ret) {
			break;
		}

		if (val >= WDT_MUX_NUMBER) {
			dev_err(dev, "ti,wdt-list property can contain"
				"only numbers < 4\n");
			return -EINVAL;
		}

		rg = rsmux_offset + val * 4;

		ret = regmap_update_bits(devctrl_regs, rg, RSMUX_OMODE_MASK,
					 RSMUX_OMODE_RESET_ON |
					 RSMUX_LOCK_SET);
		if (ret)
			return ret;
	}

	ret = register_restart_handler(&rsctrl_restart_nb);
	if (ret)
		dev_err(dev, "cannot register restart handler (err=%d)\n", ret);

	return ret;
}

static struct platform_driver rsctrl_driver = {
	.probe = rsctrl_probe,
	.driver = {
		.name = KBUILD_MODNAME,
		.of_match_table = rsctrl_of_match,
	},
};
module_platform_driver(rsctrl_driver);

MODULE_AUTHOR("Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>");
MODULE_DESCRIPTION("Texas Instruments keystone reset driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" KBUILD_MODNAME);
