]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_GCC/freedom-metal/src/drivers/sifive_fu540-c000_l2.c
Base project to replace existing Freedom Studio project using latest Freedom Studio...
[freertos] / FreeRTOS / Demo / RISC-V_RV32_SiFive_HiFive1_GCC / freedom-metal / src / drivers / sifive_fu540-c000_l2.c
1 /* Copyright 2018 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
3
4 #include <metal/machine/platform.h>
5 #include <metal/drivers/sifive_fu540-c000_l2.h>
6
7 #define L2_CONFIG_WAYS_SHIFT    8
8 #define L2_CONFIG_WAYS_MASK     (0xFF << L2_CONFIG_WAYS_SHIFT)
9
10 #ifdef CONFIG_SIFIVE_FU540_C000_L2
11
12 static void metal_driver_sifive_fu540_c000_l2_init(void) __attribute__((constructor));
13 static void metal_driver_sifive_fu540_c000_l2_init(void)
14 {
15 #ifdef __METAL_DT_SIFIVE_FU540_C000_L2_HANDLE
16     /* Get the handle for the L2 cache controller */
17     struct __metal_driver_sifive_fu540_c000_l2 *l2 = __METAL_DT_SIFIVE_FU540_C000_L2_HANDLE;
18     if(!l2) {
19         return;
20     }
21
22     /* Get the number of available ways per bank */
23     uint32_t ways = __METAL_ACCESS_ONCE((__metal_io_u32 *)(l2->control_base + SIFIVE_FU540_C000_L2_CONFIG));
24     ways = ((ways & L2_CONFIG_WAYS_MASK) >> L2_CONFIG_WAYS_SHIFT);
25
26     /* Enable all the ways */
27     __metal_driver_sifive_fu540_c000_l2_init(l2, ways);
28 #endif
29 }
30
31 void __metal_driver_sifive_fu540_c000_l2_init(struct metal_cache *l2, int ways)
32 {
33     metal_cache_set_enabled_ways(l2, ways);
34 }
35
36 int __metal_driver_sifive_fu540_c000_l2_get_enabled_ways(struct metal_cache *cache)
37 {
38     struct __metal_driver_sifive_fu540_c000_l2 *l2 = (struct __metal_driver_sifive_fu540_c000_l2 *) cache;
39     if(!l2) {
40         return -1;
41     }
42
43     uint32_t way_enable = __METAL_ACCESS_ONCE((__metal_io_u32 *)(l2->control_base + SIFIVE_FU540_C000_L2_WAYENABLE));
44
45     /* The stored number is the index, so add one */
46     return (0xFF & way_enable) + 1;
47 }
48
49 int __metal_driver_sifive_fu540_c000_l2_set_enabled_ways(struct metal_cache *cache, int ways)
50 {
51     struct __metal_driver_sifive_fu540_c000_l2 *l2 = (struct __metal_driver_sifive_fu540_c000_l2 *) cache;
52     if(!l2) {
53         return -1;
54     }
55
56     /* We can't decrease the number of enabled ways */
57     if(metal_cache_get_enabled_ways(cache) > ways) {
58         return -2;
59     }
60
61     /* The stored value is the index, so subtract one */
62     uint32_t value = 0xFF & (ways - 1);
63
64     /* Set the number of enabled ways */
65     __METAL_ACCESS_ONCE((__metal_io_u32 *)(l2->control_base + SIFIVE_FU540_C000_L2_WAYENABLE)) = value;
66
67     /* Make sure the number of ways was set correctly */
68     if(metal_cache_get_enabled_ways(cache) != ways) {
69         return -3;
70     }
71
72     return 0;
73 }
74
75 __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fu540_c000_l2) = {
76         .cache.init = __metal_driver_sifive_fu540_c000_l2_init,
77         .cache.get_enabled_ways = __metal_driver_sifive_fu540_c000_l2_get_enabled_ways,
78         .cache.set_enabled_ways = __metal_driver_sifive_fu540_c000_l2_set_enabled_ways,
79 };
80
81 #endif