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