blob: d61788dc32e77abe0a699dbc62de63c2c1ce53c0 [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 = {
32 .local_ipi_id = IPI_ID_APU,
33 .remote_ipi_id = IPI_ID_PMC,
34 .buffer_base = IPI_BUFFER_APU_BASE,
35};
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/* Interrupt to PM node index map */
54static enum pm_device_node_idx irq_node_map[IRQ_MAX + 1] = {
55 [13] = XPM_NODEIDX_DEV_GPIO,
56 [14] = XPM_NODEIDX_DEV_I2C_0,
57 [15] = XPM_NODEIDX_DEV_I2C_1,
58 [16] = XPM_NODEIDX_DEV_SPI_0,
59 [17] = XPM_NODEIDX_DEV_SPI_1,
60 [18] = XPM_NODEIDX_DEV_UART_0,
61 [19] = XPM_NODEIDX_DEV_UART_1,
62 [20] = XPM_NODEIDX_DEV_CAN_FD_0,
63 [21] = XPM_NODEIDX_DEV_CAN_FD_1,
64 [22] = XPM_NODEIDX_DEV_USB_0,
65 [23] = XPM_NODEIDX_DEV_USB_0,
66 [24] = XPM_NODEIDX_DEV_USB_0,
67 [25] = XPM_NODEIDX_DEV_USB_0,
68 [26] = XPM_NODEIDX_DEV_USB_0,
69 [37] = XPM_NODEIDX_DEV_TTC_0,
70 [38] = XPM_NODEIDX_DEV_TTC_0,
71 [39] = XPM_NODEIDX_DEV_TTC_0,
72 [40] = XPM_NODEIDX_DEV_TTC_1,
73 [41] = XPM_NODEIDX_DEV_TTC_1,
74 [42] = XPM_NODEIDX_DEV_TTC_1,
75 [43] = XPM_NODEIDX_DEV_TTC_2,
76 [44] = XPM_NODEIDX_DEV_TTC_2,
77 [45] = XPM_NODEIDX_DEV_TTC_2,
78 [46] = XPM_NODEIDX_DEV_TTC_3,
79 [47] = XPM_NODEIDX_DEV_TTC_3,
80 [48] = XPM_NODEIDX_DEV_TTC_3,
81 [56] = XPM_NODEIDX_DEV_GEM_0,
82 [57] = XPM_NODEIDX_DEV_GEM_0,
83 [58] = XPM_NODEIDX_DEV_GEM_1,
84 [59] = XPM_NODEIDX_DEV_GEM_1,
85 [60] = XPM_NODEIDX_DEV_ADMA_0,
86 [61] = XPM_NODEIDX_DEV_ADMA_1,
87 [62] = XPM_NODEIDX_DEV_ADMA_2,
88 [63] = XPM_NODEIDX_DEV_ADMA_3,
89 [64] = XPM_NODEIDX_DEV_ADMA_4,
90 [65] = XPM_NODEIDX_DEV_ADMA_5,
91 [66] = XPM_NODEIDX_DEV_ADMA_6,
92 [67] = XPM_NODEIDX_DEV_ADMA_7,
93 [74] = XPM_NODEIDX_DEV_USB_0,
94 [126] = XPM_NODEIDX_DEV_SDIO_0,
95 [127] = XPM_NODEIDX_DEV_SDIO_0,
96 [128] = XPM_NODEIDX_DEV_SDIO_1,
97 [129] = XPM_NODEIDX_DEV_SDIO_1,
98 [142] = XPM_NODEIDX_DEV_RTC,
99};
100
101/**
102 * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number
103 * @irq: Interrupt number
104 *
105 * Return: PM node index corresponding to the specified interrupt
106 */
Jay Buddhabhattia63b3542023-02-28 02:22:02 -0800107enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq)
Tejas Patelfcb7c162019-02-27 18:44:56 +0530108{
109 assert(irq <= IRQ_MAX);
110 return irq_node_map[irq];
111}
112
113/**
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800114 * pm_client_suspend() - Client-specific suspend actions
115 *
116 * This function should contain any PU-specific actions
117 * required prior to sending suspend request to PMU
118 * Actions taken depend on the state system is suspending to.
119 */
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +0530120void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800121{
122 bakery_lock_get(&pm_client_secure_lock);
123
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700124 if (state == PM_STATE_SUSPEND_TO_RAM) {
Abhyuday Godhasaraedc38ae2021-08-04 23:58:46 -0700125 pm_client_set_wakeup_sources((uint32_t)proc->node_id);
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700126 }
Tejas Patelfcb7c162019-02-27 18:44:56 +0530127
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800128 /* Set powerdown request */
129 mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
Abhyuday Godhasara44877942021-08-05 02:59:26 -0700130 (uint32_t)proc->pwrdn_mask);
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800131
132 bakery_lock_release(&pm_client_secure_lock);
133}
134
135/**
136 * pm_client_abort_suspend() - Client-specific abort-suspend actions
137 *
138 * This function should contain any PU-specific actions
139 * required for aborting a prior suspend request
140 */
141void pm_client_abort_suspend(void)
142{
143 /* Enable interrupts at processor level (for current cpu) */
144 gicv3_cpuif_enable(plat_my_core_pos());
145
146 bakery_lock_get(&pm_client_secure_lock);
147
148 /* Clear powerdown request */
149 mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
Abhyuday Godhasara44877942021-08-05 02:59:26 -0700150 ~((uint32_t)primary_proc->pwrdn_mask));
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800151
152 bakery_lock_release(&pm_client_secure_lock);
153}
154
155/**
Tejas Patel7029dd82019-02-27 18:44:54 +0530156 * pm_get_cpuid() - get the local cpu ID for a global node ID
157 * @nid: node id of the processor
158 *
159 * Return: the cpu ID (starting from 0) for the subsystem
160 */
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +0530161static uint32_t pm_get_cpuid(uint32_t nid)
Tejas Patel7029dd82019-02-27 18:44:54 +0530162{
Abhyuday Godhasaraedc38ae2021-08-04 23:58:46 -0700163 for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700164 if (pm_procs_all[i].node_id == nid) {
Tejas Patel7029dd82019-02-27 18:44:54 +0530165 return i;
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700166 }
Tejas Patel7029dd82019-02-27 18:44:54 +0530167 }
168 return UNDEFINED_CPUID;
169}
170
171/**
172 * pm_client_wakeup() - Client-specific wakeup actions
173 *
174 * This function should contain any PU-specific actions
175 * required for waking up another APU core
176 */
177void pm_client_wakeup(const struct pm_proc *proc)
178{
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +0530179 uint32_t cpuid = pm_get_cpuid(proc->node_id);
Tejas Patel7029dd82019-02-27 18:44:54 +0530180
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700181 if (cpuid == UNDEFINED_CPUID) {
Tejas Patel7029dd82019-02-27 18:44:54 +0530182 return;
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700183 }
Tejas Patel7029dd82019-02-27 18:44:54 +0530184
185 bakery_lock_get(&pm_client_secure_lock);
186
187 /* clear powerdown bit for affected cpu */
188 uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
189 val &= ~(proc->pwrdn_mask);
190 mmio_write_32(FPD_APU_PWRCTL, val);
191
192 bakery_lock_release(&pm_client_secure_lock);
193}
194
195/**
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800196 * pm_get_proc() - returns pointer to the proc structure
197 * @cpuid: id of the cpu whose proc struct pointer should be returned
198 *
199 * Return: pointer to a proc structure if proc is found, otherwise NULL
200 */
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +0530201const struct pm_proc *pm_get_proc(uint32_t cpuid)
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800202{
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700203 if (cpuid < ARRAY_SIZE(pm_procs_all)) {
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800204 return &pm_procs_all[cpuid];
Abhyuday Godhasaraddc46622021-08-05 03:14:17 -0700205 }
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800206
207 return NULL;
208}