/*
 * Copyright (C) 2011-2016 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
 *
 * A copy of the licence is included with the program, and can also be obtained from Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "mali_osk_mali.h"
#include "mali_kernel_common.h"

#include <linux/clk.h>
#include <linux/devfreq.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/driver.h>
#ifdef CONFIG_DEVFREQ_THERMAL
#include <linux/devfreq_cooling.h>
#endif

#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
#include <linux/pm_opp.h>
#else /* Linux >= 3.13 */
/* In 3.13 the OPP include header file, types, and functions were all
 * renamed. Use the old filename for the include, and define the new names to
 * the old, when an old kernel is detected.
 */
#include <linux/opp.h>
#define dev_pm_opp opp
#define dev_pm_opp_get_voltage opp_get_voltage
#define dev_pm_opp_get_opp_count opp_get_opp_count
#define dev_pm_opp_find_freq_ceil opp_find_freq_ceil
#endif /* Linux >= 3.13 */

#include "mali_pm_metrics.h"

static int
mali_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
{
	struct mali_device *mdev = dev_get_drvdata(dev);
	struct dev_pm_opp *opp;
	unsigned long freq = 0;
	unsigned long voltage;
	int err;

	freq = *target_freq;

	rcu_read_lock();
	opp = devfreq_recommended_opp(dev, &freq, flags);
	voltage = dev_pm_opp_get_voltage(opp);
	rcu_read_unlock();
	if (IS_ERR_OR_NULL(opp)) {
		MALI_PRINT_ERROR(("Failed to get opp (%ld)\n", PTR_ERR(opp)));
		return PTR_ERR(opp);
	}

	MALI_DEBUG_PRINT(2, ("mali_devfreq_target:set_freq = %lld flags = 0x%x\n", freq, flags));
	/*
	 * Only update if there is a change of frequency
	 */
	if (mdev->current_freq == freq) {
		*target_freq = freq;
		mali_pm_reset_dvfs_utilisation(mdev);
		return 0;
	}

#ifdef CONFIG_REGULATOR
	if (mdev->regulator && mdev->current_voltage != voltage
	    && mdev->current_freq < freq) {
		err = regulator_set_voltage(mdev->regulator, voltage, voltage);
		if (err) {
			MALI_PRINT_ERROR(("Failed to increase voltage (%d)\n", err));
			return err;
		}
	}
#endif

	err = clk_set_rate(mdev->clock, freq);
	if (err) {
		MALI_PRINT_ERROR(("Failed to set clock %lu (target %lu)\n", freq, *target_freq));
		return err;
	}

#ifdef CONFIG_REGULATOR
	if (mdev->regulator && mdev->current_voltage != voltage
	    && mdev->current_freq > freq) {
		err = regulator_set_voltage(mdev->regulator, voltage, voltage);
		if (err) {
			MALI_PRINT_ERROR(("Failed to decrease voltage (%d)\n", err));
			return err;
		}
	}
#endif

	*target_freq = freq;
	mdev->current_voltage = voltage;
	mdev->current_freq = freq;

	mali_pm_reset_dvfs_utilisation(mdev);

	return err;
}

static int
mali_devfreq_cur_freq(struct device *dev, unsigned long *freq)
{
	struct mali_device *mdev = dev_get_drvdata(dev);

	*freq = mdev->current_freq;

	MALI_DEBUG_PRINT(2, ("mali_devfreq_cur_freq: freq = %d\n", *freq));
	return 0;
}

static int
mali_devfreq_status(struct device *dev, struct devfreq_dev_status *stat)
{
	struct mali_device *mdev = dev_get_drvdata(dev);

	stat->current_frequency = mdev->current_freq;

	mali_pm_get_dvfs_utilisation(mdev,
				     &stat->total_time, &stat->busy_time);

	stat->private_data = NULL;

#ifdef CONFIG_DEVFREQ_THERMAL
	memcpy(&mdev->devfreq->last_status, stat, sizeof(*stat));
#endif

	return 0;
}

/* setup platform specific opp in platform.c*/
int __weak setup_opps(void)
{
	return 0;
}

/* term platform specific opp in platform.c*/
int __weak term_opps(struct device *dev)
{
	return 0;
}

static int mali_devfreq_init_freq_table(struct mali_device *mdev,
					struct devfreq_dev_profile *dp)
{
	int err, count;
	int i = 0;
	unsigned long freq = 0;
	struct dev_pm_opp *opp;

	err = setup_opps();
	if (err)
		return err;

	rcu_read_lock();
	count = dev_pm_opp_get_opp_count(mdev->dev);
	if (count < 0) {
		rcu_read_unlock();
		return count;
	}
	rcu_read_unlock();

	MALI_DEBUG_PRINT(2, ("mali devfreq table count %d\n", count));

	dp->freq_table = kmalloc_array(count, sizeof(dp->freq_table[0]),
				       GFP_KERNEL);
	if (!dp->freq_table)
		return -ENOMEM;

	rcu_read_lock();
	for (i = 0; i < count; i++, freq++) {
		opp = dev_pm_opp_find_freq_ceil(mdev->dev, &freq);
		if (IS_ERR(opp))
			break;

		dp->freq_table[i] = freq;
		MALI_DEBUG_PRINT(2, ("mali devfreq table array[%d] = %d\n", i, freq));
	}
	rcu_read_unlock();

	if (count != i)
		MALI_PRINT_ERROR(("Unable to enumerate all OPPs (%d!=%d)\n",
				  count, i));

	dp->max_state = i;

	return 0;
}

static void mali_devfreq_term_freq_table(struct mali_device *mdev)
{
	struct devfreq_dev_profile *dp = mdev->devfreq->profile;

	kfree(dp->freq_table);
	term_opps(mdev->dev);
}

static void mali_devfreq_exit(struct device *dev)
{
	struct mali_device *mdev = dev_get_drvdata(dev);

	mali_devfreq_term_freq_table(mdev);
}

int mali_devfreq_init(struct mali_device *mdev)
{
#ifdef CONFIG_DEVFREQ_THERMAL
	struct devfreq_cooling_power *callbacks = NULL;
	_mali_osk_device_data data;
#endif
	struct devfreq_dev_profile *dp;
	int err;

	MALI_DEBUG_PRINT(2, ("Init Mali devfreq\n"));

	if (!mdev->clock)
		return -ENODEV;

	mdev->current_freq = clk_get_rate(mdev->clock);

	dp = &mdev->devfreq_profile;

	dp->initial_freq = mdev->current_freq;
	dp->polling_ms = 100;
	dp->target = mali_devfreq_target;
	dp->get_dev_status = mali_devfreq_status;
	dp->get_cur_freq = mali_devfreq_cur_freq;
	dp->exit = mali_devfreq_exit;

	if (mali_devfreq_init_freq_table(mdev, dp))
		return -EFAULT;

	mdev->devfreq = devfreq_add_device(mdev->dev, dp,
					   "simple_ondemand", NULL);
	if (IS_ERR(mdev->devfreq)) {
		mali_devfreq_term_freq_table(mdev);
		return PTR_ERR(mdev->devfreq);
	}

	err = devfreq_register_opp_notifier(mdev->dev, mdev->devfreq);
	if (err) {
		MALI_PRINT_ERROR(("Failed to register OPP notifier (%d)\n", err));
		goto opp_notifier_failed;
	}

#ifdef CONFIG_DEVFREQ_THERMAL
	/* Initilization last_status it will be used when first power allocate called */
	mdev->devfreq->last_status.current_frequency = mdev->current_freq;

	if (_mali_osk_device_data_get(&data) == _MALI_OSK_ERR_OK) {
		if (data.gpu_cooling_ops != NULL) {
			callbacks = data.gpu_cooling_ops;
			MALI_DEBUG_PRINT(2, ("Mali GPU Thermal: Callback handler installed\n"));
		}
	}

	if (callbacks) {
		mdev->devfreq_cooling = of_devfreq_cooling_register_power(
						mdev->dev->of_node,
						mdev->devfreq,
						callbacks);
		if (IS_ERR_OR_NULL(mdev->devfreq_cooling)) {
			err = PTR_ERR(mdev->devfreq_cooling);
			MALI_PRINT_ERROR(("Failed to register cooling device (%d)\n", err));
			goto cooling_failed;
		} else {
			MALI_DEBUG_PRINT(2, ("Mali GPU Thermal Cooling installed\n"));
		}
	}
#endif

	return 0;

#ifdef CONFIG_DEVFREQ_THERMAL
cooling_failed:
	devfreq_unregister_opp_notifier(mdev->dev, mdev->devfreq);
#endif /* CONFIG_DEVFREQ_THERMAL */
opp_notifier_failed:
	err = devfreq_remove_device(mdev->devfreq);
	if (err)
		MALI_PRINT_ERROR(("Failed to terminate devfreq (%d)\n", err));
	else
		mdev->devfreq = NULL;

	return err;
}

void mali_devfreq_term(struct mali_device *mdev)
{
	int err;

	MALI_DEBUG_PRINT(2, ("Term Mali devfreq\n"));

#ifdef CONFIG_DEVFREQ_THERMAL
	devfreq_cooling_unregister(mdev->devfreq_cooling);
#endif

	devfreq_unregister_opp_notifier(mdev->dev, mdev->devfreq);

	err = devfreq_remove_device(mdev->devfreq);
	if (err)
		MALI_PRINT_ERROR(("Failed to terminate devfreq (%d)\n", err));
	else
		mdev->devfreq = NULL;
}
