Date: Sat, 4 Jun 2011 09:23:55 +0000 (UTC) From: Andreas Tobler <andreast@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r222674 - head/sys/dev/iicbus Message-ID: <201106040923.p549NtXE002920@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: andreast Date: Sat Jun 4 09:23:54 2011 New Revision: 222674 URL: http://svn.freebsd.org/changeset/base/222674 Log: - Improve error handling. - Add a retry loop for the i2c sensor reading. - Check on busy status of the chip and on invalid values. - Fix a typo in a comment. - Replace the constant 2732 with the ZERO_C_TO_K macro. Approved by: nwhitehorn (mentor) Modified: head/sys/dev/iicbus/max6690.c Modified: head/sys/dev/iicbus/max6690.c ============================================================================== --- head/sys/dev/iicbus/max6690.c Sat Jun 4 09:19:53 2011 (r222673) +++ head/sys/dev/iicbus/max6690.c Sat Jun 4 09:23:54 2011 (r222674) @@ -51,12 +51,11 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus.h> #include <powerpc/powermac/powermac_thermal.h> -#define FCU_ZERO_C_TO_K 2732 - /* Inlet, Backside, U3 Heatsink sensor: MAX6690. */ #define MAX6690_INT_TEMP 0x0 #define MAX6690_EXT_TEMP 0x1 +#define MAX6690_RSL_STATUS 0x2 #define MAX6690_EEXT_TEMP 0x10 #define MAX6690_IEXT_TEMP 0x11 #define MAX6690_TEMP_MASK 0xe0 @@ -76,8 +75,8 @@ static int max6690_attach(device_t); static int max6690_sensor_read(struct max6690_sensor *sens); static int max6690_sensor_sysctl(SYSCTL_HANDLER_ARGS); static void max6690_start(void *xdev); -static int max6690_read_1(device_t dev, uint32_t addr, uint8_t reg, - uint8_t *data); +static int max6690_read(device_t dev, uint32_t addr, uint8_t reg, + uint8_t *data); struct max6690_softc { device_t sc_dev; @@ -105,23 +104,43 @@ DRIVER_MODULE(max6690, iicbus, max6690_d MALLOC_DEFINE(M_MAX6690, "max6690", "Temp-Monitor MAX6690"); static int -max6690_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data) +max6690_read(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data) { uint8_t buf[4]; + uint8_t busy[1], rsl; + int err, try = 0; - struct iic_msg msg[2] = { + /* Busy register RSL. */ + rsl = MAX6690_RSL_STATUS; + /* first read the status register, 0x2. If busy, retry. */ + struct iic_msg msg[4] = { + { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &rsl }, + { addr, IIC_M_RD, 1, busy }, { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, { addr, IIC_M_RD, 1, buf }, }; - if (iicbus_transfer(dev, msg, 2) != 0) { - device_printf(dev, "iicbus read failed\n"); - return (EIO); + for (;;) + { + err = iicbus_transfer(dev, msg, 4); + if (err != 0) + goto retry; + if (busy[0] & 0x80) + goto retry; + /* Check for invalid value and retry. */ + if (buf[0] == 0xff) + goto retry; + + *data = *((uint8_t*)buf); + return (0); + + retry: + if (++try > 5) { + device_printf(dev, "iicbus read failed\n"); + return (-1); + } + pause("max6690_read", hz); } - - *data = *((uint8_t*)buf); - - return (0); } static int @@ -193,8 +212,8 @@ max6690_fill_sensor_prop(device_t dev) for (j = 0; j < i; j++) { sc->sc_sensors[j].dev = dev; - sc->sc_sensors[j].therm.target_temp = 400 + 2732; - sc->sc_sensors[j].therm.max_temp = 800 + 2732; + sc->sc_sensors[j].therm.target_temp = 400 + ZERO_C_TO_K; + sc->sc_sensors[j].therm.max_temp = 800 + ZERO_C_TO_K; sc->sc_sensors[j].therm.read = (int (*)(struct pmac_therm *))(max6690_sensor_read); @@ -302,14 +321,15 @@ static int max6690_sensor_read(struct max6690_sensor *sens) { uint8_t reg_int = 0, reg_ext = 0; - uint8_t integer; - uint8_t fraction; - int temp; + uint8_t integer = 0; + uint8_t fraction = 0; + int err, temp; + struct max6690_softc *sc; sc = device_get_softc(sens->dev); - /* The internal sensor id's are even, the external ar odd. */ + /* The internal sensor id's are even, the external are odd. */ if ((sens->id % 2) == 0) { reg_int = MAX6690_INT_TEMP; reg_ext = MAX6690_IEXT_TEMP; @@ -318,9 +338,11 @@ max6690_sensor_read(struct max6690_senso reg_ext = MAX6690_EEXT_TEMP; } - max6690_read_1(sc->sc_dev, sc->sc_addr, reg_int, &integer); + err = max6690_read(sc->sc_dev, sc->sc_addr, reg_int, &integer); + err = max6690_read(sc->sc_dev, sc->sc_addr, reg_ext, &fraction); - max6690_read_1(sc->sc_dev, sc->sc_addr, reg_ext, &fraction); + if (err < 0) + return (-1); fraction &= MAX6690_TEMP_MASK; @@ -329,7 +351,7 @@ max6690_sensor_read(struct max6690_senso */ temp = (integer * 10) + (fraction >> 5) * 10 / 8; - return (temp + FCU_ZERO_C_TO_K); + return (temp + ZERO_C_TO_K); } static int
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106040923.p549NtXE002920>