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/arm/mv/clk/periph_clk_d.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 (c) 2021 Semihalf.
    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/bus.h>
   33 #include <sys/kernel.h>
   34 #include <sys/module.h>
   35 #include <sys/mutex.h>
   36 #include <sys/rman.h>
   37 #include <machine/bus.h>
   38 
   39 #include <dev/fdt/simplebus.h>
   40 
   41 #include <dev/extres/clk/clk.h>
   42 #include <dev/extres/clk/clk_div.h>
   43 #include <dev/extres/clk/clk_fixed.h>
   44 #include <dev/extres/clk/clk_gate.h>
   45 #include <dev/extres/clk/clk_mux.h>
   46 
   47 #include <dev/ofw/ofw_bus.h>
   48 #include <dev/ofw/ofw_bus_subr.h>
   49 
   50 #include "clkdev_if.h"
   51 #include "periph.h"
   52 
   53 #define PARENT_CNT      2
   54 
   55 /*
   56  * Register chain: mux (select proper TBG) -> div1 (first frequency divider) ->
   57  * div2 (second frequency divider) -> mux (select divided freq.
   58  * or xtal output) -> gate (enable or disable clock), which is also final node
   59  */
   60 
   61 int
   62 a37x0_periph_d_register_full_clk_dd(struct clkdom *clkdom,
   63     struct a37x0_periph_clknode_def *device_def)
   64 {
   65         const char *parent_names[PARENT_CNT];
   66         struct clk_mux_def *clk_mux;
   67         struct clk_mux_def *tbg_mux;
   68         struct clk_gate_def *gate;
   69         struct clk_div_def *div1;
   70         struct clk_div_def *div2;
   71         int error, dev_id;
   72 
   73         dev_id = device_def->common_def.device_id;
   74         tbg_mux = &device_def->clk_def.full_dd.tbg_mux;
   75         div1 = &device_def->clk_def.full_dd.div1;
   76         div2 = &device_def->clk_def.full_dd.div2;
   77         gate = &device_def->clk_def.full_dd.gate;
   78         clk_mux = &device_def->clk_def.full_dd.clk_mux;
   79 
   80         a37x0_periph_set_props(&tbg_mux->clkdef, device_def->common_def.tbgs,
   81             device_def->common_def.tbg_cnt);
   82 
   83         error = a37x0_periph_create_mux(clkdom,
   84             tbg_mux, A37x0_INTERNAL_CLK_ID(dev_id, MUX_POS));
   85         if (error)
   86                 goto fail;
   87 
   88         a37x0_periph_set_props(&div1->clkdef, &tbg_mux->clkdef.name, 1);
   89         error = a37x0_periph_create_div(clkdom, div1,
   90             A37x0_INTERNAL_CLK_ID(dev_id, DIV1_POS));
   91         if (error)
   92                 goto fail;
   93 
   94         a37x0_periph_set_props(&div2->clkdef, &div1->clkdef.name, 1);
   95         error = a37x0_periph_create_div(clkdom, div2,
   96             A37x0_INTERNAL_CLK_ID(dev_id, DIV2_POS));
   97         if (error)
   98                 goto fail;
   99 
  100         parent_names[0] = device_def->common_def.xtal;
  101         parent_names[1] = div2->clkdef.name;
  102 
  103         a37x0_periph_set_props(&clk_mux->clkdef, parent_names, PARENT_CNT);
  104         error = a37x0_periph_create_mux(clkdom, clk_mux,
  105             A37x0_INTERNAL_CLK_ID(dev_id, CLK_MUX_POS));
  106         if (error)
  107                 goto fail;
  108 
  109         a37x0_periph_set_props(&gate->clkdef, &clk_mux->clkdef.name, 1);
  110         error = a37x0_periph_create_gate(clkdom, gate,
  111             dev_id);
  112         if (error)
  113                 goto fail;
  114 
  115 fail:
  116 
  117         return (error);
  118 }
  119 
  120 /*
  121  * Register chain: mux (select proper TBG) -> div1 (first frequency divider) ->
  122  * mux (select divided freq. or xtal output) -> gate (enable or disable clock),
  123  * which is also final node
  124  */
  125 
  126 int
  127 a37x0_periph_d_register_full_clk(struct clkdom *clkdom,
  128     struct a37x0_periph_clknode_def *device_def)
  129 {
  130         const char *parent_names[PARENT_CNT];
  131         struct clk_mux_def *tbg_mux;
  132         struct clk_mux_def *clk_mux;
  133         struct clk_gate_def *gate;
  134         struct clk_div_def *div;
  135         int error, dev_id;
  136 
  137         dev_id = device_def->common_def.device_id;
  138         tbg_mux = &device_def->clk_def.full_d.tbg_mux;
  139         div = &device_def->clk_def.full_d.div;
  140         gate = &device_def->clk_def.full_d.gate;
  141         clk_mux = &device_def->clk_def.full_d. clk_mux;
  142 
  143         a37x0_periph_set_props(&tbg_mux->clkdef, device_def->common_def.tbgs,
  144             device_def->common_def.tbg_cnt);
  145         error = a37x0_periph_create_mux(clkdom, tbg_mux,
  146             A37x0_INTERNAL_CLK_ID(device_def->common_def.device_id, MUX_POS));
  147         if (error)
  148                 goto fail;
  149 
  150         a37x0_periph_set_props(&div->clkdef, &tbg_mux->clkdef.name, 1);
  151         error = a37x0_periph_create_div(clkdom, div,
  152             A37x0_INTERNAL_CLK_ID(device_def->common_def.device_id, DIV1_POS));
  153         if (error)
  154                 goto fail;
  155 
  156         parent_names[0] = device_def->common_def.xtal;
  157         parent_names[1] = div->clkdef.name;
  158 
  159         a37x0_periph_set_props(&clk_mux->clkdef, parent_names, PARENT_CNT);
  160         error = a37x0_periph_create_mux(clkdom, clk_mux,
  161             A37x0_INTERNAL_CLK_ID(dev_id, CLK_MUX_POS));
  162         if (error)
  163                 goto fail;
  164 
  165         a37x0_periph_set_props(&gate->clkdef, &clk_mux->clkdef.name, 1);
  166         error = a37x0_periph_create_gate(clkdom, gate,
  167             dev_id);
  168         if (error)
  169                 goto fail;
  170 
  171 fail:
  172 
  173         return (error);
  174 }
  175 
  176 /*
  177  * Register CPU clock. It consists of mux (select proper TBG) -> div (frequency
  178  * divider) -> mux (choose divided or xtal output).
  179  */
  180 
  181 int
  182 a37x0_periph_d_register_periph_cpu(struct clkdom *clkdom,
  183     struct a37x0_periph_clknode_def *device_def)
  184 {
  185         const char *parent_names[PARENT_CNT];
  186         struct clk_mux_def *clk_mux;
  187         struct clk_mux_def *tbg_mux;
  188         struct clk_div_def *div;
  189         int error, dev_id;
  190 
  191         dev_id = device_def->common_def.device_id;
  192         tbg_mux = &device_def->clk_def.cpu.tbg_mux;
  193         div = &device_def->clk_def.cpu.div;
  194         clk_mux = &device_def->clk_def.cpu.clk_mux;
  195 
  196         a37x0_periph_set_props(&tbg_mux->clkdef, device_def->common_def.tbgs,
  197             device_def->common_def.tbg_cnt);
  198         error = a37x0_periph_create_mux(clkdom, tbg_mux,
  199             A37x0_INTERNAL_CLK_ID(dev_id, MUX_POS));
  200         if (error)
  201                 goto fail;
  202 
  203         a37x0_periph_set_props(&div->clkdef, &tbg_mux->clkdef.name, 1);
  204         error = a37x0_periph_create_div(clkdom, div,
  205             A37x0_INTERNAL_CLK_ID(dev_id, DIV1_POS));
  206         if (error)
  207                 goto fail;
  208 
  209         parent_names[0] = device_def->common_def.xtal;
  210         parent_names[1] = div->clkdef.name;
  211 
  212         a37x0_periph_set_props(&clk_mux->clkdef, parent_names, PARENT_CNT);
  213         error = a37x0_periph_create_mux(clkdom, clk_mux,
  214             dev_id);
  215 
  216 fail:
  217 
  218         return (error);
  219 }
  220 
  221 /*
  222  * Register chain: mux (choose proper TBG) -> div1 (first frequency divider) ->
  223  * div2 (second frequency divider) -> mux (choose divided or xtal output).
  224  */
  225 int
  226 a37x0_periph_d_register_mdd(struct clkdom *clkdom,
  227     struct a37x0_periph_clknode_def *device_def)
  228 {
  229         const char *parent_names[PARENT_CNT];
  230         struct clk_mux_def *tbg_mux;
  231         struct clk_mux_def *clk_mux;
  232         struct clk_div_def *div1;
  233         struct clk_div_def *div2;
  234         int error, dev_id;
  235 
  236         dev_id = device_def->common_def.device_id;
  237         tbg_mux = &device_def->clk_def.mdd.tbg_mux;
  238         div1 = &device_def->clk_def.mdd.div1;
  239         div2 = &device_def->clk_def.mdd.div2;
  240         clk_mux = &device_def->clk_def.mdd.clk_mux;
  241 
  242         a37x0_periph_set_props(&tbg_mux->clkdef, device_def->common_def.tbgs,
  243             device_def->common_def.tbg_cnt);
  244         error = a37x0_periph_create_mux(clkdom, tbg_mux,
  245             A37x0_INTERNAL_CLK_ID(dev_id, MUX_POS));
  246         if (error)
  247                 goto fail;
  248 
  249         a37x0_periph_set_props(&div1->clkdef, &tbg_mux->clkdef.name, 1);
  250         error = a37x0_periph_create_div(clkdom, div1,
  251             A37x0_INTERNAL_CLK_ID(dev_id, DIV1_POS));
  252         if (error)
  253                 goto fail;
  254 
  255         a37x0_periph_set_props(&div2->clkdef, &div1->clkdef.name, 1);
  256         error = a37x0_periph_create_div(clkdom, div2,
  257             A37x0_INTERNAL_CLK_ID(dev_id, DIV2_POS));
  258 
  259         if (error)
  260                 goto fail;
  261 
  262         parent_names[0] = device_def->common_def.xtal;
  263         parent_names[1] = div2->clkdef.name;
  264 
  265         a37x0_periph_set_props(&clk_mux->clkdef, parent_names, PARENT_CNT);
  266         error = a37x0_periph_create_mux(clkdom, clk_mux,
  267             dev_id);
  268         if (error)
  269                 goto fail;
  270 
  271 fail:
  272 
  273         return (error);
  274 }

Cache object: f653d198916815456b76eeef5bc9d3ca


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