/* $NetBSD: imx7_ccm.c,v 1.2 2016/10/20 16:50:11 ryo Exp $ */ /* * Copyright (c) 2010-2012, 2014 Genetec Corporation. All rights reserved. * Written by Hashimoto Kenichi for Genetec Corporation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Clock Controller Module (CCM) for i.MX7 */ #include __KERNEL_RCSID(0, "$NetBSD: imx7_ccm.c,v 1.2 2016/10/20 16:50:11 ryo Exp $"); #include "opt_imx.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CCM_DEBUG int ccm_debug = 1; #endif struct imxccm_softc { device_t sc_dev; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; bus_space_handle_t sc_ioh_analog; /* for sysctl */ struct sysctllog *sc_log; int sc_sysctlnode_arm_pll; int sc_sysctlnode_sys_pll; int sc_sysctlnode_enet_pll; int sc_sysctlnode_audio_pll; int sc_sysctlnode_video_pll; int sc_sysctlnode_ddr_pll; int sc_sysctlnode_usb_pll; int sc_sysctlnode_arm_a7_clk; int sc_sysctlnode_arm_m4_clk; }; const struct imx7clkroottbl { int clksrc[8]; uint32_t targetroot; int type; #define CLKTYPE_CORE 0 #define CLKTYPE_DRAM 1 #define CLKTYPE_DRAM_PHYM 2 #define CLKTYPE_IP 3 #define CLKTYPE_AHB 4 #define CLKTYPE_BUS 5 } imx7clkroottbl[] = { [IMX7CLK_ARM_A7_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ARM_A7_CLK_ROOT, .type = CLKTYPE_CORE, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ARM_PLL, IMX7CLK_ENET_PLL_DIV2, IMX7CLK_DDR_PLL, IMX7CLK_SYS_PLL, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_AUDIO_PLL, IMX7CLK_USB_PLL } }, [IMX7CLK_ARM_M4_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ARM_M4_CLK_ROOT, .type = CLKTYPE_BUS, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_SYS_PLL_PFD2, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_USB_PLL } }, [IMX7CLK_MAIN_AXI_CLK_ROOT] = { .targetroot = CCM_CLKROOT_MAIN_AXI_CLK_ROOT, .type = CLKTYPE_BUS, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD1, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_SYS_PLL_PFD5, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_SYS_PLL_PFD7 } }, [IMX7CLK_DISP_AXI_CLK_ROOT] = { .targetroot = CCM_CLKROOT_DISP_AXI_CLK_ROOT, .type = CLKTYPE_BUS, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD1, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_SYS_PLL_PFD6, IMX7CLK_SYS_PLL_PFD7, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_ENET_AXI_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ENET_AXI_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_SYS_PLL_PFD4 } }, [IMX7CLK_NAND_USDHC_BUS_CLK_ROOT] = { .targetroot = CCM_CLKROOT_NAND_USDHC_BUS_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_AHB_CLK_ROOT, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_SYS_PLL_PFD2_DIV2, IMX7CLK_SYS_PLL_PFD6, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_AUDIO_PLL } }, [IMX7CLK_AHB_CLK_ROOT] = { .targetroot = CCM_CLKROOT_AHB_CLK_ROOT, .type = CLKTYPE_AHB, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_USB_PLL, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_IPG_CLK_ROOT] = { .targetroot = CCM_CLKROOT_IPG_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_AHB_CLK_ROOT, -1, -1, -1, -1, -1, -1, -1 } }, [IMX7CLK_DRAM_PHYM_CLK_ROOT] = { .targetroot = CCM_CLKROOT_DRAM_PHYM_CLK_ROOT, .type = CLKTYPE_DRAM_PHYM, .clksrc = { IMX7CLK_DDR_PLL, IMX7CLK_DRAM_PHYM_ALT_CLK_ROOT, -1, -1, -1, -1, -1, -1 } }, [IMX7CLK_DRAM_CLK_ROOT] = { .targetroot = CCM_CLKROOT_DRAM_CLK_ROOT, .type = CLKTYPE_DRAM, .clksrc = { IMX7CLK_DDR_PLL, IMX7CLK_DRAM_ALT_CLK_ROOT, -1, -1, -1, -1, -1, -1 } }, [IMX7CLK_DRAM_PHYM_ALT_CLK_ROOT] = { .targetroot = CCM_CLKROOT_DRAM_PHYM_ALT_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_SYS_PLL, IMX7CLK_ENET_PLL_DIV2, IMX7CLK_USB_PLL, IMX7CLK_SYS_PLL_PFD7, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_DRAM_ALT_CLK_ROOT] = { .targetroot = CCM_CLKROOT_DRAM_ALT_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_SYS_PLL, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_USB_PLL, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_AUDIO_PLL, IMX7CLK_SYS_PLL_PFD2 } }, [IMX7CLK_USB_HSIC_CLK_ROOT] = { .targetroot = CCM_CLKROOT_USB_HSIC_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL, IMX7CLK_USB_PLL, IMX7CLK_SYS_PLL_PFD3, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_SYS_PLL_PFD5, IMX7CLK_SYS_PLL_PFD6, IMX7CLK_SYS_PLL_PFD7 } }, [IMX7CLK_PCIE_CTRL_CLK_ROOT] = { .targetroot = CCM_CLKROOT_PCIE_CTRL_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_SYS_PLL_PFD2, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV2, IMX7CLK_SYS_PLL_PFD1, IMX7CLK_SYS_PLL_PFD6 } }, [IMX7CLK_PCIE_PHY_CLK_ROOT] = { .targetroot = CCM_CLKROOT_PCIE_PHY_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_ENET_PLL_DIV2, IMX7CLK_EXT_CLK1, IMX7CLK_EXT_CLK2, IMX7CLK_EXT_CLK3, IMX7CLK_EXT_CLK4, IMX7CLK_SYS_PLL_PFD0 } }, [IMX7CLK_EPDC_PIXEL_CLK_ROOT] = { .targetroot = CCM_CLKROOT_EPDC_PIXEL_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD1, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_SYS_PLL, IMX7CLK_SYS_PLL_PFD5, IMX7CLK_SYS_PLL_PFD6, IMX7CLK_SYS_PLL_PFD7, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_LCDIF_PIXEL_CLK_ROOT] = { .targetroot = CCM_CLKROOT_LCDIF_PIXEL_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD5, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_EXT_CLK3, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_SYS_PLL_PFD2, IMX7CLK_VIDEO_PLL, IMX7CLK_USB_PLL } }, [IMX7CLK_MIPI_DSI_CLK_ROOT] = { .targetroot = CCM_CLKROOT_MIPI_DSI_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD5, IMX7CLK_SYS_PLL_PFD3, IMX7CLK_SYS_PLL, IMX7CLK_SYS_PLL_PFD0_DIV2, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_VIDEO_PLL, IMX7CLK_AUDIO_PLL } }, [IMX7CLK_MIPI_CSI_CLK_ROOT] = { .targetroot = CCM_CLKROOT_MIPI_CSI_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_SYS_PLL_PFD3, IMX7CLK_SYS_PLL, IMX7CLK_SYS_PLL_PFD0_DIV2, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_VIDEO_PLL, IMX7CLK_AUDIO_PLL } }, [IMX7CLK_MIPI_DPHY_REF_CLK_ROOT] = { .targetroot = CCM_CLKROOT_MIPI_DPHY_REF_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_SYS_PLL_PFD5, IMX7CLK_REF_1M, IMX7CLK_EXT_CLK2, IMX7CLK_VIDEO_PLL, IMX7CLK_EXT_CLK3 } }, [IMX7CLK_SAI1_CLK_ROOT] = { .targetroot = CCM_CLKROOT_SAI1_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2_DIV2, IMX7CLK_AUDIO_PLL, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_VIDEO_PLL, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_EXT_CLK2 } }, [IMX7CLK_SAI2_CLK_ROOT] = { .targetroot = CCM_CLKROOT_SAI2_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2_DIV2, IMX7CLK_AUDIO_PLL, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_VIDEO_PLL, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_EXT_CLK2 } }, [IMX7CLK_SAI3_CLK_ROOT] = { .targetroot = CCM_CLKROOT_SAI3_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2_DIV2, IMX7CLK_AUDIO_PLL, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_VIDEO_PLL, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_EXT_CLK3 } }, [IMX7CLK_ENET1_REF_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ENET1_REF_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_ENET_PLL_DIV20, IMX7CLK_ENET_PLL_DIV40, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_EXT_CLK4 } }, [IMX7CLK_ENET1_TIME_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ENET1_TIME_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK1, IMX7CLK_EXT_CLK2, IMX7CLK_EXT_CLK3, IMX7CLK_EXT_CLK4, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_ENET2_REF_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ENET2_REF_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_ENET_PLL_DIV20, IMX7CLK_ENET_PLL_DIV40, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_EXT_CLK4 } }, [IMX7CLK_ENET2_TIME_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ENET2_TIME_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK1, IMX7CLK_EXT_CLK2, IMX7CLK_EXT_CLK3, IMX7CLK_EXT_CLK4, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_ENET_PHY_REF_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ENET_PHY_REF_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV40, IMX7CLK_ENET_PLL_DIV20, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_SYS_PLL_PFD3 } }, [IMX7CLK_EIM_CLK_ROOT] = { .targetroot = CCM_CLKROOT_EIM_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2_DIV2, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_SYS_PLL_PFD2, IMX7CLK_SYS_PLL_PFD3, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_USB_PLL } }, [IMX7CLK_NAND_CLK_ROOT] = { .targetroot = CCM_CLKROOT_NAND_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_SYS_PLL_PFD3, IMX7CLK_ENET_PLL_DIV2, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_QSPI_CLK_ROOT] = { .targetroot = CCM_CLKROOT_QSPI_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV2, IMX7CLK_SYS_PLL_PFD3, IMX7CLK_SYS_PLL_PFD2, IMX7CLK_SYS_PLL_PFD6, IMX7CLK_SYS_PLL_PFD7 } }, [IMX7CLK_USDHC1_CLK_ROOT] = { .targetroot = CCM_CLKROOT_USDHC1_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV2, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_SYS_PLL_PFD2, IMX7CLK_SYS_PLL_PFD6, IMX7CLK_SYS_PLL_PFD7 } }, [IMX7CLK_USDHC2_CLK_ROOT] = { .targetroot = CCM_CLKROOT_USDHC2_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV2, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_SYS_PLL_PFD2, IMX7CLK_SYS_PLL_PFD6, IMX7CLK_SYS_PLL_PFD7 } }, [IMX7CLK_USDHC3_CLK_ROOT] = { .targetroot = CCM_CLKROOT_USDHC3_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV2, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_SYS_PLL_PFD2, IMX7CLK_SYS_PLL_PFD6, IMX7CLK_SYS_PLL_PFD7 } }, [IMX7CLK_CAN1_CLK_ROOT] = { .targetroot = CCM_CLKROOT_CAN1_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_SYS_PLL, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_USB_PLL, IMX7CLK_EXT_CLK1, IMX7CLK_EXT_CLK4 } }, [IMX7CLK_CAN2_CLK_ROOT] = { .targetroot = CCM_CLKROOT_CAN2_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_SYS_PLL, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_USB_PLL, IMX7CLK_EXT_CLK1, IMX7CLK_EXT_CLK3 } }, [IMX7CLK_I2C1_CLK_ROOT] = { .targetroot = CCM_CLKROOT_I2C1_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_ENET_PLL_DIV20, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_USB_PLL, IMX7CLK_SYS_PLL_PFD2_DIV2 } }, [IMX7CLK_I2C2_CLK_ROOT] = { .targetroot = CCM_CLKROOT_I2C2_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_ENET_PLL_DIV20, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_USB_PLL, IMX7CLK_SYS_PLL_PFD2_DIV2 } }, [IMX7CLK_I2C3_CLK_ROOT] = { .targetroot = CCM_CLKROOT_I2C3_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_ENET_PLL_DIV20, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_USB_PLL, IMX7CLK_SYS_PLL_PFD2_DIV2 } }, [IMX7CLK_I2C4_CLK_ROOT] = { .targetroot = CCM_CLKROOT_I2C4_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_ENET_PLL_DIV20, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_USB_PLL, IMX7CLK_SYS_PLL_PFD2_DIV2 } }, [IMX7CLK_UART1_CLK_ROOT] = { .targetroot = CCM_CLKROOT_UART1_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL, IMX7CLK_EXT_CLK2, IMX7CLK_EXT_CLK4, IMX7CLK_USB_PLL } }, [IMX7CLK_UART2_CLK_ROOT] = { .targetroot = CCM_CLKROOT_UART2_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL, IMX7CLK_EXT_CLK2, IMX7CLK_EXT_CLK3, IMX7CLK_USB_PLL } }, [IMX7CLK_UART3_CLK_ROOT] = { .targetroot = CCM_CLKROOT_UART3_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL, IMX7CLK_EXT_CLK2, IMX7CLK_EXT_CLK4, IMX7CLK_USB_PLL } }, [IMX7CLK_UART4_CLK_ROOT] = { .targetroot = CCM_CLKROOT_UART4_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL, IMX7CLK_EXT_CLK2, IMX7CLK_EXT_CLK3, IMX7CLK_USB_PLL } }, [IMX7CLK_UART5_CLK_ROOT] = { .targetroot = CCM_CLKROOT_UART5_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL, IMX7CLK_EXT_CLK2, IMX7CLK_EXT_CLK4, IMX7CLK_USB_PLL } }, [IMX7CLK_UART6_CLK_ROOT] = { .targetroot = CCM_CLKROOT_UART6_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL, IMX7CLK_EXT_CLK2, IMX7CLK_EXT_CLK3, IMX7CLK_USB_PLL } }, [IMX7CLK_UART7_CLK_ROOT] = { .targetroot = CCM_CLKROOT_UART7_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL, IMX7CLK_EXT_CLK2, IMX7CLK_EXT_CLK4, IMX7CLK_USB_PLL } }, [IMX7CLK_ECSPI1_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ECSPI1_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_SYS_PLL, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_USB_PLL } }, [IMX7CLK_ECSPI2_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ECSPI2_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_SYS_PLL, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_USB_PLL } }, [IMX7CLK_ECSPI3_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ECSPI3_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_SYS_PLL, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_USB_PLL } }, [IMX7CLK_ECSPI4_CLK_ROOT] = { .targetroot = CCM_CLKROOT_ECSPI4_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_SYS_PLL, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_ENET_PLL_DIV4, IMX7CLK_USB_PLL } }, [IMX7CLK_PWM1_CLK_ROOT] = { .targetroot = CCM_CLKROOT_PWM1_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK1, IMX7CLK_REF_1M, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_PWM2_CLK_ROOT] = { .targetroot = CCM_CLKROOT_PWM2_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK1, IMX7CLK_REF_1M, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_PWM3_CLK_ROOT] = { .targetroot = CCM_CLKROOT_PWM3_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK2, IMX7CLK_REF_1M, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_PWM4_CLK_ROOT] = { .targetroot = CCM_CLKROOT_PWM4_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK2, IMX7CLK_REF_1M, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_FLEXTIMER1_CLK_ROOT] = { .targetroot = CCM_CLKROOT_FLEXTIMER1_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK3, IMX7CLK_REF_1M, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_FLEXTIMER2_CLK_ROOT] = { .targetroot = CCM_CLKROOT_FLEXTIMER2_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK3, IMX7CLK_REF_1M, IMX7CLK_VIDEO_PLL } }, [IMX7CLK_SIM1_CLK_ROOT] = { .targetroot = CCM_CLKROOT_SIM1_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2_DIV2, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_USB_PLL, IMX7CLK_AUDIO_PLL, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_SYS_PLL_PFD7 } }, [IMX7CLK_SIM2_CLK_ROOT] = { .targetroot = CCM_CLKROOT_SIM2_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2_DIV2, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_USB_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_SYS_PLL_PFD7 } }, [IMX7CLK_GPT1_CLK_ROOT] = { .targetroot = CCM_CLKROOT_GPT1_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_VIDEO_PLL, IMX7CLK_REF_1M, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK1 } }, [IMX7CLK_GPT2_CLK_ROOT] = { .targetroot = CCM_CLKROOT_GPT2_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_VIDEO_PLL, IMX7CLK_REF_1M, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK2 } }, [IMX7CLK_GPT3_CLK_ROOT] = { .targetroot = CCM_CLKROOT_GPT3_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_VIDEO_PLL, IMX7CLK_REF_1M, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK3 } }, [IMX7CLK_GPT4_CLK_ROOT] = { .targetroot = CCM_CLKROOT_GPT4_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_ENET_PLL_DIV10, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_ENET_PLL_DIV25, IMX7CLK_VIDEO_PLL, IMX7CLK_REF_1M, IMX7CLK_AUDIO_PLL, IMX7CLK_EXT_CLK4 } }, [IMX7CLK_TRACE_CLK_ROOT] = { .targetroot = CCM_CLKROOT_TRACE_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2_DIV2, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_USB_PLL, IMX7CLK_EXT_CLK2, IMX7CLK_EXT_CLK3 } }, [IMX7CLK_WDOG_CLK_ROOT] = { .targetroot = CCM_CLKROOT_WDOG_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2_DIV2, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_USB_PLL, IMX7CLK_REF_1M, IMX7CLK_SYS_PLL_PFD1_DIV2 } }, [IMX7CLK_CSI_MCLK_CLK_ROOT] = { .targetroot = CCM_CLKROOT_CSI_MCLK_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2_DIV2, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_USB_PLL } }, [IMX7CLK_AUDIO_MCLK_CLK_ROOT] = { .targetroot = CCM_CLKROOT_AUDIO_MCLK_CLK_ROOT, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_PFD2_DIV2, IMX7CLK_SYS_PLL_DIV4, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_ENET_PLL_DIV8, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_USB_PLL } }, [IMX7CLK_CCM_CLKO1] = { .targetroot = CCM_CLKROOT_CCM_CLKO1, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_SYS_PLL_PFD0_DIV2, IMX7CLK_SYS_PLL_PFD3, IMX7CLK_ENET_PLL_DIV2, IMX7CLK_DDR_PLL_DIV2, IMX7CLK_REF_1M } }, [IMX7CLK_CCM_CLKO2] = { .targetroot = CCM_CLKROOT_CCM_CLKO2, .type = CLKTYPE_IP, .clksrc = { IMX7CLK_OSC_24M, IMX7CLK_SYS_PLL_DIV2, IMX7CLK_SYS_PLL_PFD0, IMX7CLK_SYS_PLL_PFD1_DIV2, IMX7CLK_SYS_PLL_PFD4, IMX7CLK_AUDIO_PLL, IMX7CLK_VIDEO_PLL, IMX7CLK_OSC_32K } } }; struct imxccm_softc *ccm_softc; static int imxccm_match(device_t, cfdata_t, void *); static void imxccm_attach(device_t, device_t, void *); static int imxccm_sysctl_freq_helper(SYSCTLFN_PROTO); static int imxccm_sysctl_setup(struct imxccm_softc *); CFATTACH_DECL_NEW(imxccm, sizeof(struct imxccm_softc), imxccm_match, imxccm_attach, NULL, NULL); /* ARGSUSED */ static int imxccm_match(device_t parent __unused, cfdata_t cfdata __unused, void *aux) { struct axi_attach_args *aa = aux; if (ccm_softc != NULL) return 0; if (aa->aa_addr == IMX7_AIPS_BASE + AIPS1_CCM_BASE) return 1; return 0; } /* ARGSUSED */ static void imxccm_attach(device_t parent __unused, device_t self, void *aux) { struct imxccm_softc * const sc = device_private(self); struct axi_attach_args *aa = aux; bus_space_tag_t iot = aa->aa_iot; ccm_softc = sc; sc->sc_dev = self; sc->sc_iot = iot; sc->sc_log = NULL; if (bus_space_map(iot, IMX7_AIPS_BASE + AIPS1_CCM_BASE, AIPS1_CCM_SIZE, 0, &sc->sc_ioh)) { aprint_error(": can't map CCM registers\n"); return; } if (bus_space_map(iot, IMX7_AIPS_BASE + AIPS1_CCM_ANALOG_BASE, AIPS1_CCM_ANALOG_SIZE, 0, &sc->sc_ioh_analog)) { aprint_error(": can't map CCM_ANALOG registers\n"); bus_space_unmap(iot, sc->sc_ioh, AIPS1_CCM_SIZE); return; } aprint_normal(": Clock Control Module\n"); aprint_naive("\n"); imxccm_sysctl_setup(sc); aprint_verbose_dev(self, "ARM_PLL clock=%d\n", imx7_get_clock(IMX7CLK_ARM_PLL)); aprint_verbose_dev(self, "SYS_PLL clock=%d\n", imx7_get_clock(IMX7CLK_SYS_PLL)); aprint_verbose_dev(self, "ENET_PLL clock=%d\n", imx7_get_clock(IMX7CLK_ENET_PLL)); aprint_verbose_dev(self, "AUDIO_PLL clock=%d\n", imx7_get_clock(IMX7CLK_AUDIO_PLL)); aprint_verbose_dev(self, "VIDEO_PLL clock=%d\n", imx7_get_clock(IMX7CLK_VIDEO_PLL)); aprint_verbose_dev(self, "DDR_PLL clock=%d\n", imx7_get_clock(IMX7CLK_DDR_PLL)); aprint_verbose_dev(self, "USB_PLL clock=%d\n", imx7_get_clock(IMX7CLK_USB_PLL)); aprint_verbose_dev(self, "AXI clock=%d\n", imx7_get_clock(IMX7CLK_MAIN_AXI_CLK_ROOT)); aprint_verbose_dev(self, "ENET AXI clock=%d\n", imx7_get_clock(IMX7CLK_ENET_AXI_CLK_ROOT)); #ifdef CCM_DEBUG #define CLOCK_PRINT(name) \ printf(# name " clock=%d\n", imx7_get_clock(name)) CLOCK_PRINT(IMX7CLK_OSC_24M); CLOCK_PRINT(IMX7CLK_ARM_PLL); CLOCK_PRINT(IMX7CLK_SYS_PLL); CLOCK_PRINT(IMX7CLK_ENET_PLL); CLOCK_PRINT(IMX7CLK_AUDIO_PLL); CLOCK_PRINT(IMX7CLK_VIDEO_PLL); CLOCK_PRINT(IMX7CLK_DDR_PLL); CLOCK_PRINT(IMX7CLK_USB_PLL); CLOCK_PRINT(IMX7CLK_SYS_PLL_PFD0); CLOCK_PRINT(IMX7CLK_SYS_PLL_PFD1); CLOCK_PRINT(IMX7CLK_SYS_PLL_PFD2); CLOCK_PRINT(IMX7CLK_SYS_PLL_PFD3); CLOCK_PRINT(IMX7CLK_SYS_PLL_PFD4); CLOCK_PRINT(IMX7CLK_SYS_PLL_PFD5); CLOCK_PRINT(IMX7CLK_SYS_PLL_PFD6); CLOCK_PRINT(IMX7CLK_SYS_PLL_PFD7); CLOCK_PRINT(IMX7CLK_ARM_A7_CLK_ROOT); CLOCK_PRINT(IMX7CLK_ARM_M4_CLK_ROOT); CLOCK_PRINT(IMX7CLK_MAIN_AXI_CLK_ROOT); CLOCK_PRINT(IMX7CLK_ENET_AXI_CLK_ROOT); CLOCK_PRINT(IMX7CLK_AHB_CLK_ROOT); CLOCK_PRINT(IMX7CLK_IPG_CLK_ROOT); CLOCK_PRINT(IMX7CLK_DRAM_CLK_ROOT); CLOCK_PRINT(IMX7CLK_DRAM_ALT_CLK_ROOT); CLOCK_PRINT(IMX7CLK_USB_HSIC_CLK_ROOT); CLOCK_PRINT(IMX7CLK_NAND_USDHC_BUS_CLK_ROOT); CLOCK_PRINT(IMX7CLK_USDHC1_CLK_ROOT); CLOCK_PRINT(IMX7CLK_USDHC2_CLK_ROOT); CLOCK_PRINT(IMX7CLK_USDHC3_CLK_ROOT); #endif } static int imxccm_sysctl_setup(struct imxccm_softc *sc) { const struct sysctlnode *node, *imxnode, *freqnode, *pllnode; int rv; rv = sysctl_createv(&sc->sc_log, 0, NULL, &node, CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL); if (rv != 0) goto fail; rv = sysctl_createv(&sc->sc_log, 0, &node, &imxnode, 0, CTLTYPE_NODE, "imx7", NULL, NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; rv = sysctl_createv(&sc->sc_log, 0, &imxnode, &freqnode, 0, CTLTYPE_NODE, "frequency", NULL, NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; rv = sysctl_createv(&sc->sc_log, 0, &freqnode, &pllnode, 0, CTLTYPE_NODE, "pll", NULL, NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; rv = sysctl_createv(&sc->sc_log, 0, &pllnode, &node, CTLFLAG_READWRITE, CTLTYPE_INT, "arm", SYSCTL_DESCR("frequency of ARM clock (ARM_PLL)"), imxccm_sysctl_freq_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; sc->sc_sysctlnode_arm_pll = node->sysctl_num; rv = sysctl_createv(&sc->sc_log, 0, &pllnode, &node, 0, CTLTYPE_INT, "system", SYSCTL_DESCR("frequency of system clock (SYS_PLL)"), imxccm_sysctl_freq_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; sc->sc_sysctlnode_sys_pll = node->sysctl_num; rv = sysctl_createv(&sc->sc_log, 0, &pllnode, &node, 0, CTLTYPE_INT, "enet", SYSCTL_DESCR("frequency of enet clock (ENET_PLL)"), imxccm_sysctl_freq_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; sc->sc_sysctlnode_enet_pll = node->sysctl_num; rv = sysctl_createv(&sc->sc_log, 0, &pllnode, &node, 0, CTLTYPE_INT, "audio", SYSCTL_DESCR("frequency of audio clock (AUDIO_PLL)"), imxccm_sysctl_freq_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; sc->sc_sysctlnode_audio_pll = node->sysctl_num; rv = sysctl_createv(&sc->sc_log, 0, &pllnode, &node, 0, CTLTYPE_INT, "video", SYSCTL_DESCR("frequency of video clock (VIDEO_PLL)"), imxccm_sysctl_freq_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; sc->sc_sysctlnode_video_pll = node->sysctl_num; rv = sysctl_createv(&sc->sc_log, 0, &pllnode, &node, 0, CTLTYPE_INT, "ddr", SYSCTL_DESCR("frequency of DDR clock (DDR_PLL)"), imxccm_sysctl_freq_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; sc->sc_sysctlnode_ddr_pll = node->sysctl_num; rv = sysctl_createv(&sc->sc_log, 0, &pllnode, &node, 0, CTLTYPE_INT, "usb", SYSCTL_DESCR("frequency of USB clock (USB_PLL)"), imxccm_sysctl_freq_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; sc->sc_sysctlnode_usb_pll = node->sysctl_num; rv = sysctl_createv(&sc->sc_log, 0, &freqnode, &node, CTLFLAG_READWRITE, CTLTYPE_INT, "arm_a7", SYSCTL_DESCR("frequency of ARM A7 Root clock"), imxccm_sysctl_freq_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; sc->sc_sysctlnode_arm_a7_clk = node->sysctl_num; rv = sysctl_createv(&sc->sc_log, 0, &freqnode, &node, CTLFLAG_READWRITE, CTLTYPE_INT, "arm_m4", SYSCTL_DESCR("frequency of ARM M4 Root clock"), imxccm_sysctl_freq_helper, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL); if (rv != 0) goto fail; sc->sc_sysctlnode_arm_m4_clk = node->sysctl_num; return 0; fail: aprint_error_dev(sc->sc_dev, "cannot initialize sysctl (err=%d)\n", rv); sysctl_teardown(&sc->sc_log); sc->sc_log = NULL; return -1; } static int imxccm_sysctl_freq_helper(SYSCTLFN_ARGS) { struct sysctlnode node; struct imxccm_softc *sc; int value, ovalue, err; node = *rnode; sc = node.sysctl_data; /* for sysctl read */ if (rnode->sysctl_num == sc->sc_sysctlnode_arm_pll) value = imx7_get_clock(IMX7CLK_ARM_PLL); else if (rnode->sysctl_num == sc->sc_sysctlnode_sys_pll) value = imx7_get_clock(IMX7CLK_SYS_PLL); else if (rnode->sysctl_num == sc->sc_sysctlnode_enet_pll) value = imx7_get_clock(IMX7CLK_ENET_PLL); else if (rnode->sysctl_num == sc->sc_sysctlnode_audio_pll) value = imx7_get_clock(IMX7CLK_AUDIO_PLL); else if (rnode->sysctl_num == sc->sc_sysctlnode_video_pll) value = imx7_get_clock(IMX7CLK_VIDEO_PLL); else if (rnode->sysctl_num == sc->sc_sysctlnode_ddr_pll) value = imx7_get_clock(IMX7CLK_DDR_PLL); else if (rnode->sysctl_num == sc->sc_sysctlnode_usb_pll) value = imx7_get_clock(IMX7CLK_USB_PLL); else if (rnode->sysctl_num == sc->sc_sysctlnode_arm_a7_clk) value = imx7_get_clock(IMX7CLK_ARM_A7_CLK_ROOT); else if (rnode->sysctl_num == sc->sc_sysctlnode_arm_m4_clk) value = imx7_get_clock(IMX7CLK_ARM_M4_CLK_ROOT); else return EOPNOTSUPP; #ifdef SYSCTL_BY_MHZ value /= 1000 * 1000; /* Hz -> MHz */ #endif ovalue = value; node.sysctl_data = &value; err = sysctl_lookup(SYSCTLFN_CALL(&node)); if (err != 0 || newp == NULL) return err; /* for sysctl write */ if (value == ovalue) return 0; #ifdef SYSCTL_BY_MHZ value *= 1000 * 1000; /* MHz -> Hz */ #endif if (rnode->sysctl_num == sc->sc_sysctlnode_arm_pll) return imx7_set_clock(IMX7CLK_ARM_PLL, value); else if (rnode->sysctl_num == sc->sc_sysctlnode_arm_a7_clk) return imx7_set_clock(IMX7CLK_ARM_A7_CLK_ROOT, value); else if (rnode->sysctl_num == sc->sc_sysctlnode_arm_m4_clk) return imx7_set_clock(IMX7CLK_ARM_M4_CLK_ROOT, value); return EOPNOTSUPP; } uint32_t imx7_ccm_read(uint32_t reg) { if (ccm_softc == NULL) return 0; return bus_space_read_4(ccm_softc->sc_iot, ccm_softc->sc_ioh, reg); } void imx7_ccm_write(uint32_t reg, uint32_t val) { if (ccm_softc == NULL) return; bus_space_write_4(ccm_softc->sc_iot, ccm_softc->sc_ioh, reg, val); } uint32_t imx7_ccm_analog_read(uint32_t reg) { if (ccm_softc == NULL) return 0; return bus_space_read_4(ccm_softc->sc_iot, ccm_softc->sc_ioh_analog, reg); } void imx7_ccm_analog_write(uint32_t reg, uint32_t val) { if (ccm_softc == NULL) return; bus_space_write_4(ccm_softc->sc_iot, ccm_softc->sc_ioh_analog, reg, val); } static uint64_t rootclk(int clk, bool nodiv) { uint32_t d, v; uint64_t freq; /* read CCM_TARGET_ROOTxx */ v = imx7_ccm_read(imx7clkroottbl[clk].targetroot); if ((v & CCM_TARGET_ROOT_ENABLE) == 0) return 0; d = __SHIFTOUT(v, CCM_TARGET_ROOT_MUX); freq = imx7_get_clock(imx7clkroottbl[clk].clksrc[d]); #ifdef CCM_DEBUG if (ccm_debug) { printf("TARGET_ROOT[%08x]: value=%08x, mux=%d, freq=%llu\n", imx7clkroottbl[clk].targetroot, v, d, freq); } #endif if (nodiv) return freq; /* eval TARGET_ROOT[PRE_PODF] */ if ((imx7clkroottbl[clk].type != CLKTYPE_CORE) && (imx7clkroottbl[clk].type != CLKTYPE_DRAM) && (imx7clkroottbl[clk].type != CLKTYPE_DRAM_PHYM)) { d = __SHIFTOUT(v, CCM_TARGET_ROOT_PRE_PODF) + 1; freq /= d; #ifdef CCM_DEBUG if (ccm_debug) { printf("TARGET_ROOT[%08x]: pre_podf=%d, freq=%llu\n", imx7clkroottbl[clk].targetroot, d, freq); } #endif } /* eval TARGET_ROOT[POST_PODF] */ if (clk != IMX7CLK_DRAM_PHYM_CLK_ROOT) { d = __SHIFTOUT(v, CCM_TARGET_ROOT_POST_PODF) + 1; if (clk == IMX7CLK_DRAM_CLK_ROOT) d &= 7; freq /= d; #ifdef CCM_DEBUG if (ccm_debug) { printf("TARGET_ROOT[%08x]: post_podf=%d, freq=%llu\n", imx7clkroottbl[clk].targetroot, d, freq); } #endif } /* eval TARGET_ROOT[AUTO_PODF] (from u-boot source, not datasheet) */ if ((imx7clkroottbl[clk].type != CLKTYPE_AHB) && (imx7clkroottbl[clk].type != CLKTYPE_BUS)) { if (v & CCM_TARGET_ROOT_AUTO_ENABLE) { d = __SHIFTOUT(v, CCM_TARGET_ROOT_AUTO_PODF) + 1; freq /= d; #ifdef CCM_DEBUG if (ccm_debug) { printf("TARGET_ROOT[%08x]: " "auto_podf=%d, freq=%llu\n", imx7clkroottbl[clk].targetroot, d, freq); } #endif } } return freq; } /* see also iMX7 Reference Manual 5.2.6.1 Input Clocks */ uint32_t imx7_get_clock(enum imx7_clock clk) { uint32_t d, denom, num, v; uint64_t freq = 0; if (ccm_softc == NULL) return 0; switch (clk) { case IMX7CLK_OSC_24M: freq = IMX7_OSC_FREQ; /* fixed clock */ break; case IMX7CLK_REF_1M: freq = IMX7_OSC_FREQ / 24; /* fixed clock */ break; case IMX7CLK_OSC_32K: freq = IMX7_OSC_FREQ / 768; /* fixed clock */ break; case IMX7CLK_ARM_PLL: v = imx7_ccm_analog_read(CCM_ANALOG_PLL_ARM); freq = IMX7_OSC_FREQ * __SHIFTOUT(v, CCM_ANALOG_PLL_ARM_DIV_SELECT) / 2; break; case IMX7CLK_DDR_PLL: v = imx7_ccm_analog_read(CCM_ANALOG_PLL_DDR); d = __SHIFTOUT(v, CCM_ANALOG_PLL_DDR_DIV_SELECT); num = imx7_ccm_analog_read(CCM_ANALOG_PLL_DDR_NUM); denom = imx7_ccm_analog_read(CCM_ANALOG_PLL_DDR_DENOM); freq = (uint64_t)IMX7_OSC_FREQ * (d + num / denom); if (v & CCM_ANALOG_PLL_DDR_DIV2_ENABLE_CLK) freq /= 2; d = __SHIFTOUT(v, CCM_ANALOG_PLL_DDR_TEST_DIV_SELECT); switch (d) { case 0: freq /= 4; break; case 1: freq /= 2; break; case 2: case 3: break; } break; case IMX7CLK_DDR_PLL_DIV2: freq = imx7_get_clock(IMX7CLK_DDR_PLL) / 2; break; case IMX7CLK_SYS_PLL: v = imx7_ccm_analog_read(CCM_ANALOG_PLL_480); freq = IMX7_OSC_FREQ * ((v & CCM_ANALOG_PLL_480_DIV_SELECT) ? 22 : 20); break; case IMX7CLK_SYS_PLL_DIV2: freq = imx7_get_clock(IMX7CLK_SYS_PLL) / 2; break; case IMX7CLK_SYS_PLL_DIV4: freq = imx7_get_clock(IMX7CLK_SYS_PLL) / 4; break; case IMX7CLK_SYS_PLL_PFD0: freq = imx7_get_clock(IMX7CLK_SYS_PLL); v = imx7_ccm_analog_read(CCM_ANALOG_PFD_480A); freq = freq * 18 / __SHIFTOUT(v, CCM_ANALOG_PFD_480A_PDF0_FRAC); break; case IMX7CLK_SYS_PLL_PFD0_DIV2: freq = imx7_get_clock(IMX7CLK_SYS_PLL_PFD0) / 2; break; case IMX7CLK_SYS_PLL_PFD1: freq = imx7_get_clock(IMX7CLK_SYS_PLL); v = imx7_ccm_analog_read(CCM_ANALOG_PFD_480A); freq = freq * 18 / __SHIFTOUT(v, CCM_ANALOG_PFD_480A_PDF1_FRAC); break; case IMX7CLK_SYS_PLL_PFD1_DIV2: freq = imx7_get_clock(IMX7CLK_SYS_PLL_PFD1) / 2; break; case IMX7CLK_SYS_PLL_PFD2: freq = imx7_get_clock(IMX7CLK_SYS_PLL); v = imx7_ccm_analog_read(CCM_ANALOG_PFD_480A); freq = freq * 18 / __SHIFTOUT(v, CCM_ANALOG_PFD_480A_PDF2_FRAC); break; case IMX7CLK_SYS_PLL_PFD2_DIV2: freq = imx7_get_clock(IMX7CLK_SYS_PLL_PFD2) / 2; break; case IMX7CLK_SYS_PLL_PFD3: freq = imx7_get_clock(IMX7CLK_SYS_PLL); v = imx7_ccm_analog_read(CCM_ANALOG_PFD_480A); freq = freq * 18 / __SHIFTOUT(v, CCM_ANALOG_PFD_480A_PDF3_FRAC); break; case IMX7CLK_SYS_PLL_PFD4: freq = imx7_get_clock(IMX7CLK_SYS_PLL); v = imx7_ccm_analog_read(CCM_ANALOG_PFD_480B); freq = freq * 18 / __SHIFTOUT(v, CCM_ANALOG_PFD_480B_PDF4_FRAC); break; case IMX7CLK_SYS_PLL_PFD5: freq = imx7_get_clock(IMX7CLK_SYS_PLL); v = imx7_ccm_analog_read(CCM_ANALOG_PFD_480B); freq = freq * 18 / __SHIFTOUT(v, CCM_ANALOG_PFD_480B_PDF5_FRAC); break; case IMX7CLK_SYS_PLL_PFD6: freq = imx7_get_clock(IMX7CLK_SYS_PLL); v = imx7_ccm_analog_read(CCM_ANALOG_PFD_480B); freq = freq * 18 / __SHIFTOUT(v, CCM_ANALOG_PFD_480B_PDF6_FRAC); break; case IMX7CLK_SYS_PLL_PFD7: freq = imx7_get_clock(IMX7CLK_SYS_PLL); v = imx7_ccm_analog_read(CCM_ANALOG_PFD_480B); freq = freq * 18 / __SHIFTOUT(v, CCM_ANALOG_PFD_480B_PDF7_FRAC); break; case IMX7CLK_ENET_PLL: freq = IMX7_ENET_PLL_CLK; /* fixed clock */ break; case IMX7CLK_ENET_PLL_DIV2: freq = imx7_get_clock(IMX7CLK_ENET_PLL) / 2; break; case IMX7CLK_ENET_PLL_DIV4: freq = imx7_get_clock(IMX7CLK_ENET_PLL) / 4; break; case IMX7CLK_ENET_PLL_DIV8: freq = imx7_get_clock(IMX7CLK_ENET_PLL) / 8; break; case IMX7CLK_ENET_PLL_DIV10: freq = imx7_get_clock(IMX7CLK_ENET_PLL) / 10; break; case IMX7CLK_ENET_PLL_DIV20: freq = imx7_get_clock(IMX7CLK_ENET_PLL) / 20; break; case IMX7CLK_ENET_PLL_DIV25: freq = imx7_get_clock(IMX7CLK_ENET_PLL) / 25; break; case IMX7CLK_ENET_PLL_DIV40: freq = imx7_get_clock(IMX7CLK_ENET_PLL) / 40; break; case IMX7CLK_ENET_PLL_DIV50: freq = imx7_get_clock(IMX7CLK_ENET_PLL) / 50; break; case IMX7CLK_USB_PLL: freq = IMX7_USB_PLL_CLK; /* fixed clock */ break; case IMX7CLK_AUDIO_PLL: v = imx7_ccm_analog_read(CCM_ANALOG_PLL_AUDIO); d = __SHIFTOUT(v, CCM_ANALOG_PLL_AUDIO_DIV_SELECT); num = imx7_ccm_analog_read(CCM_ANALOG_PLL_AUDIO_NUM); denom = imx7_ccm_analog_read(CCM_ANALOG_PLL_AUDIO_DENOM); freq = (uint64_t)IMX7_OSC_FREQ * (d + num / denom); d = __SHIFTOUT(v, CCM_ANALOG_PLL_AUDIO_TEST_DIV_SELECT); switch (d) { case 0: freq /= 4; break; case 1: freq /= 2; break; case 2: case 3: break; } d = __SHIFTOUT(v, CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT); switch (d) { case 0: case 2: break; case 1: freq /= 2; break; case 3: freq /= 4; break; } break; case IMX7CLK_VIDEO_PLL: v = imx7_ccm_analog_read(CCM_ANALOG_PLL_VIDEO); d = __SHIFTOUT(v, CCM_ANALOG_PLL_VIDEO_DIV_SELECT); num = imx7_ccm_analog_read(CCM_ANALOG_PLL_VIDEO_NUM); denom = imx7_ccm_analog_read(CCM_ANALOG_PLL_VIDEO_DENOM); freq = (uint64_t)IMX7_OSC_FREQ * (d + num / denom); d = __SHIFTOUT(v, CCM_ANALOG_PLL_VIDEO_TEST_DIV_SELECT); switch (d) { case 0: freq /= 4; break; case 1: freq /= 2; break; case 2: case 3: break; } d = __SHIFTOUT(v, CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT); switch (d) { case 0: case 2: break; case 1: freq /= 2; break; case 3: freq /= 4; break; } break; case IMX7CLK_ARM_A7_CLK_ROOT: case IMX7CLK_ARM_M4_CLK_ROOT: case IMX7CLK_MAIN_AXI_CLK_ROOT: case IMX7CLK_DISP_AXI_CLK_ROOT: case IMX7CLK_ENET_AXI_CLK_ROOT: case IMX7CLK_NAND_USDHC_BUS_CLK_ROOT: case IMX7CLK_AHB_CLK_ROOT: case IMX7CLK_IPG_CLK_ROOT: case IMX7CLK_DRAM_PHYM_CLK_ROOT: case IMX7CLK_DRAM_CLK_ROOT: case IMX7CLK_DRAM_PHYM_ALT_CLK_ROOT: case IMX7CLK_DRAM_ALT_CLK_ROOT: case IMX7CLK_USB_HSIC_CLK_ROOT: case IMX7CLK_PCIE_CTRL_CLK_ROOT: case IMX7CLK_PCIE_PHY_CLK_ROOT: case IMX7CLK_EPDC_PIXEL_CLK_ROOT: case IMX7CLK_LCDIF_PIXEL_CLK_ROOT: case IMX7CLK_MIPI_DSI_CLK_ROOT: case IMX7CLK_MIPI_CSI_CLK_ROOT: case IMX7CLK_MIPI_DPHY_REF_CLK_ROOT: case IMX7CLK_SAI1_CLK_ROOT: case IMX7CLK_SAI2_CLK_ROOT: case IMX7CLK_SAI3_CLK_ROOT: case IMX7CLK_ENET1_REF_CLK_ROOT: case IMX7CLK_ENET1_TIME_CLK_ROOT: case IMX7CLK_ENET2_REF_CLK_ROOT: case IMX7CLK_ENET2_TIME_CLK_ROOT: case IMX7CLK_ENET_PHY_REF_CLK_ROOT: case IMX7CLK_EIM_CLK_ROOT: case IMX7CLK_NAND_CLK_ROOT: case IMX7CLK_QSPI_CLK_ROOT: case IMX7CLK_USDHC1_CLK_ROOT: case IMX7CLK_USDHC2_CLK_ROOT: case IMX7CLK_USDHC3_CLK_ROOT: case IMX7CLK_CAN1_CLK_ROOT: case IMX7CLK_CAN2_CLK_ROOT: case IMX7CLK_I2C1_CLK_ROOT: case IMX7CLK_I2C2_CLK_ROOT: case IMX7CLK_I2C3_CLK_ROOT: case IMX7CLK_I2C4_CLK_ROOT: case IMX7CLK_UART1_CLK_ROOT: case IMX7CLK_UART2_CLK_ROOT: case IMX7CLK_UART3_CLK_ROOT: case IMX7CLK_UART4_CLK_ROOT: case IMX7CLK_UART5_CLK_ROOT: case IMX7CLK_UART6_CLK_ROOT: case IMX7CLK_UART7_CLK_ROOT: case IMX7CLK_ECSPI1_CLK_ROOT: case IMX7CLK_ECSPI2_CLK_ROOT: case IMX7CLK_ECSPI3_CLK_ROOT: case IMX7CLK_ECSPI4_CLK_ROOT: case IMX7CLK_PWM1_CLK_ROOT: case IMX7CLK_PWM2_CLK_ROOT: case IMX7CLK_PWM3_CLK_ROOT: case IMX7CLK_PWM4_CLK_ROOT: case IMX7CLK_FLEXTIMER1_CLK_ROOT: case IMX7CLK_FLEXTIMER2_CLK_ROOT: case IMX7CLK_SIM1_CLK_ROOT: case IMX7CLK_SIM2_CLK_ROOT: case IMX7CLK_GPT1_CLK_ROOT: case IMX7CLK_GPT2_CLK_ROOT: case IMX7CLK_GPT3_CLK_ROOT: case IMX7CLK_GPT4_CLK_ROOT: case IMX7CLK_TRACE_CLK_ROOT: case IMX7CLK_WDOG_CLK_ROOT: case IMX7CLK_CSI_MCLK_CLK_ROOT: case IMX7CLK_AUDIO_MCLK_CLK_ROOT: case IMX7CLK_CCM_CLKO1: case IMX7CLK_CCM_CLKO2: freq = rootclk(clk, false); break; default: aprint_error_dev(ccm_softc->sc_dev, "%s: clockid %d: not supported\n", __func__, clk); return 0; } return freq; } /* * resolve two clock divisors d3 and d6. * freq = maxfreq / d3(3bit) / d6(6bit) */ static void getrootclkdiv(uint32_t maxfreq, uint32_t freq, uint32_t *d3p, uint32_t *d6p) { uint32_t c_dif, c_d3, c_d6; uint32_t dif, d3, d6; uint32_t lim, base, f; c_dif = 0xffffffff; c_d3 = c_d6 = 0; for (d3 = 0; d3 < 8; d3++) { base = 0; for (lim = 64; lim != 0; lim >>= 1) { d6 = (lim >> 1) + base; f = maxfreq / (d3 + 1) / (d6 + 1); if (freq < f) { base = d6 + 1; lim--; } dif = (freq > f) ? freq - f : f - freq; if (c_dif > dif) { c_dif = dif; c_d3 = d3; c_d6 = d6; } } } *d3p = c_d3; *d6p = c_d6; } int imx7_set_clock(enum imx7_clock clk, uint32_t freq) { uint32_t v, x; uint32_t d3, d6, maxfreq; if (ccm_softc == NULL) return 0; switch (clk) { case IMX7CLK_ARM_PLL: x = (uint64_t)freq * 2 / IMX7_OSC_FREQ; v = imx7_ccm_analog_read(CCM_ANALOG_PLL_ARM); v &= ~CCM_ANALOG_PLL_ARM_DIV_SELECT; v |= __SHIFTIN(x, CCM_ANALOG_PLL_ARM_DIV_SELECT); imx7_ccm_analog_write(CCM_ANALOG_PLL_ARM, v); break; /* core type clock */ case IMX7CLK_ARM_A7_CLK_ROOT: maxfreq = rootclk(clk, true); getrootclkdiv(maxfreq, freq, &d3, &d6); v = imx7_ccm_read(imx7clkroottbl[clk].targetroot); /* core type clocks use AUTO_PODF and POST_PODF */ v &= ~CCM_TARGET_ROOT_AUTO_PODF; v |= __SHIFTIN(d3, CCM_TARGET_ROOT_AUTO_PODF); v |= CCM_TARGET_ROOT_AUTO_ENABLE; v &= ~CCM_TARGET_ROOT_POST_PODF; v |= __SHIFTIN(d6, CCM_TARGET_ROOT_POST_PODF); imx7_ccm_write(imx7clkroottbl[clk].targetroot, v); break; /* bus type clocks */ case IMX7CLK_ARM_M4_CLK_ROOT: case IMX7CLK_MAIN_AXI_CLK_ROOT: case IMX7CLK_DISP_AXI_CLK_ROOT: maxfreq = rootclk(clk, true); getrootclkdiv(maxfreq, freq, &d3, &d6); /* bus type clocks use PRE_PODF and POST_PODF */ v = imx7_ccm_read(imx7clkroottbl[clk].targetroot); v &= ~CCM_TARGET_ROOT_PRE_PODF; v |= __SHIFTIN(d3, CCM_TARGET_ROOT_PRE_PODF); v &= ~CCM_TARGET_ROOT_POST_PODF; v |= __SHIFTIN(d6, CCM_TARGET_ROOT_POST_PODF); imx7_ccm_write(imx7clkroottbl[clk].targetroot, v); break; default: aprint_error_dev(ccm_softc->sc_dev, "%s: clockid %d: not supported\n", __func__, clk); return EINVAL; } return 0; } int imx7_pll_power(uint32_t pllreg, int on) { uint32_t v; int timeout; switch (pllreg) { case CCM_ANALOG_PLL_ENET: v = imx7_ccm_analog_read(pllreg); if (on) v &= ~CCM_ANALOG_PLL_ENET_POWERDOWN; else v |= CCM_ANALOG_PLL_ENET_POWERDOWN; imx7_ccm_analog_write(pllreg, v); for (timeout = 100000; timeout > 0; timeout--) { if (imx7_ccm_analog_read(pllreg) & CCM_ANALOG_PLL_ENET_LOCK) break; } if (timeout <= 0) break; if (on) { v &= ~CCM_ANALOG_PLL_ENET_BYPASS; v |= CCM_ANALOG_PLL_ENET_ENABLE_CLK_500MHZ; v |= CCM_ANALOG_PLL_ENET_ENABLE_CLK_250MHZ; v |= CCM_ANALOG_PLL_ENET_ENABLE_CLK_125MHZ; v |= CCM_ANALOG_PLL_ENET_ENABLE_CLK_100MHZ; v |= CCM_ANALOG_PLL_ENET_ENABLE_CLK_50MHZ; v |= CCM_ANALOG_PLL_ENET_ENABLE_CLK_40MHZ; v |= CCM_ANALOG_PLL_ENET_ENABLE_CLK_25MHZ; } else { v &= ~CCM_ANALOG_PLL_ENET_ENABLE_CLK_500MHZ; v &= ~CCM_ANALOG_PLL_ENET_ENABLE_CLK_250MHZ; v &= ~CCM_ANALOG_PLL_ENET_ENABLE_CLK_125MHZ; v &= ~CCM_ANALOG_PLL_ENET_ENABLE_CLK_100MHZ; v &= ~CCM_ANALOG_PLL_ENET_ENABLE_CLK_50MHZ; v &= ~CCM_ANALOG_PLL_ENET_ENABLE_CLK_40MHZ; v &= ~CCM_ANALOG_PLL_ENET_ENABLE_CLK_25MHZ; } imx7_ccm_analog_write(pllreg, v); return 0; case CCM_ANALOG_PLL_ARM: case CCM_ANALOG_PLL_DDR: case CCM_ANALOG_PLL_480: case CCM_ANALOG_PLL_AUDIO: case CCM_ANALOG_PLL_VIDEO: default: break; } return -1; }