ssp_spi.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * driver for Android SensorHub SPI
  3. *
  4. * Copyright (c) 2013, Samsung Electronics. All rights reserved
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  12. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. * for more details.
  14. */
  15. #include <linux/init.h>
  16. #include <linux/module.h>
  17. #include <linux/spi/spi.h>
  18. #include <linux/delay.h>
  19. #if defined(DEBUG_SSP_SPI)
  20. #define ssp_log(fmt, arg...) \
  21. do { \
  22. printk(KERN_ERR "[%s:%d] " fmt , \
  23. __func__, __LINE__, ##arg); \
  24. } \
  25. while (0)
  26. #else
  27. #define ssp_log(fmt, arg...)
  28. #endif
  29. /* If AP can't change the endian to BIG */
  30. /* for s5c73m ISP, this option must is required.*/
  31. /* This option depends on SPI_DMA_MODE */
  32. /* in camera driver file*/
  33. /*#define CHANGE_ENDIAN */
  34. int ssp_spi_write_sync(struct spi_device *spi, const u8 *addr, const int len)
  35. {
  36. int ret;
  37. #if defined(CHANGE_ENDIAN)
  38. u8 buf[8] = {0};
  39. #endif
  40. struct spi_message msg;
  41. struct spi_transfer xfer = {
  42. .len = len,
  43. #if !defined(CHANGE_ENDIAN)
  44. .tx_buf = addr,
  45. /*QCTK ALRAN QUP_CONFIG 0-4 bits BIG ENDIAN*/
  46. .bits_per_word = 8,
  47. #else
  48. .tx_buf = buf,
  49. #endif
  50. };
  51. #if defined(CHANGE_ENDIAN)
  52. buf[0] = addr[3];
  53. buf[1] = addr[2];
  54. buf[2] = addr[1];
  55. buf[3] = addr[0];
  56. buf[4] = addr[7];
  57. buf[5] = addr[6];
  58. buf[6] = addr[5];
  59. buf[7] = addr[4];
  60. #endif
  61. spi_message_init(&msg);
  62. spi_message_add_tail(&xfer, &msg);
  63. ret = spi_sync(spi, &msg);
  64. if (ret < 0)
  65. ssp_log("error %d\n", ret);
  66. return ret;
  67. }
  68. int ssp_spi_read_sync(struct spi_device *spi, u8 *in_buf, size_t len)
  69. {
  70. int ret;
  71. u8 read_out_buf[2];
  72. struct spi_message msg;
  73. struct spi_transfer xfer = {
  74. .tx_buf = read_out_buf,
  75. .rx_buf = in_buf,
  76. .len = len,
  77. .cs_change = 0,
  78. };
  79. spi_message_init(&msg);
  80. spi_message_add_tail(&xfer, &msg);
  81. ret = spi_sync(spi, &msg);
  82. if (ret < 0)
  83. ssp_log("%s - error %d\n",
  84. __func__, ret);
  85. return ret;
  86. }
  87. int ssp_spi_sync(struct spi_device *spi, u8 *out_buf,
  88. size_t out_len, u8 *in_buf)
  89. {
  90. int ret;
  91. struct spi_message msg;
  92. struct spi_transfer xfer = {
  93. .tx_buf = out_buf,
  94. .rx_buf = in_buf,
  95. .len = out_len,
  96. .cs_change = 0,
  97. };
  98. spi_message_init(&msg);
  99. spi_message_add_tail(&xfer, &msg);
  100. ret = spi_sync(spi, &msg);
  101. ssp_log("%s - received %d\n", __func__, xfer.len);
  102. if (ret < 0)
  103. ssp_log("%s - error %d\n",
  104. __func__, ret);
  105. return ret;
  106. }
  107. unsigned int g_flag_spirecv;
  108. void ssp_spi_async_complete(void *context)
  109. {
  110. g_flag_spirecv = 1;
  111. }
  112. int ssp_spi_async(struct spi_device *spi, u8 *out_buf,
  113. size_t out_len, u8 *in_buf)
  114. {
  115. int ret;
  116. struct spi_message msg;
  117. struct spi_transfer xfer = {
  118. .tx_buf = out_buf,
  119. .rx_buf = in_buf,
  120. .len = out_len,
  121. .cs_change = 0,
  122. };
  123. spi_message_init(&msg);
  124. spi_message_add_tail(&xfer, &msg);
  125. msg.complete = ssp_spi_async_complete;
  126. ret = spi_async(spi, &msg);
  127. if (ret < 0)
  128. ssp_log("%s - error %d\n",
  129. __func__, ret);
  130. return ret;
  131. }
  132. int ssp_spi_read(struct spi_device *spi, u8 *buf, size_t len, const int rxSize)
  133. {
  134. int k;
  135. int ret = 0;
  136. u8 temp_buf[4] = {0};
  137. u32 count = len/rxSize;
  138. u32 extra = len%rxSize;
  139. for (k = 0; k < count; k++) {
  140. ret = ssp_spi_read_sync(spi, &buf[rxSize*k], rxSize);
  141. if (ret < 0) {
  142. ssp_log("%s - error %d\n",
  143. __func__, ret);
  144. return -EINVAL;
  145. }
  146. }
  147. if (extra != 0) {
  148. ret = ssp_spi_read_sync(spi, &buf[rxSize*k], extra);
  149. if (ret < 0) {
  150. ssp_log("%s - error %d\n",
  151. __func__, ret);
  152. return -EINVAL;
  153. }
  154. }
  155. for (k = 0; k < len-3; k += 4) {
  156. memcpy(temp_buf, (char *)&buf[k], sizeof(temp_buf));
  157. buf[k] = temp_buf[3];
  158. buf[k+1] = temp_buf[2];
  159. buf[k+2] = temp_buf[1];
  160. buf[k+3] = temp_buf[0];
  161. }
  162. return 0;
  163. }
  164. int ssp_spi_write(struct spi_device *spi, const u8 *addr,
  165. const int len, const int txSize)
  166. {
  167. int i, j = 0;
  168. int ret = 0;
  169. u8 paddingData[8];
  170. u32 count = len/txSize;
  171. u32 extra = len%txSize;
  172. ssp_log("Entered\n");
  173. ssp_log("count = %d extra = %d\n", count, extra);
  174. memset(paddingData, 0, sizeof(paddingData));
  175. for (i = 0 ; i < count ; i++) {
  176. ret = ssp_spi_write_sync(spi, &addr[j], txSize);
  177. j += txSize;
  178. if (ret < 0) {
  179. ssp_log("failed to write ssp_spi_write_sync\n");
  180. goto exit_err;
  181. }
  182. ssp_log("Delay!!!\n");
  183. msleep(50);
  184. }
  185. if (extra) {
  186. ret = ssp_spi_write_sync(spi, &addr[j], extra);
  187. if (ret < 0) {
  188. ssp_log("failed to write ssp_spi_write_sync\n");
  189. goto exit_err;
  190. }
  191. }
  192. for (i = 0; i < 4; i++) {
  193. memset(paddingData, 0, sizeof(paddingData));
  194. ret = ssp_spi_write_sync(spi, paddingData, 8);
  195. if (ret < 0) {
  196. ssp_log("failed to write ssp_spi_write_sync\n");
  197. goto exit_err;
  198. }
  199. }
  200. ssp_log("Finish!!\n");
  201. exit_err:
  202. return ret;
  203. }