1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
/*
* (C) Copyright 2007-2008
* Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
* based on lm75.c by Bill Hunter
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* National LM63/LM64 Temperature Sensor
* Main difference: LM 64 has -16 Kelvin temperature offset
*/
#include <common.h>
#include <i2c.h>
#include <dtt.h>
#define DTT_I2C_LM63_ADDR 0x4C /* National LM63 device */
#define DTT_READ_TEMP_RMT_MSB 0x01
#define DTT_CONFIG 0x03
#define DTT_READ_TEMP_RMT_LSB 0x10
#define DTT_TACHLIM_LSB 0x48
#define DTT_TACHLIM_MSB 0x49
#define DTT_FAN_CONFIG 0x4A
#define DTT_PWM_FREQ 0x4D
#define DTT_PWM_LOOKUP_BASE 0x50
struct pwm_lookup_entry {
u8 temp;
u8 pwm;
};
/*
* Device code
*/
int dtt_read(int sensor, int reg)
{
int dlen;
uchar data[2];
/*
* Calculate sensor address and register.
*/
if (!sensor)
sensor = DTT_I2C_LM63_ADDR; /* legacy config */
dlen = 1;
/*
* Now try to read the register.
*/
if (i2c_read(sensor, reg, 1, data, dlen) != 0)
return -1;
return (int)data[0];
} /* dtt_read() */
int dtt_write(int sensor, int reg, int val)
{
int dlen;
uchar data[2];
/*
* Calculate sensor address and register.
*/
if (!sensor)
sensor = DTT_I2C_LM63_ADDR; /* legacy config */
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 is_lm64(int sensor)
{
return sensor && (sensor != DTT_I2C_LM63_ADDR);
}
int dtt_init_one(int sensor)
{
int i;
int val;
struct pwm_lookup_entry pwm_lookup[] = CONFIG_DTT_PWM_LOOKUPTABLE;
/*
* Set PWM Frequency to 2.5% resolution
*/
val = 20;
if (dtt_write(sensor, DTT_PWM_FREQ, val) != 0)
return 1;
/*
* Set Tachometer Limit
*/
val = CONFIG_DTT_TACH_LIMIT;
if (dtt_write(sensor, DTT_TACHLIM_LSB, val & 0xff) != 0)
return 1;
if (dtt_write(sensor, DTT_TACHLIM_MSB, (val >> 8) & 0xff) != 0)
return 1;
/*
* Make sure PWM Lookup-Table is writeable
*/
if (dtt_write(sensor, DTT_FAN_CONFIG, 0x20) != 0)
return 1;
/*
* Setup PWM Lookup-Table
*/
for (i = 0; i < ARRAY_SIZE(pwm_lookup); i++) {
int address = DTT_PWM_LOOKUP_BASE + 2 * i;
val = pwm_lookup[i].temp;
if (is_lm64(sensor))
val -= 16;
if (dtt_write(sensor, address, val) != 0)
return 1;
val = dtt_read(sensor, address);
val = pwm_lookup[i].pwm;
if (dtt_write(sensor, address + 1, val) != 0)
return 1;
}
/*
* Enable PWM Lookup-Table, PWM Clock 360 kHz, Tachometer Mode 2
*/
val = 0x02;
if (dtt_write(sensor, DTT_FAN_CONFIG, val) != 0)
return 1;
/*
* Enable Tach input
*/
val = dtt_read(sensor, DTT_CONFIG) | 0x04;
if (dtt_write(sensor, DTT_CONFIG, val) != 0)
return 1;
return 0;
}
int dtt_get_temp(int sensor)
{
s16 temp = (dtt_read(sensor, DTT_READ_TEMP_RMT_MSB) << 8)
| (dtt_read(sensor, DTT_READ_TEMP_RMT_LSB));
if (is_lm64(sensor))
temp += 16 << 8;
/* Ignore LSB for now, U-Boot only prints natural numbers */
return temp >> 8;
}
|