/*
 * (C) Copyright 2001
 * Bill Hunter,  Wave 7 Optics, williamhunter@mediaone.net
 *
 * 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
 */

/*
 * On Semiconductor's LM75 Temperature Sensor
 */

#include <common.h>

#if !defined(CFG_EEPROM_PAGE_WRITE_ENABLE) || \
	(CFG_EEPROM_PAGE_WRITE_BITS < 1)
# error "CFG_EEPROM_PAGE_WRITE_ENABLE must be defined and CFG_EEPROM_PAGE_WRITE_BITS must be greater than  1 to use CONFIG_DTT_LM75"
#endif

#include <i2c.h>
#include <dtt.h>

/*
 * Device code
 */
#if defined(CFG_I2C_DTT_ADDR)
#define DTT_I2C_DEV_CODE CFG_I2C_DTT_ADDR
#else
#define DTT_I2C_DEV_CODE 0x48			/* ON Semi's LM75 device */
#endif
#define DTT_READ_TEMP		0x0
#define DTT_CONFIG		0x1
#define DTT_TEMP_HYST		0x2
#define DTT_TEMP_SET		0x3

int dtt_read(int sensor, int reg)
{
    int dlen;
    uchar data[2];

#ifdef CONFIG_DTT_AD7414
    /*
     * On AD7414 the first value upon bootup is not read correctly.
     * This is most likely because of the 800ms update time of the
     * temp register in normal update mode. To get current values
     * each time we issue the "dtt" command including upon powerup
     * we switch into one-short mode.
     *
     * Issue one-shot mode command
     */
    dtt_write(sensor, DTT_CONFIG, 0x64);
#endif

    /*
     * Validate 'reg' param
     */
    if((reg < 0) || (reg > 3))
	return -1;

    /*
     * Calculate sensor address and register.
     */
    sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */

    /*
     * Prepare to handle 2 byte result.
     */
    if ((reg == DTT_READ_TEMP) ||
	(reg == DTT_TEMP_HYST) ||
	(reg == DTT_TEMP_SET))
	dlen = 2;
    else
	dlen = 1;

    /*
     * Now try to read the register.
     */
    if (i2c_read(sensor, reg, 1, data, dlen) != 0)
	return -1;

    /*
     * Handle 2 byte result.
     */
    if (dlen == 2)
	return ((int)((short)data[1] + (((short)data[0]) << 8)));


    return (int)data[0];
} /* dtt_read() */


int dtt_write(int sensor, int reg, int val)
{
    int dlen;
    uchar data[2];

    /*
     * Validate 'reg' param
     */
    if ((reg < 0) || (reg > 3))
	return 1;

    /*
     * Calculate sensor address and register.
     */
    sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */

    /*
     * Handle 2 byte values.
     */
    if ((reg == DTT_READ_TEMP) ||
	(reg == DTT_TEMP_HYST) ||
	(reg == DTT_TEMP_SET)) {
	dlen = 2;
	data[0] = (char)((val >> 8) & 0xff);	/* MSB first */
	data[1] = (char)(val & 0xff);
    } else {
	dlen = 1;
	data[0] = (char)(val & 0xff);
    }

    /*
     * Write value to register.
     */
    if (i2c_write(sensor, reg, 1, data, dlen) != 0)
	return 1;

    return 0;
} /* dtt_write() */


static int _dtt_init(int sensor)
{
    int val;

    /*
     * Setup TSET ( trip point ) register
     */
    val = ((CFG_DTT_MAX_TEMP * 2) << 7) & 0xff80; /* trip */
    if (dtt_write(sensor, DTT_TEMP_SET, val) != 0)
	return 1;

    /*
     * Setup THYST ( untrip point ) register - Hysteresis
     */
    val = (((CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS) * 2) << 7) & 0xff80;
    if (dtt_write(sensor, DTT_TEMP_HYST, val) != 0)
	return 1;

    /*
     * Setup configuraton register
     */
#ifdef CONFIG_DTT_AD7414
    /* config = alert active low and disabled */
    val = 0x60;
#else
    /* config = 6 sample integration, int mode, active low, and enable */
    val = 0x18;
#endif
    if (dtt_write(sensor, DTT_CONFIG, val) != 0)
	return 1;

    return 0;
} /* _dtt_init() */


int dtt_init (void)
{
    int i;
    unsigned char sensors[] = CONFIG_DTT_SENSORS;
    const char *const header = "DTT:   ";

    for (i = 0; i < sizeof(sensors); i++) {
	if (_dtt_init(sensors[i]) != 0)
	    printf("%s%d FAILED INIT\n", header, i+1);
	else
	    printf("%s%d is %i C\n", header, i+1,
		   dtt_get_temp(sensors[i]));
    }

    return (0);
} /* dtt_init() */

int dtt_get_temp(int sensor)
{
    int const ret = dtt_read(sensor, DTT_READ_TEMP);

    if (ret < 0) {
	printf("DTT temperature read failed.\n");
	return 0;
    }
    return (int)((int16_t) ret / 256);
} /* dtt_get_temp() */
