/* * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-07-30 Emuzit first version */ #ifndef __CH56X_SPI_H__ #define __CH56X_SPI_H__ #include "soc.h" #include "ch56x_gpio.h" #ifdef __cplusplus extern "C" { #endif #define SPI0_BUS_NAME "spi0" #define SPI1_BUS_NAME "spi1" #ifndef SPI0_SCS_PIN #define SPI0_SCS_PIN GET_PIN(A, 12) #endif #define SPI0_SCK_PIN GET_PIN(A, 13) #define SPI0_MOSI_PIN GET_PIN(A, 14) #define SPI0_MISO_PIN GET_PIN(A, 15) #ifdef SOC_SERIES_CH569 #ifndef SPI1_SCS_PIN #define SPI1_SCS_PIN GET_PIN(B, 11) #endif #define SPI1_SCK_PIN GET_PIN(B, 12) #define SPI1_MOSI_PIN GET_PIN(B, 13) #define SPI1_MISO_PIN GET_PIN(B, 14) #else #define SPI1_SCK_PIN GET_PIN(A, 0) #define SPI1_MOSI_PIN GET_PIN(A, 1) #define SPI1_MISO_PIN GET_PIN(A, 2) #endif #define SPI_FIFO_SIZE 8 union _spi_ctrl_mod { uint8_t reg; struct { uint8_t mode_slave : 1; // RW, SPI master/slave (0/1) mode select uint8_t all_clear : 1; // RW, clear FIFO/count/int-flag uint8_t two_wire : 1; // RW, 2/3-wire mode (0/1), SPI slave uint8_t mst_sck_mod : 1; // RW, mode0/mode3 (0/1) for SCK idle L/H uint8_t fifo_dir : 1; // RW, FIFO direction is output/input (0/1) uint8_t sck_oe : 1; // RW, SCK pin output enable uint8_t mosi_oe : 1; // RW, MOSI pin output enable uint8_t miso_oe : 1; // RW, MISO pin output enable }; struct { uint8_t stuff_0 : 3; uint8_t slv_cmd_mod : 1; // RW, 1st byte is data/cmd (0/1), SPI slave uint8_t stuff_4 : 4; }; }; #define RB_SPI_MODE_SLAVE 0x01 #define RB_SPI_ALL_CLEAR 0x02 #define RB_SPI_2WIRE_MOD 0x04 #define RB_SPI_MST_SCK_MOD 0x08 #define RB_SPI_SLV_CMD_MOD 0x08 #define RB_SPI_FIFO_DIR 0x10 #define RB_SPI_SCK_OE 0x20 #define RB_SPI_MOSI_OE 0x40 #define RB_SPI_MISO_OE 0x80 #define MST_SCK_MOD_0 0 #define MST_SCK_MOD_3 1 #define SPI_FIFO_DIR_OUTPUT 0 #define SPI_FIFO_DIR_INPUT 1 union _spi_ctrl_cfg { uint8_t reg; struct { uint8_t dma_enable : 1; // RW, enable DMA function uint8_t resv_1 : 1; uint8_t dma_loop : 1; // RW, enable DMA loop mode (0 => single) uint8_t resv_3 : 1; uint8_t auto_if : 1; // RW, enable auto clear RB_SPI_IF_BYTE_END uint8_t bit_order : 1; // RW, data bit ordering, LSB/MSB first (0/1) uint8_t resv_6 : 2; }; }; #define RB_SPI_DMA_ENABLE 0x01 #define RB_SPI_DMA_LOOP 0x04 #define RB_SPI_AUTO_IF 0x10 #define RB_SPI_BIT_ORDER 0x20 #define SPI_BIT_ORDER_MSB 0 #define SPI_BIT_ORDER_LSB 1 union _spi_inter_en { uint8_t reg; struct { uint8_t cnt_end : 1; // RW, IE for all bytes transfered uint8_t byte_end : 1; // RW, IE for single byte transfered uint8_t fifo_hf : 1; // RW, IE for FIFO half full uint8_t dma_end : 1; // RW, IE for end of DMA uint8_t fifo_ov : 1; // RW, IE for FIFO full or empty uint8_t resv_5 : 2; uint8_t fst_byte : 1; // RW, IE for 1st byte received, SPI slave }; }; #define RB_SPI_IE_CNT_END 0x01 #define RB_SPI_IE_BYTE_END 0x02 #define RB_SPI_IE_FIFO_HF 0x04 #define RB_SPI_IE_DMA_END 0x08 #define RB_SPI_IE_FIFO_OV 0x10 #define RB_SPI_IE_FST_BYTE 0x80 union _spi_run_flag { uint8_t reg; struct { uint8_t resv_0 : 4; uint8_t slv_cmd_act : 1; // RO, SPI slave cmd received uint8_t fifo_ready : 1; // RO, SPI FIFO ready to transfer uint8_t slv_cs_load : 1; // RO, SPI slave is loading R8_SPIx_SLAVE_PRE uint8_t slv_select : 1; // RO, SPI slave CS active (selected) }; }; #define RB_SPI_SLV_CMD_ACT 0x10 #define RB_SPI_FIFO_READY 0x20 #define RB_SPI_SLV_CS_LOAD 0x40 #define RB_SPI_SLV_SELECT 0x80 union _spi_int_flag { uint8_t reg; struct { uint8_t cnt_end : 1; // RW1, IF for all bytes transfered uint8_t byte_end : 1; // RW1, IF for single byte transfered uint8_t fifo_hf : 1; // RW1, IF for FIFO half full uint8_t dma_end : 1; // RW1, IF for end of DMA uint8_t fifo_ov : 1; // RW1, IF for FIFO full or empty uint8_t resv_5 : 1; uint8_t free : 1; // RO, current SPI state is free uint8_t fst_byte : 1; // RW1, IF for 1st byte received, SPI slave }; }; #define RB_SPI_IF_CNT_END 0x01 #define RB_SPI_IF_BYTE_END 0x02 #define RB_SPI_IF_FIFO_HF 0x04 #define RB_SPI_IF_DMA_END 0x08 #define RB_SPI_IF_FIFO_OV 0x10 #define RB_SPI_FREE 0x40 #define RB_SPI_IF_FST_BYTE 0x80 /* * 0x00 R8_SPIx_CTRL_MOD: SPI mode setting register * 0x01 R8_SPIx_CTRL_CFG: SPI configuration register * 0x02 R8_SPIx_INTER_EN: SPI interrupt enable register * 0x03 R8_SPIx_CLOCK_DIV: SPI master clock divisor, minimum 2 * 0x03 R8_SPIx_SLAVE_PRE: SPI slave preset data (reset as 10h) * 0x04 R8_SPIx_BUFFER: SPI data buffer * 0x05 R8_SPIx_RUN_FLAG: SPI working state register * 0x06 R8_SPIx_INT_FLAG: SPI interrupt flags register * 0x07 R8_SPIx_FIFO_COUNT: SPI FIFO data count * 0x0c R16_SPIx_TOTAL_CNT: SPI total data length to transfer * 0x10 R8_SPIx_FIFO: SPI FIFO * 0x13 R8_SPIx_FIFO_COUNT1: SPI FIFO data count * 0x14 R32_SPIx_DMA_NOW: SPI DMA current address * 0x18 R32_SPIx_DMA_BEG: SPI DMA start address * 0x1c R32_SPIx_DMA_END: SPI DMA end address */ struct spi_registers { union _spi_ctrl_mod CTRL_MOD; union _spi_ctrl_cfg CTRL_CFG; union _spi_inter_en INTER_EN; union { uint8_t CLOCK_DIV; uint8_t SLAVE_PRE; }; uint8_t BUFFER; union _spi_run_flag RUN_FLAG; union _spi_int_flag INT_FLAG; uint8_t FIFO_COUNT; uint32_t resv_8; uint16_t TOTAL_COUNT; uint16_t resv_0e; uint8_t FIFO; uint8_t resv_11[2]; uint8_t FIFO_COUNT1; uint32_t DMA_NOW; uint32_t DMA_BIG; uint32_t DMA_END; }; CHECK_STRUCT_SIZE(struct spi_registers, 0x20); rt_err_t spi_cs_pin_assign(int spi_n, rt_base_t cs_pin); #ifdef __cplusplus } #endif #endif