1 /*
2  * Copyright (c) 2023 Rivos Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(spi_opentitan);
9 
10 #include "spi_context.h"
11 
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/spi.h>
14 #include <zephyr/drivers/spi/rtio.h>
15 #include <soc.h>
16 #include <stdbool.h>
17 
18 /* Register offsets within the SPI host register space. */
19 #define SPI_HOST_INTR_STATE_REG_OFFSET 0x00
20 #define SPI_HOST_INTR_ENABLE_REG_OFFSET 0x04
21 #define SPI_HOST_INTR_TEST_REG_OFFSET 0x08
22 #define SPI_HOST_ALERT_TEST_REG_OFFSET 0x0c
23 #define SPI_HOST_CONTROL_REG_OFFSET 0x10
24 #define SPI_HOST_STATUS_REG_OFFSET 0x14
25 #define SPI_HOST_CONFIGOPTS_REG_OFFSET 0x18
26 #define SPI_HOST_CSID_REG_OFFSET 0x1c
27 #define SPI_HOST_COMMAND_REG_OFFSET 0x20
28 #define SPI_HOST_RXDATA_REG_OFFSET 0x24
29 #define SPI_HOST_TXDATA_REG_OFFSET 0x28
30 #define SPI_HOST_ERROR_ENABLE_REG_OFFSET 0x2c
31 #define SPI_HOST_ERROR_STATUS_REG_OFFSET 0x30
32 #define SPI_HOST_EVENT_ENABLE_REG_OFFSET 0x34
33 
34 /* Control register fields. */
35 #define SPI_HOST_CONTROL_OUTPUT_EN_BIT BIT(29)
36 #define SPI_HOST_CONTROL_SW_RST_BIT BIT(30)
37 #define SPI_HOST_CONTROL_SPIEN_BIT BIT(31)
38 
39 /* Status register fields. */
40 #define SPI_HOST_STATUS_TXQD_MASK GENMASK(7, 0)
41 #define SPI_HOST_STATUS_RXQD_MASK GENMASK(15, 8)
42 #define SPI_HOST_STATUS_BYTEORDER_BIT BIT(22)
43 #define SPI_HOST_STATUS_RXEMPTY_BIT BIT(24)
44 #define SPI_HOST_STATUS_ACTIVE_BIT BIT(30)
45 #define SPI_HOST_STATUS_READY_BIT BIT(31)
46 
47 /* Command register fields. */
48 #define SPI_HOST_COMMAND_LEN_MASK GENMASK(8, 0)
49 /* "Chip select active after transaction" */
50 #define SPI_HOST_COMMAND_CSAAT_BIT BIT(9)
51 #define SPI_HOST_COMMAND_SPEED_MASK GENMASK(11, 10)
52 #define SPI_HOST_COMMAND_SPEED_STANDARD (0 << 10)
53 #define SPI_HOST_COMMAND_SPEED_DUAL (1 << 10)
54 #define SPI_HOST_COMMAND_SPEED_QUAD (2 << 10)
55 #define SPI_HOST_COMMAND_DIRECTION_MASK GENMASK(13, 12)
56 #define SPI_HOST_COMMAND_DIRECTION_RX (0x1 << 12)
57 #define SPI_HOST_COMMAND_DIRECTION_TX (0x2 << 12)
58 #define SPI_HOST_COMMAND_DIRECTION_BOTH (0x3 << 12)
59 
60 /* Configopts register fields. */
61 #define SPI_HOST_CONFIGOPTS_CPHA0_BIT BIT(30)
62 #define SPI_HOST_CONFIGOPTS_CPOL0_BIT BIT(31)
63 
64 #define DT_DRV_COMPAT lowrisc_opentitan_spi
65 
66 struct spi_opentitan_data {
67 	struct spi_context ctx;
68 };
69 
70 struct spi_opentitan_cfg {
71 	uint32_t base;
72 	uint32_t f_input;
73 };
74 
spi_config(const struct device * dev,uint32_t frequency,uint16_t operation)75 static int spi_config(const struct device *dev, uint32_t frequency,
76 		uint16_t operation)
77 {
78 	const struct spi_opentitan_cfg *cfg = dev->config;
79 
80 	uint32_t reg;
81 
82 	if (operation & SPI_HALF_DUPLEX) {
83 		return -ENOTSUP;
84 	}
85 
86 	if (SPI_OP_MODE_GET(operation) != SPI_OP_MODE_MASTER) {
87 		return -ENOTSUP;
88 	}
89 
90 	if (operation & SPI_MODE_LOOP) {
91 		return -ENOTSUP;
92 	}
93 
94 	if (SPI_WORD_SIZE_GET(operation) != 8) {
95 		return -ENOTSUP;
96 	}
97 
98 	if (IS_ENABLED(CONFIG_SPI_EXTENDED_MODES) &&
99 		(operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) {
100 		return -ENOTSUP;
101 	}
102 
103 	/* Most significant bit always transferred first. */
104 	if (operation & SPI_TRANSFER_LSB) {
105 		return -ENOTSUP;
106 	}
107 
108 	/* Set the SPI frequency, polarity, and clock phase in CONFIGOPTS register.
109 	 * Applied divider (divides f_in / 2) is CLKDIV register (16 bit) + 1.
110 	 */
111 	reg = cfg->f_input / 2 / frequency;
112 	if (reg > 0xffffu) {
113 		reg = 0xffffu;
114 	} else if (reg > 0) {
115 		reg--;
116 	}
117 	/* Setup phase */
118 	if (operation & SPI_MODE_CPHA) {
119 		reg |= SPI_HOST_CONFIGOPTS_CPHA0_BIT;
120 	}
121 	/* Setup polarity. */
122 	if (operation & SPI_MODE_CPOL) {
123 		reg |= SPI_HOST_CONFIGOPTS_CPOL0_BIT;
124 	}
125 	sys_write32(reg, cfg->base + SPI_HOST_CONFIGOPTS_REG_OFFSET);
126 
127 	return 0;
128 }
129 
spi_opentitan_rx_available(const struct spi_opentitan_cfg * cfg)130 static bool spi_opentitan_rx_available(const struct spi_opentitan_cfg *cfg)
131 {
132 	/* Rx bytes are available if Tx FIFO is non-empty. */
133 	return !(sys_read32(cfg->base + SPI_HOST_STATUS_REG_OFFSET) & SPI_HOST_STATUS_RXEMPTY_BIT);
134 }
135 
spi_opentitan_xfer(const struct device * dev,const bool gpio_cs_control)136 static void spi_opentitan_xfer(const struct device *dev, const bool gpio_cs_control)
137 {
138 	const struct spi_opentitan_cfg *cfg = dev->config;
139 	struct spi_opentitan_data *data = dev->data;
140 	struct spi_context *ctx = &data->ctx;
141 
142 	while (spi_context_tx_on(ctx) || spi_context_rx_on(ctx)) {
143 		const size_t segment_len = MAX(ctx->tx_len, ctx->rx_len);
144 		uint32_t host_command_reg;
145 
146 		/* Setup transaction duplex. */
147 		if (!spi_context_tx_on(ctx)) {
148 			host_command_reg = SPI_HOST_COMMAND_DIRECTION_RX;
149 		} else if (!spi_context_rx_on(ctx)) {
150 			host_command_reg = SPI_HOST_COMMAND_DIRECTION_TX;
151 		} else {
152 			host_command_reg = SPI_HOST_COMMAND_DIRECTION_BOTH;
153 		}
154 
155 		size_t tx_bytes_to_queue = spi_context_tx_buf_on(ctx) ? ctx->tx_len : 0;
156 
157 		/* First place Tx bytes in FIFO, packed four to a word. */
158 		while (tx_bytes_to_queue > 0) {
159 			uint32_t fifo_word = 0;
160 
161 			for (int byte = 0; byte < 4; ++byte) {
162 				if (tx_bytes_to_queue == 0) {
163 					break;
164 				}
165 				fifo_word |= *ctx->tx_buf << (8 * byte);
166 				spi_context_update_tx(ctx, 1, 1);
167 				tx_bytes_to_queue--;
168 			}
169 			sys_write32(fifo_word, cfg->base + SPI_HOST_TXDATA_REG_OFFSET);
170 		}
171 
172 		/* Keep CS asserted if another Tx segment remains or if two more Rx
173 		 * segments remain (because we will handle one Rx segment after the
174 		 * forthcoming transaction).
175 		 */
176 		if (ctx->tx_count > 0 || ctx->rx_count > 1)  {
177 			host_command_reg |= SPI_HOST_COMMAND_CSAAT_BIT;
178 		}
179 		/* Segment length field holds COMMAND.LEN + 1. */
180 		host_command_reg |= segment_len - 1;
181 
182 		/* Issue transaction. */
183 		sys_write32(host_command_reg, cfg->base + SPI_HOST_COMMAND_REG_OFFSET);
184 
185 		size_t rx_bytes_to_read = spi_context_rx_buf_on(ctx) ? ctx->rx_len : 0;
186 
187 		/* Read from Rx FIFO as required. */
188 		while (rx_bytes_to_read > 0) {
189 			while (!spi_opentitan_rx_available(cfg)) {
190 				;
191 			}
192 			uint32_t rx_word = sys_read32(cfg->base +
193 				SPI_HOST_RXDATA_REG_OFFSET);
194 			for (int byte = 0; byte < 4; ++byte) {
195 				if (rx_bytes_to_read == 0) {
196 					break;
197 				}
198 				*ctx->rx_buf = (rx_word >> (8 * byte)) & 0xff;
199 				spi_context_update_rx(ctx, 1, 1);
200 				rx_bytes_to_read--;
201 			}
202 		}
203 	}
204 
205 	/* Deassert the CS line if required. */
206 	if (gpio_cs_control) {
207 		spi_context_cs_control(ctx, false);
208 	}
209 
210 	spi_context_complete(ctx, dev, 0);
211 }
212 
spi_opentitan_init(const struct device * dev)213 static int spi_opentitan_init(const struct device *dev)
214 {
215 	const struct spi_opentitan_cfg *cfg = dev->config;
216 	struct spi_opentitan_data *data = dev->data;
217 	int err;
218 
219 	/* Place SPI host peripheral in reset and wait for reset to complete. */
220 	sys_write32(SPI_HOST_CONTROL_SW_RST_BIT,
221 		cfg->base + SPI_HOST_CONTROL_REG_OFFSET);
222 	while (sys_read32(cfg->base + SPI_HOST_STATUS_REG_OFFSET)
223 			& (SPI_HOST_STATUS_ACTIVE_BIT | SPI_HOST_STATUS_TXQD_MASK |
224 				SPI_HOST_STATUS_RXQD_MASK)) {
225 		;
226 	}
227 	/* Clear reset and enable SPI host peripheral. */
228 	sys_write32(SPI_HOST_CONTROL_OUTPUT_EN_BIT | SPI_HOST_CONTROL_SPIEN_BIT,
229 		cfg->base + SPI_HOST_CONTROL_REG_OFFSET);
230 
231 	err = spi_context_cs_configure_all(&data->ctx);
232 	if (err < 0) {
233 		return err;
234 	}
235 
236 	/* Make sure the context is unlocked */
237 	spi_context_unlock_unconditionally(&data->ctx);
238 	return 0;
239 }
240 
spi_opentitan_transceive(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs)241 static int spi_opentitan_transceive(const struct device *dev,
242 			  const struct spi_config *config,
243 			  const struct spi_buf_set *tx_bufs,
244 			  const struct spi_buf_set *rx_bufs)
245 {
246 	int rc = 0;
247 	bool gpio_cs_control = false;
248 	struct spi_opentitan_data *data = dev->data;
249 
250 	/* Lock the SPI Context */
251 	spi_context_lock(&data->ctx, false, NULL, NULL, config);
252 
253 	/* Configure the SPI bus */
254 	data->ctx.config = config;
255 	rc = spi_config(dev, config->frequency, config->operation);
256 	if (rc < 0) {
257 		spi_context_release(&data->ctx, rc);
258 		return rc;
259 	}
260 
261 	spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1);
262 
263 	/* Assert the CS line. HW will always assert the CS pin identified by CSID
264 	 * (default CSID: 0), so GPIO CS control will work in addition to HW
265 	 * asserted (and presumably ignored) CS.
266 	 */
267 	if (config->cs) {
268 		gpio_cs_control = true;
269 		spi_context_cs_control(&data->ctx, true);
270 	}
271 
272 	/* Perform transfer */
273 	spi_opentitan_xfer(dev, gpio_cs_control);
274 
275 	rc = spi_context_wait_for_completion(&data->ctx);
276 
277 	spi_context_release(&data->ctx, rc);
278 
279 	return rc;
280 }
281 
282 #ifdef CONFIG_SPI_ASYNC
spi_opentitan_transceive_async(const struct device * dev,const struct spi_config * spi_cfg,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs,spi_callback_t cb,void * userdata)283 static int spi_opentitan_transceive_async(const struct device *dev,
284 					const struct spi_config *spi_cfg,
285 					const struct spi_buf_set *tx_bufs,
286 					const struct spi_buf_set *rx_bufs,
287 					spi_callback_t cb,
288 					void *userdata)
289 {
290 	return -ENOTSUP;
291 }
292 #endif
293 
spi_opentitan_release(const struct device * dev,const struct spi_config * config)294 static int spi_opentitan_release(const struct device *dev,
295 			   const struct spi_config *config)
296 {
297 	struct spi_opentitan_data *data = dev->data;
298 
299 	spi_context_unlock_unconditionally(&data->ctx);
300 	return 0;
301 }
302 
303 /* Device Instantiation */
304 
305 static DEVICE_API(spi, spi_opentitan_api) = {
306 	.transceive = spi_opentitan_transceive,
307 #ifdef CONFIG_SPI_ASYNC
308 	.transceive_async = spi_opentitan_transceive_async,
309 #endif
310 #ifdef CONFIG_SPI_RTIO
311 	.iodev_submit = spi_rtio_iodev_default_submit,
312 #endif
313 	.release = spi_opentitan_release,
314 };
315 
316 #define SPI_INIT(n) \
317 	static struct spi_opentitan_data spi_opentitan_data_##n = { \
318 		SPI_CONTEXT_INIT_LOCK(spi_opentitan_data_##n, ctx), \
319 		SPI_CONTEXT_INIT_SYNC(spi_opentitan_data_##n, ctx), \
320 		SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx)	\
321 	}; \
322 	static struct spi_opentitan_cfg spi_opentitan_cfg_##n = { \
323 		.base = DT_INST_REG_ADDR(n), \
324 		.f_input = DT_INST_PROP(n, clock_frequency), \
325 	}; \
326 	SPI_DEVICE_DT_INST_DEFINE(n, \
327 			spi_opentitan_init, \
328 			NULL, \
329 			&spi_opentitan_data_##n, \
330 			&spi_opentitan_cfg_##n, \
331 			POST_KERNEL, \
332 			CONFIG_SPI_INIT_PRIORITY, \
333 			&spi_opentitan_api);
334 
335 DT_INST_FOREACH_STATUS_OKAY(SPI_INIT)
336