From nobody Thu Dec 01 08:18:26 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4NN88y26PXz4jk2H; Thu, 1 Dec 2022 08:18:26 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4NN88y1ZKDz4Dmw; Thu, 1 Dec 2022 08:18:26 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1669882706; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=3HA1Bz3juac76nTddTHqZYt+Rfa77Y7qOuQjXzb8bXI=; b=heKVZL/gz6OyX8KvKwyNk2yrgVidhBnGjnN5jTRoZnWY7ZJMNYjfiruXzmm9JQlkfoUI+D XUoRVxHksnZROenom5la/CR0FFwtHXkr6EsXUG9hAntqTic9JdaS/uXf637UIvF/QnUPTU armlcACFN5d21Dz/BTjy30G+i3aojE4JBZ9sbbmEVmCDgZsKzzuxpdVwHgX23dhoHSzLit CsjvZuiFD3gELgUaJWikKXkp8ZhSB4fyFlQLZpvETHj0e1TYqw9cknyNrcfpo60rW9X37u NhVNt5GLkf2rAgtUlateLfVaxfv71Mac/P55t2TeOCcVBdubOyVDzQFS/OQtdg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1669882706; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=3HA1Bz3juac76nTddTHqZYt+Rfa77Y7qOuQjXzb8bXI=; b=l4xhONCPiM6xnAvtdDYBBUS9HqUlTzbB5isgZHgAg+ZWSPQiQlHs30NqSXxkwF66XGv2md buvkIGDeoioDc2vPgz+Y4MyFWAmz9OwtZZdj77HjSJhHb7CZDYYbxopyaYMB66LcTXKwx3 DlRcvEsZxQda4fLWj1q2QTERGbOUDBnH75UYp837l+jr2Af/9/gC39bw5uWcVPmbqUNke8 3nhd7WC/QK5nlrWoWp+a2C4dj0J4e5gLggbdUY0HloqgvcsBMddJKLhBZUN2t0CpMc8Ai3 j+Gv0aEwMQdQBgVP5RvblLtP+CGshpcamlr8ek/MczGL4JNV1QUXnZ6q3pjwMA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1669882706; a=rsa-sha256; cv=none; b=pT9Tgo1wnD3nWbK5pNzP1+fcQL+gqWmqVUpWeJYE/k8DXAYaly+VhbnAXV5iVYkJqg5i4S 08lS0L9xYA+ivH3FpkBbpij+wMmIiCDltcRmA7PDvxC+oyDYBt2w5hMyflV83mEHqJL5CZ gIR1x0jQrEMfaGMXFPTqKcpisIaLsDrLz/4uIAy4CrqunrRXrYPvVGAaY7u9aeT4bOBXMU i41EnJHZRN6XlkHqZVKls6060m8DEVW+80Im2Orpy09jEfS/daZ6goxy0whUUDpGmn5DGe QysbicMBJkYHtcLj9nMLy5aZ0726sno1HOh4psxbsvyhPyfjp5KqEMb4xFJIkA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4NN88y0bSbzVjH; Thu, 1 Dec 2022 08:18:26 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2B18IQHH053171; Thu, 1 Dec 2022 08:18:26 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2B18IQRn053170; Thu, 1 Dec 2022 08:18:26 GMT (envelope-from git) Date: Thu, 1 Dec 2022 08:18:26 GMT Message-Id: <202212010818.2B18IQRn053170@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Wojciech Macek Subject: git: da3557899886 - main - lm75: Refactor code to fix io error List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: wma X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: da35578998869daf998a7a81d58fd90b2daf8f7d Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by wma: URL: https://cgit.FreeBSD.org/src/commit/?id=da35578998869daf998a7a81d58fd90b2daf8f7d commit da35578998869daf998a7a81d58fd90b2daf8f7d Author: Jakub Kolodziej AuthorDate: 2022-12-01 08:02:52 +0000 Commit: Wojciech Macek CommitDate: 2022-12-01 08:12:39 +0000 lm75: Refactor code to fix io error Use correct resolution by compat table. If dtb is not defined use default 9 bit mode. 11 bit detection is called if 9 bit mode is used. Sysctl resolution variable is added to change resolution in case. Some sensors didn't pull ACK while reading from nonexistent registers and it caused I2C read error and detect failure, so now detect failure does not cause driver break. Obtained from: Semihalf Sponsored by: Alstom Differential revision: https://reviews.freebsd.org/D37497 --- sys/dev/iicbus/lm75.c | 189 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 122 insertions(+), 67 deletions(-) diff --git a/sys/dev/iicbus/lm75.c b/sys/dev/iicbus/lm75.c index 19630aee11fe..bbc88050b488 100644 --- a/sys/dev/iicbus/lm75.c +++ b/sys/dev/iicbus/lm75.c @@ -51,8 +51,6 @@ __FBSDID("$FreeBSD$"); /* 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 @@ __FBSDID("$FreeBSD$"); #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 @@ static int lm75_attach(device_t); 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_faults_sysctl(SYSCTL_HANDLER_ARGS); 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 @@ static driver_t lm75_driver = { 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 @@ lm75_write(device_t dev, uint32_t addr, uint8_t *data, size_t len) 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 @@ lm75_attach(device_t dev) 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. @@ -232,8 +270,11 @@ lm75_type_detect(struct lm75_softc *sc) if (buf8 == 0xff) lm75a++; } - if (lm75a == 3) - sc->sc_hwtype = HWTYPE_LM75A; + if (lm75a == 3){ + sc->sc_multiplier = 1000; + sc->sc_resolution = 11; + sc->sc_max_resolution = 11; + } /* Restore the configuration register. */ sc->sc_conf = conf; @@ -251,6 +292,7 @@ lm75_start(void *xdev) 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); @@ -265,23 +307,30 @@ lm75_start(void *xdev) * This may not work for LM75 clones. */ if (lm75_type_detect(sc) != 0) { - device_printf(dev, "cannot read from sensor.\n"); + device_printf(dev, "cannot detect sesnor.\n"); +#ifndef FDT return; +#endif } - if (sc->sc_hwtype == HWTYPE_LM75A) - device_printf(dev, - "LM75A type sensor detected (11bits resolution).\n"); + + device_printf(dev,"%d bit resolution sensor attached.\n", + sc->sc_resolution); + + 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 +345,9 @@ lm75_start(void *xdev) 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 +377,43 @@ lm75_conf_write(struct lm75_softc *sc) } 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 +458,8 @@ static int 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 +606,27 @@ lm75_shutdown_sysctl(SYSCTL_HANDLER_ARGS) 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); +}