From 4065d848236e948b89591f88fd84b0f0ec53cd18 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 11 Nov 2024 20:18:29 +0000 Subject: [PATCH 1/2] drivers: mipi_dbi: mipi_dbi_nxp_lcdic: allow config of timer bases The NXP LCDIC peripheral contains two internal timers, with configurable periods. These times are used to determine delays within the peripheral, such as the reset and tearing enable signal delays. Allow these periods to be set within the devicetree for the peripheral. Raise the period where required for display drivers that need a value other than the reset setting Signed-off-by: Daniel DeGrasse --- .../rd_rw612_bga/dts/goworld_16880_lcm.overlay | 2 ++ .../boards/rd_rw612_bga.overlay | 2 ++ .../lcd_par_s035/boards/rd_rw612_bga.overlay | 2 ++ drivers/mipi_dbi/mipi_dbi_nxp_lcdic.c | 16 +++++++--------- dts/bindings/mipi-dbi/nxp,lcdic.yaml | 18 ++++++++++++++++++ 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/boards/nxp/rd_rw612_bga/dts/goworld_16880_lcm.overlay b/boards/nxp/rd_rw612_bga/dts/goworld_16880_lcm.overlay index 31ebc02eb52a1..658778d373bce 100644 --- a/boards/nxp/rd_rw612_bga/dts/goworld_16880_lcm.overlay +++ b/boards/nxp/rd_rw612_bga/dts/goworld_16880_lcm.overlay @@ -17,6 +17,8 @@ &lcdic { status = "okay"; nxp,swap-bytes; + /* Raise the timer0 ratio to enable longer reset delay */ + nxp,timer0-ratio = <15>; /* * Settings to connect this display: * Populate the following resistors: diff --git a/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay b/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay index 8c44347e63f1d..2e193a00d4ff5 100644 --- a/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay +++ b/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay @@ -22,6 +22,8 @@ &lcdic { /* Byte swapping not supported for this display */ /delete-property/ nxp,swap-bytes; + /* Set timer0 ratio to enable longer resets */ + nxp,timer0-ratio = <15>; /* * Settings to connect this display: diff --git a/boards/shields/lcd_par_s035/boards/rd_rw612_bga.overlay b/boards/shields/lcd_par_s035/boards/rd_rw612_bga.overlay index be0ba1319ec90..9a6dcc773cc85 100644 --- a/boards/shields/lcd_par_s035/boards/rd_rw612_bga.overlay +++ b/boards/shields/lcd_par_s035/boards/rd_rw612_bga.overlay @@ -92,4 +92,6 @@ /* Set pulse width for write active and write inactive to min value */ nxp,write-active-cycles = <1>; nxp,write-inactive-cycles = <1>; + /* Raise the timer0 ratio to enable longer reset delay */ + nxp,timer0-ratio = <15>; }; diff --git a/drivers/mipi_dbi/mipi_dbi_nxp_lcdic.c b/drivers/mipi_dbi/mipi_dbi_nxp_lcdic.c index 827e1d3b2b48b..5953fd4ff1273 100644 --- a/drivers/mipi_dbi/mipi_dbi_nxp_lcdic.c +++ b/drivers/mipi_dbi/mipi_dbi_nxp_lcdic.c @@ -74,6 +74,8 @@ struct mipi_dbi_lcdic_config { bool swap_bytes; uint8_t write_active_min; uint8_t write_inactive_min; + uint8_t timer0_ratio; + uint8_t timer1_ratio; }; #ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA @@ -125,12 +127,6 @@ struct mipi_dbi_lcdic_data { #define LCDIC_TX_FIFO_THRESH 0x3 #endif -/* Timer0 and Timer1 bases. We choose a longer timer0 base to enable - * long reset periods - */ -#define LCDIC_TIMER0_RATIO 0xF -#define LCDIC_TIMER1_RATIO 0x9 - /* After LCDIC is enabled or disabled, there should be a wait longer than * 5x the module clock before other registers are read */ @@ -595,7 +591,7 @@ static int mipi_dbi_lcdic_reset(const struct device *dev, k_timeout_t delay) &lcdic_freq)) { return -EIO; } - rst_width = (delay_ms * (lcdic_freq)) / ((1 << LCDIC_TIMER0_RATIO) * MSEC_PER_SEC); + rst_width = (delay_ms * (lcdic_freq)) / ((1 << config->timer0_ratio) * MSEC_PER_SEC); /* If rst_width is larger than max value supported by hardware, * increase the pulse count (rounding up) */ @@ -664,8 +660,8 @@ static int mipi_dbi_lcdic_init(const struct device *dev) LCDIC_TO_CTRL_CMD_SHORT_TO_MASK); /* Ensure LCDIC timer ratios are at reset values */ - base->TIMER_CTRL = LCDIC_TIMER_CTRL_TIMER_RATIO1(LCDIC_TIMER1_RATIO) | - LCDIC_TIMER_CTRL_TIMER_RATIO0(LCDIC_TIMER0_RATIO); + base->TIMER_CTRL = LCDIC_TIMER_CTRL_TIMER_RATIO1(config->timer1_ratio) | + LCDIC_TIMER_CTRL_TIMER_RATIO0(config->timer0_ratio); #ifdef CONFIG_MIPI_DBI_NXP_LCDIC_DMA /* Attach the LCDIC DMA request signal to the DMA channel we will @@ -807,6 +803,8 @@ static void mipi_dbi_lcdic_isr(const struct device *dev) DT_INST_PROP(n, nxp_write_active_cycles), \ .write_inactive_min = \ DT_INST_PROP(n, nxp_write_inactive_cycles), \ + .timer0_ratio = DT_INST_PROP(n, nxp_timer0_ratio), \ + .timer1_ratio = DT_INST_PROP(n, nxp_timer1_ratio), \ }; \ static struct mipi_dbi_lcdic_data mipi_dbi_lcdic_data_##n = { \ LCDIC_DMA_CHANNELS(n) \ diff --git a/dts/bindings/mipi-dbi/nxp,lcdic.yaml b/dts/bindings/mipi-dbi/nxp,lcdic.yaml index 4ce3f392a7c92..3dfc168c6f5b2 100644 --- a/dts/bindings/mipi-dbi/nxp,lcdic.yaml +++ b/dts/bindings/mipi-dbi/nxp,lcdic.yaml @@ -46,3 +46,21 @@ properties: Set minimum count of write active cycles, as a multiple of the module clock frequency. This controls the length of the active period of the WRX signal. Default is IP reset value. Only valid in 8080 mode. + + nxp,timer0-ratio: + type: int + default: 8 + description: | + Ratio for timer0, used for setting timer0 period (which is used for reset + and TX/RX short command timeout). Formula is: + timer0_period = (2 ^ timer0_ratio) / lcdic_freq + Default is IP reset value + + nxp,timer1-ratio: + type: int + default: 9 + description: | + Ratio for timer1, used for setting timer1 period (which is used for TE + wait time, timeout, and long command timeout). Formula is: + timer1_period = (2 ^ timer1_ratio) * timer0_period + Default is IP reset value From 92061a7304cc486ec429f07de575981da10b2c33 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 11 Nov 2024 20:25:24 +0000 Subject: [PATCH 2/2] drivers: mipi_dbi: mipi_dbi_nxp_lcdic: fix reset pulse calculation Reset pulse count can be up to 512 before we would be unable to support it using the peripheral. Use a uint32_t for the count, so that even long reset pulses will still be calculated correctly. Add code to warn about reset pulse requests that are too long. Signed-off-by: Daniel DeGrasse --- drivers/mipi_dbi/mipi_dbi_nxp_lcdic.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/mipi_dbi/mipi_dbi_nxp_lcdic.c b/drivers/mipi_dbi/mipi_dbi_nxp_lcdic.c index 5953fd4ff1273..4c252a277feee 100644 --- a/drivers/mipi_dbi/mipi_dbi_nxp_lcdic.c +++ b/drivers/mipi_dbi/mipi_dbi_nxp_lcdic.c @@ -38,6 +38,8 @@ enum lcdic_cmd_type { #define LCDIC_MAX_XFER 0x40000 /* Max reset width (in terms of Timer0_Period, see RST_CTRL register) */ #define LCDIC_MAX_RST_WIDTH 0x3F +/* Max reset pulse count */ +#define LCDIC_MAX_RST_PULSE_COUNT 0x7 /* Descriptor for LCDIC command */ union lcdic_trx_cmd { @@ -580,7 +582,7 @@ static int mipi_dbi_lcdic_reset(const struct device *dev, k_timeout_t delay) LCDIC_Type *base = config->base; uint32_t lcdic_freq; uint32_t delay_ms = k_ticks_to_ms_ceil32(delay.ticks); - uint8_t rst_width, pulse_cnt; + uint32_t rst_width, pulse_cnt; /* Calculate delay based off timer0 ratio. Formula given * by RM is as follows: @@ -598,6 +600,12 @@ static int mipi_dbi_lcdic_reset(const struct device *dev, k_timeout_t delay) pulse_cnt = ((rst_width + (LCDIC_MAX_RST_WIDTH - 1)) / LCDIC_MAX_RST_WIDTH); rst_width = MIN(LCDIC_MAX_RST_WIDTH, rst_width); + if ((pulse_cnt - 1) > LCDIC_MAX_RST_PULSE_COUNT) { + /* Still issue reset pulse, but warn user */ + LOG_WRN("Reset pulse is too long for configured timer0 ratio"); + pulse_cnt = LCDIC_MAX_RST_PULSE_COUNT + 1; + } + /* Start the reset signal */ base->RST_CTRL = LCDIC_RST_CTRL_RST_WIDTH(rst_width - 1) | LCDIC_RST_CTRL_RST_SEQ_NUM(pulse_cnt - 1) |