Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Bricked
ville
Commits
e34c2f02
Commit
e34c2f02
authored
11 years ago
by
Dennis Rassmann
Browse files
Options
Download
Plain Diff
Merge branch 'exp'
parents
824f15ea
d467a6d5
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
982 additions
and
386 deletions
+982
-386
arch/arm/configs/bricked_defconfig
arch/arm/configs/bricked_defconfig
+3
-0
arch/arm/mach-msm/Kconfig
arch/arm/mach-msm/Kconfig
+13
-0
arch/arm/mach-msm/msm_mpdecision.c
arch/arm/mach-msm/msm_mpdecision.c
+466
-87
drivers/thermal/msm_thermal.c
drivers/thermal/msm_thermal.c
+489
-299
include/linux/msm_thermal.h
include/linux/msm_thermal.h
+11
-0
No files found.
arch/arm/configs/bricked_defconfig
View file @
e34c2f02
...
...
@@ -431,11 +431,13 @@ CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
# CONFIG_MSM_DALRPC is not set
CONFIG_MSM_MPDEC=y
CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN=y
CONFIG_MSM_CPU_FREQ_SET_MIN_MAX=y
CONFIG_MSM_CPU_FREQ_MAX=1512000
CONFIG_MSM_CPU_FREQ_MIN=384000
CONFIG_CPU_OVERCLOCK=y
CONFIG_CPU_VOLTAGE_TABLE=y
CONFIG_CMDLINE_OPTIONS=y
# CONFIG_MSM_AVS_HW is not set
# CONFIG_MSM_HW3D is not set
CONFIG_AMSS_7X25_VERSION_2009=y
...
...
@@ -3122,6 +3124,7 @@ CONFIG_HAVE_CLK_PREPARE=y
#
CONFIG_IOMMU_SUPPORT=y
CONFIG_MSM_IOMMU=y
CONFIG_MSM_IOMMU_GPU_SYNC=y
CONFIG_IOMMU_PGTABLES_L2=y
#
...
...
This diff is collapsed.
Click to expand it.
arch/arm/mach-msm/Kconfig
View file @
e34c2f02
...
...
@@ -1640,6 +1640,13 @@ config MSM_MPDEC
This enables kernel based multi core control.
(up/down hotplug based on load)
config MSM_MPDEC_INPUTBOOST_CPUMIN
bool "Enable kernel based mpdecision"
depends on MSM_MPDEC
default n
help
This pushes the cpu min speed to predefined values on input events.
if CPU_FREQ_MSM
config MSM_CPU_FREQ_SET_MIN_MAX
...
...
@@ -1669,6 +1676,12 @@ config CPU_VOLTAGE_TABLE
bool "Enable CPU Voltage Table via sysfs for adjustements"
default n
config CMDLINE_OPTIONS
bool "Enable cmdline s2w/khz/gov/maxscroff/scheduler command parsing"
default n
help
This enables the parsing of special cmdline variables.
config MSM_CPU_AVS
bool "Enable software controlled Adaptive Voltage Scaling (AVS)"
depends on (ARCH_MSM_SCORPION && QSD_SVS)
...
...
This diff is collapsed.
Click to expand it.
arch/arm/mach-msm/msm_mpdecision.c
View file @
e34c2f02
...
...
@@ -25,6 +25,9 @@
#include <linux/earlysuspend.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cpufreq.h>
#include <linux/workqueue.h>
#include <linux/completion.h>
#include <linux/cpu.h>
...
...
@@ -32,31 +35,27 @@
#include <asm-generic/cputime.h>
#include <linux/hrtimer.h>
#include <linux/delay.h>
#include <linux/export.h>
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
#include <linux/input.h>
#include <linux/slab.h>
#endif
#include "acpuclock.h"
#define DEBUG 0
#define MPDEC_TAG "[MPDEC]: "
#define MSM_MPDEC_STARTDELAY 20000
#define MSM_MPDEC_DELAY 1
0
0
#define MSM_MPDEC_DELAY 1
3
0
#define MSM_MPDEC_PAUSE 10000
#define MSM_MPDEC_IDLE_FREQ 486000
struct
global_attr
{
struct
attribute
attr
;
ssize_t
(
*
show
)(
struct
kobject
*
kobj
,
struct
attribute
*
attr
,
char
*
buf
);
ssize_t
(
*
store
)(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
c
,
size_t
count
);
};
#define define_one_global_ro(_name) \
static struct global_attr _name = \
__ATTR(_name, 0444, show_##_name, NULL)
#define define_one_global_rw(_name) \
static struct global_attr _name = \
__ATTR(_name, 0644, show_##_name, store_##_name)
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
#define MSM_MPDEC_BOOSTTIME 1000
#define MSM_MPDEC_BOOSTFREQ_CPU0 918000
#define MSM_MPDEC_BOOSTFREQ_CPU1 918000
#define MSM_MPDEC_BOOSTFREQ_CPU2 702000
#define MSM_MPDEC_BOOSTFREQ_CPU3 594000
#endif
enum
{
MSM_MPDEC_DISABLED
=
0
,
...
...
@@ -66,19 +65,34 @@ enum {
};
struct
msm_mpdec_cpudata_t
{
struct
mutex
suspend
_mutex
;
struct
mutex
hotplug
_mutex
;
int
online
;
int
device_suspended
;
cputime64_t
on_time
;
cputime64_t
on_time_total
;
long
long
unsigned
int
times_cpu_hotplugged
;
long
long
unsigned
int
times_cpu_unplugged
;
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
struct
mutex
boost_mutex
;
struct
mutex
unboost_mutex
;
unsigned
long
int
norm_min_freq
;
unsigned
long
int
boost_freq
;
cputime64_t
boost_until
;
bool
is_boosted
;
bool
revib_wq_running
;
#endif
};
static
DEFINE_PER_CPU
(
struct
msm_mpdec_cpudata_t
,
msm_mpdec_cpudata
);
static
struct
delayed_work
msm_mpdec_work
;
static
struct
workqueue_struct
*
msm_mpdec_workq
;
static
DEFINE_MUTEX
(
mpdec_msm_cpu_lock
);
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
static
struct
workqueue_struct
*
mpdec_input_wq
;
static
DEFINE_PER_CPU
(
struct
work_struct
,
mpdec_input_work
);
static
struct
workqueue_struct
*
msm_mpdec_revib_workq
;
static
DEFINE_PER_CPU
(
struct
delayed_work
,
msm_mpdec_revib_work
);
#endif
static
struct
msm_mpdec_tuners
{
unsigned
int
startdelay
;
...
...
@@ -88,6 +102,11 @@ static struct msm_mpdec_tuners {
unsigned
long
int
idle_freq
;
unsigned
int
max_cpus
;
unsigned
int
min_cpus
;
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
bool
boost_enabled
;
unsigned
int
boost_time
;
unsigned
long
int
boost_freq
[
4
];
#endif
}
msm_mpdec_tuners_ins
=
{
.
startdelay
=
MSM_MPDEC_STARTDELAY
,
.
delay
=
MSM_MPDEC_DELAY
,
...
...
@@ -96,9 +115,19 @@ static struct msm_mpdec_tuners {
.
idle_freq
=
MSM_MPDEC_IDLE_FREQ
,
.
max_cpus
=
CONFIG_NR_CPUS
,
.
min_cpus
=
1
,
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
.
boost_enabled
=
true
,
.
boost_time
=
MSM_MPDEC_BOOSTTIME
,
.
boost_freq
=
{
MSM_MPDEC_BOOSTFREQ_CPU0
,
MSM_MPDEC_BOOSTFREQ_CPU1
,
MSM_MPDEC_BOOSTFREQ_CPU2
,
MSM_MPDEC_BOOSTFREQ_CPU3
},
#endif
};
static
unsigned
int
NwNs_Threshold
[
8
]
=
{
1
8
,
0
,
2
5
,
15
,
32
,
28
,
0
,
35
};
static
unsigned
int
NwNs_Threshold
[
8
]
=
{
1
2
,
0
,
2
0
,
7
,
25
,
10
,
0
,
18
};
static
unsigned
int
TwTs_Threshold
[
8
]
=
{
140
,
0
,
140
,
190
,
140
,
190
,
0
,
190
};
extern
unsigned
int
get_rq_info
(
void
);
...
...
@@ -106,6 +135,12 @@ extern unsigned long acpuclk_get_rate(int);
unsigned
int
state
=
MSM_MPDEC_IDLE
;
bool
was_paused
=
false
;
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
bool
is_screen_on
=
true
;
static
int
update_cpu_min_freq
(
struct
cpufreq_policy
*
cpu_policy
,
int
cpu
,
int
new_freq
);
static
void
unboost_cpu
(
int
cpu
);
#endif
static
cputime64_t
mpdec_paused_until
=
0
;
static
unsigned
long
get_rate
(
int
cpu
)
{
...
...
@@ -151,6 +186,36 @@ static unsigned long get_slowest_cpu_rate(void) {
return
slow_rate
;
}
static
void
mpdec_cpu_up
(
int
cpu
)
{
if
(
!
cpu_online
(
cpu
))
{
mutex_lock
(
&
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
hotplug_mutex
);
cpu_up
(
cpu
);
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
on_time
=
ktime_to_ms
(
ktime_get
());
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
online
=
true
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
times_cpu_hotplugged
+=
1
;
pr_info
(
MPDEC_TAG
"CPU[%d] off->on | Mask=[%d%d]
\n
"
,
cpu
,
cpu_online
(
0
),
cpu_online
(
1
));
mutex_unlock
(
&
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
hotplug_mutex
);
}
}
EXPORT_SYMBOL_GPL
(
mpdec_cpu_up
);
static
void
mpdec_cpu_down
(
int
cpu
)
{
cputime64_t
on_time
=
0
;
if
(
cpu_online
(
cpu
))
{
mutex_lock
(
&
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
hotplug_mutex
);
cpu_down
(
cpu
);
on_time
=
(
ktime_to_ms
(
ktime_get
())
-
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
on_time
);
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
online
=
false
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
on_time_total
+=
on_time
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
times_cpu_unplugged
+=
1
;
pr_info
(
MPDEC_TAG
"CPU[%d] on->off | Mask=[%d%d] | time online: %llu
\n
"
,
cpu
,
cpu_online
(
0
),
cpu_online
(
1
),
on_time
);
mutex_unlock
(
&
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
hotplug_mutex
);
}
}
EXPORT_SYMBOL_GPL
(
mpdec_cpu_down
);
static
int
mp_decision
(
void
)
{
static
bool
first_call
=
true
;
int
new_state
=
MSM_MPDEC_IDLE
;
...
...
@@ -217,7 +282,6 @@ static int mp_decision(void) {
static
void
msm_mpdec_work_thread
(
struct
work_struct
*
work
)
{
unsigned
int
cpu
=
nr_cpu_ids
;
cputime64_t
on_time
=
0
;
bool
suspended
=
false
;
if
(
ktime_to_ms
(
ktime_get
())
<=
msm_mpdec_tuners_ins
.
startdelay
)
...
...
@@ -259,13 +323,10 @@ static void msm_mpdec_work_thread(struct work_struct *work) {
cpu
=
get_slowest_cpu
();
if
(
cpu
<
nr_cpu_ids
)
{
if
((
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
online
==
true
)
&&
(
cpu_online
(
cpu
)))
{
cpu_down
(
cpu
);
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
online
=
false
;
on_time
=
ktime_to_ms
(
ktime_get
())
-
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
on_time
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
on_time_total
+=
on_time
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
times_cpu_unplugged
+=
1
;
pr_info
(
MPDEC_TAG
"CPU[%d] on->off | Mask=[%d%d] | time online: %llu
\n
"
,
cpu
,
cpu_online
(
0
),
cpu_online
(
1
),
on_time
);
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
unboost_cpu
(
cpu
);
#endif
mpdec_cpu_down
(
cpu
);
}
else
if
(
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
online
!=
cpu_online
(
cpu
))
{
pr_info
(
MPDEC_TAG
"CPU[%d] was controlled outside of mpdecision! | pausing [%d]ms
\n
"
,
cpu
,
msm_mpdec_tuners_ins
.
pause
);
...
...
@@ -278,12 +339,10 @@ static void msm_mpdec_work_thread(struct work_struct *work) {
cpu
=
cpumask_next_zero
(
0
,
cpu_online_mask
);
if
(
cpu
<
nr_cpu_ids
)
{
if
((
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
online
==
false
)
&&
(
!
cpu_online
(
cpu
)))
{
cpu_up
(
cpu
);
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
online
=
true
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
on_time
=
ktime_to_ms
(
ktime_get
());
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
times_cpu_hotplugged
+=
1
;
pr_info
(
MPDEC_TAG
"CPU[%d] off->on | Mask=[%d%d]
\n
"
,
cpu
,
cpu_online
(
0
),
cpu_online
(
1
));
mpdec_cpu_up
(
cpu
);
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
unboost_cpu
(
cpu
);
#endif
}
else
if
(
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
online
!=
cpu_online
(
cpu
))
{
pr_info
(
MPDEC_TAG
"CPU[%d] was controlled outside of mpdecision! | pausing [%d]ms
\n
"
,
cpu
,
msm_mpdec_tuners_ins
.
pause
);
...
...
@@ -305,53 +364,243 @@ out:
return
;
}
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
static
int
update_cpu_min_freq
(
struct
cpufreq_policy
*
cpu_policy
,
int
cpu
,
int
new_freq
)
{
int
ret
=
0
;
if
(
!
cpu_policy
)
return
-
EINVAL
;
cpufreq_verify_within_limits
(
cpu_policy
,
new_freq
,
cpu_policy
->
max
);
cpu_policy
->
user_policy
.
min
=
new_freq
;
ret
=
cpufreq_update_policy
(
cpu
);
if
(
!
ret
)
{
pr_debug
(
MPDEC_TAG
"Touch event! Setting CPU%d min frequency to %d
\n
"
,
cpu
,
new_freq
);
}
return
ret
;
}
static
void
unboost_cpu
(
int
cpu
)
{
struct
cpufreq_policy
*
cpu_policy
=
NULL
;
if
(
cpu_online
(
cpu
))
{
if
(
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
is_boosted
)
{
if
(
mutex_trylock
(
&
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
unboost_mutex
))
{
cpu_policy
=
cpufreq_cpu_get
(
cpu
);
if
(
!
cpu_policy
)
{
pr_debug
(
MPDEC_TAG
"NULL policy on cpu %d
\n
"
,
cpu
);
return
;
}
#if DEBUG
pr_info
(
MPDEC_TAG
"un boosted cpu%i to %lu"
,
cpu
,
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
norm_min_freq
);
#endif
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
is_boosted
=
false
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
revib_wq_running
=
false
;
if
((
cpu_policy
->
min
!=
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_freq
)
&&
(
cpu_policy
->
min
!=
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
norm_min_freq
))
{
pr_info
(
MPDEC_TAG
"cpu%u min was changed while boosted (%lu->%u), using new min"
,
cpu
,
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
norm_min_freq
,
cpu_policy
->
min
);
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
norm_min_freq
=
cpu_policy
->
min
;
}
update_cpu_min_freq
(
cpu_policy
,
cpu
,
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
norm_min_freq
);
cpufreq_cpu_put
(
cpu_policy
);
mutex_unlock
(
&
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
unboost_mutex
);
}
}
}
return
;
}
static
void
msm_mpdec_revib_work_thread
(
struct
work_struct
*
work
)
{
int
cpu
=
smp_processor_id
();
if
(
ktime_to_ms
(
ktime_get
())
>
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_until
)
{
unboost_cpu
(
cpu
);
}
else
{
queue_delayed_work_on
(
cpu
,
msm_mpdec_revib_workq
,
&
per_cpu
(
msm_mpdec_revib_work
,
cpu
),
msecs_to_jiffies
((
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_until
-
ktime_to_ms
(
ktime_get
()))));
}
return
;
}
static
void
mpdec_input_callback
(
struct
work_struct
*
unused
)
{
struct
cpufreq_policy
*
cpu_policy
=
NULL
;
int
cpu
=
smp_processor_id
();
bool
boosted
=
false
;
if
(
!
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
is_boosted
)
{
if
(
mutex_trylock
(
&
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_mutex
))
{
cpu_policy
=
cpufreq_cpu_get
(
cpu
);
if
(
!
cpu_policy
)
{
pr_debug
(
MPDEC_TAG
"NULL policy on cpu %d
\n
"
,
cpu
);
return
;
}
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
norm_min_freq
=
cpu_policy
->
min
;
update_cpu_min_freq
(
cpu_policy
,
cpu
,
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_freq
);
#if DEBUG
pr_info
(
MPDEC_TAG
"boosted cpu%i to %lu"
,
cpu
,
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_freq
);
#endif
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
is_boosted
=
true
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_until
=
ktime_to_ms
(
ktime_get
())
+
MSM_MPDEC_BOOSTTIME
;
boosted
=
true
;
cpufreq_cpu_put
(
cpu_policy
);
mutex_unlock
(
&
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_mutex
);
}
}
else
{
boosted
=
true
;
}
if
(
boosted
&&
!
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
revib_wq_running
)
{
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
revib_wq_running
=
true
;
queue_delayed_work_on
(
cpu
,
msm_mpdec_revib_workq
,
&
per_cpu
(
msm_mpdec_revib_work
,
cpu
),
msecs_to_jiffies
(
MSM_MPDEC_BOOSTTIME
));
}
else
if
(
boosted
&&
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
revib_wq_running
)
{
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_until
=
ktime_to_ms
(
ktime_get
())
+
MSM_MPDEC_BOOSTTIME
;
}
return
;
}
static
void
mpdec_input_event
(
struct
input_handle
*
handle
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
int
i
=
0
;
if
(
!
msm_mpdec_tuners_ins
.
boost_enabled
)
return
;
if
(
!
is_screen_on
)
return
;
for_each_online_cpu
(
i
)
{
queue_work_on
(
i
,
mpdec_input_wq
,
&
per_cpu
(
mpdec_input_work
,
i
));
}
}
static
int
input_dev_filter
(
const
char
*
input_dev_name
)
{
if
(
strstr
(
input_dev_name
,
"touch"
)
||
strstr
(
input_dev_name
,
"keypad"
))
{
return
0
;
}
else
{
return
1
;
}
}
static
int
mpdec_input_connect
(
struct
input_handler
*
handler
,
struct
input_dev
*
dev
,
const
struct
input_device_id
*
id
)
{
struct
input_handle
*
handle
;
int
error
;
if
(
input_dev_filter
(
dev
->
name
))
return
-
ENODEV
;
handle
=
kzalloc
(
sizeof
(
struct
input_handle
),
GFP_KERNEL
);
if
(
!
handle
)
return
-
ENOMEM
;
handle
->
dev
=
dev
;
handle
->
handler
=
handler
;
handle
->
name
=
"mpdec"
;
error
=
input_register_handle
(
handle
);
if
(
error
)
goto
err2
;
error
=
input_open_device
(
handle
);
if
(
error
)
goto
err1
;
return
0
;
err1:
input_unregister_handle
(
handle
);
err2:
kfree
(
handle
);
return
error
;
}
static
void
mpdec_input_disconnect
(
struct
input_handle
*
handle
)
{
input_close_device
(
handle
);
input_unregister_handle
(
handle
);
kfree
(
handle
);
}
static
const
struct
input_device_id
mpdec_ids
[]
=
{
{
.
driver_info
=
1
},
{
},
};
static
struct
input_handler
mpdec_input_handler
=
{
.
event
=
mpdec_input_event
,
.
connect
=
mpdec_input_connect
,
.
disconnect
=
mpdec_input_disconnect
,
.
name
=
"mpdec_inputreq"
,
.
id_table
=
mpdec_ids
,
};
#endif
static
void
msm_mpdec_early_suspend
(
struct
early_suspend
*
h
)
{
int
cpu
=
nr_cpu_ids
;
cputime64_t
on_time
=
0
;
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
is_screen_on
=
false
;
#endif
if
(
!
msm_mpdec_tuners_ins
.
scroff_single_core
)
{
pr_info
(
MPDEC_TAG
"Screen -> off
\n
"
);
return
;
}
/* main work thread can sleep now */
cancel_delayed_work_sync
(
&
msm_mpdec_work
);
for_each_possible_cpu
(
cpu
)
{
mutex_lock
(
&
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
suspend_mutex
);
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
unboost_cpu
(
cpu
);
#endif
if
((
cpu
>=
1
)
&&
(
cpu_online
(
cpu
)))
{
cpu_down
(
cpu
);
pr_info
(
MPDEC_TAG
"Screen -> off. Suspended CPU[%d] | Mask=[%d%d]
\n
"
,
cpu
,
cpu_online
(
0
),
cpu_online
(
1
));
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
online
=
false
;
on_time
=
ktime_to_ms
(
ktime_get
())
-
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
on_time
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
on_time_total
+=
on_time
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
times_cpu_unplugged
+=
1
;
mpdec_cpu_down
(
cpu
);
}
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
device_suspended
=
true
;
mutex_unlock
(
&
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
suspend_mutex
);
}
/* main work thread can sleep now */
cancel_delayed_work_sync
(
&
msm_mpdec_work
);
pr_info
(
MPDEC_TAG
"Screen -> off. Deactivated mpdecision.
\n
"
);
}
static
void
msm_mpdec_late_resume
(
struct
early_suspend
*
h
)
{
int
cpu
=
nr_cpu_ids
;
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
is_screen_on
=
true
;
#endif
for_each_possible_cpu
(
cpu
)
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
device_suspended
=
false
;
mutex_lock
(
&
per_cpu
(
msm_mpdec_cpudata
,
1
).
suspend_mutex
);
if
(
!
cpu_online
(
1
))
{
/* Always enable cpu1 when screen comes online.
* This boosts the wakeup process. */
cpu_up
(
1
);
per_cpu
(
msm_mpdec_cpudata
,
1
).
on_time
=
ktime_to_ms
(
ktime_get
());
per_cpu
(
msm_mpdec_cpudata
,
1
).
online
=
true
;
per_cpu
(
msm_mpdec_cpudata
,
1
).
times_cpu_hotplugged
+=
1
;
pr_info
(
MPDEC_TAG
"Screen -> on. Hot plugged CPU1 | Mask=[%d%d]
\n
"
,
if
(
msm_mpdec_tuners_ins
.
scroff_single_core
)
{
/* wake up main work thread */
was_paused
=
true
;
queue_delayed_work
(
msm_mpdec_workq
,
&
msm_mpdec_work
,
0
);
/* restore min/max cpus limits */
for
(
cpu
=
1
;
cpu
<
CONFIG_NR_CPUS
;
cpu
++
)
{
if
(
cpu
<
msm_mpdec_tuners_ins
.
min_cpus
)
{
if
(
!
cpu_online
(
cpu
))
mpdec_cpu_up
(
cpu
);
}
else
if
(
cpu
>
msm_mpdec_tuners_ins
.
max_cpus
)
{
if
(
cpu_online
(
cpu
))
mpdec_cpu_down
(
cpu
);
}
}
pr_info
(
MPDEC_TAG
"Screen -> on. Activated mpdecision. | Mask=[%d%d]
\n
"
,
cpu_online
(
0
),
cpu_online
(
1
));
}
else
{
pr_info
(
MPDEC_TAG
"Screen -> on
\n
"
);
}
mutex_unlock
(
&
per_cpu
(
msm_mpdec_cpudata
,
1
).
suspend_mutex
);
/* wake up main work thread */
was_paused
=
true
;
queue_delayed_work
(
msm_mpdec_workq
,
&
msm_mpdec_work
,
0
);
pr_info
(
MPDEC_TAG
"Screen -> on. Activated mpdecision. | Mask=[%d%d]
\n
"
,
cpu_online
(
0
),
cpu_online
(
1
));
}
static
struct
early_suspend
msm_mpdec_early_suspend_handler
=
{
...
...
@@ -376,6 +625,10 @@ show_one(pause, pause);
show_one
(
scroff_single_core
,
scroff_single_core
);
show_one
(
min_cpus
,
min_cpus
);
show_one
(
max_cpus
,
max_cpus
);
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
show_one
(
boost_enabled
,
boost_enabled
);
show_one
(
boost_time
,
boost_time
);
#endif
#define show_one_twts(file_name, arraypos) \
static ssize_t show_##file_name \
...
...
@@ -541,14 +794,12 @@ static ssize_t store_scroff_single_core(struct kobject *a, struct attribute *b,
if
(
ret
!=
1
)
return
-
EINVAL
;
switch
(
buf
[
0
])
{
case
'0'
:
msm_mpdec_tuners_ins
.
scroff_single_core
=
input
;
break
;
case
'1'
:
msm_mpdec_tuners_ins
.
scroff_single_core
=
input
;
break
;
default:
ret
=
-
EINVAL
;
case
'0'
:
case
'1'
:
msm_mpdec_tuners_ins
.
scroff_single_core
=
input
;
break
;
default:
ret
=
-
EINVAL
;
}
return
count
;
}
...
...
@@ -557,12 +808,22 @@ static ssize_t store_max_cpus(struct kobject *a, struct attribute *b,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
int
ret
,
cpu
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
((
ret
!=
1
)
||
input
>
CONFIG_NR_CPUS
)
if
((
ret
!=
1
)
||
input
>
CONFIG_NR_CPUS
||
input
<
msm_mpdec_tuners_ins
.
min_cpus
)
return
-
EINVAL
;
msm_mpdec_tuners_ins
.
max_cpus
=
input
;
if
(
num_online_cpus
()
>
input
)
{
for
(
cpu
=
CONFIG_NR_CPUS
;
cpu
>
0
;
cpu
--
)
{
if
(
num_online_cpus
()
<=
input
)
break
;
if
(
!
cpu_online
(
cpu
))
continue
;
mpdec_cpu_down
(
cpu
);
}
pr_info
(
MPDEC_TAG
"max_cpus set to %u. Affected CPUs were unplugged!
\n
"
,
input
);
}
return
count
;
}
...
...
@@ -571,12 +832,22 @@ static ssize_t store_min_cpus(struct kobject *a, struct attribute *b,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
int
ret
,
cpu
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
((
ret
!=
1
)
||
input
<
1
)
if
((
ret
!=
1
)
||
input
<
1
||
input
>
msm_mpdec_tuners_ins
.
max_cpus
)
return
-
EINVAL
;
msm_mpdec_tuners_ins
.
min_cpus
=
input
;
if
(
num_online_cpus
()
<
input
)
{
for
(
cpu
=
1
;
cpu
<
CONFIG_NR_CPUS
;
cpu
++
)
{
if
(
num_online_cpus
()
>=
input
)
break
;
if
(
cpu_online
(
cpu
))
continue
;
mpdec_cpu_up
(
cpu
);
}
pr_info
(
MPDEC_TAG
"min_cpus set to %u. Affected CPUs were hotplugged!
\n
"
,
input
);
}
return
count
;
}
...
...
@@ -610,17 +881,9 @@ static ssize_t store_enabled(struct kobject *a, struct attribute *b,
case
'0'
:
state
=
MSM_MPDEC_DISABLED
;
pr_info
(
MPDEC_TAG
"nap time... Hot plugging offline CPUs...
\n
"
);
for
(
cpu
=
1
;
cpu
<
CONFIG_NR_CPUS
;
cpu
++
)
{
if
(
!
cpu_online
(
cpu
))
{
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
on_time
=
ktime_to_ms
(
ktime_get
());
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
online
=
true
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
times_cpu_hotplugged
+=
1
;
cpu_up
(
cpu
);
pr_info
(
MPDEC_TAG
"nap time... Hot plugged CPU[%d] | Mask=[%d%d]
\n
"
,
cpu
,
cpu_online
(
0
),
cpu_online
(
1
));
}
}
for
(
cpu
=
1
;
cpu
<
CONFIG_NR_CPUS
;
cpu
++
)
if
(
!
cpu_online
(
cpu
))
mpdec_cpu_up
(
cpu
);
break
;
case
'1'
:
state
=
MSM_MPDEC_IDLE
;
...
...
@@ -635,6 +898,67 @@ static ssize_t store_enabled(struct kobject *a, struct attribute *b,
return
count
;
}
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
static
ssize_t
store_boost_enabled
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_mpdec_tuners_ins
.
boost_enabled
=
input
;
return
count
;
}
static
ssize_t
store_boost_time
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_mpdec_tuners_ins
.
boost_time
=
input
;
return
count
;
}
static
ssize_t
show_boost_freqs
(
struct
kobject
*
a
,
struct
attribute
*
b
,
char
*
buf
)
{
ssize_t
len
=
0
;
int
cpu
=
0
;
for_each_present_cpu
(
cpu
)
{
len
+=
sprintf
(
buf
+
len
,
"%lu
\n
"
,
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_freq
);
}
return
len
;
}
static
ssize_t
store_boost_freqs
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
{
int
i
=
0
;
unsigned
int
cpu
=
0
;
long
unsigned
int
hz
=
0
;
const
char
*
chz
=
NULL
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
buf
[
i
]
==
' '
)
{
sscanf
(
&
buf
[(
i
-
1
)],
"%u"
,
&
cpu
);
chz
=
&
buf
[(
i
+
1
)];
}
}
sscanf
(
chz
,
"%lu"
,
&
hz
);
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_freq
=
hz
;
return
count
;
}
define_one_global_rw
(
boost_freqs
);
#endif
define_one_global_rw
(
startdelay
);
define_one_global_rw
(
delay
);
define_one_global_rw
(
pause
);
...
...
@@ -643,6 +967,10 @@ define_one_global_rw(idle_freq);
define_one_global_rw
(
min_cpus
);
define_one_global_rw
(
max_cpus
);
define_one_global_rw
(
enabled
);
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
define_one_global_rw
(
boost_enabled
);
define_one_global_rw
(
boost_time
);
#endif
static
struct
attribute
*
msm_mpdec_attributes
[]
=
{
&
startdelay
.
attr
,
...
...
@@ -669,6 +997,11 @@ static struct attribute *msm_mpdec_attributes[] = {
&
nwns_threshold_5
.
attr
,
&
nwns_threshold_6
.
attr
,
&
nwns_threshold_7
.
attr
,
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
&
boost_freqs
.
attr
,
&
boost_enabled
.
attr
,
&
boost_time
.
attr
,
#endif
NULL
};
...
...
@@ -744,14 +1077,37 @@ static struct attribute_group msm_mpdec_stats_attr_group = {
static
int
__init
msm_mpdec_init
(
void
)
{
int
cpu
,
rc
,
err
=
0
;
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
int
i
;
unsigned
long
int
boost_freq
=
0
;
#endif
for_each_possible_cpu
(
cpu
)
{
mutex_init
(
&
(
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
suspend
_mutex
));
mutex_init
(
&
(
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
hotplug
_mutex
));
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
device_suspended
=
false
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
online
=
true
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
on_time_total
=
0
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
times_cpu_unplugged
=
0
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
times_cpu_hotplugged
=
0
;
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
norm_min_freq
=
CONFIG_MSM_CPU_FREQ_MIN
;
switch
(
cpu
)
{
case
0
:
case
1
:
case
2
:
boost_freq
=
msm_mpdec_tuners_ins
.
boost_freq
[
cpu
];
break
;
default:
boost_freq
=
msm_mpdec_tuners_ins
.
boost_freq
[
3
];
break
;
}
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_freq
=
boost_freq
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
is_boosted
=
false
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
revib_wq_running
=
false
;
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_until
=
0
;
mutex_init
(
&
(
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
boost_mutex
));
mutex_init
(
&
(
per_cpu
(
msm_mpdec_cpudata
,
cpu
).
unboost_mutex
));
#endif
}
was_paused
=
true
;
...
...
@@ -762,6 +1118,25 @@ static int __init msm_mpdec_init(void) {
if
(
!
msm_mpdec_workq
)
return
-
ENOMEM
;
INIT_DELAYED_WORK
(
&
msm_mpdec_work
,
msm_mpdec_work_thread
);
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
mpdec_input_wq
=
create_workqueue
(
"mpdeciwq"
);
if
(
!
mpdec_input_wq
)
{
printk
(
KERN_ERR
"%s: Failed to create mpdeciwq workqueue
\n
"
,
__func__
);
return
-
EFAULT
;
}
msm_mpdec_revib_workq
=
create_workqueue
(
"mpdecribwq"
);
if
(
!
msm_mpdec_revib_workq
)
{
printk
(
KERN_ERR
"%s: Failed to create mpdecrevibwq workqueue
\n
"
,
__func__
);
return
-
EFAULT
;
}
for_each_possible_cpu
(
i
)
{
INIT_WORK
(
&
per_cpu
(
mpdec_input_work
,
i
),
mpdec_input_callback
);
INIT_DELAYED_WORK
(
&
per_cpu
(
msm_mpdec_revib_work
,
i
),
msm_mpdec_revib_work_thread
);
}
rc
=
input_register_handler
(
&
mpdec_input_handler
);
#endif
if
(
state
!=
MSM_MPDEC_DISABLED
)
queue_delayed_work
(
msm_mpdec_workq
,
&
msm_mpdec_work
,
msecs_to_jiffies
(
msm_mpdec_tuners_ins
.
delay
));
...
...
@@ -790,6 +1165,10 @@ static int __init msm_mpdec_init(void) {
late_initcall
(
msm_mpdec_init
);
void
msm_mpdec_exit
(
void
)
{
destroy_workqueue
(
msm_mpdec_workq
);
#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN
input_unregister_handler
(
&
mpdec_input_handler
);
destroy_workqueue
(
msm_mpdec_revib_workq
);
destroy_workqueue
(
mpdec_input_wq
);
#endif
destroy_workqueue
(
msm_mpdec_workq
);
}
This diff is collapsed.
Click to expand it.
drivers/thermal/msm_thermal.c
View file @
e34c2f02
...
...
@@ -24,6 +24,7 @@
#include <linux/msm_thermal.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/hrtimer.h>
#include <mach/cpufreq.h>
static
DEFINE_MUTEX
(
emergency_shutdown_mutex
);
...
...
@@ -38,204 +39,244 @@ static int pre_throttled_max = 0;
static
struct
msm_thermal_data
msm_thermal_info
;
static
struct
msm_thermal_stat
msm_thermal_stats
=
{
.
time_low_start
=
0
,
.
time_mid_start
=
0
,
.
time_max_start
=
0
,
.
time_low
=
0
,
.
time_mid
=
0
,
.
time_max
=
0
,
};
static
struct
delayed_work
check_temp_work
;
static
struct
workqueue_struct
*
check_temp_workq
;
static
void
update_stats
(
void
)
{
if
(
msm_thermal_stats
.
time_low_start
>
0
)
{
msm_thermal_stats
.
time_low
+=
(
ktime_to_ms
(
ktime_get
())
-
msm_thermal_stats
.
time_low_start
);
msm_thermal_stats
.
time_low_start
=
0
;
}
if
(
msm_thermal_stats
.
time_mid_start
>
0
)
{
msm_thermal_stats
.
time_mid
+=
(
ktime_to_ms
(
ktime_get
())
-
msm_thermal_stats
.
time_mid_start
);
msm_thermal_stats
.
time_mid_start
=
0
;
}
if
(
msm_thermal_stats
.
time_max_start
>
0
)
{
msm_thermal_stats
.
time_max
+=
(
ktime_to_ms
(
ktime_get
())
-
msm_thermal_stats
.
time_max_start
);
msm_thermal_stats
.
time_max_start
=
0
;
}
}
static
void
start_stats
(
int
status
)
{
switch
(
thermal_throttled
)
{
case
1
:
msm_thermal_stats
.
time_low_start
=
ktime_to_ms
(
ktime_get
());
break
;
case
2
:
msm_thermal_stats
.
time_mid_start
=
ktime_to_ms
(
ktime_get
());
break
;
case
3
:
msm_thermal_stats
.
time_max_start
=
ktime_to_ms
(
ktime_get
());
break
;
}
}
static
int
update_cpu_max_freq
(
struct
cpufreq_policy
*
cpu_policy
,
int
cpu
,
int
max_freq
)
int
cpu
,
int
max_freq
)
{
int
ret
=
0
;
int
ret
=
0
;
if
(
!
cpu_policy
)
return
-
EINVAL
;
if
(
!
cpu_policy
)
return
-
EINVAL
;
cpufreq_verify_within_limits
(
cpu_policy
,
cpu_policy
->
min
,
max_freq
);
cpu_policy
->
user_policy
.
max
=
max_freq
;
cpufreq_verify_within_limits
(
cpu_policy
,
cpu_policy
->
min
,
max_freq
);
cpu_policy
->
user_policy
.
max
=
max_freq
;
ret
=
cpufreq_update_policy
(
cpu
);
if
(
!
ret
)
pr_debug
(
"msm_thermal: Setting CPU%d max frequency to %d
\n
"
,
cpu
,
max_freq
);
return
ret
;
ret
=
cpufreq_update_policy
(
cpu
);
if
(
!
ret
)
pr_debug
(
"msm_thermal: Setting CPU%d max frequency to %d
\n
"
,
cpu
,
max_freq
);
return
ret
;
}
static
void
check_temp
(
struct
work_struct
*
work
)
{
struct
cpufreq_policy
*
cpu_policy
=
NULL
;
struct
tsens_device
tsens_dev
;
unsigned
long
temp
=
0
;
uint32_t
max_freq
=
0
;
bool
update_policy
=
false
;
int
i
=
0
,
cpu
=
0
,
ret
=
0
;
tsens_dev
.
sensor_num
=
msm_thermal_info
.
sensor_id
;
ret
=
tsens_get_temp
(
&
tsens_dev
,
&
temp
);
if
(
ret
)
{
pr_err
(
"msm_thermal: FATAL: Unable to read TSENS sensor %d
\n
"
,
tsens_dev
.
sensor_num
);
goto
reschedule
;
}
if
(
temp
>=
msm_thermal_info
.
shutdown_temp
)
{
mutex_lock
(
&
emergency_shutdown_mutex
);
pr_warn
(
"################################
\n
"
);
pr_warn
(
"################################
\n
"
);
pr_warn
(
"- %u OVERTEMP! SHUTTING DOWN! -
\n
"
,
msm_thermal_info
.
shutdown_temp
);
pr_warn
(
"- cur temp:%lu measured by:%u -
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
pr_warn
(
"################################
\n
"
);
pr_warn
(
"################################
\n
"
);
/* orderly poweroff tries to power down gracefully
if it fails it will force it. */
orderly_poweroff
(
true
);
for_each_possible_cpu
(
cpu
)
{
update_policy
=
true
;
max_freq
=
msm_thermal_info
.
allowed_max_freq
;
thermal_throttled
=
3
;
pr_warn
(
"msm_thermal: Emergency throttled CPU%i to %u! temp:%lu
\n
"
,
cpu
,
msm_thermal_info
.
allowed_max_freq
,
temp
);
}
mutex_unlock
(
&
emergency_shutdown_mutex
);
struct
cpufreq_policy
*
cpu_policy
=
NULL
;
struct
tsens_device
tsens_dev
;
unsigned
long
temp
=
0
;
uint32_t
max_freq
=
0
;
bool
update_policy
=
false
;
int
i
=
0
,
cpu
=
0
,
ret
=
0
;
tsens_dev
.
sensor_num
=
msm_thermal_info
.
sensor_id
;
ret
=
tsens_get_temp
(
&
tsens_dev
,
&
temp
);
if
(
ret
)
{
pr_err
(
"msm_thermal: FATAL: Unable to read TSENS sensor %d
\n
"
,
tsens_dev
.
sensor_num
);
goto
reschedule
;
}
if
(
temp
>=
msm_thermal_info
.
shutdown_temp
)
{
mutex_lock
(
&
emergency_shutdown_mutex
);
pr_warn
(
"################################
\n
"
);
pr_warn
(
"################################
\n
"
);
pr_warn
(
"- %u OVERTEMP! SHUTTING DOWN! -
\n
"
,
msm_thermal_info
.
shutdown_temp
);
pr_warn
(
"- cur temp:%lu measured by:%u -
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
pr_warn
(
"################################
\n
"
);
pr_warn
(
"################################
\n
"
);
/* orderly poweroff tries to power down gracefully
if it fails it will force it. */
orderly_poweroff
(
true
);
for_each_possible_cpu
(
cpu
)
{
update_policy
=
true
;
max_freq
=
msm_thermal_info
.
allowed_max_freq
;
thermal_throttled
=
3
;
pr_warn
(
"msm_thermal: Emergency throttled CPU%i to %u! temp:%lu
\n
"
,
cpu
,
msm_thermal_info
.
allowed_max_freq
,
temp
);
}
mutex_unlock
(
&
emergency_shutdown_mutex
);
}
for_each_possible_cpu
(
cpu
)
{
update_policy
=
false
;
cpu_policy
=
cpufreq_cpu_get
(
cpu
);
if
(
!
cpu_policy
)
{
pr_debug
(
"msm_thermal: NULL policy on cpu %d
\n
"
,
cpu
);
continue
;
}
for_each_possible_cpu
(
cpu
)
{
update_policy
=
false
;
cpu_policy
=
cpufreq_cpu_get
(
cpu
);
if
(
!
cpu_policy
)
{
pr_debug
(
"msm_thermal: NULL policy on cpu %d
\n
"
,
cpu
);
continue
;
}
/* save pre-throttled max freq value */
if
((
thermal_throttled
==
0
)
&&
(
cpu
==
0
))
pre_throttled_max
=
cpu_policy
->
max
;
//low trip point
if
((
temp
>=
msm_thermal_info
.
allowed_low_high
)
&&
(
temp
<
msm_thermal_info
.
allowed_mid_high
)
&&
(
thermal_throttled
<
1
))
{
update_policy
=
true
;
max_freq
=
msm_thermal_info
.
allowed_low_freq
;
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
1
;
pr_warn
(
"msm_thermal: Thermal Throttled (low)! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
//low clr point
}
else
if
((
temp
<
msm_thermal_info
.
allowed_low_low
)
&&
(
thermal_throttled
>
0
))
{
if
(
pre_throttled_max
!=
0
)
max_freq
=
pre_throttled_max
;
else
{
max_freq
=
CONFIG_MSM_CPU_FREQ_MAX
;
pr_warn
(
"msm_thermal: ERROR! pre_throttled_max=0, falling back to %u
\n
"
,
max_freq
);
}
update_policy
=
true
;
for
(
i
=
1
;
i
<
CONFIG_NR_CPUS
;
i
++
)
{
if
(
cpu_online
(
i
))
continue
;
cpu_up
(
i
);
}
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
0
;
pr_warn
(
"msm_thermal: Low thermal throttle ended! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
//mid trip point
}
else
if
((
temp
>=
msm_thermal_info
.
allowed_mid_high
)
&&
(
temp
<
msm_thermal_info
.
allowed_max_high
)
&&
(
thermal_throttled
<
2
))
{
update_policy
=
true
;
max_freq
=
msm_thermal_info
.
allowed_mid_freq
;
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
2
;
pr_warn
(
"msm_thermal: Thermal Throttled (mid)! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
//mid clr point
}
else
if
((
temp
<
msm_thermal_info
.
allowed_mid_low
)
&&
(
thermal_throttled
>
1
))
{
max_freq
=
msm_thermal_info
.
allowed_low_freq
;
update_policy
=
true
;
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
1
;
pr_warn
(
"msm_thermal: Mid thermal throttle ended! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
//max trip point
}
else
if
(
temp
>=
msm_thermal_info
.
allowed_max_high
)
{
update_policy
=
true
;
max_freq
=
msm_thermal_info
.
allowed_max_freq
;
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
3
;
pr_warn
(
"msm_thermal: Thermal Throttled (max)! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
//max clr point
}
else
if
((
temp
<
msm_thermal_info
.
allowed_max_low
)
&&
(
thermal_throttled
>
2
))
{
max_freq
=
msm_thermal_info
.
allowed_mid_freq
;
update_policy
=
true
;
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
2
;
pr_warn
(
"msm_thermal: Max thermal throttle ended! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
}
if
(
update_policy
)
update_cpu_max_freq
(
cpu_policy
,
cpu
,
max_freq
);
cpufreq_cpu_put
(
cpu_policy
);
}
/* save pre-throttled max freq value */
if
((
thermal_throttled
==
0
)
&&
(
cpu
==
0
))
pre_throttled_max
=
cpu_policy
->
max
;
//low trip point
if
((
temp
>=
msm_thermal_info
.
allowed_low_high
)
&&
(
temp
<
msm_thermal_info
.
allowed_mid_high
)
&&
(
thermal_throttled
<
1
))
{
update_policy
=
true
;
max_freq
=
msm_thermal_info
.
allowed_low_freq
;
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
1
;
pr_warn
(
"msm_thermal: Thermal Throttled (low)! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
//low clr point
}
else
if
((
temp
<
msm_thermal_info
.
allowed_low_low
)
&&
(
thermal_throttled
>
0
))
{
if
(
pre_throttled_max
!=
0
)
max_freq
=
pre_throttled_max
;
else
{
max_freq
=
CONFIG_MSM_CPU_FREQ_MAX
;
pr_warn
(
"msm_thermal: ERROR! pre_throttled_max=0, falling back to %u
\n
"
,
max_freq
);
}
update_policy
=
true
;
for
(
i
=
1
;
i
<
CONFIG_NR_CPUS
;
i
++
)
{
if
(
cpu_online
(
i
))
continue
;
cpu_up
(
i
);
}
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
0
;
pr_warn
(
"msm_thermal: Low thermal throttle ended! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
//mid trip point
}
else
if
((
temp
>=
msm_thermal_info
.
allowed_mid_high
)
&&
(
temp
<
msm_thermal_info
.
allowed_max_high
)
&&
(
thermal_throttled
<
2
))
{
update_policy
=
true
;
max_freq
=
msm_thermal_info
.
allowed_mid_freq
;
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
2
;
pr_warn
(
"msm_thermal: Thermal Throttled (mid)! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
//mid clr point
}
else
if
((
temp
<
msm_thermal_info
.
allowed_mid_low
)
&&
(
thermal_throttled
>
1
))
{
max_freq
=
msm_thermal_info
.
allowed_low_freq
;
update_policy
=
true
;
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
1
;
pr_warn
(
"msm_thermal: Mid thermal throttle ended! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
//max trip point
}
else
if
(
temp
>=
msm_thermal_info
.
allowed_max_high
)
{
update_policy
=
true
;
max_freq
=
msm_thermal_info
.
allowed_max_freq
;
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
3
;
pr_warn
(
"msm_thermal: Thermal Throttled (max)! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
//max clr point
}
else
if
((
temp
<
msm_thermal_info
.
allowed_max_low
)
&&
(
thermal_throttled
>
2
))
{
max_freq
=
msm_thermal_info
.
allowed_mid_freq
;
update_policy
=
true
;
if
(
cpu
==
(
CONFIG_NR_CPUS
-
1
))
{
thermal_throttled
=
2
;
pr_warn
(
"msm_thermal: Max thermal throttle ended! temp:%lu by:%u
\n
"
,
temp
,
msm_thermal_info
.
sensor_id
);
}
}
update_stats
();
start_stats
(
thermal_throttled
);
if
(
update_policy
)
update_cpu_max_freq
(
cpu_policy
,
cpu
,
max_freq
);
cpufreq_cpu_put
(
cpu_policy
);
}
reschedule:
if
(
enabled
)
queue_delayed_work
(
check_temp_workq
,
&
check_temp_work
,
msecs_to_jiffies
(
msm_thermal_info
.
poll_ms
));
return
;
if
(
enabled
)
queue_delayed_work
(
check_temp_workq
,
&
check_temp_work
,
msecs_to_jiffies
(
msm_thermal_info
.
poll_ms
));
return
;
}
static
void
disable_msm_thermal
(
void
)
{
int
cpu
=
0
;
struct
cpufreq_policy
*
cpu_policy
=
NULL
;
/* make sure check_temp is no longer running */
cancel_delayed_work
(
&
check_temp_work
);
flush_scheduled_work
();
if
(
pre_throttled_max
!=
0
)
{
for_each_possible_cpu
(
cpu
)
{
cpu_policy
=
cpufreq_cpu_get
(
cpu
);
if
(
cpu_policy
)
{
if
(
cpu_policy
->
max
<
cpu_policy
->
cpuinfo
.
max_freq
)
update_cpu_max_freq
(
cpu_policy
,
cpu
,
pre_throttled_max
);
cpufreq_cpu_put
(
cpu_policy
);
}
}
int
cpu
=
0
;
struct
cpufreq_policy
*
cpu_policy
=
NULL
;
/* make sure check_temp is no longer running */
cancel_delayed_work
(
&
check_temp_work
);
flush_scheduled_work
();
if
(
pre_throttled_max
!=
0
)
{
for_each_possible_cpu
(
cpu
)
{
cpu_policy
=
cpufreq_cpu_get
(
cpu
);
if
(
cpu_policy
)
{
if
(
cpu_policy
->
max
<
cpu_policy
->
cpuinfo
.
max_freq
)
update_cpu_max_freq
(
cpu_policy
,
cpu
,
pre_throttled_max
);
cpufreq_cpu_put
(
cpu_policy
);
}
}
}
}
static
int
set_enabled
(
const
char
*
val
,
const
struct
kernel_param
*
kp
)
{
int
ret
=
0
;
int
ret
=
0
;
ret
=
param_set_bool
(
val
,
kp
);
if
(
!
enabled
)
disable_msm_thermal
();
else
pr_info
(
"msm_thermal: no action for enabled = %d
\n
"
,
enabled
);
ret
=
param_set_bool
(
val
,
kp
);
if
(
!
enabled
)
disable_msm_thermal
();
else
pr_info
(
"msm_thermal: no action for enabled = %d
\n
"
,
enabled
);
pr_info
(
"msm_thermal: enabled = %d
\n
"
,
enabled
);
pr_info
(
"msm_thermal: enabled = %d
\n
"
,
enabled
);
return
ret
;
return
ret
;
}
static
struct
kernel_param_ops
module_ops
=
{
.
set
=
set_enabled
,
.
get
=
param_get_bool
,
.
set
=
set_enabled
,
.
get
=
param_get_bool
,
};
module_param_cb
(
enabled
,
&
module_ops
,
&
enabled
,
0644
);
...
...
@@ -244,11 +285,11 @@ MODULE_PARM_DESC(enabled, "enforce thermal limit on cpu");
/**************************** SYSFS START ****************************/
struct
kobject
*
msm_thermal_kobject
;
#define show_one(file_name, object)
\
static ssize_t show_##file_name
\
(struct kobject *kobj, struct attribute *attr, char *buf)
\
{
\
return sprintf(buf, "%u\n", msm_thermal_info.object);
\
#define show_one(file_name, object)
\
static ssize_t show_##file_name
\
(struct kobject *kobj, struct attribute *attr, char *buf) \
{
\
return sprintf(buf, "%u\n", msm_thermal_info.object);
\
}
show_one
(
shutdown_temp
,
shutdown_temp
);
...
...
@@ -264,157 +305,157 @@ show_one(allowed_low_freq, allowed_low_freq);
show_one
(
poll_ms
,
poll_ms
);
static
ssize_t
store_shutdown_temp
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_thermal_info
.
shutdown_temp
=
input
;
msm_thermal_info
.
shutdown_temp
=
input
;
return
count
;
return
count
;
}
static
ssize_t
store_allowed_max_high
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_thermal_info
.
allowed_max_high
=
input
;
msm_thermal_info
.
allowed_max_high
=
input
;
return
count
;
return
count
;
}
static
ssize_t
store_allowed_max_low
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_thermal_info
.
allowed_max_low
=
input
;
msm_thermal_info
.
allowed_max_low
=
input
;
return
count
;
return
count
;
}
static
ssize_t
store_allowed_max_freq
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_thermal_info
.
allowed_max_freq
=
input
;
msm_thermal_info
.
allowed_max_freq
=
input
;
return
count
;
return
count
;
}
static
ssize_t
store_allowed_mid_high
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_thermal_info
.
allowed_mid_high
=
input
;
msm_thermal_info
.
allowed_mid_high
=
input
;
return
count
;
return
count
;
}
static
ssize_t
store_allowed_mid_low
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_thermal_info
.
allowed_mid_low
=
input
;
msm_thermal_info
.
allowed_mid_low
=
input
;
return
count
;
return
count
;
}
static
ssize_t
store_allowed_mid_freq
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_thermal_info
.
allowed_mid_freq
=
input
;
msm_thermal_info
.
allowed_mid_freq
=
input
;
return
count
;
return
count
;
}
static
ssize_t
store_allowed_low_high
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_thermal_info
.
allowed_low_high
=
input
;
msm_thermal_info
.
allowed_low_high
=
input
;
return
count
;
return
count
;
}
static
ssize_t
store_allowed_low_low
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_thermal_info
.
allowed_low_low
=
input
;
msm_thermal_info
.
allowed_low_low
=
input
;
return
count
;
return
count
;
}
static
ssize_t
store_allowed_low_freq
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_thermal_info
.
allowed_low_freq
=
input
;
msm_thermal_info
.
allowed_low_freq
=
input
;
return
count
;
return
count
;
}
static
ssize_t
store_poll_ms
(
struct
kobject
*
a
,
struct
attribute
*
b
,
const
char
*
buf
,
size_t
count
)
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
msm_thermal_info
.
poll_ms
=
input
;
msm_thermal_info
.
poll_ms
=
input
;
return
count
;
return
count
;
}
define_one_global_rw
(
shutdown_temp
);
...
...
@@ -430,52 +471,201 @@ define_one_global_rw(allowed_low_freq);
define_one_global_rw
(
poll_ms
);
static
struct
attribute
*
msm_thermal_attributes
[]
=
{
&
shutdown_temp
.
attr
,
&
allowed_max_high
.
attr
,
&
allowed_max_low
.
attr
,
&
allowed_max_freq
.
attr
,
&
allowed_mid_high
.
attr
,
&
allowed_mid_low
.
attr
,
&
allowed_mid_freq
.
attr
,
&
allowed_low_high
.
attr
,
&
allowed_low_low
.
attr
,
&
allowed_low_freq
.
attr
,
&
poll_ms
.
attr
,
NULL
&
shutdown_temp
.
attr
,
&
allowed_max_high
.
attr
,
&
allowed_max_low
.
attr
,
&
allowed_max_freq
.
attr
,
&
allowed_mid_high
.
attr
,
&
allowed_mid_low
.
attr
,
&
allowed_mid_freq
.
attr
,
&
allowed_low_high
.
attr
,
&
allowed_low_low
.
attr
,
&
allowed_low_freq
.
attr
,
&
poll_ms
.
attr
,
NULL
};
static
struct
attribute_group
msm_thermal_attr_group
=
{
.
attrs
=
msm_thermal_attributes
,
.
name
=
"conf"
,
.
attrs
=
msm_thermal_attributes
,
.
name
=
"conf"
,
};
/********* STATS START *********/
static
ssize_t
show_throttle_times
(
struct
kobject
*
a
,
struct
attribute
*
b
,
char
*
buf
)
{
ssize_t
len
=
0
;
if
(
thermal_throttled
==
1
)
{
len
+=
sprintf
(
buf
+
len
,
"%s %llu
\n
"
,
"low"
,
(
msm_thermal_stats
.
time_low
+
(
ktime_to_ms
(
ktime_get
())
-
msm_thermal_stats
.
time_low_start
)));
}
else
len
+=
sprintf
(
buf
+
len
,
"%s %llu
\n
"
,
"low"
,
msm_thermal_stats
.
time_low
);
if
(
thermal_throttled
==
2
)
{
len
+=
sprintf
(
buf
+
len
,
"%s %llu
\n
"
,
"mid"
,
(
msm_thermal_stats
.
time_mid
+
(
ktime_to_ms
(
ktime_get
())
-
msm_thermal_stats
.
time_mid_start
)));
}
else
len
+=
sprintf
(
buf
+
len
,
"%s %llu
\n
"
,
"mid"
,
msm_thermal_stats
.
time_mid
);
if
(
thermal_throttled
==
3
)
{
len
+=
sprintf
(
buf
+
len
,
"%s %llu
\n
"
,
"max"
,
(
msm_thermal_stats
.
time_max
+
(
ktime_to_ms
(
ktime_get
())
-
msm_thermal_stats
.
time_max_start
)));
}
else
len
+=
sprintf
(
buf
+
len
,
"%s %llu
\n
"
,
"max"
,
msm_thermal_stats
.
time_max
);
return
len
;
}
define_one_global_ro
(
throttle_times
);
static
ssize_t
show_is_throttled
(
struct
kobject
*
a
,
struct
attribute
*
b
,
char
*
buf
)
{
return
sprintf
(
buf
,
"%u
\n
"
,
thermal_throttled
);
}
define_one_global_ro
(
is_throttled
);
static
struct
attribute
*
msm_thermal_stats_attributes
[]
=
{
&
is_throttled
.
attr
,
&
throttle_times
.
attr
,
NULL
};
static
struct
attribute_group
msm_thermal_stats_attr_group
=
{
.
attrs
=
msm_thermal_stats_attributes
,
.
name
=
"stats"
,
};
/**************************** SYSFS END ****************************/
int
__devinit
msm_thermal_init
(
struct
msm_thermal_data
*
pdata
)
{
int
ret
=
0
,
rc
=
0
;
BUG_ON
(
!
pdata
);
BUG_ON
(
pdata
->
sensor_id
>=
TSENS_MAX_SENSORS
);
memcpy
(
&
msm_thermal_info
,
pdata
,
sizeof
(
struct
msm_thermal_data
));
enabled
=
1
;
check_temp_workq
=
alloc_workqueue
(
"msm_thermal"
,
WQ_UNBOUND
|
WQ_RESCUER
,
1
);
if
(
!
check_temp_workq
)
BUG_ON
(
ENOMEM
);
INIT_DELAYED_WORK
(
&
check_temp_work
,
check_temp
);
queue_delayed_work
(
check_temp_workq
,
&
check_temp_work
,
0
);
msm_thermal_kobject
=
kobject_create_and_add
(
"msm_thermal"
,
kernel_kobj
);
if
(
msm_thermal_kobject
)
{
rc
=
sysfs_create_group
(
msm_thermal_kobject
,
&
msm_thermal_attr_group
);
if
(
rc
)
{
pr_warn
(
"msm_thermal: sysfs: ERROR, could not create sysfs group"
);
}
}
else
pr_warn
(
"msm_thermal: sysfs: ERROR, could not create sysfs kobj"
);
return
ret
;
int
ret
=
0
,
rc
=
0
;
BUG_ON
(
!
pdata
);
BUG_ON
(
pdata
->
sensor_id
>=
TSENS_MAX_SENSORS
);
memcpy
(
&
msm_thermal_info
,
pdata
,
sizeof
(
struct
msm_thermal_data
));
enabled
=
1
;
check_temp_workq
=
alloc_workqueue
(
"msm_thermal"
,
WQ_UNBOUND
|
WQ_RESCUER
,
1
);
if
(
!
check_temp_workq
)
BUG_ON
(
ENOMEM
);
INIT_DELAYED_WORK
(
&
check_temp_work
,
check_temp
);
queue_delayed_work
(
check_temp_workq
,
&
check_temp_work
,
0
);
msm_thermal_kobject
=
kobject_create_and_add
(
"msm_thermal"
,
kernel_kobj
);
if
(
msm_thermal_kobject
)
{
rc
=
sysfs_create_group
(
msm_thermal_kobject
,
&
msm_thermal_attr_group
);
if
(
rc
)
{
pr_warn
(
"msm_thermal: sysfs: ERROR, could not create sysfs group"
);
}
rc
=
sysfs_create_group
(
msm_thermal_kobject
,
&
msm_thermal_stats_attr_group
);
if
(
rc
)
{
pr_warn
(
"msm_thermal: sysfs: ERROR, could not create sysfs stats group"
);
}
}
else
pr_warn
(
"msm_thermal: sysfs: ERROR, could not create sysfs kobj"
);
return
ret
;
}
static
int
__devinit
msm_thermal_dev_probe
(
struct
platform_device
*
pdev
)
{
int
ret
=
0
;
char
*
key
=
NULL
;
struct
device_node
*
node
=
pdev
->
dev
.
of_node
;
struct
msm_thermal_data
data
;
memset
(
&
data
,
0
,
sizeof
(
struct
msm_thermal_data
));
key
=
"qcom,sensor-id"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
sensor_id
);
if
(
ret
)
goto
fail
;
WARN_ON
(
data
.
sensor_id
>=
TSENS_MAX_SENSORS
);
key
=
"qcom,poll-ms"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
poll_ms
);
if
(
ret
)
goto
fail
;
key
=
"qcom,shutdown_temp"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
shutdown_temp
);
if
(
ret
)
goto
fail
;
key
=
"qcom,allowed_max_high"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
allowed_max_high
);
if
(
ret
)
goto
fail
;
key
=
"qcom,allowed_max_low"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
allowed_max_low
);
if
(
ret
)
goto
fail
;
key
=
"qcom,allowed_max_freq"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
allowed_max_freq
);
if
(
ret
)
goto
fail
;
key
=
"qcom,allowed_mid_high"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
allowed_mid_high
);
if
(
ret
)
goto
fail
;
key
=
"qcom,allowed_mid_low"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
allowed_mid_low
);
if
(
ret
)
goto
fail
;
key
=
"qcom,allowed_mid_freq"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
allowed_mid_freq
);
if
(
ret
)
goto
fail
;
key
=
"qcom,allowed_low_high"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
allowed_low_high
);
if
(
ret
)
goto
fail
;
key
=
"qcom,allowed_low_low"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
allowed_low_low
);
if
(
ret
)
goto
fail
;
key
=
"qcom,allowed_low_freq"
;
ret
=
of_property_read_u32
(
node
,
key
,
&
data
.
allowed_low_freq
);
if
(
ret
)
goto
fail
;
fail:
if
(
ret
)
pr_err
(
"%s: Failed reading node=%s, key=%s
\n
"
,
__func__
,
node
->
full_name
,
key
);
else
ret
=
msm_thermal_init
(
&
data
);
return
ret
;
}
static
struct
of_device_id
msm_thermal_match_table
[]
=
{
{.
compatible
=
"qcom,msm-thermal"
},
{},
};
static
struct
platform_driver
msm_thermal_device_driver
=
{
.
probe
=
msm_thermal_dev_probe
,
.
driver
=
{
.
name
=
"msm-thermal"
,
.
owner
=
THIS_MODULE
,
.
of_match_table
=
msm_thermal_match_table
,
},
};
int
__init
msm_thermal_device_init
(
void
)
{
return
platform_driver_register
(
&
msm_thermal_device_driver
);
}
This diff is collapsed.
Click to expand it.
include/linux/msm_thermal.h
View file @
e34c2f02
...
...
@@ -14,6 +14,8 @@
#ifndef __MSM_THERMAL_H
#define __MSM_THERMAL_H
#include <asm/cputime.h>
struct
msm_thermal_data
{
uint32_t
sensor_id
;
uint32_t
poll_ms
;
...
...
@@ -32,6 +34,15 @@ struct msm_thermal_data {
uint32_t
allowed_low_freq
;
};
struct
msm_thermal_stat
{
cputime64_t
time_low_start
;
cputime64_t
time_mid_start
;
cputime64_t
time_max_start
;
cputime64_t
time_low
;
cputime64_t
time_mid
;
cputime64_t
time_max
;
};
#ifdef CONFIG_THERMAL_MONITOR
extern
int
msm_thermal_init
(
struct
msm_thermal_data
*
pdata
);
extern
int
msm_thermal_device_init
(
void
);
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment