1276685Sadrian/*- 2276685Sadrian * Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org> 3276685Sadrian * All rights reserved. 4276685Sadrian * 5276685Sadrian * Redistribution and use in source and binary forms, with or without 6276685Sadrian * modification, are permitted provided that the following conditions 7276685Sadrian * are met: 8276685Sadrian * 1. Redistributions of source code must retain the above copyright 9276685Sadrian * notice, this list of conditions and the following disclaimer. 10276685Sadrian * 2. Redistributions in binary form must reproduce the above copyright 11276685Sadrian * notice, this list of conditions and the following disclaimer in the 12276685Sadrian * documentation and/or other materials provided with the distribution. 13276685Sadrian * 14276685Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15276685Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16276685Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17276685Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18276685Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19276685Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20276685Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21276685Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22276685Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23276685Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24276685Sadrian * SUCH DAMAGE. 25276685Sadrian */ 26276685Sadrian 27276685Sadrian#include <sys/cdefs.h> 28276685Sadrian__FBSDID("$FreeBSD$"); 29276685Sadrian 30276685Sadrian#include "opt_ddb.h" 31276685Sadrian 32276685Sadrian#include <sys/param.h> 33276685Sadrian#include <sys/conf.h> 34276685Sadrian#include <sys/kernel.h> 35276685Sadrian#include <sys/systm.h> 36276685Sadrian#include <sys/bus.h> 37276685Sadrian#include <sys/cons.h> 38276685Sadrian#include <sys/kdb.h> 39276685Sadrian#include <sys/reboot.h> 40276685Sadrian 41276685Sadrian#include <vm/vm.h> 42276685Sadrian#include <vm/vm_page.h> 43276685Sadrian 44276685Sadrian#include <net/ethernet.h> 45276685Sadrian 46276685Sadrian#include <machine/clock.h> 47276685Sadrian#include <machine/cpu.h> 48276685Sadrian#include <machine/cpuregs.h> 49276685Sadrian#include <machine/hwfunc.h> 50276685Sadrian#include <machine/md_var.h> 51276685Sadrian#include <machine/trap.h> 52276685Sadrian#include <machine/vmparam.h> 53276685Sadrian 54276685Sadrian#include <mips/atheros/ar71xxreg.h> 55276685Sadrian//#include <mips/atheros/ar934xreg.h> 56276685Sadrian#include <mips/atheros/qca955xreg.h> 57276685Sadrian 58276685Sadrian#include <mips/atheros/ar71xx_cpudef.h> 59276685Sadrian#include <mips/atheros/ar71xx_setup.h> 60276685Sadrian 61276685Sadrian#include <mips/atheros/ar71xx_chip.h> 62276685Sadrian 63276685Sadrian#include <mips/atheros/qca955x_chip.h> 64276685Sadrian 65276685Sadrianstatic void 66276685Sadrianqca955x_chip_detect_mem_size(void) 67276685Sadrian{ 68276685Sadrian} 69276685Sadrian 70276685Sadrianstatic void 71276685Sadrianqca955x_chip_detect_sys_frequency(void) 72276685Sadrian{ 73276685Sadrian unsigned long ref_rate; 74276685Sadrian unsigned long cpu_rate; 75276685Sadrian unsigned long ddr_rate; 76276685Sadrian unsigned long ahb_rate; 77276685Sadrian uint32_t pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; 78276685Sadrian uint32_t cpu_pll, ddr_pll; 79276685Sadrian uint32_t bootstrap; 80276685Sadrian 81276685Sadrian bootstrap = ATH_READ_REG(QCA955X_RESET_REG_BOOTSTRAP); 82276685Sadrian if (bootstrap & QCA955X_BOOTSTRAP_REF_CLK_40) 83276685Sadrian ref_rate = 40 * 1000 * 1000; 84276685Sadrian else 85276685Sadrian ref_rate = 25 * 1000 * 1000; 86276685Sadrian 87276685Sadrian pll = ATH_READ_REG(QCA955X_PLL_CPU_CONFIG_REG); 88276685Sadrian out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 89276685Sadrian QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK; 90276685Sadrian ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 91276685Sadrian QCA955X_PLL_CPU_CONFIG_REFDIV_MASK; 92276685Sadrian nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) & 93276685Sadrian QCA955X_PLL_CPU_CONFIG_NINT_MASK; 94276685Sadrian frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 95276685Sadrian QCA955X_PLL_CPU_CONFIG_NFRAC_MASK; 96276685Sadrian 97276685Sadrian cpu_pll = nint * ref_rate / ref_div; 98276685Sadrian cpu_pll += frac * ref_rate / (ref_div * (1 << 6)); 99276685Sadrian cpu_pll /= (1 << out_div); 100276685Sadrian 101276685Sadrian pll = ATH_READ_REG(QCA955X_PLL_DDR_CONFIG_REG); 102276685Sadrian out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 103276685Sadrian QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK; 104276685Sadrian ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 105276685Sadrian QCA955X_PLL_DDR_CONFIG_REFDIV_MASK; 106276685Sadrian nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) & 107276685Sadrian QCA955X_PLL_DDR_CONFIG_NINT_MASK; 108276685Sadrian frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 109276685Sadrian QCA955X_PLL_DDR_CONFIG_NFRAC_MASK; 110276685Sadrian 111276685Sadrian ddr_pll = nint * ref_rate / ref_div; 112276685Sadrian ddr_pll += frac * ref_rate / (ref_div * (1 << 10)); 113276685Sadrian ddr_pll /= (1 << out_div); 114276685Sadrian 115276685Sadrian clk_ctrl = ATH_READ_REG(QCA955X_PLL_CLK_CTRL_REG); 116276685Sadrian 117276685Sadrian postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & 118276685Sadrian QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; 119276685Sadrian 120276685Sadrian if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS) 121276685Sadrian cpu_rate = ref_rate; 122276685Sadrian else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) 123276685Sadrian cpu_rate = ddr_pll / (postdiv + 1); 124276685Sadrian else 125276685Sadrian cpu_rate = cpu_pll / (postdiv + 1); 126276685Sadrian 127276685Sadrian postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & 128276685Sadrian QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; 129276685Sadrian 130276685Sadrian if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS) 131276685Sadrian ddr_rate = ref_rate; 132276685Sadrian else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) 133276685Sadrian ddr_rate = cpu_pll / (postdiv + 1); 134276685Sadrian else 135276685Sadrian ddr_rate = ddr_pll / (postdiv + 1); 136276685Sadrian 137276685Sadrian postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & 138276685Sadrian QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; 139276685Sadrian 140276685Sadrian if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS) 141276685Sadrian ahb_rate = ref_rate; 142276685Sadrian else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) 143276685Sadrian ahb_rate = ddr_pll / (postdiv + 1); 144276685Sadrian else 145276685Sadrian ahb_rate = cpu_pll / (postdiv + 1); 146276685Sadrian 147276685Sadrian u_ar71xx_ddr_freq = ddr_rate; 148276685Sadrian u_ar71xx_cpu_freq = cpu_rate; 149276685Sadrian u_ar71xx_ahb_freq = ahb_rate; 150276685Sadrian 151276685Sadrian u_ar71xx_wdt_freq = ref_rate; 152276685Sadrian u_ar71xx_uart_freq = ref_rate; 153276685Sadrian u_ar71xx_mdio_freq = ref_rate; 154276690Sadrian u_ar71xx_refclk = ref_rate; 155276685Sadrian} 156276685Sadrian 157276685Sadrianstatic void 158276685Sadrianqca955x_chip_device_stop(uint32_t mask) 159276685Sadrian{ 160276685Sadrian uint32_t reg; 161276685Sadrian 162276685Sadrian reg = ATH_READ_REG(QCA955X_RESET_REG_RESET_MODULE); 163276685Sadrian ATH_WRITE_REG(QCA955X_RESET_REG_RESET_MODULE, reg | mask); 164276685Sadrian} 165276685Sadrian 166276685Sadrianstatic void 167276685Sadrianqca955x_chip_device_start(uint32_t mask) 168276685Sadrian{ 169276685Sadrian uint32_t reg; 170276685Sadrian 171276685Sadrian reg = ATH_READ_REG(QCA955X_RESET_REG_RESET_MODULE); 172276685Sadrian ATH_WRITE_REG(QCA955X_RESET_REG_RESET_MODULE, reg & ~mask); 173276685Sadrian} 174276685Sadrian 175276685Sadrianstatic int 176276685Sadrianqca955x_chip_device_stopped(uint32_t mask) 177276685Sadrian{ 178276685Sadrian uint32_t reg; 179276685Sadrian 180276685Sadrian reg = ATH_READ_REG(QCA955X_RESET_REG_RESET_MODULE); 181276685Sadrian return ((reg & mask) == mask); 182276685Sadrian} 183276685Sadrian 184276685Sadrianstatic void 185276685Sadrianqca955x_chip_set_mii_speed(uint32_t unit, uint32_t speed) 186276685Sadrian{ 187276685Sadrian 188276685Sadrian /* XXX TODO */ 189276685Sadrian return; 190276685Sadrian} 191276685Sadrian 192276685Sadrianstatic void 193276685Sadrianqca955x_chip_set_pll_ge(int unit, int speed, uint32_t pll) 194276685Sadrian{ 195276685Sadrian switch (unit) { 196276685Sadrian case 0: 197279479Sadrian ATH_WRITE_REG(QCA955X_PLL_ETH_XMII_CONTROL_REG, pll); 198276685Sadrian break; 199276685Sadrian case 1: 200279479Sadrian ATH_WRITE_REG(QCA955X_PLL_ETH_SGMII_CONTROL_REG, pll); 201276685Sadrian break; 202276685Sadrian default: 203276685Sadrian printf("%s: invalid PLL set for arge unit: %d\n", 204276685Sadrian __func__, unit); 205276685Sadrian return; 206276685Sadrian } 207276685Sadrian} 208276685Sadrian 209276685Sadrianstatic void 210285121Sadrianqca955x_chip_ddr_flush(ar71xx_flush_ddr_id_t id) 211276685Sadrian{ 212279579Sadrian 213285121Sadrian switch (id) { 214285121Sadrian case AR71XX_CPU_DDR_FLUSH_GE0: 215279579Sadrian ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_GE0); 216276685Sadrian break; 217285121Sadrian case AR71XX_CPU_DDR_FLUSH_GE1: 218279579Sadrian ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_GE1); 219276685Sadrian break; 220285121Sadrian case AR71XX_CPU_DDR_FLUSH_USB: 221285121Sadrian ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_USB); 222285121Sadrian break; 223285121Sadrian case AR71XX_CPU_DDR_FLUSH_PCIE: 224285121Sadrian ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_PCIE); 225285121Sadrian break; 226285121Sadrian case AR71XX_CPU_DDR_FLUSH_WMAC: 227285121Sadrian ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_WMAC); 228285121Sadrian break; 229285121Sadrian case AR71XX_CPU_DDR_FLUSH_PCIE_EP: 230285121Sadrian ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_SRC1); 231285121Sadrian break; 232285121Sadrian case AR71XX_CPU_DDR_FLUSH_CHECKSUM: 233285121Sadrian ar71xx_ddr_flush(QCA955X_DDR_REG_FLUSH_SRC2); 234285121Sadrian break; 235276685Sadrian default: 236285121Sadrian printf("%s: invalid flush (%d)\n", __func__, id); 237276685Sadrian } 238276685Sadrian} 239276685Sadrian 240276685Sadrianstatic uint32_t 241276685Sadrianqca955x_chip_get_eth_pll(unsigned int mac, int speed) 242276685Sadrian{ 243276685Sadrian uint32_t pll; 244276685Sadrian 245276685Sadrian switch (speed) { 246276685Sadrian case 10: 247279479Sadrian pll = QCA955X_PLL_VAL_10; 248276685Sadrian break; 249276685Sadrian case 100: 250279479Sadrian pll = QCA955X_PLL_VAL_100; 251276685Sadrian break; 252276685Sadrian case 1000: 253279479Sadrian pll = QCA955X_PLL_VAL_1000; 254276685Sadrian break; 255276685Sadrian default: 256276685Sadrian printf("%s%d: invalid speed %d\n", __func__, mac, speed); 257276685Sadrian pll = 0; 258276685Sadrian } 259276685Sadrian return (pll); 260276685Sadrian} 261276685Sadrian 262276685Sadrianstatic void 263276685Sadrianqca955x_chip_reset_ethernet_switch(void) 264276685Sadrian{ 265276685Sadrian#if 0 266276685Sadrian ar71xx_device_stop(AR934X_RESET_ETH_SWITCH); 267276685Sadrian DELAY(100); 268276685Sadrian ar71xx_device_start(AR934X_RESET_ETH_SWITCH); 269276685Sadrian DELAY(100); 270276685Sadrian#endif 271276685Sadrian} 272276685Sadrian 273276685Sadrianstatic void 274276685Sadrianqca955x_configure_gmac(uint32_t gmac_cfg) 275276685Sadrian{ 276276685Sadrian uint32_t reg; 277276685Sadrian 278279479Sadrian reg = ATH_READ_REG(QCA955X_GMAC_REG_ETH_CFG); 279276685Sadrian printf("%s: ETH_CFG=0x%08x\n", __func__, reg); 280279479Sadrian reg &= ~(QCA955X_ETH_CFG_RGMII_EN | QCA955X_ETH_CFG_GE0_SGMII); 281276685Sadrian reg |= gmac_cfg; 282279479Sadrian ATH_WRITE_REG(QCA955X_GMAC_REG_ETH_CFG, reg); 283276685Sadrian} 284276685Sadrian 285276685Sadrianstatic void 286276685Sadrianqca955x_chip_init_usb_peripheral(void) 287276685Sadrian{ 288276685Sadrian} 289276685Sadrian 290276685Sadrianstatic void 291276685Sadrianqca955x_chip_set_mii_if(uint32_t unit, uint32_t mii_mode) 292276685Sadrian{ 293276685Sadrian 294276685Sadrian /* 295276685Sadrian * XXX ! 296276685Sadrian * 297276685Sadrian * Nothing to see here; although gmac0 can have its 298276685Sadrian * MII configuration changed, the register values 299276685Sadrian * are slightly different. 300276685Sadrian */ 301276685Sadrian} 302276685Sadrian 303276685Sadrian/* 304276685Sadrian * XXX TODO: fetch default MII divider configuration 305276685Sadrian */ 306276685Sadrian 307276685Sadrianstatic void 308276685Sadrianqca955x_chip_reset_wmac(void) 309276685Sadrian{ 310276685Sadrian 311276685Sadrian /* XXX TODO */ 312276685Sadrian} 313276685Sadrian 314276685Sadrianstatic void 315276685Sadrianqca955x_chip_init_gmac(void) 316276685Sadrian{ 317276685Sadrian long gmac_cfg; 318276685Sadrian 319279479Sadrian if (resource_long_value("qca955x_gmac", 0, "gmac_cfg", 320276685Sadrian &gmac_cfg) == 0) { 321276685Sadrian printf("%s: gmac_cfg=0x%08lx\n", 322276685Sadrian __func__, 323276685Sadrian (long) gmac_cfg); 324279479Sadrian qca955x_configure_gmac((uint32_t) gmac_cfg); 325276685Sadrian } 326276685Sadrian} 327276685Sadrian 328276685Sadrian/* 329276685Sadrian * Reset the NAND Flash Controller. 330276685Sadrian * 331276685Sadrian * + active=1 means "make it active". 332276685Sadrian * + active=0 means "make it inactive". 333276685Sadrian */ 334276685Sadrianstatic void 335276685Sadrianqca955x_chip_reset_nfc(int active) 336276685Sadrian{ 337276685Sadrian#if 0 338276685Sadrian if (active) { 339276685Sadrian ar71xx_device_start(AR934X_RESET_NANDF); 340276685Sadrian DELAY(100); 341276685Sadrian 342276685Sadrian ar71xx_device_start(AR934X_RESET_ETH_SWITCH_ANALOG); 343276685Sadrian DELAY(250); 344276685Sadrian } else { 345276685Sadrian ar71xx_device_stop(AR934X_RESET_ETH_SWITCH_ANALOG); 346276685Sadrian DELAY(250); 347276685Sadrian 348276685Sadrian ar71xx_device_stop(AR934X_RESET_NANDF); 349276685Sadrian DELAY(100); 350276685Sadrian } 351276685Sadrian#endif 352276685Sadrian} 353276685Sadrian 354276685Sadrian/* 355276685Sadrian * Configure the GPIO output mux setup. 356276685Sadrian * 357285073Sadrian * The QCA955x has an output mux which allowed 358276685Sadrian * certain functions to be configured on any pin. 359276685Sadrian * Specifically, the switch PHY link LEDs and 360276685Sadrian * WMAC external RX LNA switches are not limited to 361276685Sadrian * a specific GPIO pin. 362276685Sadrian */ 363276685Sadrianstatic void 364276685Sadrianqca955x_chip_gpio_output_configure(int gpio, uint8_t func) 365276685Sadrian{ 366276685Sadrian uint32_t reg, s; 367276685Sadrian uint32_t t; 368276685Sadrian 369276685Sadrian if (gpio > QCA955X_GPIO_COUNT) 370276685Sadrian return; 371276685Sadrian 372298848Spfg reg = QCA955X_GPIO_REG_OUT_FUNC0 + rounddown(gpio, 4); 373276685Sadrian s = 8 * (gpio % 4); 374276685Sadrian 375276685Sadrian /* read-modify-write */ 376276685Sadrian t = ATH_READ_REG(AR71XX_GPIO_BASE + reg); 377276685Sadrian t &= ~(0xff << s); 378276685Sadrian t |= func << s; 379276685Sadrian ATH_WRITE_REG(AR71XX_GPIO_BASE + reg, t); 380276685Sadrian 381276685Sadrian /* flush write */ 382276685Sadrian ATH_READ_REG(AR71XX_GPIO_BASE + reg); 383276685Sadrian} 384276685Sadrian 385276685Sadrianstruct ar71xx_cpu_def qca955x_chip_def = { 386276685Sadrian &qca955x_chip_detect_mem_size, 387276685Sadrian &qca955x_chip_detect_sys_frequency, 388276685Sadrian &qca955x_chip_device_stop, 389276685Sadrian &qca955x_chip_device_start, 390276685Sadrian &qca955x_chip_device_stopped, 391276685Sadrian &qca955x_chip_set_pll_ge, 392276685Sadrian &qca955x_chip_set_mii_speed, 393276685Sadrian &qca955x_chip_set_mii_if, 394276685Sadrian &qca955x_chip_get_eth_pll, 395285121Sadrian &qca955x_chip_ddr_flush, 396276685Sadrian &qca955x_chip_init_usb_peripheral, 397276685Sadrian &qca955x_chip_reset_ethernet_switch, 398276685Sadrian &qca955x_chip_reset_wmac, 399276685Sadrian &qca955x_chip_init_gmac, 400276685Sadrian &qca955x_chip_reset_nfc, 401276685Sadrian &qca955x_chip_gpio_output_configure, 402276685Sadrian}; 403