From 88bce43426c9d97f321ca96d8cf55250acc07963 Mon Sep 17 00:00:00 2001 From: Mary Ruthven Date: Tue, 5 Jan 2021 18:47:34 -0800 Subject: coil: sps->spp BUG=b:175244613 TEST=make buildall -j Change-Id: Ia34cccffdd6a82c25b479bb8d2e6370bbf00baf0 Signed-off-by: Mary Ruthven Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2615121 Reviewed-by: Namyoon Woo --- chip/g/build.mk | 2 +- chip/g/spp.c | 616 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ chip/g/spp.h | 54 +++++ chip/g/sps.c | 616 ------------------------------------------------------- chip/g/sps.h | 54 ----- chip/g/sps_tpm.c | 56 ++--- 6 files changed, 699 insertions(+), 699 deletions(-) create mode 100644 chip/g/spp.c create mode 100644 chip/g/spp.h delete mode 100644 chip/g/sps.c delete mode 100644 chip/g/sps.h (limited to 'chip') diff --git a/chip/g/build.mk b/chip/g/build.mk index c52e51cab3..621ab6c1b0 100644 --- a/chip/g/build.mk +++ b/chip/g/build.mk @@ -70,7 +70,7 @@ chip-$(CONFIG_CCD_ITE_PROGRAMMING)+= ite_sync.o chip-$(CONFIG_ENABLE_H1_ALERTS)+= alerts.o chip-$(CONFIG_USB_FW_UPDATE)+= usb_upgrade.o chip-$(CONFIG_NON_HC_FW_UPDATE)+= upgrade_fw.o post_reset.o upgrade.o -chip-$(CONFIG_SPP)+= sps.o +chip-$(CONFIG_SPP)+= spp.o chip-$(CONFIG_TPM_SPS)+=sps_tpm.o chip-$(CONFIG_WATCHDOG)+=watchdog.o diff --git a/chip/g/spp.c b/chip/g/spp.c new file mode 100644 index 0000000000..377d11d296 --- /dev/null +++ b/chip/g/spp.c @@ -0,0 +1,616 @@ +/* Copyright 2015 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. + */ + +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "pmu.h" +#include "registers.h" +#include "spp.h" +#include "system.h" +#include "task.h" +#include "watchdog.h" + +/* + * This file is a driver for the CR50 SPS (SPI slave) controller. The + * controller deploys a 2KB buffer split evenly between receive and transmit + * directions. + * + * Each one kilobyte of memory is organized into a FIFO with read + * and write pointers. RX FIFO write and TX FIFO read pointers are managed by + * hardware. RX FIFO read and TX FIFO write pointers are managed by + * software. + * + * As of time of writing, TX fifo allows only 32 bit wide write accesses, + * which makes the function feeding the FIFO unnecessarily complicated. + * + * Even though both FIFOs are 1KByte in size, the hardware pointers + * controlling access to the FIFOs are 11 bits in size, this is another issue + * requiring special software handling. + * + * The driver API includes three functions: + * + * - transmit a packet of a certain size, runs on the task context and can + * exit before the entire packet is transmitted., + * + * - register a receive callback. The callback is running in interrupt + * context. Registering the callback (re)initializes the interface. + * + * - unregister receive callback. + */ + +/* + * Hardware pointers use one extra bit, which means that indexing FIFO and + * values written into the pointers have to have different sizes. Tracked under + * http://b/20894690 + */ +#define SPP_FIFO_PTR_MASK ((SPP_FIFO_MASK << 1) | 1) + +#define SPP_TX_FIFO_BASE_ADDR (GBASE(SPS) + 0x1000) +#define SPP_RX_FIFO_BASE_ADDR (SPP_TX_FIFO_BASE_ADDR + SPP_FIFO_SIZE) + +/* SPP Statistic Counters */ +static uint32_t spp_tx_count, spp_rx_count, tx_empty_count, max_rx_batch; + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_SPS, outstr) +#define CPRINTS(format, args...) cprints(CC_SPS, format, ## args) + +/* Flag indicating if there has been any data received while CS was asserted. */ +static uint8_t seen_data; + +static bool int_ap_extension_enabled_; + +void spp_tx_status(uint8_t byte) +{ + GREG32(SPS, DUMMY_WORD) = byte; +} + +/* + * Push data to the SPS TX FIFO + * @param data Pointer to 8-bit data + * @param data_size Number of bytes to transmit + * @return : actual number of bytes placed into tx fifo + */ +int spp_transmit(uint8_t *data, size_t data_size) +{ + volatile uint32_t *spp_tx_fifo; + uint32_t rptr; + uint32_t wptr; + uint32_t fifo_room; + int bytes_sent; + int inst = 0; + + if (GREAD_FIELD_I(SPS, inst, ISTATE, TXFIFO_EMPTY)) + tx_empty_count++; /* Inside packet this means underrun. */ + + spp_tx_fifo = (volatile uint32_t *)SPP_TX_FIFO_BASE_ADDR; + + wptr = GREG32_I(SPS, inst, TXFIFO_WPTR); + rptr = GREG32_I(SPS, inst, TXFIFO_RPTR); + fifo_room = (rptr - wptr - 1) & SPP_FIFO_MASK; + + if (fifo_room < data_size) { + bytes_sent = fifo_room; + data_size = fifo_room; + } else { + bytes_sent = data_size; + } + + spp_tx_fifo += (wptr & SPP_FIFO_MASK) / sizeof(*spp_tx_fifo); + + while (data_size) { + + if ((wptr & 3) || (data_size < 4) || ((uintptr_t)data & 3)) { + /* + * Either we have less then 4 bytes to send, or one of + * the pointers is not 4 byte aligned. Need to go byte + * by byte. + */ + uint32_t fifo_contents; + int bit_shift; + + fifo_contents = *spp_tx_fifo; + do { + /* + * CR50 SPS controller does not allow byte + * accesses for writes into the FIFO, so read + * modify/write is required. Tracked under + * http://b/20894727 + */ + bit_shift = 8 * (wptr & 3); + fifo_contents &= ~(0xff << bit_shift); + fifo_contents |= + (((uint32_t)(*data++)) << bit_shift); + data_size--; + wptr++; + + } while (data_size && (wptr & 3)); + + *spp_tx_fifo++ = fifo_contents; + } else { + /* + * Both fifo wptr and data are aligned and there is + * plenty to send. + */ + *spp_tx_fifo++ = *((uint32_t *)data); + data += 4; + data_size -= 4; + wptr += 4; + } + GREG32_I(SPS, inst, TXFIFO_WPTR) = wptr & SPP_FIFO_PTR_MASK; + + /* Make sure FIFO pointer wraps along with the index. */ + if (!(wptr & SPP_FIFO_MASK)) + spp_tx_fifo = (volatile uint32_t *) + SPP_TX_FIFO_BASE_ADDR; + } + + /* + * Start TX if necessary. This happens after FIFO is primed, which + * helps alleviate TX underrun problems but introduces delay before + * data starts coming out. + */ + if (!GREAD_FIELD(SPS, FIFO_CTRL, TXFIFO_EN)) + GWRITE_FIELD(SPS, FIFO_CTRL, TXFIFO_EN, 1); + + spp_tx_count += bytes_sent; + return bytes_sent; +} + +static int spp_cs_asserted(void) +{ + /* + * Read the current value on the SPS CS line and return the iversion + * of it (CS is active low). + */ + return !GREAD_FIELD(SPS, VAL, CSB); +} + +/** Configure the data transmission format + * + * @param mode Clock polarity and phase mode (0 - 3) + * + */ +static void spp_configure(enum spp_mode mode, enum spi_clock_mode clk_mode, + unsigned rx_fifo_threshold) +{ + /* Disable All Interrupts */ + GREG32(SPS, ICTRL) = 0; + + GWRITE_FIELD(SPS, CTRL, MODE, mode); + GWRITE_FIELD(SPS, CTRL, IDLE_LVL, 0); + GWRITE_FIELD(SPS, CTRL, CPHA, clk_mode & 1); + GWRITE_FIELD(SPS, CTRL, CPOL, (clk_mode >> 1) & 1); + GWRITE_FIELD(SPS, CTRL, TXBITOR, 1); /* MSB first */ + GWRITE_FIELD(SPS, CTRL, RXBITOR, 1); /* MSB first */ + /* xfer 0xff when tx fifo is empty */ + GREG32(SPS, DUMMY_WORD) = GC_SPS_DUMMY_WORD_DEFAULT; + + /* [5,4,3] [2,1,0] + * RX{DIS, EN, RST} TX{DIS, EN, RST} + */ + GREG32(SPS, FIFO_CTRL) = 0x9; + + /* wait for reset to self clear. */ + while (GREG32(SPS, FIFO_CTRL) & 9) + ; + + /* Do not enable TX FIFO until we have something to send. */ + GWRITE_FIELD(SPS, FIFO_CTRL, RXFIFO_EN, 1); + + GREG32(SPS, RXFIFO_THRESHOLD) = rx_fifo_threshold; + + GWRITE_FIELD(SPS, ICTRL, RXFIFO_LVL, 1); + + seen_data = 0; + + /* Use CS_DEASSERT to retrieve all remaining bytes from RX FIFO. */ + GWRITE_FIELD(SPS, ISTATE_CLR, CS_DEASSERT, 1); + GWRITE_FIELD(SPS, ICTRL, CS_DEASSERT, 1); +} + +static void enable_cs_assert_irq_(void) +{ + GWRITE_FIELD(SPS, ISTATE_CLR, CS_ASSERT, 1); + GWRITE_FIELD(SPS, ICTRL, CS_ASSERT, 1); + + task_enable_irq(GC_IRQNUM_SPS0_CS_ASSERT_INTR); +} + +/* + * Register and unregister rx_handler. Side effects of registering the handler + * is reinitializing the interface. + */ +static rx_handler_f spp_rx_handler; + +int spp_register_rx_handler(enum spp_mode mode, rx_handler_f rx_handler, + unsigned rx_fifo_threshold) +{ + task_disable_irq(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR); + task_disable_irq(GC_IRQNUM_SPS0_CS_DEASSERT_INTR); + + if (int_ap_extension_enabled_) { + task_disable_irq(GC_IRQNUM_SPS0_CS_ASSERT_INTR); + int_ap_extension_stop_pulse(); + } + + if (!rx_handler) + return 0; + + if (!rx_fifo_threshold) + rx_fifo_threshold = 8; /* This is a sensible default. */ + spp_rx_handler = rx_handler; + + spp_configure(mode, SPI_CLOCK_MODE0, rx_fifo_threshold); + task_enable_irq(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR); + task_enable_irq(GC_IRQNUM_SPS0_CS_DEASSERT_INTR); + + if (int_ap_extension_enabled_) + enable_cs_assert_irq_(); + + return 0; +} + +/* Function that sets up for SPS to enable INT_AP_L extension. */ +static void spp_int_ap_extension_enable_(void) +{ + enable_cs_assert_irq_(); + + int_ap_extension_enabled_ = true; +} + +static void spp_init(void) +{ + /* + * Check to see if slave SPI interface is required by the board before + * initializing it. If SPI option is not set, then just return. + */ + if (!board_tpm_uses_spi()) + return; + + pmu_clock_en(PERIPH_SPP); + + /* The pinmux connections are preset, but we have to set IN/OUT */ + GWRITE_FIELD(PINMUX, DIOA2_CTL, IE, 1); /* SPS_MOSI */ + GWRITE_FIELD(PINMUX, DIOA6_CTL, IE, 1); /* SPS_CLK */ + GWRITE_FIELD(PINMUX, DIOA10_CTL, IE, 0); /* SPS_MISO */ + GWRITE_FIELD(PINMUX, DIOA12_CTL, IE, 1); /* SPS_CS_L */ + + /* Configure the SPS_CS_L signal, DIOA12, as wake falling */ + gpio_set_wakepin(GPIO_STRAP_B1, GPIO_HIB_WAKE_FALLING); + + int_ap_register(spp_int_ap_extension_enable_); +} +DECLARE_HOOK(HOOK_INIT, spp_init, HOOK_PRIO_INIT_CR50_BOARD - 1); + +/*****************************************************************************/ +/* Interrupt handler stuff */ + +/* + * Check how much data is available in RX FIFO and return pointer to the + * available data and its size. + * + * @param inst Interface number + * @param data - pointer to set to the beginning of data in the fifo + * @return number of available bytes and the sets the pointer if number of + * bytes is non zero + */ +static int spp_check_rx(uint32_t inst, uint8_t **data) +{ + uint32_t write_ptr = GREG32_I(SPS, inst, RXFIFO_WPTR) & SPP_FIFO_MASK; + uint32_t read_ptr = GREG32_I(SPS, inst, RXFIFO_RPTR) & SPP_FIFO_MASK; + + if (read_ptr == write_ptr) + return 0; + + *data = (uint8_t *)(SPP_RX_FIFO_BASE_ADDR + read_ptr); + + if (read_ptr > write_ptr) + return SPP_FIFO_SIZE - read_ptr; + + return write_ptr - read_ptr; +} + +/* Advance RX FIFO read pointer after data has been read from the FIFO. */ +static void spp_advance_rx(int port, int data_size) +{ + uint32_t read_ptr = GREG32_I(SPS, port, RXFIFO_RPTR) + data_size; + + GREG32_I(SPS, port, RXFIFO_RPTR) = read_ptr & SPP_FIFO_PTR_MASK; +} + +/* + * Actual receive interrupt processing function. Invokes the callback passing + * it a pointer to the linear space in the RX FIFO and the number of bytes + * available at that address. + * + * If RX fifo is wrapping around, the callback will be called twice with two + * flat pointers. + * + * If the CS has been deasserted, after all remaining RX FIFO data has been + * passed to the callback, the callback is called one last time with zero data + * size and the CS indication, this allows the client to delineate received + * packets. + * + * Returns a Boolean indicating if data was seen during the most recent CS + * assertion. When 1, it indicates to the caller that the confirmation + * pulse to the AP needs to be generated. + */ +static uint32_t spp_rx_interrupt(uint32_t port, int cs_deasserted) +{ + uint32_t pulse_needed = 0; + + for (;;) { + uint8_t *received_data = NULL; + size_t data_size; + + data_size = spp_check_rx(port, &received_data); + if (!data_size) + break; + + seen_data = 1; + spp_rx_count += data_size; + + if (spp_rx_handler) + spp_rx_handler(received_data, data_size, 0); + + if (data_size > max_rx_batch) + max_rx_batch = data_size; + + spp_advance_rx(port, data_size); + } + + if (cs_deasserted) { + if (seen_data) { + spp_rx_handler(NULL, 0, 1); + seen_data = 0; + pulse_needed = 1; + } + } + + return pulse_needed; +} + +static void spp_cs_deassert_interrupt(uint32_t port) +{ + uint32_t pulse_needed; + + if (spp_cs_asserted()) { + /* + * we must have been slow, this is the next CS assertion after + * the 'wake up' pulse, but we have not processed the wake up + * interrupt yet. + * + * There would be no other out of order CS assertions, as all + * the 'real' ones (as opposed to the wake up pulses) are + * confirmed by the H1 pulsing the AP interrupt line + */ + + /* + * Make sure we react to the next deassertion when it + * happens. + */ + GWRITE_FIELD(SPS, ISTATE_CLR, CS_DEASSERT, 1); + GWRITE_FIELD(SPS, FIFO_CTRL, TXFIFO_EN, 0); + if (spp_cs_asserted()) + return; + + /* + * The CS went away while we were processing this interrupt, + * this was the 'real' CS, need to process data. + */ + } + + /* Make sure the receive FIFO is drained. */ + pulse_needed = spp_rx_interrupt(port, 1); + GWRITE_FIELD(SPS, ISTATE_CLR, CS_DEASSERT, 1); + GWRITE_FIELD(SPS, FIFO_CTRL, TXFIFO_EN, 0); + + /* + * And transmit FIFO is emptied, so the next transaction doesn't start + * by clocking out any bytes left over from this one. + */ + GREG32(SPS, TXFIFO_WPTR) = GREG32(SPS, TXFIFO_RPTR); + + if (pulse_needed) { + /* + * If assert_int_ap() returns 1, it generated a long + * pulse of INT_AP_L. Then, there is no need to generate + * a short pulse. + */ + if (assert_int_ap()) + return; + + /* + * Signal the AP that this SPI frame processing is + * completed. + */ + gpio_set_level(GPIO_INT_AP_L, 0); + + tick_delay(2); + + gpio_set_level(GPIO_INT_AP_L, 1); + } +} + +void _sps0_interrupt(void) +{ + spp_rx_interrupt(0, 0); +} + +void _sps0_cs_deassert_interrupt(void) +{ + spp_cs_deassert_interrupt(0); +} +DECLARE_IRQ(GC_IRQNUM_SPS0_CS_DEASSERT_INTR, _sps0_cs_deassert_interrupt, 1); +DECLARE_IRQ(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR, _sps0_interrupt, 1); + +void sps0_cs_assert_interrupt_(void) +{ + GWRITE_FIELD(SPS, ISTATE_CLR, CS_ASSERT, 1); + + deassert_int_ap(); +} +DECLARE_IRQ(GC_IRQNUM_SPS0_CS_ASSERT_INTR, sps0_cs_assert_interrupt_, 1); + +#ifdef CONFIG_SPP_TEST + +/* Function to test SPS driver. It expects the host to send SPI frames of size + * (not exceeding 1100) of the following format: + * + * [ bytes of payload] + * + * Once the frame is received, it is sent back. The host can receive it and + * compare with the original. + */ + + /* + * Receive callback implements a simple state machine, it could be in one of + * three states: not started, receiving frame, frame finished. + */ + +enum spp_test_rx_state { + spptrx_not_started, + spptrx_receiving, + spptrx_finished +}; + +static enum spp_test_rx_state rx_state; +static uint8_t test_frame[1100]; /* Storage for the received frame. */ +/* + * To verify different alignment cases, the frame is saved in the buffer + * starting with a certain offset (in range 0..3). + */ +static size_t frame_base; +/* + * This is the index of the next location where received data will be added + * to. Points to the end of the received frame once it has been pulled in. + */ +static size_t frame_index; + +static void spp_receive_callback(uint8_t *data, size_t data_size, int cs_status) +{ + static size_t frame_size; /* Total size of the frame being received. */ + size_t to_go; /* Number of bytes still to receive. */ + + if (rx_state == spptrx_not_started) { + if (data_size < 2) + return; /* Something went wrong.*/ + + frame_size = data[0] * 256 + data[1] + 2; + frame_base = (frame_base + 1) % 3; + frame_index = frame_base; + + if ((frame_index + frame_size) <= sizeof(test_frame)) + /* Enter 'receiving frame' state. */ + rx_state = spptrx_receiving; + else + /* + * If we won't be able to receive this much, enter the + * 'frame finished' state. + */ + rx_state = spptrx_finished; + } + + if (rx_state == spptrx_finished) { + /* + * If CS was deasserted (transitioned to 1) - prepare to start + * receiving the next frame. + */ + if (cs_status) + rx_state = spptrx_not_started; + return; + } + + if (frame_size > data_size) + to_go = data_size; + else + to_go = frame_size; + + memcpy(test_frame + frame_index, data, to_go); + frame_index += to_go; + frame_size -= to_go; + + if (!frame_size) + rx_state = spptrx_finished; /* Frame finished.*/ +} + +static int command_spp(int argc, char **argv) +{ + int count = 0; + int target = 10; /* Expect 10 frames by default.*/ + char *e; + + spp_tx_status(GC_SPS_DUMMY_WORD_DEFAULT); + + rx_state = spptrx_not_started; + spp_register_rx_handler(SPP_GENERIC_MODE, spp_receive_callback, 0); + + if (argc > 1) { + target = strtoi(argv[1], &e, 10); + if (*e) + return EC_ERROR_PARAM1; + } + + while (count++ < target) { + size_t transmitted; + size_t to_go; + size_t index; + + /* Wait for a frame to be received.*/ + while (rx_state != spptrx_finished) { + watchdog_reload(); + usleep(10); + } + + /* Transmit the frame back to the host.*/ + index = frame_base; + to_go = frame_index - frame_base; + do { + if ((index == frame_base) && (to_go > 8)) { + /* + * This is the first transmit attempt for this + * frame. Send a little just to prime the + * transmit FIFO. + */ + transmitted = spp_transmit + (test_frame + index, 8); + } else { + transmitted = spp_transmit + (test_frame + index, to_go); + } + index += transmitted; + to_go -= transmitted; + } while (to_go); + + /* + * Wait for receive state machine to transition out of 'frame + * finished' state. + */ + while (rx_state == spptrx_finished) { + watchdog_reload(); + usleep(10); + } + } + + ccprintf("Processed %d frames\n", count - 1); + ccprintf("rx count %d, tx count %d, tx_empty %d, max rx batch %d\n", + spp_rx_count, spp_tx_count, + tx_empty_count, max_rx_batch); + + spp_rx_count = + spp_tx_count = + tx_empty_count = + max_rx_batch = 0; + + return EC_SUCCESS; +} + +DECLARE_CONSOLE_COMMAND(spptest, command_spp, + "", + "Loop back frames (10 by default) back to the host"); +#endif /* CONFIG_SPP_TEST */ diff --git a/chip/g/spp.h b/chip/g/spp.h new file mode 100644 index 0000000000..fcf0cea3fe --- /dev/null +++ b/chip/g/spp.h @@ -0,0 +1,54 @@ +/* + * Copyright 2015 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. + */ + +#ifndef __CROS_EC_INCLUDE_SPP_H +#define __CROS_EC_INCLUDE_SPP_H + +#include "spi.h" +#include "util.h" + +/* SPP Control Mode */ +enum spp_mode { + SPP_GENERIC_MODE = 0, + SPP_SWETLAND_MODE = 1, + SPP_ROM_MODE = 2, + SPP_UNDEF_MODE = 3, +}; + +/* Receive and transmit FIFO size and mask. */ +#define SPP_FIFO_SIZE BIT(10) +#define SPP_FIFO_MASK (SPP_FIFO_SIZE - 1) + +/* + * Tx interrupt callback function prototype. This function returns a portion + * of the received SPI data and current status of the CS line. When CS is + * deasserted, this function is called with data_size of zero and a non-zero + * cs_status. This allows the recipient to delineate the SPP frames. + */ +typedef void (*rx_handler_f)(uint8_t *data, size_t data_size, int cs_disabled); + +/* + * Push data to the SPP TX FIFO + * @param data Pointer to 8-bit data + * @param data_size Number of bytes to transmit + * @return : actual number of bytes placed into tx fifo + */ +int spp_transmit(uint8_t *data, size_t data_size); + +/* + * These functions return zero on success or non-zero on failure (attempt to + * register a callback on top of existing one, or attempt to unregister + * non-existing callback. + * + * rx_fifo_threshold value of zero means 'default'. + */ +int spp_register_rx_handler(enum spp_mode mode, + rx_handler_f rx_handler, + unsigned rx_fifo_threshold); +int spp_unregister_rx_handler(void); +void spp_tx_status(uint8_t byte); + +#endif diff --git a/chip/g/sps.c b/chip/g/sps.c deleted file mode 100644 index 0e4888a946..0000000000 --- a/chip/g/sps.c +++ /dev/null @@ -1,616 +0,0 @@ -/* Copyright 2015 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. - */ - -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "pmu.h" -#include "registers.h" -#include "sps.h" -#include "system.h" -#include "task.h" -#include "watchdog.h" - -/* - * This file is a driver for the CR50 SPS (SPI slave) controller. The - * controller deploys a 2KB buffer split evenly between receive and transmit - * directions. - * - * Each one kilobyte of memory is organized into a FIFO with read - * and write pointers. RX FIFO write and TX FIFO read pointers are managed by - * hardware. RX FIFO read and TX FIFO write pointers are managed by - * software. - * - * As of time of writing, TX fifo allows only 32 bit wide write accesses, - * which makes the function feeding the FIFO unnecessarily complicated. - * - * Even though both FIFOs are 1KByte in size, the hardware pointers - * controlling access to the FIFOs are 11 bits in size, this is another issue - * requiring special software handling. - * - * The driver API includes three functions: - * - * - transmit a packet of a certain size, runs on the task context and can - * exit before the entire packet is transmitted., - * - * - register a receive callback. The callback is running in interrupt - * context. Registering the callback (re)initializes the interface. - * - * - unregister receive callback. - */ - -/* - * Hardware pointers use one extra bit, which means that indexing FIFO and - * values written into the pointers have to have different sizes. Tracked under - * http://b/20894690 - */ -#define SPS_FIFO_PTR_MASK ((SPS_FIFO_MASK << 1) | 1) - -#define SPS_TX_FIFO_BASE_ADDR (GBASE(SPS) + 0x1000) -#define SPS_RX_FIFO_BASE_ADDR (SPS_TX_FIFO_BASE_ADDR + SPS_FIFO_SIZE) - -/* SPS Statistic Counters */ -static uint32_t sps_tx_count, sps_rx_count, tx_empty_count, max_rx_batch; - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_SPS, outstr) -#define CPRINTS(format, args...) cprints(CC_SPS, format, ## args) - -/* Flag indicating if there has been any data received while CS was asserted. */ -static uint8_t seen_data; - -static bool int_ap_extension_enabled_; - -void sps_tx_status(uint8_t byte) -{ - GREG32(SPS, DUMMY_WORD) = byte; -} - -/* - * Push data to the SPS TX FIFO - * @param data Pointer to 8-bit data - * @param data_size Number of bytes to transmit - * @return : actual number of bytes placed into tx fifo - */ -int sps_transmit(uint8_t *data, size_t data_size) -{ - volatile uint32_t *sps_tx_fifo; - uint32_t rptr; - uint32_t wptr; - uint32_t fifo_room; - int bytes_sent; - int inst = 0; - - if (GREAD_FIELD_I(SPS, inst, ISTATE, TXFIFO_EMPTY)) - tx_empty_count++; /* Inside packet this means underrun. */ - - sps_tx_fifo = (volatile uint32_t *)SPS_TX_FIFO_BASE_ADDR; - - wptr = GREG32_I(SPS, inst, TXFIFO_WPTR); - rptr = GREG32_I(SPS, inst, TXFIFO_RPTR); - fifo_room = (rptr - wptr - 1) & SPS_FIFO_MASK; - - if (fifo_room < data_size) { - bytes_sent = fifo_room; - data_size = fifo_room; - } else { - bytes_sent = data_size; - } - - sps_tx_fifo += (wptr & SPS_FIFO_MASK) / sizeof(*sps_tx_fifo); - - while (data_size) { - - if ((wptr & 3) || (data_size < 4) || ((uintptr_t)data & 3)) { - /* - * Either we have less then 4 bytes to send, or one of - * the pointers is not 4 byte aligned. Need to go byte - * by byte. - */ - uint32_t fifo_contents; - int bit_shift; - - fifo_contents = *sps_tx_fifo; - do { - /* - * CR50 SPS controller does not allow byte - * accesses for writes into the FIFO, so read - * modify/write is required. Tracked under - * http://b/20894727 - */ - bit_shift = 8 * (wptr & 3); - fifo_contents &= ~(0xff << bit_shift); - fifo_contents |= - (((uint32_t)(*data++)) << bit_shift); - data_size--; - wptr++; - - } while (data_size && (wptr & 3)); - - *sps_tx_fifo++ = fifo_contents; - } else { - /* - * Both fifo wptr and data are aligned and there is - * plenty to send. - */ - *sps_tx_fifo++ = *((uint32_t *)data); - data += 4; - data_size -= 4; - wptr += 4; - } - GREG32_I(SPS, inst, TXFIFO_WPTR) = wptr & SPS_FIFO_PTR_MASK; - - /* Make sure FIFO pointer wraps along with the index. */ - if (!(wptr & SPS_FIFO_MASK)) - sps_tx_fifo = (volatile uint32_t *) - SPS_TX_FIFO_BASE_ADDR; - } - - /* - * Start TX if necessary. This happens after FIFO is primed, which - * helps alleviate TX underrun problems but introduces delay before - * data starts coming out. - */ - if (!GREAD_FIELD(SPS, FIFO_CTRL, TXFIFO_EN)) - GWRITE_FIELD(SPS, FIFO_CTRL, TXFIFO_EN, 1); - - sps_tx_count += bytes_sent; - return bytes_sent; -} - -static int sps_cs_asserted(void) -{ - /* - * Read the current value on the SPS CS line and return the iversion - * of it (CS is active low). - */ - return !GREAD_FIELD(SPS, VAL, CSB); -} - -/** Configure the data transmission format - * - * @param mode Clock polarity and phase mode (0 - 3) - * - */ -static void sps_configure(enum sps_mode mode, enum spi_clock_mode clk_mode, - unsigned rx_fifo_threshold) -{ - /* Disable All Interrupts */ - GREG32(SPS, ICTRL) = 0; - - GWRITE_FIELD(SPS, CTRL, MODE, mode); - GWRITE_FIELD(SPS, CTRL, IDLE_LVL, 0); - GWRITE_FIELD(SPS, CTRL, CPHA, clk_mode & 1); - GWRITE_FIELD(SPS, CTRL, CPOL, (clk_mode >> 1) & 1); - GWRITE_FIELD(SPS, CTRL, TXBITOR, 1); /* MSB first */ - GWRITE_FIELD(SPS, CTRL, RXBITOR, 1); /* MSB first */ - /* xfer 0xff when tx fifo is empty */ - GREG32(SPS, DUMMY_WORD) = GC_SPS_DUMMY_WORD_DEFAULT; - - /* [5,4,3] [2,1,0] - * RX{DIS, EN, RST} TX{DIS, EN, RST} - */ - GREG32(SPS, FIFO_CTRL) = 0x9; - - /* wait for reset to self clear. */ - while (GREG32(SPS, FIFO_CTRL) & 9) - ; - - /* Do not enable TX FIFO until we have something to send. */ - GWRITE_FIELD(SPS, FIFO_CTRL, RXFIFO_EN, 1); - - GREG32(SPS, RXFIFO_THRESHOLD) = rx_fifo_threshold; - - GWRITE_FIELD(SPS, ICTRL, RXFIFO_LVL, 1); - - seen_data = 0; - - /* Use CS_DEASSERT to retrieve all remaining bytes from RX FIFO. */ - GWRITE_FIELD(SPS, ISTATE_CLR, CS_DEASSERT, 1); - GWRITE_FIELD(SPS, ICTRL, CS_DEASSERT, 1); -} - -static void enable_cs_assert_irq_(void) -{ - GWRITE_FIELD(SPS, ISTATE_CLR, CS_ASSERT, 1); - GWRITE_FIELD(SPS, ICTRL, CS_ASSERT, 1); - - task_enable_irq(GC_IRQNUM_SPS0_CS_ASSERT_INTR); -} - -/* - * Register and unregister rx_handler. Side effects of registering the handler - * is reinitializing the interface. - */ -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) -{ - task_disable_irq(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR); - task_disable_irq(GC_IRQNUM_SPS0_CS_DEASSERT_INTR); - - if (int_ap_extension_enabled_) { - task_disable_irq(GC_IRQNUM_SPS0_CS_ASSERT_INTR); - int_ap_extension_stop_pulse(); - } - - if (!rx_handler) - return 0; - - if (!rx_fifo_threshold) - rx_fifo_threshold = 8; /* This is a sensible default. */ - sps_rx_handler = rx_handler; - - sps_configure(mode, SPI_CLOCK_MODE0, rx_fifo_threshold); - task_enable_irq(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR); - task_enable_irq(GC_IRQNUM_SPS0_CS_DEASSERT_INTR); - - if (int_ap_extension_enabled_) - enable_cs_assert_irq_(); - - return 0; -} - -/* Function that sets up for SPS to enable INT_AP_L extension. */ -static void sps_int_ap_extension_enable_(void) -{ - enable_cs_assert_irq_(); - - int_ap_extension_enabled_ = true; -} - -static void sps_init(void) -{ - /* - * Check to see if slave SPI interface is required by the board before - * initializing it. If SPI option is not set, then just return. - */ - if (!board_tpm_uses_spi()) - return; - - pmu_clock_en(PERIPH_SPP); - - /* The pinmux connections are preset, but we have to set IN/OUT */ - GWRITE_FIELD(PINMUX, DIOA2_CTL, IE, 1); /* SPS_MOSI */ - GWRITE_FIELD(PINMUX, DIOA6_CTL, IE, 1); /* SPS_CLK */ - GWRITE_FIELD(PINMUX, DIOA10_CTL, IE, 0); /* SPS_MISO */ - GWRITE_FIELD(PINMUX, DIOA12_CTL, IE, 1); /* SPS_CS_L */ - - /* Configure the SPS_CS_L signal, DIOA12, as wake falling */ - gpio_set_wakepin(GPIO_STRAP_B1, GPIO_HIB_WAKE_FALLING); - - int_ap_register(sps_int_ap_extension_enable_); -} -DECLARE_HOOK(HOOK_INIT, sps_init, HOOK_PRIO_INIT_CR50_BOARD - 1); - -/*****************************************************************************/ -/* Interrupt handler stuff */ - -/* - * Check how much data is available in RX FIFO and return pointer to the - * available data and its size. - * - * @param inst Interface number - * @param data - pointer to set to the beginning of data in the fifo - * @return number of available bytes and the sets the pointer if number of - * bytes is non zero - */ -static int sps_check_rx(uint32_t inst, uint8_t **data) -{ - uint32_t write_ptr = GREG32_I(SPS, inst, RXFIFO_WPTR) & SPS_FIFO_MASK; - uint32_t read_ptr = GREG32_I(SPS, inst, RXFIFO_RPTR) & SPS_FIFO_MASK; - - if (read_ptr == write_ptr) - return 0; - - *data = (uint8_t *)(SPS_RX_FIFO_BASE_ADDR + read_ptr); - - if (read_ptr > write_ptr) - return SPS_FIFO_SIZE - read_ptr; - - return write_ptr - read_ptr; -} - -/* Advance RX FIFO read pointer after data has been read from the FIFO. */ -static void sps_advance_rx(int port, int data_size) -{ - uint32_t read_ptr = GREG32_I(SPS, port, RXFIFO_RPTR) + data_size; - - GREG32_I(SPS, port, RXFIFO_RPTR) = read_ptr & SPS_FIFO_PTR_MASK; -} - -/* - * Actual receive interrupt processing function. Invokes the callback passing - * it a pointer to the linear space in the RX FIFO and the number of bytes - * available at that address. - * - * If RX fifo is wrapping around, the callback will be called twice with two - * flat pointers. - * - * If the CS has been deasserted, after all remaining RX FIFO data has been - * passed to the callback, the callback is called one last time with zero data - * size and the CS indication, this allows the client to delineate received - * packets. - * - * Returns a Boolean indicating if data was seen during the most recent CS - * assertion. When 1, it indicates to the caller that the confirmation - * pulse to the AP needs to be generated. - */ -static uint32_t sps_rx_interrupt(uint32_t port, int cs_deasserted) -{ - uint32_t pulse_needed = 0; - - for (;;) { - uint8_t *received_data = NULL; - size_t data_size; - - data_size = sps_check_rx(port, &received_data); - if (!data_size) - break; - - seen_data = 1; - sps_rx_count += data_size; - - if (sps_rx_handler) - sps_rx_handler(received_data, data_size, 0); - - if (data_size > max_rx_batch) - max_rx_batch = data_size; - - sps_advance_rx(port, data_size); - } - - if (cs_deasserted) { - if (seen_data) { - sps_rx_handler(NULL, 0, 1); - seen_data = 0; - pulse_needed = 1; - } - } - - return pulse_needed; -} - -static void sps_cs_deassert_interrupt(uint32_t port) -{ - uint32_t pulse_needed; - - if (sps_cs_asserted()) { - /* - * we must have been slow, this is the next CS assertion after - * the 'wake up' pulse, but we have not processed the wake up - * interrupt yet. - * - * There would be no other out of order CS assertions, as all - * the 'real' ones (as opposed to the wake up pulses) are - * confirmed by the H1 pulsing the AP interrupt line - */ - - /* - * Make sure we react to the next deassertion when it - * happens. - */ - GWRITE_FIELD(SPS, ISTATE_CLR, CS_DEASSERT, 1); - GWRITE_FIELD(SPS, FIFO_CTRL, TXFIFO_EN, 0); - if (sps_cs_asserted()) - return; - - /* - * The CS went away while we were processing this interrupt, - * this was the 'real' CS, need to process data. - */ - } - - /* Make sure the receive FIFO is drained. */ - pulse_needed = sps_rx_interrupt(port, 1); - GWRITE_FIELD(SPS, ISTATE_CLR, CS_DEASSERT, 1); - GWRITE_FIELD(SPS, FIFO_CTRL, TXFIFO_EN, 0); - - /* - * And transmit FIFO is emptied, so the next transaction doesn't start - * by clocking out any bytes left over from this one. - */ - GREG32(SPS, TXFIFO_WPTR) = GREG32(SPS, TXFIFO_RPTR); - - if (pulse_needed) { - /* - * If assert_int_ap() returns 1, it generated a long - * pulse of INT_AP_L. Then, there is no need to generate - * a short pulse. - */ - if (assert_int_ap()) - return; - - /* - * Signal the AP that this SPI frame processing is - * completed. - */ - gpio_set_level(GPIO_INT_AP_L, 0); - - tick_delay(2); - - gpio_set_level(GPIO_INT_AP_L, 1); - } -} - -void _sps0_interrupt(void) -{ - sps_rx_interrupt(0, 0); -} - -void _sps0_cs_deassert_interrupt(void) -{ - sps_cs_deassert_interrupt(0); -} -DECLARE_IRQ(GC_IRQNUM_SPS0_CS_DEASSERT_INTR, _sps0_cs_deassert_interrupt, 1); -DECLARE_IRQ(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR, _sps0_interrupt, 1); - -void sps0_cs_assert_interrupt_(void) -{ - GWRITE_FIELD(SPS, ISTATE_CLR, CS_ASSERT, 1); - - deassert_int_ap(); -} -DECLARE_IRQ(GC_IRQNUM_SPS0_CS_ASSERT_INTR, sps0_cs_assert_interrupt_, 1); - -#ifdef CONFIG_SPP_TEST - -/* Function to test SPS driver. It expects the host to send SPI frames of size - * (not exceeding 1100) of the following format: - * - * [ bytes of payload] - * - * Once the frame is received, it is sent back. The host can receive it and - * compare with the original. - */ - - /* - * Receive callback implements a simple state machine, it could be in one of - * three states: not started, receiving frame, frame finished. - */ - -enum sps_test_rx_state { - spstrx_not_started, - spstrx_receiving, - spstrx_finished -}; - -static enum sps_test_rx_state rx_state; -static uint8_t test_frame[1100]; /* Storage for the received frame. */ -/* - * To verify different alignment cases, the frame is saved in the buffer - * starting with a certain offset (in range 0..3). - */ -static size_t frame_base; -/* - * This is the index of the next location where received data will be added - * to. Points to the end of the received frame once it has been pulled in. - */ -static size_t frame_index; - -static void sps_receive_callback(uint8_t *data, size_t data_size, int cs_status) -{ - static size_t frame_size; /* Total size of the frame being received. */ - size_t to_go; /* Number of bytes still to receive. */ - - if (rx_state == spstrx_not_started) { - if (data_size < 2) - return; /* Something went wrong.*/ - - frame_size = data[0] * 256 + data[1] + 2; - frame_base = (frame_base + 1) % 3; - frame_index = frame_base; - - if ((frame_index + frame_size) <= sizeof(test_frame)) - /* Enter 'receiving frame' state. */ - rx_state = spstrx_receiving; - else - /* - * If we won't be able to receive this much, enter the - * 'frame finished' state. - */ - rx_state = spstrx_finished; - } - - if (rx_state == spstrx_finished) { - /* - * If CS was deasserted (transitioned to 1) - prepare to start - * receiving the next frame. - */ - if (cs_status) - rx_state = spstrx_not_started; - return; - } - - if (frame_size > data_size) - to_go = data_size; - else - to_go = frame_size; - - memcpy(test_frame + frame_index, data, to_go); - frame_index += to_go; - frame_size -= to_go; - - if (!frame_size) - rx_state = spstrx_finished; /* Frame finished.*/ -} - -static int command_sps(int argc, char **argv) -{ - int count = 0; - int target = 10; /* Expect 10 frames by default.*/ - char *e; - - sps_tx_status(GC_SPS_DUMMY_WORD_DEFAULT); - - rx_state = spstrx_not_started; - sps_register_rx_handler(SPS_GENERIC_MODE, sps_receive_callback, 0); - - if (argc > 1) { - target = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - } - - while (count++ < target) { - size_t transmitted; - size_t to_go; - size_t index; - - /* Wait for a frame to be received.*/ - while (rx_state != spstrx_finished) { - watchdog_reload(); - usleep(10); - } - - /* Transmit the frame back to the host.*/ - index = frame_base; - to_go = frame_index - frame_base; - do { - if ((index == frame_base) && (to_go > 8)) { - /* - * This is the first transmit attempt for this - * frame. Send a little just to prime the - * transmit FIFO. - */ - transmitted = sps_transmit - (test_frame + index, 8); - } else { - transmitted = sps_transmit - (test_frame + index, to_go); - } - index += transmitted; - to_go -= transmitted; - } while (to_go); - - /* - * Wait for receive state machine to transition out of 'frame - * finished' state. - */ - while (rx_state == spstrx_finished) { - watchdog_reload(); - usleep(10); - } - } - - 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, - tx_empty_count, max_rx_batch); - - sps_rx_count = - sps_tx_count = - tx_empty_count = - max_rx_batch = 0; - - return EC_SUCCESS; -} - -DECLARE_CONSOLE_COMMAND(spstest, command_sps, - "", - "Loop back frames (10 by default) back to the host"); -#endif /* CONFIG_SPP_TEST */ diff --git a/chip/g/sps.h b/chip/g/sps.h deleted file mode 100644 index 5e95042a7e..0000000000 --- a/chip/g/sps.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2015 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. - */ - -#ifndef __CROS_EC_INCLUDE_SPS_H -#define __CROS_EC_INCLUDE_SPS_H - -#include "spi.h" -#include "util.h" - -/* SPS Control Mode */ -enum sps_mode { - SPS_GENERIC_MODE = 0, - SPS_SWETLAND_MODE = 1, - SPS_ROM_MODE = 2, - SPS_UNDEF_MODE = 3, -}; - -/* Receive and transmit FIFO size and mask. */ -#define SPS_FIFO_SIZE BIT(10) -#define SPS_FIFO_MASK (SPS_FIFO_SIZE - 1) - -/* - * Tx interrupt callback function prototype. This function returns a portion - * of the received SPI data and current status of the CS line. When CS is - * deasserted, this function is called with data_size of zero and a non-zero - * cs_status. This allows the recipient to delineate the SPS frames. - */ -typedef void (*rx_handler_f)(uint8_t *data, size_t data_size, int cs_disabled); - -/* - * Push data to the SPS TX FIFO - * @param data Pointer to 8-bit data - * @param data_size Number of bytes to transmit - * @return : actual number of bytes placed into tx fifo - */ -int sps_transmit(uint8_t *data, size_t data_size); - -/* - * These functions return zero on success or non-zero on failure (attempt to - * register a callback on top of existing one, or attempt to unregister - * non-existing callback. - * - * rx_fifo_threshold value of zero means 'default'. - */ -int sps_register_rx_handler(enum sps_mode mode, - rx_handler_f rx_handler, - unsigned rx_fifo_threshold); -int sps_unregister_rx_handler(void); -void sps_tx_status(uint8_t byte); - -#endif diff --git a/chip/g/sps_tpm.c b/chip/g/sps_tpm.c index a4775e70f6..a2bb4be171 100644 --- a/chip/g/sps_tpm.c +++ b/chip/g/sps_tpm.c @@ -6,14 +6,14 @@ #include "common.h" #include "console.h" #include "hooks.h" -#include "sps.h" +#include "spp.h" #include "system.h" #include "tpm_registers.h" #include "util.h" /* * This implements the TCG's TPM SPI Hardware Protocol on the SPI bus, using - * the Cr50 SPS (SPI slave) controller. This turns out to be very similar to + * the Cr50 SPP (SPI periph) controller. This turns out to be very similar to * the EC host command protocol, which is itself similar to HDLC. All of those * protocols provide ways to identify data frames over transports that don't * provide them natively. That's the nice thing about standards: there are so @@ -100,26 +100,26 @@ static uint32_t regaddr; /* Address of register to read/write. */ #define TXBUF_MAX 512 /* chosen arbitrarily */ static uint8_t txbuf[1 + TXBUF_MAX]; -static enum sps_state { +static enum spp_state { /* Receiving header */ - SPS_TPM_STATE_RECEIVING_HEADER, + SPP_TPM_STATE_RECEIVING_HEADER, /* Receiving data. */ - SPS_TPM_STATE_RECEIVING_WRITE_DATA, + SPP_TPM_STATE_RECEIVING_WRITE_DATA, /* Finished rx processing, waiting for SPI transaction to finish. */ - SPS_TPM_STATE_PONDERING, + SPP_TPM_STATE_PONDERING, /* Something went wrong. */ - SPS_TPM_STATE_RX_BAD, -} sps_tpm_state; + SPP_TPM_STATE_RX_BAD, +} spp_tpm_state; /* Set initial conditions to get ready to receive a command. */ static void init_new_cycle(void) { rxbuf_count = 0; - sps_tpm_state = SPS_TPM_STATE_RECEIVING_HEADER; - sps_tx_status(TPM_STALL_ASSERT); + spp_tpm_state = SPP_TPM_STATE_RECEIVING_HEADER; + spp_tx_status(TPM_STALL_ASSERT); /* We're just waiting for a new command, so we could sleep. */ delay_sleep_by(1 * SECOND); enable_sleep(SLEEP_MASK_SPI); @@ -144,9 +144,9 @@ static void process_rx_data(uint8_t *data, size_t data_size, int cs_deasserted) if ((rxbuf_count + data_size) > RXBUF_MAX) { CPRINTS("TPM SPI input overflow: %d + %d > %d in state %d", - rxbuf_count, data_size, RXBUF_MAX, sps_tpm_state); - sps_tx_status(TPM_STALL_DEASSERT); - sps_tpm_state = SPS_TPM_STATE_RX_BAD; + rxbuf_count, data_size, RXBUF_MAX, spp_tpm_state); + spp_tx_status(TPM_STALL_DEASSERT); + spp_tpm_state = SPP_TPM_STATE_RX_BAD; /* In this state, this function won't be called again until * after the CS deasserts and we've prepared for a new * transaction. */ @@ -156,7 +156,7 @@ static void process_rx_data(uint8_t *data, size_t data_size, int cs_deasserted) rxbuf_count += data_size; /* Okay, we have enough. Now what? */ - if (sps_tpm_state == SPS_TPM_STATE_RECEIVING_HEADER) { + if (spp_tpm_state == SPP_TPM_STATE_RECEIVING_HEADER) { if (rxbuf_count < 4) return; /* Header is 4 bytes in size. */ @@ -170,8 +170,8 @@ static void process_rx_data(uint8_t *data, size_t data_size, int cs_deasserted) * room. What can we do if it doesn't? */ tpm_register_get(regaddr - TPM_LOCALITY_0_SPI_BASE, txbuf + 1, bytecount); - sps_transmit(txbuf, bytecount + 1); - sps_tpm_state = SPS_TPM_STATE_PONDERING; + spp_transmit(txbuf, bytecount + 1); + spp_tpm_state = SPP_TPM_STATE_PONDERING; return; } @@ -179,13 +179,13 @@ static void process_rx_data(uint8_t *data, size_t data_size, int cs_deasserted) * Write the new idle byte value, to signal the master to * proceed with data. */ - sps_tx_status(TPM_STALL_DEASSERT); - sps_tpm_state = SPS_TPM_STATE_RECEIVING_WRITE_DATA; + spp_tx_status(TPM_STALL_DEASSERT); + spp_tpm_state = SPP_TPM_STATE_RECEIVING_WRITE_DATA; return; } if (cs_deasserted && - (sps_tpm_state == SPS_TPM_STATE_RECEIVING_WRITE_DATA)) + (spp_tpm_state == SPP_TPM_STATE_RECEIVING_WRITE_DATA)) /* Ok, we have all the write data, pass it to the tpm. */ tpm_register_put(regaddr - TPM_LOCALITY_0_SPI_BASE, rxbuf + rxbuf_count - bytecount, bytecount); @@ -193,36 +193,36 @@ static void process_rx_data(uint8_t *data, size_t data_size, int cs_deasserted) static void tpm_rx_handler(uint8_t *data, size_t data_size, int cs_deasserted) { - if ((sps_tpm_state == SPS_TPM_STATE_RECEIVING_HEADER) || - (sps_tpm_state == SPS_TPM_STATE_RECEIVING_WRITE_DATA)) + if ((spp_tpm_state == SPP_TPM_STATE_RECEIVING_HEADER) || + (spp_tpm_state == SPP_TPM_STATE_RECEIVING_WRITE_DATA)) process_rx_data(data, data_size, cs_deasserted); if (cs_deasserted) init_new_cycle(); } -static void sps_if_stop(void) +static void spp_if_stop(void) { /* Let's shut down the interface while TPM is being reset. */ - sps_register_rx_handler(0, NULL, 0); + spp_register_rx_handler(0, NULL, 0); } -static void sps_if_start(void) +static void spp_if_start(void) { /* * Threshold of 3 makes sure we get an interrupt as soon as the header * is received. */ init_new_cycle(); - sps_register_rx_handler(SPS_GENERIC_MODE, tpm_rx_handler, 3); + spp_register_rx_handler(SPP_GENERIC_MODE, tpm_rx_handler, 3); } -static void sps_if_register(void) +static void spp_if_register(void) { if (!board_tpm_uses_spi()) return; - tpm_register_interface(sps_if_start, sps_if_stop); + tpm_register_interface(spp_if_start, spp_if_stop); } -DECLARE_HOOK(HOOK_INIT, sps_if_register, HOOK_PRIO_LAST); +DECLARE_HOOK(HOOK_INIT, spp_if_register, HOOK_PRIO_LAST); -- cgit v1.2.1