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