summary refs log tree commit diff stats
path: root/hw/misc/tmp105.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-11-17 16:41:47 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-11-17 16:41:47 +0000
commitc446ac37b7e79d971e55b3423981ada0c3db6459 (patch)
treef53b8231f446fee6d4d446ce00281113932ee4e2 /hw/misc/tmp105.c
parentc8e5c4b246584da36694a3c259a7dbb8a7e7b1f3 (diff)
parentab135622cf478585bdfcb68b85e4a817d74a0c42 (diff)
downloadfocaccia-qemu-c446ac37b7e79d971e55b3423981ada0c3db6459.tar.gz
focaccia-qemu-c446ac37b7e79d971e55b3423981ada0c3db6459.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20201117' into staging
target-arm queue:
 * hw/arm/virt: ARM_VIRT must select ARM_GIC
 * exynos: Fix bad printf format specifiers
 * hw/input/ps2.c: Remove remnants of printf debug
 * target/openrisc: Remove dead code attempting to check "is timer disabled"
 * register: Remove unnecessary NULL check
 * util/cutils: Fix Coverity array overrun in freq_to_str()
 * configure: Make "does libgio work" test pull in some actual functions
 * tmp105: reset the T_low and T_High registers
 * tmp105: Correct handling of temperature limit checks

# gpg: Signature made Tue 17 Nov 2020 13:47:48 GMT
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20201117:
  tmp105: Correct handling of temperature limit checks
  hw/misc/tmp105: reset the T_low and T_High registers
  configure: Make "does libgio work" test pull in some actual functions
  util/cutils: Fix Coverity array overrun in freq_to_str()
  register: Remove unnecessary NULL check
  target/openrisc: Remove dead code attempting to check "is timer disabled"
  hw/input/ps2.c: Remove remnants of printf debug
  exynos: Fix bad printf format specifiers
  hw/arm/virt: ARM_VIRT must select ARM_GIC

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/misc/tmp105.c')
-rw-r--r--hw/misc/tmp105.c73
1 files changed, 64 insertions, 9 deletions
diff --git a/hw/misc/tmp105.c b/hw/misc/tmp105.c
index b47120492a..d299d9b21b 100644
--- a/hw/misc/tmp105.c
+++ b/hw/misc/tmp105.c
@@ -41,16 +41,40 @@ static void tmp105_alarm_update(TMP105State *s)
             return;
     }
 
-    if ((s->config >> 1) & 1) {					/* TM */
-        if (s->temperature >= s->limit[1])
-            s->alarm = 1;
-        else if (s->temperature < s->limit[0])
-            s->alarm = 1;
+    if (s->config >> 1 & 1) {
+        /*
+         * TM == 1 : Interrupt mode. We signal Alert when the
+         * temperature rises above T_high, and expect the guest to clear
+         * it (eg by reading a device register).
+         */
+        if (s->detect_falling) {
+            if (s->temperature < s->limit[0]) {
+                s->alarm = 1;
+                s->detect_falling = false;
+            }
+        } else {
+            if (s->temperature >= s->limit[1]) {
+                s->alarm = 1;
+                s->detect_falling = true;
+            }
+        }
     } else {
-        if (s->temperature >= s->limit[1])
-            s->alarm = 1;
-        else if (s->temperature < s->limit[0])
-            s->alarm = 0;
+        /*
+         * TM == 0 : Comparator mode. We signal Alert when the temperature
+         * rises above T_high, and stop signalling it when the temperature
+         * falls below T_low.
+         */
+        if (s->detect_falling) {
+            if (s->temperature < s->limit[0]) {
+                s->alarm = 0;
+                s->detect_falling = false;
+            }
+        } else {
+            if (s->temperature >= s->limit[1]) {
+                s->alarm = 1;
+                s->detect_falling = true;
+            }
+        }
     }
 
     tmp105_interrupt_update(s);
@@ -197,6 +221,29 @@ static int tmp105_post_load(void *opaque, int version_id)
     return 0;
 }
 
+static bool detect_falling_needed(void *opaque)
+{
+    TMP105State *s = opaque;
+
+    /*
+     * We only need to migrate the detect_falling bool if it's set;
+     * for migration from older machines we assume that it is false
+     * (ie temperature is not out of range).
+     */
+    return s->detect_falling;
+}
+
+static const VMStateDescription vmstate_tmp105_detect_falling = {
+    .name = "TMP105/detect-falling",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = detect_falling_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_BOOL(detect_falling, TMP105State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static const VMStateDescription vmstate_tmp105 = {
     .name = "TMP105",
     .version_id = 0,
@@ -212,6 +259,10 @@ static const VMStateDescription vmstate_tmp105 = {
         VMSTATE_UINT8(alarm, TMP105State),
         VMSTATE_I2C_SLAVE(i2c, TMP105State),
         VMSTATE_END_OF_LIST()
+    },
+    .subsections = (const VMStateDescription*[]) {
+        &vmstate_tmp105_detect_falling,
+        NULL
     }
 };
 
@@ -224,6 +275,10 @@ static void tmp105_reset(I2CSlave *i2c)
     s->config = 0;
     s->faults = tmp105_faultq[(s->config >> 3) & 3];
     s->alarm = 0;
+    s->detect_falling = false;
+
+    s->limit[0] = 0x4b00; /* T_LOW, 75 degrees C */
+    s->limit[1] = 0x5000; /* T_HIGH, 80 degrees C */
 
     tmp105_interrupt_update(s);
 }