mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-02 13:14:51 +00:00
Support up to 24 thermal sensors
And tidy reporting fan/thermal via memmap.
BUG=chrome-os-partner:11628
TEST=manual
ectool pwmgetfanrpm -> should report fan speed
ectool temps N ->
should work for N=0-9
reports error for N=15-23
reports invalid sensor ID for N<0 or N>23
Change-Id: I484f81399f5e9dae9c759401091cc6f5acc733ff
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/28032
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
This commit is contained in:
@@ -662,7 +662,11 @@ static int lpc_init(void)
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, lpc_init, HOOK_PRIO_DEFAULT);
|
||||
/*
|
||||
* Set prio to higher than default so other inits can initialize their
|
||||
* memmap data.
|
||||
*/
|
||||
DECLARE_HOOK(HOOK_INIT, lpc_init, HOOK_PRIO_DEFAULT - 1);
|
||||
|
||||
|
||||
static int lpc_resume(void)
|
||||
|
||||
@@ -530,7 +530,7 @@ static int power_button_init(void)
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, power_button_init, HOOK_PRIO_DEFAULT + 1);
|
||||
DECLARE_HOOK(HOOK_INIT, power_button_init, HOOK_PRIO_DEFAULT);
|
||||
|
||||
|
||||
void power_button_interrupt(enum gpio_signal signal)
|
||||
|
||||
@@ -125,41 +125,36 @@ int pwm_set_keyboard_backlight(int percent)
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static void update_mapped_memory(void)
|
||||
/**
|
||||
* Return non-zero if fan is enabled but stalled
|
||||
*/
|
||||
static int fan_is_stalled(void)
|
||||
{
|
||||
int i, r;
|
||||
uint16_t *mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_FAN);
|
||||
/* Must be enabled with non-zero target to stall */
|
||||
if (!pwm_get_fan_enabled() || pwm_get_fan_target_rpm() == 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
mapped[i] = 0xffff;
|
||||
|
||||
r = pwm_get_fan_rpm();
|
||||
|
||||
/* Write fan speed. Or 0xFFFE for fan stalled. */
|
||||
if (r)
|
||||
mapped[0] = r;
|
||||
else
|
||||
mapped[0] = 0xfffe;
|
||||
}
|
||||
|
||||
static void check_fan_failure(void)
|
||||
{
|
||||
if (pwm_get_fan_target_rpm() != 0 && pwm_get_fan_enabled() &&
|
||||
((LM4_FAN_FANSTS >> (2 * FAN_CH_CPU)) & 0x03) == 0) {
|
||||
/*
|
||||
* Fan enabled but stalled. Issues warning. As we have thermal
|
||||
* shutdown protection, issuing warning here should be enough.
|
||||
*/
|
||||
host_set_single_event(EC_HOST_EVENT_THERMAL);
|
||||
cputs(CC_PWM, "[Fan stalled!]\n");
|
||||
}
|
||||
/* Check for stall condition */
|
||||
return (((LM4_FAN_FANSTS >> (2 * FAN_CH_CPU)) & 0x03) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void pwm_task(void)
|
||||
{
|
||||
uint16_t *mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_FAN);
|
||||
|
||||
while (1) {
|
||||
check_fan_failure();
|
||||
update_mapped_memory();
|
||||
if (fan_is_stalled()) {
|
||||
mapped[0] = EC_FAN_SPEED_STALLED;
|
||||
/*
|
||||
* Issue warning. As we have thermal shutdown
|
||||
* protection, issuing warning here should be enough.
|
||||
*/
|
||||
host_set_single_event(EC_HOST_EVENT_THERMAL);
|
||||
cprintf(CC_PWM, "[%T Fan stalled!]\n");
|
||||
} else
|
||||
mapped[0] = pwm_get_fan_rpm();
|
||||
|
||||
/* Update about once a second */
|
||||
usleep(1000000);
|
||||
}
|
||||
}
|
||||
@@ -299,7 +294,9 @@ static int pwm_init(void)
|
||||
{
|
||||
volatile uint32_t scratch __attribute__((unused));
|
||||
const struct pwm_state *prev;
|
||||
uint16_t *mapped;
|
||||
int version, size;
|
||||
int i;
|
||||
|
||||
/* Enable the fan module and delay a few clocks */
|
||||
LM4_SYSTEM_RCGCFAN = 1;
|
||||
@@ -359,6 +356,11 @@ static int pwm_init(void)
|
||||
pwm_enable_keyboard_backlight(1);
|
||||
}
|
||||
|
||||
/* Initialize memory-mapped data */
|
||||
mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_FAN);
|
||||
for (i = 0; i < EC_FAN_SPEED_ENTRIES; i++)
|
||||
mapped[i] = EC_FAN_SPEED_NOT_PRESENT;
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, pwm_init, HOOK_PRIO_DEFAULT);
|
||||
|
||||
@@ -76,20 +76,29 @@ static void poll_fast_sensors(void)
|
||||
static void update_mapped_memory(void)
|
||||
{
|
||||
int i, t;
|
||||
uint8_t *mapped = host_get_memmap(EC_MEMMAP_TEMP_SENSOR);
|
||||
uint8_t *mptr = host_get_memmap(EC_MEMMAP_TEMP_SENSOR);
|
||||
|
||||
memset(mapped, 0xff, 16);
|
||||
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;
|
||||
|
||||
for (i = 0; i < TEMP_SENSOR_COUNT && i < 16; ++i) {
|
||||
if (!temp_sensor_powered(i)) {
|
||||
mapped[i] = 0xfd;
|
||||
*mptr = EC_TEMP_SENSOR_NOT_POWERED;
|
||||
continue;
|
||||
}
|
||||
|
||||
t = temp_sensor_read(i);
|
||||
if (t != -1)
|
||||
mapped[i] = t - EC_TEMP_SENSOR_OFFSET;
|
||||
if (t == -1)
|
||||
*mptr = EC_TEMP_SENSOR_ERROR;
|
||||
else
|
||||
mapped[i] = 0xfe;
|
||||
*mptr = t - EC_TEMP_SENSOR_OFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,8 +107,14 @@ void temp_sensor_task(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Switch data is now present */
|
||||
*host_get_memmap(EC_MEMMAP_THERMAL_VERSION) = 1;
|
||||
/* Initialize memory-mapped data */
|
||||
memset(host_get_memmap(EC_MEMMAP_TEMP_SENSOR),
|
||||
EC_TEMP_SENSOR_NOT_PRESENT, EC_TEMP_SENSOR_ENTRIES);
|
||||
memset(host_get_memmap(EC_MEMMAP_TEMP_SENSOR_B),
|
||||
EC_TEMP_SENSOR_NOT_PRESENT, EC_TEMP_SENSOR_B_ENTRIES);
|
||||
|
||||
/* Temp sensor data is present, with B range supported. */
|
||||
*host_get_memmap(EC_MEMMAP_THERMAL_VERSION) = 2;
|
||||
|
||||
while (1) {
|
||||
for (i = 0; i < 4; ++i) {
|
||||
|
||||
@@ -65,8 +65,9 @@
|
||||
#define EC_MEMMAP_TEXT_MAX 8 /* Size of a string in the memory map */
|
||||
|
||||
/* The offset address of each type of data in mapped memory. */
|
||||
#define EC_MEMMAP_TEMP_SENSOR 0x00
|
||||
#define EC_MEMMAP_FAN 0x10
|
||||
#define EC_MEMMAP_TEMP_SENSOR 0x00 /* Temp sensors */
|
||||
#define EC_MEMMAP_FAN 0x10 /* Fan speeds */
|
||||
#define EC_MEMMAP_TEMP_SENSOR_B 0x18 /* Temp sensors (second set) */
|
||||
#define EC_MEMMAP_ID 0x20 /* 'E' 'C' */
|
||||
#define EC_MEMMAP_ID_VERSION 0x22 /* Version of data in 0x20 - 0x2f */
|
||||
#define EC_MEMMAP_THERMAL_VERSION 0x23 /* Version of data in 0x00 - 0x1f */
|
||||
@@ -89,6 +90,27 @@
|
||||
#define EC_MEMMAP_BATT_SERIAL 0x70 /* Battery Serial Number String */
|
||||
#define EC_MEMMAP_BATT_TYPE 0x78 /* Battery Type String */
|
||||
|
||||
/* Number of temp sensors at EC_MEMMAP_TEMP_SENSOR */
|
||||
#define EC_TEMP_SENSOR_ENTRIES 16
|
||||
/*
|
||||
* Number of temp sensors at EC_MEMMAP_TEMP_SENSOR_B.
|
||||
*
|
||||
* Valid only if EC_MEMMAP_THERMAL_VERSION returns >= 2.
|
||||
*/
|
||||
#define EC_TEMP_SENSOR_B_ENTRIES 8
|
||||
#define EC_TEMP_SENSOR_NOT_PRESENT 0xff
|
||||
#define EC_TEMP_SENSOR_ERROR 0xfe
|
||||
#define EC_TEMP_SENSOR_NOT_POWERED 0xfd
|
||||
/*
|
||||
* The offset of temperature value stored in mapped memory. This allows
|
||||
* reporting a temperature range of 200K to 454K = -73C to 181C.
|
||||
*/
|
||||
#define EC_TEMP_SENSOR_OFFSET 200
|
||||
|
||||
#define EC_FAN_SPEED_ENTRIES 4 /* Number of fans at EC_MEMMAP_FAN */
|
||||
#define EC_FAN_SPEED_NOT_PRESENT 0xffff /* Entry not present */
|
||||
#define EC_FAN_SPEED_STALLED 0xfffe /* Fan stalled */
|
||||
|
||||
/* Battery bit flags at EC_MEMMAP_BATT_FLAG. */
|
||||
#define EC_BATT_FLAG_AC_PRESENT 0x01
|
||||
#define EC_BATT_FLAG_BATT_PRESENT 0x02
|
||||
@@ -115,12 +137,6 @@
|
||||
#define EC_WIRELESS_SWITCH_WLAN 0x01
|
||||
#define EC_WIRELESS_SWITCH_BLUETOOTH 0x02
|
||||
|
||||
/*
|
||||
* The offset of temperature value stored in mapped memory. This allows
|
||||
* reporting a temperature range of 200K to 454K = -73C to 181C.
|
||||
*/
|
||||
#define EC_TEMP_SENSOR_OFFSET 200
|
||||
|
||||
/*
|
||||
* This header file is used in coreboot both in C and ACPI code. The ACPI code
|
||||
* is pre-processed to handle constants but the ASL compiler is unable to
|
||||
|
||||
@@ -684,25 +684,34 @@ int cmd_temperature(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Currently we only store up to 16 temperature sensor data in
|
||||
* mapped memory. */
|
||||
if (id >= 16) {
|
||||
printf("Sensor with ID greater than 16 unsupported.\n");
|
||||
if (id < 0 ||
|
||||
id >= EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES) {
|
||||
printf("Sensor ID invalid.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Reading temperature...");
|
||||
rv = read_mapped_mem8(EC_MEMMAP_TEMP_SENSOR + id);
|
||||
if (rv == 0xff) {
|
||||
if (id < EC_TEMP_SENSOR_ENTRIES)
|
||||
rv = read_mapped_mem8(EC_MEMMAP_TEMP_SENSOR + id);
|
||||
else if (read_mapped_mem8(EC_MEMMAP_THERMAL_VERSION) >= 2)
|
||||
rv = read_mapped_mem8(EC_MEMMAP_TEMP_SENSOR_B +
|
||||
id - EC_TEMP_SENSOR_ENTRIES);
|
||||
else {
|
||||
/* Sensor in second bank, but second bank isn't supported */
|
||||
rv = EC_TEMP_SENSOR_NOT_PRESENT;
|
||||
}
|
||||
|
||||
switch (rv) {
|
||||
case EC_TEMP_SENSOR_NOT_PRESENT:
|
||||
printf("Sensor not present\n");
|
||||
return -1;
|
||||
} else if (rv == 0xfe) {
|
||||
case EC_TEMP_SENSOR_ERROR:
|
||||
printf("Error\n");
|
||||
return -1;
|
||||
} else if (rv == 0xfd) {
|
||||
case EC_TEMP_SENSOR_NOT_POWERED:
|
||||
printf("Sensor disabled/unpowered\n");
|
||||
return -1;
|
||||
} else {
|
||||
default:
|
||||
printf("%d\n", rv + EC_TEMP_SENSOR_OFFSET);
|
||||
return 0;
|
||||
}
|
||||
@@ -840,13 +849,16 @@ int cmd_pwm_get_fan_rpm(int argc, char *argv[])
|
||||
int rv;
|
||||
|
||||
rv = read_mapped_mem16(EC_MEMMAP_FAN);
|
||||
if (rv == 0xffff)
|
||||
switch (rv) {
|
||||
case EC_FAN_SPEED_NOT_PRESENT:
|
||||
return -1;
|
||||
|
||||
if (rv == 0xfffe)
|
||||
case EC_FAN_SPEED_STALLED:
|
||||
printf("Fan stalled!\n");
|
||||
else
|
||||
break;
|
||||
default:
|
||||
printf("Current fan RPM: %d\n", rv);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user