From f19ee0d73745d4301ed562aefb671c03401ac619 Mon Sep 17 00:00:00 2001 From: V Sowmya Date: Thu, 20 Jul 2017 11:12:33 +0530 Subject: [PATCH] mb/google/kblrvp: Add camera devices power sequencing through ACPI power resources This patch controls the camera devices power through ACPI power resource. * Add Opregions for PMIC1 and PMIC2, * TI_PMIC_POWER_OPREGION * TI_PMIC_VR_VAL_OPREGION * TI_PMIC_CLK_OPREGION * TI_PMIC_CLK_FREQ_OPREGION * Add power resources for sensors and VCM, * OVTH for CAM0 * OVFI for CAM1 * VCMP for VCM * Implement _ON and _OFF methods for sensor and VCM module's power on and power off sequences. BUG=none BRANCH=none TEST=Build and boot kblrvp. Dump and verify that the generated DSDT table has the required entries. Verified that sensor probe is successful. Change-Id: I02c4784ab3f4d6e1f0e657ad50b727ff11da8b9c Signed-off-by: V Sowmya Reviewed-on: https://review.coreboot.org/20663 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- .../intel/kblrvp/acpi/mipi_camera.asl | 696 ++++++++++++++++++ 1 file changed, 696 insertions(+) diff --git a/src/mainboard/intel/kblrvp/acpi/mipi_camera.asl b/src/mainboard/intel/kblrvp/acpi/mipi_camera.asl index 8a4450572e..1efad473f1 100644 --- a/src/mainboard/intel/kblrvp/acpi/mipi_camera.asl +++ b/src/mainboard/intel/kblrvp/acpi/mipi_camera.asl @@ -27,13 +27,358 @@ Scope (\_SB.PCI0.I2C2) Return (0x0F) } + /* Marks the availability of all the operation regions */ + Name (AVP1, Zero) + Name (AVGP, Zero) + Name (AVB0, Zero) + Name (AVB1, Zero) + Name (AVB2, Zero) + Name (AVB3, Zero) + Method (_REG, 2, NotSerialized) + { + If (LEqual (Arg0, 0x08)) + { + /* Marks the availability of GeneralPurposeIO + * 0x08: opregion space for GeneralPurposeIO + */ + Store (Arg1, AVGP) + } + If (LEqual (Arg0, 0xB0)) + { + /* Marks the availability of + * TI_PMIC_POWER_OPREGION_ID */ + Store (Arg1, AVB0) + } + If (LEqual (Arg0, 0xB1)) + { + /* Marks the availability of + * TI_PMIC_VR_VAL_OPREGION_ID */ + Store (Arg1, AVB1) + } + If (LEqual (Arg0, 0xB2)) + { + /* Marks the availability of + * TI_PMIC_CLK_OPREGION_ID */ + Store (Arg1, AVB2) + } + If (LEqual (Arg0, 0xB3)) + { + /* Marks the availability of + * TI_PMIC_CLK_FREQ_OPREGION_ID */ + Store (Arg1, AVB3) + } + If (LAnd (AVGP, LAnd (LAnd (AVB0, AVB1), + LAnd(AVB2, AVB3)))) + { + /* Marks the availability of all opregions */ + Store (1, AVP1) + } + Else + { + Store (0, AVP1) + } + } + + OperationRegion (GPOP, GeneralPurposeIo, 0, 0x2) Name (_CRS, ResourceTemplate () { I2cSerialBus (0x004D, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\\_SB.PCI0.I2C2", 0x00, ResourceConsumer, , ) + /* GPIO.9 is XSHUTDOWN pin for world facing camera */ + GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, + IoRestrictionOutputOnly, "\\_SB.PCI0.I2C2.PMIC", + 0x00, ResourceConsumer,,) + { + 9 + } }) + + /* PMIC operation regions */ + /* 0xB0: TI_PMIC_POWER_OPREGION_ID + * VSIO: Sensor IO LDO output + * VCMC: VCM LDO output + * VAX1: Auxiliary LDO1 output + * VAX2: Auxiliary LDO2 output + * VACT: Analog LDO output + * VDCT: Core buck output + */ + OperationRegion (PWR1, 0xB0, Zero, 0x0100) + Field (PWR1, DWordAcc, NoLock, Preserve) + { + VSIO, 32, + VCMC, 32, + VAX1, 32, + VAX2, 32, + VACT, 32, + VDCT, 32, + } + + /* 0xB1: TI_PMIC_VR_VAL_OPREGION_ID + * SIOV: VSIO VR voltage value + * IOVA: VIO VR voltage value + * VCMV: VCM VR voltage value + * AX1V: Auxiliary LDO1 VR voltage value + * AX2V: Auxiliary LDO2 VR voltage value + * ACVA: Analog LDO VR voltage + * DCVA: Core buck VR volatage + */ + OperationRegion (PWR2, 0xB1, Zero, 0x0100) + Field (PWR2, DWordAcc, NoLock, Preserve) + { + SIOV, 32, + IOVA, 32, + VCMV, 32, + AX1V, 32, + AX2V, 32, + ACVA, 32, + DCVA, 32, + } + + /* 0xB2: TI_PMIC_CLK_OPREGION_ID + * PCTL: PLL control register + * PCT2: PLL control 2 register + * CFG1: Clock configuration 1 register + * CFG2: Clock configuration 2 register + */ + OperationRegion (CLKC, 0xB2, Zero, 0x0100) + Field (CLKC, DWordAcc, NoLock, Preserve) + { + PCTL, 32, + PCT2, 32, + CFG1, 32, + CFG2, 32, + } + + /* 0xB3: TI_PMIC_CLK_FREQ_OPREGION_ID + * PDV2: PLL output divider for HCLK_B + * BODI: PLL output divider for boost clock + * BUDI: PLL output divider for buck clock + * PSWR: PLL reference clock setting + * XTDV: Reference crystal divider + * PLDV: PLL feedback divider + * PODV: PLL output divider for HCLK_A + */ + OperationRegion (CLKF, 0xB3, Zero, 0x0100) + Field (CLKF, DWordAcc, NoLock, Preserve) + { + PDV2, 32, + BODI, 32, + BUDI, 32, + PSWR, 32, + XTDV, 32, + PLDV, 32, + PODV, 32, + } + + Mutex (MUTC, 0) + Method (CLKE, 0, Serialized) { + /* save Acquire result so we can check for + Mutex acquired */ + Store (Acquire (MUTC, 1000), Local0) + /* check for Mutex acquired */ + If (LEqual (Local0, Zero)) { + /* Set boost clock divider */ + BODI = 3 + /* Set buck clock divider */ + BUDI = 2 + /* Set the PLL_REF_CLK cyles */ + PSWR = 19 + /* Set the reference crystal divider */ + XTDV = 170 + /* Set PLL feedback divider */ + PLDV = 32 + /* Set PLL output divider for HCLK_A */ + PODV = 1 + /* Enable HCLK_A clock. + * CFG1: output selection for HCLK_A. + * CFG2: set drive strength for HCLK_A. + */ + CFG2 = 1 + CFG1 = 2 + /* Enable PLL output, crystal oscillator + * input capacitance control and set + * Xtal oscillator as clock source. + */ + PCTL = 209 + Sleep(1) + Release (MUTC) + } + } + + Method (CLKD, 0, Serialized) { + /* save Acquire result so we can check for + Mutex acquired */ + Store (Acquire (MUTC, 1000), Local0) + /* check for Mutex acquired */ + If (LEqual (Local0, Zero)) { + BODI = 0 + BUDI = 0 + PSWR = 0 + XTDV = 0 + PLDV = 0 + PODV = 0 + /* Disable HCLK_A clock */ + CFG2 = 0 + CFG1 = 0 + PCTL = 0 + Release (MUTC) + } + } + + /* Reference count for VSIO */ + Mutex (MUTV, 0) + Name (VSIC, 0) + Method (DOVD, 1, Serialized) { + /* Save Acquire result so we can check for + Mutex acquired */ + Store (Acquire (MUTV, 1000), Local0) + /* Check for Mutex acquired */ + If (LEqual (Local0, Zero)) { + /* Turn off VSIO */ + If (LEqual (Arg0, Zero)) { + /* Decrement only if VSIC > 0 */ + if (LGreater (VSIC, 0)) { + Decrement (VSIC) + If (LEqual (VSIC, Zero)) { + VSIO = 0 + } + } + } ElseIf (LEqual (Arg0, 1)) { + /* Increment only if VSIC < 2 */ + If (LLess (VSIC, 2)) { + /* Turn on VSIO */ + If (LEqual (VSIC, Zero)) { + VSIO = 3 + } + Increment (VSIC) + } + } + + Release (MUTV) + } + } + + /* Power resource methods for CAM0 */ + PowerResource (OVTH, 0, 0) { + Name (STA, 0) + Method (_ON, 0, Serialized) { + If (LEqual (AVP1, 1)) { + If (LEqual (STA, 0)) { + /* Enable VSIO regulator + + daisy chain */ + DOVD(1) + + if (LNotEqual (IOVA, 52)) { + /* Set VSIO value as + 1.8006 V */ + IOVA = 52 + } + if (LNotEqual (SIOV, 52)) { + /* Set VSIO value as + 1.8006 V */ + SIOV = 52 + } + Sleep(3) + + VACT = 1 + if (LNotEqual (ACVA, 109)) { + /* Set ANA at 2.8152V */ + ACVA = 109 + } + Sleep(3) + + \_SB.PCI0.I2C2.PMIC.CLKE() + + VDCT = 1 + if (LNotEqual (DCVA, 12)) { + /* Set CORE at 1.2V */ + DCVA = 12 + } + Sleep(3) + \_SB.PCI0.I2C2.CAM0.CRST(1) + Sleep(5) + + STA = 1 + } + } + } + + Method (_OFF, 0, Serialized) { + If (LEqual (AVP1, 1)) { + If (LEqual (STA, 1)) { + Sleep(2) + \_SB.PCI0.I2C2.PMIC.CLKD() + Sleep(2) + \_SB.PCI0.I2C2.CAM0.CRST(0) + Sleep(3) + VDCT = 0 + Sleep(3) + VACT = 0 + Sleep(1) + DOVD(0) + Sleep(1) + } + } + STA = 0 + } + Method (_STA, 0, NotSerialized) { + Return (STA) + } + } + + /* Power resource methods for VCM */ + PowerResource (VCMP, 0, 0) { + Name (STA, 0) + Method (_ON, 0, Serialized) { + If (LEqual (AVP1, 1)) { + If (LEqual (STA, 0)) { + /* Enable VSIO regulator + + daisy chain */ + DOVD(1) + if (LNotEqual (IOVA, 52)) { + /* Set VSIO value as + 1.8006 V */ + IOVA = 52 + } + if (LNotEqual (SIOV, 52)) { + /* Set VSIO value as + 1.8006 V */ + SIOV = 52 + } + Sleep(3) + + /* Enable VCM regulator */ + VCMC = 1 + if (LNotEqual (VCMV, 109)) { + /* Set VCM value at + 2.8152 V */ + VCMV = 109 + } + Sleep(3) + + STA = 1 + } + } + } + + Method (_OFF, 0, Serialized) { + If (LEqual (AVP1, 1)) { + If (LEqual (STA, 1)) { + VCMC = 0 /* Disable regulator */ + Sleep(1) + DOVD(0) /* Disable regulator */ + Sleep(1) + STA = 0 + } + } + } + + Method (_STA, 0, NotSerialized) { + Return (STA) + } + } } Device (CAM0) @@ -57,6 +402,30 @@ Scope (\_SB.PCI0.I2C2) ) }) + Field (\_SB.PCI0.I2C2.PMIC.GPOP, ByteAcc, NoLock, Preserve) + { + Connection + ( + GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, + IoRestrictionOutputOnly, + "\\_SB.PCI0.I2C2.PMIC", 0x00, + ResourceConsumer,,) + { + 9 + } + ), + GRST, 1, + } + + /* Set or clear GRST GPIO */ + Method (CRST, 1, Serialized) + { + GRST = Arg0 + } + + Name (_PR0, Package () { ^^I2C2.PMIC.OVTH }) + Name (_PR3, Package () { ^^I2C2.PMIC.OVTH }) + /* Port0 of CAM0 is connected to port0 of CIO2 device */ Name (_DSD, Package () { ToUUID ("dbb8e3e6-5886-4ba6-8795-1319f52a966b"), @@ -137,6 +506,9 @@ Scope (\_SB.PCI0.I2C2) 0x00, ResourceConsumer, , ) }) + + Name (_PR0, Package () { ^PMIC.VCMP }) + Name (_PR3, Package () { ^PMIC.VCMP }) } } @@ -154,13 +526,296 @@ Scope (\_SB.PCI0.I2C3) Return (0x0F) } + /* Marks the availability of all the operation regions */ + Name (AVP2, Zero) + Name (AVGP, Zero) + Name (AVB0, Zero) + Name (AVB1, Zero) + Name (AVB2, Zero) + Name (AVB3, Zero) + Method (_REG, 2, NotSerialized) + { + If (LEqual (Arg0, 0x08)) + { + /* Marks the availability of GeneralPurposeIO + * 0x08: opregion space for GeneralPurposeIO + */ + Store (Arg1, AVGP) + } + If (LEqual (Arg0, 0xB0)) + { + /* Marks the availability of + * TI_PMIC_POWER_OPREGION_ID */ + Store (Arg1, AVB0) + } + If (LEqual (Arg0, 0xB1)) + { + /* Marks the availability of + * TI_PMIC_VR_VAL_OPREGION_ID */ + Store (Arg1, AVB1) + } + If (LEqual (Arg0, 0xB2)) + { + /* Marks the availability of + * TI_PMIC_CLK_OPREGION_ID */ + Store (Arg1, AVB2) + } + If (LEqual (Arg0, 0xB3)) + { + /* Marks the availability of + * TI_PMIC_CLK_FREQ_OPREGION_ID */ + Store (Arg1, AVB3) + } + If (LAnd (AVGP, LAnd (LAnd (AVB0, AVB1), + LAnd(AVB2, AVB3)))) + { + /* Marks the availability of all opregions */ + Store (1, AVP2) + } + Else + { + Store (0, AVP2) + } + } + + OperationRegion (GPOP, GeneralPurposeIo, 0, 0x2) Name (_CRS, ResourceTemplate () { I2cSerialBus (0x0049, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\\_SB.PCI0.I2C3", 0x00, ResourceConsumer, , ) + /* GPIO.4 is AVDD pin for user facing camera */ + GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, + IoRestrictionOutputOnly, "\\_SB.PCI0.I2C3.PMIC", + 0x00, ResourceConsumer,,) + { + 4 + } + /* GPIO.5 is XSHUTDOWN pin for user facing camera */ + GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, + IoRestrictionOutputOnly, "\\_SB.PCI0.I2C3.PMIC", + 0x00, ResourceConsumer,,) + { + 5 + } }) + + /* PMIC operation regions */ + /* 0xB0: TI_PMIC_POWER_OPREGION_ID + * VSIO: Sensor IO LDO output + * VCMC: VCM LDO output + * VAX1: Auxiliary LDO1 output + * VAX2: Auxiliary LDO2 output + * VACT: Analog LDO output + * VDCT: Core buck output + */ + OperationRegion (PWR1, 0xB0, Zero, 0x0100) + Field (PWR1, DWordAcc, NoLock, Preserve) + { + VSIO, 32, + VCMC, 32, + VAX1, 32, + VAX2, 32, + VACT, 32, + VDCT, 32, + } + + /* 0xB1: TI_PMIC_VR_VAL_OPREGION_ID + * SIOV: VSIO VR voltage value + * IOVA: VIO VR voltage value + * VCMV: VCM VR voltage value + * AX1V: Auxiliary LDO1 VR voltage value + * AX2V: Auxiliary LDO2 VR voltage value + * ACVA: Analog LDO VR voltage + * DCVA: Core buck VR volatage + */ + OperationRegion (PWR2, 0xB1, Zero, 0x0100) + Field (PWR2, DWordAcc, NoLock, Preserve) + { + SIOV, 32, + IOVA, 32, + VCMV, 32, + AX1V, 32, + AX2V, 32, + ACVA, 32, + DCVA, 32, + } + + /* 0xB2: TI_PMIC_CLK_OPREGION_ID + * PCTL: PLL control register + * PCT2: PLL control 2 register + * CFG1: Clock configuration 1 register + * CFG2: Clock configuration 2 register + */ + OperationRegion (CLKC, 0xB2, Zero, 0x0100) + Field (CLKC, DWordAcc, NoLock, Preserve) + { + PCTL, 32, + PCT2, 32, + CFG1, 32, + CFG2, 32, + } + + /* 0xB3: TI_PMIC_CLK_FREQ_OPREGION_ID + * PDV2: PLL output divider for HCLK_B + * BODI: PLL output divider for boost clock + * BUDI: PLL output divider for buck clock + * PSWR: PLL reference clock setting + * XTDV: Reference crystal divider + * PLDV: PLL feedback divider + * PODV: PLL output divider for HCLK_A + */ + OperationRegion (CLKF, 0xB3, Zero, 0x0100) + Field (CLKF, DWordAcc, NoLock, Preserve) + { + PDV2, 32, + BODI, 32, + BUDI, 32, + PSWR, 32, + XTDV, 32, + PLDV, 32, + PODV, 32, + } + + Mutex (MUTC, 0) + Method (CLKE, 0, Serialized) { + /* save Acquire result so we can check for + Mutex acquired */ + Store (Acquire (MUTC, 1000), Local0) + /* check for Mutex acquired */ + If (LEqual (Local0, Zero)) { + /* Set boost clock divider */ + BODI = 3 + /* Set buck clock divider */ + BUDI = 2 + /* Set the PLL_REF_CLK cyles */ + PSWR = 19 + /* Set the reference crystal divider */ + XTDV = 170 + /* Set PLL feedback divider */ + PLDV = 32 + /* Set PLL output divider for HCLK_A */ + PODV = 1 + /* Enable HCLK_A clock. + * CFG1: output selection for HCLK_A. + * CFG2: set drive strength for HCLK_A. + */ + CFG2 = 1 + CFG1 = 2 + /* Enable PLL output, crystal oscillator + * input capacitance control and set + * Xtal oscillator as clock source. + */ + PCTL = 209 + Sleep(1) + Release (MUTC) + } + } + + Method (CLKD, 0, Serialized) { + /* save Acquire result so we can check for + Mutex acquired */ + Store (Acquire (MUTC, 1000), Local0) + /* check for Mutex acquired */ + If (LEqual (Local0, Zero)) { + BODI = 0 + BUDI = 0 + PSWR = 0 + XTDV = 0 + PLDV = 0 + PODV = 0 + /* Disable HCLK_A clock */ + CFG2 = 0 + CFG1 = 0 + PCTL = 0 + Release (MUTC) + } + } + + /* Reference count for VSIO */ + Mutex (MUTV, 0) + Name (VSIC, 0) + Method (DOVD, 1, Serialized) { + /* Save Acquire result so we can check for + Mutex acquired */ + Store (Acquire (MUTV, 1000), Local0) + /* Check for Mutex acquired */ + If (LEqual (Local0, Zero)) { + /* Turn off VSIO */ + If (LEqual (Arg0, Zero)) { + VSIO = 0 + } ElseIf (LEqual (Arg0, 1)) { + VSIO = 3 + } + Release (MUTV) + } + } + + /* Power resource methods for CAM1 */ + PowerResource (OVFI, 0, 0) { + Name (STA, 0) + Method (_ON, 0, Serialized) { + If (LEqual (AVP2, 1)) { + If (LEqual (STA, 0)) { + /* Enable VSIO regulator + + daisy chain */ + DOVD(1) + + VAX2 = 1 /* Enable VAUX2 */ + + if (LNotEqual (AX2V, 52)) { + /* Set VAUX2 as + 1.8006 V */ + AX2V = 52 + } + Sleep(1) + + \_SB.PCI0.I2C3.PMIC.CLKE() + + VAX1 = 1 /* Enable VAUX1 */ + if (LNotEqual (AX1V, 19)) { + /* Set VAUX1 as 1.2132V */ + AX1V = 19 + } + Sleep(3) + + \_SB.PCI0.I2C3.CAM1.CGP4(1) + Sleep(3) + + \_SB.PCI0.I2C3.CAM1.CGP5(1) + Sleep(5) + STA = 1 + } + } + } + + Method (_OFF, 0, Serialized) { + If (LEqual (AVP2, 1)) { + If (LEqual (STA, 1)) { + Sleep(2) + \_SB.PCI0.I2C3.PMIC.CLKD() + Sleep(2) + \_SB.PCI0.I2C3.CAM1.CGP5(0) + Sleep(3) + VAX1 = 0 + Sleep(1) + \_SB.PCI0.I2C3.CAM1.CGP4(0) + Sleep(1) + VAX2 = 0 + Sleep(1) + DOVD(0) + Sleep(1) + + } + STA = 0 + } + } + + Method (_STA, 0, NotSerialized) { + Return (STA) + } + } } Device (CAM1) @@ -184,6 +839,47 @@ Scope (\_SB.PCI0.I2C3) ) }) + Field (\_SB.PCI0.I2C3.PMIC.GPOP, ByteAcc, NoLock, Preserve) + { + Connection + ( + GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, + IoRestrictionOutputOnly, + "\\_SB.PCI0.I2C3.PMIC", 0x00, + ResourceConsumer,,) + { + 4 + } + ), + GPO4, 1, + Connection + ( + GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, + IoRestrictionOutputOnly, + "\\_SB.PCI0.I2C3.PMIC", 0x00, + ResourceConsumer,,) + { + 5 + } + ), + GPO5, 1, + } + + /* Set or clear GPO4 GPIO */ + Method (CGP4, 1, Serialized) + { + GPO4 = Arg0 + } + + /* Set or clear GPO5 GPIO */ + Method (CGP5, 1, Serialized) + { + GPO5 = Arg0 + } + + Name (_PR0, Package () { ^^I2C3.PMIC.OVFI }) + Name (_PR3, Package () { ^^I2C3.PMIC.OVFI }) + /* Port0 of CAM1 is connected to port1 of CIO2 device */ Name (_DSD, Package () { ToUUID ("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),