xref: /rk3399_ARM-atf/plat/xilinx/versal/pm_service/pm_client.c (revision 5cac1d853df2bd15e04c2198b80c2eb2a4182243)
1c73a90e5STejas Patel /*
20b151872STanmay Shah  * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
34b4080d7SDevanshi Chauhan Alpeshbhai  * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
4c73a90e5STejas Patel  *
5c73a90e5STejas Patel  * SPDX-License-Identifier: BSD-3-Clause
6c73a90e5STejas Patel  */
7c73a90e5STejas Patel 
8c73a90e5STejas Patel /*
9c73a90e5STejas Patel  * APU specific definition of processors in the subsystem as well as functions
10c73a90e5STejas Patel  * for getting information about and changing state of the APU.
11c73a90e5STejas Patel  */
12c73a90e5STejas Patel 
136e82cd8cSTejas Patel #include <assert.h>
1401a326abSPrasad Kummari 
1501a326abSPrasad Kummari #include <drivers/arm/gic_common.h>
1601a326abSPrasad Kummari #include <drivers/arm/gicv3.h>
17c73a90e5STejas Patel #include <lib/bakery_lock.h>
18fbb32695STejas Patel #include <lib/mmio.h>
196e82cd8cSTejas Patel #include <lib/utils.h>
20fbb32695STejas Patel #include <plat/common/platform.h>
2101a326abSPrasad Kummari 
2201a326abSPrasad Kummari #include <plat_ipi.h>
2301a326abSPrasad Kummari #include <platform_def.h>
246e82cd8cSTejas Patel #include "pm_api_sys.h"
25c73a90e5STejas Patel #include "pm_client.h"
260b151872STanmay Shah #include "pm_defs.h"
2701a326abSPrasad Kummari #include <versal_def.h>
28c73a90e5STejas Patel 
29b802b278SMaheedhar Bollapalli #define UNDEFINED_CPUID		(~0U)
3025b1a910STejas Patel 
314b4080d7SDevanshi Chauhan Alpeshbhai static DEFINE_BAKERY_LOCK(pm_client_secure_lock);
32c73a90e5STejas Patel 
33c73a90e5STejas Patel static const struct pm_ipi apu_ipi = {
34068b0bc6SMichal Simek 	.local_ipi_id = IPI_LOCAL_ID,
35068b0bc6SMichal Simek 	.remote_ipi_id = IPI_REMOTE_ID,
36bfd06265SMichal Simek 	.buffer_base = IPI_BUFFER_LOCAL_BASE,
37c73a90e5STejas Patel };
38c73a90e5STejas Patel 
39c73a90e5STejas Patel /* Order in pm_procs_all array must match cpu ids */
40c73a90e5STejas Patel static const struct pm_proc pm_procs_all[] = {
41c73a90e5STejas Patel 	{
42c73a90e5STejas Patel 		.node_id = XPM_DEVID_ACPU_0,
43c73a90e5STejas Patel 		.ipi = &apu_ipi,
44fbb32695STejas Patel 		.pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
45c73a90e5STejas Patel 	},
46c73a90e5STejas Patel 	{
47c73a90e5STejas Patel 		.node_id = XPM_DEVID_ACPU_1,
48c73a90e5STejas Patel 		.ipi = &apu_ipi,
49fbb32695STejas Patel 		.pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
50c73a90e5STejas Patel 	}
51c73a90e5STejas Patel };
52c73a90e5STejas Patel 
53c73a90e5STejas Patel const struct pm_proc *primary_proc = &pm_procs_all[0];
54fbb32695STejas Patel 
556e82cd8cSTejas Patel /**
56de7ed953SPrasad Kummari  * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number.
576e82cd8cSTejas Patel  * @irq: Interrupt number
586e82cd8cSTejas Patel  *
59de7ed953SPrasad Kummari  * Return: PM node index corresponding to the specified interrupt.
60de7ed953SPrasad Kummari  *
616e82cd8cSTejas Patel  */
623ae28aa4SJay Buddhabhatti enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq)
636e82cd8cSTejas Patel {
640ec6c313SJay Buddhabhatti 	enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN;
650ec6c313SJay Buddhabhatti 
666e82cd8cSTejas Patel 	assert(irq <= IRQ_MAX);
670ec6c313SJay Buddhabhatti 
680ec6c313SJay Buddhabhatti 	switch (irq) {
690ec6c313SJay Buddhabhatti 	case 13:
700ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_GPIO;
710ec6c313SJay Buddhabhatti 		break;
720ec6c313SJay Buddhabhatti 	case 14:
730ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_I2C_0;
740ec6c313SJay Buddhabhatti 		break;
750ec6c313SJay Buddhabhatti 	case 15:
760ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_I2C_1;
770ec6c313SJay Buddhabhatti 		break;
780ec6c313SJay Buddhabhatti 	case 16:
790ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SPI_0;
800ec6c313SJay Buddhabhatti 		break;
810ec6c313SJay Buddhabhatti 	case 17:
820ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SPI_1;
830ec6c313SJay Buddhabhatti 		break;
840ec6c313SJay Buddhabhatti 	case 18:
850ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_UART_0;
860ec6c313SJay Buddhabhatti 		break;
870ec6c313SJay Buddhabhatti 	case 19:
880ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_UART_1;
890ec6c313SJay Buddhabhatti 		break;
900ec6c313SJay Buddhabhatti 	case 20:
910ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_CAN_FD_0;
920ec6c313SJay Buddhabhatti 		break;
930ec6c313SJay Buddhabhatti 	case 21:
940ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_CAN_FD_1;
950ec6c313SJay Buddhabhatti 		break;
960ec6c313SJay Buddhabhatti 	case 22:
970ec6c313SJay Buddhabhatti 	case 23:
980ec6c313SJay Buddhabhatti 	case 24:
990ec6c313SJay Buddhabhatti 	case 25:
1000ec6c313SJay Buddhabhatti 	case 26:
1010ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_USB_0;
1020ec6c313SJay Buddhabhatti 		break;
1030ec6c313SJay Buddhabhatti 	case 37:
1040ec6c313SJay Buddhabhatti 	case 38:
1050ec6c313SJay Buddhabhatti 	case 39:
1060ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_0;
1070ec6c313SJay Buddhabhatti 		break;
1080ec6c313SJay Buddhabhatti 	case 40:
1090ec6c313SJay Buddhabhatti 	case 41:
1100ec6c313SJay Buddhabhatti 	case 42:
1110ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_1;
1120ec6c313SJay Buddhabhatti 		break;
1130ec6c313SJay Buddhabhatti 	case 43:
1140ec6c313SJay Buddhabhatti 	case 44:
1150ec6c313SJay Buddhabhatti 	case 45:
1160ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_2;
1170ec6c313SJay Buddhabhatti 		break;
1180ec6c313SJay Buddhabhatti 	case 46:
1190ec6c313SJay Buddhabhatti 	case 47:
1200ec6c313SJay Buddhabhatti 	case 48:
1210ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_3;
1220ec6c313SJay Buddhabhatti 		break;
1230ec6c313SJay Buddhabhatti 	case 56:
1240ec6c313SJay Buddhabhatti 	case 57:
1250ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_GEM_0;
1260ec6c313SJay Buddhabhatti 		break;
12706b9c4c8SJay Buddhabhatti 	case 58:
12806b9c4c8SJay Buddhabhatti 	case 59:
12906b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_GEM_1;
13006b9c4c8SJay Buddhabhatti 		break;
13106b9c4c8SJay Buddhabhatti 	case 60:
13206b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_0;
13306b9c4c8SJay Buddhabhatti 		break;
13406b9c4c8SJay Buddhabhatti 	case 61:
13506b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_1;
13606b9c4c8SJay Buddhabhatti 		break;
13706b9c4c8SJay Buddhabhatti 	case 62:
13806b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_2;
13906b9c4c8SJay Buddhabhatti 		break;
14006b9c4c8SJay Buddhabhatti 	case 63:
14106b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_3;
14206b9c4c8SJay Buddhabhatti 		break;
14306b9c4c8SJay Buddhabhatti 	case 64:
14406b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_4;
14506b9c4c8SJay Buddhabhatti 		break;
14606b9c4c8SJay Buddhabhatti 	case 65:
14706b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_5;
14806b9c4c8SJay Buddhabhatti 		break;
14906b9c4c8SJay Buddhabhatti 	case 66:
15006b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_6;
15106b9c4c8SJay Buddhabhatti 		break;
15206b9c4c8SJay Buddhabhatti 	case 67:
15306b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_7;
15406b9c4c8SJay Buddhabhatti 		break;
15506b9c4c8SJay Buddhabhatti 	case 74:
15606b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_USB_0;
15706b9c4c8SJay Buddhabhatti 		break;
158692d32b5SRonak Jain 	case 122:
159692d32b5SRonak Jain 		dev_idx = XPM_NODEIDX_DEV_GPIO_PMC;
160692d32b5SRonak Jain 		break;
16106b9c4c8SJay Buddhabhatti 	case 126:
16206b9c4c8SJay Buddhabhatti 	case 127:
16306b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SDIO_0;
16406b9c4c8SJay Buddhabhatti 		break;
16506b9c4c8SJay Buddhabhatti 	case 128:
16606b9c4c8SJay Buddhabhatti 	case 129:
16706b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SDIO_1;
16806b9c4c8SJay Buddhabhatti 		break;
16906b9c4c8SJay Buddhabhatti 	case 142:
17006b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_RTC;
17106b9c4c8SJay Buddhabhatti 		break;
1720ec6c313SJay Buddhabhatti 	default:
1730ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_MIN;
1740ec6c313SJay Buddhabhatti 		break;
1750ec6c313SJay Buddhabhatti 	}
1760ec6c313SJay Buddhabhatti 
1770ec6c313SJay Buddhabhatti 	return dev_idx;
1786e82cd8cSTejas Patel }
1796e82cd8cSTejas Patel 
1806e82cd8cSTejas Patel /**
181de7ed953SPrasad Kummari  * pm_client_suspend() - Client-specific suspend actions.
182de7ed953SPrasad Kummari  * @proc: processor which need to suspend.
183de7ed953SPrasad Kummari  * @state: desired suspend state.
184*5cac1d85SRonak Jain  * @flag: 0 - Call from secure source.
185*5cac1d85SRonak Jain  *	  1 - Call from non-secure source.
186fbb32695STejas Patel  *
187fbb32695STejas Patel  * This function should contain any PU-specific actions
188fbb32695STejas Patel  * required prior to sending suspend request to PMU
189fbb32695STejas Patel  * Actions taken depend on the state system is suspending to.
190de7ed953SPrasad Kummari  *
191fbb32695STejas Patel  */
192*5cac1d85SRonak Jain void pm_client_suspend(const struct pm_proc *proc, uint32_t state, uint32_t flag)
193fbb32695STejas Patel {
194fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
195fbb32695STejas Patel 
19641567195SAbhyuday Godhasara 	if (state == PM_STATE_SUSPEND_TO_RAM) {
197*5cac1d85SRonak Jain 		pm_client_set_wakeup_sources((uint32_t)proc->node_id, flag);
19841567195SAbhyuday Godhasara 	}
1996e82cd8cSTejas Patel 
200fbb32695STejas Patel 	/* Set powerdown request */
201fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
202775bf1bbSAbhyuday Godhasara 		      (uint32_t)proc->pwrdn_mask);
203fbb32695STejas Patel 
204fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
205fbb32695STejas Patel }
206fbb32695STejas Patel 
207fbb32695STejas Patel /**
208de7ed953SPrasad Kummari  * pm_client_abort_suspend() - Client-specific abort-suspend actions.
209fbb32695STejas Patel  *
210fbb32695STejas Patel  * This function should contain any PU-specific actions
211de7ed953SPrasad Kummari  * required for aborting a prior suspend request.
212de7ed953SPrasad Kummari  *
213fbb32695STejas Patel  */
214fbb32695STejas Patel void pm_client_abort_suspend(void)
215fbb32695STejas Patel {
216fbb32695STejas Patel 	/* Enable interrupts at processor level (for current cpu) */
217fbb32695STejas Patel 	gicv3_cpuif_enable(plat_my_core_pos());
218fbb32695STejas Patel 
219fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
220fbb32695STejas Patel 
221fbb32695STejas Patel 	/* Clear powerdown request */
222fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
223775bf1bbSAbhyuday Godhasara 		      ~((uint32_t)primary_proc->pwrdn_mask));
224fbb32695STejas Patel 
225fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
226fbb32695STejas Patel }
227fbb32695STejas Patel 
228fbb32695STejas Patel /**
229de7ed953SPrasad Kummari  * pm_get_cpuid() - get the local cpu ID for a global node ID.
230de7ed953SPrasad Kummari  * @nid: node id of the processor.
23125b1a910STejas Patel  *
232de7ed953SPrasad Kummari  * Return: the cpu ID (starting from 0) for the subsystem.
233de7ed953SPrasad Kummari  *
23425b1a910STejas Patel  */
235912b7a6fSVenkatesh Yadav Abbarapu static uint32_t pm_get_cpuid(uint32_t nid)
23625b1a910STejas Patel {
2379b89de5fSMaheedhar Bollapalli 	uint32_t ret = UNDEFINED_CPUID;
2388e4d5c6dSMaheedhar Bollapalli 	uint32_t i;
2399b89de5fSMaheedhar Bollapalli 
2408e4d5c6dSMaheedhar Bollapalli 	for (i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
24141567195SAbhyuday Godhasara 		if (pm_procs_all[i].node_id == nid) {
2429b89de5fSMaheedhar Bollapalli 			ret = i;
2439b89de5fSMaheedhar Bollapalli 			break;
24425b1a910STejas Patel 		}
24541567195SAbhyuday Godhasara 	}
2469b89de5fSMaheedhar Bollapalli 	return ret;
24725b1a910STejas Patel }
24825b1a910STejas Patel 
24925b1a910STejas Patel /**
250de7ed953SPrasad Kummari  * pm_client_wakeup() - Client-specific wakeup actions.
251de7ed953SPrasad Kummari  * @proc: Processor which need to wakeup.
25225b1a910STejas Patel  *
25325b1a910STejas Patel  * This function should contain any PU-specific actions
254de7ed953SPrasad Kummari  * required for waking up another APU core.
255de7ed953SPrasad Kummari  *
25625b1a910STejas Patel  */
25725b1a910STejas Patel void pm_client_wakeup(const struct pm_proc *proc)
25825b1a910STejas Patel {
259912b7a6fSVenkatesh Yadav Abbarapu 	uint32_t cpuid = pm_get_cpuid(proc->node_id);
26025b1a910STejas Patel 
26141567195SAbhyuday Godhasara 	if (cpuid == UNDEFINED_CPUID) {
26225b1a910STejas Patel 		return;
26341567195SAbhyuday Godhasara 	}
26425b1a910STejas Patel 
26525b1a910STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
26625b1a910STejas Patel 
26725b1a910STejas Patel 	/* clear powerdown bit for affected cpu */
26825b1a910STejas Patel 	uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
26925b1a910STejas Patel 	val &= ~(proc->pwrdn_mask);
27025b1a910STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, val);
27125b1a910STejas Patel 
27225b1a910STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
27325b1a910STejas Patel }
27425b1a910STejas Patel 
27525b1a910STejas Patel /**
276de7ed953SPrasad Kummari  * pm_get_proc() - returns pointer to the proc structure.
277de7ed953SPrasad Kummari  * @cpuid: id of the cpu whose proc struct pointer should be returned.
278fbb32695STejas Patel  *
279de7ed953SPrasad Kummari  * Return: pointer to a proc structure if proc is found, otherwise NULL.
280de7ed953SPrasad Kummari  *
281fbb32695STejas Patel  */
282912b7a6fSVenkatesh Yadav Abbarapu const struct pm_proc *pm_get_proc(uint32_t cpuid)
283fbb32695STejas Patel {
28441567195SAbhyuday Godhasara 	if (cpuid < ARRAY_SIZE(pm_procs_all)) {
285fbb32695STejas Patel 		return &pm_procs_all[cpuid];
28641567195SAbhyuday Godhasara 	}
287fbb32695STejas Patel 
288fbb32695STejas Patel 	return NULL;
289fbb32695STejas Patel }
290