blob: af5263daa49d354cd74f78982fd590f760768352 [file] [log] [blame]
Tejas Patel354fe572018-12-14 00:55:37 -08001/*
Tanmay Shahb145e122022-03-23 12:43:45 -07002 * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
Jay Buddhabhatti6a44ad02023-02-28 01:23:04 -08003 * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
Tejas Patel354fe572018-12-14 00:55:37 -08004 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8/*
9 * APU specific definition of processors in the subsystem as well as functions
10 * for getting information about and changing state of the APU.
11 */
12
Tejas Patelfcb7c162019-02-27 18:44:56 +053013#include <assert.h>
Tejas Patel354fe572018-12-14 00:55:37 -080014#include <plat_ipi.h>
15#include <platform_def.h>
16#include <versal_def.h>
17#include <lib/bakery_lock.h>
Tejas Patelfe0e10a2019-12-08 23:29:44 -080018#include <lib/mmio.h>
Tejas Patelfcb7c162019-02-27 18:44:56 +053019#include <lib/utils.h>
Tejas Patelfe0e10a2019-12-08 23:29:44 -080020#include <drivers/arm/gicv3.h>
Tejas Patelfcb7c162019-02-27 18:44:56 +053021#include <drivers/arm/gic_common.h>
Tejas Patelfe0e10a2019-12-08 23:29:44 -080022#include <plat/common/platform.h>
Tejas Patelfcb7c162019-02-27 18:44:56 +053023#include "pm_api_sys.h"
Tejas Patel354fe572018-12-14 00:55:37 -080024#include "pm_client.h"
Tanmay Shahb145e122022-03-23 12:43:45 -070025#include "pm_defs.h"
Tejas Patel354fe572018-12-14 00:55:37 -080026
Tejas Patel7029dd82019-02-27 18:44:54 +053027#define UNDEFINED_CPUID (~0)
28
Tejas Patel354fe572018-12-14 00:55:37 -080029DEFINE_BAKERY_LOCK(pm_client_secure_lock);
30
31static const struct pm_ipi apu_ipi = {
Michal Simek3a63f052023-04-25 14:21:20 +020032 .local_ipi_id = IPI_LOCAL_ID,
33 .remote_ipi_id = IPI_REMOTE_ID,
Michal Simek9a8da502023-04-25 14:04:02 +020034 .buffer_base = IPI_BUFFER_LOCAL_BASE,
Tejas Patel354fe572018-12-14 00:55:37 -080035};
36
37/* Order in pm_procs_all array must match cpu ids */
38static const struct pm_proc pm_procs_all[] = {
39 {
40 .node_id = XPM_DEVID_ACPU_0,
41 .ipi = &apu_ipi,
Tejas Patelfe0e10a2019-12-08 23:29:44 -080042 .pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
Tejas Patel354fe572018-12-14 00:55:37 -080043 },
44 {
45 .node_id = XPM_DEVID_ACPU_1,
46 .ipi = &apu_ipi,
Tejas Patelfe0e10a2019-12-08 23:29:44 -080047 .pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
Tejas Patel354fe572018-12-14 00:55:37 -080048 }
49};
50
51const struct pm_proc *primary_proc = &pm_procs_all[0];
Tejas Patelfe0e10a2019-12-08 23:29:44 -080052
Tejas Patelfcb7c162019-02-27 18:44:56 +053053/**
54 * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number
55 * @irq: Interrupt number
56 *
57 * Return: PM node index corresponding to the specified interrupt
58 */
Jay Buddhabhattia63b3542023-02-28 02:22:02 -080059enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq)
Tejas Patelfcb7c162019-02-27 18:44:56 +053060{
Jay Buddhabhattic06a2712022-12-22 22:27:01 -080061 enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN;
62
Tejas Patelfcb7c162019-02-27 18:44:56 +053063 assert(irq <= IRQ_MAX);
Jay Buddhabhattic06a2712022-12-22 22:27:01 -080064
65 switch (irq) {
66 case 13:
67 dev_idx = XPM_NODEIDX_DEV_GPIO;
68 break;
69 case 14:
70 dev_idx = XPM_NODEIDX_DEV_I2C_0;
71 break;
72 case 15:
73 dev_idx = XPM_NODEIDX_DEV_I2C_1;
74 break;
75 case 16:
76 dev_idx = XPM_NODEIDX_DEV_SPI_0;
77 break;
78 case 17:
79 dev_idx = XPM_NODEIDX_DEV_SPI_1;
80 break;
81 case 18:
82 dev_idx = XPM_NODEIDX_DEV_UART_0;
83 break;
84 case 19:
85 dev_idx = XPM_NODEIDX_DEV_UART_1;
86 break;
87 case 20:
88 dev_idx = XPM_NODEIDX_DEV_CAN_FD_0;
89 break;
90 case 21:
91 dev_idx = XPM_NODEIDX_DEV_CAN_FD_1;
92 break;
93 case 22:
94 case 23:
95 case 24:
96 case 25:
97 case 26:
98 dev_idx = XPM_NODEIDX_DEV_USB_0;
99 break;
100 case 37:
101 case 38:
102 case 39:
103 dev_idx = XPM_NODEIDX_DEV_TTC_0;
104 break;
105 case 40:
106 case 41:
107 case 42:
108 dev_idx = XPM_NODEIDX_DEV_TTC_1;
109 break;
110 case 43:
111 case 44:
112 case 45:
113 dev_idx = XPM_NODEIDX_DEV_TTC_2;
114 break;
115 case 46:
116 case 47:
117 case 48:
118 dev_idx = XPM_NODEIDX_DEV_TTC_3;
119 break;
120 case 56:
121 case 57:
122 dev_idx = XPM_NODEIDX_DEV_GEM_0;
123 break;
Jay Buddhabhattib31b9202023-06-12 04:36:38 -0700124 case 58:
125 case 59:
126 dev_idx = XPM_NODEIDX_DEV_GEM_1;
127 break;
128 case 60:
129 dev_idx = XPM_NODEIDX_DEV_ADMA_0;
130 break;
131 case 61:
132 dev_idx = XPM_NODEIDX_DEV_ADMA_1;
133 break;
134 case 62:
135 dev_idx = XPM_NODEIDX_DEV_ADMA_2;
136 break;
137 case 63:
138 dev_idx = XPM_NODEIDX_DEV_ADMA_3;
139 break;
140 case 64:
141 dev_idx = XPM_NODEIDX_DEV_ADMA_4;
142 break;
143 case 65:
144 dev_idx = XPM_NODEIDX_DEV_ADMA_5;
145 break;
146 case 66:
147 dev_idx = XPM_NODEIDX_DEV_ADMA_6;
148 break;
149 case 67:
150 dev_idx = XPM_NODEIDX_DEV_ADMA_7;
151 break;
152 case 74:
153 dev_idx = XPM_NODEIDX_DEV_USB_0;
154 break;
155 case 126:
156 case 127:
157 dev_idx = XPM_NODEIDX_DEV_SDIO_0;
158 break;
159 case 128:
160 case 129:
161 dev_idx = XPM_NODEIDX_DEV_SDIO_1;
162 break;
163 case 142:
164 dev_idx = XPM_NODEIDX_DEV_RTC;
165 break;
Jay Buddhabhattic06a2712022-12-22 22:27:01 -0800166 default:
167 dev_idx = XPM_NODEIDX_DEV_MIN;
168 break;
169 }
170
171 return dev_idx;
Tejas Patelfcb7c162019-02-27 18:44:56 +0530172}
173
174/**
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800175 * pm_client_suspend() - Client-specific suspend actions
176 *
177 * This function should contain any PU-specific actions
178 * required prior to sending suspend request to PMU
179 * Actions taken depend on the state system is suspending to.
180 */
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +0530181void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800182{
183 bakery_lock_get(&pm_client_secure_lock);
184
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700185 if (state == PM_STATE_SUSPEND_TO_RAM) {
Abhyuday Godhasaraedc38ae2021-08-04 23:58:46 -0700186 pm_client_set_wakeup_sources((uint32_t)proc->node_id);
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700187 }
Tejas Patelfcb7c162019-02-27 18:44:56 +0530188
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800189 /* Set powerdown request */
190 mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
Abhyuday Godhasara44877942021-08-05 02:59:26 -0700191 (uint32_t)proc->pwrdn_mask);
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800192
193 bakery_lock_release(&pm_client_secure_lock);
194}
195
196/**
197 * pm_client_abort_suspend() - Client-specific abort-suspend actions
198 *
199 * This function should contain any PU-specific actions
200 * required for aborting a prior suspend request
201 */
202void pm_client_abort_suspend(void)
203{
204 /* Enable interrupts at processor level (for current cpu) */
205 gicv3_cpuif_enable(plat_my_core_pos());
206
207 bakery_lock_get(&pm_client_secure_lock);
208
209 /* Clear powerdown request */
210 mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
Abhyuday Godhasara44877942021-08-05 02:59:26 -0700211 ~((uint32_t)primary_proc->pwrdn_mask));
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800212
213 bakery_lock_release(&pm_client_secure_lock);
214}
215
216/**
Tejas Patel7029dd82019-02-27 18:44:54 +0530217 * pm_get_cpuid() - get the local cpu ID for a global node ID
218 * @nid: node id of the processor
219 *
220 * Return: the cpu ID (starting from 0) for the subsystem
221 */
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +0530222static uint32_t pm_get_cpuid(uint32_t nid)
Tejas Patel7029dd82019-02-27 18:44:54 +0530223{
Abhyuday Godhasaraedc38ae2021-08-04 23:58:46 -0700224 for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700225 if (pm_procs_all[i].node_id == nid) {
Tejas Patel7029dd82019-02-27 18:44:54 +0530226 return i;
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700227 }
Tejas Patel7029dd82019-02-27 18:44:54 +0530228 }
229 return UNDEFINED_CPUID;
230}
231
232/**
233 * pm_client_wakeup() - Client-specific wakeup actions
234 *
235 * This function should contain any PU-specific actions
236 * required for waking up another APU core
237 */
238void pm_client_wakeup(const struct pm_proc *proc)
239{
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +0530240 uint32_t cpuid = pm_get_cpuid(proc->node_id);
Tejas Patel7029dd82019-02-27 18:44:54 +0530241
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700242 if (cpuid == UNDEFINED_CPUID) {
Tejas Patel7029dd82019-02-27 18:44:54 +0530243 return;
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700244 }
Tejas Patel7029dd82019-02-27 18:44:54 +0530245
246 bakery_lock_get(&pm_client_secure_lock);
247
248 /* clear powerdown bit for affected cpu */
249 uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
250 val &= ~(proc->pwrdn_mask);
251 mmio_write_32(FPD_APU_PWRCTL, val);
252
253 bakery_lock_release(&pm_client_secure_lock);
254}
255
256/**
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800257 * pm_get_proc() - returns pointer to the proc structure
258 * @cpuid: id of the cpu whose proc struct pointer should be returned
259 *
260 * Return: pointer to a proc structure if proc is found, otherwise NULL
261 */
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +0530262const struct pm_proc *pm_get_proc(uint32_t cpuid)
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800263{
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700264 if (cpuid < ARRAY_SIZE(pm_procs_all)) {
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800265 return &pm_procs_all[cpuid];
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700266 }
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800267
268 return NULL;
269}