The branch main has been updated by pouria:

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

commit f87ba4522ec9e7b2227b8f20f3a4d7c6a129da1c
Author:     Pouria Mousavizadeh Tehrani <[email protected]>
AuthorDate: 2026-03-07 18:33:43 +0000
Commit:     Pouria Mousavizadeh Tehrani <[email protected]>
CommitDate: 2026-03-09 09:11:56 +0000

    acpi_system76: Add support for battary charge thresholds
    
    Reviewed by: wulf
    Differential Revision: https://reviews.freebsd.org/D55710
---
 sys/dev/acpi_support/acpi_system76.c | 147 +++++++++++++++++++++++++++--------
 1 file changed, 116 insertions(+), 31 deletions(-)

diff --git a/sys/dev/acpi_support/acpi_system76.c 
b/sys/dev/acpi_support/acpi_system76.c
index c20725f0174e..9ae7d116be0b 100644
--- a/sys/dev/acpi_support/acpi_system76.c
+++ b/sys/dev/acpi_support/acpi_system76.c
@@ -54,7 +54,9 @@ struct acpi_system76_softc {
        ACPI_HANDLE     handle;
 
        struct acpi_ctrl        kbb,    /* S76_CTRL_KBB */
-                               kbc;    /* S76_CTRL_KBC */
+                               kbc,    /* S76_CTRL_KBC */
+                               bctl,   /* S76_CTRL_BCTL */
+                               bcth;   /* S76_CTRL_BCTH */
 
        struct sysctl_ctx_list  sysctl_ctx;
        struct sysctl_oid       *sysctl_tree;
@@ -72,19 +74,25 @@ static void acpi_system76_notify_handler(ACPI_HANDLE, 
uint32_t, void *);
 static void    acpi_system76_check(struct acpi_system76_softc *);
 
 /* methods */
-#define        S76_CTRL_KBB    1       /* Keyboard Brightness */
-#define        S76_CTRL_KBC    2       /* Keyboard Color */
-#define        S76_CTRL_MAX    3
+enum {
+       S76_CTRL_KBB    = 1,    /* Keyboard Brightness */
+       S76_CTRL_KBC    = 2,    /* Keyboard Color */
+       S76_CTRL_BCTL   = 3,    /* Battary Charging Start Thresholds */
+       S76_CTRL_BCTH   = 4,    /* Battary Charging End Thresholds */
+};
+#define        S76_CTRL_MAX    5
 
 struct s76_ctrl_table {
        char    *name;
        char    *get_method;
 #define S76_CTRL_GKBB  "\\_SB.S76D.GKBB"
 #define S76_CTRL_GKBC  "\\_SB.S76D.GKBC"
+#define S76_CTRL_GBCT  "\\_SB.PCI0.LPCB.EC0.GBCT"
 
        char    *set_method;
 #define S76_CTRL_SKBB  "\\_SB.S76D.SKBB"
 #define S76_CTRL_SKBC  "\\_SB.S76D.SKBC"
+#define S76_CTRL_SBCT  "\\_SB.PCI0.LPCB.EC0.SBCT"
 
        char    *desc;
 };
@@ -102,6 +110,18 @@ static const struct s76_ctrl_table s76_sysctl_table[] = {
                .set_method = S76_CTRL_SKBC,
                .desc = "Keyboard Color",
        },
+       [S76_CTRL_BCTL] = {
+               .name = "battary_thresholds_low",
+               .get_method = S76_CTRL_GBCT,
+               .set_method = S76_CTRL_SBCT,
+               .desc = "Battary charging start thresholds",
+       },
+       [S76_CTRL_BCTH] = {
+               .name = "battary_thresholds_high",
+               .get_method = S76_CTRL_GBCT,
+               .set_method = S76_CTRL_SBCT,
+               .desc = "Battary charging end thresholds",
+       },
 };
 
 static device_method_t acpi_system76_methods[] = {
@@ -135,10 +155,12 @@ acpi_system76_ctrl_map(struct acpi_system76_softc *sc, 
int method)
        switch (method) {
        case S76_CTRL_KBB:
                return (&sc->kbb);
-               break;
        case S76_CTRL_KBC:
                return (&sc->kbc);
-               break;
+       case S76_CTRL_BCTL:
+               return (&sc->bctl);
+       case S76_CTRL_BCTH:
+               return (&sc->bcth);
        default:
                device_printf(sc->dev, "Driver received unknown method\n");
                return (NULL);
@@ -150,6 +172,9 @@ acpi_system76_update(struct acpi_system76_softc *sc, int 
method, bool set)
 {
        struct acpi_ctrl *ctrl;
        ACPI_STATUS status;
+       ACPI_BUFFER Buf;
+       ACPI_OBJECT Arg[2], Obj;
+       ACPI_OBJECT_LIST Args;
 
        ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
        ACPI_SERIAL_ASSERT(system76);
@@ -157,12 +182,41 @@ acpi_system76_update(struct acpi_system76_softc *sc, int 
method, bool set)
        if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL)
                return (EINVAL);
 
-       if (set)
-               status = acpi_SetInteger(sc->handle, 
s76_sysctl_table[method].set_method,
-                   ctrl->val);
-       else
-               status = acpi_GetInteger(sc->handle, 
s76_sysctl_table[method].get_method,
-                   &ctrl->val);
+       switch (method) {
+       case S76_CTRL_BCTL:
+       case S76_CTRL_BCTH:
+               Arg[0].Type = ACPI_TYPE_INTEGER;
+               Arg[0].Integer.Value = method == S76_CTRL_BCTH ? 1 : 0;
+               Args.Count = set ? 2 : 1;
+               Args.Pointer = Arg;
+               Buf.Length = sizeof(Obj);
+               Buf.Pointer = &Obj;
+
+               if (set) {
+                       Arg[1].Type = ACPI_TYPE_INTEGER;
+                       Arg[1].Integer.Value = ctrl->val;
+
+                       status = AcpiEvaluateObject(sc->handle,
+                           s76_sysctl_table[method].set_method, &Args, &Buf);
+               } else {
+                       status = AcpiEvaluateObject(sc->handle,
+                           s76_sysctl_table[method].get_method, &Args, &Buf);
+                       if (ACPI_SUCCESS(status) &&
+                           Obj.Type == ACPI_TYPE_INTEGER)
+                               ctrl->val = Obj.Integer.Value;
+               }
+               break;
+       case S76_CTRL_KBB:
+       case S76_CTRL_KBC:
+               if (set)
+                       status = acpi_SetInteger(sc->handle, 
s76_sysctl_table[method].set_method,
+                           ctrl->val);
+               else
+                       status = acpi_GetInteger(sc->handle, 
s76_sysctl_table[method].get_method,
+                           &ctrl->val);
+               break;
+       }
+
        if (ACPI_FAILURE(status)) {
                device_printf(sc->dev, "Couldn't query method (%s)\n",
                    s76_sysctl_table[method].name);
@@ -183,8 +237,12 @@ acpi_system76_notify_update(void *arg)
        sc = (struct acpi_system76_softc *)device_get_softc(arg);
 
        ACPI_SERIAL_BEGIN(system76);
-       for (method = 1; method < S76_CTRL_MAX; method++)
+       for (method = 1; method < S76_CTRL_MAX; method++) {
+               if (method == S76_CTRL_BCTL ||
+                   method == S76_CTRL_BCTH)
+                       continue;
                acpi_system76_update(sc, method, false);
+       }
        ACPI_SERIAL_END(system76);
 }
 
@@ -201,6 +259,14 @@ acpi_system76_check(struct acpi_system76_softc *sc)
                if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL)
                        continue;
 
+               /* available in all models */
+               if (method == S76_CTRL_BCTL ||
+                   method == S76_CTRL_BCTH) {
+                       ctrl->exists = true;
+                       acpi_system76_update(sc, method, false);
+                       continue;
+               }
+
                if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
                    s76_sysctl_table[method].get_method, &ctrl->val))) {
                        ctrl->exists = false;
@@ -236,9 +302,10 @@ acpi_system76_notify_handler(ACPI_HANDLE handle, uint32_t 
notify, void *ctx)
 static int
 acpi_system76_sysctl_handler(SYSCTL_HANDLER_ARGS)
 {
-       struct acpi_ctrl *ctrl;
+       struct acpi_ctrl *ctrl, *ctrl_cmp;
        struct acpi_system76_softc *sc;
        int val, method, error;
+       bool update;
 
        ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
@@ -253,27 +320,45 @@ acpi_system76_sysctl_handler(SYSCTL_HANDLER_ARGS)
                device_printf(sc->dev, "Driver query failed\n");
                return (error);
        }
-       if (req->newptr == NULL)
-               return (error);
 
-       /* Input validation */
-       switch (method) {
-       case S76_CTRL_KBB:
-               if (val > UINT8_MAX || val < 0)
-                       return (EINVAL);
-               break;
-       case S76_CTRL_KBC:
-               if (val >= (1 << 24) || val < 0)
-                       return (EINVAL);
-               break;
-       default:
-               break;
+       if (req->newptr == NULL) {
+               /*
+                * ACPI will not notify us if battary thresholds changes
+                * outside this module. Therefore, always fetch those values.
+                */
+               if (method != S76_CTRL_BCTL && method != S76_CTRL_BCTH)
+                       return (error);
+               update = false;
+       } else {
+               /* Input validation */
+               switch (method) {
+               case S76_CTRL_KBB:
+                       if (val > UINT8_MAX || val < 0)
+                               return (EINVAL);
+                       break;
+               case S76_CTRL_KBC:
+                       if (val >= (1 << 24) || val < 0)
+                               return (EINVAL);
+                       break;
+               case S76_CTRL_BCTL:
+                       if ((ctrl_cmp = acpi_system76_ctrl_map(sc, 
S76_CTRL_BCTH)) == NULL)
+                               return (EINVAL);
+                       if (val > 100 || val < 0 || val >= ctrl_cmp->val)
+                               return (EINVAL);
+                       break;
+               case S76_CTRL_BCTH:
+                       if ((ctrl_cmp = acpi_system76_ctrl_map(sc, 
S76_CTRL_BCTL)) == NULL)
+                               return (EINVAL);
+                       if (val > 100 || val < 0 || val <= ctrl_cmp->val)
+                               return (EINVAL);
+                       break;
+               }
+               ctrl->val = val;
+               update = true;
        }
 
-       ctrl->val = val;
-
        ACPI_SERIAL_BEGIN(system76);
-       error = acpi_system76_update(sc, method, true);
+       error = acpi_system76_update(sc, method, update);
        ACPI_SERIAL_END(system76);
        return (error);
 }

Reply via email to