2 * Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
3 * Copyright (c) 2014 Intel Corporation.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include <sys/ioctl.h>
28 #include <linux/spi/spidev.h>
34 #include "mraa_internal.h"
37 #define SPI_MAX_LENGTH 4096
40 * A structure representing the SPI device
44 int devfd; /**< File descriptor to SPI Device */
45 uint32_t mode; /**< Spi mode see spidev.h */
46 int clock; /**< clock to run transactions at */
47 mraa_boolean_t lsb; /**< least significant bit mode */
48 unsigned int bpw; /**< Bits per word */
53 mraa_spi_init(int bus)
56 syslog(LOG_ERR, "spi: Platform Not Initialised");
59 if (plat->spi_bus_count == 0) {
60 syslog(LOG_ERR, "spi: no spi buses defined in platform");
63 if (plat->spi_bus_count == 1) {
64 bus = plat->def_spi_bus;
66 if (bus >= plat->spi_bus_count) {
67 syslog(LOG_ERR, "spi: requested bus above spi bus count");
70 if (advance_func->spi_init_pre != NULL) {
71 if (advance_func->spi_init_pre(bus) != MRAA_SUCCESS)
75 int pos = plat->spi_bus[bus].sclk;
76 if (plat->pins[pos].spi.mux_total > 0) {
77 if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
78 syslog(LOG_ERR, "spi: failed to set-up spi sclk multiplexer");
83 pos = plat->spi_bus[bus].mosi;
84 if (plat->pins[pos].spi.mux_total > 0) {
85 if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
86 syslog(LOG_ERR, "spi: failed to set-up spi mosi multiplexer");
91 pos = plat->spi_bus[bus].miso;
92 if (plat->pins[pos].spi.mux_total > 0) {
93 if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
94 syslog(LOG_ERR, "spi: failed to set-up spi miso multiplexer");
99 pos = plat->spi_bus[bus].cs;
100 if (plat->pins[pos].spi.mux_total > 0) {
101 if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS) {
102 syslog(LOG_ERR, "spi: failed to set-up spi cs multiplexer");
106 mraa_spi_context dev = mraa_spi_init_raw(plat->spi_bus[bus].bus_id, plat->spi_bus[bus].slave_s);
108 if (advance_func->spi_init_post != NULL) {
109 mraa_result_t ret = advance_func->spi_init_post(dev);
110 if (ret != MRAA_SUCCESS) {
120 mraa_spi_init_raw(unsigned int bus, unsigned int cs)
122 mraa_spi_context dev = (mraa_spi_context) malloc(sizeof(struct _spi));
124 syslog(LOG_CRIT, "spi: Failed to allocate memory for context");
127 memset(dev, 0, sizeof(struct _spi));
130 sprintf(path, "/dev/spidev%u.%u", bus, cs);
132 dev->devfd = open(path, O_RDWR);
133 if (dev->devfd < 0) {
134 syslog(LOG_ERR, "spi: Failed opening SPI Device. bus:%s", path);
140 if ((ioctl(dev->devfd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) != -1) && (speed < 4000000)) {
144 dev->clock = 4000000;
147 if (mraa_spi_mode(dev, MRAA_SPI_MODE0) != MRAA_SUCCESS) {
152 if (mraa_spi_lsbmode(dev, 0) != MRAA_SUCCESS) {
157 if (mraa_spi_bit_per_word(dev, 8) != MRAA_SUCCESS) {
166 mraa_spi_mode(mraa_spi_context dev, mraa_spi_mode_t mode)
168 uint8_t spi_mode = 0;
171 spi_mode = SPI_MODE_0;
174 spi_mode = SPI_MODE_1;
177 spi_mode = SPI_MODE_2;
180 spi_mode = SPI_MODE_3;
183 spi_mode = SPI_MODE_0;
187 if (ioctl (dev->devfd, SPI_IOC_WR_MODE, &spi_mode) < 0) {
188 syslog(LOG_ERR, "spi: Failed to set spi mode");
189 return MRAA_ERROR_INVALID_RESOURCE;
192 dev->mode = spi_mode;
197 mraa_spi_frequency(mraa_spi_context dev, int hz)
201 if (ioctl(dev->devfd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) != -1) {
204 syslog(LOG_WARNING, "spi: Selected speed reduced to max allowed speed");
211 mraa_spi_lsbmode(mraa_spi_context dev, mraa_boolean_t lsb)
213 uint8_t lsb_mode = (uint8_t) lsb;
214 if (ioctl (dev->devfd, SPI_IOC_WR_LSB_FIRST, &lsb_mode) < 0) {
215 syslog(LOG_ERR, "spi: Failed to set bit order");
216 return MRAA_ERROR_INVALID_RESOURCE;
218 if (ioctl (dev->devfd, SPI_IOC_RD_LSB_FIRST, &lsb_mode) < 0) {
219 syslog(LOG_ERR, "spi: Failed to set bit order");
220 return MRAA_ERROR_INVALID_RESOURCE;
227 mraa_spi_bit_per_word(mraa_spi_context dev, unsigned int bits)
229 if (ioctl(dev->devfd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0) {
230 syslog(LOG_ERR, "spi: Failed to set bit per word");
231 return MRAA_ERROR_INVALID_RESOURCE;
238 mraa_spi_write(mraa_spi_context dev, uint8_t data)
240 struct spi_ioc_transfer msg;
241 memset(&msg, 0, sizeof(msg));
245 unsigned long recv = 0;
246 msg.tx_buf = (unsigned long) &data;
247 msg.rx_buf = (unsigned long) &recv;
248 msg.speed_hz = dev->clock;
249 msg.bits_per_word = dev->bpw;
252 if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
253 syslog(LOG_ERR, "spi: Failed to perform dev transfer");
260 mraa_spi_write_word(mraa_spi_context dev, uint16_t data)
262 struct spi_ioc_transfer msg;
263 memset(&msg, 0, sizeof(msg));
268 msg.tx_buf = (unsigned long) &data;
269 msg.rx_buf = (unsigned long) &recv;
270 msg.speed_hz = dev->clock;
271 msg.bits_per_word = dev->bpw;
274 if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
275 syslog(LOG_ERR, "spi: Failed to perform dev transfer");
282 mraa_spi_transfer_buf(mraa_spi_context dev, uint8_t* data, uint8_t* rxbuf, int length)
284 struct spi_ioc_transfer msg;
285 memset(&msg, 0, sizeof(msg));
287 msg.tx_buf = (unsigned long) data;
288 msg.rx_buf = (unsigned long) rxbuf;
289 msg.speed_hz = dev->clock;
290 msg.bits_per_word = dev->bpw;
293 if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
294 syslog(LOG_ERR, "spi: Failed to perform dev transfer");
295 return MRAA_ERROR_INVALID_RESOURCE;
301 mraa_spi_transfer_buf_word(mraa_spi_context dev, uint16_t* data, uint16_t* rxbuf, int length)
303 struct spi_ioc_transfer msg;
304 memset(&msg, 0, sizeof(msg));
306 msg.tx_buf = (unsigned long) data;
307 msg.rx_buf = (unsigned long) rxbuf;
308 msg.speed_hz = dev->clock;
309 msg.bits_per_word = dev->bpw;
312 if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
313 syslog(LOG_ERR, "spi: Failed to perform dev transfer");
314 return MRAA_ERROR_INVALID_RESOURCE;
320 mraa_spi_write_buf(mraa_spi_context dev, uint8_t* data, int length)
322 uint8_t* recv = malloc(sizeof(uint8_t) * length);
324 if (mraa_spi_transfer_buf(dev, data, recv, length) != MRAA_SUCCESS) {
332 mraa_spi_write_buf_word(mraa_spi_context dev, uint16_t *data, int length)
334 uint16_t* recv = malloc(sizeof(uint16_t) * length);
336 if (mraa_spi_transfer_buf_word(dev, data, recv, length) != MRAA_SUCCESS) {
344 mraa_spi_stop(mraa_spi_context dev)