FreeBSD kernel IICBUS device code
tmp461.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2021 Alstom Group.
5 * Copyright (c) 2021 Semihalf.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD$");
30
31#include "opt_platform.h"
32
33#include <sys/param.h>
34#include <sys/bus.h>
35#include <sys/module.h>
36#include <sys/ctype.h>
37#include <sys/kernel.h>
38#include <sys/libkern.h>
39#include <sys/sysctl.h>
40
41#include <dev/iicbus/iicbus.h>
42#include <dev/iicbus/iiconf.h>
43
44#include <dev/ofw/ofw_bus_subr.h>
45#include <dev/ofw/ofw_bus.h>
46
47#define BIT(x) (1UL << (x))
48
49#define TMP461_LOCAL_TEMP_REG_MSB 0x0
50#define TMP461_LOCAL_TEMP_REG_LSB 0x15
51#define TMP461_GLOBAL_TEMP_REG_MSB 0x1
52#define TMP461_GLOBAL_TEMP_REG_LSB 0x10
53#define TMP461_CONFIG_REG 0x3
54#define TMP461_CONFIG_REG_TEMP_RANGE_BIT BIT(2)
55
56#define TMP461_EXTENDED_TEMP_MODIFIER 64
57/* 28.4 fixed point representation of 273.15f */
58#define TMP461_C_TO_K_FIX 4370
59#define TMP461_TEMP_LSB 0
60
61static int tmp461_probe(device_t dev);
62static int tmp461_attach(device_t dev);
63static int tmp461_read_1(device_t dev, uint8_t reg, uint8_t *data);
64static int tmp461_read_temp(device_t dev, int32_t *temp);
65static int tmp461_detach(device_t dev);
66static int tmp461_sensor_sysctl(SYSCTL_HANDLER_ARGS);
67static int32_t tmp461_signed_extend32(uint32_t value, int sign_pos);
68
69static device_method_t tmp461_methods[] = {
70 DEVMETHOD(device_probe, tmp461_probe),
71 DEVMETHOD(device_attach, tmp461_attach),
72 DEVMETHOD(device_detach, tmp461_detach),
73
74 DEVMETHOD_END
75};
76
77static driver_t tmp461_driver = {
78 "tmp461_dev",
80 0
81};
82
83static devclass_t tmp461_devclass;
84
85static struct ofw_compat_data tmp461_compat_data[] = {
86 { "ti,tmp461", 1 },
87 { NULL, 0 }
88};
89
92
93static int
95{
96 struct sysctl_oid *sensor_root_oid;
97 struct sysctl_ctx_list *ctx;
98
99 ctx = device_get_sysctl_ctx(dev);
100
101 sensor_root_oid = SYSCTL_ADD_NODE(ctx, SYSCTL_STATIC_CHILDREN(_hw),
102 OID_AUTO, "temperature", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
103 "TMP 461 Thermal Sensor Information");
104 if (sensor_root_oid == NULL)
105 return (ENXIO);
106
107 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(sensor_root_oid), OID_AUTO,
108 "tmp461", CTLTYPE_INT | CTLFLAG_RD, dev, 0,
109 tmp461_sensor_sysctl, "IK0", "TMP461 Thermal Sensor");
110
111 return (0);
112}
113
114static int
116{
117
118 if (!ofw_bus_status_okay(dev))
119 return (ENXIO);
120
121 if (!ofw_bus_search_compatible(dev, tmp461_compat_data)->ocd_data)
122 return (ENXIO);
123
124 device_set_desc(dev, "TMP461 Thermal Sensor");
125
126 return (BUS_PROBE_GENERIC);
127}
128
129static int
131{
132
133 return (0);
134}
135
136static int
137tmp461_read_1(device_t dev, uint8_t reg, uint8_t *data)
138{
139 int error;
140
141 error = iicdev_readfrom(dev, reg, (void *) data, 1, IIC_WAIT);
142 if (error != 0)
143 device_printf(dev, "Failed to read from device\n");
144
145 return (error);
146}
147
148static int
149tmp461_read_temp(device_t dev, int32_t *temp)
150{
151 bool extended_mode;
152 uint8_t data;
153 int error;
154
155 /* read temperature range */
157 if (error != 0)
158 return (ENXIO);
159
160 extended_mode = data & TMP461_CONFIG_REG_TEMP_RANGE_BIT;
161
162 /* read temp MSB */
164 if (error != 0)
165 return (ENXIO);
166
167 *temp = signed_extend32(data, TMP461_TEMP_LSB, 8) -
168 (extended_mode ? TMP461_EXTENDED_TEMP_MODIFIER : 0);
169
171 if (error != 0)
172 return (ENXIO);
173
174 *temp = (((*temp << 4) | (data >> 4)) + TMP461_C_TO_K_FIX) >> 4;
175
176 return (0);
177}
178
179static int
180tmp461_sensor_sysctl(SYSCTL_HANDLER_ARGS)
181{
182 device_t dev;
183 int32_t temp;
184 int error;
185
186 dev = arg1;
187
188 error = tmp461_read_temp(dev, &temp);
189 if (error != 0)
190 return (error);
191
192 return (sysctl_handle_int(oidp, &temp, 0, req));
193}
194
caddr_t data
Definition: iicbb_if.m:61
INTERFACE iicbus
Definition: iicbus_if.m:32
int iicdev_readfrom(device_t slavedev, uint8_t regaddr, void *buffer, uint16_t buflen, int waithow)
Definition: iiconf.c:524
#define IIC_WAIT
Definition: iiconf.h:46
device_t dev
Definition: ofw_iicbus_if.m:38
static device_method_t tmp461_methods[]
Definition: tmp461.c:69
#define TMP461_TEMP_LSB
Definition: tmp461.c:59
static int tmp461_probe(device_t dev)
Definition: tmp461.c:115
static int tmp461_read_1(device_t dev, uint8_t reg, uint8_t *data)
Definition: tmp461.c:137
IICBUS_FDT_PNP_INFO(tmp461_compat_data)
#define TMP461_CONFIG_REG_TEMP_RANGE_BIT
Definition: tmp461.c:54
static int tmp461_sensor_sysctl(SYSCTL_HANDLER_ARGS)
Definition: tmp461.c:180
#define TMP461_LOCAL_TEMP_REG_LSB
Definition: tmp461.c:50
__FBSDID("$FreeBSD$")
static int tmp461_detach(device_t dev)
Definition: tmp461.c:130
static struct ofw_compat_data tmp461_compat_data[]
Definition: tmp461.c:85
#define TMP461_C_TO_K_FIX
Definition: tmp461.c:58
#define TMP461_EXTENDED_TEMP_MODIFIER
Definition: tmp461.c:56
DRIVER_MODULE(tmp461, iicbus, tmp461_driver, tmp461_devclass, 0, 0)
static int tmp461_read_temp(device_t dev, int32_t *temp)
Definition: tmp461.c:149
static int tmp461_attach(device_t dev)
Definition: tmp461.c:94
#define TMP461_CONFIG_REG
Definition: tmp461.c:53
static int32_t tmp461_signed_extend32(uint32_t value, int sign_pos)
#define TMP461_LOCAL_TEMP_REG_MSB
Definition: tmp461.c:49
static devclass_t tmp461_devclass
Definition: tmp461.c:83
static driver_t tmp461_driver
Definition: tmp461.c:77