Home | History | Annotate | Download | only in flowctrl
      1 /*
      2  * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
      3  *
      4  * SPDX-License-Identifier: BSD-3-Clause
      5  */
      6 
      7 #include <arch_helpers.h>
      8 #include <assert.h>
      9 #include <cortex_a53.h>
     10 #include <debug.h>
     11 #include <delay_timer.h>
     12 #include <flowctrl.h>
     13 #include <mmio.h>
     14 #include <pmc.h>
     15 #include <tegra_def.h>
     16 
     17 #define CLK_RST_DEV_L_SET		0x300
     18 #define CLK_RST_DEV_L_CLR		0x304
     19 #define  CLK_BPMP_RST			(1 << 1)
     20 
     21 #define EVP_BPMP_RESET_VECTOR		0x200
     22 
     23 static const uint64_t flowctrl_offset_cpu_csr[4] = {
     24 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU0_CSR),
     25 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR),
     26 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 8),
     27 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 16)
     28 };
     29 
     30 static const uint64_t flowctrl_offset_halt_cpu[4] = {
     31 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU0_EVENTS),
     32 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS),
     33 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 8),
     34 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 16)
     35 };
     36 
     37 static const uint64_t flowctrl_offset_cc4_ctrl[4] = {
     38 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL),
     39 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 4),
     40 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 8),
     41 	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 12)
     42 };
     43 
     44 static inline void tegra_fc_cc4_ctrl(int cpu_id, uint32_t val)
     45 {
     46 	mmio_write_32(flowctrl_offset_cc4_ctrl[cpu_id], val);
     47 	val = mmio_read_32(flowctrl_offset_cc4_ctrl[cpu_id]);
     48 }
     49 
     50 static inline void tegra_fc_cpu_csr(int cpu_id, uint32_t val)
     51 {
     52 	mmio_write_32(flowctrl_offset_cpu_csr[cpu_id], val);
     53 	val = mmio_read_32(flowctrl_offset_cpu_csr[cpu_id]);
     54 }
     55 
     56 static inline void tegra_fc_halt_cpu(int cpu_id, uint32_t val)
     57 {
     58 	mmio_write_32(flowctrl_offset_halt_cpu[cpu_id], val);
     59 	val = mmio_read_32(flowctrl_offset_halt_cpu[cpu_id]);
     60 }
     61 
     62 static void tegra_fc_prepare_suspend(int cpu_id, uint32_t csr)
     63 {
     64 	uint32_t val;
     65 
     66 	val = FLOWCTRL_HALT_GIC_IRQ | FLOWCTRL_HALT_GIC_FIQ |
     67 	      FLOWCTRL_HALT_LIC_IRQ | FLOWCTRL_HALT_LIC_FIQ |
     68 	      FLOWCTRL_WAITEVENT;
     69 	tegra_fc_halt_cpu(cpu_id, val);
     70 
     71 	val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
     72 	      FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu_id);
     73 	tegra_fc_cpu_csr(cpu_id, val | csr);
     74 }
     75 
     76 /*******************************************************************************
     77  * Powerdn the current CPU
     78  ******************************************************************************/
     79 void tegra_fc_cpu_powerdn(uint32_t mpidr)
     80 {
     81 	int cpu = mpidr & MPIDR_CPU_MASK;
     82 
     83 	VERBOSE("CPU%d powering down...\n", cpu);
     84 	tegra_fc_prepare_suspend(cpu, 0);
     85 }
     86 
     87 /*******************************************************************************
     88  * Suspend the current CPU cluster
     89  ******************************************************************************/
     90 void tegra_fc_cluster_idle(uint32_t mpidr)
     91 {
     92 	int cpu = mpidr & MPIDR_CPU_MASK;
     93 	uint32_t val;
     94 
     95 	VERBOSE("Entering cluster idle state...\n");
     96 
     97 	tegra_fc_cc4_ctrl(cpu, 0);
     98 
     99 	/* hardware L2 flush is faster for A53 only */
    100 	tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
    101 		!!MPIDR_AFFLVL1_VAL(mpidr));
    102 
    103 	/* suspend the CPU cluster */
    104 	val = FLOWCTRL_PG_CPU_NONCPU << FLOWCTRL_ENABLE_EXT;
    105 	tegra_fc_prepare_suspend(cpu, val);
    106 }
    107 
    108 /*******************************************************************************
    109  * Power down the current CPU cluster
    110  ******************************************************************************/
    111 void tegra_fc_cluster_powerdn(uint32_t mpidr)
    112 {
    113 	int cpu = mpidr & MPIDR_CPU_MASK;
    114 	uint32_t val;
    115 
    116 	VERBOSE("Entering cluster powerdn state...\n");
    117 
    118 	tegra_fc_cc4_ctrl(cpu, 0);
    119 
    120 	/* hardware L2 flush is faster for A53 only */
    121 	tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
    122 		read_midr() == CORTEX_A53_MIDR);
    123 
    124 	/* power down the CPU cluster */
    125 	val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
    126 	tegra_fc_prepare_suspend(cpu, val);
    127 }
    128 
    129 /*******************************************************************************
    130  * Suspend the entire SoC
    131  ******************************************************************************/
    132 void tegra_fc_soc_powerdn(uint32_t mpidr)
    133 {
    134 	int cpu = mpidr & MPIDR_CPU_MASK;
    135 	uint32_t val;
    136 
    137 	VERBOSE("Entering SoC powerdn state...\n");
    138 
    139 	tegra_fc_cc4_ctrl(cpu, 0);
    140 
    141 	tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL, 1);
    142 
    143 	val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
    144 	tegra_fc_prepare_suspend(cpu, val);
    145 
    146 	/* overwrite HALT register */
    147 	tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
    148 }
    149 
    150 /*******************************************************************************
    151  * Power up the CPU
    152  ******************************************************************************/
    153 void tegra_fc_cpu_on(int cpu)
    154 {
    155 	tegra_fc_cpu_csr(cpu, FLOWCTRL_CSR_ENABLE);
    156 	tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT | FLOWCTRL_HALT_SCLK);
    157 }
    158 
    159 /*******************************************************************************
    160  * Power down the CPU
    161  ******************************************************************************/
    162 void tegra_fc_cpu_off(int cpu)
    163 {
    164 	uint32_t val;
    165 
    166 	/*
    167 	 * Flow controller powers down the CPU during wfi. The CPU would be
    168 	 * powered on when it receives any interrupt.
    169 	 */
    170 	val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
    171 		FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu);
    172 	tegra_fc_cpu_csr(cpu, val);
    173 	tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
    174 	tegra_fc_cc4_ctrl(cpu, 0);
    175 }
    176 
    177 /*******************************************************************************
    178  * Inform the BPMP that we have completed the cluster power up
    179  ******************************************************************************/
    180 void tegra_fc_lock_active_cluster(void)
    181 {
    182 	uint32_t val;
    183 
    184 	val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
    185 	val |= FLOWCTRL_BPMP_CLUSTER_PWRON_LOCK;
    186 	tegra_fc_write_32(FLOWCTRL_BPMP_CLUSTER_CONTROL, val);
    187 	val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
    188 }
    189 
    190 /*******************************************************************************
    191  * Reset BPMP processor
    192  ******************************************************************************/
    193 void tegra_fc_reset_bpmp(void)
    194 {
    195 	uint32_t val;
    196 
    197 	/* halt BPMP */
    198 	tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
    199 
    200 	/* Assert BPMP reset */
    201 	mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
    202 
    203 	/* Restore reset address (stored in PMC_SCRATCH39) */
    204 	val = tegra_pmc_read_32(PMC_SCRATCH39);
    205 	mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, val);
    206 	while (val != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
    207 		; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
    208 
    209 	/* Wait for 2us before de-asserting the reset signal. */
    210 	udelay(2);
    211 
    212 	/* De-assert BPMP reset */
    213 	mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_CLR, CLK_BPMP_RST);
    214 
    215 	/* Un-halt BPMP */
    216 	tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, 0);
    217 }
    218