blob: c1a9f0dc1a989f96aa235bc8955631d7b2e36e47 [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.
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +00003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/*
Andre Przywarae1cc1302020-03-25 15:50:38 +00008 * Driver for GIC-500 and GIC-600 specific features. This driver only
9 * overrides APIs that are different to those generic ones in GICv3
10 * driver.
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000011 *
Alexei Fedorov88fba672019-07-31 13:24:22 +010012 * GIC-600 supports independently power-gating redistributor interface.
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000013 */
14
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000015#include <assert.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000016
17#include <arch_helpers.h>
18#include <drivers/arm/gicv3.h>
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000019
20#include "gicv3_private.h"
21
Alexei Fedorov88fba672019-07-31 13:24:22 +010022/* GIC-600 specific register offsets */
Andre Przywarae1cc1302020-03-25 15:50:38 +000023#define GICR_PWRR 0x24
24#define IIDR_MODEL_ARM_GIC_600 0x0200043b
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000025
26/* GICR_PWRR fields */
27#define PWRR_RDPD_SHIFT 0
Alexei Fedorov88fba672019-07-31 13:24:22 +010028#define PWRR_RDAG_SHIFT 1
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000029#define PWRR_RDGPD_SHIFT 2
30#define PWRR_RDGPO_SHIFT 3
31
Alexei Fedorov88fba672019-07-31 13:24:22 +010032#define PWRR_RDPD (1 << PWRR_RDPD_SHIFT)
33#define PWRR_RDAG (1 << PWRR_RDAG_SHIFT)
Douglas Raillard1bd2d742017-08-03 15:59:49 +010034#define PWRR_RDGPD (1 << PWRR_RDGPD_SHIFT)
35#define PWRR_RDGPO (1 << PWRR_RDGPO_SHIFT)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000036
Alexei Fedorov88fba672019-07-31 13:24:22 +010037/*
38 * Values to write to GICR_PWRR register to power redistributor
39 * for operating through the core (GICR_PWRR.RDAG = 0)
40 */
Douglas Raillard1bd2d742017-08-03 15:59:49 +010041#define PWRR_ON (0 << PWRR_RDPD_SHIFT)
42#define PWRR_OFF (1 << PWRR_RDPD_SHIFT)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000043
Andre Przywarae1cc1302020-03-25 15:50:38 +000044#if GICV3_SUPPORT_GIC600
45
Alexei Fedorov88fba672019-07-31 13:24:22 +010046/* GIC-600 specific accessor functions */
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000047static void gicr_write_pwrr(uintptr_t base, unsigned int val)
48{
Douglas Raillard1bd2d742017-08-03 15:59:49 +010049 mmio_write_32(base + GICR_PWRR, val);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000050}
51
52static uint32_t gicr_read_pwrr(uintptr_t base)
53{
Douglas Raillard1bd2d742017-08-03 15:59:49 +010054 return mmio_read_32(base + GICR_PWRR);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000055}
56
Alexei Fedorov88fba672019-07-31 13:24:22 +010057static void gicr_wait_group_not_in_transit(uintptr_t base)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000058{
Alexei Fedorov88fba672019-07-31 13:24:22 +010059 /* Check group not transitioning: RDGPD == RDGPO */
60 while (((gicr_read_pwrr(base) & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) !=
61 ((gicr_read_pwrr(base) & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT))
62 ;
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000063}
64
65static void gic600_pwr_on(uintptr_t base)
66{
Alexei Fedorov88fba672019-07-31 13:24:22 +010067 do { /* Wait until group not transitioning */
68 gicr_wait_group_not_in_transit(base);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000069
Alexei Fedorov88fba672019-07-31 13:24:22 +010070 /* Power on redistributor */
71 gicr_write_pwrr(base, PWRR_ON);
72
73 /*
74 * Wait until the power on state is reflected.
75 * If RDPD == 0 then powered on.
76 */
77 } while ((gicr_read_pwrr(base) & PWRR_RDPD) != PWRR_ON);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000078}
79
80static void gic600_pwr_off(uintptr_t base)
81{
Alexei Fedorov88fba672019-07-31 13:24:22 +010082 /* Wait until group not transitioning */
83 gicr_wait_group_not_in_transit(base);
84
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000085 /* Power off redistributor */
86 gicr_write_pwrr(base, PWRR_OFF);
87
88 /*
89 * If this is the last man, turning this redistributor frame off will
Alexei Fedorov88fba672019-07-31 13:24:22 +010090 * result in the group itself being powered off and RDGPD = 1.
91 * In that case, wait as long as it's in transition, or has aborted
92 * the transition altogether for any reason.
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000093 */
Alexei Fedorov88fba672019-07-31 13:24:22 +010094 if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0) {
95 /* Wait until group not transitioning */
96 gicr_wait_group_not_in_transit(base);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +000097 }
98}
99
Andre Przywarae1cc1302020-03-25 15:50:38 +0000100static uintptr_t get_gicr_base(unsigned int proc_num)
101{
102 uintptr_t gicr_base;
103
104 assert(gicv3_driver_data);
105 assert(proc_num < gicv3_driver_data->rdistif_num);
106 assert(gicv3_driver_data->rdistif_base_addrs);
107
108 gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
109 assert(gicr_base);
110
111 return gicr_base;
112}
113
114static bool gicv3_is_gic600(uintptr_t gicr_base)
115{
116 uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR);
117
118 return (reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600;
119}
120
121#endif
122
Soby Mathew327548c2017-07-13 15:19:51 +0100123void gicv3_distif_pre_save(unsigned int proc_num)
124{
125 arm_gicv3_distif_pre_save(proc_num);
126}
127
128void gicv3_distif_post_restore(unsigned int proc_num)
129{
130 arm_gicv3_distif_post_restore(proc_num);
131}
132
Andre Przywarae1cc1302020-03-25 15:50:38 +0000133
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000134/*
Andre Przywarae1cc1302020-03-25 15:50:38 +0000135 * Power off GIC-600 redistributor (if configured and detected)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000136 */
137void gicv3_rdistif_off(unsigned int proc_num)
138{
Andre Przywarae1cc1302020-03-25 15:50:38 +0000139#if GICV3_SUPPORT_GIC600
140 uintptr_t gicr_base = get_gicr_base(proc_num);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000141
142 /* Attempt to power redistributor off */
Andre Przywarae1cc1302020-03-25 15:50:38 +0000143 if (gicv3_is_gic600(gicr_base)) {
144 gic600_pwr_off(gicr_base);
145 }
146#endif
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000147}
148
149/*
Andre Przywarae1cc1302020-03-25 15:50:38 +0000150 * Power on GIC-600 redistributor (if configured and detected)
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000151 */
152void gicv3_rdistif_on(unsigned int proc_num)
153{
Andre Przywarae1cc1302020-03-25 15:50:38 +0000154#if GICV3_SUPPORT_GIC600
155 uintptr_t gicr_base = get_gicr_base(proc_num);
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000156
157 /* Power redistributor on */
Andre Przywarae1cc1302020-03-25 15:50:38 +0000158 if (gicv3_is_gic600(gicr_base)) {
159 gic600_pwr_on(gicr_base);
160 }
161#endif
Jeenu Viswambharand7a901e2016-12-06 16:15:22 +0000162}