diff options
Diffstat (limited to 'chip/npcx/peci.c')
-rw-r--r-- | chip/npcx/peci.c | 298 |
1 files changed, 0 insertions, 298 deletions
diff --git a/chip/npcx/peci.c b/chip/npcx/peci.c deleted file mode 100644 index badfbd87d9..0000000000 --- a/chip/npcx/peci.c +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright 2014 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 "clock.h" -#include "clock_chip.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "peci.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "temp_sensor.h" -#include "util.h" - - -/* Initial PECI baud rate */ -#define PECI_BAUD_RATE 750000 - -#define TEMP_AVG_LENGTH 4 /* Should be power of 2 */ - - -/* PECI Time-out */ -#define PECI_DONE_TIMEOUT_US (10*MSEC) - -#define NULL_PENDING_TASK_ID 0xFFFFFFFF -#define PECI_MAX_FIFO_SIZE 16 -#define PROC_SOCKET 0x30 -/* PECI Command Code */ -enum peci_command_t { - PECI_COMMAND_PING = 0x00, - PECI_COMMAND_GET_DIB = 0xF7, - PECI_COMMAND_GET_TEMP = 0x01, - PECI_COMMAND_RD_PKG_CFG = 0xA1, - PECI_COMMAND_WR_PKG_CFG = 0xA5, - PECI_COMMAND_RD_IAMSR = 0xB1, - PECI_COMMAND_RD_PCI_CFG = 0x61, - PECI_COMMAND_RD_PCI_CFG_LOCAL = 0xE1, - PECI_COMMAND_WR_PCI_CFG_LOCAL = 0xE5, - PECI_COMMAND_NONE = 0xFF -}; - -#define PECI_COMMAND_GET_TEMP_WR_LENS 0x00 -#define PECI_COMMAND_GET_TEMP_RD_LENS 0x02 - -/* PECI Domain Number */ -static int temp_vals[TEMP_AVG_LENGTH]; -static int temp_idx; -static uint8_t peci_sts; -/* For PECI Done interrupt usage */ -static int peci_pending_task_id; - -/*****************************************************************************/ -/* Internal functions */ - -/** - * This routine initiates the parameters of a PECI transaction - * - * @param wr_length How many byte of *wr_data went to be send - * @param rd_length How many byte went to received (not include FCS) - * @param cmd_code Command code - * @param *wr_data Buffer pointer of write data - * @return TASK_EVENT_PECI_DONE that mean slave had a response - */ -static uint32_t peci_trans( - uint8_t wr_length, - uint8_t rd_length, - enum peci_command_t cmd_code, - uint8_t *wr_data -) -{ - uint32_t events; - /* Ensure no PECI transaction is in progress */ - if (IS_BIT_SET(NPCX_PECI_CTL_STS, NPCX_PECI_CTL_STS_START_BUSY)) { - /* - * PECI transaction is in progress - - * can not initiate a new one - */ - return 0; - } - /* Set basic transaction parameters */ - NPCX_PECI_ADDR = PROC_SOCKET; - NPCX_PECI_CMD = cmd_code; - /* Aviod over space */ - if (rd_length > PECI_MAX_FIFO_SIZE) - rd_length = PECI_MAX_FIFO_SIZE; - /* Read-Length */ - NPCX_PECI_RD_LENGTH = rd_length; - if (wr_length > PECI_MAX_FIFO_SIZE) - wr_length = PECI_MAX_FIFO_SIZE; - /* copy of data */ - for (events = 0; events < wr_length; events++) - NPCX_PECI_DATA_OUT(events) = wr_data[events]; - /* Write-Length */ - if (cmd_code != PECI_COMMAND_PING) { - if ((cmd_code == PECI_COMMAND_WR_PKG_CFG) || - (cmd_code == PECI_COMMAND_WR_PCI_CFG_LOCAL)) { - /*CMD+AWFCS*/ - NPCX_PECI_WR_LENGTH = wr_length + 2; - /* Enable AWFCS */ - SET_BIT(NPCX_PECI_CTL_STS, NPCX_PECI_CTL_STS_AWFCS_EN); - } else { - /*CMD*/ - NPCX_PECI_WR_LENGTH = wr_length + 1; - /* Enable AWFCS */ - CLEAR_BIT(NPCX_PECI_CTL_STS, - NPCX_PECI_CTL_STS_AWFCS_EN); - } - } - - /* Start the PECI transaction */ - SET_BIT(NPCX_PECI_CTL_STS, NPCX_PECI_CTL_STS_START_BUSY); - - /* It should be using a interrupt , don't waste cpu computing power */ - peci_pending_task_id = task_get_current(); - return task_wait_event_mask(TASK_EVENT_PECI_DONE, - PECI_DONE_TIMEOUT_US); - -} - -/** - * PECI transaction error status. - * - * @return Bit3 - CRC error Bit4 - ABRT error - */ -static uint8_t peci_check_error_state(void) -{ - return peci_sts; -} - -/*****************************************************************************/ -/* PECI drivers */ -int peci_get_cpu_temp(void) -{ - uint32_t events; - int16_t cpu_temp = -1; - - /* Start PECI trans */ - events = peci_trans(PECI_COMMAND_GET_TEMP_WR_LENS, - PECI_COMMAND_GET_TEMP_RD_LENS, - PECI_COMMAND_GET_TEMP, NULL); - /* if return DONE , that mean slave had a PECI response */ - if ((events & TASK_EVENT_PECI_DONE) == TASK_EVENT_PECI_DONE) { - /* check CRC & ABRT */ - events = peci_check_error_state(); - if (events) { - ; - } else { - uint16_t *ptr; - ptr = (uint16_t *)&cpu_temp; - ptr[0] = (NPCX_PECI_DATA_IN(1) << 8) | - (NPCX_PECI_DATA_IN(0) << 0); - } - } - return (int)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) -{ - int val; - - val = peci_get_cpu_temp(); - if (val != -1) { - temp_vals[temp_idx] = val; - temp_idx = (temp_idx + 1) & (TEMP_AVG_LENGTH - 1); - } -} -DECLARE_HOOK(HOOK_TICK, peci_temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR); - -static void peci_freq_changed(void) -{ - /* PECI's clock source is FMCLK */ - int freq = clock_get_fm_freq(); - int baud = 0xF; - - /* Disable polling while reconfiguring */ - NPCX_PECI_CTL_STS = 0; - - /* - * Set the maximum bit rate used by the PECI module during both - * Address Timing Negotiation and Data Timing Negotiation. - * The resulting maximum bit rate MAX_BIT_RATE in decimal is - * according to the following formula: - * - * MAX_BIT_RATE [d] = (freq / (4 * baudrate)) - 1 - * Maximum bit rate should not extend the field's boundaries. - */ - if (freq != 0) { - baud = (uint8_t)(freq / (4 * PECI_BAUD_RATE)) - 1; - /* Set maximum PECI baud rate (bit0 - bit4) */ - if (baud > 0x1F) - baud = 0x1F; - } - /* Enhanced High-Speed */ - if (baud >= 7) { - CLEAR_BIT(NPCX_PECI_RATE, 6); - CLEAR_BIT(NPCX_PECI_CFG, 3); - } else { - SET_BIT(NPCX_PECI_RATE, 6); - SET_BIT(NPCX_PECI_CFG, 3); - } - /* Setting Rate */ - NPCX_PECI_RATE = baud; -} -DECLARE_HOOK(HOOK_FREQ_CHANGE, peci_freq_changed, HOOK_PRIO_DEFAULT); - -static void peci_init(void) -{ - int i; - - /* Enable clock for PECI peripheral */ - clock_enable_peripheral(CGC_OFFSET_PECI, CGC_PECI_MASK, - CGC_MODE_RUN | CGC_MODE_SLEEP); - /* Set PECI freq */ - peci_freq_changed(); - - /* make sure PECI_DATA function pin enable */ - CLEAR_BIT(NPCX_DEVALT(0x0A), 6); - /* Set initial clock frequency */ - peci_freq_changed(); - /* Initialize temperature reading buffer to a valid value. */ - for (i = 0; i < TEMP_AVG_LENGTH; ++i) - temp_vals[i] = 300; /* 27 C */ - - /* init Pending task id */ - peci_pending_task_id = NULL_PENDING_TASK_ID; - /* Enable PECI Done interrupt */ - SET_BIT(NPCX_PECI_CTL_STS, NPCX_PECI_CTL_STS_DONE_EN); - - task_enable_irq(NPCX_IRQ_PECI); -} -DECLARE_HOOK(HOOK_INIT, peci_init, HOOK_PRIO_DEFAULT); - -/* If received a PECI DONE interrupt, post the event to PECI task */ -void peci_done_interrupt(void){ - if (peci_pending_task_id != NULL_PENDING_TASK_ID) - task_set_event(peci_pending_task_id, TASK_EVENT_PECI_DONE); - peci_sts = NPCX_PECI_CTL_STS & 0x18; - /* no matter what, clear status bit again */ - SET_BIT(NPCX_PECI_CTL_STS, NPCX_PECI_CTL_STS_DONE); - SET_BIT(NPCX_PECI_CTL_STS, NPCX_PECI_CTL_STS_CRC_ERR); - SET_BIT(NPCX_PECI_CTL_STS, NPCX_PECI_CTL_STS_ABRT_ERR); -} -DECLARE_IRQ(NPCX_IRQ_PECI, peci_done_interrupt, 4); - -/*****************************************************************************/ -/* Console commands */ - -static int command_peci_temp(int argc, char **argv) -{ - int t = peci_get_cpu_temp(); - if (t == -1) { - ccprintf("PECI response timeout\n"); - return EC_ERROR_UNKNOWN; - } - ccprintf("CPU temp = %d K = %d\n", t, K_TO_C(t)); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp, - NULL, - "Print CPU temperature"); |