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