diff options
Diffstat (limited to 'drivers/clk/imx/clk-imx6.c')
-rw-r--r-- | drivers/clk/imx/clk-imx6.c | 74 |
1 files changed, 42 insertions, 32 deletions
diff --git a/drivers/clk/imx/clk-imx6.c b/drivers/clk/imx/clk-imx6.c index ed29e8c271..bac0c73d21 100644 --- a/drivers/clk/imx/clk-imx6.c +++ b/drivers/clk/imx/clk-imx6.c @@ -1,13 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright 2011 Freescale Semiconductor, Inc. * Copyright 2011 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html */ #include <common.h> @@ -18,9 +12,9 @@ #include <of.h> #include <linux/clkdev.h> #include <linux/err.h> -#include <mach/imx6-regs.h> -#include <mach/revision.h> -#include <mach/imx6.h> +#include <mach/imx/imx6-regs.h> +#include <mach/imx/revision.h> +#include <mach/imx/imx6.h> #include <dt-bindings/clock/imx6qdl-clock.h> #include "clk.h" @@ -66,8 +60,8 @@ static inline int cpu_mx6_is_plus(void) /* Audio/Video PLL post dividers don't work on i.MX6q revision 1.0 */ static inline int cpu_has_working_video_pll_post_div(void) { - return !((cpu_is_mx6q() || cpu_is_mx6d()) && - imx_silicon_revision() == IMX_CHIP_REV_1_0); + return !((cpu_mx6_is_mx6q() || cpu_mx6_is_mx6d()) && + __imx6_cpu_revision() == IMX_CHIP_REV_1_0); } /* i.MX6 Quad/Dual/DualLite/Solo are all affected */ @@ -97,6 +91,13 @@ static const char *periph_pre_sels[] = { static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", + "osc", + "dummy", +}; + +static const char *periph2_clk2_sels[] = { + "pll3_usb_otg", + "pll2_bus", }; static const char *periph_sels[] = { @@ -112,6 +113,7 @@ static const char *periph2_sels[] = { static const char *axi_sels[] = { "periph", "pll2_pfd2_396m", + "periph", "pll3_pfd1_540m", }; @@ -137,6 +139,13 @@ static const char *enfc_sels_plus[] = { }; static const char *eim_sels[] = { + "pll2_pfd2_396m", + "pll3_usb_otg", + "axi", + "pll2_pfd0_352m", +}; + +static const char *eim_slow_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", @@ -157,8 +166,8 @@ static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", - "pll5_video", - "dummy", + "pll5_video_div", + "video_27m", "axi", "enfc", "ipu1_di0", @@ -169,7 +178,7 @@ static const char *cko1_sels[] = { "ipg", "ipg_per", "ckil", - "pll4_audio", + "pll4_audio_div", }; static const char *cko2_sels[] = { @@ -488,9 +497,9 @@ static void init_ldb_clks(struct device_node *np, void __iomem *ccm_base) of_assigned_ldb_sels(np, &sel[0][3], &sel[1][3]); for (i = 0; i < 2; i++) { - /* Warn if a glitch might have been introduced already */ + /* log if a glitch might have been introduced already */ if (sel[i][0] != LDB_DI_SEL_MMDC_CH1_AXI) { - pr_warn("ccm: ldb_di%d_sel already changed from reset value: %d\n", + pr_debug("ccm: ldb_di%d_sel already changed from reset value: %d\n", i, sel[i][0]); } @@ -579,10 +588,6 @@ static void imx6_add_video_clks(void __iomem *anab, void __iomem *cb, struct dev clks[IMX6QDL_CLK_IPU1_SEL] = imx_clk_mux("ipu1_sel", cb + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); clks[IMX6QDL_CLK_IPU2_SEL] = imx_clk_mux("ipu2_sel", cb + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); - disable_anatop_clocks(anab); - - imx6q_mmdc_ch1_mask_handshake(cb); - if (cpu_mx6_has_err009219()) { /* * The LDB_DI0/1_SEL muxes should be read-only due to a hardware @@ -618,6 +623,8 @@ static void imx6_add_video_clks(void __iomem *anab, void __iomem *cb, struct dev clks[IMX6QDL_CLK_IPU2_DI0_PRE] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", cb + 0x38, 3, 3); clks[IMX6QDL_CLK_IPU2_DI1_PRE] = imx_clk_divider("ipu2_di1_pre", "ipu2_di1_pre_sel", cb + 0x38, 12, 3); + clks[IMX6QDL_CLK_HDMI_IAHB] = imx_clk_gate2("hdmi_iahb", "ahb", cb + 0x70, 0); + clks[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "mipi_core_cfg", cb + 0x70, 4); clks[IMX6QDL_CLK_IPU1] = imx_clk_gate2("ipu1", "ipu1_podf", cb + 0x74, 0); clks[IMX6QDL_CLK_IPU1_DI0] = imx_clk_gate2("ipu1_di0", "ipu1_di0_sel", cb + 0x74, 2); clks[IMX6QDL_CLK_IPU1_DI1] = imx_clk_gate2("ipu1_di1", "ipu1_di1_sel", cb + 0x74, 4); @@ -626,6 +633,8 @@ static void imx6_add_video_clks(void __iomem *anab, void __iomem *cb, struct dev clks[IMX6QDL_CLK_LDB_DI0] = imx_clk_gate2("ldb_di0", "ldb_di0_podf", cb + 0x74, 12); clks[IMX6QDL_CLK_LDB_DI1] = imx_clk_gate2("ldb_di1", "ldb_di1_podf", cb + 0x74, 14); clks[IMX6QDL_CLK_IPU2_DI1] = imx_clk_gate2("ipu2_di1", "ipu2_di1_sel", cb + 0x74, 10); + clks[IMX6QDL_CLK_MIPI_CORE_CFG] = imx_clk_gate2("mipi_core_cfg", "video_27m", cb + 0x74, 16); + clks[IMX6QDL_CLK_VIDEO_27M] = imx_clk_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20); clk_set_parent(clks[IMX6QDL_CLK_IPU1_DI0_SEL], clks[IMX6QDL_CLK_IPU1_DI0_PRE]); clk_set_parent(clks[IMX6QDL_CLK_IPU1_DI1_SEL], clks[IMX6QDL_CLK_IPU1_DI1_PRE]); @@ -638,7 +647,7 @@ static void imx6_add_video_clks(void __iomem *anab, void __iomem *cb, struct dev clk_set_parent(clks[IMX6QDL_CLK_IPU2_DI1_PRE_SEL], clks[IMX6QDL_CLK_PLL5_VIDEO_DIV]); } -static int imx6_ccm_probe(struct device_d *dev) +static int imx6_ccm_probe(struct device *dev) { struct resource *iores; void __iomem *base, *anatop_base, *ccm_base; @@ -701,7 +710,7 @@ static int imx6_ccm_probe(struct device_d *dev) clks[IMX6QDL_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels)); clks[IMX6QDL_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels)); clks[IMX6QDL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 1, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)); - clks[IMX6QDL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)); + clks[IMX6QDL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels)); clks[IMX6QDL_CLK_AXI_SEL] = imx_clk_mux("axi_sel", base + 0x14, 6, 2, axi_sels, ARRAY_SIZE(axi_sels)); clks[IMX6QDL_CLK_USDHC1_SEL] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); clks[IMX6QDL_CLK_USDHC2_SEL] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); @@ -712,7 +721,7 @@ static int imx6_ccm_probe(struct device_d *dev) else clks[IMX6QDL_CLK_ENFC_SEL] = imx_clk_mux("enfc_sel", base + 0x2c, 16, 2, enfc_sels, ARRAY_SIZE(enfc_sels)); clks[IMX6QDL_CLK_EIM_SEL] = imx_clk_mux("eim_sel", base + 0x1c, 27, 2, eim_sels, ARRAY_SIZE(eim_sels)); - clks[IMX6QDL_CLK_EIM_SLOW_SEL] = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_sels, ARRAY_SIZE(eim_sels)); + clks[IMX6QDL_CLK_EIM_SLOW_SEL] = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_sels, ARRAY_SIZE(eim_slow_sels)); clks[IMX6QDL_CLK_VDO_AXI_SEL] = imx_clk_mux("vdo_axi_sel", base + 0x18, 11, 1, vdo_axi_sels, ARRAY_SIZE(vdo_axi_sels)); clks[IMX6QDL_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels)); clks[IMX6QDL_CLK_CKO2_SEL] = imx_clk_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels)); @@ -794,8 +803,12 @@ static int imx6_ccm_probe(struct device_d *dev) clkdev_add_physbase(clks[IMX6QDL_CLK_IPG], MX6_OCOTP_BASE_ADDR, NULL); + disable_anatop_clocks(anatop_base); + + imx6q_mmdc_ch1_mask_handshake(ccm_base); + if (IS_ENABLED(CONFIG_DRIVER_VIDEO_IMX_IPUV3)) - imx6_add_video_clks(anatop_base, ccm_base, dev->device_node); + imx6_add_video_clks(anatop_base, ccm_base, dev->of_node); writel(0xffffffff, ccm_base + CCGR0); writel(0xf0ffffff, ccm_base + CCGR1); /* gate GPU3D, GPU2D */ @@ -811,7 +824,7 @@ static int imx6_ccm_probe(struct device_d *dev) clk_data.clks = clks; clk_data.clk_num = IMX6QDL_CLK_END; - of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, &clk_data); + of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, &clk_data); clk_enable(clks[IMX6QDL_CLK_MMDC_CH0_AXI_PODF]); clk_enable(clks[IMX6QDL_CLK_PLL6_ENET]); @@ -836,15 +849,12 @@ static __maybe_unused struct of_device_id imx6_ccm_dt_ids[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, imx6_ccm_dt_ids); -static struct driver_d imx6_ccm_driver = { +static struct driver imx6_ccm_driver = { .probe = imx6_ccm_probe, .name = "imx6-ccm", .of_compatible = DRV_OF_COMPAT(imx6_ccm_dt_ids), }; -static int imx6_ccm_init(void) -{ - return platform_driver_register(&imx6_ccm_driver); -} -core_initcall(imx6_ccm_init); +core_platform_driver(imx6_ccm_driver); |