#include <linux/opp.h>
#include <linux/rockchip/dvfs.h>
#include <linux/rockchip/common.h>
+#include <linux/fb.h>
+#include <linux/reboot.h>
+#include "../../../drivers/clk/rockchip/clk-pd.h"
extern int rockchip_tsadc_get_temp(int chn);
static unsigned int target_temp = 80;
static int temp_limit_enable = 1;
+static int pd_gpu_off, early_suspend;
+static DEFINE_MUTEX(switch_vdd_gpu_mutex);
+struct regulator *vdd_gpu_regulator;
+
+static int vdd_gpu_reboot_notifier_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ int ret;
+
+ DVFS_DBG("%s: enable vdd_gpu\n", __func__);
+ mutex_lock(&switch_vdd_gpu_mutex);
+ if (!regulator_is_enabled(vdd_gpu_regulator))
+ ret = regulator_enable(vdd_gpu_regulator);
+ mutex_unlock(&switch_vdd_gpu_mutex);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block vdd_gpu_reboot_notifier = {
+ .notifier_call = vdd_gpu_reboot_notifier_event,
+};
+
+static int clk_pd_gpu_notifier_call(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ int ret;
+
+ mutex_lock(&switch_vdd_gpu_mutex);
+ switch (event) {
+ case RK_CLK_PD_PREPARE:
+ pd_gpu_off = 0;
+ if (early_suspend) {
+ if (!regulator_is_enabled(vdd_gpu_regulator))
+ ret = regulator_enable(vdd_gpu_regulator);
+ }
+ break;
+ case RK_CLK_PD_UNPREPARE:
+ pd_gpu_off = 1;
+ if (early_suspend) {
+ if (regulator_is_enabled(vdd_gpu_regulator))
+ ret = regulator_disable(vdd_gpu_regulator);
+ }
+ break;
+ default:
+ break;
+ }
+ mutex_unlock(&switch_vdd_gpu_mutex);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block clk_pd_gpu_notifier = {
+ .notifier_call = clk_pd_gpu_notifier_call,
+};
+
+
+static int early_suspend_notifier_call(struct notifier_block *self,
+ unsigned long action, void *data)
+{
+ struct fb_event *event = data;
+ int blank_mode = *((int *)event->data);
+ int ret;
+
+ mutex_lock(&switch_vdd_gpu_mutex);
+ if (action == FB_EARLY_EVENT_BLANK) {
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ early_suspend = 0;
+ if (pd_gpu_off) {
+ if (!regulator_is_enabled(vdd_gpu_regulator))
+ ret = regulator_enable(
+ vdd_gpu_regulator);
+ }
+ break;
+ default:
+ break;
+ }
+ } else if (action == FB_EVENT_BLANK) {
+ switch (blank_mode) {
+ case FB_BLANK_POWERDOWN:
+ early_suspend = 1;
+ if (pd_gpu_off) {
+ if (regulator_is_enabled(vdd_gpu_regulator))
+ ret = regulator_disable(
+ vdd_gpu_regulator);
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+ mutex_unlock(&switch_vdd_gpu_mutex);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block early_suspend_notifier = {
+ .notifier_call = early_suspend_notifier_call,
+};
+
+
static void dvfs_volt_up_delay(struct vd_node *vd, int new_volt, int old_volt)
{
int u_time;
queue_delayed_work_on(0, dvfs_wq, &dvfs_temp_limit_work, 0*HZ);
}
+ vdd_gpu_regulator = dvfs_get_regulator("vdd_gpu");
+ if (!IS_ERR_OR_NULL(vdd_gpu_regulator)) {
+ struct clk *clk = clk_get(NULL, "pd_gpu");
+
+ if (clk)
+ rk_clk_pd_notifier_register(clk, &clk_pd_gpu_notifier);
+
+ fb_register_client(&early_suspend_notifier);
+ register_reboot_notifier(&vdd_gpu_reboot_notifier);
+ }
+
return ret;
}
#include <asm/cpu.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>
+#include <asm/system_misc.h>
#include "../../../drivers/clk/rockchip/clk-pd.h"
extern void dvfs_disable_temp_limit(void);
static int cpufreq_init_cpu0(struct cpufreq_policy *policy)
{
unsigned int i;
+ int ret;
+ struct regulator *vdd_gpu_regulator;
+
gpu_is_mali400 = cpu_is_rk3188();
clk_gpu_dvfs_node = clk_get_dvfs_node("clk_gpu");
if (clk_gpu_dvfs_node){
clk_enable_dvfs(clk_gpu_dvfs_node);
+ vdd_gpu_regulator = dvfs_get_regulator("vdd_gpu");
+ if (!IS_ERR_OR_NULL(vdd_gpu_regulator)) {
+ if (!regulator_is_enabled(vdd_gpu_regulator)) {
+ ret = regulator_enable(vdd_gpu_regulator);
+ arm_pm_restart('h', NULL);
+ }
+ /* make sure vdd_gpu_regulator is in use,
+ so it will not be disable by regulator_init_complete*/
+ ret = regulator_enable(vdd_gpu_regulator);
+ if (ret != 0)
+ arm_pm_restart('h', NULL);
+ }
if (gpu_is_mali400)
dvfs_clk_enable_limit(clk_gpu_dvfs_node, 133000000, 600000000);
}