1/*- 2 * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include "opt_ddb.h" 31 32#include <sys/param.h> 33#include <sys/conf.h> 34#include <sys/kernel.h> 35#include <sys/systm.h> 36#include <sys/bus.h> 37#include <sys/cons.h> 38#include <sys/kdb.h> 39#include <sys/reboot.h> 40 41#include <vm/vm.h> 42#include <vm/vm_page.h> 43 44#include <net/ethernet.h> 45 46#include <machine/clock.h> 47#include <machine/cpu.h> 48#include <machine/cpuregs.h> 49#include <machine/hwfunc.h> 50#include <machine/md_var.h> 51#include <machine/trap.h> 52#include <machine/vmparam.h> 53 54#include <mips/atheros/ar71xxreg.h> 55#include <mips/atheros/ar934xreg.h> 56 57#include <mips/atheros/ar71xx_cpudef.h> 58#include <mips/atheros/ar71xx_setup.h> 59 60#include <mips/atheros/ar71xx_chip.h> 61#include <mips/atheros/ar934x_chip.h> 62 63static void 64ar934x_chip_detect_mem_size(void) 65{ 66} 67 68static uint32_t 69ar934x_get_pll_freq(uint32_t ref, uint32_t ref_div, uint32_t nint, 70 uint32_t nfrac, uint32_t frac, uint32_t out_div) 71{ 72 uint64_t t; 73 uint32_t ret; 74 75 t = u_ar71xx_refclk; 76 t *= nint; 77 t = t / ref_div; 78 ret = t; 79 80 t = u_ar71xx_refclk; 81 t *= nfrac; 82 t = t / (ref_div * frac); 83 ret += t; 84 85 ret /= (1 << out_div); 86 return (ret); 87} 88 89static void 90ar934x_chip_detect_sys_frequency(void) 91{ 92 uint32_t pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; 93 uint32_t cpu_pll, ddr_pll; 94 uint32_t bootstrap; 95 96 bootstrap = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP); 97 if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) 98 u_ar71xx_refclk = 40 * 1000 * 1000; 99 else 100 u_ar71xx_refclk = 25 * 1000 * 1000; 101 102 pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL2_REG); 103 if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 104 out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 105 AR934X_SRIF_DPLL2_OUTDIV_MASK; 106 pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL1_REG); 107 nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 108 AR934X_SRIF_DPLL1_NINT_MASK; 109 nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 110 ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 111 AR934X_SRIF_DPLL1_REFDIV_MASK; 112 frac = 1 << 18; 113 } else { 114 pll = ATH_READ_REG(AR934X_PLL_CPU_CONFIG_REG); 115 out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 116 AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; 117 ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 118 AR934X_PLL_CPU_CONFIG_REFDIV_MASK; 119 nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & 120 AR934X_PLL_CPU_CONFIG_NINT_MASK; 121 nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 122 AR934X_PLL_CPU_CONFIG_NFRAC_MASK; 123 frac = 1 << 6; 124 } 125 126 cpu_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint, 127 nfrac, frac, out_div); 128 129 pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL2_REG); 130 if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 131 out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 132 AR934X_SRIF_DPLL2_OUTDIV_MASK; 133 pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL1_REG); 134 nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 135 AR934X_SRIF_DPLL1_NINT_MASK; 136 nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 137 ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 138 AR934X_SRIF_DPLL1_REFDIV_MASK; 139 frac = 1 << 18; 140 } else { 141 pll = ATH_READ_REG(AR934X_PLL_DDR_CONFIG_REG); 142 out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 143 AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; 144 ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 145 AR934X_PLL_DDR_CONFIG_REFDIV_MASK; 146 nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & 147 AR934X_PLL_DDR_CONFIG_NINT_MASK; 148 nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 149 AR934X_PLL_DDR_CONFIG_NFRAC_MASK; 150 frac = 1 << 10; 151 } 152 153 ddr_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint, 154 nfrac, frac, out_div); 155 156 clk_ctrl = ATH_READ_REG(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 157 158 postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) & 159 AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK; 160 161 if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS) 162 u_ar71xx_cpu_freq = u_ar71xx_refclk; 163 else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL) 164 u_ar71xx_cpu_freq = cpu_pll / (postdiv + 1); 165 else 166 u_ar71xx_cpu_freq = ddr_pll / (postdiv + 1); 167 168 postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) & 169 AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK; 170 171 if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS) 172 u_ar71xx_ddr_freq = u_ar71xx_refclk; 173 else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL) 174 u_ar71xx_ddr_freq = ddr_pll / (postdiv + 1); 175 else 176 u_ar71xx_ddr_freq = cpu_pll / (postdiv + 1); 177 178 postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) & 179 AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK; 180 181 if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS) 182 u_ar71xx_ahb_freq = u_ar71xx_refclk; 183 else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL) 184 u_ar71xx_ahb_freq = ddr_pll / (postdiv + 1); 185 else 186 u_ar71xx_ahb_freq = cpu_pll / (postdiv + 1); 187 188 u_ar71xx_wdt_freq = u_ar71xx_refclk; 189 u_ar71xx_uart_freq = u_ar71xx_refclk; 190} 191 192static void 193ar934x_chip_device_stop(uint32_t mask) 194{ 195 uint32_t reg; 196 197 reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE); 198 ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg | mask); 199} 200 201static void 202ar934x_chip_device_start(uint32_t mask) 203{ 204 uint32_t reg; 205 206 reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE); 207 ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg & ~mask); 208} 209 210static int 211ar934x_chip_device_stopped(uint32_t mask) 212{ 213 uint32_t reg; 214 215 reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE); 216 return ((reg & mask) == mask); 217} 218 219static void 220ar934x_chip_set_mii_speed(uint32_t unit, uint32_t speed) 221{ 222 223 /* XXX TODO */ 224 return; 225} 226 227/* 228 * XXX TODO !! 229 */ 230static void 231ar934x_chip_set_pll_ge(int unit, int speed, uint32_t pll) 232{ 233 234 switch (unit) { 235 case 0: 236 /* XXX TODO */ 237 break; 238 case 1: 239 /* XXX TODO */ 240 break; 241 default: 242 printf("%s: invalid PLL set for arge unit: %d\n", 243 __func__, unit); 244 return; 245 } 246} 247 248static void 249ar934x_chip_ddr_flush_ge(int unit) 250{ 251 252 switch (unit) { 253 case 0: 254 ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE0); 255 break; 256 case 1: 257 ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE1); 258 break; 259 default: 260 printf("%s: invalid DDR flush for arge unit: %d\n", 261 __func__, unit); 262 return; 263 } 264} 265 266static void 267ar934x_chip_ddr_flush_ip2(void) 268{ 269 270 ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_WMAC); 271} 272 273static uint32_t 274ar934x_chip_get_eth_pll(unsigned int mac, int speed) 275{ 276#if 0 277 uint32_t pll; 278 279 switch (speed) { 280 case 10: 281 pll = AR933X_PLL_VAL_10; 282 break; 283 case 100: 284 pll = AR933X_PLL_VAL_100; 285 break; 286 case 1000: 287 pll = AR933X_PLL_VAL_1000; 288 break; 289 default: 290 printf("%s%d: invalid speed %d\n", __func__, mac, speed); 291 pll = 0; 292 } 293 return (pll); 294#endif 295 return (0); 296} 297 298static void 299ar934x_chip_init_usb_peripheral(void) 300{ 301 uint32_t reg; 302 303 reg = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP); 304 if (reg & AR934X_BOOTSTRAP_USB_MODE_DEVICE) 305 return; 306 307 ar71xx_device_stop(AR934X_RESET_USBSUS_OVERRIDE); 308 DELAY(100); 309 310 ar71xx_device_start(AR934X_RESET_USB_PHY); 311 DELAY(100); 312 313 ar71xx_device_start(AR934X_RESET_USB_PHY_ANALOG); 314 DELAY(100); 315 316 ar71xx_device_start(AR934X_RESET_USB_HOST); 317 DELAY(100); 318} 319 320struct ar71xx_cpu_def ar934x_chip_def = { 321 &ar934x_chip_detect_mem_size, 322 &ar934x_chip_detect_sys_frequency, 323 &ar934x_chip_device_stop, 324 &ar934x_chip_device_start, 325 &ar934x_chip_device_stopped, 326 &ar934x_chip_set_pll_ge, 327 &ar934x_chip_set_mii_speed, 328 &ar71xx_chip_set_mii_if, 329 &ar934x_chip_ddr_flush_ge, 330 &ar934x_chip_get_eth_pll, 331 &ar934x_chip_ddr_flush_ip2, 332 &ar934x_chip_init_usb_peripheral 333}; 334