xref: /rk3399_ARM-atf/plat/xilinx/versal/pm_service/pm_client.c (revision 068b0bc6e39f1fc18f9450619942c711f860a7e2)
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 = {
32*068b0bc6SMichal Simek 	.local_ipi_id = IPI_LOCAL_ID,
33*068b0bc6SMichal 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 /**
546e82cd8cSTejas Patel  * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number
556e82cd8cSTejas Patel  * @irq:	Interrupt number
566e82cd8cSTejas Patel  *
576e82cd8cSTejas Patel  * Return:	PM node index corresponding to the specified interrupt
586e82cd8cSTejas Patel  */
593ae28aa4SJay Buddhabhatti enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq)
606e82cd8cSTejas Patel {
610ec6c313SJay Buddhabhatti 	enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN;
620ec6c313SJay Buddhabhatti 
636e82cd8cSTejas Patel 	assert(irq <= IRQ_MAX);
640ec6c313SJay Buddhabhatti 
650ec6c313SJay Buddhabhatti 	switch (irq) {
660ec6c313SJay Buddhabhatti 	case 13:
670ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_GPIO;
680ec6c313SJay Buddhabhatti 		break;
690ec6c313SJay Buddhabhatti 	case 14:
700ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_I2C_0;
710ec6c313SJay Buddhabhatti 		break;
720ec6c313SJay Buddhabhatti 	case 15:
730ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_I2C_1;
740ec6c313SJay Buddhabhatti 		break;
750ec6c313SJay Buddhabhatti 	case 16:
760ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SPI_0;
770ec6c313SJay Buddhabhatti 		break;
780ec6c313SJay Buddhabhatti 	case 17:
790ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_SPI_1;
800ec6c313SJay Buddhabhatti 		break;
810ec6c313SJay Buddhabhatti 	case 18:
820ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_UART_0;
830ec6c313SJay Buddhabhatti 		break;
840ec6c313SJay Buddhabhatti 	case 19:
850ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_UART_1;
860ec6c313SJay Buddhabhatti 		break;
870ec6c313SJay Buddhabhatti 	case 20:
880ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_CAN_FD_0;
890ec6c313SJay Buddhabhatti 		break;
900ec6c313SJay Buddhabhatti 	case 21:
910ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_CAN_FD_1;
920ec6c313SJay Buddhabhatti 		break;
930ec6c313SJay Buddhabhatti 	case 22:
940ec6c313SJay Buddhabhatti 	case 23:
950ec6c313SJay Buddhabhatti 	case 24:
960ec6c313SJay Buddhabhatti 	case 25:
970ec6c313SJay Buddhabhatti 	case 26:
980ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_USB_0;
990ec6c313SJay Buddhabhatti 		break;
1000ec6c313SJay Buddhabhatti 	case 37:
1010ec6c313SJay Buddhabhatti 	case 38:
1020ec6c313SJay Buddhabhatti 	case 39:
1030ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_0;
1040ec6c313SJay Buddhabhatti 		break;
1050ec6c313SJay Buddhabhatti 	case 40:
1060ec6c313SJay Buddhabhatti 	case 41:
1070ec6c313SJay Buddhabhatti 	case 42:
1080ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_1;
1090ec6c313SJay Buddhabhatti 		break;
1100ec6c313SJay Buddhabhatti 	case 43:
1110ec6c313SJay Buddhabhatti 	case 44:
1120ec6c313SJay Buddhabhatti 	case 45:
1130ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_2;
1140ec6c313SJay Buddhabhatti 		break;
1150ec6c313SJay Buddhabhatti 	case 46:
1160ec6c313SJay Buddhabhatti 	case 47:
1170ec6c313SJay Buddhabhatti 	case 48:
1180ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_TTC_3;
1190ec6c313SJay Buddhabhatti 		break;
1200ec6c313SJay Buddhabhatti 	case 56:
1210ec6c313SJay Buddhabhatti 	case 57:
1220ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_GEM_0;
1230ec6c313SJay Buddhabhatti 		break;
1240ec6c313SJay Buddhabhatti 	default:
1250ec6c313SJay Buddhabhatti 		dev_idx = XPM_NODEIDX_DEV_MIN;
1260ec6c313SJay Buddhabhatti 		break;
1270ec6c313SJay Buddhabhatti 	}
1280ec6c313SJay Buddhabhatti 
1290ec6c313SJay Buddhabhatti 	return dev_idx;
1306e82cd8cSTejas Patel }
1316e82cd8cSTejas Patel 
1326e82cd8cSTejas Patel /**
133fbb32695STejas Patel  * pm_client_suspend() - Client-specific suspend actions
134fbb32695STejas Patel  *
135fbb32695STejas Patel  * This function should contain any PU-specific actions
136fbb32695STejas Patel  * required prior to sending suspend request to PMU
137fbb32695STejas Patel  * Actions taken depend on the state system is suspending to.
138fbb32695STejas Patel  */
139912b7a6fSVenkatesh Yadav Abbarapu void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
140fbb32695STejas Patel {
141fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
142fbb32695STejas Patel 
14341567195SAbhyuday Godhasara 	if (state == PM_STATE_SUSPEND_TO_RAM) {
1445d1c211eSAbhyuday Godhasara 		pm_client_set_wakeup_sources((uint32_t)proc->node_id);
14541567195SAbhyuday Godhasara 	}
1466e82cd8cSTejas Patel 
147fbb32695STejas Patel 	/* Set powerdown request */
148fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
149775bf1bbSAbhyuday Godhasara 		      (uint32_t)proc->pwrdn_mask);
150fbb32695STejas Patel 
151fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
152fbb32695STejas Patel }
153fbb32695STejas Patel 
154fbb32695STejas Patel /**
155fbb32695STejas Patel  * pm_client_abort_suspend() - Client-specific abort-suspend actions
156fbb32695STejas Patel  *
157fbb32695STejas Patel  * This function should contain any PU-specific actions
158fbb32695STejas Patel  * required for aborting a prior suspend request
159fbb32695STejas Patel  */
160fbb32695STejas Patel void pm_client_abort_suspend(void)
161fbb32695STejas Patel {
162fbb32695STejas Patel 	/* Enable interrupts at processor level (for current cpu) */
163fbb32695STejas Patel 	gicv3_cpuif_enable(plat_my_core_pos());
164fbb32695STejas Patel 
165fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
166fbb32695STejas Patel 
167fbb32695STejas Patel 	/* Clear powerdown request */
168fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
169775bf1bbSAbhyuday Godhasara 		      ~((uint32_t)primary_proc->pwrdn_mask));
170fbb32695STejas Patel 
171fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
172fbb32695STejas Patel }
173fbb32695STejas Patel 
174fbb32695STejas Patel /**
17525b1a910STejas Patel  * pm_get_cpuid() - get the local cpu ID for a global node ID
17625b1a910STejas Patel  * @nid:	node id of the processor
17725b1a910STejas Patel  *
17825b1a910STejas Patel  * Return: the cpu ID (starting from 0) for the subsystem
17925b1a910STejas Patel  */
180912b7a6fSVenkatesh Yadav Abbarapu static uint32_t pm_get_cpuid(uint32_t nid)
18125b1a910STejas Patel {
1825d1c211eSAbhyuday Godhasara 	for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
18341567195SAbhyuday Godhasara 		if (pm_procs_all[i].node_id == nid) {
18425b1a910STejas Patel 			return i;
18525b1a910STejas Patel 		}
18641567195SAbhyuday Godhasara 	}
18725b1a910STejas Patel 	return UNDEFINED_CPUID;
18825b1a910STejas Patel }
18925b1a910STejas Patel 
19025b1a910STejas Patel /**
19125b1a910STejas Patel  * pm_client_wakeup() - Client-specific wakeup actions
19225b1a910STejas Patel  *
19325b1a910STejas Patel  * This function should contain any PU-specific actions
19425b1a910STejas Patel  * required for waking up another APU core
19525b1a910STejas Patel  */
19625b1a910STejas Patel void pm_client_wakeup(const struct pm_proc *proc)
19725b1a910STejas Patel {
198912b7a6fSVenkatesh Yadav Abbarapu 	uint32_t cpuid = pm_get_cpuid(proc->node_id);
19925b1a910STejas Patel 
20041567195SAbhyuday Godhasara 	if (cpuid == UNDEFINED_CPUID) {
20125b1a910STejas Patel 		return;
20241567195SAbhyuday Godhasara 	}
20325b1a910STejas Patel 
20425b1a910STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
20525b1a910STejas Patel 
20625b1a910STejas Patel 	/* clear powerdown bit for affected cpu */
20725b1a910STejas Patel 	uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
20825b1a910STejas Patel 	val &= ~(proc->pwrdn_mask);
20925b1a910STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, val);
21025b1a910STejas Patel 
21125b1a910STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
21225b1a910STejas Patel }
21325b1a910STejas Patel 
21425b1a910STejas Patel /**
215fbb32695STejas Patel  * pm_get_proc() - returns pointer to the proc structure
216fbb32695STejas Patel  * @cpuid:	id of the cpu whose proc struct pointer should be returned
217fbb32695STejas Patel  *
218fbb32695STejas Patel  * Return: pointer to a proc structure if proc is found, otherwise NULL
219fbb32695STejas Patel  */
220912b7a6fSVenkatesh Yadav Abbarapu const struct pm_proc *pm_get_proc(uint32_t cpuid)
221fbb32695STejas Patel {
22241567195SAbhyuday Godhasara 	if (cpuid < ARRAY_SIZE(pm_procs_all)) {
223fbb32695STejas Patel 		return &pm_procs_all[cpuid];
22441567195SAbhyuday Godhasara 	}
225fbb32695STejas Patel 
226fbb32695STejas Patel 	return NULL;
227fbb32695STejas Patel }
228