tsc2000.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  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 <asm/arch/s3c24x0_cpu.h>
  29. #include <asm/io.h>
  30. #include <div64.h>
  31. #include "tsc2000.h"
  32. #include "Pt1000_temp_data.h"
  33. /* helper function */
  34. #define abs(value) (((value) < 0) ? ((value)*-1) : (value))
  35. /*
  36. * Maximal allowed deviation between two immediate meassurments of an analog
  37. * thermo channel. 1 DIGIT = 0.0276 °C. This is used to filter sporadic
  38. * "jumps" in measurment.
  39. */
  40. #define MAX_DEVIATION 18 /* unit: DIGITs of adc; 18 DIGIT = 0.5 °C */
  41. void tsc2000_spi_init(void)
  42. {
  43. struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
  44. struct s3c24x0_spi * const spi = s3c24x0_get_base_spi();
  45. int i;
  46. /* Configure I/O ports. */
  47. gpio->PDCON = (gpio->PDCON & 0xF3FFFF) | 0x040000;
  48. gpio->PGCON = (gpio->PGCON & 0x0F3FFF) | 0x008000;
  49. gpio->PGCON = (gpio->PGCON & 0x0CFFFF) | 0x020000;
  50. gpio->PGCON = (gpio->PGCON & 0x03FFFF) | 0x080000;
  51. CLR_CS_TOUCH();
  52. spi->ch[0].SPPRE = 0x1F; /* Baud-rate ca. 514kHz */
  53. spi->ch[0].SPPIN = 0x01; /* SPI-MOSI holds Level after last bit */
  54. spi->ch[0].SPCON = 0x1A; /* Polling, Prescaler, Master, CPOL=0,
  55. CPHA=1 */
  56. /* Dummy byte ensures clock to be low. */
  57. for (i = 0; i < 10; i++) {
  58. spi->ch[0].SPTDAT = 0xFF;
  59. }
  60. spi_wait_transmit_done();
  61. }
  62. void spi_wait_transmit_done(void)
  63. {
  64. struct s3c24x0_spi * const spi = s3c24x0_get_base_spi();
  65. while (!(spi->ch[0].SPSTA & 0x01)); /* wait until transfer is done */
  66. }
  67. void tsc2000_write(unsigned short reg, unsigned short data)
  68. {
  69. struct s3c24x0_spi * const spi = s3c24x0_get_base_spi();
  70. unsigned int command;
  71. SET_CS_TOUCH();
  72. command = reg;
  73. spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
  74. spi_wait_transmit_done();
  75. spi->ch[0].SPTDAT = (command & 0x00FF);
  76. spi_wait_transmit_done();
  77. spi->ch[0].SPTDAT = (data & 0xFF00) >> 8;
  78. spi_wait_transmit_done();
  79. spi->ch[0].SPTDAT = (data & 0x00FF);
  80. spi_wait_transmit_done();
  81. CLR_CS_TOUCH();
  82. }
  83. unsigned short tsc2000_read (unsigned short reg)
  84. {
  85. unsigned short command, data;
  86. struct s3c24x0_spi * const spi = s3c24x0_get_base_spi();
  87. SET_CS_TOUCH();
  88. command = 0x8000 | reg;
  89. spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
  90. spi_wait_transmit_done();
  91. spi->ch[0].SPTDAT = (command & 0x00FF);
  92. spi_wait_transmit_done();
  93. spi->ch[0].SPTDAT = 0xFF;
  94. spi_wait_transmit_done();
  95. data = spi->ch[0].SPRDAT;
  96. spi->ch[0].SPTDAT = 0xFF;
  97. spi_wait_transmit_done();
  98. CLR_CS_TOUCH();
  99. return (spi->ch[0].SPRDAT & 0x0FF) | (data << 8);
  100. }
  101. void tsc2000_set_mux (unsigned int channel)
  102. {
  103. struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
  104. CLR_MUX1_ENABLE; CLR_MUX2_ENABLE;
  105. CLR_MUX3_ENABLE; CLR_MUX4_ENABLE;
  106. switch (channel) {
  107. case 0:
  108. CLR_MUX0; CLR_MUX1;
  109. SET_MUX1_ENABLE;
  110. break;
  111. case 1:
  112. SET_MUX0; CLR_MUX1;
  113. SET_MUX1_ENABLE;
  114. break;
  115. case 2:
  116. CLR_MUX0; SET_MUX1;
  117. SET_MUX1_ENABLE;
  118. break;
  119. case 3:
  120. SET_MUX0; SET_MUX1;
  121. SET_MUX1_ENABLE;
  122. break;
  123. case 4:
  124. CLR_MUX0; CLR_MUX1;
  125. SET_MUX2_ENABLE;
  126. break;
  127. case 5:
  128. SET_MUX0; CLR_MUX1;
  129. SET_MUX2_ENABLE;
  130. break;
  131. case 6:
  132. CLR_MUX0; SET_MUX1;
  133. SET_MUX2_ENABLE;
  134. break;
  135. case 7:
  136. SET_MUX0; SET_MUX1;
  137. SET_MUX2_ENABLE;
  138. break;
  139. case 8:
  140. CLR_MUX0; CLR_MUX1;
  141. SET_MUX3_ENABLE;
  142. break;
  143. case 9:
  144. SET_MUX0; CLR_MUX1;
  145. SET_MUX3_ENABLE;
  146. break;
  147. case 10:
  148. CLR_MUX0; SET_MUX1;
  149. SET_MUX3_ENABLE;
  150. break;
  151. case 11:
  152. SET_MUX0; SET_MUX1;
  153. SET_MUX3_ENABLE;
  154. break;
  155. case 12:
  156. CLR_MUX0; CLR_MUX1;
  157. SET_MUX4_ENABLE;
  158. break;
  159. case 13:
  160. SET_MUX0; CLR_MUX1;
  161. SET_MUX4_ENABLE;
  162. break;
  163. case 14:
  164. CLR_MUX0; SET_MUX1;
  165. SET_MUX4_ENABLE;
  166. break;
  167. case 15:
  168. SET_MUX0; SET_MUX1;
  169. SET_MUX4_ENABLE;
  170. break;
  171. default:
  172. CLR_MUX0; CLR_MUX1;
  173. }
  174. }
  175. void tsc2000_set_range (unsigned int range)
  176. {
  177. struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
  178. switch (range) {
  179. case 1:
  180. CLR_SEL_TEMP_V_0; SET_SEL_TEMP_V_1;
  181. CLR_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
  182. break;
  183. case 2:
  184. CLR_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
  185. CLR_SEL_TEMP_V_2; SET_SEL_TEMP_V_3;
  186. break;
  187. case 3:
  188. SET_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
  189. SET_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
  190. break;
  191. }
  192. }
  193. u16 tsc2000_read_channel (unsigned int channel)
  194. {
  195. u16 res;
  196. tsc2000_set_mux(channel);
  197. udelay(20 * TSC2000_DELAY_BASE);
  198. tsc2000_write(TSC2000_REG_ADC, 0x2036);
  199. adc_wait_conversion_done ();
  200. res = tsc2000_read(TSC2000_REG_AUX1);
  201. return res;
  202. }
  203. s32 tsc2000_contact_temp (void)
  204. {
  205. long adc_pt1000, offset;
  206. long u_pt1000;
  207. long contact_temp;
  208. long temp1, temp2;
  209. tsc2000_reg_init ();
  210. tsc2000_set_range (3);
  211. /*
  212. * Because of sporadic "jumps" in the measured adc values every
  213. * channel is read two times. If there is a significant difference
  214. * between the two measurements, then print an error and do a third
  215. * measurement, because it is very unlikely that a successive third
  216. * measurement goes also wrong.
  217. */
  218. temp1 = tsc2000_read_channel (14);
  219. temp2 = tsc2000_read_channel (14);
  220. if (abs(temp2 - temp1) < MAX_DEVIATION)
  221. adc_pt1000 = temp2;
  222. else {
  223. printf ("%s: read adc value (channel 14) exceeded max allowed "
  224. "deviation: %d * 0.0276 °C\n",
  225. __FUNCTION__, MAX_DEVIATION);
  226. printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",
  227. temp1, temp2);
  228. adc_pt1000 = tsc2000_read_channel (14);
  229. printf ("use (third read) adc value: adc_pt1000 = "
  230. "%ld DIGITs\n", adc_pt1000);
  231. }
  232. debug ("read channel 14 (pt1000 adc value): %ld\n", adc_pt1000);
  233. temp1 = tsc2000_read_channel (15);
  234. temp2 = tsc2000_read_channel (15);
  235. if (abs(temp2 - temp1) < MAX_DEVIATION)
  236. offset = temp2;
  237. else {
  238. printf ("%s: read adc value (channel 15) exceeded max allowed "
  239. "deviation: %d * 0.0276 °C\n",
  240. __FUNCTION__, MAX_DEVIATION);
  241. printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",
  242. temp1, temp2);
  243. offset = tsc2000_read_channel (15);
  244. printf ("use (third read) adc value: offset = %ld DIGITs\n",
  245. offset);
  246. }
  247. debug ("read channel 15 (offset): %ld\n", offset);
  248. /*
  249. * Formula for calculating voltage drop on PT1000 resistor: u_pt1000 =
  250. * x_range3 * (adc_raw - offset) / 10. Formula to calculate x_range3:
  251. * x_range3 = (2500 * (1000000 + err_vref + err_amp3)) / (4095*6). The
  252. * error correction Values err_vref and err_amp3 are assumed as 0 in
  253. * u-boot, because this could cause only a very small error (< 1%).
  254. */
  255. u_pt1000 = (101750 * (adc_pt1000 - offset)) / 10;
  256. debug ("u_pt1000: %ld\n", u_pt1000);
  257. if (tsc2000_interpolate(u_pt1000, Pt1000_temp_table,
  258. &contact_temp) == -1) {
  259. printf ("%s: error interpolating PT1000 vlaue\n",
  260. __FUNCTION__);
  261. return (-1000);
  262. }
  263. debug ("contact_temp: %ld\n", contact_temp);
  264. return contact_temp;
  265. }
  266. void tsc2000_reg_init (void)
  267. {
  268. struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
  269. tsc2000_write(TSC2000_REG_ADC, 0x2036);
  270. tsc2000_write(TSC2000_REG_REF, 0x0011);
  271. tsc2000_write(TSC2000_REG_DACCTL, 0x0000);
  272. CON_MUX0;
  273. CON_MUX1;
  274. CON_MUX1_ENABLE;
  275. CON_MUX2_ENABLE;
  276. CON_MUX3_ENABLE;
  277. CON_MUX4_ENABLE;
  278. CON_SEL_TEMP_V_0;
  279. CON_SEL_TEMP_V_1;
  280. CON_SEL_TEMP_V_2;
  281. CON_SEL_TEMP_V_3;
  282. tsc2000_set_mux(0);
  283. tsc2000_set_range(0);
  284. }
  285. int tsc2000_interpolate(long value, long data[][2], long *result)
  286. {
  287. int i;
  288. unsigned long long val;
  289. /* the data is sorted and the first element is upper
  290. * limit so we can easily check for out-of-band values
  291. */
  292. if (data[0][0] < value || data[1][0] > value)
  293. return -1;
  294. i = 1;
  295. while (data[i][0] < value)
  296. i++;
  297. /* To prevent overflow we have to store the intermediate
  298. result in 'long long'.
  299. */
  300. val = ((unsigned long long)(data[i][1] - data[i-1][1])
  301. * (unsigned long long)(value - data[i-1][0]));
  302. do_div(val, (data[i][0] - data[i-1][0]));
  303. *result = data[i-1][1] + val;
  304. return 0;
  305. }
  306. void adc_wait_conversion_done(void)
  307. {
  308. while (!(tsc2000_read(TSC2000_REG_ADC) & (1 << 14)));
  309. }