soc/intel/common/block/chip: Refactor chip_get_common_soc_structure()
[coreboot.git] / src / soc / sifive / fu540 / spi_internal.h
blob96124c1fdfba5efd2f5f6762eb163881a457a264
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #ifndef __SOC_SIFIVE_HIFIVE_U_SPI_INTERNAL_H__
3 #define __SOC_SIFIVE_HIFIVE_U_SPI_INTERNAL_H__
5 #include <stdint.h>
7 #define _ASSERT_SIZEOF(type, size) _Static_assert( \
8 sizeof(type) == (size), \
9 #type " must be " #size " bytes wide")
11 #define FU540_SPI_CSMODE_AUTO 0
12 #define FU540_SPI_CSMODE_HOLD 2
13 #define FU540_SPI_CSMODE_OFF 3
15 typedef union {
16 struct {
17 uint32_t pha : 1;
18 uint32_t pol : 1;
19 uint32_t reserved : 30;
21 uint32_t raw_bits;
22 } spi_reg_sckmode;
23 _ASSERT_SIZEOF(spi_reg_sckmode, 4);
25 typedef union {
26 struct {
27 uint32_t mode : 2;
28 uint32_t reserved : 30;
30 uint32_t raw_bits;
31 } spi_reg_csmode;
32 _ASSERT_SIZEOF(spi_reg_csmode, 4);
34 typedef union {
35 struct {
36 uint32_t cssck : 8;
37 uint32_t reserved0 : 8;
38 uint32_t sckcs : 8;
39 uint32_t reserved1 : 8;
41 uint32_t raw_bits;
42 } spi_reg_delay0;
43 _ASSERT_SIZEOF(spi_reg_delay0, 4);
45 typedef union {
46 struct {
47 uint32_t intercs : 8;
48 uint32_t reserved0 : 8;
49 uint32_t interxfr : 8;
50 uint32_t reserved1 : 8;
52 uint32_t raw_bits;
53 } spi_reg_delay1;
54 _ASSERT_SIZEOF(spi_reg_delay1, 4);
56 typedef union {
57 struct {
58 uint32_t proto : 2;
59 uint32_t endian : 1;
60 uint32_t dir : 1;
61 uint32_t reserved0 : 12;
62 uint32_t len : 4;
63 uint32_t reserved1 : 12;
65 uint32_t raw_bits;
66 } spi_reg_fmt;
67 _ASSERT_SIZEOF(spi_reg_fmt, 4);
69 typedef union {
70 struct {
71 uint32_t data : 8;
72 uint32_t reserved : 23;
73 uint32_t full : 1;
75 uint32_t raw_bits;
76 } spi_reg_txdata;
77 _ASSERT_SIZEOF(spi_reg_txdata, 4);
79 typedef union {
80 struct {
81 uint32_t data : 8;
82 uint32_t reserved : 23;
83 uint32_t empty : 1;
85 uint32_t raw_bits;
86 } spi_reg_rxdata;
87 _ASSERT_SIZEOF(spi_reg_rxdata, 4);
89 typedef union {
90 struct {
91 uint32_t txmark : 3;
92 uint32_t reserved : 29;
94 uint32_t raw_bits;
95 } spi_reg_txmark;
96 _ASSERT_SIZEOF(spi_reg_txmark, 4);
98 typedef union {
99 struct {
100 uint32_t rxmark : 3;
101 uint32_t reserved : 29;
103 uint32_t raw_bits;
104 } spi_reg_rxmark;
105 _ASSERT_SIZEOF(spi_reg_rxmark, 4);
107 typedef union {
108 struct {
109 uint32_t en : 1;
110 uint32_t reserved : 31;
112 uint32_t raw_bits;
113 } spi_reg_fctrl;
114 _ASSERT_SIZEOF(spi_reg_fctrl, 4);
116 typedef union {
117 struct {
118 uint32_t cmd_en : 1;
119 uint32_t addr_len : 3;
120 uint32_t pad_cnt : 4;
121 uint32_t command_proto : 2;
122 uint32_t addr_proto : 2;
123 uint32_t data_proto : 2;
124 uint32_t reserved : 2;
125 uint32_t command_code : 8;
126 uint32_t pad_code : 8;
128 uint32_t raw_bits;
129 } spi_reg_ffmt;
130 _ASSERT_SIZEOF(spi_reg_ffmt, 4);
132 typedef union {
133 struct {
134 uint32_t txwm : 1;
135 uint32_t rxwm : 1;
136 uint32_t reserved : 30;
138 uint32_t raw_bits;
139 } spi_reg_ie;
140 typedef spi_reg_ie spi_reg_ip;
141 _ASSERT_SIZEOF(spi_reg_ie, 4);
142 _ASSERT_SIZEOF(spi_reg_ip, 4);
144 #undef _ASSERT_SIZEOF
147 * SPI control register memory map.
149 * All functions take a pointer to a SPI device's control registers.
151 struct spi_ctrl {
152 uint32_t sckdiv;
153 spi_reg_sckmode sckmode;
154 uint32_t reserved08;
155 uint32_t reserved0c;
157 uint32_t csid;
158 uint32_t csdef;
159 spi_reg_csmode csmode;
160 uint32_t reserved1c;
162 uint32_t reserved20;
163 uint32_t reserved24;
164 spi_reg_delay0 delay0;
165 spi_reg_delay1 delay1;
167 uint32_t reserved30;
168 uint32_t reserved34;
169 uint32_t reserved38;
170 uint32_t reserved3c;
172 spi_reg_fmt fmt;
173 uint32_t reserved44;
174 spi_reg_txdata txdata;
175 spi_reg_rxdata rxdata;
177 spi_reg_txmark txmark;
178 spi_reg_rxmark rxmark;
179 uint32_t reserved58;
180 uint32_t reserved5c;
182 spi_reg_fctrl fctrl;
183 spi_reg_ffmt ffmt;
184 uint32_t reserved68;
185 uint32_t reserved6c;
187 spi_reg_ie ie;
188 spi_reg_ip ip;
192 * Get smallest clock divisor that divides input_khz to a quotient less than or
193 * equal to max_target_khz;
195 static inline unsigned int
196 spi_min_clk_divisor(unsigned int input_khz, unsigned int max_target_khz)
198 // f_sck = f_in / (2 * (div + 1)) => div = (f_in / (2*f_sck)) - 1
200 // The nearest integer solution for div requires rounding up as to not
201 // exceed max_target_khz.
203 // div = ceil(f_in / (2*f_sck)) - 1
204 // = floor((f_in - 1 + 2*f_sck) / (2*f_sck)) - 1
206 // This should not overflow as long as (f_in - 1 + 2*f_sck) does not
207 // exceed 2^32 - 1, which is unlikely since we represent frequencies
208 // in kHz.
209 unsigned int quotient =
210 (input_khz + 2 * max_target_khz - 1) / (2 * max_target_khz);
211 // Avoid underflow
212 if (quotient == 0)
213 return 0;
214 return quotient - 1;
217 #endif /* __SOC_SIFIVE_HIFIVE_U_SPI_INTERNAL_H__ */