diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-02-10 14:09:42 -0800 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2012-02-10 14:09:42 -0800 |
commit | 6063ad473c9921420145f6d0fa51873ba2d05062 (patch) | |
tree | acc0701717c8b47c5096eb9800f5466ee0f1dc34 | |
parent | 186c81dcac9ae96a1ace3ad5bf147fbf8fd35c50 (diff) | |
download | chrome-ec-6063ad473c9921420145f6d0fa51873ba2d05062.tar.gz |
Add PECI module and CPU temperature monitoring
Signed-off-by: Randall Spangler <rspangler@chromium.org>
BUG=chrome-os-partner:7493
TEST='powerbtn' to boot main processor, then 'temps' and 'pecitemp'
Change-Id: Id57526ebb37c8aecb05ecebccc2824f462b9de1a
-rw-r--r-- | board/link/board.h | 4 | ||||
-rw-r--r-- | board/link/board_temp_sensor.c | 21 | ||||
-rw-r--r-- | chip/lm4/build.mk | 1 | ||||
-rw-r--r-- | chip/lm4/config.h | 1 | ||||
-rw-r--r-- | chip/lm4/peci.c | 106 | ||||
-rw-r--r-- | chip/lm4/registers.h | 24 | ||||
-rw-r--r-- | common/main.c | 15 | ||||
-rw-r--r-- | include/peci.h | 28 |
8 files changed, 184 insertions, 16 deletions
diff --git a/board/link/board.h b/board/link/board.h index d199d6c74f..9b6c40f2e1 100644 --- a/board/link/board.h +++ b/board/link/board.h @@ -159,8 +159,10 @@ enum temp_sensor_id { TEMP_SENSOR_I2C_DIE_NEAR_CHARGER, /* EC internal temperature sensor */ TEMP_SENSOR_EC_INTERNAL, + /* CPU die temperature via PECI */ + TEMP_SENSOR_CPU_PECI, - /* TODO: I2C temperature sensors. */ + /* TODO: I2C remote temperature sensors. */ TEMP_SENSOR_COUNT }; diff --git a/board/link/board_temp_sensor.c b/board/link/board_temp_sensor.c index 4a937c9bf3..2477e36f34 100644 --- a/board/link/board_temp_sensor.c +++ b/board/link/board_temp_sensor.c @@ -9,6 +9,7 @@ #include "chip_temp_sensor.h" #include "board.h" #include "i2c.h" +#include "peci.h" #define TEMP_CPU_REG_ADDR ((0x40 << 1) | I2C_FLAG_BIG_ENDIAN) #define TEMP_PCH_REG_ADDR ((0x41 << 1) | I2C_FLAG_BIG_ENDIAN) @@ -24,14 +25,16 @@ * temp_sensor_id. */ const struct temp_sensor_t temp_sensors[TEMP_SENSOR_COUNT] = { - {"CPU", TEMP_SENSOR_I2C_DIE_NEAR_CPU, TEMP_CPU_ADDR, - temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print}, - {"PCH", TEMP_SENSOR_I2C_DIE_NEAR_PCH, TEMP_PCH_ADDR, - temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print}, - {"DDR", TEMP_SENSOR_I2C_DIE_NEAR_DDR, TEMP_DDR_ADDR, - temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print}, - {"Charger", TEMP_SENSOR_I2C_DIE_NEAR_CHARGER, TEMP_CHARGER_ADDR, - temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print}, + {"I2C_CPU", TEMP_SENSOR_I2C_DIE_NEAR_CPU, TEMP_CPU_ADDR, + temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print}, + {"I2C_PCH", TEMP_SENSOR_I2C_DIE_NEAR_PCH, TEMP_PCH_ADDR, + temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print}, + {"I2C_DDR", TEMP_SENSOR_I2C_DIE_NEAR_DDR, TEMP_DDR_ADDR, + temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print}, + {"I2C_Charger", TEMP_SENSOR_I2C_DIE_NEAR_CHARGER, TEMP_CHARGER_ADDR, + temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print}, {"ECInternal", TEMP_SENSOR_EC_INTERNAL, TEMP_SENSOR_NO_ADDR, - chip_temp_sensor_read, TEMP_SENSOR_NO_PRINT}, + chip_temp_sensor_read, TEMP_SENSOR_NO_PRINT}, + {"PECI", TEMP_SENSOR_CPU_PECI, TEMP_SENSOR_NO_ADDR, + peci_temp_sensor_read, TEMP_SENSOR_NO_PRINT}, }; diff --git a/chip/lm4/build.mk b/chip/lm4/build.mk index 028eeecc3f..63d0376102 100644 --- a/chip/lm4/build.mk +++ b/chip/lm4/build.mk @@ -13,6 +13,7 @@ chip-y+=clock.o gpio.o system.o uart.o power_button.o chip-y+=watchdog.o eeprom.o hwtimer.o chip-$(CONFIG_FLASH)+=flash.o chip-$(CONFIG_LPC)+=lpc.o +chip-$(CONFIG_PECI)+=peci.o chip-$(CONFIG_PWM)+=pwm.o chip-$(CONFIG_TEMP_SENSOR)+=chip_temp_sensor.o chip-$(CONFIG_TASK_KEYSCAN)+=keyboard_scan.o diff --git a/chip/lm4/config.h b/chip/lm4/config.h index f2224f8226..033810c682 100644 --- a/chip/lm4/config.h +++ b/chip/lm4/config.h @@ -37,6 +37,7 @@ #define CONFIG_PWM #define CONFIG_TEMP_SENSOR #define CONFIG_CHARGER +#define CONFIG_PECI /* Compile for running from RAM instead of flash */ /* #define COMPILE_FOR_RAM */ diff --git a/chip/lm4/peci.c b/chip/lm4/peci.c new file mode 100644 index 0000000000..fc0d09f71d --- /dev/null +++ b/chip/lm4/peci.c @@ -0,0 +1,106 @@ +/* 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. + */ + +/* PECI interface for Chrome EC */ + +#include "board.h" +#include "console.h" +#include "gpio.h" +#include "peci.h" +#include "registers.h" +#include "uart.h" +#include "util.h" + +/* Max junction temperature for processor in degrees C */ +/* TODO: read TjMax from processor via PECI */ +#define PECI_TJMAX 105 + +/* Initial PECI baud rate */ +#define PECI_BAUD_RATE 150000 + +/* Polling interval for PECI, in ms */ +#define PECI_POLL_INTERVAL_MS 200 + +/* Internal and external path delays, in ns */ +#define PECI_TD_FET_NS 25 /* Guess; TODO: what is real delay */ +#define PECI_TD_INT_NS 80 + + +/* Configures the GPIOs for the PECI module. */ +static void configure_gpios(void) +{ + /* PJ6 alternate function 1 = PECI Tx */ + gpio_set_alternate_function(LM4_GPIO_J, 0x40, 1); + + /* PJ7 analog input = PECI Rx (comparator) */ + LM4_GPIO_DEN(LM4_GPIO_J) &= ~0x80; +} + + +int peci_get_cpu_temp(void) +{ + int v = LM4_PECI_M0D0 & 0xffff; + + if (v >= 0x8000 && v <= 0x8fff) + return -1; + + return v >> 6; +} + + +int peci_temp_sensor_read(const struct temp_sensor_t* sensor) +{ + if (sensor->id != TEMP_SENSOR_CPU_PECI) + return EC_ERROR_INVAL; + + return peci_get_cpu_temp(); +} + +/*****************************************************************************/ +/* Console commands */ + +static int command_peci_temp(int argc, char **argv) +{ + int t = peci_get_cpu_temp(); + if (t == -1) { + uart_puts("Error reading CPU temperature via PECI\n"); + uart_printf("Error code = 0x%04x\n", LM4_PECI_M0D0 & 0xffff); + return EC_ERROR_UNKNOWN; + } + uart_printf("Current CPU temperature = %d K = %d C\n", t, t - 273); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp); + +/*****************************************************************************/ +/* Initialization */ + +int peci_init(void) +{ + volatile uint32_t scratch __attribute__((unused)); + int baud; + + /* Enable the PECI module and delay a few clocks */ + LM4_SYSTEM_RCGCPECI = 1; + scratch = LM4_SYSTEM_RCGCPECI; + + /* Configure GPIOs */ + configure_gpios(); + + /* Calculate baud setting from desired rate, compensating for internal + * and external delays. */ + baud = CPU_CLOCK / (4 * PECI_BAUD_RATE) - 2; + baud -= (CPU_CLOCK / 1000000) * (PECI_TD_FET_NS + PECI_TD_INT_NS) + / 1000; + + /* Set baud rate and polling rate */ + LM4_PECI_DIV = (baud << 16) | + (PECI_POLL_INTERVAL_MS * (CPU_CLOCK / 1000 / 4096)); + + /* Set up temperature monitoring to report in degrees K */ + LM4_PECI_CTL = ((PECI_TJMAX + 273) << 22) | 0x2001; + + return EC_SUCCESS; +} diff --git a/chip/lm4/registers.h b/chip/lm4/registers.h index a379be16d8..05e6db3ad7 100644 --- a/chip/lm4/registers.h +++ b/chip/lm4/registers.h @@ -124,6 +124,29 @@ static inline int lm4_fan_addr(int ch, int offset) #define LM4_EEPROM_EEINT LM4REG(0x400af040) #define LM4_EEPROM_EEHIDE LM4REG(0x400af050) +#define LM4_PECI_CTL LM4REG(0x400b0000) +#define LM4_PECI_DIV LM4REG(0x400b0004) +#define LM4_PECI_CMP LM4REG(0x400b0008) +#define LM4_PECI_M0D0C LM4REG(0x400b0010) +#define LM4_PECI_M0D1C LM4REG(0x400b0014) +#define LM4_PECI_M1D0C LM4REG(0x400b0018) +#define LM4_PECI_M1D1C LM4REG(0x400b001c) +#define LM4_PECI_M0D0 LM4REG(0x400b0040) +#define LM4_PECI_M0D1 LM4REG(0x400b0044) +#define LM4_PECI_M1D0 LM4REG(0x400b0048) +#define LM4_PECI_M1D1 LM4REG(0x400b004c) +#define LM4_PECI_IM LM4REG(0x400b0080) +#define LM4_PECI_RIS LM4REG(0x400b0084) +#define LM4_PECI_MIS LM4REG(0x400b0088) +#define LM4_PECI_IC LM4REG(0x400b008c) +#define LM4_PECI_ACADDR LM4REG(0x400b0100) +#define LM4_PECI_ACARG LM4REG(0x400b0104) +#define LM4_PECI_ACRDWR0 LM4REG(0x400b0108) +#define LM4_PECI_ACRDWR1 LM4REG(0x400b010c) +#define LM4_PECI_ACCMD LM4REG(0x400b0110) +#define LM4_PECI_ACCODE LM4REG(0x400b0114) + + #define LM4_HIBERNATE_HIBRTCC LM4REG(0x400fc000) #define LM4_HIBERNATE_HIBRTCM0 LM4REG(0x400fc004) #define LM4_HIBERNATE_HIBRTCLD LM4REG(0x400fc00c) @@ -172,6 +195,7 @@ static inline int lm4_fan_addr(int ch, int offset) #define LM4_SYSTEM_RCGCI2C LM4REG(0x400fe620) #define LM4_SYSTEM_RCGCADC LM4REG(0x400fe638) #define LM4_SYSTEM_RCGCLPC LM4REG(0x400fe648) +#define LM4_SYSTEM_RCGCPECI LM4REG(0x400fe650) #define LM4_SYSTEM_RCGCFAN LM4REG(0x400fe654) #define LM4_SYSTEM_RCGCEEPROM LM4REG(0x400fe658) #define LM4_SYSTEM_RCGCWTIMER LM4REG(0x400fe65c) diff --git a/common/main.c b/common/main.c index 79533b9411..70b2178d74 100644 --- a/common/main.c +++ b/common/main.c @@ -6,8 +6,10 @@ */ #include "adc.h" -#include "config.h" +#include "charger.h" +#include "chip_temp_sensor.h" #include "clock.h" +#include "config.h" #include "console.h" #include "eeprom.h" #include "flash.h" @@ -18,6 +20,7 @@ #include "keyboard.h" #include "lpc.h" #include "memory_commands.h" +#include "peci.h" #include "port80.h" #include "power_button.h" #include "powerdemo.h" @@ -25,16 +28,12 @@ #include "pwm_commands.h" #include "system.h" #include "task.h" -#ifdef CONFIG_TEMP_SENSOR #include "temp_sensor.h" -#endif #include "timer.h" #include "uart.h" +#include "usb_charge.h" #include "vboot.h" #include "watchdog.h" -#include "usb_charge.h" -#include "chip_temp_sensor.h" -#include "charger.h" int main(void) { @@ -87,6 +86,10 @@ int main(void) charger_init(); #endif +#ifdef CONFIG_PECI + peci_init(); +#endif + /* Print the reset cause */ uart_printf("\n\n--- Chrome EC initialized! ---\n"); uart_printf("(image: %s, version: %s, last reset: %s)\n", diff --git a/include/peci.h b/include/peci.h new file mode 100644 index 0000000000..95c9d0efe8 --- /dev/null +++ b/include/peci.h @@ -0,0 +1,28 @@ +/* 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. + */ + +/* PECI module for Chrome EC */ + +#ifndef __CROS_EC_PECI_H +#define __CROS_EC_PECI_H + +#include "common.h" +#include "temp_sensor.h" + +/* Initializes the module. */ +int peci_init(void); + +/* Returns the current CPU temperature in degrees K, or -1 if error. + * + * Note that the PECI interface is currently a little flaky; if you get an + * error, retry a bit later. */ +int peci_get_cpu_temp(void); + +/* Reads the CPU temperature sensor via PECI. This interface is for the + * temperature sensor module. Returns the temperature in degrees K, or -1 if + * error. */ +int peci_temp_sensor_read(const struct temp_sensor_t *sensor); + +#endif /* __CROS_EC_PECI_H */ |