aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugen Mandrenko <ievgen.mandrenko@ti.com>2012-03-22 11:37:52 +0200
committerZiyann <jaraidaniel@gmail.com>2014-10-01 12:57:36 +0200
commitf3d626caeb80f1698f4878bb4e5414aa0c582f4c (patch)
tree58f99451f9c63d3fc88eaa99657c4c7052e18d31
parent067fc30aae22ba09f9ad369f756f398cacdabdff (diff)
downloadkernel_samsung_tuna-f3d626caeb80f1698f4878bb4e5414aa0c582f4c.zip
kernel_samsung_tuna-f3d626caeb80f1698f4878bb4e5414aa0c582f4c.tar.gz
kernel_samsung_tuna-f3d626caeb80f1698f4878bb4e5414aa0c582f4c.tar.bz2
Thermal Governor: Added duty cycle governor
Add the OMAP duty cycle governor to the thermal framework. This component will impose the policy for the PCB temp sensor in case ondie sensor is absent. Change-Id: I05f7272445567cf74be6f0932d7024f0d9d34dee Signed-off-by: Eugen Mandrenko <ievgen.mandrenko@ti.com> Conflicts: arch/arm/mach-omap2/board-4430sdp.c
-rw-r--r--drivers/staging/thermal_framework/governor/Makefile1
-rw-r--r--drivers/staging/thermal_framework/governor/omap4_duty_cycle_governor.c199
-rw-r--r--drivers/staging/thermal_framework/omap4_duty_cycle.c45
-rw-r--r--include/linux/omap4_duty_cycle_governor.h47
4 files changed, 290 insertions, 2 deletions
diff --git a/drivers/staging/thermal_framework/governor/Makefile b/drivers/staging/thermal_framework/governor/Makefile
index 0b5eff7..8ba37ee 100644
--- a/drivers/staging/thermal_framework/governor/Makefile
+++ b/drivers/staging/thermal_framework/governor/Makefile
@@ -2,3 +2,4 @@
# Makefile for Thermal governor drivers.
#
obj-$(CONFIG_OMAP_DIE_GOVERNOR) += omap_die_governor.o
+obj-$(CONFIG_OMAP4_DUTY_CYCLE) += omap4_duty_cycle_governor.o
diff --git a/drivers/staging/thermal_framework/governor/omap4_duty_cycle_governor.c b/drivers/staging/thermal_framework/governor/omap4_duty_cycle_governor.c
new file mode 100644
index 0000000..c1d4edb
--- /dev/null
+++ b/drivers/staging/thermal_framework/governor/omap4_duty_cycle_governor.c
@@ -0,0 +1,199 @@
+/*
+ * Duty cycle governor
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Eugene Mandrenko <Ievgen.mandrenko@ti.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that 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.
+ *
+*/
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/omap4_duty_cycle_governor.h>
+#include <plat/omap_device.h>
+
+#define NORMAL_TEMP_MONITORING_RATE 1000
+#define NORMAL_MONITORING_RATE 10000
+#define DEFAULT_TEMPERATURE 65000
+#define TEMP_THRESHOLD 1
+#define INIT_SECTION -1
+
+struct duty_governor {
+ struct pcb_sens *tpcb;
+ struct duty_cycle *tduty;
+ struct pcb_section *tpcb_sections;
+ int period;
+ int previous_temp;
+ int curr_pcb_temp;
+ int previous_pcb_temp;
+ int working_section;
+ int npcb_sections;
+ struct delayed_work duty_cycle_governor_work;
+};
+
+static struct duty_governor *t_governor;
+static struct pcb_section *pcb_sections;
+static int pcb_sections_size;
+
+void omap4_duty_pcb_section_reg(struct pcb_section *pcb_sect, int sect_size)
+{
+ pcb_sections = pcb_sect;
+ pcb_sections_size = sect_size;
+}
+
+static void omap4_duty_schedule(struct duty_governor *t_gov)
+{
+ if (!IS_ERR_OR_NULL(t_gov) &&
+ !IS_ERR_OR_NULL(t_gov->tpcb) &&
+ !IS_ERR_OR_NULL(t_gov->tduty))
+ schedule_delayed_work(&t_governor->duty_cycle_governor_work,
+ msecs_to_jiffies(0));
+}
+
+int omap4_duty_pcb_register(struct pcb_sens *tpcb)
+{
+ if (!IS_ERR_OR_NULL(t_governor)) {
+ if (t_governor->tpcb == NULL) {
+ t_governor->tpcb = tpcb;
+ t_governor->period = NORMAL_TEMP_MONITORING_RATE;
+ } else {
+ pr_err("%s:dublicate of pcb registration\n", __func__);
+
+ return -EBUSY;
+ }
+ }
+ omap4_duty_schedule(t_governor);
+
+ return 0;
+}
+static bool is_treshold(struct duty_governor *tgov)
+{
+ int delta;
+
+ delta = abs(tgov->previous_pcb_temp - tgov->curr_pcb_temp);
+
+ if (delta > TEMP_THRESHOLD)
+ return true;
+
+ return false;
+}
+
+static int omap4_duty_apply_constraint(struct duty_governor *tgov,
+ int sect_num)
+{
+ struct pcb_section *t_pcb_sections = &tgov->tpcb_sections[sect_num];
+ struct duty_cycle_params *tduty_params = &t_pcb_sections->tduty_params;
+ int dc_enabled = t_pcb_sections->duty_cycle_enabled;
+ struct duty_cycle *t_duty = tgov->tduty;
+ int ret = true;
+
+ if (tgov->working_section != sect_num) {
+ ret = tgov->tduty->enable(false, false);
+
+ if (ret)
+ return ret;
+
+ if (dc_enabled) {
+ if (t_duty->update_params(tduty_params))
+ return ret;
+
+ tgov->tduty->enable(dc_enabled, true);
+ }
+ tgov->working_section = sect_num;
+ }
+
+ return ret;
+}
+
+static void omap4_duty_update(struct duty_governor *tgov)
+{
+ int sect_num;
+
+ for (sect_num = 0; sect_num < tgov->npcb_sections; sect_num++)
+ if (tgov->tpcb_sections[sect_num].pcb_temp_level >
+ tgov->curr_pcb_temp)
+ break;
+ if (sect_num >= tgov->npcb_sections)
+ sect_num = tgov->npcb_sections - 1;
+
+ if (omap4_duty_apply_constraint(tgov, sect_num))
+ tgov->previous_pcb_temp = tgov->curr_pcb_temp;
+}
+
+static void omap4_duty_governor_delayed_work_fn(struct work_struct *work)
+{
+ if (!IS_ERR_OR_NULL(t_governor->tpcb)) {
+ if (!IS_ERR_OR_NULL(t_governor->tpcb->update_temp)) {
+ t_governor->curr_pcb_temp =
+ t_governor->tpcb->update_temp();
+ if (is_treshold(t_governor))
+ omap4_duty_update(t_governor);
+ } else {
+ pr_err("%s:update_temp() isn't defined\n", __func__);
+ }
+ }
+ schedule_delayed_work(&t_governor->duty_cycle_governor_work,
+ msecs_to_jiffies(t_governor->period));
+}
+
+int omap4_duty_cycle_register(struct duty_cycle *tduty)
+{
+ if (!IS_ERR_OR_NULL(t_governor)) {
+ if (t_governor->tduty == NULL) {
+ t_governor->tduty = tduty;
+ } else {
+ pr_err("%s:dublicate of duty cycle registration\n",
+ __func__);
+
+ return -EBUSY;
+ }
+ }
+ omap4_duty_schedule(t_governor);
+
+ return 0;
+}
+
+static int __init omap4_duty_governor_init(void)
+{
+ if (!cpu_is_omap443x())
+ return 0;
+
+ t_governor = kzalloc(sizeof(struct duty_governor), GFP_KERNEL);
+ if (IS_ERR_OR_NULL(t_governor)) {
+ pr_err("%s:Cannot allocate memory\n", __func__);
+
+ return -ENOMEM;
+ }
+ t_governor->period = NORMAL_MONITORING_RATE;
+ t_governor->previous_temp = DEFAULT_TEMPERATURE;
+ t_governor->tpcb_sections = pcb_sections;
+ t_governor->npcb_sections = pcb_sections_size;
+ t_governor->working_section = INIT_SECTION;
+ INIT_DELAYED_WORK(&t_governor->duty_cycle_governor_work,
+ omap4_duty_governor_delayed_work_fn);
+
+ return 0;
+}
+
+static void __exit omap4_duty_governor_exit(void)
+{
+ cancel_delayed_work_sync(&t_governor->duty_cycle_governor_work);
+ kfree(t_governor);
+}
+
+early_initcall(omap4_duty_governor_init);
+module_exit(omap4_duty_governor_exit);
+
+MODULE_AUTHOR("Euvgen Mandrenko <ievgen.mandrenko@ti.com>");
+MODULE_DESCRIPTION("OMAP on-die thermal governor");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/staging/thermal_framework/omap4_duty_cycle.c b/drivers/staging/thermal_framework/omap4_duty_cycle.c
index cf81548..896ec5c 100644
--- a/drivers/staging/thermal_framework/omap4_duty_cycle.c
+++ b/drivers/staging/thermal_framework/omap4_duty_cycle.c
@@ -30,6 +30,7 @@
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
+#include <linux/omap4_duty_cycle_governor.h>
#include <plat/omap_device.h>
@@ -62,6 +63,7 @@ static bool enabled;
static bool saved_hotplug_enabled;
static int heating_budget;
static unsigned long t_heating_start;
+static struct duty_cycle *t_duty;
static struct workqueue_struct *duty_wq;
static struct delayed_work work_exit_cool;
@@ -556,6 +558,39 @@ static struct platform_driver omap4_duty_driver = {
.remove = __exit_p(omap4_duty_remove),
};
+static int update_params(struct duty_cycle_params *dc_params)
+{
+ int ret;
+
+ ret = mutex_lock_interruptible(&mutex_duty);
+ if (ret)
+ return ret;
+
+ cooling_rate = dc_params->cooling_rate;
+ nitro_rate = dc_params->nitro_rate;
+ nitro_percentage = dc_params->nitro_percentage;
+ nitro_interval = dc_params->nitro_interval;
+
+ mutex_unlock(&mutex_duty);
+
+ return 0;
+}
+
+static int __init omap4_duty_register(void)
+{
+ t_duty = kzalloc(sizeof(struct duty_cycle), GFP_KERNEL);
+ if (IS_ERR_OR_NULL(t_duty)) {
+ pr_err("%s:Cannot allocate memory\n", __func__);
+
+ return -ENOMEM;
+ }
+ t_duty->enable = omap4_duty_cycle_set_enabled;
+ t_duty->update_params = update_params;
+ omap4_duty_cycle_register(t_duty);
+
+ return 0;
+}
+
/* Module Interface */
static int __init omap4_duty_module_init(void)
{
@@ -604,12 +639,18 @@ static int __init omap4_duty_module_init(void)
goto unregister_hotplug;
}
- err = platform_driver_probe(&omap4_duty_driver, omap4_duty_probe);
+ err = omap4_duty_register();
if (err)
goto exit_pdevice;
+ err = platform_driver_probe(&omap4_duty_driver, omap4_duty_probe);
+ if (err)
+ goto unregister_duty;
+
return 0;
+unregister_duty:
+ kfree(t_duty);
exit_pdevice:
platform_device_unregister(omap4_duty_device);
unregister_hotplug:
@@ -637,7 +678,7 @@ static void __exit omap4_duty_module_exit(void)
cancel_work_sync(&work_enter_cool1);
cancel_work_sync(&work_cpu1_plugin);
cancel_work_sync(&work_cpu1_plugout);
-
+ kfree(t_duty);
destroy_workqueue(duty_wq);
pr_debug("%s Done\n", __func__);
diff --git a/include/linux/omap4_duty_cycle_governor.h b/include/linux/omap4_duty_cycle_governor.h
new file mode 100644
index 0000000..4e2baa9
--- /dev/null
+++ b/include/linux/omap4_duty_cycle_governor.h
@@ -0,0 +1,47 @@
+/*
+ * Duty sycle governor
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Eugene Mandrenko <ievgen.mandrenko@ti.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that 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.
+ *
+*/
+
+#ifndef __OMAP4_DUTY_CYCLE_GOVERNOR_H__
+#define __OMAP4_DUTY_CYCLE_GOVERNOR_H__
+
+struct pcb_sens {
+ int (*update_temp) (void);
+};
+
+struct duty_cycle_params {
+ u32 nitro_rate; /* the maximum OPP frequency */
+ u32 cooling_rate; /* the OPP used to cool off */
+ u32 nitro_interval; /* time interval to control the duty cycle */
+ u32 nitro_percentage; /* % out of nitro_interval to use max OPP */
+};
+
+struct pcb_section {
+ u32 pcb_temp_level;
+ u32 max_opp;
+ struct duty_cycle_params tduty_params;
+ bool duty_cycle_enabled;
+};
+
+struct duty_cycle {
+ int (*update_params)(struct duty_cycle_params *);
+ int (*enable)(bool val, bool update);
+};
+
+void omap4_duty_pcb_section_reg(struct pcb_section *pcb_sect, int sect_size);
+int omap4_duty_pcb_register(struct pcb_sens *tpcb);
+int omap4_duty_cycle_register(struct duty_cycle *tduty);
+#endif /*__OMAP4_DUTY_CYCLE_GOVERNOR_H__*/