1 1.27 skrll /* $NetBSD: bcm53xx_board.c,v 1.27 2024/02/16 16:28:49 skrll Exp $ */ 2 1.1 matt /*- 3 1.1 matt * Copyright (c) 2012 The NetBSD Foundation, Inc. 4 1.1 matt * All rights reserved. 5 1.1 matt * 6 1.1 matt * This code is derived from software contributed to The NetBSD Foundation 7 1.1 matt * by Matt Thomas of 3am Software Foundry. 8 1.1 matt * 9 1.1 matt * Redistribution and use in source and binary forms, with or without 10 1.1 matt * modification, are permitted provided that the following conditions 11 1.1 matt * are met: 12 1.1 matt * 1. Redistributions of source code must retain the above copyright 13 1.1 matt * notice, this list of conditions and the following disclaimer. 14 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 matt * notice, this list of conditions and the following disclaimer in the 16 1.1 matt * documentation and/or other materials provided with the distribution. 17 1.1 matt * 18 1.1 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 1.1 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 1.1 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 1.1 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 1.1 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 1.1 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 1.1 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 1.1 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 1.1 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 1.1 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 1.1 matt * POSSIBILITY OF SUCH DAMAGE. 29 1.1 matt */ 30 1.1 matt 31 1.25 skrll #include "opt_arm_debug.h" 32 1.1 matt #include "opt_broadcom.h" 33 1.18 matt #include "arml2cc.h" 34 1.1 matt 35 1.1 matt #define _ARM32_BUS_DMA_PRIVATE 36 1.1 matt 37 1.1 matt #include <sys/cdefs.h> 38 1.1 matt 39 1.27 skrll __KERNEL_RCSID(1, "$NetBSD: bcm53xx_board.c,v 1.27 2024/02/16 16:28:49 skrll Exp $"); 40 1.1 matt 41 1.1 matt #include <sys/param.h> 42 1.1 matt #include <sys/bus.h> 43 1.1 matt #include <sys/cpu.h> 44 1.1 matt #include <sys/device.h> 45 1.1 matt 46 1.1 matt #include <prop/proplib.h> 47 1.1 matt 48 1.4 matt #include <net/if.h> 49 1.4 matt #include <net/if_ether.h> 50 1.4 matt 51 1.17 matt #define CCA_PRIVATE 52 1.1 matt #define CRU_PRIVATE 53 1.1 matt #define DDR_PRIVATE 54 1.1 matt #define DMU_PRIVATE 55 1.1 matt #define ARMCORE_PRIVATE 56 1.4 matt #define SRAB_PRIVATE 57 1.1 matt 58 1.1 matt #include <arm/cortex/a9tmr_var.h> 59 1.2 matt #include <arm/cortex/pl310_var.h> 60 1.1 matt #include <arm/mainbus/mainbus.h> 61 1.1 matt 62 1.1 matt #include <arm/broadcom/bcm53xx_reg.h> 63 1.1 matt #include <arm/broadcom/bcm53xx_var.h> 64 1.1 matt 65 1.1 matt bus_space_tag_t bcm53xx_ioreg_bst = &bcmgen_bs_tag; 66 1.1 matt bus_space_handle_t bcm53xx_ioreg_bsh; 67 1.1 matt bus_space_tag_t bcm53xx_armcore_bst = &bcmgen_bs_tag; 68 1.1 matt bus_space_handle_t bcm53xx_armcore_bsh; 69 1.1 matt 70 1.1 matt static struct cpu_softc cpu_softc; 71 1.1 matt 72 1.13 matt struct arm32_dma_range bcm53xx_dma_ranges[] = { 73 1.17 matt #ifdef BCM5301X 74 1.8 matt [0] = { 75 1.8 matt .dr_sysbase = 0x80000000, 76 1.8 matt .dr_busbase = 0x80000000, 77 1.8 matt .dr_len = 0x10000000, 78 1.8 matt }, [1] = { 79 1.8 matt .dr_sysbase = 0x90000000, 80 1.8 matt .dr_busbase = 0x90000000, 81 1.8 matt }, 82 1.19 matt #elif defined(BCM563XX) 83 1.17 matt [0] = { 84 1.17 matt .dr_sysbase = 0x60000000, 85 1.17 matt .dr_busbase = 0x60000000, 86 1.17 matt .dr_len = 0x20000000, 87 1.17 matt }, [1] = { 88 1.19 matt .dr_sysbase = 0x80000000, 89 1.19 matt .dr_busbase = 0x80000000, 90 1.20 matt }, 91 1.17 matt #endif 92 1.8 matt }; 93 1.5 matt 94 1.1 matt struct arm32_bus_dma_tag bcm53xx_dma_tag = { 95 1.8 matt ._ranges = bcm53xx_dma_ranges, 96 1.8 matt ._nranges = __arraycount(bcm53xx_dma_ranges), 97 1.3 matt _BUS_DMAMAP_FUNCS, 98 1.3 matt _BUS_DMAMEM_FUNCS, 99 1.3 matt _BUS_DMATAG_FUNCS, 100 1.1 matt }; 101 1.1 matt 102 1.13 matt struct arm32_dma_range bcm53xx_coherent_dma_ranges[] = { 103 1.17 matt #ifdef BCM5301X 104 1.8 matt [0] = { 105 1.8 matt .dr_sysbase = 0x80000000, 106 1.8 matt .dr_busbase = 0x80000000, 107 1.8 matt .dr_len = 0x10000000, 108 1.8 matt .dr_flags = _BUS_DMAMAP_COHERENT, 109 1.8 matt }, [1] = { 110 1.8 matt .dr_sysbase = 0x90000000, 111 1.8 matt .dr_busbase = 0x90000000, 112 1.8 matt }, 113 1.17 matt #elif defined(BCM563XX) 114 1.17 matt [0] = { 115 1.17 matt .dr_sysbase = 0x60000000, 116 1.17 matt .dr_busbase = 0x60000000, 117 1.17 matt .dr_len = 0x20000000, 118 1.17 matt .dr_flags = _BUS_DMAMAP_COHERENT, 119 1.17 matt }, [1] = { 120 1.19 matt .dr_sysbase = 0x80000000, 121 1.19 matt .dr_busbase = 0x80000000, 122 1.17 matt }, 123 1.17 matt #endif 124 1.8 matt }; 125 1.6 matt 126 1.6 matt struct arm32_bus_dma_tag bcm53xx_coherent_dma_tag = { 127 1.8 matt ._ranges = bcm53xx_coherent_dma_ranges, 128 1.8 matt ._nranges = __arraycount(bcm53xx_coherent_dma_ranges), 129 1.6 matt _BUS_DMAMAP_FUNCS, 130 1.6 matt _BUS_DMAMEM_FUNCS, 131 1.6 matt _BUS_DMATAG_FUNCS, 132 1.6 matt }; 133 1.6 matt 134 1.14 matt #ifdef _ARM32_NEED_BUS_DMA_BOUNCE 135 1.14 matt struct arm32_bus_dma_tag bcm53xx_bounce_dma_tag = { 136 1.15 matt ._ranges = bcm53xx_coherent_dma_ranges, 137 1.15 matt ._nranges = 1, 138 1.14 matt _BUS_DMAMAP_FUNCS, 139 1.14 matt _BUS_DMAMEM_FUNCS, 140 1.14 matt _BUS_DMATAG_FUNCS, 141 1.14 matt }; 142 1.14 matt #endif 143 1.14 matt 144 1.1 matt psize_t 145 1.1 matt bcm53xx_memprobe(void) 146 1.1 matt { 147 1.1 matt bus_space_tag_t bst = bcm53xx_ioreg_bst; 148 1.1 matt bus_space_handle_t bsh = bcm53xx_ioreg_bsh; 149 1.1 matt 150 1.1 matt /* 151 1.1 matt * First, let's read the magic DDR registers! 152 1.1 matt */ 153 1.1 matt const uint32_t v01 = bus_space_read_4(bst, bsh, DDR_BASE + DDR_CTL_01); 154 1.1 matt const uint32_t v82 = bus_space_read_4(bst, bsh, DDR_BASE + DDR_CTL_82); 155 1.1 matt const uint32_t v86 = bus_space_read_4(bst, bsh, DDR_BASE + DDR_CTL_86); 156 1.1 matt const uint32_t v87 = bus_space_read_4(bst, bsh, DDR_BASE + DDR_CTL_87); 157 1.1 matt 158 1.1 matt /* 159 1.1 matt * Calculate chip parameters 160 1.1 matt * */ 161 1.1 matt const u_int rows = __SHIFTOUT(v01, CTL_01_MAX_ROW) 162 1.1 matt - __SHIFTOUT(v82, CTL_82_ROW_DIFF); 163 1.1 matt const u_int cols = __SHIFTOUT(v01, CTL_01_MAX_COL) 164 1.1 matt - __SHIFTOUT(v82, CTL_82_COL_DIFF); 165 1.1 matt const u_int banks_log2 = 3 - __SHIFTOUT(v82, CTL_82_BANK_DIFF); 166 1.1 matt 167 1.1 matt /* 168 1.1 matt * For each chip select, increase the chip count if if is enabled. 169 1.1 matt */ 170 1.1 matt const u_int max_chips = __SHIFTOUT(v01, CTL_01_MAX_CHIP_SEL); 171 1.1 matt u_int cs_map = __SHIFTOUT(v86, CTL_86_CS_MAP); 172 1.1 matt u_int chips = 0; 173 1.1 matt 174 1.1 matt for (u_int i = 0; cs_map != 0 && i < max_chips; i++, cs_map >>= 1) { 175 1.1 matt chips += (cs_map & 1); 176 1.1 matt } 177 1.1 matt 178 1.1 matt /* get log2(ddr width) */ 179 1.1 matt 180 1.1 matt const u_int ddr_width_log2 = (v87 & CTL_87_REDUC) ? 1 : 2; 181 1.1 matt 182 1.1 matt /* 183 1.1 matt * Let's add up all the things that contribute to the size of a chip. 184 1.1 matt */ 185 1.1 matt const u_int chip_size_log2 = cols + rows + banks_log2 + ddr_width_log2; 186 1.1 matt 187 1.1 matt /* 188 1.1 matt * Now our memory size is simply the number of chip shifted by the 189 1.1 matt * log2(chip_size). 190 1.1 matt */ 191 1.1 matt return (psize_t) chips << chip_size_log2; 192 1.1 matt } 193 1.1 matt 194 1.1 matt static inline uint32_t 195 1.1 matt bcm53xx_freq_calc(struct bcm53xx_clock_info *clk, 196 1.1 matt uint32_t pdiv, uint32_t ndiv_int, uint32_t ndiv_frac) 197 1.1 matt { 198 1.1 matt if (ndiv_frac == 0 && pdiv == 1) 199 1.1 matt return ndiv_int * clk->clk_ref; 200 1.1 matt 201 1.1 matt uint64_t freq64 = ((uint64_t)ndiv_int << 30) + ndiv_frac; 202 1.1 matt freq64 *= clk->clk_ref; 203 1.1 matt if (pdiv > 1) 204 1.1 matt freq64 /= pdiv; 205 1.1 matt return (uint32_t) (freq64 >> 30); 206 1.1 matt } 207 1.1 matt 208 1.1 matt static uint32_t 209 1.1 matt bcm53xx_value_wrap(uint32_t value, uint32_t mask) 210 1.1 matt { 211 1.1 matt /* 212 1.1 matt * n is n except when n is 0 then n = mask + 1. 213 1.1 matt */ 214 1.1 matt return ((__SHIFTOUT(value, mask) - 1) & __SHIFTOUT(mask, mask)) + 1; 215 1.1 matt } 216 1.1 matt 217 1.1 matt static void 218 1.1 matt bcm53xx_genpll_clock_init(struct bcm53xx_clock_info *clk, uint32_t control5, 219 1.1 matt uint32_t control6, uint32_t control7) 220 1.1 matt { 221 1.1 matt const uint32_t pdiv = bcm53xx_value_wrap(control6, 222 1.1 matt GENPLL_CONTROL6_PDIV); 223 1.1 matt const uint32_t ndiv_int = bcm53xx_value_wrap(control5, 224 1.1 matt GENPLL_CONTROL5_NDIV_INT); 225 1.1 matt const uint32_t ndiv_frac = __SHIFTOUT(control5, 226 1.1 matt GENPLL_CONTROL5_NDIV_FRAC); 227 1.1 matt 228 1.1 matt clk->clk_genpll = bcm53xx_freq_calc(clk, pdiv, ndiv_int, ndiv_frac); 229 1.1 matt 230 1.1 matt const uint32_t ch0_mdiv = bcm53xx_value_wrap(control6, 231 1.1 matt GENPLL_CONTROL6_CH0_MDIV); 232 1.1 matt const uint32_t ch1_mdiv = bcm53xx_value_wrap(control6, 233 1.1 matt GENPLL_CONTROL6_CH1_MDIV); 234 1.1 matt const uint32_t ch2_mdiv = bcm53xx_value_wrap(control6, 235 1.1 matt GENPLL_CONTROL6_CH2_MDIV); 236 1.1 matt const uint32_t ch3_mdiv = bcm53xx_value_wrap(control7, 237 1.1 matt GENPLL_CONTROL7_CH3_MDIV); 238 1.1 matt 239 1.1 matt clk->clk_mac = clk->clk_genpll / ch0_mdiv; // GENPLL CH0 240 1.1 matt clk->clk_robo = clk->clk_genpll / ch1_mdiv; // GENPLL CH1 241 1.1 matt clk->clk_usb2 = clk->clk_genpll / ch2_mdiv; // GENPLL CH2 242 1.1 matt clk->clk_iproc = clk->clk_genpll / ch3_mdiv; // GENPLL CH3 243 1.1 matt } 244 1.1 matt 245 1.1 matt static void 246 1.1 matt bcm53xx_lcpll_clock_init(struct bcm53xx_clock_info *clk, uint32_t control1, 247 1.1 matt uint32_t control2) 248 1.1 matt { 249 1.1 matt const uint32_t pdiv = bcm53xx_value_wrap(control1, 250 1.1 matt LCPLL_CONTROL1_PDIV); 251 1.1 matt const uint32_t ndiv_int = bcm53xx_value_wrap(control1, 252 1.1 matt LCPLL_CONTROL1_NDIV_INT); 253 1.1 matt const uint32_t ndiv_frac = __SHIFTOUT(control1, 254 1.1 matt LCPLL_CONTROL1_NDIV_FRAC); 255 1.1 matt 256 1.1 matt clk->clk_lcpll = bcm53xx_freq_calc(clk, pdiv, ndiv_int, ndiv_frac); 257 1.1 matt 258 1.1 matt const uint32_t ch0_mdiv = bcm53xx_value_wrap(control2, 259 1.1 matt LCPLL_CONTROL2_CH0_MDIV); 260 1.1 matt const uint32_t ch1_mdiv = bcm53xx_value_wrap(control2, 261 1.1 matt LCPLL_CONTROL2_CH1_MDIV); 262 1.1 matt const uint32_t ch2_mdiv = bcm53xx_value_wrap(control2, 263 1.1 matt LCPLL_CONTROL2_CH2_MDIV); 264 1.1 matt const uint32_t ch3_mdiv = bcm53xx_value_wrap(control2, 265 1.1 matt LCPLL_CONTROL2_CH3_MDIV); 266 1.1 matt 267 1.1 matt clk->clk_pcie_ref = clk->clk_lcpll / ch0_mdiv; // LCPLL CH0 268 1.1 matt clk->clk_sdio = clk->clk_lcpll / ch1_mdiv; // LCPLL CH1 269 1.1 matt clk->clk_ddr_ref = clk->clk_lcpll / ch2_mdiv; // LCPLL CH2 270 1.1 matt clk->clk_axi = clk->clk_lcpll / ch3_mdiv; // LCPLL CH3 271 1.1 matt } 272 1.1 matt 273 1.1 matt static void 274 1.1 matt bcm53xx_usb_clock_init(struct bcm53xx_clock_info *clk, uint32_t usb2_control) 275 1.1 matt { 276 1.1 matt const uint32_t pdiv = bcm53xx_value_wrap(usb2_control, 277 1.1 matt USB2_CONTROL_PDIV); 278 1.1 matt const uint32_t ndiv = bcm53xx_value_wrap(usb2_control, 279 1.1 matt USB2_CONTROL_NDIV_INT); 280 1.1 matt 281 1.26 skrll uint32_t usb_ref = (clk->clk_usb2 / pdiv) * ndiv; 282 1.1 matt if (usb_ref != USB2_REF_CLK) { 283 1.1 matt /* 284 1.1 matt * USB Reference Clock isn't 1.92GHz. So we need to modify 285 1.1 matt * USB2_CONTROL to produce it. 286 1.1 matt */ 287 1.1 matt uint32_t new_ndiv = (USB2_REF_CLK / clk->clk_usb2) * pdiv; 288 1.1 matt usb2_control &= ~USB2_CONTROL_NDIV_INT; 289 1.1 matt usb2_control |= __SHIFTIN(new_ndiv, USB2_CONTROL_NDIV_INT); 290 1.1 matt 291 1.1 matt // Allow Clocks to be modified 292 1.1 matt bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 293 1.1 matt CRU_BASE + CRU_CLKSET_KEY, CRU_CLKSET_KEY_MAGIC); 294 1.1 matt 295 1.1 matt // Update USB2 clock generator 296 1.1 matt bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 297 1.1 matt CRU_BASE + CRU_USB2_CONTROL, usb2_control); 298 1.1 matt 299 1.1 matt // Prevent Clock modification 300 1.1 matt bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 301 1.1 matt CRU_BASE + CRU_CLKSET_KEY, 0); 302 1.1 matt 303 1.26 skrll usb_ref = (clk->clk_usb2 / pdiv) * new_ndiv; 304 1.1 matt } 305 1.1 matt 306 1.1 matt clk->clk_usb_ref = usb_ref; 307 1.1 matt } 308 1.1 matt 309 1.1 matt 310 1.1 matt static void 311 1.1 matt bcm53xx_clock_init(struct bcm53xx_clock_info *clk) 312 1.1 matt { 313 1.1 matt clk->clk_ref = BCM53XX_REF_CLK; 314 1.1 matt clk->clk_sys = 8*clk->clk_ref; 315 1.1 matt } 316 1.1 matt 317 1.1 matt /* 318 1.1 matt * F(ddr) = ((1 / pdiv) * ndiv * CH2) / (post_div * 2) 319 1.1 matt */ 320 1.26 skrll static void 321 1.1 matt bcm53xx_get_ddr_freq(struct bcm53xx_clock_info *clk, uint32_t pll_status, 322 1.1 matt uint32_t pll_dividers) 323 1.1 matt { 324 1.1 matt const bool clocking_4x = (pll_status & PLL_STATUS_CLOCKING_4X) != 0; 325 1.1 matt u_int post_div = __SHIFTOUT(pll_dividers, PLL_DIVIDERS_POST_DIV); 326 1.1 matt u_int pdiv = __SHIFTOUT(pll_dividers, PLL_DIVIDERS_PDIV); 327 1.1 matt u_int ndiv = __SHIFTOUT(pll_dividers, PLL_DIVIDERS_NDIV); 328 1.1 matt 329 1.1 matt pdiv = ((pdiv - (clocking_4x ? 1 : 5)) & 7) + 1; 330 1.1 matt 331 1.1 matt clk->clk_ddr_mhz = __SHIFTOUT(pll_status, PLL_STATUS_MHZ); 332 1.1 matt clk->clk_ddr = (clk->clk_ddr_ref / pdiv) * ndiv / (2 + post_div); 333 1.1 matt } 334 1.1 matt 335 1.1 matt /* 336 1.1 matt * CPU_CLK = (1 / pdiv) * (ndiv_int + (ndiv_frac / 0x40000000)) x F(ref) 337 1.1 matt */ 338 1.1 matt static void 339 1.1 matt bcm53xx_get_cpu_freq(struct bcm53xx_clock_info *clk, 340 1.1 matt uint32_t pllarma, uint32_t pllarmb, uint32_t policy) 341 1.1 matt { 342 1.1 matt policy = __SHIFTOUT(policy, CLK_POLICY_FREQ_POLICY2); 343 1.1 matt 344 1.1 matt if (policy == CLK_POLICY_REF_CLK) { 345 1.1 matt clk->clk_cpu = clk->clk_ref; 346 1.1 matt clk->clk_apb = clk->clk_cpu; 347 1.1 matt return; 348 1.1 matt } 349 1.1 matt 350 1.1 matt if (policy == CLK_POLICY_SYS_CLK) { 351 1.1 matt clk->clk_cpu = clk->clk_sys; 352 1.1 matt clk->clk_apb = clk->clk_cpu / 4; 353 1.1 matt return; 354 1.1 matt } 355 1.26 skrll 356 1.1 matt const u_int pdiv = bcm53xx_value_wrap(pllarma, CLK_PLLARMA_PDIV); 357 1.1 matt const u_int ndiv_int = bcm53xx_value_wrap(pllarma, CLK_PLLARMA_NDIV_INT); 358 1.1 matt const u_int ndiv_frac = __SHIFTOUT(pllarmb, CLK_PLLARMB_NDIV_FRAC); 359 1.1 matt // const u_int apb_clk_div = __SHIFTOUT(apb_clk_div, CLK_APB_DIV_VALUE)+1; 360 1.1 matt 361 1.1 matt const u_int cpu_div = (policy == CLK_POLICY_ARM_PLL_CH0) ? 4 : 2; 362 1.1 matt 363 1.1 matt clk->clk_cpu = bcm53xx_freq_calc(clk, pdiv, ndiv_int, ndiv_frac) / cpu_div; 364 1.1 matt clk->clk_apb = clk->clk_cpu / 4; 365 1.1 matt } 366 1.1 matt 367 1.1 matt struct bcm53xx_chip_state { 368 1.1 matt uint32_t bcs_lcpll_control1; 369 1.1 matt uint32_t bcs_lcpll_control2; 370 1.1 matt 371 1.1 matt uint32_t bcs_genpll_control5; 372 1.1 matt uint32_t bcs_genpll_control6; 373 1.1 matt uint32_t bcs_genpll_control7; 374 1.1 matt 375 1.1 matt uint32_t bcs_usb2_control; 376 1.1 matt 377 1.1 matt uint32_t bcs_ddr_phy_ctl_pll_status; 378 1.1 matt uint32_t bcs_ddr_phy_ctl_pll_dividers; 379 1.1 matt 380 1.1 matt uint32_t bcs_armcore_clk_policy; 381 1.1 matt uint32_t bcs_armcore_clk_pllarma; 382 1.1 matt uint32_t bcs_armcore_clk_pllarmb; 383 1.1 matt }; 384 1.1 matt 385 1.1 matt static void 386 1.1 matt bcm53xx_get_chip_ioreg_state(struct bcm53xx_chip_state *bcs, 387 1.1 matt bus_space_tag_t bst, bus_space_handle_t bsh) 388 1.1 matt { 389 1.1 matt bcs->bcs_lcpll_control1 = bus_space_read_4(bst, bsh, 390 1.1 matt DMU_BASE + DMU_LCPLL_CONTROL1); 391 1.1 matt bcs->bcs_lcpll_control2 = bus_space_read_4(bst, bsh, 392 1.1 matt DMU_BASE + DMU_LCPLL_CONTROL2); 393 1.1 matt 394 1.1 matt bcs->bcs_genpll_control5 = bus_space_read_4(bst, bsh, 395 1.1 matt CRU_BASE + CRU_GENPLL_CONTROL5); 396 1.1 matt bcs->bcs_genpll_control6 = bus_space_read_4(bst, bsh, 397 1.1 matt CRU_BASE + CRU_GENPLL_CONTROL6); 398 1.1 matt bcs->bcs_genpll_control7 = bus_space_read_4(bst, bsh, 399 1.1 matt CRU_BASE + CRU_GENPLL_CONTROL7); 400 1.1 matt 401 1.1 matt bcs->bcs_usb2_control = bus_space_read_4(bst, bsh, 402 1.1 matt CRU_BASE + CRU_USB2_CONTROL); 403 1.1 matt 404 1.1 matt bcs->bcs_ddr_phy_ctl_pll_status = bus_space_read_4(bst, bsh, 405 1.1 matt DDR_BASE + DDR_PHY_CTL_PLL_STATUS); 406 1.1 matt bcs->bcs_ddr_phy_ctl_pll_dividers = bus_space_read_4(bst, bsh, 407 1.1 matt DDR_BASE + DDR_PHY_CTL_PLL_DIVIDERS); 408 1.1 matt } 409 1.1 matt 410 1.1 matt static void 411 1.1 matt bcm53xx_get_chip_armcore_state(struct bcm53xx_chip_state *bcs, 412 1.1 matt bus_space_tag_t bst, bus_space_handle_t bsh) 413 1.1 matt { 414 1.1 matt bcs->bcs_armcore_clk_policy = bus_space_read_4(bst, bsh, 415 1.1 matt ARMCORE_CLK_POLICY_FREQ); 416 1.1 matt bcs->bcs_armcore_clk_pllarma = bus_space_read_4(bst, bsh, 417 1.1 matt ARMCORE_CLK_PLLARMA); 418 1.1 matt bcs->bcs_armcore_clk_pllarmb = bus_space_read_4(bst, bsh, 419 1.1 matt ARMCORE_CLK_PLLARMB); 420 1.1 matt } 421 1.1 matt 422 1.1 matt void 423 1.1 matt bcm53xx_cpu_softc_init(struct cpu_info *ci) 424 1.1 matt { 425 1.1 matt struct cpu_softc * const cpu = ci->ci_softc; 426 1.1 matt 427 1.1 matt cpu->cpu_ioreg_bst = bcm53xx_ioreg_bst; 428 1.1 matt cpu->cpu_ioreg_bsh = bcm53xx_ioreg_bsh; 429 1.1 matt 430 1.1 matt cpu->cpu_armcore_bst = bcm53xx_armcore_bst; 431 1.1 matt cpu->cpu_armcore_bsh = bcm53xx_armcore_bsh; 432 1.17 matt 433 1.17 matt const uint32_t chipid = bus_space_read_4(cpu->cpu_ioreg_bst, 434 1.17 matt cpu->cpu_ioreg_bsh, CCA_MISC_BASE + MISC_CHIPID); 435 1.17 matt 436 1.17 matt cpu->cpu_chipid = __SHIFTOUT(chipid, CHIPID_ID); 437 1.1 matt } 438 1.1 matt 439 1.1 matt void 440 1.1 matt bcm53xx_print_clocks(void) 441 1.1 matt { 442 1.16 riz #if defined(VERBOSE_INIT_ARM) 443 1.9 matt const struct bcm53xx_clock_info * const clk = &cpu_softc.cpu_clk; 444 1.9 matt printf("ref clk = %u (%#x)\n", clk->clk_ref, clk->clk_ref); 445 1.9 matt printf("sys clk = %u (%#x)\n", clk->clk_sys, clk->clk_sys); 446 1.9 matt printf("lcpll clk = %u (%#x)\n", clk->clk_lcpll, clk->clk_lcpll); 447 1.9 matt printf("pcie ref clk = %u (%#x) [CH0]\n", clk->clk_pcie_ref, clk->clk_pcie_ref); 448 1.9 matt printf("sdio clk = %u (%#x) [CH1]\n", clk->clk_sdio, clk->clk_sdio); 449 1.9 matt printf("ddr ref clk = %u (%#x) [CH2]\n", clk->clk_ddr_ref, clk->clk_ddr_ref); 450 1.9 matt printf("axi clk = %u (%#x) [CH3]\n", clk->clk_axi, clk->clk_axi); 451 1.9 matt printf("genpll clk = %u (%#x)\n", clk->clk_genpll, clk->clk_genpll); 452 1.9 matt printf("mac clk = %u (%#x) [CH0]\n", clk->clk_mac, clk->clk_mac); 453 1.9 matt printf("robo clk = %u (%#x) [CH1]\n", clk->clk_robo, clk->clk_robo); 454 1.9 matt printf("usb2 clk = %u (%#x) [CH2]\n", clk->clk_usb2, clk->clk_usb2); 455 1.9 matt printf("iproc clk = %u (%#x) [CH3]\n", clk->clk_iproc, clk->clk_iproc); 456 1.9 matt printf("ddr clk = %u (%#x)\n", clk->clk_ddr, clk->clk_ddr); 457 1.9 matt printf("ddr mhz = %u (%#x)\n", clk->clk_ddr_mhz, clk->clk_ddr_mhz); 458 1.9 matt printf("cpu clk = %u (%#x)\n", clk->clk_cpu, clk->clk_cpu); 459 1.9 matt printf("apb clk = %u (%#x)\n", clk->clk_apb, clk->clk_apb); 460 1.9 matt printf("usb ref clk = %u (%#x)\n", clk->clk_usb_ref, clk->clk_usb_ref); 461 1.1 matt #endif 462 1.1 matt } 463 1.1 matt 464 1.1 matt void 465 1.1 matt bcm53xx_bootstrap(vaddr_t iobase) 466 1.1 matt { 467 1.1 matt struct bcm53xx_chip_state bcs; 468 1.1 matt int error; 469 1.1 matt 470 1.1 matt bcm53xx_ioreg_bsh = (bus_space_handle_t) iobase; 471 1.1 matt error = bus_space_map(bcm53xx_ioreg_bst, BCM53XX_IOREG_PBASE, 472 1.1 matt BCM53XX_IOREG_SIZE, 0, &bcm53xx_ioreg_bsh); 473 1.1 matt if (error) 474 1.1 matt panic("%s: failed to map BCM53xx %s registers: %d", 475 1.1 matt __func__, "io", error); 476 1.1 matt 477 1.1 matt bcm53xx_armcore_bsh = (bus_space_handle_t) iobase + BCM53XX_IOREG_SIZE; 478 1.1 matt error = bus_space_map(bcm53xx_armcore_bst, BCM53XX_ARMCORE_PBASE, 479 1.1 matt BCM53XX_ARMCORE_SIZE, 0, &bcm53xx_armcore_bsh); 480 1.1 matt if (error) 481 1.1 matt panic("%s: failed to map BCM53xx %s registers: %d", 482 1.1 matt __func__, "armcore", error); 483 1.1 matt 484 1.1 matt curcpu()->ci_softc = &cpu_softc; 485 1.1 matt 486 1.1 matt bcm53xx_get_chip_ioreg_state(&bcs, bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh); 487 1.1 matt bcm53xx_get_chip_armcore_state(&bcs, bcm53xx_armcore_bst, bcm53xx_armcore_bsh); 488 1.1 matt 489 1.9 matt struct bcm53xx_clock_info * const clk = &cpu_softc.cpu_clk; 490 1.1 matt 491 1.1 matt bcm53xx_clock_init(clk); 492 1.1 matt bcm53xx_lcpll_clock_init(clk, bcs.bcs_lcpll_control1, 493 1.1 matt bcs.bcs_lcpll_control2); 494 1.1 matt bcm53xx_genpll_clock_init(clk, bcs.bcs_genpll_control5, 495 1.1 matt bcs.bcs_genpll_control6, bcs.bcs_genpll_control7); 496 1.1 matt bcm53xx_usb_clock_init(clk, bcs.bcs_usb2_control); 497 1.1 matt bcm53xx_get_ddr_freq(clk, bcs.bcs_ddr_phy_ctl_pll_status, 498 1.1 matt bcs.bcs_ddr_phy_ctl_pll_dividers); 499 1.1 matt bcm53xx_get_cpu_freq(clk, bcs.bcs_armcore_clk_pllarma, 500 1.1 matt bcs.bcs_armcore_clk_pllarmb, bcs.bcs_armcore_clk_policy); 501 1.1 matt 502 1.1 matt curcpu()->ci_data.cpu_cc_freq = clk->clk_cpu; 503 1.2 matt 504 1.18 matt #if NARML2CC > 0 505 1.17 matt arml2cc_init(bcm53xx_armcore_bst, bcm53xx_armcore_bsh, 506 1.17 matt ARMCORE_L2C_BASE); 507 1.18 matt #endif 508 1.1 matt } 509 1.1 matt 510 1.5 matt void 511 1.5 matt bcm53xx_dma_bootstrap(psize_t memsize) 512 1.5 matt { 513 1.13 matt if (memsize <= 256*1024*1024) { 514 1.10 matt bcm53xx_dma_ranges[0].dr_len = memsize; 515 1.10 matt bcm53xx_coherent_dma_ranges[0].dr_len = memsize; 516 1.11 matt bcm53xx_dma_tag._nranges = 1; 517 1.10 matt bcm53xx_coherent_dma_tag._nranges = 1; 518 1.10 matt } else { 519 1.5 matt /* 520 1.5 matt * By setting up two ranges, bus_dmamem_alloc will always 521 1.5 matt * try to allocate from range 0 first resulting in allocations 522 1.5 matt * below 256MB which for PCI and GMAC are coherent. 523 1.5 matt */ 524 1.5 matt bcm53xx_dma_ranges[1].dr_len = memsize - 0x10000000; 525 1.8 matt bcm53xx_coherent_dma_ranges[1].dr_len = memsize - 0x10000000; 526 1.5 matt } 527 1.8 matt KASSERT(bcm53xx_dma_tag._ranges[0].dr_flags == 0); 528 1.8 matt KASSERT(bcm53xx_coherent_dma_tag._ranges[0].dr_flags == _BUS_DMAMAP_COHERENT); 529 1.14 matt #ifdef _ARM32_NEED_BUS_DMA_BOUNCE 530 1.14 matt KASSERT(bcm53xx_bounce_dma_tag._ranges[0].dr_flags == _BUS_DMAMAP_COHERENT); 531 1.14 matt #endif 532 1.5 matt } 533 1.5 matt 534 1.1 matt #ifdef MULTIPROCESSOR 535 1.1 matt void 536 1.1 matt bcm53xx_cpu_hatch(struct cpu_info *ci) 537 1.1 matt { 538 1.1 matt a9tmr_init_cpu_clock(ci); 539 1.1 matt } 540 1.1 matt #endif 541 1.1 matt 542 1.1 matt void 543 1.1 matt bcm53xx_device_register(device_t self, void *aux) 544 1.1 matt { 545 1.1 matt prop_dictionary_t dict = device_properties(self); 546 1.1 matt 547 1.1 matt if (device_is_a(self, "armperiph") 548 1.1 matt && device_is_a(device_parent(self), "mainbus")) { 549 1.1 matt /* 550 1.1 matt * XXX KLUDGE ALERT XXX 551 1.1 matt * The iot mainbus supplies is completely wrong since it scales 552 1.22 skrll * addresses by 2. The simplest remedy is to replace with our 553 1.26 skrll * bus space used for the armcore registers (which armperiph uses). 554 1.1 matt */ 555 1.1 matt struct mainbus_attach_args * const mb = aux; 556 1.1 matt mb->mb_iot = bcm53xx_armcore_bst; 557 1.1 matt return; 558 1.1 matt } 559 1.26 skrll 560 1.1 matt /* 561 1.1 matt * We need to tell the A9 Global/Watchdog Timer 562 1.1 matt * what frequency it runs at. 563 1.1 matt */ 564 1.24 hkenken if (device_is_a(self, "arma9tmr") || device_is_a(self, "a9wdt")) { 565 1.1 matt /* 566 1.1 matt * This clock always runs at (arm_clk div 2) and only goes 567 1.1 matt * to timers that are part of the A9 MP core subsystem. 568 1.1 matt */ 569 1.1 matt prop_dictionary_set_uint32(dict, "frequency", 570 1.9 matt cpu_softc.cpu_clk.clk_cpu / 2); 571 1.1 matt return; 572 1.4 matt } 573 1.4 matt 574 1.4 matt if (device_is_a(self, "bcmeth")) { 575 1.4 matt const struct bcmccb_attach_args * const ccbaa = aux; 576 1.4 matt const uint8_t enaddr[ETHER_ADDR_LEN] = { 577 1.4 matt 0x00, 0x01, 0x02, 0x03, 0x04, 578 1.4 matt 0x05 + 2 * ccbaa->ccbaa_loc.loc_port, 579 1.4 matt }; 580 1.4 matt prop_data_t pd = prop_data_create_data(enaddr, ETHER_ADDR_LEN); 581 1.4 matt KASSERT(pd != NULL); 582 1.4 matt if (prop_dictionary_set(device_properties(self), "mac-address", pd) == false) { 583 1.4 matt printf("WARNING: Unable to set mac-address property for %s\n", device_xname(self)); 584 1.4 matt } 585 1.4 matt prop_object_release(pd); 586 1.4 matt } 587 1.4 matt } 588 1.4 matt 589 1.21 matt #ifdef SRAB_BASE 590 1.4 matt static kmutex_t srab_lock __cacheline_aligned; 591 1.4 matt 592 1.4 matt void 593 1.4 matt bcm53xx_srab_init(void) 594 1.4 matt { 595 1.4 matt mutex_init(&srab_lock, MUTEX_DEFAULT, IPL_VM); 596 1.4 matt 597 1.26 skrll bcm53xx_srab_write_4(0x0079, 0x90); // reset switch 598 1.26 skrll for (u_int port = 0; port < 8; port++) { 599 1.4 matt /* per port control: no stp */ 600 1.4 matt bcm53xx_srab_write_4(port, 0x00); 601 1.4 matt } 602 1.4 matt bcm53xx_srab_write_4(0x0008, 0x1c); // IMP port (enab UC/MC/BC) 603 1.4 matt bcm53xx_srab_write_4(0x000e, 0xbb); // IMP port force-link 1G 604 1.4 matt bcm53xx_srab_write_4(0x005d, 0x7b); // port5 force-link 1G 605 1.4 matt bcm53xx_srab_write_4(0x005f, 0x7b); // port7 force-link 1G 606 1.4 matt bcm53xx_srab_write_4(0x000b, 0x7); // management mode 607 1.4 matt bcm53xx_srab_write_4(0x0203, 0x0); // disable BRCM tag 608 1.4 matt bcm53xx_srab_write_4(0x0200, 0x80); // enable IMP=port8 609 1.4 matt } 610 1.4 matt 611 1.4 matt static inline void 612 1.4 matt bcm53xx_srab_busywait(bus_space_tag_t bst, bus_space_handle_t bsh) 613 1.4 matt { 614 1.4 matt while (bus_space_read_4(bst, bsh, SRAB_BASE + SRAB_CMDSTAT) & SRA_GORDYN) { 615 1.4 matt delay(10); 616 1.4 matt } 617 1.4 matt } 618 1.4 matt 619 1.4 matt uint32_t 620 1.4 matt bcm53xx_srab_read_4(u_int pageoffset) 621 1.4 matt { 622 1.4 matt bus_space_tag_t bst = bcm53xx_ioreg_bst; 623 1.4 matt bus_space_handle_t bsh = bcm53xx_ioreg_bsh; 624 1.4 matt uint32_t rv; 625 1.4 matt 626 1.4 matt mutex_spin_enter(&srab_lock); 627 1.4 matt 628 1.4 matt bcm53xx_srab_busywait(bst, bsh); 629 1.4 matt bus_space_write_4(bst, bsh, SRAB_BASE + SRAB_CMDSTAT, 630 1.4 matt __SHIFTIN(pageoffset, SRA_PAGEOFFSET) | SRA_GORDYN); 631 1.4 matt bcm53xx_srab_busywait(bst, bsh); 632 1.4 matt rv = bus_space_read_4(bst, bsh, SRAB_BASE + SRAB_RDL); 633 1.4 matt 634 1.4 matt mutex_spin_exit(&srab_lock); 635 1.4 matt return rv; 636 1.4 matt } 637 1.4 matt 638 1.4 matt uint64_t 639 1.4 matt bcm53xx_srab_read_8(u_int pageoffset) 640 1.4 matt { 641 1.4 matt bus_space_tag_t bst = bcm53xx_ioreg_bst; 642 1.4 matt bus_space_handle_t bsh = bcm53xx_ioreg_bsh; 643 1.4 matt uint64_t rv; 644 1.4 matt 645 1.4 matt mutex_spin_enter(&srab_lock); 646 1.4 matt 647 1.4 matt bcm53xx_srab_busywait(bst, bsh); 648 1.4 matt bus_space_write_4(bst, bsh, SRAB_BASE + SRAB_CMDSTAT, 649 1.4 matt __SHIFTIN(pageoffset, SRA_PAGEOFFSET) | SRA_GORDYN); 650 1.4 matt bcm53xx_srab_busywait(bst, bsh); 651 1.4 matt rv = bus_space_read_4(bst, bsh, SRAB_BASE + SRAB_RDH); 652 1.4 matt rv <<= 32; 653 1.4 matt rv |= bus_space_read_4(bst, bsh, SRAB_BASE + SRAB_RDL); 654 1.4 matt 655 1.4 matt mutex_spin_exit(&srab_lock); 656 1.4 matt return rv; 657 1.4 matt } 658 1.4 matt 659 1.4 matt void 660 1.4 matt bcm53xx_srab_write_4(u_int pageoffset, uint32_t val) 661 1.4 matt { 662 1.4 matt bus_space_tag_t bst = bcm53xx_ioreg_bst; 663 1.4 matt bus_space_handle_t bsh = bcm53xx_ioreg_bsh; 664 1.4 matt 665 1.4 matt mutex_spin_enter(&srab_lock); 666 1.4 matt 667 1.4 matt bcm53xx_srab_busywait(bst, bsh); 668 1.4 matt bus_space_write_4(bst, bsh, SRAB_BASE + SRAB_WDL, val); 669 1.4 matt bus_space_write_4(bst, bsh, SRAB_BASE + SRAB_CMDSTAT, 670 1.4 matt __SHIFTIN(pageoffset, SRA_PAGEOFFSET) | SRA_WRITE | SRA_GORDYN); 671 1.4 matt bcm53xx_srab_busywait(bst, bsh); 672 1.4 matt 673 1.4 matt mutex_spin_exit(&srab_lock); 674 1.4 matt } 675 1.4 matt 676 1.4 matt void 677 1.4 matt bcm53xx_srab_write_8(u_int pageoffset, uint64_t val) 678 1.4 matt { 679 1.4 matt bus_space_tag_t bst = bcm53xx_ioreg_bst; 680 1.4 matt bus_space_handle_t bsh = bcm53xx_ioreg_bsh; 681 1.4 matt 682 1.4 matt mutex_spin_enter(&srab_lock); 683 1.4 matt 684 1.4 matt bcm53xx_srab_busywait(bst, bsh); 685 1.4 matt bus_space_write_4(bst, bsh, SRAB_BASE + SRAB_WDL, val); 686 1.4 matt bus_space_write_4(bst, bsh, SRAB_BASE + SRAB_WDH, val >> 32); 687 1.4 matt bus_space_write_4(bst, bsh, SRAB_BASE + SRAB_CMDSTAT, 688 1.4 matt __SHIFTIN(pageoffset, SRA_PAGEOFFSET) | SRA_WRITE | SRA_GORDYN); 689 1.4 matt bcm53xx_srab_busywait(bst, bsh); 690 1.4 matt mutex_spin_exit(&srab_lock); 691 1.1 matt } 692 1.21 matt #endif 693