s5c73m3-spi.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Samsung LSI S5C73M3 8M pixel camera driver
  4. *
  5. * Copyright (C) 2012, Samsung Electronics, Co., Ltd.
  6. * Sylwester Nawrocki <[email protected]>
  7. * Andrzej Hajda <[email protected]>
  8. */
  9. #include <linux/sizes.h>
  10. #include <linux/delay.h>
  11. #include <linux/init.h>
  12. #include <linux/media.h>
  13. #include <linux/module.h>
  14. #include <linux/slab.h>
  15. #include <linux/spi/spi.h>
  16. #include "s5c73m3.h"
  17. #define S5C73M3_SPI_DRV_NAME "S5C73M3-SPI"
  18. static const struct of_device_id s5c73m3_spi_ids[] = {
  19. { .compatible = "samsung,s5c73m3" },
  20. { }
  21. };
  22. MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids);
  23. enum spi_direction {
  24. SPI_DIR_RX,
  25. SPI_DIR_TX
  26. };
  27. static int spi_xmit(struct spi_device *spi_dev, void *addr, const int len,
  28. enum spi_direction dir)
  29. {
  30. struct spi_message msg;
  31. int r;
  32. struct spi_transfer xfer = {
  33. .len = len,
  34. };
  35. if (dir == SPI_DIR_TX)
  36. xfer.tx_buf = addr;
  37. else
  38. xfer.rx_buf = addr;
  39. if (spi_dev == NULL) {
  40. pr_err("SPI device is uninitialized\n");
  41. return -ENODEV;
  42. }
  43. spi_message_init(&msg);
  44. spi_message_add_tail(&xfer, &msg);
  45. r = spi_sync(spi_dev, &msg);
  46. if (r < 0)
  47. dev_err(&spi_dev->dev, "%s spi_sync failed %d\n", __func__, r);
  48. return r;
  49. }
  50. int s5c73m3_spi_write(struct s5c73m3 *state, const void *addr,
  51. const unsigned int len, const unsigned int tx_size)
  52. {
  53. struct spi_device *spi_dev = state->spi_dev;
  54. u32 count = len / tx_size;
  55. u32 extra = len % tx_size;
  56. unsigned int i, j = 0;
  57. u8 padding[32];
  58. int r = 0;
  59. memset(padding, 0, sizeof(padding));
  60. for (i = 0; i < count; i++) {
  61. r = spi_xmit(spi_dev, (void *)addr + j, tx_size, SPI_DIR_TX);
  62. if (r < 0)
  63. return r;
  64. j += tx_size;
  65. }
  66. if (extra > 0) {
  67. r = spi_xmit(spi_dev, (void *)addr + j, extra, SPI_DIR_TX);
  68. if (r < 0)
  69. return r;
  70. }
  71. return spi_xmit(spi_dev, padding, sizeof(padding), SPI_DIR_TX);
  72. }
  73. int s5c73m3_spi_read(struct s5c73m3 *state, void *addr,
  74. const unsigned int len, const unsigned int tx_size)
  75. {
  76. struct spi_device *spi_dev = state->spi_dev;
  77. u32 count = len / tx_size;
  78. u32 extra = len % tx_size;
  79. unsigned int i, j = 0;
  80. int r = 0;
  81. for (i = 0; i < count; i++) {
  82. r = spi_xmit(spi_dev, addr + j, tx_size, SPI_DIR_RX);
  83. if (r < 0)
  84. return r;
  85. j += tx_size;
  86. }
  87. if (extra > 0)
  88. return spi_xmit(spi_dev, addr + j, extra, SPI_DIR_RX);
  89. return 0;
  90. }
  91. static int s5c73m3_spi_probe(struct spi_device *spi)
  92. {
  93. int r;
  94. struct s5c73m3 *state = container_of(spi->dev.driver, struct s5c73m3,
  95. spidrv.driver);
  96. spi->bits_per_word = 32;
  97. r = spi_setup(spi);
  98. if (r < 0) {
  99. dev_err(&spi->dev, "spi_setup() failed\n");
  100. return r;
  101. }
  102. mutex_lock(&state->lock);
  103. state->spi_dev = spi;
  104. mutex_unlock(&state->lock);
  105. v4l2_info(&state->sensor_sd, "S5C73M3 SPI probed successfully\n");
  106. return 0;
  107. }
  108. int s5c73m3_register_spi_driver(struct s5c73m3 *state)
  109. {
  110. struct spi_driver *spidrv = &state->spidrv;
  111. spidrv->probe = s5c73m3_spi_probe;
  112. spidrv->driver.name = S5C73M3_SPI_DRV_NAME;
  113. spidrv->driver.of_match_table = s5c73m3_spi_ids;
  114. return spi_register_driver(spidrv);
  115. }
  116. void s5c73m3_unregister_spi_driver(struct s5c73m3 *state)
  117. {
  118. spi_unregister_driver(&state->spidrv);
  119. }