blob: 83ef32f05633b48b2b9627893480b5c6ad80c7e6 [file] [log] [blame]
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +00001/*
Manish V Badarkhe173c2962022-05-09 21:55:19 +01002 * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved.
Varun Wadekar75594062020-07-05 13:12:28 -07003 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +00004 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8/*
Andre Przywarae1cc1302020-03-25 15:50:38 +00009 * Driver for GIC-500 and GIC-600 specific features. This driver only
10 * overrides APIs that are different to those generic ones in GICv3
11 * driver.
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000012 *
Alexei Fedorov88fba672019-07-31 13:24:22 +010013 * GIC-600 supports independently power-gating redistributor interface.
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000014 */
15
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000016#include <assert.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000017
18#include <arch_helpers.h>
Claus Pedersen785e66c2022-09-12 22:42:58 +000019#include <common/debug.h>
Andre Przywaradaf89a72021-08-24 10:02:52 +010020#include <drivers/arm/arm_gicv3_common.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000021#include <drivers/arm/gicv3.h>
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000022
23#include "gicv3_private.h"
24
Alexei Fedorov88fba672019-07-31 13:24:22 +010025/* GIC-600 specific register offsets */
Alexei Fedorov06d29cf2020-07-29 15:16:36 +010026#define GICR_PWRR 0x24U
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000027
28/* GICR_PWRR fields */
Varun Wadekar75594062020-07-05 13:12:28 -070029#define PWRR_RDPD_SHIFT 0
30#define PWRR_RDAG_SHIFT 1
31#define PWRR_RDGPD_SHIFT 2
32#define PWRR_RDGPO_SHIFT 3
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000033
Alexei Fedorov06d29cf2020-07-29 15:16:36 +010034#define PWRR_RDPD (1U << PWRR_RDPD_SHIFT)
35#define PWRR_RDAG (1U << PWRR_RDAG_SHIFT)
36#define PWRR_RDGPD (1U << PWRR_RDGPD_SHIFT)
37#define PWRR_RDGPO (1U << PWRR_RDGPO_SHIFT)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000038
Alexei Fedorov88fba672019-07-31 13:24:22 +010039/*
40 * Values to write to GICR_PWRR register to power redistributor
41 * for operating through the core (GICR_PWRR.RDAG = 0)
42 */
Alexei Fedorov06d29cf2020-07-29 15:16:36 +010043#define PWRR_ON (0U << PWRR_RDPD_SHIFT)
44#define PWRR_OFF (1U << PWRR_RDPD_SHIFT)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000045
Manish V Badarkhe173c2962022-05-09 21:55:19 +010046static bool gic600_errata_wa_2384374 __unused;
47
Andre Przywarae1cc1302020-03-25 15:50:38 +000048#if GICV3_SUPPORT_GIC600
49
Andre Przywarab6c24ce2021-07-20 19:20:07 +010050/* GIC-600/700 specific accessor functions */
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000051static void gicr_write_pwrr(uintptr_t base, unsigned int val)
52{
Douglas Raillard1bd2d742017-08-03 15:59:49 +010053 mmio_write_32(base + GICR_PWRR, val);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000054}
55
56static uint32_t gicr_read_pwrr(uintptr_t base)
57{
Douglas Raillard1bd2d742017-08-03 15:59:49 +010058 return mmio_read_32(base + GICR_PWRR);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000059}
60
Alexei Fedorov88fba672019-07-31 13:24:22 +010061static void gicr_wait_group_not_in_transit(uintptr_t base)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000062{
Alexei Fedorov06d29cf2020-07-29 15:16:36 +010063 uint32_t pwrr;
64
65 do {
66 pwrr = gicr_read_pwrr(base);
67
Alexei Fedorov88fba672019-07-31 13:24:22 +010068 /* Check group not transitioning: RDGPD == RDGPO */
Alexei Fedorov06d29cf2020-07-29 15:16:36 +010069 } while (((pwrr & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) !=
70 ((pwrr & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT));
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000071}
72
73static void gic600_pwr_on(uintptr_t base)
74{
Alexei Fedorov88fba672019-07-31 13:24:22 +010075 do { /* Wait until group not transitioning */
76 gicr_wait_group_not_in_transit(base);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000077
Alexei Fedorov88fba672019-07-31 13:24:22 +010078 /* Power on redistributor */
79 gicr_write_pwrr(base, PWRR_ON);
80
81 /*
82 * Wait until the power on state is reflected.
83 * If RDPD == 0 then powered on.
84 */
85 } while ((gicr_read_pwrr(base) & PWRR_RDPD) != PWRR_ON);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000086}
87
88static void gic600_pwr_off(uintptr_t base)
89{
Alexei Fedorov88fba672019-07-31 13:24:22 +010090 /* Wait until group not transitioning */
91 gicr_wait_group_not_in_transit(base);
92
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000093 /* Power off redistributor */
94 gicr_write_pwrr(base, PWRR_OFF);
95
96 /*
97 * If this is the last man, turning this redistributor frame off will
Alexei Fedorov88fba672019-07-31 13:24:22 +010098 * result in the group itself being powered off and RDGPD = 1.
99 * In that case, wait as long as it's in transition, or has aborted
100 * the transition altogether for any reason.
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000101 */
Alexei Fedorov06d29cf2020-07-29 15:16:36 +0100102 if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0U) {
Alexei Fedorov88fba672019-07-31 13:24:22 +0100103 /* Wait until group not transitioning */
104 gicr_wait_group_not_in_transit(base);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000105 }
106}
107
Andre Przywarae1cc1302020-03-25 15:50:38 +0000108static uintptr_t get_gicr_base(unsigned int proc_num)
109{
110 uintptr_t gicr_base;
111
Alexei Fedorov06d29cf2020-07-29 15:16:36 +0100112 assert(gicv3_driver_data != NULL);
Andre Przywarae1cc1302020-03-25 15:50:38 +0000113 assert(proc_num < gicv3_driver_data->rdistif_num);
Alexei Fedorov06d29cf2020-07-29 15:16:36 +0100114 assert(gicv3_driver_data->rdistif_base_addrs != NULL);
Andre Przywarae1cc1302020-03-25 15:50:38 +0000115
116 gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
Alexei Fedorov06d29cf2020-07-29 15:16:36 +0100117 assert(gicr_base != 0UL);
Andre Przywarae1cc1302020-03-25 15:50:38 +0000118
119 return gicr_base;
120}
121
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100122static bool gicv3_redists_need_power_mgmt(uintptr_t gicr_base)
Andre Przywarae1cc1302020-03-25 15:50:38 +0000123{
124 uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR);
125
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100126 /*
Andre Przywarab6c24ce2021-07-20 19:20:07 +0100127 * The Arm GIC-600 and GIC-700 models have their redistributors
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100128 * powered down at reset.
129 */
Varun Wadekar75594062020-07-05 13:12:28 -0700130 return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) ||
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100131 ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) ||
Andre Przywarab6c24ce2021-07-20 19:20:07 +0100132 ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700));
Andre Przywarae1cc1302020-03-25 15:50:38 +0000133}
134
Alexei Fedorov06d29cf2020-07-29 15:16:36 +0100135#endif /* GICV3_SUPPORT_GIC600 */
Andre Przywarae1cc1302020-03-25 15:50:38 +0000136
Soby Mathew327548c2017-07-13 15:19:51 +0100137void gicv3_distif_pre_save(unsigned int proc_num)
138{
139 arm_gicv3_distif_pre_save(proc_num);
140}
141
142void gicv3_distif_post_restore(unsigned int proc_num)
143{
144 arm_gicv3_distif_post_restore(proc_num);
145}
146
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000147/*
Andre Przywarae1cc1302020-03-25 15:50:38 +0000148 * Power off GIC-600 redistributor (if configured and detected)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000149 */
150void gicv3_rdistif_off(unsigned int proc_num)
151{
Andre Przywarae1cc1302020-03-25 15:50:38 +0000152#if GICV3_SUPPORT_GIC600
153 uintptr_t gicr_base = get_gicr_base(proc_num);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000154
155 /* Attempt to power redistributor off */
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100156 if (gicv3_redists_need_power_mgmt(gicr_base)) {
Andre Przywarae1cc1302020-03-25 15:50:38 +0000157 gic600_pwr_off(gicr_base);
158 }
159#endif
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000160}
161
162/*
Andre Przywarae1cc1302020-03-25 15:50:38 +0000163 * Power on GIC-600 redistributor (if configured and detected)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000164 */
165void gicv3_rdistif_on(unsigned int proc_num)
166{
Andre Przywarae1cc1302020-03-25 15:50:38 +0000167#if GICV3_SUPPORT_GIC600
168 uintptr_t gicr_base = get_gicr_base(proc_num);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000169
170 /* Power redistributor on */
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100171 if (gicv3_redists_need_power_mgmt(gicr_base)) {
Andre Przywarae1cc1302020-03-25 15:50:38 +0000172 gic600_pwr_on(gicr_base);
173 }
174#endif
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000175}
Manish V Badarkhe173c2962022-05-09 21:55:19 +0100176
177#if GIC600_ERRATA_WA_2384374
178/*******************************************************************************
179 * Apply part 2 of workaround for errata-2384374 as per SDEN:
180 * https://developer.arm.com/documentation/sden892601/latest/
181 ******************************************************************************/
182void gicv3_apply_errata_wa_2384374(uintptr_t gicr_base)
183{
184 if (gic600_errata_wa_2384374) {
185 uint32_t gicr_ctlr_val = gicr_read_ctlr(gicr_base);
186
187 gicr_write_ctlr(gicr_base, gicr_ctlr_val |
188 (GICR_CTLR_DPG0_BIT | GICR_CTLR_DPG1NS_BIT |
189 GICR_CTLR_DPG1S_BIT));
190 gicr_write_ctlr(gicr_base, gicr_ctlr_val &
191 ~(GICR_CTLR_DPG0_BIT | GICR_CTLR_DPG1NS_BIT |
192 GICR_CTLR_DPG1S_BIT));
193 }
194}
195#endif /* GIC600_ERRATA_WA_2384374 */
196
197void gicv3_check_erratas_applies(uintptr_t gicd_base)
198{
199 unsigned int gic_prod_id;
200 uint8_t gic_rev;
201
202 assert(gicd_base != 0UL);
203
204 gicv3_get_component_prodid_rev(gicd_base, &gic_prod_id, &gic_rev);
205
206 /*
207 * This workaround applicable only to GIC600 and GIC600AE products with
208 * revision less than r1p6 and r0p2 respectively.
209 * As per GIC600/GIC600AE specification -
210 * r1p6 = 0x17 => GICD_IIDR[19:12]
211 * r0p2 = 0x04 => GICD_IIDR[19:12]
212 */
213 if ((gic_prod_id == GIC_PRODUCT_ID_GIC600) ||
214 (gic_prod_id == GIC_PRODUCT_ID_GIC600AE)) {
215 if (((gic_prod_id == GIC_PRODUCT_ID_GIC600) &&
216 (gic_rev <= GIC_REV(GIC_VARIANT_R1, GIC_REV_P6))) ||
217 ((gic_prod_id == GIC_PRODUCT_ID_GIC600AE) &&
218 (gic_rev <= GIC_REV(GIC_VARIANT_R0, GIC_REV_P2)))) {
219#if GIC600_ERRATA_WA_2384374
220 gic600_errata_wa_2384374 = true;
221 VERBOSE("%s applies\n",
222 "GIC600/GIC600AE errata workaround 2384374");
223#else
224 WARN("%s missing\n",
225 "GIC600/GIC600AE errata workaround 2384374");
226#endif /* GIC600_ERRATA_WA_2384374 */
227 } else {
228 VERBOSE("%s not applies\n",
229 "GIC600/GIC600AE errata workaround 2384374");
230 }
231 }
232}