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/imx8mq_ccm.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 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 /*
   32  * Clocks driver for Freescale i.MX8MQ SoC
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/kernel.h>
   38 #include <sys/module.h>
   39 #include <sys/mutex.h>
   40 #include <sys/bus.h>
   41 #include <sys/rman.h>
   42 
   43 #include <dev/ofw/ofw_bus.h>
   44 #include <dev/ofw/ofw_bus_subr.h>
   45 
   46 #include <machine/bus.h>
   47 
   48 #include <arm64/freescale/imx/imx_ccm_clk.h>
   49 #include <arm64/freescale/imx/imx8mq_ccm.h>
   50 #include <arm64/freescale/imx/clk/imx_clk_gate.h>
   51 #include <arm64/freescale/imx/clk/imx_clk_mux.h>
   52 #include <arm64/freescale/imx/clk/imx_clk_composite.h>
   53 #include <arm64/freescale/imx/clk/imx_clk_sscg_pll.h>
   54 #include <arm64/freescale/imx/clk/imx_clk_frac_pll.h>
   55 
   56 #include "clkdev_if.h"
   57 
   58 static const char *pll_ref_p[] = {
   59         "osc_25m", "osc_27m", "dummy", "dummy"
   60 };
   61 static const char *sys3_pll_out_p[] = {
   62         "sys3_pll1_ref_sel"
   63 };
   64 static const char * arm_pll_bypass_p[] = {
   65         "arm_pll", "arm_pll_ref_sel"
   66 };
   67 static const char * gpu_pll_bypass_p[] = {
   68         "gpu_pll", "gpu_pll_ref_sel"
   69 };
   70 static const char * vpu_pll_bypass_p[] = {
   71         "vpu_pll", "vpu_pll_ref_sel"
   72 };
   73 static const char * audio_pll1_bypass_p[] = {
   74         "audio_pll1", "audio_pll1_ref_sel"
   75 };
   76 static const char * audio_pll2_bypass_p[] = {
   77         "audio_pll2", "audio_pll2_ref_sel"
   78 };
   79 static const char * video_pll1_bypass_p[] = {
   80         "video_pll1", "video_pll1_ref_sel"
   81 };
   82 static const char *uart_p[] = {
   83         "osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m", "sys3_pll_out",
   84         "clk_ext2", "clk_ext4", "audio_pll2_out"
   85 };
   86 static const char *usdhc_p[] = {
   87         "osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m", "audio_pll2_out",
   88         "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m"
   89 };
   90 static const char *enet_axi_p[] = {
   91         "osc_25m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_250m", "sys2_pll_200m",
   92         "audio_pll1_out", "video_pll1_out", "sys3_pll_out"
   93 };
   94 static const char *enet_ref_p[] = {
   95         "osc_25m", "sys2_pll_125m", "sys2_pll_500m", "sys2_pll_100m", "sys1_pll_160m",
   96         "audio_pll1_out", "video_pll1_out", "clk_ext4"
   97 };
   98 static const char *enet_timer_p[] = {
   99         "osc_25m", "sys2_pll_100m", "audio_pll1_out", "clk_ext1", "clk_ext2", "clk_ext3",
  100         "clk_ext4", "video_pll1_out"
  101 };
  102 static const char *enet_phy_ref_p[] = {
  103         "osc_25m", "sys2_pll_50m", "sys2_pll_125m", "sys2_pll_500m", "audio_pll1_out",
  104         "video_pll1_out", "audio_pll2_out"
  105 };
  106 static const char *usb_bus_p[] = {
  107         "osc_25m", "sys2_pll_500m", "sys1_pll_800m", "sys2_pll_100m", "sys2_pll_200m",
  108         "clk_ext2", "clk_ext4", "audio_pll2_out"
  109 };
  110 static const char *usb_core_phy_p[] = {
  111         "osc_25m", "sys1_pll_100m", "sys1_pll_40m", "sys2_pll_100m", "sys2_pll_200m",
  112         "clk_ext2", "clk_ext3", "audio_pll2_out"
  113 };
  114 static const char *i2c_p[] = {
  115         "osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll_out", "audio_pll1_out",
  116         "video_pll1_out", "audio_pll2_out", "sys1_pll_133m"
  117 };
  118 static const char *ahb_p[] = {
  119         "osc_25m", "sys1_pll_133m", "sys1_pll_800m", "sys1_pll_400m", "sys2_pll_125m",
  120         "sys3_pll_out", "audio_pll1_out", "video_pll1_out"
  121 };
  122 
  123 static struct imx_clk imx_clks[] = {
  124         FIXED(IMX8MQ_CLK_DUMMY, "dummy", 0),
  125 
  126         LINK(IMX8MQ_CLK_32K, "ckil"),
  127         LINK(IMX8MQ_CLK_25M, "osc_25m"),
  128         LINK(IMX8MQ_CLK_27M, "osc_27m"),
  129         LINK(IMX8MQ_CLK_EXT1, "clk_ext1"),
  130         LINK(IMX8MQ_CLK_EXT2, "clk_ext2"),
  131         LINK(IMX8MQ_CLK_EXT3, "clk_ext3"),
  132         LINK(IMX8MQ_CLK_EXT4, "clk_ext4"),
  133 
  134         FIXED(IMX8MQ_SYS1_PLL_OUT, "sys1_pll_out", 800000000),
  135         FIXED(IMX8MQ_SYS2_PLL_OUT, "sys2_pll_out", 1000000000),
  136         SSCG_PLL(IMX8MQ_SYS3_PLL_OUT, "sys3_pll_out", sys3_pll_out_p, 0x48),
  137 
  138         MUX(IMX8MQ_ARM_PLL_REF_SEL, "arm_pll_ref_sel", pll_ref_p, 0, 0x28, 16, 2),
  139         MUX(IMX8MQ_GPU_PLL_REF_SEL, "gpu_pll_ref_sel", pll_ref_p, 0, 0x18, 16, 2),
  140         MUX(IMX8MQ_VPU_PLL_REF_SEL, "vpu_pll_ref_sel", pll_ref_p, 0, 0x20, 16, 2),
  141         MUX(IMX8MQ_AUDIO_PLL1_REF_SEL, "audio_pll1_ref_sel", pll_ref_p, 0, 0x0, 16, 2),
  142         MUX(IMX8MQ_AUDIO_PLL2_REF_SEL, "audio_pll2_ref_sel", pll_ref_p, 0, 0x8, 16, 2),
  143         MUX(IMX8MQ_VIDEO_PLL1_REF_SEL, "video_pll1_ref_sel", pll_ref_p, 0, 0x10, 16, 2),
  144         MUX(IMX8MQ_SYS3_PLL1_REF_SEL, "sys3_pll1_ref_sel", pll_ref_p, 0, 0x48, 0, 2),
  145         MUX(IMX8MQ_DRAM_PLL1_REF_SEL, "dram_pll1_ref_sel", pll_ref_p, 0, 0x60, 0, 2),
  146         MUX(IMX8MQ_VIDEO2_PLL1_REF_SEL, "video2_pll1_ref_sel", pll_ref_p, 0, 0x54, 0, 2),
  147 
  148         DIV(IMX8MQ_ARM_PLL_REF_DIV, "arm_pll_ref_div", "arm_pll_ref_sel", 0x28, 5, 6),
  149         DIV(IMX8MQ_GPU_PLL_REF_DIV, "gpu_pll_ref_div", "gpu_pll_ref_sel", 0x18, 5, 6),
  150         DIV(IMX8MQ_VPU_PLL_REF_DIV, "vpu_pll_ref_div", "vpu_pll_ref_sel", 0x20, 5, 6),
  151         DIV(IMX8MQ_AUDIO_PLL1_REF_DIV, "audio_pll1_ref_div", "audio_pll1_ref_sel", 0x0, 5, 6),
  152         DIV(IMX8MQ_AUDIO_PLL2_REF_DIV, "audio_pll2_ref_div", "audio_pll2_ref_sel", 0x8, 5, 6),
  153         DIV(IMX8MQ_VIDEO_PLL1_REF_DIV, "video_pll1_ref_div", "video_pll1_ref_sel", 0x10, 5, 6),
  154 
  155         FRAC_PLL(IMX8MQ_ARM_PLL, "arm_pll", "arm_pll_ref_div", 0x28),
  156         FRAC_PLL(IMX8MQ_GPU_PLL, "gpu_pll", "gpu_pll_ref_div", 0x18),
  157         FRAC_PLL(IMX8MQ_VPU_PLL, "vpu_pll", "vpu_pll_ref_div", 0x20),
  158         FRAC_PLL(IMX8MQ_AUDIO_PLL1, "audio_pll1", "audio_pll1_ref_div", 0x0),
  159         FRAC_PLL(IMX8MQ_AUDIO_PLL2, "audio_pll2", "audio_pll2_ref_div", 0x8),
  160         FRAC_PLL(IMX8MQ_VIDEO_PLL1, "video_pll1", "video_pll1_ref_div", 0x10),
  161 
  162         /* ARM_PLL needs SET_PARENT flag */
  163         MUX(IMX8MQ_ARM_PLL_BYPASS, "arm_pll_bypass", arm_pll_bypass_p, 0, 0x28, 14, 1),
  164         MUX(IMX8MQ_GPU_PLL_BYPASS, "gpu_pll_bypass", gpu_pll_bypass_p, 0, 0x18, 14, 1),
  165         MUX(IMX8MQ_VPU_PLL_BYPASS, "vpu_pll_bypass", vpu_pll_bypass_p, 0, 0x20, 14, 1),
  166         MUX(IMX8MQ_AUDIO_PLL1_BYPASS, "audio_pll1_bypass", audio_pll1_bypass_p, 0, 0x0, 14, 1),
  167         MUX(IMX8MQ_AUDIO_PLL2_BYPASS, "audio_pll2_bypass", audio_pll2_bypass_p, 0, 0x8, 14, 1),
  168         MUX(IMX8MQ_VIDEO_PLL1_BYPASS, "video_pll1_bypass", video_pll1_bypass_p, 0, 0x10, 14, 1),
  169 
  170         GATE(IMX8MQ_ARM_PLL_OUT, "arm_pll_out", "arm_pll_bypass", 0x28, 21),
  171         GATE(IMX8MQ_GPU_PLL_OUT, "gpu_pll_out", "gpu_pll_bypass", 0x18, 21),
  172         GATE(IMX8MQ_VPU_PLL_OUT, "vpu_pll_out", "vpu_pll_bypass", 0x20, 21),
  173         GATE(IMX8MQ_AUDIO_PLL1_OUT, "audio_pll1_out", "audio_pll1_bypass", 0x0, 21),
  174         GATE(IMX8MQ_AUDIO_PLL2_OUT, "audio_pll2_out", "audio_pll2_bypass", 0x8, 21),
  175         GATE(IMX8MQ_VIDEO_PLL1_OUT, "video_pll1_out", "video_pll1_bypass", 0x10, 21),
  176 
  177         GATE(IMX8MQ_SYS1_PLL_40M_CG, "sys1_pll_40m_cg", "sys1_pll_out", 0x30, 9),
  178         GATE(IMX8MQ_SYS1_PLL_80M_CG, "sys1_pll_80m_cg", "sys1_pll_out", 0x30, 11),
  179         GATE(IMX8MQ_SYS1_PLL_100M_CG, "sys1_pll_100m_cg", "sys1_pll_out", 0x30, 13),
  180         GATE(IMX8MQ_SYS1_PLL_133M_CG, "sys1_pll_133m_cg", "sys1_pll_out", 0x30, 15),
  181         GATE(IMX8MQ_SYS1_PLL_160M_CG, "sys1_pll_160m_cg", "sys1_pll_out", 0x30, 17),
  182         GATE(IMX8MQ_SYS1_PLL_200M_CG, "sys1_pll_200m_cg", "sys1_pll_out", 0x30, 19),
  183         GATE(IMX8MQ_SYS1_PLL_266M_CG, "sys1_pll_266m_cg", "sys1_pll_out", 0x30, 21),
  184         GATE(IMX8MQ_SYS1_PLL_400M_CG, "sys1_pll_400m_cg", "sys1_pll_out", 0x30, 23),
  185         GATE(IMX8MQ_SYS1_PLL_800M_CG, "sys1_pll_800m_cg", "sys1_pll_out", 0x30, 25),
  186 
  187         FFACT(IMX8MQ_SYS1_PLL_40M, "sys1_pll_40m", "sys1_pll_40m_cg", 1, 20),
  188         FFACT(IMX8MQ_SYS1_PLL_80M, "sys1_pll_80m", "sys1_pll_80m_cg", 1, 10),
  189         FFACT(IMX8MQ_SYS1_PLL_100M, "sys1_pll_100m", "sys1_pll_100m_cg", 1, 8),
  190         FFACT(IMX8MQ_SYS1_PLL_133M, "sys1_pll_133m", "sys1_pll_133m_cg", 1, 6),
  191         FFACT(IMX8MQ_SYS1_PLL_160M, "sys1_pll_160m", "sys1_pll_160m_cg", 1, 5),
  192         FFACT(IMX8MQ_SYS1_PLL_200M, "sys1_pll_200m", "sys1_pll_200m_cg", 1, 4),
  193         FFACT(IMX8MQ_SYS1_PLL_266M, "sys1_pll_266m", "sys1_pll_266m_cg", 1, 3),
  194         FFACT(IMX8MQ_SYS1_PLL_400M, "sys1_pll_400m", "sys1_pll_400m_cg", 1, 2),
  195         FFACT(IMX8MQ_SYS1_PLL_800M, "sys1_pll_800m", "sys1_pll_800m_cg", 1, 1),
  196 
  197         GATE(IMX8MQ_SYS2_PLL_50M_CG, "sys2_pll_50m_cg", "sys2_pll_out", 0x3c, 9),
  198         GATE(IMX8MQ_SYS2_PLL_100M_CG, "sys2_pll_100m_cg", "sys2_pll_out", 0x3c, 11),
  199         GATE(IMX8MQ_SYS2_PLL_125M_CG, "sys2_pll_125m_cg", "sys2_pll_out", 0x3c, 13),
  200         GATE(IMX8MQ_SYS2_PLL_166M_CG, "sys2_pll_166m_cg", "sys2_pll_out", 0x3c, 15),
  201         GATE(IMX8MQ_SYS2_PLL_200M_CG, "sys2_pll_200m_cg", "sys2_pll_out", 0x3c, 17),
  202         GATE(IMX8MQ_SYS2_PLL_250M_CG, "sys2_pll_250m_cg", "sys2_pll_out", 0x3c, 19),
  203         GATE(IMX8MQ_SYS2_PLL_333M_CG, "sys2_pll_333m_cg", "sys2_pll_out", 0x3c, 21),
  204         GATE(IMX8MQ_SYS2_PLL_500M_CG, "sys2_pll_500m_cg", "sys2_pll_out", 0x3c, 23),
  205         GATE(IMX8MQ_SYS2_PLL_1000M_CG, "sys2_pll_1000m_cg", "sys2_pll_out", 0x3c, 25),
  206 
  207         FFACT(IMX8MQ_SYS2_PLL_50M, "sys2_pll_50m", "sys2_pll_50m_cg", 1, 20),
  208         FFACT(IMX8MQ_SYS2_PLL_100M, "sys2_pll_100m", "sys2_pll_100m_cg", 1, 10),
  209         FFACT(IMX8MQ_SYS2_PLL_125M, "sys2_pll_125m", "sys2_pll_125m_cg", 1, 8),
  210         FFACT(IMX8MQ_SYS2_PLL_166M, "sys2_pll_166m", "sys2_pll_166m_cg", 1, 6),
  211         FFACT(IMX8MQ_SYS2_PLL_200M, "sys2_pll_200m", "sys2_pll_200m_cg", 1, 5),
  212         FFACT(IMX8MQ_SYS2_PLL_250M, "sys2_pll_250m", "sys2_pll_250m_cg", 1, 4),
  213         FFACT(IMX8MQ_SYS2_PLL_333M, "sys2_pll_333m", "sys2_pll_333m_cg", 1, 3),
  214         FFACT(IMX8MQ_SYS2_PLL_500M, "sys2_pll_500m", "sys2_pll_500m_cg", 1, 2),
  215         FFACT(IMX8MQ_SYS2_PLL_1000M, "sys2_pll_1000m", "sys2_pll_1000m_cg", 1, 1),
  216 
  217         COMPOSITE(IMX8MQ_CLK_AHB, "ahb", ahb_p, 0x9000, 0),
  218         DIV(IMX8MQ_CLK_IPG_ROOT, "ipg_root", "ahb", 0x9080, 0, 1),
  219 
  220         COMPOSITE(IMX8MQ_CLK_UART1, "uart1", uart_p, 0xaf00, 0),
  221         COMPOSITE(IMX8MQ_CLK_UART2, "uart2", uart_p, 0xaf80, 0),
  222         COMPOSITE(IMX8MQ_CLK_UART3, "uart3", uart_p, 0xb000, 0),
  223         COMPOSITE(IMX8MQ_CLK_UART4, "uart4", uart_p, 0xb080, 0),
  224 
  225         ROOT_GATE(IMX8MQ_CLK_UART1_ROOT, "uart1_root_clk", "uart1", 0x4490),
  226         ROOT_GATE(IMX8MQ_CLK_UART2_ROOT, "uart2_root_clk", "uart2", 0x44a0),
  227         ROOT_GATE(IMX8MQ_CLK_UART3_ROOT, "uart3_root_clk", "uart3", 0x44b0),
  228         ROOT_GATE(IMX8MQ_CLK_UART4_ROOT, "uart4_root_clk", "uart4", 0x44c0),
  229 
  230         COMPOSITE(IMX8MQ_CLK_USDHC1, "usdhc1", usdhc_p, 0xac00, CLK_SET_ROUND_DOWN),
  231         COMPOSITE(IMX8MQ_CLK_USDHC2, "usdhc2", usdhc_p, 0xac80, CLK_SET_ROUND_DOWN),
  232 
  233         ROOT_GATE(IMX8MQ_CLK_USDHC1_ROOT, "usdhc1_root_clk", "usdhc1", 0x4510),
  234         ROOT_GATE(IMX8MQ_CLK_USDHC2_ROOT, "usdhc2_root_clk", "usdhc2", 0x4520),
  235 
  236         ROOT_GATE(IMX8MQ_CLK_TMU_ROOT, "tmu_root_clk", "ipg_root", 0x4620),
  237 
  238         COMPOSITE(IMX8MQ_CLK_ENET_AXI, "enet_axi", enet_axi_p, 0x8800, 0),
  239         COMPOSITE(IMX8MQ_CLK_ENET_REF, "enet_ref", enet_ref_p, 0xa980, 0),
  240         COMPOSITE(IMX8MQ_CLK_ENET_TIMER, "enet_timer", enet_timer_p, 0xaa00, 0),
  241         COMPOSITE(IMX8MQ_CLK_ENET_PHY_REF, "enet_phy_ref", enet_phy_ref_p, 0xaa80, 0),
  242 
  243         ROOT_GATE(IMX8MQ_CLK_ENET1_ROOT, "enet1_root_clk", "enet_axi", 0x40a0),
  244 
  245         COMPOSITE(IMX8MQ_CLK_USB_BUS, "usb_bus", usb_bus_p, 0x8b80, 0),
  246         COMPOSITE(IMX8MQ_CLK_USB_CORE_REF, "usb_core_ref", usb_core_phy_p, 0xb100, 0),
  247         COMPOSITE(IMX8MQ_CLK_USB_PHY_REF, "usb_phy_ref", usb_core_phy_p, 0xb180, 0),
  248 
  249         ROOT_GATE(IMX8MQ_CLK_USB1_CTRL_ROOT, "usb1_ctrl_root_clk", "usb_bus", 0x44d0),
  250         ROOT_GATE(IMX8MQ_CLK_USB2_CTRL_ROOT, "usb2_ctrl_root_clk", "usb_bus", 0x44e0),
  251         ROOT_GATE(IMX8MQ_CLK_USB1_PHY_ROOT, "usb1_phy_root_clk", "usb_phy_ref", 0x44f0),
  252         ROOT_GATE(IMX8MQ_CLK_USB2_PHY_ROOT, "usb2_phy_root_clk", "usb_phy_ref", 0x4500),
  253 
  254         COMPOSITE(IMX8MQ_CLK_I2C1, "i2c1", i2c_p, 0xad00, 0),
  255         COMPOSITE(IMX8MQ_CLK_I2C2, "i2c2", i2c_p, 0xad80, 0),
  256         COMPOSITE(IMX8MQ_CLK_I2C3, "i2c3", i2c_p, 0xae00, 0),
  257         COMPOSITE(IMX8MQ_CLK_I2C4, "i2c4", i2c_p, 0xae80, 0),
  258 
  259         ROOT_GATE(IMX8MQ_CLK_I2C1_ROOT, "i2c1_root_clk", "i2c1", 0x4170),
  260         ROOT_GATE(IMX8MQ_CLK_I2C2_ROOT, "i2c2_root_clk", "i2c2", 0x4180),
  261         ROOT_GATE(IMX8MQ_CLK_I2C3_ROOT, "i2c3_root_clk", "i2c3", 0x4190),
  262         ROOT_GATE(IMX8MQ_CLK_I2C4_ROOT, "i2c4_root_clk", "i2c4", 0x41a0),
  263 
  264         ROOT_GATE(IMX8MQ_CLK_GPIO1_ROOT, "gpio1_root_clk", "ipg_root", 0x40b0),
  265         ROOT_GATE(IMX8MQ_CLK_GPIO2_ROOT, "gpio2_root_clk", "ipg_root", 0x40c0),
  266         ROOT_GATE(IMX8MQ_CLK_GPIO3_ROOT, "gpio3_root_clk", "ipg_root", 0x40d0),
  267         ROOT_GATE(IMX8MQ_CLK_GPIO4_ROOT, "gpio4_root_clk", "ipg_root", 0x40e0),
  268         ROOT_GATE(IMX8MQ_CLK_GPIO5_ROOT, "gpio5_root_clk", "ipg_root", 0x40f0),
  269 };
  270 
  271 struct ccm_softc {
  272         device_t                dev;
  273         struct resource         *mem_res;
  274         struct clkdom           *clkdom;
  275         struct mtx              mtx;
  276         struct imx_clk          *clks;
  277         int                     nclks;
  278 };
  279 
  280 static inline uint32_t
  281 CCU_READ4(struct ccm_softc *sc, bus_size_t off)
  282 {
  283 
  284         return (bus_read_4(sc->mem_res, off));
  285 }
  286 
  287 static inline void
  288 CCU_WRITE4(struct ccm_softc *sc, bus_size_t off, uint32_t val)
  289 {
  290 
  291         bus_write_4(sc->mem_res, off, val);
  292 }
  293 
  294 static int
  295 ccm_detach(device_t dev)
  296 {
  297         struct ccm_softc *sc;
  298 
  299         sc = device_get_softc(dev);
  300 
  301         if (sc->mem_res != NULL)
  302                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
  303 
  304         return (0);
  305 }
  306 
  307 static int
  308 ccm_attach(device_t dev)
  309 {
  310         struct ccm_softc *sc;
  311         int err, rid;
  312         phandle_t node;
  313         int i;
  314 
  315         sc = device_get_softc(dev);
  316         err = 0;
  317 
  318         /* Allocate bus_space resources. */
  319         rid = 0;
  320         sc->clks = imx_clks;
  321         sc->nclks = nitems(imx_clks);
  322         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  323             RF_ACTIVE);
  324         if (sc->mem_res == NULL) {
  325                 device_printf(dev, "Cannot allocate memory resources\n");
  326                 err = ENXIO;
  327                 goto out;
  328         }
  329 
  330         mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
  331 
  332         sc->clkdom = clkdom_create(dev);
  333         if (sc->clkdom == NULL)
  334                 panic("Cannot create clkdom\n");
  335 
  336         for (i = 0; i < sc->nclks; i++) {
  337                 switch (sc->clks[i].type) {
  338                 case IMX_CLK_UNDEFINED:
  339                         break;
  340                 case IMX_CLK_LINK:
  341                         clknode_link_register(sc->clkdom,
  342                             sc->clks[i].clk.link);
  343                         break;
  344                 case IMX_CLK_FIXED:
  345                         clknode_fixed_register(sc->clkdom,
  346                             sc->clks[i].clk.fixed);
  347                         break;
  348                 case IMX_CLK_MUX:
  349                         imx_clk_mux_register(sc->clkdom, sc->clks[i].clk.mux);
  350                         break;
  351                 case IMX_CLK_GATE:
  352                         imx_clk_gate_register(sc->clkdom, sc->clks[i].clk.gate);
  353                         break;
  354                 case IMX_CLK_COMPOSITE:
  355                         imx_clk_composite_register(sc->clkdom, sc->clks[i].clk.composite);
  356                         break;
  357                 case IMX_CLK_SSCG_PLL:
  358                         imx_clk_sscg_pll_register(sc->clkdom, sc->clks[i].clk.sscg_pll);
  359                         break;
  360                 case IMX_CLK_FRAC_PLL:
  361                         imx_clk_frac_pll_register(sc->clkdom, sc->clks[i].clk.frac_pll);
  362                         break;
  363                 case IMX_CLK_DIV:
  364                         clknode_div_register(sc->clkdom, sc->clks[i].clk.div);
  365                         break;
  366                 default:
  367                         device_printf(dev, "Unknown clock type %d\n", sc->clks[i].type);
  368                         return (ENXIO);
  369                 }
  370         }
  371 
  372         if (clkdom_finit(sc->clkdom) != 0)
  373                 panic("cannot finalize clkdom initialization\n");
  374 
  375         if (bootverbose)
  376                 clkdom_dump(sc->clkdom);
  377 
  378         node = ofw_bus_get_node(dev);
  379         clk_set_assigned(dev, node);
  380 
  381         err = 0;
  382 
  383 out:
  384 
  385         if (err != 0)
  386                 ccm_detach(dev);
  387 
  388         return (err);
  389 }
  390 
  391 static int
  392 ccm_probe(device_t dev)
  393 {
  394 
  395         if (!ofw_bus_status_okay(dev))
  396                 return (ENXIO);
  397 
  398         if (ofw_bus_is_compatible(dev, "fsl,imx8mq-ccm") == 0)
  399                 return (ENXIO);
  400 
  401         device_set_desc(dev, "Freescale i.MX8 Clock Control Module");
  402 
  403         return (BUS_PROBE_DEFAULT);
  404 }
  405 
  406 static int
  407 imx_ccm_write_4(device_t dev, bus_addr_t addr, uint32_t val)
  408 {
  409         struct ccm_softc *sc;
  410 
  411         sc = device_get_softc(dev);
  412         CCU_WRITE4(sc, addr, val);
  413         return (0);
  414 }
  415 
  416 static int
  417 imx_ccm_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
  418 {
  419         struct ccm_softc *sc;
  420 
  421         sc = device_get_softc(dev);
  422 
  423         *val = CCU_READ4(sc, addr);
  424         return (0);
  425 }
  426 
  427 static int
  428 imx_ccm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set)
  429 {
  430         struct ccm_softc *sc;
  431         uint32_t reg;
  432 
  433         sc = device_get_softc(dev);
  434 
  435         reg = CCU_READ4(sc, addr);
  436         reg &= ~clr;
  437         reg |= set;
  438         CCU_WRITE4(sc, addr, reg);
  439 
  440         return (0);
  441 }
  442 
  443 static void
  444 imx_ccm_device_lock(device_t dev)
  445 {
  446         struct ccm_softc *sc;
  447 
  448         sc = device_get_softc(dev);
  449         mtx_lock(&sc->mtx);
  450 }
  451 
  452 static void
  453 imx_ccm_device_unlock(device_t dev)
  454 {
  455         struct ccm_softc *sc;
  456 
  457         sc = device_get_softc(dev);
  458         mtx_unlock(&sc->mtx);
  459 }
  460 
  461 static device_method_t ccm_methods[] = {
  462         /* Device interface */
  463         DEVMETHOD(device_probe,  ccm_probe),
  464         DEVMETHOD(device_attach, ccm_attach),
  465         DEVMETHOD(device_detach, ccm_detach),
  466 
  467         /* clkdev interface */
  468         DEVMETHOD(clkdev_write_4,       imx_ccm_write_4),
  469         DEVMETHOD(clkdev_read_4,        imx_ccm_read_4),
  470         DEVMETHOD(clkdev_modify_4,      imx_ccm_modify_4),
  471         DEVMETHOD(clkdev_device_lock,   imx_ccm_device_lock),
  472         DEVMETHOD(clkdev_device_unlock, imx_ccm_device_unlock),
  473 
  474         DEVMETHOD_END
  475 };
  476 
  477 static driver_t ccm_driver = {
  478         "ccm",
  479         ccm_methods,
  480         sizeof(struct ccm_softc)
  481 };
  482 
  483 EARLY_DRIVER_MODULE(ccm, simplebus, ccm_driver, 0, 0, 
  484     BUS_PASS_CPU + BUS_PASS_ORDER_EARLY);

Cache object: c5cda443cd4f4af5f4123b0f218a6e3f


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