diff --git a/applications/sdp/mspi/src/main.c b/applications/sdp/mspi/src/main.c index 2d26c02c2197..b18848412083 100644 --- a/applications/sdp/mspi/src/main.c +++ b/applications/sdp/mspi/src/main.c @@ -22,7 +22,6 @@ #define DEVICES_MAX 5 #define DATA_PINS_MAX 8 -#define VIO_COUNT 11 /* Bellow this CNT0 period pin steering force has to be increased to produce correct waveform. * CNT0 value 1 generates 32MHz clock. @@ -53,7 +52,7 @@ BUILD_ASSERT(CONFIG_SDP_MSPI_MAX_RESPONSE_SIZE > 0, "Response max size should be greater that 0"); -static const uint8_t pin_to_vio_map[VIO_COUNT] = { +static const uint8_t pin_to_vio_map[NRFE_MSPI_PINS_MAX] = { 4, /* Physical pin 0 */ 0, /* Physical pin 1 */ 1, /* Physical pin 2 */ @@ -81,6 +80,7 @@ static volatile uint8_t ce_vios_count; static volatile uint8_t ce_vios[DEVICES_MAX]; static volatile uint8_t data_vios_count; static volatile uint8_t data_vios[DATA_PINS_MAX]; +static volatile uint8_t clk_vio; static volatile nrfe_mspi_dev_config_t nrfe_mspi_devices[DEVICES_MAX]; static volatile nrfe_mspi_xfer_config_t nrfe_mspi_xfer_config; static volatile nrfe_mspi_xfer_config_t *nrfe_mspi_xfer_config_ptr = &nrfe_mspi_xfer_config; @@ -191,22 +191,22 @@ static void configure_clock(enum mspi_cpp_mode cpp_mode) switch (cpp_mode) { case MSPI_CPP_MODE_0: { vio_config.clk_polarity = 0; - WRITE_BIT(out, pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], VPRCSR_NORDIC_OUT_LOW); + WRITE_BIT(out, clk_vio, VPRCSR_NORDIC_OUT_LOW); break; } case MSPI_CPP_MODE_1: { vio_config.clk_polarity = 1; - WRITE_BIT(out, pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], VPRCSR_NORDIC_OUT_LOW); + WRITE_BIT(out, clk_vio, VPRCSR_NORDIC_OUT_LOW); break; } case MSPI_CPP_MODE_2: { vio_config.clk_polarity = 1; - WRITE_BIT(out, pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], VPRCSR_NORDIC_OUT_HIGH); + WRITE_BIT(out, clk_vio, VPRCSR_NORDIC_OUT_HIGH); break; } case MSPI_CPP_MODE_3: { vio_config.clk_polarity = 0; - WRITE_BIT(out, pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], VPRCSR_NORDIC_OUT_HIGH); + WRITE_BIT(out, clk_vio, VPRCSR_NORDIC_OUT_HIGH); break; } } @@ -240,7 +240,7 @@ static void xfer_execute(nrfe_mspi_xfer_packet_msg_t *xfer_packet, volatile uint xfer_params.cpp_mode = device->cpp; xfer_params.ce_polarity = device->ce_polarity; xfer_params.bus_widths = io_modes[device->io_mode]; - xfer_params.clk_vio = pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER]; + xfer_params.clk_vio = clk_vio; /* Fix position of command and address if command/address length is < BITS_IN_WORD, * so that leading zeros would not be printed instead of data bits. @@ -341,7 +341,7 @@ static void config_pins(nrfe_mspi_pinctrl_soc_pin_msg_t *pins_cfg) xfer_params.tx_direction_mask = 0; xfer_params.rx_direction_mask = 0; - for (uint8_t i = 0; i < NRFE_MSPI_PINS_MAX; i++) { + for (uint8_t i = 0; i < pins_cfg->pins_count; i++) { uint32_t psel = NRF_GET_PIN(pins_cfg->pin[i]); uint32_t fun = NRF_GET_FUN(pins_cfg->pin[i]); @@ -351,7 +351,7 @@ static void config_pins(nrfe_mspi_pinctrl_soc_pin_msg_t *pins_cfg) uint8_t pin_number = NRF_PIN_NUMBER_TO_PIN(psel); - NRFX_ASSERT(pin_number < VIO_COUNT); + NRFX_ASSERT(pin_number < NRFE_MSPI_PINS_MAX); if ((fun >= NRF_FUN_SDP_MSPI_CS0) && (fun <= NRF_FUN_SDP_MSPI_CS4)) { @@ -371,12 +371,9 @@ static void config_pins(nrfe_mspi_pinctrl_soc_pin_msg_t *pins_cfg) VPRCSR_NORDIC_DIR_INPUT); data_vios_count++; } else if (fun == NRF_FUN_SDP_MSPI_SCK) { - WRITE_BIT(xfer_params.tx_direction_mask, - pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], - VPRCSR_NORDIC_DIR_OUTPUT); - WRITE_BIT(xfer_params.rx_direction_mask, - pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], - VPRCSR_NORDIC_DIR_OUTPUT); + clk_vio = pin_to_vio_map[pin_number]; + WRITE_BIT(xfer_params.tx_direction_mask, clk_vio, VPRCSR_NORDIC_DIR_OUTPUT); + WRITE_BIT(xfer_params.rx_direction_mask, clk_vio, VPRCSR_NORDIC_DIR_OUTPUT); } } nrf_vpr_csr_vio_dir_set(xfer_params.tx_direction_mask); diff --git a/drivers/mspi/mspi_nrfe.c b/drivers/mspi/mspi_nrfe.c index 4129c32c6df1..8b8ce8494cff 100644 --- a/drivers/mspi/mspi_nrfe.c +++ b/drivers/mspi/mspi_nrfe.c @@ -29,6 +29,16 @@ LOG_MODULE_REGISTER(mspi_nrfe, CONFIG_MSPI_LOG_LEVEL); #define EXTREME_DRIVE_FREQ_THRESHOLD 32000000 #define CNT0_TOP_CALCULATE(freq) (NRFX_CEIL_DIV(SystemCoreClock, freq * 2) - 1) +#ifdef CONFIG_SOC_NRF54L15 + +#define NRFE_MSPI_PORT_NUMBER 2 /* Physical port number */ +#define NRFE_MSPI_SCK_PIN_NUMBER 1 /* Physical pin number on port 2 */ + +#define NRFE_MSPI_DATA_LINE_CNT_MAX 8 +#else +#error "Unsupported SoC for SDP MSPI" +#endif + #define SDP_MPSI_PINCTRL_DEV_CONFIG_INIT(node_id) \ { \ .reg = PINCTRL_REG_NONE, \ @@ -310,6 +320,75 @@ static int send_data(nrfe_mspi_opcode_t opcode, const void *data, size_t len) return rc; } +static int check_pin_assignments(const struct pinctrl_state *state) +{ + uint8_t data_pins[NRFE_MSPI_DATA_LINE_CNT_MAX]; + uint8_t data_pins_cnt = 0; + uint8_t cs_pins[NRFE_MSPI_PINS_MAX]; + uint8_t cs_pins_cnt = 0; + uint32_t psel = 0; + + for (uint8_t i = 0; i < state->pin_cnt; i++) { + psel = NRF_GET_PIN(state->pins[i]); + if (NRF_PIN_NUMBER_TO_PORT(psel) != NRFE_MSPI_PORT_NUMBER) { + LOG_ERR("Wrong port number. Only %d port is supported.", + NRFE_MSPI_PORT_NUMBER); + return -ENOTSUP; + } + switch (NRF_GET_FUN(state->pins[i])) { + case NRF_FUN_SDP_MSPI_DQ0: + case NRF_FUN_SDP_MSPI_DQ1: + case NRF_FUN_SDP_MSPI_DQ2: + case NRF_FUN_SDP_MSPI_DQ3: + case NRF_FUN_SDP_MSPI_DQ4: + case NRF_FUN_SDP_MSPI_DQ5: + case NRF_FUN_SDP_MSPI_DQ6: + case NRF_FUN_SDP_MSPI_DQ7: + data_pins[data_pins_cnt] = NRF_PIN_NUMBER_TO_PIN(psel); + data_pins_cnt++; + break; + case NRF_FUN_SDP_MSPI_CS0: + case NRF_FUN_SDP_MSPI_CS1: + case NRF_FUN_SDP_MSPI_CS2: + case NRF_FUN_SDP_MSPI_CS3: + case NRF_FUN_SDP_MSPI_CS4: + cs_pins[cs_pins_cnt] = NRF_PIN_NUMBER_TO_PIN(psel); + cs_pins_cnt++; + break; + case NRF_FUN_SDP_MSPI_SCK: + if (NRF_PIN_NUMBER_TO_PIN(psel) != NRFE_MSPI_SCK_PIN_NUMBER) { + LOG_ERR("Clock signal only supported on pin %d.%d", + NRFE_MSPI_PORT_NUMBER, NRFE_MSPI_SCK_PIN_NUMBER); + return -ENOTSUP; + } + break; + default: + LOG_ERR("Not supported pin function: %d", NRF_GET_FUN(state->pins[i])); + return -ENOTSUP; + } + } + + if (cs_pins_cnt == 0) { + LOG_ERR("No CS pin defined."); + return -EINVAL; + } + + for (uint8_t i = 0; i < cs_pins_cnt; i++) { + for (uint8_t j = 0; j < data_pins_cnt; j++) { + if (cs_pins[i] == data_pins[j]) { + LOG_ERR("CS pin cannot be the same as any data line pin."); + return -EINVAL; + } + } + if (cs_pins[i] == NRFE_MSPI_SCK_PIN_NUMBER) { + LOG_ERR("CS pin cannot be the same CLK pin."); + return -EINVAL; + } + } + + return 0; +} + /** * @brief Configures the MSPI controller based on the provided spec. * @@ -326,6 +405,7 @@ static int api_config(const struct mspi_dt_spec *spec) const struct mspi_cfg *config = &spec->config; const struct mspi_nrfe_config *drv_cfg = spec->bus->config; nrfe_mspi_pinctrl_soc_pin_msg_t mspi_pin_config; + int ret; if (config->op_mode != MSPI_OP_MODE_CONTROLLER) { LOG_ERR("Only MSPI controller mode is supported."); @@ -361,10 +441,17 @@ static int api_config(const struct mspi_dt_spec *spec) return -ENOTSUP; } + ret = check_pin_assignments(&drv_cfg->pcfg->states[state_id]); + + if (ret < 0) { + return ret; + } + for (uint8_t i = 0; i < drv_cfg->pcfg->states[state_id].pin_cnt; i++) { mspi_pin_config.pin[i] = drv_cfg->pcfg->states[state_id].pins[i]; } mspi_pin_config.opcode = NRFE_MSPI_CONFIG_PINS; + mspi_pin_config.pins_count = drv_cfg->pcfg->states[state_id].pin_cnt; /* Send pinout configuration to FLPR */ return send_data(NRFE_MSPI_CONFIG_PINS, (const void *)&mspi_pin_config, @@ -387,6 +474,54 @@ static int check_io_mode(enum mspi_io_mode io_mode) return 0; } +static int check_pins_for_io_mode(const struct pinctrl_state *state, enum mspi_io_mode io_mode) +{ + bool d0_defined = false; + bool d1_defined = false; + uint8_t data_pins_cnt = 0; + + switch (io_mode) { + case MSPI_IO_MODE_SINGLE: { + for (uint8_t i = 0; i < state->pin_cnt; i++) { + if (NRF_GET_FUN(state->pins[i]) == NRF_FUN_SDP_MSPI_DQ0) { + d0_defined = true; + } else if (NRF_GET_FUN(state->pins[i]) == NRF_FUN_SDP_MSPI_DQ1) { + d1_defined = true; + } + } + if (!d0_defined || !d1_defined) { + LOG_ERR("IO SINGLE mode requires definitions of D0 and D1 pins."); + return -EINVAL; + } + break; + } + case MSPI_IO_MODE_QUAD: + case MSPI_IO_MODE_QUAD_1_1_4: + case MSPI_IO_MODE_QUAD_1_4_4: { + for (uint8_t i = 0; i < state->pin_cnt; i++) { + switch (NRF_GET_FUN(state->pins[i])) { + case NRF_FUN_SDP_MSPI_DQ0: + case NRF_FUN_SDP_MSPI_DQ1: + case NRF_FUN_SDP_MSPI_DQ2: + case NRF_FUN_SDP_MSPI_DQ3: + data_pins_cnt++; + break; + default: + break; + } + } + if (data_pins_cnt < 4) { + LOG_ERR("Not enough data pins for QUAD mode: %d", data_pins_cnt); + return -EINVAL; + } + break; + } + default: + break; + } + return 0; +} + /** * @brief Configure a device on the MSPI bus. * @@ -458,6 +593,11 @@ static int api_dev_config(const struct device *dev, const struct mspi_dev_id *de if (rc < 0) { return rc; } + rc = check_pins_for_io_mode(&drv_cfg->pcfg->states[PINCTRL_STATE_DEFAULT], + cfg->io_mode); + if (rc < 0) { + return rc; + } } if (param_mask & MSPI_DEVICE_CONFIG_DATA_RATE) { diff --git a/include/drivers/mspi/nrfe_mspi.h b/include/drivers/mspi/nrfe_mspi.h index 31cb73ab4731..aacfa0b70e6a 100644 --- a/include/drivers/mspi/nrfe_mspi.h +++ b/include/drivers/mspi/nrfe_mspi.h @@ -16,16 +16,7 @@ extern "C" { #endif #ifdef CONFIG_SOC_NRF54L15 - -#define NRFE_MSPI_PORT_NUMBER 2 /* Physical port number */ -#define NRFE_MSPI_SCK_PIN_NUMBER 1 /* Physical pins number on port 2 */ -#define NRFE_MSPI_DQ0_PIN_NUMBER 2 -#define NRFE_MSPI_DQ1_PIN_NUMBER 4 -#define NRFE_MSPI_DQ2_PIN_NUMBER 3 -#define NRFE_MSPI_DQ3_PIN_NUMBER 0 -#define NRFE_MSPI_CS0_PIN_NUMBER 5 -#define NRFE_MSPI_PINS_MAX 6 - +#define NRFE_MSPI_PINS_MAX 11 #else #error "Unsupported SoC for SDP MSPI" #endif @@ -70,6 +61,7 @@ typedef struct { typedef struct { nrfe_mspi_opcode_t opcode; /* NRFE_MSPI_CONFIG_PINS */ + uint8_t pins_count; pinctrl_soc_pin_t pin[NRFE_MSPI_PINS_MAX]; } nrfe_mspi_pinctrl_soc_pin_msg_t;