soc: qcom: Snapshot of thermal/LMH drivers
This snapshot is taken as of msm-3.18 commit e70ad0c (Promotion of kernel.lnx.3.18-151201.) Include necessary thermal_core changes to convert long to int inline with upstream kernel changes. Change-Id: I642b666518fe72385794b743989a0f5e5120ec03 Conflicts: drivers/thermal/Makefile
This commit is contained in:
parent
3da2a8c7d1
commit
b68798fafa
11 changed files with 10838 additions and 10 deletions
|
@ -175,6 +175,36 @@ config THERMAL_EMULATION
|
|||
because userland can easily disable the thermal policy by simply
|
||||
flooding this sysfs node with low temperature values.
|
||||
|
||||
config LIMITS_MONITOR
|
||||
bool "LMH monitor driver"
|
||||
depends on THERMAL
|
||||
help
|
||||
Enable this to manage the limits hardware for interrupts, throttling
|
||||
intensities, and LMH device profiles. This driver also registers the
|
||||
Limits hardware's monitoring entities as sensors with the thermal
|
||||
framework.
|
||||
|
||||
config LIMITS_LITE_HW
|
||||
bool "LMH Lite hardware driver"
|
||||
depends on LIMITS_MONITOR
|
||||
help
|
||||
Enable this option for interacting with LMH Lite hardware. This
|
||||
implements the APIs required for getting the details about sensors
|
||||
supported by LMH Lite, their throttling intensity and the operating
|
||||
profiles.
|
||||
|
||||
config THERMAL_MONITOR
|
||||
bool "Monitor thermal state and limit CPU Frequency"
|
||||
depends on THERMAL_TSENS8974
|
||||
depends on CPU_FREQ || CPU_FREQ_MSM
|
||||
depends on PM_OPP
|
||||
default n
|
||||
help
|
||||
This enables thermal monitoring capability in the kernel in the
|
||||
absence of a system wide thermal monitoring entity or until such an
|
||||
entity starts running in the userspace. Monitors TSENS temperature
|
||||
and limits the max frequency of the cores.
|
||||
|
||||
config HISI_THERMAL
|
||||
tristate "Hisilicon thermal driver"
|
||||
depends on (ARCH_HISI && CPU_THERMAL && OF) || COMPILE_TEST
|
||||
|
|
|
@ -51,3 +51,6 @@ obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
|
|||
obj-$(CONFIG_THERMAL_QPNP) += qpnp-temp-alarm.o
|
||||
obj-$(CONFIG_THERMAL_QPNP_ADC_TM) += qpnp-adc-tm.o
|
||||
obj-$(CONFIG_THERMAL_TSENS8974) += msm8974-tsens.o
|
||||
obj-$(CONFIG_THERMAL_MONITOR) += msm_thermal.o msm_thermal-dev.o
|
||||
obj-$(CONFIG_LIMITS_MONITOR) += lmh_interface.o
|
||||
obj-$(CONFIG_LIMITS_LITE_HW) += lmh_lite.o
|
||||
|
|
1211
drivers/thermal/lmh_interface.c
Normal file
1211
drivers/thermal/lmh_interface.c
Normal file
File diff suppressed because it is too large
Load diff
112
drivers/thermal/lmh_interface.h
Normal file
112
drivers/thermal/lmh_interface.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 __LMH_INTERFACE_H
|
||||
#define __LMH_INTERFACE_H
|
||||
|
||||
#define LMH_NAME_MAX 20
|
||||
#define LMH_POLLING_MSEC 30
|
||||
#define LMH_READ_LINE_LENGTH 10
|
||||
|
||||
enum lmh_trip_type {
|
||||
LMH_LOW_TRIP,
|
||||
LMH_HIGH_TRIP,
|
||||
LMH_TRIP_MAX,
|
||||
};
|
||||
|
||||
enum lmh_monitor_state {
|
||||
LMH_ISR_DISABLED,
|
||||
LMH_ISR_MONITOR,
|
||||
LMH_ISR_POLLING,
|
||||
LMH_ISR_NR,
|
||||
};
|
||||
|
||||
struct lmh_sensor_ops {
|
||||
int (*read)(struct lmh_sensor_ops *, long *);
|
||||
int (*enable_hw_log)(uint32_t, uint32_t);
|
||||
int (*disable_hw_log)(void);
|
||||
void (*new_value_notify)(struct lmh_sensor_ops *, long);
|
||||
};
|
||||
|
||||
struct lmh_device_ops {
|
||||
int (*get_available_levels)(struct lmh_device_ops *, int *);
|
||||
int (*get_curr_level)(struct lmh_device_ops *, int *);
|
||||
int (*set_level)(struct lmh_device_ops *, int);
|
||||
};
|
||||
|
||||
struct lmh_debug_ops {
|
||||
int (*debug_read)(struct lmh_debug_ops *, uint32_t **);
|
||||
int (*debug_config_read)(struct lmh_debug_ops *, uint32_t *, int);
|
||||
int (*debug_config_lmh)(struct lmh_debug_ops *, uint32_t *, int);
|
||||
int (*debug_get_types)(struct lmh_debug_ops *, bool, uint32_t **);
|
||||
};
|
||||
|
||||
static int lmh_poll_interval = LMH_POLLING_MSEC;
|
||||
#ifdef CONFIG_LIMITS_MONITOR
|
||||
int lmh_get_all_dev_levels(char *, int *);
|
||||
int lmh_set_dev_level(char *, int);
|
||||
int lmh_get_curr_level(char *, int *);
|
||||
int lmh_sensor_register(char *, struct lmh_sensor_ops *);
|
||||
void lmh_sensor_deregister(struct lmh_sensor_ops *);
|
||||
int lmh_device_register(char *, struct lmh_device_ops *);
|
||||
void lmh_device_deregister(struct lmh_device_ops *);
|
||||
int lmh_debug_register(struct lmh_debug_ops *);
|
||||
void lmh_debug_deregister(struct lmh_debug_ops *ops);
|
||||
#else
|
||||
static inline int lmh_get_all_dev_levels(char *device_name, int *level)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int lmh_set_dev_level(char *device_name, int level)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int lmh_get_curr_level(char *device_name, int *level)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int lmh_sensor_register(char *sensor_name,
|
||||
struct lmh_sensor_ops *ops)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void lmh_sensor_deregister(struct lmh_sensor_ops *ops)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int lmh_device_register(char *device_name,
|
||||
struct lmh_device_ops *ops)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void lmh_device_deregister(struct lmh_device_ops *ops)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int lmh_debug_register(struct lmh_debug_ops *)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void lmh_debug_deregister(struct lmh_debug_ops *ops)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
#endif /*__LMH_INTERFACE_H*/
|
1408
drivers/thermal/lmh_lite.c
Normal file
1408
drivers/thermal/lmh_lite.c
Normal file
File diff suppressed because it is too large
Load diff
425
drivers/thermal/msm_thermal-dev.c
Normal file
425
drivers/thermal/msm_thermal-dev.c
Normal file
|
@ -0,0 +1,425 @@
|
|||
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/msm_thermal_ioctl.h>
|
||||
#include <linux/msm_thermal.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
struct msm_thermal_ioctl_dev {
|
||||
struct semaphore sem;
|
||||
struct cdev char_dev;
|
||||
};
|
||||
|
||||
static int msm_thermal_major;
|
||||
static struct class *thermal_class;
|
||||
static struct msm_thermal_ioctl_dev *msm_thermal_dev;
|
||||
static unsigned int freq_table_len[NR_CPUS], freq_table_set[NR_CPUS];
|
||||
static unsigned int voltage_table_set[NR_CPUS];
|
||||
static unsigned int *freq_table_ptr[NR_CPUS];
|
||||
static uint32_t *voltage_table_ptr[NR_CPUS];
|
||||
|
||||
static int msm_thermal_ioctl_open(struct inode *node, struct file *filep)
|
||||
{
|
||||
int ret = 0;
|
||||
struct msm_thermal_ioctl_dev *dev;
|
||||
|
||||
dev = container_of(node->i_cdev, struct msm_thermal_ioctl_dev,
|
||||
char_dev);
|
||||
filep->private_data = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_thermal_ioctl_release(struct inode *node, struct file *filep)
|
||||
{
|
||||
pr_debug("%s: IOCTL: release\n", KBUILD_MODNAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long validate_and_copy(unsigned int *cmd, unsigned long *arg,
|
||||
struct msm_thermal_ioctl *query)
|
||||
{
|
||||
long ret = 0, err_val = 0;
|
||||
|
||||
if ((_IOC_TYPE(*cmd) != MSM_THERMAL_MAGIC_NUM) ||
|
||||
(_IOC_NR(*cmd) >= MSM_CMD_MAX_NR)) {
|
||||
ret = -ENOTTY;
|
||||
goto validate_exit;
|
||||
}
|
||||
|
||||
if (_IOC_DIR(*cmd) & _IOC_READ) {
|
||||
err_val = !access_ok(VERIFY_WRITE, (void __user *)*arg,
|
||||
_IOC_SIZE(*cmd));
|
||||
} else if (_IOC_DIR(*cmd) & _IOC_WRITE) {
|
||||
err_val = !access_ok(VERIFY_READ, (void __user *)*arg,
|
||||
_IOC_SIZE(*cmd));
|
||||
}
|
||||
if (err_val) {
|
||||
ret = -EFAULT;
|
||||
goto validate_exit;
|
||||
}
|
||||
|
||||
if (copy_from_user(query, (void __user *)(*arg),
|
||||
sizeof(struct msm_thermal_ioctl))) {
|
||||
ret = -EACCES;
|
||||
goto validate_exit;
|
||||
}
|
||||
|
||||
if (query->size != sizeof(struct msm_thermal_ioctl)) {
|
||||
pr_err("%s: Invalid input argument size\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto validate_exit;
|
||||
}
|
||||
|
||||
switch (*cmd) {
|
||||
case MSM_THERMAL_SET_CPU_MAX_FREQUENCY:
|
||||
case MSM_THERMAL_SET_CPU_MIN_FREQUENCY:
|
||||
if (query->cpu_freq.cpu_num >= num_possible_cpus()) {
|
||||
pr_err("%s: Invalid CPU number: %u\n", __func__,
|
||||
query->cpu_freq.cpu_num);
|
||||
ret = -EINVAL;
|
||||
goto validate_exit;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
validate_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long msm_thermal_process_freq_table_req(struct msm_thermal_ioctl *query,
|
||||
unsigned long *arg)
|
||||
{
|
||||
long ret = 0;
|
||||
uint32_t table_idx, idx = 0, cluster_id = query->clock_freq.cluster_num;
|
||||
struct clock_plan_arg *clock_freq = &(query->clock_freq);
|
||||
|
||||
if (!freq_table_len[cluster_id]) {
|
||||
ret = msm_thermal_get_freq_plan_size(cluster_id,
|
||||
&freq_table_len[cluster_id]);
|
||||
if (ret) {
|
||||
pr_err("%s: Cluster%d freq table length get err:%ld\n",
|
||||
KBUILD_MODNAME, cluster_id, ret);
|
||||
goto process_freq_exit;
|
||||
}
|
||||
if (!freq_table_len[cluster_id]) {
|
||||
pr_err("%s: Cluster%d freq table empty\n",
|
||||
KBUILD_MODNAME, cluster_id);
|
||||
ret = -EAGAIN;
|
||||
goto process_freq_exit;
|
||||
}
|
||||
|
||||
freq_table_set[cluster_id] = freq_table_len[cluster_id]
|
||||
/ MSM_IOCTL_FREQ_SIZE;
|
||||
if (freq_table_len[cluster_id] % MSM_IOCTL_FREQ_SIZE)
|
||||
freq_table_set[cluster_id]++;
|
||||
|
||||
if (!freq_table_ptr[cluster_id]) {
|
||||
freq_table_ptr[cluster_id] = kzalloc(
|
||||
sizeof(unsigned int) *
|
||||
freq_table_len[cluster_id], GFP_KERNEL);
|
||||
if (!freq_table_ptr[cluster_id]) {
|
||||
pr_err("%s: memory alloc failed\n",
|
||||
KBUILD_MODNAME);
|
||||
freq_table_len[cluster_id] = 0;
|
||||
ret = -ENOMEM;
|
||||
goto process_freq_exit;
|
||||
}
|
||||
}
|
||||
ret = msm_thermal_get_cluster_freq_plan(cluster_id,
|
||||
freq_table_ptr[cluster_id]);
|
||||
if (ret) {
|
||||
pr_err("%s: Error getting frequency table. err:%ld\n",
|
||||
KBUILD_MODNAME, ret);
|
||||
freq_table_len[cluster_id] = 0;
|
||||
freq_table_set[cluster_id] = 0;
|
||||
kfree(freq_table_ptr[cluster_id]);
|
||||
freq_table_ptr[cluster_id] = NULL;
|
||||
goto process_freq_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!clock_freq->freq_table_len) {
|
||||
clock_freq->freq_table_len = freq_table_len[cluster_id];
|
||||
goto copy_and_return;
|
||||
}
|
||||
if (clock_freq->set_idx >= freq_table_set[cluster_id]) {
|
||||
pr_err("%s: Invalid freq table set%d for cluster%d\n",
|
||||
KBUILD_MODNAME, clock_freq->set_idx,
|
||||
cluster_id);
|
||||
ret = -EINVAL;
|
||||
goto process_freq_exit;
|
||||
}
|
||||
|
||||
table_idx = MSM_IOCTL_FREQ_SIZE * clock_freq->set_idx;
|
||||
for (; table_idx < freq_table_len[cluster_id]
|
||||
&& idx < MSM_IOCTL_FREQ_SIZE; idx++, table_idx++) {
|
||||
clock_freq->freq_table[idx] =
|
||||
freq_table_ptr[cluster_id][table_idx];
|
||||
}
|
||||
clock_freq->freq_table_len = idx;
|
||||
|
||||
copy_and_return:
|
||||
ret = copy_to_user((void __user *)(*arg), query,
|
||||
sizeof(struct msm_thermal_ioctl));
|
||||
if (ret) {
|
||||
pr_err("%s: copy_to_user error:%ld.\n", KBUILD_MODNAME, ret);
|
||||
goto process_freq_exit;
|
||||
}
|
||||
|
||||
process_freq_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long msm_thermal_process_voltage_table_req(
|
||||
struct msm_thermal_ioctl *query,
|
||||
unsigned long *arg)
|
||||
{
|
||||
long ret = 0;
|
||||
uint32_t table_idx = 0, idx = 0;
|
||||
uint32_t cluster_id = query->voltage.cluster_num;
|
||||
struct voltage_plan_arg *voltage = &(query->voltage);
|
||||
|
||||
if (!voltage_table_ptr[cluster_id]) {
|
||||
if (!freq_table_len[cluster_id]) {
|
||||
ret = msm_thermal_get_freq_plan_size(cluster_id,
|
||||
&freq_table_len[cluster_id]);
|
||||
if (ret) {
|
||||
pr_err(
|
||||
"%s: Cluster%d freq table len err:%ld\n",
|
||||
KBUILD_MODNAME, cluster_id, ret);
|
||||
goto process_volt_exit;
|
||||
}
|
||||
if (!freq_table_len[cluster_id]) {
|
||||
pr_err("%s: Cluster%d freq table empty\n",
|
||||
KBUILD_MODNAME, cluster_id);
|
||||
ret = -EAGAIN;
|
||||
goto process_volt_exit;
|
||||
}
|
||||
}
|
||||
voltage_table_ptr[cluster_id] = kzalloc(
|
||||
sizeof(uint32_t) *
|
||||
freq_table_len[cluster_id], GFP_KERNEL);
|
||||
if (!voltage_table_ptr[cluster_id]) {
|
||||
pr_err("%s: memory alloc failed\n",
|
||||
KBUILD_MODNAME);
|
||||
ret = -ENOMEM;
|
||||
goto process_volt_exit;
|
||||
}
|
||||
ret = msm_thermal_get_cluster_voltage_plan(cluster_id,
|
||||
voltage_table_ptr[cluster_id]);
|
||||
if (ret) {
|
||||
pr_err("%s: Error getting voltage table. err:%ld\n",
|
||||
KBUILD_MODNAME, ret);
|
||||
kfree(voltage_table_ptr[cluster_id]);
|
||||
voltage_table_ptr[cluster_id] = NULL;
|
||||
goto process_volt_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!voltage->voltage_table_len) {
|
||||
voltage->voltage_table_len = freq_table_len[cluster_id];
|
||||
goto copy_and_return;
|
||||
}
|
||||
|
||||
voltage_table_set[cluster_id] = freq_table_len[cluster_id]
|
||||
/ MSM_IOCTL_FREQ_SIZE;
|
||||
if (freq_table_len[cluster_id] % MSM_IOCTL_FREQ_SIZE)
|
||||
voltage_table_set[cluster_id]++;
|
||||
|
||||
if (voltage->set_idx >= voltage_table_set[cluster_id]) {
|
||||
pr_err("%s: Invalid voltage table set%d for cluster%d\n",
|
||||
KBUILD_MODNAME, voltage->set_idx,
|
||||
cluster_id);
|
||||
ret = -EINVAL;
|
||||
goto process_volt_exit;
|
||||
}
|
||||
|
||||
table_idx = MSM_IOCTL_FREQ_SIZE * voltage->set_idx;
|
||||
for (; table_idx < freq_table_len[cluster_id]
|
||||
&& idx < MSM_IOCTL_FREQ_SIZE; idx++, table_idx++) {
|
||||
voltage->voltage_table[idx] =
|
||||
voltage_table_ptr[cluster_id][table_idx];
|
||||
}
|
||||
voltage->voltage_table_len = idx;
|
||||
|
||||
copy_and_return:
|
||||
ret = copy_to_user((void __user *)(*arg), query,
|
||||
sizeof(struct msm_thermal_ioctl));
|
||||
if (ret) {
|
||||
pr_err("%s: copy_to_user error:%ld.\n", KBUILD_MODNAME, ret);
|
||||
goto process_volt_exit;
|
||||
}
|
||||
|
||||
process_volt_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long msm_thermal_ioctl_process(struct file *filep, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
long ret = 0;
|
||||
struct msm_thermal_ioctl query;
|
||||
|
||||
pr_debug("%s: IOCTL: processing cmd:%u\n", KBUILD_MODNAME, cmd);
|
||||
|
||||
ret = validate_and_copy(&cmd, &arg, &query);
|
||||
if (ret)
|
||||
goto process_exit;
|
||||
|
||||
switch (cmd) {
|
||||
case MSM_THERMAL_SET_CPU_MAX_FREQUENCY:
|
||||
ret = msm_thermal_set_frequency(query.cpu_freq.cpu_num,
|
||||
query.cpu_freq.freq_req, true);
|
||||
break;
|
||||
case MSM_THERMAL_SET_CPU_MIN_FREQUENCY:
|
||||
ret = msm_thermal_set_frequency(query.cpu_freq.cpu_num,
|
||||
query.cpu_freq.freq_req, false);
|
||||
break;
|
||||
case MSM_THERMAL_SET_CLUSTER_MAX_FREQUENCY:
|
||||
ret = msm_thermal_set_cluster_freq(query.cpu_freq.cpu_num,
|
||||
query.cpu_freq.freq_req, true);
|
||||
break;
|
||||
case MSM_THERMAL_SET_CLUSTER_MIN_FREQUENCY:
|
||||
ret = msm_thermal_set_cluster_freq(query.cpu_freq.cpu_num,
|
||||
query.cpu_freq.freq_req, false);
|
||||
break;
|
||||
case MSM_THERMAL_GET_CLUSTER_FREQUENCY_PLAN:
|
||||
ret = msm_thermal_process_freq_table_req(&query, &arg);
|
||||
break;
|
||||
case MSM_THERMAL_GET_CLUSTER_VOLTAGE_PLAN:
|
||||
ret = msm_thermal_process_voltage_table_req(&query, &arg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
goto process_exit;
|
||||
}
|
||||
process_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long msm_thermal_compat_ioctl_process(struct file *filep,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
arg = (unsigned long)compat_ptr(arg);
|
||||
return msm_thermal_ioctl_process(filep, cmd, arg);
|
||||
}
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
static const struct file_operations msm_thermal_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = msm_thermal_ioctl_open,
|
||||
.unlocked_ioctl = msm_thermal_ioctl_process,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = msm_thermal_compat_ioctl_process,
|
||||
#endif /* CONFIG_COMPAT */
|
||||
.release = msm_thermal_ioctl_release,
|
||||
};
|
||||
|
||||
int msm_thermal_ioctl_init()
|
||||
{
|
||||
int ret = 0;
|
||||
dev_t thermal_dev;
|
||||
struct device *therm_device;
|
||||
|
||||
ret = alloc_chrdev_region(&thermal_dev, 0, 1,
|
||||
MSM_THERMAL_IOCTL_NAME);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Error in allocating char device region. Err:%d\n",
|
||||
KBUILD_MODNAME, ret);
|
||||
goto ioctl_init_exit;
|
||||
}
|
||||
|
||||
msm_thermal_major = MAJOR(thermal_dev);
|
||||
|
||||
thermal_class = class_create(THIS_MODULE, "msm_thermal");
|
||||
if (IS_ERR(thermal_class)) {
|
||||
pr_err("%s: Error in creating class\n",
|
||||
KBUILD_MODNAME);
|
||||
ret = PTR_ERR(thermal_class);
|
||||
goto ioctl_class_fail;
|
||||
}
|
||||
|
||||
therm_device = device_create(thermal_class, NULL, thermal_dev, NULL,
|
||||
MSM_THERMAL_IOCTL_NAME);
|
||||
if (IS_ERR(therm_device)) {
|
||||
pr_err("%s: Error in creating character device\n",
|
||||
KBUILD_MODNAME);
|
||||
ret = PTR_ERR(therm_device);
|
||||
goto ioctl_dev_fail;
|
||||
}
|
||||
msm_thermal_dev = kmalloc(sizeof(struct msm_thermal_ioctl_dev),
|
||||
GFP_KERNEL);
|
||||
if (!msm_thermal_dev) {
|
||||
pr_err("%s: Error allocating memory\n",
|
||||
KBUILD_MODNAME);
|
||||
ret = -ENOMEM;
|
||||
goto ioctl_clean_all;
|
||||
}
|
||||
|
||||
memset(msm_thermal_dev, 0, sizeof(struct msm_thermal_ioctl_dev));
|
||||
sema_init(&msm_thermal_dev->sem, 1);
|
||||
cdev_init(&msm_thermal_dev->char_dev, &msm_thermal_fops);
|
||||
ret = cdev_add(&msm_thermal_dev->char_dev, thermal_dev, 1);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Error in adding character device\n",
|
||||
KBUILD_MODNAME);
|
||||
goto ioctl_clean_all;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
ioctl_clean_all:
|
||||
device_destroy(thermal_class, thermal_dev);
|
||||
ioctl_dev_fail:
|
||||
class_destroy(thermal_class);
|
||||
ioctl_class_fail:
|
||||
unregister_chrdev_region(thermal_dev, 1);
|
||||
ioctl_init_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void msm_thermal_ioctl_cleanup()
|
||||
{
|
||||
uint32_t idx = 0;
|
||||
dev_t thermal_dev = MKDEV(msm_thermal_major, 0);
|
||||
|
||||
if (!msm_thermal_dev) {
|
||||
pr_err("%s: Thermal IOCTL cleanup already done\n",
|
||||
KBUILD_MODNAME);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; idx < num_possible_cpus(); idx++) {
|
||||
kfree(freq_table_ptr[idx]);
|
||||
kfree(voltage_table_ptr[idx]);
|
||||
}
|
||||
device_destroy(thermal_class, thermal_dev);
|
||||
class_destroy(thermal_class);
|
||||
cdev_del(&msm_thermal_dev->char_dev);
|
||||
unregister_chrdev_region(thermal_dev, 1);
|
||||
kfree(msm_thermal_dev);
|
||||
msm_thermal_dev = NULL;
|
||||
thermal_class = NULL;
|
||||
}
|
7214
drivers/thermal/msm_thermal.c
Normal file
7214
drivers/thermal/msm_thermal.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -271,8 +271,8 @@ static void init_sensor_trip(struct sensor_info *sensor)
|
|||
|
||||
static int __update_sensor_thresholds(struct sensor_info *sensor)
|
||||
{
|
||||
long max_of_low_thresh = LONG_MIN;
|
||||
long min_of_high_thresh = LONG_MAX;
|
||||
int max_of_low_thresh = INT_MIN;
|
||||
int min_of_high_thresh = INT_MAX;
|
||||
struct sensor_threshold *pos, *var;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -300,7 +300,7 @@ static int __update_sensor_thresholds(struct sensor_info *sensor)
|
|||
}
|
||||
}
|
||||
|
||||
pr_debug("sensor %d: Thresholds: max of low: %ld min of high: %ld\n",
|
||||
pr_debug("sensor %d: Thresholds: max of low: %d min of high: %d\n",
|
||||
sensor->sensor_id, max_of_low_thresh,
|
||||
min_of_high_thresh);
|
||||
|
||||
|
@ -346,7 +346,7 @@ static int __update_sensor_thresholds(struct sensor_info *sensor)
|
|||
goto update_done;
|
||||
}
|
||||
|
||||
pr_debug("sensor %d: low: %ld high: %ld\n",
|
||||
pr_debug("sensor %d: low: %d high: %d\n",
|
||||
sensor->sensor_id,
|
||||
sensor->threshold_min, sensor->threshold_max);
|
||||
|
||||
|
@ -422,7 +422,7 @@ int thermal_sensor_trip(struct thermal_zone_device *tz,
|
|||
}
|
||||
EXPORT_SYMBOL(thermal_sensor_trip);
|
||||
|
||||
int sensor_get_temp(uint32_t sensor_id, long *temp)
|
||||
int sensor_get_temp(uint32_t sensor_id, int *temp)
|
||||
{
|
||||
struct sensor_info *sensor = get_sensor(sensor_id);
|
||||
int ret = 0;
|
||||
|
@ -565,8 +565,8 @@ int sensor_init(struct thermal_zone_device *tz)
|
|||
|
||||
sensor->sensor_id = tz->id;
|
||||
sensor->tz = tz;
|
||||
sensor->threshold_min = LONG_MIN;
|
||||
sensor->threshold_max = LONG_MAX;
|
||||
sensor->threshold_min = INT_MIN;
|
||||
sensor->threshold_max = INT_MAX;
|
||||
sensor->max_idx = -1;
|
||||
sensor->min_idx = -1;
|
||||
mutex_init(&sensor->lock);
|
||||
|
|
333
include/linux/msm_thermal.h
Normal file
333
include/linux/msm_thermal.h
Normal file
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 __MSM_THERMAL_H
|
||||
#define __MSM_THERMAL_H
|
||||
|
||||
#include <linux/thermal.h>
|
||||
|
||||
#define MAX_THRESHOLD 2
|
||||
#define TSENS_NAME_MAX 20
|
||||
#define MONITOR_ALL_TSENS -1
|
||||
#define HOTPLUG_DEVICE "hotplug"
|
||||
#define CPU0_DEVICE "cpu0"
|
||||
#define CPU1_DEVICE "cpu1"
|
||||
#define CPU2_DEVICE "cpu2"
|
||||
#define CPU3_DEVICE "cpu3"
|
||||
#define CPU4_DEVICE "cpu4"
|
||||
#define CPU5_DEVICE "cpu5"
|
||||
#define CPU6_DEVICE "cpu6"
|
||||
#define CPU7_DEVICE "cpu7"
|
||||
#define CPUFREQ_MAX_NO_MITIGATION UINT_MAX
|
||||
#define CPUFREQ_MIN_NO_MITIGATION 0
|
||||
#define HOTPLUG_NO_MITIGATION(_mask) cpumask_clear(_mask)
|
||||
|
||||
#define IS_HI_THRESHOLD_SET(_val) (_val & 1)
|
||||
#define IS_LOW_THRESHOLD_SET(_val) (_val & 2)
|
||||
|
||||
struct msm_thermal_data {
|
||||
struct platform_device *pdev;
|
||||
uint32_t sensor_id;
|
||||
uint32_t poll_ms;
|
||||
int32_t limit_temp_degC;
|
||||
int32_t temp_hysteresis_degC;
|
||||
uint32_t bootup_freq_step;
|
||||
uint32_t bootup_freq_control_mask;
|
||||
int32_t core_limit_temp_degC;
|
||||
int32_t core_temp_hysteresis_degC;
|
||||
int32_t hotplug_temp_degC;
|
||||
int32_t hotplug_temp_hysteresis_degC;
|
||||
uint32_t core_control_mask;
|
||||
uint32_t freq_mitig_temp_degc;
|
||||
uint32_t freq_mitig_temp_hysteresis_degc;
|
||||
uint32_t freq_mitig_control_mask;
|
||||
uint32_t freq_limit;
|
||||
int32_t vdd_rstr_temp_degC;
|
||||
int32_t vdd_rstr_temp_hyst_degC;
|
||||
int32_t vdd_mx_min;
|
||||
int32_t vdd_cx_min;
|
||||
int32_t psm_temp_degC;
|
||||
int32_t psm_temp_hyst_degC;
|
||||
int32_t ocr_temp_degC;
|
||||
int32_t ocr_temp_hyst_degC;
|
||||
uint32_t ocr_sensor_id;
|
||||
int32_t phase_rpm_resource_type;
|
||||
int32_t phase_rpm_resource_id;
|
||||
int32_t gfx_phase_warm_temp_degC;
|
||||
int32_t gfx_phase_warm_temp_hyst_degC;
|
||||
int32_t gfx_phase_hot_temp_degC;
|
||||
int32_t gfx_phase_hot_temp_hyst_degC;
|
||||
int32_t gfx_sensor;
|
||||
int32_t gfx_phase_request_key;
|
||||
int32_t cx_phase_hot_temp_degC;
|
||||
int32_t cx_phase_hot_temp_hyst_degC;
|
||||
int32_t cx_phase_request_key;
|
||||
int32_t vdd_mx_temp_degC;
|
||||
int32_t vdd_mx_temp_hyst_degC;
|
||||
int32_t therm_reset_temp_degC;
|
||||
};
|
||||
|
||||
enum sensor_id_type {
|
||||
THERM_ZONE_ID,
|
||||
THERM_TSENS_ID,
|
||||
THERM_ID_MAX_NR,
|
||||
};
|
||||
|
||||
struct threshold_info;
|
||||
struct therm_threshold {
|
||||
int32_t sensor_id;
|
||||
enum sensor_id_type id_type;
|
||||
struct sensor_threshold threshold[MAX_THRESHOLD];
|
||||
int32_t trip_triggered;
|
||||
void (*notify)(struct therm_threshold *);
|
||||
struct threshold_info *parent;
|
||||
};
|
||||
|
||||
struct threshold_info {
|
||||
uint32_t thresh_ct;
|
||||
bool thresh_triggered;
|
||||
struct list_head list_ptr;
|
||||
struct therm_threshold *thresh_list;
|
||||
};
|
||||
|
||||
enum device_req_type {
|
||||
DEVICE_REQ_NONE = -1,
|
||||
HOTPLUG_MITIGATION_REQ,
|
||||
CPUFREQ_MITIGATION_REQ,
|
||||
DEVICE_REQ_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* For frequency mitigation request, if client is interested
|
||||
* only in one, either max_freq or min_freq, update default
|
||||
* value for other one also for mitigation request.
|
||||
* Default value for request structure variables:
|
||||
* max_freq = UINT_MAX;
|
||||
* min_freq = 0;
|
||||
* offline_mask = CPU_MASK_NONE;
|
||||
*/
|
||||
struct cpufreq_request {
|
||||
uint32_t max_freq;
|
||||
uint32_t min_freq;
|
||||
};
|
||||
|
||||
union device_request {
|
||||
struct cpufreq_request freq;
|
||||
cpumask_t offline_mask;
|
||||
};
|
||||
|
||||
struct device_clnt_data;
|
||||
struct device_manager_data {
|
||||
char device_name[TSENS_NAME_MAX];
|
||||
union device_request active_req;
|
||||
struct list_head client_list;
|
||||
struct list_head dev_ptr;
|
||||
struct mutex clnt_lock;
|
||||
int (*request_validate)(struct device_clnt_data *,
|
||||
union device_request *,
|
||||
enum device_req_type);
|
||||
int (*update)(struct device_manager_data *);
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct device_clnt_data {
|
||||
struct device_manager_data *dev_mgr;
|
||||
bool req_active;
|
||||
union device_request request;
|
||||
struct list_head clnt_ptr;
|
||||
void (*callback)(struct device_clnt_data *,
|
||||
union device_request *req, void *);
|
||||
void *usr_data;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_THERMAL_MONITOR
|
||||
extern int msm_thermal_ioctl_init(void);
|
||||
extern void msm_thermal_ioctl_cleanup(void);
|
||||
extern int msm_thermal_init(struct msm_thermal_data *pdata);
|
||||
extern int msm_thermal_device_init(void);
|
||||
extern int msm_thermal_set_frequency(uint32_t cpu, uint32_t freq,
|
||||
bool is_max);
|
||||
extern int msm_thermal_set_cluster_freq(uint32_t cluster, uint32_t freq,
|
||||
bool is_max);
|
||||
extern int msm_thermal_get_freq_plan_size(uint32_t cluster,
|
||||
unsigned int *table_len);
|
||||
extern int msm_thermal_get_cluster_freq_plan(uint32_t cluster,
|
||||
unsigned int *table_ptr);
|
||||
extern int msm_thermal_get_cluster_voltage_plan(uint32_t cluster,
|
||||
uint32_t *table_ptr);
|
||||
/**
|
||||
* sensor_mgr_init_threshold - Initialize thresholds data structure for
|
||||
* sensor(s) with high and low thresholds and
|
||||
* threshold callback.
|
||||
*
|
||||
* @thresh_inp: Client threshold data structure.
|
||||
* @sensor_id: Sensor h/w ID to be monitored. Use MONITOR_ALL_TSENS
|
||||
* to monitor all temperature sensors.
|
||||
*
|
||||
* @high_temp: Trigger threshold value for sensor_id or all sensors.
|
||||
* @low_temp: Clear threshold value for sensor_id or all sensors.
|
||||
* @callback: Callback pointer for threshold notification.
|
||||
*
|
||||
* Returns which threshold is set on success, negative error number
|
||||
* on failure. MACRO IS_HI_THRESHOLD_SET/IS_LOW_THRESHOLD_SET can be used
|
||||
* to decipher which threshold being set.
|
||||
*/
|
||||
extern int sensor_mgr_init_threshold(struct threshold_info *thresh_inp,
|
||||
int sensor_id, int32_t high_temp,
|
||||
int32_t low_temp,
|
||||
void (*callback)(struct therm_threshold *));
|
||||
/**
|
||||
* sensor_mgr_convert_id_and_set_threshold - It accepts sensor h/w ID, converts
|
||||
* it to sensor zone id and sets
|
||||
* thermal threshold for those
|
||||
* sensors listed in threshold info.
|
||||
*
|
||||
* @thresh_inp: Client threshold data structure.
|
||||
*
|
||||
* Returns zero on success, negative error number on failure.
|
||||
*/
|
||||
extern int sensor_mgr_convert_id_and_set_threshold(
|
||||
struct threshold_info *thresh_inp);
|
||||
/**
|
||||
* sensor_mgr_set_threshold- It sets thermal threshold trips for a sensor.
|
||||
*
|
||||
* @zone_id: Thermal zone ID for the sensor.
|
||||
* @threshold: threshold info for the sensor.
|
||||
*
|
||||
* Returns zero on success, negative error number on failure.
|
||||
*/
|
||||
extern int sensor_mgr_set_threshold(uint32_t zone_id,
|
||||
struct sensor_threshold *threshold);
|
||||
/**
|
||||
* sensor_mgr_remove_threshold- It cancels threshold notification and
|
||||
* removes threshold from sensor manager
|
||||
* threshold list.
|
||||
*
|
||||
* @thresh_inp: The threshold info which needs to be removed.
|
||||
*/
|
||||
extern void sensor_mgr_remove_threshold(struct threshold_info *thresh_inp);
|
||||
/**
|
||||
* devmgr_register_mitigation_client - Register for a device and
|
||||
* gets a handle for mitigation.
|
||||
* @dev: Client device structure.
|
||||
* @device_name: Mitgation device name which the client is interested
|
||||
* to mitigate.
|
||||
* @callback: Optional callback pointer for device change notification,
|
||||
* otherwise pass NULL.
|
||||
*
|
||||
* Returns client handle structure for that device on success, or NULL
|
||||
* with IS_ERR() condition containing error number.
|
||||
*/
|
||||
extern struct device_clnt_data *devmgr_register_mitigation_client(
|
||||
struct device *dev,
|
||||
const char *device_name,
|
||||
void (*callback)(struct device_clnt_data *,
|
||||
union device_request *, void *));
|
||||
/**
|
||||
* devmgr_client_request_mitigation - Set a valid mitigation for
|
||||
* registered device.
|
||||
* @clnt: Client handle for device.
|
||||
* @type: Type of device request populated above.
|
||||
* @req: Valid mitigation request.
|
||||
*
|
||||
* Returns zero on successful mitigation update, or negative error number.
|
||||
*/
|
||||
extern int devmgr_client_request_mitigation(struct device_clnt_data *clnt,
|
||||
enum device_req_type type,
|
||||
union device_request *req);
|
||||
/**
|
||||
* devmgr_unregister_mitigation_client - Unregister mitigation device
|
||||
* @dev: Client device structure.
|
||||
* @clnt: Client handle for device.
|
||||
*/
|
||||
extern void devmgr_unregister_mitigation_client(
|
||||
struct device *dev,
|
||||
struct device_clnt_data *clnt);
|
||||
#else
|
||||
static inline int msm_thermal_init(struct msm_thermal_data *pdata)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int msm_thermal_device_init(void)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int msm_thermal_set_frequency(uint32_t cpu, uint32_t freq,
|
||||
bool is_max)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int msm_thermal_set_cluster_freq(uint32_t cluster, uint32_t freq,
|
||||
bool is_max)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int msm_thermal_get_freq_plan_size(uint32_t cluster,
|
||||
unsigned int *table_len)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int msm_thermal_get_cluster_freq_plan(uint32_t cluster,
|
||||
unsigned int *table_ptr)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int msm_thermal_get_cluster_voltage_plan(uint32_t cluster,
|
||||
uint32_t *table_ptr)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int sensor_mgr_init_threshold(struct threshold_info *thresh_inp,
|
||||
int sensor_id, int32_t high_temp,
|
||||
int32_t low_temp,
|
||||
void (*callback)(struct therm_threshold *))
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int sensor_mgr_convert_id_and_set_threshold(
|
||||
struct threshold_info *thresh_inp)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int sensor_mgr_set_threshold(uint32_t zone_id,
|
||||
struct sensor_threshold *threshold)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline void sensor_mgr_remove_threshold(
|
||||
struct threshold_info *thresh_inp)
|
||||
{
|
||||
}
|
||||
static inline struct device_clnt_data *devmgr_register_mitigation_client(
|
||||
struct device *dev,
|
||||
const char *device_name,
|
||||
void (*callback)(struct device_clnt_data *,
|
||||
union device_request *, void *))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline int devmgr_client_request_mitigation(
|
||||
struct device_clnt_data *clnt,
|
||||
enum device_req_type type,
|
||||
union device_request *req)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline void devmgr_unregister_mitigation_client(
|
||||
struct device *dev,
|
||||
struct device_clnt_data *clnt)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__MSM_THERMAL_H*/
|
|
@ -165,8 +165,8 @@ struct sensor_threshold {
|
|||
struct sensor_info {
|
||||
uint32_t sensor_id;
|
||||
struct thermal_zone_device *tz;
|
||||
long threshold_min;
|
||||
long threshold_max;
|
||||
int threshold_min;
|
||||
int threshold_max;
|
||||
int max_idx;
|
||||
int min_idx;
|
||||
struct list_head sensor_list;
|
||||
|
@ -450,7 +450,7 @@ struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
|
|||
void thermal_cdev_update(struct thermal_cooling_device *);
|
||||
void thermal_notify_framework(struct thermal_zone_device *, int);
|
||||
|
||||
int sensor_get_temp(uint32_t sensor_id, long *temp);
|
||||
int sensor_get_temp(uint32_t sensor_id, int *temp);
|
||||
int sensor_get_id(char *name);
|
||||
int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
|
||||
int sensor_cancel_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
|
||||
|
|
92
include/uapi/linux/msm_thermal_ioctl.h
Normal file
92
include/uapi/linux/msm_thermal_ioctl.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
#ifndef _MSM_THERMAL_IOCTL_H
|
||||
#define _MSM_THERMAL_IOCTL_H
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
#define MSM_THERMAL_IOCTL_NAME "msm_thermal_query"
|
||||
#define MSM_IOCTL_FREQ_SIZE 16
|
||||
|
||||
struct __attribute__((__packed__)) cpu_freq_arg {
|
||||
uint32_t cpu_num;
|
||||
uint32_t freq_req;
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) clock_plan_arg {
|
||||
uint32_t cluster_num;
|
||||
/*
|
||||
** A value of zero for freq_table_len, will fetch the length of the
|
||||
** cluster frequency table. A non-zero value will fetch the frequency
|
||||
** table contents.
|
||||
*/
|
||||
uint32_t freq_table_len;
|
||||
/*
|
||||
** For clusters with frequency table length greater than
|
||||
** MSM_IOCTL_FREQ_SIZE, the frequency table is fetched from kernel
|
||||
** in multiple sets or iterations. The set_idx variable,
|
||||
** indicates, which set/part of frequency table the user is requesting.
|
||||
** The set index value starts from zero. A set index value of 'Z',
|
||||
** will fetch MSM_IOCTL_FREQ_SIZE or maximum available number of
|
||||
** frequency values (if it is less than MSM_IOCTL_FREQ_SIZE)
|
||||
** from the frequency table, starting from the index
|
||||
** (Z * MSM_IOCTL_FREQ_SIZE).
|
||||
** For example, in a device supporting 19 different frequencies, a set
|
||||
** index value of 0 will fetch the first 16 (MSM_IOCTL_FREQ_SIZE)
|
||||
** frequencies starting from the index 0 and a set value of 1 will fetch
|
||||
** the remaining 3 frequencies starting from the index 16.
|
||||
** A successful get, will populate the freq_table_len with the
|
||||
** number of frequency table entries fetched.
|
||||
*/
|
||||
uint32_t set_idx;
|
||||
unsigned int freq_table[MSM_IOCTL_FREQ_SIZE];
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) voltage_plan_arg {
|
||||
uint32_t cluster_num;
|
||||
uint32_t voltage_table_len;
|
||||
uint32_t set_idx;
|
||||
uint32_t voltage_table[MSM_IOCTL_FREQ_SIZE];
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) msm_thermal_ioctl {
|
||||
uint32_t size;
|
||||
union {
|
||||
struct cpu_freq_arg cpu_freq;
|
||||
struct clock_plan_arg clock_freq;
|
||||
struct voltage_plan_arg voltage;
|
||||
};
|
||||
};
|
||||
|
||||
enum {
|
||||
/*Set CPU Frequency*/
|
||||
MSM_SET_CPU_MAX_FREQ = 0x00,
|
||||
MSM_SET_CPU_MIN_FREQ = 0x01,
|
||||
/*Set cluster frequency*/
|
||||
MSM_SET_CLUSTER_MAX_FREQ = 0x02,
|
||||
MSM_SET_CLUSTER_MIN_FREQ = 0x03,
|
||||
/*Get cluster frequency plan*/
|
||||
MSM_GET_CLUSTER_FREQ_PLAN = 0x04,
|
||||
/*Get cluster voltage plan */
|
||||
MSM_GET_CLUSTER_VOLTAGE_PLAN = 0x05,
|
||||
MSM_CMD_MAX_NR,
|
||||
};
|
||||
|
||||
#define MSM_THERMAL_MAGIC_NUM 0xCA /*Unique magic number*/
|
||||
|
||||
#define MSM_THERMAL_SET_CPU_MAX_FREQUENCY _IOW(MSM_THERMAL_MAGIC_NUM,\
|
||||
MSM_SET_CPU_MAX_FREQ, struct msm_thermal_ioctl)
|
||||
|
||||
#define MSM_THERMAL_SET_CPU_MIN_FREQUENCY _IOW(MSM_THERMAL_MAGIC_NUM,\
|
||||
MSM_SET_CPU_MIN_FREQ, struct msm_thermal_ioctl)
|
||||
|
||||
#define MSM_THERMAL_SET_CLUSTER_MAX_FREQUENCY _IOW(MSM_THERMAL_MAGIC_NUM,\
|
||||
MSM_SET_CLUSTER_MAX_FREQ, struct msm_thermal_ioctl)
|
||||
|
||||
#define MSM_THERMAL_SET_CLUSTER_MIN_FREQUENCY _IOW(MSM_THERMAL_MAGIC_NUM,\
|
||||
MSM_SET_CLUSTER_MIN_FREQ, struct msm_thermal_ioctl)
|
||||
|
||||
#define MSM_THERMAL_GET_CLUSTER_FREQUENCY_PLAN _IOR(MSM_THERMAL_MAGIC_NUM,\
|
||||
MSM_GET_CLUSTER_FREQ_PLAN, struct msm_thermal_ioctl)
|
||||
|
||||
#define MSM_THERMAL_GET_CLUSTER_VOLTAGE_PLAN _IOR(MSM_THERMAL_MAGIC_NUM,\
|
||||
MSM_GET_CLUSTER_VOLTAGE_PLAN, struct msm_thermal_ioctl)
|
||||
#endif
|
Loading…
Add table
Reference in a new issue