192 lines
5.0 KiB
C
192 lines
5.0 KiB
C
/*
|
|
* 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;
|
|
}
|
|
|