1290910Sadrian/*- 2290910Sadrian * Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org> 3290910Sadrian * All rights reserved. 4290910Sadrian * 5290910Sadrian * Redistribution and use in source and binary forms, with or without 6290910Sadrian * modification, are permitted provided that the following conditions 7290910Sadrian * are met: 8290910Sadrian * 1. Redistributions of source code must retain the above copyright 9290910Sadrian * notice, this list of conditions and the following disclaimer. 10290910Sadrian * 2. Redistributions in binary form must reproduce the above copyright 11290910Sadrian * notice, this list of conditions and the following disclaimer in the 12290910Sadrian * documentation and/or other materials provided with the distribution. 13290910Sadrian * 14290910Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15290910Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16290910Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17290910Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18290910Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19290910Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20290910Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21290910Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22290910Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23290910Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24290910Sadrian * SUCH DAMAGE. 25290910Sadrian */ 26290910Sadrian 27290910Sadrian#include <sys/cdefs.h> 28290910Sadrian__FBSDID("$FreeBSD: releng/11.0/sys/mips/atheros/qca953x_chip.c 298848 2016-04-30 14:41:18Z pfg $"); 29290910Sadrian 30290910Sadrian#include "opt_ddb.h" 31290910Sadrian 32290910Sadrian#include <sys/param.h> 33290910Sadrian#include <sys/conf.h> 34290910Sadrian#include <sys/kernel.h> 35290910Sadrian#include <sys/systm.h> 36290910Sadrian#include <sys/bus.h> 37290910Sadrian#include <sys/cons.h> 38290910Sadrian#include <sys/kdb.h> 39290910Sadrian#include <sys/reboot.h> 40290910Sadrian 41290910Sadrian#include <vm/vm.h> 42290910Sadrian#include <vm/vm_page.h> 43290910Sadrian 44290910Sadrian#include <net/ethernet.h> 45290910Sadrian 46290910Sadrian#include <machine/clock.h> 47290910Sadrian#include <machine/cpu.h> 48290910Sadrian#include <machine/cpuregs.h> 49290910Sadrian#include <machine/hwfunc.h> 50290910Sadrian#include <machine/md_var.h> 51290910Sadrian#include <machine/trap.h> 52290910Sadrian#include <machine/vmparam.h> 53290910Sadrian 54290910Sadrian#include <mips/atheros/ar71xxreg.h> 55290910Sadrian#include <mips/atheros/qca953xreg.h> 56290910Sadrian 57290910Sadrian#include <mips/atheros/ar71xx_cpudef.h> 58290910Sadrian#include <mips/atheros/ar71xx_setup.h> 59290910Sadrian 60290910Sadrian#include <mips/atheros/ar71xx_chip.h> 61290910Sadrian 62290910Sadrian#include <mips/atheros/qca953x_chip.h> 63290910Sadrian 64290910Sadrianstatic void 65290910Sadrianqca953x_chip_detect_mem_size(void) 66290910Sadrian{ 67290910Sadrian} 68290910Sadrian 69290910Sadrianstatic void 70290910Sadrianqca953x_chip_detect_sys_frequency(void) 71290910Sadrian{ 72290910Sadrian unsigned long ref_rate; 73290910Sadrian unsigned long cpu_rate; 74290910Sadrian unsigned long ddr_rate; 75290910Sadrian unsigned long ahb_rate; 76290910Sadrian uint32_t pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; 77290910Sadrian uint32_t cpu_pll, ddr_pll; 78290910Sadrian uint32_t bootstrap; 79290910Sadrian 80290910Sadrian bootstrap = ATH_READ_REG(QCA953X_RESET_REG_BOOTSTRAP); 81290910Sadrian if (bootstrap & QCA953X_BOOTSTRAP_REF_CLK_40) 82290910Sadrian ref_rate = 40 * 1000 * 1000; 83290910Sadrian else 84290910Sadrian ref_rate = 25 * 1000 * 1000; 85290910Sadrian 86290910Sadrian pll = ATH_READ_REG(QCA953X_PLL_CPU_CONFIG_REG); 87290910Sadrian out_div = (pll >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 88290910Sadrian QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK; 89290910Sadrian ref_div = (pll >> QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 90290910Sadrian QCA953X_PLL_CPU_CONFIG_REFDIV_MASK; 91290910Sadrian nint = (pll >> QCA953X_PLL_CPU_CONFIG_NINT_SHIFT) & 92290910Sadrian QCA953X_PLL_CPU_CONFIG_NINT_MASK; 93290910Sadrian frac = (pll >> QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 94290910Sadrian QCA953X_PLL_CPU_CONFIG_NFRAC_MASK; 95290910Sadrian 96290910Sadrian cpu_pll = nint * ref_rate / ref_div; 97290910Sadrian cpu_pll += frac * (ref_rate >> 6) / ref_div; 98290910Sadrian cpu_pll /= (1 << out_div); 99290910Sadrian 100290910Sadrian pll = ATH_READ_REG(QCA953X_PLL_DDR_CONFIG_REG); 101290910Sadrian out_div = (pll >> QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 102290910Sadrian QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK; 103290910Sadrian ref_div = (pll >> QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 104290910Sadrian QCA953X_PLL_DDR_CONFIG_REFDIV_MASK; 105290910Sadrian nint = (pll >> QCA953X_PLL_DDR_CONFIG_NINT_SHIFT) & 106290910Sadrian QCA953X_PLL_DDR_CONFIG_NINT_MASK; 107290910Sadrian frac = (pll >> QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 108290910Sadrian QCA953X_PLL_DDR_CONFIG_NFRAC_MASK; 109290910Sadrian 110290910Sadrian ddr_pll = nint * ref_rate / ref_div; 111290910Sadrian ddr_pll += frac * (ref_rate >> 6) / (ref_div << 4); 112290910Sadrian ddr_pll /= (1 << out_div); 113290910Sadrian 114290910Sadrian clk_ctrl = ATH_READ_REG(QCA953X_PLL_CLK_CTRL_REG); 115290910Sadrian 116290910Sadrian postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & 117290910Sadrian QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; 118290910Sadrian 119290910Sadrian if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS) 120290910Sadrian cpu_rate = ref_rate; 121290910Sadrian else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) 122290910Sadrian cpu_rate = cpu_pll / (postdiv + 1); 123290910Sadrian else 124290910Sadrian cpu_rate = ddr_pll / (postdiv + 1); 125290910Sadrian 126290910Sadrian postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & 127290910Sadrian QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; 128290910Sadrian 129290910Sadrian if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS) 130290910Sadrian ddr_rate = ref_rate; 131290910Sadrian else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) 132290910Sadrian ddr_rate = ddr_pll / (postdiv + 1); 133290910Sadrian else 134290910Sadrian ddr_rate = cpu_pll / (postdiv + 1); 135290910Sadrian 136290910Sadrian postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & 137290910Sadrian QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; 138290910Sadrian 139290910Sadrian if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS) 140290910Sadrian ahb_rate = ref_rate; 141290910Sadrian else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) 142290910Sadrian ahb_rate = ddr_pll / (postdiv + 1); 143290910Sadrian else 144290910Sadrian ahb_rate = cpu_pll / (postdiv + 1); 145290910Sadrian 146290910Sadrian u_ar71xx_ddr_freq = ddr_rate; 147290910Sadrian u_ar71xx_cpu_freq = cpu_rate; 148290910Sadrian u_ar71xx_ahb_freq = ahb_rate; 149290910Sadrian 150290910Sadrian u_ar71xx_wdt_freq = ref_rate; 151290910Sadrian u_ar71xx_uart_freq = ref_rate; 152290910Sadrian u_ar71xx_mdio_freq = ref_rate; 153290910Sadrian u_ar71xx_refclk = ref_rate; 154290910Sadrian} 155290910Sadrian 156290910Sadrianstatic void 157290910Sadrianqca953x_chip_device_stop(uint32_t mask) 158290910Sadrian{ 159290910Sadrian uint32_t reg; 160290910Sadrian 161290910Sadrian reg = ATH_READ_REG(QCA953X_RESET_REG_RESET_MODULE); 162290910Sadrian ATH_WRITE_REG(QCA953X_RESET_REG_RESET_MODULE, reg | mask); 163290910Sadrian} 164290910Sadrian 165290910Sadrianstatic void 166290910Sadrianqca953x_chip_device_start(uint32_t mask) 167290910Sadrian{ 168290910Sadrian uint32_t reg; 169290910Sadrian 170290910Sadrian reg = ATH_READ_REG(QCA953X_RESET_REG_RESET_MODULE); 171290910Sadrian ATH_WRITE_REG(QCA953X_RESET_REG_RESET_MODULE, reg & ~mask); 172290910Sadrian} 173290910Sadrian 174290910Sadrianstatic int 175290910Sadrianqca953x_chip_device_stopped(uint32_t mask) 176290910Sadrian{ 177290910Sadrian uint32_t reg; 178290910Sadrian 179290910Sadrian reg = ATH_READ_REG(QCA953X_RESET_REG_RESET_MODULE); 180290910Sadrian return ((reg & mask) == mask); 181290910Sadrian} 182290910Sadrian 183290910Sadrianstatic void 184290910Sadrianqca953x_chip_set_mii_speed(uint32_t unit, uint32_t speed) 185290910Sadrian{ 186290910Sadrian 187290910Sadrian /* XXX TODO */ 188290910Sadrian return; 189290910Sadrian} 190290910Sadrian 191290910Sadrianstatic void 192290910Sadrianqca953x_chip_set_pll_ge(int unit, int speed, uint32_t pll) 193290910Sadrian{ 194290910Sadrian switch (unit) { 195290910Sadrian case 0: 196290910Sadrian ATH_WRITE_REG(QCA953X_PLL_ETH_XMII_CONTROL_REG, pll); 197290910Sadrian break; 198290910Sadrian case 1: 199292247Sadrian /* nothing */ 200290910Sadrian break; 201290910Sadrian default: 202290910Sadrian printf("%s: invalid PLL set for arge unit: %d\n", 203290910Sadrian __func__, unit); 204290910Sadrian return; 205290910Sadrian } 206290910Sadrian} 207290910Sadrian 208290910Sadrianstatic void 209290910Sadrianqca953x_chip_ddr_flush(ar71xx_flush_ddr_id_t id) 210290910Sadrian{ 211290910Sadrian 212290910Sadrian switch (id) { 213290910Sadrian case AR71XX_CPU_DDR_FLUSH_GE0: 214290910Sadrian ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_GE0); 215290910Sadrian break; 216290910Sadrian case AR71XX_CPU_DDR_FLUSH_GE1: 217290910Sadrian ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_GE1); 218290910Sadrian break; 219290910Sadrian case AR71XX_CPU_DDR_FLUSH_USB: 220290910Sadrian ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_USB); 221290910Sadrian break; 222290910Sadrian case AR71XX_CPU_DDR_FLUSH_PCIE: 223290910Sadrian ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_PCIE); 224290910Sadrian break; 225290910Sadrian case AR71XX_CPU_DDR_FLUSH_WMAC: 226290910Sadrian ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_WMAC); 227290910Sadrian break; 228290910Sadrian default: 229290910Sadrian printf("%s: invalid flush (%d)\n", __func__, id); 230290910Sadrian } 231290910Sadrian} 232290910Sadrian 233290910Sadrianstatic uint32_t 234290910Sadrianqca953x_chip_get_eth_pll(unsigned int mac, int speed) 235290910Sadrian{ 236290910Sadrian uint32_t pll; 237290910Sadrian 238290910Sadrian switch (speed) { 239290910Sadrian case 10: 240290910Sadrian pll = QCA953X_PLL_VAL_10; 241290910Sadrian break; 242290910Sadrian case 100: 243290910Sadrian pll = QCA953X_PLL_VAL_100; 244290910Sadrian break; 245290910Sadrian case 1000: 246290910Sadrian pll = QCA953X_PLL_VAL_1000; 247290910Sadrian break; 248290910Sadrian default: 249290910Sadrian printf("%s%d: invalid speed %d\n", __func__, mac, speed); 250290910Sadrian pll = 0; 251290910Sadrian } 252290910Sadrian return (pll); 253290910Sadrian} 254290910Sadrian 255290910Sadrianstatic void 256290910Sadrianqca953x_chip_reset_ethernet_switch(void) 257290910Sadrian{ 258290910Sadrian} 259290910Sadrian 260290910Sadrianstatic void 261290910Sadrianqca953x_configure_gmac(uint32_t gmac_cfg) 262290910Sadrian{ 263290910Sadrian uint32_t reg; 264290910Sadrian 265290910Sadrian reg = ATH_READ_REG(QCA953X_GMAC_REG_ETH_CFG); 266290910Sadrian printf("%s: ETH_CFG=0x%08x\n", __func__, reg); 267290910Sadrian reg &= ~(QCA953X_ETH_CFG_SW_ONLY_MODE | 268290910Sadrian QCA953X_ETH_CFG_SW_PHY_SWAP | 269290910Sadrian QCA953X_ETH_CFG_SW_APB_ACCESS | 270290910Sadrian QCA953X_ETH_CFG_SW_ACC_MSB_FIRST); 271290910Sadrian 272290910Sadrian reg |= gmac_cfg; 273290910Sadrian ATH_WRITE_REG(QCA953X_GMAC_REG_ETH_CFG, reg); 274290910Sadrian} 275290910Sadrian 276290910Sadrianstatic void 277290910Sadrianqca953x_chip_init_usb_peripheral(void) 278290910Sadrian{ 279290910Sadrian uint32_t bootstrap; 280290910Sadrian 281290910Sadrian bootstrap = ATH_READ_REG(QCA953X_RESET_REG_BOOTSTRAP); 282290910Sadrian 283290910Sadrian ar71xx_device_stop(QCA953X_RESET_USBSUS_OVERRIDE); 284290910Sadrian DELAY(1000); 285290910Sadrian 286290910Sadrian ar71xx_device_start(QCA953X_RESET_USB_PHY); 287290910Sadrian DELAY(1000); 288290910Sadrian 289290910Sadrian ar71xx_device_start(QCA953X_RESET_USB_PHY_ANALOG); 290290910Sadrian DELAY(1000); 291290910Sadrian 292290910Sadrian ar71xx_device_start(QCA953X_RESET_USB_HOST); 293290910Sadrian DELAY(1000); 294290910Sadrian} 295290910Sadrian 296290910Sadrianstatic void 297290910Sadrianqca953x_chip_set_mii_if(uint32_t unit, uint32_t mii_mode) 298290910Sadrian{ 299290910Sadrian 300290910Sadrian /* 301290910Sadrian * XXX ! 302290910Sadrian * 303290910Sadrian * Nothing to see here; although gmac0 can have its 304290910Sadrian * MII configuration changed, the register values 305290910Sadrian * are slightly different. 306290910Sadrian */ 307290910Sadrian} 308290910Sadrian 309290910Sadrian/* 310290910Sadrian * XXX TODO: fetch default MII divider configuration 311290910Sadrian */ 312290910Sadrian 313290910Sadrianstatic void 314290910Sadrianqca953x_chip_reset_wmac(void) 315290910Sadrian{ 316290910Sadrian 317290910Sadrian /* XXX TODO */ 318290910Sadrian} 319290910Sadrian 320290910Sadrianstatic void 321290910Sadrianqca953x_chip_init_gmac(void) 322290910Sadrian{ 323290910Sadrian long gmac_cfg; 324290910Sadrian 325290910Sadrian if (resource_long_value("qca953x_gmac", 0, "gmac_cfg", 326290910Sadrian &gmac_cfg) == 0) { 327290910Sadrian printf("%s: gmac_cfg=0x%08lx\n", 328290910Sadrian __func__, 329290910Sadrian (long) gmac_cfg); 330290910Sadrian qca953x_configure_gmac((uint32_t) gmac_cfg); 331290910Sadrian } 332290910Sadrian} 333290910Sadrian 334290910Sadrian/* 335290910Sadrian * Reset the NAND Flash Controller. 336290910Sadrian * 337290910Sadrian * + active=1 means "make it active". 338290910Sadrian * + active=0 means "make it inactive". 339290910Sadrian */ 340290910Sadrianstatic void 341290910Sadrianqca953x_chip_reset_nfc(int active) 342290910Sadrian{ 343290910Sadrian} 344290910Sadrian 345290910Sadrian/* 346290910Sadrian * Configure the GPIO output mux setup. 347290910Sadrian * 348290910Sadrian * The QCA953x has an output mux which allowed 349290910Sadrian * certain functions to be configured on any pin. 350290910Sadrian * Specifically, the switch PHY link LEDs and 351290910Sadrian * WMAC external RX LNA switches are not limited to 352290910Sadrian * a specific GPIO pin. 353290910Sadrian */ 354290910Sadrianstatic void 355290910Sadrianqca953x_chip_gpio_output_configure(int gpio, uint8_t func) 356290910Sadrian{ 357290910Sadrian uint32_t reg, s; 358290910Sadrian uint32_t t; 359290910Sadrian 360290910Sadrian if (gpio > QCA953X_GPIO_COUNT) 361290910Sadrian return; 362290910Sadrian 363298848Spfg reg = QCA953X_GPIO_REG_OUT_FUNC0 + rounddown(gpio, 4); 364290910Sadrian s = 8 * (gpio % 4); 365290910Sadrian 366290910Sadrian /* read-modify-write */ 367290910Sadrian t = ATH_READ_REG(AR71XX_GPIO_BASE + reg); 368290910Sadrian t &= ~(0xff << s); 369290910Sadrian t |= func << s; 370290910Sadrian ATH_WRITE_REG(AR71XX_GPIO_BASE + reg, t); 371290910Sadrian 372290910Sadrian /* flush write */ 373290910Sadrian ATH_READ_REG(AR71XX_GPIO_BASE + reg); 374290910Sadrian} 375290910Sadrian 376290910Sadrianstruct ar71xx_cpu_def qca953x_chip_def = { 377290910Sadrian &qca953x_chip_detect_mem_size, 378290910Sadrian &qca953x_chip_detect_sys_frequency, 379290910Sadrian &qca953x_chip_device_stop, 380290910Sadrian &qca953x_chip_device_start, 381290910Sadrian &qca953x_chip_device_stopped, 382290910Sadrian &qca953x_chip_set_pll_ge, 383290910Sadrian &qca953x_chip_set_mii_speed, 384290910Sadrian &qca953x_chip_set_mii_if, 385290910Sadrian &qca953x_chip_get_eth_pll, 386290910Sadrian &qca953x_chip_ddr_flush, 387290910Sadrian &qca953x_chip_init_usb_peripheral, 388290910Sadrian &qca953x_chip_reset_ethernet_switch, 389290910Sadrian &qca953x_chip_reset_wmac, 390290910Sadrian &qca953x_chip_init_gmac, 391290910Sadrian &qca953x_chip_reset_nfc, 392290910Sadrian &qca953x_chip_gpio_output_configure, 393290910Sadrian}; 394