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