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
8cb68501
Commit
8cb68501
authored
Jan 30, 2015
by
Zhang Rui
Browse files
Options
Browse Files
Download
Plain Diff
Merge branches 'intel-dts-soc-thermal' and 'int340x-enhancement' of .git into next
parents
6c355faf
317d9dda
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
727 additions
and
484 deletions
+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
No files found.
drivers/acpi/Makefile
View file @
8cb68501
...
...
@@ -55,6 +55,7 @@ acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
ifdef
CONFIG_ACPI_VIDEO
acpi-y
+=
video_detect.o
endif
acpi-y
+=
acpi_lpat.o
# These are (potentially) separate modules
...
...
drivers/acpi/acpi_lpat.c
0 → 100644
View file @
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
View file @
8cb68501
...
...
@@ -16,20 +16,15 @@
#include <linux/module.h>
#include <linux/acpi.h>
#include <linux/regmap.h>
#include <acpi/acpi_lpat.h>
#include "intel_pmic.h"
#define PMIC_POWER_OPREGION_ID 0x8d
#define PMIC_THERMAL_OPREGION_ID 0x8c
struct
acpi_lpat
{
int
temp
;
int
raw
;
};
struct
intel_pmic_opregion
{
struct
mutex
lock
;
struct
acpi_lpat
*
lpat
;
int
lpat_count
;
struct
acpi_lpat_conversion_table
*
lpat_table
;
struct
regmap
*
regmap
;
struct
intel_pmic_opregion_data
*
data
;
};
...
...
@@ -50,105 +45,6 @@ static int pmic_get_reg_bit(int address, struct pmic_table *table,
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
,
acpi_physical_address
address
,
u32
bits
,
u64
*
value64
,
void
*
handler_context
,
void
*
region_context
)
...
...
@@ -192,12 +88,12 @@ static int pmic_read_temp(struct intel_pmic_opregion *opregion,
if
(
raw_temp
<
0
)
return
raw_temp
;
if
(
!
opregion
->
lpat
)
{
if
(
!
opregion
->
lpat
_table
)
{
*
value
=
raw_temp
;
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
)
return
temp
;
...
...
@@ -223,9 +119,8 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg,
if
(
!
opregion
->
data
->
update_aux
)
return
-
ENXIO
;
if
(
opregion
->
lpat
)
{
raw_temp
=
temp_to_raw
(
opregion
->
lpat
,
opregion
->
lpat_count
,
*
value
);
if
(
opregion
->
lpat_table
)
{
raw_temp
=
acpi_lpat_temp_to_raw
(
opregion
->
lpat_table
,
*
value
);
if
(
raw_temp
<
0
)
return
raw_temp
;
}
else
{
...
...
@@ -314,6 +209,7 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
{
acpi_status
status
;
struct
intel_pmic_opregion
*
opregion
;
int
ret
;
if
(
!
dev
||
!
regmap
||
!
d
)
return
-
EINVAL
;
...
...
@@ -327,14 +223,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
mutex_init
(
&
opregion
->
lock
);
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
,
PMIC_POWER_OPREGION_ID
,
intel_pmic_power_handler
,
NULL
,
opregion
);
if
(
ACPI_FAILURE
(
status
))
return
-
ENODEV
;
if
(
ACPI_FAILURE
(
status
))
{
ret
=
-
ENODEV
;
goto
out_error
;
}
status
=
acpi_install_address_space_handler
(
handle
,
PMIC_THERMAL_OPREGION_ID
,
...
...
@@ -343,11 +241,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
if
(
ACPI_FAILURE
(
status
))
{
acpi_remove_address_space_handler
(
handle
,
PMIC_POWER_OPREGION_ID
,
intel_pmic_power_handler
);
return
-
ENODEV
;
ret
=
-
ENODEV
;
goto
out_error
;
}
opregion
->
data
=
d
;
return
0
;
out_error:
acpi_lpat_free_conversion_table
(
opregion
->
lpat_table
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
intel_pmic_install_opregion_handler
);
...
...
drivers/thermal/int340x_thermal/Makefile
View file @
8cb68501
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)
+=
int3403_thermal.o
obj-$(CONFIG_INT340X_THERMAL)
+=
processor_thermal_device.o
...
...
drivers/thermal/int340x_thermal/int3402_thermal.c
View file @
8cb68501
...
...
@@ -14,152 +14,39 @@
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/thermal.h>
#include "int340x_thermal_zone.h"
#define ACPI_ACTIVE_COOLING_MAX_NR 10
struct
active_trip
{
unsigned
long
temp
;
int
id
;
bool
valid
;
};
#define INT3402_PERF_CHANGED_EVENT 0x80
#define INT3402_THERMAL_EVENT 0x90
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
;
struct
int34x_thermal_zone
*
int340x_zone
;
};
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
)
static
void
int3402_notify
(
acpi_handle
handle
,
u32
event
,
void
*
data
)
{
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
;
struct
int3402_thermal_data
*
priv
=
data
;
if
(
!
priv
)
return
;
switch
(
event
)
{
case
INT3402_PERF_CHANGED_EVENT
:
break
;
case
INT3402_THERMAL_EVENT
:
int340x_thermal_zone_device_update
(
priv
->
int340x_zone
);
break
;
default:
break
;
}
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
;
int
ret
;
if
(
!
acpi_has_method
(
adev
->
handle
,
"_TMP"
))
return
-
ENODEV
;
...
...
@@ -168,54 +55,33 @@ static int int3402_thermal_probe(struct platform_device *pdev)
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
;
d
->
int340x_zone
=
int340x_thermal_zone_add
(
adev
,
NULL
);
if
(
IS_ERR
(
d
->
int340x_zone
))
return
PTR_ERR
(
d
->
int340x_zone
);
ret
=
acpi_install_notify_handler
(
adev
->
handle
,
ACPI_DEVICE_NOTIFY
,
int3402_notify
,
d
);
if
(
ret
)
{
int340x_thermal_zone_remove
(
d
->
int340x_zone
);
return
ret
;
}
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
);
d
->
handle
=
adev
->
handle
;
platform_set_drvdata
(
pdev
,
d
);
return
0
;
}
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
;
}
...
...
drivers/thermal/int340x_thermal/int3403_thermal.c
View file @
8cb68501
...
...
@@ -19,6 +19,7 @@
#include <linux/acpi.h>
#include <linux/thermal.h>
#include <linux/platform_device.h>
#include "int340x_thermal_zone.h"
#define INT3403_TYPE_SENSOR 0x03
#define INT3403_TYPE_CHARGER 0x0B
...
...
@@ -26,18 +27,9 @@
#define INT3403_PERF_CHANGED_EVENT 0x80
#define INT3403_THERMAL_EVENT 0x90
#define DECI_KELVIN_TO_MILLI_CELSIUS(t, off) (((t) - (off)) * 100)
#define KELVIN_OFFSET 2732
#define MILLI_CELSIUS_TO_DECI_KELVIN(t, off) (((t) / 100) + (off))
/* Preserved structure for future expandbility */
struct
int3403_sensor
{
struct
thermal_zone_device
*
tzone
;
unsigned
long
*
thresholds
;
unsigned
long
crit_temp
;
int
crit_trip_id
;
unsigned
long
psv_temp
;
int
psv_trip_id
;
struct
int34x_thermal_zone
*
int340x_zone
;
};
struct
int3403_performance_state
{
...
...
@@ -63,126 +55,6 @@ struct int3403_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
,
u32
event
,
void
*
data
)
{
...
...
@@ -200,7 +72,7 @@ static void int3403_notify(acpi_handle handle,
case
INT3403_PERF_CHANGED_EVENT
:
break
;
case
INT3403_THERMAL_EVENT
:
thermal_zone_device_update
(
obj
->
t
zone
);
int340x_thermal_zone_device_update
(
obj
->
int340x_
zone
);
break
;
default:
dev_err
(
&
priv
->
pdev
->
dev
,
"Unsupported event [0x%x]
\n
"
,
event
);
...
...
@@ -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
)
{
int
result
=
0
;
acpi_status
status
;
struct
int3403_sensor
*
obj
;
unsigned
long
long
trip_cnt
;
int
trip_mask
=
0
;
obj
=
devm_kzalloc
(
&
priv
->
pdev
->
dev
,
sizeof
(
*
obj
),
GFP_KERNEL
);
if
(
!
obj
)
...
...
@@ -250,39 +91,9 @@ static int int3403_sensor_add(struct int3403_priv *priv)
priv
->
priv
=
obj
;
status
=
acpi_evaluate_integer
(
priv
->
adev
->
handle
,
"PATC"
,
NULL
,
&
trip_cnt
);
if
(
ACPI_FAILURE
(
status
))
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
;
}
obj
->
int340x_zone
=
int340x_thermal_zone_add
(
priv
->
adev
,
NULL
);
if
(
IS_ERR
(
obj
->
int340x_zone
))
return
PTR_ERR
(
obj
->
int340x_zone
);
result
=
acpi_install_notify_handler
(
priv
->
adev
->
handle
,
ACPI_DEVICE_NOTIFY
,
int3403_notify
,
...
...
@@ -293,7 +104,7 @@ static int int3403_sensor_add(struct int3403_priv *priv)
return
0
;
err_free_obj:
thermal_zone_device_unregister
(
obj
->
t
zone
);
int340x_thermal_zone_remove
(
obj
->
int340x_
zone
);
return
result
;
}
...
...
@@ -303,7 +114,8 @@ static int int3403_sensor_remove(struct int3403_priv *priv)
acpi_remove_notify_handler
(
priv
->
adev
->
handle
,
ACPI_DEVICE_NOTIFY
,
int3403_notify
);
thermal_zone_device_unregister
(
obj
->
tzone
);
int340x_thermal_zone_remove
(
obj
->
int340x_zone
);
return
0
;
}
...
...
drivers/thermal/int340x_thermal/int340x_thermal_zone.c
0 → 100644
View file @
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
View file @
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
View file @
8cb68501
...
...
@@ -18,6 +18,8 @@
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/thermal.h>
#include "int340x_thermal_zone.h"
/* Broadwell-U/HSB thermal reporting device */
#define PCI_DEVICE_ID_PROC_BDW_THERMAL 0x1603
...
...
@@ -39,6 +41,7 @@ struct proc_thermal_device {
struct
device
*
dev
;
struct
acpi_device
*
adev
;
struct
power_config
power_limits
[
2
];
struct
int34x_thermal_zone
*
int340x_zone
;
};
enum
proc_thermal_emum_mode_type
{
...
...
@@ -117,6 +120,72 @@ static struct attribute_group power_limit_attribute_group = {
.
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
,
struct
proc_thermal_device
**
priv
)
{
...
...
@@ -126,6 +195,8 @@ static int proc_thermal_add(struct device *dev,
struct
acpi_buffer
buf
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
elements
,
*
ppcc
;
union
acpi_object
*
p
;
unsigned
long
long
tmp
;
struct
thermal_zone_device_ops
*
ops
=
NULL
;
int
i
;
int
ret
;
...
...
@@ -178,6 +249,24 @@ static int proc_thermal_add(struct device *dev,
ret
=
sysfs_create_group
(
&
dev
->
kobj
,
&
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:
kfree
(
buf
.
pointer
);
...
...
@@ -187,6 +276,7 @@ static int proc_thermal_add(struct device *dev,
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
,
&
power_limit_attribute_group
);
}
...
...
include/acpi/acpi_lpat.h
0 → 100644
View file @
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
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