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
5a6954fb
Commit
5a6954fb
authored
Jun 24, 2015
by
danh-arm
Browse files
Merge pull request #321 from vwadekar/tegra-gic-implementation-v1
Add missing features to the Tegra GIC driver
parents
e347e843
e1e094c7
Changes
2
Hide whitespace changes
Inline
Side-by-side
plat/nvidia/tegra/common/tegra_common.mk
View file @
5a6954fb
...
...
@@ -43,14 +43,12 @@ PLAT_BL_COMMON_SOURCES := lib/aarch64/xlat_tables.c \
COMMON_DIR
:=
plat/nvidia/tegra/common
BL31_SOURCES
+=
drivers/arm/gic/arm_gic.c
\
drivers/arm/gic/gic_v2.c
\
BL31_SOURCES
+=
drivers/arm/gic/gic_v2.c
\
drivers/arm/gic/gic_v3.c
\
drivers/console/console.S
\
drivers/ti/uart/16550_console.S
\
lib/cpus/aarch64/cortex_a53.S
\
lib/cpus/aarch64/cortex_a57.S
\
plat/common/plat_gic.c
\
plat/common/aarch64/platform_mp_stack.S
\
${COMMON_DIR}
/aarch64/tegra_helpers.S
\
${COMMON_DIR}
/drivers/memctrl/memctrl.c
\
...
...
plat/nvidia/tegra/common/tegra_gic.c
View file @
5a6954fb
...
...
@@ -30,6 +30,7 @@
#include <arch_helpers.h>
#include <assert.h>
#include <arm_gic.h>
#include <bl_common.h>
#include <debug.h>
#include <gic_v2.h>
...
...
@@ -39,6 +40,13 @@
#include <tegra_private.h>
#include <tegra_def.h>
/* Value used to initialize Non-Secure IRQ priorities four at a time */
#define GICD_IPRIORITYR_DEF_VAL \
(GIC_HIGHEST_NS_PRIORITY | \
(GIC_HIGHEST_NS_PRIORITY << 8) | \
(GIC_HIGHEST_NS_PRIORITY << 16) | \
(GIC_HIGHEST_NS_PRIORITY << 24))
/*******************************************************************************
* Place the cpu interface in a state where it can never make a cpu exit wfi as
* as result of an asserted interrupt. This is critical for powering down a cpu
...
...
@@ -61,10 +69,40 @@ void tegra_gic_cpuif_deactivate(void)
******************************************************************************/
static
void
tegra_gic_cpuif_setup
(
unsigned
int
gicc_base
)
{
gicc_write_ctlr
(
gicc_base
,
ENABLE_GRP0
|
ENABLE_GRP1
);
unsigned
int
val
;
val
=
ENABLE_GRP0
|
ENABLE_GRP1
|
FIQ_EN
|
FIQ_BYP_DIS_GRP0
;
val
|=
IRQ_BYP_DIS_GRP0
|
FIQ_BYP_DIS_GRP1
|
IRQ_BYP_DIS_GRP1
;
gicc_write_ctlr
(
gicc_base
,
val
);
gicc_write_pmr
(
gicc_base
,
GIC_PRI_MASK
);
}
/*******************************************************************************
* Per cpu gic distributor setup which will be done by all cpus after a cold
* boot/hotplug. This marks out the secure interrupts & enables them.
******************************************************************************/
static
void
tegra_gic_pcpu_distif_setup
(
unsigned
int
gicd_base
)
{
unsigned
int
index
,
sec_ppi_sgi_mask
=
0
;
assert
(
gicd_base
);
/* Setup PPI priorities doing four at a time */
for
(
index
=
0
;
index
<
32
;
index
+=
4
)
{
gicd_write_ipriorityr
(
gicd_base
,
index
,
GICD_IPRIORITYR_DEF_VAL
);
}
/*
* Invert the bitmask to create a mask for non-secure PPIs and
* SGIs. Program the GICD_IGROUPR0 with this bit mask. This write will
* update the GICR_IGROUPR0 as well in case we are running on a GICv3
* system. This is critical if GICD_CTLR.ARE_NS=1.
*/
gicd_write_igroupr
(
gicd_base
,
0
,
~
sec_ppi_sgi_mask
);
}
/*******************************************************************************
* Global gic distributor setup which will be done by the primary cpu after a
* cold boot. It marks out the non secure SPIs, PPIs & SGIs and enables them.
...
...
@@ -72,7 +110,7 @@ static void tegra_gic_cpuif_setup(unsigned int gicc_base)
******************************************************************************/
static
void
tegra_gic_distif_setup
(
unsigned
int
gicd_base
)
{
unsigned
int
ctr
,
num_ints
;
unsigned
int
index
,
num_ints
;
/*
* Mark out non-secure interrupts. Calculate number of
...
...
@@ -80,9 +118,22 @@ static void tegra_gic_distif_setup(unsigned int gicd_base)
* number of IT_LINES
*/
num_ints
=
gicd_read_typer
(
gicd_base
)
&
IT_LINES_NO_MASK
;
num_ints
++
;
for
(
ctr
=
0
;
ctr
<
num_ints
;
ctr
++
)
gicd_write_igroupr
(
gicd_base
,
ctr
<<
IGROUPR_SHIFT
,
~
0
);
num_ints
=
(
num_ints
+
1
)
<<
5
;
for
(
index
=
MIN_SPI_ID
;
index
<
num_ints
;
index
+=
32
)
gicd_write_igroupr
(
gicd_base
,
index
,
~
0
);
/* Setup SPI priorities doing four at a time */
for
(
index
=
MIN_SPI_ID
;
index
<
num_ints
;
index
+=
4
)
{
gicd_write_ipriorityr
(
gicd_base
,
index
,
GICD_IPRIORITYR_DEF_VAL
);
}
/*
* Configure the SGI and PPI. This is done in a separated function
* because each CPU is responsible for initializing its own private
* interrupts.
*/
tegra_gic_pcpu_distif_setup
(
gicd_base
);
/* enable distributor */
gicd_write_ctlr
(
gicd_base
,
ENABLE_GRP0
|
ENABLE_GRP1
);
...
...
@@ -93,3 +144,151 @@ void tegra_gic_setup(void)
tegra_gic_cpuif_setup
(
TEGRA_GICC_BASE
);
tegra_gic_distif_setup
(
TEGRA_GICD_BASE
);
}
/*******************************************************************************
* An ARM processor signals interrupt exceptions through the IRQ and FIQ pins.
* The interrupt controller knows which pin/line it uses to signal a type of
* interrupt. This function provides a common implementation of
* plat_interrupt_type_to_line() in an ARM GIC environment for optional re-use
* across platforms. It lets the interrupt management framework determine
* for a type of interrupt and security state, which line should be used in the
* SCR_EL3 to control its routing to EL3. The interrupt line is represented as
* the bit position of the IRQ or FIQ bit in the SCR_EL3.
******************************************************************************/
uint32_t
tegra_gic_interrupt_type_to_line
(
uint32_t
type
,
uint32_t
security_state
)
{
assert
(
type
==
INTR_TYPE_S_EL1
||
type
==
INTR_TYPE_EL3
||
type
==
INTR_TYPE_NS
);
assert
(
sec_state_is_valid
(
security_state
));
/*
* We ignore the security state parameter under the assumption that
* both normal and secure worlds are using ARM GICv2. This parameter
* will be used when the secure world starts using GICv3.
*/
#if ARM_GIC_ARCH == 2
return
gicv2_interrupt_type_to_line
(
TEGRA_GICC_BASE
,
type
);
#else
#error "Invalid ARM GIC architecture version specified for platform port"
#endif
/* ARM_GIC_ARCH */
}
#if ARM_GIC_ARCH == 2
/*******************************************************************************
* This function returns the type of the highest priority pending interrupt at
* the GIC cpu interface. INTR_TYPE_INVAL is returned when there is no
* interrupt pending.
******************************************************************************/
uint32_t
tegra_gic_get_pending_interrupt_type
(
void
)
{
uint32_t
id
;
id
=
gicc_read_hppir
(
TEGRA_GICC_BASE
)
&
INT_ID_MASK
;
/* Assume that all secure interrupts are S-EL1 interrupts */
if
(
id
<
1022
)
return
INTR_TYPE_S_EL1
;
if
(
id
==
GIC_SPURIOUS_INTERRUPT
)
return
INTR_TYPE_INVAL
;
return
INTR_TYPE_NS
;
}
/*******************************************************************************
* This function returns the id of the highest priority pending interrupt at
* the GIC cpu interface. INTR_ID_UNAVAILABLE is returned when there is no
* interrupt pending.
******************************************************************************/
uint32_t
tegra_gic_get_pending_interrupt_id
(
void
)
{
uint32_t
id
;
id
=
gicc_read_hppir
(
TEGRA_GICC_BASE
)
&
INT_ID_MASK
;
if
(
id
<
1022
)
return
id
;
if
(
id
==
1023
)
return
INTR_ID_UNAVAILABLE
;
/*
* Find out which non-secure interrupt it is under the assumption that
* the GICC_CTLR.AckCtl bit is 0.
*/
return
gicc_read_ahppir
(
TEGRA_GICC_BASE
)
&
INT_ID_MASK
;
}
/*******************************************************************************
* This functions reads the GIC cpu interface Interrupt Acknowledge register
* to start handling the pending interrupt. It returns the contents of the IAR.
******************************************************************************/
uint32_t
tegra_gic_acknowledge_interrupt
(
void
)
{
return
gicc_read_IAR
(
TEGRA_GICC_BASE
);
}
/*******************************************************************************
* This functions writes the GIC cpu interface End Of Interrupt register with
* the passed value to finish handling the active interrupt
******************************************************************************/
void
tegra_gic_end_of_interrupt
(
uint32_t
id
)
{
gicc_write_EOIR
(
TEGRA_GICC_BASE
,
id
);
}
/*******************************************************************************
* This function returns the type of the interrupt id depending upon the group
* this interrupt has been configured under by the interrupt controller i.e.
* group0 or group1.
******************************************************************************/
uint32_t
tegra_gic_get_interrupt_type
(
uint32_t
id
)
{
uint32_t
group
;
group
=
gicd_get_igroupr
(
TEGRA_GICD_BASE
,
id
);
/* Assume that all secure interrupts are S-EL1 interrupts */
if
(
group
==
GRP0
)
return
INTR_TYPE_S_EL1
;
else
return
INTR_TYPE_NS
;
}
#else
#error "Invalid ARM GIC architecture version specified for platform port"
#endif
/* ARM_GIC_ARCH */
uint32_t
plat_ic_get_pending_interrupt_id
(
void
)
{
return
tegra_gic_get_pending_interrupt_id
();
}
uint32_t
plat_ic_get_pending_interrupt_type
(
void
)
{
return
tegra_gic_get_pending_interrupt_type
();
}
uint32_t
plat_ic_acknowledge_interrupt
(
void
)
{
return
tegra_gic_acknowledge_interrupt
();
}
uint32_t
plat_ic_get_interrupt_type
(
uint32_t
id
)
{
return
tegra_gic_get_interrupt_type
(
id
);
}
void
plat_ic_end_of_interrupt
(
uint32_t
id
)
{
tegra_gic_end_of_interrupt
(
id
);
}
uint32_t
plat_interrupt_type_to_line
(
uint32_t
type
,
uint32_t
security_state
)
{
return
tegra_gic_interrupt_type_to_line
(
type
,
security_state
);
}
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