xref: /rk3399_ARM-atf/plat/xilinx/versal/pm_service/pm_client.c (revision 3ae28aa44ed1f46bfa71c5aed3a6e67b17aed422)
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 = {
32c73a90e5STejas Patel 	.local_ipi_id = IPI_ID_APU,
33c73a90e5STejas Patel 	.remote_ipi_id = IPI_ID_PMC,
34c73a90e5STejas Patel 	.buffer_base = IPI_BUFFER_APU_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 /* Interrupt to PM node index map */
546e82cd8cSTejas Patel static enum pm_device_node_idx irq_node_map[IRQ_MAX + 1] = {
556e82cd8cSTejas Patel 	[13] = XPM_NODEIDX_DEV_GPIO,
566e82cd8cSTejas Patel 	[14] = XPM_NODEIDX_DEV_I2C_0,
576e82cd8cSTejas Patel 	[15] = XPM_NODEIDX_DEV_I2C_1,
586e82cd8cSTejas Patel 	[16] = XPM_NODEIDX_DEV_SPI_0,
596e82cd8cSTejas Patel 	[17] = XPM_NODEIDX_DEV_SPI_1,
606e82cd8cSTejas Patel 	[18] = XPM_NODEIDX_DEV_UART_0,
616e82cd8cSTejas Patel 	[19] = XPM_NODEIDX_DEV_UART_1,
626e82cd8cSTejas Patel 	[20] = XPM_NODEIDX_DEV_CAN_FD_0,
636e82cd8cSTejas Patel 	[21] = XPM_NODEIDX_DEV_CAN_FD_1,
646e82cd8cSTejas Patel 	[22] = XPM_NODEIDX_DEV_USB_0,
656e82cd8cSTejas Patel 	[23] = XPM_NODEIDX_DEV_USB_0,
666e82cd8cSTejas Patel 	[24] = XPM_NODEIDX_DEV_USB_0,
676e82cd8cSTejas Patel 	[25] = XPM_NODEIDX_DEV_USB_0,
686e82cd8cSTejas Patel 	[26] = XPM_NODEIDX_DEV_USB_0,
696e82cd8cSTejas Patel 	[37] = XPM_NODEIDX_DEV_TTC_0,
706e82cd8cSTejas Patel 	[38] = XPM_NODEIDX_DEV_TTC_0,
716e82cd8cSTejas Patel 	[39] = XPM_NODEIDX_DEV_TTC_0,
726e82cd8cSTejas Patel 	[40] = XPM_NODEIDX_DEV_TTC_1,
736e82cd8cSTejas Patel 	[41] = XPM_NODEIDX_DEV_TTC_1,
746e82cd8cSTejas Patel 	[42] = XPM_NODEIDX_DEV_TTC_1,
756e82cd8cSTejas Patel 	[43] = XPM_NODEIDX_DEV_TTC_2,
766e82cd8cSTejas Patel 	[44] = XPM_NODEIDX_DEV_TTC_2,
776e82cd8cSTejas Patel 	[45] = XPM_NODEIDX_DEV_TTC_2,
786e82cd8cSTejas Patel 	[46] = XPM_NODEIDX_DEV_TTC_3,
796e82cd8cSTejas Patel 	[47] = XPM_NODEIDX_DEV_TTC_3,
806e82cd8cSTejas Patel 	[48] = XPM_NODEIDX_DEV_TTC_3,
816e82cd8cSTejas Patel 	[56] = XPM_NODEIDX_DEV_GEM_0,
826e82cd8cSTejas Patel 	[57] = XPM_NODEIDX_DEV_GEM_0,
836e82cd8cSTejas Patel 	[58] = XPM_NODEIDX_DEV_GEM_1,
846e82cd8cSTejas Patel 	[59] = XPM_NODEIDX_DEV_GEM_1,
856e82cd8cSTejas Patel 	[60] = XPM_NODEIDX_DEV_ADMA_0,
866e82cd8cSTejas Patel 	[61] = XPM_NODEIDX_DEV_ADMA_1,
876e82cd8cSTejas Patel 	[62] = XPM_NODEIDX_DEV_ADMA_2,
886e82cd8cSTejas Patel 	[63] = XPM_NODEIDX_DEV_ADMA_3,
896e82cd8cSTejas Patel 	[64] = XPM_NODEIDX_DEV_ADMA_4,
906e82cd8cSTejas Patel 	[65] = XPM_NODEIDX_DEV_ADMA_5,
916e82cd8cSTejas Patel 	[66] = XPM_NODEIDX_DEV_ADMA_6,
926e82cd8cSTejas Patel 	[67] = XPM_NODEIDX_DEV_ADMA_7,
936e82cd8cSTejas Patel 	[74] = XPM_NODEIDX_DEV_USB_0,
946e82cd8cSTejas Patel 	[126] = XPM_NODEIDX_DEV_SDIO_0,
956e82cd8cSTejas Patel 	[127] = XPM_NODEIDX_DEV_SDIO_0,
966e82cd8cSTejas Patel 	[128] = XPM_NODEIDX_DEV_SDIO_1,
976e82cd8cSTejas Patel 	[129] = XPM_NODEIDX_DEV_SDIO_1,
986e82cd8cSTejas Patel 	[142] = XPM_NODEIDX_DEV_RTC,
996e82cd8cSTejas Patel };
1006e82cd8cSTejas Patel 
1016e82cd8cSTejas Patel /**
1026e82cd8cSTejas Patel  * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number
1036e82cd8cSTejas Patel  * @irq:	Interrupt number
1046e82cd8cSTejas Patel  *
1056e82cd8cSTejas Patel  * Return:	PM node index corresponding to the specified interrupt
1066e82cd8cSTejas Patel  */
107*3ae28aa4SJay Buddhabhatti enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq)
1086e82cd8cSTejas Patel {
1096e82cd8cSTejas Patel 	assert(irq <= IRQ_MAX);
1106e82cd8cSTejas Patel 	return irq_node_map[irq];
1116e82cd8cSTejas Patel }
1126e82cd8cSTejas Patel 
1136e82cd8cSTejas Patel /**
114fbb32695STejas Patel  * pm_client_suspend() - Client-specific suspend actions
115fbb32695STejas Patel  *
116fbb32695STejas Patel  * This function should contain any PU-specific actions
117fbb32695STejas Patel  * required prior to sending suspend request to PMU
118fbb32695STejas Patel  * Actions taken depend on the state system is suspending to.
119fbb32695STejas Patel  */
120912b7a6fSVenkatesh Yadav Abbarapu void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
121fbb32695STejas Patel {
122fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
123fbb32695STejas Patel 
12441567195SAbhyuday Godhasara 	if (state == PM_STATE_SUSPEND_TO_RAM) {
1255d1c211eSAbhyuday Godhasara 		pm_client_set_wakeup_sources((uint32_t)proc->node_id);
12641567195SAbhyuday Godhasara 	}
1276e82cd8cSTejas Patel 
128fbb32695STejas Patel 	/* Set powerdown request */
129fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
130775bf1bbSAbhyuday Godhasara 		      (uint32_t)proc->pwrdn_mask);
131fbb32695STejas Patel 
132fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
133fbb32695STejas Patel }
134fbb32695STejas Patel 
135fbb32695STejas Patel /**
136fbb32695STejas Patel  * pm_client_abort_suspend() - Client-specific abort-suspend actions
137fbb32695STejas Patel  *
138fbb32695STejas Patel  * This function should contain any PU-specific actions
139fbb32695STejas Patel  * required for aborting a prior suspend request
140fbb32695STejas Patel  */
141fbb32695STejas Patel void pm_client_abort_suspend(void)
142fbb32695STejas Patel {
143fbb32695STejas Patel 	/* Enable interrupts at processor level (for current cpu) */
144fbb32695STejas Patel 	gicv3_cpuif_enable(plat_my_core_pos());
145fbb32695STejas Patel 
146fbb32695STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
147fbb32695STejas Patel 
148fbb32695STejas Patel 	/* Clear powerdown request */
149fbb32695STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
150775bf1bbSAbhyuday Godhasara 		      ~((uint32_t)primary_proc->pwrdn_mask));
151fbb32695STejas Patel 
152fbb32695STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
153fbb32695STejas Patel }
154fbb32695STejas Patel 
155fbb32695STejas Patel /**
15625b1a910STejas Patel  * pm_get_cpuid() - get the local cpu ID for a global node ID
15725b1a910STejas Patel  * @nid:	node id of the processor
15825b1a910STejas Patel  *
15925b1a910STejas Patel  * Return: the cpu ID (starting from 0) for the subsystem
16025b1a910STejas Patel  */
161912b7a6fSVenkatesh Yadav Abbarapu static uint32_t pm_get_cpuid(uint32_t nid)
16225b1a910STejas Patel {
1635d1c211eSAbhyuday Godhasara 	for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
16441567195SAbhyuday Godhasara 		if (pm_procs_all[i].node_id == nid) {
16525b1a910STejas Patel 			return i;
16625b1a910STejas Patel 		}
16741567195SAbhyuday Godhasara 	}
16825b1a910STejas Patel 	return UNDEFINED_CPUID;
16925b1a910STejas Patel }
17025b1a910STejas Patel 
17125b1a910STejas Patel /**
17225b1a910STejas Patel  * pm_client_wakeup() - Client-specific wakeup actions
17325b1a910STejas Patel  *
17425b1a910STejas Patel  * This function should contain any PU-specific actions
17525b1a910STejas Patel  * required for waking up another APU core
17625b1a910STejas Patel  */
17725b1a910STejas Patel void pm_client_wakeup(const struct pm_proc *proc)
17825b1a910STejas Patel {
179912b7a6fSVenkatesh Yadav Abbarapu 	uint32_t cpuid = pm_get_cpuid(proc->node_id);
18025b1a910STejas Patel 
18141567195SAbhyuday Godhasara 	if (cpuid == UNDEFINED_CPUID) {
18225b1a910STejas Patel 		return;
18341567195SAbhyuday Godhasara 	}
18425b1a910STejas Patel 
18525b1a910STejas Patel 	bakery_lock_get(&pm_client_secure_lock);
18625b1a910STejas Patel 
18725b1a910STejas Patel 	/* clear powerdown bit for affected cpu */
18825b1a910STejas Patel 	uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
18925b1a910STejas Patel 	val &= ~(proc->pwrdn_mask);
19025b1a910STejas Patel 	mmio_write_32(FPD_APU_PWRCTL, val);
19125b1a910STejas Patel 
19225b1a910STejas Patel 	bakery_lock_release(&pm_client_secure_lock);
19325b1a910STejas Patel }
19425b1a910STejas Patel 
19525b1a910STejas Patel /**
196fbb32695STejas Patel  * pm_get_proc() - returns pointer to the proc structure
197fbb32695STejas Patel  * @cpuid:	id of the cpu whose proc struct pointer should be returned
198fbb32695STejas Patel  *
199fbb32695STejas Patel  * Return: pointer to a proc structure if proc is found, otherwise NULL
200fbb32695STejas Patel  */
201912b7a6fSVenkatesh Yadav Abbarapu const struct pm_proc *pm_get_proc(uint32_t cpuid)
202fbb32695STejas Patel {
20341567195SAbhyuday Godhasara 	if (cpuid < ARRAY_SIZE(pm_procs_all)) {
204fbb32695STejas Patel 		return &pm_procs_all[cpuid];
20541567195SAbhyuday Godhasara 	}
206fbb32695STejas Patel 
207fbb32695STejas Patel 	return NULL;
208fbb32695STejas Patel }
209