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