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/freescale/imx/clk/imx_clk_frac_pll.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) 2020 Oleksandr Tymoshenko <gonzo@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 ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   23  * 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  * $FreeBSD$
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/bus.h>
   36 
   37 #include <dev/extres/clk/clk.h>
   38 
   39 #include <arm64/freescale/imx/clk/imx_clk_frac_pll.h>
   40 
   41 #include "clkdev_if.h"
   42 
   43 struct imx_clk_frac_pll_sc {
   44         uint32_t        offset;
   45 };
   46 
   47 #define WRITE4(_clk, off, val)                                          \
   48         CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
   49 #define READ4(_clk, off, val)                                           \
   50         CLKDEV_READ_4(clknode_get_device(_clk), off, val)
   51 #define DEVICE_LOCK(_clk)                                               \
   52         CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
   53 #define DEVICE_UNLOCK(_clk)                                             \
   54         CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
   55 
   56 #define CFG0    0
   57 #define  CFG0_PLL_LOCK          (1 << 31)
   58 #define  CFG0_PD                (1 << 19)
   59 #define  CFG0_BYPASS            (1 << 14)
   60 #define  CFG0_NEWDIV_VAL        (1 << 12)
   61 #define  CFG0_NEWDIV_ACK        (1 << 11)
   62 #define  CFG0_OUTPUT_DIV_MASK   (0x1f << 0)
   63 #define  CFG0_OUTPUT_DIV_SHIFT  0
   64 #define CFG1    4
   65 #define  CFG1_FRAC_DIV_MASK     (0xffffff << 7)
   66 #define  CFG1_FRAC_DIV_SHIFT    7
   67 #define  CFG1_INT_DIV_MASK      (0x7f << 0)
   68 #define  CFG1_INT_DIV_SHIFT     0
   69 
   70 #if 0
   71 #define dprintf(format, arg...)                                         \
   72         printf("%s:(%s)" format, __func__, clknode_get_name(clk), arg)
   73 #else
   74 #define dprintf(format, arg...)
   75 #endif
   76 
   77 static int
   78 imx_clk_frac_pll_init(struct clknode *clk, device_t dev)
   79 {
   80 
   81         clknode_init_parent_idx(clk, 0);
   82         return (0);
   83 }
   84 
   85 static int
   86 imx_clk_frac_pll_set_gate(struct clknode *clk, bool enable)
   87 {
   88         struct imx_clk_frac_pll_sc *sc;
   89         uint32_t cfg0;
   90         int timeout;
   91 
   92         sc = clknode_get_softc(clk);
   93 
   94         DEVICE_LOCK(clk);
   95         READ4(clk, sc->offset + CFG0, &cfg0);
   96         if (enable)
   97                 cfg0 &= ~(CFG0_PD);
   98         else
   99                 cfg0 |= CFG0_PD;
  100         WRITE4(clk, sc->offset + CFG0, cfg0);
  101 
  102         /* Wait for PLL to lock */
  103         if (enable && ((cfg0 & CFG0_BYPASS) == 0)) {
  104                 for (timeout = 1000; timeout; timeout--) {
  105                         READ4(clk, sc->offset + CFG0, &cfg0);
  106                         if (cfg0 & CFG0_PLL_LOCK)
  107                                 break;
  108                         DELAY(1);
  109                 }
  110         }
  111 
  112         DEVICE_UNLOCK(clk);
  113 
  114         return (0);
  115 }
  116 
  117 static int
  118 imx_clk_frac_pll_recalc(struct clknode *clk, uint64_t *freq)
  119 {
  120         struct imx_clk_frac_pll_sc *sc;
  121         uint32_t cfg0, cfg1;
  122         uint64_t div, divfi, divff, divf_val;
  123 
  124         sc = clknode_get_softc(clk);
  125 
  126         DEVICE_LOCK(clk);
  127         READ4(clk, sc->offset + CFG0, &cfg0);
  128         READ4(clk, sc->offset + CFG1, &cfg1);
  129         DEVICE_UNLOCK(clk);
  130 
  131         div = (cfg0 & CFG0_OUTPUT_DIV_MASK) >> CFG0_OUTPUT_DIV_SHIFT;
  132         div = (div + 1) * 2;
  133         divff = (cfg1 & CFG1_FRAC_DIV_MASK) >> CFG1_FRAC_DIV_SHIFT;
  134         divfi = (cfg1 & CFG1_INT_DIV_MASK) >> CFG1_INT_DIV_SHIFT;
  135 
  136         /* PLL is bypassed */
  137         if (cfg0 & CFG0_BYPASS)
  138                 return (0);
  139 
  140         divf_val = 1 + divfi + (divff/0x1000000);
  141         *freq = *freq * 8 * divf_val / div;
  142 
  143         return (0);
  144 }
  145 
  146 static clknode_method_t imx_clk_frac_pll_clknode_methods[] = {
  147         /* Device interface */
  148         CLKNODEMETHOD(clknode_init,             imx_clk_frac_pll_init),
  149         CLKNODEMETHOD(clknode_set_gate,         imx_clk_frac_pll_set_gate),
  150         CLKNODEMETHOD(clknode_recalc_freq,      imx_clk_frac_pll_recalc),
  151         CLKNODEMETHOD_END
  152 };
  153 
  154 DEFINE_CLASS_1(imx_clk_frac_pll_clknode, imx_clk_frac_pll_clknode_class,
  155     imx_clk_frac_pll_clknode_methods, sizeof(struct imx_clk_frac_pll_sc),
  156     clknode_class);
  157 
  158 int
  159 imx_clk_frac_pll_register(struct clkdom *clkdom,
  160     struct imx_clk_frac_pll_def *clkdef)
  161 {
  162         struct clknode *clk;
  163         struct imx_clk_frac_pll_sc *sc;
  164 
  165         clk = clknode_create(clkdom, &imx_clk_frac_pll_clknode_class,
  166             &clkdef->clkdef);
  167         if (clk == NULL)
  168                 return (1);
  169 
  170         sc = clknode_get_softc(clk);
  171 
  172         sc->offset = clkdef->offset;
  173 
  174         clknode_register(clkdom, clk);
  175 
  176         return (0);
  177 }

Cache object: 36bba440bd50fb05c8cd8bb33dd56608


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