Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nrf fromlist] drivers: spi: nrfx_spim: Add support for device PM #1882

Merged
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
101 changes: 64 additions & 37 deletions drivers/spi/spi_nrfx_spim.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <zephyr/drivers/spi.h>
#include <zephyr/cache.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/device_runtime.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/mem_mgmt/mem_attr.h>
#include <soc.h>
Expand Down Expand Up @@ -139,15 +140,56 @@ static inline nrf_spim_bit_order_t get_nrf_spim_bit_order(uint16_t operation)
}
}

static int spim_init(const struct device *dev)
{
struct spi_nrfx_data *dev_data = dev->data;
const struct spi_nrfx_config *dev_config = dev->config;
nrfx_spim_config_t config;
struct spi_context *ctx = &dev_data->ctx;
const struct spi_config *spi_cfg = ctx->config;
uint32_t max_freq = dev_config->max_freq;
nrfx_err_t result = NRFX_SUCCESS;

#if defined(CONFIG_SOC_NRF5340_CPUAPP)
/* On nRF5340, the 32 Mbps speed is supported by the application core
* when it is running at 128 MHz (see the Timing specifications section
* in the nRF5340 PS).
*/
if (max_freq > 16000000 &&
nrf_clock_hfclk_div_get(NRF_CLOCK) != NRF_CLOCK_HFCLK_DIV_1) {
max_freq = 16000000;
}
#endif

config = dev_config->def_config;

/* Limit the frequency to that supported by the SPIM instance. */
config.frequency = get_nrf_spim_frequency(MIN(spi_cfg->frequency,
max_freq));
config.mode = get_nrf_spim_mode(spi_cfg->operation);
config.bit_order = get_nrf_spim_bit_order(spi_cfg->operation);

if (dev_data->initialized) {
nrfx_spim_uninit(&dev_config->spim);
dev_data->initialized = false;
}

result = nrfx_spim_init(&dev_config->spim, &config,
event_handler, (void *)dev);
if (result != NRFX_SUCCESS) {
LOG_ERR("Failed to initialize nrfx driver: %08x", result);
return -EIO;
}
return 0;
}

static int configure(const struct device *dev,
const struct spi_config *spi_cfg)
{
struct spi_nrfx_data *dev_data = dev->data;
const struct spi_nrfx_config *dev_config = dev->config;
struct spi_context *ctx = &dev_data->ctx;
uint32_t max_freq = dev_config->max_freq;
nrfx_spim_config_t config;
nrfx_err_t result;
int ret;

if (dev_data->initialized && spi_context_configured(ctx, spi_cfg)) {
/* Already configured. No need to do it again. */
Expand Down Expand Up @@ -185,44 +227,22 @@ static int configure(const struct device *dev,
return -EINVAL;
}

#if defined(CONFIG_SOC_NRF5340_CPUAPP)
/* On nRF5340, the 32 Mbps speed is supported by the application core
* when it is running at 128 MHz (see the Timing specifications section
* in the nRF5340 PS).
*/
if (max_freq > 16000000 &&
nrf_clock_hfclk_div_get(NRF_CLOCK) != NRF_CLOCK_HFCLK_DIV_1) {
max_freq = 16000000;
}
#endif

config = dev_config->def_config;

/* Limit the frequency to that supported by the SPIM instance. */
config.frequency = get_nrf_spim_frequency(MIN(spi_cfg->frequency,
max_freq));
config.mode = get_nrf_spim_mode(spi_cfg->operation);
config.bit_order = get_nrf_spim_bit_order(spi_cfg->operation);

nrfy_gpio_pin_write(nrfy_spim_sck_pin_get(dev_config->spim.p_reg),
spi_cfg->operation & SPI_MODE_CPOL ? 1 : 0);

if (dev_data->initialized) {
nrfx_spim_uninit(&dev_config->spim);
dev_data->initialized = false;
}
ctx->config = spi_cfg;
#ifdef CONFIG_PM_DEVICE_RUNTIME
ret = pm_device_runtime_get(dev);
#else
ret = spim_init(dev);
#endif
if (ret < 0) {

result = nrfx_spim_init(&dev_config->spim, &config,
event_handler, (void *)dev);
if (result != NRFX_SUCCESS) {
LOG_ERR("Failed to initialize nrfx driver: %08x", result);
return -EIO;
return ret;
}

dev_data->initialized = true;

ctx->config = spi_cfg;

return 0;
}

Expand Down Expand Up @@ -320,6 +340,7 @@ static void finish_transaction(const struct device *dev, int error)
dev_data->busy = false;

finalize_spi_transaction(dev, true);
(void)pm_device_runtime_put(dev);
}

static void transfer_next_chunk(const struct device *dev)
Expand Down Expand Up @@ -579,9 +600,7 @@ static int spim_nrfx_pm_action(const struct device *dev,
if (ret < 0) {
return ret;
}
/* nrfx_spim_init() will be called at configuration before
* the next transfer.
*/
ret = spim_init(dev);
break;

case PM_DEVICE_ACTION_SUSPEND:
Expand Down Expand Up @@ -612,7 +631,10 @@ static int spi_nrfx_init(const struct device *dev)
struct spi_nrfx_data *dev_data = dev->data;
int err;

err = pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_DEFAULT);
err = pinctrl_apply_state(dev_config->pcfg,
COND_CODE_1(CONFIG_PM_DEVICE_RUNTIME,
(PINCTRL_STATE_SLEEP),
(PINCTRL_STATE_DEFAULT)));
if (err < 0) {
return err;
}
Expand All @@ -638,6 +660,11 @@ static int spi_nrfx_init(const struct device *dev)

spi_context_unlock_unconditionally(&dev_data->ctx);

#ifdef CONFIG_PM_DEVICE_RUNTIME
pm_device_init_suspended(dev);
pm_device_runtime_enable(dev);
#endif

#ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58
return anomaly_58_workaround_init(dev);
#else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
dut_spi_dt: test-spi-dev@0 {
compatible = "vnd,spi-device";
reg = <0>;
spi-max-frequency = <DT_FREQ_M(8)>;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
dut_spi_dt: test-spi-dev@0 {
compatible = "vnd,spi-device";
reg = <0>;
spi-max-frequency = <DT_FREQ_M(8)>;
};
};

Expand Down
6 changes: 6 additions & 0 deletions tests/drivers/spi/spi_controller_peripheral/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,9 @@ tests:
- nrf52840dk/nrf52840
- nrf54l15pdk/nrf54l15/cpuapp
- nrf54h20dk/nrf54h20/cpurad

drivers.spi.pm_runtime:
extra_configs:
- CONFIG_PM_DEVICE=y
- CONFIG_PM_DEVICE_RUNTIME=y
filter: CONFIG_SOC_FAMILY_NORDIC_NRF
5 changes: 5 additions & 0 deletions tests/drivers/spi/spi_loopback/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,8 @@ tests:
extra_args: DTC_OVERLAY_FILE="boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay"
platform_allow:
- nrf54h20dk/nrf54h20/cpuapp
drivers.spi.nrf_pm_runtime:
extra_configs:
- CONFIG_PM_DEVICE=y
- CONFIG_PM_DEVICE_RUNTIME=y
filter: CONFIG_SOC_FAMILY_NORDIC_NRF
Loading