/*
 * Copyright (C) 2017 NXP
 *
 * 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/clk.h>
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpu_cooling.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/pm_opp.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/suspend.h>

#define DC_VOLTAGE_MIN		900000
#define DC_VOLTAGE_MAX		1000000

static struct device *cpu_dev;
static bool free_opp;
static struct cpufreq_frequency_table *freq_table;
static struct mutex set_cpufreq_lock;
static unsigned int transition_latency;
static struct clk *a53_clk;
static struct clk *arm_a53_src_clk;
static struct clk *arm_pll_clk;
static struct clk *arm_pll_out_clk;
static struct clk *sys1_pll_800m_clk;
struct thermal_cooling_device *cdev;
static struct regulator *dc_reg;

static int imx8mq_set_target(struct cpufreq_policy *policy, unsigned int index)
{
	struct dev_pm_opp *opp;
	unsigned long freq_hz;
	unsigned int old_freq, new_freq;
	int ret;

	mutex_lock(&set_cpufreq_lock);

	new_freq = freq_table[index].frequency;
	freq_hz = new_freq * 1000;
	old_freq = policy->cur;

	rcu_read_lock();
	opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
	if (IS_ERR(opp)) {
		rcu_read_unlock();
		dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz);
		mutex_unlock(&set_cpufreq_lock);
		return PTR_ERR(opp);
	}
	rcu_read_unlock();

	dev_dbg(cpu_dev, "%u MHz --> %u MHz\n",
		old_freq / 1000, new_freq / 1000);

	if (new_freq == policy->max) {
		if (!IS_ERR(dc_reg)) {
			ret = regulator_set_voltage_tol(dc_reg, DC_VOLTAGE_MAX, 0);
			if (ret) {
				dev_err(cpu_dev, "failed to scale dc_reg up: %d\n", ret);
				mutex_unlock(&set_cpufreq_lock);
				return ret;
			}
		}
	}

	clk_set_parent(arm_a53_src_clk, sys1_pll_800m_clk);
	clk_set_rate(arm_pll_clk, new_freq * 1000);
	clk_set_parent(arm_a53_src_clk, arm_pll_out_clk);

	if (old_freq == policy->max) {
		if (!IS_ERR(dc_reg)) {
			ret = regulator_set_voltage_tol(dc_reg, DC_VOLTAGE_MIN, 0);
			if (ret) {
				dev_err(cpu_dev, "failed to scale dc_reg down: %d\n", ret);
				mutex_unlock(&set_cpufreq_lock);
				return ret;
			}
		}
	}

	/* Ensure the arm clock divider is what we expect */
	ret = clk_set_rate(a53_clk, new_freq * 1000);
	if (ret)
		dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);

	mutex_unlock(&set_cpufreq_lock);
	return ret;
}

static void imx8mq_cpufreq_ready(struct cpufreq_policy *policy)
{
	struct device_node *np = of_get_cpu_node(policy->cpu, NULL);

	if (of_find_property(np, "#cooling-cells", NULL)) {
		cdev = of_cpufreq_cooling_register(np,
			policy->related_cpus);

		if (IS_ERR(cdev) && PTR_ERR(cdev) != -ENOSYS) {
			pr_err("cpu%d is not running as cooling device: %ld\n",
					policy->cpu, PTR_ERR(cdev));

			cdev = NULL;
		}
	}

	of_node_put(np);
}

static int imx8mq_cpufreq_init(struct cpufreq_policy *policy)
{
	int ret;

	policy->clk = a53_clk;
	policy->cur = clk_get_rate(a53_clk) / 1000;

	ret = cpufreq_generic_init(policy, freq_table, transition_latency);
	if (ret) {
		dev_err(cpu_dev, "imx8mq cpufreq init failed!\n");
		return ret;
	}

	policy->suspend_freq = policy->max;

	return 0;
}

static struct cpufreq_driver imx8mq_cpufreq_driver = {
	.flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
	.verify = cpufreq_generic_frequency_table_verify,
	.target_index = imx8mq_set_target,
	.get = cpufreq_generic_get,
	.init = imx8mq_cpufreq_init,
	.name = "imx8mq-cpufreq",
	.ready = imx8mq_cpufreq_ready,
	.attr = cpufreq_generic_attr,
#ifdef CONFIG_PM
	.suspend = cpufreq_generic_suspend,
#endif
};

static int imx8mq_cpufreq_probe(struct platform_device *pdev)
{
	struct device_node *np;
	int ret, num;

	cpu_dev = get_cpu_device(0);
	if (!cpu_dev) {
		pr_err("failed to get cpu0 device\n");
		return -ENODEV;
	}

	np = of_node_get(cpu_dev->of_node);
	if (!np) {
		dev_err(cpu_dev, "failed to find cpu0 node\n");
		return -ENOENT;
	}

	a53_clk = clk_get(cpu_dev, "a53");
	arm_a53_src_clk = clk_get(cpu_dev, "arm_a53_src");
	arm_pll_clk = clk_get(cpu_dev, "arm_pll");
	arm_pll_out_clk = clk_get(cpu_dev, "arm_pll_out");
	sys1_pll_800m_clk = clk_get(cpu_dev, "sys1_pll_800m");
	if (IS_ERR(a53_clk) || IS_ERR(arm_a53_src_clk)
		|| IS_ERR(arm_pll_out_clk) || IS_ERR(arm_pll_clk)
		|| IS_ERR(sys1_pll_800m_clk)) {
		dev_err(cpu_dev, "failed to get clocks\n");
		ret = -ENOENT;
		goto put_clk;
	}

	dc_reg = regulator_get_optional(cpu_dev, "dc");

	/*
	 * We expect an OPP table supplied by platform.
	 * Just, incase the platform did not supply the OPP
	 * table, it will try to get it.
	 */
	num = dev_pm_opp_get_opp_count(cpu_dev);
	if (num < 0) {
		ret = dev_pm_opp_of_add_table(cpu_dev);
		if (ret < 0) {
			dev_err(cpu_dev, "failed to init OPP table: %d\n", ret);
			goto put_clk;
		}
	}

	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
	if (ret) {
		dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
		goto out_free_opp;
	}

	if (of_property_read_u32(np, "clock-latency", &transition_latency))
		transition_latency = CPUFREQ_ETERNAL;

	mutex_init(&set_cpufreq_lock);

	ret = cpufreq_register_driver(&imx8mq_cpufreq_driver);
	if (ret) {
		dev_err(cpu_dev, "failed register driver: %d\n", ret);
		goto free_freq_table;
	}

	of_node_put(np);
	dev_info(cpu_dev, "registered imx8mq-cpufreq\n");

	return 0;

free_freq_table:
	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_free_opp:
	dev_pm_opp_of_remove_table(cpu_dev);
put_clk:
	if (!IS_ERR(a53_clk))
		clk_put(a53_clk);
	if (!IS_ERR(arm_a53_src_clk))
		clk_put(arm_a53_src_clk);
	if (!IS_ERR(arm_pll_clk))
		clk_put(arm_pll_clk);
	if (!IS_ERR(arm_pll_out_clk))
		clk_put(arm_pll_out_clk);
	if (!IS_ERR(sys1_pll_800m_clk))
		clk_put(sys1_pll_800m_clk);
	of_node_put(np);
	return ret;
}

static int imx8mq_cpufreq_remove(struct platform_device *pdev)
{
	cpufreq_cooling_unregister(cdev);
	cpufreq_unregister_driver(&imx8mq_cpufreq_driver);
	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
	if (free_opp)
		dev_pm_opp_of_remove_table(cpu_dev);
	clk_put(a53_clk);
	clk_put(arm_a53_src_clk);
	clk_put(arm_pll_clk);
	clk_put(arm_pll_out_clk);
	clk_put(sys1_pll_800m_clk);

	return 0;
}

static struct platform_driver imx8mq_cpufreq_platdrv = {
	.driver = {
		.name	= "imx8mq-cpufreq",
	},
	.probe		= imx8mq_cpufreq_probe,
	.remove		= imx8mq_cpufreq_remove,
};
module_platform_driver(imx8mq_cpufreq_platdrv);

MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
MODULE_DESCRIPTION("Freescale i.MX8MQ cpufreq driver");
MODULE_LICENSE("GPL");
