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

Rework to follow ctx->lock for PM runtime get/put #1

Open
wants to merge 3 commits into
base: NRFX-5953-Add-device-PM-to-SPIM
Choose a base branch
from
Open
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
54 changes: 50 additions & 4 deletions drivers/spi/spi_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ static inline bool spi_context_is_slave(struct spi_context *ctx)
return (ctx->config->operation & SPI_OP_MODE_SLAVE);
}

static inline void spi_context_lock(struct spi_context *ctx,
static inline void spi_context_lock_pm(const struct device *dev,
struct spi_context *ctx,
bool asynchronous,
spi_callback_t callback,
void *callback_data,
Expand All @@ -99,6 +100,9 @@ static inline void spi_context_lock(struct spi_context *ctx,
}

k_sem_take(&ctx->lock, K_FOREVER);
if (dev) {
pm_device_runtime_get(dev);
}
ctx->owner = spi_cfg;

#ifdef CONFIG_SPI_ASYNC
Expand All @@ -108,7 +112,18 @@ static inline void spi_context_lock(struct spi_context *ctx,
#endif /* CONFIG_SPI_ASYNC */
}

static inline void spi_context_release(struct spi_context *ctx, int status)
static inline void spi_context_lock(struct spi_context *ctx,
bool asynchronous,
spi_callback_t callback,
void *callback_data,
const struct spi_config *spi_cfg)
{
spi_context_lock_pm(NULL, ctx, asynchronous,
callback, callback_data, spi_cfg);
}

static inline void spi_context_release_pm(const struct device *dev,
struct spi_context *ctx, int status)
{
#ifdef CONFIG_SPI_SLAVE
if (status >= 0 && (ctx->config->operation & SPI_LOCK_ON)) {
Expand All @@ -119,16 +134,27 @@ static inline void spi_context_release(struct spi_context *ctx, int status)
#ifdef CONFIG_SPI_ASYNC
if (!ctx->asynchronous || (status < 0)) {
ctx->owner = NULL;
if (dev) {
pm_device_runtime_put_async(dev);
}
k_sem_give(&ctx->lock);
}
#else
if (!(ctx->config->operation & SPI_LOCK_ON)) {
ctx->owner = NULL;
if (dev) {
pm_device_runtime_put_async(dev);
}
k_sem_give(&ctx->lock);
}
#endif /* CONFIG_SPI_ASYNC */
}

static inline void spi_context_release(struct spi_context *ctx, int status)
{
spi_context_release_pm(NULL, ctx, status);
}

static inline size_t spi_context_total_tx_len(struct spi_context *ctx);
static inline size_t spi_context_total_rx_len(struct spi_context *ctx);

Expand Down Expand Up @@ -180,7 +206,7 @@ static inline int spi_context_wait_for_completion(struct spi_context *ctx)
return status;
}

static inline void spi_context_complete(struct spi_context *ctx,
static inline void spi_context_complete_pm(int do_pm, struct spi_context *ctx,
const struct device *dev,
int status)
{
Expand All @@ -203,6 +229,9 @@ static inline void spi_context_complete(struct spi_context *ctx,

if (!(ctx->config->operation & SPI_LOCK_ON)) {
ctx->owner = NULL;
if (do_pm) {
pm_device_runtime_put_async(dev);
}
k_sem_give(&ctx->lock);
}
}
Expand All @@ -212,6 +241,13 @@ static inline void spi_context_complete(struct spi_context *ctx,
#endif /* CONFIG_SPI_ASYNC */
}

static inline void spi_context_complete(struct spi_context *ctx,
const struct device *dev,
int status)
{
spi_context_complete_pm(0, ctx, dev, status);
}

static inline int spi_context_cs_configure_all(struct spi_context *ctx)
{
int ret;
Expand Down Expand Up @@ -257,17 +293,27 @@ static inline void spi_context_cs_control(struct spi_context *ctx, bool on)
_spi_context_cs_control(ctx, on, false);
}

static inline void spi_context_unlock_unconditionally(struct spi_context *ctx)
static inline void spi_context_unlock_unconditionally_pm(
const struct device *dev,
struct spi_context *ctx)
{
/* Forcing CS to go to inactive status */
_spi_context_cs_control(ctx, false, true);

if (!k_sem_count_get(&ctx->lock)) {
ctx->owner = NULL;
if (dev) {
pm_device_runtime_put_async(dev);
}
k_sem_give(&ctx->lock);
}
}

static inline void spi_context_unlock_unconditionally(struct spi_context *ctx)
{
spi_context_unlock_unconditionally_pm(NULL, ctx);
}

static inline void *spi_context_get_next_buf(const struct spi_buf **current,
size_t *count,
size_t *buf_len,
Expand Down
51 changes: 26 additions & 25 deletions drivers/spi/spi_nrfx_spim.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <zephyr/drivers/spi/rtio.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 @@ -317,10 +318,10 @@ static void finish_transaction(const struct device *dev, int error)

LOG_DBG("Transaction finished with status %d", error);

spi_context_complete(ctx, dev, error);
finalize_spi_transaction(dev, true);
dev_data->busy = false;

finalize_spi_transaction(dev, true);
spi_context_complete_pm(1, ctx, dev, error);
}

static void transfer_next_chunk(const struct device *dev)
Expand Down Expand Up @@ -457,7 +458,8 @@ static int transceive(const struct device *dev,
void *reg = dev_config->spim.p_reg;
int error;

spi_context_lock(&dev_data->ctx, asynchronous, cb, userdata, spi_cfg);
spi_context_lock_pm(dev, &dev_data->ctx, asynchronous,
cb, userdata, spi_cfg);

error = configure(dev, spi_cfg);
if (error == 0) {
Expand Down Expand Up @@ -513,7 +515,7 @@ static int transceive(const struct device *dev,
}
}

spi_context_release(&dev_data->ctx, error);
spi_context_release_pm(dev, &dev_data->ctx, error);

return error;
}
Expand Down Expand Up @@ -551,8 +553,8 @@ static int spi_nrfx_release(const struct device *dev,
return -EBUSY;
}

spi_context_unlock_unconditionally(&dev_data->ctx);
finalize_spi_transaction(dev, false);
spi_context_unlock_unconditionally_pm(dev, &dev_data->ctx);

return 0;
}
Expand All @@ -568,47 +570,40 @@ static const struct spi_driver_api spi_nrfx_driver_api = {
.release = spi_nrfx_release,
};

#ifdef CONFIG_PM_DEVICE
static int spim_nrfx_pm_action(const struct device *dev,
enum pm_device_action action)
{
int ret = 0;
int ret = -ENOTSUP;
struct spi_nrfx_data *dev_data = dev->data;
const struct spi_nrfx_config *dev_config = dev->config;

switch (action) {
case PM_DEVICE_ACTION_RESUME:
ret = pinctrl_apply_state(dev_config->pcfg,
PINCTRL_STATE_DEFAULT);
if (ret < 0) {
return ret;
}
/* nrfx_spim_init() will be called at configuration before
* the next transfer.
*/
break;

case PM_DEVICE_ACTION_SUSPEND:
if (dev_data->initialized) {
nrfx_spim_uninit(&dev_config->spim);
dev_data->initialized = false;
}
if (IS_ENABLED(CONFIG_PM_DEVICE)) {
if (dev_data->initialized) {
nrfx_spim_uninit(&dev_config->spim);
dev_data->initialized = false;
}

ret = pinctrl_apply_state(dev_config->pcfg,
PINCTRL_STATE_SLEEP);
if (ret < 0) {
return ret;
}
ret = pinctrl_apply_state(dev_config->pcfg,
PINCTRL_STATE_SLEEP);
}
break;

default:
ret = -ENOTSUP;
break;
}

return ret;
}
#endif /* CONFIG_PM_DEVICE */


static int spi_nrfx_init(const struct device *dev)
{
Expand Down Expand Up @@ -643,10 +638,16 @@ static int spi_nrfx_init(const struct device *dev)
spi_context_unlock_unconditionally(&dev_data->ctx);

#ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58
return anomaly_58_workaround_init(dev);
#else
return 0;
err = anomaly_58_workaround_init(dev);
if (err < 0) {
return err;
}
#endif
if (IS_ENABLED(CONFIG_PM_DEVICE)) {
/* start in suspended state */
pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_SLEEP);
}
return pm_device_driver_init(dev, spim_nrfx_pm_action);
}
/*
* We use NODELABEL here because the nrfx API requires us to call
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@
pinctrl-names = "default", "sleep";
overrun-character = <0x00>;
cs-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
zephyr,pm-device-runtime-auto;
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 @@ -60,6 +60,7 @@
pinctrl-names = "default", "sleep";
overrun-character = <0x00>;
cs-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
zephyr,pm-device-runtime-auto;
dut_spi_dt: test-spi-dev@0 {
compatible = "vnd,spi-device";
reg = <0>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
overrun-character = <0x00>;
memory-regions = <&dma_fast_region>;
cs-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
zephyr,pm-device-runtime-auto;
dut_spi_dt: test-spi-dev@0 {
compatible = "vnd,spi-device";
reg = <0>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@
pinctrl-names = "default", "sleep";
overrun-character = <0x00>;
cs-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
zephyr,pm-device-runtime-auto;
dut_spi_dt: test-spi-dev@0 {
compatible = "vnd,spi-device";
reg = <0>;
spi-max-frequency = <DT_FREQ_M(16)>;
};
};

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
- nrf54l15dk/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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
&spi1 {
overrun-character = <0x00>;
cs-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
zephyr,pm-device-runtime-auto;
slow@0 {
compatible = "test-spi-loopback-slow";
reg = <0>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
overrun-character = <0x00>;
rx-delay = <1>;
cs-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
zephyr,pm-device-runtime-auto;
slow@0 {
compatible = "test-spi-loopback-slow";
reg = <0>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
&spi1 {
overrun-character = <0x00>;
cs-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
zephyr,pm-device-runtime-auto;
slow@0 {
compatible = "test-spi-loopback-slow";
reg = <0>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
pinctrl-names = "default", "sleep";
overrun-character = <0x00>;
memory-regions = <&cpuapp_dma_region>;
zephyr,pm-device-runtime-auto;
slow@0 {
compatible = "test-spi-loopback-slow";
reg = <0>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
pinctrl-names = "default", "sleep";
overrun-character = <0x00>;
memory-regions = <&dma_fast_region>;
zephyr,pm-device-runtime-auto;
slow@0 {
compatible = "test-spi-loopback-slow";
reg = <0>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
pinctrl-1 = <&spi00_sleep>;
pinctrl-names = "default", "sleep";
overrun-character = <0x00>;
zephyr,pm-device-runtime-auto;
slow@0 {
compatible = "test-spi-loopback-slow";
reg = <0>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
&spi3 {
overrun-character = <0x00>;
cs-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
zephyr,pm-device-runtime-auto;
slow@0 {
compatible = "test-spi-loopback-slow";
reg = <0>;
Expand Down
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 @@ -210,3 +210,8 @@ tests:
platform_allow:
- s32z2xxdc2/s32z270/rtu0
- s32z2xxdc2/s32z270/rtu1
drivers.spi.nrf_pm_runtime:
extra_configs:
- CONFIG_PM_DEVICE=y
- CONFIG_PM_DEVICE_RUNTIME=y
filter: CONFIG_SOC_FAMILY_NORDIC_NRF
Loading