blob: 9071096e9e59e2a663e8c08d24df25715cbcf2c8 [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>
lijuangfdf2fa62015-03-11 16:46:41 +080040
41#if USER_FORCE_RESET_SUPPORT
42/* Return 1 if it is a force resin triggered by user. */
43uint32_t is_user_force_reset(void)
44{
45 uint8_t poff_reason1 = pm8x41_get_pon_poff_reason1();
46 uint8_t poff_reason2 = pm8x41_get_pon_poff_reason2();
47
48 dprintf(SPEW, "poff_reason1: %d\n", poff_reason1);
49 dprintf(SPEW, "poff_reason2: %d\n", poff_reason2);
50 if (pm8x41_get_is_cold_boot() && (poff_reason1 == KPDPWR_AND_RESIN ||
51 poff_reason2 == STAGE3))
52 return 1;
53 else
54 return 0;
55}
56#endif
57
58unsigned check_reboot_mode(void)
59{
60 uint32_t restart_reason = 0;
61
62 /* Read reboot reason and scrub it */
63 restart_reason = readl(RESTART_REASON_ADDR);
64 writel(0x00, RESTART_REASON_ADDR);
65
66 return restart_reason;
67}
68
69unsigned check_hard_reboot_mode(void)
70{
71 uint8_t hard_restart_reason = 0;
lijuangfdf2fa62015-03-11 16:46:41 +080072
73 /* Read reboot reason and scrub it
Channagoud Kadabi17a0c942015-10-08 17:40:35 -070074 * Bit-2 to bit-7 of SOFT_RB_SPARE for hard reset reason
lijuangfdf2fa62015-03-11 16:46:41 +080075 */
Channagoud Kadabi88e52c12015-08-06 15:21:14 -070076 hard_restart_reason = REG_READ(PON_SOFT_RB_SPARE);
Channagoud Kadabi17a0c942015-10-08 17:40:35 -070077 REG_WRITE(PON_SOFT_RB_SPARE, hard_restart_reason & 0x03);
lijuangfdf2fa62015-03-11 16:46:41 +080078
lijuang395b5e62015-11-19 17:39:44 +080079 /* Extract the bits 2 to 7 and return */
Channagoud Kadabi17a0c942015-10-08 17:40:35 -070080 return (hard_restart_reason & 0xFC) >> 2;
lijuangfdf2fa62015-03-11 16:46:41 +080081}
82
lijuangdc20de12015-02-11 12:09:57 +080083/* Return true if it is triggered by alarm. */
84uint32_t check_alarm_boot(void)
85{
86 /* Check reboot reason and power on reason */
87 if (pm8x41_get_is_cold_boot()) {
88 if (pm8x41_get_pon_reason() == RTC_TRG)
89 return 1;
90 } else {
91 if (readl(RESTART_REASON_ADDR) == ALARM_BOOT)
92 return 1;
93 }
94
95 return 0;
96}
97
lijuangfdf2fa62015-03-11 16:46:41 +080098void reboot_device(unsigned reboot_reason)
99{
100 uint8_t reset_type = 0;
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700101 int ret = 0;
102#if USE_PON_REBOOT_REG
103 uint8_t value;
104#endif
lijuangfdf2fa62015-03-11 16:46:41 +0800105
lijuang395b5e62015-11-19 17:39:44 +0800106 /* Set cookie for dload mode */
107 if(set_download_mode(reboot_reason)) {
108 dprintf(CRITICAL, "HALT: set_download_mode not supported\n");
109 return;
110 }
lijuangfdf2fa62015-03-11 16:46:41 +0800111
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700112#if USE_PON_REBOOT_REG
113 value = REG_READ(PON_SOFT_RB_SPARE);
Channagoud Kadabi17a0c942015-10-08 17:40:35 -0700114 value |= (reboot_reason << 2);
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700115 REG_WRITE(PON_SOFT_RB_SPARE, value);
116#else
lijuangfdf2fa62015-03-11 16:46:41 +0800117 writel(reboot_reason, RESTART_REASON_ADDR);
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700118#endif
119 /* For Dload cases do a warm reset
120 * For other cases do a hard reset
lijuangfdf2fa62015-03-11 16:46:41 +0800121 */
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700122#if USE_PON_REBOOT_REG
lijuang395b5e62015-11-19 17:39:44 +0800123 if(reboot_reason == NORMAL_DLOAD || reboot_reason == EMERGENCY_DLOAD)
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700124#else
lijuang395b5e62015-11-19 17:39:44 +0800125 if(reboot_reason == FASTBOOT_MODE || reboot_reason == NORMAL_DLOAD ||
126 reboot_reason == EMERGENCY_DLOAD || reboot_reason == RECOVERY_MODE)
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700127#endif
lijuangfdf2fa62015-03-11 16:46:41 +0800128 reset_type = PON_PSHOLD_WARM_RESET;
129 else
130 reset_type = PON_PSHOLD_HARD_RESET;
131
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700132 pmic_reset_configure(reset_type);
lijuangfdf2fa62015-03-11 16:46:41 +0800133
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700134 /* Force spmi shutdown to avoid spmi lock up on some pmics */
135 ret = is_scm_call_available(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER);
136 if ( ret > 0)
137 {
138 ret = scm_halt_pmic_arbiter();
139 if (ret)
140 dprintf(CRITICAL , "Failed to halt pmic arbiter: %d\n", ret);
141 }
lijuangfdf2fa62015-03-11 16:46:41 +0800142
143 /* Drop PS_HOLD for MSM */
144 writel(0x00, MPM2_MPM_PS_HOLD);
145
146 mdelay(5000);
147
148 dprintf(CRITICAL, "Rebooting failed\n");
149}
150
Channagoud Kadabi77f46a32015-08-05 16:13:13 -0700151void shutdown_device()
152{
153 dprintf(CRITICAL, "Going down for shutdown.\n");
154
155 /* Configure PMIC for shutdown. */
156 pmic_reset_configure(PON_PSHOLD_SHUTDOWN);
157
158 /* Drop PS_HOLD for MSM */
159 writel(0x00, MPM2_MPM_PS_HOLD);
160
161 mdelay(5000);
162
163 dprintf(CRITICAL, "Shutdown failed\n");
164
165 ASSERT(0);
166}