> From: "Theo de Raadt" <[email protected]>
> Date: Sun, 14 Aug 2016 10:51:19 -0600
>
> I am concerned with having a 25 x delay(1) in the refresh.
>
> Is possible to do the measurement startup -- then schedule a task
> to pick up the results?
I'm not too worried. There are worse offenders in the tree ;).
But since this is easy to fix, here is a new diff. We don't need
process context, a simple timeout does the job.
ok?
Index: arch/armv7/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/armv7/conf/GENERIC,v
retrieving revision 1.46
diff -u -p -r1.46 GENERIC
--- arch/armv7/conf/GENERIC 13 Aug 2016 22:07:01 -0000 1.46
+++ arch/armv7/conf/GENERIC 14 Aug 2016 17:44:14 -0000
@@ -45,6 +45,7 @@ imxiomuxc* at imx? # iomux controller
imxgpc* at fdt? # power controller
imxdog* at fdt? # watchdog timer
imxocotp* at imx? # on-chip otp controller
+imxtemp* at fdt? # temperature monitor
imxgpio* at fdt? # user-visible GPIO pins?
fec* at fdt? # Ethernet
imxuart* at fdt? # onboard uarts
Index: arch/armv7/imx/files.imx
===================================================================
RCS file: /cvs/src/sys/arch/armv7/imx/files.imx,v
retrieving revision 1.16
diff -u -p -r1.16 files.imx
--- arch/armv7/imx/files.imx 4 Aug 2016 14:31:50 -0000 1.16
+++ arch/armv7/imx/files.imx 14 Aug 2016 17:44:14 -0000
@@ -55,3 +55,7 @@ file arch/armv7/imx/imxesdhc.c imxesdhc
device imxahci: scsi, atascsi
attach imxahci at fdt
file arch/armv7/imx/imxahci.c imxahci
+
+device imxtemp
+attach imxtemp at fdt
+file arch/armv7/imx/imxtemp.c imxtemp
\ No newline at end of file
Index: arch/armv7/imx/imxocotp.c
===================================================================
RCS file: /cvs/src/sys/arch/armv7/imx/imxocotp.c,v
retrieving revision 1.2
diff -u -p -r1.2 imxocotp.c
--- arch/armv7/imx/imxocotp.c 6 Nov 2013 19:03:07 -0000 1.2
+++ arch/armv7/imx/imxocotp.c 14 Aug 2016 17:44:14 -0000
@@ -30,6 +30,9 @@
#include <armv7/imx/imxocotpvar.h>
/* registers */
+#define OCOTP_ANA0 0x4d0
+#define OCOTP_ANA1 0x4e0
+#define OCOTP_ANA2 0x4f0
#define OCOTP_MAC0 0x620
#define OCOTP_MAC1 0x630
@@ -79,4 +82,10 @@ imxocotp_get_ethernet_address(u_int8_t*
value = bus_space_read_4(imxocotp_sc->sc_iot, imxocotp_sc->sc_ioh,
OCOTP_MAC1);
mac[1] = value & 0xff;
mac[0] = (value >> 8) & 0xff;
+}
+
+uint32_t
+imxocotp_get_temperature_calibration(void)
+{
+ return bus_space_read_4(imxocotp_sc->sc_iot, imxocotp_sc->sc_ioh,
OCOTP_ANA1);
}
Index: arch/armv7/imx/imxocotpvar.h
===================================================================
RCS file: /cvs/src/sys/arch/armv7/imx/imxocotpvar.h,v
retrieving revision 1.1
diff -u -p -r1.1 imxocotpvar.h
--- arch/armv7/imx/imxocotpvar.h 6 Sep 2013 20:45:54 -0000 1.1
+++ arch/armv7/imx/imxocotpvar.h 14 Aug 2016 17:44:14 -0000
@@ -16,3 +16,4 @@
*/
void imxocotp_get_ethernet_address(u_int8_t* mac);
+uint32_t imxocotp_get_temperature_calibration(void);
Index: arch/armv7/imx/imxtemp.c
===================================================================
RCS file: arch/armv7/imx/imxtemp.c
diff -N arch/armv7/imx/imxtemp.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/armv7/imx/imxtemp.c 14 Aug 2016 17:44:14 -0000
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2014 Patrick Wildt <[email protected]>
+ * Copyright (c) 2016 Mark Kettenis <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/evcount.h>
+#include <sys/sensors.h>
+#include <sys/socket.h>
+#include <sys/timeout.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <armv7/armv7/armv7var.h>
+#include <armv7/imx/imxocotpvar.h>
+#include <armv7/imx/imxccmvar.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+/* registers */
+#define TEMPMON_TEMPSENSE0 0x180
+#define TEMPMON_TEMPSENSE0_SET 0x184
+#define TEMPMON_TEMPSENSE0_CLR 0x188
+#define TEMPMON_TEMPSENSE0_TOG 0x18c
+#define TEMPMON_TEMPSENSE1 0x190
+#define TEMPMON_TEMPSENSE1_SET 0x194
+#define TEMPMON_TEMPSENSE1_CLR 0x198
+#define TEMPMON_TEMPSENSE1_TOG 0x19c
+
+/* bits and bytes */
+#define TEMPMON_TEMPSENSE0_POWER_DOWN (1 << 0)
+#define TEMPMON_TEMPSENSE0_MEASURE_TEMP (1 << 1)
+#define TEMPMON_TEMPSENSE0_FINISHED (1 << 2)
+#define TEMPMON_TEMPSENSE0_TEMP_CNT_MASK 0xfff
+#define TEMPMON_TEMPSENSE0_TEMP_CNT_SHIFT 8
+#define TEMPMON_TEMPSENSE0_ALARM_VALUE_MASK 0xfff
+#define TEMPMON_TEMPSENSE0_ALARM_VALUE_SHIFT 20
+
+/* calibration */
+#define OCOTP_ANA1_HOT_TEMP_MASK 0xff
+#define OCOTP_ANA1_HOT_TEMP_SHIFT 0
+#define OCOTP_ANA1_HOT_COUNT_MASK 0xfff
+#define OCOTP_ANA1_HOT_COUNT_SHIFT 8
+#define OCOTP_ANA1_ROOM_COUNT_MASK 0xfff
+#define OCOTP_ANA1_ROOM_COUNT_SHIFT 20
+
+#define HREAD4(sc, reg)
\
+ (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
+#define HWRITE4(sc, reg, val) \
+ bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+#define HSET4(sc, reg, bits) \
+ HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
+#define HCLR4(sc, reg, bits) \
+ HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
+
+struct imxtemp_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ uint32_t sc_hot_count;
+ uint32_t sc_hot_temp;
+ uint32_t sc_room_count;
+
+ struct ksensor sc_sensor;
+ struct ksensordev sc_sensordev;
+ struct timeout sc_sensorto;
+};
+
+int imxtemp_match(struct device *, void *, void *);
+void imxtemp_attach(struct device *, struct device *, void *);
+
+struct cfattach imxtemp_ca = {
+ sizeof(struct imxtemp_softc), imxtemp_match, imxtemp_attach
+};
+
+struct cfdriver imxtemp_cd = {
+ NULL, "imxtemp", DV_DULL
+};
+
+int32_t imxtemp_calc_temp(struct imxtemp_softc *, uint32_t);
+void imxtemp_refresh_sensors(void *);
+void imxtemp_pickup_sensors(void *);
+
+int
+imxtemp_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ if (OF_is_compatible(faa->fa_node, "fsl,imx6q-anatop"))
+ return 10; /* Must beat simplebus(4). */
+
+ return 0;
+}
+
+void
+imxtemp_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct imxtemp_softc *sc = (struct imxtemp_softc *)self;
+ struct fdt_attach_args *faa = aux;
+ uint32_t calibration;
+
+ if (faa->fa_nreg < 1)
+ return;
+
+ sc->sc_iot = faa->fa_iot;
+ if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
+ faa->fa_reg[0].size, 0, &sc->sc_ioh))
+ panic("%s: bus_space_map failed!", __func__);
+
+ printf("\n");
+
+ calibration = imxocotp_get_temperature_calibration();
+ sc->sc_hot_count = (calibration >> OCOTP_ANA1_HOT_COUNT_SHIFT) &
+ OCOTP_ANA1_HOT_COUNT_MASK;
+ sc->sc_hot_temp = (calibration >> OCOTP_ANA1_HOT_TEMP_SHIFT) &
+ OCOTP_ANA1_HOT_TEMP_MASK;
+ sc->sc_room_count = (calibration >> OCOTP_ANA1_ROOM_COUNT_SHIFT) &
+ OCOTP_ANA1_ROOM_COUNT_MASK;
+
+ strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
+ sizeof(sc->sc_sensordev.xname));
+ strlcpy(sc->sc_sensor.desc, "core",
+ sizeof(sc->sc_sensor.desc));
+ sc->sc_sensor.type = SENSOR_TEMP;
+ sc->sc_sensor.flags = SENSOR_FINVALID;
+ sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
+ sensordev_install(&sc->sc_sensordev);
+ timeout_set(&sc->sc_sensorto, imxtemp_pickup_sensors, sc);
+ sensor_task_register(sc, imxtemp_refresh_sensors, 5);
+}
+
+int32_t
+imxtemp_calc_temp(struct imxtemp_softc *sc, uint32_t temp_cnt)
+{
+ int32_t value;
+
+ /*
+ * Calculate the calibrated tempterature based on the equation
+ * provided in the i.MX6 reference manual:
+ *
+ * Tmeas = HOT_TEMP - (Nmeas - HOT_COUNT) * ((HOT_TEMP - 25.0) /
+ * (ROOM_COUNT - HOT_COUNT))
+ *
+ * Note that we calculate the temperature in uC to avoid loss
+ * of precision.
+ */
+ value = ((sc->sc_hot_temp - 25) * 1000000) /
+ (sc->sc_room_count - sc->sc_hot_count);
+ value *= (temp_cnt - sc->sc_hot_count);
+ return ((sc->sc_hot_temp * 1000000) - value);
+}
+
+void
+imxtemp_refresh_sensors(void *arg)
+{
+ struct imxtemp_softc *sc = (struct imxtemp_softc *)arg;
+
+ timeout_del(&sc->sc_sensorto);
+
+ /* Power on temperature sensor. */
+ HCLR4(sc, TEMPMON_TEMPSENSE0, TEMPMON_TEMPSENSE0_POWER_DOWN);
+ HSET4(sc, TEMPMON_TEMPSENSE0, TEMPMON_TEMPSENSE0_MEASURE_TEMP);
+
+ /* It may require up to ~17us to complete a measurement. */
+ timeout_add_usec(&sc->sc_sensorto, 25);
+}
+
+void
+imxtemp_pickup_sensors(void *arg)
+{
+ struct imxtemp_softc *sc = (struct imxtemp_softc *)arg;
+ uint32_t value;
+ uint32_t temp_cnt;
+
+ value = HREAD4(sc, TEMPMON_TEMPSENSE0);
+
+ /* Power down temperature sensor. */
+ HCLR4(sc, TEMPMON_TEMPSENSE0, TEMPMON_TEMPSENSE0_MEASURE_TEMP);
+ HSET4(sc, TEMPMON_TEMPSENSE0, TEMPMON_TEMPSENSE0_POWER_DOWN);
+
+ if ((value & TEMPMON_TEMPSENSE0_FINISHED) == 0) {
+ sc->sc_sensor.flags |= SENSOR_FINVALID;
+ return;
+ }
+
+ temp_cnt = (value >> TEMPMON_TEMPSENSE0_TEMP_CNT_SHIFT) &
+ TEMPMON_TEMPSENSE0_TEMP_CNT_MASK;
+ sc->sc_sensor.value = imxtemp_calc_temp(sc, temp_cnt) + 273150000;
+ sc->sc_sensor.flags &= ~SENSOR_FINVALID;
+}