xref: /rk3399_ARM-atf/plat/xilinx/versal/pm_service/pm_client.c (revision de7ed953e33b4dbeed1f0e6df16628e07d015570)
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>
14c73a90e5STejas Patel #include <plat_ipi.h>
15c73a90e5STejas Patel #include <platform_def.h>
16c73a90e5STejas Patel #include <versal_def.h>
17c73a90e5STejas Patel #include <lib/bakery_lock.h>
18fbb32695STejas Patel #include <lib/mmio.h>
196e82cd8cSTejas Patel #include <lib/utils.h>
20fbb32695STejas Patel #include <drivers/arm/gicv3.h>
216e82cd8cSTejas Patel #include <drivers/arm/gic_common.h>
22fbb32695STejas Patel #include <plat/common/platform.h>
236e82cd8cSTejas Patel #include "pm_api_sys.h"
24c73a90e5STejas Patel #include "pm_client.h"
250b151872STanmay Shah #include "pm_defs.h"
26c73a90e5STejas Patel 
2725b1a910STejas Patel #define UNDEFINED_CPUID		(~0)
2825b1a910STejas Patel 
29c73a90e5STejas Patel DEFINE_BAKERY_LOCK(pm_client_secure_lock);
30c73a90e5STejas Patel 
31c73a90e5STejas Patel static const struct pm_ipi apu_ipi = {
32068b0bc6SMichal Simek 	.local_ipi_id = IPI_LOCAL_ID,
33068b0bc6SMichal Simek 	.remote_ipi_id = IPI_REMOTE_ID,
34bfd06265SMichal Simek 	.buffer_base = IPI_BUFFER_LOCAL_BASE,
35c73a90e5STejas Patel };
36c73a90e5STejas Patel 
37c73a90e5STejas Patel /* Order in pm_procs_all array must match cpu ids */
38c73a90e5STejas Patel static const struct pm_proc pm_procs_all[] = {
39c73a90e5STejas Patel 	{
40c73a90e5STejas Patel 		.node_id = XPM_DEVID_ACPU_0,
41c73a90e5STejas Patel 		.ipi = &apu_ipi,
42fbb32695STejas Patel 		.pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
43c73a90e5STejas Patel 	},
44c73a90e5STejas Patel 	{
45c73a90e5STejas Patel 		.node_id = XPM_DEVID_ACPU_1,
46c73a90e5STejas Patel 		.ipi = &apu_ipi,
47fbb32695STejas Patel 		.pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
48c73a90e5STejas Patel 	}
49c73a90e5STejas Patel };
50c73a90e5STejas Patel 
51c73a90e5STejas Patel const struct pm_proc *primary_proc = &pm_procs_all[0];
52fbb32695STejas Patel 
536e82cd8cSTejas Patel /**
54*de7ed953SPrasad Kummari  * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number.
556e82cd8cSTejas Patel  * @irq: Interrupt number
566e82cd8cSTejas Patel  *
57*de7ed953SPrasad Kummari  * Return: PM node index corresponding to the specified interrupt.
58*de7ed953SPrasad Kummari  *
596e82cd8cSTejas Patel  */
603ae28aa4SJay Buddhabhatti enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq)
616e82cd8cSTejas Patel {
620ec6c313SJay Buddhabhatti 	enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN;
630ec6c313SJay Buddhabhatti 
646e82cd8cSTejas Patel 	assert(irq <= IRQ_MAX);
650ec6c313SJay Buddhabhatti 
660ec6c313SJay Buddhabhatti 	switch (irq) {
670ec6c313SJay Buddhabhatti 	case 13:
680ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_GPIO;
690ec6c313SJay Buddhabhatti 		break;
700ec6c313SJay Buddhabhatti 	case 14:
710ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_I2C_0;
720ec6c313SJay Buddhabhatti 		break;
730ec6c313SJay Buddhabhatti 	case 15:
740ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_I2C_1;
750ec6c313SJay Buddhabhatti 		break;
760ec6c313SJay Buddhabhatti 	case 16:
770ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SPI_0;
780ec6c313SJay Buddhabhatti 		break;
790ec6c313SJay Buddhabhatti 	case 17:
800ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SPI_1;
810ec6c313SJay Buddhabhatti 		break;
820ec6c313SJay Buddhabhatti 	case 18:
830ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_UART_0;
840ec6c313SJay Buddhabhatti 		break;
850ec6c313SJay Buddhabhatti 	case 19:
860ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_UART_1;
870ec6c313SJay Buddhabhatti 		break;
880ec6c313SJay Buddhabhatti 	case 20:
890ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_CAN_FD_0;
900ec6c313SJay Buddhabhatti 		break;
910ec6c313SJay Buddhabhatti 	case 21:
920ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_CAN_FD_1;
930ec6c313SJay Buddhabhatti 		break;
940ec6c313SJay Buddhabhatti 	case 22:
950ec6c313SJay Buddhabhatti 	case 23:
960ec6c313SJay Buddhabhatti 	case 24:
970ec6c313SJay Buddhabhatti 	case 25:
980ec6c313SJay Buddhabhatti 	case 26:
990ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_USB_0;
1000ec6c313SJay Buddhabhatti 		break;
1010ec6c313SJay Buddhabhatti 	case 37:
1020ec6c313SJay Buddhabhatti 	case 38:
1030ec6c313SJay Buddhabhatti 	case 39:
1040ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_0;
1050ec6c313SJay Buddhabhatti 		break;
1060ec6c313SJay Buddhabhatti 	case 40:
1070ec6c313SJay Buddhabhatti 	case 41:
1080ec6c313SJay Buddhabhatti 	case 42:
1090ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_1;
1100ec6c313SJay Buddhabhatti 		break;
1110ec6c313SJay Buddhabhatti 	case 43:
1120ec6c313SJay Buddhabhatti 	case 44:
1130ec6c313SJay Buddhabhatti 	case 45:
1140ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_2;
1150ec6c313SJay Buddhabhatti 		break;
1160ec6c313SJay Buddhabhatti 	case 46:
1170ec6c313SJay Buddhabhatti 	case 47:
1180ec6c313SJay Buddhabhatti 	case 48:
1190ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_3;
1200ec6c313SJay Buddhabhatti 		break;
1210ec6c313SJay Buddhabhatti 	case 56:
1220ec6c313SJay Buddhabhatti 	case 57:
1230ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_GEM_0;
1240ec6c313SJay Buddhabhatti 		break;
12506b9c4c8SJay Buddhabhatti 	case 58:
12606b9c4c8SJay Buddhabhatti 	case 59:
12706b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_GEM_1;
12806b9c4c8SJay Buddhabhatti 		break;
12906b9c4c8SJay Buddhabhatti 	case 60:
13006b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_0;
13106b9c4c8SJay Buddhabhatti 		break;
13206b9c4c8SJay Buddhabhatti 	case 61:
13306b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_1;
13406b9c4c8SJay Buddhabhatti 		break;
13506b9c4c8SJay Buddhabhatti 	case 62:
13606b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_2;
13706b9c4c8SJay Buddhabhatti 		break;
13806b9c4c8SJay Buddhabhatti 	case 63:
13906b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_3;
14006b9c4c8SJay Buddhabhatti 		break;
14106b9c4c8SJay Buddhabhatti 	case 64:
14206b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_4;
14306b9c4c8SJay Buddhabhatti 		break;
14406b9c4c8SJay Buddhabhatti 	case 65:
14506b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_5;
14606b9c4c8SJay Buddhabhatti 		break;
14706b9c4c8SJay Buddhabhatti 	case 66:
14806b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_6;
14906b9c4c8SJay Buddhabhatti 		break;
15006b9c4c8SJay Buddhabhatti 	case 67:
15106b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_ADMA_7;
15206b9c4c8SJay Buddhabhatti 		break;
15306b9c4c8SJay Buddhabhatti 	case 74:
15406b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_USB_0;
15506b9c4c8SJay Buddhabhatti 		break;
15606b9c4c8SJay Buddhabhatti 	case 126:
15706b9c4c8SJay Buddhabhatti 	case 127:
15806b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SDIO_0;
15906b9c4c8SJay Buddhabhatti 		break;
16006b9c4c8SJay Buddhabhatti 	case 128:
16106b9c4c8SJay Buddhabhatti 	case 129:
16206b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SDIO_1;
16306b9c4c8SJay Buddhabhatti 		break;
16406b9c4c8SJay Buddhabhatti 	case 142:
16506b9c4c8SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_RTC;
16606b9c4c8SJay Buddhabhatti 		break;
1670ec6c313SJay Buddhabhatti 	default:
1680ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_MIN;
1690ec6c313SJay Buddhabhatti 		break;
1700ec6c313SJay Buddhabhatti 	}
1710ec6c313SJay Buddhabhatti 
1720ec6c313SJay Buddhabhatti 	return dev_idx;
1736e82cd8cSTejas Patel }
1746e82cd8cSTejas Patel 
1756e82cd8cSTejas Patel /**
176*de7ed953SPrasad Kummari  * pm_client_suspend() - Client-specific suspend actions.
177*de7ed953SPrasad Kummari  * @proc: processor which need to suspend.
178*de7ed953SPrasad Kummari  * @state: desired suspend state.
179fbb32695STejas Patel  *
180fbb32695STejas Patel  * This function should contain any PU-specific actions
181fbb32695STejas Patel  * required prior to sending suspend request to PMU
182fbb32695STejas Patel  * Actions taken depend on the state system is suspending to.
183*de7ed953SPrasad Kummari  *
184fbb32695STejas Patel  */
185912b7a6fSVenkatesh Yadav Abbarapu void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
186fbb32695STejas Patel {
187fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
188fbb32695STejas Patel 
18941567195SAbhyuday Godhasara 	if (state == PM_STATE_SUSPEND_TO_RAM) {
1905d1c211eSAbhyuday Godhasara 		pm_client_set_wakeup_sources((uint32_t)proc->node_id);
19141567195SAbhyuday Godhasara 	}
1926e82cd8cSTejas Patel 
193fbb32695STejas Patel 	/* Set powerdown request */
194fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
195775bf1bbSAbhyuday Godhasara 		      (uint32_t)proc->pwrdn_mask);
196fbb32695STejas Patel 
197fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
198fbb32695STejas Patel }
199fbb32695STejas Patel 
200fbb32695STejas Patel /**
201*de7ed953SPrasad Kummari  * pm_client_abort_suspend() - Client-specific abort-suspend actions.
202fbb32695STejas Patel  *
203fbb32695STejas Patel  * This function should contain any PU-specific actions
204*de7ed953SPrasad Kummari  * required for aborting a prior suspend request.
205*de7ed953SPrasad Kummari  *
206fbb32695STejas Patel  */
207fbb32695STejas Patel void pm_client_abort_suspend(void)
208fbb32695STejas Patel {
209fbb32695STejas Patel 	/* Enable interrupts at processor level (for current cpu) */
210fbb32695STejas Patel 	gicv3_cpuif_enable(plat_my_core_pos());
211fbb32695STejas Patel 
212fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
213fbb32695STejas Patel 
214fbb32695STejas Patel 	/* Clear powerdown request */
215fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
216775bf1bbSAbhyuday Godhasara 		      ~((uint32_t)primary_proc->pwrdn_mask));
217fbb32695STejas Patel 
218fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
219fbb32695STejas Patel }
220fbb32695STejas Patel 
221fbb32695STejas Patel /**
222*de7ed953SPrasad Kummari  * pm_get_cpuid() - get the local cpu ID for a global node ID.
223*de7ed953SPrasad Kummari  * @nid: node id of the processor.
22425b1a910STejas Patel  *
225*de7ed953SPrasad Kummari  * Return: the cpu ID (starting from 0) for the subsystem.
226*de7ed953SPrasad Kummari  *
22725b1a910STejas Patel  */
228912b7a6fSVenkatesh Yadav Abbarapu static uint32_t pm_get_cpuid(uint32_t nid)
22925b1a910STejas Patel {
2305d1c211eSAbhyuday Godhasara 	for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
23141567195SAbhyuday Godhasara 		if (pm_procs_all[i].node_id == nid) {
23225b1a910STejas Patel 			return i;
23325b1a910STejas Patel 		}
23441567195SAbhyuday Godhasara 	}
23525b1a910STejas Patel 	return UNDEFINED_CPUID;
23625b1a910STejas Patel }
23725b1a910STejas Patel 
23825b1a910STejas Patel /**
239*de7ed953SPrasad Kummari  * pm_client_wakeup() - Client-specific wakeup actions.
240*de7ed953SPrasad Kummari  * @proc: Processor which need to wakeup.
24125b1a910STejas Patel  *
24225b1a910STejas Patel  * This function should contain any PU-specific actions
243*de7ed953SPrasad Kummari  * required for waking up another APU core.
244*de7ed953SPrasad Kummari  *
24525b1a910STejas Patel  */
24625b1a910STejas Patel void pm_client_wakeup(const struct pm_proc *proc)
24725b1a910STejas Patel {
248912b7a6fSVenkatesh Yadav Abbarapu 	uint32_t cpuid = pm_get_cpuid(proc->node_id);
24925b1a910STejas Patel 
25041567195SAbhyuday Godhasara 	if (cpuid == UNDEFINED_CPUID) {
25125b1a910STejas Patel 		return;
25241567195SAbhyuday Godhasara 	}
25325b1a910STejas Patel 
25425b1a910STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
25525b1a910STejas Patel 
25625b1a910STejas Patel 	/* clear powerdown bit for affected cpu */
25725b1a910STejas Patel 	uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
25825b1a910STejas Patel 	val &= ~(proc->pwrdn_mask);
25925b1a910STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, val);
26025b1a910STejas Patel 
26125b1a910STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
26225b1a910STejas Patel }
26325b1a910STejas Patel 
26425b1a910STejas Patel /**
265*de7ed953SPrasad Kummari  * pm_get_proc() - returns pointer to the proc structure.
266*de7ed953SPrasad Kummari  * @cpuid: id of the cpu whose proc struct pointer should be returned.
267fbb32695STejas Patel  *
268*de7ed953SPrasad Kummari  * Return: pointer to a proc structure if proc is found, otherwise NULL.
269*de7ed953SPrasad Kummari  *
270fbb32695STejas Patel  */
271912b7a6fSVenkatesh Yadav Abbarapu const struct pm_proc *pm_get_proc(uint32_t cpuid)
272fbb32695STejas Patel {
27341567195SAbhyuday Godhasara 	if (cpuid < ARRAY_SIZE(pm_procs_all)) {
274fbb32695STejas Patel 		return &pm_procs_all[cpuid];
27541567195SAbhyuday Godhasara 	}
276fbb32695STejas Patel 
277fbb32695STejas Patel 	return NULL;
278fbb32695STejas Patel }
279