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/broadcom/bcm_pmu.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 Landon Fuller <landonf@FreeBSD.org>
    3  *
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include <dev/bhnd/bhnd.h>
   32 
   33 #include <dev/bhnd/cores/chipc/chipcreg.h>
   34 
   35 #include <dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctlvar.h>
   36 
   37 #include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
   38 #include <dev/bhnd/cores/pmu/bhnd_pmuvar.h>
   39 
   40 #include "bcm_machdep.h"
   41 
   42 static struct bhnd_pmu_query    *bcm_get_pmu(struct bcm_platform *bp);
   43 static bool                      bcm_has_pmu(struct bcm_platform *bp);
   44 
   45 static uint32_t                  bcm_pmu_read4(bus_size_t reg, void *ctx);
   46 static void                      bcm_pmu_write4(bus_size_t reg, uint32_t val,
   47                                      void *ctx);
   48 static uint32_t                  bcm_pmu_read_chipst(void *ctx);
   49 
   50 const struct bhnd_pmu_io bcm_pmu_soc_io = {
   51         .rd4            = bcm_pmu_read4,
   52         .wr4            = bcm_pmu_write4,
   53         .rd_chipst      = bcm_pmu_read_chipst
   54 };
   55 
   56 /**
   57  * Supported UART clock sources.
   58  */
   59 typedef enum {
   60         BCM_UART_RCLK_PLL_T1    = 0,    /**< UART uses PLL m2 (mii/uart/mipsref) with no divisor */
   61         BCM_UART_RCLK_ALP       = 1,    /**< UART uses ALP rclk with no divisor */
   62         BCM_UART_RCLK_EXT       = 2,    /**< UART uses 1.8423 MHz external clock */
   63         BCM_UART_RCLK_SI        = 3,    /**< UART uses backplane clock with divisor of two */
   64         BCM_UART_RCLK_FIXED     = 4,    /**< UART uses fixed 88Mhz backplane clock with a divisor of 48 */
   65 } bcm_uart_clksrc;
   66 
   67 /**
   68  * UART clock configuration.
   69  */
   70 struct bcm_uart_clkcfg {
   71         bcm_uart_clksrc         src;    /**< clock source */
   72         uint32_t                div;    /**< clock divisor */
   73         uint32_t                freq;   /**< clock frequency (Hz) */
   74 };
   75 
   76 #define BCM_UART_RCLK_PLL_T1_DIV        1
   77 #define BCM_UART_RCLK_ALP_DIV           1
   78 #define BCM_UART_RCLK_EXT_HZ            1842300         /* 1.8423MHz */
   79 #define BCM_UART_RCLK_EXT_DIV           1
   80 #define BCM_UART_RCLK_FIXED_HZ          88000000        /* 88MHz */
   81 #define BCM_UART_RCLK_FIXED_DIV         48
   82 
   83 /* Fetch PLL type from ChipCommon capability flags */
   84 #define BCM_PMU_PLL_TYPE(_bp)   \
   85         CHIPC_GET_BITS(_bp->cc_caps, CHIPC_CAP_PLL)
   86 
   87 /**
   88  * Return the PMU instance, or NULL if no PMU.
   89  */
   90 static struct bhnd_pmu_query *
   91 bcm_get_pmu(struct bcm_platform *bp)
   92 {
   93         if (!bcm_has_pmu(bp))
   94                 return (NULL);
   95         return (&bp->pmu);
   96 }
   97 
   98 /**
   99  * Return true if a PMU is available, false otherwise.
  100  */
  101 static bool
  102 bcm_has_pmu(struct bcm_platform *bp)
  103 {
  104         return (bp->pmu_addr != 0);
  105 }
  106 
  107 /**
  108  * Determine the UART clock source for @p bp and return the
  109  * corresponding clock configuration, if any.
  110  */
  111 static struct bcm_uart_clkcfg
  112 bcm_get_uart_clkcfg(struct bcm_platform *bp)
  113 {
  114         struct bcm_uart_clkcfg   cfg;
  115         struct bhnd_core_info   *cc_id;
  116 
  117         cc_id = &bp->cc_id;
  118 
  119         /* These tests are ordered by precedence. */
  120 
  121         /* PLL M2 clock source? */
  122         if (!bcm_has_pmu(bp) && BCM_PMU_PLL_TYPE(bp) == CHIPC_PLL_TYPE1) {
  123                 uint32_t n, m;
  124         
  125                 n = BCM_CHIPC_READ_4(bp, CHIPC_CLKC_N);
  126                 m = BCM_CHIPC_READ_4(bp, CHIPC_CLKC_M2);
  127 
  128                 cfg = (struct bcm_uart_clkcfg) {
  129                         BCM_UART_RCLK_PLL_T1,
  130                         BCM_UART_RCLK_PLL_T1_DIV,
  131                         bhnd_pwrctl_clock_rate(BCM_PMU_PLL_TYPE(bp), n, m)
  132                 };
  133         
  134                 return (cfg);
  135         }
  136 
  137         /* ALP clock source? */
  138         if (cc_id->hwrev != 15 && cc_id->hwrev >= 11) {
  139                 cfg = (struct bcm_uart_clkcfg) {
  140                         BCM_UART_RCLK_ALP,
  141                         BCM_UART_RCLK_ALP_DIV,
  142                         bcm_get_alpfreq(bp)
  143                 };
  144                 return (cfg);
  145         }
  146 
  147         /* External clock? */
  148         if (CHIPC_HWREV_HAS_CORECTRL(cc_id->hwrev)) {
  149                 uint32_t        corectrl, uclksel;
  150                 bool            uintclk0;
  151 
  152                 /* Fetch UART clock support flag */ 
  153                 uclksel = CHIPC_GET_BITS(bp->cc_caps, CHIPC_CAP_UCLKSEL);
  154 
  155                 /* Is UART using internal clock? */
  156                 corectrl = BCM_CHIPC_READ_4(bp, CHIPC_CORECTRL);
  157                 uintclk0 = CHIPC_GET_FLAG(corectrl, CHIPC_UARTCLKO);
  158 
  159                 if (uintclk0 && uclksel == CHIPC_CAP_UCLKSEL_UINTCLK) {
  160                         cfg = (struct bcm_uart_clkcfg) {
  161                                 BCM_UART_RCLK_EXT,
  162                                 BCM_UART_RCLK_EXT_DIV,
  163                                 BCM_UART_RCLK_EXT_HZ
  164                         };
  165                         return (cfg);
  166                 }
  167         }
  168 
  169         /* UART uses backplane clock? */
  170         if (cc_id->hwrev == 15 || (cc_id->hwrev >= 3 && cc_id->hwrev <= 10)) {
  171                 cfg = (struct bcm_uart_clkcfg) {
  172                         BCM_UART_RCLK_SI,
  173                         BCM_CHIPC_READ_4(bp, CHIPC_CLKDIV) & CHIPC_CLKD_UART,
  174                         bcm_get_sifreq(bp)
  175                 };
  176 
  177                 return (cfg);
  178         }
  179 
  180         /* UART uses fixed clock? */
  181         if (cc_id->hwrev <= 2) {
  182                 cfg = (struct bcm_uart_clkcfg) {
  183                         BCM_UART_RCLK_FIXED,
  184                         BCM_UART_RCLK_FIXED_DIV,
  185                         BCM_UART_RCLK_FIXED_HZ
  186                 };
  187 
  188                 return (cfg);
  189         }
  190 
  191         /* All cases must be accounted for above */
  192         panic("unreachable - no clock config");
  193 }
  194 
  195 /**
  196  * Return the UART reference clock frequency (in Hz).
  197  */
  198 u_int
  199 bcm_get_uart_rclk(struct bcm_platform *bp)
  200 {
  201         struct bcm_uart_clkcfg cfg;
  202 
  203         cfg = bcm_get_uart_clkcfg(bp);
  204         return (cfg.freq / cfg.div);
  205 }
  206 
  207 /** ALP clock frequency (in Hz) */
  208 uint64_t
  209 bcm_get_alpfreq(struct bcm_platform *bp) {
  210         if (!bcm_has_pmu(bp))
  211                 return (BHND_PMU_ALP_CLOCK);
  212 
  213         return (bhnd_pmu_alp_clock(bcm_get_pmu(bp)));
  214 }
  215 
  216 /** ILP clock frequency (in Hz) */
  217 uint64_t
  218 bcm_get_ilpfreq(struct bcm_platform *bp) {
  219         if (!bcm_has_pmu(bp))
  220                 return (BHND_PMU_ILP_CLOCK);
  221 
  222         return (bhnd_pmu_ilp_clock(bcm_get_pmu(bp)));
  223 }
  224 
  225 /** CPU clock frequency (in Hz) */
  226 uint64_t
  227 bcm_get_cpufreq(struct bcm_platform *bp)
  228 {
  229         uint32_t                 fixed_hz;
  230         uint32_t                 n, m;
  231         bus_size_t               mreg;
  232         uint8_t                  pll_type;
  233 
  234         /* PMU support */
  235         if (bcm_has_pmu(bp))
  236                 return (bhnd_pmu_cpu_clock(bcm_get_pmu(bp)));
  237 
  238         /*
  239          * PWRCTL support
  240          */
  241         pll_type = CHIPC_GET_BITS(bp->cc_caps, CHIPC_CAP_PLL);
  242         mreg = bhnd_pwrctl_cpu_clkreg_m(&bp->cid, pll_type, &fixed_hz);
  243         if (mreg == 0)
  244                 return (fixed_hz);
  245 
  246         n = BCM_CHIPC_READ_4(bp, CHIPC_CLKC_N);
  247         m = BCM_CHIPC_READ_4(bp, mreg);
  248 
  249         return (bhnd_pwrctl_cpu_clock_rate(&bp->cid, pll_type, n, m));
  250         
  251 }
  252 
  253 /** Backplane clock frequency (in Hz) */
  254 uint64_t
  255 bcm_get_sifreq(struct bcm_platform *bp)
  256 {
  257         uint32_t                 fixed_hz;
  258         uint32_t                 n, m;
  259         bus_size_t               mreg;
  260         uint8_t                  pll_type;
  261 
  262         /* PMU support */
  263         if (bcm_has_pmu(bp))
  264                 return (bhnd_pmu_si_clock(bcm_get_pmu(bp)));
  265 
  266         /*
  267          * PWRCTL support
  268          */
  269         pll_type = CHIPC_GET_BITS(bp->cc_caps, CHIPC_CAP_PLL);
  270         mreg = bhnd_pwrctl_si_clkreg_m(&bp->cid, pll_type, &fixed_hz);
  271         if (mreg == 0)
  272                 return (fixed_hz);
  273 
  274         n = BCM_CHIPC_READ_4(bp, CHIPC_CLKC_N);
  275         m = BCM_CHIPC_READ_4(bp, mreg);
  276 
  277         return (bhnd_pwrctl_si_clock_rate(&bp->cid, pll_type, n, m));
  278 }
  279 
  280 
  281 static uint32_t
  282 bcm_pmu_read4(bus_size_t reg, void *ctx) {
  283         struct bcm_platform *bp = ctx;
  284         return (readl(BCM_SOC_ADDR(bp->pmu_addr, reg)));
  285 }
  286 
  287 static void
  288 bcm_pmu_write4(bus_size_t reg, uint32_t val, void *ctx) {
  289         struct bcm_platform *bp = ctx;
  290         writel(BCM_SOC_ADDR(bp->pmu_addr, reg), val);
  291 }
  292 
  293 static uint32_t
  294 bcm_pmu_read_chipst(void *ctx)
  295 {
  296         struct bcm_platform *bp = ctx;
  297         return (readl(BCM_SOC_ADDR(bp->cc_addr, CHIPC_CHIPST)));
  298 }

Cache object: 77ba62d339831463b5177d0c50fae7d7


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