/arch/arm/mach-msm/restart.c

https://bitbucket.org/sammyz/iscream_thunderc-2.6.35-rebase · C · 136 lines · 97 code · 22 blank · 17 comment · 11 complexity · a1b3800a3ce6cb0ea95510d191ea57df MD5 · raw file

  1. /* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  2. *
  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. * You should have received a copy of the GNU General Public License
  13. * along with this program; if not, write to the Free Software
  14. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. * 02110-1301, USA.
  16. *
  17. */
  18. #include <linux/module.h>
  19. #include <linux/kernel.h>
  20. #include <linux/init.h>
  21. #include <linux/reboot.h>
  22. #include <linux/io.h>
  23. #include <linux/delay.h>
  24. #include <linux/pm.h>
  25. #include <linux/mfd/pmic8058.h>
  26. #include <linux/mfd/pmic8901.h>
  27. #include <mach/msm_iomap.h>
  28. #include <mach/scm-io.h>
  29. #define TCSR_WDT_CFG 0x30
  30. #define WDT0_RST (MSM_TMR0_BASE + 0x38)
  31. #define WDT0_EN (MSM_TMR0_BASE + 0x40)
  32. #define WDT0_BARK_TIME (MSM_TMR0_BASE + 0x4C)
  33. #define WDT0_BITE_TIME (MSM_TMR0_BASE + 0x5C)
  34. #define PSHOLD_CTL_SU (MSM_TLMM_BASE + 0x820)
  35. #define RESTART_REASON_ADDR 0x2A05F65C
  36. #ifdef CONFIG_MSM_DLOAD_MODE
  37. static int in_panic;
  38. static int panic_prep_restart(struct notifier_block *this,
  39. unsigned long event, void *ptr)
  40. {
  41. in_panic = 1;
  42. return NOTIFY_DONE;
  43. }
  44. static struct notifier_block panic_blk = {
  45. .notifier_call = panic_prep_restart,
  46. };
  47. static void set_dload_mode(int on)
  48. {
  49. void *dload_mode_addr;
  50. dload_mode_addr = ioremap_nocache(0x2A05F000, SZ_4K);
  51. if (dload_mode_addr) {
  52. writel(on ? 0xE47B337D : 0, dload_mode_addr);
  53. writel(on ? 0xCE14091A : 0,
  54. dload_mode_addr + sizeof(unsigned int));
  55. dmb();
  56. iounmap(dload_mode_addr);
  57. }
  58. }
  59. #else
  60. #define set_dload_mode(x) do {} while (0)
  61. #endif
  62. static void msm_power_off(void)
  63. {
  64. printk(KERN_NOTICE "Powering off the SoC\n");
  65. pm8058_reset_pwr_off(0);
  66. pm8901_reset_pwr_off(0);
  67. writel(0, PSHOLD_CTL_SU);
  68. mdelay(10000);
  69. printk(KERN_ERR "Powering off has failed\n");
  70. return;
  71. }
  72. void arch_reset(char mode, const char *cmd)
  73. {
  74. void *restart_reason;
  75. #ifdef CONFIG_MSM_DLOAD_MODE
  76. if (in_panic)
  77. set_dload_mode(1);
  78. #endif
  79. printk(KERN_NOTICE "Going down for restart now\n");
  80. pm8058_reset_pwr_off(1);
  81. if (cmd != NULL) {
  82. restart_reason = ioremap_nocache(RESTART_REASON_ADDR, SZ_4K);
  83. if (!strncmp(cmd, "bootloader", 10)) {
  84. writel(0x77665500, restart_reason);
  85. } else if (!strncmp(cmd, "recovery", 8)) {
  86. writel(0x77665502, restart_reason);
  87. } else if (!strncmp(cmd, "oem-", 4)) {
  88. unsigned long code;
  89. strict_strtoul(cmd + 4, 16, &code);
  90. code = code & 0xff;
  91. writel(0x6f656d00 | code, restart_reason);
  92. } else {
  93. writel(0x77665501, restart_reason);
  94. }
  95. iounmap(restart_reason);
  96. }
  97. writel(1, WDT0_RST);
  98. writel(0, WDT0_EN);
  99. writel(0x31F3, WDT0_BARK_TIME);
  100. writel(0x31F3, WDT0_BITE_TIME);
  101. writel(3, WDT0_EN);
  102. dmb();
  103. secure_writel(3, MSM_TCSR_BASE + TCSR_WDT_CFG);
  104. mdelay(10000);
  105. }
  106. static int __init msm_restart_init(void)
  107. {
  108. #ifdef CONFIG_MSM_DLOAD_MODE
  109. atomic_notifier_chain_register(&panic_notifier_list, &panic_blk);
  110. #endif
  111. pm_power_off = msm_power_off;
  112. return 0;
  113. }
  114. late_initcall(msm_restart_init);