xref: /openbsd/sys/dev/i2c/thmc50.c (revision 4bdff4be)
1 /*	$OpenBSD: thmc50.c,v 1.5 2022/04/06 18:59:28 naddy Exp $	*/
2 
3 /*
4  * Copyright (c) 2007 Theo de Raadt
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/device.h>
22 #include <sys/sensors.h>
23 
24 #include <dev/i2c/i2cvar.h>
25 
26 /* THMC50 registers */
27 #define THMC50_TEMP0		0x27
28 #define THMC50_TEMP1		0x26
29 #define THMC50_TEMP2		0x20
30 
31 /* Sensors */
32 #define THMC_TEMP0		0
33 #define THMC_TEMP1		1
34 #define THMC_TEMP2		2
35 #define THMC_NUM_SENSORS	3
36 
37 struct thmc_softc {
38 	struct device	sc_dev;
39 	i2c_tag_t	sc_tag;
40 	i2c_addr_t	sc_addr;
41 
42 	struct ksensor	sc_sensor[THMC_NUM_SENSORS];
43 	struct ksensordev sc_sensordev;
44 };
45 
46 int	thmc_match(struct device *, void *, void *);
47 void	thmc_attach(struct device *, struct device *, void *);
48 void	thmc_refresh(void *);
49 
50 const struct cfattach thmc_ca = {
51 	sizeof(struct thmc_softc), thmc_match, thmc_attach
52 };
53 
54 struct cfdriver thmc_cd = {
55 	NULL, "thmc", DV_DULL
56 };
57 
58 int
59 thmc_match(struct device *parent, void *match, void *aux)
60 {
61 	struct i2c_attach_args *ia = aux;
62 
63 	if (strcmp(ia->ia_name, "thmc50") == 0 ||
64 	    strcmp(ia->ia_name, "adm1022") == 0 ||
65 	    strcmp(ia->ia_name, "adm1028") == 0)
66 		return (1);
67 	return (0);
68 }
69 
70 void
71 thmc_attach(struct device *parent, struct device *self, void *aux)
72 {
73 	struct thmc_softc *sc = (struct thmc_softc *)self;
74 	struct i2c_attach_args *ia = aux;
75 	int numsensors = THMC_NUM_SENSORS;
76 	int i;
77 
78 	sc->sc_tag = ia->ia_tag;
79 	sc->sc_addr = ia->ia_addr;
80 
81 	printf(": %s", ia->ia_name);
82 
83 	/* Initialize sensor data. */
84 	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
85 	    sizeof(sc->sc_sensordev.xname));
86 
87 	sc->sc_sensor[THMC_TEMP0].type = SENSOR_TEMP;
88 	strlcpy(sc->sc_sensor[THMC_TEMP0].desc, "Internal",
89 	    sizeof(sc->sc_sensor[THMC_TEMP0].desc));
90 
91 	sc->sc_sensor[THMC_TEMP1].type = SENSOR_TEMP;
92 	strlcpy(sc->sc_sensor[THMC_TEMP1].desc, "External",
93 	    sizeof(sc->sc_sensor[THMC_TEMP1].desc));
94 
95 	if (strcmp(ia->ia_name, "adm1022") == 0) {
96 		/* Only the adm1022 has a THMC50_TEMP2 sensor */
97 		sc->sc_sensor[THMC_TEMP2].type = SENSOR_TEMP;
98 		strlcpy(sc->sc_sensor[THMC_TEMP2].desc, "External",
99 		    sizeof(sc->sc_sensor[THMC_TEMP2].desc));
100 	} else {
101 		sc->sc_sensor[THMC_TEMP2].type = -1;
102 		numsensors--;
103 	}
104 
105 	if (sensor_task_register(sc, thmc_refresh, 5) == NULL) {
106 		printf(", unable to register update task\n");
107 		return;
108 	}
109 
110 	for (i = 0; i < numsensors; i++)
111 		sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
112 	sensordev_install(&sc->sc_sensordev);
113 
114 	printf("\n");
115 }
116 
117 void
118 thmc_refresh(void *arg)
119 {
120 	struct thmc_softc *sc = arg;
121 	u_int8_t cmd;
122 	int8_t sdata;
123 
124 	iic_acquire_bus(sc->sc_tag, 0);
125 
126 	cmd = THMC50_TEMP0;
127 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
128 	    sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) {
129 		sc->sc_sensor[THMC_TEMP0].value = 273150000 + 1000000 * sdata;
130 		sc->sc_sensor[THMC_TEMP0].flags &= ~SENSOR_FINVALID;
131 	} else
132 		sc->sc_sensor[THMC_TEMP0].flags |= SENSOR_FINVALID;
133 
134 	cmd = THMC50_TEMP1;
135 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
136 	    sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) {
137 		sc->sc_sensor[THMC_TEMP1].value = 273150000 + 1000000 * sdata;
138 		sc->sc_sensor[THMC_TEMP1].flags &= ~SENSOR_FINVALID;
139 	} else
140 		sc->sc_sensor[THMC_TEMP1].flags |= SENSOR_FINVALID;
141 
142 	if (sc->sc_sensor[THMC_TEMP2].type > 0) {
143 		cmd = THMC50_TEMP2;
144 		if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
145 		    sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) {
146 			sc->sc_sensor[THMC_TEMP2].value = 273150000 + 1000000 * sdata;
147 			sc->sc_sensor[THMC_TEMP2].flags &= ~SENSOR_FINVALID;
148 		} else
149 			sc->sc_sensor[THMC_TEMP2].flags |= SENSOR_FINVALID;
150 	}
151 
152 	iic_release_bus(sc->sc_tag, 0);
153 }
154