blob: 7e76a20edc688887557fccc1ba1d47375bf72350 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
Deepika Bhavnanic249d5e2020-02-06 16:29:45 -06002 * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch.h>
8#include <arch_helpers.h>
9#include <assert.h>
Antonio Nino Diaz09a00ef2019-01-11 13:12:58 +000010#include <drivers/arm/gic_common.h>
11#include <drivers/arm/gic_v3.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020012#include <mmio.h>
13
14/*******************************************************************************
15 * GIC Distributor interface accessors for reading entire registers
16 ******************************************************************************/
17
Marek Bykowskid6514442019-12-17 07:41:43 -060018unsigned int gicd_read_isenabler(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020019{
20 unsigned int n = interrupt_id >> ISENABLER_SHIFT;
21 return mmio_read_32(base + GICD_ISENABLER + (n << 2));
22}
23
Marek Bykowskid6514442019-12-17 07:41:43 -060024unsigned int gicd_read_icenabler(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020025{
26 unsigned int n = interrupt_id >> ICENABLER_SHIFT;
27 return mmio_read_32(base + GICD_ICENABLER + (n << 2));
28}
29
Marek Bykowskid6514442019-12-17 07:41:43 -060030unsigned int gicd_read_ispendr(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020031{
32 unsigned int n = interrupt_id >> ISPENDR_SHIFT;
33 return mmio_read_32(base + GICD_ISPENDR + (n << 2));
34}
35
Marek Bykowskid6514442019-12-17 07:41:43 -060036unsigned int gicd_read_icpendr(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020037{
38 unsigned int n = interrupt_id >> ICPENDR_SHIFT;
39 return mmio_read_32(base + GICD_ICPENDR + (n << 2));
40}
41
Marek Bykowskid6514442019-12-17 07:41:43 -060042unsigned int gicd_read_isactiver(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020043{
44 unsigned int n = interrupt_id >> ISACTIVER_SHIFT;
45 return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
46}
47
Marek Bykowskid6514442019-12-17 07:41:43 -060048unsigned int gicd_read_icactiver(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020049{
50 unsigned int n = interrupt_id >> ICACTIVER_SHIFT;
51 return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
52}
53
Marek Bykowskid6514442019-12-17 07:41:43 -060054unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020055{
56 unsigned int n = interrupt_id >> IPRIORITYR_SHIFT;
57 return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
58}
59
Marek Bykowskid6514442019-12-17 07:41:43 -060060unsigned int gicd_read_icfgr(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020061{
62 unsigned int n = interrupt_id >> ICFGR_SHIFT;
63 return mmio_read_32(base + GICD_ICFGR + (n << 2));
64}
65
66/*******************************************************************************
67 * GIC Distributor interface accessors for writing entire registers
68 ******************************************************************************/
69
Marek Bykowskid6514442019-12-17 07:41:43 -060070void gicd_write_isenabler(uintptr_t base,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020071 unsigned int interrupt_id, unsigned int val)
72{
73 unsigned int n = interrupt_id >> ISENABLER_SHIFT;
74 mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
75}
76
Marek Bykowskid6514442019-12-17 07:41:43 -060077void gicd_write_icenabler(uintptr_t base,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020078 unsigned int interrupt_id, unsigned int val)
79{
80 unsigned int n = interrupt_id >> ICENABLER_SHIFT;
81 mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
82}
83
Marek Bykowskid6514442019-12-17 07:41:43 -060084void gicd_write_ispendr(uintptr_t base,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020085 unsigned int interrupt_id, unsigned int val)
86{
87 unsigned int n = interrupt_id >> ISPENDR_SHIFT;
88 mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
89}
90
Marek Bykowskid6514442019-12-17 07:41:43 -060091void gicd_write_icpendr(uintptr_t base,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020092 unsigned int interrupt_id, unsigned int val)
93{
94 unsigned int n = interrupt_id >> ICPENDR_SHIFT;
95 mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
96}
97
Marek Bykowskid6514442019-12-17 07:41:43 -060098void gicd_write_isactiver(uintptr_t base,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020099 unsigned int interrupt_id, unsigned int val)
100{
101 unsigned int n = interrupt_id >> ISACTIVER_SHIFT;
102 mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
103}
104
Marek Bykowskid6514442019-12-17 07:41:43 -0600105void gicd_write_icactiver(uintptr_t base,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200106 unsigned int interrupt_id, unsigned int val)
107{
108 unsigned int n = interrupt_id >> ICACTIVER_SHIFT;
109 mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
110}
111
Marek Bykowskid6514442019-12-17 07:41:43 -0600112void gicd_write_ipriorityr(uintptr_t base,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200113 unsigned int interrupt_id, unsigned int val)
114{
115 unsigned int n = interrupt_id >> IPRIORITYR_SHIFT;
116 mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
117}
118
Marek Bykowskid6514442019-12-17 07:41:43 -0600119void gicd_write_icfgr(uintptr_t base,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200120 unsigned int interrupt_id, unsigned int val)
121{
122 unsigned int n = interrupt_id >> ICFGR_SHIFT;
123 mmio_write_32(base + GICD_ICFGR + (n << 2), val);
124}
125
126/*******************************************************************************
127 * GIC Distributor interface accessors for individual interrupt manipulation
128 ******************************************************************************/
Marek Bykowskid6514442019-12-17 07:41:43 -0600129unsigned int gicd_get_isenabler(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200130{
131 unsigned int bit_num = interrupt_id & ((1 << ISENABLER_SHIFT) - 1);
132
133 return gicd_read_isenabler(base, interrupt_id) & (1 << bit_num);
134}
135
Marek Bykowskid6514442019-12-17 07:41:43 -0600136void gicd_set_isenabler(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200137{
138 unsigned int bit_num = interrupt_id & ((1 << ISENABLER_SHIFT) - 1);
139
140 gicd_write_isenabler(base, interrupt_id, (1 << bit_num));
141}
142
Marek Bykowskid6514442019-12-17 07:41:43 -0600143void gicd_set_icenabler(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200144{
145 unsigned int bit_num = interrupt_id & ((1 << ICENABLER_SHIFT) - 1);
146
147 gicd_write_icenabler(base, interrupt_id, (1 << bit_num));
148}
149
Marek Bykowskid6514442019-12-17 07:41:43 -0600150void gicd_set_ispendr(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200151{
152 unsigned int bit_num = interrupt_id & ((1 << ISPENDR_SHIFT) - 1);
153
154 gicd_write_ispendr(base, interrupt_id, (1 << bit_num));
155}
156
Marek Bykowskid6514442019-12-17 07:41:43 -0600157void gicd_set_icpendr(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200158{
159 unsigned int bit_num = interrupt_id & ((1 << ICPENDR_SHIFT) - 1);
160
161 gicd_write_icpendr(base, interrupt_id, (1 << bit_num));
162}
163
Marek Bykowskid6514442019-12-17 07:41:43 -0600164void gicd_set_isactiver(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200165{
166 unsigned int bit_num = interrupt_id & ((1 << ISACTIVER_SHIFT) - 1);
167
168 gicd_write_isactiver(base, interrupt_id, (1 << bit_num));
169}
170
Marek Bykowskid6514442019-12-17 07:41:43 -0600171void gicd_set_icactiver(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200172{
173 unsigned int bit_num = interrupt_id & ((1 << ICACTIVER_SHIFT) - 1);
174
175 gicd_write_icactiver(base, interrupt_id, (1 << bit_num));
176}
177
Marek Bykowskid6514442019-12-17 07:41:43 -0600178unsigned int gicd_get_ipriorityr(uintptr_t base, unsigned int interrupt_id)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200179{
180 return gicd_read_ipriorityr(base, interrupt_id) & GIC_PRI_MASK;
181}
182
Marek Bykowskid6514442019-12-17 07:41:43 -0600183void gicd_set_ipriorityr(uintptr_t base, unsigned int interrupt_id,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200184 unsigned int priority)
185{
186 mmio_write_8(base + GICD_IPRIORITYR + interrupt_id,
187 priority & GIC_PRI_MASK);
188}
189
190unsigned int is_gicv3_mode(void)
191{
192 /* Check if GICv3 system register available */
Deepika Bhavnanic249d5e2020-02-06 16:29:45 -0600193#ifdef __aarch64__
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200194 if (!(read_id_aa64pfr0_el1() & (ID_AA64PFR0_GIC_MASK << ID_AA64PFR0_GIC_SHIFT)))
195 return 0;
196#else
197 if (!(read_id_pfr1() & (ID_PFR1_GIC_MASK << ID_PFR1_GIC_SHIFT)))
198 return 0;
199#endif
200
201 /* Check whether the system register interface is enabled */
202 return !!is_sre_enabled();
203}