xref: /rk3399_ARM-atf/plat/xilinx/versal/pm_service/pm_client.c (revision 25b1a91033ae3e4220c933333764c01c7a687c2d)
1c73a90e5STejas Patel /*
2c73a90e5STejas Patel  * Copyright (c) 2019, Xilinx, Inc. All rights reserved.
3c73a90e5STejas Patel  *
4c73a90e5STejas Patel  * SPDX-License-Identifier: BSD-3-Clause
5c73a90e5STejas Patel  */
6c73a90e5STejas Patel 
7c73a90e5STejas Patel /*
8c73a90e5STejas Patel  * APU specific definition of processors in the subsystem as well as functions
9c73a90e5STejas Patel  * for getting information about and changing state of the APU.
10c73a90e5STejas Patel  */
11c73a90e5STejas Patel 
12c73a90e5STejas Patel #include <plat_ipi.h>
13c73a90e5STejas Patel #include <platform_def.h>
14c73a90e5STejas Patel #include <versal_def.h>
15c73a90e5STejas Patel #include <lib/bakery_lock.h>
16fbb32695STejas Patel #include <lib/mmio.h>
17fbb32695STejas Patel #include <drivers/arm/gicv3.h>
18fbb32695STejas Patel #include <plat/common/platform.h>
19c73a90e5STejas Patel #include "pm_client.h"
20c73a90e5STejas Patel 
21*25b1a910STejas Patel #define UNDEFINED_CPUID		(~0)
22*25b1a910STejas Patel 
23c73a90e5STejas Patel DEFINE_BAKERY_LOCK(pm_client_secure_lock);
24c73a90e5STejas Patel 
25c73a90e5STejas Patel static const struct pm_ipi apu_ipi = {
26c73a90e5STejas Patel 	.local_ipi_id = IPI_ID_APU,
27c73a90e5STejas Patel 	.remote_ipi_id = IPI_ID_PMC,
28c73a90e5STejas Patel 	.buffer_base = IPI_BUFFER_APU_BASE,
29c73a90e5STejas Patel };
30c73a90e5STejas Patel 
31c73a90e5STejas Patel /* Order in pm_procs_all array must match cpu ids */
32c73a90e5STejas Patel static const struct pm_proc pm_procs_all[] = {
33c73a90e5STejas Patel 	{
34c73a90e5STejas Patel 		.node_id = XPM_DEVID_ACPU_0,
35c73a90e5STejas Patel 		.ipi = &apu_ipi,
36fbb32695STejas Patel 		.pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
37c73a90e5STejas Patel 	},
38c73a90e5STejas Patel 	{
39c73a90e5STejas Patel 		.node_id = XPM_DEVID_ACPU_1,
40c73a90e5STejas Patel 		.ipi = &apu_ipi,
41fbb32695STejas Patel 		.pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
42c73a90e5STejas Patel 	}
43c73a90e5STejas Patel };
44c73a90e5STejas Patel 
45c73a90e5STejas Patel const struct pm_proc *primary_proc = &pm_procs_all[0];
46fbb32695STejas Patel 
47fbb32695STejas Patel /**
48fbb32695STejas Patel  * pm_client_suspend() - Client-specific suspend actions
49fbb32695STejas Patel  *
50fbb32695STejas Patel  * This function should contain any PU-specific actions
51fbb32695STejas Patel  * required prior to sending suspend request to PMU
52fbb32695STejas Patel  * Actions taken depend on the state system is suspending to.
53fbb32695STejas Patel  */
54fbb32695STejas Patel void pm_client_suspend(const struct pm_proc *proc, unsigned int state)
55fbb32695STejas Patel {
56fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
57fbb32695STejas Patel 
58fbb32695STejas Patel 	/* Set powerdown request */
59fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
60fbb32695STejas Patel 		      proc->pwrdn_mask);
61fbb32695STejas Patel 
62fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
63fbb32695STejas Patel }
64fbb32695STejas Patel 
65fbb32695STejas Patel /**
66fbb32695STejas Patel  * pm_client_abort_suspend() - Client-specific abort-suspend actions
67fbb32695STejas Patel  *
68fbb32695STejas Patel  * This function should contain any PU-specific actions
69fbb32695STejas Patel  * required for aborting a prior suspend request
70fbb32695STejas Patel  */
71fbb32695STejas Patel void pm_client_abort_suspend(void)
72fbb32695STejas Patel {
73fbb32695STejas Patel 	/* Enable interrupts at processor level (for current cpu) */
74fbb32695STejas Patel 	gicv3_cpuif_enable(plat_my_core_pos());
75fbb32695STejas Patel 
76fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
77fbb32695STejas Patel 
78fbb32695STejas Patel 	/* Clear powerdown request */
79fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
80fbb32695STejas Patel 		      ~primary_proc->pwrdn_mask);
81fbb32695STejas Patel 
82fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
83fbb32695STejas Patel }
84fbb32695STejas Patel 
85fbb32695STejas Patel /**
86*25b1a910STejas Patel  * pm_get_cpuid() - get the local cpu ID for a global node ID
87*25b1a910STejas Patel  * @nid:	node id of the processor
88*25b1a910STejas Patel  *
89*25b1a910STejas Patel  * Return: the cpu ID (starting from 0) for the subsystem
90*25b1a910STejas Patel  */
91*25b1a910STejas Patel static unsigned int pm_get_cpuid(uint32_t nid)
92*25b1a910STejas Patel {
93*25b1a910STejas Patel 	for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
94*25b1a910STejas Patel 		if (pm_procs_all[i].node_id == nid)
95*25b1a910STejas Patel 			return i;
96*25b1a910STejas Patel 	}
97*25b1a910STejas Patel 	return UNDEFINED_CPUID;
98*25b1a910STejas Patel }
99*25b1a910STejas Patel 
100*25b1a910STejas Patel /**
101*25b1a910STejas Patel  * pm_client_wakeup() - Client-specific wakeup actions
102*25b1a910STejas Patel  *
103*25b1a910STejas Patel  * This function should contain any PU-specific actions
104*25b1a910STejas Patel  * required for waking up another APU core
105*25b1a910STejas Patel  */
106*25b1a910STejas Patel void pm_client_wakeup(const struct pm_proc *proc)
107*25b1a910STejas Patel {
108*25b1a910STejas Patel 	unsigned int cpuid = pm_get_cpuid(proc->node_id);
109*25b1a910STejas Patel 
110*25b1a910STejas Patel 	if (cpuid == UNDEFINED_CPUID)
111*25b1a910STejas Patel 		return;
112*25b1a910STejas Patel 
113*25b1a910STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
114*25b1a910STejas Patel 
115*25b1a910STejas Patel 	/* clear powerdown bit for affected cpu */
116*25b1a910STejas Patel 	uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
117*25b1a910STejas Patel 	val &= ~(proc->pwrdn_mask);
118*25b1a910STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, val);
119*25b1a910STejas Patel 
120*25b1a910STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
121*25b1a910STejas Patel }
122*25b1a910STejas Patel 
123*25b1a910STejas Patel /**
124fbb32695STejas Patel  * pm_get_proc() - returns pointer to the proc structure
125fbb32695STejas Patel  * @cpuid:	id of the cpu whose proc struct pointer should be returned
126fbb32695STejas Patel  *
127fbb32695STejas Patel  * Return: pointer to a proc structure if proc is found, otherwise NULL
128fbb32695STejas Patel  */
129fbb32695STejas Patel const struct pm_proc *pm_get_proc(unsigned int cpuid)
130fbb32695STejas Patel {
131fbb32695STejas Patel 	if (cpuid < ARRAY_SIZE(pm_procs_all))
132fbb32695STejas Patel 		return &pm_procs_all[cpuid];
133fbb32695STejas Patel 
134fbb32695STejas Patel 	return NULL;
135fbb32695STejas Patel }
136