2 * Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
3 * Author: Brendan Le Foll <brendan.le.foll@intel.com>
4 * Copyright (c) 2014, 2015 Intel Corporation.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include <sys/ioctl.h>
29 #include <linux/spi/spidev.h>
35 #include "mraa_internal.h"
38 #define SPI_MAX_LENGTH 4096
40 static mraa_spi_context
41 mraa_spi_init_internal(mraa_adv_func_t* func_table)
43 mraa_spi_context dev = (mraa_spi_context) calloc(1, sizeof(struct _spi));
47 dev->advance_func = func_table;
53 mraa_spi_init(int bus)
56 syslog(LOG_ERR, "spi: Platform Not Initialised");
59 if (mraa_is_sub_platform_id(bus)) {
60 syslog(LOG_ERR, "spi: Spi module doesn't support subplatforms");
63 if (plat->spi_bus_count == 0) {
64 syslog(LOG_ERR, "spi: no spi buses defined in platform");
67 if (plat->spi_bus_count == 1) {
68 bus = plat->def_spi_bus;
70 if (bus >= plat->spi_bus_count) {
71 syslog(LOG_ERR, "spi: requested bus above spi bus count");
74 if (plat->adv_func->spi_init_pre != NULL) {
75 if (plat->adv_func->spi_init_pre(bus) != MRAA_SUCCESS) {
80 int pos = plat->spi_bus[bus].sclk;
81 if (plat->pins[pos].spi.mux_total > 0) {
82 if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
83 syslog(LOG_ERR, "spi: failed to set-up spi sclk multiplexer");
88 pos = plat->spi_bus[bus].mosi;
89 if (plat->pins[pos].spi.mux_total > 0) {
90 if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
91 syslog(LOG_ERR, "spi: failed to set-up spi mosi multiplexer");
96 pos = plat->spi_bus[bus].miso;
97 if (plat->pins[pos].spi.mux_total > 0) {
98 if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
99 syslog(LOG_ERR, "spi: failed to set-up spi miso multiplexer");
104 pos = plat->spi_bus[bus].cs;
105 if (plat->pins[pos].spi.mux_total > 0) {
106 if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
107 syslog(LOG_ERR, "spi: failed to set-up spi cs multiplexer");
111 mraa_spi_context dev = mraa_spi_init_raw(plat->spi_bus[bus].bus_id, plat->spi_bus[bus].slave_s);
113 if (plat->adv_func->spi_init_post != NULL) {
114 mraa_result_t ret = plat->adv_func->spi_init_post(dev);
115 if (ret != MRAA_SUCCESS) {
125 mraa_spi_init_raw(unsigned int bus, unsigned int cs)
127 mraa_spi_context dev = mraa_spi_init_internal(plat == NULL ? NULL : plat->adv_func);
129 syslog(LOG_CRIT, "spi: Failed to allocate memory for context");
134 sprintf(path, "/dev/spidev%u.%u", bus, cs);
136 dev->devfd = open(path, O_RDWR);
137 if (dev->devfd < 0) {
138 syslog(LOG_ERR, "spi: Failed opening SPI Device. bus:%s", path);
144 if ((ioctl(dev->devfd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) != -1) && (speed < 4000000)) {
147 dev->clock = 4000000;
150 if (mraa_spi_mode(dev, MRAA_SPI_MODE0) != MRAA_SUCCESS) {
155 if (mraa_spi_lsbmode(dev, 0) != MRAA_SUCCESS) {
160 if (mraa_spi_bit_per_word(dev, 8) != MRAA_SUCCESS) {
169 mraa_spi_mode(mraa_spi_context dev, mraa_spi_mode_t mode)
171 uint8_t spi_mode = 0;
174 spi_mode = SPI_MODE_0;
177 spi_mode = SPI_MODE_1;
180 spi_mode = SPI_MODE_2;
183 spi_mode = SPI_MODE_3;
186 spi_mode = SPI_MODE_0;
190 if (ioctl(dev->devfd, SPI_IOC_WR_MODE, &spi_mode) < 0) {
191 syslog(LOG_ERR, "spi: Failed to set spi mode");
192 return MRAA_ERROR_INVALID_RESOURCE;
195 dev->mode = spi_mode;
200 mraa_spi_frequency(mraa_spi_context dev, int hz)
204 if (ioctl(dev->devfd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) != -1) {
207 syslog(LOG_WARNING, "spi: Selected speed reduced to max allowed speed");
214 mraa_spi_lsbmode(mraa_spi_context dev, mraa_boolean_t lsb)
216 if (IS_FUNC_DEFINED(dev, spi_lsbmode_replace)) {
217 return dev->advance_func->spi_lsbmode_replace(dev, lsb);
220 uint8_t lsb_mode = (uint8_t) lsb;
221 if (ioctl(dev->devfd, SPI_IOC_WR_LSB_FIRST, &lsb_mode) < 0) {
222 syslog(LOG_ERR, "spi: Failed to set bit order");
223 return MRAA_ERROR_INVALID_RESOURCE;
225 if (ioctl(dev->devfd, SPI_IOC_RD_LSB_FIRST, &lsb_mode) < 0) {
226 syslog(LOG_ERR, "spi: Failed to set bit order");
227 return MRAA_ERROR_INVALID_RESOURCE;
234 mraa_spi_bit_per_word(mraa_spi_context dev, unsigned int bits)
236 if (ioctl(dev->devfd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0) {
237 syslog(LOG_ERR, "spi: Failed to set bit per word");
238 return MRAA_ERROR_INVALID_RESOURCE;
245 mraa_spi_write(mraa_spi_context dev, uint8_t data)
247 struct spi_ioc_transfer msg;
248 memset(&msg, 0, sizeof(msg));
252 unsigned long recv = 0;
253 msg.tx_buf = (unsigned long) &data;
254 msg.rx_buf = (unsigned long) &recv;
255 msg.speed_hz = dev->clock;
256 msg.bits_per_word = dev->bpw;
259 if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
260 syslog(LOG_ERR, "spi: Failed to perform dev transfer");
267 mraa_spi_write_word(mraa_spi_context dev, uint16_t data)
269 struct spi_ioc_transfer msg;
270 memset(&msg, 0, sizeof(msg));
275 msg.tx_buf = (unsigned long) &data;
276 msg.rx_buf = (unsigned long) &recv;
277 msg.speed_hz = dev->clock;
278 msg.bits_per_word = dev->bpw;
281 if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
282 syslog(LOG_ERR, "spi: Failed to perform dev transfer");
289 mraa_spi_transfer_buf(mraa_spi_context dev, uint8_t* data, uint8_t* rxbuf, int length)
291 struct spi_ioc_transfer msg;
292 memset(&msg, 0, sizeof(msg));
294 msg.tx_buf = (unsigned long) data;
295 msg.rx_buf = (unsigned long) rxbuf;
296 msg.speed_hz = dev->clock;
297 msg.bits_per_word = dev->bpw;
300 if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
301 syslog(LOG_ERR, "spi: Failed to perform dev transfer");
302 return MRAA_ERROR_INVALID_RESOURCE;
308 mraa_spi_transfer_buf_word(mraa_spi_context dev, uint16_t* data, uint16_t* rxbuf, int length)
310 struct spi_ioc_transfer msg;
311 memset(&msg, 0, sizeof(msg));
313 msg.tx_buf = (unsigned long) data;
314 msg.rx_buf = (unsigned long) rxbuf;
315 msg.speed_hz = dev->clock;
316 msg.bits_per_word = dev->bpw;
319 if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
320 syslog(LOG_ERR, "spi: Failed to perform dev transfer");
321 return MRAA_ERROR_INVALID_RESOURCE;
327 mraa_spi_write_buf(mraa_spi_context dev, uint8_t* data, int length)
329 uint8_t* recv = malloc(sizeof(uint8_t) * length);
331 if (mraa_spi_transfer_buf(dev, data, recv, length) != MRAA_SUCCESS) {
339 mraa_spi_write_buf_word(mraa_spi_context dev, uint16_t* data, int length)
341 uint16_t* recv = malloc(sizeof(uint16_t) * length);
343 if (mraa_spi_transfer_buf_word(dev, data, recv, length) != MRAA_SUCCESS) {
351 mraa_spi_stop(mraa_spi_context dev)