reset.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. * arch/arm/mach-tegra/reset.c
  3. *
  4. * Copyright (C) 2011,2012 NVIDIA Corporation.
  5. *
  6. * This software is licensed under the terms of the GNU General Public
  7. * License version 2, as published by the Free Software Foundation, and
  8. * may be copied, distributed, and modified under those terms.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. */
  16. #include <linux/init.h>
  17. #include <linux/io.h>
  18. #include <linux/cpumask.h>
  19. #include <linux/bitops.h>
  20. #include <asm/cacheflush.h>
  21. #include <asm/hardware/cache-l2x0.h>
  22. #include "iomap.h"
  23. #include "irammap.h"
  24. #include "reset.h"
  25. #include "sleep.h"
  26. #include "fuse.h"
  27. #define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
  28. TEGRA_IRAM_RESET_HANDLER_OFFSET)
  29. static bool is_enabled;
  30. static void __init tegra_cpu_reset_handler_enable(void)
  31. {
  32. void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE);
  33. void __iomem *evp_cpu_reset =
  34. IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100);
  35. void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE);
  36. u32 reg;
  37. BUG_ON(is_enabled);
  38. BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE);
  39. memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start,
  40. tegra_cpu_reset_handler_size);
  41. /*
  42. * NOTE: This must be the one and only write to the EVP CPU reset
  43. * vector in the entire system.
  44. */
  45. writel(TEGRA_IRAM_RESET_BASE + tegra_cpu_reset_handler_offset,
  46. evp_cpu_reset);
  47. wmb();
  48. reg = readl(evp_cpu_reset);
  49. /*
  50. * Prevent further modifications to the physical reset vector.
  51. * NOTE: Has no effect on chips prior to Tegra30.
  52. */
  53. if (tegra_chip_id != TEGRA20) {
  54. reg = readl(sb_ctrl);
  55. reg |= 2;
  56. writel(reg, sb_ctrl);
  57. wmb();
  58. }
  59. is_enabled = true;
  60. }
  61. void __init tegra_cpu_reset_handler_init(void)
  62. {
  63. #ifdef CONFIG_SMP
  64. __tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
  65. *((u32 *)cpu_present_mask);
  66. __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] =
  67. virt_to_phys((void *)tegra_secondary_startup);
  68. #endif
  69. #ifdef CONFIG_PM_SLEEP
  70. __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] =
  71. virt_to_phys((void *)tegra_resume);
  72. #endif
  73. tegra_cpu_reset_handler_enable();
  74. }