tsc2000.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. * Functions to access the TSC2000 controller on TRAB board (used for scanning
  3. * thermo sensors)
  4. *
  5. * Copyright (C) 2003 Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
  6. *
  7. * Copyright (C) 2002 DENX Software Engineering, Wolfgang Denk, wd@denx.de
  8. *
  9. * See file CREDITS for list of people who contributed to this
  10. * project.
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License as
  14. * published by the Free Software Foundation; either version 2 of
  15. * the License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  25. * MA 02111-1307 USA
  26. */
  27. #include <common.h>
  28. #include <s3c2400.h>
  29. #include "tsc2000.h"
  30. #include "Pt1000_temp_data.h"
  31. void spi_init(void)
  32. {
  33. S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
  34. S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
  35. int i;
  36. /* Configure I/O ports. */
  37. gpio->PDCON = (gpio->PDCON & 0xF3FFFF) | 0x040000;
  38. gpio->PGCON = (gpio->PGCON & 0x0F3FFF) | 0x008000;
  39. gpio->PGCON = (gpio->PGCON & 0x0CFFFF) | 0x020000;
  40. gpio->PGCON = (gpio->PGCON & 0x03FFFF) | 0x080000;
  41. CLR_CS_TOUCH();
  42. spi->ch[0].SPPRE = 0x1F; /* Baud-rate ca. 514kHz */
  43. spi->ch[0].SPPIN = 0x01; /* SPI-MOSI holds Level after last bit */
  44. spi->ch[0].SPCON = 0x1A; /* Polling, Prescaler, Master, CPOL=0,
  45. CPHA=1 */
  46. /* Dummy byte ensures clock to be low. */
  47. for (i = 0; i < 10; i++) {
  48. spi->ch[0].SPTDAT = 0xFF;
  49. }
  50. spi_wait_transmit_done();
  51. }
  52. void spi_wait_transmit_done(void)
  53. {
  54. S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
  55. while (!(spi->ch[0].SPSTA & 0x01)); /* wait until transfer is done */
  56. }
  57. void tsc2000_write(unsigned short reg, unsigned short data)
  58. {
  59. S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
  60. unsigned int command;
  61. SET_CS_TOUCH();
  62. command = reg;
  63. spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
  64. spi_wait_transmit_done();
  65. spi->ch[0].SPTDAT = (command & 0x00FF);
  66. spi_wait_transmit_done();
  67. spi->ch[0].SPTDAT = (data & 0xFF00) >> 8;
  68. spi_wait_transmit_done();
  69. spi->ch[0].SPTDAT = (data & 0x00FF);
  70. spi_wait_transmit_done();
  71. CLR_CS_TOUCH();
  72. }
  73. unsigned short tsc2000_read (unsigned short reg)
  74. {
  75. unsigned short command, data;
  76. S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
  77. SET_CS_TOUCH();
  78. command = 0x8000 | reg;
  79. spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
  80. spi_wait_transmit_done();
  81. spi->ch[0].SPTDAT = (command & 0x00FF);
  82. spi_wait_transmit_done();
  83. spi->ch[0].SPTDAT = 0xFF;
  84. spi_wait_transmit_done();
  85. data = spi->ch[0].SPRDAT;
  86. spi->ch[0].SPTDAT = 0xFF;
  87. spi_wait_transmit_done();
  88. CLR_CS_TOUCH();
  89. return (spi->ch[0].SPRDAT & 0x0FF) | (data << 8);
  90. }
  91. void tsc2000_set_mux (unsigned int channel)
  92. {
  93. S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
  94. CLR_MUX1_ENABLE; CLR_MUX2_ENABLE;
  95. CLR_MUX3_ENABLE; CLR_MUX4_ENABLE;
  96. switch (channel) {
  97. case 0:
  98. CLR_MUX0; CLR_MUX1;
  99. SET_MUX1_ENABLE;
  100. break;
  101. case 1:
  102. SET_MUX0; CLR_MUX1;
  103. SET_MUX1_ENABLE;
  104. break;
  105. case 2:
  106. CLR_MUX0; SET_MUX1;
  107. SET_MUX1_ENABLE;
  108. break;
  109. case 3:
  110. SET_MUX0; SET_MUX1;
  111. SET_MUX1_ENABLE;
  112. break;
  113. case 4:
  114. CLR_MUX0; CLR_MUX1;
  115. SET_MUX2_ENABLE;
  116. break;
  117. case 5:
  118. SET_MUX0; CLR_MUX1;
  119. SET_MUX2_ENABLE;
  120. break;
  121. case 6:
  122. CLR_MUX0; SET_MUX1;
  123. SET_MUX2_ENABLE;
  124. break;
  125. case 7:
  126. SET_MUX0; SET_MUX1;
  127. SET_MUX2_ENABLE;
  128. break;
  129. case 8:
  130. CLR_MUX0; CLR_MUX1;
  131. SET_MUX3_ENABLE;
  132. break;
  133. case 9:
  134. SET_MUX0; CLR_MUX1;
  135. SET_MUX3_ENABLE;
  136. break;
  137. case 10:
  138. CLR_MUX0; SET_MUX1;
  139. SET_MUX3_ENABLE;
  140. break;
  141. case 11:
  142. SET_MUX0; SET_MUX1;
  143. SET_MUX3_ENABLE;
  144. break;
  145. case 12:
  146. CLR_MUX0; CLR_MUX1;
  147. SET_MUX4_ENABLE;
  148. break;
  149. case 13:
  150. SET_MUX0; CLR_MUX1;
  151. SET_MUX4_ENABLE;
  152. break;
  153. case 14:
  154. CLR_MUX0; SET_MUX1;
  155. SET_MUX4_ENABLE;
  156. break;
  157. case 15:
  158. SET_MUX0; SET_MUX1;
  159. SET_MUX4_ENABLE;
  160. break;
  161. default:
  162. CLR_MUX0; CLR_MUX1;
  163. }
  164. }
  165. void tsc2000_set_range (unsigned int range)
  166. {
  167. S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
  168. switch (range) {
  169. case 1:
  170. CLR_SEL_TEMP_V_0; SET_SEL_TEMP_V_1;
  171. CLR_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
  172. break;
  173. case 2:
  174. CLR_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
  175. CLR_SEL_TEMP_V_2; SET_SEL_TEMP_V_3;
  176. break;
  177. case 3:
  178. SET_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
  179. SET_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
  180. break;
  181. }
  182. }
  183. u16 tsc2000_read_channel (unsigned int channel)
  184. {
  185. u16 res;
  186. tsc2000_set_mux(channel);
  187. udelay(3 * TSC2000_DELAY_BASE);
  188. tsc2000_write(TSC2000_REG_ADC, 0x2036);
  189. adc_wait_conversion_done ();
  190. res = tsc2000_read(TSC2000_REG_AUX1);
  191. return res;
  192. }
  193. s32 tsc2000_contact_temp (void)
  194. {
  195. long adc_pt1000, offset;
  196. long u_pt1000;
  197. long contact_temp;
  198. tsc2000_reg_init ();
  199. tsc2000_set_range (3);
  200. adc_pt1000 = tsc2000_read_channel (14);
  201. debug ("read channel 14 (pt1000 adc value): %ld\n", adc_pt1000);
  202. offset = tsc2000_read_channel (15);
  203. debug ("read channel 15 (offset): %ld\n", offset);
  204. /*
  205. * Formula for calculating voltage drop on PT1000 resistor: u_pt1000 =
  206. * x_range3 * (adc_raw - offset) / 10. Formula to calculate x_range3:
  207. * x_range3 = (2500 * (1000000 + err_vref + err_amp3)) / (4095*6). The
  208. * error correction Values err_vref and err_amp3 are assumed as 0 in
  209. * u-boot, because this could cause only a very small error (< 1%).
  210. */
  211. u_pt1000 = (101750 * (adc_pt1000 - offset)) / 10;
  212. debug ("u_pt1000: %ld\n", u_pt1000);
  213. if (tsc2000_interpolate(u_pt1000, Pt1000_temp_table,
  214. &contact_temp) == -1) {
  215. printf ("%s: error interpolating PT1000 vlaue\n",
  216. __FUNCTION__);
  217. return (-1000);
  218. }
  219. debug ("contact_temp: %ld\n", contact_temp);
  220. return contact_temp;
  221. }
  222. void tsc2000_reg_init (void)
  223. {
  224. S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
  225. tsc2000_write(TSC2000_REG_ADC, 0x2036);
  226. tsc2000_write(TSC2000_REG_REF, 0x0011);
  227. tsc2000_write(TSC2000_REG_DACCTL, 0x0000);
  228. CON_MUX0;
  229. CON_MUX1;
  230. CON_MUX1_ENABLE;
  231. CON_MUX2_ENABLE;
  232. CON_MUX3_ENABLE;
  233. CON_MUX4_ENABLE;
  234. CON_SEL_TEMP_V_0;
  235. CON_SEL_TEMP_V_1;
  236. CON_SEL_TEMP_V_2;
  237. CON_SEL_TEMP_V_3;
  238. tsc2000_set_mux(0);
  239. tsc2000_set_range(0);
  240. }
  241. int tsc2000_interpolate(long value, long data[][2], long *result)
  242. {
  243. int i;
  244. /* the data is sorted and the first element is upper
  245. * limit so we can easily check for out-of-band values
  246. */
  247. if (data[0][0] < value || data[1][0] > value)
  248. return -1;
  249. i = 1;
  250. while (data[i][0] < value)
  251. i++;
  252. /* To prevent overflow we have to store the intermediate
  253. result in 'long long'.
  254. */
  255. *result = data[i-1][1] +
  256. ((unsigned long long)(data[i][1] - data[i-1][1])
  257. * (unsigned long long)(value - data[i-1][0]))
  258. / (data[i][0] - data[i-1][0]);
  259. return 0;
  260. }
  261. void adc_wait_conversion_done(void)
  262. {
  263. while (!(tsc2000_read(TSC2000_REG_ADC) & (1 << 14)));
  264. }