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