hw/ssi: Extend SPI model
In this commit SPI shift engine and sequencer logic is implemented. Shift engine performs serialization and de-serialization according to the control by the sequencer and according to the setup defined in the configuration registers. Sequencer implements the main control logic and FSM to handle data transmit and data receive control of the shift engine. Signed-off-by: Chalapathi V <chalapathi.v@linux.ibm.com> Reviewed-by: Caleb Schlossin <calebs@linux.vnet.ibm.com> Reviewed-by: Glenn Miles <milesg@linux.ibm.com> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
This commit is contained in:
parent
29318db133
commit
b4cb930e40
1045
hw/ssi/pnv_spi.c
1045
hw/ssi/pnv_spi.c
File diff suppressed because it is too large
Load Diff
@ -38,3 +38,18 @@ pnv_spi_read(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64
|
||||
pnv_spi_write(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64
|
||||
pnv_spi_read_RDR(uint64_t val) "data extracted = 0x%" PRIx64
|
||||
pnv_spi_write_TDR(uint64_t val) "being written, data written = 0x%" PRIx64
|
||||
pnv_spi_start_sequencer(void) ""
|
||||
pnv_spi_reset(void) "spic engine sequencer configuration and spi communication"
|
||||
pnv_spi_sequencer_op(const char* op, uint8_t index) "%s at index = 0x%x"
|
||||
pnv_spi_shifter_stating(void) "pull CS line low"
|
||||
pnv_spi_shifter_done(void) "pull the CS line high"
|
||||
pnv_spi_log_Ncounts(uint8_t N1_bits, uint8_t N1_bytes, uint8_t N1_tx, uint8_t N1_rx, uint8_t N2_bits, uint8_t N2_bytes, uint8_t N2_tx, uint8_t N2_rx) "N1_bits = %d, N1_bytes = %d, N1_tx = %d, N1_rx = %d, N2_bits = %d, N2_bytes = %d, N2_tx = %d, N2_rx = %d"
|
||||
pnv_spi_tx_append(const char* frame, uint8_t byte, uint8_t tdr_index) "%s = 0x%2.2x to payload from TDR at index %d"
|
||||
pnv_spi_tx_append_FF(const char* frame) "%s to Payload"
|
||||
pnv_spi_tx_request(const char* frame, uint32_t payload_len) "%s, payload len = %d"
|
||||
pnv_spi_rx_received(uint32_t payload_len) "payload len = %d"
|
||||
pnv_spi_rx_read_N1frame(void) ""
|
||||
pnv_spi_rx_read_N2frame(void) ""
|
||||
pnv_spi_shift_rx(uint8_t byte, uint32_t index) "byte = 0x%2.2x into RDR from payload index %d"
|
||||
pnv_spi_sequencer_stop_requested(const char* reason) "due to %s"
|
||||
pnv_spi_RDR_match(const char* result) "%s"
|
||||
|
@ -8,6 +8,14 @@
|
||||
* This model Supports a connection to a single SPI responder.
|
||||
* Introduced for P10 to provide access to SPI seeproms, TPM, flash device
|
||||
* and an ADC controller.
|
||||
*
|
||||
* All SPI function control is mapped into the SPI register space to enable
|
||||
* full control by firmware.
|
||||
*
|
||||
* SPI Controller has sequencer and shift engine. The SPI shift engine
|
||||
* performs serialization and de-serialization according to the control by
|
||||
* the sequencer and according to the setup defined in the configuration
|
||||
* registers and the SPI sequencer implements the main control logic.
|
||||
*/
|
||||
|
||||
#ifndef PPC_PNV_SPI_H
|
||||
@ -31,6 +39,25 @@ typedef struct PnvSpi {
|
||||
MemoryRegion xscom_spic_regs;
|
||||
/* SPI object number */
|
||||
uint32_t spic_num;
|
||||
uint8_t transfer_len;
|
||||
uint8_t responder_select;
|
||||
/* To verify if shift_n1 happens prior to shift_n2 */
|
||||
bool shift_n1_done;
|
||||
/* Loop counter for branch operation opcode Ex/Fx */
|
||||
uint8_t loop_counter_1;
|
||||
uint8_t loop_counter_2;
|
||||
/* N1/N2_bits specifies the size of the N1/N2 segment of a frame in bits.*/
|
||||
uint8_t N1_bits;
|
||||
uint8_t N2_bits;
|
||||
/* Number of bytes in a payload for the N1/N2 frame segment.*/
|
||||
uint8_t N1_bytes;
|
||||
uint8_t N2_bytes;
|
||||
/* Number of N1/N2 bytes marked for transmit */
|
||||
uint8_t N1_tx;
|
||||
uint8_t N2_tx;
|
||||
/* Number of N1/N2 bytes marked for receive */
|
||||
uint8_t N1_rx;
|
||||
uint8_t N2_rx;
|
||||
|
||||
/* SPI registers */
|
||||
uint64_t regs[PNV_SPI_REGS];
|
||||
|
@ -28,6 +28,17 @@
|
||||
|
||||
/* counter_config_reg */
|
||||
#define SPI_CTR_CFG_REG 0x01
|
||||
#define SPI_CTR_CFG_N1 PPC_BITMASK(0, 7)
|
||||
#define SPI_CTR_CFG_N2 PPC_BITMASK(8, 15)
|
||||
#define SPI_CTR_CFG_CMP1 PPC_BITMASK(24, 31)
|
||||
#define SPI_CTR_CFG_CMP2 PPC_BITMASK(32, 39)
|
||||
#define SPI_CTR_CFG_N1_CTRL_B1 PPC_BIT(49)
|
||||
#define SPI_CTR_CFG_N1_CTRL_B2 PPC_BIT(50)
|
||||
#define SPI_CTR_CFG_N1_CTRL_B3 PPC_BIT(51)
|
||||
#define SPI_CTR_CFG_N2_CTRL_B0 PPC_BIT(52)
|
||||
#define SPI_CTR_CFG_N2_CTRL_B1 PPC_BIT(53)
|
||||
#define SPI_CTR_CFG_N2_CTRL_B2 PPC_BIT(54)
|
||||
#define SPI_CTR_CFG_N2_CTRL_B3 PPC_BIT(55)
|
||||
|
||||
/* config_reg */
|
||||
#define CONFIG_REG1 0x02
|
||||
@ -36,9 +47,13 @@
|
||||
#define SPI_CLK_CFG_REG 0x03
|
||||
#define SPI_CLK_CFG_HARD_RST 0x0084000000000000;
|
||||
#define SPI_CLK_CFG_RST_CTRL PPC_BITMASK(24, 27)
|
||||
#define SPI_CLK_CFG_ECC_EN PPC_BIT(28)
|
||||
#define SPI_CLK_CFG_ECC_CTRL PPC_BITMASK(29, 30)
|
||||
|
||||
/* memory_mapping_reg */
|
||||
#define SPI_MM_REG 0x04
|
||||
#define SPI_MM_RDR_MATCH_VAL PPC_BITMASK(32, 47)
|
||||
#define SPI_MM_RDR_MATCH_MASK PPC_BITMASK(48, 63)
|
||||
|
||||
/* transmit_data_reg */
|
||||
#define SPI_XMIT_DATA_REG 0x05
|
||||
@ -60,8 +75,59 @@
|
||||
#define SPI_STS_SEQ_FSM PPC_BITMASK(8, 15)
|
||||
#define SPI_STS_SHIFTER_FSM PPC_BITMASK(16, 27)
|
||||
#define SPI_STS_SEQ_INDEX PPC_BITMASK(28, 31)
|
||||
#define SPI_STS_GEN_STATUS PPC_BITMASK(32, 63)
|
||||
#define SPI_STS_GEN_STATUS_B3 PPC_BIT(35)
|
||||
#define SPI_STS_RDR PPC_BITMASK(1, 3)
|
||||
#define SPI_STS_TDR PPC_BITMASK(5, 7)
|
||||
|
||||
/*
|
||||
* Shifter states
|
||||
*
|
||||
* These are the same values defined for the Shifter FSM field of the
|
||||
* status register. It's a 12 bit field so we will represent it as three
|
||||
* nibbles in the constants.
|
||||
*
|
||||
* These are shifter_fsm values
|
||||
*
|
||||
* Status reg bits 16-27 -> field bits 0-11
|
||||
* bits 0,1,2,5 unused/reserved
|
||||
* bit 4 crc shift in (unused)
|
||||
* bit 8 crc shift out (unused)
|
||||
*/
|
||||
|
||||
#define FSM_DONE 0x100 /* bit 3 */
|
||||
#define FSM_SHIFT_N2 0x020 /* bit 6 */
|
||||
#define FSM_WAIT 0x010 /* bit 7 */
|
||||
#define FSM_SHIFT_N1 0x004 /* bit 9 */
|
||||
#define FSM_START 0x002 /* bit 10 */
|
||||
#define FSM_IDLE 0x001 /* bit 11 */
|
||||
|
||||
/*
|
||||
* Sequencer states
|
||||
*
|
||||
* These are sequencer_fsm values
|
||||
*
|
||||
* Status reg bits 8-15 -> field bits 0-7
|
||||
* bits 0-3 unused/reserved
|
||||
*
|
||||
*/
|
||||
#define SEQ_STATE_INDEX_INCREMENT 0x08 /* bit 4 */
|
||||
#define SEQ_STATE_EXECUTE 0x04 /* bit 5 */
|
||||
#define SEQ_STATE_DECODE 0x02 /* bit 6 */
|
||||
#define SEQ_STATE_IDLE 0x01 /* bit 7 */
|
||||
|
||||
/*
|
||||
* These are the supported sequencer operations.
|
||||
* Only the upper nibble is significant because for many operations
|
||||
* the lower nibble is a variable specific to the operation.
|
||||
*/
|
||||
#define SEQ_OP_STOP 0x00
|
||||
#define SEQ_OP_SELECT_SLAVE 0x10
|
||||
#define SEQ_OP_SHIFT_N1 0x30
|
||||
#define SEQ_OP_SHIFT_N2 0x40
|
||||
#define SEQ_OP_BRANCH_IFNEQ_RDR 0x60
|
||||
#define SEQ_OP_TRANSFER_TDR 0xC0
|
||||
#define SEQ_OP_BRANCH_IFNEQ_INC_1 0xE0
|
||||
#define SEQ_OP_BRANCH_IFNEQ_INC_2 0xF0
|
||||
#define NUM_SEQ_OPS 8
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user