summaryrefslogtreecommitdiff
path: root/bsp/phytium/libraries/common/phytium_interrupt.c
blob: 0714c563f42833d4ace32de7c618472573522c6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "rtconfig.h"
#if defined(TARGET_ARMV8_AARCH64)
#include <rthw.h>
#include <rtthread.h>
#include "interrupt.h"
#include "gic.h"
#include "gicv3.h"
#include "ioremap.h"
#include "phytium_cpu.h"
#include "ftypes.h"
#include "fparameters.h"

struct arm_gic *phytium_gic_table;

extern struct rt_irq_desc isr_table[MAX_HANDLERS];

int arm_gic_redist_address_set(rt_uint64_t index, rt_uint64_t redist_addr, int cpu_id)
{
    RT_ASSERT(index < ARM_GIC_MAX_NR);

    if (cpu_id == 0)
    {
        rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, &cpu_id, sizeof(cpu_id));
    }

    phytium_gic_table[index].redist_hw_base[cpu_id] = redist_addr;

    return 0;
}

static int arm_gicv3_wait_rwp(rt_uint64_t index, rt_uint64_t irq)
{
    rt_uint64_t rwp_bit;
    rt_uint64_t base;

    RT_ASSERT(index < ARM_GIC_MAX_NR);

    if (irq < 32)
    {
        rt_int32_t cpu_id = rt_hw_cpu_id();

        base = phytium_gic_table[index].redist_hw_base[cpu_id];
        rwp_bit = GICR_CTLR_RWP;
    }
    else
    {
        base = phytium_gic_table[index].dist_hw_base;
        rwp_bit = GICD_CTLR_RWP;
    }

    while (HWREG32(base) & rwp_bit)
    {
    }

    return 0;
}

int phytium_aarch64_arm_gic_redist_init()
{
    rt_uint64_t cpu_id = rt_hw_cpu_id();
    rt_uint64_t redist_base = phytium_gic_table[0].redist_hw_base[cpu_id];

    /* redistributor enable */
    GIC_RDIST_WAKER(redist_base) &= ~(1 << 1);
    while (GIC_RDIST_WAKER(redist_base) & (1 << 2))
    {
    }

    /* Disable all sgi and ppi interrupt */
    GIC_RDISTSGI_ICENABLER0(redist_base) = 0xffffffff;
    arm_gicv3_wait_rwp(0, 0);

    /* Clear all inetrrupt pending */
    GIC_RDISTSGI_ICPENDR0(redist_base) = 0xffffffff;

    /* the corresponding interrupt is Group 1 or Non-secure Group 1. */
    GIC_RDISTSGI_IGROUPR0(redist_base, 0) = 0xffffffff;
    GIC_RDISTSGI_IGRPMODR0(redist_base, 0) = 0xffffffff;

    /* Configure default priorities for SGI 0:15 and PPI 16:31. */
    for (int i = 0; i < 32; i += 4)
    {
        GIC_RDISTSGI_IPRIORITYR(redist_base, i) = 0xa0a0a0a0U;
    }

    /* Trigger level for PPI interrupts*/
    GIC_RDISTSGI_ICFGR1(redist_base) = 0;

    return 0;
}

void phytium_interrupt_init(void)
{
    rt_uint64_t gic_cpu_base;
    rt_uint64_t gic_dist_base;
    rt_uint64_t gic_irq_start;
    rt_uint64_t redist_addr;

    phytium_gic_table = (struct arm_gic *)arm_gic_get_gic_table_addr();
    /* initialize vector table */
    rt_hw_vector_init();

    /* initialize exceptions table */
    rt_memset(isr_table, 0x00, sizeof(isr_table));

#if defined(RT_USING_SMART)
    gic_dist_base = (rt_uint64_t)rt_ioremap((void *)platform_get_gic_dist_base(), 0x40000);
    gic_cpu_base = (rt_uint64_t)rt_ioremap((void*)platform_get_gic_cpu_base(), 0x1000);
    redist_addr = (rt_uint64_t)rt_ioremap(GICV3_RD_BASE_ADDR, 4 * GICV3_RD_OFFSET);
#else
    gic_dist_base = platform_get_gic_dist_base();
    gic_cpu_base = platform_get_gic_cpu_base();
    redist_addr = GICV3_RD_BASE_ADDR;
#endif

    gic_irq_start = 0;
    arm_gic_dist_init(0, gic_dist_base, gic_irq_start);
    arm_gic_cpu_init(0, gic_cpu_base);
    arm_gic_redist_address_set(0, redist_addr + 2 * GICV3_RD_OFFSET, 0);

#if defined(TARGET_E2000Q) || defined(TARGET_PHYTIUMPI)
#if RT_CPUS_NR == 2
    arm_gic_redist_address_set(0, redist_addr + 3 * GICV3_RD_OFFSET, 1);
#elif RT_CPUS_NR == 3
    arm_gic_redist_address_set(0, redist_addr + 3 * GICV3_RD_OFFSET, 1);
    arm_gic_redist_address_set(0, redist_addr, 2);
#elif RT_CPUS_NR == 4
    arm_gic_redist_address_set(0, redist_addr + 3 * GICV3_RD_OFFSET, 1);
    arm_gic_redist_address_set(0, redist_addr, 2);
    arm_gic_redist_address_set(0, redist_addr + GICV3_RD_OFFSET, 3);
#endif
#else
#if defined(TARGET_E2000D)
    rt_uint32_t cpu_offset =  2;
#endif
#if RT_CPUS_NR == 2
    arm_gic_redist_address_set(0, redist_addr + (1 + cpu_offset) * GICV3_RD_OFFSET, 1);
#elif RT_CPUS_NR == 3
    arm_gic_redist_address_set(0, redist_addr + (1 + cpu_offset) * GICV3_RD_OFFSET, 1);
    arm_gic_redist_address_set(0, redist_addr + (2 + cpu_offset) * GICV3_RD_OFFSET, 2);
#elif RT_CPUS_NR == 4
    arm_gic_redist_address_set(0, redist_addr + (1 + cpu_offset) * GICV3_RD_OFFSET, 1);
    arm_gic_redist_address_set(0, redist_addr + (2 + cpu_offset) * GICV3_RD_OFFSET, 2);
    arm_gic_redist_address_set(0, redist_addr + (3 + cpu_offset) * GICV3_RD_OFFSET, 3);
#endif
#endif

    phytium_aarch64_arm_gic_redist_init();
}
#endif