drivers: i2s_nrfx: Add support for pinctrl

Add support for the new pinctrl API to the nRF I2S driver. Update code
of the driver and the related devicetree binding.

Signed-off-by: Andrzej Głąbek <andrzej.glabek@nordicsemi.no>
This commit is contained in:
Andrzej Głąbek 2022-03-01 17:02:16 +01:00 committed by Carles Cufí
commit 3966a33c5c
2 changed files with 64 additions and 14 deletions

View file

@ -7,6 +7,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <drivers/i2s.h> #include <drivers/i2s.h>
#include <drivers/clock_control/nrf_clock_control.h> #include <drivers/clock_control/nrf_clock_control.h>
#include <drivers/pinctrl.h>
#include <soc.h>
#include <nrfx_i2s.h> #include <nrfx_i2s.h>
#include <logging/log.h> #include <logging/log.h>
@ -38,6 +40,9 @@ struct i2s_nrfx_drv_data {
struct i2s_nrfx_drv_cfg { struct i2s_nrfx_drv_cfg {
nrfx_i2s_data_handler_t data_handler; nrfx_i2s_data_handler_t data_handler;
nrfx_i2s_config_t nrfx_def_cfg; nrfx_i2s_config_t nrfx_def_cfg;
#ifdef CONFIG_PINCTRL
const struct pinctrl_dev_config *pcfg;
#endif
enum clock_source { enum clock_source {
PCLK32M, PCLK32M,
PCLK32M_HFXO, PCLK32M_HFXO,
@ -873,14 +878,12 @@ static const struct i2s_driver_api i2s_nrf_drv_api = {
}; };
#define I2S(idx) DT_NODELABEL(i2s##idx) #define I2S(idx) DT_NODELABEL(i2s##idx)
#define I2S_PIN(idx, name) DT_PROP_OR(I2S(idx), name##_pin, \
#define I2S_PIN(idx, name) \ NRFX_I2S_PIN_NOT_USED)
COND_CODE_1(DT_NODE_HAS_PROP(I2S(idx), name##_pin), \
(DT_PROP(I2S(idx), name##_pin)), \
(NRFX_I2S_PIN_NOT_USED))
#define I2S_CLK_SRC(idx) DT_STRING_TOKEN(I2S(idx), clock_source) #define I2S_CLK_SRC(idx) DT_STRING_TOKEN(I2S(idx), clock_source)
#define I2S_NRFX_DEVICE(idx) \ #define I2S_NRFX_DEVICE(idx) \
NRF_DT_ENSURE_PINS_ASSIGNED(I2S(idx), sck_pin); \
static void *tx_msgs##idx[CONFIG_I2S_NRFX_TX_BLOCK_COUNT]; \ static void *tx_msgs##idx[CONFIG_I2S_NRFX_TX_BLOCK_COUNT]; \
static void *rx_msgs##idx[CONFIG_I2S_NRFX_RX_BLOCK_COUNT]; \ static void *rx_msgs##idx[CONFIG_I2S_NRFX_RX_BLOCK_COUNT]; \
static struct i2s_nrfx_drv_data i2s_nrfx_data##idx = { \ static struct i2s_nrfx_drv_data i2s_nrfx_data##idx = { \
@ -890,6 +893,14 @@ static const struct i2s_driver_api i2s_nrf_drv_api = {
{ \ { \
IRQ_CONNECT(DT_IRQN(I2S(idx)), DT_IRQ(I2S(idx), priority), \ IRQ_CONNECT(DT_IRQN(I2S(idx)), DT_IRQ(I2S(idx), priority), \
nrfx_isr, nrfx_i2s_irq_handler, 0); \ nrfx_isr, nrfx_i2s_irq_handler, 0); \
IF_ENABLED(CONFIG_PINCTRL, ( \
const struct i2s_nrfx_drv_cfg *drv_cfg = dev->config;\
int err = pinctrl_apply_state(drv_cfg->pcfg, \
PINCTRL_STATE_DEFAULT);\
if (err < 0) { \
return err; \
} \
)) \
k_msgq_init(&i2s_nrfx_data##idx.tx_queue, \ k_msgq_init(&i2s_nrfx_data##idx.tx_queue, \
(char *)tx_msgs##idx, sizeof(void *), \ (char *)tx_msgs##idx, sizeof(void *), \
ARRAY_SIZE(tx_msgs##idx)); \ ARRAY_SIZE(tx_msgs##idx)); \
@ -904,6 +915,7 @@ static const struct i2s_driver_api i2s_nrf_drv_api = {
{ \ { \
data_handler(DEVICE_DT_GET(I2S(idx)), p_released, status); \ data_handler(DEVICE_DT_GET(I2S(idx)), p_released, status); \
} \ } \
IF_ENABLED(CONFIG_PINCTRL, (PINCTRL_DT_DEFINE(I2S(idx)))); \
static const struct i2s_nrfx_drv_cfg i2s_nrfx_cfg##idx = { \ static const struct i2s_nrfx_drv_cfg i2s_nrfx_cfg##idx = { \
.data_handler = data_handler##idx, \ .data_handler = data_handler##idx, \
.nrfx_def_cfg = NRFX_I2S_DEFAULT_CONFIG(I2S_PIN(idx, sck), \ .nrfx_def_cfg = NRFX_I2S_DEFAULT_CONFIG(I2S_PIN(idx, sck), \
@ -911,6 +923,10 @@ static const struct i2s_driver_api i2s_nrf_drv_api = {
I2S_PIN(idx, mck), \ I2S_PIN(idx, mck), \
I2S_PIN(idx, sdout), \ I2S_PIN(idx, sdout), \
I2S_PIN(idx, sdin)), \ I2S_PIN(idx, sdin)), \
IF_ENABLED(CONFIG_PINCTRL, \
(.nrfx_def_cfg.skip_gpio_cfg = true, \
.nrfx_def_cfg.skip_psel_cfg = true, \
.pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2S(idx)),)) \
.clk_src = I2S_CLK_SRC(idx), \ .clk_src = I2S_CLK_SRC(idx), \
}; \ }; \
BUILD_ASSERT(I2S_CLK_SRC(idx) != ACLK || NRF_I2S_HAS_CLKCONFIG, \ BUILD_ASSERT(I2S_CLK_SRC(idx) != ACLK || NRF_I2S_HAS_CLKCONFIG, \

View file

@ -5,7 +5,7 @@ description: Nordic I2S (Inter-IC sound interface)
compatible: "nordic,nrf-i2s" compatible: "nordic,nrf-i2s"
include: i2s-controller.yaml include: [i2s-controller.yaml, pinctrl-device.yaml]
properties: properties:
reg: reg:
@ -16,28 +16,62 @@ properties:
sck-pin: sck-pin:
type: int type: int
required: true required: false
description: SCK pin 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,
to use P0.16 for SCK, set:
sck-pin = <16>;
For pins P1.0 through P1.31, add 32 to the pin number. For
example, to use P1.2 for SCK, set:
sck-pin = <34>; /* 32 + 2 */
lrck-pin: lrck-pin:
type: int type: int
required: true required: false
description: LRCK pin 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 LRCK pin to use. The pin numbering scheme is the same as
the sck-pin property's.
sdout-pin: sdout-pin:
type: int type: int
required: false required: false
description: SDOUT pin 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 SDOUT pin to use. The pin numbering scheme is the same as
the sck-pin property's.
sdin-pin: sdin-pin:
type: int type: int
required: false required: false
description: SDIN pin 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 SDIN pin to use. The pin numbering scheme is the same as
the sck-pin property's.
mck-pin: mck-pin:
type: int type: int
required: false required: false
description: MCK pin 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 MCK pin to use. The pin numbering scheme is the same as
the sck-pin property's.
clock-source: clock-source:
type: string type: string