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
2 changed files with 20 additions and 21 deletions
|
@ -147,32 +147,27 @@ static inline void spi_context_complete(struct spi_context *ctx, int status)
|
||||||
#endif /* CONFIG_SPI_ASYNC */
|
#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) {
|
if (ctx->config->operation & SPI_CS_ACTIVE_HIGH) {
|
||||||
return 1;
|
return GPIO_ACTIVE_HIGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return GPIO_ACTIVE_LOW;
|
||||||
}
|
|
||||||
|
|
||||||
static inline int spi_context_cs_inactive_value(struct spi_context *ctx)
|
|
||||||
{
|
|
||||||
if (ctx->config->operation & SPI_CS_ACTIVE_HIGH) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void spi_context_cs_configure(struct spi_context *ctx)
|
static inline void spi_context_cs_configure(struct spi_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx->config->cs && ctx->config->cs->gpio_dev) {
|
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,
|
gpio_pin_configure(ctx->config->cs->gpio_dev,
|
||||||
ctx->config->cs->gpio_pin, GPIO_OUTPUT);
|
ctx->config->cs->gpio_pin,
|
||||||
gpio_pin_set(ctx->config->cs->gpio_dev,
|
ctx->config->cs->gpio_dt_flags |
|
||||||
ctx->config->cs->gpio_pin,
|
GPIO_OUTPUT_INACTIVE);
|
||||||
spi_context_cs_inactive_value(ctx));
|
|
||||||
} else {
|
} else {
|
||||||
LOG_INF("CS control inhibited (no GPIO device)");
|
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 (ctx->config && ctx->config->cs && ctx->config->cs->gpio_dev) {
|
||||||
if (on) {
|
if (on) {
|
||||||
gpio_pin_set(ctx->config->cs->gpio_dev,
|
gpio_pin_set(ctx->config->cs->gpio_dev,
|
||||||
ctx->config->cs->gpio_pin,
|
ctx->config->cs->gpio_pin, 1);
|
||||||
spi_context_cs_active_value(ctx));
|
|
||||||
k_busy_wait(ctx->config->cs->delay);
|
k_busy_wait(ctx->config->cs->delay);
|
||||||
} else {
|
} else {
|
||||||
if (!force_off &&
|
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);
|
k_busy_wait(ctx->config->cs->delay);
|
||||||
gpio_pin_set(ctx->config->cs->gpio_dev,
|
gpio_pin_set(ctx->config->cs->gpio_dev,
|
||||||
ctx->config->cs->gpio_pin,
|
ctx->config->cs->gpio_pin, 0);
|
||||||
spi_context_cs_inactive_value(ctx));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <zephyr/types.h>
|
#include <zephyr/types.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <device.h>
|
#include <device.h>
|
||||||
|
#include <drivers/gpio.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -129,11 +130,16 @@ extern "C" {
|
||||||
* to act as a CS line
|
* to act as a CS line
|
||||||
* @param delay is a delay in microseconds to wait before starting the
|
* @param delay is a delay in microseconds to wait before starting the
|
||||||
* transmission and before releasing the CS line
|
* 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 spi_cs_control {
|
||||||
struct device *gpio_dev;
|
struct device *gpio_dev;
|
||||||
uint32_t gpio_pin;
|
|
||||||
uint32_t delay;
|
uint32_t delay;
|
||||||
|
gpio_pin_t gpio_pin;
|
||||||
|
gpio_dt_flags_t gpio_dt_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue