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..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 { @@ -74,6 +76,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 +129,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 */ @@ -584,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: @@ -595,13 +593,19 @@ 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) */ 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) | @@ -664,8 +668,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 +811,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