soc/intel/cannonlake: Add a config for configuring SD_VDD1_PWR_EN#

SD controller in CNL-PCH provides a ability to configure the behavior of
SD_VDD1_PWR_EN# as an active high or low signal. FSP provides an UPD
"SdCardPowerEnableActiveHigh" to control the same.

However, for platforms using SD_VDD1_PWR_EN# as active high, the SDXC
card connector is always powered and may impact system power. This is because
SD_VDD1_PWR_EN# does not de-assert during SDXC D3 or when SD card is not
inserted.

Workaround is to change the pad ownership of SD_VDD1_PWR_EN to GPIO and
force the TX buffer to low in _PS3. And restore the pad mode to native
function in _PS0.

Hence add a Kconfig option to update the UPD, which the board can select
based on how the SD_VDD1_PWR_EN is implemented on it. And, the workaround
gets applied based on this config.

BUG=b:123350329

Change-Id: Iee262d7ecdf8c31362aec3d95dd9b3e8359e0c25
Signed-off-by: Rizwan Qureshi <rizwan.qureshi@intel.com>
Reviewed-on: https://review.coreboot.org/c/31445
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/soc/intel/cannonlake/Kconfig b/src/soc/intel/cannonlake/Kconfig
index cd8819d..927409d 100644
--- a/src/soc/intel/cannonlake/Kconfig
+++ b/src/soc/intel/cannonlake/Kconfig
@@ -235,6 +235,15 @@
 	hex
 	default 0x200000
 
+config MB_HAS_ACTIVE_HIGH_SD_PWR_ENABLE
+	bool
+	default n
+	help
+	  Select this if the board has a SD_PWR_ENABLE pin connected to a
+	  active high sensing load switch to turn on power to the card reader.
+	  This will enable a workaround in ASL _PS3 and _PS0 methods to force
+	  SD_PWR_ENABLE to stay low in D3.
+
 choice
 	prompt "Cache-as-ram implementation"
 	default USE_CANNONLAKE_CAR_NEM_ENHANCED if MAINBOARD_HAS_CHROMEOS
diff --git a/src/soc/intel/cannonlake/acpi/scs.asl b/src/soc/intel/cannonlake/acpi/scs.asl
index 896fd77..1806e75 100644
--- a/src/soc/intel/cannonlake/acpi/scs.asl
+++ b/src/soc/intel/cannonlake/acpi/scs.asl
@@ -111,6 +111,11 @@
 			/* Set Power State to D0 */
 			And (PMCR, 0xFFFC, PMCR)
 			Store (PMCR, ^TEMP)
+
+#if IS_ENABLED(CONFIG_MB_HAS_ACTIVE_HIGH_SD_PWR_ENABLE)
+			/* Change pad mode to Native */
+			GPMO(SD_PWR_EN_PIN, 0x1)
+#endif
 		}
 
 		Method (_PS3, 0, Serialized)
@@ -120,6 +125,17 @@
 			/* Set Power State to D3 */
 			Or (PMCR, 0x0003, PMCR)
 			Store (PMCR, ^TEMP)
+
+#if IS_ENABLED(CONFIG_MB_HAS_ACTIVE_HIGH_SD_PWR_ENABLE)
+			/* Change pad mode to GPIO control */
+			GPMO(SD_PWR_EN_PIN, 0x0)
+
+			/* Enable Tx Buffer */
+			GTXE(SD_PWR_EN_PIN, 0x1)
+
+			/* Drive TX to zero */
+			CTXS(SD_PWR_EN_PIN)
+#endif
 		}
 
 		Device (CARD)
diff --git a/src/soc/intel/cannonlake/fsp_params.c b/src/soc/intel/cannonlake/fsp_params.c
index 17a014b..1ebde35 100644
--- a/src/soc/intel/cannonlake/fsp_params.c
+++ b/src/soc/intel/cannonlake/fsp_params.c
@@ -208,10 +208,13 @@
 	}
 
 	dev = dev_find_slot(0, PCH_DEVFN_SDCARD);
-	if (!dev)
+	if (!dev) {
 		params->ScsSdCardEnabled = 0;
-	else
+	} else {
 		params->ScsSdCardEnabled = dev->enabled;
+		params->SdCardPowerEnableActiveHigh =
+			IS_ENABLED(CONFIG_MB_HAS_ACTIVE_HIGH_SD_PWR_ENABLE);
+	}
 
 	dev = dev_find_slot(0, PCH_DEVFN_UFS);
 	if (!dev)
diff --git a/src/soc/intel/cannonlake/include/soc/gpio_soc_defs.h b/src/soc/intel/cannonlake/include/soc/gpio_soc_defs.h
index 5d7c0e8..03f4314 100644
--- a/src/soc/intel/cannonlake/include/soc/gpio_soc_defs.h
+++ b/src/soc/intel/cannonlake/include/soc/gpio_soc_defs.h
@@ -352,4 +352,6 @@
 #define NUM_GPIO_COM3_PADS	(GPIO_RSVD_38 - HDA_BCLK + 1)
 
 #define TOTAL_PADS		275
+
+#define SD_PWR_EN_PIN		GPP_A17
 #endif