1 /* spi_dw.h - Designware SPI driver private definitions */
2
3 /*
4 * Copyright (c) 2015 Intel Corporation.
5 * Copyright (c) 2023 Synopsys, Inc. All rights reserved.
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #ifndef ZEPHYR_DRIVERS_SPI_SPI_DW_H_
11 #define ZEPHYR_DRIVERS_SPI_SPI_DW_H_
12
13 #include <string.h>
14 #include <zephyr/device.h>
15 #include <zephyr/drivers/spi.h>
16
17 #include "spi_context.h"
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23 typedef void (*spi_dw_config_t)(void);
24 typedef uint32_t (*spi_dw_read_t)(uint8_t size, mm_reg_t addr, uint32_t off);
25 typedef void (*spi_dw_write_t)(uint8_t size, uint32_t data, mm_reg_t addr, uint32_t off);
26 typedef void (*spi_dw_set_bit_t)(uint8_t bit, mm_reg_t addr, uint32_t off);
27 typedef void (*spi_dw_clear_bit_t)(uint8_t bit, mm_reg_t addr, uint32_t off);
28 typedef int (*spi_dw_test_bit_t)(uint8_t bit, mm_reg_t addr, uint32_t off);
29
30 /* Private structures */
31 struct spi_dw_config {
32 DEVICE_MMIO_ROM;
33 uint32_t clock_frequency;
34 spi_dw_config_t config_func;
35 bool serial_target;
36 uint8_t fifo_depth;
37 uint8_t max_xfer_size;
38 #ifdef CONFIG_PINCTRL
39 const struct pinctrl_dev_config *pcfg;
40 #endif
41 spi_dw_read_t read_func;
42 spi_dw_write_t write_func;
43 spi_dw_set_bit_t set_bit_func;
44 spi_dw_clear_bit_t clear_bit_func;
45 spi_dw_test_bit_t test_bit_func;
46 };
47
48 struct spi_dw_data {
49 DEVICE_MMIO_RAM;
50 struct spi_context ctx;
51 uint8_t dfs; /* dfs in bytes: 1,2 or 4 */
52 uint8_t fifo_diff; /* cannot be bigger than FIFO depth */
53 };
54
55 /* Register operation functions */
56 #define DT_INST_NODE_PROP_NOT_OR(inst, prop) \
57 !DT_INST_PROP(inst, prop) ||
58 #define DT_ANY_INST_NOT_PROP_STATUS_OKAY(prop) \
59 (DT_INST_FOREACH_STATUS_OKAY_VARGS(DT_INST_NODE_PROP_NOT_OR, prop) 0)
60
61 #define DT_INST_NODE_PROP_AND_OR(inst, prop) \
62 DT_INST_PROP(inst, prop) ||
63 #define DT_ANY_INST_PROP_STATUS_OKAY(prop) \
64 (DT_INST_FOREACH_STATUS_OKAY_VARGS(DT_INST_NODE_PROP_AND_OR, prop) 0)
65
66 #if DT_ANY_INST_PROP_STATUS_OKAY(aux_reg)
aux_reg_read(uint8_t size,mm_reg_t addr,uint32_t off)67 static uint32_t aux_reg_read(uint8_t size, mm_reg_t addr, uint32_t off)
68 {
69 ARG_UNUSED(size);
70 return sys_in32(addr + off/4);
71 }
72
aux_reg_write(uint8_t size,uint32_t data,mm_reg_t addr,uint32_t off)73 static void aux_reg_write(uint8_t size, uint32_t data, mm_reg_t addr, uint32_t off)
74 {
75 ARG_UNUSED(size);
76 sys_out32(data, addr + off/4);
77 }
78
aux_reg_set_bit(uint8_t bit,mm_reg_t addr,uint32_t off)79 static void aux_reg_set_bit(uint8_t bit, mm_reg_t addr, uint32_t off)
80 {
81 sys_io_set_bit(addr + off/4, bit);
82 }
83
aux_reg_clear_bit(uint8_t bit,mm_reg_t addr,uint32_t off)84 static void aux_reg_clear_bit(uint8_t bit, mm_reg_t addr, uint32_t off)
85 {
86 sys_io_clear_bit(addr + off/4, bit);
87 }
88
aux_reg_test_bit(uint8_t bit,mm_reg_t addr,uint32_t off)89 static int aux_reg_test_bit(uint8_t bit, mm_reg_t addr, uint32_t off)
90 {
91 return sys_io_test_bit(addr + off/4, bit);
92 }
93 #endif
94
95 #if DT_ANY_INST_NOT_PROP_STATUS_OKAY(aux_reg)
reg_read(uint8_t size,mm_reg_t addr,uint32_t off)96 static uint32_t reg_read(uint8_t size, mm_reg_t addr, uint32_t off)
97 {
98 switch (size) {
99 case 8:
100 return sys_read8(addr + off);
101 case 16:
102 return sys_read16(addr + off);
103 case 32:
104 return sys_read32(addr + off);
105 default:
106 return -EINVAL;
107 }
108 }
109
reg_write(uint8_t size,uint32_t data,mm_reg_t addr,uint32_t off)110 static void reg_write(uint8_t size, uint32_t data, mm_reg_t addr, uint32_t off)
111 {
112 switch (size) {
113 case 8:
114 sys_write8(data, addr + off); break;
115 case 16:
116 sys_write16(data, addr + off); break;
117 case 32:
118 sys_write32(data, addr + off); break;
119 default:
120 break;
121 }
122 }
123
reg_set_bit(uint8_t bit,mm_reg_t addr,uint32_t off)124 static void reg_set_bit(uint8_t bit, mm_reg_t addr, uint32_t off)
125 {
126 sys_set_bit(addr + off, bit);
127 }
128
reg_clear_bit(uint8_t bit,mm_reg_t addr,uint32_t off)129 static void reg_clear_bit(uint8_t bit, mm_reg_t addr, uint32_t off)
130 {
131 sys_clear_bit(addr + off, bit);
132 }
133
reg_test_bit(uint8_t bit,mm_reg_t addr,uint32_t off)134 static int reg_test_bit(uint8_t bit, mm_reg_t addr, uint32_t off)
135 {
136 return sys_test_bit(addr + off, bit);
137 }
138 #endif
139
140 /* Helper macros */
141
142 #define SPI_DW_CLK_DIVIDER(clock_freq, ssi_clk_hz) \
143 ((clock_freq / ssi_clk_hz) & 0xFFFF)
144
145 #define DEFINE_MM_REG_READ(__reg, __off, __sz) \
146 static inline uint32_t read_##__reg(const struct device *dev) \
147 { \
148 const struct spi_dw_config *info = dev->config; \
149 return info->read_func(__sz, (mm_reg_t)DEVICE_MMIO_GET(dev), __off); \
150 }
151 #define DEFINE_MM_REG_WRITE(__reg, __off, __sz) \
152 static inline void write_##__reg(const struct device *dev, uint32_t data)\
153 { \
154 const struct spi_dw_config *info = dev->config; \
155 info->write_func(__sz, data, (mm_reg_t)DEVICE_MMIO_GET(dev), __off); \
156 }
157
158 #define DEFINE_SET_BIT_OP(__reg_bit, __reg_off, __bit) \
159 static inline void set_bit_##__reg_bit(const struct device *dev) \
160 { \
161 const struct spi_dw_config *info = dev->config; \
162 info->set_bit_func(__bit, (mm_reg_t)DEVICE_MMIO_GET(dev), __reg_off); \
163 }
164
165 #define DEFINE_CLEAR_BIT_OP(__reg_bit, __reg_off, __bit) \
166 static inline void clear_bit_##__reg_bit(const struct device *dev)\
167 { \
168 const struct spi_dw_config *info = dev->config; \
169 info->clear_bit_func(__bit, (mm_reg_t)DEVICE_MMIO_GET(dev), __reg_off); \
170 }
171
172 #define DEFINE_TEST_BIT_OP(__reg_bit, __reg_off, __bit) \
173 static inline int test_bit_##__reg_bit(const struct device *dev)\
174 { \
175 const struct spi_dw_config *info = dev->config; \
176 return info->test_bit_func(__bit, (mm_reg_t)DEVICE_MMIO_GET(dev), __reg_off); \
177 }
178
179 /* Common registers settings, bits etc... */
180
181 /* CTRLR0 settings */
182 #if !defined(CONFIG_SPI_DW_HSSI)
183 #define DW_SPI_CTRLR0_SCPH_BIT (6)
184 #define DW_SPI_CTRLR0_SCPOL_BIT (7)
185 #define DW_SPI_CTRLR0_TMOD_SHIFT (8)
186 #define DW_SPI_CTRLR0_SLV_OE_BIT (10)
187 #define DW_SPI_CTRLR0_SRL_BIT (11)
188 #else
189 /* The register layout is different in the HSSI variant */
190 #define DW_SPI_CTRLR0_SCPH_BIT (8)
191 #define DW_SPI_CTRLR0_SCPOL_BIT (9)
192 #define DW_SPI_CTRLR0_TMOD_SHIFT (10)
193 #define DW_SPI_CTRLR0_SLV_OE_BIT (12)
194 #define DW_SPI_CTRLR0_SRL_BIT (13)
195 #endif
196
197 #define DW_SPI_CTRLR0_SCPH BIT(DW_SPI_CTRLR0_SCPH_BIT)
198 #define DW_SPI_CTRLR0_SCPOL BIT(DW_SPI_CTRLR0_SCPOL_BIT)
199 #define DW_SPI_CTRLR0_SRL BIT(DW_SPI_CTRLR0_SRL_BIT)
200 #define DW_SPI_CTRLR0_SLV_OE BIT(DW_SPI_CTRLR0_SLV_OE_BIT)
201
202 #define DW_SPI_CTRLR0_TMOD_TX_RX (0)
203 #define DW_SPI_CTRLR0_TMOD_TX (1 << DW_SPI_CTRLR0_TMOD_SHIFT)
204 #define DW_SPI_CTRLR0_TMOD_RX (2 << DW_SPI_CTRLR0_TMOD_SHIFT)
205 #define DW_SPI_CTRLR0_TMOD_EEPROM (3 << DW_SPI_CTRLR0_TMOD_SHIFT)
206 #define DW_SPI_CTRLR0_TMOD_RESET (3 << DW_SPI_CTRLR0_TMOD_SHIFT)
207
208 #define DW_SPI_CTRLR0_DFS_16(__bpw) ((__bpw) - 1)
209 #define DW_SPI_CTRLR0_DFS_32(__bpw) (((__bpw) - 1) << 16)
210
211 /* 0x38 represents the bits 8, 16 and 32. Knowing that 24 is bits 8 and 16
212 * These are the bits were when you divide by 8, you keep the result as it is.
213 * For all the other ones, 4 to 7, 9 to 15, etc... you need a +1,
214 * since on such division it takes only the result above 0
215 */
216 #define SPI_WS_TO_DFS(__bpw) (((__bpw) & ~0x38) ? \
217 (((__bpw) / 8) + 1) : \
218 ((__bpw) / 8))
219
220 /* SSIENR bits */
221 #define DW_SPI_SSIENR_SSIEN_BIT (0)
222
223 /* CLK_ENA bits */
224 #define DW_SPI_CLK_ENA_BIT (0)
225
226 /* SR bits and values */
227 #define DW_SPI_SR_BUSY_BIT (0)
228 #define DW_SPI_SR_TFNF_BIT (1)
229 #define DW_SPI_SR_RFNE_BIT (3)
230
231 /* IMR bits (ISR valid as well) */
232 #define DW_SPI_IMR_TXEIM_BIT (0)
233 #define DW_SPI_IMR_TXOIM_BIT (1)
234 #define DW_SPI_IMR_RXUIM_BIT (2)
235 #define DW_SPI_IMR_RXOIM_BIT (3)
236 #define DW_SPI_IMR_RXFIM_BIT (4)
237 #define DW_SPI_IMR_MSTIM_BIT (5)
238
239 /* IMR values */
240 #define DW_SPI_IMR_TXEIM BIT(DW_SPI_IMR_TXEIM_BIT)
241 #define DW_SPI_IMR_TXOIM BIT(DW_SPI_IMR_TXOIM_BIT)
242 #define DW_SPI_IMR_RXUIM BIT(DW_SPI_IMR_RXUIM_BIT)
243 #define DW_SPI_IMR_RXOIM BIT(DW_SPI_IMR_RXOIM_BIT)
244 #define DW_SPI_IMR_RXFIM BIT(DW_SPI_IMR_RXFIM_BIT)
245 #define DW_SPI_IMR_MSTIM BIT(DW_SPI_IMR_MSTIM_BIT)
246
247 /* ISR values (same as IMR) */
248 #define DW_SPI_ISR_TXEIS DW_SPI_IMR_TXEIM
249 #define DW_SPI_ISR_TXOIS DW_SPI_IMR_TXOIM
250 #define DW_SPI_ISR_RXUIS DW_SPI_IMR_RXUIM
251 #define DW_SPI_ISR_RXOIS DW_SPI_IMR_RXOIM
252 #define DW_SPI_ISR_RXFIS DW_SPI_IMR_RXFIM
253 #define DW_SPI_ISR_MSTIS DW_SPI_IMR_MSTIM
254
255 /* Error interrupt */
256 #define DW_SPI_ISR_ERRORS_MASK (DW_SPI_ISR_TXOIS | \
257 DW_SPI_ISR_RXUIS | \
258 DW_SPI_ISR_RXOIS | \
259 DW_SPI_ISR_MSTIS)
260 /* ICR Bit */
261 #define DW_SPI_SR_ICR_BIT (0)
262
263 /* Interrupt mask (IMR) */
264 #define DW_SPI_IMR_MASK (0x0)
265 #define DW_SPI_IMR_UNMASK (DW_SPI_IMR_TXEIM | \
266 DW_SPI_IMR_TXOIM | \
267 DW_SPI_IMR_RXUIM | \
268 DW_SPI_IMR_RXOIM | \
269 DW_SPI_IMR_RXFIM)
270 #define DW_SPI_IMR_MASK_TX (~(DW_SPI_IMR_TXEIM | \
271 DW_SPI_IMR_TXOIM))
272 #define DW_SPI_IMR_MASK_RX (~(DW_SPI_IMR_RXUIM | \
273 DW_SPI_IMR_RXOIM | \
274 DW_SPI_IMR_RXFIM))
275
276 /*
277 * Including the right register definition file
278 * SoC SPECIFIC!
279 *
280 * The file included next uses the DEFINE_MM_REG macros above to
281 * declare functions. In this situation we'll leave the containing
282 * extern "C" active in C++ compilations.
283 */
284 #include "spi_dw_regs.h"
285
286 #define z_extra_clock_on(...)
287 #define z_extra_clock_off(...)
288
289 /* Based on those macros above, here are common helpers for some registers */
290
291 DEFINE_MM_REG_READ(txflr, DW_SPI_REG_TXFLR, 32)
292 DEFINE_MM_REG_READ(rxflr, DW_SPI_REG_RXFLR, 32)
293
294 #ifdef CONFIG_SPI_DW_ACCESS_WORD_ONLY
295 DEFINE_MM_REG_WRITE(baudr, DW_SPI_REG_BAUDR, 32)
296 DEFINE_MM_REG_WRITE(imr, DW_SPI_REG_IMR, 32)
297 DEFINE_MM_REG_READ(imr, DW_SPI_REG_IMR, 32)
298 DEFINE_MM_REG_READ(isr, DW_SPI_REG_ISR, 32)
299 #else
300 DEFINE_MM_REG_WRITE(baudr, DW_SPI_REG_BAUDR, 16)
301 DEFINE_MM_REG_WRITE(imr, DW_SPI_REG_IMR, 8)
302 DEFINE_MM_REG_READ(imr, DW_SPI_REG_IMR, 8)
303 DEFINE_MM_REG_READ(isr, DW_SPI_REG_ISR, 8)
304 #endif
305
306 DEFINE_SET_BIT_OP(ssienr, DW_SPI_REG_SSIENR, DW_SPI_SSIENR_SSIEN_BIT)
307 DEFINE_CLEAR_BIT_OP(ssienr, DW_SPI_REG_SSIENR, DW_SPI_SSIENR_SSIEN_BIT)
308 DEFINE_TEST_BIT_OP(ssienr, DW_SPI_REG_SSIENR, DW_SPI_SSIENR_SSIEN_BIT)
309 DEFINE_TEST_BIT_OP(sr_busy, DW_SPI_REG_SR, DW_SPI_SR_BUSY_BIT)
310
311 #ifdef __cplusplus
312 }
313 #endif
314
315 #endif /* ZEPHYR_DRIVERS_SPI_SPI_DW_H_ */
316