blob: 7be94cd2ff52f7885883e1b8fe705234ef11a89c [file] [log] [blame]
lijuang395b5e62015-11-19 17:39:44 +08001/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
lijuangfdf2fa62015-03-11 16:46:41 +08002*
3* Redistribution and use in source and binary forms, with or without
4* modification, are permitted provided that the following conditions are
5* met:
6* * Redistributions of source code must retain the above copyright
7* notice, this list of conditions and the following disclaimer.
8* * Redistributions in binary form must reproduce the above
9* copyright notice, this list of conditions and the following
10* disclaimer in the documentation and/or other materials provided
11* with the distribution.
12* * Neither the name of The Linux Foundation nor the names of its
13* contributors may be used to endorse or promote products derived
14* from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29#include <debug.h>
30#include <platform/iomap.h>
31#include <reg.h>
32#include <target.h>
33#include <platform.h>
lijuangfdf2fa62015-03-11 16:46:41 +080034#include <pm8x41.h>
Channagoud Kadabi77f46a32015-08-05 16:13:13 -070035#include <pm8x41_hw.h>
lijuangfdf2fa62015-03-11 16:46:41 +080036#include <scm.h>
lijuangfdf2fa62015-03-11 16:46:41 +080037#include <stdlib.h>
38#include <reboot.h>
Channagoud Kadabi77f46a32015-08-05 16:13:13 -070039#include <qtimer.h>
Umang Agrawal233d5112019-05-23 16:31:14 +053040#include <smem.h>
lijuangfdf2fa62015-03-11 16:46:41 +080041
42#if USER_FORCE_RESET_SUPPORT
43/* Return 1 if it is a force resin triggered by user. */
44uint32_t is_user_force_reset(void)
45{
Umang Agrawal233d5112019-05-23 16:31:14 +053046 uint8_t poff_reason1;
47 uint8_t poff_reason2;
48 uint8_t is_cold_boot;
49 uint32_t pmic = target_get_pmic();
50 bool s3_reset;
51
52 if (pmic == PMIC_IS_PM660) {
53 poff_reason1 = pm660_get_pon_poff_reason1();
54 poff_reason2 = pm660_get_pon_poff_reason2();
55 is_cold_boot = pm660_get_is_cold_boot();
56 s3_reset = (poff_reason2 == PM660_STAGE3);
57 } else {
58 poff_reason1 = pm8x41_get_pon_poff_reason1();
59 poff_reason2 = pm8x41_get_pon_poff_reason2();
60 is_cold_boot = pm8x41_get_is_cold_boot();
61 s3_reset = (poff_reason2 == STAGE3);
62 }
lijuangfdf2fa62015-03-11 16:46:41 +080063
64 dprintf(SPEW, "poff_reason1: %d\n", poff_reason1);
65 dprintf(SPEW, "poff_reason2: %d\n", poff_reason2);
Umang Agrawal233d5112019-05-23 16:31:14 +053066 if (is_cold_boot && (poff_reason1 == KPDPWR_AND_RESIN || s3_reset))
lijuangfdf2fa62015-03-11 16:46:41 +080067 return 1;
68 else
69 return 0;
70}
71#endif
72
73unsigned check_reboot_mode(void)
74{
75 uint32_t restart_reason = 0;
76
77 /* Read reboot reason and scrub it */
78 restart_reason = readl(RESTART_REASON_ADDR);
79 writel(0x00, RESTART_REASON_ADDR);
80
81 return restart_reason;
82}
83
84unsigned check_hard_reboot_mode(void)
85{
86 uint8_t hard_restart_reason = 0;
lijuangfdf2fa62015-03-11 16:46:41 +080087
88 /* Read reboot reason and scrub it
Channagoud Kadabi17a0c942015-10-08 17:40:35 -070089 * Bit-2 to bit-7 of SOFT_RB_SPARE for hard reset reason
lijuangfdf2fa62015-03-11 16:46:41 +080090 */
Channagoud Kadabi88e52c12015-08-06 15:21:14 -070091 hard_restart_reason = REG_READ(PON_SOFT_RB_SPARE);
Channagoud Kadabi17a0c942015-10-08 17:40:35 -070092 REG_WRITE(PON_SOFT_RB_SPARE, hard_restart_reason & 0x03);
lijuangfdf2fa62015-03-11 16:46:41 +080093
lijuang395b5e62015-11-19 17:39:44 +080094 /* Extract the bits 2 to 7 and return */
Channagoud Kadabi17a0c942015-10-08 17:40:35 -070095 return (hard_restart_reason & 0xFC) >> 2;
lijuangfdf2fa62015-03-11 16:46:41 +080096}
97
lijuangdc20de12015-02-11 12:09:57 +080098/* Return true if it is triggered by alarm. */
99uint32_t check_alarm_boot(void)
100{
101 /* Check reboot reason and power on reason */
102 if (pm8x41_get_is_cold_boot()) {
103 if (pm8x41_get_pon_reason() == RTC_TRG)
104 return 1;
105 } else {
106 if (readl(RESTART_REASON_ADDR) == ALARM_BOOT)
107 return 1;
108 }
109
110 return 0;
111}
112
lijuangfdf2fa62015-03-11 16:46:41 +0800113void reboot_device(unsigned reboot_reason)
114{
115 uint8_t reset_type = 0;
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700116 int ret = 0;
117#if USE_PON_REBOOT_REG
118 uint8_t value;
119#endif
lijuangfdf2fa62015-03-11 16:46:41 +0800120
lijuang395b5e62015-11-19 17:39:44 +0800121 /* Set cookie for dload mode */
122 if(set_download_mode(reboot_reason)) {
123 dprintf(CRITICAL, "HALT: set_download_mode not supported\n");
124 return;
125 }
lijuangfdf2fa62015-03-11 16:46:41 +0800126
lijuangf0c7b622016-05-24 16:06:12 +0800127 if (reboot_reason != NORMAL_DLOAD && reboot_reason != EMERGENCY_DLOAD) {
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700128#if USE_PON_REBOOT_REG
lijuangf0c7b622016-05-24 16:06:12 +0800129 value = REG_READ(PON_SOFT_RB_SPARE);
130 value |= (reboot_reason << 2);
131 REG_WRITE(PON_SOFT_RB_SPARE, value);
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700132#else
lijuangf0c7b622016-05-24 16:06:12 +0800133 writel(reboot_reason, RESTART_REASON_ADDR);
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700134#endif
lijuangf0c7b622016-05-24 16:06:12 +0800135 }
136
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700137 /* For Dload cases do a warm reset
138 * For other cases do a hard reset
lijuangfdf2fa62015-03-11 16:46:41 +0800139 */
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700140#if USE_PON_REBOOT_REG
lijuang1cff8382016-01-11 17:56:54 +0800141 if(reboot_reason == NORMAL_DLOAD || reboot_reason == EMERGENCY_DLOAD) {
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700142#else
lijuang395b5e62015-11-19 17:39:44 +0800143 if(reboot_reason == FASTBOOT_MODE || reboot_reason == NORMAL_DLOAD ||
lijuang1cff8382016-01-11 17:56:54 +0800144 reboot_reason == EMERGENCY_DLOAD || reboot_reason == RECOVERY_MODE) {
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700145#endif
lijuangfdf2fa62015-03-11 16:46:41 +0800146 reset_type = PON_PSHOLD_WARM_RESET;
lijuang1cff8382016-01-11 17:56:54 +0800147#if DISABLE_DLOAD_MODE
148 if (reboot_reason == NORMAL_DLOAD)
149 reset_type = PON_PSHOLD_HARD_RESET;
150#endif
151 } else {
lijuangfdf2fa62015-03-11 16:46:41 +0800152 reset_type = PON_PSHOLD_HARD_RESET;
lijuang1cff8382016-01-11 17:56:54 +0800153 }
lijuangfdf2fa62015-03-11 16:46:41 +0800154
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700155 pmic_reset_configure(reset_type);
lijuangfdf2fa62015-03-11 16:46:41 +0800156
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700157 /* Force spmi shutdown to avoid spmi lock up on some pmics */
158 ret = is_scm_call_available(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER);
159 if ( ret > 0)
160 {
161 ret = scm_halt_pmic_arbiter();
162 if (ret)
163 dprintf(CRITICAL , "Failed to halt pmic arbiter: %d\n", ret);
164 }
lijuangfdf2fa62015-03-11 16:46:41 +0800165
166 /* Drop PS_HOLD for MSM */
167 writel(0x00, MPM2_MPM_PS_HOLD);
168
169 mdelay(5000);
170
171 dprintf(CRITICAL, "Rebooting failed\n");
172}
173
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700174void shutdown_device()
175{
176 dprintf(CRITICAL, "Going down for shutdown.\n");
177
178 /* Configure PMIC for shutdown. */
179 pmic_reset_configure(PON_PSHOLD_SHUTDOWN);
180
181 /* Drop PS_HOLD for MSM */
182 writel(0x00, MPM2_MPM_PS_HOLD);
183
184 mdelay(5000);
185
186 dprintf(CRITICAL, "Shutdown failed\n");
187
188 ASSERT(0);
189}