1 /*
2  * Copyright (c) 2018, NXP
3  *
4  * Forked off the spi_mcux_lpi2c driver.
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #define DT_DRV_COMPAT openisa_rv32m1_lpspi
10 
11 #include <errno.h>
12 #include <zephyr/drivers/spi.h>
13 #include <zephyr/drivers/clock_control.h>
14 #include <fsl_lpspi.h>
15 #include <zephyr/drivers/pinctrl.h>
16 
17 #define LOG_LEVEL CONFIG_SPI_LOG_LEVEL
18 #include <zephyr/logging/log.h>
19 #include <zephyr/irq.h>
20 LOG_MODULE_REGISTER(spi_rv32m1_lpspi);
21 
22 #include <soc.h>
23 
24 #include "spi_context.h"
25 
26 #define CHIP_SELECT_COUNT	4
27 #define MAX_DATA_WIDTH		4096
28 
29 struct spi_mcux_config {
30 	LPSPI_Type *base;
31 	const struct device *clock_dev;
32 	clock_control_subsys_t clock_subsys;
33 	clock_ip_name_t clock_ip_name;
34 	uint32_t clock_ip_src;
35 	void (*irq_config_func)(const struct device *dev);
36 	const struct pinctrl_dev_config *pincfg;
37 };
38 
39 struct spi_mcux_data {
40 	const struct device *dev;
41 	lpspi_master_handle_t handle;
42 	struct spi_context ctx;
43 	size_t transfer_len;
44 };
45 
spi_mcux_transfer_next_packet(const struct device * dev)46 static void spi_mcux_transfer_next_packet(const struct device *dev)
47 {
48 	const struct spi_mcux_config *config = dev->config;
49 	struct spi_mcux_data *data = dev->data;
50 	LPSPI_Type *base = config->base;
51 	struct spi_context *ctx = &data->ctx;
52 	lpspi_transfer_t transfer;
53 	status_t status;
54 
55 	if ((ctx->tx_len == 0) && (ctx->rx_len == 0)) {
56 		/* nothing left to rx or tx, we're done! */
57 		spi_context_cs_control(&data->ctx, false);
58 		spi_context_complete(&data->ctx, dev, 0);
59 		return;
60 	}
61 
62 	transfer.configFlags = kLPSPI_MasterPcsContinuous |
63 			       (ctx->config->slave << LPSPI_MASTER_PCS_SHIFT);
64 
65 	if (ctx->tx_len == 0) {
66 		/* rx only, nothing to tx */
67 		transfer.txData = NULL;
68 		transfer.rxData = ctx->rx_buf;
69 		transfer.dataSize = ctx->rx_len;
70 	} else if (ctx->rx_len == 0) {
71 		/* tx only, nothing to rx */
72 		transfer.txData = (uint8_t *) ctx->tx_buf;
73 		transfer.rxData = NULL;
74 		transfer.dataSize = ctx->tx_len;
75 	} else if (ctx->tx_len == ctx->rx_len) {
76 		/* rx and tx are the same length */
77 		transfer.txData = (uint8_t *) ctx->tx_buf;
78 		transfer.rxData = ctx->rx_buf;
79 		transfer.dataSize = ctx->tx_len;
80 	} else if (ctx->tx_len > ctx->rx_len) {
81 		/* Break up the tx into multiple transfers so we don't have to
82 		 * rx into a longer intermediate buffer. Leave chip select
83 		 * active between transfers.
84 		 */
85 		transfer.txData = (uint8_t *) ctx->tx_buf;
86 		transfer.rxData = ctx->rx_buf;
87 		transfer.dataSize = ctx->rx_len;
88 		transfer.configFlags |= kLPSPI_MasterPcsContinuous;
89 	} else {
90 		/* Break up the rx into multiple transfers so we don't have to
91 		 * tx from a longer intermediate buffer. Leave chip select
92 		 * active between transfers.
93 		 */
94 		transfer.txData = (uint8_t *) ctx->tx_buf;
95 		transfer.rxData = ctx->rx_buf;
96 		transfer.dataSize = ctx->tx_len;
97 		transfer.configFlags |= kLPSPI_MasterPcsContinuous;
98 	}
99 
100 	if (!(ctx->tx_count <= 1 && ctx->rx_count <= 1)) {
101 		transfer.configFlags |= kLPSPI_MasterPcsContinuous;
102 	}
103 
104 	data->transfer_len = transfer.dataSize;
105 	status = LPSPI_MasterTransferNonBlocking(base, &data->handle,
106 						 &transfer);
107 	if (status != kStatus_Success) {
108 		LOG_ERR("Transfer could not start");
109 	}
110 }
111 
spi_mcux_isr(const struct device * dev)112 static void spi_mcux_isr(const struct device *dev)
113 {
114 	const struct spi_mcux_config *config = dev->config;
115 	struct spi_mcux_data *data = dev->data;
116 	LPSPI_Type *base = config->base;
117 
118 	LPSPI_MasterTransferHandleIRQ(base, &data->handle);
119 }
120 
spi_mcux_master_transfer_callback(LPSPI_Type * base,lpspi_master_handle_t * handle,status_t status,void * userData)121 static void spi_mcux_master_transfer_callback(LPSPI_Type *base,
122 					      lpspi_master_handle_t *handle,
123 					      status_t status, void *userData)
124 {
125 	struct spi_mcux_data *data = userData;
126 
127 	spi_context_update_tx(&data->ctx, 1, data->transfer_len);
128 	spi_context_update_rx(&data->ctx, 1, data->transfer_len);
129 
130 	spi_mcux_transfer_next_packet(data->dev);
131 }
132 
spi_mcux_configure(const struct device * dev,const struct spi_config * spi_cfg)133 static int spi_mcux_configure(const struct device *dev,
134 			      const struct spi_config *spi_cfg)
135 {
136 	const struct spi_mcux_config *config = dev->config;
137 	struct spi_mcux_data *data = dev->data;
138 	LPSPI_Type *base = config->base;
139 	lpspi_master_config_t master_config;
140 	uint32_t clock_freq;
141 	uint32_t word_size;
142 
143 	if (spi_context_configured(&data->ctx, spi_cfg)) {
144 		/* This configuration is already in use */
145 		return 0;
146 	}
147 
148 	if (spi_cfg->operation & SPI_HALF_DUPLEX) {
149 		LOG_ERR("Half-duplex not supported");
150 		return -ENOTSUP;
151 	}
152 
153 	LPSPI_MasterGetDefaultConfig(&master_config);
154 
155 	if (spi_cfg->slave > CHIP_SELECT_COUNT) {
156 		LOG_ERR("Slave %d is greater than %d",
157 			    spi_cfg->slave,
158 			    CHIP_SELECT_COUNT);
159 		return -EINVAL;
160 	}
161 
162 	word_size = SPI_WORD_SIZE_GET(spi_cfg->operation);
163 	if (word_size > MAX_DATA_WIDTH) {
164 		LOG_ERR("Word size %d is greater than %d",
165 			    word_size, MAX_DATA_WIDTH);
166 		return -EINVAL;
167 	}
168 
169 	master_config.bitsPerFrame = word_size;
170 
171 	master_config.cpol =
172 		(SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL)
173 		? kLPSPI_ClockPolarityActiveLow
174 		: kLPSPI_ClockPolarityActiveHigh;
175 
176 	master_config.cpha =
177 		(SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA)
178 		? kLPSPI_ClockPhaseSecondEdge
179 		: kLPSPI_ClockPhaseFirstEdge;
180 
181 	master_config.direction =
182 		(spi_cfg->operation & SPI_TRANSFER_LSB)
183 		? kLPSPI_LsbFirst
184 		: kLPSPI_MsbFirst;
185 
186 	master_config.baudRate = spi_cfg->frequency;
187 
188 	if (!device_is_ready(config->clock_dev)) {
189 		LOG_ERR("clock control device not ready");
190 		return -ENODEV;
191 	}
192 
193 	if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
194 				   &clock_freq)) {
195 		return -EINVAL;
196 	}
197 
198 	LPSPI_MasterInit(base, &master_config, clock_freq);
199 
200 	LPSPI_MasterTransferCreateHandle(base, &data->handle,
201 					 spi_mcux_master_transfer_callback,
202 					 data);
203 
204 	LPSPI_SetDummyData(base, 0);
205 
206 	data->ctx.config = spi_cfg;
207 
208 	return 0;
209 }
210 
transceive(const struct device * dev,const struct spi_config * spi_cfg,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs,bool asynchronous,spi_callback_t cb,void * userdata)211 static int transceive(const struct device *dev,
212 		      const struct spi_config *spi_cfg,
213 		      const struct spi_buf_set *tx_bufs,
214 		      const struct spi_buf_set *rx_bufs,
215 		      bool asynchronous,
216 		      spi_callback_t cb,
217 		      void *userdata)
218 {
219 	struct spi_mcux_data *data = dev->data;
220 	int ret;
221 
222 	spi_context_lock(&data->ctx, asynchronous, cb, userdata, spi_cfg);
223 
224 	ret = spi_mcux_configure(dev, spi_cfg);
225 	if (ret) {
226 		goto out;
227 	}
228 
229 	spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1);
230 
231 	spi_context_cs_control(&data->ctx, true);
232 
233 	spi_mcux_transfer_next_packet(dev);
234 
235 	ret = spi_context_wait_for_completion(&data->ctx);
236 out:
237 	spi_context_release(&data->ctx, ret);
238 
239 	return ret;
240 }
241 
spi_mcux_transceive(const struct device * dev,const struct spi_config * spi_cfg,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs)242 static int spi_mcux_transceive(const struct device *dev,
243 			       const struct spi_config *spi_cfg,
244 			       const struct spi_buf_set *tx_bufs,
245 			       const struct spi_buf_set *rx_bufs)
246 {
247 	return transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL);
248 }
249 
250 #ifdef CONFIG_SPI_ASYNC
spi_mcux_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)251 static int spi_mcux_transceive_async(const struct device *dev,
252 				     const struct spi_config *spi_cfg,
253 				     const struct spi_buf_set *tx_bufs,
254 				     const struct spi_buf_set *rx_bufs,
255 				     spi_callback_t cb,
256 				     void *userdata)
257 {
258 	return transceive(dev, spi_cfg, tx_bufs, rx_bufs, true, cb, userdata);
259 }
260 #endif /* CONFIG_SPI_ASYNC */
261 
spi_mcux_release(const struct device * dev,const struct spi_config * spi_cfg)262 static int spi_mcux_release(const struct device *dev,
263 			    const struct spi_config *spi_cfg)
264 {
265 	struct spi_mcux_data *data = dev->data;
266 
267 	spi_context_unlock_unconditionally(&data->ctx);
268 
269 	return 0;
270 }
271 
spi_mcux_init(const struct device * dev)272 static int spi_mcux_init(const struct device *dev)
273 {
274 	int err;
275 	const struct spi_mcux_config *config = dev->config;
276 	struct spi_mcux_data *data = dev->data;
277 
278 	CLOCK_SetIpSrc(config->clock_ip_name, config->clock_ip_src);
279 
280 	config->irq_config_func(dev);
281 
282 	data->dev = dev;
283 
284 	err = spi_context_cs_configure_all(&data->ctx);
285 	if (err < 0) {
286 		return err;
287 	}
288 
289 	err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
290 	if (err != 0) {
291 		return err;
292 	}
293 
294 	spi_context_unlock_unconditionally(&data->ctx);
295 
296 	return 0;
297 }
298 
299 static const struct spi_driver_api spi_mcux_driver_api = {
300 	.transceive = spi_mcux_transceive,
301 #ifdef CONFIG_SPI_ASYNC
302 	.transceive_async = spi_mcux_transceive_async,
303 #endif
304 	.release = spi_mcux_release,
305 };
306 
307 #define SPI_RV32M1_INIT(n)						\
308 	PINCTRL_DT_INST_DEFINE(n);					\
309 									\
310 	static void spi_mcux_config_func_##n(const struct device *dev);	\
311 									\
312 	static const struct spi_mcux_config spi_mcux_config_##n = {	\
313 		.base = (LPSPI_Type *) DT_INST_REG_ADDR(n),		\
314 		.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)),	\
315 		.clock_subsys = (clock_control_subsys_t)		\
316 			DT_INST_CLOCKS_CELL(n, name),			\
317 		.irq_config_func = spi_mcux_config_func_##n,		\
318 		.clock_ip_name = INST_DT_CLOCK_IP_NAME(n),		\
319 		.clock_ip_src  = kCLOCK_IpSrcFircAsync,			\
320 		.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),		\
321 	};								\
322 									\
323 	static struct spi_mcux_data spi_mcux_data_##n = {		\
324 		SPI_CONTEXT_INIT_LOCK(spi_mcux_data_##n, ctx),		\
325 		SPI_CONTEXT_INIT_SYNC(spi_mcux_data_##n, ctx),		\
326 		SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx)	\
327 	};								\
328 									\
329 	DEVICE_DT_INST_DEFINE(n, &spi_mcux_init, NULL,			\
330 			    &spi_mcux_data_##n,				\
331 			    &spi_mcux_config_##n,			\
332 			    POST_KERNEL,				\
333 			    CONFIG_SPI_INIT_PRIORITY,			\
334 			    &spi_mcux_driver_api);			\
335 									\
336 	static void spi_mcux_config_func_##n(const struct device *dev)	\
337 	{								\
338 		IRQ_CONNECT(DT_INST_IRQN(n),				\
339 			    0,						\
340 			    spi_mcux_isr, DEVICE_DT_INST_GET(n), 0);	\
341 		irq_enable(DT_INST_IRQN(n));				\
342 	}
343 
344 DT_INST_FOREACH_STATUS_OKAY(SPI_RV32M1_INIT)
345