blob: bfc401a01bd713b0858029b3f42405f35f36d71f [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;
304 int ret;
305
306 ret = kstrtoul(cmd + 4, 16, &code);
307 if (!ret)
308 __raw_writel(0x6f656d00 | (code & 0xff),
309 restart_reason);
310 } else if (!strncmp(cmd, "edl", 3)) {
311 enable_emergency_dload_mode();
312 } else {
313 __raw_writel(0x77665501, restart_reason);
314 }
315 }
316
Channagoud Kadabia8d05602017-02-03 15:39:00 -0800317 flush_cache_all();
318
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700319 /*outer_flush_all is not supported by 64bit kernel*/
320#ifndef CONFIG_ARM64
321 outer_flush_all();
322#endif
323
324}
325
326/*
327 * Deassert PS_HOLD to signal the PMIC that we are ready to power down or reset.
328 * Do this by calling into the secure environment, if available, or by directly
329 * writing to a hardware register.
330 *
331 * This function should never return.
332 */
333static void deassert_ps_hold(void)
334{
335 struct scm_desc desc = {
336 .args[0] = 0,
337 .arginfo = SCM_ARGS(1),
338 };
339
340 if (scm_deassert_ps_hold_supported) {
341 /* This call will be available on ARMv8 only */
342 scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_PWR,
343 SCM_IO_DEASSERT_PS_HOLD), &desc);
344 }
345
346 /* Fall-through to the direct write in case the scm_call "returns" */
347 __raw_writel(0, msm_ps_hold);
348}
349
350static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
351{
352 int ret;
353 struct scm_desc desc = {
354 .args[0] = 1,
355 .args[1] = 0,
356 .arginfo = SCM_ARGS(2),
357 };
358
359 pr_notice("Going down for restart now\n");
360
361 msm_restart_prepare(cmd);
362
363#ifdef CONFIG_QCOM_DLOAD_MODE
364 /*
365 * Trigger a watchdog bite here and if this fails,
366 * device will take the usual restart path.
367 */
368
369 if (WDOG_BITE_ON_PANIC && in_panic)
370 msm_trigger_wdog_bite();
371#endif
372
373 /* Needed to bypass debug image on some chips */
374 if (!is_scm_armv8())
375 ret = scm_call_atomic2(SCM_SVC_BOOT,
376 SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
377 else
378 ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
379 SCM_WDOG_DEBUG_BOOT_PART), &desc);
380 if (ret)
381 pr_err("Failed to disable secure wdog debug: %d\n", ret);
382
383 halt_spmi_pmic_arbiter();
384 deassert_ps_hold();
385
386 msleep(10000);
387}
388
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700389static void do_msm_poweroff(void)
390{
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700391 int ret;
392 struct scm_desc desc = {
393 .args[0] = 1,
394 .args[1] = 0,
395 .arginfo = SCM_ARGS(2),
396 };
397
398 pr_notice("Powering off the SoC\n");
399#ifdef CONFIG_QCOM_DLOAD_MODE
400 set_dload_mode(0);
401#endif
402 qpnp_pon_system_pwr_off(PON_POWER_OFF_SHUTDOWN);
403 /* Needed to bypass debug image on some chips */
404 if (!is_scm_armv8())
405 ret = scm_call_atomic2(SCM_SVC_BOOT,
406 SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
407 else
408 ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
409 SCM_WDOG_DEBUG_BOOT_PART), &desc);
410 if (ret)
411 pr_err("Failed to disable wdog debug: %d\n", ret);
412
413 halt_spmi_pmic_arbiter();
414 deassert_ps_hold();
415
416 msleep(10000);
417 pr_err("Powering off has failed\n");
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700418}
419
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530420static ssize_t attr_show(struct kobject *kobj, struct attribute *attr,
421 char *buf)
422{
423 struct reset_attribute *reset_attr = to_reset_attr(attr);
424 ssize_t ret = -EIO;
425
426 if (reset_attr->show)
427 ret = reset_attr->show(kobj, attr, buf);
428
429 return ret;
430}
431
432static ssize_t attr_store(struct kobject *kobj, struct attribute *attr,
433 const char *buf, size_t count)
434{
435 struct reset_attribute *reset_attr = to_reset_attr(attr);
436 ssize_t ret = -EIO;
437
438 if (reset_attr->store)
439 ret = reset_attr->store(kobj, attr, buf, count);
440
441 return ret;
442}
443
444static const struct sysfs_ops reset_sysfs_ops = {
445 .show = attr_show,
446 .store = attr_store,
447};
448
449static struct kobj_type reset_ktype = {
450 .sysfs_ops = &reset_sysfs_ops,
451};
452
453static ssize_t show_emmc_dload(struct kobject *kobj, struct attribute *attr,
454 char *buf)
455{
456 uint32_t read_val, show_val;
457
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +0530458 if (!dload_type_addr)
459 return -ENODEV;
460
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530461 read_val = __raw_readl(dload_type_addr);
462 if (read_val == EMMC_DLOAD_TYPE)
463 show_val = 1;
464 else
465 show_val = 0;
466
467 return snprintf(buf, sizeof(show_val), "%u\n", show_val);
468}
469
470static size_t store_emmc_dload(struct kobject *kobj, struct attribute *attr,
471 const char *buf, size_t count)
472{
473 uint32_t enabled;
474 int ret;
475
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +0530476 if (!dload_type_addr)
477 return -ENODEV;
478
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530479 ret = kstrtouint(buf, 0, &enabled);
480 if (ret < 0)
481 return ret;
482
483 if (!((enabled == 0) || (enabled == 1)))
484 return -EINVAL;
485
486 if (enabled == 1)
487 __raw_writel(EMMC_DLOAD_TYPE, dload_type_addr);
488 else
489 __raw_writel(0, dload_type_addr);
490
491 return count;
492}
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +0530493
494#ifdef CONFIG_QCOM_MINIDUMP
495static DEFINE_MUTEX(tcsr_lock);
496
497static ssize_t show_dload_mode(struct kobject *kobj, struct attribute *attr,
498 char *buf)
499{
500 return scnprintf(buf, PAGE_SIZE, "DLOAD dump type: %s\n",
501 (dload_type == SCM_DLOAD_BOTHDUMPS) ? "both" :
502 ((dload_type == SCM_DLOAD_MINIDUMP) ? "mini" : "full"));
503}
504
505static size_t store_dload_mode(struct kobject *kobj, struct attribute *attr,
506 const char *buf, size_t count)
507{
508 if (sysfs_streq(buf, "full")) {
509 dload_type = SCM_DLOAD_FULLDUMP;
510 } else if (sysfs_streq(buf, "mini")) {
511 if (!msm_minidump_enabled()) {
512 pr_err("Minidump is not enabled\n");
513 return -ENODEV;
514 }
515 dload_type = SCM_DLOAD_MINIDUMP;
516 } else if (sysfs_streq(buf, "both")) {
517 if (!msm_minidump_enabled()) {
518 pr_err("Minidump not enabled, setting fulldump only\n");
519 dload_type = SCM_DLOAD_FULLDUMP;
520 return count;
521 }
522 dload_type = SCM_DLOAD_BOTHDUMPS;
523 } else{
524 pr_err("Invalid Dump setup request..\n");
525 pr_err("Supported dumps:'full', 'mini', or 'both'\n");
526 return -EINVAL;
527 }
528
529 mutex_lock(&tcsr_lock);
530 /*Overwrite TCSR reg*/
531 set_dload_mode(dload_type);
532 mutex_unlock(&tcsr_lock);
533 return count;
534}
535RESET_ATTR(dload_mode, 0644, show_dload_mode, store_dload_mode);
536#endif
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530537RESET_ATTR(emmc_dload, 0644, show_emmc_dload, store_emmc_dload);
538
539static struct attribute *reset_attrs[] = {
540 &reset_attr_emmc_dload.attr,
Lingutla Chandrasekhar0a4b1e52017-10-03 18:05:07 +0530541#ifdef CONFIG_QCOM_MINIDUMP
542 &reset_attr_dload_mode.attr,
543#endif
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530544 NULL
545};
546
547static struct attribute_group reset_attr_group = {
548 .attrs = reset_attrs,
549};
550
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700551static int msm_restart_probe(struct platform_device *pdev)
552{
553 struct device *dev = &pdev->dev;
554 struct resource *mem;
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700555 struct device_node *np;
556 int ret = 0;
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700557
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700558#ifdef CONFIG_QCOM_DLOAD_MODE
559 if (scm_is_call_available(SCM_SVC_BOOT, SCM_DLOAD_CMD) > 0)
560 scm_dload_supported = true;
561
562 atomic_notifier_chain_register(&panic_notifier_list, &panic_blk);
563 np = of_find_compatible_node(NULL, NULL, DL_MODE_PROP);
564 if (!np) {
565 pr_err("unable to find DT imem DLOAD mode node\n");
566 } else {
567 dload_mode_addr = of_iomap(np, 0);
568 if (!dload_mode_addr)
569 pr_err("unable to map imem DLOAD offset\n");
570 }
571
572 np = of_find_compatible_node(NULL, NULL, EDL_MODE_PROP);
573 if (!np) {
574 pr_err("unable to find DT imem EDLOAD mode node\n");
575 } else {
576 emergency_dload_mode_addr = of_iomap(np, 0);
577 if (!emergency_dload_mode_addr)
578 pr_err("unable to map imem EDLOAD mode offset\n");
579 }
580
Channagoud Kadabica9159d2017-04-25 19:44:07 -0700581#ifdef CONFIG_RANDOMIZE_BASE
582#define KASLR_OFFSET_BIT_MASK 0x00000000FFFFFFFF
583 np = of_find_compatible_node(NULL, NULL, KASLR_OFFSET_PROP);
584 if (!np) {
585 pr_err("unable to find DT imem KASLR_OFFSET node\n");
586 } else {
587 kaslr_imem_addr = of_iomap(np, 0);
588 if (!kaslr_imem_addr)
589 pr_err("unable to map imem KASLR offset\n");
590 }
591
Prasad Sodagudi6998d1f2016-04-06 17:55:29 +0530592 if (kaslr_imem_addr) {
Channagoud Kadabica9159d2017-04-25 19:44:07 -0700593 __raw_writel(0xdead4ead, kaslr_imem_addr);
594 __raw_writel(KASLR_OFFSET_BIT_MASK &
595 (kimage_vaddr - KIMAGE_VADDR), kaslr_imem_addr + 4);
596 __raw_writel(KASLR_OFFSET_BIT_MASK &
597 ((kimage_vaddr - KIMAGE_VADDR) >> 32),
598 kaslr_imem_addr + 8);
599 iounmap(kaslr_imem_addr);
600 }
601#endif
Prasad Sodagudi2b0dfea2015-12-29 19:29:59 +0530602 np = of_find_compatible_node(NULL, NULL,
603 "qcom,msm-imem-dload-type");
604 if (!np) {
605 pr_err("unable to find DT imem dload-type node\n");
606 goto skip_sysfs_create;
607 } else {
608 dload_type_addr = of_iomap(np, 0);
609 if (!dload_type_addr) {
610 pr_err("unable to map imem dload-type offset\n");
611 goto skip_sysfs_create;
612 }
613 }
614
615 ret = kobject_init_and_add(&dload_kobj, &reset_ktype,
616 kernel_kobj, "%s", "dload");
617 if (ret) {
618 pr_err("%s:Error in creation kobject_add\n", __func__);
619 kobject_put(&dload_kobj);
620 goto skip_sysfs_create;
621 }
622
623 ret = sysfs_create_group(&dload_kobj, &reset_attr_group);
624 if (ret) {
625 pr_err("%s:Error in creation sysfs_create_group\n", __func__);
626 kobject_del(&dload_kobj);
627 }
628skip_sysfs_create:
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700629#endif
630 np = of_find_compatible_node(NULL, NULL,
631 "qcom,msm-imem-restart_reason");
632 if (!np) {
633 pr_err("unable to find DT imem restart reason node\n");
634 } else {
635 restart_reason = of_iomap(np, 0);
636 if (!restart_reason) {
637 pr_err("unable to map imem restart reason offset\n");
638 ret = -ENOMEM;
639 goto err_restart_reason;
640 }
641 }
642
643 mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pshold-base");
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700644 msm_ps_hold = devm_ioremap_resource(dev, mem);
645 if (IS_ERR(msm_ps_hold))
646 return PTR_ERR(msm_ps_hold);
647
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700648 mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
649 "tcsr-boot-misc-detect");
650 if (mem)
651 tcsr_boot_misc_detect = mem->start;
Pramod Gurav18a702e2014-09-25 17:03:51 +0530652
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700653 pm_power_off = do_msm_poweroff;
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700654 arm_pm_restart = do_msm_restart;
655
656 if (scm_is_call_available(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER) > 0)
657 scm_pmic_arbiter_disable_supported = true;
658
659 if (scm_is_call_available(SCM_SVC_PWR, SCM_IO_DEASSERT_PS_HOLD) > 0)
660 scm_deassert_ps_hold_supported = true;
661
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700662 set_dload_mode(download_mode);
Pramod Gurav18a702e2014-09-25 17:03:51 +0530663
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700664 return 0;
Channagoud Kadabi4059cb62016-08-23 12:14:01 -0700665
666err_restart_reason:
667#ifdef CONFIG_QCOM_DLOAD_MODE
668 iounmap(emergency_dload_mode_addr);
669 iounmap(dload_mode_addr);
670#endif
671 return ret;
Abhimanyu Kapur78be31762013-07-30 17:05:28 -0700672}
673
674static const struct of_device_id of_msm_restart_match[] = {
675 { .compatible = "qcom,pshold", },
676 {},
677};
678MODULE_DEVICE_TABLE(of, of_msm_restart_match);
679
680static struct platform_driver msm_restart_driver = {
681 .probe = msm_restart_probe,
682 .driver = {
683 .name = "msm-restart",
684 .of_match_table = of_match_ptr(of_msm_restart_match),
685 },
686};
687
688static int __init msm_restart_init(void)
689{
690 return platform_driver_register(&msm_restart_driver);
691}
Channagoud Kadabica9159d2017-04-25 19:44:07 -0700692pure_initcall(msm_restart_init);