summaryrefslogtreecommitdiff
path: root/power/sdm845.c
diff options
context:
space:
mode:
Diffstat (limited to 'power/sdm845.c')
-rw-r--r--power/sdm845.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/power/sdm845.c b/power/sdm845.c
index 9fb4bcd141..837a54875d 100644
--- a/power/sdm845.c
+++ b/power/sdm845.c
@@ -37,7 +37,9 @@
#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args)
/* Masks for power signals */
-#define IN_POWER_GOOD POWER_SIGNAL_MASK(SDM845_POWER_GOOD)
+#define IN_POWER_GOOD POWER_SIGNAL_MASK(SDM845_POWER_GOOD)
+#define IN_AP_RST_ASSERTED POWER_SIGNAL_MASK(SDM845_AP_RST_ASSERTED)
+
/* Long power key press to force shutdown */
#define DELAY_FORCE_SHUTDOWN (8 * SECOND)
@@ -67,6 +69,9 @@
/* Wait for polling the AP on signal */
#define PMIC_POWER_AP_WAIT (1 * MSEC)
+/* The length of an issued low pulse to the PM845_RESIN_L signal */
+#define PMIC_RESIN_PULSE_LENGTH (20 * MSEC)
+
/* The timeout of the check if the system can boot AP */
#define CAN_BOOT_AP_CHECK_TIMEOUT (500 * MSEC)
@@ -670,14 +675,39 @@ void chipset_force_shutdown(enum chipset_shutdown_reason reason)
void chipset_reset(enum chipset_reset_reason reason)
{
- /*
- * Before we can reprogram the PMIC to make the PMIC RESIN_N pin as
- * reset pin and zero-latency. We do cold reset instead.
- */
+ int rv;
+
CPRINTS("%s(%d)", __func__, reason);
report_ap_reset(reason);
- request_cold_reset();
+ /* The host command is used to hard reset AP. Check b/119261783 */
+ if (reason == CHIPSET_RESET_HOST_CMD) {
+ request_cold_reset();
+ return;
+ }
+
+ /*
+ * Warm reset sequence:
+ * 1. Issue a low pulse to PM845_RESIN_L, which triggers PMIC
+ * to do a warm reset (requiring reprogramming PMIC registers
+ * to make PM845_RESIN_L as a warm reset trigger).
+ * 2. PMIC then issues a low pulse to AP_RST_L to reset AP.
+ * EC monitors the signal to see any low pulse.
+ * 2.1. If a low pulse found, done.
+ * 2.2. If a low pulse not found (the above PMIC registers
+ * not programmed or programmed wrong), issue a request
+ * to initiate a cold reset power sequence.
+ */
+
+ gpio_set_level(GPIO_PM845_RESIN_L, 0);
+ usleep(PMIC_RESIN_PULSE_LENGTH);
+ gpio_set_level(GPIO_PM845_RESIN_L, 1);
+
+ rv = power_wait_signals_timeout(IN_AP_RST_ASSERTED,
+ PMIC_POWER_AP_RESPONSE_TIMEOUT);
+ /* Exception case: PMIC not work as expected, request a cold reset */
+ if (rv != EC_SUCCESS)
+ request_cold_reset();
}
/**