Skip to content

Commit dd0c359

Browse files
Tomasz BursztykaAnas Nashif
authored andcommitted
api: New SPI API
Such API improves many aspects of the former API by reducing the number of function, allowing more buffer flexibility etc... This leads in better memory usag and performance as well. However, as this will take sometime to get into use, the former API is still present and is the one enabled by default. Jira: ZEP-852 Jira: ZEP-287 Jira: ZEP-1725 Signed-off-by: Tomasz Bursztyka <[email protected]>
1 parent 6294136 commit dd0c359

File tree

3 files changed

+367
-109
lines changed

3 files changed

+367
-109
lines changed

drivers/spi/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
# SPDX-License-Identifier: Apache-2.0
77
#
88

9+
config SPI_LEGACY_API
10+
bool "Use legacy SPI API (default)"
11+
default y
12+
help
13+
Driver and user API is the legacy SPI API (spi_legacy.h).
14+
If unselected, the new API will be used.
15+
916
#
1017
# SPI Drivers
1118
#

include/spi.h

Lines changed: 157 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,19 @@
66

77
/**
88
* @file
9-
* @brief Public API for SPI drivers
9+
* @brief Public API for SPI drivers and applications
1010
*/
1111

12+
#if defined(CONFIG_SPI_LEGACY_API)
13+
14+
/*
15+
* This is the default, and will be the way until the new API below
16+
* will be enforced everywhere.
17+
*/
18+
#include <spi_legacy.h>
19+
20+
#else
21+
1222
#ifndef __SPI_H__
1323
#define __SPI_H__
1424

@@ -27,173 +37,209 @@
2737
extern "C" {
2838
#endif
2939

40+
/**x
41+
* @brief SPI operational mode
42+
*/
43+
#define SPI_OP_MODE_MASTER 0
44+
#define SPI_OP_MODE_SLAVE 1
45+
3046
/**
3147
* @brief SPI Polarity & Phase Modes
3248
*/
33-
#define SPI_MODE_CPOL 0x1
34-
#define SPI_MODE_CPHA 0x2
35-
#define SPI_MODE_LOOP 0x4
3649

37-
#define SPI_MODE_MASK (0x7)
38-
#define SPI_MODE(_in_) ((_in_) & SPI_MODE_MASK)
50+
/**
51+
* Clock Polarity: if set, clock idle state will be 1
52+
* and active state will be 0. If untouched, the inverse will be true
53+
* which is the default.
54+
*/
55+
#define SPI_MODE_CPOL BIT(1)
56+
57+
/**
58+
* Clock Phase: this dictates when is the data captured, and depends
59+
* clock's polarity. When SPI_MODE_CPOL is set and this bit as well,
60+
* capture will occure on low to high transition and high to low if
61+
* this bit is not set (default). This is fully reversed if CPOL is
62+
* not set.
63+
*/
64+
#define SPI_MODE_CPHA BIT(2)
65+
66+
/**
67+
* Whatever data is transmitted is looped-back to the receiving buffer of
68+
* the controller. This is fully controller dependent as some may not
69+
* support this, and can be used for testing purposes only.
70+
*/
71+
#define SPI_MODE_LOOP BIT(3)
72+
73+
#define SPI_MODE_MASK (0xE)
74+
#define SPI_MODE_GET(_mode_) \
75+
((_mode_) & SPI_MODE_MASK)
3976

4077
/**
4178
* @brief SPI Transfer modes (host controller dependent)
4279
*/
43-
#define SPI_TRANSFER_MSB (0 << 3)
44-
#define SPI_TRANSFER_LSB (1 << 3)
80+
#define SPI_TRANSFER_MSB (0)
81+
#define SPI_TRANSFER_LSB BIT(4)
4582

46-
#define SPI_TRANSFER_MASK (0x8)
83+
/**
84+
* @brief SPI word size
85+
*/
86+
#define SPI_WORD_SIZE_SHIFT (5)
87+
#define SPI_WORD_SIZE_MASK (0x3F << SPI_WORD_SIZE_SHIFT)
88+
#define SPI_WORD_SIZE_GET(_operation_) \
89+
(((_operation_) & SPI_WORD_SIZE_MASK) >> SPI_WORD_SIZE_SHIFT)
4790

48-
#define SPI_WORD_SIZE_MASK (0xFF << 4)
49-
#define SPI_WORD_SIZE_GET(_in_) (((_in_) & SPI_WORD_SIZE_MASK) >> 4)
50-
#define SPI_WORD(_in_) ((_in_) << 4)
91+
#define SPI_WORD_SET(_word_size_) \
92+
((_word_size_) << SPI_WORD_SIZE_SHIFT)
5193

5294
/**
53-
* @brief SPI configuration structure.
54-
*
55-
* config is a bit field with the following parts:
56-
* mode [ 0 : 2 ] - Polarity, phase and loop mode.
57-
* transfer_mode [ 3 ] - LSB or MSB first transfer mode.
58-
* word_size [ 4 : 11 ] - Size of a data frame in bits.
59-
* RESERVED [ 12 : 31 ] - Undefined or device-specific usage.
95+
* @brief SPI MISO lines
6096
*
61-
* max_sys_freq is the clock divider supported by the the host
62-
* spi controller.
97+
* Some controllers support dual or quad MISO lines connected to slaves.
98+
* Default is single, which is the case most of the time.
6399
*/
64-
struct spi_config {
65-
u32_t config;
66-
u32_t max_sys_freq;
67-
};
100+
#define SPI_LINES_SINGLE (0)
101+
#define SPI_LINES_DUAL BIT(11)
102+
#define SPI_LINES_QUAD BIT(12)
68103

69-
struct spi_buf {
104+
#define SPI_LINES_MASK (0x3 << 11)
70105

106+
/**
107+
* @brief SPI Chip Select control structure
108+
*
109+
* This can be used to control a CS line via a GPIO line, instead of
110+
* using the controller inner CS logic.
111+
*
112+
* gpio_dev is a valid pointer to an actual GPIO device
113+
* gpio_pin is a number representing the gpio PIN that will be used
114+
* to act as a CS line
115+
* delay is a delay in microseconds to wait before starting the
116+
* transmission and before releasing the CS line
117+
*/
118+
struct spi_cs_control {
119+
struct device *gpio_dev;
120+
u32_t gpio_pin;
121+
u32_t delay;
71122
};
72123

73124
/**
74-
* @typedef spi_api_configure
75-
* @brief Callback API upon configuring the const controller
76-
* See spi_configure() for argument description
125+
* @brief SPI controller configuration structure
126+
*
127+
* frequency is the bus frequency in Hertz
128+
* operation is a bit field with the following parts:
129+
* operational mode [ 0 ] - master or slave.
130+
* mode [ 1 : 3 ] - Polarity, phase and loop mode.
131+
* transfer [ 4 ] - LSB or MSB first.
132+
* word_size [ 5 : 10 ] - Size of a data frame in bits.
133+
* lines [ 11 : 12 ] - MISO lines: Single/Dual/Quad.
134+
* RESERVED [ 13 : 15 ] - Unused yet
135+
*
136+
* slave is the slave number from 0 to host constoller slave limit.
137+
*
138+
* cs is a valid pointer on a struct spi_cs_control is CS line is
139+
* emulated through a gpio line, or NULL otherwise.
77140
*/
78-
typedef int (*spi_api_configure)(struct device *dev,
79-
struct spi_config *config);
141+
struct spi_config {
142+
u32_t frequency;
143+
u16_t operation;
144+
u16_t slave;
145+
struct spi_cs_control *cs;
146+
};
147+
80148
/**
81-
* @typedef spi_api_slave_select
82-
* @brief Callback API upon selecting a slave
83-
* See spi_slave_select() for argument description
149+
* @brief SPI buffer structure
150+
*
151+
* buf is a valid pointer on a data buffer, or NULL otherwise.
152+
* len is the length of the buffer or, if buf is NULL, will be the
153+
* length which as to be sent as dummy bytes (as TX buffer) or
154+
* the length of bytes that should be skipped (as RX buffer).
84155
*/
85-
typedef int (*spi_api_slave_select)(struct device *dev, u32_t slave);
156+
struct spi_buf {
157+
void *buf;
158+
size_t len;
159+
};
160+
86161
/**
87162
* @typedef spi_api_io
88163
* @brief Callback API for I/O
89-
* See spi_read() and spi_write() for argument descriptions
164+
* See spi_transceive() for argument descriptions
90165
*/
91-
typedef int (*spi_api_io)(struct device *dev,
92-
const void *tx_buf, u32_t tx_buf_len,
93-
void *rx_buf, u32_t rx_buf_len);
166+
typedef int (*spi_api_io)(struct device *dev,
167+
struct spi_config *config,
168+
const struct spi_buf **tx_bufs,
169+
struct spi_buf **rx_bufs);
94170

171+
/**
172+
* @brief SPI driver API
173+
* This is the mandatory API any SPI driver needs to expose.
174+
*/
95175
struct spi_driver_api {
96-
spi_api_configure configure;
97-
spi_api_slave_select slave_select;
98176
spi_api_io transceive;
99177
};
100178

101179
/**
102-
* @brief Configure a host controller for operating against slaves.
103-
* @param dev Pointer to the device structure for the driver instance.
104-
* @param config Pointer to the configuration provided by the application.
105-
*
106-
* @retval 0 If successful.
107-
* @retval Negative errno code if failure.
108-
*/
109-
static inline int spi_configure(struct device *dev,
110-
struct spi_config *config)
111-
{
112-
const struct spi_driver_api *api = dev->driver_api;
113-
114-
return api->configure(dev, config);
115-
}
116-
117-
/**
118-
* @brief Select a slave to deal with.
180+
* @brief Read/write the specified amount of data from the SPI driver.
119181
*
120-
* This routine is meaningful only if the controller supports per-slave
121-
* addressing: One SS line per-slave. If not, this routine has no effect
122-
* and daisy-chaining should be considered to deal with multiple slaves
123-
* on the same line.
182+
* Note: This function is synchronous.
124183
*
125-
* @param dev Pointer to the device structure for the driver instance
126-
* @param slave An integer identifying the slave. It starts from 1 which
127-
* corresponds to cs0.
184+
* @param dev is a valid pointer to an actual SPI device
185+
* @param config Pointer to a valid spi_config structure instance.
186+
* @param tx_bufs NULL terminated buffer array where data to be sent
187+
* originates from, or NULL if none.
188+
* @param rx_bufs NULL terminated buffer array where data to be read
189+
* will be written to, or NULL if none.
128190
*
129-
* @retval 0 If successful.
130-
* @retval Negative errno code if failure.
191+
* @retval 0 If successful, negative errno code otherwise.
131192
*/
132-
static inline int spi_slave_select(struct device *dev, u32_t slave)
193+
static inline int spi_transceive(struct device *dev,
194+
struct spi_config *config,
195+
const struct spi_buf **tx_bufs,
196+
struct spi_buf **rx_bufs)
133197
{
134198
const struct spi_driver_api *api = dev->driver_api;
135199

136-
if (!api->slave_select) {
137-
return 0;
138-
}
139-
140-
return api->slave_select(dev, slave);
200+
return api->transceive(dev, config, tx_bufs, rx_bufs);
141201
}
142202

143203
/**
144204
* @brief Read the specified amount of data from the SPI driver.
145-
* @param dev Pointer to the device structure for the driver instance.
146-
* @param buf Memory buffer where data will be transferred.
147-
* @param len Size of the memory buffer available for writing.
148205
*
149-
* @retval 0 If successful.
150-
* @retval Negative errno code if failure.
151-
*/
152-
static inline int spi_read(struct device *dev, void *buf, u32_t len)
153-
{
154-
const struct spi_driver_api *api = dev->driver_api;
155-
156-
return api->transceive(dev, NULL, 0, buf, len);
157-
}
158-
159-
/**
160-
* @brief Write the specified amount of data from the SPI driver.
161-
* @param dev Pointer to the device structure for the driver instance.
162-
* @param buf Memory buffer from where data is transferred.
163-
* @param len Size of the memory buffer available for reading.
206+
* Note: This function is synchronous.
207+
*
208+
* @param dev is a valid pointer to an actual SPI device
209+
* @param config Pointer to a valid spi_config structure instance.
210+
* @param rx_bufs NULL terminated buffer array where data to be read
211+
* will be written to.
164212
*
165-
* @retval 0 If successful.
166-
* @retval Negative errno code if failure.
213+
* @retval 0 If successful, negative errno code otherwise.
167214
*/
168-
static inline int spi_write(struct device *dev, const void *buf, u32_t len)
215+
static inline int spi_read(struct device *dev,
216+
struct spi_config *config,
217+
struct spi_buf **rx_bufs)
169218
{
170219
const struct spi_driver_api *api = dev->driver_api;
171220

172-
return api->transceive(dev, buf, len, NULL, 0);
221+
return api->transceive(dev, config, NULL, rx_bufs);
173222
}
174223

175224
/**
176-
* @brief Read and write the specified amount of data from the SPI driver.
225+
* @brief Write the specified amount of data from the SPI driver.
177226
*
178-
* This routine is meant for full-duplex transmission.
179-
* Only equal length is supported(tx_buf_len must be equal to rx_buf_len).
227+
* Note: This function is synchronous.
180228
*
181-
* @param dev Pointer to the device structure for the driver instance.
182-
* @param tx_buf Memory buffer where data originates
183-
* @param tx_buf_len Size of the memory buffer available for reading.
184-
* @param rx_buf Memory buffer where data is transferred.
185-
* @param rx_buf_len Size of the memory buffer available for writing.
229+
* @param dev is a valid pointer to an actual SPI device
230+
* @param config Pointer to a valid spi_config structure instance.
231+
* @param tx_bufs NULL terminated buffer array where data to be sent
232+
* originates from.
186233
*
187-
* @retval 0 If successful.
188-
* @retval Negative errno code if failure.
234+
* @retval 0 If successful, negative errno code otherwise.
189235
*/
190-
static inline int spi_transceive(struct device *dev,
191-
const void *tx_buf, u32_t tx_buf_len,
192-
void *rx_buf, u32_t rx_buf_len)
236+
static inline int spi_write(struct device *dev,
237+
struct spi_config *config,
238+
const struct spi_buf **tx_bufs)
193239
{
194240
const struct spi_driver_api *api = dev->driver_api;
195241

196-
return api->transceive(dev, tx_buf, tx_buf_len, rx_buf, rx_buf_len);
242+
return api->transceive(dev, config, tx_bufs, NULL);
197243
}
198244

199245
#ifdef __cplusplus
@@ -205,3 +251,5 @@ static inline int spi_transceive(struct device *dev,
205251
*/
206252

207253
#endif /* __SPI_H__ */
254+
255+
#endif /* CONFIG_SPI_LEGACY_API */

0 commit comments

Comments
 (0)