drivers: spi: spi_context: improve support of multiple cs gpios
Add extra cs_gpios and num_cs_gpios members into spi_context structure that will be used to initialize all defined cs gpios during the driver initialization using SPI_CONTEXT_CS_GPIOS_INITIALIZE macro. While at it add a new spi_context_cs_configure_all function that allows the user to configure all available cs gpios in inactive mode. Signed-off-by: Bartosz Bilas <bartosz.bilas@hotmail.com>
This commit is contained in:
parent
ea25b92cd9
commit
54907c7014
1 changed files with 42 additions and 0 deletions
|
@ -27,6 +27,8 @@ enum spi_ctx_runtime_op_mode {
|
||||||
struct spi_context {
|
struct spi_context {
|
||||||
const struct spi_config *config;
|
const struct spi_config *config;
|
||||||
const struct spi_config *owner;
|
const struct spi_config *owner;
|
||||||
|
const struct gpio_dt_spec *cs_gpios;
|
||||||
|
size_t num_cs_gpios;
|
||||||
|
|
||||||
struct k_sem lock;
|
struct k_sem lock;
|
||||||
struct k_sem sync;
|
struct k_sem sync;
|
||||||
|
@ -57,6 +59,20 @@ struct spi_context {
|
||||||
#define SPI_CONTEXT_INIT_SYNC(_data, _ctx_name) \
|
#define SPI_CONTEXT_INIT_SYNC(_data, _ctx_name) \
|
||||||
._ctx_name.sync = Z_SEM_INITIALIZER(_data._ctx_name.sync, 0, 1)
|
._ctx_name.sync = Z_SEM_INITIALIZER(_data._ctx_name.sync, 0, 1)
|
||||||
|
|
||||||
|
#define SPI_CONTEXT_CS_GPIO_SPEC_ELEM(_node_id, _prop, _idx) \
|
||||||
|
GPIO_DT_SPEC_GET_BY_IDX(_node_id, _prop, _idx),
|
||||||
|
|
||||||
|
#define SPI_CONTEXT_CS_GPIOS_FOREACH_ELEM(_node_id) \
|
||||||
|
DT_FOREACH_PROP_ELEM(_node_id, cs_gpios, \
|
||||||
|
SPI_CONTEXT_CS_GPIO_SPEC_ELEM)
|
||||||
|
|
||||||
|
#define SPI_CONTEXT_CS_GPIOS_INITIALIZE(_node_id, _ctx_name) \
|
||||||
|
._ctx_name.cs_gpios = (const struct gpio_dt_spec []) { \
|
||||||
|
COND_CODE_1(DT_SPI_HAS_CS_GPIOS(_node_id), \
|
||||||
|
(SPI_CONTEXT_CS_GPIOS_FOREACH_ELEM(_node_id)), ({0})) \
|
||||||
|
}, \
|
||||||
|
._ctx_name.num_cs_gpios = DT_PROP_LEN_OR(_node_id, cs_gpios, 0),
|
||||||
|
|
||||||
static inline bool spi_context_configured(struct spi_context *ctx,
|
static inline bool spi_context_configured(struct spi_context *ctx,
|
||||||
const struct spi_config *config)
|
const struct spi_config *config)
|
||||||
{
|
{
|
||||||
|
@ -183,6 +199,32 @@ gpio_dt_flags_t spi_context_cs_active_level(struct spi_context *ctx)
|
||||||
return GPIO_ACTIVE_LOW;
|
return GPIO_ACTIVE_LOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int spi_context_cs_configure_all(struct spi_context *ctx)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
const struct gpio_dt_spec *cs_gpio;
|
||||||
|
|
||||||
|
for (cs_gpio = ctx->cs_gpios; cs_gpio < &ctx->cs_gpios[ctx->num_cs_gpios]; cs_gpio++) {
|
||||||
|
if (!device_is_ready(cs_gpio->port)) {
|
||||||
|
LOG_ERR("CS GPIO port %s pin %d is not ready",
|
||||||
|
cs_gpio->port->name, cs_gpio->pin);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate CS active levels are equivalent */
|
||||||
|
__ASSERT(spi_context_cs_active_level(ctx) ==
|
||||||
|
(cs_gpio->dt_flags & GPIO_ACTIVE_LOW),
|
||||||
|
"Devicetree and spi_context CS levels are not equal");
|
||||||
|
|
||||||
|
ret = gpio_pin_configure_dt(cs_gpio, GPIO_OUTPUT_INACTIVE);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int spi_context_cs_configure(struct spi_context *ctx)
|
static inline int spi_context_cs_configure(struct spi_context *ctx)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue