783 lines
18 KiB
C
783 lines
18 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
#include <linux/version.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/dmi.h>
|
|
#include <linux/acpi.h>
|
|
#include <linux/thermal.h>
|
|
#include <linux/platform_device.h>
|
|
#include <mt-plat/aee.h>
|
|
#include <linux/types.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/seq_file.h>
|
|
#include "mt-plat/mtk_thermal_monitor.h"
|
|
#include "mach/mtk_thermal.h"
|
|
#include "mtk_thermal_timer.h"
|
|
#include <linux/uidgid.h>
|
|
#include <linux/slab.h>
|
|
|
|
#define RESERVED_TZS (21)
|
|
#define AUTO_GEN_COOLERS (1)
|
|
|
|
static kuid_t uid = KUIDT_INIT(0);
|
|
static kgid_t gid = KGIDT_INIT(1000);
|
|
|
|
struct thz_data {
|
|
struct thermal_zone_device *thz_dev;
|
|
char thz_name[20];
|
|
int trip_temp[10];
|
|
int trip_type[10]; /*ACTIVE, PASSIVE, HOT, and Critical*/
|
|
char bind[10][20];
|
|
int num_trip;
|
|
unsigned int interval; /* mseconds, 0 : no auto polling */
|
|
int kernelmode;
|
|
struct semaphore sem_mutex;
|
|
int isTimerCancelled;
|
|
};
|
|
|
|
static struct thz_data g_tsData[RESERVED_TZS];
|
|
|
|
#if AUTO_GEN_COOLERS
|
|
static int tztsAll_polling_interval = 1000; /* mseconds, 0 : no auto polling */
|
|
static int tztsAll_enable_switch; /* 1: switch on, 0: switch off */
|
|
struct cooler_data {
|
|
struct thermal_cooling_device *cooler_dev;
|
|
int state; /* 0: inactivated, 1: activated */
|
|
};
|
|
/* Our purpose is to make all tsX report their temperatures
|
|
* regularly without activating by a thermal policy,
|
|
* so we have to create the same amount of coolers and bind
|
|
* them together.
|
|
*/
|
|
static struct cooler_data g_coolerData[RESERVED_TZS];
|
|
#endif
|
|
|
|
static int tsallts_debug_log;
|
|
|
|
#define TSALLTS_TEMP_CRIT 120000 /* 120.000 degree Celsius */
|
|
|
|
#define tsallts_dprintk(fmt, args...) \
|
|
do { \
|
|
if (tsallts_debug_log) { \
|
|
pr_debug("[Thermal/TZ/CPUALL]" fmt, ##args);\
|
|
} \
|
|
} while (0)
|
|
|
|
#if AUTO_GEN_COOLERS
|
|
#define clnothings_dprintk(fmt, args...) \
|
|
do { \
|
|
if (tsallts_debug_log) { \
|
|
pr_debug("[Thermal/TZ/CLNOTHINGS]" fmt, ##args);\
|
|
} \
|
|
} while (0)
|
|
#endif
|
|
|
|
#define tsallts_printk(fmt, args...) \
|
|
pr_debug("[Thermal/TZ/CPUALL]" fmt, ##args)
|
|
|
|
static void tsX_register(int index);
|
|
static void tsX_unregister(int index);
|
|
|
|
static int tsallts_get_index(struct thermal_zone_device *thermal)
|
|
{
|
|
/* ex: tzts1, tzts2, ..., and tzts10 */
|
|
int index;
|
|
|
|
index = thermal->type[4] - '0';
|
|
|
|
if (thermal->type[5] != '\0')
|
|
index = index * 10 + thermal->type[5] - '0';
|
|
|
|
index = index - 1;
|
|
|
|
if (index < 0 || index >= TS_ENUM_MAX)
|
|
index = 0;
|
|
|
|
return index;
|
|
}
|
|
|
|
static int tsallts_get_temp(struct thermal_zone_device *thermal, int *t)
|
|
{
|
|
int curr_temp, index;
|
|
|
|
index = tsallts_get_index(thermal);
|
|
curr_temp = get_immediate_tsX[index]();
|
|
tsallts_dprintk("%s ts%d =%d\n", __func__, index, curr_temp);
|
|
|
|
*t = curr_temp;
|
|
|
|
#if AUTO_GEN_COOLERS
|
|
thermal->polling_delay = g_tsData[index].interval;
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static int tsallts_bind(
|
|
struct thermal_zone_device *thermal, struct thermal_cooling_device *cdev)
|
|
{
|
|
int table_val = -1, index, i;
|
|
|
|
index = tsallts_get_index(thermal);
|
|
tsallts_dprintk("[%s ts%d]\n", __func__, index);
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
if (!strcmp(cdev->type, g_tsData[index].bind[i])) {
|
|
table_val = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (table_val == -1)
|
|
return 0;
|
|
|
|
tsallts_dprintk("[%s ts %d] %s\n", __func__, index, cdev->type);
|
|
|
|
if (mtk_thermal_zone_bind_cooling_device(thermal, table_val, cdev)) {
|
|
tsallts_dprintk(
|
|
"[%s ts %d] error binding cooling dev\n", __func__,
|
|
index);
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
tsallts_dprintk("[%s ts %d] binding OK, %d\n", __func__, index,
|
|
table_val);
|
|
return 0;
|
|
}
|
|
|
|
static int tsallts_unbind(
|
|
struct thermal_zone_device *thermal, struct thermal_cooling_device *cdev)
|
|
{
|
|
int table_val = -1, index, i;
|
|
|
|
index = tsallts_get_index(thermal);
|
|
tsallts_dprintk("[%s ts%d]\n", __func__, index);
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
if (!strcmp(cdev->type, g_tsData[index].bind[i])) {
|
|
table_val = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (table_val == -1)
|
|
return 0;
|
|
|
|
tsallts_dprintk("[%s ts %d] %s\n", __func__, index, cdev->type);
|
|
|
|
if (thermal_zone_unbind_cooling_device(thermal, table_val, cdev)) {
|
|
tsallts_dprintk(
|
|
"[%s ts %d] error unbinding cooling dev\n", __func__,
|
|
index);
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
tsallts_dprintk("[%s ts %d] unbinding OK\n", __func__, index);
|
|
return 0;
|
|
}
|
|
|
|
static int tsallts_get_mode(
|
|
struct thermal_zone_device *thermal, enum thermal_device_mode *mode)
|
|
{
|
|
int index;
|
|
|
|
index = tsallts_get_index(thermal);
|
|
|
|
*mode = (g_tsData[index].kernelmode) ?
|
|
THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED;
|
|
return 0;
|
|
}
|
|
|
|
static int tsallts_set_mode(
|
|
struct thermal_zone_device *thermal, enum thermal_device_mode mode)
|
|
{
|
|
int index;
|
|
|
|
index = tsallts_get_index(thermal);
|
|
|
|
g_tsData[index].kernelmode = mode;
|
|
return 0;
|
|
}
|
|
|
|
static int tsallts_get_trip_type(struct thermal_zone_device *thermal, int trip,
|
|
enum thermal_trip_type *type)
|
|
{
|
|
int index;
|
|
|
|
index = tsallts_get_index(thermal);
|
|
*type = g_tsData[index].trip_type[trip];
|
|
return 0;
|
|
}
|
|
|
|
static int tsallts_get_trip_temp(
|
|
struct thermal_zone_device *thermal, int trip, int *temp)
|
|
{
|
|
int index;
|
|
|
|
index = tsallts_get_index(thermal);
|
|
*temp = g_tsData[index].trip_temp[trip];
|
|
return 0;
|
|
}
|
|
|
|
static int tsallts_get_crit_temp(
|
|
struct thermal_zone_device *thermal, int *temperature)
|
|
{
|
|
*temperature = TSALLTS_TEMP_CRIT;
|
|
return 0;
|
|
}
|
|
|
|
static void mtkts_allts_cancel_timer(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < TS_ENUM_MAX; i++) {
|
|
if (down_trylock(&g_tsData[i].sem_mutex))
|
|
continue;
|
|
|
|
if (g_tsData[i].thz_dev) {
|
|
cancel_delayed_work(&(g_tsData[i].thz_dev->poll_queue));
|
|
g_tsData[i].isTimerCancelled = 1;
|
|
}
|
|
up(&g_tsData[i].sem_mutex);
|
|
}
|
|
}
|
|
|
|
|
|
static void mtkts_allts_start_timer(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < TS_ENUM_MAX; i++) {
|
|
if (!g_tsData[i].isTimerCancelled)
|
|
continue;
|
|
|
|
|
|
if (down_trylock(&g_tsData[i].sem_mutex))
|
|
continue;
|
|
|
|
if (g_tsData[i].thz_dev != NULL && g_tsData[i].interval != 0) {
|
|
mod_delayed_work(system_freezable_power_efficient_wq,
|
|
&(g_tsData[i].thz_dev->poll_queue),
|
|
round_jiffies(msecs_to_jiffies(1000)));
|
|
g_tsData[i].isTimerCancelled = 0;
|
|
}
|
|
up(&g_tsData[i].sem_mutex);
|
|
/*1000 = 1sec */
|
|
}
|
|
}
|
|
|
|
/* bind callback functions to thermalzone */
|
|
static struct thermal_zone_device_ops tsallts_dev_ops = {
|
|
.bind = tsallts_bind,
|
|
.unbind = tsallts_unbind,
|
|
.get_temp = tsallts_get_temp,
|
|
.get_mode = tsallts_get_mode,
|
|
.set_mode = tsallts_set_mode,
|
|
.get_trip_type = tsallts_get_trip_type,
|
|
.get_trip_temp = tsallts_get_trip_temp,
|
|
.get_crit_temp = tsallts_get_crit_temp,
|
|
};
|
|
|
|
#define PROC_FOPS_RW(num) \
|
|
static int tz ## num ## _proc_read(struct seq_file *m, void *v) \
|
|
{ \
|
|
int i; \
|
|
\
|
|
for (i = 0; i < 10; i++) { \
|
|
seq_printf(m, "Trip_%d_temp=%d ", i, \
|
|
g_tsData[(num - 1)].trip_temp[i]); \
|
|
if ((i + 1) % 5 == 0) \
|
|
seq_printf(m, "\n"); \
|
|
} \
|
|
\
|
|
for (i = 0; i < 10; i++) { \
|
|
seq_printf(m, "Trip_type%d=%d ", i, \
|
|
g_tsData[(num - 1)].trip_type[i]); \
|
|
if ((i + 1) % 5 == 0) \
|
|
seq_printf(m, "\n"); \
|
|
} \
|
|
\
|
|
for (i = 0; i < 10; i++) { \
|
|
seq_printf(m, "Cool_dev%d=%s ", i, \
|
|
g_tsData[(num - 1)].bind[i]); \
|
|
if ((i + 1) % 5 == 0) \
|
|
seq_printf(m, "\n"); \
|
|
} \
|
|
seq_printf(m, "Time_ms=%d\n", g_tsData[(num - 1)].interval); \
|
|
return 0; \
|
|
} \
|
|
\
|
|
static ssize_t tz ## num ## _proc_write( \
|
|
struct file *file, const char __user *buffer, size_t count, \
|
|
loff_t *data) \
|
|
{ \
|
|
int len = 0, i, j; \
|
|
struct tempD { \
|
|
int num_trip; \
|
|
int time_msec; \
|
|
int trip[10]; \
|
|
int t_type[10]; \
|
|
char bind[10][20]; \
|
|
char desc[512]; \
|
|
}; \
|
|
\
|
|
struct tempD *pTempD = kmalloc(sizeof(*pTempD), GFP_KERNEL); \
|
|
\
|
|
tsallts_printk("[tsallts_write_"__stringify(num)"]\n"); \
|
|
\
|
|
if (pTempD == NULL) \
|
|
return -ENOMEM; \
|
|
\
|
|
len = (count < (sizeof(pTempD->desc) - 1)) ? \
|
|
count : (sizeof(pTempD->desc) - 1); \
|
|
if (copy_from_user(pTempD->desc, buffer, len)) { \
|
|
kfree(pTempD); \
|
|
return 0; \
|
|
} \
|
|
\
|
|
pTempD->desc[len] = '\0';\
|
|
\
|
|
i = sscanf(pTempD->desc, \
|
|
"%d %d %d %19s %d %d %19s %d %d %19s %d %d %19s %d %d %19s %d %d" \
|
|
"%19s %d %d %19s %d %d %19s %d %d %19s %d %d %19s %d", \
|
|
&pTempD->num_trip, \
|
|
&pTempD->trip[0], &pTempD->t_type[0], pTempD->bind[0], \
|
|
&pTempD->trip[1], &pTempD->t_type[1], pTempD->bind[1], \
|
|
&pTempD->trip[2], &pTempD->t_type[2], pTempD->bind[2], \
|
|
&pTempD->trip[3], &pTempD->t_type[3], pTempD->bind[3], \
|
|
&pTempD->trip[4], &pTempD->t_type[4], pTempD->bind[4], \
|
|
&pTempD->trip[5], &pTempD->t_type[5], pTempD->bind[5], \
|
|
&pTempD->trip[6], &pTempD->t_type[6], pTempD->bind[6], \
|
|
&pTempD->trip[7], &pTempD->t_type[7], pTempD->bind[7], \
|
|
&pTempD->trip[8], &pTempD->t_type[8], pTempD->bind[8], \
|
|
&pTempD->trip[9], &pTempD->t_type[9], pTempD->bind[9], \
|
|
&pTempD->time_msec); \
|
|
\
|
|
if (i == 32) { \
|
|
down(&g_tsData[(num - 1)].sem_mutex); \
|
|
tsallts_dprintk("[tsallts_write_"__stringify(num) \
|
|
"]thermal unregister\n"); \
|
|
\
|
|
if (g_tsData[(num - 1)].thz_dev) { \
|
|
mtk_thermal_zone_device_unregister( \
|
|
g_tsData[(num - 1)].thz_dev); \
|
|
g_tsData[(num - 1)].thz_dev = NULL; \
|
|
} \
|
|
\
|
|
if (pTempD->num_trip < 0 || pTempD->num_trip > 10) { \
|
|
tsallts_dprintk( \
|
|
"[tsallts_write1] bad argument\n"); \
|
|
kfree(pTempD); \
|
|
up(&g_tsData[(num - 1)].sem_mutex); \
|
|
return -EINVAL; \
|
|
} \
|
|
\
|
|
g_tsData[(num - 1)].num_trip = pTempD->num_trip; \
|
|
\
|
|
for (i = 0; i < g_tsData[(num - 1)].num_trip; i++) { \
|
|
g_tsData[(num - 1)].trip_type[i] = \
|
|
pTempD->t_type[i]; \
|
|
g_tsData[(num - 1)].trip_temp[i] = \
|
|
pTempD->trip[i]; \
|
|
} \
|
|
\
|
|
for (i = 0; i < 10; i++) { \
|
|
g_tsData[(num - 1)].bind[i][0] = '\0'; \
|
|
for (j = 0; j < 20; j++) \
|
|
g_tsData[(num - 1)].bind[i][j] = \
|
|
pTempD->bind[i][j]; \
|
|
} \
|
|
\
|
|
g_tsData[(num - 1)].interval = pTempD->time_msec; \
|
|
\
|
|
if (tsallts_debug_log) { \
|
|
for (i = 0; i < 10; i++) { \
|
|
tsallts_printk("Trip_%d_temp=%d ", i, \
|
|
g_tsData[(num - 1)].trip_temp[i]); \
|
|
if ((i + 1) % 5 == 0) \
|
|
tsallts_printk("\n"); \
|
|
} \
|
|
\
|
|
for (i = 0; i < 10; i++) { \
|
|
tsallts_printk("Trip_type%d=%d ", i, \
|
|
g_tsData[(num - 1)].trip_type[i]); \
|
|
if ((i + 1) % 5 == 0) \
|
|
tsallts_printk("\n"); \
|
|
} \
|
|
\
|
|
for (i = 0; i < 10; i++) { \
|
|
tsallts_printk("Cool_dev%d=%s ", i, \
|
|
g_tsData[(num - 1)].bind[i]); \
|
|
if ((i + 1) % 5 == 0) \
|
|
tsallts_printk("\n"); \
|
|
} \
|
|
tsallts_printk("Time_ms=%d\n", \
|
|
g_tsData[(num - 1)].interval); \
|
|
} \
|
|
\
|
|
tsallts_dprintk("[tsallts_write_"__stringify(num) \
|
|
"] thermal register\n"); \
|
|
if (g_tsData[(num - 1)].thz_dev == NULL) { \
|
|
g_tsData[(num - 1)].thz_dev = \
|
|
mtk_thermal_zone_device_register( \
|
|
g_tsData[(num - 1)].thz_name,\
|
|
g_tsData[(num - 1)].num_trip, \
|
|
NULL, &tsallts_dev_ops, 0, \
|
|
0, 0, g_tsData[(num - 1)].interval); \
|
|
} \
|
|
\
|
|
up(&g_tsData[(num - 1)].sem_mutex); \
|
|
kfree(pTempD); \
|
|
return count; \
|
|
} \
|
|
\
|
|
tsallts_dprintk("[tsallts_write_"__stringify(num) \
|
|
"] bad argument\n"); \
|
|
kfree(pTempD); \
|
|
return -EINVAL; \
|
|
} \
|
|
static int tz ## num ## _proc_open( \
|
|
struct inode *inode, struct file *file) \
|
|
{ \
|
|
return single_open(file, tz ## num ## _proc_read, \
|
|
PDE_DATA(inode)); \
|
|
} \
|
|
static const struct file_operations tz ## num ## _proc_fops = { \
|
|
.owner = THIS_MODULE, \
|
|
.open = tz ## num ## _proc_open, \
|
|
.read = seq_read, \
|
|
.llseek = seq_lseek, \
|
|
.release = single_release, \
|
|
.write = tz ## num ## _proc_write, \
|
|
}
|
|
|
|
#define FOPS(num) (&tz ## num ## _proc_fops)
|
|
|
|
PROC_FOPS_RW(1);
|
|
PROC_FOPS_RW(2);
|
|
PROC_FOPS_RW(3);
|
|
PROC_FOPS_RW(4);
|
|
PROC_FOPS_RW(5);
|
|
PROC_FOPS_RW(6);
|
|
PROC_FOPS_RW(7);
|
|
PROC_FOPS_RW(8);
|
|
PROC_FOPS_RW(9);
|
|
PROC_FOPS_RW(10);
|
|
PROC_FOPS_RW(11);
|
|
PROC_FOPS_RW(12);
|
|
PROC_FOPS_RW(13);
|
|
PROC_FOPS_RW(14);
|
|
PROC_FOPS_RW(15);
|
|
PROC_FOPS_RW(16);
|
|
PROC_FOPS_RW(17);
|
|
PROC_FOPS_RW(18);
|
|
PROC_FOPS_RW(19);
|
|
PROC_FOPS_RW(20);
|
|
PROC_FOPS_RW(21);
|
|
|
|
static const struct file_operations *thz_fops[RESERVED_TZS] = {
|
|
FOPS(1),
|
|
FOPS(2),
|
|
FOPS(3),
|
|
FOPS(4),
|
|
FOPS(5),
|
|
FOPS(6),
|
|
FOPS(7),
|
|
FOPS(8),
|
|
FOPS(9),
|
|
FOPS(10),
|
|
FOPS(11),
|
|
FOPS(12),
|
|
FOPS(13),
|
|
FOPS(14),
|
|
FOPS(15),
|
|
FOPS(16),
|
|
FOPS(17),
|
|
FOPS(18),
|
|
FOPS(19),
|
|
FOPS(20),
|
|
FOPS(21)
|
|
};
|
|
|
|
#if AUTO_GEN_COOLERS
|
|
static int thz_enable_read(struct seq_file *m, void *v)
|
|
{
|
|
seq_puts(m, "Current status:\n");
|
|
seq_printf(m, "tztsAll_enable_switch: %d\n", tztsAll_enable_switch);
|
|
seq_printf(m, "tztsAll_polling_interval: %d ms\n\n",
|
|
tztsAll_polling_interval);
|
|
seq_puts(m, "[Note]\n");
|
|
seq_puts(m, "1. Enable tztsAll\n");
|
|
seq_puts(m, " echo switch 1 > /proc/driver/thermal/tztsAll_enable\n");
|
|
seq_puts(m, "2. Disable tztsAll\n");
|
|
seq_puts(m, " echo switch 0 > /proc/driver/thermal/tztsAll_enable\n");
|
|
seq_puts(m, "3. Change polling interval\n");
|
|
seq_puts(m, " The polling interval is in millisecond\n");
|
|
seq_puts(m, " For example: the polling interval is 1s\n");
|
|
seq_puts(m, " echo polling_interval 1000 > /proc/driver/thermal/tztsAll_enable\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t thz_enable_write
|
|
(struct file *file, const char __user *buffer, size_t count,
|
|
loff_t *data)
|
|
{
|
|
char desc[32], arg_name[32];
|
|
int i, len = 0, arg_val;
|
|
|
|
|
|
len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
|
|
if (copy_from_user(desc, buffer, len))
|
|
return 0;
|
|
|
|
desc[len] = '\0';
|
|
|
|
if (sscanf(desc, "%31s %d", arg_name, &arg_val) == 2) {
|
|
if ((strncmp(arg_name, "switch", 6) == 0)) {
|
|
if (arg_val != 0 && arg_val != 1)
|
|
goto THZ_ENABLE_WRITE_ERROR;
|
|
|
|
tztsAll_enable_switch = arg_val;
|
|
for (i = 0; i < TS_ENUM_MAX; i++) {
|
|
if (tztsAll_enable_switch == 1) {
|
|
down(&g_tsData[i].sem_mutex);
|
|
g_tsData[i].interval =
|
|
tztsAll_polling_interval;
|
|
tsX_unregister(i);
|
|
tsX_register(i);
|
|
up(&g_tsData[i].sem_mutex);
|
|
} else {
|
|
g_tsData[i].interval = 0;
|
|
}
|
|
}
|
|
} else if ((strncmp(arg_name, "polling_interval", 16) == 0)) {
|
|
tztsAll_polling_interval = arg_val;
|
|
for (i = 0; i < TS_ENUM_MAX; i++)
|
|
g_tsData[i].interval = arg_val;
|
|
} else {
|
|
goto THZ_ENABLE_WRITE_ERROR;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
THZ_ENABLE_WRITE_ERROR:
|
|
tsallts_printk("%s bad argument: %s\n", __func__, desc);
|
|
return -EINVAL;
|
|
}
|
|
|
|
static int thz_enable_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, thz_enable_read, NULL);
|
|
}
|
|
static const struct file_operations thz_enable_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = thz_enable_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.write = thz_enable_write,
|
|
.release = single_release,
|
|
};
|
|
static int clnothings_get_index(struct thermal_cooling_device *cdev)
|
|
{
|
|
/* ex: clnothing1, clnothing2, ..., and clnothing10 */
|
|
int index;
|
|
|
|
index = cdev->type[9] - '0';
|
|
|
|
if (cdev->type[10] != '\0')
|
|
index = index * 10 + cdev->type[10] - '0';
|
|
|
|
index = index - 1;
|
|
|
|
if (index < 0 || index >= TS_ENUM_MAX)
|
|
index = 0;
|
|
|
|
return index;
|
|
}
|
|
|
|
static int clnothings_get_max_state
|
|
(struct thermal_cooling_device *cdev, unsigned long *state)
|
|
{
|
|
*state = 1;
|
|
return 0;
|
|
}
|
|
|
|
static int clnothings_get_cur_state
|
|
(struct thermal_cooling_device *cdev, unsigned long *state)
|
|
{
|
|
int i;
|
|
|
|
i = clnothings_get_index(cdev);
|
|
*state = g_coolerData[i].state;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int clnothings_set_cur_state
|
|
(struct thermal_cooling_device *cdev, unsigned long state)
|
|
{
|
|
int i;
|
|
|
|
i = clnothings_get_index(cdev);
|
|
g_coolerData[i].state = state;
|
|
|
|
if (state == 1) {
|
|
/* Do nothing */
|
|
clnothings_dprintk("%s triggered\n", cdev->type);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
static struct thermal_cooling_device_ops clnothings_ops = {
|
|
.get_max_state = clnothings_get_max_state,
|
|
.get_cur_state = clnothings_get_cur_state,
|
|
.set_cur_state = clnothings_set_cur_state,
|
|
};
|
|
#endif
|
|
|
|
static int __init tsallts_init(void)
|
|
{
|
|
int i, j;
|
|
struct proc_dir_entry *entry = NULL;
|
|
struct proc_dir_entry *tsallts_dir = NULL;
|
|
|
|
#if AUTO_GEN_COOLERS
|
|
char temp[20] = { 0 };
|
|
#endif
|
|
|
|
tsallts_dprintk("[%s]\n", __func__);
|
|
|
|
if (TS_ENUM_MAX > RESERVED_TZS) {
|
|
tsallts_printk("Didn't reserve enough memory for all tsX\n");
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0; i < RESERVED_TZS; i++) {
|
|
g_tsData[i].thz_dev = NULL;
|
|
g_tsData[i].thz_name[0] = '\0';
|
|
for (j = 0; j < 10; j++) {
|
|
g_tsData[i].trip_temp[j] = 0;
|
|
g_tsData[i].trip_type[j] = 0;
|
|
g_tsData[i].bind[j][0] = '\0';
|
|
}
|
|
g_tsData[i].num_trip = 0;
|
|
g_tsData[i].interval = 0;
|
|
g_tsData[i].kernelmode = 0;
|
|
sema_init(&g_tsData[i].sem_mutex, 1);
|
|
g_tsData[i].isTimerCancelled = 0;
|
|
}
|
|
|
|
#if AUTO_GEN_COOLERS
|
|
for (i = 0; i < TS_ENUM_MAX; i++) {
|
|
g_coolerData[i].cooler_dev = NULL;
|
|
g_coolerData[i].state = 0;
|
|
|
|
sprintf(temp, "clnothing%d", (i + 1));
|
|
g_coolerData[i].cooler_dev =
|
|
mtk_thermal_cooling_device_register(
|
|
temp, (void *)&g_coolerData[i].state,
|
|
&clnothings_ops);
|
|
}
|
|
#endif
|
|
|
|
tsallts_dir = mtk_thermal_get_proc_drv_therm_dir_entry();
|
|
|
|
if (!tsallts_dir) {
|
|
tsallts_dprintk("[%s]: mkdir /proc/driver/thermal failed\n",
|
|
__func__);
|
|
} else {
|
|
for (i = 0; i < TS_ENUM_MAX; i++)
|
|
sprintf(g_tsData[i].thz_name, "tzts%d", (i + 1));
|
|
|
|
for (i = 0; i < TS_ENUM_MAX; i++) {
|
|
entry = proc_create(g_tsData[i].thz_name, 0664,
|
|
tsallts_dir, thz_fops[i]);
|
|
if (entry)
|
|
proc_set_user(entry, uid, gid);
|
|
}
|
|
|
|
#if AUTO_GEN_COOLERS
|
|
entry = proc_create("tztsAll_enable", 0664,
|
|
tsallts_dir, &thz_enable_fops);
|
|
if (entry)
|
|
proc_set_user(entry, uid, gid);
|
|
#endif
|
|
}
|
|
|
|
#if AUTO_GEN_COOLERS
|
|
for (i = 0; i < TS_ENUM_MAX; i++) {
|
|
down(&g_tsData[i].sem_mutex);
|
|
tsX_unregister(i);
|
|
|
|
g_tsData[i].num_trip = 1;
|
|
g_tsData[i].trip_type[0] = 0;
|
|
g_tsData[i].trip_temp[0] = 150000;
|
|
sprintf(g_tsData[i].bind[0], "clnothing%d", (i + 1));
|
|
|
|
if (tztsAll_enable_switch == 1) {
|
|
g_tsData[i].interval = tztsAll_polling_interval;
|
|
tsX_register(i);
|
|
} else {
|
|
g_tsData[i].interval = 0;
|
|
}
|
|
|
|
up(&g_tsData[i].sem_mutex);
|
|
}
|
|
#endif
|
|
|
|
mtkTTimer_register("tztsAll", mtkts_allts_start_timer,
|
|
mtkts_allts_cancel_timer);
|
|
return 0;
|
|
}
|
|
|
|
static void tsX_register(int index)
|
|
{
|
|
if (g_tsData[index].thz_dev == NULL) {
|
|
g_tsData[index].thz_dev = mtk_thermal_zone_device_register(
|
|
g_tsData[index].thz_name,
|
|
g_tsData[index].num_trip,
|
|
NULL, &tsallts_dev_ops, 0,
|
|
0, 0, g_tsData[index].interval);
|
|
}
|
|
}
|
|
|
|
static void tsX_unregister(int index)
|
|
{
|
|
if (g_tsData[index].thz_dev != NULL) {
|
|
mtk_thermal_zone_device_unregister(
|
|
g_tsData[index].thz_dev);
|
|
g_tsData[index].thz_dev = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
static void tsallts_unregister_thermal(void)
|
|
{
|
|
int i;
|
|
|
|
tsallts_dprintk("[%s]\n", __func__);
|
|
|
|
for (i = 0; i < RESERVED_TZS; i++) {
|
|
down(&g_tsData[i].sem_mutex);
|
|
tsX_unregister(i);
|
|
up(&g_tsData[i].sem_mutex);
|
|
}
|
|
}
|
|
|
|
static void __exit tsallts_exit(void)
|
|
{
|
|
tsallts_dprintk("[%s]\n", __func__);
|
|
tsallts_unregister_thermal();
|
|
mtkTTimer_unregister("tztsAll");
|
|
}
|
|
module_init(tsallts_init);
|
|
module_exit(tsallts_exit);
|