Home | History | Annotate | Download | only in pmc
      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 <debug.h>
     10 #include <mmio.h>
     11 #include <pmc.h>
     12 #include <tegra_def.h>
     13 
     14 #define RESET_ENABLE	0x10U
     15 
     16 /* Module IDs used during power ungate procedure */
     17 static const uint32_t pmc_cpu_powergate_id[4] = {
     18 	0, /* CPU 0 */
     19 	9, /* CPU 1 */
     20 	10, /* CPU 2 */
     21 	11 /* CPU 3 */
     22 };
     23 
     24 /*******************************************************************************
     25  * Power ungate CPU to start the boot process. CPU reset vectors must be
     26  * populated before calling this function.
     27  ******************************************************************************/
     28 void tegra_pmc_cpu_on(int32_t cpu)
     29 {
     30 	uint32_t val;
     31 
     32 	/*
     33 	 * Check if CPU is already power ungated
     34 	 */
     35 	val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);
     36 	if ((val & (1U << pmc_cpu_powergate_id[cpu])) == 0U) {
     37 		/*
     38 		 * The PMC deasserts the START bit when it starts the power
     39 		 * ungate process. Loop till no power toggle is in progress.
     40 		 */
     41 		do {
     42 			val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE);
     43 		} while ((val & PMC_TOGGLE_START) != 0U);
     44 
     45 		/*
     46 		 * Start the power ungate procedure
     47 		 */
     48 		val = pmc_cpu_powergate_id[cpu] | PMC_TOGGLE_START;
     49 		tegra_pmc_write_32(PMC_PWRGATE_TOGGLE, val);
     50 
     51 		/*
     52 		 * The PMC deasserts the START bit when it starts the power
     53 		 * ungate process. Loop till powergate START bit is asserted.
     54 		 */
     55 		do {
     56 			val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE);
     57 		} while ((val & (1U << 8)) != 0U);
     58 
     59 		/* loop till the CPU is power ungated */
     60 		do {
     61 			val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);
     62 		} while ((val & (1U << pmc_cpu_powergate_id[cpu])) == 0U);
     63 	}
     64 }
     65 
     66 /*******************************************************************************
     67  * Setup CPU vectors for resume from deep sleep
     68  ******************************************************************************/
     69 void tegra_pmc_cpu_setup(uint64_t reset_addr)
     70 {
     71 	uint32_t val;
     72 
     73 	tegra_pmc_write_32(PMC_SECURE_SCRATCH34,
     74 			   ((uint32_t)reset_addr & 0xFFFFFFFFU) | 1U);
     75 	val = (uint32_t)(reset_addr >> 32U);
     76 	tegra_pmc_write_32(PMC_SECURE_SCRATCH35, val & 0x7FFU);
     77 }
     78 
     79 /*******************************************************************************
     80  * Lock CPU vectors to restrict further writes
     81  ******************************************************************************/
     82 void tegra_pmc_lock_cpu_vectors(void)
     83 {
     84 	uint32_t val;
     85 
     86 	/* lock PMC_SECURE_SCRATCH22 */
     87 	val = tegra_pmc_read_32(PMC_SECURE_DISABLE2);
     88 	val |= PMC_SECURE_DISABLE2_WRITE22_ON;
     89 	tegra_pmc_write_32(PMC_SECURE_DISABLE2, val);
     90 
     91 	/* lock PMC_SECURE_SCRATCH34/35 */
     92 	val = tegra_pmc_read_32(PMC_SECURE_DISABLE3);
     93 	val |= (PMC_SECURE_DISABLE3_WRITE34_ON |
     94 		PMC_SECURE_DISABLE3_WRITE35_ON);
     95 	tegra_pmc_write_32(PMC_SECURE_DISABLE3, val);
     96 }
     97 
     98 /*******************************************************************************
     99  * Restart the system
    100  ******************************************************************************/
    101 __dead2 void tegra_pmc_system_reset(void)
    102 {
    103 	uint32_t reg;
    104 
    105 	reg = tegra_pmc_read_32(PMC_CONFIG);
    106 	reg |= RESET_ENABLE;		/* restart */
    107 	tegra_pmc_write_32(PMC_CONFIG, reg);
    108 	wfi();
    109 
    110 	ERROR("Tegra System Reset: operation not handled.\n");
    111 	panic();
    112 }
    113