1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <drivers/arm/fvp/fvp_pwrc.h> 8*91f16700Schasinglulu #include <lib/bakery_lock.h> 9*91f16700Schasinglulu #include <lib/mmio.h> 10*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h> 11*91f16700Schasinglulu #include <platform_def.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #define FVP_PWRC_ID_MASK U(0x00FFFFFF) 14*91f16700Schasinglulu 15*91f16700Schasinglulu /* 16*91f16700Schasinglulu * TODO: Someday there will be a generic power controller api. At the moment 17*91f16700Schasinglulu * each platform has its own pwrc so just exporting functions is fine. 18*91f16700Schasinglulu */ 19*91f16700Schasinglulu ARM_INSTANTIATE_LOCK; 20*91f16700Schasinglulu 21*91f16700Schasinglulu /* 22*91f16700Schasinglulu * Core ID field is 24 bits wide and extracted from MPIDR. 23*91f16700Schasinglulu * Bits[23:16] represent Affinity Level 2 24*91f16700Schasinglulu * Bits[15:8] represent Affinity Level 1 25*91f16700Schasinglulu * Bits[7:0] represent Affinity Level 0 26*91f16700Schasinglulu */ 27*91f16700Schasinglulu static unsigned int fvp_pwrc_core_id(u_register_t mpidr) 28*91f16700Schasinglulu { 29*91f16700Schasinglulu return (unsigned int)(mpidr & FVP_PWRC_ID_MASK); 30*91f16700Schasinglulu } 31*91f16700Schasinglulu 32*91f16700Schasinglulu unsigned int fvp_pwrc_get_cpu_wkr(u_register_t mpidr) 33*91f16700Schasinglulu { 34*91f16700Schasinglulu unsigned int id = fvp_pwrc_core_id(mpidr); 35*91f16700Schasinglulu 36*91f16700Schasinglulu return PSYSR_WK(fvp_pwrc_read_psysr(id)); 37*91f16700Schasinglulu } 38*91f16700Schasinglulu 39*91f16700Schasinglulu unsigned int fvp_pwrc_read_psysr(u_register_t mpidr) 40*91f16700Schasinglulu { 41*91f16700Schasinglulu unsigned int rc; 42*91f16700Schasinglulu unsigned int id = fvp_pwrc_core_id(mpidr); 43*91f16700Schasinglulu 44*91f16700Schasinglulu arm_lock_get(); 45*91f16700Schasinglulu mmio_write_32(PWRC_BASE + PSYSR_OFF, id); 46*91f16700Schasinglulu rc = mmio_read_32(PWRC_BASE + PSYSR_OFF); 47*91f16700Schasinglulu arm_lock_release(); 48*91f16700Schasinglulu return rc; 49*91f16700Schasinglulu } 50*91f16700Schasinglulu 51*91f16700Schasinglulu void fvp_pwrc_write_pponr(u_register_t mpidr) 52*91f16700Schasinglulu { 53*91f16700Schasinglulu unsigned int id = fvp_pwrc_core_id(mpidr); 54*91f16700Schasinglulu 55*91f16700Schasinglulu arm_lock_get(); 56*91f16700Schasinglulu mmio_write_32(PWRC_BASE + PPONR_OFF, id); 57*91f16700Schasinglulu arm_lock_release(); 58*91f16700Schasinglulu } 59*91f16700Schasinglulu 60*91f16700Schasinglulu void fvp_pwrc_write_ppoffr(u_register_t mpidr) 61*91f16700Schasinglulu { 62*91f16700Schasinglulu unsigned int id = fvp_pwrc_core_id(mpidr); 63*91f16700Schasinglulu 64*91f16700Schasinglulu arm_lock_get(); 65*91f16700Schasinglulu mmio_write_32(PWRC_BASE + PPOFFR_OFF, id); 66*91f16700Schasinglulu arm_lock_release(); 67*91f16700Schasinglulu } 68*91f16700Schasinglulu 69*91f16700Schasinglulu void fvp_pwrc_set_wen(u_register_t mpidr) 70*91f16700Schasinglulu { 71*91f16700Schasinglulu unsigned int id = fvp_pwrc_core_id(mpidr); 72*91f16700Schasinglulu 73*91f16700Schasinglulu arm_lock_get(); 74*91f16700Schasinglulu mmio_write_32(PWRC_BASE + PWKUPR_OFF, 75*91f16700Schasinglulu (unsigned int) (PWKUPR_WEN | id)); 76*91f16700Schasinglulu arm_lock_release(); 77*91f16700Schasinglulu } 78*91f16700Schasinglulu 79*91f16700Schasinglulu void fvp_pwrc_clr_wen(u_register_t mpidr) 80*91f16700Schasinglulu { 81*91f16700Schasinglulu unsigned int id = fvp_pwrc_core_id(mpidr); 82*91f16700Schasinglulu 83*91f16700Schasinglulu arm_lock_get(); 84*91f16700Schasinglulu mmio_write_32(PWRC_BASE + PWKUPR_OFF, id); 85*91f16700Schasinglulu arm_lock_release(); 86*91f16700Schasinglulu } 87*91f16700Schasinglulu 88*91f16700Schasinglulu void fvp_pwrc_write_pcoffr(u_register_t mpidr) 89*91f16700Schasinglulu { 90*91f16700Schasinglulu unsigned int id = fvp_pwrc_core_id(mpidr); 91*91f16700Schasinglulu 92*91f16700Schasinglulu arm_lock_get(); 93*91f16700Schasinglulu mmio_write_32(PWRC_BASE + PCOFFR_OFF, id); 94*91f16700Schasinglulu arm_lock_release(); 95*91f16700Schasinglulu } 96*91f16700Schasinglulu 97*91f16700Schasinglulu /* Nothing else to do here apart from initializing the lock */ 98*91f16700Schasinglulu void __init plat_arm_pwrc_setup(void) 99*91f16700Schasinglulu { 100*91f16700Schasinglulu arm_lock_init(); 101*91f16700Schasinglulu } 102*91f16700Schasinglulu 103*91f16700Schasinglulu 104*91f16700Schasinglulu 105