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/arm64/nvidia/tegra210/tegra210_clk_super.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright 2020 Michal Meloun <mmel@FreeBSD.org>
    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 <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/bus.h>
   34 #include <sys/lock.h>
   35 #include <sys/mutex.h>
   36 #include <sys/rman.h>
   37 
   38 #include <machine/bus.h>
   39 
   40 #include <dev/extres/clk/clk.h>
   41 
   42 #include <dt-bindings/clock/tegra210-car.h>
   43 #include "tegra210_car.h"
   44 
   45 struct super_mux_def {
   46         struct clknode_init_def clkdef;
   47         uint32_t                base_reg;
   48         uint32_t                flags;
   49 };
   50 
   51 #define PLIST(x) static const char *x[]
   52 #define SM(_id, cn, pl, r)                                              \
   53 {                                                                       \
   54         .clkdef.id = _id,                                               \
   55         .clkdef.name = cn,                                              \
   56         .clkdef.parent_names = pl,                                      \
   57         .clkdef.parent_cnt = nitems(pl),                                \
   58         .clkdef.flags = CLK_NODE_STATIC_STRINGS,                        \
   59         .base_reg = r,                                                  \
   60 }
   61 
   62 
   63 PLIST(cclk_g_parents) = {
   64         "clk_m", NULL, "clk_s", NULL,
   65         "pllP_out0", "pllP_out4", NULL, NULL,
   66         "pllX_out0", "dfllCPU_out_alias", NULL, NULL,
   67         NULL, NULL, "pllX_out0_alias", "dfllCPU_out",
   68 };
   69 
   70 PLIST(cclk_lp_parents) = {
   71         "clk_m", NULL, "clk_s", NULL,
   72         "pllP_out0", "pllP_out4", NULL, NULL,
   73         "pllX_out0", "dfllCPU_out_alias", NULL, NULL,
   74         NULL, NULL, "pllX_out0_alias", "dfllCPU_out",
   75 };
   76 
   77 PLIST(sclk_parents) = {
   78         "clk_m", "pllC_out1", "pllC4_out3", "pllP_out0",
   79         "pllP_out2", "pllC4_out1", "clk_s", "pllC4_out1",
   80 };
   81 
   82 static struct super_mux_def super_mux_def[] = {
   83  SM(TEGRA210_CLK_CCLK_G, "cclk_g", cclk_g_parents, CCLKG_BURST_POLICY),
   84  SM(TEGRA210_CLK_CCLK_LP, "cclk_lp", cclk_lp_parents, CCLKLP_BURST_POLICY),
   85  SM(TEGRA210_CLK_SCLK, "sclk", sclk_parents, SCLK_BURST_POLICY),
   86 };
   87 
   88 static int super_mux_init(struct clknode *clk, device_t dev);
   89 static int super_mux_set_mux(struct clknode *clk, int idx);
   90 
   91 struct super_mux_sc {
   92         device_t                clkdev;
   93         uint32_t                base_reg;
   94         uint32_t                flags;
   95 
   96         int                     mux;
   97 };
   98 
   99 static clknode_method_t super_mux_methods[] = {
  100         /* Device interface */
  101         CLKNODEMETHOD(clknode_init,             super_mux_init),
  102         CLKNODEMETHOD(clknode_set_mux,          super_mux_set_mux),
  103         CLKNODEMETHOD_END
  104 };
  105 DEFINE_CLASS_1(tegra210_super_mux, tegra210_super_mux_class, super_mux_methods,
  106    sizeof(struct super_mux_sc), clknode_class);
  107 
  108 /* Mux status. */
  109 #define SUPER_MUX_STATE_STDBY           0
  110 #define SUPER_MUX_STATE_IDLE            1
  111 #define SUPER_MUX_STATE_RUN             2
  112 #define SUPER_MUX_STATE_IRQ             3
  113 #define SUPER_MUX_STATE_FIQ             4
  114 
  115 /* Mux register bits. */
  116 #define SUPER_MUX_STATE_BIT_SHIFT       28
  117 #define SUPER_MUX_STATE_BIT_MASK        0xF
  118 /* State is Priority encoded */
  119 #define SUPER_MUX_STATE_BIT_STDBY       0x00
  120 #define SUPER_MUX_STATE_BIT_IDLE        0x01
  121 #define SUPER_MUX_STATE_BIT_RUN         0x02
  122 #define SUPER_MUX_STATE_BIT_IRQ         0x04
  123 #define SUPER_MUX_STATE_BIT_FIQ         0x08
  124 
  125 #define SUPER_MUX_MUX_WIDTH             4
  126 
  127 static uint32_t
  128 super_mux_get_state(uint32_t reg)
  129 {
  130         reg = (reg >> SUPER_MUX_STATE_BIT_SHIFT) & SUPER_MUX_STATE_BIT_MASK;
  131         if (reg & SUPER_MUX_STATE_BIT_FIQ)
  132                  return (SUPER_MUX_STATE_FIQ);
  133         if (reg & SUPER_MUX_STATE_BIT_IRQ)
  134                  return (SUPER_MUX_STATE_IRQ);
  135         if (reg & SUPER_MUX_STATE_BIT_RUN)
  136                  return (SUPER_MUX_STATE_RUN);
  137         if (reg & SUPER_MUX_STATE_BIT_IDLE)
  138                  return (SUPER_MUX_STATE_IDLE);
  139         return (SUPER_MUX_STATE_STDBY);
  140 }
  141 
  142 static int
  143 super_mux_init(struct clknode *clk, device_t dev)
  144 {
  145         struct super_mux_sc *sc;
  146         uint32_t reg;
  147         int shift, state;
  148 
  149         sc = clknode_get_softc(clk);
  150 
  151         DEVICE_LOCK(sc);
  152         RD4(sc, sc->base_reg, &reg);
  153         DEVICE_UNLOCK(sc);
  154         state = super_mux_get_state(reg);
  155 
  156         if ((state != SUPER_MUX_STATE_RUN) &&
  157             (state != SUPER_MUX_STATE_IDLE)) {
  158                 panic("Unexpected super mux state: %u", state);
  159         }
  160 
  161         shift = state * SUPER_MUX_MUX_WIDTH;
  162         sc->mux = (reg >> shift) & ((1 << SUPER_MUX_MUX_WIDTH) - 1);
  163 
  164         clknode_init_parent_idx(clk, sc->mux);
  165 
  166         return(0);
  167 }
  168 
  169 static int
  170 super_mux_set_mux(struct clknode *clk, int idx)
  171 {
  172 
  173         struct super_mux_sc *sc;
  174         int shift, state;
  175         uint32_t reg, dummy;
  176 
  177         sc = clknode_get_softc(clk);
  178 
  179         DEVICE_LOCK(sc);
  180         RD4(sc, sc->base_reg, &reg);
  181         state = super_mux_get_state(reg);
  182 
  183         if ((state != SUPER_MUX_STATE_RUN) &&
  184             (state != SUPER_MUX_STATE_IDLE)) {
  185                 panic("Unexpected super mux state: %u", state);
  186         }
  187 
  188         shift = (state - 1) * SUPER_MUX_MUX_WIDTH;
  189         sc->mux = idx;
  190         reg &= ~(((1 << SUPER_MUX_MUX_WIDTH) - 1) << shift);
  191         reg |= idx << shift;
  192 
  193         WR4(sc, sc->base_reg, reg);
  194         RD4(sc, sc->base_reg, &dummy);
  195         DEVICE_UNLOCK(sc);
  196 
  197         return(0);
  198 }
  199 
  200 static int
  201 super_mux_register(struct clkdom *clkdom, struct super_mux_def *clkdef)
  202 {
  203         struct clknode *clk;
  204         struct super_mux_sc *sc;
  205 
  206         clk = clknode_create(clkdom, &tegra210_super_mux_class,
  207             &clkdef->clkdef);
  208         if (clk == NULL)
  209                 return (1);
  210 
  211         sc = clknode_get_softc(clk);
  212         sc->clkdev = clknode_get_device(clk);
  213         sc->base_reg = clkdef->base_reg;
  214         sc->flags = clkdef->flags;
  215 
  216         clknode_register(clkdom, clk);
  217         return (0);
  218 }
  219 
  220 void
  221 tegra210_super_mux_clock(struct tegra210_car_softc *sc)
  222 {
  223         int i, rv;
  224 
  225         for (i = 0; i <  nitems(super_mux_def); i++) {
  226                 rv = super_mux_register(sc->clkdom, &super_mux_def[i]);
  227                 if (rv != 0)
  228                         panic("super_mux_register failed");
  229         }
  230 
  231 }

Cache object: ba5ae6e197ed7640e860d08f677e7bb4


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