mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 09:01:35 +00:00
tpm: reset communications channels when resetting TPM
TPM resets happen asynchronously, conceivably there is some interface
(i2cs or sps) activity under way when TPM is reset.
Sps driver provides a means of disconnecting the client of the driver,
while the i2cs driver does not. Come to think of it, there is no real
need to provide a special function to disconnect a client, this makes
API simpler and allows to add driver initialization to the client
registration function.
To make tpm_registers.c more flexible - allow to register a callback
for interface initialization, this way when TPM is reset, the
interface can be also re-initialized and is guaranteed to start from
scratch after reset.
BRANCH=none
BUG=chrome-os-partner:52366
TEST=both firmware_TPMExtend and firmware_TPMKernelVersion autotests
pass
Change-Id: I212166a23f9cd512d8f75315377d1f5620aea070
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/388886
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
This commit is contained in:
committed by
chrome-bot
parent
75aaabcd9a
commit
5a6bb19a88
@@ -114,7 +114,6 @@ static void i2cs_init(void)
|
||||
/* Slave address is hardcoded to 0x50. */
|
||||
GWRITE(I2CS, SLAVE_DEVADDRVAL, 0x50);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, i2cs_init, HOOK_PRIO_DEFAULT);
|
||||
|
||||
/* Process the 'end of a write cycle' interrupt. */
|
||||
static void _i2cs_write_complete_int(void)
|
||||
@@ -258,9 +257,8 @@ void i2cs_post_read_fill_fifo(uint8_t *buffer, size_t len)
|
||||
|
||||
int i2cs_register_write_complete_handler(wr_complete_handler_f wc_handler)
|
||||
{
|
||||
if (write_complete_handler_)
|
||||
return -1;
|
||||
|
||||
task_disable_irq(GC_IRQNUM_I2CS0_INTR_WRITE_COMPLETE_INT);
|
||||
i2cs_init();
|
||||
write_complete_handler_ = wc_handler;
|
||||
task_enable_irq(GC_IRQNUM_I2CS0_INTR_WRITE_COMPLETE_INT);
|
||||
|
||||
|
||||
18
chip/g/sps.c
18
chip/g/sps.c
@@ -211,8 +211,8 @@ static rx_handler_f sps_rx_handler;
|
||||
int sps_register_rx_handler(enum sps_mode mode, rx_handler_f rx_handler,
|
||||
unsigned rx_fifo_threshold)
|
||||
{
|
||||
if (sps_rx_handler)
|
||||
return -1;
|
||||
task_disable_irq(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR);
|
||||
task_disable_irq(GC_IRQNUM_SPS0_CS_DEASSERT_INTR);
|
||||
|
||||
if (!rx_fifo_threshold)
|
||||
rx_fifo_threshold = 8; /* This is a sensible default. */
|
||||
@@ -225,18 +225,6 @@ int sps_register_rx_handler(enum sps_mode mode, rx_handler_f rx_handler,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sps_unregister_rx_handler(void)
|
||||
{
|
||||
if (!sps_rx_handler)
|
||||
return -1;
|
||||
|
||||
task_disable_irq(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR);
|
||||
task_disable_irq(GC_IRQNUM_SPS0_CS_DEASSERT_INTR);
|
||||
|
||||
sps_rx_handler = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sps_init(void)
|
||||
{
|
||||
/*
|
||||
@@ -503,8 +491,6 @@ static int command_sps(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
sps_unregister_rx_handler();
|
||||
|
||||
ccprintf("Processed %d frames\n", count - 1);
|
||||
ccprintf("rx count %d, tx count %d, tx_empty %d, max rx batch %d\n",
|
||||
sps_rx_count, sps_tx_count,
|
||||
|
||||
@@ -262,7 +262,7 @@ static void tpm_rx_handler(uint8_t *data, size_t data_size, int cs_disabled)
|
||||
init_new_cycle();
|
||||
}
|
||||
|
||||
void sps_tpm_enable(void)
|
||||
static void sps_tpm_enable(void)
|
||||
{
|
||||
/*
|
||||
* Let's make sure we get an interrupt as soon as the header is
|
||||
@@ -272,11 +272,12 @@ void sps_tpm_enable(void)
|
||||
init_new_cycle();
|
||||
}
|
||||
|
||||
void sps_tpm_disable(void)
|
||||
|
||||
static void sps_if_register(void)
|
||||
{
|
||||
sps_tpm_state = SPS_TPM_STATE_PONDERING;
|
||||
sps_unregister_rx_handler();
|
||||
/* We don't care anymore, so we can sleep whenever */
|
||||
delay_sleep_by(0);
|
||||
enable_sleep(SLEEP_MASK_SPI);
|
||||
if (!(system_get_board_properties() & BOARD_SLAVE_CONFIG_SPI))
|
||||
return;
|
||||
|
||||
tpm_register_interface(sps_tpm_enable);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, sps_if_register, HOOK_PRIO_LAST);
|
||||
|
||||
@@ -223,8 +223,16 @@ static void wr_complete_handler(void *i2cs_data, size_t i2cs_data_size)
|
||||
gpio_set_level(GPIO_INT_AP_L, 1);
|
||||
}
|
||||
|
||||
static void i2cs_tpm_init(void)
|
||||
static void i2cs_tpm_enable(void)
|
||||
{
|
||||
i2cs_register_write_complete_handler(wr_complete_handler);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, i2cs_tpm_init, HOOK_PRIO_LAST);
|
||||
|
||||
static void i2cs_if_register(void)
|
||||
{
|
||||
if (!(system_get_board_properties() & BOARD_SLAVE_CONFIG_I2C))
|
||||
return;
|
||||
|
||||
tpm_register_interface(i2cs_tpm_enable);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, i2cs_if_register, HOOK_PRIO_LAST);
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#define GOOGLE_DID 0x0028
|
||||
#define CR50_RID 0 /* No revision ID yet */
|
||||
|
||||
static uint8_t reset_in_progress __attribute__((section(".bss.noreinit")));
|
||||
|
||||
/* Tpm state machine states. */
|
||||
enum tpm_states {
|
||||
tpm_state_idle,
|
||||
@@ -372,6 +374,9 @@ void tpm_register_put(uint32_t regaddr, const uint8_t *data, uint32_t data_size)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (reset_in_progress)
|
||||
return;
|
||||
|
||||
CPRINTF("%s(0x%03x, %d,", __func__, regaddr, data_size);
|
||||
for (i = 0; i < data_size && i < 4; i++)
|
||||
CPRINTF(" %02x", data[i]);
|
||||
@@ -443,6 +448,9 @@ void tpm_register_get(uint32_t regaddr, uint8_t *dest, uint32_t data_size)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (reset_in_progress)
|
||||
return;
|
||||
|
||||
CPRINTF("%s(0x%06x, %d)", __func__, regaddr, data_size);
|
||||
switch (regaddr) {
|
||||
case TPM_DID_VID:
|
||||
@@ -492,11 +500,23 @@ void tpm_register_get(uint32_t regaddr, uint8_t *dest, uint32_t data_size)
|
||||
CPRINTF("\n");
|
||||
}
|
||||
|
||||
static interface_restart_func if_restart
|
||||
__attribute__((section(".bss.noreinit")));
|
||||
void tpm_register_interface(interface_restart_func interface_restart)
|
||||
{
|
||||
if_restart = interface_restart;
|
||||
}
|
||||
|
||||
static void tpm_init(void)
|
||||
{
|
||||
/* This is more related to TPM task activity than TPM transactions */
|
||||
cprints(CC_TASK, "%s", __func__);
|
||||
|
||||
if (system_rolling_reboot_suspected()) {
|
||||
cprints(CC_TASK, "%s interrupted", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
set_tpm_state(tpm_state_idle);
|
||||
tpm_.regs.access = tpm_reg_valid_sts;
|
||||
/*
|
||||
@@ -534,6 +554,9 @@ static void tpm_init(void)
|
||||
}
|
||||
|
||||
_plat__SetNvAvail();
|
||||
|
||||
/* Reinitialize TPM interface. */
|
||||
if_restart();
|
||||
}
|
||||
|
||||
size_t tpm_get_burst_size(void)
|
||||
@@ -604,11 +627,11 @@ int tpm_reset(void)
|
||||
|
||||
static void tpm_reset_now(void)
|
||||
{
|
||||
reset_in_progress = 1;
|
||||
|
||||
/* This is more related to TPM task activity than TPM transactions */
|
||||
cprints(CC_TASK, "%s", __func__);
|
||||
|
||||
sps_tpm_disable();
|
||||
|
||||
/*
|
||||
* Clear the TPM library's zero-init data. Note that the linker script
|
||||
* includes this file's .bss in the same section, so it will be cleared
|
||||
@@ -626,22 +649,17 @@ static void tpm_reset_now(void)
|
||||
/* Re-initialize our registers */
|
||||
tpm_init();
|
||||
|
||||
sps_tpm_enable();
|
||||
|
||||
if (waiting_for_reset != TASK_ID_INVALID) {
|
||||
/* Wake the waiting task, if any */
|
||||
task_set_event(waiting_for_reset, TPM_EVENT_RESET, 0);
|
||||
waiting_for_reset = TASK_ID_INVALID;
|
||||
}
|
||||
reset_in_progress = 0;
|
||||
}
|
||||
|
||||
void tpm_task(void)
|
||||
{
|
||||
if (system_rolling_reboot_suspected())
|
||||
return;
|
||||
|
||||
tpm_init();
|
||||
sps_tpm_enable();
|
||||
while (1) {
|
||||
uint8_t *response;
|
||||
unsigned response_size;
|
||||
|
||||
@@ -23,14 +23,13 @@ void tpm_register_put(uint32_t regaddr,
|
||||
/* The SPI master is reading data from a TPM register. */
|
||||
void tpm_register_get(uint32_t regaddr, uint8_t *dest, uint32_t data_size);
|
||||
|
||||
/* Enable SPS TPM driver. */
|
||||
void sps_tpm_enable(void);
|
||||
/* Disable SPS TPM driver. */
|
||||
void sps_tpm_disable(void);
|
||||
|
||||
/* Get the current value of the burst size field of the status register. */
|
||||
size_t tpm_get_burst_size(void);
|
||||
|
||||
/* Register a function to restart TPM communications layer. */
|
||||
typedef void (*interface_restart_func)(void);
|
||||
void tpm_register_interface(interface_restart_func interface_restart);
|
||||
|
||||
/*
|
||||
* Reset the TPM. This sends a request to the TPM task, so that the reset can
|
||||
* happen when the TPM task finishes whatever it's doing at the moment.
|
||||
|
||||
Reference in New Issue
Block a user