trogdor: Add fingerprint power sequencing

Some Trogdor variants will include a fingerprint sensor, so this patch
adds support for its power sequencing. There is a requirement that the
fingerprint power needs to be *off* for at least 200ms, and when it is
turned back on it needs to stabilize for at least 3.5ms before taking
the FPMCU out of reset. We meet these timing requirements by splitting
the sequence across bootblock, romstage and ramstage. On current Trogdor
boards we measured <end of bootblock> to <end of romstage> at ~430ms and
<end of romstage> to <start of ramstage> at 12ms, so we easily meet the
required numbers this way.

BRANCH=trogdor
BUG=b:170284663

Signed-off-by: Julius Werner <jwerner@chromium.org>
Change-Id: Iccd77e6e1c378110fca2b2b7ff1f534fce54f8ea
Reviewed-on: https://review.coreboot.org/c/coreboot/+/50504
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Shelley Chen <shchen@google.com>
diff --git a/src/mainboard/google/trogdor/Kconfig b/src/mainboard/google/trogdor/Kconfig
index b3ec4b5..dd9c4a6 100644
--- a/src/mainboard/google/trogdor/Kconfig
+++ b/src/mainboard/google/trogdor/Kconfig
@@ -8,6 +8,11 @@
 	def_bool y if BOARD_GOOGLE_TROGDOR
 	def_bool n
 
+config TROGDOR_HAS_FINGERPRINT
+	bool
+	default y if BOARD_GOOGLE_COACHZ
+	default n
+
 config BOARD_SPECIFIC_OPTIONS
 	def_bool y
 	select BOARD_ROMSIZE_KB_8192
diff --git a/src/mainboard/google/trogdor/board.h b/src/mainboard/google/trogdor/board.h
index ebce3b5..4dc5010 100644
--- a/src/mainboard/google/trogdor/board.h
+++ b/src/mainboard/google/trogdor/board.h
@@ -3,6 +3,7 @@
 #ifndef _COREBOOT_SRC_MAINBOARD_GOOGLE_TROGDOR_BOARD_H_
 #define _COREBOOT_SRC_MAINBOARD_GOOGLE_TROGDOR_BOARD_H_
 
+#include <assert.h>
 #include <boardid.h>
 #include <gpio.h>
 #include <soc/gpio.h>
@@ -20,6 +21,18 @@
 	(CONFIG(BOARD_GOOGLE_COACHZ) ? (board_id() == 0 ? GPIO(52) : \
 	GPIO(67)) : GPIO(30)))
 
+/* Fingerprint-specific GPIOs. Only for fingerprint-enabled devices (e.g. CoachZ). */
+#if CONFIG(TROGDOR_HAS_FINGERPRINT)
+#define GPIO_FPMCU_BOOT0	GPIO(10)
+#define GPIO_FP_RST_L		GPIO(22)
+#define GPIO_EN_FP_RAILS	GPIO(74)
+#else
+#define GPIO_FPMCU_BOOT0	dead_code_t(gpio_t)
+#define GPIO_FP_RST_L		dead_code_t(gpio_t)
+#define GPIO_EN_FP_RAILS	dead_code_t(gpio_t)
+#endif
+
+
 void setup_chromeos_gpios(void);
 
 #endif /* _COREBOOT_SRC_MAINBOARD_GOOGLE_TROGDOR_BOARD_H_ */
diff --git a/src/mainboard/google/trogdor/chromeos.c b/src/mainboard/google/trogdor/chromeos.c
index d6b1836..2136da3 100644
--- a/src/mainboard/google/trogdor/chromeos.c
+++ b/src/mainboard/google/trogdor/chromeos.c
@@ -12,9 +12,16 @@
 	gpio_input_pullup(GPIO_SD_CD_L);
 	gpio_input_irq(GPIO_H1_AP_INT, IRQ_TYPE_RISING_EDGE, GPIO_PULL_UP);
 	gpio_output(GPIO_AMP_ENABLE, 0);
+
 	gpio_output(GPIO_BACKLIGHT_ENABLE, 0);
 	gpio_output(GPIO_EN_PP3300_DX_EDP, 0);
 	gpio_output(GPIO_EDP_BRIDGE_ENABLE, 0);
+
+	if (CONFIG(TROGDOR_HAS_FINGERPRINT)) {
+		gpio_output(GPIO_FPMCU_BOOT0, 0);
+		gpio_output(GPIO_FP_RST_L, 0);
+		gpio_output(GPIO_EN_FP_RAILS, 0);
+	}
 }
 
 void fill_lb_gpios(struct lb_gpios *gpios)
diff --git a/src/mainboard/google/trogdor/mainboard.c b/src/mainboard/google/trogdor/mainboard.c
index 7465c63..9bf8507 100644
--- a/src/mainboard/google/trogdor/mainboard.c
+++ b/src/mainboard/google/trogdor/mainboard.c
@@ -110,6 +110,11 @@
 
 static void mainboard_init(struct device *dev)
 {
+	/* Take FPMCU out of reset. Power was already applied
+	   in romstage and should have stabilized by now. */
+	if (CONFIG(TROGDOR_HAS_FINGERPRINT))
+		gpio_output(GPIO_FP_RST_L, 1);
+
 	setup_usb();
 	qi2s_configure_gpios();
 	load_qup_fw();
diff --git a/src/mainboard/google/trogdor/romstage.c b/src/mainboard/google/trogdor/romstage.c
index 8b6f1de..e110460 100644
--- a/src/mainboard/google/trogdor/romstage.c
+++ b/src/mainboard/google/trogdor/romstage.c
@@ -5,6 +5,8 @@
 #include <soc/qclib_common.h>
 #include <soc/watchdog.h>
 
+#include "board.h"
+
 static void prepare_usb(void)
 {
 	/*
@@ -22,4 +24,10 @@
 
 	/* QCLib: DDR init & train */
 	qclib_load_and_run();
+
+	/* This rail needs to be stable by the time we take the FPMCU out of
+	   reset in ramstage, so already turn it on here. This needs to happen
+	   at least 200ms after this pin was first driven low in the bootblock. */
+	if (CONFIG(TROGDOR_HAS_FINGERPRINT))
+		gpio_output(GPIO_EN_FP_RAILS, 1);
 }