Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
c66f4ade
Commit
c66f4ade
authored
Jun 05, 2017
by
danh-arm
Committed by
GitHub
Jun 05, 2017
Browse files
Merge pull request #961 from jeenu-arm/gic-600
Introduce ARM GIC-600 driver
parents
03dd6391
e1c59ab3
Changes
5
Hide whitespace changes
Inline
Side-by-side
docs/user-guide.md
View file @
c66f4ade
...
...
@@ -638,6 +638,7 @@ map is explained in the [Firmware Design].
if
`FVP_CLUSTER_COUNT`
> 2.
*
`FVP_USE_GIC_DRIVER`
: Selects the GIC driver to be built. Options:
-
`FVP_GIC600`
: The GIC600 implementation of GICv3 is selected
-
`FVP_GICV2`
: The GICv2 only driver is selected
-
`FVP_GICV3`
: The GICv3 only driver is selected (default option)
-
`FVP_GICV3_LEGACY`
: The Legacy GICv3 driver is selected (deprecated)
...
...
drivers/arm/gic/v3/gic600.c
0 → 100644
View file @
c66f4ade
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* Driver for GIC600-specific features. This driver only overrides APIs that are
* different to those generic ones in GICv3 driver.
*
* GIC600 supports independently power-gating redistributor interface.
*/
#include <arch_helpers.h>
#include <assert.h>
#include <gicv3.h>
#include "gicv3_private.h"
/* GIC600-specific register offsets */
#define GICR_PWRR 0x24
/* GICR_PWRR fields */
#define PWRR_RDPD_SHIFT 0
#define PWRR_RDGPD_SHIFT 2
#define PWRR_RDGPO_SHIFT 3
#define PWRR_RDGPD (1 << PWRR_RDGPD_SHIFT)
#define PWRR_RDGPO (1 << PWRR_RDGPO_SHIFT)
/* Values to write to GICR_PWRR register to power redistributor */
#define PWRR_ON (0 << PWRR_RDPD_SHIFT)
#define PWRR_OFF (1 << PWRR_RDPD_SHIFT)
/* Generic GICv3 resources */
extern
const
gicv3_driver_data_t
*
gicv3_driver_data
;
/* GIC600-specific accessor functions */
static
void
gicr_write_pwrr
(
uintptr_t
base
,
unsigned
int
val
)
{
mmio_write_32
(
base
+
GICR_PWRR
,
val
);
}
static
uint32_t
gicr_read_pwrr
(
uintptr_t
base
)
{
return
mmio_read_32
(
base
+
GICR_PWRR
);
}
static
int
gicr_group_powering_down
(
uint32_t
pwrr
)
{
/*
* Whether the redistributor group power down operation is in transit:
* i.e. it's intending to, but not finished yet.
*/
return
((
pwrr
&
PWRR_RDGPD
)
&&
!
(
pwrr
&
PWRR_RDGPO
));
}
static
void
gic600_pwr_on
(
uintptr_t
base
)
{
/* Power on redistributor */
gicr_write_pwrr
(
base
,
PWRR_ON
);
/* Wait until the power on state is reflected */
while
(
gicr_read_pwrr
(
base
)
&
PWRR_RDGPO
)
;
}
static
void
gic600_pwr_off
(
uintptr_t
base
)
{
/* Power off redistributor */
gicr_write_pwrr
(
base
,
PWRR_OFF
);
/*
* If this is the last man, turning this redistributor frame off will
* result in the group itself being powered off. In that case, wait as
* long as it's in transition, or has aborted the transition altogether
* for any reason.
*/
if
(
gicr_read_pwrr
(
base
)
&
PWRR_RDGPD
)
{
while
(
gicr_group_powering_down
(
gicr_read_pwrr
(
base
)))
;
}
}
/*
* Power off GIC600 redistributor
*/
void
gicv3_rdistif_off
(
unsigned
int
proc_num
)
{
uintptr_t
gicr_base
;
assert
(
gicv3_driver_data
);
assert
(
proc_num
<
gicv3_driver_data
->
rdistif_num
);
assert
(
gicv3_driver_data
->
rdistif_base_addrs
);
gicr_base
=
gicv3_driver_data
->
rdistif_base_addrs
[
proc_num
];
assert
(
gicr_base
);
/* Attempt to power redistributor off */
gic600_pwr_off
(
gicr_base
);
}
/*
* Power on GIC600 redistributor
*/
void
gicv3_rdistif_on
(
unsigned
int
proc_num
)
{
uintptr_t
gicr_base
;
assert
(
gicv3_driver_data
);
assert
(
proc_num
<
gicv3_driver_data
->
rdistif_num
);
assert
(
gicv3_driver_data
->
rdistif_base_addrs
);
gicr_base
=
gicv3_driver_data
->
rdistif_base_addrs
[
proc_num
];
assert
(
gicr_base
);
/* Power redistributor on */
gic600_pwr_on
(
gicr_base
);
}
drivers/arm/gic/v3/gicv3_main.c
View file @
c66f4ade
...
...
@@ -8,12 +8,10 @@
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
#include <gic_common.h>
#include <gicv3.h>
#include "../common/gic_common_private.h"
#include "gicv3_private.h"
static
const
gicv3_driver_data_t
*
driver_data
;
const
gicv3_driver_data_t
*
gicv3_
driver_data
;
static
unsigned
int
gicv2_compat
;
/*
...
...
@@ -90,18 +88,20 @@ void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data)
plat_driver_data
->
gicr_base
,
plat_driver_data
->
mpidr_to_core_pos
);
driver_data
=
plat_driver_data
;
gicv3_
driver_data
=
plat_driver_data
;
/*
* The GIC driver data is initialized by the primary CPU with caches
* enabled. When the secondary CPU boots up, it initializes the
* GICC/GICR interface with the caches disabled. Hence flush the
* driver
_
data to ensure coherency. This is not required if the
* driver
data to ensure coherency. This is not required if the
* platform has HW_ASSISTED_COHERENCY enabled.
*/
#if !HW_ASSISTED_COHERENCY
flush_dcache_range
((
uintptr_t
)
&
driver_data
,
sizeof
(
driver_data
));
flush_dcache_range
((
uintptr_t
)
driver_data
,
sizeof
(
*
driver_data
));
flush_dcache_range
((
uintptr_t
)
&
gicv3_driver_data
,
sizeof
(
gicv3_driver_data
));
flush_dcache_range
((
uintptr_t
)
gicv3_driver_data
,
sizeof
(
*
gicv3_driver_data
));
#endif
INFO
(
"GICv3 %s legacy support detected."
...
...
@@ -117,10 +117,10 @@ void gicv3_distif_init(void)
{
unsigned
int
bitmap
=
0
;
assert
(
driver_data
);
assert
(
driver_data
->
gicd_base
);
assert
(
driver_data
->
g1s_interrupt_array
||
driver_data
->
g0_interrupt_array
);
assert
(
gicv3_
driver_data
);
assert
(
gicv3_
driver_data
->
gicd_base
);
assert
(
gicv3_
driver_data
->
g1s_interrupt_array
||
gicv3_
driver_data
->
g0_interrupt_array
);
assert
(
IS_IN_EL3
());
...
...
@@ -129,39 +129,39 @@ void gicv3_distif_init(void)
* the ARE_S bit. The Distributor might generate a system error
* otherwise.
*/
gicd_clr_ctlr
(
driver_data
->
gicd_base
,
gicd_clr_ctlr
(
gicv3_
driver_data
->
gicd_base
,
CTLR_ENABLE_G0_BIT
|
CTLR_ENABLE_G1S_BIT
|
CTLR_ENABLE_G1NS_BIT
,
RWP_TRUE
);
/* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */
gicd_set_ctlr
(
driver_data
->
gicd_base
,
gicd_set_ctlr
(
gicv3_
driver_data
->
gicd_base
,
CTLR_ARE_S_BIT
|
CTLR_ARE_NS_BIT
,
RWP_TRUE
);
/* Set the default attribute of all SPIs */
gicv3_spis_configure_defaults
(
driver_data
->
gicd_base
);
gicv3_spis_configure_defaults
(
gicv3_
driver_data
->
gicd_base
);
/* Configure the G1S SPIs */
if
(
driver_data
->
g1s_interrupt_array
)
{
gicv3_secure_spis_configure
(
driver_data
->
gicd_base
,
driver_data
->
g1s_interrupt_num
,
driver_data
->
g1s_interrupt_array
,
if
(
gicv3_
driver_data
->
g1s_interrupt_array
)
{
gicv3_secure_spis_configure
(
gicv3_
driver_data
->
gicd_base
,
gicv3_
driver_data
->
g1s_interrupt_num
,
gicv3_
driver_data
->
g1s_interrupt_array
,
INTR_GROUP1S
);
bitmap
|=
CTLR_ENABLE_G1S_BIT
;
}
/* Configure the G0 SPIs */
if
(
driver_data
->
g0_interrupt_array
)
{
gicv3_secure_spis_configure
(
driver_data
->
gicd_base
,
driver_data
->
g0_interrupt_num
,
driver_data
->
g0_interrupt_array
,
if
(
gicv3_
driver_data
->
g0_interrupt_array
)
{
gicv3_secure_spis_configure
(
gicv3_
driver_data
->
gicd_base
,
gicv3_
driver_data
->
g0_interrupt_num
,
gicv3_
driver_data
->
g0_interrupt_array
,
INTR_GROUP0
);
bitmap
|=
CTLR_ENABLE_G0_BIT
;
}
/* Enable the secure SPIs now that they have been configured */
gicd_set_ctlr
(
driver_data
->
gicd_base
,
bitmap
,
RWP_TRUE
);
gicd_set_ctlr
(
gicv3_
driver_data
->
gicd_base
,
bitmap
,
RWP_TRUE
);
}
/*******************************************************************************
...
...
@@ -173,37 +173,37 @@ void gicv3_rdistif_init(unsigned int proc_num)
{
uintptr_t
gicr_base
;
assert
(
driver_data
);
assert
(
proc_num
<
driver_data
->
rdistif_num
);
assert
(
driver_data
->
rdistif_base_addrs
);
assert
(
driver_data
->
gicd_base
);
assert
(
gicd_read_ctlr
(
driver_data
->
gicd_base
)
&
CTLR_ARE_S_BIT
);
assert
(
driver_data
->
g1s_interrupt_array
||
driver_data
->
g0_interrupt_array
);
assert
(
gicv3_
driver_data
);
assert
(
proc_num
<
gicv3_
driver_data
->
rdistif_num
);
assert
(
gicv3_
driver_data
->
rdistif_base_addrs
);
assert
(
gicv3_
driver_data
->
gicd_base
);
assert
(
gicd_read_ctlr
(
gicv3_
driver_data
->
gicd_base
)
&
CTLR_ARE_S_BIT
);
assert
(
gicv3_
driver_data
->
g1s_interrupt_array
||
gicv3_
driver_data
->
g0_interrupt_array
);
assert
(
IS_IN_EL3
());
/* Power on redistributor */
gicv3_rdistif_on
(
proc_num
);
gicr_base
=
driver_data
->
rdistif_base_addrs
[
proc_num
];
gicr_base
=
gicv3_
driver_data
->
rdistif_base_addrs
[
proc_num
];
/* Set the default attribute of all SGIs and PPIs */
gicv3_ppi_sgi_configure_defaults
(
gicr_base
);
/* Configure the G1S SGIs/PPIs */
if
(
driver_data
->
g1s_interrupt_array
)
{
if
(
gicv3_
driver_data
->
g1s_interrupt_array
)
{
gicv3_secure_ppi_sgi_configure
(
gicr_base
,
driver_data
->
g1s_interrupt_num
,
driver_data
->
g1s_interrupt_array
,
gicv3_
driver_data
->
g1s_interrupt_num
,
gicv3_
driver_data
->
g1s_interrupt_array
,
INTR_GROUP1S
);
}
/* Configure the G0 SGIs/PPIs */
if
(
driver_data
->
g0_interrupt_array
)
{
if
(
gicv3_
driver_data
->
g0_interrupt_array
)
{
gicv3_secure_ppi_sgi_configure
(
gicr_base
,
driver_data
->
g0_interrupt_num
,
driver_data
->
g0_interrupt_array
,
gicv3_
driver_data
->
g0_interrupt_num
,
gicv3_
driver_data
->
g0_interrupt_array
,
INTR_GROUP0
);
}
}
...
...
@@ -231,13 +231,13 @@ void gicv3_cpuif_enable(unsigned int proc_num)
unsigned
int
scr_el3
;
unsigned
int
icc_sre_el3
;
assert
(
driver_data
);
assert
(
proc_num
<
driver_data
->
rdistif_num
);
assert
(
driver_data
->
rdistif_base_addrs
);
assert
(
gicv3_
driver_data
);
assert
(
proc_num
<
gicv3_
driver_data
->
rdistif_num
);
assert
(
gicv3_
driver_data
->
rdistif_base_addrs
);
assert
(
IS_IN_EL3
());
/* Mark the connected core as awake */
gicr_base
=
driver_data
->
rdistif_base_addrs
[
proc_num
];
gicr_base
=
gicv3_
driver_data
->
rdistif_base_addrs
[
proc_num
];
gicv3_rdistif_mark_core_awake
(
gicr_base
);
/* Disable the legacy interrupt bypass */
...
...
@@ -291,9 +291,9 @@ void gicv3_cpuif_disable(unsigned int proc_num)
{
uintptr_t
gicr_base
;
assert
(
driver_data
);
assert
(
proc_num
<
driver_data
->
rdistif_num
);
assert
(
driver_data
->
rdistif_base_addrs
);
assert
(
gicv3_
driver_data
);
assert
(
proc_num
<
gicv3_
driver_data
->
rdistif_num
);
assert
(
gicv3_
driver_data
->
rdistif_base_addrs
);
assert
(
IS_IN_EL3
());
...
...
@@ -314,7 +314,7 @@ void gicv3_cpuif_disable(unsigned int proc_num)
isb
();
/* Mark the connected core as asleep */
gicr_base
=
driver_data
->
rdistif_base_addrs
[
proc_num
];
gicr_base
=
gicv3_
driver_data
->
rdistif_base_addrs
[
proc_num
];
gicv3_rdistif_mark_core_asleep
(
gicr_base
);
}
...
...
@@ -371,25 +371,25 @@ unsigned int gicv3_get_interrupt_type(unsigned int id,
uintptr_t
gicr_base
;
assert
(
IS_IN_EL3
());
assert
(
driver_data
);
assert
(
gicv3_
driver_data
);
/* Ensure the parameters are valid */
assert
(
id
<
PENDING_G1S_INTID
||
id
>=
MIN_LPI_ID
);
assert
(
proc_num
<
driver_data
->
rdistif_num
);
assert
(
proc_num
<
gicv3_
driver_data
->
rdistif_num
);
/* All LPI interrupts are Group 1 non secure */
if
(
id
>=
MIN_LPI_ID
)
return
INTR_GROUP1NS
;
if
(
id
<
MIN_SPI_ID
)
{
assert
(
driver_data
->
rdistif_base_addrs
);
gicr_base
=
driver_data
->
rdistif_base_addrs
[
proc_num
];
assert
(
gicv3_
driver_data
->
rdistif_base_addrs
);
gicr_base
=
gicv3_
driver_data
->
rdistif_base_addrs
[
proc_num
];
igroup
=
gicr_get_igroupr0
(
gicr_base
,
id
);
grpmodr
=
gicr_get_igrpmodr0
(
gicr_base
,
id
);
}
else
{
assert
(
driver_data
->
gicd_base
);
igroup
=
gicd_get_igroupr
(
driver_data
->
gicd_base
,
id
);
grpmodr
=
gicd_get_igrpmodr
(
driver_data
->
gicd_base
,
id
);
assert
(
gicv3_
driver_data
->
gicd_base
);
igroup
=
gicd_get_igroupr
(
gicv3_
driver_data
->
gicd_base
,
id
);
grpmodr
=
gicd_get_igrpmodr
(
gicv3_
driver_data
->
gicd_base
,
id
);
}
/*
...
...
drivers/arm/gic/v3/gicv3_private.h
View file @
c66f4ade
/*
* Copyright (c) 2015-201
6
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-201
7
, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
...
...
@@ -7,9 +7,11 @@
#ifndef __GICV3_PRIVATE_H__
#define __GICV3_PRIVATE_H__
#include <gic_common.h>
#include <gicv3.h>
#include <mmio.h>
#include <stdint.h>
#include "../common/gic_common_private.h"
/*******************************************************************************
* GICv3 private macro definitions
...
...
plat/arm/board/fvp/platform.mk
View file @
c66f4ade
...
...
@@ -31,13 +31,18 @@ endif
$(eval
$(call
add_define,FVP_INTERCONNECT_DRIVER))
# Choose the GIC sources depending upon the how the FVP will be invoked
ifeq
(${FVP_USE_GIC_DRIVER}, FVP_GICV3)
FVP_GIC_SOURCES
:=
drivers/arm/gic/common/gic_common.c
\
FVP_GICV3_SOURCES
:=
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v3/gicv3_main.c
\
drivers/arm/gic/v3/gicv3_helpers.c
\
plat/common/plat_gicv3.c
\
plat/arm/common/arm_gicv3.c
# Choose the GIC sources depending upon the how the FVP will be invoked
ifeq
(${FVP_USE_GIC_DRIVER}, FVP_GICV3)
FVP_GIC_SOURCES
:=
${FVP_GICV3_SOURCES}
else
ifeq
(${FVP_USE_GIC_DRIVER},FVP_GIC600)
FVP_GIC_SOURCES
:=
${FVP_GICV3_SOURCES}
\
drivers/arm/gic/v3/gic600.c
else
ifeq
(${FVP_USE_GIC_DRIVER}, FVP_GICV2)
FVP_GIC_SOURCES
:=
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v2/gicv2_main.c
\
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment