blob: aaef485ff786b089b44be2fb28a9b8d1f018ad41 [file] [log] [blame]
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +00001/*
Alexei Fedorov06d29cf2020-07-29 15:16:36 +01002 * Copyright (c) 2017-2020, 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>
Andre Przywaradaf89a72021-08-24 10:02:52 +010019#include <drivers/arm/arm_gicv3_common.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000020#include <drivers/arm/gicv3.h>
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000021
22#include "gicv3_private.h"
23
Alexei Fedorov88fba672019-07-31 13:24:22 +010024/* GIC-600 specific register offsets */
Alexei Fedorov06d29cf2020-07-29 15:16:36 +010025#define GICR_PWRR 0x24U
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000026
27/* GICR_PWRR fields */
Varun Wadekar75594062020-07-05 13:12:28 -070028#define PWRR_RDPD_SHIFT 0
29#define PWRR_RDAG_SHIFT 1
30#define PWRR_RDGPD_SHIFT 2
31#define PWRR_RDGPO_SHIFT 3
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000032
Alexei Fedorov06d29cf2020-07-29 15:16:36 +010033#define PWRR_RDPD (1U << PWRR_RDPD_SHIFT)
34#define PWRR_RDAG (1U << PWRR_RDAG_SHIFT)
35#define PWRR_RDGPD (1U << PWRR_RDGPD_SHIFT)
36#define PWRR_RDGPO (1U << PWRR_RDGPO_SHIFT)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000037
Alexei Fedorov88fba672019-07-31 13:24:22 +010038/*
39 * Values to write to GICR_PWRR register to power redistributor
40 * for operating through the core (GICR_PWRR.RDAG = 0)
41 */
Alexei Fedorov06d29cf2020-07-29 15:16:36 +010042#define PWRR_ON (0U << PWRR_RDPD_SHIFT)
43#define PWRR_OFF (1U << PWRR_RDPD_SHIFT)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000044
Andre Przywarae1cc1302020-03-25 15:50:38 +000045#if GICV3_SUPPORT_GIC600
46
Andre Przywarab6c24ce2021-07-20 19:20:07 +010047/* GIC-600/700 specific accessor functions */
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000048static void gicr_write_pwrr(uintptr_t base, unsigned int val)
49{
Douglas Raillard1bd2d742017-08-03 15:59:49 +010050 mmio_write_32(base + GICR_PWRR, val);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000051}
52
53static uint32_t gicr_read_pwrr(uintptr_t base)
54{
Douglas Raillard1bd2d742017-08-03 15:59:49 +010055 return mmio_read_32(base + GICR_PWRR);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000056}
57
Alexei Fedorov88fba672019-07-31 13:24:22 +010058static void gicr_wait_group_not_in_transit(uintptr_t base)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000059{
Alexei Fedorov06d29cf2020-07-29 15:16:36 +010060 uint32_t pwrr;
61
62 do {
63 pwrr = gicr_read_pwrr(base);
64
Alexei Fedorov88fba672019-07-31 13:24:22 +010065 /* Check group not transitioning: RDGPD == RDGPO */
Alexei Fedorov06d29cf2020-07-29 15:16:36 +010066 } while (((pwrr & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) !=
67 ((pwrr & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT));
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000068}
69
70static void gic600_pwr_on(uintptr_t base)
71{
Alexei Fedorov88fba672019-07-31 13:24:22 +010072 do { /* Wait until group not transitioning */
73 gicr_wait_group_not_in_transit(base);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000074
Alexei Fedorov88fba672019-07-31 13:24:22 +010075 /* Power on redistributor */
76 gicr_write_pwrr(base, PWRR_ON);
77
78 /*
79 * Wait until the power on state is reflected.
80 * If RDPD == 0 then powered on.
81 */
82 } while ((gicr_read_pwrr(base) & PWRR_RDPD) != PWRR_ON);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000083}
84
85static void gic600_pwr_off(uintptr_t base)
86{
Alexei Fedorov88fba672019-07-31 13:24:22 +010087 /* Wait until group not transitioning */
88 gicr_wait_group_not_in_transit(base);
89
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000090 /* Power off redistributor */
91 gicr_write_pwrr(base, PWRR_OFF);
92
93 /*
94 * If this is the last man, turning this redistributor frame off will
Alexei Fedorov88fba672019-07-31 13:24:22 +010095 * result in the group itself being powered off and RDGPD = 1.
96 * In that case, wait as long as it's in transition, or has aborted
97 * the transition altogether for any reason.
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000098 */
Alexei Fedorov06d29cf2020-07-29 15:16:36 +010099 if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0U) {
Alexei Fedorov88fba672019-07-31 13:24:22 +0100100 /* Wait until group not transitioning */
101 gicr_wait_group_not_in_transit(base);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000102 }
103}
104
Andre Przywarae1cc1302020-03-25 15:50:38 +0000105static uintptr_t get_gicr_base(unsigned int proc_num)
106{
107 uintptr_t gicr_base;
108
Alexei Fedorov06d29cf2020-07-29 15:16:36 +0100109 assert(gicv3_driver_data != NULL);
Andre Przywarae1cc1302020-03-25 15:50:38 +0000110 assert(proc_num < gicv3_driver_data->rdistif_num);
Alexei Fedorov06d29cf2020-07-29 15:16:36 +0100111 assert(gicv3_driver_data->rdistif_base_addrs != NULL);
Andre Przywarae1cc1302020-03-25 15:50:38 +0000112
113 gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
Alexei Fedorov06d29cf2020-07-29 15:16:36 +0100114 assert(gicr_base != 0UL);
Andre Przywarae1cc1302020-03-25 15:50:38 +0000115
116 return gicr_base;
117}
118
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100119static bool gicv3_redists_need_power_mgmt(uintptr_t gicr_base)
Andre Przywarae1cc1302020-03-25 15:50:38 +0000120{
121 uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR);
122
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100123 /*
Andre Przywarab6c24ce2021-07-20 19:20:07 +0100124 * The Arm GIC-600 and GIC-700 models have their redistributors
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100125 * powered down at reset.
126 */
Varun Wadekar75594062020-07-05 13:12:28 -0700127 return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) ||
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100128 ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) ||
Andre Przywarab6c24ce2021-07-20 19:20:07 +0100129 ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700));
Andre Przywarae1cc1302020-03-25 15:50:38 +0000130}
131
Alexei Fedorov06d29cf2020-07-29 15:16:36 +0100132#endif /* GICV3_SUPPORT_GIC600 */
Andre Przywarae1cc1302020-03-25 15:50:38 +0000133
Soby Mathew327548c2017-07-13 15:19:51 +0100134void gicv3_distif_pre_save(unsigned int proc_num)
135{
136 arm_gicv3_distif_pre_save(proc_num);
137}
138
139void gicv3_distif_post_restore(unsigned int proc_num)
140{
141 arm_gicv3_distif_post_restore(proc_num);
142}
143
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000144/*
Andre Przywarae1cc1302020-03-25 15:50:38 +0000145 * Power off GIC-600 redistributor (if configured and detected)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000146 */
147void gicv3_rdistif_off(unsigned int proc_num)
148{
Andre Przywarae1cc1302020-03-25 15:50:38 +0000149#if GICV3_SUPPORT_GIC600
150 uintptr_t gicr_base = get_gicr_base(proc_num);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000151
152 /* Attempt to power redistributor off */
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100153 if (gicv3_redists_need_power_mgmt(gicr_base)) {
Andre Przywarae1cc1302020-03-25 15:50:38 +0000154 gic600_pwr_off(gicr_base);
155 }
156#endif
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000157}
158
159/*
Andre Przywarae1cc1302020-03-25 15:50:38 +0000160 * Power on GIC-600 redistributor (if configured and detected)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000161 */
162void gicv3_rdistif_on(unsigned int proc_num)
163{
Andre Przywarae1cc1302020-03-25 15:50:38 +0000164#if GICV3_SUPPORT_GIC600
165 uintptr_t gicr_base = get_gicr_base(proc_num);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000166
167 /* Power redistributor on */
Andre Przywara19b2d4e2020-06-26 10:30:33 +0100168 if (gicv3_redists_need_power_mgmt(gicr_base)) {
Andre Przywarae1cc1302020-03-25 15:50:38 +0000169 gic600_pwr_on(gicr_base);
170 }
171#endif
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000172}