summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-02-10 14:09:42 -0800
committerRandall Spangler <rspangler@chromium.org>2012-02-10 14:09:42 -0800
commit6063ad473c9921420145f6d0fa51873ba2d05062 (patch)
treeacc0701717c8b47c5096eb9800f5466ee0f1dc34
parent186c81dcac9ae96a1ace3ad5bf147fbf8fd35c50 (diff)
downloadchrome-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.h4
-rw-r--r--board/link/board_temp_sensor.c21
-rw-r--r--chip/lm4/build.mk1
-rw-r--r--chip/lm4/config.h1
-rw-r--r--chip/lm4/peci.c106
-rw-r--r--chip/lm4/registers.h24
-rw-r--r--common/main.c15
-rw-r--r--include/peci.h28
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 */