spi-mem-nodm.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
  4. */
  5. #include <malloc.h>
  6. #include <spi.h>
  7. #include <spi-mem.h>
  8. int spi_mem_exec_op(struct spi_slave *slave,
  9. const struct spi_mem_op *op)
  10. {
  11. unsigned int pos = 0;
  12. const u8 *tx_buf = NULL;
  13. u8 *rx_buf = NULL;
  14. u8 *op_buf;
  15. int op_len;
  16. u32 flag;
  17. int ret;
  18. int i;
  19. if (op->data.nbytes) {
  20. if (op->data.dir == SPI_MEM_DATA_IN)
  21. rx_buf = op->data.buf.in;
  22. else
  23. tx_buf = op->data.buf.out;
  24. }
  25. op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
  26. op_buf = calloc(1, op_len);
  27. ret = spi_claim_bus(slave);
  28. if (ret < 0)
  29. return ret;
  30. op_buf[pos++] = op->cmd.opcode;
  31. if (op->addr.nbytes) {
  32. for (i = 0; i < op->addr.nbytes; i++)
  33. op_buf[pos + i] = op->addr.val >>
  34. (8 * (op->addr.nbytes - i - 1));
  35. pos += op->addr.nbytes;
  36. }
  37. if (op->dummy.nbytes)
  38. memset(op_buf + pos, 0xff, op->dummy.nbytes);
  39. /* 1st transfer: opcode + address + dummy cycles */
  40. flag = SPI_XFER_BEGIN;
  41. /* Make sure to set END bit if no tx or rx data messages follow */
  42. if (!tx_buf && !rx_buf)
  43. flag |= SPI_XFER_END;
  44. ret = spi_xfer(slave, op_len * 8, op_buf, NULL, flag);
  45. if (ret)
  46. return ret;
  47. /* 2nd transfer: rx or tx data path */
  48. if (tx_buf || rx_buf) {
  49. ret = spi_xfer(slave, op->data.nbytes * 8, tx_buf,
  50. rx_buf, SPI_XFER_END);
  51. if (ret)
  52. return ret;
  53. }
  54. spi_release_bus(slave);
  55. for (i = 0; i < pos; i++)
  56. debug("%02x ", op_buf[i]);
  57. debug("| [%dB %s] ",
  58. tx_buf || rx_buf ? op->data.nbytes : 0,
  59. tx_buf || rx_buf ? (tx_buf ? "out" : "in") : "-");
  60. for (i = 0; i < op->data.nbytes; i++)
  61. debug("%02x ", tx_buf ? tx_buf[i] : rx_buf[i]);
  62. debug("[ret %d]\n", ret);
  63. free(op_buf);
  64. if (ret < 0)
  65. return ret;
  66. return 0;
  67. }
  68. int spi_mem_adjust_op_size(struct spi_slave *slave,
  69. struct spi_mem_op *op)
  70. {
  71. unsigned int len;
  72. len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
  73. if (slave->max_write_size && len > slave->max_write_size)
  74. return -EINVAL;
  75. if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size)
  76. op->data.nbytes = min(op->data.nbytes,
  77. slave->max_read_size);
  78. else if (slave->max_write_size)
  79. op->data.nbytes = min(op->data.nbytes,
  80. slave->max_write_size - len);
  81. if (!op->data.nbytes)
  82. return -EINVAL;
  83. return 0;
  84. }