2 * Texas Instruments TMP105 temperature sensor.
4 * Copyright (C) 2008 Nokia Corporation
5 * Written by Andrzej Zaborowski <andrew@openedhand.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 or
10 * (at your option) version 3 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
40 static void tmp105_interrupt_update(struct tmp105_s
*s
)
42 qemu_set_irq(s
->pin
, s
->alarm
^ ((~s
->config
>> 2) & 1)); /* POL */
45 static void tmp105_alarm_update(struct tmp105_s
*s
)
47 if ((s
->config
>> 0) & 1) { /* SD */
48 if ((s
->config
>> 7) & 1) /* OS */
49 s
->config
&= ~(1 << 7); /* OS */
54 if ((s
->config
>> 1) & 1) { /* TM */
55 if (s
->temperature
>= s
->limit
[1])
57 else if (s
->temperature
< s
->limit
[0])
60 if (s
->temperature
>= s
->limit
[1])
62 else if (s
->temperature
< s
->limit
[0])
66 tmp105_interrupt_update(s
);
69 /* Units are 0.001 centigrades relative to 0 C. */
70 void tmp105_set(i2c_slave
*i2c
, int temp
)
72 struct tmp105_s
*s
= (struct tmp105_s
*) i2c
;
74 if (temp
>= 128000 || temp
< -128000) {
75 fprintf(stderr
, "%s: values is out of range (%i.%03i C)\n",
76 __FUNCTION__
, temp
/ 1000, temp
% 1000);
80 s
->temperature
= ((int16_t) (temp
* 0x800 / 128000)) << 4;
82 tmp105_alarm_update(s
);
85 static const int tmp105_faultq
[4] = { 1, 2, 4, 6 };
87 static void tmp105_read(struct tmp105_s
*s
)
91 if ((s
->config
>> 1) & 1) { /* TM */
93 tmp105_interrupt_update(s
);
96 switch (s
->pointer
& 3) {
97 case 0: /* Temperature */
98 s
->buf
[s
->len
++] = (((uint16_t) s
->temperature
) >> 8);
99 s
->buf
[s
->len
++] = (((uint16_t) s
->temperature
) >> 0) &
100 (0xf0 << ((~s
->config
>> 5) & 3)); /* R */
103 case 1: /* Configuration */
104 s
->buf
[s
->len
++] = s
->config
;
108 s
->buf
[s
->len
++] = ((uint16_t) s
->limit
[0]) >> 8;
109 s
->buf
[s
->len
++] = ((uint16_t) s
->limit
[0]) >> 0;
113 s
->buf
[s
->len
++] = ((uint16_t) s
->limit
[1]) >> 8;
114 s
->buf
[s
->len
++] = ((uint16_t) s
->limit
[1]) >> 0;
119 static void tmp105_write(struct tmp105_s
*s
)
121 switch (s
->pointer
& 3) {
122 case 0: /* Temperature */
125 case 1: /* Configuration */
126 if (s
->buf
[0] & ~s
->config
& (1 << 0)) /* SD */
127 printf("%s: TMP105 shutdown\n", __FUNCTION__
);
128 s
->config
= s
->buf
[0];
129 s
->faults
= tmp105_faultq
[(s
->config
>> 3) & 3]; /* F */
130 tmp105_alarm_update(s
);
136 s
->limit
[s
->pointer
& 1] = (int16_t)
137 ((((uint16_t) s
->buf
[0]) << 8) | s
->buf
[1]);
138 tmp105_alarm_update(s
);
143 static int tmp105_rx(i2c_slave
*i2c
)
145 struct tmp105_s
*s
= (struct tmp105_s
*) i2c
;
148 return s
->buf
[s
->len
++];
153 static int tmp105_tx(i2c_slave
*i2c
, uint8_t data
)
155 struct tmp105_s
*s
= (struct tmp105_s
*) i2c
;
161 s
->buf
[s
->len
- 1] = data
;
168 static void tmp105_event(i2c_slave
*i2c
, enum i2c_event event
)
170 struct tmp105_s
*s
= (struct tmp105_s
*) i2c
;
172 if (event
== I2C_START_RECV
)
178 static void tmp105_save(QEMUFile
*f
, void *opaque
)
180 struct tmp105_s
*s
= (struct tmp105_s
*) opaque
;
182 qemu_put_byte(f
, s
->len
);
183 qemu_put_8s(f
, &s
->buf
[0]);
184 qemu_put_8s(f
, &s
->buf
[1]);
186 qemu_put_8s(f
, &s
->pointer
);
187 qemu_put_8s(f
, &s
->config
);
188 qemu_put_be16s(f
, (uint16_t *) &s
->temperature
);
189 qemu_put_be16s(f
, (uint16_t *) &s
->limit
[0]);
190 qemu_put_be16s(f
, (uint16_t *) &s
->limit
[1]);
191 qemu_put_byte(f
, s
->alarm
);
192 s
->faults
= tmp105_faultq
[(s
->config
>> 3) & 3]; /* F */
194 i2c_slave_save(f
, &s
->i2c
);
197 static int tmp105_load(QEMUFile
*f
, void *opaque
, int version_id
)
199 struct tmp105_s
*s
= (struct tmp105_s
*) opaque
;
201 s
->len
= qemu_get_byte(f
);
202 qemu_get_8s(f
, &s
->buf
[0]);
203 qemu_get_8s(f
, &s
->buf
[1]);
205 qemu_get_8s(f
, &s
->pointer
);
206 qemu_get_8s(f
, &s
->config
);
207 qemu_get_be16s(f
, (uint16_t *) &s
->temperature
);
208 qemu_get_be16s(f
, (uint16_t *) &s
->limit
[0]);
209 qemu_get_be16s(f
, (uint16_t *) &s
->limit
[1]);
210 s
->alarm
= qemu_get_byte(f
);
212 tmp105_interrupt_update(s
);
214 i2c_slave_load(f
, &s
->i2c
);
218 void tmp105_reset(i2c_slave
*i2c
)
220 struct tmp105_s
*s
= (struct tmp105_s
*) i2c
;
225 s
->faults
= tmp105_faultq
[(s
->config
>> 3) & 3];
228 tmp105_interrupt_update(s
);
231 static int tmp105_iid
= 0;
233 struct i2c_slave
*tmp105_init(i2c_bus
*bus
, qemu_irq alarm
)
235 struct tmp105_s
*s
= (struct tmp105_s
*)
236 i2c_slave_init(bus
, 0, sizeof(struct tmp105_s
));
238 s
->i2c
.event
= tmp105_event
;
239 s
->i2c
.recv
= tmp105_rx
;
240 s
->i2c
.send
= tmp105_tx
;
243 tmp105_reset(&s
->i2c
);
245 register_savevm("TMP105", tmp105_iid
++, 0,
246 tmp105_save
, tmp105_load
, s
);