xref: /aosp_15_r20/external/coreboot/src/vendorcode/cavium/bdk/libbdk-hal/bdk-l2c.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /***********************license start***********************************
2 * Copyright (c) 2003-2017  Cavium Inc. ([email protected]). All rights
3 * reserved.
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *   * Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 *
13 *   * Redistributions in binary form must reproduce the above
14 *     copyright notice, this list of conditions and the following
15 *     disclaimer in the documentation and/or other materials provided
16 *     with the distribution.
17 *
18 *   * Neither the name of Cavium Inc. nor the names of
19 *     its contributors may be used to endorse or promote products
20 *     derived from this software without specific prior written
21 *     permission.
22 *
23 * This Software, including technical data, may be subject to U.S. export
24 * control laws, including the U.S. Export Administration Act and its
25 * associated regulations, and may be subject to export or import
26 * regulations in other countries.
27 *
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
31 * TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
32 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
33 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
34 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
35 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
36 * QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK
37 * ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
39 #include <bdk.h>
40 #include "libbdk-arch/bdk-csrs-ap.h"
41 #include "libbdk-arch/bdk-csrs-l2c.h"
42 #include "libbdk-arch/bdk-csrs-l2c_cbc.h"
43 #include "libbdk-arch/bdk-csrs-mio_fus.h"
44 #include "libbdk-hal/bdk-l2c.h"
45 #include "libbdk-hal/bdk-utils.h"
46 
47 typedef struct
48 {
49     int sets;
50     int ways;
51     bool is_locked;
52 } l2_node_state_t;
53 
54 static l2_node_state_t l2_node_state[BDK_NUMA_MAX_NODES];
55 
bdk_l2c_set_core_way_partition(bdk_node_t node,int core,uint32_t mask)56 int bdk_l2c_set_core_way_partition(bdk_node_t node, int core, uint32_t mask)
57 {
58     uint32_t valid_mask = (1 << bdk_l2c_get_num_assoc(node)) - 1;
59     mask &= valid_mask;
60 
61     BDK_CSR_WRITE(node, BDK_L2C_WPAR_PPX(core), mask);
62     return 0;
63 }
64 
65 
bdk_l2c_set_hw_way_partition(bdk_node_t node,uint32_t mask)66 int bdk_l2c_set_hw_way_partition(bdk_node_t node, uint32_t mask)
67 {
68     uint32_t valid_mask = (1 << bdk_l2c_get_num_assoc(node)) - 1;
69     mask &= valid_mask;
70 
71     BDK_CSR_WRITE(node, BDK_L2C_WPAR_IOBX(0), mask);
72     return 0;
73 }
74 
bdk_l2c_get_hw_way_partition(bdk_node_t node)75 int bdk_l2c_get_hw_way_partition(bdk_node_t node)
76 {
77     return (BDK_CSR_READ(node, BDK_L2C_WPAR_IOBX(0)) & 0xffff);
78 }
79 
bdk_l2c_get_cache_size_bytes(bdk_node_t node)80 int bdk_l2c_get_cache_size_bytes(bdk_node_t node)
81 {
82     return bdk_l2c_get_num_sets(node) * bdk_l2c_get_num_assoc(node) * BDK_CACHE_LINE_SIZE;
83 }
84 
85 /* Return the number of sets in the L2 Cache */
bdk_l2c_get_num_sets(bdk_node_t node)86 int bdk_l2c_get_num_sets(bdk_node_t node)
87 {
88     if (bdk_unlikely(l2_node_state[node].sets == 0))
89     {
90         /* Select the L2 cache */
91         bdk_ap_csselr_el1_t csselr_el1;
92         csselr_el1.u = 0;
93         csselr_el1.s.ind = 0;
94         csselr_el1.s.level = CAVIUM_IS_MODEL(CAVIUM_CN8XXX) ? 1 : 2;
95         BDK_MSR(CSSELR_EL1, csselr_el1.u);
96         /* Read its size */
97         bdk_ap_ccsidr_el1_t ccsidr_el1;
98         BDK_MRS(CCSIDR_EL1, ccsidr_el1.u);
99         /* Store it for use later */
100         l2_node_state[node].sets = ccsidr_el1.s.numsets + 1;
101         l2_node_state[node].ways = ccsidr_el1.s.associativity + 1;
102 
103         /* Early chips didn't update the number of ways based on fusing */
104         if ((l2_node_state[node].ways == 16) && CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
105         {
106             /* The l2 can be reduced in 25% increments */
107             BDK_CSR_INIT(mio_fus_dat3, node, BDK_MIO_FUS_DAT3);
108             switch (mio_fus_dat3.s.l2c_crip)
109             {
110                 case 3: /* 1/4 size */
111                     l2_node_state[node].ways *= 1;
112                     break;
113                 case 2: /* 1/2 size */
114                     l2_node_state[node].ways *= 2;
115                     break;
116                 case 1: /* 3/4 size */
117                     l2_node_state[node].ways *= 3;
118                     break;
119                 default: /* Full size */
120                     l2_node_state[node].ways *= 4;
121                     break;
122             }
123             l2_node_state[node].ways /= 4;
124         }
125     }
126     return l2_node_state[node].sets;
127 }
128 
129 /* Return the number of associations in the L2 Cache */
bdk_l2c_get_num_assoc(bdk_node_t node)130 int bdk_l2c_get_num_assoc(bdk_node_t node)
131 {
132     /* Get the number of sets if the global sets/ways is not setup */
133     if (bdk_unlikely(l2_node_state[node].ways == 0))
134         bdk_l2c_get_num_sets(node);
135     return l2_node_state[node].ways;
136 }
137 
bdk_l2c_unlock_mem_region(bdk_node_t node,uint64_t start,uint64_t len)138 int bdk_l2c_unlock_mem_region(bdk_node_t node, uint64_t start, uint64_t len)
139 {
140     /* Round start/end to cache line boundaries */
141     len += start & BDK_CACHE_LINE_MASK;
142     start &= ~BDK_CACHE_LINE_MASK;
143     len = (len + BDK_CACHE_LINE_MASK) & ~BDK_CACHE_LINE_MASK;
144     void *ptr = bdk_phys_to_ptr(start);
145 
146     while (len > 0)
147     {
148         /* Must use invalidate version to release lock */
149         BDK_CACHE_WBI_L2(ptr);
150         ptr += BDK_CACHE_LINE_SIZE;
151         len -= BDK_CACHE_LINE_SIZE;
152     }
153 
154     l2_node_state[node].is_locked = false;
155     return 0;
156 }
157