cxd2880_devio_spi.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * cxd2880_devio_spi.c
  4. * Sony CXD2880 DVB-T2/T tuner + demodulator driver
  5. * I/O interface via SPI
  6. *
  7. * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
  8. */
  9. #include "cxd2880_devio_spi.h"
  10. #define BURST_WRITE_MAX 128
  11. static int cxd2880_io_spi_read_reg(struct cxd2880_io *io,
  12. enum cxd2880_io_tgt tgt,
  13. u8 sub_address, u8 *data,
  14. u32 size)
  15. {
  16. int ret = 0;
  17. struct cxd2880_spi *spi = NULL;
  18. u8 send_data[6];
  19. u8 *read_data_top = data;
  20. if (!io || !io->if_object || !data)
  21. return -EINVAL;
  22. if (sub_address + size > 0x100)
  23. return -EINVAL;
  24. spi = io->if_object;
  25. if (tgt == CXD2880_IO_TGT_SYS)
  26. send_data[0] = 0x0b;
  27. else
  28. send_data[0] = 0x0a;
  29. send_data[3] = 0;
  30. send_data[4] = 0;
  31. send_data[5] = 0;
  32. while (size > 0) {
  33. send_data[1] = sub_address;
  34. if (size > 255)
  35. send_data[2] = 255;
  36. else
  37. send_data[2] = size;
  38. ret =
  39. spi->write_read(spi, send_data, sizeof(send_data),
  40. read_data_top, send_data[2]);
  41. if (ret)
  42. return ret;
  43. sub_address += send_data[2];
  44. read_data_top += send_data[2];
  45. size -= send_data[2];
  46. }
  47. return ret;
  48. }
  49. static int cxd2880_io_spi_write_reg(struct cxd2880_io *io,
  50. enum cxd2880_io_tgt tgt,
  51. u8 sub_address,
  52. const u8 *data, u32 size)
  53. {
  54. int ret = 0;
  55. struct cxd2880_spi *spi = NULL;
  56. u8 send_data[BURST_WRITE_MAX + 4];
  57. const u8 *write_data_top = data;
  58. if (!io || !io->if_object || !data)
  59. return -EINVAL;
  60. if (size > BURST_WRITE_MAX)
  61. return -EINVAL;
  62. if (sub_address + size > 0x100)
  63. return -EINVAL;
  64. spi = io->if_object;
  65. if (tgt == CXD2880_IO_TGT_SYS)
  66. send_data[0] = 0x0f;
  67. else
  68. send_data[0] = 0x0e;
  69. while (size > 0) {
  70. send_data[1] = sub_address;
  71. if (size > 255)
  72. send_data[2] = 255;
  73. else
  74. send_data[2] = size;
  75. memcpy(&send_data[3], write_data_top, send_data[2]);
  76. if (tgt == CXD2880_IO_TGT_SYS) {
  77. send_data[3 + send_data[2]] = 0x00;
  78. ret = spi->write(spi, send_data, send_data[2] + 4);
  79. } else {
  80. ret = spi->write(spi, send_data, send_data[2] + 3);
  81. }
  82. if (ret)
  83. return ret;
  84. sub_address += send_data[2];
  85. write_data_top += send_data[2];
  86. size -= send_data[2];
  87. }
  88. return ret;
  89. }
  90. int cxd2880_io_spi_create(struct cxd2880_io *io,
  91. struct cxd2880_spi *spi, u8 slave_select)
  92. {
  93. if (!io || !spi)
  94. return -EINVAL;
  95. io->read_regs = cxd2880_io_spi_read_reg;
  96. io->write_regs = cxd2880_io_spi_write_reg;
  97. io->write_reg = cxd2880_io_common_write_one_reg;
  98. io->if_object = spi;
  99. io->i2c_address_sys = 0;
  100. io->i2c_address_demod = 0;
  101. io->slave_select = slave_select;
  102. return 0;
  103. }