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
49 changes: 30 additions & 19 deletions applications/sdp/mspi/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ 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 nrfe_mspi_xfer_config_t nrfe_mspi_xfer_config;
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;

static volatile hrt_xfer_t xfer_params;

Expand Down Expand Up @@ -181,11 +182,11 @@ static void configure_clock(enum mspi_cpp_mode cpp_mode)
static void xfer_execute(nrfe_mspi_xfer_packet_msg_t *xfer_packet)
{
volatile nrfe_mspi_dev_config_t *device =
&nrfe_mspi_devices[nrfe_mspi_xfer_config.device_index];
&nrfe_mspi_devices[nrfe_mspi_xfer_config_ptr->device_index];

xfer_params.counter_value = 4;
xfer_params.ce_vio = ce_vios[device->ce_index];
xfer_params.ce_hold = nrfe_mspi_xfer_config.hold_ce;
xfer_params.ce_hold = nrfe_mspi_xfer_config_ptr->hold_ce;
xfer_params.cpp_mode = device->cpp;
xfer_params.ce_polarity = device->ce_polarity;
xfer_params.bus_widths = io_modes[device->io_mode];
Expand All @@ -196,46 +197,47 @@ static void xfer_execute(nrfe_mspi_xfer_packet_msg_t *xfer_packet)
*/
xfer_packet->command =
xfer_packet->command
<< (BITS_IN_WORD - nrfe_mspi_xfer_config.command_length * BITS_IN_BYTE);
<< (BITS_IN_WORD - nrfe_mspi_xfer_config_ptr->command_length * BITS_IN_BYTE);
xfer_packet->address =
xfer_packet->address
<< (BITS_IN_WORD - nrfe_mspi_xfer_config.address_length * BITS_IN_BYTE);
<< (BITS_IN_WORD - nrfe_mspi_xfer_config_ptr->address_length * BITS_IN_BYTE);

xfer_params.xfer_data[HRT_FE_COMMAND].vio_out_set =
&nrf_vpr_csr_vio_out_buffered_reversed_word_set;
xfer_params.xfer_data[HRT_FE_COMMAND].data = (uint8_t *)&xfer_packet->command;
xfer_params.xfer_data[HRT_FE_COMMAND].word_count = 0;

adjust_tail(&xfer_params.xfer_data[HRT_FE_COMMAND], xfer_params.bus_widths.command,
nrfe_mspi_xfer_config.command_length * BITS_IN_BYTE);
nrfe_mspi_xfer_config_ptr->command_length * BITS_IN_BYTE);

xfer_params.xfer_data[HRT_FE_ADDRESS].vio_out_set =
&nrf_vpr_csr_vio_out_buffered_reversed_word_set;
xfer_params.xfer_data[HRT_FE_ADDRESS].data = (uint8_t *)&xfer_packet->address;
xfer_params.xfer_data[HRT_FE_ADDRESS].word_count = 0;

adjust_tail(&xfer_params.xfer_data[HRT_FE_ADDRESS], xfer_params.bus_widths.address,
nrfe_mspi_xfer_config.address_length * BITS_IN_BYTE);
nrfe_mspi_xfer_config_ptr->address_length * BITS_IN_BYTE);

xfer_params.xfer_data[HRT_FE_DUMMY_CYCLES].vio_out_set =
&nrf_vpr_csr_vio_out_buffered_reversed_word_set;
xfer_params.xfer_data[HRT_FE_DUMMY_CYCLES].data = NULL;
xfer_params.xfer_data[HRT_FE_DUMMY_CYCLES].word_count = 0;

hrt_frame_element_t elem =
nrfe_mspi_xfer_config.address_length != 0 ? HRT_FE_ADDRESS : HRT_FE_COMMAND;
nrfe_mspi_xfer_config_ptr->address_length != 0 ? HRT_FE_ADDRESS : HRT_FE_COMMAND;

/* Up to 63 clock pulses (including data from previous part) can be sent by simply
* increasing shift count of last word in the previous part.
* Beyond that, dummy cycles have to be treated af different transfer part.
*/
if (xfer_params.xfer_data[elem].last_word_clocks + nrfe_mspi_xfer_config.tx_dummy <=
if (xfer_params.xfer_data[elem].last_word_clocks + nrfe_mspi_xfer_config_ptr->tx_dummy <=
MAX_SHIFT_COUNT) {
xfer_params.xfer_data[elem].last_word_clocks += nrfe_mspi_xfer_config.tx_dummy;
xfer_params.xfer_data[elem].last_word_clocks += nrfe_mspi_xfer_config_ptr->tx_dummy;
} else {
adjust_tail(&xfer_params.xfer_data[HRT_FE_DUMMY_CYCLES],
xfer_params.bus_widths.dummy_cycles,
nrfe_mspi_xfer_config.tx_dummy * xfer_params.bus_widths.dummy_cycles);
nrfe_mspi_xfer_config_ptr->tx_dummy *
xfer_params.bus_widths.dummy_cycles);
}

xfer_params.xfer_data[HRT_FE_DATA].vio_out_set =
Expand Down Expand Up @@ -267,12 +269,12 @@ static void xfer_execute(nrfe_mspi_xfer_packet_msg_t *xfer_packet)
void prepare_and_read_data(nrfe_mspi_xfer_packet_msg_t *xfer_packet, volatile uint8_t *buffer)
{
volatile nrfe_mspi_dev_config_t *device =
&nrfe_mspi_devices[nrfe_mspi_xfer_config.device_index];
&nrfe_mspi_devices[nrfe_mspi_xfer_config_ptr->device_index];
nrf_vpr_csr_vio_config_t config;

xfer_params.counter_value = 4;
xfer_params.ce_vio = ce_vios[device->ce_index];
xfer_params.ce_hold = nrfe_mspi_xfer_config.hold_ce;
xfer_params.ce_hold = nrfe_mspi_xfer_config_ptr->hold_ce;
xfer_params.ce_polarity = device->ce_polarity;
xfer_params.bus_widths = io_modes[device->io_mode];
xfer_params.xfer_data[HRT_FE_DATA].data = buffer;
Expand All @@ -287,22 +289,24 @@ void prepare_and_read_data(nrfe_mspi_xfer_packet_msg_t *xfer_packet, volatile ui
*/
xfer_packet->command =
xfer_packet->command
<< (BITS_IN_WORD - nrfe_mspi_xfer_config.command_length * BITS_IN_BYTE);
<< (BITS_IN_WORD - nrfe_mspi_xfer_config_ptr->command_length * BITS_IN_BYTE);
xfer_packet->address =
xfer_packet->address
<< (BITS_IN_WORD - nrfe_mspi_xfer_config.address_length * BITS_IN_BYTE);
<< (BITS_IN_WORD - nrfe_mspi_xfer_config_ptr->address_length * BITS_IN_BYTE);

/* Configure command phase. */
xfer_params.xfer_data[HRT_FE_COMMAND].vio_out_set =
nrf_vpr_csr_vio_out_buffered_reversed_word_set;
xfer_params.xfer_data[HRT_FE_COMMAND].data = (uint8_t *)&xfer_packet->command;
xfer_params.xfer_data[HRT_FE_COMMAND].word_count = nrfe_mspi_xfer_config.command_length;
xfer_params.xfer_data[HRT_FE_COMMAND].word_count =
nrfe_mspi_xfer_config_ptr->command_length;

/* Configure address phase. */
xfer_params.xfer_data[HRT_FE_ADDRESS].vio_out_set =
nrf_vpr_csr_vio_out_buffered_reversed_word_set;
xfer_params.xfer_data[HRT_FE_ADDRESS].data = (uint8_t *)&xfer_packet->address;
xfer_params.xfer_data[HRT_FE_ADDRESS].word_count = nrfe_mspi_xfer_config.address_length;
xfer_params.xfer_data[HRT_FE_ADDRESS].word_count =
nrfe_mspi_xfer_config_ptr->address_length;

/* Configure data phase. */
xfer_params.xfer_data[HRT_FE_DATA].word_count = xfer_packet->num_bytes;
Expand Down Expand Up @@ -370,6 +374,10 @@ static void ep_bound(void *priv)

static void ep_recv(const void *data, size_t len, void *priv)
{
#ifdef CONFIG_SDP_MSPI_IPC_NO_COPY
data = *(void **)data;
#endif

(void)priv;
(void)len;
nrfe_mspi_flpr_response_msg_t response;
Expand Down Expand Up @@ -421,9 +429,12 @@ static void ep_recv(const void *data, size_t len, void *priv)
xfer_config->xfer_config.command_length != 0 ||
xfer_config->xfer_config.address_length != 0);

#ifdef CONFIG_SDP_MSPI_IPC_NO_COPY
nrfe_mspi_xfer_config_ptr = &xfer_config->xfer_config;
#else
nrfe_mspi_xfer_config = xfer_config->xfer_config;

configure_clock(nrfe_mspi_devices[nrfe_mspi_xfer_config.device_index].cpp);
#endif
configure_clock(nrfe_mspi_devices[nrfe_mspi_xfer_config_ptr->device_index].cpp);
break;
}
case NRFE_MSPI_TX:
Expand Down
97 changes: 61 additions & 36 deletions drivers/mspi/mspi_nrfe.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ LOG_MODULE_REGISTER(mspi_nrfe, CONFIG_MSPI_LOG_LEVEL);
#define MSPI_NRFE_NODE DT_DRV_INST(0)
#define MAX_TX_MSG_SIZE (DT_REG_SIZE(DT_NODELABEL(sram_tx)))
#define MAX_RX_MSG_SIZE (DT_REG_SIZE(DT_NODELABEL(sram_rx)))
#define CONFIG_TIMEOUT_MS 100
#define IPC_TIMEOUT_MS 100
#define EP_SEND_TIMEOUT_MS 10

#define SDP_MPSI_PINCTRL_DEV_CONFIG_INIT(node_id) \
Expand Down Expand Up @@ -65,6 +65,10 @@ static atomic_t ipc_atomic_sem = ATOMIC_INIT(0);
.sw_multi_periph = false, \
}

struct mspi_nrfe_data {
nrfe_mspi_xfer_config_msg_t xfer_config_msg;
};

struct mspi_nrfe_config {
struct mspi_cfg mspicfg;
const struct pinctrl_dev_config *pcfg;
Expand All @@ -75,6 +79,8 @@ static const struct mspi_nrfe_config dev_config = {
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
};

static struct mspi_nrfe_data dev_data;

static void ep_recv(const void *data, size_t len, void *priv);

static void ep_bound(void *priv)
Expand Down Expand Up @@ -254,27 +260,35 @@ static int nrfe_mspi_wait_for_response(nrfe_mspi_opcode_t opcode, uint32_t timeo
}

/**
* @brief Send a configuration struct to the FLPR core using the IPC service.
* @brief Send data to the FLPR core using the IPC service, and wait for FLPR response.
*
* @param opcode The configuration packet opcode to send.
* @param config The data to send.
* @param data The data to send.
* @param len The length of the data to send.
*
* @return 0 on success, negative errno code on failure.
*/
static int send_config(nrfe_mspi_opcode_t opcode, const void *config, size_t len)
static int send_data(nrfe_mspi_opcode_t opcode, const void *data, size_t len)
{
int rc;
rc = mspi_ipc_data_send(opcode, config, len);

#ifdef CONFIG_MSPI_NRFE_IPC_NO_COPY
(void)len;
void *data_ptr = (void *)data;

rc = mspi_ipc_data_send(opcode, &data_ptr, sizeof(void *));
#else
rc = mspi_ipc_data_send(opcode, data, len);
#endif

if (rc < 0) {
LOG_ERR("Configuration send failed: %d", rc);
LOG_ERR("Data transfer failed: %d", rc);
return rc;
}

rc = nrfe_mspi_wait_for_response(opcode, CONFIG_TIMEOUT_MS);
rc = nrfe_mspi_wait_for_response(opcode, IPC_TIMEOUT_MS);
if (rc < 0) {
LOG_ERR("FLPR config: %d response timeout: %d!", opcode, rc);
LOG_ERR("Data transfer: %d response timeout: %d!", opcode, rc);
}

return rc;
Expand Down Expand Up @@ -337,8 +351,8 @@ static int api_config(const struct mspi_dt_spec *spec)
mspi_pin_config.opcode = NRFE_MSPI_CONFIG_PINS;

/* Send pinout configuration to FLPR */
return send_config(NRFE_MSPI_CONFIG_PINS, (const void *)&mspi_pin_config,
sizeof(nrfe_mspi_pinctrl_soc_pin_msg_t));
return send_data(NRFE_MSPI_CONFIG_PINS, (const void *)&mspi_pin_config,
sizeof(nrfe_mspi_pinctrl_soc_pin_msg_t));
}

static int check_io_mode(enum mspi_io_mode io_mode)
Expand Down Expand Up @@ -425,8 +439,8 @@ static int api_dev_config(const struct device *dev, const struct mspi_dev_id *de
mspi_dev_config_msg.dev_config.freq = cfg->freq;
mspi_dev_config_msg.dev_config.ce_index = cfg->ce_num;

return send_config(NRFE_MSPI_CONFIG_DEV, (void *)&mspi_dev_config_msg,
sizeof(nrfe_mspi_dev_config_msg_t));
return send_data(NRFE_MSPI_CONFIG_DEV, (void *)&mspi_dev_config_msg,
sizeof(nrfe_mspi_dev_config_msg_t));
}

static int api_get_channel_status(const struct device *dev, uint8_t ch)
Expand All @@ -449,27 +463,38 @@ static int api_get_channel_status(const struct device *dev, uint8_t ch)
static int xfer_packet(struct mspi_xfer_packet *packet, uint32_t timeout)
{
int rc;
nrfe_mspi_opcode_t opcode = (packet->dir == MSPI_RX) ? NRFE_MSPI_TXRX : NRFE_MSPI_TX;

#ifdef CONFIG_MSPI_NRFE_IPC_NO_COPY
/* Check for alignment problems. */
uint32_t len = ((uint32_t)packet->data_buf) % sizeof(uint32_t) != 0
? sizeof(nrfe_mspi_xfer_packet_msg_t) + packet->num_bytes
: sizeof(nrfe_mspi_xfer_packet_msg_t);
#else
uint32_t len = sizeof(nrfe_mspi_xfer_packet_msg_t) + packet->num_bytes;
#endif
uint8_t buffer[len];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This buffer should be word aligned.
Also, it really should not be a local variable length array, but that can be fixed separately.

nrfe_mspi_xfer_packet_msg_t *xfer_packet = (nrfe_mspi_xfer_packet_msg_t *)buffer;

xfer_packet->opcode = (packet->dir == MSPI_RX) ? NRFE_MSPI_TXRX : NRFE_MSPI_TX;
xfer_packet->opcode = opcode;
xfer_packet->command = packet->cmd;
xfer_packet->address = packet->address;
xfer_packet->num_bytes = packet->num_bytes;

memcpy((void *)xfer_packet->data, (void *)packet->data_buf, packet->num_bytes);

rc = mspi_ipc_data_send(xfer_packet->opcode, buffer, len);
if (rc < 0) {
LOG_ERR("Packet transfer error: %d", rc);
#ifdef CONFIG_MSPI_NRFE_IPC_NO_COPY
/* Check for alignlemt problems. */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* Check for alignlemt problems. */
/* Check for alignment problems. */

Also, please add explanation why this is needed.

if (((uint32_t)packet->data_buf) % sizeof(uint32_t) != 0) {
memcpy((void *)(buffer + sizeof(nrfe_mspi_xfer_packet_msg_t)),
(void *)packet->data_buf, packet->num_bytes);
xfer_packet->data = buffer + sizeof(nrfe_mspi_xfer_packet_msg_t);
} else {
xfer_packet->data = packet->data_buf;
}
#else
memcpy((void *)xfer_packet->data, (void *)packet->data_buf, packet->num_bytes);
#endif

rc = nrfe_mspi_wait_for_response(xfer_packet->opcode, timeout);
if (rc < 0) {
LOG_ERR("FLPR Xfer response timeout: %d", rc);
return rc;
}
rc = send_data(xfer_packet->opcode, xfer_packet, len);

/* Wait for the transfer to complete and receive data. */
if ((packet->dir == MSPI_RX) && (ipc_receive_buffer != NULL) && (ipc_received > 0)) {
Expand Down Expand Up @@ -534,10 +559,9 @@ static int start_next_packet(struct mspi_xfer *xfer, uint32_t packets_done)
static int api_transceive(const struct device *dev, const struct mspi_dev_id *dev_id,
const struct mspi_xfer *req)
{
(void)dev;
struct mspi_nrfe_data *drv_data = dev->data;
uint32_t packets_done = 0;
int rc;
nrfe_mspi_xfer_config_msg_t mspi_xfer_config_msg;

/* TODO: add support for asynchronous transfers */
if (req->async) {
Expand All @@ -549,16 +573,17 @@ static int api_transceive(const struct device *dev, const struct mspi_dev_id *de
return -EFAULT;
}

mspi_xfer_config_msg.opcode = NRFE_MSPI_CONFIG_XFER;
mspi_xfer_config_msg.xfer_config.device_index = dev_id->dev_idx;
mspi_xfer_config_msg.xfer_config.command_length = req->cmd_length;
mspi_xfer_config_msg.xfer_config.address_length = req->addr_length;
mspi_xfer_config_msg.xfer_config.hold_ce = req->hold_ce;
mspi_xfer_config_msg.xfer_config.tx_dummy = req->tx_dummy;
mspi_xfer_config_msg.xfer_config.rx_dummy = req->rx_dummy;
drv_data->xfer_config_msg.opcode = NRFE_MSPI_CONFIG_XFER;
drv_data->xfer_config_msg.xfer_config.device_index = dev_id->dev_idx;
drv_data->xfer_config_msg.xfer_config.command_length = req->cmd_length;
drv_data->xfer_config_msg.xfer_config.address_length = req->addr_length;
drv_data->xfer_config_msg.xfer_config.hold_ce = req->hold_ce;
drv_data->xfer_config_msg.xfer_config.tx_dummy = req->tx_dummy;
drv_data->xfer_config_msg.xfer_config.rx_dummy = req->rx_dummy;

rc = send_data(NRFE_MSPI_CONFIG_XFER, (void *)&drv_data->xfer_config_msg,
sizeof(nrfe_mspi_xfer_config_msg_t));

rc = send_config(NRFE_MSPI_CONFIG_XFER, (void *)&mspi_xfer_config_msg,
sizeof(nrfe_mspi_xfer_config_msg_t));
if (rc < 0) {
LOG_ERR("Send xfer config error: %d", rc);
return rc;
Expand Down Expand Up @@ -678,5 +703,5 @@ static const struct mspi_driver_api drv_api = {

PM_DEVICE_DT_INST_DEFINE(0, dev_pm_action_cb);

DEVICE_DT_INST_DEFINE(0, nrfe_mspi_init, PM_DEVICE_DT_INST_GET(0), NULL, &dev_config, POST_KERNEL,
CONFIG_MSPI_NRFE_INIT_PRIORITY, &drv_api);
DEVICE_DT_INST_DEFINE(0, nrfe_mspi_init, PM_DEVICE_DT_INST_GET(0), &dev_data, &dev_config,
POST_KERNEL, CONFIG_MSPI_NRFE_INIT_PRIORITY, &drv_api);
4 changes: 4 additions & 0 deletions include/drivers/mspi/nrfe_mspi.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,11 @@ typedef struct {
uint32_t command;
uint32_t address;
uint32_t num_bytes; /* Size of data */
#if (defined(CONFIG_MSPI_NRFE_IPC_NO_COPY) || defined(CONFIG_SDP_MSPI_IPC_NO_COPY))
uint8_t *data;
#else
uint8_t data[]; /* Variable length data field at the end of packet. */
#endif
} nrfe_mspi_xfer_packet_msg_t;

typedef struct {
Expand Down