1*a2847172SGrzegorz Jaszczyk /*
2*a2847172SGrzegorz Jaszczyk * Copyright (C) 2018 Marvell International Ltd.
3*a2847172SGrzegorz Jaszczyk *
4*a2847172SGrzegorz Jaszczyk * SPDX-License-Identifier: BSD-3-Clause
5*a2847172SGrzegorz Jaszczyk * https://spdx.org/licenses
6*a2847172SGrzegorz Jaszczyk */
7*a2847172SGrzegorz Jaszczyk
8*a2847172SGrzegorz Jaszczyk #include <platform_def.h>
9*a2847172SGrzegorz Jaszczyk
10*a2847172SGrzegorz Jaszczyk #include <bl31/interrupt_mgmt.h>
11*a2847172SGrzegorz Jaszczyk #include <common/debug.h>
12*a2847172SGrzegorz Jaszczyk #include <drivers/arm/gicv2.h>
13*a2847172SGrzegorz Jaszczyk #include <lib/bakery_lock.h>
14*a2847172SGrzegorz Jaszczyk #include <lib/mmio.h>
15*a2847172SGrzegorz Jaszczyk #include <plat/common/platform.h>
16*a2847172SGrzegorz Jaszczyk
17*a2847172SGrzegorz Jaszczyk #include <plat_marvell.h>
18*a2847172SGrzegorz Jaszczyk
19*a2847172SGrzegorz Jaszczyk /*
20*a2847172SGrzegorz Jaszczyk * The following functions are defined as weak to allow a platform to override
21*a2847172SGrzegorz Jaszczyk * the way the GICv2 driver is initialised and used.
22*a2847172SGrzegorz Jaszczyk */
23*a2847172SGrzegorz Jaszczyk #pragma weak plat_marvell_gic_driver_init
24*a2847172SGrzegorz Jaszczyk #pragma weak plat_marvell_gic_init
25*a2847172SGrzegorz Jaszczyk
26*a2847172SGrzegorz Jaszczyk #define A7K8K_PIC_CAUSE_REG 0xf03f0100
27*a2847172SGrzegorz Jaszczyk #define A7K8K_PIC0_MASK_REG 0xf03f0108
28*a2847172SGrzegorz Jaszczyk
29*a2847172SGrzegorz Jaszczyk #define A7K8K_PIC_PMUOF_IRQ_MASK (1 << 17)
30*a2847172SGrzegorz Jaszczyk
31*a2847172SGrzegorz Jaszczyk #define A7K8K_PIC_MAX_IRQS 32
32*a2847172SGrzegorz Jaszczyk #define A7K8K_PIC_MAX_IRQ_MASK ((1UL << A7K8K_PIC_MAX_IRQS) - 1)
33*a2847172SGrzegorz Jaszczyk
34*a2847172SGrzegorz Jaszczyk #define A7K8K_ODMIN_SET_REG 0xf0300040
35*a2847172SGrzegorz Jaszczyk #define A7K8K_ODMI_PMU_IRQ(idx) ((2 + idx) << 12)
36*a2847172SGrzegorz Jaszczyk
37*a2847172SGrzegorz Jaszczyk #define A7K8K_ODMI_PMU_GIC_IRQ(idx) (130 + idx)
38*a2847172SGrzegorz Jaszczyk
39*a2847172SGrzegorz Jaszczyk static DEFINE_BAKERY_LOCK(a7k8k_irq_lock);
40*a2847172SGrzegorz Jaszczyk
41*a2847172SGrzegorz Jaszczyk /*
42*a2847172SGrzegorz Jaszczyk * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
43*a2847172SGrzegorz Jaszczyk * interrupts.
44*a2847172SGrzegorz Jaszczyk */
45*a2847172SGrzegorz Jaszczyk static const interrupt_prop_t marvell_interrupt_props[] = {
46*a2847172SGrzegorz Jaszczyk PLAT_MARVELL_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
47*a2847172SGrzegorz Jaszczyk PLAT_MARVELL_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
48*a2847172SGrzegorz Jaszczyk };
49*a2847172SGrzegorz Jaszczyk
50*a2847172SGrzegorz Jaszczyk static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
51*a2847172SGrzegorz Jaszczyk
52*a2847172SGrzegorz Jaszczyk /*
53*a2847172SGrzegorz Jaszczyk * Ideally `marvell_gic_data` structure definition should be a `const` but it is
54*a2847172SGrzegorz Jaszczyk * kept as modifiable for overwriting with different GICD and GICC base when
55*a2847172SGrzegorz Jaszczyk * running on FVP with VE memory map.
56*a2847172SGrzegorz Jaszczyk */
57*a2847172SGrzegorz Jaszczyk static gicv2_driver_data_t marvell_gic_data = {
58*a2847172SGrzegorz Jaszczyk .gicd_base = PLAT_MARVELL_GICD_BASE,
59*a2847172SGrzegorz Jaszczyk .gicc_base = PLAT_MARVELL_GICC_BASE,
60*a2847172SGrzegorz Jaszczyk .interrupt_props = marvell_interrupt_props,
61*a2847172SGrzegorz Jaszczyk .interrupt_props_num = ARRAY_SIZE(marvell_interrupt_props),
62*a2847172SGrzegorz Jaszczyk .target_masks = target_mask_array,
63*a2847172SGrzegorz Jaszczyk .target_masks_num = ARRAY_SIZE(target_mask_array),
64*a2847172SGrzegorz Jaszczyk };
65*a2847172SGrzegorz Jaszczyk
66*a2847172SGrzegorz Jaszczyk /*
67*a2847172SGrzegorz Jaszczyk * ARM common helper to initialize the GICv2 only driver.
68*a2847172SGrzegorz Jaszczyk */
plat_marvell_gic_driver_init(void)69*a2847172SGrzegorz Jaszczyk void plat_marvell_gic_driver_init(void)
70*a2847172SGrzegorz Jaszczyk {
71*a2847172SGrzegorz Jaszczyk gicv2_driver_init(&marvell_gic_data);
72*a2847172SGrzegorz Jaszczyk }
73*a2847172SGrzegorz Jaszczyk
a7k8k_pmu_interrupt_handler(uint32_t id,uint32_t flags,void * handle,void * cookie)74*a2847172SGrzegorz Jaszczyk static uint64_t a7k8k_pmu_interrupt_handler(uint32_t id,
75*a2847172SGrzegorz Jaszczyk uint32_t flags,
76*a2847172SGrzegorz Jaszczyk void *handle,
77*a2847172SGrzegorz Jaszczyk void *cookie)
78*a2847172SGrzegorz Jaszczyk {
79*a2847172SGrzegorz Jaszczyk unsigned int idx = plat_my_core_pos();
80*a2847172SGrzegorz Jaszczyk uint32_t irq;
81*a2847172SGrzegorz Jaszczyk
82*a2847172SGrzegorz Jaszczyk bakery_lock_get(&a7k8k_irq_lock);
83*a2847172SGrzegorz Jaszczyk
84*a2847172SGrzegorz Jaszczyk /* Acknowledge IRQ */
85*a2847172SGrzegorz Jaszczyk irq = plat_ic_acknowledge_interrupt();
86*a2847172SGrzegorz Jaszczyk
87*a2847172SGrzegorz Jaszczyk plat_ic_end_of_interrupt(irq);
88*a2847172SGrzegorz Jaszczyk
89*a2847172SGrzegorz Jaszczyk if (irq != MARVELL_IRQ_PIC0) {
90*a2847172SGrzegorz Jaszczyk bakery_lock_release(&a7k8k_irq_lock);
91*a2847172SGrzegorz Jaszczyk return 0;
92*a2847172SGrzegorz Jaszczyk }
93*a2847172SGrzegorz Jaszczyk
94*a2847172SGrzegorz Jaszczyk /* Acknowledge PMU overflow IRQ in PIC0 */
95*a2847172SGrzegorz Jaszczyk mmio_setbits_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_PMUOF_IRQ_MASK);
96*a2847172SGrzegorz Jaszczyk
97*a2847172SGrzegorz Jaszczyk /* Trigger ODMI Frame IRQ */
98*a2847172SGrzegorz Jaszczyk mmio_write_32(A7K8K_ODMIN_SET_REG, A7K8K_ODMI_PMU_IRQ(idx));
99*a2847172SGrzegorz Jaszczyk
100*a2847172SGrzegorz Jaszczyk bakery_lock_release(&a7k8k_irq_lock);
101*a2847172SGrzegorz Jaszczyk
102*a2847172SGrzegorz Jaszczyk return 0;
103*a2847172SGrzegorz Jaszczyk }
104*a2847172SGrzegorz Jaszczyk
mvebu_pmu_interrupt_enable(void)105*a2847172SGrzegorz Jaszczyk void mvebu_pmu_interrupt_enable(void)
106*a2847172SGrzegorz Jaszczyk {
107*a2847172SGrzegorz Jaszczyk unsigned int idx;
108*a2847172SGrzegorz Jaszczyk uint32_t flags;
109*a2847172SGrzegorz Jaszczyk int32_t rc;
110*a2847172SGrzegorz Jaszczyk
111*a2847172SGrzegorz Jaszczyk /* Reset PIC */
112*a2847172SGrzegorz Jaszczyk mmio_write_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_MAX_IRQ_MASK);
113*a2847172SGrzegorz Jaszczyk /* Unmask PMU overflow IRQ in PIC0 */
114*a2847172SGrzegorz Jaszczyk mmio_clrbits_32(A7K8K_PIC0_MASK_REG, A7K8K_PIC_PMUOF_IRQ_MASK);
115*a2847172SGrzegorz Jaszczyk
116*a2847172SGrzegorz Jaszczyk /* Configure ODMI Frame IRQs as edge triggered */
117*a2847172SGrzegorz Jaszczyk for (idx = 0; idx < PLATFORM_CORE_COUNT; idx++)
118*a2847172SGrzegorz Jaszczyk gicv2_interrupt_set_cfg(A7K8K_ODMI_PMU_GIC_IRQ(idx),
119*a2847172SGrzegorz Jaszczyk GIC_INTR_CFG_EDGE);
120*a2847172SGrzegorz Jaszczyk
121*a2847172SGrzegorz Jaszczyk /*
122*a2847172SGrzegorz Jaszczyk * Register IRQ handler as INTR_TYPE_S_EL1 as its the only valid type
123*a2847172SGrzegorz Jaszczyk * for GICv2 in ARM-TF.
124*a2847172SGrzegorz Jaszczyk */
125*a2847172SGrzegorz Jaszczyk flags = 0U;
126*a2847172SGrzegorz Jaszczyk set_interrupt_rm_flag((flags), (NON_SECURE));
127*a2847172SGrzegorz Jaszczyk rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
128*a2847172SGrzegorz Jaszczyk a7k8k_pmu_interrupt_handler,
129*a2847172SGrzegorz Jaszczyk flags);
130*a2847172SGrzegorz Jaszczyk if (rc != 0)
131*a2847172SGrzegorz Jaszczyk panic();
132*a2847172SGrzegorz Jaszczyk }
133*a2847172SGrzegorz Jaszczyk
mvebu_pmu_interrupt_disable(void)134*a2847172SGrzegorz Jaszczyk void mvebu_pmu_interrupt_disable(void)
135*a2847172SGrzegorz Jaszczyk {
136*a2847172SGrzegorz Jaszczyk /* Reset PIC */
137*a2847172SGrzegorz Jaszczyk mmio_write_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_MAX_IRQ_MASK);
138*a2847172SGrzegorz Jaszczyk /* Mask PMU overflow IRQ in PIC0 */
139*a2847172SGrzegorz Jaszczyk mmio_setbits_32(A7K8K_PIC0_MASK_REG, A7K8K_PIC_PMUOF_IRQ_MASK);
140*a2847172SGrzegorz Jaszczyk }
141*a2847172SGrzegorz Jaszczyk
plat_marvell_gic_init(void)142*a2847172SGrzegorz Jaszczyk void plat_marvell_gic_init(void)
143*a2847172SGrzegorz Jaszczyk {
144*a2847172SGrzegorz Jaszczyk gicv2_distif_init();
145*a2847172SGrzegorz Jaszczyk gicv2_pcpu_distif_init();
146*a2847172SGrzegorz Jaszczyk gicv2_set_pe_target_mask(plat_my_core_pos());
147*a2847172SGrzegorz Jaszczyk gicv2_cpuif_enable();
148*a2847172SGrzegorz Jaszczyk }
149