blob: cec6a9df77473fc2a65196f9ec5c38a3e85a041a [file] [log] [blame]
Achin Gupta1fa7eb62015-11-03 14:18:34 +00001/*
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +00002 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
Achin Gupta1fa7eb62015-11-03 14:18:34 +00003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Achin Gupta1fa7eb62015-11-03 14:18:34 +00005 */
6
7#include <arm_def.h>
8#include <gicv3.h>
Jeenu Viswambharan723dce02017-09-22 08:59:59 +01009#include <interrupt_props.h>
Achin Gupta1fa7eb62015-11-03 14:18:34 +000010#include <plat_arm.h>
11#include <platform.h>
12#include <platform_def.h>
13
14/******************************************************************************
15 * The following functions are defined as weak to allow a platform to override
16 * the way the GICv3 driver is initialised and used.
17 *****************************************************************************/
18#pragma weak plat_arm_gic_driver_init
19#pragma weak plat_arm_gic_init
20#pragma weak plat_arm_gic_cpuif_enable
21#pragma weak plat_arm_gic_cpuif_disable
22#pragma weak plat_arm_gic_pcpu_init
Jeenu Viswambharan78132c92016-12-09 11:12:34 +000023#pragma weak plat_arm_gic_redistif_on
24#pragma weak plat_arm_gic_redistif_off
Achin Gupta1fa7eb62015-11-03 14:18:34 +000025
26/* The GICv3 driver only needs to be initialized in EL3 */
Soby Mathewcf022c52016-01-13 17:06:00 +000027static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
Achin Gupta1fa7eb62015-11-03 14:18:34 +000028
Jeenu Viswambharan723dce02017-09-22 08:59:59 +010029static const interrupt_prop_t arm_interrupt_props[] = {
30 PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
31 PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
Achin Gupta1fa7eb62015-11-03 14:18:34 +000032};
33
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +000034/*
35 * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
36 * to core position.
37 *
38 * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
39 * values read from GICR_TYPER don't have an MT field. To reuse the same
40 * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
41 * that read from GICR_TYPER.
42 *
43 * Assumptions:
44 *
45 * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
46 * - No CPUs implemented in the system use affinity level 3.
47 */
48static unsigned int arm_gicv3_mpidr_hash(u_register_t mpidr)
49{
50 mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
51 return plat_arm_calc_core_pos(mpidr);
52}
53
Achin Gupta1fa7eb62015-11-03 14:18:34 +000054const gicv3_driver_data_t arm_gic_data = {
55 .gicd_base = PLAT_ARM_GICD_BASE,
56 .gicr_base = PLAT_ARM_GICR_BASE,
Jeenu Viswambharan723dce02017-09-22 08:59:59 +010057 .interrupt_props = arm_interrupt_props,
58 .interrupt_props_num = ARRAY_SIZE(arm_interrupt_props),
Achin Gupta1fa7eb62015-11-03 14:18:34 +000059 .rdistif_num = PLATFORM_CORE_COUNT,
60 .rdistif_base_addrs = rdistif_base_addrs,
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +000061 .mpidr_to_core_pos = arm_gicv3_mpidr_hash
Achin Gupta1fa7eb62015-11-03 14:18:34 +000062};
63
64void plat_arm_gic_driver_init(void)
65{
66 /*
67 * The GICv3 driver is initialized in EL3 and does not need
68 * to be initialized again in SEL1. This is because the S-EL1
69 * can use GIC system registers to manage interrupts and does
70 * not need GIC interface base addresses to be configured.
71 */
Masahiro Yamadaa2698372016-12-26 00:22:47 +090072#if (defined(AARCH32) && defined(IMAGE_BL32)) || \
73 (defined(IMAGE_BL31) && !defined(AARCH32))
Achin Gupta1fa7eb62015-11-03 14:18:34 +000074 gicv3_driver_init(&arm_gic_data);
75#endif
76}
77
78/******************************************************************************
79 * ARM common helper to initialize the GIC. Only invoked by BL31
80 *****************************************************************************/
81void plat_arm_gic_init(void)
82{
83 gicv3_distif_init();
84 gicv3_rdistif_init(plat_my_core_pos());
85 gicv3_cpuif_enable(plat_my_core_pos());
86}
87
88/******************************************************************************
89 * ARM common helper to enable the GIC CPU interface
90 *****************************************************************************/
91void plat_arm_gic_cpuif_enable(void)
92{
93 gicv3_cpuif_enable(plat_my_core_pos());
94}
95
96/******************************************************************************
97 * ARM common helper to disable the GIC CPU interface
98 *****************************************************************************/
99void plat_arm_gic_cpuif_disable(void)
100{
101 gicv3_cpuif_disable(plat_my_core_pos());
102}
103
104/******************************************************************************
105 * ARM common helper to initialize the per-cpu redistributor interface in GICv3
106 *****************************************************************************/
107void plat_arm_gic_pcpu_init(void)
108{
109 gicv3_rdistif_init(plat_my_core_pos());
110}
Jeenu Viswambharan78132c92016-12-09 11:12:34 +0000111
112/******************************************************************************
113 * ARM common helpers to power GIC redistributor interface
114 *****************************************************************************/
115void plat_arm_gic_redistif_on(void)
116{
117 gicv3_rdistif_on(plat_my_core_pos());
118}
119
120void plat_arm_gic_redistif_off(void)
121{
122 gicv3_rdistif_off(plat_my_core_pos());
123}