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/mediatek/mtk_soc.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) 2016 Stanislav Galabov.
    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 <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 #include <sys/kernel.h>
   34 #include <sys/module.h>
   35 #include <sys/rman.h>
   36 
   37 #include <machine/fdt.h>
   38 
   39 #include <dev/ofw/openfirm.h>
   40 #include <dev/ofw/ofw_bus.h>
   41 #include <dev/ofw/ofw_bus_subr.h>
   42 
   43 #include <dev/fdt/fdt_common.h>
   44 #include <dev/fdt/fdt_clock.h>
   45 
   46 #include <mips/mediatek/fdt_reset.h>
   47 #include <mips/mediatek/mtk_sysctl.h>
   48 #include <mips/mediatek/mtk_soc.h>
   49 
   50 static uint32_t mtk_soc_socid = MTK_SOC_UNKNOWN;
   51 static uint32_t mtk_soc_uartclk = 0;
   52 static uint32_t mtk_soc_cpuclk = MTK_CPU_CLK_880MHZ;
   53 static uint32_t mtk_soc_timerclk = MTK_CPU_CLK_880MHZ / 2;
   54 
   55 static uint32_t mtk_soc_chipid0_3 = MTK_UNKNOWN_CHIPID0_3;
   56 static uint32_t mtk_soc_chipid4_7 = MTK_UNKNOWN_CHIPID4_7;
   57 
   58 static const struct ofw_compat_data compat_data[] = {
   59         { "ralink,rt2880-soc",          MTK_SOC_RT2880 },
   60         { "ralink,rt3050-soc",          MTK_SOC_RT3050 },
   61         { "ralink,rt3052-soc",          MTK_SOC_RT3052 },
   62         { "ralink,rt3350-soc",          MTK_SOC_RT3350 },
   63         { "ralink,rt3352-soc",          MTK_SOC_RT3352 },
   64         { "ralink,rt3662-soc",          MTK_SOC_RT3662 },
   65         { "ralink,rt3883-soc",          MTK_SOC_RT3883 },
   66         { "ralink,rt5350-soc",          MTK_SOC_RT5350 },
   67         { "ralink,mtk7620a-soc",        MTK_SOC_MT7620A },
   68         { "ralink,mt7620a-soc",         MTK_SOC_MT7620A },
   69         { "ralink,mtk7620n-soc",        MTK_SOC_MT7620N },
   70         { "ralink,mt7620n-soc",         MTK_SOC_MT7620N },
   71         { "mediatek,mtk7621-soc",       MTK_SOC_MT7621 },
   72         { "mediatek,mt7621-soc",        MTK_SOC_MT7621 },
   73         { "ralink,mt7621-soc",          MTK_SOC_MT7621 },
   74         { "ralink,mtk7621-soc",         MTK_SOC_MT7621 },
   75         { "ralink,mtk7628an-soc",       MTK_SOC_MT7628 },
   76         { "mediatek,mt7628an-soc",      MTK_SOC_MT7628 },
   77         { "ralink,mtk7688-soc",         MTK_SOC_MT7688 },
   78 
   79         /* Sentinel */
   80         { NULL,                         MTK_SOC_UNKNOWN },
   81 };
   82 
   83 static uint32_t
   84 mtk_detect_cpuclk_rt2880(bus_space_tag_t bst, bus_space_handle_t bsh)
   85 {
   86         uint32_t val;
   87 
   88         val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
   89         val >>= RT2880_CPU_CLKSEL_OFF;
   90         val &= RT2880_CPU_CLKSEL_MSK;
   91 
   92         switch (val) {
   93         case 0:
   94                 return (MTK_CPU_CLK_250MHZ);
   95         case 1:
   96                 return (MTK_CPU_CLK_266MHZ);
   97         case 2:
   98                 return (MTK_CPU_CLK_280MHZ);
   99         case 3:
  100                 return (MTK_CPU_CLK_300MHZ);
  101         }
  102 
  103         /* Never reached */
  104         return (0);
  105 }
  106 
  107 static uint32_t
  108 mtk_detect_cpuclk_rt305x(bus_space_tag_t bst, bus_space_handle_t bsh)
  109 {
  110         uint32_t val;
  111 
  112         val = bus_space_read_4(bst, bsh, SYSCTL_CHIPID0_3);
  113         if (val == RT3350_CHIPID0_3)
  114                 return (MTK_CPU_CLK_320MHZ);
  115 
  116         val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
  117         val >>= RT305X_CPU_CLKSEL_OFF;
  118         val &= RT305X_CPU_CLKSEL_MSK;
  119 
  120         return ((val == 0) ? MTK_CPU_CLK_320MHZ : MTK_CPU_CLK_384MHZ);
  121 }
  122 
  123 static uint32_t
  124 mtk_detect_cpuclk_rt3352(bus_space_tag_t bst, bus_space_handle_t bsh)
  125 {
  126         uint32_t val;
  127 
  128         val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
  129         val >>= RT3352_CPU_CLKSEL_OFF;
  130         val &= RT3352_CPU_CLKSEL_MSK;
  131 
  132         if (val)
  133                 return (MTK_CPU_CLK_400MHZ);
  134 
  135         return (MTK_CPU_CLK_384MHZ);
  136 }
  137 
  138 static uint32_t
  139 mtk_detect_cpuclk_rt3883(bus_space_tag_t bst, bus_space_handle_t bsh)
  140 {
  141         uint32_t val;
  142 
  143         val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
  144         val >>= RT3883_CPU_CLKSEL_OFF;
  145         val &= RT3883_CPU_CLKSEL_MSK;
  146 
  147         switch (val) {
  148         case 0:
  149                 return (MTK_CPU_CLK_250MHZ);
  150         case 1:
  151                 return (MTK_CPU_CLK_384MHZ);
  152         case 2:
  153                 return (MTK_CPU_CLK_480MHZ);
  154         case 3:
  155                 return (MTK_CPU_CLK_500MHZ);
  156         }
  157 
  158         /* Never reached */
  159         return (0);
  160 }
  161 
  162 static uint32_t
  163 mtk_detect_cpuclk_rt5350(bus_space_tag_t bst, bus_space_handle_t bsh)
  164 {
  165         uint32_t val1, val2;
  166 
  167         val1 = val2 = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
  168 
  169         val1 >>= RT5350_CPU_CLKSEL_OFF1;
  170         val2 >>= RT5350_CPU_CLKSEL_OFF2;
  171         val1 &= RT5350_CPU_CLKSEL_MSK;
  172         val2 &= RT5350_CPU_CLKSEL_MSK;
  173         val1 |= (val2 << 1);
  174 
  175         switch (val1) {
  176         case 0:
  177                 return (MTK_CPU_CLK_360MHZ);
  178         case 1:
  179                 /* Reserved value, but we return UNKNOWN */
  180                 return (MTK_CPU_CLK_UNKNOWN);
  181         case 2:
  182                 return (MTK_CPU_CLK_320MHZ);
  183         case 3:
  184                 return (MTK_CPU_CLK_300MHZ);
  185         }
  186 
  187         /* Never reached */
  188         return (0);
  189 }
  190 
  191 static uint32_t
  192 mtk_detect_cpuclk_mt7620(bus_space_tag_t bst, bus_space_handle_t bsh)
  193 {
  194         uint32_t val, mul, div, res;
  195 
  196         val = bus_space_read_4(bst, bsh, SYSCTL_MT7620_CPLL_CFG1);
  197         if (val & MT7620_CPU_CLK_AUX0)
  198                 return (MTK_CPU_CLK_480MHZ);
  199 
  200         val = bus_space_read_4(bst, bsh, SYSCTL_MT7620_CPLL_CFG0);
  201         if (!(val & MT7620_CPLL_SW_CFG))
  202                 return (MTK_CPU_CLK_600MHZ);
  203 
  204         mul = MT7620_PLL_MULT_RATIO_BASE + ((val >> MT7620_PLL_MULT_RATIO_OFF) &
  205             MT7620_PLL_MULT_RATIO_MSK);
  206         div = (val >> MT7620_PLL_DIV_RATIO_OFF) & MT7620_PLL_DIV_RATIO_MSK;
  207 
  208         if (div != MT7620_PLL_DIV_RATIO_MSK)
  209                 div += MT7620_PLL_DIV_RATIO_BASE;
  210         else
  211                 div = MT7620_PLL_DIV_RATIO_MAX;
  212 
  213         res = (MT7620_XTAL_40 * mul) / div;
  214 
  215         return (MTK_MHZ(res));
  216 }
  217 
  218 static uint32_t
  219 mtk_detect_cpuclk_mt7621(bus_space_tag_t bst, bus_space_handle_t bsh)
  220 {
  221         uint32_t val, div, res;
  222 
  223         val = bus_space_read_4(bst, bsh, SYSCTL_CLKCFG0);
  224         if (val & MT7621_USES_MEMDIV) {
  225                 div = bus_space_read_4(bst, bsh, MTK_MT7621_CLKDIV_REG);
  226                 div >>= MT7621_MEMDIV_OFF;
  227                 div &= MT7621_MEMDIV_MSK;
  228                 div += MT7621_MEMDIV_BASE;
  229 
  230                 val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
  231                 val >>= MT7621_CLKSEL_OFF;
  232                 val &= MT7621_CLKSEL_MSK;
  233 
  234                 if (val >= MT7621_CLKSEL_25MHZ_VAL)
  235                         res = div * MT7621_CLKSEL_25MHZ;
  236                 else if (val >= MT7621_CLKSEL_20MHZ_VAL)
  237                         res = div * MT7621_CLKSEL_20MHZ;
  238                 else
  239                         res = div * 0; /* XXX: not sure about this */
  240         } else {
  241                 val = bus_space_read_4(bst, bsh, SYSCTL_CUR_CLK_STS);
  242                 div = (val >> MT7621_CLK_STS_DIV_OFF) & MT7621_CLK_STS_MSK;
  243                 val &= MT7621_CLK_STS_MSK;
  244 
  245                 res = (MT7621_CLK_STS_BASE * val) / div;
  246         }
  247 
  248         return (MTK_MHZ(res));
  249 }
  250 
  251 static uint32_t
  252 mtk_detect_cpuclk_mt7628(bus_space_tag_t bst, bus_space_handle_t bsh)
  253 {
  254         uint32_t val;
  255 
  256         val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
  257         val >>= MT7628_CPU_CLKSEL_OFF;
  258         val &= MT7628_CPU_CLKSEL_MSK;
  259 
  260         if (val)
  261                 return (MTK_CPU_CLK_580MHZ);
  262 
  263         return (MTK_CPU_CLK_575MHZ);
  264 }
  265 
  266 void
  267 mtk_soc_try_early_detect(void)
  268 {
  269         bus_space_tag_t bst;
  270         bus_space_handle_t bsh;
  271         uint32_t base;
  272         phandle_t node;
  273         int i;
  274 
  275         if ((node = OF_finddevice("/")) == -1)
  276                 return;
  277 
  278         for (i = 0; compat_data[i].ocd_str != NULL; i++) {
  279                 if (ofw_bus_node_is_compatible(node, compat_data[i].ocd_str)) {
  280                         mtk_soc_socid = compat_data[i].ocd_data;
  281                         break;
  282                 }
  283         }
  284 
  285         if (mtk_soc_socid == MTK_SOC_UNKNOWN) {
  286                 /* We don't know the SoC, so we don't know how to get clocks */
  287                 return;
  288         }
  289 
  290         bst = fdtbus_bs_tag;
  291         if (mtk_soc_socid == MTK_SOC_RT2880)
  292                 base = MTK_RT2880_BASE;
  293         else if (mtk_soc_socid == MTK_SOC_MT7621)
  294                 base = MTK_MT7621_BASE;
  295         else
  296                 base = MTK_DEFAULT_BASE;
  297 
  298         if (bus_space_map(bst, base, MTK_DEFAULT_SIZE, 0, &bsh))
  299                 return;
  300 
  301         /* Get our CHIP ID */
  302         mtk_soc_chipid0_3 = bus_space_read_4(bst, bsh, SYSCTL_CHIPID0_3);
  303         mtk_soc_chipid4_7 = bus_space_read_4(bst, bsh, SYSCTL_CHIPID4_7);
  304 
  305         /* First, figure out the CPU clock */
  306         switch (mtk_soc_socid) {
  307         case MTK_SOC_RT2880:
  308                 mtk_soc_cpuclk = mtk_detect_cpuclk_rt2880(bst, bsh);
  309                 break;
  310         case MTK_SOC_RT3050:  /* fallthrough */
  311         case MTK_SOC_RT3052:
  312         case MTK_SOC_RT3350:
  313                 mtk_soc_cpuclk = mtk_detect_cpuclk_rt305x(bst, bsh);
  314                 break;
  315         case MTK_SOC_RT3352:
  316                 mtk_soc_cpuclk = mtk_detect_cpuclk_rt3352(bst, bsh);
  317                 break;
  318         case MTK_SOC_RT3662:  /* fallthrough */
  319         case MTK_SOC_RT3883:
  320                 mtk_soc_cpuclk = mtk_detect_cpuclk_rt3883(bst, bsh);
  321                 break;
  322         case MTK_SOC_RT5350:
  323                 mtk_soc_cpuclk = mtk_detect_cpuclk_rt5350(bst, bsh);
  324                 break;
  325         case MTK_SOC_MT7620A: /* fallthrough */
  326         case MTK_SOC_MT7620N:
  327                 mtk_soc_cpuclk = mtk_detect_cpuclk_mt7620(bst, bsh);
  328                 break;
  329         case MTK_SOC_MT7621:
  330                 mtk_soc_cpuclk = mtk_detect_cpuclk_mt7621(bst, bsh);
  331                 break;
  332         case MTK_SOC_MT7628:  /* fallthrough */
  333         case MTK_SOC_MT7688:
  334                 mtk_soc_cpuclk = mtk_detect_cpuclk_mt7628(bst, bsh);
  335                 break;
  336         default:
  337                 /* We don't know the SoC, so we can't find the CPU clock */
  338                 break;
  339         }
  340 
  341         /* Now figure out the timer clock */
  342         if (mtk_soc_socid == MTK_SOC_MT7621) {
  343 #ifdef notyet
  344                 /* 
  345                  * We use the GIC timer for timing source and its clock freq is
  346                  * the same as the CPU's clock freq
  347                  */
  348                 mtk_soc_timerclk = mtk_soc_cpuclk;
  349 #else
  350                 /*
  351                  * When GIC timer and MIPS timer are ready to co-exist and
  352                  * GIC timer is actually implemented, we need to switch to it.
  353                  * Until then we use a fake GIC timer, which is actually a
  354                  * normal MIPS ticker, so the timer clock is half the CPU clock
  355                  */
  356                 mtk_soc_timerclk = mtk_soc_cpuclk / 2;
  357 #endif
  358         } else {
  359                 /*
  360                  * We use the MIPS ticker for the rest for now, so
  361                  * the CPU clock is divided by 2
  362                  */
  363                 mtk_soc_timerclk = mtk_soc_cpuclk / 2;
  364         }
  365 
  366         switch (mtk_soc_socid) {
  367         case MTK_SOC_RT2880:
  368                 mtk_soc_uartclk = mtk_soc_cpuclk / MTK_UARTDIV_2;
  369                 break;
  370         case MTK_SOC_RT3350:  /* fallthrough */
  371         case MTK_SOC_RT3050:  /* fallthrough */
  372         case MTK_SOC_RT3052:
  373                 /* UART clock is CPU clock / 3 */
  374                 mtk_soc_uartclk = mtk_soc_cpuclk / MTK_UARTDIV_3;
  375                 break;
  376         case MTK_SOC_RT3352:  /* fallthrough */
  377         case MTK_SOC_RT3662:  /* fallthrough */
  378         case MTK_SOC_RT3883:  /* fallthrough */
  379         case MTK_SOC_RT5350:  /* fallthrough */
  380         case MTK_SOC_MT7620A: /* fallthrough */
  381         case MTK_SOC_MT7620N: /* fallthrough */
  382         case MTK_SOC_MT7628:  /* fallthrough */
  383         case MTK_SOC_MT7688:
  384                 /* UART clock is always 40MHz */
  385                 mtk_soc_uartclk = MTK_UART_CLK_40MHZ;
  386                 break;
  387         case MTK_SOC_MT7621:
  388                 /* UART clock is always 50MHz */
  389                 mtk_soc_uartclk = MTK_UART_CLK_50MHZ;
  390                 break;
  391         default:
  392                 /* We don't know the SoC, so we don't know the UART clock */
  393                 break;
  394         }
  395 
  396         bus_space_unmap(bst, bsh, MTK_DEFAULT_SIZE);
  397 }
  398 
  399 void
  400 mtk_soc_set_cpu_model(void)
  401 {
  402         int idx, offset = sizeof(mtk_soc_chipid0_3);
  403         char *chipid0_3 = (char *)(&mtk_soc_chipid0_3);
  404         char *chipid4_7 = (char *)(&mtk_soc_chipid4_7);
  405 
  406         /*
  407          * CHIPID is always 2x32 bit registers, containing the ASCII
  408          * representation of the chip, so use that directly.
  409          *
  410          * The info is either pre-populated in mtk_soc_try_early_detect() or
  411          * it is left at its default value of "unknown " if it could not be
  412          * obtained for some reason.
  413          */
  414         for (idx = 0; idx < offset; idx++) {
  415                 cpu_model[idx] = chipid0_3[idx];
  416                 cpu_model[idx + offset] = chipid4_7[idx];
  417         }
  418 
  419         /* Null-terminate the string */
  420         cpu_model[2 * offset] = 0;
  421 }
  422 
  423 uint32_t
  424 mtk_soc_get_uartclk(void)
  425 {
  426 
  427         return mtk_soc_uartclk;
  428 }
  429 
  430 uint32_t
  431 mtk_soc_get_cpuclk(void)
  432 {
  433 
  434         return mtk_soc_cpuclk;
  435 }
  436 
  437 uint32_t
  438 mtk_soc_get_timerclk(void)
  439 {
  440 
  441         return mtk_soc_timerclk;
  442 }
  443 
  444 uint32_t
  445 mtk_soc_get_socid(void)
  446 {
  447 
  448         return mtk_soc_socid;
  449 }
  450 
  451 /*
  452  * The following are generic reset and clock functions
  453  */
  454 
  455 /* Default reset time is 100ms */
  456 #define DEFAULT_RESET_TIME      100000
  457 
  458 int
  459 mtk_soc_reset_device(device_t dev)
  460 {
  461         int res;
  462 
  463         res = fdt_reset_assert_all(dev);
  464         if (res == 0) {
  465                 DELAY(DEFAULT_RESET_TIME);
  466                 res = fdt_reset_deassert_all(dev);
  467                 if (res == 0)
  468                         DELAY(DEFAULT_RESET_TIME);
  469         }
  470 
  471         return (res);
  472 }
  473 
  474 int
  475 mtk_soc_stop_clock(device_t dev)
  476 {
  477 
  478         return (fdt_clock_disable_all(dev));
  479 }
  480 
  481 int
  482 mtk_soc_start_clock(device_t dev)
  483 {
  484 
  485         return (fdt_clock_enable_all(dev));
  486 }
  487 
  488 int
  489 mtk_soc_assert_reset(device_t dev)
  490 {
  491 
  492         return (fdt_reset_assert_all(dev));
  493 }
  494 
  495 int
  496 mtk_soc_deassert_reset(device_t dev)
  497 {
  498 
  499         return (fdt_reset_deassert_all(dev));
  500 }
  501 
  502 void
  503 mtk_soc_reset(void)
  504 {
  505 
  506         mtk_sysctl_clr_set(SYSCTL_RSTCTRL, 0, 1);
  507         mtk_sysctl_clr_set(SYSCTL_RSTCTRL, 1, 0);
  508 }

Cache object: e6d65bc13540ab74e2e784aec46f09ce


[ 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.