Home | History | Annotate | Line # | Download | only in nxp
imx6_ccm.c revision 1.2
      1 /*	$NetBSD: imx6_ccm.c,v 1.2 2022/09/27 06:36:42 skrll Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2010-2012, 2014  Genetec Corporation.  All rights reserved.
      5  * Written by Hashimoto Kenichi for Genetec Corporation.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 /*
     29  * Clock Controller Module (CCM) for i.MX6
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: imx6_ccm.c,v 1.2 2022/09/27 06:36:42 skrll Exp $");
     34 
     35 #include "opt_imx.h"
     36 #include "opt_cputypes.h"
     37 
     38 #include "locators.h"
     39 
     40 #include <sys/types.h>
     41 #include <sys/time.h>
     42 #include <sys/bus.h>
     43 #include <sys/device.h>
     44 #include <sys/sysctl.h>
     45 #include <sys/cpufreq.h>
     46 #include <sys/param.h>
     47 
     48 #include <machine/cpu.h>
     49 
     50 #include <arm/nxp/imx6_ccmvar.h>
     51 #include <arm/nxp/imx6_ccmreg.h>
     52 
     53 #include <dev/clk/clk_backend.h>
     54 
     55 /* Clock Parents Tables */
     56 static const char *step_p[] = {
     57 	"osc",
     58 	"pll2_pfd2_396m"
     59 };
     60 
     61 static const char *pll1_sw_p[] = {
     62 	"pll1_sys",
     63 	"step"
     64 };
     65 
     66 static const char *periph_pre_p[] = {
     67 	"pll2_bus",
     68 	"pll2_pfd2_396m",
     69 	"pll2_pfd0_352m",
     70 	"pll2_198m"
     71 };
     72 
     73 static const char *periph_clk2_p[] = {
     74 	"pll3_usb_otg",
     75 	"osc",
     76 	"osc",
     77 	"dummy"
     78 };
     79 
     80 static const char *periph2_clk2_p[] = {
     81 	"pll3_usb_otg",
     82 	"pll2_bus"
     83 };
     84 
     85 static const char *axi_p[] = {
     86 	"periph",
     87 	"pll2_pfd2_396m",
     88 	"periph",
     89 	"pll3_pfd1_540m"
     90 };
     91 
     92 static const char *audio_p[] = {
     93 	"pll4_audio_div",
     94 	"pll3_pfd2_508m",
     95 	"pll3_pfd3_454m",
     96 	"pll3_usb_otg"
     97 };
     98 
     99 static const char *gpu2d_core_p[] = {
    100 	"axi",
    101 	"pll3_usb_otg",
    102 	"pll2_pfd0_352m",
    103 	"pll2_pfd2_396m"
    104 };
    105 
    106 static const char *gpu3d_core_p[] = {
    107 	"mmdc_ch0_axi",
    108 	"pll3_usb_otg",
    109 	"pll2_pfd1_594m",
    110 	"pll2_pfd2_396m"
    111 };
    112 
    113 static const char *gpu3d_shader_p[] = {
    114 	"mmdc_ch0_axi",
    115 	"pll3_usb_otg",
    116 	"pll2_pfd1_594m",
    117 	"pll3_pfd0_720m"
    118 };
    119 
    120 static const char *ipu_p[] = {
    121 	"mmdc_ch0_axi",
    122 	"pll2_pfd2_396m",
    123 	"pll3_120m",
    124 	"pll3_pfd1_540m"
    125 };
    126 
    127 static const char *pll_bypass_src_p[] = {
    128 	"osc",
    129 	"lvds1_in",
    130 	"lvds2_in",
    131 	"dummy"
    132 };
    133 
    134 static const char *pll1_bypass_p[] = {
    135 	"pll1",
    136 	"pll1_bypass_src"
    137 };
    138 
    139 static const char *pll2_bypass_p[] = {
    140 	"pll2",
    141 	"pll2_bypass_src"
    142 };
    143 
    144 static const char *pll3_bypass_p[] = {
    145 	"pll3",
    146 	"pll3_bypass_src"
    147 };
    148 
    149 static const char *pll4_bypass_p[] = {
    150 	"pll4",
    151 	"pll4_bypass_src"
    152 };
    153 
    154 static const char *pll5_bypass_p[] = {
    155 	"pll5",
    156 	"pll5_bypass_src"
    157 };
    158 
    159 static const char *pll6_bypass_p[] = {
    160 	"pll6",
    161 	"pll6_bypass_src"
    162 };
    163 
    164 static const char *pll7_bypass_p[] = {
    165 	"pll7",
    166 	"pll7_bypass_src"
    167 };
    168 
    169 static const char *ipu_di_pre_p[] = {
    170 	"mmdc_ch0_axi",
    171 	"pll3_usb_otg",
    172 	"pll5_video_div",
    173 	"pll2_pfd0_352m",
    174 	"pll2_pfd2_396m",
    175 	"pll3_pfd1_540m"
    176 };
    177 
    178 static const char *ipu1_di0_p[] = {
    179 	"ipu1_di0_pre",
    180 	"dummy",
    181 	"dummy",
    182 	"ldb_di0",
    183 	"ldb_di1"
    184 };
    185 
    186 static const char *ipu1_di1_p[] = {
    187 	"ipu1_di1_pre",
    188 	"dummy",
    189 	"dummy",
    190 	"ldb_di0",
    191 	"ldb_di1"
    192 };
    193 
    194 static const char *ipu2_di0_p[] = {
    195 	"ipu2_di0_pre",
    196 	"dummy",
    197 	"dummy",
    198 	"ldb_di0",
    199 	"ldb_di1"
    200 };
    201 
    202 static const char *ipu2_di1_p[] = {
    203 	"ipu2_di1_pre",
    204 	"dummy",
    205 	"dummy",
    206 	"ldb_di0",
    207 	"ldb_di1"
    208 };
    209 
    210 static const char *ldb_di_p[] = {
    211 	"pll5_video_div",
    212 	"pll2_pfd0_352m",
    213 	"pll2_pfd2_396m",
    214 	"mmdc_ch1_axi",
    215 	"pll3_usb_otg"
    216 };
    217 
    218 static const char *periph_p[] = {
    219 	"periph_pre",
    220 	"periph_clk2"
    221 };
    222 
    223 static const char *periph2_p[] = {
    224 	"periph2_pre",
    225 	"periph2_clk2"
    226 };
    227 
    228 static const char *vdo_axi_p[] = {
    229 	"axi",
    230 	"ahb"
    231 };
    232 
    233 static const char *vpu_axi_p[] = {
    234 	"axi",
    235 	"pll2_pfd2_396m",
    236 	"pll2_pfd0_352m"
    237 };
    238 
    239 static const char *cko1_p[] = {
    240 	"pll3_usb_otg",
    241 	"pll2_bus",
    242 	"pll1_sys",
    243 	"pll5_video_div",
    244 	"dummy",
    245 	"axi",
    246 	"enfc",
    247 	"ipu1_di0",
    248 	"ipu1_di1",
    249 	"ipu2_di0",
    250 	"ipu2_di1",
    251 	"ahb",
    252 	"ipg",
    253 	"ipg_per",
    254 	"ckil",
    255 	"pll4_audio_div"
    256 };
    257 
    258 static const char *cko2_p[] = {
    259 	"mmdc_ch0_axi",
    260 	"mmdc_ch1_axi",
    261 	"usdhc4",
    262 	"usdhc1",
    263 	"gpu2d_axi",
    264 	"dummy",
    265 	"ecspi_root",
    266 	"gpu3d_axi",
    267 	"usdhc3",
    268 	"dummy",
    269 	"arm",
    270 	"ipu1",
    271 	"ipu2",
    272 	"vdo_axi",
    273 	"osc",
    274 	"gpu2d_core",
    275 	"gpu3d_core",
    276 	"usdhc2",
    277 	"ssi1",
    278 	"ssi2",
    279 	"ssi3",
    280 	"gpu3d_shader",
    281 	"vpu_axi",
    282 	"can_root",
    283 	"ldb_di0",
    284 	"ldb_di1",
    285 	"esai_extal",
    286 	"eim_slow",
    287 	"uart_serial",
    288 	"spdif",
    289 	"asrc",
    290 	"hsi_tx"
    291 };
    292 
    293 static const char *cko_p[] = {
    294 	"cko1",
    295 	"cko2"
    296 };
    297 
    298 static const char *hsi_tx_p[] = {
    299 	"pll3_120m",
    300 	"pll2_pfd2_396m"
    301 };
    302 
    303 static const char *pcie_axi_p[] = {
    304 	"axi",
    305 	"ahb"
    306 };
    307 
    308 static const char *ssi_p[] = {
    309 	"pll3_pfd2_508m",
    310 	"pll3_pfd3_454m",
    311 	"pll4_audio_div"
    312 };
    313 
    314 static const char *usdhc_p[] = {
    315 	"pll2_pfd2_396m",
    316 	"pll2_pfd0_352m"
    317 };
    318 
    319 static const char *eim_p[] = {
    320 	"pll2_pfd2_396m",
    321 	"pll3_usb_otg",
    322 	"axi",
    323 	"pll2_pfd0_352m"
    324 };
    325 
    326 static const char *eim_slow_p[] = {
    327 	"axi",
    328 	"pll3_usb_otg",
    329 	"pll2_pfd2_396m",
    330 	"pll2_pfd0_352m"
    331 };
    332 
    333 static const char *enfc_p[] = {
    334 	"pll2_pfd0_352m",
    335 	"pll2_bus",
    336 	"pll3_usb_otg",
    337 	"pll2_pfd2_396m"
    338 };
    339 
    340 static const char *lvds_p[] = {
    341 	"dummy",
    342 	"dummy",
    343 	"dummy",
    344 	"dummy",
    345 	"dummy",
    346 	"dummy",
    347 	"pll4_audio",
    348 	"pll5_video",
    349 	"pll8_mlb",
    350 	"enet_ref",
    351 	"pcie_ref_125m",
    352 	"sata_ref_100m"
    353 };
    354 
    355 /* DT clock ID to clock name mappings */
    356 static struct imx_clock_id {
    357 	u_int		id;
    358 	const char	*name;
    359 } imx6_clock_ids[] = {
    360 	{ IMX6CLK_DUMMY,		"dummy" },
    361 	{ IMX6CLK_CKIL,			"ckil" },
    362 	{ IMX6CLK_CKIH,			"ckih" },
    363 	{ IMX6CLK_OSC,			"osc" },
    364 	{ IMX6CLK_PLL2_PFD0_352M,	"pll2_pfd0_352m" },
    365 	{ IMX6CLK_PLL2_PFD1_594M,	"pll2_pfd1_594m" },
    366 	{ IMX6CLK_PLL2_PFD2_396M,	"pll2_pfd2_396m" },
    367 	{ IMX6CLK_PLL3_PFD0_720M,	"pll3_pfd0_720m" },
    368 	{ IMX6CLK_PLL3_PFD1_540M,	"pll3_pfd1_540m" },
    369 	{ IMX6CLK_PLL3_PFD2_508M,	"pll3_pfd2_508m" },
    370 	{ IMX6CLK_PLL3_PFD3_454M,	"pll3_pfd3_454m" },
    371 	{ IMX6CLK_PLL2_198M,		"pll2_198m" },
    372 	{ IMX6CLK_PLL3_120M,		"pll3_120m" },
    373 	{ IMX6CLK_PLL3_80M,		"pll3_80m" },
    374 	{ IMX6CLK_PLL3_60M,		"pll3_60m" },
    375 	{ IMX6CLK_TWD,			"twd" },
    376 	{ IMX6CLK_STEP,			"step" },
    377 	{ IMX6CLK_PLL1_SW,		"pll1_sw" },
    378 	{ IMX6CLK_PERIPH_PRE,		"periph_pre" },
    379 	{ IMX6CLK_PERIPH2_PRE,		"periph2_pre" },
    380 	{ IMX6CLK_PERIPH_CLK2_SEL,	"periph_clk2_sel" },
    381 	{ IMX6CLK_PERIPH2_CLK2_SEL,	"periph2_clk2_sel" },
    382 	{ IMX6CLK_AXI_SEL,		"axi_sel" },
    383 	{ IMX6CLK_ESAI_SEL,		"esai_sel" },
    384 	{ IMX6CLK_ASRC_SEL,		"asrc_sel" },
    385 	{ IMX6CLK_SPDIF_SEL,		"spdif_sel" },
    386 	{ IMX6CLK_GPU2D_AXI,		"gpu2d_axi" },
    387 	{ IMX6CLK_GPU3D_AXI,		"gpu3d_axi" },
    388 	{ IMX6CLK_GPU2D_CORE_SEL,	"gpu2d_core_sel" },
    389 	{ IMX6CLK_GPU3D_CORE_SEL,	"gpu3d_core_sel" },
    390 	{ IMX6CLK_GPU3D_SHADER_SEL,	"gpu3d_shader_sel" },
    391 	{ IMX6CLK_IPU1_SEL,		"ipu1_sel" },
    392 	{ IMX6CLK_IPU2_SEL,		"ipu2_sel" },
    393 	{ IMX6CLK_LDB_DI0_SEL,		"ldb_di0_sel" },
    394 	{ IMX6CLK_LDB_DI1_SEL,		"ldb_di1_sel" },
    395 	{ IMX6CLK_IPU1_DI0_PRE_SEL,	"ipu1_di0_pre_sel" },
    396 	{ IMX6CLK_IPU1_DI1_PRE_SEL,	"ipu1_di1_pre_sel" },
    397 	{ IMX6CLK_IPU2_DI0_PRE_SEL,	"ipu2_di0_pre_sel" },
    398 	{ IMX6CLK_IPU2_DI1_PRE_SEL,	"ipu2_di1_pre_sel" },
    399 	{ IMX6CLK_IPU1_DI0_SEL,		"ipu1_di0_sel" },
    400 	{ IMX6CLK_IPU1_DI1_SEL,		"ipu1_di1_sel" },
    401 	{ IMX6CLK_IPU2_DI0_SEL,		"ipu2_di0_sel" },
    402 	{ IMX6CLK_IPU2_DI1_SEL,		"ipu2_di1_sel" },
    403 	{ IMX6CLK_HSI_TX_SEL,		"hsi_tx_sel" },
    404 	{ IMX6CLK_PCIE_AXI_SEL,		"pcie_axi_sel" },
    405 	{ IMX6CLK_SSI1_SEL,		"ssi1_sel" },
    406 	{ IMX6CLK_SSI2_SEL,		"ssi2_sel" },
    407 	{ IMX6CLK_SSI3_SEL,		"ssi3_sel" },
    408 	{ IMX6CLK_USDHC1_SEL,		"usdhc1_sel" },
    409 	{ IMX6CLK_USDHC2_SEL,		"usdhc2_sel" },
    410 	{ IMX6CLK_USDHC3_SEL,		"usdhc3_sel" },
    411 	{ IMX6CLK_USDHC4_SEL,		"usdhc4_sel" },
    412 	{ IMX6CLK_ENFC_SEL,		"enfc_sel" },
    413 	{ IMX6CLK_EIM_SEL,		"eim_sel" },
    414 	{ IMX6CLK_EIM_SLOW_SEL,		"eim_slow_sel" },
    415 	{ IMX6CLK_VDO_AXI_SEL,		"vdo_axi_sel" },
    416 	{ IMX6CLK_VPU_AXI_SEL,		"vpu_axi_sel" },
    417 	{ IMX6CLK_CKO1_SEL,		"cko1_sel" },
    418 	{ IMX6CLK_PERIPH,		"periph" },
    419 	{ IMX6CLK_PERIPH2,		"periph2" },
    420 	{ IMX6CLK_PERIPH_CLK2,		"periph_clk2" },
    421 	{ IMX6CLK_PERIPH2_CLK2,		"periph2_clk2" },
    422 	{ IMX6CLK_IPG,			"ipg" },
    423 	{ IMX6CLK_IPG_PER,		"ipg_per" },
    424 	{ IMX6CLK_ESAI_PRED,		"esai_pred" },
    425 	{ IMX6CLK_ESAI_PODF,		"esai_podf" },
    426 	{ IMX6CLK_ASRC_PRED,		"asrc_pred" },
    427 	{ IMX6CLK_ASRC_PODF,		"asrc_podf" },
    428 	{ IMX6CLK_SPDIF_PRED,		"spdif_pred" },
    429 	{ IMX6CLK_SPDIF_PODF,		"spdif_podf" },
    430 	{ IMX6CLK_CAN_ROOT,		"can_root" },
    431 	{ IMX6CLK_ECSPI_ROOT,		"ecspi_root" },
    432 	{ IMX6CLK_GPU2D_CORE_PODF,	"gpu2d_core_podf" },
    433 	{ IMX6CLK_GPU3D_CORE_PODF,	"gpu3d_core_podf" },
    434 	{ IMX6CLK_GPU3D_SHADER,		"gpu3d_shader" },
    435 	{ IMX6CLK_IPU1_PODF,		"ipu1_podf" },
    436 	{ IMX6CLK_IPU2_PODF,		"ipu2_podf" },
    437 	{ IMX6CLK_LDB_DI0_PODF,		"ldb_di0_podf" },
    438 	{ IMX6CLK_LDB_DI1_PODF,		"ldb_di1_podf" },
    439 	{ IMX6CLK_IPU1_DI0_PRE,		"ipu1_di0_pre" },
    440 	{ IMX6CLK_IPU1_DI1_PRE,		"ipu1_di1_pre" },
    441 	{ IMX6CLK_IPU2_DI0_PRE,		"ipu2_di0_pre" },
    442 	{ IMX6CLK_IPU2_DI1_PRE,		"ipu2_di1_pre" },
    443 	{ IMX6CLK_HSI_TX_PODF,		"hsi_tx_podf" },
    444 	{ IMX6CLK_SSI1_PRED,		"ssi1_pred" },
    445 	{ IMX6CLK_SSI1_PODF,		"ssi1_podf" },
    446 	{ IMX6CLK_SSI2_PRED,		"ssi2_pred" },
    447 	{ IMX6CLK_SSI2_PODF,		"ssi2_podf" },
    448 	{ IMX6CLK_SSI3_PRED,		"ssi3_pred" },
    449 	{ IMX6CLK_SSI3_PODF,		"ssi3_podf" },
    450 	{ IMX6CLK_UART_SERIAL_PODF,	"uart_serial_podf" },
    451 	{ IMX6CLK_USDHC1_PODF,		"usdhc1_podf" },
    452 	{ IMX6CLK_USDHC2_PODF,		"usdhc2_podf" },
    453 	{ IMX6CLK_USDHC3_PODF,		"usdhc3_podf" },
    454 	{ IMX6CLK_USDHC4_PODF,		"usdhc4_podf" },
    455 	{ IMX6CLK_ENFC_PRED,		"enfc_pred" },
    456 	{ IMX6CLK_ENFC_PODF,		"enfc_podf" },
    457 	{ IMX6CLK_EIM_PODF,		"eim_podf" },
    458 	{ IMX6CLK_EIM_SLOW_PODF,	"eim_slow_podf" },
    459 	{ IMX6CLK_VPU_AXI_PODF,		"vpu_axi_podf" },
    460 	{ IMX6CLK_CKO1_PODF,		"cko1_podf" },
    461 	{ IMX6CLK_AXI,			"axi" },
    462 	{ IMX6CLK_MMDC_CH0_AXI_PODF,	"mmdc_ch0_axi_podf" },
    463 	{ IMX6CLK_MMDC_CH1_AXI_PODF,	"mmdc_ch1_axi_podf" },
    464 	{ IMX6CLK_ARM,			"arm" },
    465 	{ IMX6CLK_AHB,			"ahb" },
    466 	{ IMX6CLK_APBH_DMA,		"apbh_dma" },
    467 	{ IMX6CLK_ASRC,			"asrc" },
    468 	{ IMX6CLK_CAN1_IPG,		"can1_ipg" },
    469 	{ IMX6CLK_CAN1_SERIAL,		"can1_serial" },
    470 	{ IMX6CLK_CAN2_IPG,		"can2_ipg" },
    471 	{ IMX6CLK_CAN2_SERIAL,		"can2_serial" },
    472 	{ IMX6CLK_ECSPI1,		"ecspi1" },
    473 	{ IMX6CLK_ECSPI2,		"ecspi2" },
    474 	{ IMX6CLK_ECSPI3,		"ecspi3" },
    475 	{ IMX6CLK_ECSPI4,		"ecspi4" },
    476 	{ IMX6CLK_ECSPI5,		"ecspi5" },
    477 	{ IMX6CLK_ENET,			"enet" },
    478 	{ IMX6CLK_ESAI_EXTAL,		"esai_extal" },
    479 	{ IMX6CLK_GPT_IPG,		"gpt_ipg" },
    480 	{ IMX6CLK_GPT_IPG_PER,		"gpt_ipg_per" },
    481 	{ IMX6CLK_GPU2D_CORE,		"gpu2d_core" },
    482 	{ IMX6CLK_GPU3D_CORE,		"gpu3d_core" },
    483 	{ IMX6CLK_HDMI_IAHB,		"hdmi_iahb" },
    484 	{ IMX6CLK_HDMI_ISFR,		"hdmi_isfr" },
    485 	{ IMX6CLK_I2C1,			"i2c1" },
    486 	{ IMX6CLK_I2C2,			"i2c2" },
    487 	{ IMX6CLK_I2C3,			"i2c3" },
    488 	{ IMX6CLK_IIM,			"iim" },
    489 	{ IMX6CLK_ENFC,			"enfc" },
    490 	{ IMX6CLK_IPU1,			"ipu1" },
    491 	{ IMX6CLK_IPU1_DI0,		"ipu1_di0" },
    492 	{ IMX6CLK_IPU1_DI1,		"ipu1_di1" },
    493 	{ IMX6CLK_IPU2,			"ipu2" },
    494 	{ IMX6CLK_IPU2_DI0,		"ipu2_di0" },
    495 	{ IMX6CLK_LDB_DI0,		"ldb_di0" },
    496 	{ IMX6CLK_LDB_DI1,		"ldb_di1" },
    497 	{ IMX6CLK_IPU2_DI1,		"ipu2_di1" },
    498 	{ IMX6CLK_HSI_TX,		"hsi_tx" },
    499 	{ IMX6CLK_MLB,			"mlb" },
    500 	{ IMX6CLK_MMDC_CH0_AXI,		"mmdc_ch0_axi" },
    501 	{ IMX6CLK_MMDC_CH1_AXI,		"mmdc_ch1_axi" },
    502 	{ IMX6CLK_OCRAM,		"ocram" },
    503 	{ IMX6CLK_OPENVG_AXI,		"openvg_axi" },
    504 	{ IMX6CLK_PCIE_AXI,		"pcie_axi" },
    505 	{ IMX6CLK_PWM1,			"pwm1" },
    506 	{ IMX6CLK_PWM2,			"pwm2" },
    507 	{ IMX6CLK_PWM3,			"pwm3" },
    508 	{ IMX6CLK_PWM4,			"pwm4" },
    509 	{ IMX6CLK_PER1_BCH,		"per1_bch" },
    510 	{ IMX6CLK_GPMI_BCH_APB,		"gpmi_bch_apb" },
    511 	{ IMX6CLK_GPMI_BCH,		"gpmi_bch" },
    512 	{ IMX6CLK_GPMI_IO,		"gpmi_io" },
    513 	{ IMX6CLK_GPMI_APB,		"gpmi_apb" },
    514 	{ IMX6CLK_SATA,			"sata" },
    515 	{ IMX6CLK_SDMA,			"sdma" },
    516 	{ IMX6CLK_SPBA,			"spba" },
    517 	{ IMX6CLK_SSI1,			"ssi1" },
    518 	{ IMX6CLK_SSI2,			"ssi2" },
    519 	{ IMX6CLK_SSI3,			"ssi3" },
    520 	{ IMX6CLK_UART_IPG,		"uart_ipg" },
    521 	{ IMX6CLK_UART_SERIAL,		"uart_serial" },
    522 	{ IMX6CLK_USBOH3,		"usboh3" },
    523 	{ IMX6CLK_USDHC1,		"usdhc1" },
    524 	{ IMX6CLK_USDHC2,		"usdhc2" },
    525 	{ IMX6CLK_USDHC3,		"usdhc3" },
    526 	{ IMX6CLK_USDHC4,		"usdhc4" },
    527 	{ IMX6CLK_VDO_AXI,		"vdo_axi" },
    528 	{ IMX6CLK_VPU_AXI,		"vpu_axi" },
    529 	{ IMX6CLK_CKO1,			"cko1" },
    530 	{ IMX6CLK_PLL1_SYS,		"pll1_sys" },
    531 	{ IMX6CLK_PLL2_BUS,		"pll2_bus" },
    532 	{ IMX6CLK_PLL3_USB_OTG,		"pll3_usb_otg" },
    533 	{ IMX6CLK_PLL4_AUDIO,		"pll4_audio" },
    534 	{ IMX6CLK_PLL5_VIDEO,		"pll5_video" },
    535 	{ IMX6CLK_PLL8_MLB,		"pll8_mlb" },
    536 	{ IMX6CLK_PLL7_USB_HOST,	"pll7_usb_host" },
    537 	{ IMX6CLK_PLL6_ENET,		"pll6_enet" },
    538 	{ IMX6CLK_SSI1_IPG,		"ssi1_ipg" },
    539 	{ IMX6CLK_SSI2_IPG,		"ssi2_ipg" },
    540 	{ IMX6CLK_SSI3_IPG,		"ssi3_ipg" },
    541 	{ IMX6CLK_ROM,			"rom" },
    542 	{ IMX6CLK_USBPHY1,		"usbphy1" },
    543 	{ IMX6CLK_USBPHY2,		"usbphy2" },
    544 	{ IMX6CLK_LDB_DI0_DIV_3_5,	"ldb_di0_div_3_5" },
    545 	{ IMX6CLK_LDB_DI1_DIV_3_5,	"ldb_di1_div_3_5" },
    546 	{ IMX6CLK_SATA_REF,		"sata_ref" },
    547 	{ IMX6CLK_SATA_REF_100M,	"sata_ref_100m" },
    548 	{ IMX6CLK_PCIE_REF,		"pcie_ref" },
    549 	{ IMX6CLK_PCIE_REF_125M,	"pcie_ref_125m" },
    550 	{ IMX6CLK_ENET_REF,		"enet_ref" },
    551 	{ IMX6CLK_USBPHY1_GATE,		"usbphy1_gate" },
    552 	{ IMX6CLK_USBPHY2_GATE,		"usbphy2_gate" },
    553 	{ IMX6CLK_PLL4_POST_DIV,	"pll4_post_div" },
    554 	{ IMX6CLK_PLL5_POST_DIV,	"pll5_post_div" },
    555 	{ IMX6CLK_PLL5_VIDEO_DIV,	"pll5_video_div" },
    556 	{ IMX6CLK_EIM_SLOW,		"eim_slow" },
    557 	{ IMX6CLK_SPDIF,		"spdif" },
    558 	{ IMX6CLK_CKO2_SEL,		"cko2_sel" },
    559 	{ IMX6CLK_CKO2_PODF,		"cko2_podf" },
    560 	{ IMX6CLK_CKO2,			"cko2" },
    561 	{ IMX6CLK_CKO,			"cko" },
    562 	{ IMX6CLK_VDOA,			"vdoa" },
    563 	{ IMX6CLK_PLL4_AUDIO_DIV,	"pll4_audio_div" },
    564 	{ IMX6CLK_LVDS1_SEL,		"lvds1_sel" },
    565 	{ IMX6CLK_LVDS2_SEL,		"lvds2_sel" },
    566 	{ IMX6CLK_LVDS1_GATE,		"lvds1_gate" },
    567 	{ IMX6CLK_LVDS2_GATE,		"lvds2_gate" },
    568 	{ IMX6CLK_ESAI_IPG,		"esai_ipg" },
    569 	{ IMX6CLK_ESAI_MEM,		"esai_mem" },
    570 	{ IMX6CLK_ASRC_IPG,		"asrc_ipg" },
    571 	{ IMX6CLK_ASRC_MEM,		"asrc_mem" },
    572 	{ IMX6CLK_LVDS1_IN,		"lvds1_in" },
    573 	{ IMX6CLK_LVDS2_IN,		"lvds2_in" },
    574 	{ IMX6CLK_ANACLK1,		"anaclk1" },
    575 	{ IMX6CLK_ANACLK2,		"anaclk2" },
    576 	{ IMX6CLK_PLL1_BYPASS_SRC,	"pll1_bypass_src" },
    577 	{ IMX6CLK_PLL2_BYPASS_SRC,	"pll2_bypass_src" },
    578 	{ IMX6CLK_PLL3_BYPASS_SRC,	"pll3_bypass_src" },
    579 	{ IMX6CLK_PLL4_BYPASS_SRC,	"pll4_bypass_src" },
    580 	{ IMX6CLK_PLL5_BYPASS_SRC,	"pll5_bypass_src" },
    581 	{ IMX6CLK_PLL6_BYPASS_SRC,	"pll6_bypass_src" },
    582 	{ IMX6CLK_PLL7_BYPASS_SRC,	"pll7_bypass_src" },
    583 	{ IMX6CLK_PLL1,			"pll1" },
    584 	{ IMX6CLK_PLL2,			"pll2" },
    585 	{ IMX6CLK_PLL3,			"pll3" },
    586 	{ IMX6CLK_PLL4,			"pll4" },
    587 	{ IMX6CLK_PLL5,			"pll5" },
    588 	{ IMX6CLK_PLL6,			"pll6" },
    589 	{ IMX6CLK_PLL7,			"pll7" },
    590 	{ IMX6CLK_PLL1_BYPASS,		"pll1_bypass" },
    591 	{ IMX6CLK_PLL2_BYPASS,		"pll2_bypass" },
    592 	{ IMX6CLK_PLL3_BYPASS,		"pll3_bypass" },
    593 	{ IMX6CLK_PLL4_BYPASS,		"pll4_bypass" },
    594 	{ IMX6CLK_PLL5_BYPASS,		"pll5_bypass" },
    595 	{ IMX6CLK_PLL6_BYPASS,		"pll6_bypass" },
    596 	{ IMX6CLK_PLL7_BYPASS,		"pll7_bypass" },
    597 	{ IMX6CLK_GPT_3M,		"gpt_3m" },
    598 	{ IMX6CLK_VIDEO_27M,		"video_27m" },
    599 	{ IMX6CLK_MIPI_CORE_CFG,	"mipi_core_cfg" },
    600 	{ IMX6CLK_MIPI_IPG,		"mipi_ipg" },
    601 	{ IMX6CLK_CAAM_MEM,		"caam_mem" },
    602 	{ IMX6CLK_CAAM_ACLK,		"caam_aclk" },
    603 	{ IMX6CLK_CAAM_IPG,		"caam_ipg" },
    604 	{ IMX6CLK_SPDIF_GCLK,		"spdif_gclk" },
    605 	{ IMX6CLK_UART_SEL,		"uart_sel" },
    606 	{ IMX6CLK_IPG_PER_SEL,		"ipg_per_sel" },
    607 	{ IMX6CLK_ECSPI_SEL,		"ecspi_sel" },
    608 	{ IMX6CLK_CAN_SEL,		"can_sel" },
    609 	{ IMX6CLK_MMDC_CH1_AXI_CG,	"mmdc_ch1_axi_cg" },
    610 	{ IMX6CLK_PRE0,			"pre0" },
    611 	{ IMX6CLK_PRE1,			"pre1" },
    612 	{ IMX6CLK_PRE2,			"pre2" },
    613 	{ IMX6CLK_PRE3,			"pre3" },
    614 	{ IMX6CLK_PRG0_AXI,		"prg0_axi" },
    615 	{ IMX6CLK_PRG1_AXI,		"prg1_axi" },
    616 	{ IMX6CLK_PRG0_APB,		"prg0_apb" },
    617 	{ IMX6CLK_PRG1_APB,		"prg1_apb" },
    618 	{ IMX6CLK_PRE_AXI,		"pre_axi" },
    619 	{ IMX6CLK_MLB_SEL,		"mlb_sel" },
    620 	{ IMX6CLK_MLB_PODF,		"mlb_podf" },
    621 	{ IMX6CLK_END,			"end" },
    622 };
    623 
    624 /* Clock Divider Tables */
    625 static const int enet_ref_tbl[] = { 20, 10, 5, 4, 0 };
    626 static const int post_div_tbl[] = { 4, 2, 1, 0 };
    627 static const int audiovideo_div_tbl[] = { 1, 2, 1, 4, 0 };
    628 
    629 static struct imx6_clk imx6_clks[] = {
    630 	CLK_FIXED("dummy", 0),
    631 
    632 	CLK_FIXED("ckil", IMX6_CKIL_FREQ),
    633 	CLK_FIXED("ckih", IMX6_CKIH_FREQ),
    634 	CLK_FIXED("osc", IMX6_OSC_FREQ),
    635 	CLK_FIXED("anaclk1", IMX6_ANACLK1_FREQ),
    636 	CLK_FIXED("anaclk2", IMX6_ANACLK2_FREQ),
    637 
    638 	CLK_FIXED_FACTOR("sata_ref", "pll6_enet", 5, 1),
    639 	CLK_FIXED_FACTOR("pcie_ref", "pll6_enet", 4, 1),
    640 	CLK_FIXED_FACTOR("pll2_198m", "pll2_pfd2_396m", 2, 1),
    641 	CLK_FIXED_FACTOR("pll3_120m", "pll3_usb_otg", 4, 1),
    642 	CLK_FIXED_FACTOR("pll3_80m", "pll3_usb_otg", 6, 1),
    643 	CLK_FIXED_FACTOR("pll3_60m", "pll3_usb_otg", 8, 1),
    644 	CLK_FIXED_FACTOR("twd", "arm", 2, 1),
    645 	CLK_FIXED_FACTOR("gpt_3m", "osc", 8, 1),
    646 	CLK_FIXED_FACTOR("video_27m", "pll3_pfd1_540m", 20, 1),
    647 	CLK_FIXED_FACTOR("gpu2d_axi", "mmdc_ch0_axi_podf", 1, 1),
    648 	CLK_FIXED_FACTOR("gpu3d_axi", "mmdc_ch0_axi_podf", 1, 1),
    649 	CLK_FIXED_FACTOR("ldb_di0_div_3_5", "ldb_di0_sel", 7, 2),
    650 	CLK_FIXED_FACTOR("ldb_di1_div_3_5", "ldb_di1_sel", 7, 2),
    651 
    652 	CLK_PFD("pll2_pfd0_352m", "pll2_bus", PFD_528, 0),
    653 	CLK_PFD("pll2_pfd1_594m", "pll2_bus", PFD_528, 1),
    654 	CLK_PFD("pll2_pfd2_396m", "pll2_bus", PFD_528, 2),
    655 	CLK_PFD("pll3_pfd0_720m", "pll3_usb_otg", PFD_480, 0),
    656 	CLK_PFD("pll3_pfd1_540m", "pll3_usb_otg", PFD_480, 1),
    657 	CLK_PFD("pll3_pfd2_508m", "pll3_usb_otg", PFD_480, 2),
    658 	CLK_PFD("pll3_pfd3_454m", "pll3_usb_otg", PFD_480, 3),
    659 
    660 	CLK_PLL("pll1", "osc", SYS, PLL_ARM, DIV_SELECT, POWERDOWN, 0),
    661 	CLK_PLL("pll2", "osc", GENERIC, PLL_SYS, DIV_SELECT, POWERDOWN, 0),
    662 	CLK_PLL("pll3", "osc", USB, PLL_USB1, DIV_SELECT, POWER, 0),
    663 	CLK_PLL("pll4", "osc", AUDIO_VIDEO, PLL_AUDIO, DIV_SELECT, POWERDOWN, 0),
    664 	CLK_PLL("pll5", "osc", AUDIO_VIDEO, PLL_VIDEO, DIV_SELECT, POWERDOWN, 0),
    665 	CLK_PLL("pll6", "osc", ENET, PLL_ENET, DIV_SELECT, POWERDOWN, 500000000),
    666 	CLK_PLL("pll7", "osc", USB, PLL_USB2, DIV_SELECT, POWER, 0),
    667 
    668 	CLK_DIV("periph_clk2", "periph_clk2_sel", CBCDR, PERIPH_CLK2_PODF),
    669 	CLK_DIV("periph2_clk2", "periph2_clk2_sel", CBCDR, PERIPH2_CLK2_PODF),
    670 	CLK_DIV("ipg", "ahb", CBCDR, IPG_PODF),
    671 	CLK_DIV("esai_pred", "esai_sel", CS1CDR, ESAI_CLK_PRED),
    672 	CLK_DIV("esai_podf", "esai_pred", CS1CDR, ESAI_CLK_PODF),
    673 	CLK_DIV("asrc_pred", "asrc_sel", CDCDR, SPDIF1_CLK_PRED),
    674 	CLK_DIV("asrc_podf", "asrc_pred", CDCDR, SPDIF1_CLK_PODF),
    675 	CLK_DIV("spdif_pred", "spdif_sel", CDCDR, SPDIF0_CLK_PRED),
    676 	CLK_DIV("spdif_podf", "spdif_pred", CDCDR, SPDIF0_CLK_PODF),
    677 	CLK_DIV("ecspi_root", "pll3_60m", CSCDR2, ECSPI_CLK_PODF),
    678 	CLK_DIV("can_root", "pll3_60m", CSCMR2, CAN_CLK_PODF),
    679 	CLK_DIV("uart_serial_podf", "pll3_80m", CSCDR1, UART_CLK_PODF),
    680 	CLK_DIV("gpu2d_core_podf", "gpu2d_core_sel", CBCMR, GPU2D_CORE_CLK_PODF),
    681 	CLK_DIV("gpu3d_core_podf", "gpu3d_core_sel", CBCMR, GPU3D_CORE_PODF),
    682 	CLK_DIV("gpu3d_shader", "gpu3d_shader_sel", CBCMR, GPU3D_SHADER_PODF),
    683 	CLK_DIV("ipu1_podf", "ipu1_sel", CSCDR3, IPU1_HSP_PODF),
    684 	CLK_DIV("ipu2_podf", "ipu2_sel", CSCDR3, IPU2_HSP_PODF),
    685 	CLK_DIV("ldb_di0_podf", "ldb_di0_div_3_5", CSCMR2, LDB_DI0_IPU_DIV),
    686 	CLK_DIV("ldb_di1_podf", "ldb_di1_div_3_5", CSCMR2, LDB_DI1_IPU_DIV),
    687 	CLK_DIV("ipu1_di0_pre", "ipu1_di0_pre_sel", CHSCCDR, IPU1_DI0_PODF),
    688 	CLK_DIV("ipu1_di1_pre", "ipu1_di1_pre_sel", CHSCCDR, IPU1_DI1_PODF),
    689 	CLK_DIV("ipu2_di0_pre", "ipu2_di0_pre_sel", CSCDR2, IPU2_DI0_PODF),
    690 	CLK_DIV("ipu2_di1_pre", "ipu2_di1_pre_sel", CSCDR2, IPU2_DI1_PODF),
    691 	CLK_DIV("hsi_tx_podf", "hsi_tx_sel", CDCDR, HSI_TX_PODF),
    692 	CLK_DIV("ssi1_pred", "ssi1_sel", CS1CDR, SSI1_CLK_PRED),
    693 	CLK_DIV("ssi1_podf", "ssi1_pred", CS1CDR, SSI1_CLK_PODF),
    694 	CLK_DIV("ssi2_pred", "ssi2_sel", CS2CDR, SSI2_CLK_PRED),
    695 	CLK_DIV("ssi2_podf", "ssi2_pred", CS2CDR, SSI2_CLK_PODF),
    696 	CLK_DIV("ssi3_pred", "ssi3_sel", CS1CDR, SSI3_CLK_PRED),
    697 	CLK_DIV("ssi3_podf", "ssi3_pred", CS1CDR, SSI3_CLK_PODF),
    698 	CLK_DIV("usdhc1_podf", "usdhc1_sel", CSCDR1, USDHC1_PODF),
    699 	CLK_DIV("usdhc2_podf", "usdhc2_sel", CSCDR1, USDHC2_PODF),
    700 	CLK_DIV("usdhc3_podf", "usdhc3_sel", CSCDR1, USDHC3_PODF),
    701 	CLK_DIV("usdhc4_podf", "usdhc4_sel", CSCDR1, USDHC4_PODF),
    702 	CLK_DIV("enfc_pred", "enfc_sel", CS2CDR, ENFC_CLK_PRED),
    703 	CLK_DIV("enfc_podf", "enfc_pred", CS2CDR, ENFC_CLK_PODF),
    704 	CLK_DIV("vpu_axi_podf", "vpu_axi_sel", CSCDR1, VPU_AXI_PODF),
    705 	CLK_DIV("cko1_podf", "cko1_sel", CCOSR, CLKO1_DIV),
    706 	CLK_DIV("cko2_podf", "cko2_sel", CCOSR, CLKO2_DIV),
    707 	CLK_DIV("ipg_per", "ipg", CSCMR1, PERCLK_PODF),
    708 	CLK_DIV("eim_podf", "eim_sel", CSCMR1, ACLK_PODF),
    709 	CLK_DIV("eim_slow_podf", "eim_slow_sel", CSCMR1, ACLK_EIM_SLOW_PODF),
    710 
    711 	CLK_DIV_BUSY("axi", "axi_sel", CBCDR, AXI_PODF, CDHIPR, AXI_PODF_BUSY),
    712 	CLK_DIV_BUSY("mmdc_ch0_axi_podf", "periph", CBCDR, MMDC_CH0_AXI_PODF, CDHIPR, MMDC_CH0_PODF_BUSY),
    713 	CLK_DIV_BUSY("mmdc_ch1_axi_podf", "periph2", CBCDR, MMDC_CH1_AXI_PODF, CDHIPR, MMDC_CH1_PODF_BUSY),
    714 	CLK_DIV_BUSY("arm", "pll1_sw", CACRR, ARM_PODF, CDHIPR, ARM_PODF_BUSY),
    715 	CLK_DIV_BUSY("ahb", "periph", CBCDR, AHB_PODF, CDHIPR, AHB_PODF_BUSY),
    716 
    717 	CLK_DIV_TABLE("pll4_post_div", "pll4_audio", PLL_AUDIO, POST_DIV_SELECT, post_div_tbl),
    718 	CLK_DIV_TABLE("pll4_audio_div", "pll4_post_div", MISC2, AUDIO_DIV_LSB, audiovideo_div_tbl),
    719 	CLK_DIV_TABLE("pll5_post_div", "pll5_video", PLL_VIDEO, POST_DIV_SELECT, post_div_tbl),
    720 	CLK_DIV_TABLE("pll5_video_div", "pll5_post_div", MISC2, VIDEO_DIV, audiovideo_div_tbl),
    721 	CLK_DIV_TABLE("enet_ref", "pll6_enet", PLL_ENET, DIV_SELECT, enet_ref_tbl),
    722 
    723 	CLK_MUX("step", step_p, CCM, CCSR, STEP_SEL),
    724 	CLK_MUX("pll1_sw", pll1_sw_p, CCM, CCSR, PLL1_SW_CLK_SEL),
    725 	CLK_MUX("periph_pre", periph_pre_p, CCM, CBCMR, PRE_PERIPH_CLK_SEL),
    726 	CLK_MUX("periph2_pre", periph_pre_p, CCM, CBCMR, PRE_PERIPH2_CLK_SEL),
    727 	CLK_MUX("periph_clk2_sel", periph_clk2_p, CCM,CBCMR, PERIPH_CLK2_SEL),
    728 	CLK_MUX("periph2_clk2_sel", periph2_clk2_p, CCM,CBCMR, PERIPH2_CLK2_SEL),
    729 	CLK_MUX("axi_sel", axi_p, CCM, CBCDR, AXI_SEL),
    730 	CLK_MUX("asrc_sel", audio_p, CCM, CDCDR, SPDIF1_CLK_SEL),
    731 	CLK_MUX("spdif_sel", audio_p, CCM, CDCDR, SPDIF0_CLK_SEL),
    732 	CLK_MUX("gpu2d_core_sel", gpu2d_core_p, CCM, CBCMR, GPU2D_CLK_SEL),
    733 	CLK_MUX("gpu3d_core_sel", gpu3d_core_p, CCM, CBCMR, GPU3D_CORE_CLK_SEL),
    734 	CLK_MUX("gpu3d_shader_sel", gpu3d_shader_p, CCM,CBCMR, GPU3D_SHADER_CLK_SEL),
    735 	CLK_MUX("esai_sel", audio_p, CCM, CSCMR2, ESAI_CLK_SEL),
    736 	CLK_MUX("ipu1_sel", ipu_p, CCM, CSCDR3, IPU1_HSP_CLK_SEL),
    737 	CLK_MUX("ipu2_sel", ipu_p, CCM, CSCDR3, IPU2_HSP_CLK_SEL),
    738 	CLK_MUX("ipu1_di0_pre_sel", ipu_di_pre_p, CCM, CHSCCDR, IPU1_DI0_PRE_CLK_SEL),
    739 	CLK_MUX("ipu1_di1_pre_sel", ipu_di_pre_p, CCM, CHSCCDR, IPU1_DI1_PRE_CLK_SEL),
    740 	CLK_MUX("ipu2_di0_pre_sel", ipu_di_pre_p, CCM, CSCDR2, IPU2_DI0_PRE_CLK_SEL),
    741 	CLK_MUX("ipu2_di1_pre_sel", ipu_di_pre_p, CCM, CSCDR2, IPU2_DI1_PRE_CLK_SEL),
    742 	CLK_MUX("ipu1_di0_sel", ipu1_di0_p, CCM, CHSCCDR, IPU1_DI0_CLK_SEL),
    743 	CLK_MUX("ipu1_di1_sel", ipu1_di1_p, CCM, CHSCCDR, IPU1_DI1_CLK_SEL),
    744 	CLK_MUX("ipu2_di0_sel", ipu2_di0_p, CCM, CSCDR2, IPU2_DI0_CLK_SEL),
    745 	CLK_MUX("ipu2_di1_sel", ipu2_di1_p, CCM, CSCDR2, IPU2_DI1_CLK_SEL),
    746 	CLK_MUX("ldb_di0_sel", ldb_di_p, CCM, CS2CDR, LDB_DI0_CLK_SEL),
    747 	CLK_MUX("ldb_di1_sel", ldb_di_p, CCM, CS2CDR, LDB_DI1_CLK_SEL),
    748 	CLK_MUX("vdo_axi_sel", vdo_axi_p, CCM, CBCMR, VDOAXI_CLK_SEL),
    749 	CLK_MUX("vpu_axi_sel", vpu_axi_p, CCM, CBCMR, VPU_AXI_CLK_SEL),
    750 	CLK_MUX("cko1_sel", cko1_p, CCM, CCOSR, CLKO1_SEL),
    751 	CLK_MUX("cko2_sel", cko2_p, CCM, CCOSR, CLKO2_SEL),
    752 	CLK_MUX("cko", cko_p, CCM, CCOSR, CLK_OUT_SEL),
    753 	CLK_MUX("hsi_tx_sel", hsi_tx_p, CCM, CDCDR, HSI_TX_CLK_SEL),
    754 	CLK_MUX("pcie_axi_sel", pcie_axi_p, CCM, CBCMR, PCIE_AXI_CLK_SEL),
    755 	CLK_MUX("ssi1_sel", ssi_p, CCM, CSCMR1, SSI1_CLK_SEL),
    756 	CLK_MUX("ssi2_sel", ssi_p, CCM, CSCMR1, SSI2_CLK_SEL),
    757 	CLK_MUX("ssi3_sel", ssi_p, CCM, CSCMR1, SSI3_CLK_SEL),
    758 	CLK_MUX("usdhc1_sel", usdhc_p, CCM, CSCMR1, USDHC1_CLK_SEL),
    759 	CLK_MUX("usdhc2_sel", usdhc_p, CCM, CSCMR1, USDHC2_CLK_SEL),
    760 	CLK_MUX("usdhc3_sel", usdhc_p, CCM, CSCMR1, USDHC3_CLK_SEL),
    761 	CLK_MUX("usdhc4_sel", usdhc_p, CCM, CSCMR1, USDHC4_CLK_SEL),
    762 	CLK_MUX("eim_sel", eim_p, CCM, CSCMR1, ACLK_SEL),
    763 	CLK_MUX("eim_slow_sel", eim_slow_p, CCM, CSCMR1, ACLK_EIM_SLOW_SEL),
    764 	CLK_MUX("enfc_sel", enfc_p, CCM, CS2CDR, ENFC_CLK_SEL),
    765 
    766 	CLK_MUX("pll1_bypass_src", pll_bypass_src_p, CCM_ANALOG, PLL_ARM, BYPASS_CLK_SRC),
    767 	CLK_MUX("pll2_bypass_src", pll_bypass_src_p, CCM_ANALOG, PLL_SYS, BYPASS_CLK_SRC),
    768 	CLK_MUX("pll3_bypass_src", pll_bypass_src_p, CCM_ANALOG, PLL_USB1, BYPASS_CLK_SRC),
    769 	CLK_MUX("pll4_bypass_src", pll_bypass_src_p, CCM_ANALOG, PLL_AUDIO, BYPASS_CLK_SRC),
    770 	CLK_MUX("pll5_bypass_src", pll_bypass_src_p, CCM_ANALOG, PLL_VIDEO, BYPASS_CLK_SRC),
    771 	CLK_MUX("pll6_bypass_src", pll_bypass_src_p, CCM_ANALOG, PLL_ENET, BYPASS_CLK_SRC),
    772 	CLK_MUX("pll7_bypass_src", pll_bypass_src_p, CCM_ANALOG, PLL_USB2, BYPASS_CLK_SRC),
    773 	CLK_MUX("pll1_bypass", pll1_bypass_p, CCM_ANALOG, PLL_ARM, BYPASS),
    774 	CLK_MUX("pll2_bypass", pll2_bypass_p, CCM_ANALOG, PLL_SYS, BYPASS),
    775 	CLK_MUX("pll3_bypass", pll3_bypass_p, CCM_ANALOG, PLL_USB1, BYPASS),
    776 	CLK_MUX("pll4_bypass", pll4_bypass_p, CCM_ANALOG, PLL_AUDIO, BYPASS),
    777 	CLK_MUX("pll5_bypass", pll5_bypass_p, CCM_ANALOG, PLL_VIDEO, BYPASS),
    778 	CLK_MUX("pll6_bypass", pll6_bypass_p, CCM_ANALOG, PLL_ENET, BYPASS),
    779 	CLK_MUX("pll7_bypass", pll7_bypass_p, CCM_ANALOG, PLL_USB2, BYPASS),
    780 
    781 	CLK_MUX("lvds1_sel", lvds_p, CCM_ANALOG, MISC1, LVDS_CLK1_SRC),
    782 	CLK_MUX("lvds2_sel", lvds_p, CCM_ANALOG, MISC1, LVDS_CLK2_SRC),
    783 
    784 	CLK_MUX_BUSY("periph", periph_p, CBCDR, PERIPH_CLK_SEL, CDHIPR, PERIPH_CLK_SEL_BUSY),
    785 	CLK_MUX_BUSY("periph2", periph2_p, CBCDR, PERIPH2_CLK_SEL, CDHIPR, PERIPH2_CLK_SEL_BUSY),
    786 
    787 	CLK_GATE("apbh_dma", "usdhc3", CCM, CCGR0, APBHDMA_HCLK_ENABLE),
    788 	CLK_GATE("asrc", "asrc_podf", CCM, CCGR0, ASRC_CLK_ENABLE),
    789 	CLK_GATE("asrc_ipg", "ahb", CCM, CCGR0, ASRC_CLK_ENABLE),
    790 	CLK_GATE("asrc_mem", "ahb", CCM, CCGR0, ASRC_CLK_ENABLE),
    791 	CLK_GATE("caam_mem", "ahb", CCM, CCGR0, CAAM_SECURE_MEM_CLK_ENABLE),
    792 	CLK_GATE("caam_aclk", "ahb", CCM, CCGR0, CAAM_WRAPPER_ACLK_ENABLE),
    793 	CLK_GATE("caam_ipg", "ipg", CCM, CCGR0, CAAM_WRAPPER_IPG_ENABLE),
    794 	CLK_GATE("can1_ipg", "ipg", CCM, CCGR0, CAN1_CLK_ENABLE),
    795 	CLK_GATE("can1_serial", "can_root", CCM, CCGR0, CAN1_SERIAL_CLK_ENABLE),
    796 	CLK_GATE("can2_ipg", "ipg", CCM, CCGR0, CAN2_CLK_ENABLE),
    797 	CLK_GATE("can2_serial", "can_root", CCM, CCGR0, CAN2_SERIAL_CLK_ENABLE),
    798 	CLK_GATE("ecspi1", "ecspi_root", CCM, CCGR1, ECSPI1_CLK_ENABLE),
    799 	CLK_GATE("ecspi2", "ecspi_root", CCM, CCGR1, ECSPI2_CLK_ENABLE),
    800 	CLK_GATE("ecspi3", "ecspi_root", CCM, CCGR1, ECSPI3_CLK_ENABLE),
    801 	CLK_GATE("ecspi4", "ecspi_root", CCM, CCGR1, ECSPI4_CLK_ENABLE),
    802 	CLK_GATE("ecspi5", "ecspi_root", CCM, CCGR1, ECSPI5_CLK_ENABLE),
    803 	CLK_GATE("enet", "ipg", CCM, CCGR1, ENET_CLK_ENABLE),
    804 	CLK_GATE("esai_extal", "esai_podf", CCM, CCGR1, ESAI_CLK_ENABLE),
    805 	CLK_GATE("esai_ipg", "ahb", CCM, CCGR1, ESAI_CLK_ENABLE),
    806 	CLK_GATE("esai_mem", "ahb", CCM, CCGR1, ESAI_CLK_ENABLE),
    807 	CLK_GATE("gpt_ipg", "ipg", CCM, CCGR1, GPT_CLK_ENABLE),
    808 	CLK_GATE("gpt_ipg_per", "ipg_per", CCM, CCGR1, GPT_SERIAL_CLK_ENABLE),
    809 	CLK_GATE("gpu2d_core", "gpu2d_core_podf", CCM, CCGR1, GPU2D_CLK_ENABLE),
    810 	CLK_GATE("gpu3d_core", "gpu3d_core_podf", CCM, CCGR1, GPU3D_CLK_ENABLE),
    811 	CLK_GATE("hdmi_iahb", "ahb", CCM, CCGR2, HDMI_TX_IAHBCLK_ENABLE),
    812 	CLK_GATE("hdmi_isfr", "video_27m", CCM, CCGR2, HDMI_TX_ISFRCLK_ENABLE),
    813 	CLK_GATE("i2c1", "ipg_per", CCM, CCGR2, I2C1_SERIAL_CLK_ENABLE),
    814 	CLK_GATE("i2c2", "ipg_per", CCM, CCGR2, I2C2_SERIAL_CLK_ENABLE),
    815 	CLK_GATE("i2c3", "ipg_per", CCM, CCGR2, I2C3_SERIAL_CLK_ENABLE),
    816 	CLK_GATE("iim", "ipg", CCM, CCGR2, IIM_CLK_ENABLE),
    817 	CLK_GATE("enfc", "enfc_podf", CCM, CCGR2, IOMUX_IPT_CLK_IO_CLK_ENABLE),
    818 	CLK_GATE("vdoa", "vdo_axi", CCM, CCGR2, IPSYNC_VDOA_IPG_CLK_ENABLE),
    819 	CLK_GATE("ipu1", "ipu1_podf", CCM, CCGR3, IPU1_IPU_CLK_ENABLE),
    820 	CLK_GATE("ipu1_di0", "ipu1_di0_sel", CCM, CCGR3, IPU1_IPU_DI0_CLK_ENABLE),
    821 	CLK_GATE("ipu1_di1", "ipu1_di1_sel", CCM, CCGR3, IPU1_IPU_DI1_CLK_ENABLE),
    822 	CLK_GATE("ipu2", "ipu2_podf", CCM, CCGR3, IPU2_IPU_CLK_ENABLE),
    823 	CLK_GATE("ipu2_di0", "ipu2_di0_sel", CCM, CCGR3, IPU2_IPU_DI0_CLK_ENABLE),
    824 	CLK_GATE("ldb_di0", "ldb_di0_podf", CCM, CCGR3, LDB_DI0_CLK_ENABLE),
    825 	CLK_GATE("ldb_di1", "ldb_di1_podf", CCM, CCGR3, LDB_DI1_CLK_ENABLE),
    826 	CLK_GATE("ipu2_di1", "ipu2_di1_sel", CCM, CCGR3, IPU2_IPU_DI1_CLK_ENABLE),
    827 	CLK_GATE("hsi_tx", "hsi_tx_podf", CCM, CCGR3, MIPI_CORE_CFG_CLK_ENABLE),
    828 	CLK_GATE("mipi_core_cfg", "video_27m", CCM, CCGR3, MIPI_CORE_CFG_CLK_ENABLE),
    829 	CLK_GATE("mipi_ipg", "ipg", CCM, CCGR3, MIPI_CORE_CFG_CLK_ENABLE),
    830 	CLK_GATE("mlb", "axi", CCM, CCGR3, MLB_CLK_ENABLE),
    831 	CLK_GATE("mmdc_ch0_axi", "mmdc_ch0_axi_podf", CCM, CCGR3, MMDC_CORE_ACLK_FAST_CORE_P0_ENABLE),
    832 	CLK_GATE("mmdc_ch1_axi", "mmdc_ch1_axi_podf", CCM, CCGR3, MMDC_CORE_ACLK_FAST_CORE_P1_ENABLE),
    833 	CLK_GATE("ocram", "ahb", CCM, CCGR3, OCRAM_CLK_ENABLE),
    834 	CLK_GATE("openvg_axi", "axi", CCM, CCGR3, OPENVGAXICLK_CLK_ROOT_ENABLE),
    835 	CLK_GATE("pcie_axi", "pcie_axi_sel", CCM, CCGR4, PCIE_ROOT_ENABLE),
    836 	CLK_GATE("per1_bch", "usdhc3", CCM, CCGR4, PL301_MX6QPER1_BCHCLK_ENABLE),
    837 	CLK_GATE("pwm1", "ipg_per", CCM, CCGR4, PWM1_CLK_ENABLE),
    838 	CLK_GATE("pwm2", "ipg_per", CCM, CCGR4, PWM2_CLK_ENABLE),
    839 	CLK_GATE("pwm3", "ipg_per", CCM, CCGR4, PWM3_CLK_ENABLE),
    840 	CLK_GATE("pwm4", "ipg_per", CCM, CCGR4, PWM4_CLK_ENABLE),
    841 	CLK_GATE("gpmi_bch_apb", "usdhc3", CCM, CCGR4, RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE),
    842 	CLK_GATE("gpmi_bch", "usdhc4", CCM, CCGR4, RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE),
    843 	CLK_GATE("gpmi_io", "enfc", CCM, CCGR4, RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE),
    844 	CLK_GATE("gpmi_apb", "usdhc3", CCM, CCGR4, RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE),
    845 	CLK_GATE("rom", "ahb", CCM, CCGR5, ROM_CLK_ENABLE),
    846 	CLK_GATE("sata", "ahb", CCM, CCGR5, SATA_CLK_ENABLE),
    847 	CLK_GATE("sdma", "ahb", CCM, CCGR5, SDMA_CLK_ENABLE),
    848 	CLK_GATE("spba", "ipg", CCM, CCGR5, SPBA_CLK_ENABLE),
    849 	CLK_GATE("spdif", "spdif_podf", CCM, CCGR5, SPDIF_CLK_ENABLE),
    850 	CLK_GATE("spdif_gclk", "ipg", CCM, CCGR5, SPDIF_CLK_ENABLE),
    851 	CLK_GATE("ssi1_ipg", "ipg", CCM, CCGR5, SSI1_CLK_ENABLE),
    852 	CLK_GATE("ssi2_ipg", "ipg", CCM, CCGR5, SSI2_CLK_ENABLE),
    853 	CLK_GATE("ssi3_ipg", "ipg", CCM, CCGR5, SSI3_CLK_ENABLE),
    854 	CLK_GATE("ssi1", "ssi1_podf", CCM, CCGR5, SSI1_CLK_ENABLE),
    855 	CLK_GATE("ssi2", "ssi2_podf", CCM, CCGR5, SSI2_CLK_ENABLE),
    856 	CLK_GATE("ssi3", "ssi3_podf", CCM, CCGR5, SSI3_CLK_ENABLE),
    857 	CLK_GATE("uart_ipg", "ipg", CCM, CCGR5, UART_CLK_ENABLE),
    858 	CLK_GATE("uart_serial", "uart_serial_podf", CCM, CCGR5, UART_SERIAL_CLK_ENABLE),
    859 	CLK_GATE("usboh3", "ipg", CCM, CCGR6, USBOH3_CLK_ENABLE),
    860 	CLK_GATE("usdhc1", "usdhc1_podf", CCM, CCGR6, USDHC1_CLK_ENABLE),
    861 	CLK_GATE("usdhc2", "usdhc2_podf", CCM, CCGR6, USDHC2_CLK_ENABLE),
    862 	CLK_GATE("usdhc3", "usdhc3_podf", CCM, CCGR6, USDHC3_CLK_ENABLE),
    863 	CLK_GATE("usdhc4", "usdhc4_podf", CCM, CCGR6, USDHC4_CLK_ENABLE),
    864 	CLK_GATE("eim_slow", "eim_slow_podf", CCM, CCGR6, EIM_SLOW_CLK_ENABLE),
    865 	CLK_GATE("vdo_axi", "vdo_axi_sel", CCM, CCGR6, VDOAXICLK_CLK_ENABLE),
    866 	CLK_GATE("vpu_axi", "vpu_axi_podf", CCM, CCGR6, VPU_CLK_ENABLE),
    867 	CLK_GATE("cko1", "cko1_podf", CCM, CCOSR, CLKO1_EN),
    868 	CLK_GATE("cko2", "cko2_podf", CCM, CCOSR, CLKO2_EN),
    869 
    870 	CLK_GATE("sata_ref_100m", "sata_ref", CCM_ANALOG, PLL_ENET, ENABLE_100M),
    871 	CLK_GATE("pcie_ref_125m", "pcie_ref", CCM_ANALOG, PLL_ENET, ENABLE_125M),
    872 
    873 	CLK_GATE("pll1_sys", "pll1_bypass", CCM_ANALOG, PLL_ARM, ENABLE),
    874 	CLK_GATE("pll2_bus", "pll2_bypass", CCM_ANALOG, PLL_SYS, ENABLE),
    875 	CLK_GATE("pll3_usb_otg", "pll3_bypass", CCM_ANALOG, PLL_USB1, ENABLE),
    876 	CLK_GATE("pll4_audio", "pll4_bypass", CCM_ANALOG, PLL_AUDIO, ENABLE),
    877 	CLK_GATE("pll5_video", "pll5_bypass", CCM_ANALOG, PLL_VIDEO, ENABLE),
    878 	CLK_GATE("pll6_enet", "pll6_bypass", CCM_ANALOG, PLL_ENET, ENABLE),
    879 	CLK_GATE("pll7_usb_host", "pll7_bypass", CCM_ANALOG, PLL_USB2, ENABLE),
    880 
    881 	CLK_GATE("usbphy1", "pll3_usb_otg", CCM_ANALOG, PLL_USB1, RESERVED),
    882 	CLK_GATE("usbphy2", "pll7_usb_host", CCM_ANALOG, PLL_USB2, RESERVED),
    883 
    884 	CLK_GATE_EXCLUSIVE("lvds1_gate", "lvds1_sel", CCM_ANALOG, MISC1, LVDS_CLK1_OBEN, LVDS_CLK1_IBEN),
    885 	CLK_GATE_EXCLUSIVE("lvds2_gate", "lvds2_sel", CCM_ANALOG, MISC1, LVDS_CLK2_OBEN, LVDS_CLK2_IBEN),
    886 	CLK_GATE_EXCLUSIVE("lvds1_in", "anaclk1", CCM_ANALOG, MISC1, LVDS_CLK1_IBEN, LVDS_CLK1_OBEN),
    887 	CLK_GATE_EXCLUSIVE("lvds2_in", "anaclk2", CCM_ANALOG, MISC1, LVDS_CLK2_IBEN, LVDS_CLK2_OBEN),
    888 };
    889 
    890 static struct imx6_clk *imx6_clk_find(const char *);
    891 static struct imx6_clk *imx6_clk_find_by_id(u_int);
    892 
    893 static void imxccm_init_clocks(struct imx6ccm_softc *);
    894 static struct clk *imxccm_clk_get(void *, const char *);
    895 static void imxccm_clk_put(void *, struct clk *);
    896 static u_int imxccm_clk_get_rate(void *, struct clk *);
    897 static int imxccm_clk_set_rate(void *, struct clk *, u_int);
    898 static int imxccm_clk_enable(void *, struct clk *);
    899 static int imxccm_clk_disable(void *, struct clk *);
    900 static int imxccm_clk_set_parent(void *, struct clk *, struct clk *);
    901 static struct clk *imxccm_clk_get_parent(void *, struct clk *);
    902 
    903 static const struct clk_funcs imxccm_clk_funcs = {
    904 	.get = imxccm_clk_get,
    905 	.put = imxccm_clk_put,
    906 	.get_rate = imxccm_clk_get_rate,
    907 	.set_rate = imxccm_clk_set_rate,
    908 	.enable = imxccm_clk_enable,
    909 	.disable = imxccm_clk_disable,
    910 	.set_parent = imxccm_clk_set_parent,
    911 	.get_parent = imxccm_clk_get_parent,
    912 };
    913 
    914 void
    915 imx6ccm_attach_common(device_t self)
    916 {
    917 	struct imx6ccm_softc * const sc = device_private(self);
    918 
    919 	sc->sc_dev = self;
    920 
    921 	sc->sc_clkdom.name = device_xname(self);
    922 	sc->sc_clkdom.funcs = &imxccm_clk_funcs;
    923 	sc->sc_clkdom.priv = sc;
    924 	for (u_int n = 0; n < __arraycount(imx6_clks); n++) {
    925 		imx6_clks[n].base.domain = &sc->sc_clkdom;
    926 		clk_attach(&imx6_clks[n].base);
    927 	}
    928 
    929 	imxccm_init_clocks(sc);
    930 
    931 	for (int n = 0; n < __arraycount(imx6_clks); n++) {
    932 		struct clk *clk = &imx6_clks[n].base;
    933 		struct clk *clk_parent = clk_get_parent(clk);
    934 		const char *parent_str = clk_parent ? clk_parent->name : "none";
    935 		aprint_verbose_dev(self, "%s (%s) : %u Hz\n", clk->name,
    936 		    parent_str, clk_get_rate(clk));
    937 	}
    938 }
    939 
    940 struct clk *
    941 imx6_get_clock(const char *name)
    942 {
    943 	struct imx6_clk *iclk;
    944 	iclk = imx6_clk_find(name);
    945 
    946 	if (iclk == NULL)
    947 		return NULL;
    948 
    949 	return &iclk->base;
    950 }
    951 
    952 struct clk *
    953 imx6_get_clock_by_id(u_int clock_id)
    954 {
    955 	struct imx6_clk *iclk;
    956 	iclk = imx6_clk_find_by_id(clock_id);
    957 
    958 	if (iclk == NULL)
    959 		return NULL;
    960 
    961 	return &iclk->base;
    962 }
    963 
    964 static struct imx6_clk *
    965 imx6_clk_find(const char *name)
    966 {
    967 	if (name == NULL)
    968 		return NULL;
    969 
    970 	for (int n = 0; n < __arraycount(imx6_clks); n++) {
    971 		if (strcmp(imx6_clks[n].base.name, name) == 0)
    972 			return &imx6_clks[n];
    973 	}
    974 
    975 	return NULL;
    976 }
    977 
    978 static struct imx6_clk *
    979 imx6_clk_find_by_id(u_int clock_id)
    980 {
    981 	for (int n = 0; n < __arraycount(imx6_clock_ids); n++) {
    982 		if (imx6_clock_ids[n].id == clock_id) {
    983 			const char *name = imx6_clock_ids[n].name;
    984 			return imx6_clk_find(name);
    985 		}
    986 	}
    987 
    988 	return NULL;
    989 }
    990 
    991 struct imxccm_init_parent {
    992 	const char *clock;
    993 	const char *parent;
    994 } imxccm_init_parents[] = {
    995 	{ "pll1_bypass",	"pll1" },
    996 	{ "pll2_bypass",	"pll2" },
    997 	{ "pll3_bypass",	"pll3" },
    998 	{ "pll4_bypass",	"pll4" },
    999 	{ "pll5_bypass",	"pll5" },
   1000 	{ "pll6_bypass",	"pll6" },
   1001 	{ "pll7_bypass",	"pll7" },
   1002 	{ "lvds1_sel",		"sata_ref_100m" },
   1003 };
   1004 
   1005 static void
   1006 imxccm_init_clocks(struct imx6ccm_softc *sc)
   1007 {
   1008 	struct clk *clk;
   1009 	struct clk *clk_parent;
   1010 
   1011 	for (u_int n = 0; n < __arraycount(imxccm_init_parents); n++) {
   1012 		clk = clk_get(&sc->sc_clkdom, imxccm_init_parents[n].clock);
   1013 		KASSERT(clk != NULL);
   1014 		clk_parent = clk_get(&sc->sc_clkdom, imxccm_init_parents[n].parent);
   1015 		KASSERT(clk_parent != NULL);
   1016 
   1017 		int error = clk_set_parent(clk, clk_parent);
   1018 		if (error) {
   1019 			aprint_error_dev(sc->sc_dev,
   1020 			    "couldn't set '%s' parent to '%s': %d\n",
   1021 			    clk->name, clk_parent->name, error);
   1022 		}
   1023 		clk_put(clk_parent);
   1024 		clk_put(clk);
   1025 	}
   1026 }
   1027 
   1028 static u_int
   1029 imxccm_clk_get_rate_pll_generic(struct imx6ccm_softc *sc, struct imx6_clk *iclk,
   1030     const u_int rate_parent)
   1031 {
   1032 	struct imx6_clk_pll *pll = &iclk->clk.pll;
   1033 	uint64_t freq = rate_parent;
   1034 
   1035 	KASSERT((pll->type == IMX6_CLK_PLL_GENERIC) ||
   1036 	    (pll->type == IMX6_CLK_PLL_USB));
   1037 
   1038 	uint32_t v = bus_space_read_4(sc->sc_iot, sc->sc_ioh_analog, pll->reg);
   1039 	uint32_t div = __SHIFTOUT(v, pll->mask);
   1040 
   1041 	return freq * ((div == 1) ? 22 : 20);
   1042 }
   1043 
   1044 static u_int
   1045 imxccm_clk_get_rate_pll_sys(struct imx6ccm_softc *sc, struct imx6_clk *iclk,
   1046     const u_int rate_parent)
   1047 {
   1048 	struct imx6_clk_pll *pll = &iclk->clk.pll;
   1049 	uint64_t freq = rate_parent;
   1050 
   1051 	KASSERT(pll->type == IMX6_CLK_PLL_SYS);
   1052 
   1053 	uint32_t v = bus_space_read_4(sc->sc_iot, sc->sc_ioh_analog, pll->reg);
   1054 	uint32_t div = __SHIFTOUT(v, pll->mask);
   1055 
   1056 	return freq * div / 2;
   1057 }
   1058 
   1059 #define PLL_AUDIO_VIDEO_NUM_OFFSET	0x10
   1060 #define PLL_AUDIO_VIDEO_DENOM_OFFSET	0x20
   1061 
   1062 static u_int
   1063 imxccm_clk_get_rate_pll_audio_video(struct imx6ccm_softc *sc,
   1064     struct imx6_clk *iclk, const u_int rate_parent)
   1065 {
   1066 	struct imx6_clk_pll *pll = &iclk->clk.pll;
   1067 	uint64_t freq = rate_parent;
   1068 
   1069 	KASSERT(pll->type == IMX6_CLK_PLL_AUDIO_VIDEO);
   1070 
   1071 	uint32_t v = bus_space_read_4(sc->sc_iot, sc->sc_ioh_analog, pll->reg);
   1072 	uint32_t div = __SHIFTOUT(v, pll->mask);
   1073 	uint32_t num = bus_space_read_4(sc->sc_iot, sc->sc_ioh_analog,
   1074 	    pll->reg + PLL_AUDIO_VIDEO_NUM_OFFSET);
   1075 	uint32_t denom = bus_space_read_4(sc->sc_iot, sc->sc_ioh_analog,
   1076 	    pll->reg + PLL_AUDIO_VIDEO_DENOM_OFFSET);
   1077 
   1078 	uint64_t tmp = freq * num / denom;
   1079 
   1080 	return freq * div + tmp;
   1081 }
   1082 
   1083 static u_int
   1084 imxccm_clk_get_rate_pll_enet(struct imx6ccm_softc *sc,
   1085     struct imx6_clk *iclk, const u_int rate_parent)
   1086 {
   1087 	struct imx6_clk_pll *pll = &iclk->clk.pll;
   1088 
   1089 	KASSERT(pll->type == IMX6_CLK_PLL_ENET);
   1090 
   1091 	return pll->ref;
   1092 }
   1093 
   1094 static u_int
   1095 imxccm_clk_get_rate_fixed_factor(struct imx6ccm_softc *sc, struct imx6_clk *iclk)
   1096 {
   1097 	struct imx6_clk_fixed_factor *fixed_factor = &iclk->clk.fixed_factor;
   1098 	struct imx6_clk *parent;
   1099 
   1100 	KASSERT(iclk->type == IMX6_CLK_FIXED_FACTOR);
   1101 
   1102 	parent = imx6_clk_find(iclk->parent);
   1103 	KASSERT(parent != NULL);
   1104 
   1105 	uint64_t rate_parent = imxccm_clk_get_rate(sc, &parent->base);
   1106 
   1107 	return rate_parent * fixed_factor->mult / fixed_factor->div;
   1108 }
   1109 
   1110 static u_int
   1111 imxccm_clk_get_rate_pll(struct imx6ccm_softc *sc, struct imx6_clk *iclk)
   1112 {
   1113 	struct imx6_clk_pll *pll = &iclk->clk.pll;
   1114 	struct imx6_clk *parent;
   1115 
   1116 	KASSERT(iclk->type == IMX6_CLK_PLL);
   1117 
   1118 	parent = imx6_clk_find(iclk->parent);
   1119 	KASSERT(parent != NULL);
   1120 
   1121 	uint64_t rate_parent = imxccm_clk_get_rate(sc, &parent->base);
   1122 
   1123 	switch(pll->type) {
   1124 	case IMX6_CLK_PLL_GENERIC:
   1125 		return imxccm_clk_get_rate_pll_generic(sc, iclk, rate_parent);
   1126 	case IMX6_CLK_PLL_SYS:
   1127 		return imxccm_clk_get_rate_pll_sys(sc, iclk, rate_parent);
   1128 	case IMX6_CLK_PLL_USB:
   1129 		return imxccm_clk_get_rate_pll_generic(sc, iclk, rate_parent);
   1130 	case IMX6_CLK_PLL_AUDIO_VIDEO:
   1131 		return imxccm_clk_get_rate_pll_audio_video(sc, iclk, rate_parent);
   1132 	case IMX6_CLK_PLL_ENET:
   1133 		return imxccm_clk_get_rate_pll_enet(sc, iclk, rate_parent);
   1134 	default:
   1135 		panic("imx6: unknown pll type %d", iclk->type);
   1136 	}
   1137 }
   1138 
   1139 static u_int
   1140 imxccm_clk_get_rate_div(struct imx6ccm_softc *sc, struct imx6_clk *iclk)
   1141 {
   1142 	struct imx6_clk_div *div = &iclk->clk.div;
   1143 	struct imx6_clk *parent;
   1144 
   1145 	KASSERT(iclk->type == IMX6_CLK_DIV);
   1146 
   1147 	parent = imx6_clk_find(iclk->parent);
   1148 	KASSERT(parent != NULL);
   1149 
   1150 	u_int rate = imxccm_clk_get_rate(sc, &parent->base);
   1151 
   1152 	bus_space_handle_t ioh;
   1153 	if (div->base == IMX6_CLK_REG_CCM_ANALOG)
   1154 		ioh = sc->sc_ioh_analog;
   1155 	else
   1156 		ioh = sc->sc_ioh;
   1157 
   1158 	uint32_t v = bus_space_read_4(sc->sc_iot, ioh, div->reg);
   1159 	uint32_t n = __SHIFTOUT(v, div->mask);
   1160 
   1161 	if (div->type == IMX6_CLK_DIV_TABLE) {
   1162 		KASSERT(div->tbl != NULL);
   1163 
   1164 		for (int i = 0; div->tbl[i] != 0; i++)
   1165 			if (i == n)
   1166 				rate /= div->tbl[i];
   1167 	} else {
   1168 		rate /= n + 1;
   1169 	}
   1170 
   1171 	return rate;
   1172 }
   1173 
   1174 static u_int
   1175 imxccm_clk_get_rate_pfd(struct imx6ccm_softc *sc, struct imx6_clk *iclk)
   1176 {
   1177 	struct imx6_clk_pfd *pfd = &iclk->clk.pfd;
   1178 	struct imx6_clk *parent;
   1179 
   1180 	KASSERT(iclk->type == IMX6_CLK_PFD);
   1181 
   1182 	parent = imx6_clk_find(iclk->parent);
   1183 	KASSERT(parent != NULL);
   1184 
   1185 	uint64_t rate_parent = imxccm_clk_get_rate(sc, &parent->base);
   1186 
   1187 	uint32_t v = bus_space_read_4(sc->sc_iot, sc->sc_ioh_analog, pfd->reg);
   1188 	uint32_t n = __SHIFTOUT(v, __BITS(5, 0) << (pfd->index * 8));
   1189 
   1190 	KASSERT(n != 0);
   1191 
   1192 	return (rate_parent * 18) / n;
   1193 }
   1194 
   1195 static int
   1196 imxccm_clk_mux_wait(struct imx6ccm_softc *sc, struct imx6_clk_mux *mux)
   1197 {
   1198 	KASSERT(mux->busy_reg == 0);
   1199 	KASSERT(mux->busy_mask == 0);
   1200 
   1201 	bus_space_handle_t ioh;
   1202 	if (mux->base == IMX6_CLK_REG_CCM_ANALOG)
   1203 		ioh = sc->sc_ioh_analog;
   1204 	else
   1205 		ioh = sc->sc_ioh;
   1206 
   1207 	while (bus_space_read_4(sc->sc_iot, ioh, mux->busy_reg) & mux->busy_mask)
   1208 		delay(10);
   1209 
   1210 	return 0;
   1211 }
   1212 
   1213 static int
   1214 imxccm_clk_set_parent_mux(struct imx6ccm_softc *sc,
   1215     struct imx6_clk *iclk, struct clk *parent)
   1216 {
   1217 	struct imx6_clk_mux *mux = &iclk->clk.mux;
   1218 	const char *pname = parent->name;
   1219 	u_int sel;
   1220 
   1221 	KASSERT(iclk->type == IMX6_CLK_MUX);
   1222 
   1223 	for (sel = 0; sel < mux->nparents; sel++)
   1224 		if (strcmp(pname, mux->parents[sel]) == 0)
   1225 			break;
   1226 
   1227 	if (sel == mux->nparents)
   1228 		return EINVAL;
   1229 
   1230 	bus_space_handle_t ioh;
   1231 	if (mux->base == IMX6_CLK_REG_CCM_ANALOG)
   1232 		ioh = sc->sc_ioh_analog;
   1233 	else
   1234 		ioh = sc->sc_ioh;
   1235 
   1236 	uint32_t v = bus_space_read_4(sc->sc_iot, ioh, mux->reg);
   1237 	v &= ~mux->mask;
   1238 	v |= __SHIFTIN(sel, mux->mask);
   1239 
   1240 	bus_space_write_4(sc->sc_iot, ioh, mux->reg, v);
   1241 
   1242 	iclk->parent = pname;
   1243 
   1244 	if (mux->type == IMX6_CLK_MUX_BUSY)
   1245 		imxccm_clk_mux_wait(sc, mux);
   1246 
   1247 	return 0;
   1248 }
   1249 
   1250 static struct imx6_clk *
   1251 imxccm_clk_get_parent_mux(struct imx6ccm_softc *sc, struct imx6_clk *iclk)
   1252 {
   1253 	struct imx6_clk_mux *mux = &iclk->clk.mux;
   1254 
   1255 	KASSERT(iclk->type == IMX6_CLK_MUX);
   1256 
   1257 	bus_space_handle_t ioh;
   1258 	if (mux->base == IMX6_CLK_REG_CCM_ANALOG)
   1259 		ioh = sc->sc_ioh_analog;
   1260 	else
   1261 		ioh = sc->sc_ioh;
   1262 
   1263 	uint32_t v = bus_space_read_4(sc->sc_iot, ioh, mux->reg);
   1264 	u_int sel = __SHIFTOUT(v, mux->mask);
   1265 
   1266 	KASSERT(sel < mux->nparents);
   1267 
   1268 	iclk->parent = mux->parents[sel];
   1269 
   1270 	return imx6_clk_find(iclk->parent);
   1271 }
   1272 
   1273 static int
   1274 imxccm_clk_set_rate_pll(struct imx6ccm_softc *sc,
   1275     struct imx6_clk *iclk, u_int rate)
   1276 {
   1277 	/* ToDo */
   1278 
   1279 	return EOPNOTSUPP;
   1280 }
   1281 
   1282 static int
   1283 imxccm_clk_set_rate_div(struct imx6ccm_softc *sc,
   1284     struct imx6_clk *iclk, u_int rate)
   1285 {
   1286 	struct imx6_clk_div *div = &iclk->clk.div;
   1287 	struct imx6_clk *parent;
   1288 
   1289 	KASSERT(iclk->type == IMX6_CLK_DIV);
   1290 
   1291 	parent = imx6_clk_find(iclk->parent);
   1292 	KASSERT(parent != NULL);
   1293 
   1294 	u_int rate_parent = imxccm_clk_get_rate(sc, &parent->base);
   1295 	u_int divider = uimax(1, rate_parent / rate);
   1296 
   1297 	bus_space_handle_t ioh;
   1298 	if (div->base == IMX6_CLK_REG_CCM_ANALOG)
   1299 		ioh = sc->sc_ioh_analog;
   1300 	else
   1301 		ioh = sc->sc_ioh;
   1302 
   1303 	uint32_t v = bus_space_read_4(sc->sc_iot, ioh, div->reg);
   1304 	v &= ~div->mask;
   1305 	if (div->type == IMX6_CLK_DIV_TABLE) {
   1306 		int n = -1;
   1307 
   1308 		KASSERT(div->tbl != NULL);
   1309 		for (int i = 0; div->tbl[i] != 0; i++)
   1310 			if (div->tbl[i] == divider)
   1311 				n = i;
   1312 
   1313 		if (n >= 0)
   1314 			v |= __SHIFTIN(n, div->mask);
   1315 		else
   1316 			return EINVAL;
   1317 	} else {
   1318 		v |= __SHIFTIN(divider - 1, div->mask);
   1319 	}
   1320 	bus_space_write_4(sc->sc_iot, ioh, div->reg, v);
   1321 
   1322 	return 0;
   1323 }
   1324 
   1325 /*
   1326  * CLK Driver APIs
   1327  */
   1328 static struct clk *
   1329 imxccm_clk_get(void *priv, const char *name)
   1330 {
   1331 	struct imx6_clk *iclk;
   1332 
   1333 	iclk = imx6_clk_find(name);
   1334 	if (iclk == NULL)
   1335 		return NULL;
   1336 
   1337 	atomic_inc_uint(&iclk->refcnt);
   1338 
   1339 	return &iclk->base;
   1340 }
   1341 
   1342 static void
   1343 imxccm_clk_put(void *priv, struct clk *clk)
   1344 {
   1345 	struct imx6_clk *iclk = (struct imx6_clk *)clk;
   1346 
   1347 	KASSERT(iclk->refcnt > 0);
   1348 
   1349 	atomic_dec_uint(&iclk->refcnt);
   1350 }
   1351 
   1352 static u_int
   1353 imxccm_clk_get_rate(void *priv, struct clk *clk)
   1354 {
   1355 	struct imx6_clk *iclk = (struct imx6_clk *)clk;
   1356 	struct clk *parent;
   1357 	struct imx6ccm_softc *sc = priv;
   1358 
   1359 	switch (iclk->type) {
   1360 	case IMX6_CLK_FIXED:
   1361 		return iclk->clk.fixed.rate;
   1362 	case IMX6_CLK_FIXED_FACTOR:
   1363 		return imxccm_clk_get_rate_fixed_factor(sc, iclk);
   1364 	case IMX6_CLK_PLL:
   1365 		return imxccm_clk_get_rate_pll(sc, iclk);
   1366 	case IMX6_CLK_MUX:
   1367 	case IMX6_CLK_GATE:
   1368 		parent = imxccm_clk_get_parent(sc, clk);
   1369 		return imxccm_clk_get_rate(sc, parent);
   1370 	case IMX6_CLK_DIV:
   1371 		return imxccm_clk_get_rate_div(sc, iclk);
   1372 	case IMX6_CLK_PFD:
   1373 		return imxccm_clk_get_rate_pfd(sc, iclk);
   1374 	default:
   1375 		panic("imx6: unknown clk type %d", iclk->type);
   1376 	}
   1377 }
   1378 
   1379 static int
   1380 imxccm_clk_set_rate(void *priv, struct clk *clk, u_int rate)
   1381 {
   1382 	struct imx6_clk *iclk = (struct imx6_clk *)clk;
   1383 	struct imx6ccm_softc *sc = priv;
   1384 
   1385 	switch (iclk->type) {
   1386 	case IMX6_CLK_FIXED:
   1387 	case IMX6_CLK_FIXED_FACTOR:
   1388 		return ENXIO;
   1389 	case IMX6_CLK_PLL:
   1390 		return imxccm_clk_set_rate_pll(sc, iclk, rate);
   1391 	case IMX6_CLK_MUX:
   1392 		return ENXIO;
   1393 	case IMX6_CLK_GATE:
   1394 		return ENXIO;
   1395 	case IMX6_CLK_DIV:
   1396 		return imxccm_clk_set_rate_div(sc, iclk, rate);
   1397 	case IMX6_CLK_PFD:
   1398 		return EINVAL;
   1399 	default:
   1400 		panic("imx6: unknown clk type %d", iclk->type);
   1401 	}
   1402 }
   1403 
   1404 static int
   1405 imxccm_clk_enable_pll(struct imx6ccm_softc *sc, struct imx6_clk *iclk, bool enable)
   1406 {
   1407 	struct imx6_clk_pll *pll = &iclk->clk.pll;
   1408 
   1409 	KASSERT(iclk->type == IMX6_CLK_PLL);
   1410 
   1411 	/* Power up bit */
   1412 	if (pll->type == IMX6_CLK_PLL_USB)
   1413 		enable = !enable;
   1414 
   1415 	bus_space_handle_t ioh = sc->sc_ioh_analog;
   1416 	uint32_t  v = bus_space_read_4(sc->sc_iot, ioh, pll->reg);
   1417 	if (__SHIFTOUT(v, pll->powerdown) != enable)
   1418 		return 0;
   1419 	if (enable)
   1420 		v &= ~pll->powerdown;
   1421 	else
   1422 		v |= pll->powerdown;
   1423 	bus_space_write_4(sc->sc_iot, ioh, pll->reg, v);
   1424 
   1425 	/* wait look */
   1426 	while (!(bus_space_read_4(sc->sc_iot, ioh, pll->reg) & CCM_ANALOG_PLL_LOCK))
   1427 		delay(10);
   1428 
   1429 	return 0;
   1430 }
   1431 
   1432 static int
   1433 imxccm_clk_enable_gate(struct imx6ccm_softc *sc, struct imx6_clk *iclk, bool enable)
   1434 {
   1435 	struct imx6_clk_gate *gate = &iclk->clk.gate;
   1436 
   1437 	KASSERT(iclk->type == IMX6_CLK_GATE);
   1438 
   1439 	bus_space_handle_t ioh;
   1440 	if (gate->base == IMX6_CLK_REG_CCM_ANALOG)
   1441 		ioh = sc->sc_ioh_analog;
   1442 	else
   1443 		ioh = sc->sc_ioh;
   1444 
   1445 	uint32_t v = bus_space_read_4(sc->sc_iot, ioh, gate->reg);
   1446 	if (enable) {
   1447 		if (gate->exclusive_mask)
   1448 			v &= ~gate->exclusive_mask;
   1449 		v |= gate->mask;
   1450 	} else {
   1451 		if (gate->exclusive_mask)
   1452 			v |= gate->exclusive_mask;
   1453 		v &= ~gate->mask;
   1454 	}
   1455 	bus_space_write_4(sc->sc_iot, ioh, gate->reg, v);
   1456 
   1457 	return 0;
   1458 }
   1459 
   1460 static int
   1461 imxccm_clk_enable(void *priv, struct clk *clk)
   1462 {
   1463 	struct imx6_clk *iclk = (struct imx6_clk *)clk;
   1464 	struct imx6_clk *parent = NULL;
   1465 	struct imx6ccm_softc *sc = priv;
   1466 
   1467 	if ((parent = imx6_clk_find(iclk->parent)) != NULL)
   1468 		imxccm_clk_enable(sc, &parent->base);
   1469 
   1470 	switch (iclk->type) {
   1471 	case IMX6_CLK_FIXED:
   1472 	case IMX6_CLK_FIXED_FACTOR:
   1473 		return 0;	/* always on */
   1474 	case IMX6_CLK_PLL:
   1475 		return imxccm_clk_enable_pll(sc, iclk, true);
   1476 	case IMX6_CLK_MUX:
   1477 	case IMX6_CLK_DIV:
   1478 	case IMX6_CLK_PFD:
   1479 		return 0;
   1480 	case IMX6_CLK_GATE:
   1481 		return imxccm_clk_enable_gate(sc, iclk, true);
   1482 	default:
   1483 		panic("imx6: unknown clk type %d", iclk->type);
   1484 	}
   1485 }
   1486 
   1487 static int
   1488 imxccm_clk_disable(void *priv, struct clk *clk)
   1489 {
   1490 	struct imx6_clk *iclk = (struct imx6_clk *)clk;
   1491 	struct imx6ccm_softc *sc = priv;
   1492 
   1493 	switch (iclk->type) {
   1494 	case IMX6_CLK_FIXED:
   1495 	case IMX6_CLK_FIXED_FACTOR:
   1496 		return EINVAL;	/* always on */
   1497 	case IMX6_CLK_PLL:
   1498 		return imxccm_clk_enable_pll(sc, iclk, false);
   1499 	case IMX6_CLK_MUX:
   1500 	case IMX6_CLK_DIV:
   1501 	case IMX6_CLK_PFD:
   1502 		return EINVAL;
   1503 	case IMX6_CLK_GATE:
   1504 		return imxccm_clk_enable_gate(sc, iclk, false);
   1505 	default:
   1506 		panic("imx6: unknown clk type %d", iclk->type);
   1507 	}
   1508 }
   1509 
   1510 static int
   1511 imxccm_clk_set_parent(void *priv, struct clk *clk, struct clk *parent)
   1512 {
   1513 	struct imx6_clk *iclk = (struct imx6_clk *)clk;
   1514 	struct imx6ccm_softc *sc = priv;
   1515 
   1516 	switch (iclk->type) {
   1517 	case IMX6_CLK_FIXED:
   1518 	case IMX6_CLK_FIXED_FACTOR:
   1519 	case IMX6_CLK_PLL:
   1520 	case IMX6_CLK_GATE:
   1521 	case IMX6_CLK_DIV:
   1522 	case IMX6_CLK_PFD:
   1523 		return EINVAL;
   1524 	case IMX6_CLK_MUX:
   1525 		return imxccm_clk_set_parent_mux(sc, iclk, parent);
   1526 	default:
   1527 		panic("imx6: unknown clk type %d", iclk->type);
   1528 	}
   1529 }
   1530 
   1531 static struct clk *
   1532 imxccm_clk_get_parent(void *priv, struct clk *clk)
   1533 {
   1534 	struct imx6_clk *iclk = (struct imx6_clk *)clk;
   1535 	struct imx6_clk *parent = NULL;
   1536 	struct imx6ccm_softc *sc = priv;
   1537 
   1538 	switch (iclk->type) {
   1539 	case IMX6_CLK_FIXED:
   1540 	case IMX6_CLK_FIXED_FACTOR:
   1541 	case IMX6_CLK_PLL:
   1542 	case IMX6_CLK_GATE:
   1543 	case IMX6_CLK_DIV:
   1544 	case IMX6_CLK_PFD:
   1545 		if (iclk->parent != NULL)
   1546 			parent = imx6_clk_find(iclk->parent);
   1547 		break;
   1548 	case IMX6_CLK_MUX:
   1549 		parent = imxccm_clk_get_parent_mux(sc, iclk);
   1550 		break;
   1551 	default:
   1552 		panic("imx6: unknown clk type %d", iclk->type);
   1553 	}
   1554 
   1555 	return (struct clk *)parent;
   1556 }
   1557