drivers: spi: CS configuration through devicetree
Add an additional option to the spi_cs_control struct that records how the pin has been configured in devicetree. For drivers that are not updated, the CS behaviour is the same as before (Push-Pull). Use the devicetree knowledge with the GPIO subsystem so that the correct physical pin levels for the CS pin are automatically selected. Fixes #26267 Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
This commit is contained in:
parent
a670c95452
commit
5963ebaf33
|
@ -147,32 +147,27 @@ static inline void spi_context_complete(struct spi_context *ctx, int status)
|
|||
#endif /* CONFIG_SPI_ASYNC */
|
||||
}
|
||||
|
||||
static inline int spi_context_cs_active_value(struct spi_context *ctx)
|
||||
static inline
|
||||
gpio_dt_flags_t spi_context_cs_active_level(struct spi_context *ctx)
|
||||
{
|
||||
if (ctx->config->operation & SPI_CS_ACTIVE_HIGH) {
|
||||
return 1;
|
||||
return GPIO_ACTIVE_HIGH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int spi_context_cs_inactive_value(struct spi_context *ctx)
|
||||
{
|
||||
if (ctx->config->operation & SPI_CS_ACTIVE_HIGH) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return GPIO_ACTIVE_LOW;
|
||||
}
|
||||
|
||||
static inline void spi_context_cs_configure(struct spi_context *ctx)
|
||||
{
|
||||
if (ctx->config->cs && ctx->config->cs->gpio_dev) {
|
||||
/* Validate CS active levels are equivalent */
|
||||
__ASSERT(spi_context_cs_active_level(ctx) ==
|
||||
(ctx->config->cs->gpio_dt_flags & GPIO_ACTIVE_LOW),
|
||||
"Devicetree and spi_context CS levels are not equal");
|
||||
gpio_pin_configure(ctx->config->cs->gpio_dev,
|
||||
ctx->config->cs->gpio_pin, GPIO_OUTPUT);
|
||||
gpio_pin_set(ctx->config->cs->gpio_dev,
|
||||
ctx->config->cs->gpio_pin,
|
||||
spi_context_cs_inactive_value(ctx));
|
||||
ctx->config->cs->gpio_pin,
|
||||
ctx->config->cs->gpio_dt_flags |
|
||||
GPIO_OUTPUT_INACTIVE);
|
||||
} else {
|
||||
LOG_INF("CS control inhibited (no GPIO device)");
|
||||
}
|
||||
|
@ -184,8 +179,7 @@ static inline void _spi_context_cs_control(struct spi_context *ctx,
|
|||
if (ctx->config && ctx->config->cs && ctx->config->cs->gpio_dev) {
|
||||
if (on) {
|
||||
gpio_pin_set(ctx->config->cs->gpio_dev,
|
||||
ctx->config->cs->gpio_pin,
|
||||
spi_context_cs_active_value(ctx));
|
||||
ctx->config->cs->gpio_pin, 1);
|
||||
k_busy_wait(ctx->config->cs->delay);
|
||||
} else {
|
||||
if (!force_off &&
|
||||
|
@ -195,8 +189,7 @@ static inline void _spi_context_cs_control(struct spi_context *ctx,
|
|||
|
||||
k_busy_wait(ctx->config->cs->delay);
|
||||
gpio_pin_set(ctx->config->cs->gpio_dev,
|
||||
ctx->config->cs->gpio_pin,
|
||||
spi_context_cs_inactive_value(ctx));
|
||||
ctx->config->cs->gpio_pin, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <zephyr/types.h>
|
||||
#include <stddef.h>
|
||||
#include <device.h>
|
||||
#include <drivers/gpio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -129,11 +130,16 @@ extern "C" {
|
|||
* to act as a CS line
|
||||
* @param delay is a delay in microseconds to wait before starting the
|
||||
* transmission and before releasing the CS line
|
||||
* @param gpio_dt_flags is the devicetree flags corresponding to how the CS
|
||||
* line should be driven. GPIO_ACTIVE_LOW/GPIO_ACTIVE_HIGH should be
|
||||
* equivalent to SPI_CS_ACTIVE_HIGH/SPI_CS_ACTIVE_LOW options in struct
|
||||
* spi_config.
|
||||
*/
|
||||
struct spi_cs_control {
|
||||
struct device *gpio_dev;
|
||||
uint32_t gpio_pin;
|
||||
uint32_t delay;
|
||||
gpio_pin_t gpio_pin;
|
||||
gpio_dt_flags_t gpio_dt_flags;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue