The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mips/atheros/ar934x_chip.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: releng/11.0/sys/mips/atheros/ar934x_chip.c 298848 2016-04-30 14:41:18Z pfg $");
   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 
   63 static void
   64 ar934x_chip_detect_mem_size(void)
   65 {
   66 }
   67 
   68 static uint32_t
   69 ar934x_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 
   89 static void
   90 ar934x_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         uint32_t reg;
   96 
   97         bootstrap = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP);
   98         if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40)
   99                 u_ar71xx_refclk = 40 * 1000 * 1000;
  100         else
  101                 u_ar71xx_refclk = 25 * 1000 * 1000;
  102 
  103         pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL2_REG);
  104         if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
  105                 out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
  106                     AR934X_SRIF_DPLL2_OUTDIV_MASK;
  107                 pll = ATH_READ_REG(AR934X_SRIF_CPU_DPLL1_REG);
  108                 nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
  109                     AR934X_SRIF_DPLL1_NINT_MASK;
  110                 nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
  111                 ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
  112                     AR934X_SRIF_DPLL1_REFDIV_MASK;
  113                 frac = 1 << 18;
  114         } else {
  115                 pll = ATH_READ_REG(AR934X_PLL_CPU_CONFIG_REG);
  116                 out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
  117                         AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
  118                 ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
  119                           AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
  120                 nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
  121                        AR934X_PLL_CPU_CONFIG_NINT_MASK;
  122                 nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
  123                         AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
  124                 frac = 1 << 6;
  125         }
  126 
  127         cpu_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint,
  128             nfrac, frac, out_div);
  129 
  130         pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL2_REG);
  131         if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
  132                 out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
  133                     AR934X_SRIF_DPLL2_OUTDIV_MASK;
  134                 pll = ATH_READ_REG(AR934X_SRIF_DDR_DPLL1_REG);
  135                 nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
  136                     AR934X_SRIF_DPLL1_NINT_MASK;
  137                 nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
  138                 ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
  139                     AR934X_SRIF_DPLL1_REFDIV_MASK;
  140                 frac = 1 << 18;
  141         } else {
  142                 pll = ATH_READ_REG(AR934X_PLL_DDR_CONFIG_REG);
  143                 out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
  144                     AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
  145                 ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
  146                     AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
  147                 nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
  148                     AR934X_PLL_DDR_CONFIG_NINT_MASK;
  149                 nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
  150                     AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
  151                 frac = 1 << 10;
  152         }
  153 
  154         ddr_pll = ar934x_get_pll_freq(u_ar71xx_refclk, ref_div, nint,
  155             nfrac, frac, out_div);
  156 
  157         clk_ctrl = ATH_READ_REG(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
  158 
  159         postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) &
  160             AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK;
  161 
  162         if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS)
  163             u_ar71xx_cpu_freq = u_ar71xx_refclk;
  164         else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL)
  165                 u_ar71xx_cpu_freq = cpu_pll / (postdiv + 1);
  166         else
  167                 u_ar71xx_cpu_freq = ddr_pll / (postdiv + 1);
  168 
  169         postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) &
  170             AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK;
  171 
  172         if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS)
  173                 u_ar71xx_ddr_freq = u_ar71xx_refclk;
  174         else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL)
  175                 u_ar71xx_ddr_freq = ddr_pll / (postdiv + 1);
  176         else
  177                 u_ar71xx_ddr_freq = cpu_pll / (postdiv + 1);
  178 
  179         postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) &
  180                   AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK;
  181 
  182         if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS)
  183                 u_ar71xx_ahb_freq = u_ar71xx_refclk;
  184         else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL)
  185                 u_ar71xx_ahb_freq = ddr_pll / (postdiv + 1);
  186         else
  187                 u_ar71xx_ahb_freq = cpu_pll / (postdiv + 1);
  188 
  189         u_ar71xx_wdt_freq = u_ar71xx_refclk;
  190         u_ar71xx_uart_freq = u_ar71xx_refclk;
  191 
  192         /*
  193          * Next, fetch reference clock speed for MDIO bus.
  194          */
  195         reg = ATH_READ_REG(AR934X_PLL_SWITCH_CLOCK_CONTROL_REG);
  196         if (reg & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL) {
  197                 printf("%s: mdio=100MHz\n", __func__);
  198                 u_ar71xx_mdio_freq = (100 * 1000 * 1000);
  199         } else {
  200                 printf("%s: mdio=%d Hz\n", __func__, u_ar71xx_refclk);
  201                 u_ar71xx_mdio_freq = u_ar71xx_refclk;
  202         }
  203 }
  204 
  205 static void
  206 ar934x_chip_device_stop(uint32_t mask)
  207 {
  208         uint32_t reg;
  209 
  210         reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
  211         ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg | mask);
  212 }
  213 
  214 static void
  215 ar934x_chip_device_start(uint32_t mask)
  216 {
  217         uint32_t reg;
  218 
  219         reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
  220         ATH_WRITE_REG(AR934X_RESET_REG_RESET_MODULE, reg & ~mask);
  221 }
  222 
  223 static int
  224 ar934x_chip_device_stopped(uint32_t mask)
  225 {
  226         uint32_t reg;
  227 
  228         reg = ATH_READ_REG(AR934X_RESET_REG_RESET_MODULE);
  229         return ((reg & mask) == mask);
  230 }
  231 
  232 static void
  233 ar934x_chip_set_mii_speed(uint32_t unit, uint32_t speed)
  234 {
  235 
  236         /* XXX TODO */
  237         return;
  238 }
  239 
  240 /*
  241  * XXX TODO !!
  242  */
  243 static void
  244 ar934x_chip_set_pll_ge(int unit, int speed, uint32_t pll)
  245 {
  246 
  247         switch (unit) {
  248         case 0:
  249                 ATH_WRITE_REG(AR934X_PLL_ETH_XMII_CONTROL_REG, pll);
  250                 break;
  251         case 1:
  252                 /* XXX nothing */
  253                 break;
  254         default:
  255                 printf("%s: invalid PLL set for arge unit: %d\n",
  256                     __func__, unit);
  257                 return;
  258         }
  259 }
  260 
  261 static void
  262 ar934x_chip_ddr_flush(ar71xx_flush_ddr_id_t id)
  263 {
  264 
  265         switch (id) {
  266         case AR71XX_CPU_DDR_FLUSH_GE0:
  267                 ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE0);
  268                 break;
  269         case AR71XX_CPU_DDR_FLUSH_GE1:
  270                 ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_GE1);
  271                 break;
  272         case AR71XX_CPU_DDR_FLUSH_USB:
  273                 ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_USB);
  274                 break;
  275         case AR71XX_CPU_DDR_FLUSH_PCIE:
  276                 ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_PCIE);
  277                 break;
  278         case AR71XX_CPU_DDR_FLUSH_WMAC:
  279                 ar71xx_ddr_flush(AR934X_DDR_REG_FLUSH_WMAC);
  280                 break;
  281         default:
  282                 printf("%s: invalid DDR flush id (%d)\n", __func__, id);
  283                 break;
  284         }
  285 }
  286 
  287 
  288 static uint32_t
  289 ar934x_chip_get_eth_pll(unsigned int mac, int speed)
  290 {
  291         uint32_t pll;
  292 
  293         switch (speed) {
  294         case 10:
  295                 pll = AR934X_PLL_VAL_10;
  296                 break;
  297         case 100:
  298                 pll = AR934X_PLL_VAL_100;
  299                 break;
  300         case 1000:
  301                 pll = AR934X_PLL_VAL_1000;
  302                 break;
  303         default:
  304                 printf("%s%d: invalid speed %d\n", __func__, mac, speed);
  305                 pll = 0;
  306         }
  307         return (pll);
  308 }
  309 
  310 static void
  311 ar934x_chip_reset_ethernet_switch(void)
  312 {
  313 
  314         ar71xx_device_stop(AR934X_RESET_ETH_SWITCH);
  315         DELAY(100);
  316         ar71xx_device_start(AR934X_RESET_ETH_SWITCH);
  317         DELAY(100);
  318 }
  319 
  320 static void
  321 ar934x_configure_gmac(uint32_t gmac_cfg)
  322 {
  323         uint32_t reg;
  324 
  325         reg = ATH_READ_REG(AR934X_GMAC_REG_ETH_CFG);
  326         printf("%s: ETH_CFG=0x%08x\n", __func__, reg);
  327 
  328         reg &= ~(AR934X_ETH_CFG_RGMII_GMAC0 | AR934X_ETH_CFG_MII_GMAC0 |
  329             AR934X_ETH_CFG_MII_GMAC0 | AR934X_ETH_CFG_SW_ONLY_MODE |
  330             AR934X_ETH_CFG_SW_PHY_SWAP);
  331 
  332         reg |= gmac_cfg;
  333 
  334         ATH_WRITE_REG(AR934X_GMAC_REG_ETH_CFG, reg);
  335 }
  336 
  337 static void
  338 ar934x_chip_init_usb_peripheral(void)
  339 {
  340         uint32_t reg;
  341 
  342         reg = ATH_READ_REG(AR934X_RESET_REG_BOOTSTRAP);
  343         if (reg & AR934X_BOOTSTRAP_USB_MODE_DEVICE)
  344                 return;
  345 
  346         ar71xx_device_stop(AR934X_RESET_USBSUS_OVERRIDE);
  347         DELAY(100);
  348 
  349         ar71xx_device_start(AR934X_RESET_USB_PHY);
  350         DELAY(100);
  351 
  352         ar71xx_device_start(AR934X_RESET_USB_PHY_ANALOG);
  353         DELAY(100);
  354 
  355         ar71xx_device_start(AR934X_RESET_USB_HOST);
  356         DELAY(100);
  357 }
  358 
  359 static void
  360 ar934x_chip_set_mii_if(uint32_t unit, uint32_t mii_mode)
  361 {
  362 
  363         /*
  364          * XXX !
  365          *
  366          * Nothing to see here; although gmac0 can have its
  367          * MII configuration changed, the register values
  368          * are slightly different.
  369          */
  370 }
  371 
  372 /*
  373  * XXX TODO: fetch default MII divider configuration
  374  */
  375 
  376 static void
  377 ar934x_chip_reset_wmac(void)
  378 {
  379 
  380         /* XXX TODO */
  381 }
  382 
  383 static void
  384 ar934x_chip_init_gmac(void)
  385 {
  386         long gmac_cfg;
  387 
  388         if (resource_long_value("ar934x_gmac", 0, "gmac_cfg",
  389             &gmac_cfg) == 0) {
  390                 printf("%s: gmac_cfg=0x%08lx\n",
  391                     __func__,
  392                     (long) gmac_cfg);
  393                 ar934x_configure_gmac((uint32_t) gmac_cfg);
  394         }
  395 }
  396 
  397 /*
  398  * Reset the NAND Flash Controller.
  399  *
  400  * + active=1 means "make it active".
  401  * + active=0 means "make it inactive".
  402  */
  403 static void
  404 ar934x_chip_reset_nfc(int active)
  405 {
  406 
  407         if (active) {
  408                 ar71xx_device_start(AR934X_RESET_NANDF);
  409                 DELAY(100);
  410 
  411                 ar71xx_device_start(AR934X_RESET_ETH_SWITCH_ANALOG);
  412                 DELAY(250);
  413         } else {
  414                 ar71xx_device_stop(AR934X_RESET_ETH_SWITCH_ANALOG);
  415                 DELAY(250);
  416 
  417                 ar71xx_device_stop(AR934X_RESET_NANDF);
  418                 DELAY(100);
  419         }
  420 }
  421 
  422 /*
  423  * Configure the GPIO output mux setup.
  424  *
  425  * The AR934x introduced an output mux which allowed
  426  * certain functions to be configured on any pin.
  427  * Specifically, the switch PHY link LEDs and
  428  * WMAC external RX LNA switches are not limited to
  429  * a specific GPIO pin.
  430  */
  431 static void
  432 ar934x_chip_gpio_output_configure(int gpio, uint8_t func)
  433 {
  434         uint32_t reg, s;
  435         uint32_t t;
  436 
  437         if (gpio > AR934X_GPIO_COUNT)
  438                 return;
  439 
  440         reg = AR934X_GPIO_REG_OUT_FUNC0 + rounddown(gpio, 4);
  441         s = 8 * (gpio % 4);
  442 
  443         /* read-modify-write */
  444         t = ATH_READ_REG(AR71XX_GPIO_BASE + reg);
  445         t &= ~(0xff << s);
  446         t |= func << s;
  447         ATH_WRITE_REG(AR71XX_GPIO_BASE + reg, t);
  448 
  449         /* flush write */
  450         ATH_READ_REG(AR71XX_GPIO_BASE + reg);
  451 }
  452 
  453 struct ar71xx_cpu_def ar934x_chip_def = {
  454         &ar934x_chip_detect_mem_size,
  455         &ar934x_chip_detect_sys_frequency,
  456         &ar934x_chip_device_stop,
  457         &ar934x_chip_device_start,
  458         &ar934x_chip_device_stopped,
  459         &ar934x_chip_set_pll_ge,
  460         &ar934x_chip_set_mii_speed,
  461         &ar934x_chip_set_mii_if,
  462         &ar934x_chip_get_eth_pll,
  463         &ar934x_chip_ddr_flush,
  464         &ar934x_chip_init_usb_peripheral,
  465         &ar934x_chip_reset_ethernet_switch,
  466         &ar934x_chip_reset_wmac,
  467         &ar934x_chip_init_gmac,
  468         &ar934x_chip_reset_nfc,
  469         &ar934x_chip_gpio_output_configure,
  470 };

Cache object: ed6919a49f18e96073a588c9ddb08647


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.