Skip to content

Commit d33b89b

Browse files
andysancarlescufi
authored andcommitted
drivers: spi: spi-bitbang: Add support for half duplex
Implement support for half duplex communication in the bit bang SPI driver. The SPI driver will use the MOSI pin is for both TX and RX operations when using half duplex mode. In half-duplex mode, the driver configures the MOSI pin as an input pin for input only transactions. Transactions that are bidirectional are forbidden. After an SPI transaction, the MOSI pin is left as an input if it was an RX transaction or an output after a TX transaction. Like before, the MOSI pin is initialized as an (inactive) output pin when the bus is initialized. Signed-off-by: Andreas Sandberg <[email protected]>
1 parent 8bfc215 commit d33b89b

File tree

1 file changed

+48
-23
lines changed

1 file changed

+48
-23
lines changed

drivers/spi/spi_bitbang.c

+48-23
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,6 @@ struct spi_bitbang_config {
2727
struct gpio_dt_spec miso_gpio;
2828
};
2929

30-
static inline bool spi_bitbang_has_miso(const struct device *dev)
31-
{
32-
const struct spi_bitbang_config *info = dev->config;
33-
34-
return info->miso_gpio.port != NULL;
35-
}
36-
37-
static inline bool spi_bitbang_has_mosi(const struct device *dev)
38-
{
39-
const struct spi_bitbang_config *info = dev->config;
40-
41-
return info->mosi_gpio.port != NULL;
42-
}
43-
4430
static int spi_bitbang_configure(const struct spi_bitbang_config *info,
4531
struct spi_bitbang_data *data,
4632
const struct spi_config *config)
@@ -88,8 +74,50 @@ static int spi_bitbang_transceive(const struct device *dev,
8874
const struct spi_bitbang_config *info = dev->config;
8975
struct spi_bitbang_data *data = dev->data;
9076
struct spi_context *ctx = &data->ctx;
77+
int rc;
78+
const struct gpio_dt_spec *miso = NULL;
79+
const struct gpio_dt_spec *mosi = NULL;
80+
gpio_flags_t mosi_flags = GPIO_OUTPUT_INACTIVE;
9181

92-
spi_bitbang_configure(info, data, spi_cfg);
82+
rc = spi_bitbang_configure(info, data, spi_cfg);
83+
if (rc < 0) {
84+
return rc;
85+
}
86+
87+
if (spi_cfg->operation & SPI_HALF_DUPLEX) {
88+
if (!info->mosi_gpio.port) {
89+
LOG_ERR("No MOSI pin specified in half duplex mode");
90+
return -EINVAL;
91+
}
92+
93+
if (tx_bufs && rx_bufs) {
94+
LOG_ERR("Both RX and TX specified in half duplex mode");
95+
return -EINVAL;
96+
} else if (tx_bufs && !rx_bufs) {
97+
/* TX mode */
98+
mosi = &info->mosi_gpio;
99+
} else if (!tx_bufs && rx_bufs) {
100+
/* RX mode */
101+
mosi_flags = GPIO_INPUT;
102+
miso = &info->mosi_gpio;
103+
}
104+
} else {
105+
if (info->mosi_gpio.port) {
106+
mosi = &info->mosi_gpio;
107+
}
108+
109+
if (info->miso_gpio.port) {
110+
miso = &info->miso_gpio;
111+
}
112+
}
113+
114+
if (info->mosi_gpio.port) {
115+
rc = gpio_pin_configure_dt(&info->mosi_gpio, mosi_flags);
116+
if (rc < 0) {
117+
LOG_ERR("Couldn't configure MOSI pin: %d", rc);
118+
return rc;
119+
}
120+
}
93121

94122
spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, data->dfs);
95123

@@ -114,9 +142,6 @@ static int spi_bitbang_transceive(const struct device *dev,
114142

115143
const uint32_t wait_us = data->wait_us;
116144

117-
const bool has_miso = spi_bitbang_has_miso(dev);
118-
const bool has_mosi = spi_bitbang_has_mosi(dev);
119-
120145
while (spi_context_tx_buf_on(ctx) || spi_context_rx_buf_on(ctx)) {
121146
uint16_t w = 0;
122147

@@ -136,7 +161,7 @@ static int spi_bitbang_transceive(const struct device *dev,
136161
int b = 0;
137162
bool do_read = false;
138163

139-
if (has_miso && spi_context_rx_buf_on(ctx)) {
164+
if (miso && spi_context_rx_buf_on(ctx)) {
140165
do_read = true;
141166
}
142167

@@ -146,8 +171,8 @@ static int spi_bitbang_transceive(const struct device *dev,
146171
b = 0;
147172

148173
/* setup data out first thing */
149-
if (has_mosi) {
150-
gpio_pin_set_dt(&info->mosi_gpio, d);
174+
if (mosi) {
175+
gpio_pin_set_dt(mosi, d);
151176
}
152177

153178
k_busy_wait(wait_us);
@@ -156,7 +181,7 @@ static int spi_bitbang_transceive(const struct device *dev,
156181
gpio_pin_set_dt(&info->clk_gpio, !clock_state);
157182

158183
if (!loop && do_read && !cpha) {
159-
b = gpio_pin_get_dt(&info->miso_gpio);
184+
b = gpio_pin_get_dt(miso);
160185
}
161186

162187
k_busy_wait(wait_us);
@@ -165,7 +190,7 @@ static int spi_bitbang_transceive(const struct device *dev,
165190
gpio_pin_set_dt(&info->clk_gpio, clock_state);
166191

167192
if (!loop && do_read && cpha) {
168-
b = gpio_pin_get_dt(&info->miso_gpio);
193+
b = gpio_pin_get_dt(miso);
169194
}
170195

171196
if (loop) {

0 commit comments

Comments
 (0)