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
6654d17e
"frontend/src/vscode:/vscode.git/clone" did not exist on "dd25281305e7e30a4dcc91b7994a705d85fb95b9"
Commit
6654d17e
authored
Mar 11, 2020
by
Mark Dykes
Committed by
TrustedFirmware Code Review
Mar 11, 2020
Browse files
Merge "TF-A GICv3 driver: Separate GICD and GICR accessor functions" into integration
parents
9f41b0b1
6e19bd56
Changes
22
Hide whitespace changes
Inline
Side-by-side
drivers/arm/gic/v3/gicdv3_helpers.c
0 → 100644
View file @
6654d17e
/*
* Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include "gicv3_private.h"
/*******************************************************************************
* GIC Distributor interface accessors for bit operations
******************************************************************************/
/*
* Accessor to read the GIC Distributor IGRPMODR corresponding to the
* interrupt `id`, 32 interrupt IDs at a time.
*/
uint32_t
gicd_read_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
)
{
return
GICD_READ
(
IGRPMODR
,
base
,
id
);
}
/*
* Accessor to write the GIC Distributor IGRPMODR corresponding to the
* interrupt `id`, 32 interrupt IDs at a time.
*/
void
gicd_write_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
,
uint32_t
val
)
{
GICD_WRITE
(
IGRPMODR
,
base
,
id
,
val
);
}
/*
* Accessor to get the bit corresponding to interrupt ID
* in GIC Distributor IGRPMODR.
*/
unsigned
int
gicd_get_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
)
{
return
GICD_GET_BIT
(
IGRPMODR
,
base
,
id
);
}
/*
* Accessor to set the bit corresponding to interrupt ID
* in GIC Distributor IGRPMODR.
*/
void
gicd_set_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
)
{
GICD_SET_BIT
(
IGRPMODR
,
base
,
id
);
}
/*
* Accessor to clear the bit corresponding to interrupt ID
* in GIC Distributor IGRPMODR.
*/
void
gicd_clr_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
)
{
GICD_CLR_BIT
(
IGRPMODR
,
base
,
id
);
}
drivers/arm/gic/v3/gicrv3_helpers.c
0 → 100644
View file @
6654d17e
/*
* Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <common/interrupt_props.h>
#include <drivers/arm/gicv3.h>
#include "gicv3_private.h"
/*******************************************************************************
* GIC Redistributor functions
* Note: The raw register values correspond to multiple interrupt IDs and
* the number of interrupt IDs involved depends on the register accessed.
******************************************************************************/
/*
* Accessor to read the GIC Redistributor IPRIORITYR corresponding to the
* interrupt `id`, 4 interrupts IDs at a time.
*/
unsigned
int
gicr_read_ipriorityr
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
n
=
id
>>
IPRIORITYR_SHIFT
;
return
mmio_read_32
(
base
+
GICR_IPRIORITYR
+
(
n
<<
2
));
}
/*
* Accessor to write the GIC Redistributor IPRIORITYR corresponding to the
* interrupt `id`, 4 interrupts IDs at a time.
*/
void
gicr_write_ipriorityr
(
uintptr_t
base
,
unsigned
int
id
,
unsigned
int
val
)
{
unsigned
int
n
=
id
>>
IPRIORITYR_SHIFT
;
mmio_write_32
(
base
+
GICR_IPRIORITYR
+
(
n
<<
2
),
val
);
}
/*
* Accessor to set the byte corresponding to interrupt ID
* in GIC Redistributor IPRIORITYR.
*/
void
gicr_set_ipriorityr
(
uintptr_t
base
,
unsigned
int
id
,
unsigned
int
pri
)
{
GICR_WRITE_8
(
IPRIORITYR
,
base
,
id
,
pri
&
GIC_PRI_MASK
);
}
/*
* Accessor to get the bit corresponding to interrupt ID
* from GIC Redistributor IGROUPR0.
*/
unsigned
int
gicr_get_igroupr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGROUPR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igroupr0
(
base
);
return
(
reg_val
>>
bit_num
)
&
0x1U
;
}
/*
* Accessor to set the bit corresponding to interrupt ID
* in GIC Redistributor IGROUPR0.
*/
void
gicr_set_igroupr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGROUPR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igroupr0
(
base
);
gicr_write_igroupr0
(
base
,
reg_val
|
(
1U
<<
bit_num
));
}
/*
* Accessor to clear the bit corresponding to interrupt ID
* in GIC Redistributor IGROUPR0.
*/
void
gicr_clr_igroupr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGROUPR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igroupr0
(
base
);
gicr_write_igroupr0
(
base
,
reg_val
&
~
(
1U
<<
bit_num
));
}
/*
* Accessor to get the bit corresponding to interrupt ID
* from GIC Redistributor IGRPMODR0.
*/
unsigned
int
gicr_get_igrpmodr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGRPMODR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igrpmodr0
(
base
);
return
(
reg_val
>>
bit_num
)
&
0x1U
;
}
/*
* Accessor to set the bit corresponding to interrupt ID
* in GIC Redistributor IGRPMODR0.
*/
void
gicr_set_igrpmodr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGRPMODR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igrpmodr0
(
base
);
gicr_write_igrpmodr0
(
base
,
reg_val
|
(
1U
<<
bit_num
));
}
/*
* Accessor to clear the bit corresponding to interrupt ID
* in GIC Redistributor IGRPMODR0.
*/
void
gicr_clr_igrpmodr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGRPMODR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igrpmodr0
(
base
);
gicr_write_igrpmodr0
(
base
,
reg_val
&
~
(
1U
<<
bit_num
));
}
/*
* Accessor to set the bit corresponding to interrupt ID
* in GIC Redistributor ISENABLER0.
*/
void
gicr_set_isenabler0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
ISENABLER_SHIFT
)
-
1U
);
gicr_write_isenabler0
(
base
,
(
1U
<<
bit_num
));
}
/*
* Accessor to set the bit corresponding to interrupt ID in GIC Redistributor
* ICENABLER0.
*/
void
gicr_set_icenabler0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
ICENABLER_SHIFT
)
-
1U
);
gicr_write_icenabler0
(
base
,
(
1U
<<
bit_num
));
}
/*
* Accessor to set the bit corresponding to interrupt ID in GIC Redistributor
* ISACTIVER0.
*/
unsigned
int
gicr_get_isactiver0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
ISACTIVER_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_isactiver0
(
base
);
return
(
reg_val
>>
bit_num
)
&
0x1U
;
}
/*
* Accessor to clear the bit corresponding to interrupt ID in GIC Redistributor
* ICPENDRR0.
*/
void
gicr_set_icpendr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
ICPENDR_SHIFT
)
-
1U
);
gicr_write_icpendr0
(
base
,
(
1U
<<
bit_num
));
}
/*
* Accessor to set the bit corresponding to interrupt ID in GIC Redistributor
* ISPENDR0.
*/
void
gicr_set_ispendr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
ISPENDR_SHIFT
)
-
1U
);
gicr_write_ispendr0
(
base
,
(
1U
<<
bit_num
));
}
/*
* Accessor to set the bit fields corresponding to interrupt ID
* in GIC Redistributor ICFGR0.
*/
void
gicr_set_icfgr0
(
uintptr_t
base
,
unsigned
int
id
,
unsigned
int
cfg
)
{
/* Interrupt configuration is a 2-bit field */
unsigned
int
bit_num
=
id
&
((
1U
<<
ICFGR_SHIFT
)
-
1U
);
unsigned
int
bit_shift
=
bit_num
<<
1U
;
uint32_t
reg_val
=
gicr_read_icfgr0
(
base
);
/* Clear the field, and insert required configuration */
reg_val
&=
~
(
GIC_CFG_MASK
<<
bit_shift
);
reg_val
|=
((
cfg
&
GIC_CFG_MASK
)
<<
bit_shift
);
gicr_write_icfgr0
(
base
,
reg_val
);
}
/*
* Accessor to set the bit fields corresponding to interrupt ID
* in GIC Redistributor ICFGR1.
*/
void
gicr_set_icfgr1
(
uintptr_t
base
,
unsigned
int
id
,
unsigned
int
cfg
)
{
/* Interrupt configuration is a 2-bit field */
unsigned
int
bit_num
=
id
&
((
1U
<<
ICFGR_SHIFT
)
-
1U
);
unsigned
int
bit_shift
=
bit_num
<<
1U
;
uint32_t
reg_val
=
gicr_read_icfgr1
(
base
);
/* Clear the field, and insert required configuration */
reg_val
&=
~
(
GIC_CFG_MASK
<<
bit_shift
);
reg_val
|=
((
cfg
&
GIC_CFG_MASK
)
<<
bit_shift
);
gicr_write_icfgr1
(
base
,
reg_val
);
}
drivers/arm/gic/v3/gicv3_helpers.c
View file @
6654d17e
...
...
@@ -15,263 +15,6 @@
#include "../common/gic_common_private.h"
#include "gicv3_private.h"
/*
* Accessor to read the GIC Distributor IGRPMODR corresponding to the
* interrupt `id`, 32 interrupt IDs at a time.
*/
unsigned
int
gicd_read_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
n
=
id
>>
IGRPMODR_SHIFT
;
return
mmio_read_32
(
base
+
GICD_IGRPMODR
+
(
n
<<
2
));
}
/*
* Accessor to write the GIC Distributor IGRPMODR corresponding to the
* interrupt `id`, 32 interrupt IDs at a time.
*/
void
gicd_write_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
,
unsigned
int
val
)
{
unsigned
int
n
=
id
>>
IGRPMODR_SHIFT
;
mmio_write_32
(
base
+
GICD_IGRPMODR
+
(
n
<<
2
),
val
);
}
/*
* Accessor to get the bit corresponding to interrupt ID
* in GIC Distributor IGRPMODR.
*/
unsigned
int
gicd_get_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGRPMODR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicd_read_igrpmodr
(
base
,
id
);
return
(
reg_val
>>
bit_num
)
&
0x1U
;
}
/*
* Accessor to set the bit corresponding to interrupt ID
* in GIC Distributor IGRPMODR.
*/
void
gicd_set_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGRPMODR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicd_read_igrpmodr
(
base
,
id
);
gicd_write_igrpmodr
(
base
,
id
,
reg_val
|
(
1U
<<
bit_num
));
}
/*
* Accessor to clear the bit corresponding to interrupt ID
* in GIC Distributor IGRPMODR.
*/
void
gicd_clr_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGRPMODR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicd_read_igrpmodr
(
base
,
id
);
gicd_write_igrpmodr
(
base
,
id
,
reg_val
&
~
(
1U
<<
bit_num
));
}
/*
* Accessor to read the GIC Re-distributor IPRIORITYR corresponding to the
* interrupt `id`, 4 interrupts IDs at a time.
*/
unsigned
int
gicr_read_ipriorityr
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
n
=
id
>>
IPRIORITYR_SHIFT
;
return
mmio_read_32
(
base
+
GICR_IPRIORITYR
+
(
n
<<
2
));
}
/*
* Accessor to write the GIC Re-distributor IPRIORITYR corresponding to the
* interrupt `id`, 4 interrupts IDs at a time.
*/
void
gicr_write_ipriorityr
(
uintptr_t
base
,
unsigned
int
id
,
unsigned
int
val
)
{
unsigned
int
n
=
id
>>
IPRIORITYR_SHIFT
;
mmio_write_32
(
base
+
GICR_IPRIORITYR
+
(
n
<<
2
),
val
);
}
/*
* Accessor to get the bit corresponding to interrupt ID
* from GIC Re-distributor IGROUPR0.
*/
unsigned
int
gicr_get_igroupr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGROUPR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igroupr0
(
base
);
return
(
reg_val
>>
bit_num
)
&
0x1U
;
}
/*
* Accessor to set the bit corresponding to interrupt ID
* in GIC Re-distributor IGROUPR0.
*/
void
gicr_set_igroupr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGROUPR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igroupr0
(
base
);
gicr_write_igroupr0
(
base
,
reg_val
|
(
1U
<<
bit_num
));
}
/*
* Accessor to clear the bit corresponding to interrupt ID
* in GIC Re-distributor IGROUPR0.
*/
void
gicr_clr_igroupr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGROUPR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igroupr0
(
base
);
gicr_write_igroupr0
(
base
,
reg_val
&
~
(
1U
<<
bit_num
));
}
/*
* Accessor to get the bit corresponding to interrupt ID
* from GIC Re-distributor IGRPMODR0.
*/
unsigned
int
gicr_get_igrpmodr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGRPMODR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igrpmodr0
(
base
);
return
(
reg_val
>>
bit_num
)
&
0x1U
;
}
/*
* Accessor to set the bit corresponding to interrupt ID
* in GIC Re-distributor IGRPMODR0.
*/
void
gicr_set_igrpmodr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGRPMODR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igrpmodr0
(
base
);
gicr_write_igrpmodr0
(
base
,
reg_val
|
(
1U
<<
bit_num
));
}
/*
* Accessor to clear the bit corresponding to interrupt ID
* in GIC Re-distributor IGRPMODR0.
*/
void
gicr_clr_igrpmodr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
IGRPMODR_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_igrpmodr0
(
base
);
gicr_write_igrpmodr0
(
base
,
reg_val
&
~
(
1U
<<
bit_num
));
}
/*
* Accessor to set the bit corresponding to interrupt ID
* in GIC Re-distributor ISENABLER0.
*/
void
gicr_set_isenabler0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
ISENABLER_SHIFT
)
-
1U
);
gicr_write_isenabler0
(
base
,
(
1U
<<
bit_num
));
}
/*
* Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
* ICENABLER0.
*/
void
gicr_set_icenabler0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
ICENABLER_SHIFT
)
-
1U
);
gicr_write_icenabler0
(
base
,
(
1U
<<
bit_num
));
}
/*
* Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
* ISACTIVER0.
*/
unsigned
int
gicr_get_isactiver0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
ISACTIVER_SHIFT
)
-
1U
);
unsigned
int
reg_val
=
gicr_read_isactiver0
(
base
);
return
(
reg_val
>>
bit_num
)
&
0x1U
;
}
/*
* Accessor to clear the bit corresponding to interrupt ID in GIC Re-distributor
* ICPENDRR0.
*/
void
gicr_set_icpendr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
ICPENDR_SHIFT
)
-
1U
);
gicr_write_icpendr0
(
base
,
(
1U
<<
bit_num
));
}
/*
* Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
* ISPENDR0.
*/
void
gicr_set_ispendr0
(
uintptr_t
base
,
unsigned
int
id
)
{
unsigned
int
bit_num
=
id
&
((
1U
<<
ISPENDR_SHIFT
)
-
1U
);
gicr_write_ispendr0
(
base
,
(
1U
<<
bit_num
));
}
/*
* Accessor to set the byte corresponding to interrupt ID
* in GIC Re-distributor IPRIORITYR.
*/
void
gicr_set_ipriorityr
(
uintptr_t
base
,
unsigned
int
id
,
unsigned
int
pri
)
{
uint8_t
val
=
pri
&
GIC_PRI_MASK
;
mmio_write_8
(
base
+
GICR_IPRIORITYR
+
id
,
val
);
}
/*
* Accessor to set the bit fields corresponding to interrupt ID
* in GIC Re-distributor ICFGR0.
*/
void
gicr_set_icfgr0
(
uintptr_t
base
,
unsigned
int
id
,
unsigned
int
cfg
)
{
/* Interrupt configuration is a 2-bit field */
unsigned
int
bit_num
=
id
&
((
1U
<<
ICFGR_SHIFT
)
-
1U
);
unsigned
int
bit_shift
=
bit_num
<<
1U
;
uint32_t
reg_val
=
gicr_read_icfgr0
(
base
);
/* Clear the field, and insert required configuration */
reg_val
&=
~
(
GIC_CFG_MASK
<<
bit_shift
);
reg_val
|=
((
cfg
&
GIC_CFG_MASK
)
<<
bit_shift
);
gicr_write_icfgr0
(
base
,
reg_val
);
}
/*
* Accessor to set the bit fields corresponding to interrupt ID
* in GIC Re-distributor ICFGR1.
*/
void
gicr_set_icfgr1
(
uintptr_t
base
,
unsigned
int
id
,
unsigned
int
cfg
)
{
/* Interrupt configuration is a 2-bit field */
unsigned
int
bit_num
=
id
&
((
1U
<<
ICFGR_SHIFT
)
-
1U
);
unsigned
int
bit_shift
=
bit_num
<<
1U
;
uint32_t
reg_val
=
gicr_read_icfgr1
(
base
);
/* Clear the field, and insert required configuration */
reg_val
&=
~
(
GIC_CFG_MASK
<<
bit_shift
);
reg_val
|=
((
cfg
&
GIC_CFG_MASK
)
<<
bit_shift
);
gicr_write_icfgr1
(
base
,
reg_val
);
}
/******************************************************************************
* This function marks the core as awake in the re-distributor and
* ensures that the interface is active.
...
...
@@ -292,7 +35,6 @@ void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base)
;
}
/******************************************************************************
* This function marks the core as asleep in the re-distributor and ensures
* that the interface is quiescent.
...
...
drivers/arm/gic/v3/gicv3_private.h
View file @
6654d17e
/*
* Copyright (c) 2015-20
18
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-20
20
, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
...
...
@@ -24,6 +24,100 @@
#define RWP_TRUE U(1)
#define RWP_FALSE U(0)
/* Calculate GIC register bit number corresponding to its interrupt ID */
#define BIT_NUM(REG, id) \
((id) & ((1U << REG##_SHIFT) - 1U))
/* Calculate 8-bit GICD register offset corresponding to its interrupt ID */
#define GICD_OFFSET_8(REG, id) \
GICD_##REG + (id)
/* Calculate 32-bit GICD register offset corresponding to its interrupt ID */
#define GICD_OFFSET(REG, id) \
GICD_##REG + (((id) >> REG##_SHIFT) << 2)
/* Calculate 64-bit GICD register offset corresponding to its interrupt ID */
#define GICD_OFFSET_64(REG, id) \
GICD_##REG + (((id) >> REG##_SHIFT) << 3)
/* Read 32-bit GIC Distributor register corresponding to its interrupt ID */
#define GICD_READ(REG, base, id) \
mmio_read_32((base) + GICD_OFFSET(REG, (id)))
/* Read 64-bit GIC Distributor register corresponding to its interrupt ID */
#define GICD_READ_64(REG, base, id) \
mmio_read_64((base) + GICD_OFFSET_64(REG, (id)))
/* Write to 64-bit GIC Distributor register corresponding to its interrupt ID */
#define GICD_WRITE_64(REG, base, id, val) \
mmio_write_64((base) + GICD_OFFSET_64(REG, (id)), (val))
/* Write to 32-bit GIC Distributor register corresponding to its interrupt ID */
#define GICD_WRITE(REG, base, id, val) \
mmio_write_32((base) + GICD_OFFSET(REG, (id)), (val))
/* Write to 8-bit GIC Distributor register corresponding to its interrupt ID */
#define GICD_WRITE_8(REG, base, id, val) \
mmio_write_8((base) + GICD_OFFSET_8(REG, (id)), (val))
/*
* Bit operations on GIC Distributor register corresponding
* to its interrupt ID
*/
/* Get bit in GIC Distributor register */
#define GICD_GET_BIT(REG, base, id) \
((mmio_read_32((base) + GICD_OFFSET(REG, (id))) >> \
BIT_NUM(REG, (id))) & 1U)
/* Set bit in GIC Distributor register */
#define GICD_SET_BIT(REG, base, id) \
mmio_setbits_32((base) + GICD_OFFSET(REG, (id)), \
((uint32_t)1 << BIT_NUM(REG, (id))))
/* Clear bit in GIC Distributor register */
#define GICD_CLR_BIT(REG, base, id) \
mmio_clrbits_32((base) + GICD_OFFSET(REG, (id)), \
((uint32_t)1 << BIT_NUM(REG, (id))))
/* Write bit in GIC Distributor register */
#define GICD_WRITE_BIT(REG, base, id) \
mmio_write_32((base) + GICD_OFFSET(REG, (id)), \
((uint32_t)1 << BIT_NUM(REG, (id))))
/*
* Calculate GICv3 GICR register offset
*/
#define GICR_OFFSET(REG, id) \
GICR_##REG + (((id) >> REG##_SHIFT) << 2)
/* Write to GIC Redistributor register corresponding to its interrupt ID */
#define GICR_WRITE_8(REG, base, id, val) \
mmio_write_8((base) + GICR_##REG + (id), (val))
/*
* Bit operations on GIC Redistributor register
* corresponding to its interrupt ID
*/
/* Get bit in GIC Redistributor register */
#define GICR_GET_BIT(REG, base, id) \
((mmio_read_32((base) + GICR_OFFSET(REG, (id))) >> \
BIT_NUM(REG, (id))) & 1U)
/* Write bit in GIC Redistributor register */
#define GICR_WRITE_BIT(REG, base, id) \
mmio_write_32((base) + GICR_OFFSET(REG, (id)), \
((uint32_t)1 << BIT_NUM(REG, (id))))
/* Set bit in GIC Redistributor register */
#define GICR_SET_BIT(REG, base, id) \
mmio_setbits_32((base) + GICR_OFFSET(REG, (id)), \
((uint32_t)1 << BIT_NUM(REG, (id))))
/* Clear bit in GIC Redistributor register */
#define GICR_CLR_BIT(REG, base, id) \
mmio_clrbits_32((base) + GICR_OFFSET(REG, (id)), \
((uint32_t)1 << BIT_NUM(REG, (id))))
/*
* Macro to convert an mpidr to a value suitable for programming into a
* GICD_IROUTER. Bits[31:24] in the MPIDR are cleared as they are not relevant
...
...
@@ -63,9 +157,9 @@ extern const gicv3_driver_data_t *gicv3_driver_data;
* Note: The raw register values correspond to multiple interrupt IDs and
* the number of interrupt IDs involved depends on the register accessed.
******************************************************************************/
u
nsigned
in
t
gicd_read_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
);
u
int32_
t
gicd_read_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
);
unsigned
int
gicr_read_ipriorityr
(
uintptr_t
base
,
unsigned
int
id
);
void
gicd_write_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
,
u
nsigned
in
t
val
);
void
gicd_write_igrpmodr
(
uintptr_t
base
,
unsigned
int
id
,
u
int32_
t
val
);
void
gicr_write_ipriorityr
(
uintptr_t
base
,
unsigned
int
id
,
unsigned
int
val
);
/*******************************************************************************
...
...
@@ -121,27 +215,27 @@ void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base);
*/
static
inline
void
gicd_wait_for_pending_write
(
uintptr_t
gicd_base
)
{
while
((
gicd_read_ctlr
(
gicd_base
)
&
GICD_CTLR_RWP_BIT
)
!=
0U
)
;
while
((
gicd_read_ctlr
(
gicd_base
)
&
GICD_CTLR_RWP_BIT
)
!=
0U
)
{
}
}
static
inline
u
nsigned
in
t
gicd_read_pidr2
(
uintptr_t
base
)
static
inline
u
int32_
t
gicd_read_pidr2
(
uintptr_t
base
)
{
return
mmio_read_32
(
base
+
GICD_PIDR2_GICV3
);
}
static
inline
u
nsigned
long
long
gicd_read_irouter
(
uintptr_t
base
,
unsigned
int
id
)
static
inline
u
int64_t
gicd_read_irouter
(
uintptr_t
base
,
unsigned
int
id
)
{
assert
(
id
>=
MIN_SPI_ID
);
return
mmio_read_64
(
base
+
GICD_IROUTER
+
(
id
<<
3
)
);
return
GICD_READ_64
(
IROUTER
,
base
,
id
);
}
static
inline
void
gicd_write_irouter
(
uintptr_t
base
,
unsigned
int
id
,
u
nsigned
long
long
affinity
)
u
int64_t
affinity
)
{
assert
(
id
>=
MIN_SPI_ID
);
mmio_write_64
(
base
+
GICD_IROUTER
+
(
id
<<
3
)
,
affinity
);
GICD_WRITE_64
(
IROUTER
,
base
,
id
,
affinity
);
}
static
inline
void
gicd_clr_ctlr
(
uintptr_t
base
,
...
...
@@ -149,8 +243,9 @@ static inline void gicd_clr_ctlr(uintptr_t base,
unsigned
int
rwp
)
{
gicd_write_ctlr
(
base
,
gicd_read_ctlr
(
base
)
&
~
bitmap
);
if
(
rwp
!=
0U
)
if
(
rwp
!=
0U
)
{
gicd_wait_for_pending_write
(
base
);
}
}
static
inline
void
gicd_set_ctlr
(
uintptr_t
base
,
...
...
@@ -158,8 +253,9 @@ static inline void gicd_set_ctlr(uintptr_t base,
unsigned
int
rwp
)
{
gicd_write_ctlr
(
base
,
gicd_read_ctlr
(
base
)
|
bitmap
);
if
(
rwp
!=
0U
)
if
(
rwp
!=
0U
)
{
gicd_wait_for_pending_write
(
base
);
}
}
/*******************************************************************************
...
...
@@ -175,17 +271,17 @@ static inline void gicr_write_ctlr(uintptr_t base, uint32_t val)
mmio_write_32
(
base
+
GICR_CTLR
,
val
);
}
static
inline
u
nsigned
long
long
gicr_read_typer
(
uintptr_t
base
)
static
inline
u
int64_t
gicr_read_typer
(
uintptr_t
base
)
{
return
mmio_read_64
(
base
+
GICR_TYPER
);
}
static
inline
u
nsigned
in
t
gicr_read_waker
(
uintptr_t
base
)
static
inline
u
int32_
t
gicr_read_waker
(
uintptr_t
base
)
{
return
mmio_read_32
(
base
+
GICR_WAKER
);
}
static
inline
void
gicr_write_waker
(
uintptr_t
base
,
u
nsigned
in
t
val
)
static
inline
void
gicr_write_waker
(
uintptr_t
base
,
u
int32_
t
val
)
{
mmio_write_32
(
base
+
GICR_WAKER
,
val
);
}
...
...
@@ -199,14 +295,14 @@ static inline void gicr_write_waker(uintptr_t base, unsigned int val)
*/
static
inline
void
gicr_wait_for_pending_write
(
uintptr_t
gicr_base
)
{
while
((
gicr_read_ctlr
(
gicr_base
)
&
GICR_CTLR_RWP_BIT
)
!=
0U
)
;
while
((
gicr_read_ctlr
(
gicr_base
)
&
GICR_CTLR_RWP_BIT
)
!=
0U
)
{
}
}
static
inline
void
gicr_wait_for_upstream_pending_write
(
uintptr_t
gicr_base
)
{
while
((
gicr_read_ctlr
(
gicr_base
)
&
GICR_CTLR_UWP_BIT
)
!=
0U
)
;
while
((
gicr_read_ctlr
(
gicr_base
)
&
GICR_CTLR_UWP_BIT
)
!=
0U
)
{
}
}
/* Private implementation of Distributor power control hooks */
...
...
@@ -214,7 +310,7 @@ void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num);
void
arm_gicv3_distif_post_restore
(
unsigned
int
rdist_proc_num
);
/*******************************************************************************
* GIC Re
-
distributor functions for accessing entire registers.
* GIC Redistributor functions for accessing entire registers.
* Note: The raw register values correspond to multiple interrupt IDs and
* the number of interrupt IDs involved depends on the register accessed.
******************************************************************************/
...
...
@@ -341,7 +437,7 @@ static inline uint32_t gits_read_ctlr(uintptr_t base)
return
mmio_read_32
(
base
+
GITS_CTLR
);
}
static
inline
void
gits_write_ctlr
(
uintptr_t
base
,
u
nsigned
in
t
val
)
static
inline
void
gits_write_ctlr
(
uintptr_t
base
,
u
int32_
t
val
)
{
mmio_write_32
(
base
+
GITS_CTLR
,
val
);
}
...
...
@@ -366,13 +462,15 @@ static inline void gits_write_cwriter(uintptr_t base, uint64_t val)
mmio_write_64
(
base
+
GITS_CWRITER
,
val
);
}
static
inline
uint64_t
gits_read_baser
(
uintptr_t
base
,
unsigned
int
its_table_id
)
static
inline
uint64_t
gits_read_baser
(
uintptr_t
base
,
unsigned
int
its_table_id
)
{
assert
(
its_table_id
<
8U
);
return
mmio_read_64
(
base
+
GITS_BASER
+
(
8U
*
its_table_id
));
}
static
inline
void
gits_write_baser
(
uintptr_t
base
,
unsigned
int
its_table_id
,
uint64_t
val
)
static
inline
void
gits_write_baser
(
uintptr_t
base
,
unsigned
int
its_table_id
,
uint64_t
val
)
{
assert
(
its_table_id
<
8U
);
mmio_write_64
(
base
+
GITS_BASER
+
(
8U
*
its_table_id
),
val
);
...
...
@@ -384,9 +482,8 @@ static inline void gits_write_baser(uintptr_t base, unsigned int its_table_id, u
static
inline
void
gits_wait_for_quiescent_bit
(
uintptr_t
gits_base
)
{
assert
((
gits_read_ctlr
(
gits_base
)
&
GITS_CTLR_ENABLED_BIT
)
==
0U
);
while
((
gits_read_ctlr
(
gits_base
)
&
GITS_CTLR_QUIESCENT_BIT
)
==
0U
)
;
while
((
gits_read_ctlr
(
gits_base
)
&
GITS_CTLR_QUIESCENT_BIT
)
==
0U
)
{
}
}
#endif
/* GICV3_PRIVATE_H */
include/drivers/arm/gicv3.h
View file @
6654d17e
/*
* Copyright (c) 2015-20
19
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-20
20
, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
...
...
@@ -32,7 +32,7 @@
#define GICD_SETSPI_NSR U(0x40)
#define GICD_CLRSPI_NSR U(0x48)
#define GICD_SETSPI_SR U(0x50)
#define GICD_CLRSPI_SR U(0x5
0
)
#define GICD_CLRSPI_SR U(0x5
8
)
#define GICD_IGRPMODR U(0xd00)
/*
* GICD_IROUTER<n> register is at 0x6000 + 8n, where n is the interrupt id and
...
...
@@ -79,7 +79,7 @@
#define NUM_OF_DIST_REGS 30
/*******************************************************************************
* GICv3 Re
-
distributor interface registers & constants
* GICv3 Redistributor interface registers & constants
******************************************************************************/
#define GICR_PCPUBASE_SHIFT 0x11
#define GICR_SGIBASE_OFFSET U(65536)
/* 64 KB */
...
...
plat/arm/board/fvp/platform.mk
View file @
6654d17e
...
...
@@ -56,6 +56,8 @@ $(eval $(call add_define,FVP_INTERCONNECT_DRIVER))
FVP_GICV3_SOURCES
:=
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v3/gicv3_main.c
\
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
plat/common/plat_gicv3.c
\
plat/arm/common/arm_gicv3.c
...
...
plat/arm/board/n1sdp/platform.mk
View file @
6654d17e
#
# Copyright (c) 2018-20
19
, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2018-20
20
, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
...
...
@@ -18,6 +18,8 @@ N1SDP_CPU_SOURCES := lib/cpus/aarch64/neoverse_n1.S
N1SDP_GIC_SOURCES
:=
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v3/gicv3_main.c
\
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
drivers/arm/gic/v3/gic600_multichip.c
\
plat/common/plat_gicv3.c
\
plat/arm/common/arm_gicv3.c
\
...
...
plat/arm/css/sgi/sgi-common.mk
View file @
6654d17e
#
# Copyright (c) 2018-20
19
, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2018-20
20
, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
...
...
@@ -25,6 +25,8 @@ PLAT_INCLUDES += -I${CSS_ENT_BASE}/include
ENT_GIC_SOURCES
:=
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v3/gicv3_main.c
\
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
plat/common/plat_gicv3.c
\
plat/arm/common/arm_gicv3.c
\
drivers/arm/gic/v3/gic600.c
...
...
plat/arm/css/sgm/sgm-common.mk
View file @
6654d17e
#
# Copyright (c) 2018-20
19
, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2018-20
20
, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
...
...
@@ -25,6 +25,8 @@ INTERCONNECT_SOURCES := ${CSS_SGM_BASE}/sgm_interconnect.c
SGM_GIC_SOURCES
:=
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v3/gicv3_main.c
\
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
plat/common/plat_gicv3.c
\
plat/arm/common/arm_gicv3.c
\
drivers/arm/gic/v3/gic600.c
\
...
...
plat/imx/imx8m/imx8mm/platform.mk
View file @
6654d17e
#
# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2019
-2020
, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
...
...
@@ -9,6 +9,8 @@ PLAT_INCLUDES := -Iplat/imx/common/include \
-Iplat
/imx/imx8m/imx8mm/include
IMX_GIC_SOURCES
:=
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
drivers/arm/gic/v3/arm_gicv3_common.c
\
drivers/arm/gic/v3/gic500.c
\
drivers/arm/gic/v3/gicv3_main.c
\
...
...
plat/imx/imx8m/imx8mq/platform.mk
View file @
6654d17e
#
# Copyright (c) 2018-20
19
, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2018-20
20
, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
...
...
@@ -9,6 +9,8 @@ PLAT_INCLUDES := -Iplat/imx/common/include \
-Iplat
/imx/imx8m/imx8mq/include
IMX_GIC_SOURCES
:=
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
drivers/arm/gic/v3/arm_gicv3_common.c
\
drivers/arm/gic/v3/gic500.c
\
drivers/arm/gic/v3/gicv3_main.c
\
...
...
plat/imx/imx8qm/platform.mk
View file @
6654d17e
#
# Copyright (c) 2015-20
18
, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2015-20
20
, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
...
...
@@ -8,6 +8,8 @@ PLAT_INCLUDES := -Iplat/imx/imx8qm/include \
-Iplat
/imx/common/include
\
IMX_GIC_SOURCES
:=
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
drivers/arm/gic/v3/arm_gicv3_common.c
\
drivers/arm/gic/v3/gic500.c
\
drivers/arm/gic/v3/gicv3_main.c
\
...
...
plat/imx/imx8qx/platform.mk
View file @
6654d17e
#
# Copyright (c) 2015-20
18
, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2015-20
20
, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
...
...
@@ -8,6 +8,8 @@ PLAT_INCLUDES := -Iplat/imx/imx8qx/include \
-Iplat
/imx/common/include
\
IMX_GIC_SOURCES
:=
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
drivers/arm/gic/v3/arm_gicv3_common.c
\
drivers/arm/gic/v3/gic500.c
\
drivers/arm/gic/v3/gicv3_main.c
\
...
...
plat/marvell/a3700/common/a3700_common.mk
View file @
6654d17e
...
...
@@ -81,6 +81,8 @@ $(eval $(call add_define,USE_CCI))
MARVELL_GIC_SOURCES
:=
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v3/gicv3_main.c
\
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
drivers/arm/gic/v3/arm_gicv3_common.c
\
plat/common/plat_gicv3.c
\
drivers/arm/gic/v3/gic500.c
...
...
plat/mediatek/mt8183/platform.mk
View file @
6654d17e
...
...
@@ -31,6 +31,8 @@ BL31_SOURCES += common/desc_image_load.c \
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v3/arm_gicv3_common.c
\
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
drivers/arm/gic/v3/gic500.c
\
drivers/arm/gic/v3/gicv3_main.c
\
drivers/delay_timer/delay_timer.c
\
...
...
plat/qemu/qemu/platform.mk
View file @
6654d17e
#
# Copyright (c) 2013-20
19
, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2013-20
20
, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
...
...
@@ -140,6 +140,8 @@ QEMU_GICV2_SOURCES := drivers/arm/gic/v2/gicv2_helpers.c \
${PLAT_QEMU_COMMON_PATH}
/qemu_gicv2.c
QEMU_GICV3_SOURCES
:=
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
drivers/arm/gic/v3/gicv3_main.c
\
drivers/arm/gic/common/gic_common.c
\
plat/common/plat_gicv3.c
\
...
...
plat/qemu/qemu_sbsa/platform.mk
View file @
6654d17e
...
...
@@ -63,6 +63,8 @@ BL2_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_bl2_mem_params_desc.c \
endif
QEMU_GIC_SOURCES
:=
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
drivers/arm/gic/v3/gicv3_main.c
\
drivers/arm/gic/common/gic_common.c
\
plat/common/plat_gicv3.c
\
...
...
plat/rockchip/rk3399/platform.mk
View file @
6654d17e
#
# Copyright (c) 2016-20
19
, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2016-20
20
, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
...
...
@@ -29,6 +29,8 @@ RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
drivers/arm/gic/v3/gic500.c
\
drivers/arm/gic/v3/gicv3_main.c
\
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
plat/common/plat_gicv3.c
\
${RK_PLAT}
/common/rockchip_gicv3.c
...
...
plat/socionext/synquacer/platform.mk
View file @
6654d17e
#
# Copyright (c) 2018-20
19
, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2018-20
20
, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
...
...
@@ -33,6 +33,8 @@ PLAT_BL_COMMON_SOURCES += $(PLAT_PATH)/sq_helpers.S \
BL31_SOURCES
+=
drivers/arm/ccn/ccn.c
\
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
drivers/arm/gic/v3/gicv3_main.c
\
lib/cpus/aarch64/cortex_a53.S
\
plat/common/plat_gicv3.c
\
...
...
plat/socionext/uniphier/platform.mk
View file @
6654d17e
...
...
@@ -58,6 +58,8 @@ BL2_SOURCES += common/desc_image_load.c \
BL31_SOURCES
+=
drivers/arm/cci/cci.c
\
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/gicdv3_helpers.c
\
drivers/arm/gic/v3/gicrv3_helpers.c
\
drivers/arm/gic/v3/gicv3_main.c
\
lib/cpus/aarch64/cortex_a53.S
\
lib/cpus/aarch64/cortex_a72.S
\
...
...
Prev
1
2
Next
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