*/
struct _spi {
/*@{*/
- int devfd; /**< File descriptor to SPI Device */
- int mode; /**< Spi mode see spidev.h */
- int clock; /**< clock to run transactions at */
+ int devfd; /**< File descriptor to SPI Device */
+ uint32_t mode; /**< Spi mode see spidev.h */
+ int clock; /**< clock to run transactions at */
mraa_boolean_t lsb; /**< least significant bit mode */
- unsigned int bpw; /**< Bits per word */
+ unsigned int bpw; /**< Bits per word */
/*@}*/
};
mraa_spi_context
mraa_spi_init(int bus)
{
+ if (plat == NULL) {
+ syslog(LOG_ERR, "spi: Platform Not Initialised");
+ return NULL;
+ }
+ if (plat->spi_bus_count == 0) {
+ syslog(LOG_ERR, "spi: no spi buses defined in platform");
+ return NULL;
+ }
+ if (plat->spi_bus_count == 1) {
+ bus = plat->def_spi_bus;
+ }
+ if (bus >= plat->spi_bus_count) {
+ syslog(LOG_ERR, "spi: requested bus above spi bus count");
+ return NULL;
+ }
if (advance_func->spi_init_pre != NULL) {
if (advance_func->spi_init_pre(bus) != MRAA_SUCCESS)
return NULL;
}
- mraa_spi_bus_t *spi = mraa_setup_spi(bus);
- if(bus < 0) {
- fprintf(stderr, "Failed. SPI platform Error\n");
- return NULL;
+ int pos = plat->spi_bus[bus].sclk;
+ if (plat->pins[pos].spi.mux_total > 0) {
+ if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
+ syslog(LOG_ERR, "spi: failed to set-up spi sclk multiplexer");
+ return NULL;
+ }
}
+
+ pos = plat->spi_bus[bus].mosi;
+ if (plat->pins[pos].spi.mux_total > 0) {
+ if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
+ syslog(LOG_ERR, "spi: failed to set-up spi mosi multiplexer");
+ return NULL;
+ }
+ }
+
+ pos = plat->spi_bus[bus].miso;
+ if (plat->pins[pos].spi.mux_total > 0) {
+ if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
+ syslog(LOG_ERR, "spi: failed to set-up spi miso multiplexer");
+ return NULL;
+ }
+ }
+
+ pos = plat->spi_bus[bus].cs;
+ if (plat->pins[pos].spi.mux_total > 0) {
+ if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
+ syslog(LOG_ERR, "spi: failed to set-up spi cs multiplexer");
+ return NULL;
+ }
+ }
+ mraa_spi_context dev = mraa_spi_init_raw(plat->spi_bus[bus].bus_id, plat->spi_bus[bus].slave_s);
+
+ if (advance_func->spi_init_post != NULL) {
+ mraa_result_t ret = advance_func->spi_init_post(dev);
+ if (ret != MRAA_SUCCESS) {
+ free(dev);
+ return NULL;
+ }
+ }
+
+ return dev;
+}
+
+mraa_spi_context
+mraa_spi_init_raw(unsigned int bus, unsigned int cs)
+{
mraa_spi_context dev = (mraa_spi_context) malloc(sizeof(struct _spi));
+ if (dev == NULL) {
+ syslog(LOG_CRIT, "spi: Failed to allocate memory for context");
+ return NULL;
+ }
memset(dev, 0, sizeof(struct _spi));
char path[MAX_SIZE];
- sprintf(path, "/dev/spidev%u.%u", spi->bus_id, spi->slave_s);
+ sprintf(path, "/dev/spidev%u.%u", bus, cs);
dev->devfd = open(path, O_RDWR);
if (dev->devfd < 0) {
- fprintf(stderr, "Failed opening SPI Device. bus:%s\n", path);
+ syslog(LOG_ERR, "spi: Failed opening SPI Device. bus:%s", path);
free(dev);
return NULL;
}
- dev->bpw = 8;
- dev->clock = 4000000;
- dev->lsb = 0;
- dev->mode = 0;
- if (advance_func->spi_init_post != NULL) {
- mraa_result_t ret = advance_func->spi_init_post(dev);
- if (ret != MRAA_SUCCESS) {
- free(dev);
- return NULL;
- }
+ int speed = 0;
+ if ((ioctl(dev->devfd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) != -1) && (speed < 4000000)) {
+ dev->clock = speed;
+ } else {
+ dev->clock = 4000000;
+ }
+
+ if (mraa_spi_mode(dev, MRAA_SPI_MODE0) != MRAA_SUCCESS) {
+ free(dev);
+ return NULL;
+ }
+
+ if (mraa_spi_lsbmode(dev, 0) != MRAA_SUCCESS) {
+ free(dev);
+ return NULL;
+ }
+
+ if (mraa_spi_bit_per_word(dev, 8) != MRAA_SUCCESS) {
+ free(dev);
+ return NULL;
}
return dev;
break;
}
- if (ioctl (dev->devfd, SPI_IOC_WR_MODE, &spi_mode) < 0) {
- fprintf(stderr, "Failed to set spi mode\n");
+ if (ioctl(dev->devfd, SPI_IOC_WR_MODE, &spi_mode) < 0) {
+ syslog(LOG_ERR, "spi: Failed to set spi mode");
return MRAA_ERROR_INVALID_RESOURCE;
}
mraa_result_t
mraa_spi_frequency(mraa_spi_context dev, int hz)
{
+ int speed = 0;
dev->clock = hz;
+ if (ioctl(dev->devfd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) != -1) {
+ if (speed < hz) {
+ dev->clock = speed;
+ syslog(LOG_WARNING, "spi: Selected speed reduced to max allowed speed");
+ }
+ }
return MRAA_SUCCESS;
}
mraa_result_t
mraa_spi_lsbmode(mraa_spi_context dev, mraa_boolean_t lsb)
{
- uint8_t lsb_mode = 0;
- if (lsb == 1) {
- lsb_mode = 1;
+ uint8_t lsb_mode = (uint8_t) lsb;
+ if (ioctl(dev->devfd, SPI_IOC_WR_LSB_FIRST, &lsb_mode) < 0) {
+ syslog(LOG_ERR, "spi: Failed to set bit order");
+ return MRAA_ERROR_INVALID_RESOURCE;
}
- if (ioctl (dev->devfd, SPI_IOC_WR_LSB_FIRST, &lsb_mode) < 0) {
- fprintf(stderr, "Failed to set bit order\n");
+ if (ioctl(dev->devfd, SPI_IOC_RD_LSB_FIRST, &lsb_mode) < 0) {
+ syslog(LOG_ERR, "spi: Failed to set bit order");
return MRAA_ERROR_INVALID_RESOURCE;
}
dev->lsb = lsb;
mraa_result_t
mraa_spi_bit_per_word(mraa_spi_context dev, unsigned int bits)
{
+ if (ioctl(dev->devfd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0) {
+ syslog(LOG_ERR, "spi: Failed to set bit per word");
+ return MRAA_ERROR_INVALID_RESOURCE;
+ }
dev->bpw = bits;
return MRAA_SUCCESS;
}
-uint8_t
+int
mraa_spi_write(mraa_spi_context dev, uint8_t data)
{
struct spi_ioc_transfer msg;
uint16_t length = 1;
- uint8_t recv = 0;
+ unsigned long recv = 0;
+ msg.tx_buf = (unsigned long) &data;
+ msg.rx_buf = (unsigned long) &recv;
+ msg.speed_hz = dev->clock;
+ msg.bits_per_word = dev->bpw;
+ msg.delay_usecs = 0;
+ msg.len = length;
+ if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
+ syslog(LOG_ERR, "spi: Failed to perform dev transfer");
+ return -1;
+ }
+ return (int) recv;
+}
+
+uint16_t
+mraa_spi_write_word(mraa_spi_context dev, uint16_t data)
+{
+ struct spi_ioc_transfer msg;
+ memset(&msg, 0, sizeof(msg));
+
+ uint16_t length = 2;
+
+ uint16_t recv = 0;
msg.tx_buf = (unsigned long) &data;
msg.rx_buf = (unsigned long) &recv;
msg.speed_hz = dev->clock;
msg.delay_usecs = 0;
msg.len = length;
if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
- fprintf(stderr, "Failed to perform dev transfer\n");
+ syslog(LOG_ERR, "spi: Failed to perform dev transfer");
return -1;
}
return recv;
}
-uint8_t*
-mraa_spi_write_buf(mraa_spi_context dev, uint8_t* data, int length)
+mraa_result_t
+mraa_spi_transfer_buf(mraa_spi_context dev, uint8_t* data, uint8_t* rxbuf, int length)
{
struct spi_ioc_transfer msg;
memset(&msg, 0, sizeof(msg));
- uint8_t* recv = malloc(sizeof(uint8_t) * length);
+ msg.tx_buf = (unsigned long) data;
+ msg.rx_buf = (unsigned long) rxbuf;
+ msg.speed_hz = dev->clock;
+ msg.bits_per_word = dev->bpw;
+ msg.delay_usecs = 0;
+ msg.len = length;
+ if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
+ syslog(LOG_ERR, "spi: Failed to perform dev transfer");
+ return MRAA_ERROR_INVALID_RESOURCE;
+ }
+ return MRAA_SUCCESS;
+}
+
+mraa_result_t
+mraa_spi_transfer_buf_word(mraa_spi_context dev, uint16_t* data, uint16_t* rxbuf, int length)
+{
+ struct spi_ioc_transfer msg;
+ memset(&msg, 0, sizeof(msg));
msg.tx_buf = (unsigned long) data;
- msg.rx_buf = (unsigned long) recv;
+ msg.rx_buf = (unsigned long) rxbuf;
msg.speed_hz = dev->clock;
msg.bits_per_word = dev->bpw;
msg.delay_usecs = 0;
msg.len = length;
if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
- fprintf(stderr, "Failed to perform dev transfer\n");
+ syslog(LOG_ERR, "spi: Failed to perform dev transfer");
+ return MRAA_ERROR_INVALID_RESOURCE;
+ }
+ return MRAA_SUCCESS;
+}
+
+uint8_t*
+mraa_spi_write_buf(mraa_spi_context dev, uint8_t* data, int length)
+{
+ uint8_t* recv = malloc(sizeof(uint8_t) * length);
+
+ if (mraa_spi_transfer_buf(dev, data, recv, length) != MRAA_SUCCESS) {
+ free(recv);
+ return NULL;
+ }
+ return recv;
+}
+
+uint16_t*
+mraa_spi_write_buf_word(mraa_spi_context dev, uint16_t* data, int length)
+{
+ uint16_t* recv = malloc(sizeof(uint16_t) * length);
+
+ if (mraa_spi_transfer_buf_word(dev, data, recv, length) != MRAA_SUCCESS) {
+ free(recv);
return NULL;
}
return recv;