2 * Copyright (c) 2016 Andriy Gapon <avg@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
29 #include <sys/param.h>
30 #include <sys/kernel.h>
32 #include <sys/endian.h>
33 #include <sys/module.h>
35 #include <sys/sysctl.h>
36 #include <sys/systm.h>
38 #include <dev/smbus/smbconf.h>
39 #include <dev/smbus/smbus.h>
45 * SMBus specification defines little-endian byte order,
46 * but it seems that the JEDEC devices expect it to
50 ts_readw_be(device_t dev, uint8_t reg, uint16_t *val)
52 device_t bus = device_get_parent(dev);
53 uint8_t addr = smbus_get_addr(dev);
56 err = smbus_readw(bus, addr, reg, val);
64 ts_temp_sysctl(SYSCTL_HANDLER_ARGS)
71 err = ts_readw_be(dev, 5, &val);
76 * Convert the reading to temperature in 0.0001 Kelvins.
77 * Three most significant bits are flags, the next
78 * most significant bit is a sign bit.
79 * Each step is 0.0625 degrees.
82 if ((val & 0x1000) != 0)
84 temp = temp * 625 + 2731500;
85 err = sysctl_handle_int(oidp, &temp, 0, req);
90 ts_probe(device_t dev)
92 device_set_desc(dev, "DIMM memory sensor");
93 return (BUS_PROBE_DEFAULT);
97 ts_attach(device_t dev)
99 struct sysctl_ctx_list *ctx;
100 struct sysctl_oid_list *tree;
106 addr = smbus_get_addr(dev);
107 if ((addr & 0xf0) != 0x30) {
108 /* Up to 8 slave devices starting at 0x30. */
112 err = ts_readw_be(dev, 6, &vendorid);
114 device_printf(dev, "failed to read Manufacturer ID\n");
117 err = ts_readw_be(dev, 7, &devid);
119 device_printf(dev, "failed to read Device ID\n");
122 if ((devid & 0xff00) == 0x2200) {
124 * Defined by JEDEC Standard No. 21-C, Release 26,
127 } else if (vendorid == 0x104a) {
129 * STMicroelectronics datasheets say that
130 * device ID and revision can vary.
131 * E.g. STT424E02, Doc ID 13448 Rev 8,
132 * section 4.6, page 26.
134 } else if (vendorid == 0xb3 && (devid & 0xff00) == 0x2900) {
136 * IDT TS3000B3A and TSE2002B3C chips and their variants.
137 * Revision IDs (the lower byte) can vary.
138 * http://www.idt.com/sites/default/files/documents/IDT_TSE2002B3C_DST_20100512_120303152056.pdf
139 * http://www.idt.com/sites/default/files/documents/IDT_TS3000B3A_DST_20101129_120303152013.pdf
143 device_printf(dev, "Unknown Manufacturer and Device IDs"
144 ", 0x%x and 0x%x\n", vendorid, devid);
149 ctx = device_get_sysctl_ctx(dev);
150 tree = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
152 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "temp",
153 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0,
154 ts_temp_sysctl, "IK4", "Current temperature");
160 ts_detach(device_t dev)
166 static device_method_t jedec_ts_methods[] = {
167 /* Methods from the device interface */
168 DEVMETHOD(device_probe, ts_probe),
169 DEVMETHOD(device_attach, ts_attach),
170 DEVMETHOD(device_detach, ts_detach),
172 /* Terminate method list */
176 static driver_t jedec_ts_driver = {
182 static devclass_t jedec_ts_devclass;
184 DRIVER_MODULE(jedec_ts, smbus, jedec_ts_driver, jedec_ts_devclass, 0, 0);
185 MODULE_DEPEND(jedec_ts, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
186 MODULE_VERSION(jedec_ts, 1);