xref: /rk3399_ARM-atf/plat/xilinx/versal/pm_service/pm_client.c (revision 01a326abeb1726b7756ef21a3c7188ca79a30e2e)
1c73a90e5STejas Patel /*
20b151872STanmay Shah  * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
331b68489SJay Buddhabhatti  * Copyright (c) 2022-2023, 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>
14*01a326abSPrasad Kummari 
15*01a326abSPrasad Kummari #include <drivers/arm/gic_common.h>
16*01a326abSPrasad 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>
21*01a326abSPrasad Kummari 
22*01a326abSPrasad Kummari #include <plat_ipi.h>
23*01a326abSPrasad Kummari #include <platform_def.h>
246e82cd8cSTejas Patel #include "pm_api_sys.h"
25c73a90e5STejas Patel #include "pm_client.h"
260b151872STanmay Shah #include "pm_defs.h"
27*01a326abSPrasad Kummari #include <versal_def.h>
28c73a90e5STejas Patel 
2925b1a910STejas Patel #define UNDEFINED_CPUID		(~0)
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;
15806b9c4c8SJay Buddhabhatti 	case 126:
15906b9c4c8SJay Buddhabhatti 	case 127:
16006b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SDIO_0;
16106b9c4c8SJay Buddhabhatti 		break;
16206b9c4c8SJay Buddhabhatti 	case 128:
16306b9c4c8SJay Buddhabhatti 	case 129:
16406b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SDIO_1;
16506b9c4c8SJay Buddhabhatti 		break;
16606b9c4c8SJay Buddhabhatti 	case 142:
16706b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_RTC;
16806b9c4c8SJay Buddhabhatti 		break;
1690ec6c313SJay Buddhabhatti 	default:
1700ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_MIN;
1710ec6c313SJay Buddhabhatti 		break;
1720ec6c313SJay Buddhabhatti 	}
1730ec6c313SJay Buddhabhatti 
1740ec6c313SJay Buddhabhatti 	return dev_idx;
1756e82cd8cSTejas Patel }
1766e82cd8cSTejas Patel 
1776e82cd8cSTejas Patel /**
178de7ed953SPrasad Kummari  * pm_client_suspend() - Client-specific suspend actions.
179de7ed953SPrasad Kummari  * @proc: processor which need to suspend.
180de7ed953SPrasad Kummari  * @state: desired suspend state.
181fbb32695STejas Patel  *
182fbb32695STejas Patel  * This function should contain any PU-specific actions
183fbb32695STejas Patel  * required prior to sending suspend request to PMU
184fbb32695STejas Patel  * Actions taken depend on the state system is suspending to.
185de7ed953SPrasad Kummari  *
186fbb32695STejas Patel  */
187912b7a6fSVenkatesh Yadav Abbarapu void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
188fbb32695STejas Patel {
189fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
190fbb32695STejas Patel 
19141567195SAbhyuday Godhasara 	if (state == PM_STATE_SUSPEND_TO_RAM) {
1925d1c211eSAbhyuday Godhasara 		pm_client_set_wakeup_sources((uint32_t)proc->node_id);
19341567195SAbhyuday Godhasara 	}
1946e82cd8cSTejas Patel 
195fbb32695STejas Patel 	/* Set powerdown request */
196fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
197775bf1bbSAbhyuday Godhasara 		      (uint32_t)proc->pwrdn_mask);
198fbb32695STejas Patel 
199fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
200fbb32695STejas Patel }
201fbb32695STejas Patel 
202fbb32695STejas Patel /**
203de7ed953SPrasad Kummari  * pm_client_abort_suspend() - Client-specific abort-suspend actions.
204fbb32695STejas Patel  *
205fbb32695STejas Patel  * This function should contain any PU-specific actions
206de7ed953SPrasad Kummari  * required for aborting a prior suspend request.
207de7ed953SPrasad Kummari  *
208fbb32695STejas Patel  */
209fbb32695STejas Patel void pm_client_abort_suspend(void)
210fbb32695STejas Patel {
211fbb32695STejas Patel 	/* Enable interrupts at processor level (for current cpu) */
212fbb32695STejas Patel 	gicv3_cpuif_enable(plat_my_core_pos());
213fbb32695STejas Patel 
214fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
215fbb32695STejas Patel 
216fbb32695STejas Patel 	/* Clear powerdown request */
217fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
218775bf1bbSAbhyuday Godhasara 		      ~((uint32_t)primary_proc->pwrdn_mask));
219fbb32695STejas Patel 
220fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
221fbb32695STejas Patel }
222fbb32695STejas Patel 
223fbb32695STejas Patel /**
224de7ed953SPrasad Kummari  * pm_get_cpuid() - get the local cpu ID for a global node ID.
225de7ed953SPrasad Kummari  * @nid: node id of the processor.
22625b1a910STejas Patel  *
227de7ed953SPrasad Kummari  * Return: the cpu ID (starting from 0) for the subsystem.
228de7ed953SPrasad Kummari  *
22925b1a910STejas Patel  */
230912b7a6fSVenkatesh Yadav Abbarapu static uint32_t pm_get_cpuid(uint32_t nid)
23125b1a910STejas Patel {
2325d1c211eSAbhyuday Godhasara 	for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
23341567195SAbhyuday Godhasara 		if (pm_procs_all[i].node_id == nid) {
23425b1a910STejas Patel 			return i;
23525b1a910STejas Patel 		}
23641567195SAbhyuday Godhasara 	}
23725b1a910STejas Patel 	return UNDEFINED_CPUID;
23825b1a910STejas Patel }
23925b1a910STejas Patel 
24025b1a910STejas Patel /**
241de7ed953SPrasad Kummari  * pm_client_wakeup() - Client-specific wakeup actions.
242de7ed953SPrasad Kummari  * @proc: Processor which need to wakeup.
24325b1a910STejas Patel  *
24425b1a910STejas Patel  * This function should contain any PU-specific actions
245de7ed953SPrasad Kummari  * required for waking up another APU core.
246de7ed953SPrasad Kummari  *
24725b1a910STejas Patel  */
24825b1a910STejas Patel void pm_client_wakeup(const struct pm_proc *proc)
24925b1a910STejas Patel {
250912b7a6fSVenkatesh Yadav Abbarapu 	uint32_t cpuid = pm_get_cpuid(proc->node_id);
25125b1a910STejas Patel 
25241567195SAbhyuday Godhasara 	if (cpuid == UNDEFINED_CPUID) {
25325b1a910STejas Patel 		return;
25441567195SAbhyuday Godhasara 	}
25525b1a910STejas Patel 
25625b1a910STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
25725b1a910STejas Patel 
25825b1a910STejas Patel 	/* clear powerdown bit for affected cpu */
25925b1a910STejas Patel 	uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
26025b1a910STejas Patel 	val &= ~(proc->pwrdn_mask);
26125b1a910STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, val);
26225b1a910STejas Patel 
26325b1a910STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
26425b1a910STejas Patel }
26525b1a910STejas Patel 
26625b1a910STejas Patel /**
267de7ed953SPrasad Kummari  * pm_get_proc() - returns pointer to the proc structure.
268de7ed953SPrasad Kummari  * @cpuid: id of the cpu whose proc struct pointer should be returned.
269fbb32695STejas Patel  *
270de7ed953SPrasad Kummari  * Return: pointer to a proc structure if proc is found, otherwise NULL.
271de7ed953SPrasad Kummari  *
272fbb32695STejas Patel  */
273912b7a6fSVenkatesh Yadav Abbarapu const struct pm_proc *pm_get_proc(uint32_t cpuid)
274fbb32695STejas Patel {
27541567195SAbhyuday Godhasara 	if (cpuid < ARRAY_SIZE(pm_procs_all)) {
276fbb32695STejas Patel 		return &pm_procs_all[cpuid];
27741567195SAbhyuday Godhasara 	}
278fbb32695STejas Patel 
279fbb32695STejas Patel 	return NULL;
280fbb32695STejas Patel }
281