git: 126f82a3eb61 - main - asmc: deduplicate sensor converters and cause sysctls

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Wed, 01 Jul 2026 00:18:47 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=126f82a3eb613976f477aa8326a208459f60465d

commit 126f82a3eb613976f477aa8326a208459f60465d
Author:     Abdelkader Boudih <freebsd@seuros.com>
AuthorDate: 2026-07-01 00:15:51 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2026-07-01 00:18:40 +0000

    asmc: deduplicate sensor converters and cause sysctls
    
    Replace per-type spXX_to_milli() functions with a table-driven
    asmc_sensor_convert() that looks up the divisor by SMC type string.
    
    Reviewed by:    adrian
    Differential Revision:  https://reviews.freebsd.org/D57854
---
 sys/dev/asmc/asmc.c | 153 ++++++++++++++++------------------------------------
 1 file changed, 45 insertions(+), 108 deletions(-)

diff --git a/sys/dev/asmc/asmc.c b/sys/dev/asmc/asmc.c
index 6513cfed7b4f..d55c585419fb 100644
--- a/sys/dev/asmc/asmc.c
+++ b/sys/dev/asmc/asmc.c
@@ -130,8 +130,7 @@ static int	asmc_aupo_sysctl(SYSCTL_HANDLER_ARGS);
 static int	asmc_key_getinfo(device_t, const char *, uint8_t *, char *);
 
 /* System state / board identity sysctls */
-static int	asmc_mssd_sysctl(SYSCTL_HANDLER_ARGS);
-static int	asmc_mssp_sysctl(SYSCTL_HANDLER_ARGS);
+static int	asmc_cause_sysctl(SYSCTL_HANDLER_ARGS);
 static int	asmc_msal_sysctl(SYSCTL_HANDLER_ARGS);
 static int	asmc_clkt_sysctl(SYSCTL_HANDLER_ARGS);
 static int	asmc_msps_sysctl(SYSCTL_HANDLER_ARGS);
@@ -687,14 +686,14 @@ asmc_attach(device_t dev)
 			SYSCTL_ADD_PROC(sysctlctx,
 			    SYSCTL_CHILDREN(sys_tree), OID_AUTO, "shutdown_cause",
 			    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
-			    dev, 0, asmc_mssd_sysctl, "A",
+			    dev, 0, asmc_cause_sysctl, "A",
 			    "Last shutdown cause (MSSD)");
 
 		if (asmc_key_getinfo(dev, ASMC_KEY_MSSP, NULL, NULL) == 0)
 			SYSCTL_ADD_PROC(sysctlctx,
 			    SYSCTL_CHILDREN(sys_tree), OID_AUTO, "sleep_cause",
 			    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
-			    dev, 0, asmc_mssp_sysctl, "A",
+			    dev, 1, asmc_cause_sysctl, "A",
 			    "Last sleep cause (MSSP)");
 
 		if (asmc_key_getinfo(dev, ASMC_KEY_MSAL, NULL, NULL) == 0)
@@ -1487,78 +1486,50 @@ asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS)
 }
 #endif
 
-/*
- * Convert signed fixed-point SMC values to milli-units.
- * Format "spXY" means signed with X integer bits and Y fraction bits.
- */
-static int
-asmc_sp78_to_milli(const uint8_t *buf)
-{
-	int16_t val = (int16_t)be16dec(buf);
-
-	return ((int)val * 1000) / 256;
-}
-
-static int
-asmc_sp87_to_milli(const uint8_t *buf)
-{
-	int16_t val = (int16_t)be16dec(buf);
-
-	return ((int)val * 1000) / 128;
-}
-
-static int
-asmc_sp4b_to_milli(const uint8_t *buf)
-{
-	int16_t val = (int16_t)be16dec(buf);
-
-	return ((int)val * 1000) / 2048;
-}
-
-static int
-asmc_sp5a_to_milli(const uint8_t *buf)
-{
-	int16_t val = (int16_t)be16dec(buf);
-
-	return ((int)val * 1000) / 1024;
-}
-
-static int
-asmc_sp69_to_milli(const uint8_t *buf)
-{
-	int16_t val = (int16_t)be16dec(buf);
-
-	return ((int)val * 1000) / 512;
-}
-
-static int
-asmc_sp96_to_milli(const uint8_t *buf)
-{
-	int16_t val = (int16_t)be16dec(buf);
-
-	return ((int)val * 1000) / 64;
-}
+/* SMC sensor type table: type string to fixed-point divisor. */
+static const struct {
+	const char	type[5];
+	int		divisor;
+} asmc_sensor_types[] = {
+	{ "sp78",  256 },
+	{ "sp87",  128 },
+	{ "sp4b", 2048 },
+	{ "sp5a", 1024 },
+	{ "sp69",  512 },
+	{ "sp96",   64 },
+	{ "sp2d", 8192 },
+	{ "ui16",    1 },
+	{ "",        0 },
+};
 
-static int
-asmc_sp2d_to_milli(const uint8_t *buf)
+/* Convert a 2-byte SMC value to milli-units. */
+static bool
+asmc_sensor_convert(const char *type, const uint8_t *buf, int *millivalue)
 {
-	int16_t val = (int16_t)be16dec(buf);
+	int i;
 
-	return ((int)val * 1000) / 8192;
+	for (i = 0; asmc_sensor_types[i].divisor != 0; i++) {
+		if (strncmp(type, asmc_sensor_types[i].type, 4) != 0)
+			continue;
+		if (asmc_sensor_types[i].divisor == 1)
+			*millivalue = be16dec(buf);
+		else
+			*millivalue = ((int)(int16_t)be16dec(buf) * 1000) /
+			    asmc_sensor_types[i].divisor;
+		return (true);
+	}
+	return (false);
 }
 
 static bool
 asmc_sensor_type_supported(const char *type)
 {
+	int i;
 
-	return (strncmp(type, "sp78", 4) == 0 ||
-	    strncmp(type, "sp87", 4) == 0 ||
-	    strncmp(type, "sp4b", 4) == 0 ||
-	    strncmp(type, "sp5a", 4) == 0 ||
-	    strncmp(type, "sp69", 4) == 0 ||
-	    strncmp(type, "sp96", 4) == 0 ||
-	    strncmp(type, "sp2d", 4) == 0 ||
-	    strncmp(type, "ui16", 4) == 0);
+	for (i = 0; asmc_sensor_types[i].divisor != 0; i++)
+		if (strncmp(type, asmc_sensor_types[i].type, 4) == 0)
+			return (true);
+	return (false);
 }
 
 /*
@@ -1589,23 +1560,7 @@ asmc_sensor_read(device_t dev, const char *key, int *millivalue)
 	if (error != 0)
 		return (error);
 
-	if (strncmp(type, "sp78", 4) == 0) {
-		*millivalue = asmc_sp78_to_milli(buf);
-	} else if (strncmp(type, "sp87", 4) == 0) {
-		*millivalue = asmc_sp87_to_milli(buf);
-	} else if (strncmp(type, "sp4b", 4) == 0) {
-		*millivalue = asmc_sp4b_to_milli(buf);
-	} else if (strncmp(type, "sp5a", 4) == 0) {
-		*millivalue = asmc_sp5a_to_milli(buf);
-	} else if (strncmp(type, "sp69", 4) == 0) {
-		*millivalue = asmc_sp69_to_milli(buf);
-	} else if (strncmp(type, "sp96", 4) == 0) {
-		*millivalue = asmc_sp96_to_milli(buf);
-	} else if (strncmp(type, "sp2d", 4) == 0) {
-		*millivalue = asmc_sp2d_to_milli(buf);
-	} else if (strncmp(type, "ui16", 4) == 0) {
-		*millivalue = be16dec(buf);
-	} else {
+	if (!asmc_sensor_convert(type, buf, millivalue)) {
 		if (bootverbose)
 			device_printf(dev,
 			    "%s: unknown type '%s' for key %s\n",
@@ -2631,40 +2586,22 @@ asmc_cause_str(int8_t cause, bool is_sleep)
 	return (NULL);
 }
 
+/* MSSD/MSSP: last shutdown/sleep cause.  arg2: 0=shutdown, 1=sleep. */
 static int
-asmc_mssd_sysctl(SYSCTL_HANDLER_ARGS)
-{
-	device_t dev = (device_t)arg1;
-	int8_t cause;
-	const char *desc;
-	char buf[ASMC_CAUSE_BUFLEN];
-
-	/* EIO: SMC I/O bus did not respond to key read. */
-	if (asmc_key_read(dev, ASMC_KEY_MSSD, (uint8_t *)&cause, 1) != 0)
-		return (EIO);
-
-	desc = asmc_cause_str(cause, false);
-	if (desc != NULL)
-		snprintf(buf, sizeof(buf), "%d (%s)", (int)cause, desc);
-	else
-		snprintf(buf, sizeof(buf), "%d", (int)cause);
-
-	return (sysctl_handle_string(oidp, buf, sizeof(buf), req));
-}
-
-static int
-asmc_mssp_sysctl(SYSCTL_HANDLER_ARGS)
+asmc_cause_sysctl(SYSCTL_HANDLER_ARGS)
 {
 	device_t dev = (device_t)arg1;
+	bool is_sleep = (arg2 != 0);
+	const char *key = is_sleep ? ASMC_KEY_MSSP : ASMC_KEY_MSSD;
 	int8_t cause;
 	const char *desc;
 	char buf[ASMC_CAUSE_BUFLEN];
 
 	/* EIO: SMC I/O bus did not respond to key read. */
-	if (asmc_key_read(dev, ASMC_KEY_MSSP, (uint8_t *)&cause, 1) != 0)
+	if (asmc_key_read(dev, key, (uint8_t *)&cause, 1) != 0)
 		return (EIO);
 
-	desc = asmc_cause_str(cause, true);
+	desc = asmc_cause_str(cause, is_sleep);
 	if (desc != NULL)
 		snprintf(buf, sizeof(buf), "%d (%s)", (int)cause, desc);
 	else