blob: cc97174519b714a3333b72f28198e4638ece5678 [file] [log] [blame]
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +00001/*
Alexei Fedorov88fba672019-07-31 13:24:22 +01002 * Copyright (c) 2017-2019, 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>
19#include <drivers/arm/gicv3.h>
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000020
21#include "gicv3_private.h"
22
Alexei Fedorov88fba672019-07-31 13:24:22 +010023/* GIC-600 specific register offsets */
Varun Wadekar75594062020-07-05 13:12:28 -070024#define GICR_PWRR 0x24
25#define IIDR_MODEL_ARM_GIC_600 (0x0200043b)
26#define IIDR_MODEL_ARM_GIC_600AE (0x0300043b)
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
Varun Wadekar75594062020-07-05 13:12:28 -070034#define PWRR_RDPD (1 << PWRR_RDPD_SHIFT)
35#define PWRR_RDAG (1 << PWRR_RDAG_SHIFT)
36#define PWRR_RDGPD (1 << PWRR_RDGPD_SHIFT)
37#define PWRR_RDGPO (1 << 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 */
Varun Wadekar75594062020-07-05 13:12:28 -070043#define PWRR_ON (0 << PWRR_RDPD_SHIFT)
44#define PWRR_OFF (1 << PWRR_RDPD_SHIFT)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000045
Andre Przywarae1cc1302020-03-25 15:50:38 +000046#if GICV3_SUPPORT_GIC600
47
Alexei Fedorov88fba672019-07-31 13:24:22 +010048/* GIC-600 specific accessor functions */
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000049static void gicr_write_pwrr(uintptr_t base, unsigned int val)
50{
Douglas Raillard1bd2d742017-08-03 15:59:49 +010051 mmio_write_32(base + GICR_PWRR, val);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000052}
53
54static uint32_t gicr_read_pwrr(uintptr_t base)
55{
Douglas Raillard1bd2d742017-08-03 15:59:49 +010056 return mmio_read_32(base + GICR_PWRR);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000057}
58
Alexei Fedorov88fba672019-07-31 13:24:22 +010059static void gicr_wait_group_not_in_transit(uintptr_t base)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000060{
Alexei Fedorov88fba672019-07-31 13:24:22 +010061 /* Check group not transitioning: RDGPD == RDGPO */
62 while (((gicr_read_pwrr(base) & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) !=
63 ((gicr_read_pwrr(base) & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT))
64 ;
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000065}
66
67static void gic600_pwr_on(uintptr_t base)
68{
Alexei Fedorov88fba672019-07-31 13:24:22 +010069 do { /* Wait until group not transitioning */
70 gicr_wait_group_not_in_transit(base);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000071
Alexei Fedorov88fba672019-07-31 13:24:22 +010072 /* Power on redistributor */
73 gicr_write_pwrr(base, PWRR_ON);
74
75 /*
76 * Wait until the power on state is reflected.
77 * If RDPD == 0 then powered on.
78 */
79 } while ((gicr_read_pwrr(base) & PWRR_RDPD) != PWRR_ON);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000080}
81
82static void gic600_pwr_off(uintptr_t base)
83{
Alexei Fedorov88fba672019-07-31 13:24:22 +010084 /* Wait until group not transitioning */
85 gicr_wait_group_not_in_transit(base);
86
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000087 /* Power off redistributor */
88 gicr_write_pwrr(base, PWRR_OFF);
89
90 /*
91 * If this is the last man, turning this redistributor frame off will
Alexei Fedorov88fba672019-07-31 13:24:22 +010092 * result in the group itself being powered off and RDGPD = 1.
93 * In that case, wait as long as it's in transition, or has aborted
94 * the transition altogether for any reason.
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000095 */
Alexei Fedorov88fba672019-07-31 13:24:22 +010096 if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0) {
97 /* Wait until group not transitioning */
98 gicr_wait_group_not_in_transit(base);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000099 }
100}
101
Andre Przywarae1cc1302020-03-25 15:50:38 +0000102static uintptr_t get_gicr_base(unsigned int proc_num)
103{
104 uintptr_t gicr_base;
105
106 assert(gicv3_driver_data);
107 assert(proc_num < gicv3_driver_data->rdistif_num);
108 assert(gicv3_driver_data->rdistif_base_addrs);
109
110 gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
111 assert(gicr_base);
112
113 return gicr_base;
114}
115
116static bool gicv3_is_gic600(uintptr_t gicr_base)
117{
118 uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR);
119
Varun Wadekar75594062020-07-05 13:12:28 -0700120 return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) ||
121 ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE));
Andre Przywarae1cc1302020-03-25 15:50:38 +0000122}
123
124#endif
125
Soby Mathew327548c2017-07-13 15:19:51 +0100126void gicv3_distif_pre_save(unsigned int proc_num)
127{
128 arm_gicv3_distif_pre_save(proc_num);
129}
130
131void gicv3_distif_post_restore(unsigned int proc_num)
132{
133 arm_gicv3_distif_post_restore(proc_num);
134}
135
Andre Przywarae1cc1302020-03-25 15:50:38 +0000136
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000137/*
Andre Przywarae1cc1302020-03-25 15:50:38 +0000138 * Power off GIC-600 redistributor (if configured and detected)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000139 */
140void gicv3_rdistif_off(unsigned int proc_num)
141{
Andre Przywarae1cc1302020-03-25 15:50:38 +0000142#if GICV3_SUPPORT_GIC600
143 uintptr_t gicr_base = get_gicr_base(proc_num);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000144
145 /* Attempt to power redistributor off */
Andre Przywarae1cc1302020-03-25 15:50:38 +0000146 if (gicv3_is_gic600(gicr_base)) {
147 gic600_pwr_off(gicr_base);
148 }
149#endif
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000150}
151
152/*
Andre Przywarae1cc1302020-03-25 15:50:38 +0000153 * Power on GIC-600 redistributor (if configured and detected)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000154 */
155void gicv3_rdistif_on(unsigned int proc_num)
156{
Andre Przywarae1cc1302020-03-25 15:50:38 +0000157#if GICV3_SUPPORT_GIC600
158 uintptr_t gicr_base = get_gicr_base(proc_num);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000159
160 /* Power redistributor on */
Andre Przywarae1cc1302020-03-25 15:50:38 +0000161 if (gicv3_is_gic600(gicr_base)) {
162 gic600_pwr_on(gicr_base);
163 }
164#endif
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000165}