api/spi: Reduce parameter number on transceive function

tx_bufs/tx_count and rx_bufs/rx_count can be hold in another dedicated
structure, thus reducing the number of parameters to transceive. This
permits to avoid using the stack when calling transceive.

Since we saved parameters, we can expose back the struct device pointer,
to stay consistent with other device driver APIs.

Fixes #5839

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2018-01-30 13:49:01 +01:00 committed by Carles Cufí
parent f3f9fab20e
commit ea2431f32f
15 changed files with 489 additions and 377 deletions

View file

@ -78,11 +78,11 @@ static void _cc1200_print_status(u8_t status)
* Generic functions *
********************/
bool _cc1200_access_reg(struct spi_config *spi, bool read, u8_t addr,
bool _cc1200_access_reg(struct cc1200_context *ctx, bool read, u8_t addr,
void *data, size_t length, bool extended, bool burst)
{
u8_t cmd_buf[2];
struct spi_buf buf[2] = {
const struct spi_buf buf[2] = {
{
.buf = cmd_buf,
.len = extended ? 2 : 1,
@ -93,6 +93,7 @@ bool _cc1200_access_reg(struct spi_config *spi, bool read, u8_t addr,
}
};
struct spi_buf_set tx = { .buffers = buf };
/*
SYS_LOG_DBG("%s: addr 0x%02x - Data %p Length %u - %s, %s",
@ -115,13 +116,22 @@ bool _cc1200_access_reg(struct spi_config *spi, bool read, u8_t addr,
}
if (read) {
const struct spi_buf_set rx = {
.buffers = buf,
.count = 2
};
cmd_buf[0] |= CC1200_ACCESS_RD;
return (spi_transceive(spi, buf, 1, buf, 2) == 0);
tx.count = 1;
return (spi_transceive(ctx->spi, &ctx->spi_cfg, &tx, &rx) == 0);
}
/* CC1200_ACCESS_WR is 0 so no need to play with it */
return (spi_write(spi, buf, data ? 2 : 1) == 0);
tx.count = data ? 2 : 1;
return (spi_write(ctx->spi, &ctx->spi_cfg, &tx) == 0);
}
static inline u8_t *get_mac(struct device *dev)
@ -149,11 +159,11 @@ static inline u8_t *get_mac(struct device *dev)
return cc1200->mac_addr;
}
static u8_t get_status(struct spi_config *spi)
static u8_t get_status(struct cc1200_context *ctx)
{
u8_t val;
if (_cc1200_access_reg(spi, true, CC1200_INS_SNOP,
if (_cc1200_access_reg(ctx, true, CC1200_INS_SNOP,
&val, 1, false, false)) {
/* See Section 3.1.2 */
return val & CC1200_STATUS_MASK;
@ -218,13 +228,13 @@ static void setup_gpio_callback(struct device *dev)
* RF functions *
***************/
static u8_t get_lo_divider(struct spi_config *spi)
static u8_t get_lo_divider(struct cc1200_context *ctx)
{
/* See Table 34 */
return FSD_BANDSELECT(read_reg_fs_cfg(spi)) << 1;
return FSD_BANDSELECT(read_reg_fs_cfg(ctx)) << 1;
}
static bool write_reg_freq(struct spi_config *spi, u32_t freq)
static bool write_reg_freq(struct cc1200_context *ctx, u32_t freq)
{
u8_t freq_data[3];
@ -232,7 +242,7 @@ static bool write_reg_freq(struct spi_config *spi, u32_t freq)
freq_data[1] = (u8_t)((freq & 0x0000FF00) >> 8);
freq_data[2] = (u8_t)(freq & 0x000000FF);
return _cc1200_access_reg(spi, false, CC1200_REG_FREQ2,
return _cc1200_access_reg(ctx, false, CC1200_REG_FREQ2,
freq_data, 3, true, true);
}
@ -266,7 +276,7 @@ static bool write_reg_freq(struct spi_config *spi, u32_t freq)
* User does not need to pass anything extra besides the nominal settings: no
* pre-computed part or else.
*/
static u32_t rf_evaluate_freq_setting(struct cc1200_context *cc1200, u32_t chan)
static u32_t rf_evaluate_freq_setting(struct cc1200_context *ctx, u32_t chan)
{
u32_t xtal = CONFIG_IEEE802154_CC1200_XOSC;
u32_t mult_10 = 100000;
@ -276,7 +286,7 @@ static u32_t rf_evaluate_freq_setting(struct cc1200_context *cc1200, u32_t chan)
rf = cc1200->rf_settings->chan_center_freq0 +
((chan * (u32_t)cc1200->rf_settings->channel_spacing) / 10);
lo_div = get_lo_divider(&cc1200->spi);
lo_div = get_lo_divider(ctx);
SYS_LOG_DBG("Calculating freq for %u KHz RF (%u)", rf, lo_div);
@ -322,14 +332,14 @@ rf_install_settings(struct device *dev,
{
struct cc1200_context *cc1200 = dev->driver_data;
if (!_cc1200_access_reg(&cc1200->spi, false, CC1200_REG_SYNC3,
if (!_cc1200_access_reg(cc1200, false, CC1200_REG_SYNC3,
(void *)rf_settings->registers,
CC1200_RF_NON_EXT_SPACE_REGS, false, true) ||
!_cc1200_access_reg(&cc1200->spi, false, CC1200_REG_IF_MIX_CFG,
!_cc1200_access_reg(cc1200, false, CC1200_REG_IF_MIX_CFG,
(void *)rf_settings->registers +
CC1200_RF_NON_EXT_SPACE_REGS,
CC1200_RF_EXT_SPACE_REGS, true, true) ||
!write_reg_pkt_len(&cc1200->spi, 0xFF)) {
!write_reg_pkt_len(cc1200, 0xFF)) {
SYS_LOG_ERR("Could not install RF settings");
return false;
}
@ -339,9 +349,9 @@ rf_install_settings(struct device *dev,
return true;
}
static int rf_calibrate(struct spi_config *spi)
static int rf_calibrate(struct cc1200_context *ctx)
{
if (!instruct_scal(spi)) {
if (!instruct_scal(ctx)) {
SYS_LOG_ERR("Could not calibrate RF");
return -EIO;
}
@ -349,16 +359,16 @@ static int rf_calibrate(struct spi_config *spi)
k_busy_wait(5 * USEC_PER_MSEC);
/* We need to re-enable RX as SCAL shuts off the freq synth */
if (!instruct_sidle(spi) ||
!instruct_sfrx(spi) ||
!instruct_srx(spi)) {
if (!instruct_sidle(ctx) ||
!instruct_sfrx(ctx) ||
!instruct_srx(ctx)) {
SYS_LOG_ERR("Could not switch to RX");
return -EIO;
}
k_busy_wait(10 * USEC_PER_MSEC);
_cc1200_print_status(get_status(spi));
_cc1200_print_status(get_status(ctx));
return 0;
}
@ -367,10 +377,10 @@ static int rf_calibrate(struct spi_config *spi)
* TX functions *
***************/
static inline bool write_txfifo(struct spi_config *spi,
static inline bool write_txfifo(struct cc1200_context *ctx,
void *data, size_t length)
{
return _cc1200_access_reg(spi, false,
return _cc1200_access_reg(ctx, false,
CC1200_REG_TXFIFO,
data, length, false, true);
}
@ -379,19 +389,19 @@ static inline bool write_txfifo(struct spi_config *spi,
* RX functions *
***************/
static inline bool read_rxfifo(struct spi_config *spi,
static inline bool read_rxfifo(struct cc1200_context *ctx,
void *data, size_t length)
{
return _cc1200_access_reg(spi, true,
return _cc1200_access_reg(ctx, true,
CC1200_REG_RXFIFO,
data, length, false, true);
}
static inline u8_t get_packet_length(struct spi_config *spi)
static inline u8_t get_packet_length(struct cc1200_context *ctx)
{
u8_t len;
if (_cc1200_access_reg(spi, true, CC1200_REG_RXFIFO,
if (_cc1200_access_reg(ctx, true, CC1200_REG_RXFIFO,
&len, 1, false, true)) {
return len;
}
@ -399,23 +409,24 @@ static inline u8_t get_packet_length(struct spi_config *spi)
return 0;
}
static inline bool verify_rxfifo_validity(struct spi_config *spi, u8_t pkt_len)
static inline bool verify_rxfifo_validity(struct cc1200_context *ctx,
u8_t pkt_len)
{
/* packet should be at least 3 bytes as a ACK */
if (pkt_len < 3 ||
read_reg_num_rxbytes(spi) > (pkt_len + CC1200_FCS_LEN)) {
read_reg_num_rxbytes(ctx) > (pkt_len + CC1200_FCS_LEN)) {
return false;
}
return true;
}
static inline bool read_rxfifo_content(struct spi_config *spi,
static inline bool read_rxfifo_content(struct cc1200_context *ctx,
struct net_buf *frag, u8_t len)
{
if (!read_rxfifo(spi, frag->data, len) ||
(get_status(spi) == CC1200_STATUS_RX_FIFO_ERROR)) {
if (!read_rxfifo(ctx, frag->data, len) ||
(get_status(ctx) == CC1200_STATUS_RX_FIFO_ERROR)) {
return false;
}
@ -424,11 +435,11 @@ static inline bool read_rxfifo_content(struct spi_config *spi,
return true;
}
static inline bool verify_crc(struct spi_config *spi, struct net_pkt *pkt)
static inline bool verify_crc(struct cc1200_context *ctx, struct net_pkt *pkt)
{
u8_t fcs[2];
if (!read_rxfifo(spi, fcs, 2)) {
if (!read_rxfifo(ctx, fcs, 2)) {
return false;
}
@ -454,13 +465,13 @@ static void cc1200_rx(struct device *dev)
k_sem_take(&cc1200->rx_lock, K_FOREVER);
if (get_status(&cc1200->spi) == CC1200_STATUS_RX_FIFO_ERROR) {
if (get_status(cc1200) == CC1200_STATUS_RX_FIFO_ERROR) {
SYS_LOG_ERR("Fifo error");
goto flush;
}
pkt_len = get_packet_length(&cc1200->spi);
if (!verify_rxfifo_validity(&cc1200->spi, pkt_len)) {
pkt_len = get_packet_length(cc1200);
if (!verify_rxfifo_validity(cc1200, pkt_len)) {
SYS_LOG_ERR("Invalid frame");
goto flush;
}
@ -479,12 +490,12 @@ static void cc1200_rx(struct device *dev)
net_pkt_frag_insert(pkt, pkt_frag);
if (!read_rxfifo_content(&cc1200->spi, pkt_frag, pkt_len)) {
if (!read_rxfifo_content(cc1200, pkt_frag, pkt_len)) {
SYS_LOG_ERR("No content read");
goto flush;
}
if (!verify_crc(&cc1200->spi, pkt)) {
if (!verify_crc(cc1200, pkt)) {
SYS_LOG_ERR("Bad packet CRC");
goto out;
}
@ -507,9 +518,9 @@ static void cc1200_rx(struct device *dev)
continue;
flush:
SYS_LOG_DBG("Flushing RX");
instruct_sidle(&cc1200->spi);
instruct_sfrx(&cc1200->spi);
instruct_srx(&cc1200->spi);
instruct_sidle(cc1200);
instruct_sfrx(cc1200);
instruct_srx(cc1200);
out:
if (pkt) {
net_pkt_unref(pkt);
@ -532,7 +543,7 @@ static int cc1200_cca(struct device *dev)
struct cc1200_context *cc1200 = dev->driver_data;
if (atomic_get(&cc1200->rx) == 0) {
u8_t status = read_reg_rssi0(&cc1200->spi);
u8_t status = read_reg_rssi0(cc1200);
if (!(status & CARRIER_SENSE) &&
(status & CARRIER_SENSE_VALID)) {
@ -560,8 +571,8 @@ static int cc1200_set_channel(struct device *dev, u16_t channel)
if (atomic_get(&cc1200->rx) == 0) {
u32_t freq = rf_evaluate_freq_setting(cc1200, channel);
if (!write_reg_freq(&cc1200->spi, freq) ||
rf_calibrate(&cc1200->spi)) {
if (!write_reg_freq(cc1200, freq) ||
rf_calibrate(cc1200)) {
SYS_LOG_ERR("Could not set channel %u", channel);
return -EIO;
}
@ -584,10 +595,10 @@ static int cc1200_set_txpower(struct device *dev, s16_t dbm)
return -EINVAL;
}
pa_power_ramp = read_reg_pa_cfg1(&cc1200->spi) & ~PA_POWER_RAMP_MASK;
pa_power_ramp = read_reg_pa_cfg1(cc1200) & ~PA_POWER_RAMP_MASK;
pa_power_ramp |= ((u8_t) dbm) & PA_POWER_RAMP_MASK;
if (!write_reg_pa_cfg1(&cc1200->spi, pa_power_ramp)) {
if (!write_reg_pa_cfg1(cc1200, pa_power_ramp)) {
SYS_LOG_ERR("Could not proceed");
return -EIO;
}
@ -611,17 +622,17 @@ static int cc1200_tx(struct device *dev,
* depending on len value, this will also take more time.
*/
if (!instruct_sidle(&cc1200->spi) ||
!instruct_sfrx(&cc1200->spi) ||
!instruct_sftx(&cc1200->spi) ||
!instruct_sfstxon(&cc1200->spi)) {
if (!instruct_sidle(cc1200) ||
!instruct_sfrx(cc1200) ||
!instruct_sftx(cc1200) ||
!instruct_sfstxon(cc1200)) {
SYS_LOG_ERR("Cannot switch to TX mode");
goto out;
}
if (!write_txfifo(&cc1200->spi, &len, CC1200_PHY_HDR_LEN) ||
!write_txfifo(&cc1200->spi, frame, len) ||
read_reg_num_txbytes(&cc1200->spi) != (len + CC1200_PHY_HDR_LEN)) {
if (!write_txfifo(cc1200, &len, CC1200_PHY_HDR_LEN) ||
!write_txfifo(cc1200, frame, len) ||
read_reg_num_txbytes(cc1200) != (len + CC1200_PHY_HDR_LEN)) {
SYS_LOG_ERR("Cannot fill-in TX fifo");
goto out;
}
@ -629,7 +640,7 @@ static int cc1200_tx(struct device *dev,
atomic_set(&cc1200->tx, 1);
atomic_set(&cc1200->tx_start, 0);
if (!instruct_stx(&cc1200->spi)) {
if (!instruct_stx(cc1200)) {
SYS_LOG_ERR("Cannot start transmission");
goto out;
}
@ -642,14 +653,14 @@ static int cc1200_tx(struct device *dev,
}
out:
_cc1200_print_status(get_status(&cc1200->spi));
_cc1200_print_status(get_status(cc1200));
if (atomic_get(&cc1200->tx) == 1 &&
read_reg_num_txbytes(&cc1200->spi) != 0) {
read_reg_num_txbytes(cc1200) != 0) {
SYS_LOG_ERR("TX Failed");
atomic_set(&cc1200->tx_start, 0);
instruct_sftx(&cc1200->spi);
instruct_sftx(cc1200);
status = false;
} else {
status = true;
@ -658,7 +669,7 @@ out:
atomic_set(&cc1200->tx, 0);
/* Get back to RX */
instruct_srx(&cc1200->spi);
instruct_srx(cc1200);
return status ? 0 : -EIO;
}
@ -667,17 +678,17 @@ static int cc1200_start(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
if (!instruct_sidle(&cc1200->spi) ||
!instruct_sftx(&cc1200->spi) ||
!instruct_sfrx(&cc1200->spi) ||
rf_calibrate(&cc1200->spi)) {
if (!instruct_sidle(cc1200) ||
!instruct_sftx(cc1200) ||
!instruct_sfrx(cc1200) ||
rf_calibrate(cc1200)) {
SYS_LOG_ERR("Could not proceed");
return -EIO;
}
enable_gpio0_interrupt(cc1200, true);
_cc1200_print_status(get_status(&cc1200->spi));
_cc1200_print_status(get_status(cc1200));
return 0;
}
@ -688,7 +699,7 @@ static int cc1200_stop(struct device *dev)
enable_gpio0_interrupt(cc1200, false);
if (!instruct_spwd(&cc1200->spi)) {
if (!instruct_spwd(cc1200)) {
SYS_LOG_ERR("Could not proceed");
return -EIO;
}
@ -711,7 +722,7 @@ static int power_on_and_setup(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
if (!instruct_sres(&cc1200->spi)) {
if (!instruct_sres(cc1200)) {
SYS_LOG_ERR("Cannot reset");
return -EIO;
}
@ -720,25 +731,25 @@ static int power_on_and_setup(struct device *dev)
return -EIO;
}
if (!write_reg_iocfg3(&cc1200->spi, CC1200_IOCFG3) ||
!write_reg_iocfg2(&cc1200->spi, CC1200_IOCFG2) ||
!write_reg_iocfg0(&cc1200->spi, CC1200_IOCFG0)) {
if (!write_reg_iocfg3(cc1200, CC1200_IOCFG3) ||
!write_reg_iocfg2(cc1200, CC1200_IOCFG2) ||
!write_reg_iocfg0(cc1200, CC1200_IOCFG0)) {
SYS_LOG_ERR("Cannot configure GPIOs");
return -EIO;
}
setup_gpio_callback(dev);
return rf_calibrate(&cc1200->spi);
return rf_calibrate(cc1200);
}
static int configure_spi(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
cc1200->spi.dev = device_get_binding(
cc1200->spi = device_get_binding(
CONFIG_IEEE802154_CC1200_SPI_DRV_NAME);
if (!cc1200->spi.dev) {
if (!cc1200->spi) {
SYS_LOG_ERR("Unable to get SPI device");
return -ENODEV;
}
@ -754,16 +765,16 @@ static int configure_spi(struct device *dev)
cs_ctrl.gpio_pin = CONFIG_IEEE802154_CC1200_GPIO_SPI_CS_PIN;
cs_ctrl.delay = 0;
cc1200->spi.cs = &cs_ctrl;
cc1200->spi_cfg.cs = &cs_ctrl;
SYS_LOG_DBG("SPI GPIO CS configured on %s:%u",
CONFIG_IEEE802154_CC1200_GPIO_SPI_CS_DRV_NAME,
CONFIG_IEEE802154_CC1200_GPIO_SPI_CS_PIN);
}
cc1200->spi.operation = SPI_WORD_SET(8);
cc1200->spi.frequency = CONFIG_IEEE802154_CC1200_SPI_FREQ;
cc1200->spi.slave = CONFIG_IEEE802154_CC1200_SPI_SLAVE;
cc1200->spi_cfg.operation = SPI_WORD_SET(8);
cc1200->spi_cfg.frequency = CONFIG_IEEE802154_CC1200_SPI_FREQ;
cc1200->spi_cfg.slave = CONFIG_IEEE802154_CC1200_SPI_SLAVE;
return 0;
}

View file

@ -24,7 +24,8 @@ struct cc1200_context {
/**************************/
struct cc1200_gpio_configuration *gpios;
struct gpio_callback rx_tx_cb;
struct spi_config spi;
struct device *spi;
struct spi_config spi_cfg;
u8_t mac_addr[8];
/************RF************/
const struct cc1200_rf_registers_set *rf_settings;
@ -46,45 +47,45 @@ struct cc1200_context {
***************************
*/
bool _cc1200_access_reg(struct spi_config *spi, bool read, u8_t addr,
bool _cc1200_access_reg(struct cc1200_context *ctx, bool read, u8_t addr,
void *data, size_t length, bool extended, bool burst);
static inline u8_t _cc1200_read_single_reg(struct spi_config *spi,
static inline u8_t _cc1200_read_single_reg(struct cc1200_context *ctx,
u8_t addr, bool extended)
{
u8_t val;
if (_cc1200_access_reg(spi, true, addr, &val, 1, extended, false)) {
if (_cc1200_access_reg(ctx, true, addr, &val, 1, extended, false)) {
return val;
}
return 0;
}
static inline bool _cc1200_write_single_reg(struct spi_config *spi,
static inline bool _cc1200_write_single_reg(struct cc1200_context *ctx,
u8_t addr, u8_t val, bool extended)
{
return _cc1200_access_reg(spi, false, addr, &val, 1, extended, false);
return _cc1200_access_reg(ctx, false, addr, &val, 1, extended, false);
}
static inline bool _cc1200_instruct(struct spi_config *spi, u8_t addr)
static inline bool _cc1200_instruct(struct cc1200_context *ctx, u8_t addr)
{
return _cc1200_access_reg(spi, false, addr, NULL, 0, false, false);
return _cc1200_access_reg(ctx, false, addr, NULL, 0, false, false);
}
#define DEFINE_REG_READ(__reg_name, __reg_addr, __ext) \
static inline u8_t read_reg_##__reg_name(struct spi_config *spi) \
static inline u8_t read_reg_##__reg_name(struct cc1200_context *ctx) \
{ \
/*SYS_LOG_DBG("");*/ \
return _cc1200_read_single_reg(spi, __reg_addr, __ext); \
return _cc1200_read_single_reg(ctx, __reg_addr, __ext); \
}
#define DEFINE_REG_WRITE(__reg_name, __reg_addr, __ext) \
static inline bool write_reg_##__reg_name(struct spi_config *spi, \
static inline bool write_reg_##__reg_name(struct cc1200_context *ctx, \
u8_t val) \
{ \
/*SYS_LOG_DBG("");*/ \
return _cc1200_write_single_reg(spi, __reg_addr, \
return _cc1200_write_single_reg(ctx, __reg_addr, \
val, __ext); \
}
@ -106,10 +107,10 @@ DEFINE_REG_READ(num_rxbytes, CC1200_REG_NUM_RXBYTES, true)
*/
#define DEFINE_STROBE_INSTRUCTION(__ins_name, __ins_addr) \
static inline bool instruct_##__ins_name(struct spi_config *spi) \
static inline bool instruct_##__ins_name(struct cc1200_context *ctx) \
{ \
/*SYS_LOG_DBG("");*/ \
return _cc1200_instruct(spi, __ins_addr); \
return _cc1200_instruct(ctx, __ins_addr); \
}
DEFINE_STROBE_INSTRUCTION(sres, CC1200_INS_SRES)

View file

@ -7,7 +7,6 @@
menuconfig APA102_STRIP
bool "APA102 SPI LED strip driver"
depends on SPI
depends on !SPI_LEGACY_API
select LED_STRIP_RGB_SCRATCH
default n
help

View file

@ -7,7 +7,6 @@
menuconfig LPD880X_STRIP
bool "Enable LPD880x SPI LED strip driver"
depends on SPI
depends on !SPI_LEGACY_API
default n
help
Enable LED strip driver for daisy chains of LPD880x

View file

@ -11,7 +11,6 @@
menuconfig WS2812_STRIP
bool "Enable WS2812 (and compatible) LED strip driver"
depends on SPI
depends on !SPI_LEGACY_API
default n
help
Enable LED strip driver for daisy chains of WS2812-ish

View file

@ -9,6 +9,7 @@
#include <spi.h>
struct apa102_data {
struct device *spi;
struct spi_config cfg;
};
@ -17,7 +18,7 @@ static int apa102_update(struct device *dev, void *buf, size_t size)
struct apa102_data *data = dev->driver_data;
static const u8_t zeros[] = {0, 0, 0, 0};
static const u8_t ones[] = {0xFF, 0xFF, 0xFF, 0xFF};
struct spi_buf tx[] = {
const struct spi_buf tx_bufs[] = {
{
/* Start frame: at least 32 zeros */
.buf = (u8_t *)zeros,
@ -37,8 +38,12 @@ static int apa102_update(struct device *dev, void *buf, size_t size)
.len = sizeof(ones),
},
};
const struct spi_buf_set tx = {
.buffers = tx_bufs,
.count = ARRAY_SIZE(tx)
};
return spi_write(&data->cfg, tx, ARRAY_SIZE(tx));
return spi_write(data->spi, &data->cfg, &tx);
}
static int apa102_update_rgb(struct device *dev, struct led_rgb *pixels,
@ -75,14 +80,12 @@ static int apa102_update_channels(struct device *dev, u8_t *channels,
static int apa102_init(struct device *dev)
{
struct apa102_data *data = dev->driver_data;
struct device *spi;
spi = device_get_binding(CONFIG_APA102_STRIP_BUS_NAME);
if (!spi) {
data->spi = device_get_binding(CONFIG_APA102_STRIP_BUS_NAME);
if (!data->spi) {
return -ENODEV;
}
data->cfg.dev = spi;
data->cfg.frequency = CONFIG_APA102_STRIP_FREQUENCY;
data->cfg.operation =
SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8);

View file

@ -29,6 +29,7 @@
SPI_LINES_SINGLE)
struct lpd880x_data {
struct device *spi;
struct spi_config config;
};
@ -43,23 +44,33 @@ static int lpd880x_update(struct device *dev, void *data, size_t size)
u8_t reset_size = ceiling_fraction(ceiling_fraction(size, 3), 32);
u8_t reset_buf[reset_size];
u8_t last = 0x00;
struct spi_buf bufs[3];
const struct spi_buf bufs[3] = {
{
/* Prepares the strip to shift in new data values. */
.buf = reset_buf,
.len = reset_size
},
{
/* Displays the serialized pixel data. */
.buf = data,
.len = size
},
{
/* Ensures the last byte of pixel data is displayed. */
.buf = &last,
.len = sizeof(last)
}
};
const struct spi_buf_set tx = {
.buffers = bufs,
.count = 3
};
size_t rc;
/* Prepares the strip to shift in new data values. */
memset(reset_buf, 0x00, reset_size);
bufs[0].buf = reset_buf;
bufs[0].len = reset_size;
/* Displays the serialized pixel data. */
bufs[1].buf = data;
bufs[1].len = size;
/* Ensures the last byte of pixel data is displayed. */
bufs[2].buf = &last;
bufs[2].len = sizeof(last);
rc = spi_write(&drv_data->config, bufs, ARRAY_SIZE(bufs));
rc = spi_write(drv_data->spi, &drv_data->config, &tx);
if (rc) {
SYS_LOG_ERR("can't update strip: %d", rc);
}
@ -112,16 +123,14 @@ static int lpd880x_strip_init(struct device *dev)
{
struct lpd880x_data *data = dev->driver_data;
struct spi_config *config = &data->config;
struct device *spi;
spi = device_get_binding(CONFIG_LPD880X_STRIP_SPI_DEV_NAME);
if (!spi) {
data->spi = device_get_binding(CONFIG_LPD880X_STRIP_SPI_DEV_NAME);
if (!data->spi) {
SYS_LOG_ERR("SPI device %s not found",
CONFIG_LPD880X_STRIP_SPI_DEV_NAME);
return -ENODEV;
}
config->dev = spi;
config->frequency = CONFIG_LPD880X_STRIP_SPI_BAUD_RATE;
config->operation = LPD880X_SPI_OPERATION;
config->slave = 0; /* MOSI/CLK only; CS is not supported. */

View file

@ -48,6 +48,7 @@
#define RESET_NFRAMES ((size_t)ceiling_fraction(3 * SPI_FREQ, 4000000) + 1)
struct ws2812_data {
struct device *spi;
struct spi_config config;
};
@ -82,17 +83,21 @@ static size_t ws2812_serialize_pixel(u8_t px[32], struct led_rgb *pixel)
/*
* Latch current color values on strip and reset its state machines.
*/
static int ws2812_reset_strip(struct spi_config *config)
static int ws2812_reset_strip(struct ws2812_data *data)
{
u8_t reset_buf[RESET_NFRAMES];
struct spi_buf reset = {
const struct spi_buf reset = {
.buf = reset_buf,
.len = sizeof(reset_buf),
};
const struct spi_buf_set tx = {
.buffers = &reset,
.count = 1
};
memset(reset_buf, 0x00, sizeof(reset_buf));
return spi_write(config, &reset, 1);
return spi_write(data->spi, &data->config, &tx);
}
static int ws2812_strip_update_rgb(struct device *dev, struct led_rgb *pixels,
@ -104,25 +109,29 @@ static int ws2812_strip_update_rgb(struct device *dev, struct led_rgb *pixels,
struct spi_buf buf = {
.buf = px_buf,
};
const struct spi_buf_set tx = {
.buffers = &buf,
.count = 1
};
size_t i;
int rc;
for (i = 0; i < num_pixels; i++) {
buf.len = ws2812_serialize_pixel(px_buf, &pixels[i]);
rc = spi_write(config, &buf, 1);
rc = spi_write(drv_data->spi, config, &tx);
if (rc) {
/*
* Latch anything we've shifted out first, to
* call visual attention to the problematic
* pixel.
*/
(void)ws2812_reset_strip(config);
(void)ws2812_reset_strip(drv_data);
SYS_LOG_ERR("can't set pixel %u: %d", i, rc);
return rc;
}
}
return ws2812_reset_strip(config);
return ws2812_reset_strip(drv_data);
}
static int ws2812_strip_update_channels(struct device *dev, u8_t *channels,
@ -131,45 +140,47 @@ static int ws2812_strip_update_channels(struct device *dev, u8_t *channels,
struct ws2812_data *drv_data = dev->driver_data;
struct spi_config *config = &drv_data->config;
u8_t px_buf[8]; /* one byte per bit */
struct spi_buf buf = {
const struct spi_buf buf = {
.buf = px_buf,
.len = sizeof(px_buf),
};
const struct spi_buf_set tx = {
.buffers = &buf,
.count = 1
};
size_t i;
int rc;
for (i = 0; i < num_channels; i++) {
ws2812_serialize_color(px_buf, channels[i]);
rc = spi_write(config, &buf, 1);
rc = spi_write(drv_data->spi, config, &tx);
if (rc) {
/*
* Latch anything we've shifted out first, to
* call visual attention to the problematic
* pixel.
*/
(void)ws2812_reset_strip(config);
(void)ws2812_reset_strip(drv_data);
SYS_LOG_ERR("can't set channel %u: %d", i, rc);
return rc;
}
}
return ws2812_reset_strip(config);
return ws2812_reset_strip(drv_data);
}
static int ws2812_strip_init(struct device *dev)
{
struct ws2812_data *data = dev->driver_data;
struct spi_config *config = &data->config;
struct device *spi;
spi = device_get_binding(CONFIG_WS2812_STRIP_SPI_DEV_NAME);
if (!spi) {
data->spi = device_get_binding(CONFIG_WS2812_STRIP_SPI_DEV_NAME);
if (!data->spi) {
SYS_LOG_ERR("SPI device %s not found",
CONFIG_WS2812_STRIP_SPI_DEV_NAME);
return -ENODEV;
}
config->dev = spi;
config->frequency = SPI_FREQ;
config->operation = SPI_OPER;
config->slave = 0; /* MOSI only. */

View file

@ -32,10 +32,10 @@ struct spi_context {
#endif
const struct spi_buf *current_tx;
size_t tx_count;
struct spi_buf *current_rx;
const struct spi_buf *current_rx;
size_t rx_count;
u8_t *tx_buf;
const u8_t *tx_buf;
size_t tx_len;
u8_t *rx_buf;
size_t rx_len;
@ -154,33 +154,34 @@ static inline void spi_context_cs_control(struct spi_context *ctx, bool on)
}
}
static inline void spi_context_buffers_setup(struct spi_context *ctx,
const struct spi_buf *tx_bufs,
size_t tx_count,
struct spi_buf *rx_bufs,
size_t rx_count,
u8_t dfs)
static inline
void spi_context_buffers_setup(struct spi_context *ctx,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs,
u8_t dfs)
{
SYS_LOG_DBG("tx_bufs %p (%zu) - rx_bufs %p (%zu) - %u",
tx_bufs, tx_count, rx_bufs, rx_count, dfs);
ctx->current_tx = tx_bufs;
ctx->tx_count = tx_count;
ctx->current_rx = rx_bufs;
ctx->rx_count = rx_count;
SYS_LOG_DBG("tx_bufs %p - rx_bufs %p - %u", tx_bufs, rx_bufs, dfs);
if (tx_bufs) {
ctx->tx_buf = tx_bufs->buf;
ctx->tx_len = tx_bufs->len / dfs;
ctx->current_tx = tx_bufs->buffers;
ctx->tx_count = tx_bufs->count;
ctx->tx_buf = ctx->current_tx->buf;
ctx->tx_len = ctx->current_tx->len / dfs;
} else {
ctx->current_tx = NULL;
ctx->tx_count = 0;
ctx->tx_buf = NULL;
ctx->tx_len = 0;
}
if (rx_bufs) {
ctx->rx_buf = rx_bufs->buf;
ctx->rx_len = rx_bufs->len / dfs;
ctx->current_rx = rx_bufs->buffers;
ctx->rx_count = rx_bufs->count;
ctx->rx_buf = ctx->current_rx->buf;
ctx->rx_len = ctx->current_rx->len / dfs;
} else {
ctx->current_rx = NULL;
ctx->rx_count = 0;
ctx->rx_buf = NULL;
ctx->rx_len = 0;
}
@ -208,10 +209,9 @@ void spi_context_update_tx(struct spi_context *ctx, u8_t dfs, u32_t len)
ctx->tx_len -= len;
if (!ctx->tx_len) {
ctx->current_tx++;
ctx->tx_count--;
if (ctx->tx_count) {
ctx->current_tx++;
ctx->tx_buf = ctx->current_tx->buf;
ctx->tx_len = ctx->current_tx->len / dfs;
} else {
@ -250,10 +250,9 @@ void spi_context_update_rx(struct spi_context *ctx, u8_t dfs, u32_t len)
ctx->rx_len -= len;
if (!ctx->rx_len) {
ctx->current_rx++;
ctx->rx_count--;
if (ctx->rx_count) {
ctx->current_rx++;
ctx->rx_buf = ctx->current_rx->buf;
ctx->rx_len = ctx->current_rx->len / dfs;
} else {

View file

@ -248,16 +248,15 @@ static int spi_dw_configure(const struct spi_dw_config *info,
return 0;
}
static int transceive(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count,
struct spi_buf *rx_bufs,
size_t rx_count,
static int transceive(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs,
bool asynchronous,
struct k_poll_signal *signal)
{
const struct spi_dw_config *info = config->dev->config->config_info;
struct spi_dw_data *spi = config->dev->driver_data;
const struct spi_dw_config *info = dev->config->config_info;
struct spi_dw_data *spi = dev->driver_data;
u32_t rx_thsld = DW_SPI_RXFTLR_DFLT;
u32_t imask = DW_SPI_IMR_UNMASK;
int ret = 0;
@ -277,8 +276,7 @@ static int transceive(const struct spi_config *config,
}
/* Set buffers info */
spi_context_buffers_setup(&spi->ctx, tx_bufs, tx_count,
rx_bufs, rx_count, spi->dfs);
spi_context_buffers_setup(&spi->ctx, tx_bufs, rx_bufs, spi->dfs);
spi->fifo_diff = 0;
@ -313,39 +311,33 @@ out:
return ret;
}
static int spi_dw_transceive(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count,
struct spi_buf *rx_bufs,
size_t rx_count)
static int spi_dw_transceive(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs)
{
SYS_LOG_DBG("%p, %p (%zu), %p (%zu)",
config->dev, tx_bufs, tx_count, rx_bufs, rx_count);
SYS_LOG_DBG("%p, %p, %p", dev, tx_bufs, rx_bufs);
return transceive(config, tx_bufs, tx_count,
rx_bufs, rx_count, false, NULL);
return transceive(dev, config, tx_bufs, rx_bufs, false, NULL);
}
#ifdef CONFIG_POLL
static int spi_dw_transceive_async(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count,
struct spi_buf *rx_bufs,
size_t rx_count,
static int spi_dw_transceive_async(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs,
struct k_poll_signal *async)
{
SYS_LOG_DBG("%p, %p (%zu), %p (%zu), %p",
config->dev, tx_bufs, tx_count, rx_bufs, rx_count, async);
SYS_LOG_DBG("%p, %p, %p, %p", dev, tx_bufs, rx_bufs, async);
return transceive(config, tx_bufs, tx_count,
rx_bufs, rx_count, true, async);
return transceive(dev, config, tx_bufs, rx_bufs, true, async);
}
#endif /* CONFIG_POLL */
static int spi_dw_release(const struct spi_config *config)
static int spi_dw_release(struct device *dev, const struct spi_config *config)
{
const struct spi_dw_config *info = config->dev->config->config_info;
struct spi_dw_data *spi = config->dev->driver_data;
const struct spi_dw_config *info = dev->config->config_info;
struct spi_dw_data *spi = dev->driver_data;
if (!spi_context_configured(&spi->ctx, config) ||
test_bit_ssienr(info->regs) || test_bit_sr_busy(info->regs)) {

View file

@ -8,7 +8,7 @@
#include <syscall_handler.h>
#ifndef CONFIG_SPI_LEGACY_API
static void verify_spi_buf_array(struct spi_buf *bufs, size_t len,
static void verify_spi_buf_array(const struct spi_buf *bufs, size_t len,
int writable, void *ssf)
{
/* Empty array, nothing to do */
@ -27,19 +27,31 @@ static void verify_spi_buf_array(struct spi_buf *bufs, size_t len,
}
}
_SYSCALL_HANDLER(spi_transceive, config_p, tx_bufs, tx_count, rx_bufs,
rx_count)
_SYSCALL_HANDLER(spi_transceive, dev, config_p, tx_bufs, rx_bufs)
{
const struct spi_config *config = (const struct spi_config *)config_p;
_SYSCALL_MEMORY_READ(config, sizeof(*config));
_SYSCALL_OBJ(config->dev, K_OBJ_DRIVER_SPI);
_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SPI);
/* ssf is implicit system call stack frame parameter, used by
* _SYSCALL_* APIs when something goes wrong.
*/
verify_spi_buf_array((struct spi_buf *)tx_bufs, tx_count, 0, ssf);
verify_spi_buf_array((struct spi_buf *)rx_bufs, rx_count, 1, ssf);
if (tx_bufs) {
const struct spi_buf_set *tx =
(const struct spi_buf_set *)tx_bufs;
_SYSCALL_MEMORY_READ(tx_bufs, sizeof(struct spi_buf_set));
verify_spi_buf_array(tx->buffers, tx->count, 0, ssf);
}
if (rx_bufs) {
const struct spi_buf_set *rx =
(const struct spi_buf_set *)rx_bufs;
_SYSCALL_MEMORY_READ(rx_bufs, sizeof(struct spi_buf_set));
verify_spi_buf_array(rx->buffers, rx->count, 1, ssf);
}
if (config->cs) {
struct spi_cs_control *cs = config->cs;
@ -50,17 +62,17 @@ _SYSCALL_HANDLER(spi_transceive, config_p, tx_bufs, tx_count, rx_bufs,
}
}
return _impl_spi_transceive(config, (const struct spi_buf *)tx_bufs,
tx_count, (struct spi_buf *)rx_bufs,
rx_count);
return _impl_spi_transceive((struct device *)dev, config,
(const struct spi_buf_set *)tx_bufs,
(const struct spi_buf_set *)rx_bufs);
}
_SYSCALL_HANDLER(spi_release, config_p)
_SYSCALL_HANDLER(spi_release, dev, config_p)
{
const struct spi_config *config = (const struct spi_config *)config_p;
_SYSCALL_MEMORY_READ(config, sizeof(*config));
_SYSCALL_OBJ(config->dev, K_OBJ_DRIVER_SPI);
return _impl_spi_release(config);
_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SPI);
return _impl_spi_release((struct device *)dev, config);
}
#endif

View file

@ -19,11 +19,11 @@
#include "spi_ll_stm32.h"
#define CONFIG_CFG(cfg) \
((const struct spi_stm32_config * const)(cfg)->dev->config->config_info)
#define DEV_CFG(dev) \
(const struct spi_stm32_config * const)(dev->config->config_info)
#define CONFIG_DATA(cfg) \
((struct spi_stm32_data * const)(cfg)->dev->driver_data)
#define DEV_DATA(dev) \
(struct spi_stm32_data * const)(dev->driver_data)
/*
* Check for SPI_SR_FRE to determine support for TI mode frame format
@ -222,10 +222,11 @@ static void spi_stm32_isr(void *arg)
}
#endif
static int spi_stm32_configure(const struct spi_config *config)
static int spi_stm32_configure(struct device *dev,
const struct spi_config *config)
{
const struct spi_stm32_config *cfg = CONFIG_CFG(config);
struct spi_stm32_data *data = CONFIG_DATA(config);
const struct spi_stm32_config *cfg = DEV_CFG(dev);
struct spi_stm32_data *data = DEV_DATA(dev);
const u32_t scaler[] = {
LL_SPI_BAUDRATEPRESCALER_DIV2,
LL_SPI_BAUDRATEPRESCALER_DIV4,
@ -340,26 +341,28 @@ static int spi_stm32_configure(const struct spi_config *config)
return 0;
}
static int spi_stm32_release(const struct spi_config *config)
static int spi_stm32_release(struct device *dev,
const struct spi_config *config)
{
struct spi_stm32_data *data = CONFIG_DATA(config);
struct spi_stm32_data *data = DEV_DATA(dev);
spi_context_unlock_unconditionally(&data->ctx);
return 0;
}
static int transceive(const struct spi_config *config,
const struct spi_buf *tx_bufs, u32_t tx_count,
struct spi_buf *rx_bufs, u32_t rx_count,
static int transceive(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs,
bool asynchronous, struct k_poll_signal *signal)
{
const struct spi_stm32_config *cfg = CONFIG_CFG(config);
struct spi_stm32_data *data = CONFIG_DATA(config);
const struct spi_stm32_config *cfg = DEV_CFG(dev);
struct spi_stm32_data *data = DEV_DATA(dev);
SPI_TypeDef *spi = cfg->spi;
int ret;
if (!tx_count && !rx_count) {
if (!tx_bufs && !rx_bufs) {
return 0;
}
@ -371,14 +374,13 @@ static int transceive(const struct spi_config *config,
spi_context_lock(&data->ctx, asynchronous, signal);
ret = spi_stm32_configure(config);
ret = spi_stm32_configure(dev, config);
if (ret) {
return ret;
}
/* Set buffers info */
spi_context_buffers_setup(&data->ctx, tx_bufs, tx_count,
rx_bufs, rx_count, 1);
spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1);
#if defined(CONFIG_SPI_STM32_HAS_FIFO)
/* Flush RX buffer */
@ -419,24 +421,22 @@ static int transceive(const struct spi_config *config,
return ret ? -EIO : 0;
}
static int spi_stm32_transceive(const struct spi_config *config,
const struct spi_buf *tx_bufs, u32_t tx_count,
struct spi_buf *rx_bufs, u32_t rx_count)
static int spi_stm32_transceive(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs)
{
return transceive(config, tx_bufs, tx_count,
rx_bufs, rx_count, false, NULL);
return transceive(dev, config, tx_bufs, rx_bufs, false, NULL);
}
#ifdef CONFIG_POLL
static int spi_stm32_transceive_async(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count,
struct spi_buf *rx_bufs,
size_t rx_count,
static int spi_stm32_transceive_async(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs,
struct k_poll_signal *async)
{
return transceive(config, tx_bufs, tx_count,
rx_bufs, rx_count, true, async);
return transceive(dev, config, tx_bufs, rx_bufs, true, async);
}
#endif /* CONFIG_POLL */

View file

@ -46,9 +46,10 @@ static void wait_synchronization(SercomSpi *regs)
#endif
}
static int spi_sam0_configure(const struct spi_config *config)
static int spi_sam0_configure(struct device *dev,
const struct spi_config *config)
{
const struct spi_sam0_config *cfg = config->dev->config->config_info;
const struct spi_sam0_config *cfg = dev->config->config_info;
SercomSpi *regs = cfg->regs;
SERCOM_SPI_CTRLA_Type ctrla = {.reg = 0};
SERCOM_SPI_CTRLB_Type ctrlb = {.reg = 0};
@ -176,7 +177,7 @@ static void spi_sam0_fast_tx(SercomSpi *regs, const struct spi_buf *tx_buf)
}
/* Fast path that reads into a buf */
static void spi_sam0_fast_rx(SercomSpi *regs, struct spi_buf *rx_buf)
static void spi_sam0_fast_rx(SercomSpi *regs, const struct spi_buf *rx_buf)
{
u8_t *rx = rx_buf->buf;
int len = rx_buf->len;
@ -213,8 +214,9 @@ static void spi_sam0_fast_rx(SercomSpi *regs, struct spi_buf *rx_buf)
}
/* Fast path that writes and reads bufs of the same length */
static void spi_sam0_fast_txrx(SercomSpi *regs, const struct spi_buf *tx_buf,
struct spi_buf *rx_buf)
static void spi_sam0_fast_txrx(SercomSpi *regs,
const struct spi_buf *tx_buf,
const struct spi_buf *rx_buf)
{
const u8_t *tx = tx_buf->buf;
const u8_t *txend = tx_buf->buf + tx_buf->len;
@ -264,34 +266,51 @@ static void spi_sam0_fast_txrx(SercomSpi *regs, const struct spi_buf *tx_buf,
}
/* Fast path where every overlapping tx and rx buffer is the same length */
static void spi_sam0_fast_transceive(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count, struct spi_buf *rx_bufs,
size_t rx_count)
static void spi_sam0_fast_transceive(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs)
{
const struct spi_sam0_config *cfg = config->dev->config->config_info;
const struct spi_sam0_config *cfg = dev->config->config_info;
size_t tx_count = 0;
size_t rx_count = 0;
SercomSpi *regs = cfg->regs;
const struct spi_buf *tx;
const struct spi_buf *rx;
if (tx_bufs) {
tx = tx_bufs->buffers;
tx_count = tx_bufs->count;
}
if (rx_bufs) {
rx = rx_bufs->buffers;
rx_count = rx_bufs->count;
} else {
rx = NULL;
}
while (tx_count != 0 && rx_count != 0) {
if (tx_bufs->buf == NULL) {
spi_sam0_fast_rx(regs, rx_bufs);
} else if (rx_bufs->buf == NULL) {
spi_sam0_fast_tx(regs, tx_bufs);
if (tx->buf == NULL) {
spi_sam0_fast_rx(regs, rx);
} else if (rx->buf == NULL) {
spi_sam0_fast_tx(regs, tx);
} else {
spi_sam0_fast_txrx(regs, tx_bufs, rx_bufs);
spi_sam0_fast_txrx(regs, tx, rx);
}
tx_bufs++;
tx++;
tx_count--;
rx_bufs++;
rx++;
rx_count--;
}
for (; tx_count != 0; tx_count--) {
spi_sam0_fast_tx(regs, tx_bufs++);
spi_sam0_fast_tx(regs, tx++);
}
for (; rx_count != 0; rx_count--) {
spi_sam0_fast_rx(regs, rx_bufs++);
spi_sam0_fast_rx(regs, rx++);
}
}
@ -302,36 +321,55 @@ static void spi_sam0_fast_transceive(const struct spi_config *config,
* - Zero or more trailing RX only bufs
* - Zero or more trailing TX only bufs
*/
static bool spi_sam0_is_regular(const struct spi_buf *tx_bufs,
size_t tx_count, struct spi_buf *rx_bufs,
size_t rx_count)
static bool spi_sam0_is_regular(const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs)
{
const struct spi_buf *tx = NULL;
const struct spi_buf *rx = NULL;
size_t tx_count = 0;
size_t rx_count = 0;
if (tx_bufs) {
tx = tx_bufs->buffers;
tx_count = tx_bufs->count;
}
if (rx_bufs) {
rx = rx_bufs->buffers;
rx_count = rx_bufs->count;
}
if (!tx || !rx) {
return false;
}
while (tx_count != 0 && rx_count != 0) {
if (tx_bufs->len != rx_bufs->len) {
if (tx->len != rx->len) {
return false;
}
tx_bufs++;
tx++;
tx_count--;
rx_bufs++;
rx++;
rx_count--;
}
return true;
}
static int spi_sam0_transceive(const struct spi_config *config,
const struct spi_buf *tx_bufs, size_t tx_count,
struct spi_buf *rx_bufs, size_t rx_count)
static int spi_sam0_transceive(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs)
{
const struct spi_sam0_config *cfg = config->dev->config->config_info;
struct spi_sam0_data *data = config->dev->driver_data;
const struct spi_sam0_config *cfg = dev->config->config_info;
struct spi_sam0_data *data = dev->driver_data;
SercomSpi *regs = cfg->regs;
int err;
spi_context_lock(&data->ctx, false, NULL);
err = spi_sam0_configure(config);
err = spi_sam0_configure(dev, config);
if (err != 0) {
goto done;
}
@ -345,12 +383,10 @@ static int spi_sam0_transceive(const struct spi_config *config,
* casing is 4x faster than the spi_context() routines
* and allows the transmit and receive to be interleaved.
*/
if (spi_sam0_is_regular(tx_bufs, tx_count, rx_bufs, rx_count)) {
spi_sam0_fast_transceive(config, tx_bufs, tx_count, rx_bufs,
rx_count);
if (spi_sam0_is_regular(tx_bufs, rx_bufs)) {
spi_sam0_fast_transceive(dev, config, tx_bufs, rx_bufs);
} else {
spi_context_buffers_setup(&data->ctx, tx_bufs, tx_count,
rx_bufs, rx_count, 1);
spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1);
do {
spi_sam0_shift_master(regs, data);
@ -365,19 +401,20 @@ done:
}
#ifdef CONFIG_POLL
static int spi_sam0_transceive_async(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count, struct spi_buf *rx_bufs,
size_t rx_count,
static int spi_sam0_transceive_async(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs,
struct k_poll_signal *async)
{
return -ENOTSUP;
}
#endif
static int spi_sam0_release(const struct spi_config *config)
static int spi_sam0_release(struct device *dev,
const struct spi_config *config)
{
struct spi_sam0_data *data = config->dev->driver_data;
struct spi_sam0_data *data = dev->driver_data;
spi_context_unlock_unconditionally(&data->ctx);

View file

@ -164,8 +164,6 @@ struct spi_cs_control {
* transceive call.
*/
struct spi_config {
struct device *dev;
u32_t frequency;
u16_t operation;
u16_t slave;
@ -186,27 +184,36 @@ struct spi_buf {
size_t len;
};
/**
* @brief SPI buffer array structure
*
* @param buffers is a valid pointer on an array of spi_buf, or NULL.
* @param count is the length of the array pointed by buffers.
*/
struct spi_buf_set {
const struct spi_buf *buffers;
size_t count;
};
/**
* @typedef spi_api_io
* @brief Callback API for I/O
* See spi_transceive() for argument descriptions
*/
typedef int (*spi_api_io)(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count,
struct spi_buf *rx_bufs,
size_t rx_count);
typedef int (*spi_api_io)(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs);
/**
* @typedef spi_api_io
* @brief Callback API for asynchronous I/O
* See spi_transceive_async() for argument descriptions
*/
typedef int (*spi_api_io_async)(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count,
struct spi_buf *rx_bufs,
size_t rx_count,
typedef int (*spi_api_io_async)(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs,
struct k_poll_signal *async);
/**
@ -214,7 +221,8 @@ typedef int (*spi_api_io_async)(const struct spi_config *config,
* @brief Callback API for unlocking SPI device.
* See spi_release() for argument descriptions
*/
typedef int (*spi_api_release)(const struct spi_config *config);
typedef int (*spi_api_release)(struct device *dev,
const struct spi_config *config);
/**
@ -234,31 +242,28 @@ struct spi_driver_api {
*
* Note: This function is synchronous.
*
* @param dev Pointer to the device structure for the driver instance
* @param config Pointer to a valid spi_config structure instance.
* @param tx_bufs Buffer array where data to be sent originates from,
* or NULL if none.
* @param tx_count Number of element in the tx_bufs array.
* @param rx_bufs Buffer array where data to be read will be written to,
* or NULL if none.
* @param rx_count Number of element in the rx_bufs array.
*
* @retval 0 If successful, negative errno code otherwise.
*/
__syscall int spi_transceive(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count,
struct spi_buf *rx_bufs,
size_t rx_count);
__syscall int spi_transceive(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs);
static inline int _impl_spi_transceive(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count,
struct spi_buf *rx_bufs,
size_t rx_count)
static inline int _impl_spi_transceive(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs)
{
const struct spi_driver_api *api = config->dev->driver_api;
const struct spi_driver_api *api = dev->driver_api;
return api->transceive(config, tx_bufs, tx_count, rx_bufs, rx_count);
return api->transceive(dev, config, tx_bufs, rx_bufs);
}
/**
@ -266,17 +271,17 @@ static inline int _impl_spi_transceive(const struct spi_config *config,
*
* Note: This function is synchronous.
*
* @param dev Pointer to the device structure for the driver instance
* @param config Pointer to a valid spi_config structure instance.
* @param rx_bufs Buffer array where data to be read will be written to.
* @param rx_count Number of element in the rx_bufs array.
*
* @retval 0 If successful, negative errno code otherwise.
*/
static inline int spi_read(const struct spi_config *config,
struct spi_buf *rx_bufs,
size_t rx_count)
static inline int spi_read(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *rx_bufs)
{
return spi_transceive(config, NULL, 0, rx_bufs, rx_count);
return spi_transceive(dev, config, NULL, rx_bufs);
}
/**
@ -284,17 +289,17 @@ static inline int spi_read(const struct spi_config *config,
*
* Note: This function is synchronous.
*
* @param dev Pointer to the device structure for the driver instance
* @param config Pointer to a valid spi_config structure instance.
* @param tx_bufs Buffer array where data to be sent originates from.
* @param tx_count Number of element in the tx_bufs array.
*
* @retval 0 If successful, negative errno code otherwise.
*/
static inline int spi_write(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count)
static inline int spi_write(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs)
{
return spi_transceive(config, tx_bufs, tx_count, NULL, 0);
return spi_transceive(dev, config, tx_bufs, NULL);
}
#ifdef CONFIG_POLL
@ -303,13 +308,12 @@ static inline int spi_write(const struct spi_config *config,
*
* Note: This function is asynchronous.
*
* @param dev Pointer to the device structure for the driver instance
* @param config Pointer to a valid spi_config structure instance.
* @param tx_bufs Buffer array where data to be sent originates from,
* or NULL if none.
* @param tx_count Number of element in the tx_bufs array.
* @param rx_bufs Buffer array where data to be read will be written to,
* or NULL if none.
* @param rx_count Number of element in the rx_bufs array.
* @param async A pointer to a valid and ready to be signaled
* struct k_poll_signal. (Note: if NULL this function will not
* notify the end of the transaction, and whether it went
@ -317,17 +321,15 @@ static inline int spi_write(const struct spi_config *config,
*
* @retval 0 If successful, negative errno code otherwise.
*/
static inline int spi_transceive_async(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count,
struct spi_buf *rx_bufs,
size_t rx_count,
static inline int spi_transceive_async(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs,
struct k_poll_signal *async)
{
const struct spi_driver_api *api = config->dev->driver_api;
const struct spi_driver_api *api = dev->driver_api;
return api->transceive_async(config, tx_bufs, tx_count,
rx_bufs, rx_count, async);
return api->transceive_async(dev, config, tx_bufs, rx_bufs, async);
}
/**
@ -335,9 +337,9 @@ static inline int spi_transceive_async(const struct spi_config *config,
*
* Note: This function is asynchronous.
*
* @param dev Pointer to the device structure for the driver instance
* @param config Pointer to a valid spi_config structure instance.
* @param rx_bufs Buffer array where data to be read will be written to.
* @param rx_count Number of element in the rx_bufs array.
* @param async A pointer to a valid and ready to be signaled
* struct k_poll_signal. (Note: if NULL this function will not
* notify the end of the transaction, and whether it went
@ -345,15 +347,12 @@ static inline int spi_transceive_async(const struct spi_config *config,
*
* @retval 0 If successful, negative errno code otherwise.
*/
static inline int spi_read_async(const struct spi_config *config,
struct spi_buf *rx_bufs,
size_t rx_count,
static inline int spi_read_async(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *rx_bufs,
struct k_poll_signal *async)
{
const struct spi_driver_api *api = config->dev->driver_api;
return api->transceive_async(config, NULL, 0,
rx_bufs, rx_count, async);
return spi_transceive_async(dev, config, NULL, rx_bufs, async);
}
/**
@ -361,9 +360,9 @@ static inline int spi_read_async(const struct spi_config *config,
*
* Note: This function is asynchronous.
*
* @param dev Pointer to the device structure for the driver instance
* @param config Pointer to a valid spi_config structure instance.
* @param tx_bufs Buffer array where data to be sent originates from.
* @param tx_count Number of element in the tx_bufs array.
* @param async A pointer to a valid and ready to be signaled
* struct k_poll_signal. (Note: if NULL this function will not
* notify the end of the transaction, and whether it went
@ -371,15 +370,12 @@ static inline int spi_read_async(const struct spi_config *config,
*
* @retval 0 If successful, negative errno code otherwise.
*/
static inline int spi_write_async(const struct spi_config *config,
const struct spi_buf *tx_bufs,
size_t tx_count,
static inline int spi_write_async(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
struct k_poll_signal *async)
{
const struct spi_driver_api *api = config->dev->driver_api;
return api->transceive_async(config, tx_bufs, tx_count,
NULL, 0, async);
return spi_transceive_async(dev, config, tx_bufs, NULL, async);
}
#endif /* CONFIG_POLL */
@ -393,15 +389,18 @@ static inline int spi_write_async(const struct spi_config *config,
* This can be used if the caller needs to keep its hand on the SPI
* device for consecutive transactions.
*
* @param dev Pointer to the device structure for the driver instance
* @param config Pointer to a valid spi_config structure instance.
*/
__syscall int spi_release(const struct spi_config *config);
__syscall int spi_release(struct device *dev,
const struct spi_config *config);
static inline int _impl_spi_release(const struct spi_config *config)
static inline int _impl_spi_release(struct device *dev,
const struct spi_config *config)
{
const struct spi_driver_api *api = config->dev->driver_api;
const struct spi_driver_api *api = dev->driver_api;
return api->release(config);
return api->release(dev, config);
}
#ifdef __cplusplus

View file

@ -51,7 +51,7 @@ static void to_display_format(const u8_t *src, size_t size, char *dst)
}
}
struct spi_config spi_slow = {
struct spi_config spi_cfg_slow = {
.frequency = SLOW_FREQ,
.operation = SPI_OP_MODE_MASTER | SPI_MODE_CPOL |
SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE,
@ -59,7 +59,7 @@ struct spi_config spi_slow = {
.cs = SPI_CS,
};
struct spi_config spi_fast = {
struct spi_config spi_cfg_fast = {
.frequency = FAST_FREQ,
.operation = SPI_OP_MODE_MASTER | SPI_MODE_CPOL |
SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE,
@ -81,7 +81,7 @@ static int cs_ctrl_gpio_config(struct spi_cs_control *cs)
return 0;
}
static int spi_complete_loop(struct spi_config *spi_conf)
static int spi_complete_loop(struct device *dev, struct spi_config *spi_conf)
{
const struct spi_buf tx_bufs[] = {
{
@ -89,18 +89,26 @@ static int spi_complete_loop(struct spi_config *spi_conf)
.len = BUF_SIZE,
},
};
struct spi_buf rx_bufs[] = {
const struct spi_buf rx_bufs[] = {
{
.buf = buffer_rx,
.len = BUF_SIZE,
},
};
const struct spi_buf_set tx = {
.buffers = tx_bufs,
.count = ARRAY_SIZE(tx_bufs)
};
const struct spi_buf_set rx = {
.buffers = rx_bufs,
.count = ARRAY_SIZE(rx_bufs)
};
int ret;
SYS_LOG_INF("Start");
ret = spi_transceive(spi_conf, tx_bufs, ARRAY_SIZE(tx_bufs),
rx_bufs, ARRAY_SIZE(rx_bufs));
ret = spi_transceive(dev, spi_conf, &tx, &rx);
if (ret) {
SYS_LOG_ERR("Code %d", ret);
return ret;
@ -121,7 +129,7 @@ static int spi_complete_loop(struct spi_config *spi_conf)
return 0;
}
static int spi_rx_half_start(struct spi_config *spi_conf)
static int spi_rx_half_start(struct device *dev, struct spi_config *spi_conf)
{
const struct spi_buf tx_bufs[] = {
{
@ -129,20 +137,27 @@ static int spi_rx_half_start(struct spi_config *spi_conf)
.len = BUF_SIZE,
},
};
struct spi_buf rx_bufs[] = {
const struct spi_buf rx_bufs[] = {
{
.buf = buffer_rx,
.len = 8,
},
};
const struct spi_buf_set tx = {
.buffers = tx_bufs,
.count = ARRAY_SIZE(tx_bufs)
};
const struct spi_buf_set rx = {
.buffers = rx_bufs,
.count = ARRAY_SIZE(rx_bufs)
};
int ret;
SYS_LOG_INF("Start");
memset(buffer_rx, 0, BUF_SIZE);
ret = spi_transceive(spi_conf, tx_bufs, ARRAY_SIZE(tx_bufs),
rx_bufs, ARRAY_SIZE(rx_bufs));
ret = spi_transceive(dev, spi_conf, &tx, &rx);
if (ret) {
SYS_LOG_ERR("Code %d", ret);
return -1;
@ -163,7 +178,7 @@ static int spi_rx_half_start(struct spi_config *spi_conf)
return 0;
}
static int spi_rx_half_end(struct spi_config *spi_conf)
static int spi_rx_half_end(struct device *dev, struct spi_config *spi_conf)
{
const struct spi_buf tx_bufs[] = {
{
@ -171,7 +186,7 @@ static int spi_rx_half_end(struct spi_config *spi_conf)
.len = BUF_SIZE,
},
};
struct spi_buf rx_bufs[] = {
const struct spi_buf rx_bufs[] = {
{
.buf = NULL,
.len = 8,
@ -181,14 +196,21 @@ static int spi_rx_half_end(struct spi_config *spi_conf)
.len = 8,
},
};
const struct spi_buf_set tx = {
.buffers = tx_bufs,
.count = ARRAY_SIZE(tx_bufs)
};
const struct spi_buf_set rx = {
.buffers = rx_bufs,
.count = ARRAY_SIZE(rx_bufs)
};
int ret;
SYS_LOG_INF("Start");
memset(buffer_rx, 0, BUF_SIZE);
ret = spi_transceive(spi_conf, tx_bufs, ARRAY_SIZE(tx_bufs),
rx_bufs, ARRAY_SIZE(rx_bufs));
ret = spi_transceive(dev, spi_conf, &tx, &rx);
if (ret) {
SYS_LOG_ERR("Code %d", ret);
return -1;
@ -209,7 +231,7 @@ static int spi_rx_half_end(struct spi_config *spi_conf)
return 0;
}
static int spi_rx_every_4(struct spi_config *spi_conf)
static int spi_rx_every_4(struct device *dev, struct spi_config *spi_conf)
{
const struct spi_buf tx_bufs[] = {
{
@ -217,7 +239,7 @@ static int spi_rx_every_4(struct spi_config *spi_conf)
.len = BUF_SIZE,
},
};
struct spi_buf rx_bufs[] = {
const struct spi_buf rx_bufs[] = {
{
.buf = NULL,
.len = 4,
@ -235,14 +257,21 @@ static int spi_rx_every_4(struct spi_config *spi_conf)
.len = 4,
},
};
const struct spi_buf_set tx = {
.buffers = tx_bufs,
.count = ARRAY_SIZE(tx_bufs)
};
const struct spi_buf_set rx = {
.buffers = rx_bufs,
.count = ARRAY_SIZE(rx_bufs)
};
int ret;
SYS_LOG_INF("Start");
memset(buffer_rx, 0, BUF_SIZE);
ret = spi_transceive(spi_conf, tx_bufs, ARRAY_SIZE(tx_bufs),
rx_bufs, ARRAY_SIZE(rx_bufs));
ret = spi_transceive(dev, spi_conf, &tx, &rx);
if (ret) {
SYS_LOG_ERR("Code %d", ret);
return -1;
@ -298,7 +327,7 @@ static void spi_async_call_cb(struct k_poll_event *async_evt,
}
}
static int spi_async_call(struct spi_config *spi_conf)
static int spi_async_call(struct device *dev, struct spi_config *spi_conf)
{
const struct spi_buf tx_bufs[] = {
{
@ -306,18 +335,25 @@ static int spi_async_call(struct spi_config *spi_conf)
.len = BUF_SIZE,
},
};
struct spi_buf rx_bufs[] = {
const struct spi_buf rx_bufs[] = {
{
.buf = buffer_rx,
.len = BUF_SIZE,
},
};
const struct spi_buf_set tx = {
.buffers = tx_bufs,
.count = ARRAY_SIZE(tx_bufs)
};
const struct spi_buf_set rx = {
.buffers = rx_bufs,
.count = ARRAY_SIZE(rx_bufs)
};
int ret;
SYS_LOG_INF("Start");
ret = spi_transceive_async(spi_conf, tx_bufs, ARRAY_SIZE(tx_bufs),
rx_bufs, ARRAY_SIZE(rx_bufs), &async_sig);
ret = spi_transceive_async(dev, spi_conf, &tx, &rx, &async_sig);
if (ret == -ENOTSUP) {
SYS_LOG_DBG("Not supported");
return 0;
@ -340,21 +376,23 @@ static int spi_async_call(struct spi_config *spi_conf)
return 0;
}
static int spi_resource_lock_test(struct spi_config *spi_conf_lock,
struct spi_config *spi_conf_try)
static int spi_resource_lock_test(struct device *lock_dev,
struct spi_config *spi_conf_lock,
struct device *try_dev,
struct spi_config *spi_conf_try)
{
spi_conf_lock->operation |= SPI_LOCK_ON;
if (spi_complete_loop(spi_conf_lock)) {
if (spi_complete_loop(lock_dev, spi_conf_lock)) {
return -1;
}
if (spi_release(spi_conf_lock)) {
if (spi_release(lock_dev, spi_conf_lock)) {
SYS_LOG_ERR("Deadlock now?");
return -1;
}
if (spi_complete_loop(spi_conf_try)) {
if (spi_complete_loop(try_dev, spi_conf_try)) {
return -1;
}
@ -365,44 +403,47 @@ void main(void)
{
struct k_thread async_thread;
k_tid_t async_thread_id;
struct device *spi_slow;
struct device *spi_fast;
SYS_LOG_INF("SPI test on buffers TX/RX %p/%p", buffer_tx, buffer_rx);
if (cs_ctrl_gpio_config(spi_slow.cs) ||
cs_ctrl_gpio_config(spi_fast.cs)) {
if (cs_ctrl_gpio_config(spi_cfg_slow.cs) ||
cs_ctrl_gpio_config(spi_cfg_fast.cs)) {
return;
}
spi_slow.dev = device_get_binding(SPI_DRV_NAME);
if (!spi_slow.dev) {
spi_slow = device_get_binding(SPI_DRV_NAME);
if (!spi_slow) {
SYS_LOG_ERR("Cannot find %s!\n", SPI_DRV_NAME);
return;
}
spi_fast.dev = spi_slow.dev;
spi_fast = spi_slow;
async_thread_id = k_thread_create(&async_thread, spi_async_stack, 256,
(k_thread_entry_t)spi_async_call_cb,
&async_evt, &caller, NULL,
K_PRIO_COOP(7), 0, 0);
if (spi_complete_loop(&spi_slow) ||
spi_rx_half_start(&spi_slow) ||
spi_rx_half_end(&spi_slow) ||
spi_rx_every_4(&spi_slow) ||
spi_async_call(&spi_slow)) {
if (spi_complete_loop(spi_slow, &spi_cfg_slow) ||
spi_rx_half_start(spi_slow, &spi_cfg_slow) ||
spi_rx_half_end(spi_slow, &spi_cfg_slow) ||
spi_rx_every_4(spi_slow, &spi_cfg_slow) ||
spi_async_call(spi_slow, &spi_cfg_slow)) {
goto end;
}
if (spi_complete_loop(&spi_fast) ||
spi_rx_half_start(&spi_fast) ||
spi_rx_half_end(&spi_fast) ||
spi_rx_every_4(&spi_fast) ||
spi_async_call(&spi_fast)) {
if (spi_complete_loop(spi_fast, &spi_cfg_fast) ||
spi_rx_half_start(spi_fast, &spi_cfg_fast) ||
spi_rx_half_end(spi_fast, &spi_cfg_fast) ||
spi_rx_every_4(spi_fast, &spi_cfg_fast) ||
spi_async_call(spi_fast, &spi_cfg_fast)) {
goto end;
}
if (spi_resource_lock_test(&spi_slow, &spi_fast)) {
if (spi_resource_lock_test(spi_slow, &spi_cfg_slow,
spi_fast, &spi_cfg_fast)) {
goto end;
}