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