Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dce69e0a authored by Hans de Goede's avatar Hans de Goede Committed by Greg Kroah-Hartman
Browse files

ACPI: PMIC: Fix intel_pmic_regs_handler() read accesses



[ Upstream commit 009a789443fe4c8e6b1ecb7c16b4865c026184cd ]

The handling of PMIC register reads through writing 0 to address 4
of the OpRegion is wrong. Instead of returning the read value
through the value64, which is a no-op for function == ACPI_WRITE calls,
store the value and then on a subsequent function == ACPI_READ with
address == 3 (the address for the value field of the OpRegion)
return the stored value.

This has been tested on a Xiaomi Mi Pad 2 and makes the ACPI battery dev
there mostly functional (unfortunately there are still other issues).

Here are the SET() / GET() functions of the PMIC ACPI device,
which use this OpRegion, which clearly show the new behavior to
be correct:

OperationRegion (REGS, 0x8F, Zero, 0x50)
Field (REGS, ByteAcc, NoLock, Preserve)
{
    CLNT,   8,
    SA,     8,
    OFF,    8,
    VAL,    8,
    RWM,    8
}

Method (GET, 3, Serialized)
{
    If ((AVBE == One))
    {
        CLNT = Arg0
        SA = Arg1
        OFF = Arg2
        RWM = Zero
        If ((AVBG == One))
        {
            GPRW = Zero
        }
    }

    Return (VAL) /* \_SB_.PCI0.I2C7.PMI5.VAL_ */
}

Method (SET, 4, Serialized)
{
    If ((AVBE == One))
    {
        CLNT = Arg0
        SA = Arg1
        OFF = Arg2
        VAL = Arg3
        RWM = One
        If ((AVBG == One))
        {
            GPRW = One
        }
    }
}

Fixes: 0afa877a ("ACPI / PMIC: intel: add REGS operation region support")
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 700602b6
Loading
Loading
Loading
Loading
+28 −23
Original line number Diff line number Diff line
@@ -211,8 +211,9 @@ static acpi_status intel_pmic_regs_handler(u32 function,
		void *handler_context, void *region_context)
{
	struct intel_pmic_opregion *opregion = region_context;
	int result = 0;
	int result = -EINVAL;

	if (function == ACPI_WRITE) {
		switch (address) {
		case 0:
			return AE_OK;
@@ -232,10 +233,14 @@ static acpi_status intel_pmic_regs_handler(u32 function,
			} else {
				result = regmap_read(opregion->regmap, opregion->ctx.addr,
						     &opregion->ctx.val);
			if (result == 0)
				*value64 = opregion->ctx.val;
			}
		memset(&opregion->ctx, 0x00, sizeof(opregion->ctx));
			opregion->ctx.addr = 0;
		}
	}

	if (function == ACPI_READ && address == 3) {
		*value64 = opregion->ctx.val;
		return AE_OK;
	}

	if (result < 0) {