summaryrefslogtreecommitdiff
path: root/bsp/wch/risc-v/libraries/ch56x_drivers/ch56x_spi.h
blob: b98e714edf31623c190c6b5f2f57907d187d5520 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*
 * Copyright (c) 2006-2023, 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