summaryrefslogtreecommitdiff
path: root/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_l2pf0.c
blob: 63690fa38dc38718847e6052fac6a771441a0e20 (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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/* Copyright 2020 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */

#include <metal/machine/platform.h>

#ifdef METAL_SIFIVE_L2PF0

#include <metal/drivers/sifive_l2pf0.h>
#include <metal/machine.h>

/* Macros to access memory mapped registers */
#define REGW(x)                                                                \
    *(volatile uint32_t *)(METAL_SIFIVE_L2PF0_0_BASE_ADDRESS +                 \
                           hartid * 0x2000 + x)

/* Macros for register bit masks */
#define REG_MASK_BITWIDTH1 0x01
#define REG_MASK_BITWIDTH4 0x0F
#define REG_MASK_BITWIDTH5 0x1F
#define REG_MASK_BITWIDTH6 0x3F
#define REG_MASK_BITWIDTH7 0x7F

/* Macros to specify register bit shift */
#define REG_BITSHIFT_1 1
#define REG_BITSHIFT_2 2
#define REG_BITSHIFT_4 4
#define REG_BITSHIFT_8 8
#define REG_BITSHIFT_9 9
#define REG_BITSHIFT_13 13
#define REG_BITSHIFT_14 14
#define REG_BITSHIFT_20 20
#define REG_BITSHIFT_21 21
#define REG_BITSHIFT_28 28

/* Macros to capture trap, if L2PF does not exist for a hart id. */
#define SIFIVE_L2PF0_TRAP_CAPTURE(exit, mtvec)                                 \
    __asm__ __volatile__("la %0, 1f \n\t"                                      \
                         "csrr %1, mtvec \n\t"                                 \
                         "csrw mtvec, %0 \n\t"                                 \
                         : "+r"(exit), "+r"(mtvec))

#define SIFIVE_L2PF0_TRAP_RESTORE(mtvec)                                       \
    __asm__ __volatile__(".align 2 \n\t"                                       \
                         "1: \n\t"                                             \
                         "csrw mtvec, %0 \n\t"                                 \
                         : "+r"(mtvec))

void sifive_l2pf0_enable(void) {
    volatile uintptr_t exit = 0, mtvec = 0;
    int hartid;
    __asm__ volatile("csrr %0, mhartid" : "=r"(hartid));

    SIFIVE_L2PF0_TRAP_CAPTURE(exit, mtvec);

    uint32_t val = REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL);

    /* Enable L2 prefetch unit for current hart */
    val |= REG_MASK_BITWIDTH1;

    REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL) = val;

    SIFIVE_L2PF0_TRAP_RESTORE(mtvec);
}

void sifive_l2pf0_disable(void) {
    volatile uintptr_t exit = 0, mtvec = 0;
    int hartid;
    __asm__ volatile("csrr %0, mhartid" : "=r"(hartid));

    SIFIVE_L2PF0_TRAP_CAPTURE(exit, mtvec);

    uint32_t val = REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL);

    /* Disable L2 prefetch unit for current hart */
    val &= ~REG_MASK_BITWIDTH1;

    REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL) = val;

    SIFIVE_L2PF0_TRAP_RESTORE(mtvec);
}

void sifive_l2pf0_get_config(sifive_l2pf0_config *config) {
    volatile uintptr_t exit = 0, mtvec = 0;
    int hartid;
    __asm__ volatile("csrr %0, mhartid" : "=r"(hartid));
    uint32_t val;

    SIFIVE_L2PF0_TRAP_CAPTURE(exit, mtvec);

    if (config) /* Check for NULL */
    {
        /* Get currently active L2 prefetch configuration values */
        val = REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL);

        config->HwPrefetchEnable = (val & REG_MASK_BITWIDTH1);
        config->CrossPageOptmDisable =
            ((val >> REG_BITSHIFT_1) & REG_MASK_BITWIDTH1);
        config->PrefetchDistance =
            ((val >> REG_BITSHIFT_2) & REG_MASK_BITWIDTH6);
        config->MaxAllowedDistance =
            ((val >> REG_BITSHIFT_8) & REG_MASK_BITWIDTH6);
        config->LinToExpThreshold =
            ((val >> REG_BITSHIFT_14) & REG_MASK_BITWIDTH6);
        config->AgeOutEn = ((val >> REG_BITSHIFT_20) & REG_MASK_BITWIDTH1);
        config->NumLdsToAgeOut =
            ((val >> REG_BITSHIFT_21) & REG_MASK_BITWIDTH7);
        config->CrossPageEn = ((val >> REG_BITSHIFT_28) & REG_MASK_BITWIDTH1);

        val = REGW(METAL_SIFIVE_L2PF0_USER_CONTROL);

        config->QFullnessThreshold = (val & REG_MASK_BITWIDTH4);
        config->HitCacheThreshold =
            ((val >> REG_BITSHIFT_4) & REG_MASK_BITWIDTH5);
        config->hitMSHRThreshold =
            ((val >> REG_BITSHIFT_9) & REG_MASK_BITWIDTH4);
        config->Window = ((val >> REG_BITSHIFT_13) & REG_MASK_BITWIDTH6);
    }
    SIFIVE_L2PF0_TRAP_RESTORE(mtvec);
}

void sifive_l2pf0_set_config(sifive_l2pf0_config *config) {
    volatile uintptr_t exit = 0, mtvec = 0;
    int hartid;
    __asm__ volatile("csrr %0, mhartid" : "=r"(hartid));
    uint32_t val;

    SIFIVE_L2PF0_TRAP_CAPTURE(exit, mtvec);

    if (config) /* Check for NULL */
    {
        /* Get values from configuration to write into register */
        val = (uint32_t)(
            (config->HwPrefetchEnable & REG_MASK_BITWIDTH1) |
            ((config->CrossPageOptmDisable & REG_MASK_BITWIDTH1)
             << REG_BITSHIFT_1) |
            ((config->PrefetchDistance & REG_MASK_BITWIDTH6)
             << REG_BITSHIFT_2) |
            ((config->MaxAllowedDistance & REG_MASK_BITWIDTH6)
             << REG_BITSHIFT_8) |
            ((config->LinToExpThreshold & REG_MASK_BITWIDTH6)
             << REG_BITSHIFT_14) |
            ((config->AgeOutEn & REG_MASK_BITWIDTH1) << REG_BITSHIFT_20) |
            ((config->NumLdsToAgeOut & REG_MASK_BITWIDTH7) << REG_BITSHIFT_21) |
            ((config->CrossPageEn & REG_MASK_BITWIDTH1) << REG_BITSHIFT_28));

        /* Set user specified L2 prefetch configuration values */
        REGW(METAL_SIFIVE_L2PF0_BASIC_CONTROL) = val;

        val = (uint32_t)(
            (config->QFullnessThreshold & REG_MASK_BITWIDTH4) |
            ((config->HitCacheThreshold & REG_MASK_BITWIDTH5)
             << REG_BITSHIFT_4) |
            ((config->hitMSHRThreshold & REG_MASK_BITWIDTH4)
             << REG_BITSHIFT_9) |
            ((config->Window & REG_MASK_BITWIDTH6) << REG_BITSHIFT_13));

        REGW(METAL_SIFIVE_L2PF0_USER_CONTROL) = val;
    }
    SIFIVE_L2PF0_TRAP_RESTORE(mtvec);
}

#endif

typedef int no_empty_translation_units;