psci-mx7.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
  3. * Copyright 2017 NXP
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <asm/io.h>
  8. #include <asm/psci.h>
  9. #include <asm/secure.h>
  10. #include <asm/arch/imx-regs.h>
  11. #include <common.h>
  12. #include <fsl_wdog.h>
  13. #define GPC_CPU_PGC_SW_PDN_REQ 0xfc
  14. #define GPC_CPU_PGC_SW_PUP_REQ 0xf0
  15. #define GPC_PGC_C1 0x840
  16. #define BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7 0x2
  17. /* below is for i.MX7D */
  18. #define SRC_GPR1_MX7D 0x074
  19. #define SRC_A7RCR0 0x004
  20. #define SRC_A7RCR1 0x008
  21. #define BP_SRC_A7RCR0_A7_CORE_RESET0 0
  22. #define BP_SRC_A7RCR1_A7_CORE1_ENABLE 1
  23. #define SNVS_LPCR 0x38
  24. #define BP_SNVS_LPCR_DP_EN 0x20
  25. #define BP_SNVS_LPCR_TOP 0x40
  26. #define CCM_CCGR_SNVS 0x4250
  27. #define CCM_ROOT_WDOG 0xbb80
  28. #define CCM_CCGR_WDOG1 0x49c0
  29. static inline void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset)
  30. {
  31. writel(enable, GPC_IPS_BASE_ADDR + offset);
  32. }
  33. __secure void imx_gpcv2_set_core1_power(bool pdn)
  34. {
  35. u32 reg = pdn ? GPC_CPU_PGC_SW_PUP_REQ : GPC_CPU_PGC_SW_PDN_REQ;
  36. u32 val;
  37. imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C1);
  38. val = readl(GPC_IPS_BASE_ADDR + reg);
  39. val |= BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
  40. writel(val, GPC_IPS_BASE_ADDR + reg);
  41. while ((readl(GPC_IPS_BASE_ADDR + reg) &
  42. BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7) != 0)
  43. ;
  44. imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C1);
  45. }
  46. __secure void imx_enable_cpu_ca7(int cpu, bool enable)
  47. {
  48. u32 mask, val;
  49. mask = 1 << (BP_SRC_A7RCR1_A7_CORE1_ENABLE + cpu - 1);
  50. val = readl(SRC_BASE_ADDR + SRC_A7RCR1);
  51. val = enable ? val | mask : val & ~mask;
  52. writel(val, SRC_BASE_ADDR + SRC_A7RCR1);
  53. }
  54. __secure int imx_cpu_on(int fn, int cpu, int pc)
  55. {
  56. writel(pc, SRC_BASE_ADDR + cpu * 8 + SRC_GPR1_MX7D);
  57. imx_gpcv2_set_core1_power(true);
  58. imx_enable_cpu_ca7(cpu, true);
  59. return 0;
  60. }
  61. __secure int imx_cpu_off(int cpu)
  62. {
  63. imx_enable_cpu_ca7(cpu, false);
  64. imx_gpcv2_set_core1_power(false);
  65. writel(0, SRC_BASE_ADDR + cpu * 8 + SRC_GPR1_MX7D + 4);
  66. return 0;
  67. }
  68. __secure void imx_system_reset(void)
  69. {
  70. struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
  71. /* make sure WDOG1 clock is enabled */
  72. writel(0x1 << 28, CCM_BASE_ADDR + CCM_ROOT_WDOG);
  73. writel(0x3, CCM_BASE_ADDR + CCM_CCGR_WDOG1);
  74. writew(WCR_WDE, &wdog->wcr);
  75. }
  76. __secure void imx_system_off(void)
  77. {
  78. u32 val;
  79. /* make sure SNVS clock is enabled */
  80. writel(0x3, CCM_BASE_ADDR + CCM_CCGR_SNVS);
  81. val = readl(SNVS_BASE_ADDR + SNVS_LPCR);
  82. val |= BP_SNVS_LPCR_DP_EN | BP_SNVS_LPCR_TOP;
  83. writel(val, SNVS_BASE_ADDR + SNVS_LPCR);
  84. }