diff --git a/src/linux/gpio.h b/src/linux/gpio.h index 8d878597..ff8e0cc2 100644 --- a/src/linux/gpio.h +++ b/src/linux/gpio.h @@ -21,6 +21,7 @@ void gpio_adc_cancel_sample(struct gpio_adc g); struct spi_config { int fd; + int rate; }; struct spi_config spi_setup(uint32_t bus, uint8_t mode, uint32_t rate); void spi_prepare(struct spi_config config); diff --git a/src/linux/spidev.c b/src/linux/spidev.c index 2d6f55ac..d14bb645 100644 --- a/src/linux/spidev.c +++ b/src/linux/spidev.c @@ -5,7 +5,10 @@ // This file may be distributed under the terms of the GNU GPLv3 license. #include // open +#include // SPI_IOC_MESSAGE #include // snprintf +#include // memset +#include // ioctl #include // write #include "command.h" // DECL_COMMAND #include "gpio.h" // spi_setup @@ -53,7 +56,12 @@ spi_setup(uint32_t bus, uint8_t mode, uint32_t rate) { int bus_id = (bus >> 8) & 0xff, dev_id = bus & 0xff; int fd = spi_open(bus_id, dev_id); - return (struct spi_config) { fd }; + int ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &rate); + if (ret < 0) { + report_errno("ioctl set max spi speed", ret); + shutdown("Unable to set SPI speed"); + } + return (struct spi_config) { fd , rate}; } void @@ -65,10 +73,29 @@ void spi_transfer(struct spi_config config, uint8_t receive_data , uint8_t len, uint8_t *data) { - int ret = write(config.fd, data, len); - if (ret < 0) { - report_errno("write spi", ret); - shutdown("Unable to write to spi"); + if (!len) + return; + + if (receive_data) { + struct spi_ioc_transfer transfer; + memset(&transfer, 0, sizeof(transfer)); + transfer.tx_buf = (uintptr_t)data; + transfer.rx_buf = (uintptr_t)data; + transfer.len = len; + transfer.speed_hz = config.rate; + transfer.bits_per_word = 8; + transfer.cs_change = 0; + int ret = ioctl(config.fd, SPI_IOC_MESSAGE(1), &transfer); + if (ret < 0) { + report_errno("spi ioctl", ret); + shutdown("Unable to issue spi ioctl"); + } + } else { + int ret = write(config.fd, data, len); + if (ret < 0) { + report_errno("write spi", ret); + shutdown("Unable to write to spi"); + } } }