blob: 5b318893727bd0ebcc1a9a32b1056a7122134b58 [file] [log] [blame]
David Collins073a2c3292016-11-30 14:27:24 -08001/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Abhimanyu Kapur78be31762013-07-30 17:05:28 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/init.h>
17#include <linux/kernel.h>
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070018
Abhimanyu Kapur78be31762013-07-30 17:05:28 -070019#include <linux/io.h>
20#include <linux/of.h>
21#include <linux/platform_device.h>
22#include <linux/module.h>
23#include <linux/reboot.h>
Pramod Gurav18a702e2014-09-25 17:03:51 +053024#include <linux/pm.h>
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070025#include <linux/delay.h>
David Collins073a2c3292016-11-30 14:27:24 -080026#include <linux/input/qpnp-power-on.h>
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070027#include <linux/of_address.h>
Abhimanyu Kapur78be31762013-07-30 17:05:28 -070028
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070029#include <asm/cacheflush.h>
30#include <asm/system_misc.h>
Channagoud Kadabica9159d2017-04-25 19:44:07 -070031#include <asm/memory.h>
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070032
33#include <soc/qcom/scm.h>
34#include <soc/qcom/restart.h>
35#include <soc/qcom/watchdog.h>
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +053036#include <soc/qcom/minidump.h>
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070037
38#define EMERGENCY_DLOAD_MAGIC1 0x322A4F99
39#define EMERGENCY_DLOAD_MAGIC2 0xC67E4350
40#define EMERGENCY_DLOAD_MAGIC3 0x77777777
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +053041#define EMMC_DLOAD_TYPE 0x2
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070042
43#define SCM_IO_DISABLE_PMIC_ARBITER 1
44#define SCM_IO_DEASSERT_PS_HOLD 2
45#define SCM_WDOG_DEBUG_BOOT_PART 0x9
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +053046#define SCM_DLOAD_FULLDUMP 0X10
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070047#define SCM_EDLOAD_MODE 0X01
48#define SCM_DLOAD_CMD 0x10
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +053049#define SCM_DLOAD_MINIDUMP 0X20
50#define SCM_DLOAD_BOTHDUMPS (SCM_DLOAD_MINIDUMP | SCM_DLOAD_FULLDUMP)
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070051
52static int restart_mode;
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +053053static void __iomem *restart_reason, *dload_type_addr;
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070054static bool scm_pmic_arbiter_disable_supported;
55static bool scm_deassert_ps_hold_supported;
56/* Download mode master kill-switch */
Abhimanyu Kapur78be31762013-07-30 17:05:28 -070057static void __iomem *msm_ps_hold;
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070058static phys_addr_t tcsr_boot_misc_detect;
Kyle Yandb13f542016-12-02 12:00:50 -080059static int download_mode = 1;
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +053060static struct kobject dload_kobj;
Pramod Gurav18a702e2014-09-25 17:03:51 +053061
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070062#ifdef CONFIG_QCOM_DLOAD_MODE
63#define EDL_MODE_PROP "qcom,msm-imem-emergency_download_mode"
64#define DL_MODE_PROP "qcom,msm-imem-download_mode"
Channagoud Kadabica9159d2017-04-25 19:44:07 -070065#ifdef CONFIG_RANDOMIZE_BASE
66#define KASLR_OFFSET_PROP "qcom,msm-imem-kaslr_offset"
67#endif
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070068
69static int in_panic;
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +053070static int dload_type = SCM_DLOAD_FULLDUMP;
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070071static void *dload_mode_addr;
72static bool dload_mode_enabled;
73static void *emergency_dload_mode_addr;
Channagoud Kadabica9159d2017-04-25 19:44:07 -070074#ifdef CONFIG_RANDOMIZE_BASE
75static void *kaslr_imem_addr;
76#endif
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070077static bool scm_dload_supported;
78
79static int dload_set(const char *val, struct kernel_param *kp);
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +053080/* interface for exporting attributes */
81struct reset_attribute {
82 struct attribute attr;
83 ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
84 char *buf);
85 size_t (*store)(struct kobject *kobj, struct attribute *attr,
86 const char *buf, size_t count);
87};
88#define to_reset_attr(_attr) \
89 container_of(_attr, struct reset_attribute, attr)
90#define RESET_ATTR(_name, _mode, _show, _store) \
91 static struct reset_attribute reset_attr_##_name = \
92 __ATTR(_name, _mode, _show, _store)
93
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070094module_param_call(download_mode, dload_set, param_get_int,
95 &download_mode, 0644);
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +053096
Channagoud Kadabi4059cb62016-08-23 12:14:01 -070097static int panic_prep_restart(struct notifier_block *this,
98 unsigned long event, void *ptr)
99{
100 in_panic = 1;
Pramod Gurav18a702e2014-09-25 17:03:51 +0530101 return NOTIFY_DONE;
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700102}
103
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700104static struct notifier_block panic_blk = {
105 .notifier_call = panic_prep_restart,
Pramod Gurav18a702e2014-09-25 17:03:51 +0530106};
107
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530108static int scm_set_dload_mode(int arg1, int arg2)
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700109{
110 struct scm_desc desc = {
111 .args[0] = arg1,
112 .args[1] = arg2,
113 .arginfo = SCM_ARGS(2),
114 };
115
116 if (!scm_dload_supported) {
117 if (tcsr_boot_misc_detect)
118 return scm_io_write(tcsr_boot_misc_detect, arg1);
119
120 return 0;
121 }
122
123 if (!is_scm_armv8())
124 return scm_call_atomic2(SCM_SVC_BOOT, SCM_DLOAD_CMD, arg1,
125 arg2);
126
127 return scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT, SCM_DLOAD_CMD),
128 &desc);
129}
130
131static void set_dload_mode(int on)
132{
133 int ret;
134
135 if (dload_mode_addr) {
136 __raw_writel(on ? 0xE47B337D : 0, dload_mode_addr);
137 __raw_writel(on ? 0xCE14091A : 0,
138 dload_mode_addr + sizeof(unsigned int));
139 /* Make sure the download cookie is updated */
140 mb();
141 }
142
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +0530143 ret = scm_set_dload_mode(on ? dload_type : 0, 0);
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700144 if (ret)
145 pr_err("Failed to set secure DLOAD mode: %d\n", ret);
146
147 dload_mode_enabled = on;
148}
149
150static bool get_dload_mode(void)
151{
152 return dload_mode_enabled;
153}
154
155static void enable_emergency_dload_mode(void)
156{
157 int ret;
158
159 if (emergency_dload_mode_addr) {
160 __raw_writel(EMERGENCY_DLOAD_MAGIC1,
161 emergency_dload_mode_addr);
162 __raw_writel(EMERGENCY_DLOAD_MAGIC2,
163 emergency_dload_mode_addr +
164 sizeof(unsigned int));
165 __raw_writel(EMERGENCY_DLOAD_MAGIC3,
166 emergency_dload_mode_addr +
167 (2 * sizeof(unsigned int)));
168
169 /* Need disable the pmic wdt, then the emergency dload mode
170 * will not auto reset.
171 */
172 qpnp_pon_wd_config(0);
173 /* Make sure all the cookied are flushed to memory */
174 mb();
175 }
176
177 ret = scm_set_dload_mode(SCM_EDLOAD_MODE, 0);
178 if (ret)
179 pr_err("Failed to set secure EDLOAD mode: %d\n", ret);
180}
181
182static int dload_set(const char *val, struct kernel_param *kp)
183{
184 int ret;
185
186 int old_val = download_mode;
187
188 ret = param_set_int(val, kp);
189
190 if (ret)
191 return ret;
192
193 /* If download_mode is not zero or one, ignore. */
194 if (download_mode >> 1) {
195 download_mode = old_val;
196 return -EINVAL;
197 }
198
199 set_dload_mode(download_mode);
200
201 return 0;
202}
203#else
204#define set_dload_mode(x) do {} while (0)
205
206static void enable_emergency_dload_mode(void)
207{
208 pr_err("dload mode is not enabled on target\n");
209}
210
211static bool get_dload_mode(void)
212{
213 return false;
214}
215#endif
216
217void msm_set_restart_mode(int mode)
218{
219 restart_mode = mode;
220}
221EXPORT_SYMBOL(msm_set_restart_mode);
222
223/*
224 * Force the SPMI PMIC arbiter to shutdown so that no more SPMI transactions
225 * are sent from the MSM to the PMIC. This is required in order to avoid an
226 * SPMI lockup on certain PMIC chips if PS_HOLD is lowered in the middle of
227 * an SPMI transaction.
228 */
229static void halt_spmi_pmic_arbiter(void)
230{
231 struct scm_desc desc = {
232 .args[0] = 0,
233 .arginfo = SCM_ARGS(1),
234 };
235
236 if (scm_pmic_arbiter_disable_supported) {
237 pr_crit("Calling SCM to disable SPMI PMIC arbiter\n");
238 if (!is_scm_armv8())
239 scm_call_atomic1(SCM_SVC_PWR,
240 SCM_IO_DISABLE_PMIC_ARBITER, 0);
241 else
242 scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_PWR,
243 SCM_IO_DISABLE_PMIC_ARBITER), &desc);
244 }
245}
246
247static void msm_restart_prepare(const char *cmd)
248{
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700249 bool need_warm_reset = false;
Kyle Yandb13f542016-12-02 12:00:50 -0800250#ifdef CONFIG_QCOM_DLOAD_MODE
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700251 /* Write download mode flags if we're panic'ing
252 * Write download mode flags if restart_mode says so
253 * Kill download mode if master-kill switch is set
254 */
255
256 set_dload_mode(download_mode &&
257 (in_panic || restart_mode == RESTART_DLOAD));
258#endif
259
260 if (qpnp_pon_check_hard_reset_stored()) {
261 /* Set warm reset as true when device is in dload mode */
262 if (get_dload_mode() ||
263 ((cmd != NULL && cmd[0] != '\0') &&
264 !strcmp(cmd, "edl")))
265 need_warm_reset = true;
266 } else {
267 need_warm_reset = (get_dload_mode() ||
268 (cmd != NULL && cmd[0] != '\0'));
269 }
270
271 /* Hard reset the PMIC unless memory contents must be maintained. */
272 if (need_warm_reset)
273 qpnp_pon_system_pwr_off(PON_POWER_OFF_WARM_RESET);
274 else
275 qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET);
276
277 if (cmd != NULL) {
278 if (!strncmp(cmd, "bootloader", 10)) {
279 qpnp_pon_set_restart_reason(
280 PON_RESTART_REASON_BOOTLOADER);
281 __raw_writel(0x77665500, restart_reason);
282 } else if (!strncmp(cmd, "recovery", 8)) {
283 qpnp_pon_set_restart_reason(
284 PON_RESTART_REASON_RECOVERY);
285 __raw_writel(0x77665502, restart_reason);
286 } else if (!strcmp(cmd, "rtc")) {
287 qpnp_pon_set_restart_reason(
288 PON_RESTART_REASON_RTC);
289 __raw_writel(0x77665503, restart_reason);
290 } else if (!strcmp(cmd, "dm-verity device corrupted")) {
291 qpnp_pon_set_restart_reason(
292 PON_RESTART_REASON_DMVERITY_CORRUPTED);
293 __raw_writel(0x77665508, restart_reason);
294 } else if (!strcmp(cmd, "dm-verity enforcing")) {
295 qpnp_pon_set_restart_reason(
296 PON_RESTART_REASON_DMVERITY_ENFORCE);
297 __raw_writel(0x77665509, restart_reason);
298 } else if (!strcmp(cmd, "keys clear")) {
299 qpnp_pon_set_restart_reason(
300 PON_RESTART_REASON_KEYS_CLEAR);
301 __raw_writel(0x7766550a, restart_reason);
302 } else if (!strncmp(cmd, "oem-", 4)) {
303 unsigned long code;
Lijuan Gao8bcfa3c2017-12-06 16:20:35 +0800304 unsigned long reset_reason;
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700305 int ret;
306
307 ret = kstrtoul(cmd + 4, 16, &code);
Lijuan Gao8bcfa3c2017-12-06 16:20:35 +0800308 if (!ret) {
309 /* Bit-2 to bit-7 of SOFT_RB_SPARE for hard
310 * reset reason:
311 * Value 0 to 31 for common defined features
312 * Value 32 to 63 for oem specific features
313 */
314 reset_reason = code +
315 PON_RESTART_REASON_OEM_MIN;
316 if (reset_reason > PON_RESTART_REASON_OEM_MAX ||
317 reset_reason < PON_RESTART_REASON_OEM_MIN) {
318 pr_err("Invalid oem reset reason: %lx\n",
319 reset_reason);
320 } else {
321 qpnp_pon_set_restart_reason(
322 reset_reason);
323 }
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700324 __raw_writel(0x6f656d00 | (code & 0xff),
325 restart_reason);
Lijuan Gao8bcfa3c2017-12-06 16:20:35 +0800326 }
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700327 } else if (!strncmp(cmd, "edl", 3)) {
328 enable_emergency_dload_mode();
329 } else {
330 __raw_writel(0x77665501, restart_reason);
331 }
332 }
333
Channagoud Kadabia8d05602017-02-03 15:39:00 -0800334 flush_cache_all();
335
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700336 /*outer_flush_all is not supported by 64bit kernel*/
337#ifndef CONFIG_ARM64
338 outer_flush_all();
339#endif
340
341}
342
343/*
344 * Deassert PS_HOLD to signal the PMIC that we are ready to power down or reset.
345 * Do this by calling into the secure environment, if available, or by directly
346 * writing to a hardware register.
347 *
348 * This function should never return.
349 */
350static void deassert_ps_hold(void)
351{
352 struct scm_desc desc = {
353 .args[0] = 0,
354 .arginfo = SCM_ARGS(1),
355 };
356
357 if (scm_deassert_ps_hold_supported) {
358 /* This call will be available on ARMv8 only */
359 scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_PWR,
360 SCM_IO_DEASSERT_PS_HOLD), &desc);
361 }
362
363 /* Fall-through to the direct write in case the scm_call "returns" */
364 __raw_writel(0, msm_ps_hold);
365}
366
367static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
368{
369 int ret;
370 struct scm_desc desc = {
371 .args[0] = 1,
372 .args[1] = 0,
373 .arginfo = SCM_ARGS(2),
374 };
375
376 pr_notice("Going down for restart now\n");
377
378 msm_restart_prepare(cmd);
379
380#ifdef CONFIG_QCOM_DLOAD_MODE
381 /*
382 * Trigger a watchdog bite here and if this fails,
383 * device will take the usual restart path.
384 */
385
386 if (WDOG_BITE_ON_PANIC && in_panic)
387 msm_trigger_wdog_bite();
388#endif
389
390 /* Needed to bypass debug image on some chips */
391 if (!is_scm_armv8())
392 ret = scm_call_atomic2(SCM_SVC_BOOT,
393 SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
394 else
395 ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
396 SCM_WDOG_DEBUG_BOOT_PART), &desc);
397 if (ret)
398 pr_err("Failed to disable secure wdog debug: %d\n", ret);
399
400 halt_spmi_pmic_arbiter();
401 deassert_ps_hold();
402
403 msleep(10000);
404}
405
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700406static void do_msm_poweroff(void)
407{
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700408 int ret;
409 struct scm_desc desc = {
410 .args[0] = 1,
411 .args[1] = 0,
412 .arginfo = SCM_ARGS(2),
413 };
414
415 pr_notice("Powering off the SoC\n");
416#ifdef CONFIG_QCOM_DLOAD_MODE
417 set_dload_mode(0);
418#endif
419 qpnp_pon_system_pwr_off(PON_POWER_OFF_SHUTDOWN);
420 /* Needed to bypass debug image on some chips */
421 if (!is_scm_armv8())
422 ret = scm_call_atomic2(SCM_SVC_BOOT,
423 SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
424 else
425 ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
426 SCM_WDOG_DEBUG_BOOT_PART), &desc);
427 if (ret)
428 pr_err("Failed to disable wdog debug: %d\n", ret);
429
430 halt_spmi_pmic_arbiter();
431 deassert_ps_hold();
432
433 msleep(10000);
434 pr_err("Powering off has failed\n");
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700435}
436
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530437static ssize_t attr_show(struct kobject *kobj, struct attribute *attr,
438 char *buf)
439{
440 struct reset_attribute *reset_attr = to_reset_attr(attr);
441 ssize_t ret = -EIO;
442
443 if (reset_attr->show)
444 ret = reset_attr->show(kobj, attr, buf);
445
446 return ret;
447}
448
449static ssize_t attr_store(struct kobject *kobj, struct attribute *attr,
450 const char *buf, size_t count)
451{
452 struct reset_attribute *reset_attr = to_reset_attr(attr);
453 ssize_t ret = -EIO;
454
455 if (reset_attr->store)
456 ret = reset_attr->store(kobj, attr, buf, count);
457
458 return ret;
459}
460
461static const struct sysfs_ops reset_sysfs_ops = {
462 .show = attr_show,
463 .store = attr_store,
464};
465
466static struct kobj_type reset_ktype = {
467 .sysfs_ops = &reset_sysfs_ops,
468};
469
470static ssize_t show_emmc_dload(struct kobject *kobj, struct attribute *attr,
471 char *buf)
472{
473 uint32_t read_val, show_val;
474
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +0530475 if (!dload_type_addr)
476 return -ENODEV;
477
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530478 read_val = __raw_readl(dload_type_addr);
479 if (read_val == EMMC_DLOAD_TYPE)
480 show_val = 1;
481 else
482 show_val = 0;
483
484 return snprintf(buf, sizeof(show_val), "%u\n", show_val);
485}
486
487static size_t store_emmc_dload(struct kobject *kobj, struct attribute *attr,
488 const char *buf, size_t count)
489{
490 uint32_t enabled;
491 int ret;
492
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +0530493 if (!dload_type_addr)
494 return -ENODEV;
495
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530496 ret = kstrtouint(buf, 0, &enabled);
497 if (ret < 0)
498 return ret;
499
500 if (!((enabled == 0) || (enabled == 1)))
501 return -EINVAL;
502
503 if (enabled == 1)
504 __raw_writel(EMMC_DLOAD_TYPE, dload_type_addr);
505 else
506 __raw_writel(0, dload_type_addr);
507
508 return count;
509}
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +0530510
511#ifdef CONFIG_QCOM_MINIDUMP
512static DEFINE_MUTEX(tcsr_lock);
513
514static ssize_t show_dload_mode(struct kobject *kobj, struct attribute *attr,
515 char *buf)
516{
517 return scnprintf(buf, PAGE_SIZE, "DLOAD dump type: %s\n",
518 (dload_type == SCM_DLOAD_BOTHDUMPS) ? "both" :
519 ((dload_type == SCM_DLOAD_MINIDUMP) ? "mini" : "full"));
520}
521
522static size_t store_dload_mode(struct kobject *kobj, struct attribute *attr,
523 const char *buf, size_t count)
524{
525 if (sysfs_streq(buf, "full")) {
526 dload_type = SCM_DLOAD_FULLDUMP;
527 } else if (sysfs_streq(buf, "mini")) {
528 if (!msm_minidump_enabled()) {
529 pr_err("Minidump is not enabled\n");
530 return -ENODEV;
531 }
532 dload_type = SCM_DLOAD_MINIDUMP;
533 } else if (sysfs_streq(buf, "both")) {
534 if (!msm_minidump_enabled()) {
535 pr_err("Minidump not enabled, setting fulldump only\n");
536 dload_type = SCM_DLOAD_FULLDUMP;
537 return count;
538 }
539 dload_type = SCM_DLOAD_BOTHDUMPS;
540 } else{
541 pr_err("Invalid Dump setup request..\n");
542 pr_err("Supported dumps:'full', 'mini', or 'both'\n");
543 return -EINVAL;
544 }
545
546 mutex_lock(&tcsr_lock);
547 /*Overwrite TCSR reg*/
548 set_dload_mode(dload_type);
549 mutex_unlock(&tcsr_lock);
550 return count;
551}
552RESET_ATTR(dload_mode, 0644, show_dload_mode, store_dload_mode);
553#endif
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530554RESET_ATTR(emmc_dload, 0644, show_emmc_dload, store_emmc_dload);
555
556static struct attribute *reset_attrs[] = {
557 &reset_attr_emmc_dload.attr,
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +0530558#ifdef CONFIG_QCOM_MINIDUMP
559 &reset_attr_dload_mode.attr,
560#endif
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530561 NULL
562};
563
564static struct attribute_group reset_attr_group = {
565 .attrs = reset_attrs,
566};
567
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700568static int msm_restart_probe(struct platform_device *pdev)
569{
570 struct device *dev = &pdev->dev;
571 struct resource *mem;
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700572 struct device_node *np;
573 int ret = 0;
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700574
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700575#ifdef CONFIG_QCOM_DLOAD_MODE
576 if (scm_is_call_available(SCM_SVC_BOOT, SCM_DLOAD_CMD) > 0)
577 scm_dload_supported = true;
578
579 atomic_notifier_chain_register(&panic_notifier_list, &panic_blk);
580 np = of_find_compatible_node(NULL, NULL, DL_MODE_PROP);
581 if (!np) {
582 pr_err("unable to find DT imem DLOAD mode node\n");
583 } else {
584 dload_mode_addr = of_iomap(np, 0);
585 if (!dload_mode_addr)
586 pr_err("unable to map imem DLOAD offset\n");
587 }
588
589 np = of_find_compatible_node(NULL, NULL, EDL_MODE_PROP);
590 if (!np) {
591 pr_err("unable to find DT imem EDLOAD mode node\n");
592 } else {
593 emergency_dload_mode_addr = of_iomap(np, 0);
594 if (!emergency_dload_mode_addr)
595 pr_err("unable to map imem EDLOAD mode offset\n");
596 }
597
Channagoud Kadabica9159d2017-04-25 19:44:07 -0700598#ifdef CONFIG_RANDOMIZE_BASE
599#define KASLR_OFFSET_BIT_MASK 0x00000000FFFFFFFF
600 np = of_find_compatible_node(NULL, NULL, KASLR_OFFSET_PROP);
601 if (!np) {
602 pr_err("unable to find DT imem KASLR_OFFSET node\n");
603 } else {
604 kaslr_imem_addr = of_iomap(np, 0);
605 if (!kaslr_imem_addr)
606 pr_err("unable to map imem KASLR offset\n");
607 }
608
Prasad Sodagudi6998d1f2016-04-06 17:55:29 +0530609 if (kaslr_imem_addr) {
Channagoud Kadabica9159d2017-04-25 19:44:07 -0700610 __raw_writel(0xdead4ead, kaslr_imem_addr);
611 __raw_writel(KASLR_OFFSET_BIT_MASK &
612 (kimage_vaddr - KIMAGE_VADDR), kaslr_imem_addr + 4);
613 __raw_writel(KASLR_OFFSET_BIT_MASK &
614 ((kimage_vaddr - KIMAGE_VADDR) >> 32),
615 kaslr_imem_addr + 8);
616 iounmap(kaslr_imem_addr);
617 }
618#endif
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530619 np = of_find_compatible_node(NULL, NULL,
620 "qcom,msm-imem-dload-type");
621 if (!np) {
622 pr_err("unable to find DT imem dload-type node\n");
623 goto skip_sysfs_create;
624 } else {
625 dload_type_addr = of_iomap(np, 0);
626 if (!dload_type_addr) {
627 pr_err("unable to map imem dload-type offset\n");
628 goto skip_sysfs_create;
629 }
630 }
631
632 ret = kobject_init_and_add(&dload_kobj, &reset_ktype,
633 kernel_kobj, "%s", "dload");
634 if (ret) {
635 pr_err("%s:Error in creation kobject_add\n", __func__);
636 kobject_put(&dload_kobj);
637 goto skip_sysfs_create;
638 }
639
640 ret = sysfs_create_group(&dload_kobj, &reset_attr_group);
641 if (ret) {
642 pr_err("%s:Error in creation sysfs_create_group\n", __func__);
643 kobject_del(&dload_kobj);
644 }
645skip_sysfs_create:
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700646#endif
647 np = of_find_compatible_node(NULL, NULL,
648 "qcom,msm-imem-restart_reason");
649 if (!np) {
650 pr_err("unable to find DT imem restart reason node\n");
651 } else {
652 restart_reason = of_iomap(np, 0);
653 if (!restart_reason) {
654 pr_err("unable to map imem restart reason offset\n");
655 ret = -ENOMEM;
656 goto err_restart_reason;
657 }
658 }
659
660 mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pshold-base");
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700661 msm_ps_hold = devm_ioremap_resource(dev, mem);
662 if (IS_ERR(msm_ps_hold))
663 return PTR_ERR(msm_ps_hold);
664
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700665 mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
666 "tcsr-boot-misc-detect");
667 if (mem)
668 tcsr_boot_misc_detect = mem->start;
Pramod Gurav18a702e2014-09-25 17:03:51 +0530669
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700670 pm_power_off = do_msm_poweroff;
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700671 arm_pm_restart = do_msm_restart;
672
673 if (scm_is_call_available(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER) > 0)
674 scm_pmic_arbiter_disable_supported = true;
675
676 if (scm_is_call_available(SCM_SVC_PWR, SCM_IO_DEASSERT_PS_HOLD) > 0)
677 scm_deassert_ps_hold_supported = true;
678
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700679 set_dload_mode(download_mode);
Pramod Gurav18a702e2014-09-25 17:03:51 +0530680
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700681 return 0;
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700682
683err_restart_reason:
684#ifdef CONFIG_QCOM_DLOAD_MODE
685 iounmap(emergency_dload_mode_addr);
686 iounmap(dload_mode_addr);
687#endif
688 return ret;
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700689}
690
691static const struct of_device_id of_msm_restart_match[] = {
692 { .compatible = "qcom,pshold", },
693 {},
694};
695MODULE_DEVICE_TABLE(of, of_msm_restart_match);
696
697static struct platform_driver msm_restart_driver = {
698 .probe = msm_restart_probe,
699 .driver = {
700 .name = "msm-restart",
701 .of_match_table = of_match_ptr(of_msm_restart_match),
702 },
703};
704
705static int __init msm_restart_init(void)
706{
707 return platform_driver_register(&msm_restart_driver);
708}
Channagoud Kadabica9159d2017-04-25 19:44:07 -0700709pure_initcall(msm_restart_init);