Page MenuHomeFreeBSD

D37497.id113491.diff
No OneTemporary

D37497.id113491.diff

Index: sys/dev/iicbus/lm75.c
===================================================================
--- sys/dev/iicbus/lm75.c
+++ sys/dev/iicbus/lm75.c
@@ -51,8 +51,6 @@
/* LM75 registers. */
#define LM75_TEMP 0x0
-#define LM75_TEMP_MASK 0xff80
-#define LM75A_TEMP_MASK 0xffe0
#define LM75_CONF 0x1
#define LM75_CONF_FSHIFT 3
#define LM75_CONF_FAULT 0x18
@@ -67,16 +65,13 @@
#define LM75_TEST_PATTERN 0xa
#define LM75_MIN_TEMP -55
#define LM75_MAX_TEMP 125
-#define LM75_0500C 0x80
-#define LM75_0250C 0x40
-#define LM75_0125C 0x20
-#define LM75_MSB 0x8000
-#define LM75_NEG_BIT LM75_MSB
-#define TZ_ZEROC 2731
+#define TZ_ZEROC 27315
+#define TZ_ZEROC_DIVIDER 100
-/* LM75 supported models. */
-#define HWTYPE_LM75 1
-#define HWTYPE_LM75A 2
+enum max_resolution{
+ BITS_9 = 1,
+ BITS_11
+};
/* Regular bus attachment functions */
static int lm75_probe(device_t);
@@ -85,9 +80,11 @@
struct lm75_softc {
device_t sc_dev;
struct intr_config_hook enum_hook;
- int32_t sc_hwtype;
uint32_t sc_addr;
uint32_t sc_conf;
+ uint8_t sc_resolution;
+ uint8_t sc_max_resolution;
+ uint16_t sc_multiplier;
};
/* Utility functions */
@@ -105,6 +102,7 @@
static int lm75_mode_sysctl(SYSCTL_HANDLER_ARGS);
static int lm75_pol_sysctl(SYSCTL_HANDLER_ARGS);
static int lm75_shutdown_sysctl(SYSCTL_HANDLER_ARGS);
+static int lm75_resolution_sysctl(SYSCTL_HANDLER_ARGS);
static device_method_t lm75_methods[] = {
/* Device interface */
@@ -120,6 +118,14 @@
sizeof(struct lm75_softc)
};
+#ifdef FDT
+static struct ofw_compat_data compat_data[] = {
+ {"national,lm75", BITS_9},
+ {"ti,lm75", BITS_9},
+ {0,0}
+};
+#endif
+
DRIVER_MODULE(lm75, iicbus, lm75_driver, 0, 0);
static int
@@ -152,13 +158,30 @@
static int
lm75_probe(device_t dev)
{
+#ifdef FDT
+ const struct ofw_compat_data *compat_ptr;
+#endif
struct lm75_softc *sc;
sc = device_get_softc(dev);
- sc->sc_hwtype = HWTYPE_LM75;
+ sc->sc_max_resolution = 9;
+
#ifdef FDT
- if (!ofw_bus_is_compatible(dev, "national,lm75"))
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ compat_ptr = ofw_bus_search_compatible(dev, compat_data);
+
+ switch (compat_ptr->ocd_data){
+ case BITS_9:
+ sc->sc_max_resolution = 9;
+ break;
+ case BITS_11:
+ sc->sc_max_resolution = 11;
+ break;
+ default:
return (ENXIO);
+ }
#endif
device_set_desc(dev, "LM75 temperature sensor");
@@ -177,6 +200,21 @@
sc->enum_hook.ich_func = lm75_start;
sc->enum_hook.ich_arg = dev;
+ switch (sc->sc_max_resolution) {
+ case 9:
+ sc->sc_resolution = 9;
+ sc->sc_max_resolution = 9;
+ sc->sc_multiplier = 10;
+ break;
+ case 11:
+ sc->sc_resolution = 11;
+ sc->sc_max_resolution = 11;
+ sc->sc_multiplier = 1000;
+ break;
+ default:
+ return (ENXIO);
+ }
+
/*
* We have to wait until interrupts are enabled. Usually I2C read
* and write only works when the interrupts are available.
@@ -231,9 +269,13 @@
return (-1);
if (buf8 == 0xff)
lm75a++;
+
+ }
+ if (lm75a == 3){
+ sc->sc_multiplier = 1000;
+ sc->sc_resolution = 11;
+ sc->sc_max_resolution = 11;
}
- if (lm75a == 3)
- sc->sc_hwtype = HWTYPE_LM75A;
/* Restore the configuration register. */
sc->sc_conf = conf;
@@ -251,6 +293,7 @@
struct sysctl_ctx_list *ctx;
struct sysctl_oid *tree_node;
struct sysctl_oid_list *tree;
+ char *mult_format;
dev = (device_t)xdev;
sc = device_get_softc(dev);
@@ -264,24 +307,26 @@
* Detect the kind of chip we are attaching to.
* This may not work for LM75 clones.
*/
- if (lm75_type_detect(sc) != 0) {
- device_printf(dev, "cannot read from sensor.\n");
- return;
- }
- if (sc->sc_hwtype == HWTYPE_LM75A)
- device_printf(dev,
- "LM75A type sensor detected (11bits resolution).\n");
+ if (sc->sc_max_resolution == 9)
+ lm75_type_detect(sc);
+ if (sc->sc_max_resolution == 11)
+ device_printf(dev,"11 bit resolution sensor detected.\n");
+
+ if (sc->sc_multiplier == 1000)
+ mult_format = "IK3";
+ else
+ mult_format = "IK";
/* Temperature. */
SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "temperature",
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, LM75_TEMP,
- lm75_temp_sysctl, "IK", "Current temperature");
+ lm75_temp_sysctl, mult_format, "Current temperature");
SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "thyst",
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, LM75_THYST,
- lm75_temp_sysctl, "IK", "Hysteresis temperature");
+ lm75_temp_sysctl, mult_format, "Hysteresis temperature");
SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "tos",
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, LM75_TOS,
- lm75_temp_sysctl, "IK", "Overtemperature");
+ lm75_temp_sysctl, mult_format, "Overtemperature");
/* Configuration parameters. */
SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "faults",
@@ -296,6 +341,9 @@
SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "shutdown",
CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, dev, 0,
lm75_shutdown_sysctl, "IU", "LM75 shutdown");
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "resolution",
+ CTLFLAG_RW | CTLTYPE_INT | CTLFLAG_MPSAFE, dev, 0,
+ lm75_resolution_sysctl, "IU", "LM75 resolution");
}
static int
@@ -325,65 +373,43 @@
}
static int
-lm75_temp_read(struct lm75_softc *sc, uint8_t reg, int *temp)
+lm75_temp_read(struct lm75_softc *sc, uint8_t reg, int32_t *temp)
{
+ int32_t buf;
uint8_t buf8[2];
- uint16_t buf;
- int neg, t;
+ uint8_t resolution = sc->sc_resolution;
+ uint16_t multiplier = sc->sc_multiplier;
if (lm75_read(sc->sc_dev, sc->sc_addr, reg, buf8, sizeof(buf8)) < 0)
return (-1);
- buf = (uint16_t)((buf8[0] << 8) | (buf8[1] & 0xff));
- /*
- * LM75 has a 9 bit ADC with resolution of 0.5 C per bit.
- * LM75A has an 11 bit ADC with resolution of 0.125 C per bit.
- * Temperature is stored with two's complement.
- */
- neg = 0;
- if (buf & LM75_NEG_BIT) {
- if (sc->sc_hwtype == HWTYPE_LM75A)
- buf = ~(buf & LM75A_TEMP_MASK) + 1;
- else
- buf = ~(buf & LM75_TEMP_MASK) + 1;
- neg = 1;
- }
- *temp = ((int16_t)buf >> 8) * 10;
- t = 0;
- if (sc->sc_hwtype == HWTYPE_LM75A) {
- if (buf & LM75_0125C)
- t += 125;
- if (buf & LM75_0250C)
- t += 250;
- }
- if (buf & LM75_0500C)
- t += 500;
- t /= 100;
- *temp += t;
- if (neg)
- *temp = -(*temp);
- *temp += TZ_ZEROC;
+
+ buf = (int16_t)((buf8[0] << 8) | buf8[1]);
+ *temp = ((buf >> (16 - resolution)) * multiplier) >> (resolution - 8);
+
+ *temp += TZ_ZEROC * sc->sc_multiplier / TZ_ZEROC_DIVIDER;
return (0);
}
static int
-lm75_temp_write(struct lm75_softc *sc, uint8_t reg, int temp)
+lm75_temp_write(struct lm75_softc *sc, uint8_t reg, int32_t temp)
{
- uint8_t buf8[3];
- uint16_t buf;
+ int32_t buf;
+ uint8_t buf8[3], resolution = sc->sc_resolution;
+ uint16_t multiplier = sc->sc_multiplier;
- temp = (temp - TZ_ZEROC) / 10;
- if (temp > LM75_MAX_TEMP)
- temp = LM75_MAX_TEMP;
- if (temp < LM75_MIN_TEMP)
- temp = LM75_MIN_TEMP;
+ temp -= TZ_ZEROC * multiplier / TZ_ZEROC_DIVIDER;
+ if (temp > LM75_MAX_TEMP * multiplier)
+ temp = LM75_MAX_TEMP * multiplier;
+ if (temp < LM75_MIN_TEMP * multiplier)
+ temp = LM75_MIN_TEMP * multiplier;
- buf = (uint16_t)temp;
- buf <<= 8;
+ buf = ((temp << (resolution - 8)) / multiplier) << (16 - resolution);
buf8[0] = reg;
- buf8[1] = buf >> 8;
+ buf8[1] = (buf >> 8) & 0xff;
buf8[2] = buf & 0xff;
+
if (lm75_write(sc->sc_dev, sc->sc_addr, buf8, sizeof(buf8)) < 0)
return (-1);
@@ -428,7 +454,8 @@
lm75_temp_sysctl(SYSCTL_HANDLER_ARGS)
{
device_t dev;
- int error, temp;
+ int error;
+ int32_t temp;
struct lm75_softc *sc;
uint8_t reg;
@@ -575,3 +602,27 @@
return (error);
}
+
+static int
+lm75_resolution_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev;
+ int error;
+ struct lm75_softc *sc;
+ int resolution;
+
+ dev = (device_t)arg1;
+ sc = device_get_softc(dev);
+ resolution = sc->sc_resolution;
+
+ error = sysctl_handle_int(oidp, &resolution, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ if (resolution > sc->sc_max_resolution || resolution < 9)
+ return (EINVAL);
+
+ sc->sc_resolution = (uint8_t) resolution;
+
+ return (0);
+}

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 10, 3:05 AM (3 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17079145
Default Alt Text
D37497.id113491.diff (7 KB)

Event Timeline