Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions applications/sdp/mspi/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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]);

Expand All @@ -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)) {

Expand All @@ -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);
Expand Down
140 changes: 140 additions & 0 deletions drivers/mspi/mspi_nrfe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, \
Expand Down Expand Up @@ -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.
*
Expand All @@ -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.");
Expand Down Expand Up @@ -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,
Expand All @@ -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.
*
Expand Down Expand Up @@ -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) {
Expand Down
12 changes: 2 additions & 10 deletions include/drivers/mspi/nrfe_mspi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand Down