diff options
Diffstat (limited to 'chip/npcx/sib.c')
-rw-r--r-- | chip/npcx/sib.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/chip/npcx/sib.c b/chip/npcx/sib.c new file mode 100644 index 0000000000..b8e2e17955 --- /dev/null +++ b/chip/npcx/sib.c @@ -0,0 +1,191 @@ +/* + * 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. + */ + +/* NPCX-specific SIB module for Chrome EC */ + +#include "console.h" +#include "hwtimer_chip.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +/* + * Timeout to wait for host transaction to be completed. + * + * For eSPI - it is 200 us. + * For LPC - it is 5 us. + */ +#ifdef CONFIG_HOSTCMD_ESPI +#define HOST_TRANSACTION_TIMEOUT_US 200 +#else +#define HOST_TRANSACTION_TIMEOUT_US 5 +#endif + +/* Console output macros */ +#ifdef DEBUG_SIB +#define CPUTS(outstr) cputs(CC_SYSTEM, outstr) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#else +#define CPUTS(...) +#define CPRINTS(...) +#endif + +/* + * Check host read is not in-progress and no timeout + */ +static void sib_wait_host_read_done(void) +{ + timestamp_t deadline, start; + + start = get_time(); + deadline.val = start.val + HOST_TRANSACTION_TIMEOUT_US; + while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD)) { + if (timestamp_expired(deadline, NULL)) { + CPRINTS("Unexpected time of host read transaction"); + break; + } + /* Handle ITIM32 overflow condition */ + __hw_clock_handle_overflow(start.le.hi); + } +} + +/* + * Check host write is not in-progress and no timeout + */ +static void sib_wait_host_write_done(void) +{ + timestamp_t deadline, start; + + start = get_time(); + deadline.val = start.val + HOST_TRANSACTION_TIMEOUT_US; + while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR)) { + if (timestamp_expired(deadline, NULL)) { + CPRINTS("Unexpected time of host write transaction"); + break; + } + /* Handle ITIM32 overflow condition */ + __hw_clock_handle_overflow(start.le.hi); + } +} + +/* Emulate host to read Keyboard I/O */ +uint8_t sib_read_kbc_reg(uint8_t io_offset) +{ + uint8_t data_value; + + /* Disable interrupts */ + interrupt_disable(); + + /* Lock host keyboard module */ + SET_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKHIKBD); + /* Verify Core read/write to host modules is not in progress */ + sib_wait_host_read_done(); + sib_wait_host_write_done(); + /* Enable Core access to keyboard module */ + SET_BIT(NPCX_CRSMAE, NPCX_CRSMAE_HIKBDAE); + + /* Specify the io_offset A0 = 0. the index register is accessed */ + NPCX_IHIOA = io_offset; + + /* Start a Core read from host module */ + SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD); + /* Wait while Core read operation is in progress */ + sib_wait_host_read_done(); + /* Read the data */ + data_value = NPCX_IHD; + + /* Disable Core access to keyboard module */ + CLEAR_BIT(NPCX_CRSMAE, NPCX_CRSMAE_HIKBDAE); + /* unlock host keyboard module */ + CLEAR_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKHIKBD); + + /* Enable interrupts */ + interrupt_enable(); + + return data_value; +} + +/* Super-IO read/write function */ +void sib_write_reg(uint8_t io_offset, uint8_t index_value, + uint8_t io_data) +{ + /* Disable interrupts */ + interrupt_disable(); + + /* Lock host CFG module */ + SET_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG); + /* Enable Core access to CFG module */ + SET_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE); + /* Verify Core read/write to host modules is not in progress */ + sib_wait_host_read_done(); + sib_wait_host_write_done(); + + /* Specify the io_offset A0 = 0. the index register is accessed */ + NPCX_IHIOA = io_offset; + /* Write the data. This starts the write access to the host module */ + NPCX_IHD = index_value; + /* Wait while Core write operation is in progress */ + sib_wait_host_write_done(); + + /* Specify the io_offset A0 = 1. the data register is accessed */ + NPCX_IHIOA = io_offset+1; + /* Write the data. This starts the write access to the host module */ + NPCX_IHD = io_data; + /* Wait while Core write operation is in progress */ + sib_wait_host_write_done(); + + /* Disable Core access to CFG module */ + CLEAR_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE); + /* unlock host CFG module */ + CLEAR_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG); + + /* Enable interrupts */ + interrupt_enable(); +} + +uint8_t sib_read_reg(uint8_t io_offset, uint8_t index_value) +{ + uint8_t data_value; + + /* Disable interrupts */ + interrupt_disable(); + + /* Lock host CFG module */ + SET_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG); + /* Enable Core access to CFG module */ + SET_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE); + /* Verify Core read/write to host modules is not in progress */ + sib_wait_host_read_done(); + sib_wait_host_write_done(); + + /* Specify the io_offset A0 = 0. the index register is accessed */ + NPCX_IHIOA = io_offset; + /* Write the data. This starts the write access to the host module */ + NPCX_IHD = index_value; + /* Wait while Core write operation is in progress */ + sib_wait_host_write_done(); + + /* Specify the io_offset A0 = 1. the data register is accessed */ + NPCX_IHIOA = io_offset+1; + /* Start a Core read from host module */ + SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD); + /* Wait while Core read operation is in progress */ + sib_wait_host_read_done(); + /* Read the data */ + data_value = NPCX_IHD; + + /* Disable Core access to CFG module */ + CLEAR_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE); + /* unlock host CFG module */ + CLEAR_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG); + + /* Enable interrupts */ + interrupt_enable(); + + return data_value; +} + |