1 /*
2  * Copyright 2023 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_lcdic
8 
9 #include <zephyr/drivers/mipi_dbi.h>
10 #include <zephyr/drivers/pinctrl.h>
11 #include <zephyr/drivers/clock_control.h>
12 #include <zephyr/drivers/spi.h>
13 #include <zephyr/drivers/dma.h>
14 #include <zephyr/logging/log.h>
15 #include <soc.h>
16 #include <zephyr/drivers/dma/dma_mcux_lpc.h>
17 LOG_MODULE_REGISTER(mipi_dbi_lcdic, CONFIG_MIPI_DBI_LOG_LEVEL);
18 
19 #include <fsl_inputmux.h>
20 
21 enum lcdic_data_fmt {
22 	LCDIC_DATA_FMT_BYTE = 0,
23 	LCDIC_DATA_FMT_HALFWORD = 1, /* 2 byte */
24 	LCDIC_DATA_FMT_WORD = 2, /* 4 byte */
25 };
26 
27 enum lcdic_cmd_dc {
28 	LCDIC_COMMAND = 0,
29 	LCDIC_DATA = 1,
30 };
31 
32 enum lcdic_cmd_type {
33 	LCDIC_RX = 0,
34 	LCDIC_TX = 1,
35 };
36 
37 enum lcdic_cmd_te {
38 	LCDIC_TE_NO_SYNC = 0,
39 	LCDIC_TE_RISING_EDGE = 1,
40 	LCDIC_TE_FALLING_EDGE = 2,
41 };
42 
43 /* Limit imposed by size of data length field in LCDIC command */
44 #define LCDIC_MAX_XFER 0x40000
45 /* Max reset width (in terms of Timer0_Period, see RST_CTRL register) */
46 #define LCDIC_MAX_RST_WIDTH 0x3F
47 /* Max reset pulse count */
48 #define LCDIC_MAX_RST_PULSE_COUNT 0x7
49 
50 /* Descriptor for LCDIC command */
51 union lcdic_trx_cmd {
52 	struct {
53 		/* Data length in bytes. LCDIC transfers data_len + 1 */
54 		uint32_t data_len: 18;
55 		/* Dummy SCLK cycles between TX and RX (for SPI mode) */
56 		uint32_t dummy_count: 3;
57 		uint32_t rsvd: 2;
58 		/* Use auto repeat mode */
59 		uint32_t auto_repeat: 1;
60 		/* Tearing enable sync mode */
61 		uint32_t te_sync_mode: 2;
62 		/* TRX command timeout mode */
63 		uint32_t trx_timeout_mode: 1;
64 		/* Data format, see lcdic_data_fmt */
65 		uint32_t data_format: 2;
66 		/* Enable command done interrupt */
67 		uint32_t cmd_done_int: 1;
68 		/* LCD command or LCD data, see lcdic_cmd_dc */
69 		uint32_t cmd_data: 1;
70 		/* TX or RX command, see lcdic_cmd_type */
71 		uint32_t trx: 1;
72 	} bits;
73 	uint32_t u32;
74 };
75 
76 struct mipi_dbi_lcdic_config {
77 	LCDIC_Type *base;
78 	void (*irq_config_func)(const struct device *dev);
79 	const struct pinctrl_dev_config *pincfg;
80 	const struct device *clock_dev;
81 	clock_control_subsys_t clock_subsys;
82 	bool swap_bytes;
83 	uint8_t write_active_min;
84 	uint8_t write_inactive_min;
85 	uint8_t timer0_ratio;
86 	uint8_t timer1_ratio;
87 };
88 
89 #ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
90 struct stream {
91 	const struct device *dma_dev;
92 	uint32_t channel;
93 	struct dma_config dma_cfg;
94 	struct dma_block_config blk_cfg[2];
95 };
96 #endif
97 
98 struct mipi_dbi_lcdic_data {
99 	/* Tracks number of bytes remaining in command */
100 	uint32_t cmd_bytes;
101 	/* Tracks number of bytes remaining in transfer */
102 	uint32_t xfer_bytes;
103 	/* Tracks start of transfer buffer */
104 	const uint8_t *xfer_buf;
105 	/* When sending data that does not evenly fit into 4 byte chunks,
106 	 * this is used to store the last unaligned segment of the data.
107 	 */
108 	uint32_t unaligned_word __aligned(4);
109 	/* Tracks lcdic_data_fmt value we should use for pixel data */
110 	uint8_t pixel_fmt;
111 	/* Tracks TE edge setting we should use for pixel data */
112 	uint8_t te_edge;
113 	/* Are we starting a new display frame */
114 	bool new_frame;
115 	const struct mipi_dbi_config *active_cfg;
116 	struct k_sem xfer_sem;
117 	struct k_sem lock;
118 #ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
119 	struct stream dma_stream;
120 #endif
121 };
122 
123 #define LCDIC_ALL_INTERRUPTS \
124 	(LCDIC_ICR_RFIFO_THRES_INTR_CLR_MASK | \
125 	LCDIC_ICR_RFIFO_UNDERFLOW_INTR_CLR_MASK | \
126 	LCDIC_ICR_TFIFO_THRES_INTR_CLR_MASK | \
127 	LCDIC_ICR_TFIFO_OVERFLOW_INTR_CLR_MASK | \
128 	LCDIC_ICR_TE_TO_INTR_CLR_MASK | \
129 	LCDIC_ICR_CMD_TO_INTR_CLR_MASK | \
130 	LCDIC_ICR_CMD_DONE_INTR_CLR_MASK | \
131 	LCDIC_ICR_RST_DONE_INTR_CLR_MASK)
132 
133 /* RX and TX FIFO thresholds */
134 #ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
135 #define LCDIC_RX_FIFO_THRESH 0x0
136 #define LCDIC_TX_FIFO_THRESH 0x0
137 #else
138 #define LCDIC_RX_FIFO_THRESH 0x0
139 #define LCDIC_TX_FIFO_THRESH 0x3
140 #endif
141 
142 /* After LCDIC is enabled or disabled, there should be a wait longer than
143  * 5x the module clock before other registers are read
144  */
mipi_dbi_lcdic_reset_delay(void)145 static inline void mipi_dbi_lcdic_reset_delay(void)
146 {
147 	k_busy_wait(1);
148 }
149 
150 /* Resets state of the LCDIC TX/RX FIFO */
mipi_dbi_lcdic_reset_state(const struct device * dev)151 static inline void mipi_dbi_lcdic_reset_state(const struct device *dev)
152 {
153 	const struct mipi_dbi_lcdic_config *config = dev->config;
154 	LCDIC_Type *base = config->base;
155 
156 	base->CTRL &= ~LCDIC_CTRL_LCDIC_EN_MASK;
157 	mipi_dbi_lcdic_reset_delay();
158 	base->CTRL |= LCDIC_CTRL_LCDIC_EN_MASK;
159 	mipi_dbi_lcdic_reset_delay();
160 }
161 
162 
163 #ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
164 
165 /* Start DMA to send data using LCDIC TX FIFO */
mipi_dbi_lcdic_start_dma(const struct device * dev)166 static int mipi_dbi_lcdic_start_dma(const struct device *dev)
167 {
168 	const struct mipi_dbi_lcdic_config *config = dev->config;
169 	struct mipi_dbi_lcdic_data *data = dev->data;
170 	struct stream *stream = &data->dma_stream;
171 	uint32_t aligned_len = data->cmd_bytes & (~0x3);
172 	uint32_t unaligned_len = data->cmd_bytes & 0x3;
173 	int ret;
174 
175 	stream->dma_cfg.head_block = &stream->blk_cfg[0];
176 	if (aligned_len == 0) {
177 		/* Only unaligned data exists, send it in the first block */
178 		/* First DMA block configuration is used to send aligned data */
179 		stream->blk_cfg[0].source_address = (uint32_t)&data->unaligned_word;
180 		stream->blk_cfg[0].dest_address = (uint32_t)&config->base->TFIFO_WDATA;
181 		/* Block size should be the aligned portion of the transfer */
182 		stream->blk_cfg[0].block_size = sizeof(uint32_t);
183 		stream->dma_cfg.block_count = 1;
184 		stream->blk_cfg[0].next_block = NULL;
185 	} else {
186 		/* First DMA block configuration is used to send aligned data */
187 		stream->blk_cfg[0].source_address = (uint32_t)data->xfer_buf;
188 		stream->blk_cfg[0].dest_address = (uint32_t)&config->base->TFIFO_WDATA;
189 		/* Block size should be the aligned portion of the transfer */
190 		stream->blk_cfg[0].block_size = aligned_len;
191 		/* Second DMA block configuration sends unaligned block */
192 		if (unaligned_len) {
193 			stream->dma_cfg.block_count = 2;
194 			stream->blk_cfg[0].next_block =
195 						&stream->blk_cfg[1];
196 			stream->blk_cfg[1].source_address =
197 				(uint32_t)&data->unaligned_word;
198 			stream->blk_cfg[1].dest_address =
199 				(uint32_t)&config->base->TFIFO_WDATA;
200 			stream->blk_cfg[1].block_size = sizeof(uint32_t);
201 		} else {
202 			stream->dma_cfg.block_count = 1;
203 			stream->blk_cfg[0].next_block = NULL;
204 		}
205 	}
206 
207 	ret = dma_config(stream->dma_dev, stream->channel, &stream->dma_cfg);
208 	if (ret) {
209 		return ret;
210 	}
211 	/* Enable DMA channel before we set up DMA request. This way,
212 	 * the hardware DMA trigger does not fire until the DMA
213 	 * start function has initialized the DMA.
214 	 */
215 	ret = dma_start(stream->dma_dev, stream->channel);
216 	if (ret) {
217 		return ret;
218 	}
219 	/* Enable DMA request */
220 	config->base->CTRL |= LCDIC_CTRL_DMA_EN_MASK;
221 	return ret;
222 }
223 
224 /* DMA completion callback */
mipi_dbi_lcdic_dma_callback(const struct device * dma_dev,void * user_data,uint32_t channel,int status)225 static void mipi_dbi_lcdic_dma_callback(const struct device *dma_dev,
226 	     void *user_data, uint32_t channel, int status)
227 {
228 	if (status < 0) {
229 		LOG_ERR("DMA callback with error %d", status);
230 	}
231 }
232 
233 #endif /* CONFIG_MIPI_DBI_NXP_LCDIC_DMA */
234 
235 /* Configure LCDIC */
mipi_dbi_lcdic_configure(const struct device * dev,const struct mipi_dbi_config * dbi_config)236 static int mipi_dbi_lcdic_configure(const struct device *dev,
237 				    const struct mipi_dbi_config  *dbi_config)
238 {
239 	const struct mipi_dbi_lcdic_config *config = dev->config;
240 	struct mipi_dbi_lcdic_data *data = dev->data;
241 	const struct spi_config *spi_cfg = &dbi_config->config;
242 	LCDIC_Type *base = config->base;
243 	int ret;
244 	uint32_t reg;
245 
246 	if (dbi_config == data->active_cfg) {
247 		return 0;
248 	}
249 
250 	/* Clear all interrupt flags */
251 	base->ICR = LCDIC_ALL_INTERRUPTS;
252 	/* Mask all interrupts */
253 	base->IMR = LCDIC_ALL_INTERRUPTS;
254 
255 	/* Set LCDIC clock frequency */
256 	ret = clock_control_set_rate(config->clock_dev, config->clock_subsys,
257 			(clock_control_subsys_rate_t)spi_cfg->frequency);
258 	if (ret) {
259 		LOG_ERR("Invalid clock frequency %d", spi_cfg->frequency);
260 		return ret;
261 	}
262 	if (spi_cfg->slave != 0) {
263 		/* Only one slave select line */
264 		return -ENOTSUP;
265 	}
266 	if (SPI_WORD_SIZE_GET(spi_cfg->operation) > 8) {
267 		LOG_ERR("Unsupported word size");
268 		return -ENOTSUP;
269 	}
270 
271 	reg = base->CTRL;
272 	/* Disable LCD module during configuration */
273 	reg &= ~LCDIC_CTRL_LCDIC_EN_MASK;
274 	if (dbi_config->mode == MIPI_DBI_MODE_8080_BUS_8_BIT) {
275 		/* Enable 8080 Mode */
276 		reg |= LCDIC_CTRL_LCDIC_MD_MASK;
277 	} else if (dbi_config->mode == MIPI_DBI_MODE_SPI_4WIRE) {
278 		/* Select SPI 4 wire mode */
279 		reg |= LCDIC_CTRL_SPI_MD_MASK;
280 		reg &= ~LCDIC_CTRL_LCDIC_MD_MASK;
281 	} else if (dbi_config->mode == MIPI_DBI_MODE_SPI_3WIRE) {
282 		/* Select SPI 3 wire mode */
283 		reg &= ~(LCDIC_CTRL_LCDIC_MD_MASK |
284 			 LCDIC_CTRL_SPI_MD_MASK);
285 	} else {
286 		/* Unsupported mode */
287 		return -ENOTSUP;
288 	}
289 	/* If using SPI mode, validate that half-duplex was requested */
290 	if ((!(reg & LCDIC_CTRL_LCDIC_MD_MASK)) &&
291 	    (!(spi_cfg->operation & SPI_HALF_DUPLEX))) {
292 		LOG_ERR("LCDIC only supports half duplex operation");
293 		return -ENOTSUP;
294 	}
295 	/* Enable byte swapping if user requested it */
296 	reg = (reg & ~LCDIC_CTRL_DAT_ENDIAN_MASK) |
297 		LCDIC_CTRL_DAT_ENDIAN(!config->swap_bytes);
298 	/* Disable DMA */
299 	reg &= ~LCDIC_CTRL_DMA_EN_MASK;
300 	base->CTRL = reg;
301 	mipi_dbi_lcdic_reset_delay();
302 
303 	/* Setup SPI CPOL and CPHA selections */
304 	reg = base->SPI_CTRL;
305 	reg = (reg & ~LCDIC_SPI_CTRL_SDAT_ENDIAN_MASK) |
306 		LCDIC_SPI_CTRL_SDAT_ENDIAN((spi_cfg->operation &
307 					    SPI_TRANSFER_LSB) ? 1 : 0);
308 	reg = (reg & ~LCDIC_SPI_CTRL_CPHA_MASK) |
309 		LCDIC_SPI_CTRL_CPHA((spi_cfg->operation & SPI_MODE_CPHA) ? 1 : 0);
310 	reg = (reg & ~LCDIC_SPI_CTRL_CPOL_MASK) |
311 		LCDIC_SPI_CTRL_CPOL((spi_cfg->operation & SPI_MODE_CPOL) ? 1 : 0);
312 	base->SPI_CTRL = reg;
313 
314 	/*
315 	 * Set 8080 control based on module properties. TRIW and TRAW are
316 	 * set to their reset values
317 	 */
318 	base->I8080_CTRL1 = LCDIC_I8080_CTRL1_TRIW(0xf) |
319 			LCDIC_I8080_CTRL1_TRAW(0xf) |
320 			LCDIC_I8080_CTRL1_TWIW(config->write_inactive_min) |
321 			LCDIC_I8080_CTRL1_TWAW(config->write_active_min);
322 
323 	/* Enable the module */
324 	base->CTRL |= LCDIC_CTRL_LCDIC_EN_MASK;
325 	mipi_dbi_lcdic_reset_delay();
326 
327 	data->active_cfg = dbi_config;
328 
329 	return 0;
330 }
331 
332 /* Gets unaligned word data from array. Return value will be a 4 byte
333  * value containing the last unaligned section of the array data
334  */
mipi_dbi_lcdic_get_unaligned(const uint8_t * bytes,uint32_t buf_len)335 static uint32_t mipi_dbi_lcdic_get_unaligned(const uint8_t *bytes,
336 					     uint32_t buf_len)
337 {
338 	uint32_t word = 0U;
339 	uint8_t unaligned_len = buf_len & 0x3;
340 	uint32_t aligned_len = buf_len - unaligned_len;
341 
342 	while ((unaligned_len--)) {
343 		word <<= 8U;
344 		word |= bytes[aligned_len + unaligned_len];
345 	}
346 	return word;
347 }
348 
349 /* Fills the TX fifo with data. Returns number of bytes written. */
mipi_dbi_lcdic_fill_tx(LCDIC_Type * base,const uint8_t * buf,uint32_t buf_len,uint32_t last_word)350 static int mipi_dbi_lcdic_fill_tx(LCDIC_Type *base, const uint8_t *buf,
351 				  uint32_t buf_len, uint32_t last_word)
352 {
353 	uint32_t *word_buf = (uint32_t *)buf;
354 	uint32_t bytes_written = 0U;
355 	uint32_t write_len;
356 
357 	/* TX FIFO consumes 4 bytes on each write, so we can write up
358 	 * to buf_len / 4 times before we send all data.
359 	 * Write to FIFO it overflows or we send entire buffer.
360 	 */
361 	while (buf_len) {
362 		if (buf_len < 4) {
363 			/* Send last bytes */
364 			base->TFIFO_WDATA = last_word;
365 			write_len = buf_len;
366 		} else {
367 			/* Otherwise, write one word */
368 			base->TFIFO_WDATA = word_buf[bytes_written >> 2];
369 			write_len = 4;
370 		}
371 		if (base->IRSR & LCDIC_IRSR_TFIFO_OVERFLOW_RAW_INTR_MASK) {
372 			/* TX FIFO has overflowed, last word write did not
373 			 * complete. Return current number of bytes written.
374 			 */
375 			base->ICR |= LCDIC_ICR_TFIFO_OVERFLOW_INTR_CLR_MASK;
376 			return bytes_written;
377 		}
378 		bytes_written += write_len;
379 		buf_len -= write_len;
380 	}
381 	return bytes_written;
382 }
383 
384 /* Writes command word */
mipi_dbi_lcdic_set_cmd(LCDIC_Type * base,enum lcdic_cmd_type dir,enum lcdic_cmd_dc dc,enum lcdic_data_fmt data_fmt,enum lcdic_cmd_te te_sync,uint32_t buf_len)385 static void mipi_dbi_lcdic_set_cmd(LCDIC_Type *base,
386 				   enum lcdic_cmd_type dir,
387 				   enum lcdic_cmd_dc dc,
388 				   enum lcdic_data_fmt data_fmt,
389 				   enum lcdic_cmd_te te_sync,
390 				   uint32_t buf_len)
391 {
392 	union lcdic_trx_cmd cmd = {0};
393 
394 
395 	/* TX FIFO will be clear, write command word */
396 	cmd.bits.data_len = buf_len - 1;
397 	cmd.bits.cmd_data = dc;
398 	cmd.bits.trx = dir;
399 	cmd.bits.cmd_done_int = true;
400 	cmd.bits.data_format = data_fmt;
401 	cmd.bits.te_sync_mode = te_sync;
402 	/* Write command */
403 	base->TFIFO_WDATA = cmd.u32;
404 }
405 
mipi_dbi_lcdic_write_display(const struct device * dev,const struct mipi_dbi_config * dbi_config,const uint8_t * framebuf,struct display_buffer_descriptor * desc,enum display_pixel_format pixfmt)406 static int mipi_dbi_lcdic_write_display(const struct device *dev,
407 					const struct mipi_dbi_config *dbi_config,
408 					const uint8_t *framebuf,
409 					struct display_buffer_descriptor *desc,
410 					enum display_pixel_format pixfmt)
411 {
412 	const struct mipi_dbi_lcdic_config *config = dev->config;
413 	struct mipi_dbi_lcdic_data *dev_data = dev->data;
414 	LCDIC_Type *base = config->base;
415 	int ret;
416 	enum lcdic_cmd_te te_sync = LCDIC_TE_NO_SYNC;
417 	uint32_t interrupts = 0U;
418 
419 	ret = k_sem_take(&dev_data->lock, K_FOREVER);
420 	if (ret) {
421 		goto out;
422 	}
423 
424 	ret = mipi_dbi_lcdic_configure(dev, dbi_config);
425 	if (ret) {
426 		goto out;
427 	}
428 
429 	if (dev_data->new_frame) {
430 		switch (dev_data->te_edge) {
431 		case MIPI_DBI_TE_RISING_EDGE:
432 			te_sync = LCDIC_TE_RISING_EDGE;
433 			break;
434 		case MIPI_DBI_TE_FALLING_EDGE:
435 			te_sync = LCDIC_TE_FALLING_EDGE;
436 			break;
437 		default:
438 			te_sync = LCDIC_TE_NO_SYNC;
439 			break;
440 		}
441 		dev_data->new_frame = false;
442 	}
443 
444 	if (!desc->frame_incomplete) {
445 		/* Next frame will be a new one */
446 		dev_data->new_frame = true;
447 	}
448 
449 	/* State reset is required before transfer */
450 	mipi_dbi_lcdic_reset_state(dev);
451 
452 	if (desc->buf_size != 0) {
453 		dev_data->xfer_bytes = desc->buf_size;
454 		/* Cap command to max transfer size */
455 		dev_data->cmd_bytes = MIN(desc->buf_size, LCDIC_MAX_XFER);
456 		dev_data->xfer_buf = framebuf;
457 		/* If the length of the transfer is not divisible by
458 		 * 4, save the unaligned portion of the transfer into
459 		 * a temporary buffer
460 		 */
461 		if (dev_data->cmd_bytes & 0x3) {
462 			dev_data->unaligned_word = mipi_dbi_lcdic_get_unaligned(
463 							dev_data->xfer_buf,
464 							dev_data->cmd_bytes);
465 		}
466 
467 		/* Save pixel format */
468 		if (DISPLAY_BITS_PER_PIXEL(pixfmt) == 32) {
469 			dev_data->pixel_fmt = LCDIC_DATA_FMT_WORD;
470 		} else if (DISPLAY_BITS_PER_PIXEL(pixfmt) == 16) {
471 			dev_data->pixel_fmt = LCDIC_DATA_FMT_HALFWORD;
472 		} else if (DISPLAY_BITS_PER_PIXEL(pixfmt) == 8) {
473 			dev_data->pixel_fmt = LCDIC_DATA_FMT_BYTE;
474 		} else {
475 			if (config->swap_bytes) {
476 				LOG_WRN("Unsupported pixel format, byte swapping disabled");
477 			}
478 		}
479 		/* Use pixel format data width, so we can byte swap
480 		 * if needed
481 		 */
482 		mipi_dbi_lcdic_set_cmd(base, LCDIC_TX, LCDIC_DATA,
483 				       dev_data->pixel_fmt,
484 				       te_sync,
485 				       dev_data->cmd_bytes);
486 #ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
487 		/* Enable command complete interrupt */
488 		interrupts |= LCDIC_IMR_CMD_DONE_INTR_MSK_MASK;
489 		/* Write interrupt mask */
490 		base->IMR &= ~interrupts;
491 		/* Configure DMA to send data */
492 		ret = mipi_dbi_lcdic_start_dma(dev);
493 		if (ret) {
494 			LOG_ERR("Could not start DMA (%d)", ret);
495 			goto out;
496 		}
497 #else
498 		/* Enable TX FIFO threshold interrupt. This interrupt
499 		 * should fire once enabled, which will kick off
500 		 * the transfer
501 		 */
502 		interrupts |= LCDIC_IMR_TFIFO_THRES_INTR_MSK_MASK;
503 		/* Enable command complete interrupt */
504 		interrupts |= LCDIC_IMR_CMD_DONE_INTR_MSK_MASK;
505 		/* Write interrupt mask */
506 		base->IMR &= ~interrupts;
507 #endif
508 		ret = k_sem_take(&dev_data->xfer_sem, K_FOREVER);
509 	}
510 out:
511 	k_sem_give(&dev_data->lock);
512 	return ret;
513 
514 }
515 
mipi_dbi_lcdic_write_cmd(const struct device * dev,const struct mipi_dbi_config * dbi_config,uint8_t cmd,const uint8_t * data,size_t data_len)516 static int mipi_dbi_lcdic_write_cmd(const struct device *dev,
517 				    const struct mipi_dbi_config *dbi_config,
518 				    uint8_t cmd,
519 				    const uint8_t *data,
520 				    size_t data_len)
521 {
522 	const struct mipi_dbi_lcdic_config *config = dev->config;
523 	struct mipi_dbi_lcdic_data *dev_data = dev->data;
524 	LCDIC_Type *base = config->base;
525 	int ret;
526 	uint32_t interrupts = 0U;
527 
528 	ret = k_sem_take(&dev_data->lock, K_FOREVER);
529 	if (ret) {
530 		goto out;
531 	}
532 
533 	ret = mipi_dbi_lcdic_configure(dev, dbi_config);
534 	if (ret) {
535 		goto out;
536 	}
537 
538 	/* State reset is required before transfer */
539 	mipi_dbi_lcdic_reset_state(dev);
540 
541 	/* Write command */
542 	mipi_dbi_lcdic_set_cmd(base, LCDIC_TX, LCDIC_COMMAND,
543 			       LCDIC_DATA_FMT_BYTE, LCDIC_TE_NO_SYNC, 1);
544 	/* Use standard byte writes */
545 	dev_data->pixel_fmt = LCDIC_DATA_FMT_BYTE;
546 	base->TFIFO_WDATA = cmd;
547 	/* Wait for command completion */
548 	while ((base->IRSR & LCDIC_IRSR_CMD_DONE_RAW_INTR_MASK) == 0) {
549 		/* Spin */
550 	}
551 	base->ICR |= LCDIC_ICR_CMD_DONE_INTR_CLR_MASK;
552 
553 	if (data_len != 0) {
554 		dev_data->xfer_bytes = data_len;
555 		/* Cap command to max transfer size */
556 		dev_data->cmd_bytes = MIN(data_len, LCDIC_MAX_XFER);
557 		dev_data->xfer_buf = data;
558 		/* If the length of the transfer is not divisible by
559 		 * 4, save the unaligned portion of the transfer into
560 		 * a temporary buffer
561 		 */
562 		if (dev_data->cmd_bytes & 0x3) {
563 			dev_data->unaligned_word = mipi_dbi_lcdic_get_unaligned(
564 							dev_data->xfer_buf,
565 							dev_data->cmd_bytes);
566 		}
567 		mipi_dbi_lcdic_set_cmd(base, LCDIC_TX, LCDIC_DATA,
568 				       LCDIC_DATA_FMT_BYTE,
569 				       LCDIC_TE_NO_SYNC,
570 				       dev_data->cmd_bytes);
571 #ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
572 		if (((((uint32_t)dev_data->xfer_buf) & 0x3) == 0) ||
573 		    (dev_data->cmd_bytes < 4)) {
574 			/* Data is aligned, we can use DMA */
575 			/* Enable command complete interrupt */
576 			interrupts |= LCDIC_IMR_CMD_DONE_INTR_MSK_MASK;
577 			/* Write interrupt mask */
578 			base->IMR &= ~interrupts;
579 			/* Configure DMA to send data */
580 			ret = mipi_dbi_lcdic_start_dma(dev);
581 			if (ret) {
582 				LOG_ERR("Could not start DMA (%d)", ret);
583 				goto out;
584 			}
585 		} else /* Data is not aligned */
586 #endif
587 		{
588 			/* Enable TX FIFO threshold interrupt. This interrupt
589 			 * should fire once enabled, which will kick off
590 			 * the transfer
591 			 */
592 			interrupts |= LCDIC_IMR_TFIFO_THRES_INTR_MSK_MASK;
593 			/* Enable command complete interrupt */
594 			interrupts |= LCDIC_IMR_CMD_DONE_INTR_MSK_MASK;
595 			/* Write interrupt mask */
596 			base->IMR &= ~interrupts;
597 		}
598 		ret = k_sem_take(&dev_data->xfer_sem, K_FOREVER);
599 	}
600 out:
601 	k_sem_give(&dev_data->lock);
602 	return ret;
603 }
604 
mipi_dbi_lcdic_reset(const struct device * dev,k_timeout_t delay)605 static int mipi_dbi_lcdic_reset(const struct device *dev, k_timeout_t delay)
606 {
607 	const struct mipi_dbi_lcdic_config *config = dev->config;
608 	LCDIC_Type *base = config->base;
609 	uint32_t lcdic_freq;
610 	uint32_t delay_ms = k_ticks_to_ms_ceil32(delay.ticks);
611 	uint32_t rst_width, pulse_cnt;
612 
613 	/* Calculate delay based off timer0 ratio. Formula given
614 	 * by RM is as follows:
615 	 * Reset pulse width = (RST_WIDTH + 1) * Timer0_Period
616 	 * Timer0_Period = 2^(TIMER_RATIO0) / LCDIC_Clock_Freq
617 	 */
618 	if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
619 				   &lcdic_freq)) {
620 		return -EIO;
621 	}
622 	rst_width = (delay_ms * (lcdic_freq)) / ((1 << config->timer0_ratio) * MSEC_PER_SEC);
623 	/* If rst_width is larger than max value supported by hardware,
624 	 * increase the pulse count (rounding up)
625 	 */
626 	pulse_cnt = ((rst_width + (LCDIC_MAX_RST_WIDTH - 1)) / LCDIC_MAX_RST_WIDTH);
627 	rst_width = MIN(LCDIC_MAX_RST_WIDTH, rst_width);
628 
629 	if ((pulse_cnt - 1) > LCDIC_MAX_RST_PULSE_COUNT) {
630 		/* Still issue reset pulse, but warn user */
631 		LOG_WRN("Reset pulse is too long for configured timer0 ratio");
632 		pulse_cnt = LCDIC_MAX_RST_PULSE_COUNT + 1;
633 	}
634 
635 	/* Start the reset signal */
636 	base->RST_CTRL = LCDIC_RST_CTRL_RST_WIDTH(rst_width - 1) |
637 			LCDIC_RST_CTRL_RST_SEQ_NUM(pulse_cnt - 1) |
638 			LCDIC_RST_CTRL_RST_START_MASK;
639 	/* Wait for reset to complete */
640 	while ((base->IRSR & LCDIC_IRSR_RST_DONE_RAW_INTR_MASK) == 0) {
641 		/* Spin */
642 	}
643 	base->ICR |= LCDIC_ICR_RST_DONE_INTR_CLR_MASK;
644 	return 0;
645 }
646 
mipi_dbi_lcdic_configure_te(const struct device * dev,uint8_t edge,k_timeout_t delay)647 static int mipi_dbi_lcdic_configure_te(const struct device *dev,
648 				       uint8_t edge,
649 				       k_timeout_t delay)
650 {
651 	const struct mipi_dbi_lcdic_config *config = dev->config;
652 	LCDIC_Type *base = config->base;
653 	struct mipi_dbi_lcdic_data *data = dev->data;
654 	uint32_t lcdic_freq, ttew, reg;
655 	uint32_t delay_us = k_ticks_to_us_ceil32(delay.ticks);
656 
657 	/* Calculate delay based off timer0 ratio. Formula given
658 	 * by RM is as follows:
659 	 * TE delay = Timer1_Period * ttew
660 	 * Timer1_Period = 2^(TIMER_RATIO1) * Timer0_Period
661 	 * Timer0_Period = 2^(TIMER_RATIO0) / LCDIC_Clock_Freq
662 	 */
663 	if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
664 				   &lcdic_freq)) {
665 		return -EIO;
666 	}
667 
668 	/*
669 	 * Calculate TTEW. Done in multiple steps to avoid overflowing
670 	 * the uint32_t type. Full formula is:
671 	 * (lcdic_freq * delay_us) /
672 	 *     ((2 ^ (TIMER_RATIO1 + TIMER_RATIO0)) * USEC_PER_SEC)
673 	 */
674 	ttew = lcdic_freq / (1 << config->timer0_ratio);
675 	ttew *= delay_us;
676 	ttew /= (1 << config->timer1_ratio);
677 	ttew /= USEC_PER_SEC;
678 
679 	/* Check to see if the delay is shorter than we can support */
680 	if ((ttew == 0)  && (delay_us != 0)) {
681 		LOG_ERR("Timer ratios too large to support this TE delay");
682 		return -ENOTSUP;
683 	}
684 	reg = base->TE_CTRL;
685 	reg &= ~LCDIC_TE_CTRL_TTEW_MASK;
686 	reg |= LCDIC_TE_CTRL_TTEW(ttew);
687 	base->TE_CTRL = reg;
688 	data->te_edge = edge;
689 	return 0;
690 }
691 
692 
693 /* Initializes LCDIC peripheral */
mipi_dbi_lcdic_init(const struct device * dev)694 static int mipi_dbi_lcdic_init(const struct device *dev)
695 {
696 	const struct mipi_dbi_lcdic_config *config = dev->config;
697 	struct mipi_dbi_lcdic_data *data = dev->data;
698 	LCDIC_Type *base = config->base;
699 	int ret;
700 
701 	ret = clock_control_on(config->clock_dev, config->clock_subsys);
702 	if (ret) {
703 		return ret;
704 	}
705 
706 	/* Set initial clock rate of 10 MHz */
707 	ret = clock_control_set_rate(config->clock_dev, config->clock_subsys,
708 			(clock_control_subsys_rate_t)MHZ(10));
709 	if (ret) {
710 		return ret;
711 	}
712 
713 	ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
714 	if (ret) {
715 		return ret;
716 	}
717 	ret = k_sem_init(&data->xfer_sem, 0, 1);
718 	if (ret) {
719 		return ret;
720 	}
721 	ret = k_sem_init(&data->lock, 1, 1);
722 	if (ret) {
723 		return ret;
724 	}
725 	/* Clear all interrupt flags */
726 	base->ICR = LCDIC_ALL_INTERRUPTS;
727 	/* Mask all interrupts */
728 	base->IMR = LCDIC_ALL_INTERRUPTS;
729 
730 	/* Enable interrupts */
731 	config->irq_config_func(dev);
732 
733 	/* Setup RX and TX fifo thresholds */
734 	base->FIFO_CTRL = LCDIC_FIFO_CTRL_RFIFO_THRES(LCDIC_RX_FIFO_THRESH) |
735 			LCDIC_FIFO_CTRL_TFIFO_THRES(LCDIC_TX_FIFO_THRESH);
736 	/* Disable command timeouts */
737 	base->TO_CTRL &= ~(LCDIC_TO_CTRL_CMD_LONG_TO_MASK |
738 			LCDIC_TO_CTRL_CMD_SHORT_TO_MASK);
739 
740 	/* Ensure LCDIC timer ratios are at reset values */
741 	base->TIMER_CTRL = LCDIC_TIMER_CTRL_TIMER_RATIO1(config->timer1_ratio) |
742 			LCDIC_TIMER_CTRL_TIMER_RATIO0(config->timer0_ratio);
743 
744 	data->te_edge = MIPI_DBI_TE_NO_EDGE;
745 
746 #ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
747 	/* Attach the LCDIC DMA request signal to the DMA channel we will
748 	 * use with hardware triggering.
749 	 */
750 	INPUTMUX_AttachSignal(INPUTMUX, data->dma_stream.channel,
751 			kINPUTMUX_LcdTxRegToDmaSingleToDma0);
752 	INPUTMUX_EnableSignal(INPUTMUX,
753 			kINPUTMUX_Dmac0InputTriggerLcdTxRegToDmaSingleEna, true);
754 #endif
755 
756 	return 0;
757 }
758 
759 static DEVICE_API(mipi_dbi, mipi_dbi_lcdic_driver_api) = {
760 	.command_write = mipi_dbi_lcdic_write_cmd,
761 	.write_display = mipi_dbi_lcdic_write_display,
762 	.configure_te = mipi_dbi_lcdic_configure_te,
763 	.reset = mipi_dbi_lcdic_reset,
764 };
765 
mipi_dbi_lcdic_isr(const struct device * dev)766 static void mipi_dbi_lcdic_isr(const struct device *dev)
767 {
768 	const struct mipi_dbi_lcdic_config *config = dev->config;
769 	struct mipi_dbi_lcdic_data *data = dev->data;
770 	LCDIC_Type *base = config->base;
771 	uint32_t bytes_written, isr_status;
772 
773 	isr_status = base->ISR;
774 	/* Clear pending interrupts */
775 	base->ICR |= isr_status;
776 
777 	if (isr_status & LCDIC_ISR_CMD_DONE_INTR_MASK) {
778 		if (config->base->CTRL & LCDIC_CTRL_DMA_EN_MASK) {
779 			/* DMA completed. Update buffer tracking data */
780 			data->xfer_bytes -= data->cmd_bytes;
781 			data->xfer_buf += data->cmd_bytes;
782 			/* Disable DMA request */
783 			config->base->CTRL &= ~LCDIC_CTRL_DMA_EN_MASK;
784 		}
785 		if (data->xfer_bytes == 0) {
786 			/* Disable interrupts */
787 			base->IMR |= LCDIC_ALL_INTERRUPTS;
788 			/* All data has been sent. */
789 			k_sem_give(&data->xfer_sem);
790 		} else {
791 			/* Command done. Queue next command */
792 			data->cmd_bytes = MIN(data->xfer_bytes, LCDIC_MAX_XFER);
793 			mipi_dbi_lcdic_set_cmd(base, LCDIC_TX, LCDIC_DATA,
794 					       data->pixel_fmt,
795 					       LCDIC_TE_NO_SYNC,
796 					       data->cmd_bytes);
797 			if (data->cmd_bytes & 0x3) {
798 				/* Save unaligned portion of transfer into
799 				 * a temporary buffer
800 				 */
801 				data->unaligned_word = mipi_dbi_lcdic_get_unaligned(
802 								data->xfer_buf,
803 								data->cmd_bytes);
804 			}
805 #ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
806 			if (((((uint32_t)data->xfer_buf) & 0x3) == 0) ||
807 			    (data->cmd_bytes < 4)) {
808 				/* Data is aligned. We can use DMA */
809 				mipi_dbi_lcdic_start_dma(dev);
810 			} else
811 #endif
812 			{
813 				/* We must refill the FIFO here in order to continue
814 				 * the next transfer, since the TX FIFO threshold
815 				 * interrupt may have already fired.
816 				 */
817 				bytes_written = mipi_dbi_lcdic_fill_tx(base, data->xfer_buf,
818 								       data->cmd_bytes,
819 								       data->unaligned_word);
820 				if (bytes_written > 0) {
821 					data->xfer_buf += bytes_written;
822 					data->cmd_bytes -= bytes_written;
823 					data->xfer_bytes -= bytes_written;
824 				}
825 			}
826 		}
827 	} else if (isr_status & LCDIC_ISR_TFIFO_THRES_INTR_MASK) {
828 		/* If command is not done, continue filling TX FIFO from
829 		 * current transfer buffer
830 		 */
831 		bytes_written = mipi_dbi_lcdic_fill_tx(base, data->xfer_buf,
832 						      data->cmd_bytes,
833 						      data->unaligned_word);
834 		if (bytes_written > 0) {
835 			data->xfer_buf += bytes_written;
836 			data->cmd_bytes -= bytes_written;
837 			data->xfer_bytes -= bytes_written;
838 		}
839 	}
840 }
841 
842 #ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA
843 #define LCDIC_DMA_CHANNELS(n)						\
844 	.dma_stream = {							\
845 		.dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR(n)),		\
846 		.channel = DT_INST_DMAS_CELL_BY_IDX(n, 0, channel),	\
847 		.dma_cfg = {						\
848 			.dma_slot = LPC_DMA_HWTRIG_EN |			\
849 				LPC_DMA_TRIGPOL_HIGH_RISING |		\
850 				LPC_DMA_TRIGBURST,			\
851 			.channel_direction = MEMORY_TO_PERIPHERAL,	\
852 			.dma_callback = mipi_dbi_lcdic_dma_callback,	\
853 			.source_data_size = 4,				\
854 			.dest_data_size = 4,				\
855 			.user_data = (void *)DEVICE_DT_INST_GET(n),	\
856 		},							\
857 	},
858 #else
859 #define LCDIC_DMA_CHANNELS(n)
860 #endif
861 
862 
863 #define MIPI_DBI_LCDIC_INIT(n)						\
864 	static void mipi_dbi_lcdic_config_func_##n(			\
865 			const struct device *dev)			\
866 	{								\
867 		IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority),	\
868 			    mipi_dbi_lcdic_isr,				\
869 			    DEVICE_DT_INST_GET(n), 0);			\
870 									\
871 		irq_enable(DT_INST_IRQN(n));				\
872 	}								\
873 									\
874 	PINCTRL_DT_INST_DEFINE(n);					\
875 	static const struct mipi_dbi_lcdic_config			\
876 	    mipi_dbi_lcdic_config_##n = {				\
877 		.base = (LCDIC_Type *)DT_INST_REG_ADDR(n),		\
878 		.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),		\
879 		.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)),	\
880 		.clock_subsys = (clock_control_subsys_t)		\
881 		    DT_INST_CLOCKS_CELL(n, name),			\
882 		.irq_config_func = mipi_dbi_lcdic_config_func_##n,	\
883 		.swap_bytes = DT_INST_PROP(n, nxp_swap_bytes),		\
884 		.write_active_min =					\
885 		    DT_INST_PROP(n, nxp_write_active_cycles),		\
886 		.write_inactive_min =					\
887 		    DT_INST_PROP(n, nxp_write_inactive_cycles),		\
888 		.timer0_ratio = DT_INST_PROP(n, nxp_timer0_ratio),      \
889 		.timer1_ratio = DT_INST_PROP(n, nxp_timer1_ratio),      \
890 	};								\
891 	static struct mipi_dbi_lcdic_data mipi_dbi_lcdic_data_##n = {	\
892 		LCDIC_DMA_CHANNELS(n)					\
893 	};								\
894 	DEVICE_DT_INST_DEFINE(n, mipi_dbi_lcdic_init, NULL,		\
895 			&mipi_dbi_lcdic_data_##n,			\
896 			&mipi_dbi_lcdic_config_##n,			\
897 			POST_KERNEL,					\
898 			CONFIG_MIPI_DBI_INIT_PRIORITY,			\
899 			&mipi_dbi_lcdic_driver_api);
900 
901 DT_INST_FOREACH_STATUS_OKAY(MIPI_DBI_LCDIC_INIT)
902