Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
8cb68501
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
8cb68501
编写于
1月 30, 2015
作者:
Z
Zhang Rui
浏览文件
操作
浏览文件
下载
差异文件
Merge branches 'intel-dts-soc-thermal' and 'int340x-enhancement' of .git into next
上级
6c355faf
317d9dda
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
727 addition
and
484 deletion
+727
-484
drivers/acpi/Makefile
drivers/acpi/Makefile
+1
-0
drivers/acpi/acpi_lpat.c
drivers/acpi/acpi_lpat.c
+161
-0
drivers/acpi/pmic/intel_pmic.c
drivers/acpi/pmic/intel_pmic.c
+18
-115
drivers/thermal/int340x_thermal/Makefile
drivers/thermal/int340x_thermal/Makefile
+1
-0
drivers/thermal/int340x_thermal/int3402_thermal.c
drivers/thermal/int340x_thermal/int3402_thermal.c
+37
-171
drivers/thermal/int340x_thermal/int3403_thermal.c
drivers/thermal/int340x_thermal/int3403_thermal.c
+10
-198
drivers/thermal/int340x_thermal/int340x_thermal_zone.c
drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+276
-0
drivers/thermal/int340x_thermal/int340x_thermal_zone.h
drivers/thermal/int340x_thermal/int340x_thermal_zone.h
+68
-0
drivers/thermal/int340x_thermal/processor_thermal_device.c
drivers/thermal/int340x_thermal/processor_thermal_device.c
+90
-0
include/acpi/acpi_lpat.h
include/acpi/acpi_lpat.h
+65
-0
未找到文件。
drivers/acpi/Makefile
浏览文件 @
8cb68501
...
@@ -55,6 +55,7 @@ acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
...
@@ -55,6 +55,7 @@ acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
ifdef
CONFIG_ACPI_VIDEO
ifdef
CONFIG_ACPI_VIDEO
acpi-y
+=
video_detect.o
acpi-y
+=
video_detect.o
endif
endif
acpi-y
+=
acpi_lpat.o
# These are (potentially) separate modules
# These are (potentially) separate modules
...
...
drivers/acpi/acpi_lpat.c
0 → 100644
浏览文件 @
8cb68501
/*
* acpi_lpat.c - LPAT table processing functions
*
* Copyright (C) 2015 Intel Corporation. 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 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/module.h>
#include <linux/acpi.h>
#include <acpi/acpi_lpat.h>
/**
* acpi_lpat_raw_to_temp(): Return temperature from raw value through
* LPAT conversion table
*
* @lpat_table: the temperature_raw mapping table structure
* @raw: the raw value, used as a key to get the temerature from the
* above mapping table
*
* A positive converted temperarure value will be returned on success,
* a negative errno will be returned in error cases.
*/
int
acpi_lpat_raw_to_temp
(
struct
acpi_lpat_conversion_table
*
lpat_table
,
int
raw
)
{
int
i
,
delta_temp
,
delta_raw
,
temp
;
struct
acpi_lpat
*
lpat
=
lpat_table
->
lpat
;
for
(
i
=
0
;
i
<
lpat_table
->
lpat_count
-
1
;
i
++
)
{
if
((
raw
>=
lpat
[
i
].
raw
&&
raw
<=
lpat
[
i
+
1
].
raw
)
||
(
raw
<=
lpat
[
i
].
raw
&&
raw
>=
lpat
[
i
+
1
].
raw
))
break
;
}
if
(
i
==
lpat_table
->
lpat_count
-
1
)
return
-
ENOENT
;
delta_temp
=
lpat
[
i
+
1
].
temp
-
lpat
[
i
].
temp
;
delta_raw
=
lpat
[
i
+
1
].
raw
-
lpat
[
i
].
raw
;
temp
=
lpat
[
i
].
temp
+
(
raw
-
lpat
[
i
].
raw
)
*
delta_temp
/
delta_raw
;
return
temp
;
}
EXPORT_SYMBOL_GPL
(
acpi_lpat_raw_to_temp
);
/**
* acpi_lpat_temp_to_raw(): Return raw value from temperature through
* LPAT conversion table
*
* @lpat: the temperature_raw mapping table
* @temp: the temperature, used as a key to get the raw value from the
* above mapping table
*
* A positive converted temperature value will be returned on success,
* a negative errno will be returned in error cases.
*/
int
acpi_lpat_temp_to_raw
(
struct
acpi_lpat_conversion_table
*
lpat_table
,
int
temp
)
{
int
i
,
delta_temp
,
delta_raw
,
raw
;
struct
acpi_lpat
*
lpat
=
lpat_table
->
lpat
;
for
(
i
=
0
;
i
<
lpat_table
->
lpat_count
-
1
;
i
++
)
{
if
(
temp
>=
lpat
[
i
].
temp
&&
temp
<=
lpat
[
i
+
1
].
temp
)
break
;
}
if
(
i
==
lpat_table
->
lpat_count
-
1
)
return
-
ENOENT
;
delta_temp
=
lpat
[
i
+
1
].
temp
-
lpat
[
i
].
temp
;
delta_raw
=
lpat
[
i
+
1
].
raw
-
lpat
[
i
].
raw
;
raw
=
lpat
[
i
].
raw
+
(
temp
-
lpat
[
i
].
temp
)
*
delta_raw
/
delta_temp
;
return
raw
;
}
EXPORT_SYMBOL_GPL
(
acpi_lpat_temp_to_raw
);
/**
* acpi_lpat_get_conversion_table(): Parse ACPI LPAT table if present.
*
* @handle: Handle to acpi device
*
* Parse LPAT table to a struct of type acpi_lpat_table. On success
* it returns a pointer to newly allocated table. This table must
* be freed by the caller when finished processing, using a call to
* acpi_lpat_free_conversion_table.
*/
struct
acpi_lpat_conversion_table
*
acpi_lpat_get_conversion_table
(
acpi_handle
handle
)
{
struct
acpi_lpat_conversion_table
*
lpat_table
=
NULL
;
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
obj_p
,
*
obj_e
;
int
*
lpat
,
i
;
acpi_status
status
;
status
=
acpi_evaluate_object
(
handle
,
"LPAT"
,
NULL
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
return
NULL
;
obj_p
=
(
union
acpi_object
*
)
buffer
.
pointer
;
if
(
!
obj_p
||
(
obj_p
->
type
!=
ACPI_TYPE_PACKAGE
)
||
(
obj_p
->
package
.
count
%
2
)
||
(
obj_p
->
package
.
count
<
4
))
goto
out
;
lpat
=
kcalloc
(
obj_p
->
package
.
count
,
sizeof
(
int
),
GFP_KERNEL
);
if
(
!
lpat
)
goto
out
;
for
(
i
=
0
;
i
<
obj_p
->
package
.
count
;
i
++
)
{
obj_e
=
&
obj_p
->
package
.
elements
[
i
];
if
(
obj_e
->
type
!=
ACPI_TYPE_INTEGER
)
{
kfree
(
lpat
);
goto
out
;
}
lpat
[
i
]
=
(
s64
)
obj_e
->
integer
.
value
;
}
lpat_table
=
kzalloc
(
sizeof
(
*
lpat_table
),
GFP_KERNEL
);
if
(
!
lpat_table
)
{
kfree
(
lpat
);
goto
out
;
}
lpat_table
->
lpat
=
(
struct
acpi_lpat
*
)
lpat
;
lpat_table
->
lpat_count
=
obj_p
->
package
.
count
/
2
;
out:
kfree
(
buffer
.
pointer
);
return
lpat_table
;
}
EXPORT_SYMBOL_GPL
(
acpi_lpat_get_conversion_table
);
/**
* acpi_lpat_free_conversion_table(): Free LPAT table.
*
* @lpat_table: the temperature_raw mapping table structure
*
* Frees the LPAT table previously allocated by a call to
* acpi_lpat_get_conversion_table.
*/
void
acpi_lpat_free_conversion_table
(
struct
acpi_lpat_conversion_table
*
lpat_table
)
{
if
(
lpat_table
)
{
kfree
(
lpat_table
->
lpat
);
kfree
(
lpat_table
);
}
}
EXPORT_SYMBOL_GPL
(
acpi_lpat_free_conversion_table
);
MODULE_LICENSE
(
"GPL"
);
drivers/acpi/pmic/intel_pmic.c
浏览文件 @
8cb68501
...
@@ -16,20 +16,15 @@
...
@@ -16,20 +16,15 @@
#include <linux/module.h>
#include <linux/module.h>
#include <linux/acpi.h>
#include <linux/acpi.h>
#include <linux/regmap.h>
#include <linux/regmap.h>
#include <acpi/acpi_lpat.h>
#include "intel_pmic.h"
#include "intel_pmic.h"
#define PMIC_POWER_OPREGION_ID 0x8d
#define PMIC_POWER_OPREGION_ID 0x8d
#define PMIC_THERMAL_OPREGION_ID 0x8c
#define PMIC_THERMAL_OPREGION_ID 0x8c
struct
acpi_lpat
{
int
temp
;
int
raw
;
};
struct
intel_pmic_opregion
{
struct
intel_pmic_opregion
{
struct
mutex
lock
;
struct
mutex
lock
;
struct
acpi_lpat
*
lpat
;
struct
acpi_lpat_conversion_table
*
lpat_table
;
int
lpat_count
;
struct
regmap
*
regmap
;
struct
regmap
*
regmap
;
struct
intel_pmic_opregion_data
*
data
;
struct
intel_pmic_opregion_data
*
data
;
};
};
...
@@ -50,105 +45,6 @@ static int pmic_get_reg_bit(int address, struct pmic_table *table,
...
@@ -50,105 +45,6 @@ static int pmic_get_reg_bit(int address, struct pmic_table *table,
return
-
ENOENT
;
return
-
ENOENT
;
}
}
/**
* raw_to_temp(): Return temperature from raw value through LPAT table
*
* @lpat: the temperature_raw mapping table
* @count: the count of the above mapping table
* @raw: the raw value, used as a key to get the temerature from the
* above mapping table
*
* A positive value will be returned on success, a negative errno will
* be returned in error cases.
*/
static
int
raw_to_temp
(
struct
acpi_lpat
*
lpat
,
int
count
,
int
raw
)
{
int
i
,
delta_temp
,
delta_raw
,
temp
;
for
(
i
=
0
;
i
<
count
-
1
;
i
++
)
{
if
((
raw
>=
lpat
[
i
].
raw
&&
raw
<=
lpat
[
i
+
1
].
raw
)
||
(
raw
<=
lpat
[
i
].
raw
&&
raw
>=
lpat
[
i
+
1
].
raw
))
break
;
}
if
(
i
==
count
-
1
)
return
-
ENOENT
;
delta_temp
=
lpat
[
i
+
1
].
temp
-
lpat
[
i
].
temp
;
delta_raw
=
lpat
[
i
+
1
].
raw
-
lpat
[
i
].
raw
;
temp
=
lpat
[
i
].
temp
+
(
raw
-
lpat
[
i
].
raw
)
*
delta_temp
/
delta_raw
;
return
temp
;
}
/**
* temp_to_raw(): Return raw value from temperature through LPAT table
*
* @lpat: the temperature_raw mapping table
* @count: the count of the above mapping table
* @temp: the temperature, used as a key to get the raw value from the
* above mapping table
*
* A positive value will be returned on success, a negative errno will
* be returned in error cases.
*/
static
int
temp_to_raw
(
struct
acpi_lpat
*
lpat
,
int
count
,
int
temp
)
{
int
i
,
delta_temp
,
delta_raw
,
raw
;
for
(
i
=
0
;
i
<
count
-
1
;
i
++
)
{
if
(
temp
>=
lpat
[
i
].
temp
&&
temp
<=
lpat
[
i
+
1
].
temp
)
break
;
}
if
(
i
==
count
-
1
)
return
-
ENOENT
;
delta_temp
=
lpat
[
i
+
1
].
temp
-
lpat
[
i
].
temp
;
delta_raw
=
lpat
[
i
+
1
].
raw
-
lpat
[
i
].
raw
;
raw
=
lpat
[
i
].
raw
+
(
temp
-
lpat
[
i
].
temp
)
*
delta_raw
/
delta_temp
;
return
raw
;
}
static
void
pmic_thermal_lpat
(
struct
intel_pmic_opregion
*
opregion
,
acpi_handle
handle
,
struct
device
*
dev
)
{
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
obj_p
,
*
obj_e
;
int
*
lpat
,
i
;
acpi_status
status
;
status
=
acpi_evaluate_object
(
handle
,
"LPAT"
,
NULL
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
return
;
obj_p
=
(
union
acpi_object
*
)
buffer
.
pointer
;
if
(
!
obj_p
||
(
obj_p
->
type
!=
ACPI_TYPE_PACKAGE
)
||
(
obj_p
->
package
.
count
%
2
)
||
(
obj_p
->
package
.
count
<
4
))
goto
out
;
lpat
=
devm_kmalloc
(
dev
,
sizeof
(
int
)
*
obj_p
->
package
.
count
,
GFP_KERNEL
);
if
(
!
lpat
)
goto
out
;
for
(
i
=
0
;
i
<
obj_p
->
package
.
count
;
i
++
)
{
obj_e
=
&
obj_p
->
package
.
elements
[
i
];
if
(
obj_e
->
type
!=
ACPI_TYPE_INTEGER
)
{
devm_kfree
(
dev
,
lpat
);
goto
out
;
}
lpat
[
i
]
=
(
s64
)
obj_e
->
integer
.
value
;
}
opregion
->
lpat
=
(
struct
acpi_lpat
*
)
lpat
;
opregion
->
lpat_count
=
obj_p
->
package
.
count
/
2
;
out:
kfree
(
buffer
.
pointer
);
}
static
acpi_status
intel_pmic_power_handler
(
u32
function
,
static
acpi_status
intel_pmic_power_handler
(
u32
function
,
acpi_physical_address
address
,
u32
bits
,
u64
*
value64
,
acpi_physical_address
address
,
u32
bits
,
u64
*
value64
,
void
*
handler_context
,
void
*
region_context
)
void
*
handler_context
,
void
*
region_context
)
...
@@ -192,12 +88,12 @@ static int pmic_read_temp(struct intel_pmic_opregion *opregion,
...
@@ -192,12 +88,12 @@ static int pmic_read_temp(struct intel_pmic_opregion *opregion,
if
(
raw_temp
<
0
)
if
(
raw_temp
<
0
)
return
raw_temp
;
return
raw_temp
;
if
(
!
opregion
->
lpat
)
{
if
(
!
opregion
->
lpat
_table
)
{
*
value
=
raw_temp
;
*
value
=
raw_temp
;
return
0
;
return
0
;
}
}
temp
=
raw_to_temp
(
opregion
->
lpat
,
opregion
->
lpat_count
,
raw_temp
);
temp
=
acpi_lpat_raw_to_temp
(
opregion
->
lpat_table
,
raw_temp
);
if
(
temp
<
0
)
if
(
temp
<
0
)
return
temp
;
return
temp
;
...
@@ -223,9 +119,8 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg,
...
@@ -223,9 +119,8 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg,
if
(
!
opregion
->
data
->
update_aux
)
if
(
!
opregion
->
data
->
update_aux
)
return
-
ENXIO
;
return
-
ENXIO
;
if
(
opregion
->
lpat
)
{
if
(
opregion
->
lpat_table
)
{
raw_temp
=
temp_to_raw
(
opregion
->
lpat
,
opregion
->
lpat_count
,
raw_temp
=
acpi_lpat_temp_to_raw
(
opregion
->
lpat_table
,
*
value
);
*
value
);
if
(
raw_temp
<
0
)
if
(
raw_temp
<
0
)
return
raw_temp
;
return
raw_temp
;
}
else
{
}
else
{
...
@@ -314,6 +209,7 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
...
@@ -314,6 +209,7 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
{
{
acpi_status
status
;
acpi_status
status
;
struct
intel_pmic_opregion
*
opregion
;
struct
intel_pmic_opregion
*
opregion
;
int
ret
;
if
(
!
dev
||
!
regmap
||
!
d
)
if
(
!
dev
||
!
regmap
||
!
d
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -327,14 +223,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
...
@@ -327,14 +223,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
mutex_init
(
&
opregion
->
lock
);
mutex_init
(
&
opregion
->
lock
);
opregion
->
regmap
=
regmap
;
opregion
->
regmap
=
regmap
;
pmic_thermal_lpat
(
opregion
,
handle
,
dev
);
opregion
->
lpat_table
=
acpi_lpat_get_conversion_table
(
handle
);
status
=
acpi_install_address_space_handler
(
handle
,
status
=
acpi_install_address_space_handler
(
handle
,
PMIC_POWER_OPREGION_ID
,
PMIC_POWER_OPREGION_ID
,
intel_pmic_power_handler
,
intel_pmic_power_handler
,
NULL
,
opregion
);
NULL
,
opregion
);
if
(
ACPI_FAILURE
(
status
))
if
(
ACPI_FAILURE
(
status
))
{
return
-
ENODEV
;
ret
=
-
ENODEV
;
goto
out_error
;
}
status
=
acpi_install_address_space_handler
(
handle
,
status
=
acpi_install_address_space_handler
(
handle
,
PMIC_THERMAL_OPREGION_ID
,
PMIC_THERMAL_OPREGION_ID
,
...
@@ -343,11 +241,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
...
@@ -343,11 +241,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
if
(
ACPI_FAILURE
(
status
))
{
if
(
ACPI_FAILURE
(
status
))
{
acpi_remove_address_space_handler
(
handle
,
PMIC_POWER_OPREGION_ID
,
acpi_remove_address_space_handler
(
handle
,
PMIC_POWER_OPREGION_ID
,
intel_pmic_power_handler
);
intel_pmic_power_handler
);
return
-
ENODEV
;
ret
=
-
ENODEV
;
goto
out_error
;
}
}
opregion
->
data
=
d
;
opregion
->
data
=
d
;
return
0
;
return
0
;
out_error:
acpi_lpat_free_conversion_table
(
opregion
->
lpat_table
);
return
ret
;
}
}
EXPORT_SYMBOL_GPL
(
intel_pmic_install_opregion_handler
);
EXPORT_SYMBOL_GPL
(
intel_pmic_install_opregion_handler
);
...
...
drivers/thermal/int340x_thermal/Makefile
浏览文件 @
8cb68501
obj-$(CONFIG_INT340X_THERMAL)
+=
int3400_thermal.o
obj-$(CONFIG_INT340X_THERMAL)
+=
int3400_thermal.o
obj-$(CONFIG_INT340X_THERMAL)
+=
int340x_thermal_zone.o
obj-$(CONFIG_INT340X_THERMAL)
+=
int3402_thermal.o
obj-$(CONFIG_INT340X_THERMAL)
+=
int3402_thermal.o
obj-$(CONFIG_INT340X_THERMAL)
+=
int3403_thermal.o
obj-$(CONFIG_INT340X_THERMAL)
+=
int3403_thermal.o
obj-$(CONFIG_INT340X_THERMAL)
+=
processor_thermal_device.o
obj-$(CONFIG_INT340X_THERMAL)
+=
processor_thermal_device.o
...
...
drivers/thermal/int340x_thermal/int3402_thermal.c
浏览文件 @
8cb68501
...
@@ -14,152 +14,39 @@
...
@@ -14,152 +14,39 @@
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/acpi.h>
#include <linux/thermal.h>
#include <linux/thermal.h>
#include "int340x_thermal_zone.h"
#define ACPI_ACTIVE_COOLING_MAX_NR 10
#define INT3402_PERF_CHANGED_EVENT 0x80
#define INT3402_THERMAL_EVENT 0x90
struct
active_trip
{
unsigned
long
temp
;
int
id
;
bool
valid
;
};
struct
int3402_thermal_data
{
struct
int3402_thermal_data
{
unsigned
long
*
aux_trips
;
int
aux_trip_nr
;
unsigned
long
psv_temp
;
int
psv_trip_id
;
unsigned
long
crt_temp
;
int
crt_trip_id
;
unsigned
long
hot_temp
;
int
hot_trip_id
;
struct
active_trip
act_trips
[
ACPI_ACTIVE_COOLING_MAX_NR
];
acpi_handle
*
handle
;
acpi_handle
*
handle
;
struct
int34x_thermal_zone
*
int340x_zone
;
};
};
static
int
int3402_thermal_get_zone_temp
(
struct
thermal_zone_device
*
zone
,
static
void
int3402_notify
(
acpi_handle
handle
,
u32
event
,
void
*
data
)
unsigned
long
*
temp
)
{
struct
int3402_thermal_data
*
d
=
zone
->
devdata
;
unsigned
long
long
tmp
;
acpi_status
status
;
status
=
acpi_evaluate_integer
(
d
->
handle
,
"_TMP"
,
NULL
,
&
tmp
);
if
(
ACPI_FAILURE
(
status
))
return
-
ENODEV
;
/* _TMP returns the temperature in tenths of degrees Kelvin */
*
temp
=
DECI_KELVIN_TO_MILLICELSIUS
(
tmp
);
return
0
;
}
static
int
int3402_thermal_get_trip_temp
(
struct
thermal_zone_device
*
zone
,
int
trip
,
unsigned
long
*
temp
)
{
{
struct
int3402_thermal_data
*
d
=
zone
->
devdata
;
struct
int3402_thermal_data
*
priv
=
data
;
int
i
;
if
(
!
priv
)
if
(
trip
<
d
->
aux_trip_nr
)
return
;
*
temp
=
d
->
aux_trips
[
trip
];
else
if
(
trip
==
d
->
crt_trip_id
)
switch
(
event
)
{
*
temp
=
d
->
crt_temp
;
case
INT3402_PERF_CHANGED_EVENT
:
else
if
(
trip
==
d
->
psv_trip_id
)
break
;
*
temp
=
d
->
psv_temp
;
case
INT3402_THERMAL_EVENT
:
else
if
(
trip
==
d
->
hot_trip_id
)
int340x_thermal_zone_device_update
(
priv
->
int340x_zone
);
*
temp
=
d
->
hot_temp
;
break
;
else
{
default:
for
(
i
=
0
;
i
<
ACPI_ACTIVE_COOLING_MAX_NR
;
i
++
)
{
break
;
if
(
d
->
act_trips
[
i
].
valid
&&
d
->
act_trips
[
i
].
id
==
trip
)
{
*
temp
=
d
->
act_trips
[
i
].
temp
;
break
;
}
}
if
(
i
==
ACPI_ACTIVE_COOLING_MAX_NR
)
return
-
EINVAL
;
}
}
return
0
;
}
static
int
int3402_thermal_get_trip_type
(
struct
thermal_zone_device
*
zone
,
int
trip
,
enum
thermal_trip_type
*
type
)
{
struct
int3402_thermal_data
*
d
=
zone
->
devdata
;
int
i
;
if
(
trip
<
d
->
aux_trip_nr
)
*
type
=
THERMAL_TRIP_PASSIVE
;
else
if
(
trip
==
d
->
crt_trip_id
)
*
type
=
THERMAL_TRIP_CRITICAL
;
else
if
(
trip
==
d
->
hot_trip_id
)
*
type
=
THERMAL_TRIP_HOT
;
else
if
(
trip
==
d
->
psv_trip_id
)
*
type
=
THERMAL_TRIP_PASSIVE
;
else
{
for
(
i
=
0
;
i
<
ACPI_ACTIVE_COOLING_MAX_NR
;
i
++
)
{
if
(
d
->
act_trips
[
i
].
valid
&&
d
->
act_trips
[
i
].
id
==
trip
)
{
*
type
=
THERMAL_TRIP_ACTIVE
;
break
;
}
}
if
(
i
==
ACPI_ACTIVE_COOLING_MAX_NR
)
return
-
EINVAL
;
}
return
0
;
}
static
int
int3402_thermal_set_trip_temp
(
struct
thermal_zone_device
*
zone
,
int
trip
,
unsigned
long
temp
)
{
struct
int3402_thermal_data
*
d
=
zone
->
devdata
;
acpi_status
status
;
char
name
[
10
];
snprintf
(
name
,
sizeof
(
name
),
"PAT%d"
,
trip
);
status
=
acpi_execute_simple_method
(
d
->
handle
,
name
,
MILLICELSIUS_TO_DECI_KELVIN
(
temp
));
if
(
ACPI_FAILURE
(
status
))
return
-
EIO
;
d
->
aux_trips
[
trip
]
=
temp
;
return
0
;
}
static
struct
thermal_zone_device_ops
int3402_thermal_zone_ops
=
{
.
get_temp
=
int3402_thermal_get_zone_temp
,
.
get_trip_temp
=
int3402_thermal_get_trip_temp
,
.
get_trip_type
=
int3402_thermal_get_trip_type
,
.
set_trip_temp
=
int3402_thermal_set_trip_temp
,
};
static
struct
thermal_zone_params
int3402_thermal_params
=
{
.
governor_name
=
"user_space"
,
.
no_hwmon
=
true
,
};
static
int
int3402_thermal_get_temp
(
acpi_handle
handle
,
char
*
name
,
unsigned
long
*
temp
)
{
unsigned
long
long
r
;
acpi_status
status
;
status
=
acpi_evaluate_integer
(
handle
,
name
,
NULL
,
&
r
);
if
(
ACPI_FAILURE
(
status
))
return
-
EIO
;
*
temp
=
DECI_KELVIN_TO_MILLICELSIUS
(
r
);
return
0
;
}
}
static
int
int3402_thermal_probe
(
struct
platform_device
*
pdev
)
static
int
int3402_thermal_probe
(
struct
platform_device
*
pdev
)
{
{
struct
acpi_device
*
adev
=
ACPI_COMPANION
(
&
pdev
->
dev
);
struct
acpi_device
*
adev
=
ACPI_COMPANION
(
&
pdev
->
dev
);
struct
int3402_thermal_data
*
d
;
struct
int3402_thermal_data
*
d
;
struct
thermal_zone_device
*
zone
;
int
ret
;
acpi_status
status
;
unsigned
long
long
trip_cnt
;
int
trip_mask
=
0
,
i
;
if
(
!
acpi_has_method
(
adev
->
handle
,
"_TMP"
))
if
(
!
acpi_has_method
(
adev
->
handle
,
"_TMP"
))
return
-
ENODEV
;
return
-
ENODEV
;
...
@@ -168,54 +55,33 @@ static int int3402_thermal_probe(struct platform_device *pdev)
...
@@ -168,54 +55,33 @@ static int int3402_thermal_probe(struct platform_device *pdev)
if
(
!
d
)
if
(
!
d
)
return
-
ENOMEM
;
return
-
ENOMEM
;
status
=
acpi_evaluate_integer
(
adev
->
handle
,
"PATC"
,
NULL
,
&
trip_cnt
);
d
->
int340x_zone
=
int340x_thermal_zone_add
(
adev
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
if
(
IS_ERR
(
d
->
int340x_zone
))
trip_cnt
=
0
;
return
PTR_ERR
(
d
->
int340x_zone
);
else
{
d
->
aux_trips
=
devm_kzalloc
(
&
pdev
->
dev
,
ret
=
acpi_install_notify_handler
(
adev
->
handle
,
sizeof
(
*
d
->
aux_trips
)
*
trip_cnt
,
GFP_KERNEL
);
ACPI_DEVICE_NOTIFY
,
if
(
!
d
->
aux_trips
)
int3402_notify
,
return
-
ENOMEM
;
d
);
trip_mask
=
trip_cnt
-
1
;
if
(
ret
)
{
d
->
handle
=
adev
->
handle
;
int340x_thermal_zone_remove
(
d
->
int340x_zone
);
d
->
aux_trip_nr
=
trip_cnt
;
return
ret
;
}
d
->
crt_trip_id
=
-
1
;
if
(
!
int3402_thermal_get_temp
(
adev
->
handle
,
"_CRT"
,
&
d
->
crt_temp
))
d
->
crt_trip_id
=
trip_cnt
++
;
d
->
hot_trip_id
=
-
1
;
if
(
!
int3402_thermal_get_temp
(
adev
->
handle
,
"_HOT"
,
&
d
->
hot_temp
))
d
->
hot_trip_id
=
trip_cnt
++
;
d
->
psv_trip_id
=
-
1
;
if
(
!
int3402_thermal_get_temp
(
adev
->
handle
,
"_PSV"
,
&
d
->
psv_temp
))
d
->
psv_trip_id
=
trip_cnt
++
;
for
(
i
=
0
;
i
<
ACPI_ACTIVE_COOLING_MAX_NR
;
i
++
)
{
char
name
[
5
]
=
{
'_'
,
'A'
,
'C'
,
'0'
+
i
,
'\0'
};
if
(
int3402_thermal_get_temp
(
adev
->
handle
,
name
,
&
d
->
act_trips
[
i
].
temp
))
break
;
d
->
act_trips
[
i
].
id
=
trip_cnt
++
;
d
->
act_trips
[
i
].
valid
=
true
;
}
}
zone
=
thermal_zone_device_register
(
acpi_device_bid
(
adev
),
trip_cnt
,
d
->
handle
=
adev
->
handle
;
trip_mask
,
d
,
platform_set_drvdata
(
pdev
,
d
);
&
int3402_thermal_zone_ops
,
&
int3402_thermal_params
,
0
,
0
);
if
(
IS_ERR
(
zone
))
return
PTR_ERR
(
zone
);
platform_set_drvdata
(
pdev
,
zone
);
return
0
;
return
0
;
}
}
static
int
int3402_thermal_remove
(
struct
platform_device
*
pdev
)
static
int
int3402_thermal_remove
(
struct
platform_device
*
pdev
)
{
{
struct
thermal_zone_device
*
zone
=
platform_get_drvdata
(
pdev
);
struct
int3402_thermal_data
*
d
=
platform_get_drvdata
(
pdev
);
acpi_remove_notify_handler
(
d
->
handle
,
ACPI_DEVICE_NOTIFY
,
int3402_notify
);
int340x_thermal_zone_remove
(
d
->
int340x_zone
);
thermal_zone_device_unregister
(
zone
);
return
0
;
return
0
;
}
}
...
...
drivers/thermal/int340x_thermal/int3403_thermal.c
浏览文件 @
8cb68501
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
#include <linux/acpi.h>
#include <linux/acpi.h>
#include <linux/thermal.h>
#include <linux/thermal.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include "int340x_thermal_zone.h"
#define INT3403_TYPE_SENSOR 0x03
#define INT3403_TYPE_SENSOR 0x03
#define INT3403_TYPE_CHARGER 0x0B
#define INT3403_TYPE_CHARGER 0x0B
...
@@ -26,18 +27,9 @@
...
@@ -26,18 +27,9 @@
#define INT3403_PERF_CHANGED_EVENT 0x80
#define INT3403_PERF_CHANGED_EVENT 0x80
#define INT3403_THERMAL_EVENT 0x90
#define INT3403_THERMAL_EVENT 0x90
#define DECI_KELVIN_TO_MILLI_CELSIUS(t, off) (((t) - (off)) * 100)
/* Preserved structure for future expandbility */
#define KELVIN_OFFSET 2732
#define MILLI_CELSIUS_TO_DECI_KELVIN(t, off) (((t) / 100) + (off))
struct
int3403_sensor
{
struct
int3403_sensor
{
struct
thermal_zone_device
*
tzone
;
struct
int34x_thermal_zone
*
int340x_zone
;
unsigned
long
*
thresholds
;
unsigned
long
crit_temp
;
int
crit_trip_id
;
unsigned
long
psv_temp
;
int
psv_trip_id
;
};
};
struct
int3403_performance_state
{
struct
int3403_performance_state
{
...
@@ -63,126 +55,6 @@ struct int3403_priv {
...
@@ -63,126 +55,6 @@ struct int3403_priv {
void
*
priv
;
void
*
priv
;
};
};
static
int
sys_get_curr_temp
(
struct
thermal_zone_device
*
tzone
,
unsigned
long
*
temp
)
{
struct
int3403_priv
*
priv
=
tzone
->
devdata
;
struct
acpi_device
*
device
=
priv
->
adev
;
unsigned
long
long
tmp
;
acpi_status
status
;
status
=
acpi_evaluate_integer
(
device
->
handle
,
"_TMP"
,
NULL
,
&
tmp
);
if
(
ACPI_FAILURE
(
status
))
return
-
EIO
;
*
temp
=
DECI_KELVIN_TO_MILLI_CELSIUS
(
tmp
,
KELVIN_OFFSET
);
return
0
;
}
static
int
sys_get_trip_hyst
(
struct
thermal_zone_device
*
tzone
,
int
trip
,
unsigned
long
*
temp
)
{
struct
int3403_priv
*
priv
=
tzone
->
devdata
;
struct
acpi_device
*
device
=
priv
->
adev
;
unsigned
long
long
hyst
;
acpi_status
status
;
status
=
acpi_evaluate_integer
(
device
->
handle
,
"GTSH"
,
NULL
,
&
hyst
);
if
(
ACPI_FAILURE
(
status
))
return
-
EIO
;
/*
* Thermal hysteresis represents a temperature difference.
* Kelvin and Celsius have same degree size. So the
* conversion here between tenths of degree Kelvin unit
* and Milli-Celsius unit is just to multiply 100.
*/
*
temp
=
hyst
*
100
;
return
0
;
}
static
int
sys_get_trip_temp
(
struct
thermal_zone_device
*
tzone
,
int
trip
,
unsigned
long
*
temp
)
{
struct
int3403_priv
*
priv
=
tzone
->
devdata
;
struct
int3403_sensor
*
obj
=
priv
->
priv
;
if
(
priv
->
type
!=
INT3403_TYPE_SENSOR
||
!
obj
)
return
-
EINVAL
;
if
(
trip
==
obj
->
crit_trip_id
)
*
temp
=
obj
->
crit_temp
;
else
if
(
trip
==
obj
->
psv_trip_id
)
*
temp
=
obj
->
psv_temp
;
else
{
/*
* get_trip_temp is a mandatory callback but
* PATx method doesn't return any value, so return
* cached value, which was last set from user space
*/
*
temp
=
obj
->
thresholds
[
trip
];
}
return
0
;
}
static
int
sys_get_trip_type
(
struct
thermal_zone_device
*
thermal
,
int
trip
,
enum
thermal_trip_type
*
type
)
{
struct
int3403_priv
*
priv
=
thermal
->
devdata
;
struct
int3403_sensor
*
obj
=
priv
->
priv
;
/* Mandatory callback, may not mean much here */
if
(
trip
==
obj
->
crit_trip_id
)
*
type
=
THERMAL_TRIP_CRITICAL
;
else
*
type
=
THERMAL_TRIP_PASSIVE
;
return
0
;
}
int
sys_set_trip_temp
(
struct
thermal_zone_device
*
tzone
,
int
trip
,
unsigned
long
temp
)
{
struct
int3403_priv
*
priv
=
tzone
->
devdata
;
struct
acpi_device
*
device
=
priv
->
adev
;
struct
int3403_sensor
*
obj
=
priv
->
priv
;
acpi_status
status
;
char
name
[
10
];
int
ret
=
0
;
snprintf
(
name
,
sizeof
(
name
),
"PAT%d"
,
trip
);
if
(
acpi_has_method
(
device
->
handle
,
name
))
{
status
=
acpi_execute_simple_method
(
device
->
handle
,
name
,
MILLI_CELSIUS_TO_DECI_KELVIN
(
temp
,
KELVIN_OFFSET
));
if
(
ACPI_FAILURE
(
status
))
ret
=
-
EIO
;
else
obj
->
thresholds
[
trip
]
=
temp
;
}
else
{
ret
=
-
EIO
;
dev_err
(
&
device
->
dev
,
"sys_set_trip_temp: method not found
\n
"
);
}
return
ret
;
}
static
struct
thermal_zone_device_ops
tzone_ops
=
{
.
get_temp
=
sys_get_curr_temp
,
.
get_trip_temp
=
sys_get_trip_temp
,
.
get_trip_type
=
sys_get_trip_type
,
.
set_trip_temp
=
sys_set_trip_temp
,
.
get_trip_hyst
=
sys_get_trip_hyst
,
};
static
struct
thermal_zone_params
int3403_thermal_params
=
{
.
governor_name
=
"user_space"
,
.
no_hwmon
=
true
,
};
static
void
int3403_notify
(
acpi_handle
handle
,
static
void
int3403_notify
(
acpi_handle
handle
,
u32
event
,
void
*
data
)
u32
event
,
void
*
data
)
{
{
...
@@ -200,7 +72,7 @@ static void int3403_notify(acpi_handle handle,
...
@@ -200,7 +72,7 @@ static void int3403_notify(acpi_handle handle,
case
INT3403_PERF_CHANGED_EVENT
:
case
INT3403_PERF_CHANGED_EVENT
:
break
;
break
;
case
INT3403_THERMAL_EVENT
:
case
INT3403_THERMAL_EVENT
:
thermal_zone_device_update
(
obj
->
t
zone
);
int340x_thermal_zone_device_update
(
obj
->
int340x_
zone
);
break
;
break
;
default:
default:
dev_err
(
&
priv
->
pdev
->
dev
,
"Unsupported event [0x%x]
\n
"
,
event
);
dev_err
(
&
priv
->
pdev
->
dev
,
"Unsupported event [0x%x]
\n
"
,
event
);
...
@@ -208,41 +80,10 @@ static void int3403_notify(acpi_handle handle,
...
@@ -208,41 +80,10 @@ static void int3403_notify(acpi_handle handle,
}
}
}
}
static
int
sys_get_trip_crt
(
struct
acpi_device
*
device
,
unsigned
long
*
temp
)
{
unsigned
long
long
crt
;
acpi_status
status
;
status
=
acpi_evaluate_integer
(
device
->
handle
,
"_CRT"
,
NULL
,
&
crt
);
if
(
ACPI_FAILURE
(
status
))
return
-
EIO
;
*
temp
=
DECI_KELVIN_TO_MILLI_CELSIUS
(
crt
,
KELVIN_OFFSET
);
return
0
;
}
static
int
sys_get_trip_psv
(
struct
acpi_device
*
device
,
unsigned
long
*
temp
)
{
unsigned
long
long
psv
;
acpi_status
status
;
status
=
acpi_evaluate_integer
(
device
->
handle
,
"_PSV"
,
NULL
,
&
psv
);
if
(
ACPI_FAILURE
(
status
))
return
-
EIO
;
*
temp
=
DECI_KELVIN_TO_MILLI_CELSIUS
(
psv
,
KELVIN_OFFSET
);
return
0
;
}
static
int
int3403_sensor_add
(
struct
int3403_priv
*
priv
)
static
int
int3403_sensor_add
(
struct
int3403_priv
*
priv
)
{
{
int
result
=
0
;
int
result
=
0
;
acpi_status
status
;
struct
int3403_sensor
*
obj
;
struct
int3403_sensor
*
obj
;
unsigned
long
long
trip_cnt
;
int
trip_mask
=
0
;
obj
=
devm_kzalloc
(
&
priv
->
pdev
->
dev
,
sizeof
(
*
obj
),
GFP_KERNEL
);
obj
=
devm_kzalloc
(
&
priv
->
pdev
->
dev
,
sizeof
(
*
obj
),
GFP_KERNEL
);
if
(
!
obj
)
if
(
!
obj
)
...
@@ -250,39 +91,9 @@ static int int3403_sensor_add(struct int3403_priv *priv)
...
@@ -250,39 +91,9 @@ static int int3403_sensor_add(struct int3403_priv *priv)
priv
->
priv
=
obj
;
priv
->
priv
=
obj
;
status
=
acpi_evaluate_integer
(
priv
->
adev
->
handle
,
"PATC"
,
NULL
,
obj
->
int340x_zone
=
int340x_thermal_zone_add
(
priv
->
adev
,
NULL
);
&
trip_cnt
);
if
(
IS_ERR
(
obj
->
int340x_zone
))
if
(
ACPI_FAILURE
(
status
))
return
PTR_ERR
(
obj
->
int340x_zone
);
trip_cnt
=
0
;
if
(
trip_cnt
)
{
/* We have to cache, thresholds can't be readback */
obj
->
thresholds
=
devm_kzalloc
(
&
priv
->
pdev
->
dev
,
sizeof
(
*
obj
->
thresholds
)
*
trip_cnt
,
GFP_KERNEL
);
if
(
!
obj
->
thresholds
)
{
result
=
-
ENOMEM
;
goto
err_free_obj
;
}
trip_mask
=
BIT
(
trip_cnt
)
-
1
;
}
obj
->
psv_trip_id
=
-
1
;
if
(
!
sys_get_trip_psv
(
priv
->
adev
,
&
obj
->
psv_temp
))
obj
->
psv_trip_id
=
trip_cnt
++
;
obj
->
crit_trip_id
=
-
1
;
if
(
!
sys_get_trip_crt
(
priv
->
adev
,
&
obj
->
crit_temp
))
obj
->
crit_trip_id
=
trip_cnt
++
;
obj
->
tzone
=
thermal_zone_device_register
(
acpi_device_bid
(
priv
->
adev
),
trip_cnt
,
trip_mask
,
priv
,
&
tzone_ops
,
&
int3403_thermal_params
,
0
,
0
);
if
(
IS_ERR
(
obj
->
tzone
))
{
result
=
PTR_ERR
(
obj
->
tzone
);
obj
->
tzone
=
NULL
;
goto
err_free_obj
;
}
result
=
acpi_install_notify_handler
(
priv
->
adev
->
handle
,
result
=
acpi_install_notify_handler
(
priv
->
adev
->
handle
,
ACPI_DEVICE_NOTIFY
,
int3403_notify
,
ACPI_DEVICE_NOTIFY
,
int3403_notify
,
...
@@ -293,7 +104,7 @@ static int int3403_sensor_add(struct int3403_priv *priv)
...
@@ -293,7 +104,7 @@ static int int3403_sensor_add(struct int3403_priv *priv)
return
0
;
return
0
;
err_free_obj:
err_free_obj:
thermal_zone_device_unregister
(
obj
->
t
zone
);
int340x_thermal_zone_remove
(
obj
->
int340x_
zone
);
return
result
;
return
result
;
}
}
...
@@ -303,7 +114,8 @@ static int int3403_sensor_remove(struct int3403_priv *priv)
...
@@ -303,7 +114,8 @@ static int int3403_sensor_remove(struct int3403_priv *priv)
acpi_remove_notify_handler
(
priv
->
adev
->
handle
,
acpi_remove_notify_handler
(
priv
->
adev
->
handle
,
ACPI_DEVICE_NOTIFY
,
int3403_notify
);
ACPI_DEVICE_NOTIFY
,
int3403_notify
);
thermal_zone_device_unregister
(
obj
->
tzone
);
int340x_thermal_zone_remove
(
obj
->
int340x_zone
);
return
0
;
return
0
;
}
}
...
...
drivers/thermal/int340x_thermal/int340x_thermal_zone.c
0 → 100644
浏览文件 @
8cb68501
/*
* int340x_thermal_zone.c
* Copyright (c) 2015, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/thermal.h>
#include "int340x_thermal_zone.h"
static
int
int340x_thermal_get_zone_temp
(
struct
thermal_zone_device
*
zone
,
unsigned
long
*
temp
)
{
struct
int34x_thermal_zone
*
d
=
zone
->
devdata
;
unsigned
long
long
tmp
;
acpi_status
status
;
if
(
d
->
override_ops
&&
d
->
override_ops
->
get_temp
)
return
d
->
override_ops
->
get_temp
(
zone
,
temp
);
status
=
acpi_evaluate_integer
(
d
->
adev
->
handle
,
"_TMP"
,
NULL
,
&
tmp
);
if
(
ACPI_FAILURE
(
status
))
return
-
EIO
;
if
(
d
->
lpat_table
)
{
int
conv_temp
;
conv_temp
=
acpi_lpat_raw_to_temp
(
d
->
lpat_table
,
(
int
)
tmp
);
if
(
conv_temp
<
0
)
return
conv_temp
;
*
temp
=
(
unsigned
long
)
conv_temp
*
10
;
}
else
/* _TMP returns the temperature in tenths of degrees Kelvin */
*
temp
=
DECI_KELVIN_TO_MILLICELSIUS
(
tmp
);
return
0
;
}
static
int
int340x_thermal_get_trip_temp
(
struct
thermal_zone_device
*
zone
,
int
trip
,
unsigned
long
*
temp
)
{
struct
int34x_thermal_zone
*
d
=
zone
->
devdata
;
int
i
;
if
(
d
->
override_ops
&&
d
->
override_ops
->
get_trip_temp
)
return
d
->
override_ops
->
get_trip_temp
(
zone
,
trip
,
temp
);
if
(
trip
<
d
->
aux_trip_nr
)
*
temp
=
d
->
aux_trips
[
trip
];
else
if
(
trip
==
d
->
crt_trip_id
)
*
temp
=
d
->
crt_temp
;
else
if
(
trip
==
d
->
psv_trip_id
)
*
temp
=
d
->
psv_temp
;
else
if
(
trip
==
d
->
hot_trip_id
)
*
temp
=
d
->
hot_temp
;
else
{
for
(
i
=
0
;
i
<
INT340X_THERMAL_MAX_ACT_TRIP_COUNT
;
i
++
)
{
if
(
d
->
act_trips
[
i
].
valid
&&
d
->
act_trips
[
i
].
id
==
trip
)
{
*
temp
=
d
->
act_trips
[
i
].
temp
;
break
;
}
}
if
(
i
==
INT340X_THERMAL_MAX_ACT_TRIP_COUNT
)
return
-
EINVAL
;
}
return
0
;
}
static
int
int340x_thermal_get_trip_type
(
struct
thermal_zone_device
*
zone
,
int
trip
,
enum
thermal_trip_type
*
type
)
{
struct
int34x_thermal_zone
*
d
=
zone
->
devdata
;
int
i
;
if
(
d
->
override_ops
&&
d
->
override_ops
->
get_trip_type
)
return
d
->
override_ops
->
get_trip_type
(
zone
,
trip
,
type
);
if
(
trip
<
d
->
aux_trip_nr
)
*
type
=
THERMAL_TRIP_PASSIVE
;
else
if
(
trip
==
d
->
crt_trip_id
)
*
type
=
THERMAL_TRIP_CRITICAL
;
else
if
(
trip
==
d
->
hot_trip_id
)
*
type
=
THERMAL_TRIP_HOT
;
else
if
(
trip
==
d
->
psv_trip_id
)
*
type
=
THERMAL_TRIP_PASSIVE
;
else
{
for
(
i
=
0
;
i
<
INT340X_THERMAL_MAX_ACT_TRIP_COUNT
;
i
++
)
{
if
(
d
->
act_trips
[
i
].
valid
&&
d
->
act_trips
[
i
].
id
==
trip
)
{
*
type
=
THERMAL_TRIP_ACTIVE
;
break
;
}
}
if
(
i
==
INT340X_THERMAL_MAX_ACT_TRIP_COUNT
)
return
-
EINVAL
;
}
return
0
;
}
static
int
int340x_thermal_set_trip_temp
(
struct
thermal_zone_device
*
zone
,
int
trip
,
unsigned
long
temp
)
{
struct
int34x_thermal_zone
*
d
=
zone
->
devdata
;
acpi_status
status
;
char
name
[
10
];
if
(
d
->
override_ops
&&
d
->
override_ops
->
set_trip_temp
)
return
d
->
override_ops
->
set_trip_temp
(
zone
,
trip
,
temp
);
snprintf
(
name
,
sizeof
(
name
),
"PAT%d"
,
trip
);
status
=
acpi_execute_simple_method
(
d
->
adev
->
handle
,
name
,
MILLICELSIUS_TO_DECI_KELVIN
(
temp
));
if
(
ACPI_FAILURE
(
status
))
return
-
EIO
;
d
->
aux_trips
[
trip
]
=
temp
;
return
0
;
}
static
int
int340x_thermal_get_trip_hyst
(
struct
thermal_zone_device
*
zone
,
int
trip
,
unsigned
long
*
temp
)
{
struct
int34x_thermal_zone
*
d
=
zone
->
devdata
;
acpi_status
status
;
unsigned
long
long
hyst
;
if
(
d
->
override_ops
&&
d
->
override_ops
->
get_trip_hyst
)
return
d
->
override_ops
->
get_trip_hyst
(
zone
,
trip
,
temp
);
status
=
acpi_evaluate_integer
(
d
->
adev
->
handle
,
"GTSH"
,
NULL
,
&
hyst
);
if
(
ACPI_FAILURE
(
status
))
return
-
EIO
;
*
temp
=
hyst
*
100
;
return
0
;
}
static
struct
thermal_zone_device_ops
int340x_thermal_zone_ops
=
{
.
get_temp
=
int340x_thermal_get_zone_temp
,
.
get_trip_temp
=
int340x_thermal_get_trip_temp
,
.
get_trip_type
=
int340x_thermal_get_trip_type
,
.
set_trip_temp
=
int340x_thermal_set_trip_temp
,
.
get_trip_hyst
=
int340x_thermal_get_trip_hyst
,
};
static
int
int340x_thermal_get_trip_config
(
acpi_handle
handle
,
char
*
name
,
unsigned
long
*
temp
)
{
unsigned
long
long
r
;
acpi_status
status
;
status
=
acpi_evaluate_integer
(
handle
,
name
,
NULL
,
&
r
);
if
(
ACPI_FAILURE
(
status
))
return
-
EIO
;
*
temp
=
DECI_KELVIN_TO_MILLICELSIUS
(
r
);
return
0
;
}
static
struct
thermal_zone_params
int340x_thermal_params
=
{
.
governor_name
=
"user_space"
,
.
no_hwmon
=
true
,
};
struct
int34x_thermal_zone
*
int340x_thermal_zone_add
(
struct
acpi_device
*
adev
,
struct
thermal_zone_device_ops
*
override_ops
)
{
struct
int34x_thermal_zone
*
int34x_thermal_zone
;
acpi_status
status
;
unsigned
long
long
trip_cnt
;
int
trip_mask
=
0
,
i
;
int
ret
;
int34x_thermal_zone
=
kzalloc
(
sizeof
(
*
int34x_thermal_zone
),
GFP_KERNEL
);
if
(
!
int34x_thermal_zone
)
return
ERR_PTR
(
-
ENOMEM
);
int34x_thermal_zone
->
adev
=
adev
;
int34x_thermal_zone
->
override_ops
=
override_ops
;
status
=
acpi_evaluate_integer
(
adev
->
handle
,
"PATC"
,
NULL
,
&
trip_cnt
);
if
(
ACPI_FAILURE
(
status
))
trip_cnt
=
0
;
else
{
int34x_thermal_zone
->
aux_trips
=
kzalloc
(
sizeof
(
*
int34x_thermal_zone
->
aux_trips
)
*
trip_cnt
,
GFP_KERNEL
);
if
(
!
int34x_thermal_zone
->
aux_trips
)
{
ret
=
-
ENOMEM
;
goto
free_mem
;
}
trip_mask
=
BIT
(
trip_cnt
)
-
1
;
int34x_thermal_zone
->
aux_trip_nr
=
trip_cnt
;
}
int34x_thermal_zone
->
crt_trip_id
=
-
1
;
if
(
!
int340x_thermal_get_trip_config
(
adev
->
handle
,
"_CRT"
,
&
int34x_thermal_zone
->
crt_temp
))
int34x_thermal_zone
->
crt_trip_id
=
trip_cnt
++
;
int34x_thermal_zone
->
hot_trip_id
=
-
1
;
if
(
!
int340x_thermal_get_trip_config
(
adev
->
handle
,
"_HOT"
,
&
int34x_thermal_zone
->
hot_temp
))
int34x_thermal_zone
->
hot_trip_id
=
trip_cnt
++
;
int34x_thermal_zone
->
psv_trip_id
=
-
1
;
if
(
!
int340x_thermal_get_trip_config
(
adev
->
handle
,
"_PSV"
,
&
int34x_thermal_zone
->
psv_temp
))
int34x_thermal_zone
->
psv_trip_id
=
trip_cnt
++
;
for
(
i
=
0
;
i
<
INT340X_THERMAL_MAX_ACT_TRIP_COUNT
;
i
++
)
{
char
name
[
5
]
=
{
'_'
,
'A'
,
'C'
,
'0'
+
i
,
'\0'
};
if
(
int340x_thermal_get_trip_config
(
adev
->
handle
,
name
,
&
int34x_thermal_zone
->
act_trips
[
i
].
temp
))
break
;
int34x_thermal_zone
->
act_trips
[
i
].
id
=
trip_cnt
++
;
int34x_thermal_zone
->
act_trips
[
i
].
valid
=
true
;
}
int34x_thermal_zone
->
lpat_table
=
acpi_lpat_get_conversion_table
(
adev
->
handle
);
int34x_thermal_zone
->
zone
=
thermal_zone_device_register
(
acpi_device_bid
(
adev
),
trip_cnt
,
trip_mask
,
int34x_thermal_zone
,
&
int340x_thermal_zone_ops
,
&
int340x_thermal_params
,
0
,
0
);
if
(
IS_ERR
(
int34x_thermal_zone
->
zone
))
{
ret
=
PTR_ERR
(
int34x_thermal_zone
->
zone
);
goto
free_lpat
;
}
return
int34x_thermal_zone
;
free_lpat:
acpi_lpat_free_conversion_table
(
int34x_thermal_zone
->
lpat_table
);
free_mem:
kfree
(
int34x_thermal_zone
);
return
ERR_PTR
(
ret
);
}
EXPORT_SYMBOL_GPL
(
int340x_thermal_zone_add
);
void
int340x_thermal_zone_remove
(
struct
int34x_thermal_zone
*
int34x_thermal_zone
)
{
thermal_zone_device_unregister
(
int34x_thermal_zone
->
zone
);
acpi_lpat_free_conversion_table
(
int34x_thermal_zone
->
lpat_table
);
kfree
(
int34x_thermal_zone
);
}
EXPORT_SYMBOL_GPL
(
int340x_thermal_zone_remove
);
MODULE_AUTHOR
(
"Aaron Lu <aaron.lu@intel.com>"
);
MODULE_AUTHOR
(
"Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"
);
MODULE_DESCRIPTION
(
"Intel INT340x common thermal zone handler"
);
MODULE_LICENSE
(
"GPL v2"
);
drivers/thermal/int340x_thermal/int340x_thermal_zone.h
0 → 100644
浏览文件 @
8cb68501
/*
* int340x_thermal_zone.h
* Copyright (c) 2015, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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 __INT340X_THERMAL_ZONE_H__
#define __INT340X_THERMAL_ZONE_H__
#include <acpi/acpi_lpat.h>
#define INT340X_THERMAL_MAX_ACT_TRIP_COUNT 10
struct
active_trip
{
unsigned
long
temp
;
int
id
;
bool
valid
;
};
struct
int34x_thermal_zone
{
struct
acpi_device
*
adev
;
struct
active_trip
act_trips
[
INT340X_THERMAL_MAX_ACT_TRIP_COUNT
];
unsigned
long
*
aux_trips
;
int
aux_trip_nr
;
unsigned
long
psv_temp
;
int
psv_trip_id
;
unsigned
long
crt_temp
;
int
crt_trip_id
;
unsigned
long
hot_temp
;
int
hot_trip_id
;
struct
thermal_zone_device
*
zone
;
struct
thermal_zone_device_ops
*
override_ops
;
void
*
priv_data
;
struct
acpi_lpat_conversion_table
*
lpat_table
;
};
struct
int34x_thermal_zone
*
int340x_thermal_zone_add
(
struct
acpi_device
*
,
struct
thermal_zone_device_ops
*
override_ops
);
void
int340x_thermal_zone_remove
(
struct
int34x_thermal_zone
*
);
static
inline
void
int340x_thermal_zone_set_priv_data
(
struct
int34x_thermal_zone
*
tzone
,
void
*
priv_data
)
{
tzone
->
priv_data
=
priv_data
;
}
static
inline
void
*
int340x_thermal_zone_get_priv_data
(
struct
int34x_thermal_zone
*
tzone
)
{
return
tzone
->
priv_data
;
}
static
inline
void
int340x_thermal_zone_device_update
(
struct
int34x_thermal_zone
*
tzone
)
{
thermal_zone_device_update
(
tzone
->
zone
);
}
#endif
drivers/thermal/int340x_thermal/processor_thermal_device.c
浏览文件 @
8cb68501
...
@@ -18,6 +18,8 @@
...
@@ -18,6 +18,8 @@
#include <linux/pci.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/acpi.h>
#include <linux/thermal.h>
#include "int340x_thermal_zone.h"
/* Broadwell-U/HSB thermal reporting device */
/* Broadwell-U/HSB thermal reporting device */
#define PCI_DEVICE_ID_PROC_BDW_THERMAL 0x1603
#define PCI_DEVICE_ID_PROC_BDW_THERMAL 0x1603
...
@@ -39,6 +41,7 @@ struct proc_thermal_device {
...
@@ -39,6 +41,7 @@ struct proc_thermal_device {
struct
device
*
dev
;
struct
device
*
dev
;
struct
acpi_device
*
adev
;
struct
acpi_device
*
adev
;
struct
power_config
power_limits
[
2
];
struct
power_config
power_limits
[
2
];
struct
int34x_thermal_zone
*
int340x_zone
;
};
};
enum
proc_thermal_emum_mode_type
{
enum
proc_thermal_emum_mode_type
{
...
@@ -117,6 +120,72 @@ static struct attribute_group power_limit_attribute_group = {
...
@@ -117,6 +120,72 @@ static struct attribute_group power_limit_attribute_group = {
.
name
=
"power_limits"
.
name
=
"power_limits"
};
};
static
int
stored_tjmax
;
/* since it is fixed, we can have local storage */
static
int
get_tjmax
(
void
)
{
u32
eax
,
edx
;
u32
val
;
int
err
;
err
=
rdmsr_safe
(
MSR_IA32_TEMPERATURE_TARGET
,
&
eax
,
&
edx
);
if
(
err
)
return
err
;
val
=
(
eax
>>
16
)
&
0xff
;
if
(
val
)
return
val
;
return
-
EINVAL
;
}
static
int
read_temp_msr
(
unsigned
long
*
temp
)
{
int
cpu
;
u32
eax
,
edx
;
int
err
;
unsigned
long
curr_temp_off
=
0
;
*
temp
=
0
;
for_each_online_cpu
(
cpu
)
{
err
=
rdmsr_safe_on_cpu
(
cpu
,
MSR_IA32_THERM_STATUS
,
&
eax
,
&
edx
);
if
(
err
)
goto
err_ret
;
else
{
if
(
eax
&
0x80000000
)
{
curr_temp_off
=
(
eax
>>
16
)
&
0x7f
;
if
(
!*
temp
||
curr_temp_off
<
*
temp
)
*
temp
=
curr_temp_off
;
}
else
{
err
=
-
EINVAL
;
goto
err_ret
;
}
}
}
return
0
;
err_ret:
return
err
;
}
static
int
proc_thermal_get_zone_temp
(
struct
thermal_zone_device
*
zone
,
unsigned
long
*
temp
)
{
int
ret
;
ret
=
read_temp_msr
(
temp
);
if
(
!
ret
)
*
temp
=
(
stored_tjmax
-
*
temp
)
*
1000
;
return
ret
;
}
static
struct
thermal_zone_device_ops
proc_thermal_local_ops
=
{
.
get_temp
=
proc_thermal_get_zone_temp
,
};
static
int
proc_thermal_add
(
struct
device
*
dev
,
static
int
proc_thermal_add
(
struct
device
*
dev
,
struct
proc_thermal_device
**
priv
)
struct
proc_thermal_device
**
priv
)
{
{
...
@@ -126,6 +195,8 @@ static int proc_thermal_add(struct device *dev,
...
@@ -126,6 +195,8 @@ static int proc_thermal_add(struct device *dev,
struct
acpi_buffer
buf
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
struct
acpi_buffer
buf
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
elements
,
*
ppcc
;
union
acpi_object
*
elements
,
*
ppcc
;
union
acpi_object
*
p
;
union
acpi_object
*
p
;
unsigned
long
long
tmp
;
struct
thermal_zone_device_ops
*
ops
=
NULL
;
int
i
;
int
i
;
int
ret
;
int
ret
;
...
@@ -178,6 +249,24 @@ static int proc_thermal_add(struct device *dev,
...
@@ -178,6 +249,24 @@ static int proc_thermal_add(struct device *dev,
ret
=
sysfs_create_group
(
&
dev
->
kobj
,
ret
=
sysfs_create_group
(
&
dev
->
kobj
,
&
power_limit_attribute_group
);
&
power_limit_attribute_group
);
if
(
ret
)
goto
free_buffer
;
status
=
acpi_evaluate_integer
(
adev
->
handle
,
"_TMP"
,
NULL
,
&
tmp
);
if
(
ACPI_FAILURE
(
status
))
{
/* there is no _TMP method, add local method */
stored_tjmax
=
get_tjmax
();
if
(
stored_tjmax
>
0
)
ops
=
&
proc_thermal_local_ops
;
}
proc_priv
->
int340x_zone
=
int340x_thermal_zone_add
(
adev
,
ops
);
if
(
IS_ERR
(
proc_priv
->
int340x_zone
))
{
sysfs_remove_group
(
&
proc_priv
->
dev
->
kobj
,
&
power_limit_attribute_group
);
ret
=
PTR_ERR
(
proc_priv
->
int340x_zone
);
}
else
ret
=
0
;
free_buffer:
free_buffer:
kfree
(
buf
.
pointer
);
kfree
(
buf
.
pointer
);
...
@@ -187,6 +276,7 @@ static int proc_thermal_add(struct device *dev,
...
@@ -187,6 +276,7 @@ static int proc_thermal_add(struct device *dev,
void
proc_thermal_remove
(
struct
proc_thermal_device
*
proc_priv
)
void
proc_thermal_remove
(
struct
proc_thermal_device
*
proc_priv
)
{
{
int340x_thermal_zone_remove
(
proc_priv
->
int340x_zone
);
sysfs_remove_group
(
&
proc_priv
->
dev
->
kobj
,
sysfs_remove_group
(
&
proc_priv
->
dev
->
kobj
,
&
power_limit_attribute_group
);
&
power_limit_attribute_group
);
}
}
...
...
include/acpi/acpi_lpat.h
0 → 100644
浏览文件 @
8cb68501
/*
* acpi_lpat.h - LPAT table processing functions
*
* Copyright (C) 2015 Intel Corporation. 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 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 ACPI_LPAT_H
#define ACPI_LPAT_H
struct
acpi_lpat
{
int
temp
;
int
raw
;
};
struct
acpi_lpat_conversion_table
{
struct
acpi_lpat
*
lpat
;
int
lpat_count
;
};
#ifdef CONFIG_ACPI
int
acpi_lpat_raw_to_temp
(
struct
acpi_lpat_conversion_table
*
lpat_table
,
int
raw
);
int
acpi_lpat_temp_to_raw
(
struct
acpi_lpat_conversion_table
*
lpat_table
,
int
temp
);
struct
acpi_lpat_conversion_table
*
acpi_lpat_get_conversion_table
(
acpi_handle
handle
);
void
acpi_lpat_free_conversion_table
(
struct
acpi_lpat_conversion_table
*
lpat_table
);
#else
static
int
acpi_lpat_raw_to_temp
(
struct
acpi_lpat_conversion_table
*
lpat_table
,
int
raw
)
{
return
0
;
}
static
int
acpi_lpat_temp_to_raw
(
struct
acpi_lpat_conversion_table
*
lpat_table
,
int
temp
)
{
return
0
;
}
static
struct
acpi_lpat_conversion_table
*
acpi_lpat_get_conversion_table
(
acpi_handle
handle
)
{
return
NULL
;
}
static
void
acpi_lpat_free_conversion_table
(
struct
acpi_lpat_conversion_table
*
lpat_table
)
{
}
#endif
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录