/*
* Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
- * Copyright (c) 2014 Intel Corporation.
+ * Author: Brendan Le Foll <brendan.le.foll@intel.com>
+ * Copyright (c) 2014, 2015 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
#define MAX_SIZE 64
#define SPI_MAX_LENGTH 4096
-/**
- * A structure representing the SPI device
- */
-struct _spi {
- /*@{*/
- int devfd; /**< File descriptor to SPI Device */
- int 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 */
- /*@}*/
-};
+static mraa_spi_context
+mraa_spi_init_internal(mraa_adv_func_t* func_table)
+{
+ mraa_spi_context dev = (mraa_spi_context) calloc(1, sizeof(struct _spi));
+ if (dev == NULL) {
+ return NULL;
+ }
+ dev->advance_func = func_table;
+
+ return dev;
+}
mraa_spi_context
mraa_spi_init(int bus)
syslog(LOG_ERR, "spi: Platform Not Initialised");
return NULL;
}
+ if (mraa_is_sub_platform_id(bus)) {
+ syslog(LOG_ERR, "spi: Spi module doesn't support subplatforms");
+ return NULL;
+ }
if (plat->spi_bus_count == 0) {
syslog(LOG_ERR, "spi: no spi buses defined in platform");
return NULL;
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)
+ if (plat->adv_func->spi_init_pre != NULL) {
+ if (plat->adv_func->spi_init_pre(bus) != MRAA_SUCCESS) {
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;
+ if (!plat->no_bus_mux) {
+ 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].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].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;
+ 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 (plat->adv_func->spi_init_post != NULL) {
+ mraa_result_t ret = plat->adv_func->spi_init_post(dev);
if (ret != MRAA_SUCCESS) {
free(dev);
return NULL;
mraa_spi_context
mraa_spi_init_raw(unsigned int bus, unsigned int cs)
{
- mraa_spi_context dev = (mraa_spi_context) malloc(sizeof(struct _spi));
+ mraa_spi_context dev = mraa_spi_init_internal(plat == NULL ? NULL : plat->adv_func);
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", bus, cs);
int speed = 0;
if ((ioctl(dev->devfd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) != -1) && (speed < 4000000)) {
dev->clock = speed;
- }
- else {
+ } 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) {
+ 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_lsbmode(mraa_spi_context dev, mraa_boolean_t lsb)
{
+ if (IS_FUNC_DEFINED(dev, spi_lsbmode_replace)) {
+ return dev->advance_func->spi_lsbmode_replace(dev, lsb);
+ }
+
uint8_t lsb_mode = (uint8_t) lsb;
- if (ioctl (dev->devfd, SPI_IOC_WR_LSB_FIRST, &lsb_mode) < 0) {
+ 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_RD_LSB_FIRST, &lsb_mode) < 0) {
+ 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;
}
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;
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) 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;
+}
+
uint8_t*
mraa_spi_write_buf(mraa_spi_context dev, uint8_t* data, int length)
{
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;
+}
+
mraa_result_t
mraa_spi_stop(mraa_spi_context dev)
{