[RFC PATCH 12/14] hwmon/macsmc: add more types
From: Atharva Tiwari
Date: Thu Oct 29 2026 - 05:10:00 EST
SMC keys come in many data types, and Intel Macs use a lot
that macsmc-hwmon couldn't read, such as the signed fixed
point types like sp1e.
Add support for the common integer and fixed point types,
and allow writing fan speeds.
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@xxxxxxxxx>
---
drivers/hwmon/macsmc-hwmon.c | 310 +++++++++++++++++++++++++++++++++++
1 file changed, 310 insertions(+)
diff --git a/drivers/hwmon/macsmc-hwmon.c b/drivers/hwmon/macsmc-hwmon.c
index 1500ec2cc..2e74dcd66 100644
--- a/drivers/hwmon/macsmc-hwmon.c
+++ b/drivers/hwmon/macsmc-hwmon.c
@@ -221,6 +221,313 @@ static int macsmc_hwmon_read_key(struct apple_smc *smc,
*val = (long)ioft;
break;
}
+ /* unsigned 8-bit integer */
+ case __SMC_KEY('u', 'i', '8', ' '): {
+ u8 ui8 = 0;
+
+ ret = apple_smc_read_u8(smc, sensor->macsmc_key, &ui8);
+ if (ret)
+ return ret;
+
+ *val = ui8 * scale;
+ break;
+ }
+ /* signed 8-bit integer */
+ case __SMC_KEY('s', 'i', '8', ' '): {
+ s8 si8 = 0;
+
+ ret = apple_smc_read_s8(smc, sensor->macsmc_key, &si8);
+ if (ret)
+ return ret;
+
+ *val = si8 * scale;
+ break;
+ }
+ /* unsigned 16-bit integer */
+ case __SMC_KEY('u', 'i', '1', '6'): {
+ u16 ui16 = 0;
+
+ ret = apple_smc_read_u16(smc, sensor->macsmc_key, &ui16);
+ if (ret)
+ return ret;
+
+ *val = ui16 * scale;
+ break;
+ }
+ /* signed 16-bit integer */
+ case __SMC_KEY('s', 'i', '1', '6'): {
+ s16 si16 = 0;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &si16);
+ if (ret)
+ return ret;
+
+ *val = si16 * scale;
+ break;
+ }
+ /* unsigned 32-bit integer */
+ case __SMC_KEY('u', 'i', '3', '2'): {
+ u32 ui32 = 0;
+
+ ret = apple_smc_read_u32(smc, sensor->macsmc_key, &ui32);
+ if (ret)
+ return ret;
+
+ *val = ui32 * scale;
+ break;
+ }
+ /* signed 32-bit integer */
+ case __SMC_KEY('s', 'i', '3', '2'): {
+ s32 si32;
+
+ ret = apple_smc_read_s32(smc, sensor->macsmc_key, &si32);
+ if (ret)
+ return ret;
+
+ *val = si32 * scale;
+ break;
+ }
+ /* 2.14 unsigned fixed point decimal */
+ case __SMC_KEY('f', 'p', '2', 'e'): {
+ u16 fp2e;
+
+ ret = apple_smc_read_u16(smc, sensor->macsmc_key, &fp2e);
+ if (ret)
+ return ret;
+
+ *val = mult_frac(be16_to_cpu(fp2e), scale, BIT(14));
+ break;
+ }
+
+ /* 3.13 unsigned fixed point decimal */
+ case __SMC_KEY('f', 'p', '3', 'd'): {
+ u16 fp3d;
+
+ ret = apple_smc_read_u16(smc, sensor->macsmc_key, &fp3d);
+ if (ret)
+ return ret;
+
+ *val = mult_frac(be16_to_cpu(fp3d), scale, BIT(13));
+ break;
+ }
+
+ /* 4.12 unsigned fixed point decimal */
+ case __SMC_KEY('f', 'p', '4', 'c'): {
+ u16 fp4c;
+
+ ret = apple_smc_read_u16(smc, sensor->macsmc_key, &fp4c);
+ if (ret)
+ return ret;
+
+ *val = mult_frac(be16_to_cpu(fp4c), scale, BIT(12));
+ break;
+ }
+
+ /* 5.11 unsigned fixed point decimal */
+ case __SMC_KEY('f', 'p', '5', 'b'): {
+ u16 fp5b;
+
+ ret = apple_smc_read_u16(smc, sensor->macsmc_key, &fp5b);
+ if (ret)
+ return ret;
+
+ *val = mult_frac(be16_to_cpu(fp5b), scale, BIT(11));
+ break;
+ }
+
+ /* 6.10 unsigned fixed point decimal */
+ case __SMC_KEY('f', 'p', '6', 'a'): {
+ u16 fp6a;
+
+ ret = apple_smc_read_u16(smc, sensor->macsmc_key, &fp6a);
+ if (ret)
+ return ret;
+
+ *val = mult_frac(be16_to_cpu(fp6a), scale, BIT(10));
+ break;
+ }
+
+ /* 8.8 unsigned fixed point decimal */
+ case __SMC_KEY('f', 'p', '8', '8'): {
+ u16 fp88;
+
+ ret = apple_smc_read_u16(smc, sensor->macsmc_key, &fp88);
+ if (ret)
+ return ret;
+
+ *val = mult_frac(be16_to_cpu(fp88), scale, BIT(8));
+ break;
+ }
+ /* 14.2 fixed point decimal */
+ case __SMC_KEY('f', 'p', 'e', '2'): {
+ /*
+ * fpe2 is only used for fan stats and fan control
+ * so precision is not needed
+ */
+ u16 fpe2;
+
+ ret = apple_smc_read_u16(smc, sensor->macsmc_key, &fpe2);
+ if (ret)
+ return ret;
+
+ *val = (be16_to_cpu(fpe2) >> 2);
+ break;
+ }
+ /* 1.14 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', '1', 'e'): {
+ s16 sp1e;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &sp1e);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(sp1e), scale, BIT(14));
+ break;
+ }
+
+ /* 2.13 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', '2', 'd'): {
+ s16 sp2d;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &sp2d);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(sp2d), scale, BIT(13));
+ break;
+ }
+
+ /* 3.12 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', '3', 'c'): {
+ s16 sp3c;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &sp3c);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(sp3c), scale, BIT(12));
+ break;
+ }
+
+ /* 4.11 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', '4', 'b'): {
+ s16 sp4b;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &sp4b);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(sp4b), scale, BIT(11));
+ break;
+ }
+
+ /* 5.10 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', '5', 'a'): {
+ s16 sp5a;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &sp5a);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(sp5a), scale, BIT(10));
+ break;
+ }
+
+ /* 6.9 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', '6', '9'): {
+ s16 sp69;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &sp69);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(sp69), scale, BIT(9));
+ break;
+ }
+
+ /* 7.8 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', '7', '8'): {
+ s16 sp78;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &sp78);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(sp78), scale, BIT(8));
+ break;
+ }
+
+ /* 8.7 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', '8', '7'): {
+ s16 sp87;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &sp87);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(sp87), scale, BIT(7));
+ break;
+ }
+
+ /* 9.6 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', '9', '6'): {
+ s16 sp96;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &sp96);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(sp96), scale, BIT(6));
+ break;
+ }
+
+ /* 10.5 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', 'a', '5'): {
+ s16 spa5;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &spa5);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(spa5), scale, BIT(5));
+ break;
+ }
+
+ /* 12.3 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', 'c', '3'): {
+ s16 spc3;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &spc3);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(spc3), scale, BIT(3));
+ break;
+ }
+
+ /* 13.2 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', 'd', '2'): {
+ s16 spd2;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &spd2);
+ if (ret)
+ return ret;
+
+ *val = mult_frac((s16)be16_to_cpu(spd2), scale, BIT(2));
+ break;
+ }
+
+ /* 15.0 signed fixed point decimal */
+ case __SMC_KEY('s', 'p', 'f', '0'): {
+ s16 spf0;
+
+ ret = apple_smc_read_s16(smc, sensor->macsmc_key, &spf0);
+ if (ret)
+ return ret;
+
+ *val = (s16)be16_to_cpu(spf0) * scale;
+ break;
+ }
default:
return -EOPNOTSUPP;
}
@@ -263,6 +570,9 @@ static int macsmc_hwmon_write_key(struct apple_smc *smc,
/* unsigned 8-bit integer */
case __SMC_KEY('u', 'i', '8', ' '):
return apple_smc_write_u8(smc, sensor->macsmc_key, val);
+ /* 14.2 fixed point decimal */
+ case __SMC_KEY('f', 'p', 'e', '2'):
+ return apple_smc_write_u16(smc, sensor->macsmc_key, cpu_to_be16(val << 2));
default:
return -EOPNOTSUPP;
}
--
2.55.0