drivers: spi: nrfx: Add support for pinctrl
Add support for the new pinctrl API to the SPI drivers that handle the nRF SPI, SPIM, and SPIS peripherals. Update code of the drivers and related devicetree bindings. Signed-off-by: Andrzej Głąbek <andrzej.glabek@nordicsemi.no>
This commit is contained in:
parent
2a87e04ce6
commit
32b9e65e4b
6 changed files with 164 additions and 45 deletions
|
@ -106,11 +106,13 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
|
|||
#if defined(NRF_PSEL_SPIM)
|
||||
case NRF_FUN_SPIM_SCK:
|
||||
NRF_PSEL_SPIM(reg, SCK) = NRF_GET_PIN(pins[i]);
|
||||
nrf_gpio_pin_write(NRF_GET_PIN(pins[i]), 0);
|
||||
nrf_pin_configure(pins[i], NRF_GPIO_PIN_DIR_OUTPUT,
|
||||
NRF_GPIO_PIN_INPUT_CONNECT);
|
||||
break;
|
||||
case NRF_FUN_SPIM_MOSI:
|
||||
NRF_PSEL_SPIM(reg, MOSI) = NRF_GET_PIN(pins[i]);
|
||||
nrf_gpio_pin_write(NRF_GET_PIN(pins[i]), 0);
|
||||
nrf_pin_configure(pins[i], NRF_GPIO_PIN_DIR_OUTPUT,
|
||||
NRF_GPIO_PIN_INPUT_DISCONNECT);
|
||||
break;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include <drivers/spi.h>
|
||||
#include <pm/device.h>
|
||||
#include <drivers/pinctrl.h>
|
||||
#include <soc.h>
|
||||
#include <nrfx_spi.h>
|
||||
|
||||
#include <logging/log.h>
|
||||
|
@ -24,6 +26,9 @@ struct spi_nrfx_data {
|
|||
struct spi_nrfx_config {
|
||||
nrfx_spi_t spi;
|
||||
nrfx_spi_config_t def_config;
|
||||
#ifdef CONFIG_PINCTRL
|
||||
const struct pinctrl_dev_config *pcfg;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void event_handler(const nrfx_spi_evt_t *p_event, void *p_context);
|
||||
|
@ -266,7 +271,6 @@ static const struct spi_driver_api spi_nrfx_driver_api = {
|
|||
.release = spi_nrfx_release,
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_PM_DEVICE
|
||||
static int spi_nrfx_pm_action(const struct device *dev,
|
||||
enum pm_device_action action)
|
||||
|
@ -277,8 +281,15 @@ static int spi_nrfx_pm_action(const struct device *dev,
|
|||
|
||||
switch (action) {
|
||||
case PM_DEVICE_ACTION_RESUME:
|
||||
/* No action needed at this point, nrfx_spi_init() will be
|
||||
* called at configuration before the next transfer.
|
||||
#ifdef CONFIG_PINCTRL
|
||||
ret = pinctrl_apply_state(dev_config->pcfg,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
/* nrfx_spi_init() will be called at configuration before
|
||||
* the next transfer.
|
||||
*/
|
||||
break;
|
||||
|
||||
|
@ -287,6 +298,14 @@ static int spi_nrfx_pm_action(const struct device *dev,
|
|||
nrfx_spi_uninit(&dev_config->spi);
|
||||
dev_data->initialized = false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PINCTRL
|
||||
ret = pinctrl_apply_state(dev_config->pcfg,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -317,9 +336,22 @@ static int spi_nrfx_pm_action(const struct device *dev,
|
|||
? NRF_GPIO_PIN_PULLDOWN \
|
||||
: NRF_GPIO_PIN_NOPULL)
|
||||
|
||||
#define SPI_NRFX_SPI_PIN_CFG(idx) \
|
||||
COND_CODE_1(CONFIG_PINCTRL, \
|
||||
(.skip_gpio_cfg = true, \
|
||||
.skip_psel_cfg = true,), \
|
||||
(.sck_pin = SPI_PROP(idx, sck_pin), \
|
||||
.mosi_pin = DT_PROP_OR(SPI(idx), mosi_pin, \
|
||||
NRFX_SPI_PIN_NOT_USED), \
|
||||
.miso_pin = DT_PROP_OR(SPI(idx), miso_pin, \
|
||||
NRFX_SPI_PIN_NOT_USED), \
|
||||
.miso_pull = SPI_NRFX_MISO_PULL(idx),))
|
||||
|
||||
#define SPI_NRFX_SPI_DEVICE(idx) \
|
||||
BUILD_ASSERT( \
|
||||
!SPI_PROP(idx, miso_pull_up) || !SPI_PROP(idx, miso_pull_down),\
|
||||
NRF_DT_ENSURE_PINS_ASSIGNED(SPI(idx), sck_pin); \
|
||||
BUILD_ASSERT(IS_ENABLED(CONFIG_PINCTRL) || \
|
||||
!(SPI_PROP(idx, miso_pull_up) && \
|
||||
SPI_PROP(idx, miso_pull_down)), \
|
||||
"SPI"#idx \
|
||||
": cannot enable both pull-up and pull-down on MISO line"); \
|
||||
static int spi_##idx##_init(const struct device *dev) \
|
||||
|
@ -328,6 +360,14 @@ static int spi_nrfx_pm_action(const struct device *dev,
|
|||
int err; \
|
||||
IRQ_CONNECT(DT_IRQN(SPI(idx)), DT_IRQ(SPI(idx), priority), \
|
||||
nrfx_isr, nrfx_spi_##idx##_irq_handler, 0); \
|
||||
IF_ENABLED(CONFIG_PINCTRL, ( \
|
||||
const struct spi_nrfx_config *dev_config = dev->config;\
|
||||
err = pinctrl_apply_state(dev_config->pcfg, \
|
||||
PINCTRL_STATE_DEFAULT); \
|
||||
if (err < 0) { \
|
||||
return err; \
|
||||
} \
|
||||
)) \
|
||||
err = spi_context_cs_configure_all(&dev_data->ctx); \
|
||||
if (err < 0) { \
|
||||
return err; \
|
||||
|
@ -342,16 +382,16 @@ static int spi_nrfx_pm_action(const struct device *dev,
|
|||
.dev = DEVICE_DT_GET(SPI(idx)), \
|
||||
.busy = false, \
|
||||
}; \
|
||||
IF_ENABLED(CONFIG_PINCTRL, (PINCTRL_DT_DEFINE(SPI(idx)))); \
|
||||
static const struct spi_nrfx_config spi_##idx##z_config = { \
|
||||
.spi = NRFX_SPI_INSTANCE(idx), \
|
||||
.def_config = { \
|
||||
.sck_pin = SPI_PROP(idx, sck_pin), \
|
||||
.mosi_pin = SPI_PROP(idx, mosi_pin), \
|
||||
.miso_pin = SPI_PROP(idx, miso_pin), \
|
||||
.ss_pin = NRFX_SPI_PIN_NOT_USED, \
|
||||
.orc = CONFIG_SPI_##idx##_NRF_ORC, \
|
||||
.miso_pull = SPI_NRFX_MISO_PULL(idx), \
|
||||
} \
|
||||
SPI_NRFX_SPI_PIN_CFG(idx) \
|
||||
.ss_pin = NRFX_SPI_PIN_NOT_USED, \
|
||||
.orc = CONFIG_SPI_##idx##_NRF_ORC, \
|
||||
}, \
|
||||
IF_ENABLED(CONFIG_PINCTRL, \
|
||||
(.pcfg = PINCTRL_DT_DEV_CONFIG_GET(SPI(idx)),)) \
|
||||
}; \
|
||||
PM_DEVICE_DT_DEFINE(SPI(idx), spi_nrfx_pm_action); \
|
||||
DEVICE_DT_DEFINE(SPI(idx), \
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include <drivers/spi.h>
|
||||
#include <pm/device.h>
|
||||
#include <drivers/pinctrl.h>
|
||||
#include <soc.h>
|
||||
#ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58
|
||||
#include <nrfx_gpiote.h>
|
||||
#include <nrfx_ppi.h>
|
||||
|
@ -40,8 +42,11 @@ struct spi_nrfx_config {
|
|||
size_t max_chunk_len;
|
||||
uint32_t max_freq;
|
||||
nrfx_spim_config_t def_config;
|
||||
#ifdef CONFIG_PINCTRL
|
||||
const struct pinctrl_dev_config *pcfg;
|
||||
#endif
|
||||
#ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58
|
||||
bool anomaly_58_workaround;
|
||||
bool anomaly_58_workaround;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -435,8 +440,15 @@ static int spim_nrfx_pm_action(const struct device *dev,
|
|||
|
||||
switch (action) {
|
||||
case PM_DEVICE_ACTION_RESUME:
|
||||
/* No action needed at this point, nrfx_spim_init() will be
|
||||
* called at configuration before the next transfer.
|
||||
#ifdef CONFIG_PINCTRL
|
||||
ret = pinctrl_apply_state(dev_config->pcfg,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
/* nrfx_spim_init() will be called at configuration before
|
||||
* the next transfer.
|
||||
*/
|
||||
break;
|
||||
|
||||
|
@ -445,6 +457,14 @@ static int spim_nrfx_pm_action(const struct device *dev,
|
|||
nrfx_spim_uninit(&dev_config->spim);
|
||||
dev_data->initialized = false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PINCTRL
|
||||
ret = pinctrl_apply_state(dev_config->pcfg,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -468,11 +488,11 @@ static int spim_nrfx_pm_action(const struct device *dev,
|
|||
#define SPIM_NRFX_MISO_PULL_UP(idx) DT_PROP(SPIM(idx), miso_pull_up)
|
||||
|
||||
#define SPIM_NRFX_MISO_PULL(idx) \
|
||||
(SPIM_NRFX_MISO_PULL_UP(idx) \
|
||||
? SPIM_NRFX_MISO_PULL_DOWN(idx) \
|
||||
(SPIM_PROP(idx, miso_pull_up) \
|
||||
? SPIM_PROP(idx, miso_pull_down) \
|
||||
? -1 /* invalid configuration */\
|
||||
: NRF_GPIO_PIN_PULLUP \
|
||||
: SPIM_NRFX_MISO_PULL_DOWN(idx) \
|
||||
: SPIM_PROP(idx, miso_pull_down) \
|
||||
? NRF_GPIO_PIN_PULLDOWN \
|
||||
: NRF_GPIO_PIN_NOPULL)
|
||||
|
||||
|
@ -483,9 +503,22 @@ static int spim_nrfx_pm_action(const struct device *dev,
|
|||
(.rx_delay = CONFIG_SPI_##idx##_NRF_RX_DELAY,)) \
|
||||
))
|
||||
|
||||
#define SPI_NRFX_SPIM_PIN_CFG(idx) \
|
||||
COND_CODE_1(CONFIG_PINCTRL, \
|
||||
(.skip_gpio_cfg = true, \
|
||||
.skip_psel_cfg = true,), \
|
||||
(.sck_pin = SPIM_PROP(idx, sck_pin), \
|
||||
.mosi_pin = DT_PROP_OR(SPIM(idx), mosi_pin, \
|
||||
NRFX_SPIM_PIN_NOT_USED), \
|
||||
.miso_pin = DT_PROP_OR(SPIM(idx), miso_pin, \
|
||||
NRFX_SPIM_PIN_NOT_USED), \
|
||||
.miso_pull = SPIM_NRFX_MISO_PULL(idx),))
|
||||
|
||||
#define SPI_NRFX_SPIM_DEVICE(idx) \
|
||||
BUILD_ASSERT( \
|
||||
!SPIM_NRFX_MISO_PULL_UP(idx) || !SPIM_NRFX_MISO_PULL_DOWN(idx),\
|
||||
NRF_DT_ENSURE_PINS_ASSIGNED(SPIM(idx), sck_pin); \
|
||||
BUILD_ASSERT(IS_ENABLED(CONFIG_PINCTRL) || \
|
||||
!(SPIM_PROP(idx, miso_pull_up) && \
|
||||
SPIM_PROP(idx, miso_pull_down)), \
|
||||
"SPIM"#idx \
|
||||
": cannot enable both pull-up and pull-down on MISO line"); \
|
||||
static int spi_##idx##_init(const struct device *dev) \
|
||||
|
@ -495,6 +528,14 @@ static int spim_nrfx_pm_action(const struct device *dev,
|
|||
IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_SPIM##idx), \
|
||||
DT_IRQ(SPIM(idx), priority), \
|
||||
nrfx_isr, nrfx_spim_##idx##_irq_handler, 0); \
|
||||
IF_ENABLED(CONFIG_PINCTRL, ( \
|
||||
const struct spi_nrfx_config *dev_config = dev->config;\
|
||||
err = pinctrl_apply_state(dev_config->pcfg, \
|
||||
PINCTRL_STATE_DEFAULT); \
|
||||
if (err < 0) { \
|
||||
return err; \
|
||||
} \
|
||||
)) \
|
||||
err = spi_context_cs_configure_all(&dev_data->ctx); \
|
||||
if (err < 0) { \
|
||||
return err; \
|
||||
|
@ -511,23 +552,23 @@ static int spim_nrfx_pm_action(const struct device *dev,
|
|||
.dev = DEVICE_DT_GET(SPIM(idx)), \
|
||||
.busy = false, \
|
||||
}; \
|
||||
IF_ENABLED(CONFIG_PINCTRL, (PINCTRL_DT_DEFINE(SPIM(idx)))); \
|
||||
static const struct spi_nrfx_config spi_##idx##z_config = { \
|
||||
.spim = NRFX_SPIM_INSTANCE(idx), \
|
||||
.max_chunk_len = (1 << SPIM##idx##_EASYDMA_MAXCNT_SIZE) - 1, \
|
||||
.max_freq = SPIM##idx##_MAX_DATARATE * 1000000, \
|
||||
.def_config = { \
|
||||
.sck_pin = SPIM_PROP(idx, sck_pin), \
|
||||
.mosi_pin = SPIM_PROP(idx, mosi_pin), \
|
||||
.miso_pin = SPIM_PROP(idx, miso_pin), \
|
||||
.ss_pin = NRFX_SPIM_PIN_NOT_USED, \
|
||||
.orc = CONFIG_SPI_##idx##_NRF_ORC, \
|
||||
.miso_pull = SPIM_NRFX_MISO_PULL(idx), \
|
||||
SPI_NRFX_SPIM_PIN_CFG(idx) \
|
||||
.ss_pin = NRFX_SPIM_PIN_NOT_USED, \
|
||||
.orc = CONFIG_SPI_##idx##_NRF_ORC, \
|
||||
SPI_NRFX_SPIM_EXTENDED_CONFIG(idx) \
|
||||
}, \
|
||||
COND_CODE_1(CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58, \
|
||||
(.anomaly_58_workaround = \
|
||||
SPIM_PROP(idx, anomaly_58_workaround),), \
|
||||
()) \
|
||||
IF_ENABLED(CONFIG_PINCTRL, \
|
||||
(.pcfg = PINCTRL_DT_DEV_CONFIG_GET(SPIM(idx)),)) \
|
||||
}; \
|
||||
PM_DEVICE_DT_DEFINE(SPIM(idx), spim_nrfx_pm_action); \
|
||||
DEVICE_DT_DEFINE(SPIM(idx), \
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
*/
|
||||
|
||||
#include <drivers/spi.h>
|
||||
#include <drivers/pinctrl.h>
|
||||
#include <soc.h>
|
||||
#include <nrfx_spis.h>
|
||||
|
||||
#include <logging/log.h>
|
||||
|
@ -19,6 +21,9 @@ struct spi_nrfx_data {
|
|||
struct spi_nrfx_config {
|
||||
nrfx_spis_t spis;
|
||||
size_t max_buf_len;
|
||||
#ifdef CONFIG_PINCTRL
|
||||
const struct pinctrl_dev_config *pcfg;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline nrf_spis_mode_t get_nrf_spis_mode(uint16_t operation)
|
||||
|
@ -208,7 +213,6 @@ static const struct spi_driver_api spi_nrfx_driver_api = {
|
|||
.release = spi_nrfx_release,
|
||||
};
|
||||
|
||||
|
||||
static void event_handler(const nrfx_spis_evt_t *p_event, void *p_context)
|
||||
{
|
||||
struct spi_nrfx_data *dev_data = p_context;
|
||||
|
@ -251,32 +255,52 @@ static int init_spis(const struct device *dev,
|
|||
#define SPIS(idx) DT_NODELABEL(spi##idx)
|
||||
#define SPIS_PROP(idx, prop) DT_PROP(SPIS(idx), prop)
|
||||
|
||||
#define SPI_NRFX_SPIS_PIN_CFG(idx) \
|
||||
COND_CODE_1(CONFIG_PINCTRL, \
|
||||
(.skip_gpio_cfg = true, \
|
||||
.skip_psel_cfg = true,), \
|
||||
(.sck_pin = SPIS_PROP(idx, sck_pin), \
|
||||
.mosi_pin = DT_PROP_OR(SPIS(idx), mosi_pin, \
|
||||
NRFX_SPIS_PIN_NOT_USED), \
|
||||
.miso_pin = DT_PROP_OR(SPIS(idx), miso_pin, \
|
||||
NRFX_SPIS_PIN_NOT_USED), \
|
||||
.csn_pin = SPIS_PROP(idx, csn_pin), \
|
||||
.csn_pullup = NRF_GPIO_PIN_NOPULL, \
|
||||
.miso_drive = NRF_GPIO_PIN_S0S1,))
|
||||
|
||||
#define SPI_NRFX_SPIS_DEVICE(idx) \
|
||||
NRF_DT_ENSURE_PINS_ASSIGNED(SPIS(idx), sck_pin); \
|
||||
static int spi_##idx##_init(const struct device *dev) \
|
||||
{ \
|
||||
IRQ_CONNECT(DT_IRQN(SPIS(idx)), DT_IRQ(SPIS(idx), priority), \
|
||||
nrfx_isr, nrfx_spis_##idx##_irq_handler, 0); \
|
||||
const nrfx_spis_config_t config = { \
|
||||
.sck_pin = SPIS_PROP(idx, sck_pin), \
|
||||
.mosi_pin = SPIS_PROP(idx, mosi_pin), \
|
||||
.miso_pin = SPIS_PROP(idx, miso_pin), \
|
||||
.csn_pin = SPIS_PROP(idx, csn_pin), \
|
||||
.mode = NRF_SPIS_MODE_0, \
|
||||
.bit_order = NRF_SPIS_BIT_ORDER_MSB_FIRST, \
|
||||
.csn_pullup = NRF_GPIO_PIN_NOPULL, \
|
||||
.miso_drive = NRF_GPIO_PIN_S0S1, \
|
||||
.orc = CONFIG_SPI_##idx##_NRF_ORC, \
|
||||
.def = SPIS_PROP(idx, def_char), \
|
||||
SPI_NRFX_SPIS_PIN_CFG(idx) \
|
||||
.mode = NRF_SPIS_MODE_0, \
|
||||
.bit_order = NRF_SPIS_BIT_ORDER_MSB_FIRST, \
|
||||
.orc = CONFIG_SPI_##idx##_NRF_ORC, \
|
||||
.def = SPIS_PROP(idx, def_char), \
|
||||
}; \
|
||||
IF_ENABLED(CONFIG_PINCTRL, ( \
|
||||
const struct spi_nrfx_config *dev_config = dev->config;\
|
||||
int err = pinctrl_apply_state(dev_config->pcfg, \
|
||||
PINCTRL_STATE_DEFAULT); \
|
||||
if (err < 0) { \
|
||||
return err; \
|
||||
} \
|
||||
)) \
|
||||
return init_spis(dev, &config); \
|
||||
} \
|
||||
static struct spi_nrfx_data spi_##idx##_data = { \
|
||||
SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx), \
|
||||
SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx), \
|
||||
}; \
|
||||
IF_ENABLED(CONFIG_PINCTRL, (PINCTRL_DT_DEFINE(SPIS(idx)))); \
|
||||
static const struct spi_nrfx_config spi_##idx##z_config = { \
|
||||
.spis = NRFX_SPIS_INSTANCE(idx), \
|
||||
.max_buf_len = BIT_MASK(SPIS##idx##_EASYDMA_MAXCNT_SIZE), \
|
||||
IF_ENABLED(CONFIG_PINCTRL, \
|
||||
(.pcfg = PINCTRL_DT_DEV_CONFIG_GET(SPIS(idx)),)) \
|
||||
}; \
|
||||
DEVICE_DT_DEFINE(SPIS(idx), \
|
||||
spi_##idx##_init, \
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
# Common fields for Nordic nRF family SPI peripherals
|
||||
|
||||
include: spi-controller.yaml
|
||||
include: [spi-controller.yaml, pinctrl-device.yaml]
|
||||
|
||||
properties:
|
||||
reg:
|
||||
|
@ -14,8 +14,11 @@ properties:
|
|||
|
||||
sck-pin:
|
||||
type: int
|
||||
required: true
|
||||
required: false
|
||||
description: |
|
||||
IMPORTANT: This option will only be used if the new pin control driver
|
||||
is not enabled. It will be deprecated in the future.
|
||||
|
||||
The SCK pin to use.
|
||||
|
||||
For pins P0.0 through P0.31, use the pin number. For example,
|
||||
|
@ -30,14 +33,20 @@ properties:
|
|||
|
||||
mosi-pin:
|
||||
type: int
|
||||
required: true
|
||||
required: false
|
||||
description: |
|
||||
IMPORTANT: This option will only be used if the new pin control driver
|
||||
is not enabled. It will be deprecated in the future.
|
||||
|
||||
The MOSI pin to use. The pin numbering scheme is the same as
|
||||
the sck-pin property's.
|
||||
|
||||
miso-pin:
|
||||
type: int
|
||||
required: true
|
||||
required: false
|
||||
description: |
|
||||
IMPORTANT: This option will only be used if the new pin control driver
|
||||
is not enabled. It will be deprecated in the future.
|
||||
|
||||
The MISO pin to use. The pin numbering scheme is the same as
|
||||
the sck-pin property's.
|
||||
|
|
|
@ -10,10 +10,13 @@ include: nordic,nrf-spi-common.yaml
|
|||
properties:
|
||||
csn-pin:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
The CSN pin to use. The pin numbering scheme is the same as
|
||||
the sck-pin property's.
|
||||
required: false
|
||||
description: |
|
||||
IMPORTANT: This option will only be used if the new pin control driver
|
||||
is not enabled. It will be deprecated in the future.
|
||||
|
||||
The CSN pin to use. The pin numbering scheme is the same as
|
||||
the sck-pin property's.
|
||||
|
||||
def-char:
|
||||
type: int
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue