mb/google/poppy: Add camera devices power sequencing through ACPI power resources

This patch controls the camera devices power through ACPI power resource.
* Add Opregions for PMIC,
	* 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=b:38326541
BRANCH=none
TEST=Build and boot poppy. Dump and verify that the generated DSDT table
has the required entries.

Change-Id: I87cd0508ed5ed922211a51f43ee96b6f44cf673d
Signed-off-by: V Sowmya <v.sowmya@intel.com>
Signed-off-by: Rizwan Qureshi <rizwan.qureshi@intel.com>
Reviewed-on: https://review.coreboot.org/20054
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
diff --git a/src/mainboard/google/poppy/acpi/mipi_camera.asl b/src/mainboard/google/poppy/acpi/mipi_camera.asl
index 13d33f6..a564b80 100644
--- a/src/mainboard/google/poppy/acpi/mipi_camera.asl
+++ b/src/mainboard/google/poppy/acpi/mipi_camera.asl
@@ -17,33 +17,478 @@
 {
 	Device (PMIC)
 	{
-		Name (_HID, "INT3472")  // _HID: Hardware ID
-		Name (_UID, Zero)  // _UID: Unique ID
-		Name (_DDN, "TPS68470 PMIC")  // _DDN: DOS Device Name
+		Name (_HID, "INT3472") /* _HID: Hardware ID */
+		Name (_UID, Zero)  /* _UID: Unique ID */
+		Name (_DDN, "TPS68470 PMIC")  /* _DDN: DOS Device Name */
 		Name (CAMD, 0x64)
 
-		Method (_STA, 0, NotSerialized)  // _STA: Status
+		Method (_STA, 0, NotSerialized)  /* _STA: Status */
 		{
 			Return (0x0F)
 		}
 
+		/* Marks the availability of all the operation regions */
+		Name (AVBL, 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, AVBL)
+			}
+			Else
+			{
+				Store (0, AVBL)
+			}
+		}
+
+		OperationRegion (GPOP, GeneralPurposeIo, 0, 0x2)
 		Name (_CRS, ResourceTemplate ()
 		{
 			I2cSerialBus (0x004D, ControllerInitiated, 0x00061A80,
 				AddressingMode7Bit, "\\_SB.PCI0.I2C2",
 				0x00, ResourceConsumer, ,
 			)
+			/* GPIO.4 is AVDD pin for user facing camera */
+			GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
+				IoRestrictionOutputOnly, "\\_SB.PCI0.I2C2.PMIC",
+				0x00, ResourceConsumer,,)
+			{
+				4
+			}
+			/* GPIO.5 is XSHUTDOWN pin for user facing camera */
+			GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
+				IoRestrictionOutputOnly, "\\_SB.PCI0.I2C2.PMIC",
+				0x00, ResourceConsumer,,)
+			{
+				5
+			}
+			/* 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,
+		}
+
+		/* CLE0 and CLE1 are used to determine if both the clocks
+		are enabled or disabled. */
+		Mutex (MUTC, 0)
+		Name (CLE0, 0)
+		Name (CLE1, 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)) {
+			/* Enable clocks only when a sensor is turned on and
+			both the clocks are disabled */
+				If (LNot (LOr (CLE0, CLE1))) {
+					/* 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
+					/* Set PLL output divider for HCLK_B */
+					PDV2 = 1
+					/* Enable clocks for both the sensors
+					 * CFG1: output selection for HCLK_A and
+					 * HCLK_B.
+					 * CFG2: set drive strength for HCLK_A
+					 * and HCLK_B.
+					 */
+					CFG2 = 5
+					CFG1 = 10
+					/* Enable PLL output, crystal oscillator
+					 * input capacitance control and set
+					 * Xtal oscillator as clock source.
+					 */
+					PCTL = 209
+					Sleep(1)
+				}
+				Release (MUTC)
+			}
+		}
+
+		/* Clocks need to be disabled only if both the sensors are
+		turned off */
+		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)) {
+				If (LNot (LOr (CLE0, CLE1))) {
+					BODI = 0
+					BUDI = 0
+					PSWR = 0
+					XTDV = 0
+					PLDV = 0
+					PODV = 0
+					PDV2 = 0
+					/* Disable clocks for both the
+					sensors */
+					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 < 3 */
+					If (LLess (VSIC, 3)) {
+						/* 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 (AVBL, 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()
+						CLE0 = 1
+
+						VDCT = 1
+						if (LNotEqual (DCVA, 12)) {
+							/* Set CORE at 1.2V */
+							DCVA = 12
+						}
+						Sleep(3)
+						\_SB.PCI0.I2C2.CAM0.CRST(1)
+
+						STA = 1
+					}
+				}
+			}
+
+			Method (_OFF, 0, Serialized) {
+				If (LEqual (AVBL, 1)) {
+					If (LEqual (STA, 1)) {
+						Sleep(2)
+						CLE0 = 0
+						\_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 CAM1 */
+		PowerResource (OVFI, 0, 0) {
+			Name (STA, 0)
+			Method (_ON, 0, Serialized) {
+				If (LEqual (AVBL, 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.I2C2.PMIC.CLKE()
+						CLE1 = 1
+
+						VAX1 = 1 /* Enable VAUX1 */
+						if (LNotEqual (AX1V, 19)) {
+						/* Set VAUX1 as 1.2132V */
+							AX1V = 19
+						}
+						Sleep(3)
+
+						\_SB.PCI0.I2C4.CAM1.CGP4(1)
+						Sleep(3)
+
+						\_SB.PCI0.I2C4.CAM1.CGP5(1)
+						Sleep(3)
+						STA = 1
+					}
+				}
+			}
+
+			Method (_OFF, 0, Serialized) {
+				If (LEqual (AVBL, 1)) {
+					If (LEqual (STA, 1)) {
+						Sleep(2)
+						CLE1 = 0
+						\_SB.PCI0.I2C2.PMIC.CLKD()
+						Sleep(2)
+						\_SB.PCI0.I2C4.CAM1.CGP5(0)
+						Sleep(3)
+						VAX1 = 0
+						Sleep(1)
+						\_SB.PCI0.I2C4.CAM1.CGP4(0)
+						Sleep(1)
+						VAX2 = 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 (AVBL, 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 (AVBL, 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)
 	{
-		Name (_HID, "OVTID850")  // _HID: Hardware ID
-		Name (_UID, Zero)  // _UID: Unique ID
-		Name (_DDN, "OV 13850 Camera")  // _DDN: DOS Device Name
+		Name (_HID, "OVTID850")  /* _HID: Hardware ID */
+		Name (_UID, Zero)  /* _UID: Unique ID */
+		Name (_DDN, "OV 13850 Camera") /* _DDN: DOS Device Name */
 		Name (CAMD, 0x02)
 
-		Method (_STA, 0, NotSerialized)  // _STA: Status
+		Method (_STA, 0, NotSerialized)  /* _STA: Status */
 		{
 			Return (0x0F)
 		}
@@ -57,6 +502,30 @@
 				)
 		})
 
+		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"),
@@ -115,12 +584,12 @@
 
 	Device (VCM0)
 	{
-		Name (_HID, "DWDWD000")  // _HID: Hardware ID
-		Name (_UID, Zero)  // _UID: Unique ID
-		Name (_DDN, "Dongwoon AF DAC")  // _DDN: DOS Device Name
+		Name (_HID, "DWDWD000")  /* _HID: Hardware ID */
+		Name (_UID, Zero)  /* _UID: Unique ID */
+		Name (_DDN, "Dongwoon AF DAC") /* _DDN: DOS Device Name */
 		Name (CAMD, 0x03)
 
-		Method (_STA, 0, NotSerialized)  // _STA: Status
+		Method (_STA, 0, NotSerialized)  /* _STA: Status */
 		{
 			Return (0x0F)
 		}
@@ -133,6 +602,9 @@
 				0x00, ResourceConsumer, ,
 				)
 		})
+
+		Name (_PR0, Package () { ^PMIC.VCMP })
+		Name (_PR3, Package () { ^PMIC.VCMP })
 	}
 }
 
@@ -140,12 +612,12 @@
 {
 	Device (CAM1)
 	{
-		Name (_HID, "INT3479")  // _HID: Hardware ID
-		Name (_UID, Zero)  // _UID: Unique ID
-		Name (_DDN, "OV 5670 Camera")  // _DDN: DOS Device Name
+		Name (_HID, "INT3479") /* _HID: Hardware ID */
+		Name (_UID, Zero)  /* _UID: Unique ID */
+		Name (_DDN, "OV 5670 Camera")  /* _DDN: DOS Device Name */
 		Name (CAMD, 0x02)
 
-		Method (_STA, 0, NotSerialized)  // _STA: Status
+		Method (_STA, 0, NotSerialized)  /* _STA: Status */
 		{
 			Return (0x0F)
 		}
@@ -159,6 +631,47 @@
 			)
 		})
 
+		Field (\_SB.PCI0.I2C2.PMIC.GPOP, ByteAcc, NoLock, Preserve)
+		{
+			Connection
+			(
+				GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
+					IoRestrictionOutputOnly,
+					"\\_SB.PCI0.I2C2.PMIC", 0x00,
+					ResourceConsumer,,)
+				{
+					4
+				}
+			),
+			GPO4, 1,
+			Connection
+			(
+				GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
+					IoRestrictionOutputOnly,
+					"\\_SB.PCI0.I2C2.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 () { ^^I2C2.PMIC.OVFI })
+		Name (_PR3, Package () { ^^I2C2.PMIC.OVFI })
+
 		/* Port0 of CAM1 is connected to port1 of CIO2 device */
 		Name (_DSD, Package () {
 			ToUUID ("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),