summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/it83xx_evb/board.h1
-rw-r--r--chip/it83xx/peci.c246
-rw-r--r--common/build.mk1
-rw-r--r--common/peci.c165
-rw-r--r--include/config.h4
-rw-r--r--include/peci.h50
6 files changed, 233 insertions, 234 deletions
diff --git a/board/it83xx_evb/board.h b/board/it83xx_evb/board.h
index 379362d4c5..b3917a8c49 100644
--- a/board/it83xx_evb/board.h
+++ b/board/it83xx_evb/board.h
@@ -24,6 +24,7 @@
#define CONFIG_LOW_POWER_IDLE
#define CONFIG_LOW_POWER_S0
#define CONFIG_PECI
+#define CONFIG_PECI_COMMON
#define CONFIG_PECI_TJMAX 100
#define CONFIG_POWER_BUTTON
#define CONFIG_PWM
diff --git a/chip/it83xx/peci.c b/chip/it83xx/peci.c
index b8e0b7c451..07336eaaf6 100644
--- a/chip/it83xx/peci.c
+++ b/chip/it83xx/peci.c
@@ -5,46 +5,14 @@
/* PECI interface for Chrome EC */
-#include "chipset.h"
#include "clock.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
#include "hooks.h"
#include "peci.h"
#include "registers.h"
-#include "temp_sensor.h"
#include "util.h"
#include "timer.h"
#include "task.h"
-#define TEMP_AVG_LENGTH 4 /* Should be power of 2 */
-static int temp_vals[TEMP_AVG_LENGTH];
-static int temp_idx;
-
-#define PECI_TARGET_ADDRESS 0x30
-#define PECI_WRITE_DATA_FIFO_SIZE 15
-#define PECI_READ_DATA_FIFO_SIZE 16
-
-#define PECI_GET_TEMP_READ_LENGTH 2
-#define PECI_GET_TEMP_WRITE_LENGTH 0
-#define PECI_GET_TEMP_TIMEOUT_US 200
-
-/* PECI Command Code */
-enum peci_command_code {
- PECI_CMD_PING = 0x00,
- PECI_CMD_GET_DIB = 0xF7,
- PECI_CMD_GET_TEMP = 0x01,
- PECI_CMD_RD_PKG_CFG = 0xA1,
- PECI_CMD_WR_PKG_CFG = 0xA5,
- PECI_CMD_RD_IAMSR = 0xB1,
- PECI_CMD_WR_IAMSR = 0xB5,
- PECI_CMD_RD_PCI_CFG = 0x61,
- PECI_CMD_WR_PCI_CFG = 0x65,
- PECI_CMD_RD_PCI_CFG_LOCAL = 0xE1,
- PECI_CMD_WR_PCI_CFG_LOCAL = 0xE5,
-};
-
enum peci_status {
PECI_STATUS_NO_ERR = 0x00,
PECI_STATUS_HOBY = 0x01,
@@ -103,23 +71,11 @@ static void peci_reset(void)
/**
* Start a PECI transaction
*
- * @param addr client address
- * @param w_len write length (no include [Cmd Code] and [AW FCS])
- * @param r_len read length (no include [FCS])
- * @param cmd_code command code
- * @param *w_buf How buffer pointer of write data
- * @param *r_buf How buffer pointer of read data
- * @param timeout_us transaction timeout unit:us
+ * @param peci transaction data
*
* @return zero if successful, non-zero if error
*/
-static enum peci_status peci_transaction(uint8_t addr,
- uint8_t w_len,
- uint8_t r_len,
- enum peci_command_code cmd_code,
- uint8_t *w_buf,
- uint8_t *r_buf,
- int timeout_us)
+int peci_transaction(struct peci_data *peci)
{
uint8_t status;
int index;
@@ -140,22 +96,22 @@ static enum peci_status peci_transaction(uint8_t addr,
IT83XX_PECI_HOCTLR |= 0x34;
/* This register is the target address field of the PECI protocol. */
- IT83XX_PECI_HOTRADDR = addr;
+ IT83XX_PECI_HOTRADDR = peci->addr;
/* This register is the write length field of the PECI protocol. */
- ASSERT(w_len <= PECI_WRITE_DATA_FIFO_SIZE);
+ ASSERT(peci->w_len <= PECI_WRITE_DATA_FIFO_SIZE);
- if (cmd_code == PECI_CMD_PING) {
+ if (peci->cmd_code == PECI_CMD_PING) {
/* write length is 0 */
IT83XX_PECI_HOWRLR = 0x00;
} else {
- if ((cmd_code == PECI_CMD_WR_PKG_CFG) ||
- (cmd_code == PECI_CMD_WR_IAMSR) ||
- (cmd_code == PECI_CMD_WR_PCI_CFG) ||
- (cmd_code == PECI_CMD_WR_PCI_CFG_LOCAL)) {
+ if ((peci->cmd_code == PECI_CMD_WR_PKG_CFG) ||
+ (peci->cmd_code == PECI_CMD_WR_IAMSR) ||
+ (peci->cmd_code == PECI_CMD_WR_PCI_CFG) ||
+ (peci->cmd_code == PECI_CMD_WR_PCI_CFG_LOCAL)) {
/* write length include Cmd Code + AW FCS */
- IT83XX_PECI_HOWRLR = w_len + 2;
+ IT83XX_PECI_HOWRLR = peci->w_len + 2;
/* bit1, The bit enables the AW_FCS hardwired mechanism
* based on the PECI command. This bit is functional
@@ -167,22 +123,22 @@ static enum peci_status peci_transaction(uint8_t addr,
IT83XX_PECI_HOCTLR |= 0x02;
} else {
/* write length include Cmd Code */
- IT83XX_PECI_HOWRLR = w_len + 1;
+ IT83XX_PECI_HOWRLR = peci->w_len + 1;
IT83XX_PECI_HOCTLR &= ~0x02;
}
}
/* This register is the read length field of the PECI protocol. */
- ASSERT(r_len <= PECI_READ_DATA_FIFO_SIZE);
- IT83XX_PECI_HORDLR = r_len;
+ ASSERT(peci->r_len <= PECI_READ_DATA_FIFO_SIZE);
+ IT83XX_PECI_HORDLR = peci->r_len;
/* This register is the command field of the PECI protocol. */
- IT83XX_PECI_HOCMDR = cmd_code;
+ IT83XX_PECI_HOCMDR = peci->cmd_code;
/* The write data field of the PECI protocol. */
- for (index = 0x00; index < w_len; index++)
- IT83XX_PECI_HOWRDR = w_buf[index];
+ for (index = 0x00; index < peci->w_len; index++)
+ IT83XX_PECI_HOWRDR = peci->w_buf[index];
peci_current_task = task_get_current();
task_clear_pending_irq(IT83XX_IRQ_PECI);
@@ -192,15 +148,15 @@ static enum peci_status peci_transaction(uint8_t addr,
IT83XX_PECI_HOCTLR |= 0x01;
/* pre-set timeout */
- index = timeout_us;
- if (task_wait_event(timeout_us) != TASK_EVENT_TIMER)
+ index = peci->timeout_us;
+ if (task_wait_event(peci->timeout_us) != TASK_EVENT_TIMER)
index = 0;
task_disable_irq(IT83XX_IRQ_PECI);
peci_current_task = TASK_ID_INVALID;
- if (index < timeout_us) {
+ if (index < peci->timeout_us) {
status = IT83XX_PECI_HOSTAR;
@@ -213,8 +169,8 @@ static enum peci_status peci_transaction(uint8_t addr,
} else if (IT83XX_PECI_HOSTAR & PECI_STATUS_FINISH) {
/* The read data field of the PECI protocol. */
- for (index = 0x00; index < r_len; index++)
- r_buf[index] = IT83XX_PECI_HORDDR;
+ for (index = 0x00; index < peci->r_len; index++)
+ peci->r_buf[index] = IT83XX_PECI_HORDDR;
/* W/C */
IT83XX_PECI_HOSTAR = PECI_STATUS_FINISH;
@@ -237,72 +193,6 @@ static enum peci_status peci_transaction(uint8_t addr,
return status;
}
-int peci_get_cpu_temp(void)
-{
- uint8_t r_buf[PECI_GET_TEMP_READ_LENGTH] = {0};
- int cpu_temp = -1;
-
- if (peci_transaction(PECI_TARGET_ADDRESS,
- PECI_GET_TEMP_WRITE_LENGTH,
- PECI_GET_TEMP_READ_LENGTH,
- PECI_CMD_GET_TEMP,
- NULL,
- r_buf,
- PECI_GET_TEMP_TIMEOUT_US) ==
- PECI_STATUS_NO_ERR) {
-
- /* Get relative raw data of temperature. */
- cpu_temp = (r_buf[1] << 8) | r_buf[0];
-
-#ifdef CONFIG_PECI_TJMAX
- /* Convert relative raw data to degrees C. */
- cpu_temp = ((cpu_temp ^ 0xFFFF) + 1) >> 6;
- /* temperature in K */
- cpu_temp = (CONFIG_PECI_TJMAX - cpu_temp) + 273;
-#endif
- }
-
- return cpu_temp;
-}
-
-int peci_temp_sensor_get_val(int idx, int *temp_ptr)
-{
- int sum = 0;
- int success_cnt = 0;
- int i;
-
- if (!chipset_in_state(CHIPSET_STATE_ON))
- return EC_ERROR_NOT_POWERED;
-
- for (i = 0; i < TEMP_AVG_LENGTH; ++i) {
- if (temp_vals[i] >= 0) {
- success_cnt++;
- sum += temp_vals[i];
- }
- }
-
- /*
- * Require at least two valid samples. When the AP transitions into S0,
- * it is possible, depending on the timing of the PECI sample, to read
- * an invalid temperature. This is very rare, but when it does happen
- * the temperature returned is CONFIG_PECI_TJMAX. Requiring two valid
- * samples here assures us that one bad maximum temperature reading
- * when entering S0 won't cause us to trigger an over temperature.
- */
- if (success_cnt < 2)
- return EC_ERROR_UNKNOWN;
-
- *temp_ptr = sum / success_cnt;
- return EC_SUCCESS;
-}
-
-static void peci_temp_sensor_poll(void)
-{
- temp_vals[temp_idx] = peci_get_cpu_temp();
- temp_idx = (temp_idx + 1) & (TEMP_AVG_LENGTH - 1);
-}
-DECLARE_HOOK(HOOK_TICK, peci_temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR);
-
void peci_interrupt(void)
{
task_clear_pending_irq(IT83XX_IRQ_PECI);
@@ -314,8 +204,6 @@ void peci_interrupt(void)
static void peci_init(void)
{
- int i;
-
clock_enable_peripheral(CGC_OFFSET_PECI, 0, 0);
peci_init_vtt_freq();
@@ -324,97 +212,5 @@ static void peci_init(void)
/* bit4, PECI enable */
IT83XX_GPIO_GRC2 |= 0x10;
-
- /* Initialize temperature reading buffer to a sane value. */
- for (i = 0; i < TEMP_AVG_LENGTH; ++i)
- temp_vals[i] = 300; /* 27 C */
}
DECLARE_HOOK(HOOK_INIT, peci_init, HOOK_PRIO_DEFAULT);
-
-/*****************************************************************************/
-/* Console commands */
-
-static int peci_cmd(int argc, char **argv)
-{
- uint8_t r_buf[PECI_READ_DATA_FIFO_SIZE] = {0};
- uint8_t w_buf[PECI_WRITE_DATA_FIFO_SIZE] = {0};
-
- int addr, wlen, rlen, cmd, time_us, param;
- char *e;
-
- if ((argc < 6) || (argc > 8))
- return EC_ERROR_PARAM_COUNT;
-
- addr = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
-
- wlen = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- rlen = strtoi(argv[3], &e, 0);
- if (*e)
- return EC_ERROR_PARAM3;
-
- cmd = strtoi(argv[4], &e, 0);
- if (*e)
- return EC_ERROR_PARAM4;
-
- time_us = strtoi(argv[5], &e, 0);
- if (*e)
- return EC_ERROR_PARAM5;
-
- if (argc > 6) {
- param = strtoi(argv[6], &e, 0);
- if (*e)
- return EC_ERROR_PARAM6;
-
- /* MSB of parameter */
- w_buf[3] = (uint8_t)(param >> 24);
- /* LSB of parameter */
- w_buf[2] = (uint8_t)(param >> 16);
- /* Index */
- w_buf[1] = (uint8_t)(param >> 8);
- /* Host ID[7:1] & Retry[0] */
- w_buf[0] = (uint8_t)(param >> 0);
-
- if (argc > 7) {
- param = strtoi(argv[7], &e, 0);
- if (*e)
- return EC_ERROR_PARAM7;
-
- /* Data (1, 2 or 4 bytes) */
- w_buf[7] = (uint8_t)(param >> 24);
- w_buf[6] = (uint8_t)(param >> 16);
- w_buf[5] = (uint8_t)(param >> 8);
- w_buf[4] = (uint8_t)(param >> 0);
- }
- } else {
- wlen = 0x00;
- }
-
- if (peci_transaction(addr, wlen, rlen, cmd, w_buf, r_buf, time_us)) {
- ccprintf("PECI transaction error\n");
- return EC_ERROR_UNKNOWN;
- }
- ccprintf("PECI read data: %.*h\n", rlen, r_buf);
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(peci, peci_cmd,
- "addr wlen rlen cmd timeout(us)",
- "PECI command");
-
-static int command_peci_temp(int argc, char **argv)
-{
- int t = peci_get_cpu_temp();
- if (t == -1) {
- ccprintf("PECI get cpu temp error\n");
- return EC_ERROR_UNKNOWN;
- }
- ccprintf("CPU temp = %d K = %d C\n", t, K_TO_C(t));
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp,
- NULL,
- "Print CPU temperature");
diff --git a/common/build.mk b/common/build.mk
index 78c97149c5..88b384bc51 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -92,6 +92,7 @@ common-$(CONFIG_HOSTCMD_X86)+=acpi.o port80.o ec_features.o
common-$(CONFIG_MAG_CALIBRATE)+= mag_cal.o math_util.o vec3.o mat33.o mat44.o
common-$(CONFIG_MKBP_EVENT)+=mkbp_event.o
common-$(CONFIG_ONEWIRE)+=onewire.o
+common-$(CONFIG_PECI_COMMON)+=peci.o
common-$(CONFIG_PHYSICAL_PRESENCE)+=physical_presence.o
common-$(CONFIG_PINWEAVER)+=pinweaver.o
common-$(CONFIG_POWER_BUTTON)+=power_button.o
diff --git a/common/peci.c b/common/peci.c
new file mode 100644
index 0000000000..b4422de05e
--- /dev/null
+++ b/common/peci.c
@@ -0,0 +1,165 @@
+/* Copyright 2019 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 "chipset.h"
+#include "console.h"
+#include "peci.h"
+#include "util.h"
+
+static int peci_get_cpu_temp(int *cpu_temp)
+{
+ int rv;
+ uint8_t r_buf[PECI_GET_TEMP_READ_LENGTH] = {0};
+ struct peci_data peci = {
+ .cmd_code = PECI_CMD_GET_TEMP,
+ .addr = PECI_TARGET_ADDRESS,
+ .w_len = PECI_GET_TEMP_WRITE_LENGTH,
+ .r_len = PECI_GET_TEMP_READ_LENGTH,
+ .w_buf = NULL,
+ .r_buf = r_buf,
+ .timeout_us = PECI_GET_TEMP_TIMEOUT_US,
+ };
+
+ rv = peci_transaction(&peci);
+ if (rv)
+ return rv;
+
+ /* Get relative raw data of temperature. */
+ *cpu_temp = (r_buf[1] << 8) | r_buf[0];
+
+ /* Convert relative raw data to degrees C. */
+ *cpu_temp = ((*cpu_temp ^ 0xFFFF) + 1) >> 6;
+
+ /*
+ * When the AP transitions into S0, it is possible, depending on the
+ * timing of the PECI sample, to read an invalid temperature. This is
+ * very rare, but when it does happen the temperature returned is
+ * greater than or equal to CONFIG_PECI_TJMAX.
+ */
+ if (*cpu_temp >= CONFIG_PECI_TJMAX)
+ return EC_ERROR_UNKNOWN;
+
+ /* temperature in K */
+ *cpu_temp = CONFIG_PECI_TJMAX - *cpu_temp + 273;
+
+ return EC_SUCCESS;
+}
+
+int peci_temp_sensor_get_val(int idx, int *temp_ptr)
+{
+ int i, rv;
+
+ if (!chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_STANDBY))
+ return EC_ERROR_NOT_POWERED;
+
+ /*
+ * Retry reading PECI CPU temperature if the first sample is
+ * invalid or failed to obtain.
+ */
+ for (i = 0; i < 2; i++) {
+ rv = peci_get_cpu_temp(temp_ptr);
+ if (!rv)
+ break;
+ }
+
+ return rv;
+}
+
+/*****************************************************************************/
+/* Console commands */
+#ifdef CONFIG_CMD_PECI
+static int peci_cmd(int argc, char **argv)
+{
+ uint8_t r_buf[PECI_READ_DATA_FIFO_SIZE] = {0};
+ uint8_t w_buf[PECI_WRITE_DATA_FIFO_SIZE] = {0};
+ struct peci_data peci = {
+ .w_buf = w_buf,
+ .r_buf = r_buf,
+ };
+
+ int param;
+ char *e;
+
+ if ((argc < 6) || (argc > 8))
+ return EC_ERROR_PARAM_COUNT;
+
+ peci.addr = strtoi(argv[1], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM1;
+
+ peci.w_len = strtoi(argv[2], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM2;
+
+ peci.r_len = strtoi(argv[3], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM3;
+
+ peci.cmd_code = strtoi(argv[4], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM4;
+
+ peci.timeout_us = strtoi(argv[5], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM5;
+
+ if (argc > 6) {
+ param = strtoi(argv[6], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM6;
+
+ /* MSB of parameter */
+ w_buf[3] = (uint8_t)(param >> 24);
+ /* LSB of parameter */
+ w_buf[2] = (uint8_t)(param >> 16);
+ /* Index */
+ w_buf[1] = (uint8_t)(param >> 8);
+ /* Host ID[7:1] & Retry[0] */
+ w_buf[0] = (uint8_t)(param >> 0);
+
+ if (argc > 7) {
+ param = strtoi(argv[7], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM7;
+
+ /* Data (1, 2 or 4 bytes) */
+ w_buf[7] = (uint8_t)(param >> 24);
+ w_buf[6] = (uint8_t)(param >> 16);
+ w_buf[5] = (uint8_t)(param >> 8);
+ w_buf[4] = (uint8_t)(param >> 0);
+ }
+ } else {
+ peci.w_len = 0x00;
+ }
+
+ if (peci_transaction(&peci)) {
+ ccprintf("PECI transaction error\n");
+ return EC_ERROR_UNKNOWN;
+ }
+ ccprintf("PECI read data: %.*h\n", peci.r_len, r_buf);
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(peci, peci_cmd,
+ "addr wlen rlen cmd timeout(us)",
+ "PECI command");
+
+static int command_peci_temp(int argc, char **argv)
+{
+ int t;
+
+ if (peci_get_cpu_temp(&t) != EC_SUCCESS) {
+ ccprintf("PECI get cpu temp error\n");
+ return EC_ERROR_UNKNOWN;
+ }
+
+ ccprintf("CPU temp: %d K, %d C\n", t, K_TO_C(t));
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp,
+ NULL,
+ "Print CPU temperature");
+#endif /* CONFIG_CMD_PECI */
diff --git a/include/config.h b/include/config.h
index ca441d17cf..9745444353 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1155,6 +1155,7 @@
#undef CONFIG_CMD_PD_CONTROL
#undef CONFIG_CMD_PD_DEV_DUMP_INFO
#undef CONFIG_CMD_PD_FLASH
+#define CONFIG_CMD_PECI
#undef CONFIG_CMD_PLL
#undef CONFIG_CMD_PMU
#define CONFIG_CMD_POWERINDEBUG
@@ -2654,6 +2655,9 @@
/* Support PECI interface to x86 processor */
#undef CONFIG_PECI
+/* Common code for PECI interface to x86 processor */
+#undef CONFIG_PECI_COMMON
+
/*
* Maximum operating temperature in degrees Celcius used on some x86
* processors. CPU chip temperature is reported relative to this value and
diff --git a/include/peci.h b/include/peci.h
index c3bb4d62b2..c553eac40d 100644
--- a/include/peci.h
+++ b/include/peci.h
@@ -10,15 +10,38 @@
#include "common.h"
-/**
- * Get the current CPU temperature.
- *
- * Note that the PECI interface is currently a little flaky; if you get an
- * error, retry a bit later.
- *
- * @return the CPU temperature in degrees K, or -1 if error.
- */
-int peci_get_cpu_temp(void);
+#define PECI_TARGET_ADDRESS 0x30
+#define PECI_WRITE_DATA_FIFO_SIZE 15
+#define PECI_READ_DATA_FIFO_SIZE 16
+
+#define PECI_GET_TEMP_READ_LENGTH 2
+#define PECI_GET_TEMP_WRITE_LENGTH 0
+#define PECI_GET_TEMP_TIMEOUT_US 200
+
+/* PECI Command Code */
+enum peci_command_code {
+ PECI_CMD_PING = 0x00,
+ PECI_CMD_GET_DIB = 0xF7,
+ PECI_CMD_GET_TEMP = 0x01,
+ PECI_CMD_RD_PKG_CFG = 0xA1,
+ PECI_CMD_WR_PKG_CFG = 0xA5,
+ PECI_CMD_RD_IAMSR = 0xB1,
+ PECI_CMD_WR_IAMSR = 0xB5,
+ PECI_CMD_RD_PCI_CFG = 0x61,
+ PECI_CMD_WR_PCI_CFG = 0x65,
+ PECI_CMD_RD_PCI_CFG_LOCAL = 0xE1,
+ PECI_CMD_WR_PCI_CFG_LOCAL = 0xE5,
+};
+
+struct peci_data {
+ enum peci_command_code cmd_code; /* command code */
+ uint8_t addr; /* client address */
+ uint8_t w_len; /* write length */
+ uint8_t r_len; /* read length */
+ uint8_t *w_buf; /* buffer pointer of write data */
+ uint8_t *r_buf; /* buffer pointer of read data */
+ int timeout_us; /* transaction timeout unit:us */
+};
/**
* Get the last polled value of the PECI temp sensor.
@@ -30,4 +53,13 @@ int peci_get_cpu_temp(void);
*/
int peci_temp_sensor_get_val(int idx, int *temp_ptr);
+/**
+ * Start a PECI transaction
+ *
+ * @param peci transaction data
+ *
+ * @return zero if successful, non-zero if error
+ */
+int peci_transaction(struct peci_data *peci);
+
#endif /* __CROS_EC_PECI_H */