123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- /*
- * Functions to access the TSC2000 controller on TRAB board (used for scanning
- * thermo sensors)
- *
- * Copyright (C) 2003 Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
- *
- * Copyright (C) 2002 DENX Software Engineering, Wolfgang Denk, wd@denx.de
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
- #include <common.h>
- #include <s3c2400.h>
- #include "tsc2000.h"
- #include "Pt1000_temp_data.h"
- void spi_init(void)
- {
- S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
- S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
- int i;
- /* Configure I/O ports. */
- gpio->PDCON = (gpio->PDCON & 0xF3FFFF) | 0x040000;
- gpio->PGCON = (gpio->PGCON & 0x0F3FFF) | 0x008000;
- gpio->PGCON = (gpio->PGCON & 0x0CFFFF) | 0x020000;
- gpio->PGCON = (gpio->PGCON & 0x03FFFF) | 0x080000;
- CLR_CS_TOUCH();
- spi->ch[0].SPPRE = 0x1F; /* Baud-rate ca. 514kHz */
- spi->ch[0].SPPIN = 0x01; /* SPI-MOSI holds Level after last bit */
- spi->ch[0].SPCON = 0x1A; /* Polling, Prescaler, Master, CPOL=0,
- CPHA=1 */
- /* Dummy byte ensures clock to be low. */
- for (i = 0; i < 10; i++) {
- spi->ch[0].SPTDAT = 0xFF;
- }
- spi_wait_transmit_done();
- }
- void spi_wait_transmit_done(void)
- {
- S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
- while (!(spi->ch[0].SPSTA & 0x01)); /* wait until transfer is done */
- }
- void tsc2000_write(unsigned short reg, unsigned short data)
- {
- S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
- unsigned int command;
- SET_CS_TOUCH();
- command = reg;
- spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
- spi_wait_transmit_done();
- spi->ch[0].SPTDAT = (command & 0x00FF);
- spi_wait_transmit_done();
- spi->ch[0].SPTDAT = (data & 0xFF00) >> 8;
- spi_wait_transmit_done();
- spi->ch[0].SPTDAT = (data & 0x00FF);
- spi_wait_transmit_done();
- CLR_CS_TOUCH();
- }
- unsigned short tsc2000_read (unsigned short reg)
- {
- unsigned short command, data;
- S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();
- SET_CS_TOUCH();
- command = 0x8000 | reg;
- spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;
- spi_wait_transmit_done();
- spi->ch[0].SPTDAT = (command & 0x00FF);
- spi_wait_transmit_done();
- spi->ch[0].SPTDAT = 0xFF;
- spi_wait_transmit_done();
- data = spi->ch[0].SPRDAT;
- spi->ch[0].SPTDAT = 0xFF;
- spi_wait_transmit_done();
- CLR_CS_TOUCH();
- return (spi->ch[0].SPRDAT & 0x0FF) | (data << 8);
- }
- void tsc2000_set_mux (unsigned int channel)
- {
- S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
- CLR_MUX1_ENABLE; CLR_MUX2_ENABLE;
- CLR_MUX3_ENABLE; CLR_MUX4_ENABLE;
- switch (channel) {
- case 0:
- CLR_MUX0; CLR_MUX1;
- SET_MUX1_ENABLE;
- break;
- case 1:
- SET_MUX0; CLR_MUX1;
- SET_MUX1_ENABLE;
- break;
- case 2:
- CLR_MUX0; SET_MUX1;
- SET_MUX1_ENABLE;
- break;
- case 3:
- SET_MUX0; SET_MUX1;
- SET_MUX1_ENABLE;
- break;
- case 4:
- CLR_MUX0; CLR_MUX1;
- SET_MUX2_ENABLE;
- break;
- case 5:
- SET_MUX0; CLR_MUX1;
- SET_MUX2_ENABLE;
- break;
- case 6:
- CLR_MUX0; SET_MUX1;
- SET_MUX2_ENABLE;
- break;
- case 7:
- SET_MUX0; SET_MUX1;
- SET_MUX2_ENABLE;
- break;
- case 8:
- CLR_MUX0; CLR_MUX1;
- SET_MUX3_ENABLE;
- break;
- case 9:
- SET_MUX0; CLR_MUX1;
- SET_MUX3_ENABLE;
- break;
- case 10:
- CLR_MUX0; SET_MUX1;
- SET_MUX3_ENABLE;
- break;
- case 11:
- SET_MUX0; SET_MUX1;
- SET_MUX3_ENABLE;
- break;
- case 12:
- CLR_MUX0; CLR_MUX1;
- SET_MUX4_ENABLE;
- break;
- case 13:
- SET_MUX0; CLR_MUX1;
- SET_MUX4_ENABLE;
- break;
- case 14:
- CLR_MUX0; SET_MUX1;
- SET_MUX4_ENABLE;
- break;
- case 15:
- SET_MUX0; SET_MUX1;
- SET_MUX4_ENABLE;
- break;
- default:
- CLR_MUX0; CLR_MUX1;
- }
- }
- void tsc2000_set_range (unsigned int range)
- {
- S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
- switch (range) {
- case 1:
- CLR_SEL_TEMP_V_0; SET_SEL_TEMP_V_1;
- CLR_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
- break;
- case 2:
- CLR_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
- CLR_SEL_TEMP_V_2; SET_SEL_TEMP_V_3;
- break;
- case 3:
- SET_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;
- SET_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;
- break;
- }
- }
- u16 tsc2000_read_channel (unsigned int channel)
- {
- u16 res;
- tsc2000_set_mux(channel);
- udelay(3 * TSC2000_DELAY_BASE);
- tsc2000_write(TSC2000_REG_ADC, 0x2036);
- adc_wait_conversion_done ();
- res = tsc2000_read(TSC2000_REG_AUX1);
- return res;
- }
- s32 tsc2000_contact_temp (void)
- {
- long adc_pt1000, offset;
- long u_pt1000;
- long contact_temp;
- tsc2000_reg_init ();
- tsc2000_set_range (3);
- adc_pt1000 = tsc2000_read_channel (14);
- debug ("read channel 14 (pt1000 adc value): %ld\n", adc_pt1000);
- offset = tsc2000_read_channel (15);
- debug ("read channel 15 (offset): %ld\n", offset);
- /*
- * Formula for calculating voltage drop on PT1000 resistor: u_pt1000 =
- * x_range3 * (adc_raw - offset) / 10. Formula to calculate x_range3:
- * x_range3 = (2500 * (1000000 + err_vref + err_amp3)) / (4095*6). The
- * error correction Values err_vref and err_amp3 are assumed as 0 in
- * u-boot, because this could cause only a very small error (< 1%).
- */
- u_pt1000 = (101750 * (adc_pt1000 - offset)) / 10;
- debug ("u_pt1000: %ld\n", u_pt1000);
- if (tsc2000_interpolate(u_pt1000, Pt1000_temp_table,
- &contact_temp) == -1) {
- printf ("%s: error interpolating PT1000 vlaue\n",
- __FUNCTION__);
- return (-1000);
- }
- debug ("contact_temp: %ld\n", contact_temp);
- return contact_temp;
- }
- void tsc2000_reg_init (void)
- {
- S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
- tsc2000_write(TSC2000_REG_ADC, 0x2036);
- tsc2000_write(TSC2000_REG_REF, 0x0011);
- tsc2000_write(TSC2000_REG_DACCTL, 0x0000);
- CON_MUX0;
- CON_MUX1;
- CON_MUX1_ENABLE;
- CON_MUX2_ENABLE;
- CON_MUX3_ENABLE;
- CON_MUX4_ENABLE;
- CON_SEL_TEMP_V_0;
- CON_SEL_TEMP_V_1;
- CON_SEL_TEMP_V_2;
- CON_SEL_TEMP_V_3;
- tsc2000_set_mux(0);
- tsc2000_set_range(0);
- }
- int tsc2000_interpolate(long value, long data[][2], long *result)
- {
- int i;
- /* the data is sorted and the first element is upper
- * limit so we can easily check for out-of-band values
- */
- if (data[0][0] < value || data[1][0] > value)
- return -1;
- i = 1;
- while (data[i][0] < value)
- i++;
- /* To prevent overflow we have to store the intermediate
- result in 'long long'.
- */
- *result = data[i-1][1] +
- ((unsigned long long)(data[i][1] - data[i-1][1])
- * (unsigned long long)(value - data[i-1][0]))
- / (data[i][0] - data[i-1][0]);
- return 0;
- }
- void adc_wait_conversion_done(void)
- {
- while (!(tsc2000_read(TSC2000_REG_ADC) & (1 << 14)));
- }
|