1253511Sadrian/*- 2253511Sadrian * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 3253511Sadrian * All rights reserved. 4253511Sadrian * 5253511Sadrian * Redistribution and use in source and binary forms, with or without 6253511Sadrian * modification, are permitted provided that the following conditions 7253511Sadrian * are met: 8253511Sadrian * 1. Redistributions of source code must retain the above copyright 9253511Sadrian * notice, this list of conditions and the following disclaimer. 10253511Sadrian * 2. Redistributions in binary form must reproduce the above copyright 11253511Sadrian * notice, this list of conditions and the following disclaimer in the 12253511Sadrian * documentation and/or other materials provided with the distribution. 13253511Sadrian * 14253511Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15253511Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16253511Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17253511Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18253511Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19253511Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20253511Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21253511Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22253511Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23253511Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24253511Sadrian * SUCH DAMAGE. 25253511Sadrian */ 26253511Sadrian 27253511Sadrian#include <sys/cdefs.h> 28253511Sadrian__FBSDID("$FreeBSD$"); 29253511Sadrian 30253511Sadrian#include "opt_ddb.h" 31253511Sadrian 32253511Sadrian#include <sys/param.h> 33253511Sadrian#include <sys/conf.h> 34253511Sadrian#include <sys/kernel.h> 35253511Sadrian#include <sys/systm.h> 36253511Sadrian#include <sys/bus.h> 37253511Sadrian#include <sys/cons.h> 38253511Sadrian#include <sys/kdb.h> 39253511Sadrian#include <sys/reboot.h> 40253511Sadrian 41253511Sadrian#include <vm/vm.h> 42253511Sadrian#include <vm/vm_page.h> 43253511Sadrian 44253511Sadrian#include <net/ethernet.h> 45253511Sadrian 46253511Sadrian#include <machine/clock.h> 47253511Sadrian#include <machine/cpu.h> 48253511Sadrian#include <machine/cpuregs.h> 49253511Sadrian#include <machine/hwfunc.h> 50253511Sadrian#include <machine/md_var.h> 51253511Sadrian#include <machine/trap.h> 52253511Sadrian#include <machine/vmparam.h> 53253511Sadrian 54253511Sadrian#include <mips/atheros/ar71xxreg.h> 55253511Sadrian#include <mips/atheros/ar934xreg.h> 56253511Sadrian 57253511Sadrian#include <mips/atheros/ar71xx_cpudef.h> 58253511Sadrian#include <mips/atheros/ar71xx_setup.h> 59253511Sadrian 60253511Sadrian#include <mips/atheros/ar71xx_chip.h> 61253511Sadrian#include <mips/atheros/ar934x_chip.h> 62253511Sadrian 63253511Sadrianstatic void 64253511Sadrianar934x_chip_detect_mem_size(void) 65253511Sadrian{ 66253511Sadrian} 67253511Sadrian 68253511Sadrianstatic uint32_t 69253511Sadrianar934x_get_pll_freq(uint32_t ref, uint32_t ref_div, uint32_t nint, 70253511Sadrian uint32_t nfrac, uint32_t frac, uint32_t out_div) 71253511Sadrian{ 72253511Sadrian uint64_t t; 73253511Sadrian uint32_t ret; 74253511Sadrian 75253511Sadrian t = u_ar71xx_refclk; 76253511Sadrian t *= nint; 77253511Sadrian t = t / ref_div; 78253511Sadrian ret = t; 79253511Sadrian 80253511Sadrian t = u_ar71xx_refclk; 81253511Sadrian t *= nfrac; 82253511Sadrian t = t / (ref_div * frac); 83253511Sadrian ret += t; 84253511Sadrian 85253511Sadrian ret /= (1 << out_div); 86253511Sadrian return (ret); 87253511Sadrian} 88253511Sadrian 89253511Sadrianstatic void 90253511Sadrianar934x_chip_detect_sys_frequency(void) 91253511Sadrian{ 92253511Sadrian uint32_t pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; 93253511Sadrian uint32_t cpu_pll, ddr_pll; 94253511Sadrian uint32_t bootstrap; 95256491Sadrian uint32_t reg; 96253511Sadrian 97253511Sadrian bootstrap = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP); 98253511Sadrian if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) 99253511Sadrian u_ar71xx_refclk = 40 * 1000 * 1000; 100253511Sadrian else 101253511Sadrian u_ar71xx_refclk = 25 * 1000 * 1000; 102253511Sadrian 103253511Sadrian pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL2_REG); 104253511Sadrian if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 105253511Sadrian out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 106253511Sadrian AR934X_SRIF_DPLL2_OUTDIV_MASK; 107253511Sadrian pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL1_REG); 108253511Sadrian nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 109253511Sadrian AR934X_SRIF_DPLL1_NINT_MASK; 110253511Sadrian nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 111253511Sadrian ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 112253511Sadrian AR934X_SRIF_DPLL1_REFDIV_MASK; 113253511Sadrian frac = 1 << 18; 114253511Sadrian } else { 115253511Sadrian pll = ATH_READ_REG(AR934X_PLL_CPU_CONFIG_REG); 116253511Sadrian out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 117253511Sadrian AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; 118253511Sadrian ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 119253511Sadrian AR934X_PLL_CPU_CONFIG_REFDIV_MASK; 120253511Sadrian nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & 121253511Sadrian AR934X_PLL_CPU_CONFIG_NINT_MASK; 122253511Sadrian nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 123253511Sadrian AR934X_PLL_CPU_CONFIG_NFRAC_MASK; 124253511Sadrian frac = 1 << 6; 125253511Sadrian } 126253511Sadrian 127253511Sadrian cpu_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint, 128253511Sadrian nfrac, frac, out_div); 129253511Sadrian 130253511Sadrian pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL2_REG); 131253511Sadrian if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 132253511Sadrian out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 133253511Sadrian AR934X_SRIF_DPLL2_OUTDIV_MASK; 134253511Sadrian pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL1_REG); 135253511Sadrian nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 136253511Sadrian AR934X_SRIF_DPLL1_NINT_MASK; 137253511Sadrian nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 138253511Sadrian ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 139253511Sadrian AR934X_SRIF_DPLL1_REFDIV_MASK; 140253511Sadrian frac = 1 << 18; 141253511Sadrian } else { 142253511Sadrian pll = ATH_READ_REG(AR934X_PLL_DDR_CONFIG_REG); 143253511Sadrian out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 144253511Sadrian AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; 145253511Sadrian ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 146253511Sadrian AR934X_PLL_DDR_CONFIG_REFDIV_MASK; 147253511Sadrian nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & 148253511Sadrian AR934X_PLL_DDR_CONFIG_NINT_MASK; 149253511Sadrian nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 150253511Sadrian AR934X_PLL_DDR_CONFIG_NFRAC_MASK; 151253511Sadrian frac = 1 << 10; 152253511Sadrian } 153253511Sadrian 154253511Sadrian ddr_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint, 155253511Sadrian nfrac, frac, out_div); 156253511Sadrian 157253511Sadrian clk_ctrl = ATH_READ_REG(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 158253511Sadrian 159253511Sadrian postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) & 160253511Sadrian AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK; 161253511Sadrian 162253511Sadrian if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS) 163253511Sadrian u_ar71xx_cpu_freq = u_ar71xx_refclk; 164253511Sadrian else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL) 165253511Sadrian u_ar71xx_cpu_freq = cpu_pll / (postdiv + 1); 166253511Sadrian else 167253511Sadrian u_ar71xx_cpu_freq = ddr_pll / (postdiv + 1); 168253511Sadrian 169253511Sadrian postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) & 170253511Sadrian AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK; 171253511Sadrian 172253511Sadrian if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS) 173253511Sadrian u_ar71xx_ddr_freq = u_ar71xx_refclk; 174253511Sadrian else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL) 175253511Sadrian u_ar71xx_ddr_freq = ddr_pll / (postdiv + 1); 176253511Sadrian else 177253511Sadrian u_ar71xx_ddr_freq = cpu_pll / (postdiv + 1); 178253511Sadrian 179253511Sadrian postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) & 180253511Sadrian AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK; 181253511Sadrian 182253511Sadrian if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS) 183253511Sadrian u_ar71xx_ahb_freq = u_ar71xx_refclk; 184253511Sadrian else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL) 185253511Sadrian u_ar71xx_ahb_freq = ddr_pll / (postdiv + 1); 186253511Sadrian else 187253511Sadrian u_ar71xx_ahb_freq = cpu_pll / (postdiv + 1); 188253511Sadrian 189253511Sadrian u_ar71xx_wdt_freq = u_ar71xx_refclk; 190253511Sadrian u_ar71xx_uart_freq = u_ar71xx_refclk; 191256491Sadrian 192256491Sadrian /* 193256491Sadrian * Next, fetch reference clock speed for MDIO bus. 194256491Sadrian */ 195256491Sadrian reg = ATH_READ_REG(AR934X_PLL_SWITCH_CLOCK_CONTROL_REG); 196256491Sadrian if (reg & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL) { 197256491Sadrian printf("%s: mdio=100MHz\n", __func__); 198256491Sadrian u_ar71xx_mdio_freq = (100 * 1000 * 1000); 199256491Sadrian } else { 200256491Sadrian printf("%s: mdio=%d Hz\n", __func__, u_ar71xx_refclk); 201256491Sadrian u_ar71xx_mdio_freq = u_ar71xx_refclk; 202256491Sadrian } 203253511Sadrian} 204253511Sadrian 205253511Sadrianstatic void 206253511Sadrianar934x_chip_device_stop(uint32_t mask) 207253511Sadrian{ 208253511Sadrian uint32_t reg; 209253511Sadrian 210253511Sadrian reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE); 211253511Sadrian ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg | mask); 212253511Sadrian} 213253511Sadrian 214253511Sadrianstatic void 215253511Sadrianar934x_chip_device_start(uint32_t mask) 216253511Sadrian{ 217253511Sadrian uint32_t reg; 218253511Sadrian 219253511Sadrian reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE); 220253511Sadrian ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg & ~mask); 221253511Sadrian} 222253511Sadrian 223253511Sadrianstatic int 224253511Sadrianar934x_chip_device_stopped(uint32_t mask) 225253511Sadrian{ 226253511Sadrian uint32_t reg; 227253511Sadrian 228253511Sadrian reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE); 229253511Sadrian return ((reg & mask) == mask); 230253511Sadrian} 231253511Sadrian 232253511Sadrianstatic void 233253511Sadrianar934x_chip_set_mii_speed(uint32_t unit, uint32_t speed) 234253511Sadrian{ 235253511Sadrian 236253511Sadrian /* XXX TODO */ 237253511Sadrian return; 238253511Sadrian} 239253511Sadrian 240253511Sadrian/* 241253511Sadrian * XXX TODO !! 242253511Sadrian */ 243253511Sadrianstatic void 244253511Sadrianar934x_chip_set_pll_ge(int unit, int speed, uint32_t pll) 245253511Sadrian{ 246253511Sadrian 247253511Sadrian switch (unit) { 248253511Sadrian case 0: 249256491Sadrian ATH_WRITE_REG(AR934X_PLL_ETH_XMII_CONTROL_REG, pll); 250253511Sadrian break; 251253511Sadrian case 1: 252256491Sadrian /* XXX nothing */ 253253511Sadrian break; 254253511Sadrian default: 255253511Sadrian printf("%s: invalid PLL set for arge unit: %d\n", 256253511Sadrian __func__, unit); 257253511Sadrian return; 258253511Sadrian } 259253511Sadrian} 260253511Sadrian 261253511Sadrianstatic void 262285121Sadrianar934x_chip_ddr_flush(ar71xx_flush_ddr_id_t id) 263253511Sadrian{ 264253511Sadrian 265285121Sadrian switch (id) { 266285121Sadrian case AR71XX_CPU_DDR_FLUSH_GE0: 267253511Sadrian ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE0); 268253511Sadrian break; 269285121Sadrian case AR71XX_CPU_DDR_FLUSH_GE1: 270253511Sadrian ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE1); 271253511Sadrian break; 272285121Sadrian case AR71XX_CPU_DDR_FLUSH_USB: 273285121Sadrian ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_USB); 274285121Sadrian break; 275285121Sadrian case AR71XX_CPU_DDR_FLUSH_PCIE: 276285121Sadrian ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_PCIE); 277285121Sadrian break; 278285121Sadrian case AR71XX_CPU_DDR_FLUSH_WMAC: 279285121Sadrian ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_WMAC); 280285121Sadrian break; 281253511Sadrian default: 282285121Sadrian printf("%s: invalid DDR flush id (%d)\n", __func__, id); 283285121Sadrian break; 284253511Sadrian } 285253511Sadrian} 286253511Sadrian 287253511Sadrian 288253511Sadrianstatic uint32_t 289253511Sadrianar934x_chip_get_eth_pll(unsigned int mac, int speed) 290253511Sadrian{ 291253511Sadrian uint32_t pll; 292253511Sadrian 293253511Sadrian switch (speed) { 294253511Sadrian case 10: 295256491Sadrian pll = AR934X_PLL_VAL_10; 296253511Sadrian break; 297253511Sadrian case 100: 298256491Sadrian pll = AR934X_PLL_VAL_100; 299253511Sadrian break; 300253511Sadrian case 1000: 301256491Sadrian pll = AR934X_PLL_VAL_1000; 302253511Sadrian break; 303253511Sadrian default: 304253511Sadrian printf("%s%d: invalid speed %d\n", __func__, mac, speed); 305253511Sadrian pll = 0; 306253511Sadrian } 307253511Sadrian return (pll); 308253511Sadrian} 309253511Sadrian 310253511Sadrianstatic void 311256491Sadrianar934x_chip_reset_ethernet_switch(void) 312256491Sadrian{ 313256491Sadrian 314256491Sadrian ar71xx_device_stop(AR934X_RESET_ETH_SWITCH); 315256491Sadrian DELAY(100); 316256491Sadrian ar71xx_device_start(AR934X_RESET_ETH_SWITCH); 317256491Sadrian DELAY(100); 318256491Sadrian} 319256491Sadrian 320256491Sadrianstatic void 321256491Sadrianar934x_configure_gmac(uint32_t gmac_cfg) 322256491Sadrian{ 323256491Sadrian uint32_t reg; 324256491Sadrian 325256491Sadrian reg = ATH_READ_REG(AR934X_GMAC_REG_ETH_CFG); 326256491Sadrian printf("%s: ETH_CFG=0x%08x\n", __func__, reg); 327256491Sadrian 328256491Sadrian reg &= ~(AR934X_ETH_CFG_RGMII_GMAC0 | AR934X_ETH_CFG_MII_GMAC0 | 329256491Sadrian AR934X_ETH_CFG_MII_GMAC0 | AR934X_ETH_CFG_SW_ONLY_MODE | 330256491Sadrian AR934X_ETH_CFG_SW_PHY_SWAP); 331256491Sadrian 332256491Sadrian reg |= gmac_cfg; 333256491Sadrian 334256491Sadrian ATH_WRITE_REG(AR934X_GMAC_REG_ETH_CFG, reg); 335256491Sadrian} 336256491Sadrian 337256491Sadrianstatic void 338253511Sadrianar934x_chip_init_usb_peripheral(void) 339253511Sadrian{ 340253511Sadrian uint32_t reg; 341253511Sadrian 342253511Sadrian reg = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP); 343253511Sadrian if (reg & AR934X_BOOTSTRAP_USB_MODE_DEVICE) 344253511Sadrian return; 345253511Sadrian 346253511Sadrian ar71xx_device_stop(AR934X_RESET_USBSUS_OVERRIDE); 347253511Sadrian DELAY(100); 348253511Sadrian 349253511Sadrian ar71xx_device_start(AR934X_RESET_USB_PHY); 350253511Sadrian DELAY(100); 351253511Sadrian 352253511Sadrian ar71xx_device_start(AR934X_RESET_USB_PHY_ANALOG); 353253511Sadrian DELAY(100); 354253511Sadrian 355253511Sadrian ar71xx_device_start(AR934X_RESET_USB_HOST); 356253511Sadrian DELAY(100); 357253511Sadrian} 358253511Sadrian 359256491Sadrianstatic void 360256491Sadrianar934x_chip_set_mii_if(uint32_t unit, uint32_t mii_mode) 361256491Sadrian{ 362256491Sadrian 363256491Sadrian /* 364256491Sadrian * XXX ! 365256491Sadrian * 366256491Sadrian * Nothing to see here; although gmac0 can have its 367256491Sadrian * MII configuration changed, the register values 368256491Sadrian * are slightly different. 369256491Sadrian */ 370256491Sadrian} 371256491Sadrian 372256491Sadrian/* 373256491Sadrian * XXX TODO: fetch default MII divider configuration 374256491Sadrian */ 375256491Sadrian 376256491Sadrianstatic void 377256491Sadrianar934x_chip_reset_wmac(void) 378256491Sadrian{ 379256491Sadrian 380263296Sadrian /* XXX TODO */ 381256491Sadrian} 382256491Sadrian 383256491Sadrianstatic void 384256491Sadrianar934x_chip_init_gmac(void) 385256491Sadrian{ 386256491Sadrian long gmac_cfg; 387256491Sadrian 388256491Sadrian if (resource_long_value("ar934x_gmac", 0, "gmac_cfg", 389256491Sadrian &gmac_cfg) == 0) { 390256491Sadrian printf("%s: gmac_cfg=0x%08lx\n", 391256491Sadrian __func__, 392256491Sadrian (long) gmac_cfg); 393256491Sadrian ar934x_configure_gmac((uint32_t) gmac_cfg); 394256491Sadrian } 395256491Sadrian} 396256491Sadrian 397263296Sadrian/* 398263296Sadrian * Reset the NAND Flash Controller. 399263296Sadrian * 400263296Sadrian * + active=1 means "make it active". 401263296Sadrian * + active=0 means "make it inactive". 402263296Sadrian */ 403263296Sadrianstatic void 404263296Sadrianar934x_chip_reset_nfc(int active) 405263296Sadrian{ 406263296Sadrian 407263296Sadrian if (active) { 408263296Sadrian ar71xx_device_start(AR934X_RESET_NANDF); 409263296Sadrian DELAY(100); 410263296Sadrian 411263296Sadrian ar71xx_device_start(AR934X_RESET_ETH_SWITCH_ANALOG); 412263296Sadrian DELAY(250); 413263296Sadrian } else { 414263296Sadrian ar71xx_device_stop(AR934X_RESET_ETH_SWITCH_ANALOG); 415263296Sadrian DELAY(250); 416263296Sadrian 417263296Sadrian ar71xx_device_stop(AR934X_RESET_NANDF); 418263296Sadrian DELAY(100); 419263296Sadrian } 420263296Sadrian} 421263296Sadrian 422276610Sadrian/* 423276610Sadrian * Configure the GPIO output mux setup. 424276610Sadrian * 425276610Sadrian * The AR934x introduced an output mux which allowed 426276610Sadrian * certain functions to be configured on any pin. 427276610Sadrian * Specifically, the switch PHY link LEDs and 428276610Sadrian * WMAC external RX LNA switches are not limited to 429276610Sadrian * a specific GPIO pin. 430276610Sadrian */ 431276610Sadrianstatic void 432276610Sadrianar934x_chip_gpio_output_configure(int gpio, uint8_t func) 433276610Sadrian{ 434276610Sadrian uint32_t reg, s; 435276610Sadrian uint32_t t; 436276610Sadrian 437276610Sadrian if (gpio > AR934X_GPIO_COUNT) 438276610Sadrian return; 439276610Sadrian 440298848Spfg reg = AR934X_GPIO_REG_OUT_FUNC0 + rounddown(gpio, 4); 441276610Sadrian s = 8 * (gpio % 4); 442276610Sadrian 443276610Sadrian /* read-modify-write */ 444276610Sadrian t = ATH_READ_REG(AR71XX_GPIO_BASE + reg); 445276610Sadrian t &= ~(0xff << s); 446276610Sadrian t |= func << s; 447276610Sadrian ATH_WRITE_REG(AR71XX_GPIO_BASE + reg, t); 448276610Sadrian 449276610Sadrian /* flush write */ 450276610Sadrian ATH_READ_REG(AR71XX_GPIO_BASE + reg); 451276610Sadrian} 452276610Sadrian 453253511Sadrianstruct ar71xx_cpu_def ar934x_chip_def = { 454253511Sadrian &ar934x_chip_detect_mem_size, 455253511Sadrian &ar934x_chip_detect_sys_frequency, 456253511Sadrian &ar934x_chip_device_stop, 457253511Sadrian &ar934x_chip_device_start, 458253511Sadrian &ar934x_chip_device_stopped, 459253511Sadrian &ar934x_chip_set_pll_ge, 460253511Sadrian &ar934x_chip_set_mii_speed, 461256491Sadrian &ar934x_chip_set_mii_if, 462253511Sadrian &ar934x_chip_get_eth_pll, 463285121Sadrian &ar934x_chip_ddr_flush, 464256491Sadrian &ar934x_chip_init_usb_peripheral, 465256491Sadrian &ar934x_chip_reset_ethernet_switch, 466256491Sadrian &ar934x_chip_reset_wmac, 467256491Sadrian &ar934x_chip_init_gmac, 468263296Sadrian &ar934x_chip_reset_nfc, 469276610Sadrian &ar934x_chip_gpio_output_configure, 470253511Sadrian}; 471