1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2011 Semihalf. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * From: FreeBSD: src/sys/arm/mv/kirkwood/sheevaplug.c,v 1.2 2010/06/13 13:28:53 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/bus.h> 34 35 #include <machine/armreg.h> 36 #include <machine/bus.h> 37 #include <machine/cpu.h> 38 39 #include <arm/mv/mvwin.h> 40 #include <arm/mv/mvreg.h> 41 #include <arm/mv/mvvar.h> 42 43 #include <dev/ofw/openfirm.h> 44 45 #include <machine/fdt.h> 46 47 #define CPU_FREQ_FIELD(sar) (((0x01 & (sar >> 52)) << 3) | \ 48 (0x07 & (sar >> 21))) 49 #define FAB_FREQ_FIELD(sar) (((0x01 & (sar >> 51)) << 4) | \ 50 (0x0F & (sar >> 24))) 51 52 void armadaxp_l2_init(void); 53 void armadaxp_init_coher_fabric(void); 54 int platform_get_ncpus(void); 55 56 #define ARMADAXP_L2_BASE (MV_BASE + 0x8000) 57 #define ARMADAXP_L2_CTRL 0x100 58 #define L2_ENABLE (1 << 0) 59 #define ARMADAXP_L2_AUX_CTRL 0x104 60 #define L2_WBWT_MODE_MASK (3 << 0) 61 #define L2_WBWT_MODE_PAGE 0 62 #define L2_WBWT_MODE_WB 1 63 #define L2_WBWT_MODE_WT 2 64 #define L2_REP_STRAT_MASK (3 << 27) 65 #define L2_REP_STRAT_LSFR (1 << 27) 66 #define L2_REP_STRAT_SEMIPLRU (3 << 27) 67 68 #define ARMADAXP_L2_CNTR_CTRL 0x200 69 #define ARMADAXP_L2_CNTR_CONF(x) (0x204 + (x) * 0xc) 70 #define ARMADAXP_L2_CNTR2_VAL_LOW (0x208 + (x) * 0xc) 71 #define ARMADAXP_L2_CNTR2_VAL_HI (0x20c + (x) * 0xc) 72 73 #define ARMADAXP_L2_INT_CAUSE 0x220 74 75 #define ARMADAXP_L2_SYNC_BARRIER 0x700 76 #define ARMADAXP_L2_INV_WAY 0x778 77 #define ARMADAXP_L2_CLEAN_WAY 0x7BC 78 #define ARMADAXP_L2_FLUSH_PHYS 0x7F0 79 #define ARMADAXP_L2_FLUSH_WAY 0x7FC 80 81 #define MV_COHERENCY_FABRIC_BASE (MV_MBUS_BRIDGE_BASE + 0x200) 82 #define COHER_FABRIC_CTRL 0x00 83 #define COHER_FABRIC_CONF 0x04 84 #define COHER_FABRIC_CFU 0x28 85 #define COHER_FABRIC_CIB_CTRL 0x80 86 87 struct vco_freq_ratio { 88 uint8_t vco_cpu; /* VCO to CLK0(CPU) clock ratio */ 89 uint8_t vco_l2c; /* VCO to NB(L2 cache) clock ratio */ 90 uint8_t vco_hcl; /* VCO to HCLK(DDR controller) clock ratio */ 91 uint8_t vco_ddr; /* VCO to DR(DDR memory) clock ratio */ 92 }; 93 94 uint32_t 95 get_tclk_armadaxp(void) 96 { 97 uint32_t cputype; 98 99 cputype = cp15_midr_get(); 100 cputype &= CPU_ID_CPU_MASK; 101 102 if (cputype == CPU_ID_MV88SV584X_V7) 103 return (TCLK_250MHZ); 104 else 105 return (TCLK_200MHZ); 106 } 107 108 uint32_t 109 get_cpu_freq_armadaxp(void) 110 { 111 112 return (0); 113 } 114 115 static uint32_t 116 read_coher_fabric(uint32_t reg) 117 { 118 119 return (bus_space_read_4(fdtbus_bs_tag, MV_COHERENCY_FABRIC_BASE, reg)); 120 } 121 122 static void 123 write_coher_fabric(uint32_t reg, uint32_t val) 124 { 125 126 bus_space_write_4(fdtbus_bs_tag, MV_COHERENCY_FABRIC_BASE, reg, val); 127 } 128 129 int 130 platform_get_ncpus(void) 131 { 132 #if !defined(SMP) 133 return (1); 134 #else 135 return ((read_coher_fabric(COHER_FABRIC_CONF) & 0xf) + 1); 136 #endif 137 } 138 139 void 140 armadaxp_init_coher_fabric(void) 141 { 142 uint32_t val, cpus, mask; 143 144 cpus = platform_get_ncpus(); 145 mask = (1 << cpus) - 1; 146 val = read_coher_fabric(COHER_FABRIC_CTRL); 147 val |= (mask << 24); 148 write_coher_fabric(COHER_FABRIC_CTRL, val); 149 150 val = read_coher_fabric(COHER_FABRIC_CONF); 151 val |= (mask << 24); 152 val |= (1 << 15); 153 write_coher_fabric(COHER_FABRIC_CONF, val); 154 } 155 156 #define ALL_WAYS 0xffffffff 157 158 /* L2 cache configuration registers */ 159 static uint32_t 160 read_l2_cache(uint32_t reg) 161 { 162 163 return (bus_space_read_4(fdtbus_bs_tag, ARMADAXP_L2_BASE, reg)); 164 } 165 166 static void 167 write_l2_cache(uint32_t reg, uint32_t val) 168 { 169 170 bus_space_write_4(fdtbus_bs_tag, ARMADAXP_L2_BASE, reg, val); 171 } 172 173 static void 174 armadaxp_l2_idcache_inv_all(void) 175 { 176 write_l2_cache(ARMADAXP_L2_INV_WAY, ALL_WAYS); 177 } 178 179 void 180 armadaxp_l2_init(void) 181 { 182 u_int32_t reg; 183 184 /* Set L2 policy */ 185 reg = read_l2_cache(ARMADAXP_L2_AUX_CTRL); 186 reg &= ~(L2_WBWT_MODE_MASK); 187 reg &= ~(L2_REP_STRAT_MASK); 188 reg |= L2_REP_STRAT_SEMIPLRU; 189 reg |= L2_WBWT_MODE_WT; 190 write_l2_cache(ARMADAXP_L2_AUX_CTRL, reg); 191 192 /* Invalidate l2 cache */ 193 armadaxp_l2_idcache_inv_all(); 194 195 /* Clear pending L2 interrupts */ 196 write_l2_cache(ARMADAXP_L2_INT_CAUSE, 0x1ff); 197 198 /* Enable l2 cache */ 199 reg = read_l2_cache(ARMADAXP_L2_CTRL); 200 write_l2_cache(ARMADAXP_L2_CTRL, reg | L2_ENABLE); 201 202 /* 203 * For debug purposes 204 * Configure and enable counter 205 */ 206 write_l2_cache(ARMADAXP_L2_CNTR_CONF(0), 0xf0000 | (4 << 2)); 207 write_l2_cache(ARMADAXP_L2_CNTR_CONF(1), 0xf0000 | (2 << 2)); 208 write_l2_cache(ARMADAXP_L2_CNTR_CTRL, 0x303); 209 210 /* 211 * Enable Cache maintenance operation propagation in coherency fabric 212 * Change point of coherency and point of unification to DRAM. 213 */ 214 reg = read_coher_fabric(COHER_FABRIC_CFU); 215 reg |= (1 << 17) | (1 << 18); 216 write_coher_fabric(COHER_FABRIC_CFU, reg); 217 218 /* Coherent IO Bridge initialization */ 219 reg = read_coher_fabric(COHER_FABRIC_CIB_CTRL); 220 reg &= ~(7 << 16); 221 reg |= (7 << 16); 222 write_coher_fabric(COHER_FABRIC_CIB_CTRL, reg); 223 } 224