Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146766556
D36464.id110379.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D36464.id110379.diff
View Options
Index: sys/dev/iicbus/tmp461.c
===================================================================
--- sys/dev/iicbus/tmp461.c
+++ sys/dev/iicbus/tmp461.c
@@ -32,6 +32,8 @@
#include <sys/param.h>
#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/ctype.h>
#include <sys/kernel.h>
@@ -46,22 +48,37 @@
#define BIT(x) (1UL << (x))
+/* register map */
#define TMP461_LOCAL_TEMP_REG_MSB 0x0
#define TMP461_LOCAL_TEMP_REG_LSB 0x15
#define TMP461_GLOBAL_TEMP_REG_MSB 0x1
#define TMP461_GLOBAL_TEMP_REG_LSB 0x10
-#define TMP461_CONFIG_REG 0x3
+#define TMP461_STATUS_REG 0x2
+#define TMP461_STATUS_REG_TEMP_LOCAL BIT(2)
+#define TMP461_CONFIG_REG_R 0x3
+#define TMP461_CONFIG_REG_W 0x9
#define TMP461_CONFIG_REG_TEMP_RANGE_BIT BIT(2)
-
+#define TMP461_CONFIG_REG_STANDBY_BIT BIT(6)
+#define TMP461_CONVERSION_RATE_REG 0x4
+#define TMP461_ONESHOT_REG 0xF
#define TMP461_EXTENDED_TEMP_MODIFIER 64
+
/* 28.4 fixed point representation of 273.15f */
#define TMP461_C_TO_K_FIX 4370
-#define TMP461_TEMP_LSB 0
+
+#define TMP461_SENSOR_MAX_CONV_TIME 16000000
+#define TMP461_LOCAL_MEASURE 0
+#define TMP461_REMOTE_MEASURE 1
+
+/* flags */
+#define TMP461_LOCAL_TEMP_DOUBLE_REG BIT(0)
+#define TMP461_REMOTE_TEMP_DOUBLE_REG BIT(1)
static int tmp461_probe(device_t dev);
static int tmp461_attach(device_t dev);
static int tmp461_read_1(device_t dev, uint8_t reg, uint8_t *data);
-static int tmp461_read_temp(device_t dev, int32_t *temp);
+static int tmp461_write_1(device_t dev, uint8_t reg, uint8_t data);
+static int tmp461_read_temperature(device_t dev, int32_t *temperature, bool mode);
static int tmp461_detach(device_t dev);
static int tmp461_sensor_sysctl(SYSCTL_HANDLER_ARGS);
@@ -73,15 +90,34 @@
DEVMETHOD_END
};
+struct tmp461_softc {
+ struct mtx mtx;
+ uint8_t conf;
+};
+
static driver_t tmp461_driver = {
"tmp461_dev",
tmp461_methods,
- 0
+ sizeof(struct tmp461_softc)
+};
+
+struct tmp461_data {
+ const char *compat;
+ const char *desc;
+ uint8_t flags;
+};
+
+static struct tmp461_data sensor_list[] = {
+ {"adt7461", "ADT7461 Thernal Sensor Information",
+ TMP461_REMOTE_TEMP_DOUBLE_REG},
+ {"tmp461", "TMP461 Thernal Sensor Information",
+ TMP461_LOCAL_TEMP_DOUBLE_REG | TMP461_REMOTE_TEMP_DOUBLE_REG}
};
static struct ofw_compat_data tmp461_compat_data[] = {
- { "ti,tmp461", 1 },
- { NULL, 0 }
+ {"adi,adt7461", (uintptr_t)&sensor_list[0]},
+ {"ti,tmp461", (uintptr_t)&sensor_list[1]},
+ {NULL, 0}
};
DRIVER_MODULE(tmp461, iicbus, tmp461_driver, 0, 0);
@@ -91,19 +127,47 @@
tmp461_attach(device_t dev)
{
struct sysctl_oid *sensor_root_oid;
+ struct tmp461_data *compat_data;
struct sysctl_ctx_list *ctx;
+ struct tmp461_softc *sc;
+ uint8_t data;
+ sc = device_get_softc(dev);
+ compat_data = (struct tmp461_data *)
+ ofw_bus_search_compatible(dev, tmp461_compat_data)->ocd_data;
+ sc->conf = compat_data->flags;
ctx = device_get_sysctl_ctx(dev);
-
+
+ mtx_init(&sc->mtx, "tmp461 temperature", "temperature", MTX_DEF);
+
sensor_root_oid = SYSCTL_ADD_NODE(ctx, SYSCTL_STATIC_CHILDREN(_hw),
OID_AUTO, "temperature", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
- "TMP 461 Thermal Sensor Information");
+ "Thermal Sensor Information");
if (sensor_root_oid == NULL)
return (ENXIO);
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(sensor_root_oid), OID_AUTO,
- "tmp461", CTLTYPE_INT | CTLFLAG_RD, dev, 0,
- tmp461_sensor_sysctl, "IK0", "TMP461 Thermal Sensor");
+ "local_sensor", CTLTYPE_INT | CTLFLAG_RD, dev,
+ TMP461_LOCAL_MEASURE, tmp461_sensor_sysctl,
+ "IK1", compat_data->desc);
+
+ /* get status register */
+ if (tmp461_read_1(dev, TMP461_STATUS_REG, &data) != 0)
+ return (ENXIO);
+
+ if (!(data & TMP461_STATUS_REG_TEMP_LOCAL))
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(sensor_root_oid), OID_AUTO,
+ "remote_sensor", CTLTYPE_INT | CTLFLAG_RD, dev,
+ TMP461_REMOTE_MEASURE, tmp461_sensor_sysctl,
+ "IK1", compat_data->desc);
+
+ /* set standby mode */
+ if (tmp461_read_1(dev, TMP461_CONFIG_REG_R, &data) != 0)
+ return (ENXIO);
+
+ data |= TMP461_CONFIG_REG_STANDBY_BIT;
+ if (tmp461_write_1(dev, TMP461_CONFIG_REG_W, data) != 0)
+ return (ENXIO);
return (0);
}
@@ -111,14 +175,17 @@
static int
tmp461_probe(device_t dev)
{
+ struct tmp461_data *compat_data;
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (!ofw_bus_search_compatible(dev, tmp461_compat_data)->ocd_data)
+ compat_data = (struct tmp461_data *)
+ ofw_bus_search_compatible(dev, tmp461_compat_data)->ocd_data;
+ if (!compat_data)
return (ENXIO);
- device_set_desc(dev, "TMP461 Thermal Sensor");
+ device_set_desc(dev, compat_data->compat);
return (BUS_PROBE_GENERIC);
}
@@ -126,16 +193,20 @@
static int
tmp461_detach(device_t dev)
{
+ struct tmp461_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_destroy(&sc->mtx);
return (0);
}
static int
-tmp461_read_1(device_t dev, uint8_t reg, uint8_t *data)
+tmp461_read_1(device_t dev, uint8_t reg, uint8_t *data)
{
int error;
- error = iicdev_readfrom(dev, reg, (void *) data, 1, IIC_WAIT);
+ error = iicdev_readfrom(dev, reg, (void *) data, 1, IIC_DONTWAIT);
if (error != 0)
device_printf(dev, "Failed to read from device\n");
@@ -143,49 +214,99 @@
}
static int
-tmp461_read_temp(device_t dev, int32_t *temp)
+tmp461_write_1(device_t dev, uint8_t reg, uint8_t data)
{
- bool extended_mode;
- uint8_t data;
int error;
- /* read temperature range */
- error = tmp461_read_1(dev, TMP461_CONFIG_REG, &data);
+ error = iicdev_writeto(dev, reg, (void *) &data, 1, IIC_DONTWAIT);
if (error != 0)
- return (ENXIO);
+ device_printf(dev, "Failed to write to device\n");
+
+ return (error);
+}
+
+static int
+tmp461_read_temperature(device_t dev, int32_t *temperature, bool remote_measure)
+{
+ uint8_t data, offset, reg;
+ struct tmp461_softc *sc;
+ int error;
- extended_mode = data & TMP461_CONFIG_REG_TEMP_RANGE_BIT;
+ sc = device_get_softc(dev);
- /* read temp MSB */
- error = tmp461_read_1(dev, TMP461_LOCAL_TEMP_REG_MSB, &data);
+ mtx_lock(&sc->mtx);
+
+ error = tmp461_read_1(dev, TMP461_CONVERSION_RATE_REG, &data);
if (error != 0)
- return (ENXIO);
+ goto fail;
- *temp = signed_extend32(data, TMP461_TEMP_LSB, 8) -
- (extended_mode ? TMP461_EXTENDED_TEMP_MODIFIER : 0);
+ /* trigger sample*/
+ error = tmp461_write_1(dev, TMP461_ONESHOT_REG, 0xFF);
+ if (error != 0)
+ goto fail;
- error = tmp461_read_1(dev, TMP461_LOCAL_TEMP_REG_LSB, &data);
+ /* wait for conversion time */
+ DELAY(TMP461_SENSOR_MAX_CONV_TIME/(1UL<<data));
+
+ /* read config register offset */
+ error = tmp461_read_1(dev, TMP461_CONFIG_REG_R, &data);
if (error != 0)
- return (ENXIO);
+ goto fail;
- *temp = (((*temp << 4) | (data >> 4)) + TMP461_C_TO_K_FIX) >> 4;
+ offset = (data & TMP461_CONFIG_REG_TEMP_RANGE_BIT ?
+ TMP461_EXTENDED_TEMP_MODIFIER : 0);
- return (0);
+ reg = remote_measure ?
+ TMP461_GLOBAL_TEMP_REG_MSB : TMP461_LOCAL_TEMP_REG_MSB;
+
+ /* read temeperature value*/
+ error = tmp461_read_1(dev, reg, &data);
+ if (error != 0)
+ goto fail;
+
+ data -= offset;
+ *temperature = signed_extend32(data, 0, 8) << 4;
+
+ if (remote_measure) {
+ if (sc->conf & TMP461_REMOTE_TEMP_DOUBLE_REG) {
+ error = tmp461_read_1(dev,
+ TMP461_GLOBAL_TEMP_REG_LSB, &data);
+ if (error != 0)
+ goto fail;
+
+ *temperature |= data >> 4;
+ }
+ } else {
+ if (sc->conf & TMP461_LOCAL_TEMP_DOUBLE_REG) {
+ error = tmp461_read_1(dev,
+ TMP461_LOCAL_TEMP_REG_LSB, &data);
+ if (error != 0)
+ goto fail;
+
+ *temperature |= data >> 4;
+ }
+ }
+ *temperature = (((*temperature + TMP461_C_TO_K_FIX) * 10) >> 4);
+
+fail:
+ mtx_unlock(&sc->mtx);
+ return (error);
}
static int
tmp461_sensor_sysctl(SYSCTL_HANDLER_ARGS)
{
+ int32_t temperature;
device_t dev;
- int32_t temp;
int error;
+ bool mode;
dev = arg1;
+ mode = arg2;
- error = tmp461_read_temp(dev, &temp);
+ error = tmp461_read_temperature(dev, &temperature, mode);
if (error != 0)
return (error);
- return (sysctl_handle_int(oidp, &temp, 0, req));
+ return (sysctl_handle_int(oidp, &temperature, 0, req));
}
-
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Mar 6, 10:21 AM (7 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29322392
Default Alt Text
D36464.id110379.diff (8 KB)
Attached To
Mode
D36464: TMP461: Add support for ADT7461 sensor
Attached
Detach File
Event Timeline
Log In to Comment