Page MenuHomeFreeBSD

D36464.id110220.diff
No OneTemporary

D36464.id110220.diff

Index: sys/dev/iicbus/tmp461.c
===================================================================
--- sys/dev/iicbus/tmp461.c
+++ sys/dev/iicbus/tmp461.c
@@ -44,94 +44,147 @@
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/ofw_bus.h>
-#define BIT(x) (1UL << (x))
+#define BIT(x) (1UL << (x))
+
+/* register map */
+#define LOCAL_TEMP_REG_MSB 0x0
+#define LOCAL_TEMP_REG_LSB 0x15
+#define REMOTE_TEMP_REG_MSB 0x1
+#define REMOTE_TEMP_REG_LSB 0x10
+#define STATUS_REG 0x2
+#define STATUS_REG_TEMP_LOCAL BIT(2)
+#define CONFIG_REG_R 0x3
+#define CONFIG_REG_W 0x9
+#define CONFIG_REG_TEMP_RANGE_BIT BIT(2)
+#define CONFIG_REG_STANDBY_BIT BIT(6)
+#define CONVERSION_RATE_REG 0x4
+#define ONESHOT_REG 0xF
+#define EXTENDED_MODE_TEMP_OFFSET 64
-#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_CONFIG_REG_TEMP_RANGE_BIT BIT(2)
-
-#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 TEMP_C_TO_K_FIX 4370
+
+#define SENSOR_MAX_CONV_TIME 16000000
+#define LOCAL_MEASURE 0
+#define REMOTE_MEASURE 1
+
+/* flags */
+#define LOCAL_TEMP_DOUBLE_REG BIT(0)
+#define 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_detach(device_t dev);
-static int tmp461_sensor_sysctl(SYSCTL_HANDLER_ARGS);
+static int temp_sensor_probe(device_t dev);
+static int temp_sensor_attach(device_t dev);
+static int temp_sensor_read_1(device_t dev, uint8_t reg, uint8_t *data);
+static int temp_sensor_write_1(device_t dev, uint8_t reg, uint8_t data);
+static int temp_sensor_read_temp(device_t dev, int32_t *temp, bool mode);
+static int temp_sensor_detach(device_t dev);
+static int temp_sensor_sysctl(SYSCTL_HANDLER_ARGS);
-static device_method_t tmp461_methods[] = {
- DEVMETHOD(device_probe, tmp461_probe),
- DEVMETHOD(device_attach, tmp461_attach),
- DEVMETHOD(device_detach, tmp461_detach),
+static device_method_t temp_sensor_methods[] = {
+ DEVMETHOD(device_probe, temp_sensor_probe),
+ DEVMETHOD(device_attach, temp_sensor_attach),
+ DEVMETHOD(device_detach, temp_sensor_detach),
DEVMETHOD_END
};
-static driver_t tmp461_driver = {
- "tmp461_dev",
- tmp461_methods,
+static driver_t temp_sensor_driver = {
+ "temp_sensor_dev",
+ temp_sensor_methods,
0
};
-static struct ofw_compat_data tmp461_compat_data[] = {
- { "ti,tmp461", 1 },
- { NULL, 0 }
+struct sensor_data {
+ const char *name;
+ const char *desc;
+ uint8_t flags;
};
-DRIVER_MODULE(tmp461, iicbus, tmp461_driver, 0, 0);
-IICBUS_FDT_PNP_INFO(tmp461_compat_data);
+static struct sensor_data sensor_list[] = {
+ {"adt7461", "ADT7461 Thernal Sensor Information",
+ REMOTE_TEMP_DOUBLE_REG},
+ {"tmp461", "TMP461 Thernal Sensor Information",
+ LOCAL_TEMP_DOUBLE_REG | REMOTE_TEMP_DOUBLE_REG}
+};
+
+static struct ofw_compat_data device_compat_data[] = {
+ {"adi,adt7461", (uintptr_t)&sensor_list[0]},
+ {"ti,tmp461", (uintptr_t)&sensor_list[1]},
+ {NULL, 0}
+};
+
+DRIVER_MODULE(generic_thermal_sensor_driver, iicbus, temp_sensor_driver, 0, 0);
+IICBUS_FDT_PNP_INFO(device_compat_data);
static int
-tmp461_attach(device_t dev)
+temp_sensor_attach(device_t dev)
{
struct sysctl_oid *sensor_root_oid;
+ struct sensor_data *local_dev;
struct sysctl_ctx_list *ctx;
+ uint8_t data;
+ local_dev = (struct sensor_data *)
+ ofw_bus_search_compatible(dev, device_compat_data)->ocd_data;
ctx = device_get_sysctl_ctx(dev);
-
+
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,
+ LOCAL_MEASURE, temp_sensor_sysctl, "IK1", local_dev->desc);
+
+ /* get status register */
+ if (temp_sensor_read_1(dev, STATUS_REG, &data) != 0)
+ return (ENXIO);
+
+ if (!(data & STATUS_REG_TEMP_LOCAL))
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(sensor_root_oid), OID_AUTO,
+ "remote_sensor", CTLTYPE_INT | CTLFLAG_RD, dev,
+ REMOTE_MEASURE, temp_sensor_sysctl, "IK1", local_dev->desc);
+
+ /* set standby mode */
+ if (temp_sensor_read_1(dev, CONFIG_REG_R, &data) != 0)
+ return (ENXIO);
+
+ data |= CONFIG_REG_STANDBY_BIT;
+ if (temp_sensor_write_1(dev, CONFIG_REG_W, data) != 0)
+ return (ENXIO);
return (0);
}
static int
-tmp461_probe(device_t dev)
+temp_sensor_probe(device_t dev)
{
+ struct sensor_data *local_dev;
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (!ofw_bus_search_compatible(dev, tmp461_compat_data)->ocd_data)
+ local_dev = (struct sensor_data *)
+ ofw_bus_search_compatible(dev, device_compat_data)->ocd_data;
+ if (!local_dev)
return (ENXIO);
- device_set_desc(dev, "TMP461 Thermal Sensor");
+ device_set_desc(dev, local_dev->name);
return (BUS_PROBE_GENERIC);
}
static int
-tmp461_detach(device_t dev)
+temp_sensor_detach(device_t dev)
{
return (0);
}
static int
-tmp461_read_1(device_t dev, uint8_t reg, uint8_t *data)
+temp_sensor_read_1(device_t dev, uint8_t reg, uint8_t *data)
{
int error;
@@ -143,49 +196,99 @@
}
static int
-tmp461_read_temp(device_t dev, int32_t *temp)
+temp_sensor_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_WAIT);
if (error != 0)
- return (ENXIO);
+ device_printf(dev, "Failed to write to device\n");
- extended_mode = data & TMP461_CONFIG_REG_TEMP_RANGE_BIT;
+ return (error);
+}
+
+static int
+temp_sensor_read_temp(device_t dev, int32_t *temp, bool remote_measure)
+{
+ struct sensor_data *local_dev;
+ uint8_t data, offset;
+ int error;
+
+ local_dev = (struct sensor_data *)
+ ofw_bus_search_compatible(dev, device_compat_data)->ocd_data;
+
+ error = temp_sensor_read_1(dev, CONVERSION_RATE_REG, &data);
+ if (error != 0)
+ return (ENXIO);
- /* read temp MSB */
- error = tmp461_read_1(dev, TMP461_LOCAL_TEMP_REG_MSB, &data);
+ /* trigger sample*/
+ error = temp_sensor_write_1(dev, ONESHOT_REG, 0xFF);
if (error != 0)
return (ENXIO);
- *temp = signed_extend32(data, TMP461_TEMP_LSB, 8) -
- (extended_mode ? TMP461_EXTENDED_TEMP_MODIFIER : 0);
+ /* wait for conversion time */
+ DELAY(SENSOR_MAX_CONV_TIME/(1UL<<data));
- error = tmp461_read_1(dev, TMP461_LOCAL_TEMP_REG_LSB, &data);
+ /* read config register offset */
+ error = temp_sensor_read_1(dev, CONFIG_REG_R, &data);
if (error != 0)
return (ENXIO);
- *temp = (((*temp << 4) | (data >> 4)) + TMP461_C_TO_K_FIX) >> 4;
+ offset = (data & CONFIG_REG_TEMP_RANGE_BIT ?
+ EXTENDED_MODE_TEMP_OFFSET : 0);
+
+ if (remote_measure == LOCAL_MEASURE) {
+ error = temp_sensor_read_1(dev, LOCAL_TEMP_REG_MSB, &data);
+ if (error != 0)
+ return (ENXIO);
+
+ data -= offset;
+ *temp = signed_extend32(data, 0, 8) << 4;
+
+ if (local_dev->flags & LOCAL_TEMP_DOUBLE_REG) {
+ error = temp_sensor_read_1(dev,
+ LOCAL_TEMP_REG_LSB, &data);
+ if (error != 0)
+ return (ENXIO);
+
+ *temp |= data >> 4;
+ }
+ } else {
+ error = temp_sensor_read_1(dev, REMOTE_TEMP_REG_MSB, &data);
+ if (error != 0)
+ return (ENXIO);
+
+ data -= offset;
+ *temp = signed_extend32(data, 0, 8) << 4;
+
+ if (local_dev->flags & REMOTE_TEMP_DOUBLE_REG) {
+ error = temp_sensor_read_1(dev,
+ REMOTE_TEMP_REG_LSB, &data);
+ if (error != 0)
+ return (ENXIO);
+
+ *temp |= data >> 4;
+ }
+ }
+ *temp = (((*temp + TEMP_C_TO_K_FIX) * 10) >> 4);
return (0);
}
static int
-tmp461_sensor_sysctl(SYSCTL_HANDLER_ARGS)
+temp_sensor_sysctl(SYSCTL_HANDLER_ARGS)
{
device_t dev;
int32_t temp;
int error;
+ bool mode;
dev = arg1;
+ mode = arg2;
- error = tmp461_read_temp(dev, &temp);
+ error = temp_sensor_read_temp(dev, &temp, mode);
if (error != 0)
return (error);
return (sysctl_handle_int(oidp, &temp, 0, req));
}
-

File Metadata

Mime Type
text/plain
Expires
Sat, May 23, 6:58 AM (1 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33442857
Default Alt Text
D36464.id110220.diff (8 KB)

Event Timeline