| /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| /* Temperature sensor module for Chrome EC */ | |
| #include "common.h" | |
| #include "console.h" | |
| #include "hooks.h" | |
| #include "host_command.h" | |
| #include "task.h" | |
| #include "temp_sensor.h" | |
| #include "thermal.h" | |
| #include "timer.h" | |
| #include "util.h" | |
| int temp_sensor_read(enum temp_sensor_id id, int *temp_ptr) | |
| { | |
| const struct temp_sensor_t *sensor; | |
| if (id < 0 || id >= TEMP_SENSOR_COUNT) | |
| return EC_ERROR_INVAL; | |
| sensor = temp_sensors + id; | |
| return sensor->read(sensor->idx, temp_ptr); | |
| } | |
| static void update_mapped_memory(void) | |
| { | |
| int i, t; | |
| uint8_t *mptr = host_get_memmap(EC_MEMMAP_TEMP_SENSOR); | |
| for (i = 0; i < TEMP_SENSOR_COUNT; i++, mptr++) { | |
| /* | |
| * Switch to second range if first one is full, or stop if | |
| * second range is also full. | |
| */ | |
| if (i == EC_TEMP_SENSOR_ENTRIES) | |
| mptr = host_get_memmap(EC_MEMMAP_TEMP_SENSOR_B); | |
| else if (i >= EC_TEMP_SENSOR_ENTRIES + | |
| EC_TEMP_SENSOR_B_ENTRIES) | |
| break; | |
| switch (temp_sensor_read(i, &t)) { | |
| case EC_ERROR_NOT_POWERED: | |
| *mptr = EC_TEMP_SENSOR_NOT_POWERED; | |
| break; | |
| case EC_ERROR_NOT_CALIBRATED: | |
| *mptr = EC_TEMP_SENSOR_NOT_CALIBRATED; | |
| break; | |
| case EC_SUCCESS: | |
| *mptr = t - EC_TEMP_SENSOR_OFFSET; | |
| break; | |
| default: | |
| *mptr = EC_TEMP_SENSOR_ERROR; | |
| } | |
| } | |
| } | |
| /* Run after other TEMP tasks, so sensors will have updated first. */ | |
| DECLARE_HOOK(HOOK_SECOND, update_mapped_memory, HOOK_PRIO_TEMP_SENSOR_DONE); | |
| static void temp_sensor_init(void) | |
| { | |
| int i; | |
| uint8_t *base, *base_b; | |
| /* | |
| * Initialize memory-mapped data so that if a temperature value is read | |
| * before we actually poll the sensors, we don't end up with an insane | |
| * value. | |
| */ | |
| base = host_get_memmap(EC_MEMMAP_TEMP_SENSOR); | |
| base_b = host_get_memmap(EC_MEMMAP_TEMP_SENSOR_B); | |
| for (i = 0; i < TEMP_SENSOR_COUNT; ++i) { | |
| if (i < EC_TEMP_SENSOR_ENTRIES) | |
| base[i] = EC_TEMP_SENSOR_DEFAULT; | |
| else | |
| base_b[i - EC_TEMP_SENSOR_ENTRIES] = | |
| EC_TEMP_SENSOR_DEFAULT; | |
| } | |
| /* Set the rest of memory region to SENSOR_NOT_PRESENT */ | |
| for (; i < EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES; ++i) { | |
| if (i < EC_TEMP_SENSOR_ENTRIES) | |
| base[i] = EC_TEMP_SENSOR_NOT_PRESENT; | |
| else | |
| base_b[i - EC_TEMP_SENSOR_ENTRIES] = | |
| EC_TEMP_SENSOR_NOT_PRESENT; | |
| } | |
| /* Temp sensor data is present, with B range supported. */ | |
| *host_get_memmap(EC_MEMMAP_THERMAL_VERSION) = 2; | |
| } | |
| DECLARE_HOOK(HOOK_INIT, temp_sensor_init, HOOK_PRIO_DEFAULT); | |
| /*****************************************************************************/ | |
| /* Console commands */ | |
| static int command_temps(int argc, char **argv) | |
| { | |
| int t, i; | |
| int rv, rv1 = EC_SUCCESS; | |
| for (i = 0; i < TEMP_SENSOR_COUNT; ++i) { | |
| ccprintf(" %-20s: ", temp_sensors[i].name); | |
| rv = temp_sensor_read(i, &t); | |
| if (rv) | |
| rv1 = rv; | |
| switch (rv) { | |
| case EC_SUCCESS: | |
| ccprintf("%d K = %d C", t, K_TO_C(t)); | |
| #ifdef CONFIG_THROTTLE_AP | |
| if (thermal_params[i].temp_fan_off && | |
| thermal_params[i].temp_fan_max) | |
| ccprintf(" %d%%", | |
| thermal_fan_percent( | |
| thermal_params[i].temp_fan_off, | |
| thermal_params[i].temp_fan_max, | |
| t)); | |
| #endif | |
| ccprintf("\n"); | |
| break; | |
| case EC_ERROR_NOT_POWERED: | |
| ccprintf("Not powered\n"); | |
| break; | |
| case EC_ERROR_NOT_CALIBRATED: | |
| ccprintf("Not calibrated\n"); | |
| break; | |
| default: | |
| ccprintf("Error %d\n", rv); | |
| } | |
| } | |
| return rv1; | |
| } | |
| DECLARE_CONSOLE_COMMAND(temps, command_temps, | |
| NULL, | |
| "Print temp sensors", | |
| NULL); | |
| /*****************************************************************************/ | |
| /* Host commands */ | |
| int temp_sensor_command_get_info(struct host_cmd_handler_args *args) | |
| { | |
| const struct ec_params_temp_sensor_get_info *p = args->params; | |
| struct ec_response_temp_sensor_get_info *r = args->response; | |
| int id = p->id; | |
| if (id >= TEMP_SENSOR_COUNT) | |
| return EC_RES_ERROR; | |
| strzcpy(r->sensor_name, temp_sensors[id].name, sizeof(r->sensor_name)); | |
| r->sensor_type = temp_sensors[id].type; | |
| args->response_size = sizeof(*r); | |
| return EC_RES_SUCCESS; | |
| } | |
| DECLARE_HOST_COMMAND(EC_CMD_TEMP_SENSOR_GET_INFO, | |
| temp_sensor_command_get_info, | |
| EC_VER_MASK(0)); |