diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_board.h b/components/esp_driver_parlio/test_apps/parlio/main/test_board.h index 067529d382c..dc8251b5991 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_board.h +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_board.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -68,6 +68,14 @@ extern "C" { #define TEST_DATA5_GPIO 29 #define TEST_DATA6_GPIO 30 #define TEST_DATA7_GPIO 31 +#define TEST_DATA8_GPIO 35 +#define TEST_DATA9_GPIO 36 +#define TEST_DATA10_GPIO 39 +#define TEST_DATA11_GPIO 40 +#define TEST_DATA12_GPIO 41 +#define TEST_DATA13_GPIO 42 +#define TEST_DATA14_GPIO 43 +#define TEST_DATA15_GPIO 44 #else #error "Unsupported target" #endif diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c index 942e0376085..4d161f4195b 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c @@ -294,18 +294,10 @@ TEST_CASE("parallel_tx_clock_gating", "[paralio_tx]") #if !PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG TEST_CASE("parallel_tx_clock_gating_and_msb_coexist", "[paralio_tx]") { - printf("init a gpio to read parlio_tx clk output\r\n"); - gpio_config_t test_gpio_conf = { - .mode = GPIO_MODE_INPUT, - .pin_bit_mask = BIT64(TEST_CLK_GPIO) | BIT64(TEST_DATA7_GPIO), - }; - TEST_ESP_OK(gpio_config(&test_gpio_conf)); - - printf("install parlio tx unit\r\n"); parlio_tx_unit_handle_t tx_unit = NULL; parlio_tx_unit_config_t config = { .clk_src = PARLIO_CLK_SRC_DEFAULT, - .data_width = 8, + .data_width = PARLIO_TX_UNIT_MAX_DATA_WIDTH, .clk_in_gpio_num = -1, // use internal clock source .valid_gpio_num = TEST_VALID_GPIO, // generate the valid signal .clk_out_gpio_num = TEST_CLK_GPIO, @@ -318,6 +310,16 @@ TEST_CASE("parallel_tx_clock_gating_and_msb_coexist", "[paralio_tx]") TEST_DATA5_GPIO, TEST_DATA6_GPIO, TEST_DATA7_GPIO, +#if PARLIO_TX_UNIT_MAX_DATA_WIDTH > 8 + TEST_DATA8_GPIO, + TEST_DATA9_GPIO, + TEST_DATA10_GPIO, + TEST_DATA11_GPIO, + TEST_DATA12_GPIO, + TEST_DATA13_GPIO, + TEST_DATA14_GPIO, + TEST_DATA15_GPIO, +#endif }, .output_clk_freq_hz = 1 * 1000 * 1000, .trans_queue_depth = 4, @@ -328,13 +330,23 @@ TEST_CASE("parallel_tx_clock_gating_and_msb_coexist", "[paralio_tx]") .valid_stop_delay = 5, .flags.clk_gate_en = true, // enable clock gating, controlled by the CS signal }; + + printf("init a gpio to read parlio_tx clk output\r\n"); + gpio_num_t msb_gpio_num = config.data_gpio_nums[PARLIO_TX_UNIT_MAX_DATA_WIDTH - 1]; + gpio_config_t test_gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT64(TEST_CLK_GPIO) | BIT64(msb_gpio_num), + }; + TEST_ESP_OK(gpio_config(&test_gpio_conf)); + + printf("install parlio tx unit\r\n"); TEST_ESP_OK(parlio_new_tx_unit(&config, &tx_unit)); TEST_ESP_OK(parlio_tx_unit_enable(tx_unit)); printf("send packets and see if the clock is gated when there's no transaction on line\r\n"); parlio_transmit_config_t transmit_config = { - // set the idle value to 0x80, so that the MSB is high when there's no transaction - .idle_value = 0x80, + // set the idle value to 1 << (PARLIO_TX_UNIT_MAX_DATA_WIDTH - 1), so that the MSB is high when there's no transaction + .idle_value = 1 << (PARLIO_TX_UNIT_MAX_DATA_WIDTH - 1), }; uint32_t size = 256; __attribute__((aligned(64))) uint8_t payload[size]; @@ -345,16 +357,17 @@ TEST_CASE("parallel_tx_clock_gating_and_msb_coexist", "[paralio_tx]") TEST_ESP_OK(parlio_tx_unit_wait_all_done(tx_unit, -1)); // check if the level on the clock line is low TEST_ASSERT_EQUAL(0, gpio_get_level(TEST_CLK_GPIO)); - TEST_ASSERT_EQUAL(1, gpio_get_level(TEST_DATA7_GPIO)); + TEST_ASSERT_EQUAL(1, gpio_get_level(msb_gpio_num)); TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, payload, size * sizeof(uint8_t) * 8, &transmit_config)); TEST_ESP_OK(parlio_tx_unit_wait_all_done(tx_unit, -1)); TEST_ASSERT_EQUAL(0, gpio_get_level(TEST_CLK_GPIO)); TEST_ASSERT_EQUAL(0, gpio_get_level(TEST_CLK_GPIO)); - TEST_ASSERT_EQUAL(1, gpio_get_level(TEST_DATA7_GPIO)); + TEST_ASSERT_EQUAL(1, gpio_get_level(msb_gpio_num)); TEST_ESP_OK(parlio_tx_unit_disable(tx_unit)); TEST_ESP_OK(parlio_del_tx_unit(tx_unit)); TEST_ESP_OK(gpio_reset_pin(TEST_CLK_GPIO)); + TEST_ESP_OK(gpio_reset_pin(msb_gpio_num)); } #endif // !PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG #endif // SOC_PARLIO_TX_CLK_SUPPORT_GATING diff --git a/components/hal/esp32p4/include/hal/parlio_ll.h b/components/hal/esp32p4/include/hal/parlio_ll.h index 2e6327394f6..be352a4ce0d 100644 --- a/components/hal/esp32p4/include/hal/parlio_ll.h +++ b/components/hal/esp32p4/include/hal/parlio_ll.h @@ -14,6 +14,7 @@ #include "hal/misc.h" #include "hal/parlio_types.h" #include "hal/hal_utils.h" +#include "hal/config.h" #include "soc/hp_sys_clkrst_struct.h" #include "soc/lp_clkrst_struct.h" #include "soc/parl_io_struct.h" @@ -33,9 +34,17 @@ #define PARLIO_LL_EVENT_TX_MASK (PARLIO_LL_EVENT_TX_FIFO_EMPTY | PARLIO_LL_EVENT_TX_EOF) #define PARLIO_LL_EVENT_RX_MASK (PARLIO_LL_EVENT_RX_FIFO_FULL) + +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) < 300 #define PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG 15 // TXD[15] can be used a valid signal +#endif + #define PARLIO_LL_TX_DATA_LINE_AS_CLK_GATE 15 // TXD[15] can be used as clock gate signal +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 +#define PARLIO_LL_TX_VALID_MAX_DELAY 32767 +#endif + #ifdef __cplusplus extern "C" { #endif @@ -553,23 +562,6 @@ static inline void parlio_ll_tx_set_trans_bit_len(parl_io_dev_t *dev, uint32_t b dev->tx_data_cfg.tx_bitlen = bitlen; } -/** - * @brief Set TX valid signal delay - * - * @param dev Parallel IO register base address - * @param start_delay Number of clock cycles to delay - * @param stop_delay Number of clock cycles to delay - * @return true: success, false: valid delay is not supported - */ -static inline bool parlio_ll_tx_set_valid_delay(parl_io_dev_t *dev, uint32_t start_delay, uint32_t stop_delay) -{ - (void)dev; - if (start_delay == 0 && stop_delay == 0) { - return true; - } - return false; -} - /** * @brief Check if tx size can be determined by DMA * @@ -621,19 +613,6 @@ static inline void parlio_ll_tx_start(parl_io_dev_t *dev, bool en) dev->tx_start_cfg.tx_start = en; } -/** - * @brief Whether to treat the MSB of TXD as the valid signal - * - * @note If enabled, TXD[15] will work as valid signal, which stay high during data transmission. - * - * @param dev Parallel IO register base address - * @param en True to enable, False to disable - */ -static inline void parlio_ll_tx_treat_msb_as_valid(parl_io_dev_t *dev, bool en) -{ - dev->tx_genrl_cfg.tx_valid_output_en = en; -} - /** * @brief Set the sample clock edge * @@ -794,6 +773,62 @@ static inline volatile void *parlio_ll_get_interrupt_status_reg(parl_io_dev_t *d return &dev->int_st; } +/**********************************************************************************************************************/ +/************************ The following functions behave differently based on the chip revision ***********************/ +/**********************************************************************************************************************/ + +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 +/** + * @brief Set the clock gating from the valid signal + * + * @param dev Parallel IO register base address + * @param en If set to true, the clock is gated by the valid signal, otherwise it is gated by the MSB of the data line. + */ +static inline void parlio_ll_tx_clock_gating_from_valid(parl_io_dev_t *dev, bool en) +{ + dev->tx_genrl_cfg.tx_valid_output_en = en; +} +#else +/** + * @brief Whether to treat the MSB of TXD as the valid signal + * + * @note If enabled, TXD[15] will work as valid signal, which stay high during data transmission. + * + * @param dev Parallel IO register base address + * @param en True to enable, False to disable + */ +static inline void parlio_ll_tx_treat_msb_as_valid(parl_io_dev_t *dev, bool en) +{ + dev->tx_genrl_cfg.tx_valid_output_en = en; +} +#endif + +/** + * @brief Set TX valid signal delay + * + * @param dev Parallel IO register base address + * @param start_delay Number of clock cycles to delay + * @param stop_delay Number of clock cycles to delay + * @return true: success, false: valid delay is not supported + */ +static inline bool parlio_ll_tx_set_valid_delay(parl_io_dev_t *dev, uint32_t start_delay, uint32_t stop_delay) +{ +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 + if (start_delay > PARLIO_LL_TX_VALID_MAX_DELAY || stop_delay > PARLIO_LL_TX_VALID_MAX_DELAY) { + return false; + } + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->tx_cs_cfg, tx_cs_start_delay, start_delay); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->tx_cs_cfg, tx_cs_stop_delay, stop_delay); + return true; +#else + (void)dev; + if (start_delay == 0 && stop_delay == 0) { + return true; + } + return false; +#endif +} + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/include/soc/gpio_sig_map.h b/components/soc/esp32p4/include/soc/gpio_sig_map.h index 756baafe93b..e1979fb566d 100644 --- a/components/soc/esp32p4/include/soc/gpio_sig_map.h +++ b/components/soc/esp32p4/include/soc/gpio_sig_map.h @@ -451,7 +451,7 @@ #define CORE_GPIO_IN_PAD_IN27_IDX 241 #define CORE_GPIO_OUT_PAD_OUT27_IDX 241 #define CORE_GPIO_IN_PAD_IN28_IDX 242 -#define PARLIO_TX_CS_PAD_OUT_IDX 242 +#define PARLIO_TX_CS_PAD_OUT_IDX 242 // only exists on ESP32P4 Rev. 3.0 and later #define CORE_GPIO_IN_PAD_IN29_IDX 243 #define EMAC_PTP_PPS_PAD_OUT_IDX 243 #define CORE_GPIO_IN_PAD_IN30_IDX 244 diff --git a/components/soc/esp32p4/parlio_periph.c b/components/soc/esp32p4/parlio_periph.c index f5fc910c583..5a7d4ce7911 100644 --- a/components/soc/esp32p4/parlio_periph.c +++ b/components/soc/esp32p4/parlio_periph.c @@ -35,7 +35,7 @@ const parlio_signal_conn_t parlio_periph_signals = { }, .clk_out_sig = PARLIO_TX_CLK_PAD_OUT_IDX, .clk_in_sig = PARLIO_TX_CLK_PAD_IN_IDX, - .cs_sig = -1, + .cs_sig = PARLIO_TX_CS_PAD_OUT_IDX, } }, .rx_units = {