spi-context.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * generic SPI functions
  3. *
  4. * Copyright 2013, 2014 Zefir Kurtisi <zefir.kurtisi@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the Free
  8. * Software Foundation; either version 3 of the License, or (at your option)
  9. * any later version. See COPYING for more details.
  10. */
  11. #include "spi-context.h"
  12. #include "logging.h"
  13. #include "miner.h"
  14. #include <fcntl.h>
  15. #include <sys/ioctl.h>
  16. #include <assert.h>
  17. #include <unistd.h>
  18. struct spi_ctx *spi_init(struct spi_config *config)
  19. {
  20. char dev_fname[PATH_MAX];
  21. struct spi_ctx *ctx;
  22. if (config == NULL)
  23. return NULL;
  24. sprintf(dev_fname, SPI_DEVICE_TEMPLATE, config->bus, config->cs_line);
  25. int fd = open(dev_fname, O_RDWR);
  26. if (fd < 0) {
  27. applog(LOG_ERR, "SPI: Can not open SPI device %s", dev_fname);
  28. return NULL;
  29. }
  30. if ((ioctl(fd, SPI_IOC_WR_MODE, &config->mode) < 0) ||
  31. (ioctl(fd, SPI_IOC_RD_MODE, &config->mode) < 0) ||
  32. (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &config->bits) < 0) ||
  33. (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &config->bits) < 0) ||
  34. (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &config->speed) < 0) ||
  35. (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &config->speed) < 0)) {
  36. applog(LOG_ERR, "SPI: ioctl error on SPI device %s", dev_fname);
  37. close(fd);
  38. return NULL;
  39. }
  40. ctx = malloc(sizeof(*ctx));
  41. assert(ctx != NULL);
  42. ctx->fd = fd;
  43. ctx->config = *config;
  44. applog(LOG_WARNING, "SPI '%s': mode=%hhu, bits=%hhu, speed=%u",
  45. dev_fname, ctx->config.mode, ctx->config.bits,
  46. ctx->config.speed);
  47. return ctx;
  48. }
  49. extern void spi_exit(struct spi_ctx *ctx)
  50. {
  51. if (NULL == ctx)
  52. return;
  53. close(ctx->fd);
  54. free(ctx);
  55. }
  56. extern bool spi_transfer(struct spi_ctx *ctx, uint8_t *txbuf,
  57. uint8_t *rxbuf, int len)
  58. {
  59. struct spi_ioc_transfer xfr;
  60. int ret;
  61. if (rxbuf != NULL)
  62. memset(rxbuf, 0xff, len);
  63. ret = len;
  64. xfr.tx_buf = (unsigned long)txbuf;
  65. xfr.rx_buf = (unsigned long)rxbuf;
  66. xfr.len = len;
  67. xfr.speed_hz = ctx->config.speed;
  68. xfr.delay_usecs = ctx->config.delay;
  69. xfr.bits_per_word = ctx->config.bits;
  70. xfr.cs_change = 0;
  71. xfr.pad = 0;
  72. ret = ioctl(ctx->fd, SPI_IOC_MESSAGE(1), &xfr);
  73. if (ret < 1)
  74. applog(LOG_ERR, "SPI: ioctl error on SPI device: %d", ret);
  75. return ret > 0;
  76. }