xref: /rk3399_ARM-atf/plat/xilinx/versal/pm_service/pm_client.c (revision b802b2784c8bcaae56d450ab55ee305880293c85)
1c73a90e5STejas Patel /*
20b151872STanmay Shah  * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
3692d32b5SRonak Jain  * Copyright (c) 2022-2024, 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 
29*b802b278SMaheedhar Bollapalli #define UNDEFINED_CPUID		(~0U)
3025b1a910STejas Patel 
31c73a90e5STejas Patel 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.
184fbb32695STejas Patel  *
185fbb32695STejas Patel  * This function should contain any PU-specific actions
186fbb32695STejas Patel  * required prior to sending suspend request to PMU
187fbb32695STejas Patel  * Actions taken depend on the state system is suspending to.
188de7ed953SPrasad Kummari  *
189fbb32695STejas Patel  */
190912b7a6fSVenkatesh Yadav Abbarapu void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
191fbb32695STejas Patel {
192fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
193fbb32695STejas Patel 
19441567195SAbhyuday Godhasara 	if (state == PM_STATE_SUSPEND_TO_RAM) {
1955d1c211eSAbhyuday Godhasara 		pm_client_set_wakeup_sources((uint32_t)proc->node_id);
19641567195SAbhyuday Godhasara 	}
1976e82cd8cSTejas Patel 
198fbb32695STejas Patel 	/* Set powerdown request */
199fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
200775bf1bbSAbhyuday Godhasara 		      (uint32_t)proc->pwrdn_mask);
201fbb32695STejas Patel 
202fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
203fbb32695STejas Patel }
204fbb32695STejas Patel 
205fbb32695STejas Patel /**
206de7ed953SPrasad Kummari  * pm_client_abort_suspend() - Client-specific abort-suspend actions.
207fbb32695STejas Patel  *
208fbb32695STejas Patel  * This function should contain any PU-specific actions
209de7ed953SPrasad Kummari  * required for aborting a prior suspend request.
210de7ed953SPrasad Kummari  *
211fbb32695STejas Patel  */
212fbb32695STejas Patel void pm_client_abort_suspend(void)
213fbb32695STejas Patel {
214fbb32695STejas Patel 	/* Enable interrupts at processor level (for current cpu) */
215fbb32695STejas Patel 	gicv3_cpuif_enable(plat_my_core_pos());
216fbb32695STejas Patel 
217fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
218fbb32695STejas Patel 
219fbb32695STejas Patel 	/* Clear powerdown request */
220fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
221775bf1bbSAbhyuday Godhasara 		      ~((uint32_t)primary_proc->pwrdn_mask));
222fbb32695STejas Patel 
223fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
224fbb32695STejas Patel }
225fbb32695STejas Patel 
226fbb32695STejas Patel /**
227de7ed953SPrasad Kummari  * pm_get_cpuid() - get the local cpu ID for a global node ID.
228de7ed953SPrasad Kummari  * @nid: node id of the processor.
22925b1a910STejas Patel  *
230de7ed953SPrasad Kummari  * Return: the cpu ID (starting from 0) for the subsystem.
231de7ed953SPrasad Kummari  *
23225b1a910STejas Patel  */
233912b7a6fSVenkatesh Yadav Abbarapu static uint32_t pm_get_cpuid(uint32_t nid)
23425b1a910STejas Patel {
2355d1c211eSAbhyuday Godhasara 	for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
23641567195SAbhyuday Godhasara 		if (pm_procs_all[i].node_id == nid) {
23725b1a910STejas Patel 			return i;
23825b1a910STejas Patel 		}
23941567195SAbhyuday Godhasara 	}
24025b1a910STejas Patel 	return UNDEFINED_CPUID;
24125b1a910STejas Patel }
24225b1a910STejas Patel 
24325b1a910STejas Patel /**
244de7ed953SPrasad Kummari  * pm_client_wakeup() - Client-specific wakeup actions.
245de7ed953SPrasad Kummari  * @proc: Processor which need to wakeup.
24625b1a910STejas Patel  *
24725b1a910STejas Patel  * This function should contain any PU-specific actions
248de7ed953SPrasad Kummari  * required for waking up another APU core.
249de7ed953SPrasad Kummari  *
25025b1a910STejas Patel  */
25125b1a910STejas Patel void pm_client_wakeup(const struct pm_proc *proc)
25225b1a910STejas Patel {
253912b7a6fSVenkatesh Yadav Abbarapu 	uint32_t cpuid = pm_get_cpuid(proc->node_id);
25425b1a910STejas Patel 
25541567195SAbhyuday Godhasara 	if (cpuid == UNDEFINED_CPUID) {
25625b1a910STejas Patel 		return;
25741567195SAbhyuday Godhasara 	}
25825b1a910STejas Patel 
25925b1a910STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
26025b1a910STejas Patel 
26125b1a910STejas Patel 	/* clear powerdown bit for affected cpu */
26225b1a910STejas Patel 	uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
26325b1a910STejas Patel 	val &= ~(proc->pwrdn_mask);
26425b1a910STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, val);
26525b1a910STejas Patel 
26625b1a910STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
26725b1a910STejas Patel }
26825b1a910STejas Patel 
26925b1a910STejas Patel /**
270de7ed953SPrasad Kummari  * pm_get_proc() - returns pointer to the proc structure.
271de7ed953SPrasad Kummari  * @cpuid: id of the cpu whose proc struct pointer should be returned.
272fbb32695STejas Patel  *
273de7ed953SPrasad Kummari  * Return: pointer to a proc structure if proc is found, otherwise NULL.
274de7ed953SPrasad Kummari  *
275fbb32695STejas Patel  */
276912b7a6fSVenkatesh Yadav Abbarapu const struct pm_proc *pm_get_proc(uint32_t cpuid)
277fbb32695STejas Patel {
27841567195SAbhyuday Godhasara 	if (cpuid < ARRAY_SIZE(pm_procs_all)) {
279fbb32695STejas Patel 		return &pm_procs_all[cpuid];
28041567195SAbhyuday Godhasara 	}
281fbb32695STejas Patel 
282fbb32695STejas Patel 	return NULL;
283fbb32695STejas Patel }
284