mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-26 22:52:18 +00:00
42d1f0394b
- Added Motorola CPU 8540/8560 support (cpu/85xx) - Added Motorola MPC8540ADS board support (board/mpc8540ads) - Added Motorola MPC8560ADS board support (board/mpc8560ads) * Minor code cleanup
319 lines
6.8 KiB
C
319 lines
6.8 KiB
C
/*
|
|
* 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)));
|
|
}
|