psci-mx7.c 2.4 KB

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