Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
6ceaf58a
Commit
6ceaf58a
authored
Oct 17, 2014
by
Zhang Rui
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'int340x-thermal' of .git into next
parents
9ceaa81e
d8054749
Changes
21
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1867 additions
and
112 deletions
+1867
-112
drivers/acpi/Kconfig
drivers/acpi/Kconfig
+1
-1
drivers/acpi/Makefile
drivers/acpi/Makefile
+1
-0
drivers/acpi/acpi_platform.c
drivers/acpi/acpi_platform.c
+1
-0
drivers/acpi/device_pm.c
drivers/acpi/device_pm.c
+1
-0
drivers/acpi/fan.c
drivers/acpi/fan.c
+265
-76
drivers/acpi/int340x_thermal.c
drivers/acpi/int340x_thermal.c
+51
-0
drivers/acpi/internal.h
drivers/acpi/internal.h
+1
-9
drivers/acpi/scan.c
drivers/acpi/scan.c
+1
-0
drivers/acpi/thermal.c
drivers/acpi/thermal.c
+9
-9
drivers/acpi/utils.c
drivers/acpi/utils.c
+27
-1
drivers/thermal/Kconfig
drivers/thermal/Kconfig
+24
-15
drivers/thermal/Makefile
drivers/thermal/Makefile
+1
-1
drivers/thermal/int340x_thermal/Makefile
drivers/thermal/int340x_thermal/Makefile
+4
-0
drivers/thermal/int340x_thermal/acpi_thermal_rel.c
drivers/thermal/int340x_thermal/acpi_thermal_rel.c
+400
-0
drivers/thermal/int340x_thermal/acpi_thermal_rel.h
drivers/thermal/int340x_thermal/acpi_thermal_rel.h
+84
-0
drivers/thermal/int340x_thermal/int3400_thermal.c
drivers/thermal/int340x_thermal/int3400_thermal.c
+271
-0
drivers/thermal/int340x_thermal/int3402_thermal.c
drivers/thermal/int340x_thermal/int3402_thermal.c
+242
-0
drivers/thermal/int340x_thermal/int3403_thermal.c
drivers/thermal/int340x_thermal/int3403_thermal.c
+477
-0
include/acpi/acpi_bus.h
include/acpi/acpi_bus.h
+1
-0
include/linux/acpi.h
include/linux/acpi.h
+1
-0
include/linux/thermal.h
include/linux/thermal.h
+4
-0
No files found.
drivers/acpi/Kconfig
View file @
6ceaf58a
...
...
@@ -144,7 +144,7 @@ config ACPI_VIDEO
config ACPI_FAN
tristate "Fan"
select
THERMAL
depends on
THERMAL
default y
help
This driver supports ACPI fan devices, allowing user-mode
...
...
drivers/acpi/Makefile
View file @
6ceaf58a
...
...
@@ -43,6 +43,7 @@ acpi-y += pci_root.o pci_link.o pci_irq.o
acpi-y
+=
acpi_lpss.o
acpi-y
+=
acpi_platform.o
acpi-y
+=
acpi_pnp.o
acpi-y
+=
int340x_thermal.o
acpi-y
+=
power.o
acpi-y
+=
event.o
acpi-y
+=
sysfs.o
...
...
drivers/acpi/acpi_platform.c
View file @
6ceaf58a
...
...
@@ -113,3 +113,4 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
kfree
(
resources
);
return
pdev
;
}
EXPORT_SYMBOL_GPL
(
acpi_create_platform_device
);
drivers/acpi/device_pm.c
View file @
6ceaf58a
...
...
@@ -343,6 +343,7 @@ int acpi_device_update_power(struct acpi_device *device, int *state_p)
return
0
;
}
EXPORT_SYMBOL_GPL
(
acpi_device_update_power
);
int
acpi_bus_update_power
(
acpi_handle
handle
,
int
*
state_p
)
{
...
...
drivers/acpi/fan.c
View file @
6ceaf58a
This diff is collapsed.
Click to expand it.
drivers/acpi/int340x_thermal.c
0 → 100644
View file @
6ceaf58a
/*
* ACPI support for int340x thermal drivers
*
* Copyright (C) 2014, Intel Corporation
* Authors: Zhang Rui <rui.zhang@intel.com>
*
* 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.
*/
#include <linux/acpi.h>
#include <linux/module.h>
#include "internal.h"
#define DO_ENUMERATION 0x01
static
const
struct
acpi_device_id
int340x_thermal_device_ids
[]
=
{
{
"INT3400"
,
DO_ENUMERATION
},
{
"INT3401"
},
{
"INT3402"
},
{
"INT3403"
},
{
"INT3404"
},
{
"INT3406"
},
{
"INT3407"
},
{
"INT3408"
},
{
"INT3409"
},
{
"INT340A"
},
{
"INT340B"
},
{
""
},
};
static
int
int340x_thermal_handler_attach
(
struct
acpi_device
*
adev
,
const
struct
acpi_device_id
*
id
)
{
#if defined(CONFIG_INT340X_THERMAL) || defined(CONFIG_INT340X_THERMAL_MODULE)
if
(
id
->
driver_data
==
DO_ENUMERATION
)
acpi_create_platform_device
(
adev
);
#endif
return
1
;
}
static
struct
acpi_scan_handler
int340x_thermal_handler
=
{
.
ids
=
int340x_thermal_device_ids
,
.
attach
=
int340x_thermal_handler_attach
,
};
void
__init
acpi_int340x_thermal_init
(
void
)
{
acpi_scan_add_handler
(
&
int340x_thermal_handler
);
}
drivers/acpi/internal.h
View file @
6ceaf58a
...
...
@@ -31,6 +31,7 @@ void acpi_pci_link_init(void);
void
acpi_processor_init
(
void
);
void
acpi_platform_init
(
void
);
void
acpi_pnp_init
(
void
);
void
acpi_int340x_thermal_init
(
void
);
int
acpi_sysfs_init
(
void
);
void
acpi_container_init
(
void
);
void
acpi_memory_hotplug_init
(
void
);
...
...
@@ -103,8 +104,6 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
int
acpi_power_on_resources
(
struct
acpi_device
*
device
,
int
state
);
int
acpi_power_transition
(
struct
acpi_device
*
device
,
int
state
);
int
acpi_device_update_power
(
struct
acpi_device
*
device
,
int
*
state_p
);
int
acpi_wakeup_device_init
(
void
);
#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
...
...
@@ -167,13 +166,6 @@ static inline int suspend_nvs_save(void) { return 0; }
static
inline
void
suspend_nvs_restore
(
void
)
{}
#endif
/*--------------------------------------------------------------------------
Platform bus support
-------------------------------------------------------------------------- */
struct
platform_device
;
struct
platform_device
*
acpi_create_platform_device
(
struct
acpi_device
*
adev
);
/*--------------------------------------------------------------------------
Video
-------------------------------------------------------------------------- */
...
...
drivers/acpi/scan.c
View file @
6ceaf58a
...
...
@@ -2306,6 +2306,7 @@ int __init acpi_scan_init(void)
acpi_container_init
();
acpi_memory_hotplug_init
();
acpi_pnp_init
();
acpi_int340x_thermal_init
();
mutex_lock
(
&
acpi_scan_lock
);
/*
...
...
drivers/acpi/thermal.c
View file @
6ceaf58a
...
...
@@ -528,7 +528,6 @@ static void acpi_thermal_check(void *data)
}
/* sys I/F for generic thermal sysfs support */
#define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
static
int
thermal_get_temp
(
struct
thermal_zone_device
*
thermal
,
unsigned
long
*
temp
)
...
...
@@ -543,7 +542,8 @@ static int thermal_get_temp(struct thermal_zone_device *thermal,
if
(
result
)
return
result
;
*
temp
=
KELVIN_TO_MILLICELSIUS
(
tz
->
temperature
,
tz
->
kelvin_offset
);
*
temp
=
DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET
(
tz
->
temperature
,
tz
->
kelvin_offset
);
return
0
;
}
...
...
@@ -647,7 +647,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
if
(
tz
->
trips
.
critical
.
flags
.
valid
)
{
if
(
!
trip
)
{
*
temp
=
KELVIN_TO_MILLICELSIUS
(
*
temp
=
DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET
(
tz
->
trips
.
critical
.
temperature
,
tz
->
kelvin_offset
);
return
0
;
...
...
@@ -657,7 +657,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
if
(
tz
->
trips
.
hot
.
flags
.
valid
)
{
if
(
!
trip
)
{
*
temp
=
KELVIN_TO_MILLICELSIUS
(
*
temp
=
DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET
(
tz
->
trips
.
hot
.
temperature
,
tz
->
kelvin_offset
);
return
0
;
...
...
@@ -667,7 +667,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
if
(
tz
->
trips
.
passive
.
flags
.
valid
)
{
if
(
!
trip
)
{
*
temp
=
KELVIN_TO_MILLICELSIUS
(
*
temp
=
DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET
(
tz
->
trips
.
passive
.
temperature
,
tz
->
kelvin_offset
);
return
0
;
...
...
@@ -678,7 +678,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
for
(
i
=
0
;
i
<
ACPI_THERMAL_MAX_ACTIVE
&&
tz
->
trips
.
active
[
i
].
flags
.
valid
;
i
++
)
{
if
(
!
trip
)
{
*
temp
=
KELVIN_TO_MILLICELSIUS
(
*
temp
=
DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET
(
tz
->
trips
.
active
[
i
].
temperature
,
tz
->
kelvin_offset
);
return
0
;
...
...
@@ -694,7 +694,7 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
struct
acpi_thermal
*
tz
=
thermal
->
devdata
;
if
(
tz
->
trips
.
critical
.
flags
.
valid
)
{
*
temperature
=
KELVIN_TO_MILLICELSIUS
(
*
temperature
=
DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET
(
tz
->
trips
.
critical
.
temperature
,
tz
->
kelvin_offset
);
return
0
;
...
...
@@ -714,8 +714,8 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
if
(
type
==
THERMAL_TRIP_ACTIVE
)
{
unsigned
long
trip_temp
;
unsigned
long
temp
=
KELVIN_TO_MILLICELSIUS
(
tz
->
temperature
,
tz
->
kelvin_offset
);
unsigned
long
temp
=
DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET
(
tz
->
temperature
,
tz
->
kelvin_offset
);
if
(
thermal_get_trip_temp
(
thermal
,
trip
,
&
trip_temp
))
return
-
EINVAL
;
...
...
drivers/acpi/utils.c
View file @
6ceaf58a
...
...
@@ -149,6 +149,21 @@ acpi_extract_package(union acpi_object *package,
break
;
}
break
;
case
ACPI_TYPE_LOCAL_REFERENCE
:
switch
(
format_string
[
i
])
{
case
'R'
:
size_required
+=
sizeof
(
void
*
);
tail_offset
+=
sizeof
(
void
*
);
break
;
default:
printk
(
KERN_WARNING
PREFIX
"Invalid package element"
" [%d] got reference,"
" expecting [%c]
\n
"
,
i
,
format_string
[
i
]);
return
AE_BAD_DATA
;
break
;
}
break
;
case
ACPI_TYPE_PACKAGE
:
default:
...
...
@@ -247,7 +262,18 @@ acpi_extract_package(union acpi_object *package,
break
;
}
break
;
case
ACPI_TYPE_LOCAL_REFERENCE
:
switch
(
format_string
[
i
])
{
case
'R'
:
*
(
void
**
)
head
=
(
void
*
)
element
->
reference
.
handle
;
head
+=
sizeof
(
void
*
);
break
;
default:
/* Should never get here */
break
;
}
break
;
case
ACPI_TYPE_PACKAGE
:
/* TBD: handle nested packages... */
default:
...
...
drivers/thermal/Kconfig
View file @
6ceaf58a
...
...
@@ -217,21 +217,6 @@ config X86_PKG_TEMP_THERMAL
two trip points which can be set by user to get notifications via thermal
notification methods.
config ACPI_INT3403_THERMAL
tristate "ACPI INT3403 thermal driver"
depends on X86 && ACPI
help
Newer laptops and tablets that use ACPI may have thermal sensors
outside the core CPU/SOC for thermal safety reasons. These
temperature sensors are also exposed for the OS to use via the so
called INT3403 ACPI object. This driver will, on devices that have
such sensors, expose the temperature information from these sensors
to userspace via the normal thermal framework. This means that a wide
range of applications and GUI widgets can show this information to
the user or use this information for making decisions. For example,
the Intel Thermal Daemon can use this information to allow the user
to select his laptop to run without turning on the fans.
config INTEL_SOC_DTS_THERMAL
tristate "Intel SoCs DTS thermal driver"
depends on X86 && IOSF_MBI
...
...
@@ -244,6 +229,30 @@ config INTEL_SOC_DTS_THERMAL
notification methods.The other trip is a critical trip point, which
was set by the driver based on the TJ MAX temperature.
config INT340X_THERMAL
tristate "ACPI INT340X thermal drivers"
depends on X86 && ACPI
select THERMAL_GOV_USER_SPACE
select ACPI_THERMAL_REL
select ACPI_FAN
help
Newer laptops and tablets that use ACPI may have thermal sensors and
other devices with thermal control capabilities outside the core
CPU/SOC, for thermal safety reasons.
They are exposed for the OS to use via the INT3400 ACPI device object
as the master, and INT3401~INT340B ACPI device objects as the slaves.
Enable this to expose the temperature information and cooling ability
from these objects to userspace via the normal thermal framework.
This means that a wide range of applications and GUI widgets can show
the information to the user or use this information for making
decisions. For example, the Intel Thermal Daemon can use this
information to allow the user to select his laptop to run without
turning on the fans.
config ACPI_THERMAL_REL
tristate
depends on ACPI
menu "Texas Instruments thermal drivers"
source "drivers/thermal/ti-soc-thermal/Kconfig"
endmenu
...
...
drivers/thermal/Makefile
View file @
6ceaf58a
...
...
@@ -32,5 +32,5 @@ obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
obj-$(CONFIG_X86_PKG_TEMP_THERMAL)
+=
x86_pkg_temp_thermal.o
obj-$(CONFIG_INTEL_SOC_DTS_THERMAL)
+=
intel_soc_dts_thermal.o
obj-$(CONFIG_TI_SOC_THERMAL)
+=
ti-soc-thermal/
obj-$(CONFIG_
ACPI_INT3403_THERMAL)
+=
int3403_thermal.o
obj-$(CONFIG_
INT340X_THERMAL)
+=
int340x_thermal/
obj-$(CONFIG_ST_THERMAL)
+=
st/
drivers/thermal/int340x_thermal/Makefile
0 → 100644
View file @
6ceaf58a
obj-$(CONFIG_INT340X_THERMAL)
+=
int3400_thermal.o
obj-$(CONFIG_INT340X_THERMAL)
+=
int3402_thermal.o
obj-$(CONFIG_INT340X_THERMAL)
+=
int3403_thermal.o
obj-$(CONFIG_ACPI_THERMAL_REL)
+=
acpi_thermal_rel.o
drivers/thermal/int340x_thermal/acpi_thermal_rel.c
0 → 100644
View file @
6ceaf58a
This diff is collapsed.
Click to expand it.
drivers/thermal/int340x_thermal/acpi_thermal_rel.h
0 → 100644
View file @
6ceaf58a
#ifndef __ACPI_ACPI_THERMAL_H
#define __ACPI_ACPI_THERMAL_H
#include <asm/ioctl.h>
#define ACPI_THERMAL_MAGIC 's'
#define ACPI_THERMAL_GET_TRT_LEN _IOR(ACPI_THERMAL_MAGIC, 1, unsigned long)
#define ACPI_THERMAL_GET_ART_LEN _IOR(ACPI_THERMAL_MAGIC, 2, unsigned long)
#define ACPI_THERMAL_GET_TRT_COUNT _IOR(ACPI_THERMAL_MAGIC, 3, unsigned long)
#define ACPI_THERMAL_GET_ART_COUNT _IOR(ACPI_THERMAL_MAGIC, 4, unsigned long)
#define ACPI_THERMAL_GET_TRT _IOR(ACPI_THERMAL_MAGIC, 5, unsigned long)
#define ACPI_THERMAL_GET_ART _IOR(ACPI_THERMAL_MAGIC, 6, unsigned long)
struct
art
{
acpi_handle
source
;
acpi_handle
target
;
u64
weight
;
u64
ac0_max
;
u64
ac1_max
;
u64
ac2_max
;
u64
ac3_max
;
u64
ac4_max
;
u64
ac5_max
;
u64
ac6_max
;
u64
ac7_max
;
u64
ac8_max
;
u64
ac9_max
;
}
__packed
;
struct
trt
{
acpi_handle
source
;
acpi_handle
target
;
u64
influence
;
u64
sample_period
;
u64
reverved1
;
u64
reverved2
;
u64
reverved3
;
u64
reverved4
;
}
__packed
;
#define ACPI_NR_ART_ELEMENTS 13
/* for usrspace */
union
art_object
{
struct
{
char
source_device
[
8
];
/* ACPI single name */
char
target_device
[
8
];
/* ACPI single name */
u64
weight
;
u64
ac0_max_level
;
u64
ac1_max_level
;
u64
ac2_max_level
;
u64
ac3_max_level
;
u64
ac4_max_level
;
u64
ac5_max_level
;
u64
ac6_max_level
;
u64
ac7_max_level
;
u64
ac8_max_level
;
u64
ac9_max_level
;
};
u64
__data
[
ACPI_NR_ART_ELEMENTS
];
};
union
trt_object
{
struct
{
char
source_device
[
8
];
/* ACPI single name */
char
target_device
[
8
];
/* ACPI single name */
u64
influence
;
u64
sample_period
;
u64
reserved
[
4
];
};
u64
__data
[
8
];
};
#ifdef __KERNEL__
int
acpi_thermal_rel_misc_device_add
(
acpi_handle
handle
);
int
acpi_thermal_rel_misc_device_remove
(
acpi_handle
handle
);
int
acpi_parse_art
(
acpi_handle
handle
,
int
*
art_count
,
struct
art
**
arts
,
bool
create_dev
);
int
acpi_parse_trt
(
acpi_handle
handle
,
int
*
trt_count
,
struct
trt
**
trts
,
bool
create_dev
);
#endif
#endif
/* __ACPI_ACPI_THERMAL_H */
drivers/thermal/int340x_thermal/int3400_thermal.c
0 → 100644
View file @
6ceaf58a
/*
* INT3400 thermal driver
*
* Copyright (C) 2014, Intel Corporation
* Authors: Zhang Rui <rui.zhang@intel.com>
*
* 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.
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/thermal.h>
#include "acpi_thermal_rel.h"
enum
int3400_thermal_uuid
{
INT3400_THERMAL_PASSIVE_1
,
INT3400_THERMAL_PASSIVE_2
,
INT3400_THERMAL_ACTIVE
,
INT3400_THERMAL_CRITICAL
,
INT3400_THERMAL_COOLING_MODE
,
INT3400_THERMAL_MAXIMUM_UUID
,
};
static
u8
*
int3400_thermal_uuids
[
INT3400_THERMAL_MAXIMUM_UUID
]
=
{
"42A441D6-AE6A-462b-A84B-4A8CE79027D3"
,
"9E04115A-AE87-4D1C-9500-0F3E340BFE75"
,
"3A95C389-E4B8-4629-A526-C52C88626BAE"
,
"97C68AE7-15FA-499c-B8C9-5DA81D606E0A"
,
"16CAF1B7-DD38-40ed-B1C1-1B8A1913D531"
,
};
struct
int3400_thermal_priv
{
struct
acpi_device
*
adev
;
struct
thermal_zone_device
*
thermal
;
int
mode
;
int
art_count
;
struct
art
*
arts
;
int
trt_count
;
struct
trt
*
trts
;
u8
uuid_bitmap
;
int
rel_misc_dev_res
;
};
static
int
int3400_thermal_get_uuids
(
struct
int3400_thermal_priv
*
priv
)
{
struct
acpi_buffer
buf
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
obja
,
*
objb
;
int
i
,
j
;
int
result
=
0
;
acpi_status
status
;
status
=
acpi_evaluate_object
(
priv
->
adev
->
handle
,
"IDSP"
,
NULL
,
&
buf
);
if
(
ACPI_FAILURE
(
status
))
return
-
ENODEV
;
obja
=
(
union
acpi_object
*
)
buf
.
pointer
;
if
(
obja
->
type
!=
ACPI_TYPE_PACKAGE
)
{
result
=
-
EINVAL
;
goto
end
;
}
for
(
i
=
0
;
i
<
obja
->
package
.
count
;
i
++
)
{
objb
=
&
obja
->
package
.
elements
[
i
];
if
(
objb
->
type
!=
ACPI_TYPE_BUFFER
)
{
result
=
-
EINVAL
;
goto
end
;
}
/* UUID must be 16 bytes */
if
(
objb
->
buffer
.
length
!=
16
)
{
result
=
-
EINVAL
;
goto
end
;
}
for
(
j
=
0
;
j
<
INT3400_THERMAL_MAXIMUM_UUID
;
j
++
)
{
u8
uuid
[
16
];
acpi_str_to_uuid
(
int3400_thermal_uuids
[
j
],
uuid
);
if
(
!
strncmp
(
uuid
,
objb
->
buffer
.
pointer
,
16
))
{
priv
->
uuid_bitmap
|=
(
1
<<
j
);
break
;
}
}
}
end:
kfree
(
buf
.
pointer
);
return
result
;
}
static
int
int3400_thermal_run_osc
(
acpi_handle
handle
,
enum
int3400_thermal_uuid
uuid
,
bool
enable
)
{
u32
ret
,
buf
[
2
];
acpi_status
status
;
int
result
=
0
;
struct
acpi_osc_context
context
=
{
.
uuid_str
=
int3400_thermal_uuids
[
uuid
],
.
rev
=
1
,
.
cap
.
length
=
8
,
};
buf
[
OSC_QUERY_DWORD
]
=
0
;
buf
[
OSC_SUPPORT_DWORD
]
=
enable
;
context
.
cap
.
pointer
=
buf
;
status
=
acpi_run_osc
(
handle
,
&
context
);
if
(
ACPI_SUCCESS
(
status
))
{
ret
=
*
((
u32
*
)(
context
.
ret
.
pointer
+
4
));
if
(
ret
!=
enable
)
result
=
-
EPERM
;
}
else
result
=
-
EPERM
;
kfree
(
context
.
ret
.
pointer
);
return
result
;
}
static
int
int3400_thermal_get_temp
(
struct
thermal_zone_device
*
thermal
,
unsigned
long
*
temp
)
{
*
temp
=
20
*
1000
;
/* faked temp sensor with 20C */
return
0
;
}
static
int
int3400_thermal_get_mode
(
struct
thermal_zone_device
*
thermal
,
enum
thermal_device_mode
*
mode
)
{
struct
int3400_thermal_priv
*
priv
=
thermal
->
devdata
;
if
(
!
priv
)
return
-
EINVAL
;
*
mode
=
priv
->
mode
;
return
0
;
}
static
int
int3400_thermal_set_mode
(
struct
thermal_zone_device
*
thermal
,
enum
thermal_device_mode
mode
)
{
struct
int3400_thermal_priv
*
priv
=
thermal
->
devdata
;
bool
enable
;
int
result
=
0
;
if
(
!
priv
)
return
-
EINVAL
;
if
(
mode
==
THERMAL_DEVICE_ENABLED
)
enable
=
true
;
else
if
(
mode
==
THERMAL_DEVICE_DISABLED
)
enable
=
false
;
else
return
-
EINVAL
;
if
(
enable
!=
priv
->
mode
)
{
priv
->
mode
=
enable
;
/* currently, only PASSIVE COOLING is supported */
result
=
int3400_thermal_run_osc
(
priv
->
adev
->
handle
,
INT3400_THERMAL_PASSIVE_1
,
enable
);
}
return
result
;
}
static
struct
thermal_zone_device_ops
int3400_thermal_ops
=
{
.
get_temp
=
int3400_thermal_get_temp
,
};
static
struct
thermal_zone_params
int3400_thermal_params
=
{
.
governor_name
=
"user_space"
,
.
no_hwmon
=
true
,
};
static
int
int3400_thermal_probe
(
struct
platform_device
*
pdev
)
{
struct
acpi_device
*
adev
=
ACPI_COMPANION
(
&
pdev
->
dev
);
struct
int3400_thermal_priv
*
priv
;
int
result
;
if
(
!
adev
)
return
-
ENODEV
;
priv
=
kzalloc
(
sizeof
(
struct
int3400_thermal_priv
),
GFP_KERNEL
);
if
(
!
priv
)
return
-
ENOMEM
;
priv
->
adev
=
adev
;
result
=
int3400_thermal_get_uuids
(
priv
);
if
(
result
)
goto
free_priv
;
result
=
acpi_parse_art
(
priv
->
adev
->
handle
,
&
priv
->
art_count
,
&
priv
->
arts
,
true
);
if
(
result
)
goto
free_priv
;
result
=
acpi_parse_trt
(
priv
->
adev
->
handle
,
&
priv
->
trt_count
,
&
priv
->
trts
,
true
);
if
(
result
)
goto
free_art
;
platform_set_drvdata
(
pdev
,
priv
);
if
(
priv
->
uuid_bitmap
&
1
<<
INT3400_THERMAL_PASSIVE_1
)
{
int3400_thermal_ops
.
get_mode
=
int3400_thermal_get_mode
;
int3400_thermal_ops
.
set_mode
=
int3400_thermal_set_mode
;
}
priv
->
thermal
=
thermal_zone_device_register
(
"INT3400 Thermal"
,
0
,
0
,
priv
,
&
int3400_thermal_ops
,
&
int3400_thermal_params
,
0
,
0
);
if
(
IS_ERR
(
priv
->
thermal
))
{
result
=
PTR_ERR
(
priv
->
thermal
);
goto
free_trt
;
}
priv
->
rel_misc_dev_res
=
acpi_thermal_rel_misc_device_add
(
priv
->
adev
->
handle
);
return
0
;
free_trt:
kfree
(
priv
->
trts
);
free_art:
kfree
(
priv
->
arts
);
free_priv:
kfree
(
priv
);
return
result
;
}
static
int
int3400_thermal_remove
(
struct
platform_device
*
pdev
)
{
struct
int3400_thermal_priv
*
priv
=
platform_get_drvdata
(
pdev
);
if
(
!
priv
->
rel_misc_dev_res
)
acpi_thermal_rel_misc_device_remove
(
priv
->
adev
->
handle
);
thermal_zone_device_unregister
(
priv
->
thermal
);
kfree
(
priv
->
trts
);
kfree
(
priv
->
arts
);
kfree
(
priv
);
return
0
;
}
static
const
struct
acpi_device_id
int3400_thermal_match
[]
=
{
{
"INT3400"
,
0
},
{}
};
MODULE_DEVICE_TABLE
(
acpi
,
int3400_thermal_match
);
static
struct
platform_driver
int3400_thermal_driver
=
{
.
probe
=
int3400_thermal_probe
,
.
remove
=
int3400_thermal_remove
,
.
driver
=
{
.
name
=
"int3400 thermal"
,
.
owner
=
THIS_MODULE
,
.
acpi_match_table
=
ACPI_PTR
(
int3400_thermal_match
),
},
};
module_platform_driver
(
int3400_thermal_driver
);
MODULE_DESCRIPTION
(
"INT3400 Thermal driver"
);
MODULE_AUTHOR
(
"Zhang Rui <rui.zhang@intel.com>"
);
MODULE_LICENSE
(
"GPL"
);
drivers/thermal/int340x_thermal/int3402_thermal.c
0 → 100644
View file @
6ceaf58a
/*
* INT3402 thermal driver for memory temperature reporting
*
* Copyright (C) 2014, Intel Corporation
* Authors: Aaron Lu <aaron.lu@intel.com>
*
* 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.
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/thermal.h>
#define ACPI_ACTIVE_COOLING_MAX_NR 10
struct
active_trip
{
unsigned
long
temp
;
int
id
;
bool
valid
;
};
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
;
};
static
int
int3402_thermal_get_zone_temp
(
struct
thermal_zone_device
*
zone
,
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
;
int
i
;
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
<
ACPI_ACTIVE_COOLING_MAX_NR
;
i
++
)
{
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
)
{
struct
acpi_device
*
adev
=
ACPI_COMPANION
(
&
pdev
->
dev
);
struct
int3402_thermal_data
*
d
;
struct
thermal_zone_device
*
zone
;
acpi_status
status
;
unsigned
long
long
trip_cnt
;
int
trip_mask
=
0
,
i
;
if
(
!
acpi_has_method
(
adev
->
handle
,
"_TMP"
))
return
-
ENODEV
;
d
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
d
),
GFP_KERNEL
);
if
(
!
d
)
return
-
ENOMEM
;
status
=
acpi_evaluate_integer
(
adev
->
handle
,
"PATC"
,
NULL
,
&
trip_cnt
);
if
(
ACPI_FAILURE
(
status
))
trip_cnt
=
0
;
else
{
d
->
aux_trips
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
d
->
aux_trips
)
*
trip_cnt
,
GFP_KERNEL
);
if
(
!
d
->
aux_trips
)
return
-
ENOMEM
;
trip_mask
=
trip_cnt
-
1
;
d
->
handle
=
adev
->
handle
;
d
->
aux_trip_nr
=
trip_cnt
;
}
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
,
trip_mask
,
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
;
}
static
int
int3402_thermal_remove
(
struct
platform_device
*
pdev
)
{
struct
thermal_zone_device
*
zone
=
platform_get_drvdata
(
pdev
);
thermal_zone_device_unregister
(
zone
);
return
0
;
}
static
const
struct
acpi_device_id
int3402_thermal_match
[]
=
{
{
"INT3402"
,
0
},
{}
};
MODULE_DEVICE_TABLE
(
acpi
,
int3402_thermal_match
);
static
struct
platform_driver
int3402_thermal_driver
=
{
.
probe
=
int3402_thermal_probe
,
.
remove
=
int3402_thermal_remove
,
.
driver
=
{
.
name
=
"int3402 thermal"
,
.
owner
=
THIS_MODULE
,
.
acpi_match_table
=
int3402_thermal_match
,
},
};
module_platform_driver
(
int3402_thermal_driver
);
MODULE_DESCRIPTION
(
"INT3402 Thermal driver"
);
MODULE_LICENSE
(
"GPL"
);
drivers/thermal/int3403_thermal.c
→
drivers/thermal/int340
x_thermal/int340
3_thermal.c
View file @
6ceaf58a
This diff is collapsed.
Click to expand it.
include/acpi/acpi_bus.h
View file @
6ceaf58a
...
...
@@ -435,6 +435,7 @@ int acpi_device_set_power(struct acpi_device *device, int state);
int
acpi_bus_init_power
(
struct
acpi_device
*
device
);
int
acpi_device_fix_up_power
(
struct
acpi_device
*
device
);
int
acpi_bus_update_power
(
acpi_handle
handle
,
int
*
state_p
);
int
acpi_device_update_power
(
struct
acpi_device
*
device
,
int
*
state_p
);
bool
acpi_bus_power_manageable
(
acpi_handle
handle
);
#ifdef CONFIG_PM
...
...
include/linux/acpi.h
View file @
6ceaf58a
...
...
@@ -432,6 +432,7 @@ static inline bool acpi_driver_match_device(struct device *dev,
int
acpi_device_uevent_modalias
(
struct
device
*
,
struct
kobj_uevent_env
*
);
int
acpi_device_modalias
(
struct
device
*
,
char
*
,
int
);
struct
platform_device
*
acpi_create_platform_device
(
struct
acpi_device
*
);
#define ACPI_PTR(_ptr) (_ptr)
#else
/* !CONFIG_ACPI */
...
...
include/linux/thermal.h
View file @
6ceaf58a
...
...
@@ -44,6 +44,10 @@
#define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732 >= 0) ? \
((long)t-2732+5)/10 : ((long)t-2732-5)/10)
#define CELSIUS_TO_KELVIN(t) ((t)*10+2732)
#define DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, off) (((t) - (off)) * 100)
#define DECI_KELVIN_TO_MILLICELSIUS(t) DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, 2732)
#define MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, off) (((t) / 100) + (off))
#define MILLICELSIUS_TO_DECI_KELVIN(t) MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, 2732)
/* Adding event notification support elements */
#define THERMAL_GENL_FAMILY_NAME "thermal_event"
...
...
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