mirror of
https://github.com/ARM-software/devlib.git
synced 2025-01-31 02:00:45 +00:00
devlib: Add ThermalZone type and policy support to thermal module
The thermal module currently only reads thermal zone ids and allow temperature reading. The mandatory thermal zone 'type' describes what the zone is and is therefore quite useful information. This commit also adds support for reading the current thermal zone policy and available policies along with a few other properties. This commit also adds async support to the thermal module. Signed-off-by: Morten Rasmussen <morten.rasmussen@arm.com>
This commit is contained in:
parent
9199d8884e
commit
403a0faf93
@ -13,8 +13,11 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import logging
|
||||||
|
import devlib.utils.asyn as asyn
|
||||||
|
|
||||||
from devlib.module import Module
|
from devlib.module import Module
|
||||||
|
from devlib.exception import TargetStableCalledProcessError
|
||||||
|
|
||||||
class TripPoint(object):
|
class TripPoint(object):
|
||||||
def __init__(self, zone, _id):
|
def __init__(self, zone, _id):
|
||||||
@ -27,19 +30,22 @@ class TripPoint(object):
|
|||||||
def target(self):
|
def target(self):
|
||||||
return self.zone.target
|
return self.zone.target
|
||||||
|
|
||||||
def get_temperature(self):
|
@asyn.asyncf
|
||||||
|
async def get_temperature(self):
|
||||||
"""Returns the currently configured temperature of the trip point"""
|
"""Returns the currently configured temperature of the trip point"""
|
||||||
temp_file = self.target.path.join(self.zone.path, self.temp_node)
|
temp_file = self.target.path.join(self.zone.path, self.temp_node)
|
||||||
return self.target.read_int(temp_file)
|
return await self.target.read_int.asyn(temp_file)
|
||||||
|
|
||||||
def set_temperature(self, temperature):
|
@asyn.asyncf
|
||||||
|
async def set_temperature(self, temperature):
|
||||||
temp_file = self.target.path.join(self.zone.path, self.temp_node)
|
temp_file = self.target.path.join(self.zone.path, self.temp_node)
|
||||||
self.target.write_value(temp_file, temperature)
|
await self.target.write_value.asyn(temp_file, temperature)
|
||||||
|
|
||||||
def get_type(self):
|
@asyn.asyncf
|
||||||
|
async def get_type(self):
|
||||||
"""Returns the type of trip point"""
|
"""Returns the type of trip point"""
|
||||||
type_file = self.target.path.join(self.zone.path, self.type_node)
|
type_file = self.target.path.join(self.zone.path, self.type_node)
|
||||||
return self.target.read_value(type_file)
|
return await self.target.read_value.asyn(type_file)
|
||||||
|
|
||||||
class ThermalZone(object):
|
class ThermalZone(object):
|
||||||
def __init__(self, target, root, _id):
|
def __init__(self, target, root, _id):
|
||||||
@ -47,6 +53,7 @@ class ThermalZone(object):
|
|||||||
self.name = 'thermal_zone' + _id
|
self.name = 'thermal_zone' + _id
|
||||||
self.path = target.path.join(root, self.name)
|
self.path = target.path.join(root, self.name)
|
||||||
self.trip_points = {}
|
self.trip_points = {}
|
||||||
|
self.type = self.target.read_value(self.target.path.join(self.path, 'type'))
|
||||||
|
|
||||||
for entry in self.target.list_directory(self.path, as_root=target.is_rooted):
|
for entry in self.target.list_directory(self.path, as_root=target.is_rooted):
|
||||||
re_match = re.match('^trip_point_([0-9]+)_temp', entry)
|
re_match = re.match('^trip_point_([0-9]+)_temp', entry)
|
||||||
@ -56,19 +63,70 @@ class ThermalZone(object):
|
|||||||
def add_trip_point(self, _id):
|
def add_trip_point(self, _id):
|
||||||
self.trip_points[int(_id)] = TripPoint(self, _id)
|
self.trip_points[int(_id)] = TripPoint(self, _id)
|
||||||
|
|
||||||
def is_enabled(self):
|
@asyn.asyncf
|
||||||
|
async def is_enabled(self):
|
||||||
"""Returns a boolean representing the 'mode' of the thermal zone"""
|
"""Returns a boolean representing the 'mode' of the thermal zone"""
|
||||||
value = self.target.read_value(self.target.path.join(self.path, 'mode'))
|
value = await self.target.read_value.asyn(self.target.path.join(self.path, 'mode'))
|
||||||
return value == 'enabled'
|
return value == 'enabled'
|
||||||
|
|
||||||
def set_enabled(self, enabled=True):
|
@asyn.asyncf
|
||||||
|
async def set_enabled(self, enabled=True):
|
||||||
value = 'enabled' if enabled else 'disabled'
|
value = 'enabled' if enabled else 'disabled'
|
||||||
self.target.write_value(self.target.path.join(self.path, 'mode'), value)
|
await self.target.write_value.asyn(self.target.path.join(self.path, 'mode'), value)
|
||||||
|
|
||||||
def get_temperature(self):
|
@asyn.asyncf
|
||||||
|
async def get_temperature(self):
|
||||||
"""Returns the temperature of the thermal zone"""
|
"""Returns the temperature of the thermal zone"""
|
||||||
temp_file = self.target.path.join(self.path, 'temp')
|
sysfs_temperature_file = self.target.path.join(self.path, 'temp')
|
||||||
return self.target.read_int(temp_file)
|
return await self.target.read_int.asyn(sysfs_temperature_file)
|
||||||
|
|
||||||
|
@asyn.asyncf
|
||||||
|
async def get_policy(self):
|
||||||
|
"""Returns the policy of the thermal zone"""
|
||||||
|
temp_file = self.target.path.join(self.path, 'policy')
|
||||||
|
return await self.target.read_value.asyn(temp_file)
|
||||||
|
|
||||||
|
@asyn.asyncf
|
||||||
|
async def set_policy(self, policy):
|
||||||
|
"""
|
||||||
|
Sets the policy of the thermal zone
|
||||||
|
|
||||||
|
:params policy: Thermal governor name
|
||||||
|
:type policy: str
|
||||||
|
"""
|
||||||
|
await self.target.write_value.asyn(self.target.path.join(self.path, 'policy'), policy)
|
||||||
|
|
||||||
|
@asyn.asyncf
|
||||||
|
async def get_offset(self):
|
||||||
|
"""Returns the temperature offset of the thermal zone"""
|
||||||
|
offset_file = self.target.path.join(self.path, 'offset')
|
||||||
|
return await self.target.read_value.asyn(offset_file)
|
||||||
|
|
||||||
|
@asyn.asyncf
|
||||||
|
async def set_offset(self, offset):
|
||||||
|
"""
|
||||||
|
Sets the temperature offset in milli-degrees of the thermal zone
|
||||||
|
|
||||||
|
:params offset: Temperature offset in milli-degrees
|
||||||
|
:type policy: int
|
||||||
|
"""
|
||||||
|
await self.target.write_value.asyn(self.target.path.join(self.path, 'offset'), policy)
|
||||||
|
|
||||||
|
@asyn.asyncf
|
||||||
|
async def set_emul_temp(self, offset):
|
||||||
|
"""
|
||||||
|
Sets the emulated temperature in milli-degrees of the thermal zone
|
||||||
|
|
||||||
|
:params offset: Emulated temperature in milli-degrees
|
||||||
|
:type policy: int
|
||||||
|
"""
|
||||||
|
await self.target.write_value.asyn(self.target.path.join(self.path, 'emul_temp'), policy)
|
||||||
|
|
||||||
|
@asyn.asyncf
|
||||||
|
async def get_available_policies(self):
|
||||||
|
"""Returns the policies available for the thermal zone"""
|
||||||
|
temp_file = self.target.path.join(self.path, 'available_policies')
|
||||||
|
return await self.target.read_value.asyn(temp_file)
|
||||||
|
|
||||||
class ThermalModule(Module):
|
class ThermalModule(Module):
|
||||||
name = 'thermal'
|
name = 'thermal'
|
||||||
@ -83,6 +141,9 @@ class ThermalModule(Module):
|
|||||||
def __init__(self, target):
|
def __init__(self, target):
|
||||||
super(ThermalModule, self).__init__(target)
|
super(ThermalModule, self).__init__(target)
|
||||||
|
|
||||||
|
self.logger = logging.getLogger(self.name)
|
||||||
|
self.logger.debug('Initialized [%s] module', self.name)
|
||||||
|
|
||||||
self.zones = {}
|
self.zones = {}
|
||||||
self.cdevs = []
|
self.cdevs = []
|
||||||
|
|
||||||
@ -105,3 +166,32 @@ class ThermalModule(Module):
|
|||||||
"""Disables all the thermal zones in the target"""
|
"""Disables all the thermal zones in the target"""
|
||||||
for zone in self.zones.values():
|
for zone in self.zones.values():
|
||||||
zone.set_enabled(False)
|
zone.set_enabled(False)
|
||||||
|
|
||||||
|
@asyn.asyncf
|
||||||
|
async def get_all_temperatures(self, error='raise'):
|
||||||
|
"""
|
||||||
|
Returns dictionary with current reading of all thermal zones.
|
||||||
|
|
||||||
|
:params error: Sensor read error handling (raise or ignore)
|
||||||
|
:type error: str
|
||||||
|
|
||||||
|
:returns: a dictionary in the form: {tz_type:temperature}
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def get_temperature_noexcep(item):
|
||||||
|
tzid, tz = item
|
||||||
|
try:
|
||||||
|
temperature = await tz.get_temperature.asyn()
|
||||||
|
except TargetStableCalledProcessError as e:
|
||||||
|
if error == 'raise':
|
||||||
|
raise e
|
||||||
|
elif error == 'ignore':
|
||||||
|
self.logger.warning(f'Skipping thermal_zone_id={tzid} thermal_zone_type={tz.type} error="{e}"')
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
raise ValueError(f'Unknown error parameter value: {error}')
|
||||||
|
return temperature
|
||||||
|
|
||||||
|
tz_temps = await self.target.async_manager.map_concurrently(get_temperature_noexcep, self.zones.items())
|
||||||
|
|
||||||
|
return {tz.type: temperature for (tzid, tz), temperature in tz_temps.items() if temperature is not None}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user