diff --git a/boards/nordic/nrf52840dk/board.cmake b/boards/nordic/nrf52840dk/board.cmake index 1ebf652634f4..a3109800d08f 100644 --- a/boards/nordic/nrf52840dk/board.cmake +++ b/boards/nordic/nrf52840dk/board.cmake @@ -1,5 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 +if(CONFIG_SOC_NRF52840_QIAA) + board_runner_args(nrfutil "--ext-mem-config-file=${BOARD_DIR}/support/nrf52840dk_qspi_nrfutil_config.json") +endif() + board_runner_args(jlink "--device=nRF52840_xxAA" "--speed=4000") board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000") include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake) diff --git a/boards/nordic/nrf52840dk/support/nrf52840dk_qspi_nrfutil_config.json b/boards/nordic/nrf52840dk/support/nrf52840dk_qspi_nrfutil_config.json new file mode 100644 index 000000000000..1918a1e5923f --- /dev/null +++ b/boards/nordic/nrf52840dk/support/nrf52840dk_qspi_nrfutil_config.json @@ -0,0 +1,22 @@ +{ + "firmware_config": { + "peripheral": "QSPI" + }, + "pins": { + "sck": 19, + "csn": 17, + "io0": 20, + "io1": 21, + "io2": 22, + "io3": 23 + }, + "flash_size": 67108864, + "sck_frequency": 8000000, + "address_mode": "MODE24BIT", + "readoc": "READ4IO", + "writeoc": "PP4IO", + "pp_size": "PPSIZE256", + "sck_delay": 128, + "rx_delay": 2, + "page_size": 4096 +} diff --git a/boards/nordic/nrf5340dk/board.cmake b/boards/nordic/nrf5340dk/board.cmake index 3634697dd770..38eefdc71fcd 100644 --- a/boards/nordic/nrf5340dk/board.cmake +++ b/boards/nordic/nrf5340dk/board.cmake @@ -5,6 +5,7 @@ if(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP_NS) endif() if(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP OR CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP_NS) + board_runner_args(nrfutil "--ext-mem-config-file=${BOARD_DIR}/support/nrf5340dk_qspi_nrfutil_config.json") board_runner_args(jlink "--device=nrf5340_xxaa_app" "--speed=4000") endif() diff --git a/boards/nordic/nrf5340dk/support/nrf5340dk_qspi_nrfutil_config.json b/boards/nordic/nrf5340dk/support/nrf5340dk_qspi_nrfutil_config.json new file mode 100644 index 000000000000..f7a1a4a06bdd --- /dev/null +++ b/boards/nordic/nrf5340dk/support/nrf5340dk_qspi_nrfutil_config.json @@ -0,0 +1,22 @@ +{ + "firmware_config": { + "peripheral": "QSPI" + }, + "pins": { + "sck": 17, + "csn": 18, + "io0": 13, + "io1": 14, + "io2": 15, + "io3": 16 + }, + "flash_size": 67108864, + "sck_frequency": 8000000, + "address_mode": "MODE24BIT", + "readoc": "READ4IO", + "writeoc": "PP4IO", + "pp_size": "PPSIZE256", + "sck_delay": 128, + "rx_delay": 2, + "page_size": 4096 +} diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi index 165fa12ba80d..f29374025540 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi @@ -7,44 +7,44 @@ / { reserved-memory { - cpurad_ram0x_region: memory@2f010000 { + cpuapp_ram0x_region: memory@2f010000 { compatible = "nordic,owned-memory"; - reg = <0x2f010000 DT_SIZE_K(4)>; + reg = <0x2f010000 DT_SIZE_K(260)>; status = "disabled"; - nordic,access = ; + nordic,access = ; #address-cells = <1>; #size-cells = <1>; - ranges = <0x0 0x2f010000 0x1000>; + ranges = <0x0 0x2f010000 0x41000>; - cpusec_cpurad_ipc_shm: memory@0 { + cpusec_cpuapp_ipc_shm: memory@0 { reg = <0x0 DT_SIZE_K(2)>; }; - cpurad_cpusec_ipc_shm: memory@800 { + cpuapp_cpusec_ipc_shm: memory@800 { reg = <0x800 DT_SIZE_K(2)>; }; + + cpuapp_data: memory@1000 { + reg = <0x1000 DT_SIZE_K(256)>; + }; }; - cpuapp_ram0x_region: memory@2f011000 { + cpurad_ram0x_region: memory@2f051000 { compatible = "nordic,owned-memory"; - reg = <0x2f011000 DT_SIZE_K(260)>; + reg = <0x2f051000 DT_SIZE_K(4)>; status = "disabled"; - nordic,access = ; + nordic,access = ; #address-cells = <1>; #size-cells = <1>; - ranges = <0x0 0x2f011000 0x41000>; + ranges = <0x0 0x2f051000 0x1000>; - cpusec_cpuapp_ipc_shm: memory@0 { + cpusec_cpurad_ipc_shm: memory@0 { reg = <0x0 DT_SIZE_K(2)>; }; - cpuapp_cpusec_ipc_shm: memory@800 { + cpurad_cpusec_ipc_shm: memory@800 { reg = <0x800 DT_SIZE_K(2)>; }; - - cpuapp_data: memory@1000 { - reg = <0x1000 DT_SIZE_K(256)>; - }; }; etr_buf_ram0x_region: memory@2f0be000 { diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index 06e642948f3a..6f28374d9767 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -268,7 +268,7 @@ ipc0: &cpuapp_cpurad_ipc { status = "okay"; mx25uw63: mx25uw6345g@0 { - compatible = "jedec,mspi-nor"; + compatible = "mxicy,mx25u", "jedec,mspi-nor"; status = "disabled"; reg = <0>; jedec-id = [c2 84 37]; diff --git a/boards/nordic/nrf7002dk/board.cmake b/boards/nordic/nrf7002dk/board.cmake index c4f86afedf7d..11a27910eebc 100644 --- a/boards/nordic/nrf7002dk/board.cmake +++ b/boards/nordic/nrf7002dk/board.cmake @@ -10,7 +10,7 @@ if(CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP OR CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NS OR CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 OR CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS) - board_runner_args(nrfutil "--ext-mem-config-file=${BOARD_DIR}/nrf7002dk_spi_nrfutil_config.json") + board_runner_args(nrfutil "--ext-mem-config-file=${BOARD_DIR}/support/nrf7002dk_spi_nrfutil_config.json") board_runner_args(jlink "--device=nrf5340_xxaa_app" "--speed=4000") endif() diff --git a/boards/nordic/nrf7002dk/nrf7002dk_spi_nrfutil_config.json b/boards/nordic/nrf7002dk/support/nrf7002dk_spi_nrfutil_config.json similarity index 100% rename from boards/nordic/nrf7002dk/nrf7002dk_spi_nrfutil_config.json rename to boards/nordic/nrf7002dk/support/nrf7002dk_spi_nrfutil_config.json diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts index a7b61861bed3..6abddbeafcc9 100644 --- a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts @@ -254,7 +254,7 @@ ipc0: &cpuapp_cpurad_ipc { status = "okay"; mx25uw63: mx25uw6345g@0 { - compatible = "jedec,mspi-nor"; + compatible = "mxicy,mx25u", "jedec,mspi-nor"; status = "disabled"; reg = <0>; jedec-id = [c2 84 37]; diff --git a/boards/nordic/thingy53/board.cmake b/boards/nordic/thingy53/board.cmake index f03b026d9fbd..6f14014a0c91 100644 --- a/boards/nordic/thingy53/board.cmake +++ b/boards/nordic/thingy53/board.cmake @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 if(CONFIG_BOARD_THINGY53_NRF5340_CPUAPP OR CONFIG_BOARD_THINGY53_NRF5340_CPUAPP_NS) - board_runner_args(nrfutil "--ext-mem-config-file=${BOARD_DIR}/thingy53_qspi_nrfutil_config.json") + board_runner_args(nrfutil "--ext-mem-config-file=${BOARD_DIR}/support/thingy53_qspi_nrfutil_config.json") board_runner_args(jlink "--device=nrf5340_xxaa_app" "--speed=4000") elseif(CONFIG_BOARD_THINGY53_NRF5340_CPUNET) board_runner_args(jlink "--device=nrf5340_xxaa_net" "--speed=4000") diff --git a/boards/nordic/thingy53/thingy53_qspi_nrfutil_config.json b/boards/nordic/thingy53/support/thingy53_qspi_nrfutil_config.json similarity index 100% rename from boards/nordic/thingy53/thingy53_qspi_nrfutil_config.json rename to boards/nordic/thingy53/support/thingy53_qspi_nrfutil_config.json diff --git a/drivers/clock_control/Kconfig.nrf b/drivers/clock_control/Kconfig.nrf index da330f7b08e3..f113a3284c26 100644 --- a/drivers/clock_control/Kconfig.nrf +++ b/drivers/clock_control/Kconfig.nrf @@ -128,6 +128,29 @@ config CLOCK_CONTROL_NRF_USES_TEMP_SENSOR endif # CLOCK_CONTROL_NRF_DRIVER_CALIBRATION endif # CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION +config CLOCK_CONTROL_NRF_HFINT_CALIBRATION + bool "HFINT clock calibration" + depends on SOC_NRF54L05 || SOC_NRF54L10 || SOC_NRF54L15 + depends on DT_HAS_NORDIC_NRF_HFXO_ENABLED + depends on !TRUSTED_EXECUTION_NONSECURE + select EXPERIMENTAL + help + Enables calibration of HFINT clock on every start of HFXO clock. + +if CLOCK_CONTROL_NRF_HFINT_CALIBRATION + +config CLOCK_CONTROL_NRF_HFINT_CALIBRATION_PERIOD + int "HFINT clock calibration period in milliseconds" + default 60000 + help + Periodically, HFINT clock calibration is performed. + This includes requesting HFXO clock and starting actual calibration. + Once the calibration is finished, the HFXO clock is released. + Set to 0 to disable periodic calibration - in such case calibration + will be done only when HFXO is started by the application itself. + +endif # CLOCK_CONTROL_NRF_HFINT_CALIBRATION + choice CLOCK_CONTROL_NRF_ACCURACY_PPM prompt "32KHz clock accuracy" default CLOCK_CONTROL_NRF_K32SRC_500PPM if CLOCK_CONTROL_NRF_K32SRC_RC && SOC_COMPATIBLE_NRF52X diff --git a/drivers/clock_control/clock_control_nrf.c b/drivers/clock_control/clock_control_nrf.c index d829a945be73..5e3fb6875e3c 100644 --- a/drivers/clock_control/clock_control_nrf.c +++ b/drivers/clock_control/clock_control_nrf.c @@ -14,6 +14,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL); @@ -172,9 +173,90 @@ static void set_on_state(uint32_t *flags) irq_unlock(key); } +#ifdef CONFIG_CLOCK_CONTROL_NRF_HFINT_CALIBRATION + +static void nrf54l_errata_30_workaround(void) +{ + while (FIELD_GET(CLOCK_XO_STAT_STATE_Msk, NRF_CLOCK->XO.STAT) != + CLOCK_XO_STAT_STATE_Running) { + } + const uint32_t higher_bits = *((volatile uint32_t *)0x50120820UL) & 0xFFFFFFC0; + *((volatile uint32_t *)0x50120864UL) = 1 | BIT(31); + *((volatile uint32_t *)0x50120848UL) = 1; + uint32_t off_abs = 24; + + while (off_abs >= 24) { + *((volatile uint32_t *)0x50120844UL) = 1; + while (((*((volatile uint32_t *)0x50120840UL)) & (1 << 16)) != 0) { + } + const uint32_t current_cal = *((volatile uint32_t *)0x50120820UL) & 0x3F; + const uint32_t cal_result = *((volatile uint32_t *)0x50120840UL) & 0x7FF; + int32_t off = 1024 - cal_result; + + off_abs = (off < 0) ? -off : off; + + if (off >= 24 && current_cal < 0x3F) { + *((volatile uint32_t *)0x50120820UL) = higher_bits | (current_cal + 1); + } else if (off <= -24 && current_cal > 0) { + *((volatile uint32_t *)0x50120820UL) = higher_bits | (current_cal - 1); + } + } + + *((volatile uint32_t *)0x50120848UL) = 0; + *((volatile uint32_t *)0x50120864UL) = 0; +} + +#if CONFIG_CLOCK_CONTROL_NRF_HFINT_CALIBRATION_PERIOD + +static struct onoff_client hf_cal_cli; + +static void calibration_finished_callback(struct onoff_manager *mgr, + struct onoff_client *cli, + uint32_t state, + int res) +{ + (void)onoff_cancel_or_release(mgr, cli); +} + +static void calibration_handler(struct k_timer *timer) +{ + nrf_clock_hfclk_t clk_src; + + bool ret = nrfx_clock_is_running(NRF_CLOCK_DOMAIN_HFCLK, &clk_src); + + if (ret && (clk_src == NRF_CLOCK_HFCLK_HIGH_ACCURACY)) { + return; + } + + sys_notify_init_callback(&hf_cal_cli.notify, calibration_finished_callback); + (void)onoff_request(z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF), + &hf_cal_cli); +} + +static K_TIMER_DEFINE(calibration_timer, calibration_handler, NULL); + +static int calibration_init(void) +{ + k_timer_start(&calibration_timer, + K_NO_WAIT, + K_MSEC(CONFIG_CLOCK_CONTROL_NRF_HFINT_CALIBRATION_PERIOD)); + + return 0; +} + +SYS_INIT(calibration_init, APPLICATION, 0); + +#endif /* CONFIG_CLOCK_CONTROL_NRF_HFINT_CALIBRATION_PERIOD */ +#endif /* CONFIG_CLOCK_CONTROL_NRF_HFINT_CALIBRATION */ + static void clkstarted_handle(const struct device *dev, enum clock_control_nrf_type type) { +#if CONFIG_CLOCK_CONTROL_NRF_HFINT_CALIBRATION + if (nrf54l_errata_30() && (type == CLOCK_CONTROL_NRF_TYPE_HFCLK)) { + nrf54l_errata_30_workaround(); + } +#endif struct nrf_clock_control_sub_data *sub_data = get_sub_data(dev, type); clock_control_cb_t callback = sub_data->cb; void *user_data = sub_data->user_data; @@ -599,6 +681,17 @@ static void clock_event_handler(nrfx_clock_evt_type_t event) const struct device *dev = CLOCK_DEVICE; switch (event) { +#if NRF_CLOCK_HAS_XO_TUNE + case NRFX_CLOCK_EVT_XO_TUNED: + clkstarted_handle(dev, CLOCK_CONTROL_NRF_TYPE_HFCLK); + break; + case NRFX_CLOCK_EVT_HFCLK_STARTED: + /* HFCLK is stable after XOTUNED event. + * HFCLK_STARTED means only that clock has been started. + */ + break; +#else + /* HFCLK started should be used only if tune operation is done implicitly. */ case NRFX_CLOCK_EVT_HFCLK_STARTED: { struct nrf_clock_control_sub_data *data = @@ -613,6 +706,8 @@ static void clock_event_handler(nrfx_clock_evt_type_t event) break; } +#endif + #if NRF_CLOCK_HAS_HFCLK192M case NRFX_CLOCK_EVT_HFCLK192M_STARTED: clkstarted_handle(dev, CLOCK_CONTROL_NRF_TYPE_HFCLK192M); @@ -643,7 +738,6 @@ static void clock_event_handler(nrfx_clock_evt_type_t event) case NRFX_CLOCK_EVT_PLL_STARTED: #endif #if NRF_CLOCK_HAS_XO_TUNE - case NRFX_CLOCK_EVT_XO_TUNED: case NRFX_CLOCK_EVT_XO_TUNE_ERROR: case NRFX_CLOCK_EVT_XO_TUNE_FAILED: #endif diff --git a/drivers/flash/flash_mspi_nor.c b/drivers/flash/flash_mspi_nor.c index 455076a7a9b3..140a5300308a 100644 --- a/drivers/flash/flash_mspi_nor.c +++ b/drivers/flash/flash_mspi_nor.c @@ -6,250 +6,58 @@ #define DT_DRV_COMPAT jedec_mspi_nor -#include #include -#include #include #include #include -#include "jesd216.h" -#include "spi_nor.h" +#include "flash_mspi_nor.h" +#include "flash_mspi_nor_quirks.h" LOG_MODULE_REGISTER(flash_mspi_nor, CONFIG_FLASH_LOG_LEVEL); -#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) -#define WITH_RESET_GPIO 1 -#endif - -#define FLASH_MX25R_LH_MASK BIT(1) - -static uint8_t hp_payload[3] = {SPI_NOR_QE_BIT, 0x0, FLASH_MX25R_LH_MASK}; - -struct flash_mspi_nor_data { - struct k_sem acquired; - struct mspi_xfer_packet packet; - struct mspi_xfer xfer; -}; +void flash_mspi_command_set(const struct device *dev, const struct flash_mspi_nor_cmd *cmd) +{ + struct flash_mspi_nor_data *dev_data = dev->data; + const struct flash_mspi_nor_config *dev_config = dev->config; -struct flash_mspi_nor_cmd { - enum mspi_xfer_direction dir; - uint32_t cmd; - uint16_t tx_dummy; - uint16_t rx_dummy; - uint8_t cmd_length; - uint8_t addr_length; - bool force_single; -}; + memset(&dev_data->xfer, 0, sizeof(dev_data->xfer)); + memset(&dev_data->packet, 0, sizeof(dev_data->packet)); -struct flash_mspi_nor_cmds { - struct flash_mspi_nor_cmd id; - struct flash_mspi_nor_cmd write_en; - struct flash_mspi_nor_cmd read; - struct flash_mspi_nor_cmd status; - struct flash_mspi_nor_cmd page_program; - struct flash_mspi_nor_cmd sector_erase; - struct flash_mspi_nor_cmd chip_erase; - struct flash_mspi_nor_cmd mode_change; - struct flash_mspi_nor_cmd sfdp; - uint8_t mode_payload; -}; + dev_data->xfer.xfer_mode = MSPI_PIO; + dev_data->xfer.packets = &dev_data->packet; + dev_data->xfer.num_packet = 1; + dev_data->xfer.timeout = 10; -static const struct flash_mspi_nor_cmds commands[] = { - [MSPI_IO_MODE_SINGLE] = { - .id = { - .dir = MSPI_RX, - .cmd = JESD216_CMD_READ_ID, - .cmd_length = 1, - }, - .write_en = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_WREN, - .cmd_length = 1, - }, - .read = { - .dir = MSPI_RX, - .cmd = SPI_NOR_CMD_READ_FAST, - .cmd_length = 1, - .addr_length = 3, - .rx_dummy = 8, - }, - .status = { - .dir = MSPI_RX, - .cmd = SPI_NOR_CMD_RDSR, - .cmd_length = 1, - }, - .page_program = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_PP, - .cmd_length = 1, - .addr_length = 3, - }, - .sector_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_SE, - .cmd_length = 1, - .addr_length = 3, - }, - .chip_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_CE, - .cmd_length = 1, - }, - .mode_change = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_WRSR, - .cmd_length = 1, - }, - .mode_payload = 0, - }, - [MSPI_IO_MODE_QUAD_1_4_4] = { - .id = { - .dir = MSPI_RX, - .cmd = JESD216_CMD_READ_ID, - .cmd_length = 1, - .force_single = true, - }, - .write_en = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_WREN, - .cmd_length = 1, - }, - .read = { - .dir = MSPI_RX, - .cmd = SPI_NOR_CMD_4READ, - .cmd_length = 1, - .addr_length = 3, - .rx_dummy = 6, - }, - .status = { - .dir = MSPI_RX, - .cmd = SPI_NOR_CMD_RDSR, - .cmd_length = 1, - .force_single = true, - }, - .page_program = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_PP_1_4_4, - .cmd_length = 1, - .addr_length = 3, - }, - .sector_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_SE, - .cmd_length = 1, - .addr_length = 3, - .force_single = true, - }, - .chip_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_CE, - .cmd_length = 1, - }, - .mode_change = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_WRSR, - .cmd_length = 1, - .force_single = true, - }, - .mode_payload = SPI_NOR_QE_BIT, - }, - [MSPI_IO_MODE_OCTAL] = { - .id = { - .dir = MSPI_RX, - .cmd = JESD216_OCMD_READ_ID, - .cmd_length = 2, - .addr_length = 4, - .rx_dummy = 4 - }, - .write_en = { - .dir = MSPI_TX, - .cmd = SPI_NOR_OCMD_WREN, - .cmd_length = 2, - }, - .read = { - .dir = MSPI_RX, - .cmd = SPI_NOR_OCMD_RD, - .cmd_length = 2, - .addr_length = 4, - .rx_dummy = 20, - }, - .status = { - .dir = MSPI_RX, - .cmd = SPI_NOR_OCMD_RDSR, - .cmd_length = 2, - .addr_length = 4, - .rx_dummy = 4, - }, - .page_program = { - .dir = MSPI_TX, - .cmd = SPI_NOR_OCMD_PAGE_PRG, - .cmd_length = 2, - .addr_length = 4, - }, - .sector_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_OCMD_SE, - .cmd_length = 2, - .addr_length = 4, - }, - .chip_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_OCMD_CE, - .cmd_length = 2, - }, - .sfdp = { - .dir = MSPI_RX, - .cmd = JESD216_OCMD_READ_SFDP, - .cmd_length = 2, - .addr_length = 4, - .rx_dummy = 20, - }, - .mode_change = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_WR_CFGREG2, - .cmd_length = 1, - .addr_length = 4, - }, - .mode_payload = 0x01, - }, -}; + dev_data->xfer.cmd_length = cmd->cmd_length; + dev_data->xfer.addr_length = cmd->addr_length; + dev_data->xfer.tx_dummy = (cmd->dir == MSPI_TX) ? + cmd->tx_dummy : dev_config->mspi_nor_cfg.tx_dummy; + dev_data->xfer.rx_dummy = (cmd->dir == MSPI_RX) ? + cmd->rx_dummy : dev_config->mspi_nor_cfg.rx_dummy; -struct flash_mspi_nor_config { - const struct device *bus; - uint32_t flash_size; - struct mspi_dev_id mspi_id; - struct mspi_dev_cfg mspi_nor_cfg; - struct mspi_dev_cfg mspi_nor_init_cfg; - enum mspi_dev_cfg_mask mspi_nor_cfg_mask; -#if defined(CONFIG_MSPI_XIP) - struct mspi_xip_cfg xip_cfg; -#endif -#if defined(WITH_RESET_GPIO) - struct gpio_dt_spec reset; - uint32_t reset_pulse_us; - uint32_t reset_recovery_us; -#endif -#if defined(CONFIG_FLASH_PAGE_LAYOUT) - struct flash_pages_layout layout; -#endif - uint8_t jedec_id[SPI_NOR_MAX_ID_LEN]; - const struct flash_mspi_nor_cmds *jedec_cmds; -}; + dev_data->packet.dir = cmd->dir; + dev_data->packet.cmd = cmd->cmd; +} static int dev_cfg_apply(const struct device *dev, const struct mspi_dev_cfg *cfg) { const struct flash_mspi_nor_config *dev_config = dev->config; + struct flash_mspi_nor_data *dev_data = dev->data; + + if (dev_data->curr_cfg == cfg) { + return 0; + } int rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, - dev_config->mspi_nor_cfg_mask, cfg); + MSPI_DEVICE_CONFIG_ALL, cfg); if (rc < 0) { LOG_ERR("Failed to set device config: %p error: %d", cfg, rc); } return rc; } -static int acquire(const struct device *dev, const struct mspi_dev_cfg *cfg) +static int acquire(const struct device *dev) { const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; @@ -264,8 +72,12 @@ static int acquire(const struct device *dev, const struct mspi_dev_cfg *cfg) /* This acquires the MSPI controller and reconfigures it * if needed for the flash device. */ - rc = dev_cfg_apply(dev, cfg); - if (rc == 0) { + rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, + dev_config->mspi_nor_cfg_mask, + &dev_config->mspi_nor_cfg); + if (rc < 0) { + LOG_ERR("mspi_dev_config() failed: %d", rc); + } else { return 0; } @@ -301,30 +113,6 @@ static inline uint16_t dev_page_size(const struct device *dev) return SPI_NOR_PAGE_SIZE; } -static void command_set(const struct device *dev, const struct flash_mspi_nor_cmd *cmd) -{ - struct flash_mspi_nor_data *dev_data = dev->data; - const struct flash_mspi_nor_config *dev_config = dev->config; - - memset(&dev_data->xfer, 0, sizeof(dev_data->xfer)); - memset(&dev_data->packet, 0, sizeof(dev_data->packet)); - - dev_data->xfer.xfer_mode = MSPI_PIO; - dev_data->xfer.packets = &dev_data->packet; - dev_data->xfer.num_packet = 1; - dev_data->xfer.timeout = 10; - - dev_data->xfer.cmd_length = cmd->cmd_length; - dev_data->xfer.addr_length = cmd->addr_length; - dev_data->xfer.tx_dummy = (cmd->dir == MSPI_TX) ? - cmd->tx_dummy : dev_config->mspi_nor_cfg.tx_dummy; - dev_data->xfer.rx_dummy = (cmd->dir == MSPI_RX) ? - cmd->rx_dummy : dev_config->mspi_nor_cfg.rx_dummy; - - dev_data->packet.dir = cmd->dir; - dev_data->packet.cmd = cmd->cmd; -} - static int api_read(const struct device *dev, off_t addr, void *dest, size_t size) { @@ -341,13 +129,23 @@ static int api_read(const struct device *dev, off_t addr, void *dest, return -EINVAL; } - rc = acquire(dev, &dev_config->mspi_nor_cfg); + rc = acquire(dev); + if (rc < 0) { + return rc; + } + + if (dev_config->jedec_cmds->read.force_single) { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); + } else { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + } + if (rc < 0) { return rc; } /* TODO: get rid of all these hard-coded values for MX25Ux chips */ - command_set(dev, &dev_config->jedec_cmds->read); + flash_mspi_command_set(dev, &dev_config->jedec_cmds->read); dev_data->packet.address = addr; dev_data->packet.data_buf = dest; dev_data->packet.num_bytes = size; @@ -364,24 +162,25 @@ static int api_read(const struct device *dev, off_t addr, void *dest, return 0; } -static int status_get(const struct device *dev, const struct mspi_dev_cfg *curr_cfg, - uint8_t *status) +static int status_get(const struct device *dev, uint8_t *status) { const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; int rc; /* Enter command mode */ - if (curr_cfg != &dev_config->mspi_nor_init_cfg) { + if (dev_config->jedec_cmds->status.force_single) { rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); + } else { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + } - if (rc < 0) { - LOG_ERR("Switching to initial dev_cfg failed: %d", rc); - return rc; - } + if (rc < 0) { + LOG_ERR("Switching to dev_cfg failed: %d", rc); + return rc; } - command_set(dev, &dev_config->jedec_cmds->status); + flash_mspi_command_set(dev, &dev_config->jedec_cmds->status); dev_data->packet.data_buf = status; dev_data->packet.num_bytes = sizeof(uint8_t); @@ -392,29 +191,19 @@ static int status_get(const struct device *dev, const struct mspi_dev_cfg *curr_ return rc; } - /* Exit command mode */ - if (curr_cfg != &dev_config->mspi_nor_init_cfg) { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); - - if (rc < 0) { - LOG_ERR("Switching to default dev_cfg failed: %d", rc); - } - } - return rc; } -static int wait_until_ready(const struct device *dev, const struct mspi_dev_cfg *curr_cfg, - k_timeout_t poll_period) +static int wait_until_ready(const struct device *dev, k_timeout_t poll_period) { int rc; uint8_t status_reg; while (true) { - rc = status_get(dev, curr_cfg, &status_reg); + rc = status_get(dev, &status_reg); if (rc < 0) { - LOG_ERR("Status xfer failed: %d", rc); + LOG_ERR("Wait until ready - status xfer failed: %d", rc); return rc; } @@ -432,8 +221,19 @@ static int write_enable(const struct device *dev) { const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; + int rc; - command_set(dev, &dev_config->jedec_cmds->write_en); + if (dev_config->jedec_cmds->write_en.force_single) { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); + } else { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + } + + if (rc < 0) { + return rc; + } + + flash_mspi_command_set(dev, &dev_config->jedec_cmds->write_en); return mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); } @@ -454,7 +254,7 @@ static int api_write(const struct device *dev, off_t addr, const void *src, return -EINVAL; } - rc = acquire(dev, &dev_config->mspi_nor_cfg); + rc = acquire(dev); if (rc < 0) { return rc; } @@ -470,7 +270,17 @@ static int api_write(const struct device *dev, off_t addr, const void *src, break; } - command_set(dev, &dev_config->jedec_cmds->page_program); + if (dev_config->jedec_cmds->page_program.force_single) { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); + } else { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + } + + if (rc < 0) { + return rc; + } + + flash_mspi_command_set(dev, &dev_config->jedec_cmds->page_program); dev_data->packet.address = addr; dev_data->packet.data_buf = (uint8_t *)src; dev_data->packet.num_bytes = to_write; @@ -485,7 +295,7 @@ static int api_write(const struct device *dev, off_t addr, const void *src, src = (const uint8_t *)src + to_write; size -= to_write; - rc = wait_until_ready(dev, &dev_config->mspi_nor_cfg, K_MSEC(1)); + rc = wait_until_ready(dev, K_MSEC(1)); if (rc < 0) { break; } @@ -515,7 +325,7 @@ static int api_erase(const struct device *dev, off_t addr, size_t size) return -EINVAL; } - rc = acquire(dev, &dev_config->mspi_nor_init_cfg); + rc = acquire(dev); if (rc < 0) { return rc; } @@ -529,11 +339,31 @@ static int api_erase(const struct device *dev, off_t addr, size_t size) if (size == flash_size) { /* Chip erase. */ - command_set(dev, &dev_config->jedec_cmds->chip_erase); + if (dev_config->jedec_cmds->chip_erase.force_single) { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); + } else { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + } + + if (rc < 0) { + return rc; + } + + flash_mspi_command_set(dev, &dev_config->jedec_cmds->chip_erase); size -= flash_size; } else { /* Sector erase. */ - command_set(dev, &dev_config->jedec_cmds->sector_erase); + if (dev_config->jedec_cmds->sector_erase.force_single) { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); + } else { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + } + + if (rc < 0) { + return rc; + } + + flash_mspi_command_set(dev, &dev_config->jedec_cmds->sector_erase); dev_data->packet.address = addr; addr += SPI_NOR_SECTOR_SIZE; size -= SPI_NOR_SECTOR_SIZE; @@ -546,7 +376,7 @@ static int api_erase(const struct device *dev, off_t addr, size_t size) break; } - rc = wait_until_ready(dev, &dev_config->mspi_nor_init_cfg, K_MSEC(1)); + rc = wait_until_ready(dev, K_MSEC(1)); if (rc < 0) { break; } @@ -576,14 +406,24 @@ static int read_jedec_id(const struct device *dev, uint8_t *id) struct flash_mspi_nor_data *dev_data = dev->data; int rc; - command_set(dev, &dev_config->jedec_cmds->id); + if (dev_config->jedec_cmds->id.force_single) { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); + } else { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + } + + if (rc < 0) { + return rc; + } + + flash_mspi_command_set(dev, &dev_config->jedec_cmds->id); dev_data->packet.data_buf = id; dev_data->packet.num_bytes = JESD216_READ_ID_LEN; rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); if (rc < 0) { - LOG_ERR("mspi_transceive() failed: %d\n", rc); + LOG_ERR("Read JEDEC ID failed: %d\n", rc); } return rc; @@ -613,20 +453,29 @@ static int api_sfdp_read(const struct device *dev, off_t addr, void *dest, return 0; } - rc = acquire(dev, dev_config->jedec_cmds->sfdp.force_single ? - &dev_config->mspi_nor_init_cfg : &dev_config->mspi_nor_cfg); + rc = acquire(dev); + if (rc < 0) { + return rc; + } + + if (dev_config->jedec_cmds->sfdp.force_single) { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); + } else { + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + } + if (rc < 0) { return rc; } - command_set(dev, &dev_config->jedec_cmds->sfdp); + flash_mspi_command_set(dev, &dev_config->jedec_cmds->sfdp); dev_data->packet.address = addr; dev_data->packet.data_buf = dest; dev_data->packet.num_bytes = size; rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); if (rc < 0) { - printk("JESD216_OCMD_READ_SFDP xfer failed: %d\n", rc); + printk("Read SFDP xfer failed: %d\n", rc); return rc; } @@ -637,10 +486,7 @@ static int api_sfdp_read(const struct device *dev, off_t addr, void *dest, static int api_read_jedec_id(const struct device *dev, uint8_t *id) { - const struct flash_mspi_nor_config *dev_config = dev->config; - - int rc = acquire(dev, dev_config->jedec_cmds->id.force_single ? - &dev_config->mspi_nor_init_cfg : &dev_config->mspi_nor_cfg); + int rc = acquire(dev); if (rc < 0) { return rc; } @@ -668,70 +514,165 @@ static int dev_pm_action_cb(const struct device *dev, return 0; } -static int switch_mode(const struct device *dev, uint8_t *id) +static int quad_enable_set(const struct device *dev, bool enable) { const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; + int rc; - /* For octal mode: - * If the read ID does not match the one from DTS, assume the flash - * is already in the Octa I/O mode, so switching it is not needed. - */ - if ((dev_config->mspi_nor_cfg.io_mode == MSPI_IO_MODE_OCTAL) && - (memcmp(id, dev_config->jedec_id, JESD216_READ_ID_LEN) != 0)) { - return 0; - } - - command_set(dev, &commands[MSPI_IO_MODE_SINGLE].write_en); - int rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, + flash_mspi_command_set(dev, &commands[MSPI_IO_MODE_SINGLE].write_en); + rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); if (rc < 0) { LOG_ERR("Failed to set write enable: %d", rc); return rc; } - command_set(dev, &dev_config->jedec_cmds->mode_change); + if (dev_config->dw15_qer == JESD216_DW15_QER_VAL_S1B6) { + const struct flash_mspi_nor_cmd cmd_status = { + .dir = MSPI_TX, + .cmd = SPI_NOR_CMD_WRSR, + .cmd_length = 1, + }; + uint8_t mode_payload = enable ? BIT(6) : 0; - /* MX25R specific: - * For quad io mode above 8 MHz and single io mode above 33 MHz, - * high performance mode needs to be enabled. - */ - if (((dev_config->mspi_nor_cfg.io_mode == MSPI_IO_MODE_QUAD_1_4_4) && - (dev_config->mspi_nor_cfg.freq > MHZ(8))) || - ((dev_config->mspi_nor_cfg.io_mode == MSPI_IO_MODE_SINGLE) && - (dev_config->mspi_nor_cfg.freq > MHZ(33)))) { - dev_data->packet.data_buf = hp_payload; - dev_data->packet.num_bytes = sizeof(hp_payload); + flash_mspi_command_set(dev, &cmd_status); + dev_data->packet.data_buf = &mode_payload; + dev_data->packet.num_bytes = sizeof(mode_payload); + rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + + if (rc < 0) { + LOG_ERR("Failed to enable/disable quad mode: %d", rc); + return rc; + } } else { - dev_data->packet.data_buf = (uint8_t *)&dev_config->jedec_cmds->mode_payload; - dev_data->packet.num_bytes = sizeof(dev_config->jedec_cmds->mode_payload); + /* TODO: handle all DW15 QER values */ + return -ENOTSUP; } - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + rc = wait_until_ready(dev, K_USEC(1)); + + if (rc < 0) { + LOG_ERR("Failed waiting until device ready after enabling quad: %d", rc); + return rc; + } + + return 0; +} + + +static int default_io_mode(const struct device *dev) +{ + const struct flash_mspi_nor_config *dev_config = dev->config; + enum mspi_io_mode io_mode = dev_config->mspi_nor_cfg.io_mode; + int rc = 0; + + /* For Quad 1-1-4 and 1-4-4, entering or leaving mode is defined in JEDEC216 BFP DW15 QER */ + if (io_mode == MSPI_IO_MODE_SINGLE) { + rc = quad_enable_set(dev, false); + } else if ((io_mode == MSPI_IO_MODE_QUAD_1_1_4) || (io_mode == MSPI_IO_MODE_QUAD_1_4_4)) { + rc = quad_enable_set(dev, true); + } + + if (rc < 0) { + LOG_ERR("Failed to modify Quad Enable bit: %d", rc); + } + + if ((dev_config->quirks != NULL) && (dev_config->quirks->post_switch_mode != NULL)) { + rc = dev_config->quirks->post_switch_mode(dev); + } if (rc < 0) { LOG_ERR("Failed to change IO mode: %d\n", rc); return rc; } + return dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); +} + +#if defined(WITH_RESET_GPIO) +static int gpio_reset(const struct device *dev) +{ + const struct flash_mspi_nor_config *dev_config = dev->config; + int rc; + + if (dev_config->reset.port) { + if (!gpio_is_ready_dt(&dev_config->reset)) { + LOG_ERR("Device %s is not ready", + dev_config->reset.port->name); + return -ENODEV; + } + + rc = gpio_pin_configure_dt(&dev_config->reset, + GPIO_OUTPUT_ACTIVE); + if (rc < 0) { + LOG_ERR("Failed to activate RESET: %d", rc); + return -EIO; + } + + if (dev_config->reset_pulse_us != 0) { + k_busy_wait(dev_config->reset_pulse_us); + } + + rc = gpio_pin_set_dt(&dev_config->reset, 0); + if (rc < 0) { + LOG_ERR("Failed to deactivate RESET: %d", rc); + return -EIO; + } + + if (dev_config->reset_recovery_us != 0) { + k_busy_wait(dev_config->reset_recovery_us); + } + } + return 0; } +#endif static int flash_chip_init(const struct device *dev) { const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; + enum mspi_io_mode io_mode = dev_config->mspi_nor_cfg.io_mode; uint8_t id[JESD216_READ_ID_LEN] = {0}; int rc; - rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, - MSPI_DEVICE_CONFIG_ALL, &dev_config->mspi_nor_init_cfg); + rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); + if (rc < 0) { - LOG_ERR("Failed to set initial device config: %d", rc); return rc; } - command_set(dev, &commands[MSPI_IO_MODE_SINGLE].id); + /* Some chips reuse RESET pin for data in Quad modes: + * force single line mode before resetting. + */ + if ((io_mode == MSPI_IO_MODE_SINGLE) || (io_mode == MSPI_IO_MODE_QUAD_1_1_4) || + (io_mode == MSPI_IO_MODE_QUAD_1_4_4)) { + rc = quad_enable_set(dev, false); + + if (rc < 0) { + LOG_ERR("Failed to switch to single line mode: %d", rc); + return rc; + } + + rc = wait_until_ready(dev, K_USEC(1)); + + if (rc < 0) { + LOG_ERR("Failed waiting for device after switch to single line: %d", rc); + return rc; + } + } + +#if defined(WITH_RESET_GPIO) + rc = gpio_reset(dev); + + if (rc < 0) { + LOG_ERR("Failed to reset with GPIO: %d", rc); + return rc; + } +#endif + + flash_mspi_command_set(dev, &commands[MSPI_IO_MODE_SINGLE].id); dev_data->packet.data_buf = id; dev_data->packet.num_bytes = sizeof(id); @@ -742,26 +683,22 @@ static int flash_chip_init(const struct device *dev) return rc; } - rc = switch_mode(dev, id); + rc = default_io_mode(dev); if (rc < 0) { - LOG_ERR("Failed to switch mode: %d", rc); + LOG_ERR("Failed to switch to default io mode: %d", rc); return rc; } - rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, - MSPI_DEVICE_CONFIG_ALL, - dev_config->jedec_cmds->id.force_single ? - &dev_config->mspi_nor_init_cfg : &dev_config->mspi_nor_cfg); - if (rc < 0) { - LOG_ERR("Failed to set device config: %d", rc); - return rc; - } - - rc = read_jedec_id(dev, id); - if (rc < 0) { - LOG_ERR("Failed to read JEDEC ID in final line mode: %d", rc); - return rc; + /* Reading JEDEC ID for mode that forces single lane would be redundant, + * since it switches back to single lane mode. Use ID from previous read. + */ + if (!dev_config->jedec_cmds->id.force_single) { + rc = read_jedec_id(dev, id); + if (rc < 0) { + LOG_ERR("Failed to read JEDEC ID in final line mode: %d", rc); + return rc; + } } if (memcmp(id, dev_config->jedec_id, sizeof(id)) != 0) { @@ -799,37 +736,6 @@ static int drv_init(const struct device *dev) return -ENODEV; } -#if defined(WITH_RESET_GPIO) - if (dev_config->reset.port) { - if (!gpio_is_ready_dt(&dev_config->reset)) { - LOG_ERR("Device %s is not ready", - dev_config->reset.port->name); - return -ENODEV; - } - - rc = gpio_pin_configure_dt(&dev_config->reset, - GPIO_OUTPUT_ACTIVE); - if (rc < 0) { - LOG_ERR("Failed to activate RESET: %d", rc); - return -EIO; - } - - if (dev_config->reset_pulse_us != 0) { - k_busy_wait(dev_config->reset_pulse_us); - } - - rc = gpio_pin_set_dt(&dev_config->reset, 0); - if (rc < 0) { - LOG_ERR("Failed to deactivate RESET: %d", rc); - return -EIO; - } - - if (dev_config->reset_recovery_us != 0) { - k_busy_wait(dev_config->reset_recovery_us); - } - } -#endif - rc = pm_device_runtime_get(dev_config->bus); if (rc < 0) { LOG_ERR("pm_device_runtime_get() failed: %d", rc); @@ -882,6 +788,13 @@ static DEVICE_API(flash, drv_api) = { #define FLASH_SIZE_INST(inst) (DT_INST_PROP(inst, size) / 8) #define FLASH_CMDS(inst) &commands[DT_INST_ENUM_IDX(inst, mspi_io_mode)] +#define FLASH_QUIRKS(inst) FLASH_MSPI_QUIRKS_GET(DT_DRV_INST(inst)) + +#define FLASH_DW15_QER_VAL(inst) _CONCAT(JESD216_DW15_QER_VAL_, \ + DT_INST_STRING_TOKEN(inst, quad_enable_requirements)) +#define FLASH_DW15_QER(inst) COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, quad_enable_requirements), \ + (FLASH_DW15_QER_VAL(inst)), (JESD216_DW15_QER_VAL_NONE)) + #if defined(CONFIG_FLASH_PAGE_LAYOUT) BUILD_ASSERT((CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE % 4096) == 0, @@ -938,6 +851,8 @@ BUILD_ASSERT((FLASH_SIZE_INST(inst) % CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE) == FLASH_PAGE_LAYOUT_DEFINE(inst) \ .jedec_id = DT_INST_PROP(inst, jedec_id), \ .jedec_cmds = FLASH_CMDS(inst), \ + .quirks = FLASH_QUIRKS(inst), \ + .dw15_qer = FLASH_DW15_QER(inst), \ }; \ FLASH_PAGE_LAYOUT_CHECK(inst) \ DEVICE_DT_INST_DEFINE(inst, \ diff --git a/drivers/flash/flash_mspi_nor.h b/drivers/flash/flash_mspi_nor.h new file mode 100644 index 000000000000..42489606ffe1 --- /dev/null +++ b/drivers/flash/flash_mspi_nor.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __FLASH_MSPI_NOR_H__ +#define __FLASH_MSPI_NOR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "jesd216.h" +#include "spi_nor.h" + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) +#define WITH_RESET_GPIO 1 +#endif + +struct flash_mspi_nor_config { + const struct device *bus; + uint32_t flash_size; + struct mspi_dev_id mspi_id; + struct mspi_dev_cfg mspi_nor_cfg; + struct mspi_dev_cfg mspi_nor_init_cfg; + enum mspi_dev_cfg_mask mspi_nor_cfg_mask; +#if defined(CONFIG_MSPI_XIP) + struct mspi_xip_cfg xip_cfg; +#endif +#if defined(WITH_RESET_GPIO) + struct gpio_dt_spec reset; + uint32_t reset_pulse_us; + uint32_t reset_recovery_us; +#endif +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + struct flash_pages_layout layout; +#endif + uint8_t jedec_id[SPI_NOR_MAX_ID_LEN]; + struct flash_mspi_nor_cmds *jedec_cmds; + struct flash_mspi_nor_quirks *quirks; + uint8_t dw15_qer; +}; + +struct flash_mspi_nor_data { + struct k_sem acquired; + struct mspi_xfer_packet packet; + struct mspi_xfer xfer; + struct mspi_dev_cfg *curr_cfg; +}; + +struct flash_mspi_nor_cmd { + enum mspi_xfer_direction dir; + uint32_t cmd; + uint16_t tx_dummy; + uint16_t rx_dummy; + uint8_t cmd_length; + uint8_t addr_length; + bool force_single; +}; + +struct flash_mspi_nor_cmds { + struct flash_mspi_nor_cmd id; + struct flash_mspi_nor_cmd write_en; + struct flash_mspi_nor_cmd read; + struct flash_mspi_nor_cmd status; + struct flash_mspi_nor_cmd config; + struct flash_mspi_nor_cmd page_program; + struct flash_mspi_nor_cmd sector_erase; + struct flash_mspi_nor_cmd chip_erase; + struct flash_mspi_nor_cmd sfdp; +}; + +struct flash_mspi_nor_cmds commands[] = { + [MSPI_IO_MODE_SINGLE] = { + .id = { + .dir = MSPI_RX, + .cmd = JESD216_CMD_READ_ID, + .cmd_length = 1, + }, + .write_en = { + .dir = MSPI_TX, + .cmd = SPI_NOR_CMD_WREN, + .cmd_length = 1, + }, + .read = { + .dir = MSPI_RX, + .cmd = SPI_NOR_CMD_READ_FAST, + .cmd_length = 1, + .addr_length = 3, + .rx_dummy = 8, + }, + .status = { + .dir = MSPI_RX, + .cmd = SPI_NOR_CMD_RDSR, + .cmd_length = 1, + }, + .config = { + .dir = MSPI_RX, + .cmd = SPI_NOR_CMD_RDCR, + .cmd_length = 1, + }, + .page_program = { + .dir = MSPI_TX, + .cmd = SPI_NOR_CMD_PP, + .cmd_length = 1, + .addr_length = 3, + }, + .sector_erase = { + .dir = MSPI_TX, + .cmd = SPI_NOR_CMD_SE, + .cmd_length = 1, + .addr_length = 3, + }, + .chip_erase = { + .dir = MSPI_TX, + .cmd = SPI_NOR_CMD_CE, + .cmd_length = 1, + }, + .sfdp = { + .dir = MSPI_RX, + .cmd = JESD216_CMD_READ_SFDP, + .cmd_length = 1, + .addr_length = 3, + .rx_dummy = 8, + }, + }, + [MSPI_IO_MODE_QUAD_1_4_4] = { + .id = { + .dir = MSPI_RX, + .cmd = JESD216_CMD_READ_ID, + .cmd_length = 1, + .force_single = true, + }, + .write_en = { + .dir = MSPI_TX, + .cmd = SPI_NOR_CMD_WREN, + .cmd_length = 1, + }, + .read = { + .dir = MSPI_RX, + .cmd = SPI_NOR_CMD_4READ, + .cmd_length = 1, + .addr_length = 3, + .rx_dummy = 6, + }, + .status = { + .dir = MSPI_RX, + .cmd = SPI_NOR_CMD_RDSR, + .cmd_length = 1, + .force_single = true, + }, + .config = { + .dir = MSPI_RX, + .cmd = SPI_NOR_CMD_RDCR, + .cmd_length = 1, + .force_single = true, + }, + .page_program = { + .dir = MSPI_TX, + .cmd = SPI_NOR_CMD_PP_1_4_4, + .cmd_length = 1, + .addr_length = 3, + }, + .sector_erase = { + .dir = MSPI_TX, + .cmd = SPI_NOR_CMD_SE, + .cmd_length = 1, + .addr_length = 3, + .force_single = true, + }, + .chip_erase = { + .dir = MSPI_TX, + .cmd = SPI_NOR_CMD_CE, + .cmd_length = 1, + }, + .sfdp = { + .dir = MSPI_RX, + .cmd = JESD216_CMD_READ_SFDP, + .cmd_length = 1, + .addr_length = 3, + .rx_dummy = 8, + .force_single = true, + }, + }, + [MSPI_IO_MODE_OCTAL] = { + .id = { + .dir = MSPI_RX, + .cmd = JESD216_OCMD_READ_ID, + .cmd_length = 2, + .addr_length = 4, + .rx_dummy = 4 + }, + .write_en = { + .dir = MSPI_TX, + .cmd = SPI_NOR_OCMD_WREN, + .cmd_length = 2, + }, + .read = { + .dir = MSPI_RX, + .cmd = SPI_NOR_OCMD_RD, + .cmd_length = 2, + .addr_length = 4, + .rx_dummy = 20, + }, + .status = { + .dir = MSPI_RX, + .cmd = SPI_NOR_OCMD_RDSR, + .cmd_length = 2, + .addr_length = 4, + .rx_dummy = 4, + }, + .page_program = { + .dir = MSPI_TX, + .cmd = SPI_NOR_OCMD_PAGE_PRG, + .cmd_length = 2, + .addr_length = 4, + }, + .sector_erase = { + .dir = MSPI_TX, + .cmd = SPI_NOR_OCMD_SE, + .cmd_length = 2, + .addr_length = 4, + }, + .chip_erase = { + .dir = MSPI_TX, + .cmd = SPI_NOR_OCMD_CE, + .cmd_length = 2, + }, + .sfdp = { + .dir = MSPI_RX, + .cmd = JESD216_OCMD_READ_SFDP, + .cmd_length = 2, + .addr_length = 4, + .rx_dummy = 20, + }, + }, +}; + +void flash_mspi_command_set(const struct device *dev, const struct flash_mspi_nor_cmd *cmd); + +#ifdef __cplusplus +} +#endif + +#endif /*__FLASH_MSPI_NOR_H__*/ diff --git a/drivers/flash/flash_mspi_nor_quirks.h b/drivers/flash/flash_mspi_nor_quirks.h new file mode 100644 index 000000000000..ba840bd79266 --- /dev/null +++ b/drivers/flash/flash_mspi_nor_quirks.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __FLASH_MSPI_NOR_QUIRKS_H__ +#define __FLASH_MSPI_NOR_QUIRKS_H__ + +/* Flash chip specific quirks */ +struct flash_mspi_nor_quirks { + /* Called after switching to default IO mode. */ + int (*post_switch_mode)(const struct device *dev); +}; + +/* Extend this macro when adding new flash chip with quirks */ +#define FLASH_MSPI_QUIRKS_GET(node) \ + COND_CODE_1(DT_NODE_HAS_COMPAT_STATUS(node, mxicy_mx25r, okay), \ + (&flash_quirks_mxicy_mx25r), \ + (COND_CODE_1(DT_NODE_HAS_COMPAT_STATUS(node, mxicy_mx25u, okay), \ + (&flash_quirks_mxicy_mx25u), \ + (NULL)))) + +#if DT_HAS_COMPAT_STATUS_OKAY(mxicy_mx25r) + +#define MXICY_MX25R_LH_MASK BIT(1) +#define MXICY_MX25R_QE_MASK BIT(6) +#define MXICY_MX25R_REGS_LEN 3 + +static uint8_t mxicy_mx25r_hp_payload[MXICY_MX25R_REGS_LEN] = { + MXICY_MX25R_QE_MASK, 0x0, MXICY_MX25R_LH_MASK +}; + +/* For quad io mode above 8 MHz and single io mode above 33 MHz, + * high performance mode needs to be enabled. + */ +static inline bool needs_hp(enum mspi_io_mode io_mode, uint32_t freq) +{ + if ((io_mode == MSPI_IO_MODE_QUAD_1_1_4) || (io_mode == MSPI_IO_MODE_QUAD_1_4_4)) { + if (freq > MHZ(8)) { + return true; + } + } else if (io_mode == MSPI_IO_MODE_SINGLE) { + if (freq > MHZ(33)) { + return true; + } + } + + return false; +} + +static inline int mxicy_mx25r_post_switch_mode(const struct device *dev) +{ + const struct flash_mspi_nor_config *dev_config = dev->config; + struct flash_mspi_nor_data *dev_data = dev->data; + enum mspi_io_mode io_mode = dev_config->mspi_nor_cfg.io_mode; + uint32_t freq = dev_config->mspi_nor_cfg.freq; + int rc; + uint8_t status; + uint8_t config[MXICY_MX25R_REGS_LEN - 1]; + + if (!needs_hp(io_mode, freq)) { + return 0; + } + + /* Wait for previous write to finish */ + do { + flash_mspi_command_set(dev, &dev_config->jedec_cmds->status); + dev_data->packet.data_buf = &status; + dev_data->packet.num_bytes = sizeof(status); + rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + if (rc < 0) { + return rc; + } + } while (status & SPI_NOR_WIP_BIT); + + /* Write enable */ + flash_mspi_command_set(dev, &commands[MSPI_IO_MODE_SINGLE].write_en); + rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, + &dev_data->xfer); + if (rc < 0) { + return rc; + } + + /* Write status and config registers */ + const struct flash_mspi_nor_cmd cmd_status = { + .dir = MSPI_TX, + .cmd = SPI_NOR_CMD_WRSR, + .cmd_length = 1, + }; + + flash_mspi_command_set(dev, &cmd_status); + dev_data->packet.data_buf = mxicy_mx25r_hp_payload; + dev_data->packet.num_bytes = sizeof(mxicy_mx25r_hp_payload); + rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + if (rc < 0) { + return rc; + } + + /* Wait for write to end and verify status register */ + do { + flash_mspi_command_set(dev, &dev_config->jedec_cmds->status); + dev_data->packet.data_buf = &status; + dev_data->packet.num_bytes = sizeof(status); + rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + if (rc < 0) { + return rc; + } + } while (status & SPI_NOR_WIP_BIT); + + if (status != mxicy_mx25r_hp_payload[0]) { + return -EIO; + } + + /* Verify configuration registers */ + flash_mspi_command_set(dev, &dev_config->jedec_cmds->config); + dev_data->packet.data_buf = config; + dev_data->packet.num_bytes = sizeof(config); + rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + if (rc < 0) { + return rc; + } + + for (uint8_t i = 0; i < MXICY_MX25R_REGS_LEN - 1; i++) { + if (config[i] != mxicy_mx25r_hp_payload[i + 1]) { + return -EIO; + } + } + + return 0; +} + +struct flash_mspi_nor_quirks flash_quirks_mxicy_mx25r = { + .post_switch_mode = mxicy_mx25r_post_switch_mode, +}; + +#endif /* DT_HAS_COMPAT_STATUS_OKAY(mxicy_mx25r) */ + +#if DT_HAS_COMPAT_STATUS_OKAY(mxicy_mx25u) + +#define MXICY_MX25R_OE_MASK BIT(0) + +static uint8_t mxicy_mx25u_oe_payload = MXICY_MX25R_OE_MASK; + +static inline int mxicy_mx25u_post_switch_mode(const struct device *dev) +{ + const struct flash_mspi_nor_config *dev_config = dev->config; + struct flash_mspi_nor_data *dev_data = dev->data; + enum mspi_io_mode io_mode = dev_config->mspi_nor_cfg.io_mode; + int rc; + + if (io_mode != MSPI_IO_MODE_OCTAL) { + return 0; + } + + /* Write enable */ + flash_mspi_command_set(dev, &commands[MSPI_IO_MODE_SINGLE].write_en); + rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, + &dev_data->xfer); + if (rc < 0) { + return rc; + } + + /* Write config register 2 */ + const struct flash_mspi_nor_cmd cmd_status = { + .dir = MSPI_TX, + .cmd = SPI_NOR_CMD_WR_CFGREG2, + .cmd_length = 1, + .addr_length = 4, + }; + + flash_mspi_command_set(dev, &cmd_status); + dev_data->packet.data_buf = &mxicy_mx25u_oe_payload; + dev_data->packet.num_bytes = sizeof(mxicy_mx25u_oe_payload); + rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + return rc; +} + +struct flash_mspi_nor_quirks flash_quirks_mxicy_mx25u = { + .post_switch_mode = mxicy_mx25u_post_switch_mode, +}; + +#endif /* DT_HAS_COMPAT_STATUS_OKAY(mxicy_mx25u) */ + +#endif /*__FLASH_MSPI_NOR_QUIRKS_H__*/ diff --git a/drivers/flash/spi_nor.h b/drivers/flash/spi_nor.h index 141b67718ef1..a918e0a99d05 100644 --- a/drivers/flash/spi_nor.h +++ b/drivers/flash/spi_nor.h @@ -14,7 +14,6 @@ /* Status register bits */ #define SPI_NOR_WIP_BIT BIT(0) /* Write in progress */ #define SPI_NOR_WEL_BIT BIT(1) /* Write enable latch */ -#define SPI_NOR_QE_BIT BIT(6) /* Quad enable */ /* Flash opcodes */ #define SPI_NOR_CMD_WRSR 0x01 /* Write status register */ diff --git a/drivers/misc/nordic_vpr_launcher/Kconfig b/drivers/misc/nordic_vpr_launcher/Kconfig index 6aeabcd251c1..d00bcc583f96 100644 --- a/drivers/misc/nordic_vpr_launcher/Kconfig +++ b/drivers/misc/nordic_vpr_launcher/Kconfig @@ -4,7 +4,8 @@ config NORDIC_VPR_LAUNCHER bool "Nordic VPR coprocessor launcher" default y - depends on DT_HAS_NORDIC_NRF_VPR_COPROCESSOR_ENABLED + depends on DT_HAS_NORDIC_NRF_VPR_COPROCESSOR_ENABLED && \ + $(dt_compat_any_has_prop,$(DT_COMPAT_NORDIC_NRF_VPR_COPROCESSOR),execution-memory) help When enabled, the VPR coprocessors will be automatically launched during system initialization. diff --git a/drivers/misc/nordic_vpr_launcher/nordic_vpr_launcher.c b/drivers/misc/nordic_vpr_launcher/nordic_vpr_launcher.c index 5bd43f87fb91..b28ebec6b5c9 100644 --- a/drivers/misc/nordic_vpr_launcher/nordic_vpr_launcher.c +++ b/drivers/misc/nordic_vpr_launcher/nordic_vpr_launcher.c @@ -34,6 +34,11 @@ static int nordic_vpr_launcher_init(const struct device *dev) { const struct nordic_vpr_launcher_config *config = dev->config; + /* Do nothing if execution memory is not specified for a given VPR. */ + if (config->exec_addr == 0) { + return 0; + } + #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(source_memory) if (config->size > 0U) { LOG_DBG("Loading VPR (%p) from %p to %p (%zu bytes)", config->vpr, @@ -63,16 +68,20 @@ static int nordic_vpr_launcher_init(const struct device *dev) (DT_REG_ADDR(node_id) + \ COND_CODE_0(DT_FIXED_PARTITION_EXISTS(node_id), (0), (DT_REG_ADDR(DT_GPARENT(node_id))))) +#define NEEDS_COPYING(inst) UTIL_AND(DT_INST_NODE_HAS_PROP(inst, execution_memory), \ + DT_INST_NODE_HAS_PROP(inst, source_memory)) + #define NORDIC_VPR_LAUNCHER_DEFINE(inst) \ - IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, source_memory), \ + IF_ENABLED(NEEDS_COPYING(inst), \ (BUILD_ASSERT((DT_REG_SIZE(DT_INST_PHANDLE(inst, execution_memory)) <= \ DT_REG_SIZE(DT_INST_PHANDLE(inst, source_memory))), \ "Execution memory exceeds source memory size");)) \ \ static const struct nordic_vpr_launcher_config config##inst = { \ .vpr = (NRF_VPR_Type *)DT_INST_REG_ADDR(inst), \ - .exec_addr = VPR_ADDR(DT_INST_PHANDLE(inst, execution_memory)), \ - IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, source_memory), \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, execution_memory), \ + (.exec_addr = VPR_ADDR(DT_INST_PHANDLE(inst, execution_memory)),)) \ + IF_ENABLED(NEEDS_COPYING(inst), \ (.src_addr = VPR_ADDR(DT_INST_PHANDLE(inst, source_memory)), \ .size = DT_REG_SIZE(DT_INST_PHANDLE(inst, execution_memory)),))}; \ \ diff --git a/drivers/pinctrl/pinctrl_nrf.c b/drivers/pinctrl/pinctrl_nrf.c index 3f909b3e9906..5e4cd6fb549e 100644 --- a/drivers/pinctrl/pinctrl_nrf.c +++ b/drivers/pinctrl/pinctrl_nrf.c @@ -112,12 +112,17 @@ static const nrf_gpio_pin_drive_t drive_modes[NRF_DRIVE_COUNT] = { #define NRF_PSEL_TDM(reg, line) ((NRF_TDM_Type *)reg)->PSEL.line #endif -#if defined(CONFIG_SOC_NRF54L15_CPUAPP) -#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrfe_mspi_controller) || defined(CONFIG_MSPI_NRFE) -#define NRF_PSEL_SDP_MSPI(psel) \ +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrfe_mspi_controller) || \ + defined(CONFIG_MSPI_NRFE) || \ + DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(nordic_nrf_vpr_coprocessor, pinctrl_0) +#if defined(CONFIG_SOC_SERIES_NRF54LX) +#define NRF_PSEL_SDP_MSPI(psel) \ nrf_gpio_pin_control_select(psel, NRF_GPIO_PIN_SEL_VPR); +#elif defined(CONFIG_SOC_SERIES_NRF54HX) +/* On nRF54H, pin routing is controlled by secure domain, via UICR. */ +#define NRF_PSEL_SDP_MSPI(psel) #endif -#endif +#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrfe_mspi_controller) || ... */ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) @@ -472,8 +477,7 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, input = NRF_GPIO_PIN_INPUT_CONNECT; break; #endif /* defined(NRF_PSEL_TWIS) */ -#if defined(CONFIG_SOC_NRF54L15_CPUAPP) -#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrfe_mspi_controller) +#if defined(NRF_PSEL_SDP_MSPI) case NRF_FUN_SDP_MSPI_CS0: case NRF_FUN_SDP_MSPI_CS1: case NRF_FUN_SDP_MSPI_CS2: @@ -492,8 +496,7 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, dir = NRF_GPIO_PIN_DIR_OUTPUT; input = NRF_GPIO_PIN_INPUT_CONNECT; break; -#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrfe_mspi_controller) */ -#endif /* CONFIG_SOC_NRF54L15_CPUAPP */ +#endif /* defined(NRF_PSEL_SDP_MSPI) */ default: return -ENOTSUP; } diff --git a/drivers/usb/udc/udc_ambiq.c b/drivers/usb/udc/udc_ambiq.c index f6f342fc21cd..11d26865df1e 100644 --- a/drivers/usb/udc/udc_ambiq.c +++ b/drivers/usb/udc/udc_ambiq.c @@ -96,13 +96,14 @@ static int usbd_ctrl_feed_dout(const struct device *dev, const size_t length) static int udc_ambiq_tx(const struct device *dev, uint8_t ep, struct net_buf *buf) { const struct udc_ambiq_data *priv = udc_get_private(dev); + struct udc_ep_config *cfg = udc_get_ep_cfg(dev, ep); uint32_t status; - if (udc_ep_is_busy(dev, ep)) { + if (udc_ep_is_busy(cfg)) { LOG_WRN("ep 0x%02x is busy!", ep); return 0; } - udc_ep_set_busy(dev, ep, true); + udc_ep_set_busy(cfg, true); /* buf equals NULL is used as indication of ZLP request */ if (buf == NULL) { @@ -112,7 +113,7 @@ static int udc_ambiq_tx(const struct device *dev, uint8_t ep, struct net_buf *bu } if (status != AM_HAL_STATUS_SUCCESS) { - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(cfg, false); LOG_ERR("am_hal_usb_ep_xfer write failed(0x%02x), %d", ep, (int)status); return -EIO; } @@ -123,15 +124,16 @@ static int udc_ambiq_tx(const struct device *dev, uint8_t ep, struct net_buf *bu static int udc_ambiq_rx(const struct device *dev, uint8_t ep, struct net_buf *buf) { struct udc_ambiq_data *priv = udc_get_private(dev); + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep); struct udc_ep_config *cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); uint32_t status; uint16_t rx_size = buf->size; - if (udc_ep_is_busy(dev, ep)) { + if (udc_ep_is_busy(ep_cfg)) { LOG_WRN("ep 0x%02x is busy!", ep); return 0; } - udc_ep_set_busy(dev, ep, true); + udc_ep_set_busy(ep_cfg, true); /* Make sure that OUT transaction size triggered doesn't exceed EP's MPS */ if ((ep != USB_CONTROL_EP_OUT) && (cfg->mps < rx_size)) { @@ -140,7 +142,7 @@ static int udc_ambiq_rx(const struct device *dev, uint8_t ep, struct net_buf *bu status = am_hal_usb_ep_xfer(priv->usb_handle, ep, buf->data, rx_size); if (status != AM_HAL_STATUS_SUCCESS) { - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(ep_cfg, false); LOG_ERR("am_hal_usb_ep_xfer read(rx) failed(0x%02x), %d", ep, (int)status); return -EIO; } @@ -223,7 +225,9 @@ static void udc_ambiq_ep_xfer_complete_callback(const struct device *dev, uint8_ if (USB_EP_DIR_IS_IN(ep_addr)) { evt.type = UDC_AMBIQ_EVT_HAL_IN_CMP; } else { - buf = udc_buf_peek(dev, ep_addr); + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep_addr); + + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { LOG_ERR("No buffer for ep 0x%02x", ep_addr); udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); @@ -281,12 +285,12 @@ static int udc_ambiq_ep_dequeue(const struct device *dev, struct udc_ep_config * lock_key = irq_lock(); - buf = udc_buf_get_all(dev, ep_cfg->addr); + buf = udc_buf_get_all(ep_cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } - udc_ep_set_busy(dev, ep_cfg->addr, false); + udc_ep_set_busy(ep_cfg, false); am_hal_usb_ep_state_reset(priv->usb_handle, ep_cfg->addr); irq_unlock(lock_key); @@ -320,7 +324,7 @@ static int udc_ambiq_ep_clear_halt(const struct device *dev, struct udc_ep_confi ep_cfg->stat.halted = false; /* Resume queued transfer if any */ - if (udc_buf_peek(dev, ep_cfg->addr)) { + if (udc_buf_peek(ep_cfg)) { struct udc_ambiq_event evt = { .ep = ep_cfg->addr, .type = UDC_AMBIQ_EVT_XFER, @@ -647,14 +651,14 @@ static inline void ambiq_handle_evt_dout(const struct device *dev, struct udc_ep struct net_buf *buf; /* retrieve endpoint buffer */ - buf = udc_buf_get(dev, cfg->addr); + buf = udc_buf_get(cfg); if (buf == NULL) { LOG_ERR("No buffer queued for control ep"); return; } /* Clear endpoint busy status */ - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); /* Handle transfer complete event */ if (cfg->addr == USB_CONTROL_EP_OUT) { @@ -686,9 +690,9 @@ static void ambiq_handle_evt_din(const struct device *dev, struct udc_ep_config bool udc_ambiq_rx_status_in_completed = false; /* Clear endpoint busy status */ - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); /* Check and Handle ZLP flag */ - buf = udc_buf_peek(dev, cfg->addr); + buf = udc_buf_peek(cfg); if (cfg->addr != USB_CONTROL_EP_IN) { if (udc_ep_buf_has_zlp(buf)) { udc_ep_buf_clear_zlp(buf); @@ -699,7 +703,7 @@ static void ambiq_handle_evt_din(const struct device *dev, struct udc_ep_config } /* retrieve endpoint buffer */ - buf = udc_buf_get(dev, cfg->addr); + buf = udc_buf_get(cfg); if (buf == NULL) { LOG_ERR("No buffer queued for control ep"); return; @@ -754,7 +758,7 @@ static void udc_event_xfer(const struct device *dev, struct udc_ep_config *const { struct net_buf *buf; - buf = udc_buf_peek(dev, cfg->addr); + buf = udc_buf_peek(cfg); if (buf == NULL) { LOG_ERR("No buffer for ep 0x%02x", cfg->addr); return; diff --git a/drivers/usb/udc/udc_common.c b/drivers/usb/udc/udc_common.c index 9429c404ad60..3718290ce42e 100644 --- a/drivers/usb/udc/udc_common.c +++ b/drivers/usb/udc/udc_common.c @@ -78,22 +78,13 @@ struct udc_ep_config *udc_get_ep_cfg(const struct device *dev, const uint8_t ep) return data->ep_lut[USB_EP_LUT_IDX(ep)]; } -bool udc_ep_is_busy(const struct device *dev, const uint8_t ep) +bool udc_ep_is_busy(const struct udc_ep_config *const ep_cfg) { - struct udc_ep_config *ep_cfg; - - ep_cfg = udc_get_ep_cfg(dev, ep); - __ASSERT(ep_cfg != NULL, "ep 0x%02x is not available", ep); - return ep_cfg->stat.busy; } -void udc_ep_set_busy(const struct device *dev, const uint8_t ep, const bool busy) +void udc_ep_set_busy(struct udc_ep_config *const ep_cfg, const bool busy) { - struct udc_ep_config *ep_cfg; - - ep_cfg = udc_get_ep_cfg(dev, ep); - __ASSERT(ep_cfg != NULL, "ep 0x%02x is not available", ep); ep_cfg->stat.busy = busy; } @@ -115,34 +106,21 @@ int udc_register_ep(const struct device *dev, struct udc_ep_config *const cfg) return 0; } -struct net_buf *udc_buf_get(const struct device *dev, const uint8_t ep) +struct net_buf *udc_buf_get(struct udc_ep_config *const ep_cfg) { - struct udc_ep_config *ep_cfg; - - ep_cfg = udc_get_ep_cfg(dev, ep); - if (ep_cfg == NULL) { - return NULL; - } - return k_fifo_get(&ep_cfg->fifo, K_NO_WAIT); } -struct net_buf *udc_buf_get_all(const struct device *dev, const uint8_t ep) +struct net_buf *udc_buf_get_all(struct udc_ep_config *const ep_cfg) { - struct udc_ep_config *ep_cfg; struct net_buf *buf; - ep_cfg = udc_get_ep_cfg(dev, ep); - if (ep_cfg == NULL) { - return NULL; - } - buf = k_fifo_get(&ep_cfg->fifo, K_NO_WAIT); if (!buf) { return NULL; } - LOG_DBG("ep 0x%02x dequeue %p", ep, buf); + LOG_DBG("ep 0x%02x dequeue %p", ep_cfg->addr, buf); for (struct net_buf *n = buf; !k_fifo_is_empty(&ep_cfg->fifo); n = n->frags) { n->frags = k_fifo_get(&ep_cfg->fifo, K_NO_WAIT); LOG_DBG("|-> %p ", n->frags); @@ -154,15 +132,8 @@ struct net_buf *udc_buf_get_all(const struct device *dev, const uint8_t ep) return buf; } -struct net_buf *udc_buf_peek(const struct device *dev, const uint8_t ep) +struct net_buf *udc_buf_peek(struct udc_ep_config *const ep_cfg) { - struct udc_ep_config *ep_cfg; - - ep_cfg = udc_get_ep_cfg(dev, ep); - if (ep_cfg == NULL) { - return NULL; - } - return k_fifo_peek_head(&ep_cfg->fifo); } diff --git a/drivers/usb/udc/udc_common.h b/drivers/usb/udc/udc_common.h index 19cad23bd39e..8cad6b6dd1c5 100644 --- a/drivers/usb/udc/udc_common.h +++ b/drivers/usb/udc/udc_common.h @@ -61,21 +61,19 @@ struct udc_ep_config *udc_get_ep_cfg(const struct device *dev, /** * @brief Checks if the endpoint is busy * - * @param[in] dev Pointer to device struct of the driver instance - * @param[in] ep Endpoint address + * @param[in] ep_cfg Pointer to endpoint configuration * * @return true if endpoint is busy */ -bool udc_ep_is_busy(const struct device *dev, const uint8_t ep); +bool udc_ep_is_busy(const struct udc_ep_config *const ep_cfg); /** * @brief Helper function to set endpoint busy state * - * @param[in] dev Pointer to device struct of the driver instance - * @param[in] ep Endpoint address + * @param[in] ep_cfg Pointer to endpoint configuration * @param[in] busy Busy state */ -void udc_ep_set_busy(const struct device *dev, const uint8_t ep, +void udc_ep_set_busy(struct udc_ep_config *const ep_cfg, const bool busy); /** @@ -85,13 +83,11 @@ void udc_ep_set_busy(const struct device *dev, const uint8_t ep, * Use it when transfer is finished and request should * be passed to the higher level. * - * @param[in] dev Pointer to device struct of the driver instance - * @param[in] ep Endpoint address + * @param[in] ep_cfg Pointer to endpoint configuration * * @return pointer to UDC request or NULL on error. */ -struct net_buf *udc_buf_get(const struct device *dev, - const uint8_t ep); +struct net_buf *udc_buf_get(struct udc_ep_config *const ep_cfg); /** * @brief Get all UDC request from endpoint FIFO. @@ -100,13 +96,11 @@ struct net_buf *udc_buf_get(const struct device *dev, * This function removes all request from endpoint FIFO and * is typically used to dequeue endpoint FIFO. * - * @param[in] dev Pointer to device struct of the driver instance - * @param[in] ep Endpoint address + * @param[in] ep_cfg Pointer to endpoint configuration * * @return pointer to UDC request or NULL on error. */ -struct net_buf *udc_buf_get_all(const struct device *dev, - const uint8_t ep); +struct net_buf *udc_buf_get_all(struct udc_ep_config *const ep_cfg); /** * @brief Peek request at the head of endpoint FIFO. @@ -114,13 +108,11 @@ struct net_buf *udc_buf_get_all(const struct device *dev, * Return request from the head of endpoint FIFO without removing. * Use it when request buffer is required for a transfer. * - * @param[in] dev Pointer to device struct of the driver instance - * @param[in] ep Endpoint address + * @param[in] ep_cfg Pointer to endpoint configuration * * @return pointer to request or NULL on error. */ -struct net_buf *udc_buf_peek(const struct device *dev, - const uint8_t ep); +struct net_buf *udc_buf_peek(struct udc_ep_config *const ep_cfg); /** * @brief Put request at the tail of endpoint FIFO. diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index feccd3d8662b..5920ae10b786 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -417,7 +417,7 @@ static void dwc2_ensure_setup_ready(const struct device *dev) return; } - if (!udc_buf_peek(dev, USB_CONTROL_EP_OUT)) { + if (!udc_buf_peek(udc_get_ep_cfg(dev, USB_CONTROL_EP_IN))) { dwc2_ctrl_feed_dout(dev, 8); } } @@ -762,7 +762,7 @@ static void dwc2_handle_xfer_next(const struct device *dev, { struct net_buf *buf; - buf = udc_buf_peek(dev, cfg->addr); + buf = udc_buf_peek(cfg); if (buf == NULL) { return; } @@ -796,7 +796,7 @@ static void dwc2_handle_xfer_next(const struct device *dev, LOG_ERR("Failed to start write to TX FIFO, ep 0x%02x (err: %d)", cfg->addr, err); - buf = udc_buf_get(dev, cfg->addr); + buf = udc_buf_get(cfg); if (udc_submit_ep_event(dev, buf, -ECONNREFUSED)) { LOG_ERR("Failed to submit endpoint event"); }; @@ -805,12 +805,14 @@ static void dwc2_handle_xfer_next(const struct device *dev, } } - udc_ep_set_busy(dev, cfg->addr, true); + udc_ep_set_busy(cfg, true); } static int dwc2_handle_evt_setup(const struct device *dev) { struct udc_dwc2_data *const priv = udc_get_private(dev); + struct udc_ep_config *cfg_out = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + struct udc_ep_config *cfg_in = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN); struct net_buf *buf; int err; @@ -820,18 +822,18 @@ static int dwc2_handle_evt_setup(const struct device *dev) */ k_event_clear(&priv->xfer_finished, BIT(0) | BIT(16)); - buf = udc_buf_get_all(dev, USB_CONTROL_EP_OUT); + buf = udc_buf_get_all(cfg_out); if (buf) { net_buf_unref(buf); } - buf = udc_buf_get_all(dev, USB_CONTROL_EP_IN); + buf = udc_buf_get_all(cfg_in); if (buf) { net_buf_unref(buf); } - udc_ep_set_busy(dev, USB_CONTROL_EP_OUT, false); - udc_ep_set_busy(dev, USB_CONTROL_EP_IN, false); + udc_ep_set_busy(cfg_out, false); + udc_ep_set_busy(cfg_in, false); /* Allocate buffer and copy received SETUP for processing */ buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, 8); @@ -877,13 +879,13 @@ static inline int dwc2_handle_evt_dout(const struct device *dev, struct net_buf *buf; int err = 0; - buf = udc_buf_get(dev, cfg->addr); + buf = udc_buf_get(cfg); if (buf == NULL) { LOG_ERR("No buffer queued for ep 0x%02x", cfg->addr); return -ENODATA; } - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); if (cfg->addr == USB_CONTROL_EP_OUT) { if (udc_ctrl_stage_is_status_out(dev)) { @@ -925,7 +927,7 @@ static int dwc2_handle_evt_din(const struct device *dev, { struct net_buf *buf; - buf = udc_buf_peek(dev, cfg->addr); + buf = udc_buf_peek(cfg); if (buf == NULL) { LOG_ERR("No buffer for ep 0x%02x", cfg->addr); udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); @@ -942,8 +944,8 @@ static int dwc2_handle_evt_din(const struct device *dev, return dwc2_tx_fifo_write(dev, cfg, buf); } - buf = udc_buf_get(dev, cfg->addr); - udc_ep_set_busy(dev, cfg->addr, false); + buf = udc_buf_get(cfg); + udc_ep_set_busy(cfg, false); if (cfg->addr == USB_CONTROL_EP_IN) { if (udc_ctrl_stage_is_status_in(dev) || @@ -1551,6 +1553,7 @@ static void udc_dwc2_ep_disable(const struct device *dev, priv->pending_tx_flush |= BIT(usb_dwc2_get_depctl_txfnum(dxepctl)); } + udc_ep_set_busy(cfg, false); return; } @@ -1649,7 +1652,7 @@ static void udc_dwc2_ep_disable(const struct device *dev, dwc2_flush_tx_fifo(dev, usb_dwc2_get_depctl_txfnum(dxepctl)); } - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); } /* Deactivated endpoint means that there will be a bus timeout when the host @@ -1723,7 +1726,7 @@ static int udc_dwc2_ep_clear_halt(const struct device *dev, cfg->stat.halted = false; /* Resume queued transfers if any */ - if (udc_buf_peek(dev, cfg->addr)) { + if (udc_buf_peek(cfg)) { uint32_t ep_bit; if (USB_EP_DIR_IS_IN(cfg->addr)) { @@ -1771,12 +1774,12 @@ static int udc_dwc2_ep_dequeue(const struct device *dev, udc_dwc2_ep_disable(dev, cfg, false); - buf = udc_buf_get_all(dev, cfg->addr); + buf = udc_buf_get_all(cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); LOG_DBG("dequeue ep 0x%02x", cfg->addr); @@ -2235,7 +2238,7 @@ static int udc_dwc2_disable(const struct device *dev) * triggering Soft Reset seems to be enough on shutdown clean up. */ dwc2_core_soft_reset(dev); - buf = udc_buf_get_all(dev, USB_CONTROL_EP_OUT); + buf = udc_buf_get_all(udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT)); if (buf) { net_buf_unref(buf); } @@ -2513,7 +2516,7 @@ static inline void dwc2_handle_rxflvl(const struct device *dev) case USB_DWC2_GRXSTSR_PKTSTS_OUT_DATA: ep_cfg = udc_get_ep_cfg(dev, ep); - buf = udc_buf_peek(dev, ep_cfg->addr); + buf = udc_buf_peek(ep_cfg); /* RxFIFO data must be retrieved even when buf is NULL */ dwc2_read_fifo(dev, ep, buf, bcnt); @@ -2539,7 +2542,7 @@ static inline void dwc2_handle_in_xfercompl(const struct device *dev, struct net_buf *buf; ep_cfg = udc_get_ep_cfg(dev, ep_idx | USB_EP_DIR_IN); - buf = udc_buf_peek(dev, ep_cfg->addr); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); return; @@ -2602,7 +2605,7 @@ static inline void dwc2_handle_out_xfercompl(const struct device *dev, doeptsiz = sys_read32((mem_addr_t)&base->out_ep[ep_idx].doeptsiz); - buf = udc_buf_peek(dev, ep_cfg->addr); + buf = udc_buf_peek(ep_cfg); if (!buf) { LOG_ERR("No buffer for ep 0x%02x", ep_cfg->addr); udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); @@ -2771,7 +2774,7 @@ static void dwc2_handle_incompisoin(const struct device *dev) udc_dwc2_ep_disable(dev, cfg, false); - buf = udc_buf_get(dev, cfg->addr); + buf = udc_buf_get(cfg); if (buf) { /* Data is no longer relevant */ udc_submit_ep_event(dev, buf, 0); @@ -2826,7 +2829,7 @@ static void dwc2_handle_incompisoout(const struct device *dev) udc_dwc2_ep_disable(dev, cfg, false); - buf = udc_buf_get(dev, cfg->addr); + buf = udc_buf_get(cfg); if (buf) { udc_submit_ep_event(dev, buf, 0); } @@ -3061,7 +3064,7 @@ static ALWAYS_INLINE void dwc2_thread_handler(void *const arg) ep = pull_next_ep_from_bitmap(&eps); ep_cfg = udc_get_ep_cfg(dev, ep); - if (!udc_ep_is_busy(dev, ep_cfg->addr)) { + if (!udc_ep_is_busy(ep_cfg)) { dwc2_handle_xfer_next(dev, ep_cfg); } else { LOG_DBG("ep 0x%02x busy", ep_cfg->addr); @@ -3091,7 +3094,7 @@ static ALWAYS_INLINE void dwc2_thread_handler(void *const arg) dwc2_handle_evt_dout(dev, ep_cfg); } - if (!udc_ep_is_busy(dev, ep_cfg->addr)) { + if (!udc_ep_is_busy(ep_cfg)) { dwc2_handle_xfer_next(dev, ep_cfg); } else { LOG_DBG("ep 0x%02x busy", ep_cfg->addr); diff --git a/drivers/usb/udc/udc_it82xx2.c b/drivers/usb/udc/udc_it82xx2.c index 0c61b7b17db8..fd00587dd653 100644 --- a/drivers/usb/udc/udc_it82xx2.c +++ b/drivers/usb/udc/udc_it82xx2.c @@ -506,12 +506,12 @@ static int it82xx2_ep_dequeue(const struct device *dev, struct udc_ep_config *co } irq_unlock(lock_key); - buf = udc_buf_get_all(dev, cfg->addr); + buf = udc_buf_get_all(cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); return 0; } @@ -861,16 +861,17 @@ static int work_handler_xfer_continue(const struct device *dev, uint8_t ep, stru return ret; } -static int work_handler_xfer_next(const struct device *dev, uint8_t ep) +static int work_handler_xfer_next(const struct device *dev, + struct udc_ep_config *ep_cfg) { struct net_buf *buf; - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { return -ENODATA; } - return work_handler_xfer_continue(dev, ep, buf); + return work_handler_xfer_continue(dev, ep_cfg->addr, buf); } /* @@ -984,11 +985,12 @@ static inline int work_handler_in(const struct device *dev, uint8_t ep) k_sem_give(&priv->fifo_sem[fifo_idx - 1]); } - buf = udc_buf_peek(dev, ep); + ep_cfg = udc_get_ep_cfg(dev, ep); + + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { return -ENODATA; } - ep_cfg = udc_get_ep_cfg(dev, ep); net_buf_pull(buf, MIN(buf->len, udc_mps_ep_size(ep_cfg))); @@ -1005,12 +1007,12 @@ static inline int work_handler_in(const struct device *dev, uint8_t ep) return 0; } - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(ep_cfg); if (buf == NULL) { return -ENODATA; } - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(ep_cfg, false); if (ep == USB_CONTROL_EP_IN) { if (udc_ctrl_stage_is_status_in(dev) || udc_ctrl_stage_is_no_data(dev)) { @@ -1042,10 +1044,13 @@ static inline int work_handler_setup(const struct device *dev, uint8_t ep) int err = 0; if (udc_ctrl_stage_is_status_out(dev)) { + struct udc_ep_config *cfg_out; + /* out -> setup */ - buf = udc_buf_get(dev, USB_CONTROL_EP_OUT); + cfg_out = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + buf = udc_buf_get(cfg_out); if (buf) { - udc_ep_set_busy(dev, USB_CONTROL_EP_OUT, false); + udc_ep_set_busy(cfg_out, false); net_buf_unref(buf); } } @@ -1109,7 +1114,8 @@ static inline int work_handler_out(const struct device *dev, uint8_t ep) return 0; } - buf = udc_buf_peek(dev, ep); + ep_cfg = udc_get_ep_cfg(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { return -ENODATA; } @@ -1121,7 +1127,7 @@ static inline int work_handler_out(const struct device *dev, uint8_t ep) if (ep == USB_CONTROL_EP_OUT) { if (udc_ctrl_stage_is_status_out(dev) && len != 0) { LOG_DBG("Handle early setup token"); - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(ep_cfg); /* Notify upper layer */ udc_ctrl_submit_status(dev, buf); /* Update to next stage of control transfer */ @@ -1130,7 +1136,6 @@ static inline int work_handler_out(const struct device *dev, uint8_t ep) } } - ep_cfg = udc_get_ep_cfg(dev, ep); if (len > udc_mps_ep_size(ep_cfg)) { LOG_ERR("Failed to handle this packet due to the packet size"); return -ENOBUFS; @@ -1148,12 +1153,12 @@ static inline int work_handler_out(const struct device *dev, uint8_t ep) return err; } - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(ep_cfg); if (buf == NULL) { return -ENODATA; } - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(ep_cfg, false); if (ep == USB_CONTROL_EP_OUT) { if (udc_ctrl_stage_is_status_out(dev)) { @@ -1179,11 +1184,14 @@ static inline int work_handler_out(const struct device *dev, uint8_t ep) static void xfer_work_handler(const struct device *dev) { while (true) { + struct udc_ep_config *ep_cfg; struct it82xx2_ep_event evt; int err = 0; k_msgq_get(&evt_msgq, &evt, K_FOREVER); + ep_cfg = udc_get_ep_cfg(evt.dev, evt.ep); + switch (evt.event) { case IT82xx2_EVT_SETUP_TOKEN: err = work_handler_setup(evt.dev, evt.ep); @@ -1206,9 +1214,9 @@ static void xfer_work_handler(const struct device *dev) udc_submit_event(evt.dev, UDC_EVT_ERROR, err); } - if (evt.ep != USB_CONTROL_EP_OUT && !udc_ep_is_busy(evt.dev, evt.ep)) { - if (work_handler_xfer_next(evt.dev, evt.ep) == 0) { - udc_ep_set_busy(evt.dev, evt.ep, true); + if (evt.ep != USB_CONTROL_EP_OUT && !udc_ep_is_busy(ep_cfg)) { + if (work_handler_xfer_next(ep_cfg) == 0) { + udc_ep_set_busy(ep_cfg, true); } } } diff --git a/drivers/usb/udc/udc_kinetis.c b/drivers/usb/udc/udc_kinetis.c index 70fae41b4871..19e1f865efa4 100644 --- a/drivers/usb/udc/udc_kinetis.c +++ b/drivers/usb/udc/udc_kinetis.c @@ -221,7 +221,7 @@ static int usbfsotg_xfer_next(const struct device *dev, { struct net_buf *buf; - buf = udc_buf_peek(dev, cfg->addr); + buf = udc_buf_peek(cfg); if (buf == NULL) { return -ENODATA; } @@ -317,7 +317,7 @@ static inline int work_handler_setup(const struct device *dev) struct net_buf *buf; int err; - buf = udc_buf_get(dev, USB_CONTROL_EP_OUT); + buf = udc_buf_get(udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT)); if (buf == NULL) { return -ENODATA; } @@ -365,17 +365,17 @@ static inline int work_handler_setup(const struct device *dev) } static inline int work_handler_out(const struct device *dev, - const uint8_t ep) + struct udc_ep_config *ep_cfg) { struct net_buf *buf; int err = 0; - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(ep_cfg); if (buf == NULL) { return -ENODATA; } - if (ep == USB_CONTROL_EP_OUT) { + if (ep_cfg->addr == USB_CONTROL_EP_OUT) { if (udc_ctrl_stage_is_status_out(dev)) { /* s-in-status finished, next bd is already fed */ LOG_DBG("dout:%p|no feed", buf); @@ -404,16 +404,16 @@ static inline int work_handler_out(const struct device *dev, } static inline int work_handler_in(const struct device *dev, - const uint8_t ep) + struct udc_ep_config *ep_cfg) { struct net_buf *buf; - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(ep_cfg); if (buf == NULL) { return -ENODATA; } - if (ep == USB_CONTROL_EP_IN) { + if (ep_cfg->addr == USB_CONTROL_EP_IN) { if (udc_ctrl_stage_is_status_in(dev) || udc_ctrl_stage_is_no_data(dev)) { /* Status stage finished, notify upper layer */ @@ -482,12 +482,12 @@ static void xfer_work_handler(struct k_work *item) err = work_handler_setup(ev->dev); break; case USBFSOTG_EVT_DOUT: - err = work_handler_out(ev->dev, ev->ep); - udc_ep_set_busy(ev->dev, ev->ep, false); + err = work_handler_out(ev->dev, ep_cfg); + udc_ep_set_busy(ep_cfg, false); break; case USBFSOTG_EVT_DIN: - err = work_handler_in(ev->dev, ev->ep); - udc_ep_set_busy(ev->dev, ev->ep, false); + err = work_handler_in(ev->dev, ep_cfg); + udc_ep_set_busy(ep_cfg, false); break; case USBFSOTG_EVT_CLEAR_HALT: err = usbfsotg_ep_clear_halt(ev->dev, ep_cfg); @@ -501,9 +501,9 @@ static void xfer_work_handler(struct k_work *item) } /* Peek next transfer */ - if (ev->ep != USB_CONTROL_EP_OUT && !udc_ep_is_busy(ev->dev, ev->ep)) { + if (ev->ep != USB_CONTROL_EP_OUT && !udc_ep_is_busy(ep_cfg)) { if (usbfsotg_xfer_next(ev->dev, ep_cfg) == 0) { - udc_ep_set_busy(ev->dev, ev->ep, true); + udc_ep_set_busy(ep_cfg, true); } } @@ -584,7 +584,7 @@ static ALWAYS_INLINE void isr_handle_xfer_done(const struct device *dev, priv->busy[odd] = false; priv->out_buf[odd] = NULL; } else { - buf = udc_buf_peek(dev, ep_cfg->addr); + buf = udc_buf_peek(ep_cfg); } if (buf == NULL) { @@ -614,7 +614,7 @@ static ALWAYS_INLINE void isr_handle_xfer_done(const struct device *dev, ep_cfg->stat.odd = !odd; ep_cfg->stat.data1 = !data1; - buf = udc_buf_peek(dev, ep_cfg->addr); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { LOG_ERR("No buffer for ep 0x%02x", ep); udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); @@ -740,12 +740,12 @@ static int usbfsotg_ep_dequeue(const struct device *dev, irq_unlock(lock_key); cfg->stat.halted = false; - buf = udc_buf_get_all(dev, cfg->addr); + buf = udc_buf_get_all(cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); return 0; } diff --git a/drivers/usb/udc/udc_mcux_ehci.c b/drivers/usb/udc/udc_mcux_ehci.c index 489540a9d159..fc5f65b76443 100644 --- a/drivers/usb/udc/udc_mcux_ehci.c +++ b/drivers/usb/udc/udc_mcux_ehci.c @@ -112,8 +112,8 @@ static int udc_mcux_ep_feed(const struct device *dev, } udc_mcux_lock(dev); - if (!udc_ep_is_busy(dev, cfg->addr)) { - udc_ep_set_busy(dev, cfg->addr, true); + if (!udc_ep_is_busy(cfg)) { + udc_ep_set_busy(cfg, true); udc_mcux_unlock(dev); if (USB_EP_DIR_IS_OUT(cfg->addr)) { @@ -130,7 +130,7 @@ static int udc_mcux_ep_feed(const struct device *dev, udc_mcux_lock(dev); if (status != kStatus_USB_Success) { - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); } udc_mcux_unlock(dev); } else { @@ -147,7 +147,7 @@ static int udc_mcux_ep_try_feed(const struct device *dev, { struct net_buf *feed_buf; - feed_buf = udc_buf_peek(dev, cfg->addr); + feed_buf = udc_buf_peek(cfg); if (feed_buf) { int ret = udc_mcux_ep_feed(dev, cfg, feed_buf); @@ -322,13 +322,14 @@ static int udc_mcux_handler_non_ctrl_out(const struct device *dev, uint8_t ep, static int udc_mcux_handler_out(const struct device *dev, uint8_t ep, uint8_t *mcux_buf, uint16_t mcux_len) { + struct udc_ep_config *const cfg = udc_get_ep_cfg(dev, ep); int err; struct net_buf *buf; - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(cfg); udc_mcux_lock(dev); - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(cfg, false); udc_mcux_unlock(dev); if (buf == NULL) { @@ -375,10 +376,11 @@ static bool udc_mcux_handler_zlt(const struct device *dev, uint8_t ep, struct ne static int udc_mcux_handler_in(const struct device *dev, uint8_t ep, uint8_t *mcux_buf, uint16_t mcux_len) { + struct udc_ep_config *const cfg = udc_get_ep_cfg(dev, ep); int err; struct net_buf *buf; - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(cfg); if (buf == NULL) { udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); return -ENOBUFS; @@ -388,10 +390,10 @@ static int udc_mcux_handler_in(const struct device *dev, uint8_t ep, return 0; } - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(cfg); udc_mcux_lock(dev); - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(cfg, false); udc_mcux_unlock(dev); if (buf == NULL) { @@ -593,13 +595,13 @@ static int udc_mcux_ep_dequeue(const struct device *dev, struct net_buf *buf; cfg->stat.halted = false; - buf = udc_buf_get_all(dev, cfg->addr); + buf = udc_buf_get_all(cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } udc_mcux_lock(dev); - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); udc_mcux_unlock(dev); return 0; diff --git a/drivers/usb/udc/udc_mcux_ip3511.c b/drivers/usb/udc/udc_mcux_ip3511.c index f8db1221e074..564f2f9357b9 100644 --- a/drivers/usb/udc/udc_mcux_ip3511.c +++ b/drivers/usb/udc/udc_mcux_ip3511.c @@ -112,8 +112,8 @@ static int udc_mcux_ep_feed(const struct device *dev, } udc_mcux_lock(dev); - if (!udc_ep_is_busy(dev, cfg->addr)) { - udc_ep_set_busy(dev, cfg->addr, true); + if (!udc_ep_is_busy(cfg)) { + udc_ep_set_busy(cfg, true); udc_mcux_unlock(dev); if (USB_EP_DIR_IS_OUT(cfg->addr)) { @@ -130,7 +130,7 @@ static int udc_mcux_ep_feed(const struct device *dev, udc_mcux_lock(dev); if (status != kStatus_USB_Success) { - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); } udc_mcux_unlock(dev); } else { @@ -147,7 +147,7 @@ static int udc_mcux_ep_try_feed(const struct device *dev, { struct net_buf *feed_buf; - feed_buf = udc_buf_peek(dev, cfg->addr); + feed_buf = udc_buf_peek(cfg); if (feed_buf) { int ret = udc_mcux_ep_feed(dev, cfg, feed_buf); @@ -322,13 +322,14 @@ static int udc_mcux_handler_non_ctrl_out(const struct device *dev, uint8_t ep, static int udc_mcux_handler_out(const struct device *dev, uint8_t ep, uint8_t *mcux_buf, uint16_t mcux_len) { + struct udc_ep_config *const cfg = udc_get_ep_cfg(dev, ep); int err; struct net_buf *buf; - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(cfg); udc_mcux_lock(dev); - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(cfg, false); udc_mcux_unlock(dev); if (buf == NULL) { @@ -375,10 +376,11 @@ static bool udc_mcux_handler_zlt(const struct device *dev, uint8_t ep, struct ne static int udc_mcux_handler_in(const struct device *dev, uint8_t ep, uint8_t *mcux_buf, uint16_t mcux_len) { + struct udc_ep_config *const cfg = udc_get_ep_cfg(dev, ep); int err; struct net_buf *buf; - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(cfg); if (buf == NULL) { udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); return -ENOBUFS; @@ -388,10 +390,10 @@ static int udc_mcux_handler_in(const struct device *dev, uint8_t ep, return 0; } - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(cfg); udc_mcux_lock(dev); - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(cfg, false); udc_mcux_unlock(dev); if (buf == NULL) { @@ -593,13 +595,13 @@ static int udc_mcux_ep_dequeue(const struct device *dev, struct net_buf *buf; cfg->stat.halted = false; - buf = udc_buf_get_all(dev, cfg->addr); + buf = udc_buf_get_all(cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } udc_mcux_lock(dev); - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); udc_mcux_unlock(dev); return 0; diff --git a/drivers/usb/udc/udc_nrf.c b/drivers/usb/udc/udc_nrf.c index cafe3fbd19fb..8e43313bd19a 100644 --- a/drivers/usb/udc/udc_nrf.c +++ b/drivers/usb/udc/udc_nrf.c @@ -96,13 +96,14 @@ static void udc_nrf_clear_control_out(const struct device *dev) static void udc_event_xfer_in_next(const struct device *dev, const uint8_t ep) { + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep); struct net_buf *buf; - if (udc_ep_is_busy(dev, ep)) { + if (udc_ep_is_busy(ep_cfg)) { return; } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf != NULL) { nrf_usbd_common_transfer_t xfer = { .p_data = {.tx = buf->data}, @@ -118,7 +119,7 @@ static void udc_event_xfer_in_next(const struct device *dev, const uint8_t ep) /* REVISE: remove from endpoint queue? ASSERT? */ udc_submit_ep_event(dev, buf, -ECONNREFUSED); } else { - udc_ep_set_busy(dev, ep, true); + udc_ep_set_busy(ep_cfg, true); } } } @@ -151,9 +152,10 @@ static void udc_event_xfer_ctrl_in(const struct device *dev, static void udc_event_fake_status_in(const struct device *dev) { + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN); struct net_buf *buf; - buf = udc_buf_get(dev, USB_CONTROL_EP_IN); + buf = udc_buf_get(ep_cfg); if (unlikely(buf == NULL)) { LOG_DBG("ep 0x%02x queue is empty", USB_CONTROL_EP_IN); return; @@ -166,19 +168,22 @@ static void udc_event_fake_status_in(const struct device *dev) static void udc_event_xfer_in(const struct device *dev, nrf_usbd_common_evt_t const *const event) { + struct udc_ep_config *ep_cfg; uint8_t ep = event->data.eptransfer.ep; struct net_buf *buf; + ep_cfg = udc_get_ep_cfg(dev, ep); + switch (event->data.eptransfer.status) { case NRF_USBD_COMMON_EP_OK: - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(ep_cfg); if (buf == NULL) { LOG_ERR("ep 0x%02x queue is empty", ep); __ASSERT_NO_MSG(false); return; } - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(ep_cfg, false); if (ep == USB_CONTROL_EP_IN) { udc_event_xfer_ctrl_in(dev, buf); return; @@ -189,14 +194,14 @@ static void udc_event_xfer_in(const struct device *dev, case NRF_USBD_COMMON_EP_ABORTED: LOG_WRN("aborted IN ep 0x%02x", ep); - buf = udc_buf_get_all(dev, ep); + buf = udc_buf_get_all(ep_cfg); if (buf == NULL) { LOG_DBG("ep 0x%02x queue is empty", ep); return; } - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(ep_cfg, false); udc_submit_ep_event(dev, buf, -ECONNABORTED); break; @@ -226,13 +231,14 @@ static void udc_event_xfer_ctrl_out(const struct device *dev, static void udc_event_xfer_out_next(const struct device *dev, const uint8_t ep) { + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep); struct net_buf *buf; - if (udc_ep_is_busy(dev, ep)) { + if (udc_ep_is_busy(ep_cfg)) { return; } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf != NULL) { nrf_usbd_common_transfer_t xfer = { .p_data = {.rx = buf->data}, @@ -247,7 +253,7 @@ static void udc_event_xfer_out_next(const struct device *dev, const uint8_t ep) /* REVISE: remove from endpoint queue? ASSERT? */ udc_submit_ep_event(dev, buf, -ECONNREFUSED); } else { - udc_ep_set_busy(dev, ep, true); + udc_ep_set_busy(ep_cfg, true); } } else { LOG_DBG("ep 0x%02x waiting, queue is empty", ep); @@ -257,6 +263,7 @@ static void udc_event_xfer_out_next(const struct device *dev, const uint8_t ep) static void udc_event_xfer_out(const struct device *dev, nrf_usbd_common_evt_t const *const event) { + struct udc_ep_config *ep_cfg; uint8_t ep = event->data.eptransfer.ep; nrf_usbd_common_ep_status_t err_code; struct net_buf *buf; @@ -276,14 +283,15 @@ static void udc_event_xfer_out(const struct device *dev, LOG_ERR("OUT transfer failed %d", err_code); } - buf = udc_buf_get(dev, ep); + ep_cfg = udc_get_ep_cfg(dev, ep); + buf = udc_buf_get(ep_cfg); if (buf == NULL) { LOG_ERR("ep 0x%02x ok, queue is empty", ep); return; } net_buf_add(buf, len); - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(ep_cfg, false); if (ep == USB_CONTROL_EP_OUT) { udc_event_xfer_ctrl_out(dev, buf); } else { @@ -616,7 +624,7 @@ static int udc_nrf_ep_dequeue(const struct device *dev, * HAL driver does not generate event for an OUT endpoint * or when IN endpoint is not busy. */ - buf = udc_buf_get_all(dev, cfg->addr); + buf = udc_buf_get_all(cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } else { @@ -625,7 +633,7 @@ static int udc_nrf_ep_dequeue(const struct device *dev, } - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); return 0; } diff --git a/drivers/usb/udc/udc_numaker.c b/drivers/usb/udc/udc_numaker.c index 5545132944d2..736ded93fc50 100644 --- a/drivers/usb/udc/udc_numaker.c +++ b/drivers/usb/udc/udc_numaker.c @@ -505,6 +505,7 @@ static void numaker_usbd_ep_config_dmabuf(struct numaker_usbd_ep *ep_cur, uint32 static void numaker_usbd_ep_abort(struct numaker_usbd_ep *ep_cur) { + struct udc_ep_config *ep_cfg; const struct device *dev = ep_cur->dev; USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx); @@ -512,7 +513,8 @@ static void numaker_usbd_ep_abort(struct numaker_usbd_ep *ep_cur) ep_base->CFGP |= USBD_CFGP_CLRRDY_Msk; if (ep_cur->addr_valid) { - udc_ep_set_busy(dev, ep_cur->addr, false); + ep_cfg = udc_get_ep_cfg(dev, ep_cur->addr); + udc_ep_set_busy(ep_cfg, false); } } @@ -589,11 +591,13 @@ static void numaker_usbd_ep_disable(struct numaker_usbd_ep *ep_cur) /* Start EP data transaction */ static void udc_numaker_ep_trigger(struct numaker_usbd_ep *ep_cur, uint32_t len) { + struct udc_ep_config *ep_cfg; const struct device *dev = ep_cur->dev; USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx); if (ep_cur->addr_valid) { - udc_ep_set_busy(dev, ep_cur->addr, true); + ep_cfg = udc_get_ep_cfg(dev, ep_cur->addr); + udc_ep_set_busy(ep_cfg, true); } ep_base->MXPLD = len; @@ -762,13 +766,15 @@ static int numaker_usbd_xfer_out(const struct device *dev, uint8_t ep, bool stri { struct net_buf *buf; struct numaker_usbd_ep *ep_cur; + struct udc_ep_config *ep_cfg; if (!USB_EP_DIR_IS_OUT(ep)) { LOG_ERR("Invalid EP address 0x%02x for data out", ep); return -EINVAL; } - if (udc_ep_is_busy(dev, ep)) { + ep_cfg = udc_get_ep_cfg(dev, ep); + if (udc_ep_is_busy(ep_cfg)) { if (strict) { LOG_ERR("EP 0x%02x busy", ep); return -EAGAIN; @@ -777,7 +783,7 @@ static int numaker_usbd_xfer_out(const struct device *dev, uint8_t ep, bool stri return 0; } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { if (strict) { LOG_ERR("No buffer queued for EP 0x%02x", ep); @@ -803,6 +809,7 @@ static int numaker_usbd_xfer_in(const struct device *dev, uint8_t ep, bool stric { struct net_buf *buf; struct numaker_usbd_ep *ep_cur; + struct udc_ep_config *ep_cfg; uint32_t data_len; if (!USB_EP_DIR_IS_IN(ep)) { @@ -810,7 +817,8 @@ static int numaker_usbd_xfer_in(const struct device *dev, uint8_t ep, bool stric return -EINVAL; } - if (udc_ep_is_busy(dev, ep)) { + ep_cfg = udc_get_ep_cfg(dev, ep); + if (udc_ep_is_busy(ep_cfg)) { if (strict) { LOG_ERR("EP 0x%02x busy", ep); return -EAGAIN; @@ -819,7 +827,7 @@ static int numaker_usbd_xfer_in(const struct device *dev, uint8_t ep, bool stric return 0; } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { if (strict) { LOG_ERR("No buffer queued for EP 0x%02x", ep); @@ -944,6 +952,7 @@ static int numaker_usbd_msg_handle_out(const struct device *dev, struct numaker_ int err; uint8_t ep; struct numaker_usbd_ep *ep_cur; + struct udc_ep_config *ep_cfg; struct net_buf *buf; uint8_t *data_ptr; uint32_t data_len; @@ -952,8 +961,9 @@ static int numaker_usbd_msg_handle_out(const struct device *dev, struct numaker_ __ASSERT_NO_MSG(msg->type == NUMAKER_USBD_MSG_TYPE_OUT); ep = msg->out.ep; + ep_cfg = udc_get_ep_cfg(ep); - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(ep_cfg, false); /* Bind EP H/W context to EP address */ ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep); @@ -962,7 +972,7 @@ static int numaker_usbd_msg_handle_out(const struct device *dev, struct numaker_ return -ENODEV; } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { LOG_ERR("No buffer queued for ep=0x%02x", ep); return -ENODATA; @@ -993,7 +1003,7 @@ static int numaker_usbd_msg_handle_out(const struct device *dev, struct numaker_ } /* To submit the peeked buffer */ - udc_buf_get(dev, ep); + udc_buf_get(ep_cfg); if (ep == USB_CONTROL_EP_OUT) { if (udc_ctrl_stage_is_status_out(dev)) { @@ -1037,13 +1047,15 @@ static int numaker_usbd_msg_handle_in(const struct device *dev, struct numaker_u int err; uint8_t ep; struct numaker_usbd_ep *ep_cur; + struct udc_ep_config *ep_cfg; struct net_buf *buf; __ASSERT_NO_MSG(msg->type == NUMAKER_USBD_MSG_TYPE_IN); ep = msg->in.ep; + ep_cfg = udc_get_ep_cfg(dev, ep); - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(ep_cfg, false); /* Bind EP H/W context to EP address */ ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep); @@ -1052,7 +1064,7 @@ static int numaker_usbd_msg_handle_in(const struct device *dev, struct numaker_u return -ENODEV; } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { /* No DATA IN request */ return 0; @@ -1063,7 +1075,7 @@ static int numaker_usbd_msg_handle_in(const struct device *dev, struct numaker_u } /* To submit the peeked buffer */ - udc_buf_get(dev, ep); + udc_buf_get(ep_cfg); if (ep == USB_CONTROL_EP_IN) { if (udc_ctrl_stage_is_status_in(dev) || udc_ctrl_stage_is_no_data(dev)) { @@ -1408,7 +1420,7 @@ static int udc_numaker_ep_dequeue(const struct device *dev, struct udc_ep_config numaker_usbd_ep_abort(ep_cur); - buf = udc_buf_get_all(dev, ep_cfg->addr); + buf = udc_buf_get_all(ep_cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } diff --git a/drivers/usb/udc/udc_renesas_ra.c b/drivers/usb/udc/udc_renesas_ra.c index 66f3ae308404..60f32d86b305 100644 --- a/drivers/usb/udc/udc_renesas_ra.c +++ b/drivers/usb/udc/udc_renesas_ra.c @@ -97,13 +97,14 @@ static void udc_renesas_ra_interrupt_handler(void *arg) static void udc_event_xfer_next(const struct device *dev, const uint8_t ep) { struct udc_renesas_ra_data *data = udc_get_private(dev); + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep); struct net_buf *buf; - if (udc_ep_is_busy(dev, ep)) { + if (udc_ep_is_busy(ep_cfg)) { return; } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf != NULL) { int err; @@ -117,7 +118,7 @@ static void udc_event_xfer_next(const struct device *dev, const uint8_t ep) LOG_ERR("ep 0x%02x error", ep); udc_submit_ep_event(dev, buf, -ECONNREFUSED); } else { - udc_ep_set_busy(dev, ep, true); + udc_ep_set_busy(ep_cfg, true); } } } @@ -200,7 +201,7 @@ static void udc_event_status_in(const struct device *dev) struct udc_renesas_ra_data *data = udc_get_private(dev); struct net_buf *buf; - buf = udc_buf_get(dev, USB_CONTROL_EP_IN); + buf = udc_buf_get(udc_get_ep_cfg(dev, USB_CONTROL_EP_IN)); if (unlikely(buf == NULL)) { LOG_DBG("ep 0x%02x queue is empty", USB_CONTROL_EP_IN); return; @@ -234,14 +235,16 @@ static void udc_event_xfer_complete(const struct device *dev, struct udc_renesas { struct net_buf *buf; struct udc_renesas_ra_data *data = udc_get_private(dev); + struct udc_ep_config *ep_cfg; uint8_t ep = evt->hal_evt.xfer_complete.ep_addr; usbd_xfer_result_t result = evt->hal_evt.xfer_complete.result; uint32_t len = evt->hal_evt.xfer_complete.len; - udc_ep_set_busy(dev, ep, false); + ep_cfg = udc_get_ep_cfg(dev, ep); + udc_ep_set_busy(ep_cfg, false); - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { return; } @@ -260,7 +263,7 @@ static void udc_event_xfer_complete(const struct device *dev, struct udc_renesas return; } - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(ep_cfg); if (ep == USB_CONTROL_EP_IN) { udc_event_xfer_ctrl_in(dev, buf); @@ -351,7 +354,7 @@ static int udc_renesas_ra_ep_dequeue(const struct device *dev, struct udc_ep_con lock_key = irq_lock(); - buf = udc_buf_get_all(dev, cfg->addr); + buf = udc_buf_get_all(cfg); if (buf != NULL) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } @@ -360,7 +363,7 @@ static int udc_renesas_ra_ep_dequeue(const struct device *dev, struct udc_ep_con return -EIO; } - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); irq_unlock(lock_key); diff --git a/drivers/usb/udc/udc_rpi_pico.c b/drivers/usb/udc/udc_rpi_pico.c index 4065f4555b15..763e5a3d8029 100644 --- a/drivers/usb/udc/udc_rpi_pico.c +++ b/drivers/usb/udc/udc_rpi_pico.c @@ -278,14 +278,16 @@ static int rpi_pico_ctrl_feed_dout(const struct device *dev, const size_t length static void drop_control_transfers(const struct device *dev) { + struct udc_ep_config *cfg_out = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + struct udc_ep_config *cfg_in = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN); struct net_buf *buf; - buf = udc_buf_get_all(dev, USB_CONTROL_EP_OUT); + buf = udc_buf_get_all(cfg_out); if (buf != NULL) { net_buf_unref(buf); } - buf = udc_buf_get_all(dev, USB_CONTROL_EP_IN); + buf = udc_buf_get_all(cfg_in); if (buf != NULL) { net_buf_unref(buf); } @@ -337,14 +339,14 @@ static inline int rpi_pico_handle_evt_dout(const struct device *dev, struct net_buf *buf; int err = 0; - buf = udc_buf_get(dev, cfg->addr); + buf = udc_buf_get(cfg); if (buf == NULL) { LOG_ERR("No buffer for OUT ep 0x%02x", cfg->addr); udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); return -ENODATA; } - udc_ep_set_busy(dev, cfg->addr, false); + udc_ep_set_busy(cfg, false); if (cfg->addr == USB_CONTROL_EP_OUT) { if (udc_ctrl_stage_is_status_out(dev)) { @@ -373,15 +375,15 @@ static int rpi_pico_handle_evt_din(const struct device *dev, struct net_buf *buf; int err; - buf = udc_buf_peek(dev, cfg->addr); + buf = udc_buf_peek(cfg); if (buf == NULL) { LOG_ERR("No buffer for ep 0x%02x", cfg->addr); udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); return -ENOBUFS; } - buf = udc_buf_get(dev, cfg->addr); - udc_ep_set_busy(dev, cfg->addr, false); + buf = udc_buf_get(cfg); + udc_ep_set_busy(cfg, false); if (cfg->addr == USB_CONTROL_EP_IN) { if (udc_ctrl_stage_is_status_in(dev) || @@ -415,7 +417,7 @@ static void rpi_pico_handle_xfer_next(const struct device *dev, struct net_buf *buf; int err; - buf = udc_buf_peek(dev, cfg->addr); + buf = udc_buf_peek(cfg); if (buf == NULL) { return; } @@ -429,7 +431,7 @@ static void rpi_pico_handle_xfer_next(const struct device *dev, if (err != 0) { udc_submit_ep_event(dev, buf, -ECONNREFUSED); } else { - udc_ep_set_busy(dev, cfg->addr, true); + udc_ep_set_busy(cfg, true); } } @@ -460,7 +462,7 @@ static ALWAYS_INLINE void rpi_pico_thread_handler(void *const arg) break; } - if (ep_cfg->addr != USB_CONTROL_EP_OUT && !udc_ep_is_busy(dev, ep_cfg->addr)) { + if (ep_cfg->addr != USB_CONTROL_EP_OUT && !udc_ep_is_busy(ep_cfg)) { rpi_pico_handle_xfer_next(dev, ep_cfg); } } @@ -503,7 +505,7 @@ static void rpi_pico_handle_buff_status_in(const struct device *dev, const uint8 struct net_buf *buf; size_t len; - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { LOG_ERR("No buffer for ep 0x%02x", ep); udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); @@ -538,7 +540,7 @@ static void rpi_pico_handle_buff_status_out(const struct device *dev, const uint struct net_buf *buf; size_t len; - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { LOG_ERR("No buffer for ep 0x%02x", ep); udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); @@ -739,7 +741,7 @@ static int udc_rpi_pico_ep_dequeue(const struct device *dev, lock_key = irq_lock(); rpi_pico_ep_cancel(dev, cfg->addr); - buf = udc_buf_get_all(dev, cfg->addr); + buf = udc_buf_get_all(cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } @@ -856,7 +858,7 @@ static int udc_rpi_pico_ep_clear_halt(const struct device *dev, arch_nop(); rpi_pico_bit_clr(buf_ctrl_reg, USB_BUF_CTRL_STALL); - if (udc_buf_peek(dev, cfg->addr)) { + if (udc_buf_peek(cfg)) { k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); } } diff --git a/drivers/usb/udc/udc_skeleton.c b/drivers/usb/udc/udc_skeleton.c index cba2016572ca..86c7cdc75f7e 100644 --- a/drivers/usb/udc/udc_skeleton.c +++ b/drivers/usb/udc/udc_skeleton.c @@ -119,7 +119,7 @@ static int udc_skeleton_ep_dequeue(const struct device *dev, lock_key = irq_lock(); - buf = udc_buf_get_all(dev, cfg->addr); + buf = udc_buf_get_all(cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } diff --git a/drivers/usb/udc/udc_smartbond.c b/drivers/usb/udc/udc_smartbond.c index dd5a2aa782a5..e413f518d68e 100644 --- a/drivers/usb/udc/udc_smartbond.c +++ b/drivers/usb/udc/udc_smartbond.c @@ -555,14 +555,15 @@ static int udc_smartbond_ep_tx(const struct device *dev, uint8_t ep) { struct usb_smartbond_data *data = dev->data; struct smartbond_ep_state *ep_state = usb_dc_get_ep_in_state(data, USB_EP_GET_IDX(ep)); + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep); struct net_buf *buf; - if (udc_ep_is_busy(dev, ep) || + if (udc_ep_is_busy(ep_cfg) || (ep_state->regs->epc_in & USB_USB_EPC1_REG_USB_STALL_Msk) != 0) { return 0; } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); LOG_DBG("TX ep 0x%02x len %u", ep, buf ? buf->len : -1); if (buf) { @@ -571,7 +572,7 @@ static int udc_smartbond_ep_tx(const struct device *dev, uint8_t ep) start_tx_packet(data, ep_state); - udc_ep_set_busy(dev, ep, true); + udc_ep_set_busy(ep_cfg, true); } return 0; @@ -581,13 +582,14 @@ static int udc_smartbond_ep_rx(const struct device *dev, uint8_t ep) { struct usb_smartbond_data *data = dev->data; struct smartbond_ep_state *ep_state = usb_dc_get_ep_out_state(data, USB_EP_GET_IDX(ep)); + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep); struct net_buf *buf; - if (udc_ep_is_busy(dev, ep)) { + if (udc_ep_is_busy(ep_cfg)) { return 0; } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf) { LOG_DBG("RX ep 0x%02x len %u", ep, buf->size); @@ -597,7 +599,7 @@ static int udc_smartbond_ep_rx(const struct device *dev, uint8_t ep) start_rx_packet(data, ep_state); - udc_ep_set_busy(dev, ep, true); + udc_ep_set_busy(ep_cfg, true); } return 0; @@ -648,12 +650,12 @@ static int udc_smartbond_ep_dequeue(const struct device *dev, struct udc_ep_conf udc_smartbond_ep_abort(dev, ep_cfg); - buf = udc_buf_get_all(dev, ep); + buf = udc_buf_get_all(ep_cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(ep_cfg, false); irq_unlock(lock_key); @@ -729,7 +731,7 @@ static int udc_smartbond_ep_set_halt(const struct device *dev, struct udc_ep_con if (ep_cfg->addr == USB_CONTROL_EP_IN) { /* Stall in DATA IN phase, drop status OUT packet */ if (udc_ctrl_stage_is_data_in(dev)) { - buf = udc_buf_get(dev, USB_CONTROL_EP_OUT); + buf = udc_buf_get(udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT)); if (buf) { net_buf_unref(buf); } @@ -992,7 +994,7 @@ static void handle_epx_rx_ev(struct usb_smartbond_data *data, uint8_t ep_idx) if (net_buf_tailroom(buf) == 0 || ep_state->last_packet_size < udc_mps_ep_size(ep_cfg) || ep_state->iso) { - buf = udc_buf_get(data->dev, ep_cfg->addr); + buf = udc_buf_get(ep_cfg); if (unlikely(buf == NULL)) { LOG_ERR("ep 0x%02x queue is empty", ep_cfg->addr); break; @@ -1063,8 +1065,8 @@ static void handle_epx_tx_ev(struct usb_smartbond_data *data, struct smartbond_e regs->txc |= USB_USB_TXC1_REG_USB_TX_EN_Msk | USB_USB_TXC1_REG_USB_LAST_Msk; } else { - udc_ep_set_busy(data->dev, ep, false); - buf = udc_buf_get(data->dev, ep); + udc_ep_set_busy(ep_cfg, false); + buf = udc_buf_get(ep_cfg); udc_submit_ep_event(data->dev, buf, 0); udc_smartbond_ep_tx(data->dev, ep); @@ -1164,13 +1166,15 @@ static void handle_ep0_nak(struct usb_smartbond_data *data) static void empty_ep0_queues(const struct device *dev) { + struct udc_ep_config *cfg_out = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + struct udc_ep_config *cfg_in = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN); struct net_buf *buf; - buf = udc_buf_get_all(dev, USB_CONTROL_EP_OUT); + buf = udc_buf_get_all(cfg_out); if (buf) { net_buf_unref(buf); } - buf = udc_buf_get_all(dev, USB_CONTROL_EP_IN); + buf = udc_buf_get_all(cfg_in); if (buf) { net_buf_unref(buf); } @@ -1452,6 +1456,7 @@ static void handle_ep0_rx_work(struct k_work *item) struct usb_smartbond_data *data = CONTAINER_OF(item, struct usb_smartbond_data, ep0_rx_work); const uint8_t ep = USB_CONTROL_EP_OUT; + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(ep); struct net_buf *buf; const struct device *dev = data->dev; unsigned int lock_key; @@ -1462,8 +1467,8 @@ static void handle_ep0_rx_work(struct k_work *item) */ lock_key = irq_lock(); - udc_ep_set_busy(dev, ep, false); - buf = udc_buf_get(dev, ep); + udc_ep_set_busy(ep_cfg, false); + buf = udc_buf_get(ep_cfg); irq_unlock(lock_key); if (unlikely(buf == NULL)) { @@ -1490,9 +1495,10 @@ static void handle_ep0_tx_work(struct k_work *item) struct net_buf *buf; const struct device *dev = data->dev; const uint8_t ep = USB_CONTROL_EP_IN; + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(ep); unsigned int lock_key; - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); __ASSERT(buf == EP0_IN_STATE(data)->buf, "TX work without buffer %p %p", buf, EP0_IN_STATE(data)->buf); @@ -1502,10 +1508,10 @@ static void handle_ep0_tx_work(struct k_work *item) */ lock_key = irq_lock(); - udc_ep_set_busy(dev, ep, false); + udc_ep_set_busy(ep_cfg, false); /* Remove buffer from queue */ - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(ep_cfg); irq_unlock(lock_key); diff --git a/drivers/usb/udc/udc_stm32.c b/drivers/usb/udc/udc_stm32.c index d95c6fb0afd5..99136d1ba447 100644 --- a/drivers/usb/udc/udc_stm32.c +++ b/drivers/usb/udc/udc_stm32.c @@ -194,7 +194,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) udc_submit_event(priv->dev, UDC_EVT_SOF, 0); } -static int udc_stm32_tx(const struct device *dev, uint8_t ep, +static int udc_stm32_tx(const struct device *dev, struct udc_ep_config *epcfg, struct net_buf *buf) { struct udc_stm32_data *priv = udc_get_private(dev); @@ -202,31 +202,31 @@ static int udc_stm32_tx(const struct device *dev, uint8_t ep, uint8_t *data; uint32_t len; HAL_StatusTypeDef status; - LOG_DBG("TX ep 0x%02x len %u", ep, buf->len); + LOG_DBG("TX ep 0x%02x len %u", epcfg->addr, buf->len); - if (udc_ep_is_busy(dev, ep)) { + if (udc_ep_is_busy(epcfg)) { return 0; } data = buf->data; len = buf->len; - if (ep == USB_CONTROL_EP_IN) { + if (epcfg->addr == USB_CONTROL_EP_IN) { len = MIN(cfg->ep0_mps, buf->len); } buf->data += len; buf->len -= len; - status = HAL_PCD_EP_Transmit(&priv->pcd, ep, data, len); + status = HAL_PCD_EP_Transmit(&priv->pcd, epcfg->addr, data, len); if (status != HAL_OK) { - LOG_ERR("HAL_PCD_EP_Transmit failed(0x%02x), %d", ep, (int)status); + LOG_ERR("HAL_PCD_EP_Transmit failed(0x%02x), %d", epcfg->addr, (int)status); return -EIO; } - udc_ep_set_busy(dev, ep, true); + udc_ep_set_busy(epcfg, true); - if (ep == USB_CONTROL_EP_IN && len > 0) { + if (epcfg->addr == USB_CONTROL_EP_IN && len > 0) { /* Wait for an empty package from the host. * This also flushes the TX FIFO to the host. */ @@ -236,25 +236,25 @@ static int udc_stm32_tx(const struct device *dev, uint8_t ep, return 0; } -static int udc_stm32_rx(const struct device *dev, uint8_t ep, +static int udc_stm32_rx(const struct device *dev, struct udc_ep_config *epcfg, struct net_buf *buf) { struct udc_stm32_data *priv = udc_get_private(dev); HAL_StatusTypeDef status; - LOG_DBG("RX ep 0x%02x len %u", ep, buf->size); + LOG_DBG("RX ep 0x%02x len %u", epcfg->addr, buf->size); - if (udc_ep_is_busy(dev, ep)) { + if (udc_ep_is_busy(epcfg)) { return 0; } - status = HAL_PCD_EP_Receive(&priv->pcd, ep, buf->data, buf->size); + status = HAL_PCD_EP_Receive(&priv->pcd, epcfg->addr, buf->data, buf->size); if (status != HAL_OK) { - LOG_ERR("HAL_PCD_EP_Receive failed(0x%02x), %d", ep, (int)status); + LOG_ERR("HAL_PCD_EP_Receive failed(0x%02x), %d", epcfg->addr, (int)status); return -EIO; } - udc_ep_set_busy(dev, ep, true); + udc_ep_set_busy(epcfg, true); return 0; } @@ -264,14 +264,16 @@ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) uint32_t rx_count = HAL_PCD_EP_GetRxCount(hpcd, epnum); struct udc_stm32_data *priv = hpcd2data(hpcd); const struct device *dev = priv->dev; + struct udc_ep_config *epcfg; uint8_t ep = epnum | USB_EP_DIR_OUT; struct net_buf *buf; LOG_DBG("DataOut ep 0x%02x", ep); - udc_ep_set_busy(dev, ep, false); + epcfg = udc_get_ep_cfg(dev, ep); + udc_ep_set_busy(epcfg, false); - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(epcfg); if (unlikely(buf == NULL)) { LOG_ERR("ep 0x%02x queue is empty", ep); return; @@ -294,9 +296,9 @@ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) udc_submit_ep_event(dev, buf, 0); } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(epcfg); if (buf) { - udc_stm32_rx(dev, ep, buf); + udc_stm32_rx(dev, epcfg, buf); } } @@ -304,14 +306,16 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { struct udc_stm32_data *priv = hpcd2data(hpcd); const struct device *dev = priv->dev; + struct udc_ep_config *epcfg; uint8_t ep = epnum | USB_EP_DIR_IN; struct net_buf *buf; LOG_DBG("DataIn ep 0x%02x", ep); - udc_ep_set_busy(dev, ep, false); + epcfg = udc_get_ep_cfg(dev, ep); + udc_ep_set_busy(epcfg, false); - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(epcfg); if (unlikely(buf == NULL)) { return; } @@ -335,7 +339,7 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) return; } - udc_buf_get(dev, ep); + udc_buf_get(epcfg); if (ep == USB_CONTROL_EP_IN) { if (udc_ctrl_stage_is_status_in(dev) || @@ -360,9 +364,9 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) udc_submit_ep_event(dev, buf, 0); - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(epcfg); if (buf) { - udc_stm32_tx(dev, ep, buf); + udc_stm32_tx(dev, epcfg, buf); } } @@ -763,9 +767,9 @@ static int udc_stm32_ep_enqueue(const struct device *dev, lock_key = irq_lock(); if (USB_EP_DIR_IS_IN(epcfg->addr)) { - ret = udc_stm32_tx(dev, epcfg->addr, buf); + ret = udc_stm32_tx(dev, epcfg, buf); } else { - ret = udc_stm32_rx(dev, epcfg->addr, buf); + ret = udc_stm32_rx(dev, epcfg, buf); } irq_unlock(lock_key); @@ -780,12 +784,12 @@ static int udc_stm32_ep_dequeue(const struct device *dev, udc_stm32_ep_flush(dev, epcfg); - buf = udc_buf_get_all(dev, epcfg->addr); + buf = udc_buf_get_all(epcfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } - udc_ep_set_busy(dev, epcfg->addr, false); + udc_ep_set_busy(epcfg, false); return 0; } diff --git a/drivers/usb/udc/udc_virtual.c b/drivers/usb/udc/udc_virtual.c index c729aa08cd75..ae32c9ae2c62 100644 --- a/drivers/usb/udc/udc_virtual.c +++ b/drivers/usb/udc/udc_virtual.c @@ -172,7 +172,7 @@ static int vrt_handle_out(const struct device *dev, return vrt_request_reply(dev, pkt, UVB_REPLY_STALL); } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { LOG_DBG("reply NACK ep 0x%02x", ep); return vrt_request_reply(dev, pkt, UVB_REPLY_NACK); @@ -184,7 +184,7 @@ static int vrt_handle_out(const struct device *dev, LOG_DBG("Handle data OUT, %zu | %zu", pkt->length, net_buf_tailroom(buf)); if (net_buf_tailroom(buf) == 0 || pkt->length < udc_mps_ep_size(ep_cfg)) { - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(ep_cfg); if (ep == USB_CONTROL_EP_OUT) { err = vrt_handle_ctrl_out(dev, buf); @@ -239,7 +239,7 @@ static int vrt_handle_in(const struct device *dev, return vrt_request_reply(dev, pkt, UVB_REPLY_STALL); } - buf = udc_buf_peek(dev, ep); + buf = udc_buf_peek(ep_cfg); if (buf == NULL) { LOG_DBG("reply NACK ep 0x%02x", ep); return vrt_request_reply(dev, pkt, UVB_REPLY_NACK); @@ -259,7 +259,7 @@ static int vrt_handle_in(const struct device *dev, } LOG_DBG("Finish data IN %zu | %u", pkt->length, buf->len); - buf = udc_buf_get(dev, ep); + buf = udc_buf_get(ep_cfg); if (ep == USB_CONTROL_EP_IN) { err = isr_handle_ctrl_in(dev, buf); @@ -411,7 +411,7 @@ static int udc_vrt_ep_dequeue(const struct device *dev, lock_key = irq_lock(); /* Draft dequeue implementation */ - buf = udc_buf_get_all(dev, cfg->addr); + buf = udc_buf_get_all(cfg); if (buf) { udc_submit_ep_event(dev, buf, -ECONNABORTED); } diff --git a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi index 18e478456a11..cbd75ce5af6f 100644 --- a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi +++ b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi @@ -182,6 +182,18 @@ config NRF70_SR_COEX_RF_SWITCH If this GPIO is asserted (1), the SR side RF switch is connected to the Wi-Fi side (shared antenna). If this GPIO is de-asserted (0), the SR side RF switch is connected to the SR side (separate antenna). +config NRF70_SR_COEX_SLEEP_CTRL_GPIO_CTRL + bool "Configuration of GPIO control for coexistence" + default y + +config NRF70_SR_COEX_SWCTRL1_OUTPUT + int "Configure SWCTRIL1 as output" + default 0 + +config NRF70_SR_COEX_BT_GRANT_ACTIVE_LOW + int "Configure BT grant active low" + default 1 + config NRF70_WORKQ_STACK_SIZE int "Stack size for workqueue" default 4096 @@ -842,4 +854,17 @@ config NRF_WIFI_ZERO_COPY_TX endif # NETWORKING +config NRF_WIFI_MAX_PS_POLL_FAIL_CNT + int "Maximum number of PS-Poll failures" + default 10 + range 10 4294967295 + help + Maximum number of PS-Poll failures before entering qos null-based power save. + +config NRF_WIFI_RX_STBC_HT + bool "Receive packets encoded with STBC in HT (Wi-Fi4) mode" + default y + help + Receive packets encoded with STBC (Space-Time Block Coding) + in HT (Wi-Fi4) mode. endif # WIFI_NRF70 diff --git a/drivers/wifi/nrf_wifi/src/coex.c b/drivers/wifi/nrf_wifi/src/coex.c index 8177fb6f85bc..a9147aad5dc9 100644 --- a/drivers/wifi/nrf_wifi/src/coex.c +++ b/drivers/wifi/nrf_wifi/src/coex.c @@ -103,7 +103,7 @@ const uint16_t config_buffer_5G[] = { /* Shared antenna */ const uint32_t ch_config_sha[] = { 0x00000028, 0x00000000, 0x001e1023, 0x00000000, 0x00000000, - 0x00000000, 0x00000021, 0x000002ca, 0x00000050, 0x00000000, + 0x00000000, 0x00000021, 0x000002ca, 0x0000005A, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; diff --git a/drivers/wifi/nrf_wifi/src/fmac_main.c b/drivers/wifi/nrf_wifi/src/fmac_main.c index 5a7d79141bc8..cc3a40c81abd 100644 --- a/drivers/wifi/nrf_wifi/src/fmac_main.c +++ b/drivers/wifi/nrf_wifi/src/fmac_main.c @@ -581,6 +581,13 @@ enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv unsigned int fw_ver = 0; +#if defined(CONFIG_NRF70_SR_COEX_SLEEP_CTRL_GPIO_CTRL) && \ + defined(CONFIG_NRF70_SYSTEM_MODE) + unsigned int alt_swctrl1_function_bt_coex_status1 = + (~CONFIG_NRF70_SR_COEX_SWCTRL1_OUTPUT) & 0x1; + unsigned int invert_bt_coex_grant_output = CONFIG_NRF70_SR_COEX_BT_GRANT_ACTIVE_LOW; +#endif /* CONFIG_NRF70_SR_COEX_SLEEP_CTRL_GPIO_CTRL && CONFIG_NRF70_SYSTEM_MODE */ + rpu_ctx_zep = &drv_priv_zep->rpu_ctx_zep; rpu_ctx_zep->drv_priv_zep = drv_priv_zep; @@ -624,6 +631,18 @@ enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv configure_board_dep_params(&board_params); +#if defined(CONFIG_NRF70_SR_COEX_SLEEP_CTRL_GPIO_CTRL) && \ + defined(CONFIG_NRF70_SYSTEM_MODE) + LOG_INF("Configuring SLEEP CTRL GPIO control register\n"); + status = nrf_wifi_coex_config_sleep_ctrl_gpio_ctrl(rpu_ctx_zep->rpu_ctx, + alt_swctrl1_function_bt_coex_status1, + invert_bt_coex_grant_output); + if (status != NRF_WIFI_STATUS_SUCCESS) { + LOG_ERR("%s: Failed to configure GPIO control register", __func__); + goto err; + } +#endif /* CONFIG_NRF70_SR_COEX_SLEEP_CTRL_GPIO_CTRL && CONFIG_NRF70_SYSTEM_MODE */ + #ifdef CONFIG_NRF70_RADIO_TEST status = nrf_wifi_rt_fmac_dev_init(rpu_ctx_zep->rpu_ctx, #ifdef CONFIG_NRF_WIFI_LOW_POWER diff --git a/drivers/wifi/nrf_wifi/src/wifi_util.c b/drivers/wifi/nrf_wifi/src/wifi_util.c index ec1dccb2a72c..4a31cae8121a 100644 --- a/drivers/wifi/nrf_wifi/src/wifi_util.c +++ b/drivers/wifi/nrf_wifi/src/wifi_util.c @@ -14,6 +14,9 @@ #include "fmac_main.h" #include "wifi_util.h" +#include "rpu_lmac_phy_stats.h" +#include "rpu_umac_stats.h" + extern struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep; struct nrf_wifi_ctx_zep *ctx = &rpu_drv_priv_zep.rpu_ctx_zep; @@ -963,6 +966,129 @@ static int nrf_wifi_util_rpu_recovery_info(const struct shell *sh, } #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ +static int nrf_wifi_dump_stats(const struct shell *sh, + struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, + const char *name, + struct rpu_stat_global *rpu_stat_g) +{ + int i; + int j; + int ret = 0; + + for (i = 0; rpu_stat_g[i].stats != NULL; i++) { + struct rpu_stat_from_mem *rpu_stat = rpu_stat_g[i].stats; + + shell_fprintf(sh, SHELL_INFO, "RPU %s - %s\n", name, rpu_stat_g[i].name); + shell_fprintf(sh, SHELL_INFO, "======================\n"); + + for (j = 0; rpu_stat[j].name[0] != '\0'; j++) { + uint32_t value = 0; + + if (hal_rpu_mem_read(hal_dev_ctx, &value, + rpu_stat[j].addr, sizeof(value)) != 0) { + shell_fprintf(sh, SHELL_ERROR, + "Failed to read stat %s\n", + rpu_stat[j].name); + continue; + } + + shell_fprintf(sh, SHELL_INFO, "%s: %u\n", + rpu_stat[j].name, + value); + } + + shell_fprintf(sh, SHELL_INFO, "\n"); + } + + return ret; +} + +static int nrf_wifi_util_dump_rpu_stats_mem(const struct shell *sh, + size_t argc, + const char *argv[]) +{ + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx; + struct nrf_wifi_hal_dev_ctx *hal_dev_ctx; + struct rpu_sys_op_stats stats; + enum rpu_stats_type stats_type = RPU_STATS_TYPE_ALL; + int ret; + + if (argc == 2) { + const char *type = argv[1]; + + if (!strcmp(type, "umac")) { + stats_type = RPU_STATS_TYPE_UMAC; + } else if (!strcmp(type, "lmac")) { + stats_type = RPU_STATS_TYPE_LMAC; + } else if (!strcmp(type, "all")) { + stats_type = RPU_STATS_TYPE_ALL; + } else { + shell_fprintf(sh, + SHELL_ERROR, + "Invalid stats type %s\n", + type); + return -ENOEXEC; + } + } + + k_mutex_lock(&ctx->rpu_lock, K_FOREVER); + if (!ctx->rpu_ctx) { + shell_fprintf(sh, + SHELL_ERROR, + "RPU context not initialized\n"); + ret = -ENOEXEC; + goto unlock; + } + fmac_dev_ctx = ctx->rpu_ctx; + if (!fmac_dev_ctx) { + shell_fprintf(sh, + SHELL_ERROR, + "RPU context not initialized\n"); + ret = -ENOEXEC; + goto unlock; + } + hal_dev_ctx = fmac_dev_ctx->hal_dev_ctx; + if (!hal_dev_ctx) { + shell_fprintf(sh, + SHELL_ERROR, + "HAL context not initialized\n"); + ret = -ENOEXEC; + goto unlock; + } + + + memset(&stats, 0, sizeof(struct rpu_sys_op_stats)); + + if (stats_type == RPU_STATS_TYPE_UMAC || stats_type == RPU_STATS_TYPE_ALL) { + nrf_wifi_hal_proc_ctx_set(hal_dev_ctx, RPU_PROC_TYPE_MCU_UMAC); + ret = nrf_wifi_dump_stats(sh, hal_dev_ctx, "UMAC", rpu_all_umac_stats); + if (ret != 0) { + shell_fprintf(sh, + SHELL_ERROR, + "Failed to dump UMAC stats\n"); + goto unlock; + } + } + + if (stats_type == RPU_STATS_TYPE_LMAC || stats_type == RPU_STATS_TYPE_ALL) { + nrf_wifi_hal_proc_ctx_set(hal_dev_ctx, RPU_PROC_TYPE_MCU_LMAC); + ret = nrf_wifi_dump_stats(sh, hal_dev_ctx, "LMAC", rpu_all_lmac_stats); + if (ret != 0) { + shell_fprintf(sh, + SHELL_ERROR, + "Failed to dump LMAC stats\n"); + goto unlock; + } + } + + /* Reset the proc context to default */ + nrf_wifi_hal_proc_ctx_set(hal_dev_ctx, RPU_PROC_TYPE_MCU_LMAC); + +unlock: + k_mutex_unlock(&ctx->rpu_lock); + return ret; +} + SHELL_STATIC_SUBCMD_SET_CREATE( nrf70_util, SHELL_CMD_ARG(he_ltf, @@ -1066,6 +1192,13 @@ SHELL_STATIC_SUBCMD_SET_CREATE( 1, 0), #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ + SHELL_CMD_ARG(rpu_stats_mem, + NULL, + "Display RPU stats by reading from memory " + "Parameters: umac or lmac or or all (default)", + nrf_wifi_util_dump_rpu_stats_mem, + 1, + 1), SHELL_SUBCMD_SET_END); diff --git a/dts/bindings/net/wireless/nordic,nrf21540-fem.yaml b/dts/bindings/net/wireless/nordic,nrf21540-fem.yaml index 706fe8dd9e66..e913733155ac 100644 --- a/dts/bindings/net/wireless/nordic,nrf21540-fem.yaml +++ b/dts/bindings/net/wireless/nordic,nrf21540-fem.yaml @@ -95,7 +95,7 @@ properties: This must be present to support SPI control of the FEM. tx-en-settle-time-us: type: int - default: 11 + default: 26 description: | Settling time in microseconds from state PG to TX. diff --git a/dts/bindings/riscv/nordic,nrf-vpr-coprocessor.yaml b/dts/bindings/riscv/nordic,nrf-vpr-coprocessor.yaml index 43deaeb6d3b0..8760e8288805 100644 --- a/dts/bindings/riscv/nordic,nrf-vpr-coprocessor.yaml +++ b/dts/bindings/riscv/nordic,nrf-vpr-coprocessor.yaml @@ -9,14 +9,17 @@ description: | VPR is a RISC-V CPU implementation. VPR instances are exposed to other CPUs as peripherals. -include: base.yaml +include: [base.yaml, pinctrl-device.yaml] properties: execution-memory: type: phandle - required: true description: | - Memory area from which the VPR core will execute. + Memory area from which the VPR code will execute. + If not specified, the VPR coprocessor will not be launched automatically + by the nordic_vpr_launcher driver when the node is enabled. In such case, + the launching is supposed to be done explicitly by the user code, in some + custom way presumably. source-memory: type: phandle diff --git a/modules/openthread/platform/radio.c b/modules/openthread/platform/radio.c index 82b54a34763e..4a9fc1279cf7 100644 --- a/modules/openthread/platform/radio.c +++ b/modules/openthread/platform/radio.c @@ -158,11 +158,6 @@ static void reset_pending_event(enum pending_events event) atomic_clear_bit(pending_events, event); } -static inline void clear_pending_events(void) -{ - atomic_clear(pending_events); -} - void energy_detected(const struct device *dev, int16_t max_ed) { if (dev == radio_dev) { diff --git a/soc/nordic/common/nrf54hx_nrf92x_mpu_regions.c b/soc/nordic/common/nrf54hx_nrf92x_mpu_regions.c index b76fac86bcd3..a9e8b3de7a91 100644 --- a/soc/nordic/common/nrf54hx_nrf92x_mpu_regions.c +++ b/soc/nordic/common/nrf54hx_nrf92x_mpu_regions.c @@ -18,6 +18,9 @@ #define CAN121_SIZE DT_REG_SIZE_BY_NAME(DT_NODELABEL(can121), message_ram) + \ DT_REG_SIZE_BY_NAME(DT_NODELABEL(can121), m_can) +#define SOFTPERIPH_BASE DT_REG_ADDR(DT_NODELABEL(softperiph_ram)) +#define SOFTPERIPH_SIZE DT_REG_SIZE(DT_NODELABEL(softperiph_ram)) + static struct arm_mpu_region mpu_regions[] = { MPU_REGION_ENTRY("FLASH_0", CONFIG_FLASH_BASE_ADDRESS, @@ -40,6 +43,10 @@ static struct arm_mpu_region mpu_regions[] = { MPU_REGION_ENTRY("CAN121_MCAN", CAN121_BASE, REGION_RAM_NOCACHE_ATTR(CAN121_BASE, CAN121_SIZE)), #endif +#if DT_NODE_EXISTS(DT_NODELABEL(softperiph_ram)) + MPU_REGION_ENTRY("SOFTPERIPH_RAM", SOFTPERIPH_BASE, + REGION_RAM_NOCACHE_ATTR(SOFTPERIPH_BASE, SOFTPERIPH_SIZE)), +#endif }; const struct arm_mpu_config mpu_config = { diff --git a/soc/nordic/nrf54h/Kconfig.defconfig b/soc/nordic/nrf54h/Kconfig.defconfig index 65023fc18ca9..e1bd0aa68014 100644 --- a/soc/nordic/nrf54h/Kconfig.defconfig +++ b/soc/nordic/nrf54h/Kconfig.defconfig @@ -42,4 +42,7 @@ config SPI_DW_ACCESS_WORD_ONLY config PM_DEVICE_POWER_DOMAIN default n if PM_DEVICE +config PM_DEVICE_RUNTIME + default y if PM_DEVICE + endif # SOC_SERIES_NRF54HX diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index 2f3b93ef4412..1dfbf9243160 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -1830,8 +1830,8 @@ int bt_mesh_model_correspond(const struct bt_mesh_model *corresponding_mod, MOD_REL_LIST_FOR_EACH(i) { if (mod_rel_list[i].type < RELATION_TYPE_EXT && - mod_rel_list[i].type > cor_id) { - cor_id = mod_rel_list[i].type; + mod_rel_list[i].type >= cor_id) { + cor_id = mod_rel_list[i].type + 1; } if ((IS_MOD_BASE(base_mod, i, base_offset) || diff --git a/subsys/bluetooth/mesh/proxy_srv.c b/subsys/bluetooth/mesh/proxy_srv.c index 7d16a42a86e3..7894ef8d6089 100644 --- a/subsys/bluetooth/mesh/proxy_srv.c +++ b/subsys/bluetooth/mesh/proxy_srv.c @@ -897,10 +897,13 @@ static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) if (sub == beacon_sub) { beacon_sub = NULL; } + + bt_mesh_proxy_identity_stop(sub); } else { bt_mesh_proxy_beacon_send(sub); - bt_mesh_adv_gatt_update(); } + + bt_mesh_adv_gatt_update(); } BT_MESH_SUBNET_CB_DEFINE(gatt_services) = { diff --git a/subsys/net/l2/openthread/openthread.c b/subsys/net/l2/openthread/openthread.c index 61fe1d5c3bc3..f3553e138742 100644 --- a/subsys/net/l2/openthread/openthread.c +++ b/subsys/net/l2/openthread/openthread.c @@ -329,7 +329,11 @@ static void ot_joiner_start_handler(otError error, void *context) switch (error) { case OT_ERROR_NONE: NET_INFO("Join success"); - otThreadSetEnabled(ot_context->instance, true); + error = otThreadSetEnabled(ot_context->instance, true); + if (error != OT_ERROR_NONE) { + NET_ERR("Failed to start the OpenThread network [%d]", error); + } + break; default: NET_ERR("Join failed [%d]", error); @@ -430,7 +434,11 @@ int openthread_start(struct openthread_context *ot_context) goto exit; } - otIp6SetEnabled(ot_context->instance, true); + error = otIp6SetEnabled(ot_context->instance, true); + if (error != OT_ERROR_NONE) { + NET_ERR("Failed to set %s [%d]", "IPv6 support", error); + goto exit; + } /* Sleepy End Device specific configuration. */ if (IS_ENABLED(CONFIG_OPENTHREAD_MTD_SED)) { @@ -441,8 +449,17 @@ int openthread_start(struct openthread_context *ot_context) */ ot_mode.mRxOnWhenIdle = false; - otThreadSetLinkMode(ot_context->instance, ot_mode); - otLinkSetPollPeriod(ot_context->instance, OT_POLL_PERIOD); + error = otThreadSetLinkMode(ot_context->instance, ot_mode); + if (error != OT_ERROR_NONE) { + NET_ERR("Failed to set %s [%d]", "link mode", error); + goto exit; + } + + error = otLinkSetPollPeriod(ot_context->instance, OT_POLL_PERIOD); + if (error != OT_ERROR_NONE) { + NET_ERR("Failed to set %s [%d]", "poll period", error); + goto exit; + } } /* Configure Child Supervision and MLE Child timeouts. */ @@ -477,16 +494,39 @@ int openthread_start(struct openthread_context *ot_context) otExtendedPanId xpanid; otNetworkKey networkKey; - otThreadSetNetworkName(ot_instance, OT_NETWORK_NAME); - otLinkSetChannel(ot_instance, OT_CHANNEL); - otLinkSetPanId(ot_instance, OT_PANID); + error = otThreadSetNetworkName(ot_instance, OT_NETWORK_NAME); + if (error != OT_ERROR_NONE) { + NET_ERR("Failed to set %s [%d]", "network name", error); + goto exit; + } + + error = otLinkSetChannel(ot_instance, OT_CHANNEL); + if (error != OT_ERROR_NONE) { + NET_ERR("Failed to set %s [%d]", "channel", error); + goto exit; + } + + error = otLinkSetPanId(ot_instance, OT_PANID); + if (error != OT_ERROR_NONE) { + NET_ERR("Failed to set %s [%d]", "PAN ID", error); + goto exit; + } + net_bytes_from_str(xpanid.m8, 8, (char *)OT_XPANID); - otThreadSetExtendedPanId(ot_instance, &xpanid); + error = otThreadSetExtendedPanId(ot_instance, &xpanid); + if (error != OT_ERROR_NONE) { + NET_ERR("Failed to set %s [%d]", "ext PAN ID", error); + goto exit; + } if (strlen(OT_NETWORKKEY)) { net_bytes_from_str(networkKey.m8, OT_NETWORK_KEY_SIZE, (char *)OT_NETWORKKEY); - otThreadSetNetworkKey(ot_instance, &networkKey); + error = otThreadSetNetworkKey(ot_instance, &networkKey); + if (error != OT_ERROR_NONE) { + NET_ERR("Failed to set %s [%d]", "network key", error); + goto exit; + } } } @@ -533,7 +573,7 @@ static int openthread_init(struct net_if *iface) .name = "openthread", .no_yield = true, }; - otError err; + otError err = OT_ERROR_NONE; NET_DBG("openthread_init"); @@ -556,7 +596,11 @@ static int openthread_init(struct net_if *iface) } if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) { - otPlatUartEnable(); + err = otPlatUartEnable(); + if (err != OT_ERROR_NONE) { + NET_ERR("Failed to enable UART: [%d]", err); + } + otNcpHdlcInit(ot_context->instance, ncp_hdlc_send); } else { otIp6SetReceiveFilterEnabled(ot_context->instance, true); @@ -604,7 +648,7 @@ static int openthread_init(struct net_if *iface) (void)k_work_submit_to_queue(&ot_context->work_q, &ot_context->api_work); - return 0; + return (err == OT_ERROR_NONE) ? 0 : -EIO; } void ieee802154_init(struct net_if *iface) diff --git a/subsys/net/l2/openthread/openthread_utils.c b/subsys/net/l2/openthread/openthread_utils.c index 2e78da6b7aad..f9b518725b7b 100644 --- a/subsys/net/l2/openthread/openthread_utils.c +++ b/subsys/net/l2/openthread/openthread_utils.c @@ -14,6 +14,7 @@ LOG_MODULE_DECLARE(net_l2_openthread, CONFIG_OPENTHREAD_L2_LOG_LEVEL); #include #include +#include "net_private.h" #include "openthread_utils.h" #define ALOC16_MASK 0xfc @@ -167,6 +168,7 @@ void add_ipv6_addr_to_ot(struct openthread_context *context, struct otNetifAddress addr = { 0 }; struct net_if_ipv6 *ipv6; struct net_if_addr *if_addr = NULL; + otError error; int i; /* IPv6 struct should've already been allocated when we get an @@ -214,14 +216,14 @@ void add_ipv6_addr_to_ot(struct openthread_context *context, } openthread_api_mutex_lock(context); - otIp6AddUnicastAddress(context->instance, &addr); + error = otIp6AddUnicastAddress(context->instance, &addr); openthread_api_mutex_unlock(context); - if (CONFIG_OPENTHREAD_L2_LOG_LEVEL == LOG_LEVEL_DBG) { - char buf[NET_IPV6_ADDR_LEN]; - - NET_DBG("Added %s", - net_addr_ntop(AF_INET6, &addr.mAddress, buf, sizeof(buf))); + if (error != OT_ERROR_NONE) { + NET_ERR("Failed to add IPv6 unicast address %s [%d]", + net_sprint_ipv6_addr(addr6), error); + } else { + NET_DBG("Added %s", net_sprint_ipv6_addr(addr6)); } } @@ -229,18 +231,19 @@ void add_ipv6_maddr_to_ot(struct openthread_context *context, const struct in6_addr *addr6) { struct otIp6Address addr; + otError error; memcpy(&addr, addr6, sizeof(addr)); openthread_api_mutex_lock(context); - otIp6SubscribeMulticastAddress(context->instance, &addr); + error = otIp6SubscribeMulticastAddress(context->instance, &addr); openthread_api_mutex_unlock(context); - if (CONFIG_OPENTHREAD_L2_LOG_LEVEL == LOG_LEVEL_DBG) { - char buf[NET_IPV6_ADDR_LEN]; - - NET_DBG("Added multicast %s", - net_addr_ntop(AF_INET6, &addr, buf, sizeof(buf))); + if (error != OT_ERROR_NONE) { + NET_ERR("Failed to add IPv6 multicast address %s [%d]", + net_sprint_ipv6_addr(addr6), error); + } else { + NET_DBG("Added %s", net_sprint_ipv6_addr(addr6)); } } diff --git a/subsys/net/lib/zperf/zperf_shell.c b/subsys/net/lib/zperf/zperf_shell.c index 97d9e1e91408..f3f2257f7cc8 100644 --- a/subsys/net/lib/zperf/zperf_shell.c +++ b/subsys/net/lib/zperf/zperf_shell.c @@ -842,6 +842,7 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc, int start = 0; size_t opt_cnt = 0; int ret; + int seconds; param.options.priority = -1; is_udp = proto == IPPROTO_UDP; @@ -909,7 +910,7 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc, break; case 'i': - int seconds = parse_arg(&i, argc, argv); + seconds = parse_arg(&i, argc, argv); if (is_udp) { shell_fprintf(sh, SHELL_WARNING, @@ -1076,6 +1077,7 @@ static int shell_cmd_upload2(const struct shell *sh, size_t argc, bool async = false; int start = 0; size_t opt_cnt = 0; + int seconds; is_udp = proto == IPPROTO_UDP; @@ -1142,7 +1144,7 @@ static int shell_cmd_upload2(const struct shell *sh, size_t argc, break; case 'i': - int seconds = parse_arg(&i, argc, argv); + seconds = parse_arg(&i, argc, argv); if (is_udp) { shell_fprintf(sh, SHELL_WARNING, diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index 17f49e4927ed..6a8e54f9f141 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -1060,6 +1060,9 @@ struct btp_priv_node_id_set_cmd { } __packed; #define BTP_MESH_PROXY_PRIVATE_IDENTITY 0x72 +struct btp_proxy_priv_identity_cmd { + uint8_t enabled; +} __packed; #define BTP_MESH_OD_PRIV_PROXY_GET 0x73 struct btp_od_priv_proxy_get_cmd { diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index acc97d5dda7c..1633fae0c349 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -899,20 +899,40 @@ static uint8_t priv_node_id_set(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +#endif +#ifdef CONFIG_BT_MESH_PRIV_BEACON_SRV static uint8_t proxy_private_identity_enable(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { + const struct btp_proxy_priv_identity_cmd *cp = cmd; + uint16_t net_idx[CONFIG_BT_MESH_SUBNET_COUNT]; + enum bt_mesh_feat_state priv_node_id = BT_MESH_FEATURE_DISABLED; + ssize_t count; int err; LOG_DBG(""); - err = bt_mesh_proxy_private_identity_enable(); - if (err) { - LOG_ERR("Failed to enable proxy private identity (err %d)", err); + count = bt_mesh_subnets_get(net_idx, ARRAY_SIZE(net_idx), 0); + + if (count <= 0) { + LOG_ERR("No subnet (err:%i)", count); return BTP_STATUS_FAILED; } + if (cp->enabled) { + priv_node_id = BT_MESH_FEATURE_ENABLED; + } + + for (int i = 0; i < count; i++) { + err = bt_mesh_subnet_priv_node_id_set(net_idx[i], priv_node_id); + if (err) { + LOG_ERR("Failed to %s proxy private identity for net idx:%x (err %d)", + cp->enabled ? "enable" : "disable", net_idx[i], err); + return BTP_STATUS_FAILED; + } + } + return BTP_STATUS_SUCCESS; } #endif @@ -5251,8 +5271,10 @@ static const struct btp_handler handlers[] = { {.opcode = BTP_MESH_PRIV_NODE_ID_SET, .expect_len = sizeof(struct btp_priv_node_id_set_cmd), .func = priv_node_id_set}, +#endif +#ifdef CONFIG_BT_MESH_PRIV_BEACON_SRV {.opcode = BTP_MESH_PROXY_PRIVATE_IDENTITY, - .expect_len = 0, + .expect_len = sizeof(struct btp_proxy_priv_identity_cmd), .func = proxy_private_identity_enable}, #endif #if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_CLI) diff --git a/tests/bsim/bluetooth/mesh/src/test_cdp1.c b/tests/bsim/bluetooth/mesh/src/test_cdp1.c index 35befdea95b1..fd9e9c9f35e7 100644 --- a/tests/bsim/bluetooth/mesh/src/test_cdp1.c +++ b/tests/bsim/bluetooth/mesh/src/test_cdp1.c @@ -197,7 +197,7 @@ static const struct bt_mesh_comp_p1_model_item test_p1_mod2 = { .cor_present = 1, .format = 0, .ext_item_cnt = 1, - .cor_id = 0, + .cor_id = 1, }; static const struct bt_mesh_comp_p1_model_item test_p1_mod3 = { @@ -211,7 +211,7 @@ static const struct bt_mesh_comp_p1_model_item test_p1_mod4 = { .cor_present = 1, .format = 0, .ext_item_cnt = 0, - .cor_id = 0, + .cor_id = 1, }; static const struct bt_mesh_comp_p1_model_item test_p1_mod5 = { diff --git a/tests/drivers/uart/uart_pm/prj.conf b/tests/drivers/uart/uart_pm/prj.conf index 949c1497802c..a01ea2777b6f 100644 --- a/tests/drivers/uart/uart_pm/prj.conf +++ b/tests/drivers/uart/uart_pm/prj.conf @@ -2,3 +2,4 @@ CONFIG_ZTEST=y CONFIG_SERIAL=y CONFIG_PM=y CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=n diff --git a/west.yml b/west.yml index d4bbd738e6a1..3a2e28b5a1d0 100644 --- a/west.yml +++ b/west.yml @@ -279,7 +279,7 @@ manifest: revision: bb85f7dde4195bfc0fca9e9c7c2eed0f8694203c path: modules/lib/liblc3 - name: libmetal - revision: 3e8781aae9d7285203118c05bc01d4eb0ca565a7 + revision: 14f519529a1e4a46aaea6826f5a41d99a3347276 path: modules/hal/libmetal groups: - hal @@ -318,10 +318,10 @@ manifest: revision: b84bd7314a239f818e78f6927f5673247816df53 path: modules/bsim_hw_models/nrf_hw_models - name: nrf_wifi - revision: f8dbe23c2af8eb06b7a4bd9aa928e93d032a8578 + revision: 8fd3cd7b088d62f145b8b9f5ecc985dd73bd9e77 path: modules/lib/nrf_wifi - name: open-amp - revision: 52bb1783521c62c019451cee9b05b8eda9d7425f + revision: f7f4d083c7909a39d86e217376c69b416ec4faf3 path: modules/lib/open-amp - name: openthread revision: 3ae741f95e7dfb391dec35c48742862049eb62e8