MLK-13441-6 ARM: imx: add i.mx7ulp clock driver
authorAnson Huang <Anson.Huang@nxp.com>
Mon, 7 Nov 2016 16:05:46 +0000 (00:05 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:52:35 +0000 (14:52 -0500)
Add i.MX7ULP clock driver.

Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Signed-off-by: Bai Ping <ping.bai@nxp.com>
Signed-off-by: Fancy Fang <chen.fang@nxp.com>
drivers/clk/imx/Makefile
drivers/clk/imx/clk-imx7ulp.c [new file with mode: 0644]
include/dt-bindings/clock/imx7ulp-clock.h [new file with mode: 0644]

index c3794f9..8ccdaf2 100644 (file)
@@ -30,4 +30,5 @@ obj-$(CONFIG_SOC_IMX6SLL) += clk-imx6sll.o
 obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
+obj-$(CONFIG_SOC_IMX7ULP)  += clk-imx7ulp.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
diff --git a/drivers/clk/imx/clk-imx7ulp.c b/drivers/clk/imx/clk-imx7ulp.c
new file mode 100644 (file)
index 0000000..ad24f7e
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * 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 <dt-bindings/clock/imx7ulp-clock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+
+static const char *pll_pre_sels[]      = { "osc", "firc", };
+static const char *spll_pfd_sels[]     = { "spll_pfd0", "spll_pfd1", "spll_pfd2", "spll_pfd3", };
+static const char *spll_sels[]         = { "spll", "spll_pfd_sel", };
+static const char *apll_pfd_sels[]     = { "apll_pfd0", "apll_pfd1", "apll_pfd2", "apll_pfd3", };
+static const char *apll_sels[]         = { "apll", "apll_pfd_sel", };
+static const char *sys_sels[]          = { "dummy", "osc", "sirc", "firc", "ckil", "apll", "spll", "upll", };
+static const char *ddr_sels[]          = { "apll_pfd_sel", "upll", };
+static const char *nic_sels[]          = { "firc", "ddr_div", };
+static const char *periph_plat_sels[]  = { "nic1_bus", "nic1_div", "ddr_div", "apll_pfd2", "apll_pfd1", "apll_pfd0", "upll", };
+/* the dummy in only a space holder of spll_bus clk */
+static const char *periph_slow_sels[]  = { "osc", "mpll", "firc", "ckil", "nic1_bus", "nic1_div", "dummy", };
+static struct clk *clks[IMX7ULP_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static int const clks_init_on[] __initconst = {
+       IMX7ULP_CLK_SPLL_PFD0,
+       IMX7ULP_CLK_CORE_DIV,
+       IMX7ULP_CLK_BUS_DIV,
+       IMX7ULP_CLK_PLAT_DIV,
+       IMX7ULP_CLK_NIC0_DIV,
+       IMX7ULP_CLK_NIC1_DIV,
+       IMX7ULP_CLK_NIC1_BUS_DIV,
+       IMX7ULP_CLK_MMDC,
+};
+
+static void __init imx7ulp_clocks_init(struct device_node *scg_node)
+{
+       struct device_node *np;
+       void __iomem *base;
+       int i;
+
+       clks[IMX7ULP_CLK_DUMMY]         = imx_clk_fixed("dummy", 0);
+
+       clks[IMX7ULP_CLK_CKIL]          = of_clk_get_by_name(scg_node, "ckil");
+       clks[IMX7ULP_CLK_OSC]           = of_clk_get_by_name(scg_node, "osc");
+       clks[IMX7ULP_CLK_SIRC]          = of_clk_get_by_name(scg_node, "sirc");
+       clks[IMX7ULP_CLK_FIRC]          = of_clk_get_by_name(scg_node, "firc");
+       clks[IMX7ULP_CLK_MIPI_PLL]      = of_clk_get_by_name(scg_node, "mpll");
+       clks[IMX7ULP_CLK_UPLL]          = of_clk_get_by_name(scg_node, "upll");
+
+       np = scg_node;
+       base = of_iomap(np, 0);
+       WARN_ON(!base);
+
+       clks[IMX7ULP_CLK_SPLL_PRE_SEL] = imx_clk_mux("spll_pre_sel", base + 0x608, 0, 1, pll_pre_sels, ARRAY_SIZE(pll_pre_sels));
+       clks[IMX7ULP_CLK_APLL_PRE_SEL] = imx_clk_mux("apll_pre_sel", base + 0x508, 0, 1, pll_pre_sels, ARRAY_SIZE(pll_pre_sels));
+       /*                                               name           parent_name     reg             shift   width */
+       clks[IMX7ULP_CLK_SPLL_PRE_DIV] = imx_clk_divider("spll_pre_div", "spll_pre_sel", base + 0x608,  8,      3);
+       clks[IMX7ULP_CLK_APLL_PRE_DIV] = imx_clk_divider("apll_pre_div", "apll_pre_sel", base + 0x508,  8,      3);
+       /*                                      name    parent_name     base*/
+       clks[IMX7ULP_CLK_SPLL] = imx_clk_pllv4("spll",  "spll_pre_div", base + 0x600);
+       clks[IMX7ULP_CLK_APLL] = imx_clk_pllv4("apll",  "apll_pre_div", base + 0x500);
+
+       /* SPLL PFDs */
+       clks[IMX7ULP_CLK_SPLL_PFD0] = imx_clk_pfdv2("spll_pfd0", "spll", base + 0x60C, 0);
+       clks[IMX7ULP_CLK_SPLL_PFD1] = imx_clk_pfdv2("spll_pfd1", "spll", base + 0x60C, 1);
+       clks[IMX7ULP_CLK_SPLL_PFD2] = imx_clk_pfdv2("spll_pfd2", "spll", base + 0x60C, 2);
+       clks[IMX7ULP_CLK_SPLL_PFD3] = imx_clk_pfdv2("spll_pfd3", "spll", base + 0x60C, 3);
+       /* APLL PFDs */
+       clks[IMX7ULP_CLK_APLL_PFD0] = imx_clk_pfdv2("apll_pfd0", "apll", base + 0x50C, 0);
+       clks[IMX7ULP_CLK_APLL_PFD1] = imx_clk_pfdv2("apll_pfd1", "apll", base + 0x50C, 1);
+       clks[IMX7ULP_CLK_APLL_PFD2] = imx_clk_pfdv2("apll_pfd2", "apll", base + 0x50C, 2);
+       clks[IMX7ULP_CLK_APLL_PFD3] = imx_clk_pfdv2("apll_pfd3", "apll", base + 0x50C, 3);
+
+       clks[IMX7ULP_CLK_SPLL_PFD_SEL] = imx_clk_mux("spll_pfd_sel", base + 0x608, 14, 2, spll_pfd_sels, ARRAY_SIZE(spll_pfd_sels));
+       clks[IMX7ULP_CLK_APLL_PFD_SEL] = imx_clk_mux("apll_pfd_sel", base + 0x508, 14, 2, apll_pfd_sels, ARRAY_SIZE(apll_pfd_sels));
+
+       clks[IMX7ULP_CLK_SPLL_SEL] = imx_clk_mux("spll_sel", base + 0x608, 1, 1, spll_sels, ARRAY_SIZE(spll_sels));
+       clks[IMX7ULP_CLK_APLL_SEL] = imx_clk_mux("apll_sel", base + 0x508, 1, 1, apll_sels, ARRAY_SIZE(apll_sels));
+
+       clks[IMX7ULP_CLK_SYS_SEL] = imx_clk_mux("sys_sel", base + 0x14, 24, 4, sys_sels, ARRAY_SIZE(sys_sels));
+       clks[IMX7ULP_CLK_DDR_SEL] = imx_clk_mux("ddr_sel", base + 0x30, 24, 1, ddr_sels, ARRAY_SIZE(ddr_sels));
+       clks[IMX7ULP_CLK_NIC_SEL] = imx_clk_mux("nic_sel", base + 0x40, 28, 1, nic_sels, ARRAY_SIZE(nic_sels));
+
+       clks[IMX7ULP_CLK_CORE_DIV] = imx_clk_divider("core_div", "sys_sel", base + 0x14, 16, 4);
+       clks[IMX7ULP_CLK_PLAT_DIV] = imx_clk_divider("plat_div", "core_div", base + 0x14, 12, 4);
+
+       clks[IMX7ULP_CLK_DDR_DIV] = clk_register_divider(NULL, "ddr_div", "ddr_sel", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x30, 0, 3, CLK_DIVIDER_ONE_BASED, &imx_ccm_lock);
+       clks[IMX7ULP_CLK_NIC0_DIV] = imx_clk_divider("nic0_div", "nic_sel",  base + 0x40, 24, 4);
+       clks[IMX7ULP_CLK_GPU_DIV]  = imx_clk_divider("gpu_div",  "nic0_div", base + 0x40, 20, 4);
+       clks[IMX7ULP_CLK_NIC1_DIV] = imx_clk_divider("nic1_div", "nic0_div", base + 0x40, 16, 4);
+       clks[IMX7ULP_CLK_NIC1_BUS_DIV] = imx_clk_divider("nic1_bus", "nic1_div", base + 0x40, 4, 4);
+
+       /* PCC2 */
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-pcc2");
+       base = of_iomap(np, 0);
+       WARN_ON(!base);
+
+       clks[IMX7ULP_CLK_DMA1]          = imx_clk_gate("dma1", "nic1_bus", base + 0x20, 30);
+       clks[IMX7ULP_CLK_RGPIO2P1]      = imx_clk_gate("gpio", "nic1_bus", base + 0x3c, 30);
+       clks[IMX7ULP_CLK_DMA_MUX1]      = imx_clk_gate("dma_mux1", "nic1_bus",  base + 0x84, 30);
+       clks[IMX7ULP_CLK_SNVS]          = imx_clk_gate("snvs", "nic1_bus",      base + 0x8c, 30);
+       clks[IMX7ULP_CLK_CAAM]          = imx_clk_gate("caam", "nic1_div",      base + 0x90, 30);
+       clks[IMX7ULP_CLK_LPTPM4]        = imx_clk_composite("lptpm4",  periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x94);
+       clks[IMX7ULP_CLK_LPTPM5]        = imx_clk_composite("lptmp5",  periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x98);
+       clks[IMX7ULP_CLK_LPIT1]         = imx_clk_composite("lpit1",   periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x9C);
+       clks[IMX7ULP_CLK_LPSPI2]        = imx_clk_composite("lpspi2",  periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xA4);
+       clks[IMX7ULP_CLK_LPSPI3]        = imx_clk_composite("lpspi3",  periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xA8);
+       clks[IMX7ULP_CLK_LPI2C4]        = imx_clk_composite("lpi2c4",  periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xAC);
+       clks[IMX7ULP_CLK_LPI2C5]        = imx_clk_composite("lpi2c5",  periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xB0);
+       clks[IMX7ULP_CLK_LPUART4]       = imx_clk_composite("lpuart4", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xB4);
+       clks[IMX7ULP_CLK_LPUART5]       = imx_clk_composite("lpuart5", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0xB8);
+       clks[IMX7ULP_CLK_FLEXIO1]       = imx_clk_composite("flexio",  periph_slow_sels, ARRAY_SIZE(periph_plat_sels), true, false, true, base + 0xC4);
+       clks[IMX7ULP_CLK_USB0]          = imx_clk_composite("usb0",    periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, true,  true, base + 0xCC);
+       clks[IMX7ULP_CLK_USB1]          = imx_clk_composite("usb1",    periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, true,  true, base + 0xD0);
+       clks[IMX7ULP_CLK_USB_PHY]       = imx_clk_gate("usb_phy",  "nic1_bus", base + 0xD4, 30);
+       clks[IMX7ULP_CLK_USDHC0]        = imx_clk_composite("usdhc0",  periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, true,  true, base + 0xDC);
+       clks[IMX7ULP_CLK_USDHC1]        = imx_clk_composite("usdhc1",  periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, true,  true, base + 0xE0);
+       clks[IMX7ULP_CLK_WDG1]          = imx_clk_composite("wdg1",    periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, true,  true, base + 0xF4);
+       clks[IMX7ULP_CLK_WDG2]          = imx_clk_composite("sdg2",    periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, true,  true, base + 0x10C);
+
+       /* PCC3 */
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-pcc3");
+       base = of_iomap(np, 0);
+       WARN_ON(!base);
+
+       clks[IMX7ULP_CLK_LPTPM6]        = imx_clk_composite("lptpm6",  periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x84);
+       clks[IMX7ULP_CLK_LPTPM7]        = imx_clk_composite("lptpm7",  periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x88);
+       clks[IMX7ULP_CLK_LPI2C6]        = imx_clk_composite("lpi2c6",  periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x90);
+       clks[IMX7ULP_CLK_LPI2C7]        = imx_clk_composite("lpi2c7",  periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x94);
+       clks[IMX7ULP_CLK_LPUART6]       = imx_clk_composite("lpuart6", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x98);
+       clks[IMX7ULP_CLK_LPUART7]       = imx_clk_composite("lpuart7", periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, false, true, base + 0x9C);
+       clks[IMX7ULP_CLK_VIU]           = imx_clk_gate("viu", "nic1_div", base + 0xA0, 30);
+       clks[IMX7ULP_CLK_DSI]           = imx_clk_composite("dsi",     periph_slow_sels, ARRAY_SIZE(periph_slow_sels), true, true,  true, base + 0xA4);
+       clks[IMX7ULP_CLK_LCDIF]         = imx_clk_composite("lcdif",   periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, true,  true, base + 0xA8);
+       clks[IMX7ULP_CLK_MMDC]          = imx_clk_gate("mmdc", "nic1_div", base + 0xAC, 30);
+       clks[IMX7ULP_CLK_GPU3D]         = imx_clk_composite("gpu3d",   periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, false, true, base + 0x140);
+       clks[IMX7ULP_CLK_GPU2D]         = imx_clk_composite("gpu2d",   periph_plat_sels, ARRAY_SIZE(periph_plat_sels), true, false, true, base + 0x144);
+
+       imx_check_clocks(clks, ARRAY_SIZE(clks));
+
+       clk_data.clks = clks;
+       clk_data.clk_num = ARRAY_SIZE(clks);
+       of_clk_add_provider(scg_node, of_clk_src_onecell_get, &clk_data);
+
+       for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+               imx_clk_prepare_enable(clks[clks_init_on[i]]);
+
+       imx_clk_set_parent(clks[IMX7ULP_CLK_LPTPM5], clks[IMX7ULP_CLK_FIRC]);
+
+       pr_info("i.MX7ULP clock tree init done.\n");
+}
+
+CLK_OF_DECLARE(imx7ulp, "fsl,imx7ulp-scg1", imx7ulp_clocks_init);
diff --git a/include/dt-bindings/clock/imx7ulp-clock.h b/include/dt-bindings/clock/imx7ulp-clock.h
new file mode 100644 (file)
index 0000000..1dd7218
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX7ULP_H
+#define __DT_BINDINGS_CLOCK_IMX7ULP_H
+
+#define IMX7ULP_CLK_DUMMY              0
+#define IMX7ULP_CLK_CKIL               1
+#define IMX7ULP_CLK_OSC                        2
+#define IMX7ULP_CLK_FIRC               3
+
+/* SCG1 */
+#define IMX7ULP_CLK_SPLL_PRE_SEL       4
+#define IMX7ULP_CLK_SPLL_PRE_DIV       5
+#define IMX7ULP_CLK_SPLL               6
+#define IMX7ULP_CLK_SPLL_POST_DIV1     7
+#define IMX7ULP_CLK_SPLL_POST_DIV2     8
+#define IMX7ULP_CLK_SPLL_PFD0          9
+#define IMX7ULP_CLK_SPLL_PFD1          10
+#define IMX7ULP_CLK_SPLL_PFD2          11
+#define IMX7ULP_CLK_SPLL_PFD3          12
+#define IMX7ULP_CLK_SPLL_PFD_SEL       13
+#define IMX7ULP_CLK_SPLL_SEL           14
+#define IMX7ULP_CLK_APLL_PRE_SEL       15
+#define IMX7ULP_CLK_APLL_PRE_DIV       16
+#define IMX7ULP_CLK_APLL               17
+#define IMX7ULP_CLK_APLL_POST_DIV1     18
+#define IMX7ULP_CLK_APLL_POST_DIV2     19
+#define IMX7ULP_CLK_APLL_PFD0          20
+#define IMX7ULP_CLK_APLL_PFD1          21
+#define IMX7ULP_CLK_APLL_PFD2          22
+#define IMX7ULP_CLK_APLL_PFD3          23
+#define IMX7ULP_CLK_APLL_PFD_SEL       24
+#define IMX7ULP_CLK_APLL_SEL           25
+#define IMX7ULP_CLK_UPLL               26
+#define IMX7ULP_CLK_SYS_SEL            27
+#define IMX7ULP_CLK_CORE_DIV           28
+#define IMX7ULP_CLK_BUS_DIV            29
+#define IMX7ULP_CLK_PLAT_DIV           30
+#define IMX7ULP_CLK_DDR_SEL            31
+#define IMX7ULP_CLK_DDR_DIV            32
+#define IMX7ULP_CLK_NIC_SEL            33
+#define IMX7ULP_CLK_NIC0_DIV           34
+#define IMX7ULP_CLK_GPU_DIV            35
+#define IMX7ULP_CLK_NIC1_DIV           36
+#define IMX7ULP_CLK_NIC1_BUS_DIV       37
+#define IMX7ULP_CLK_NIC1_EXT_DIV       38
+
+/* PCG2 */
+#define IMX7ULP_CLK_DMA1               39
+#define IMX7ULP_CLK_RGPIO2P1           40
+#define IMX7ULP_CLK_FLEXBUS            41
+#define IMX7ULP_CLK_SEMA42_1           42
+#define IMX7ULP_CLK_DMA_MUX1           43
+#define IMX7ULP_CLK_SNVS               44
+#define IMX7ULP_CLK_CAAM               45
+#define IMX7ULP_CLK_LPTPM4             46
+#define IMX7ULP_CLK_LPTPM5             47
+#define IMX7ULP_CLK_LPIT1              48
+#define IMX7ULP_CLK_LPSPI2             49
+#define IMX7ULP_CLK_LPSPI3             50
+#define IMX7ULP_CLK_LPI2C4             51
+#define IMX7ULP_CLK_LPI2C5             52
+#define IMX7ULP_CLK_LPUART4            53
+#define IMX7ULP_CLK_LPUART5            54
+#define IMX7ULP_CLK_FLEXIO1            55
+#define IMX7ULP_CLK_USB0               56
+#define IMX7ULP_CLK_USB1               57
+#define IMX7ULP_CLK_USB_PHY            58
+#define IMX7ULP_CLK_USB_PL301          59
+#define IMX7ULP_CLK_USDHC0             60
+#define IMX7ULP_CLK_USDHC1             61
+#define IMX7ULP_CLK_WDG1               62
+#define IMX7ULP_CLK_WDG2               63
+
+/* PCG3 */
+#define IMX7ULP_CLK_LPTPM6             64
+#define IMX7ULP_CLK_LPTPM7             65
+#define IMX7ULP_CLK_LPI2C6             66
+#define IMX7ULP_CLK_LPI2C7             67
+#define IMX7ULP_CLK_LPUART6            68
+#define IMX7ULP_CLK_LPUART7            69
+#define IMX7ULP_CLK_VIU                        70
+#define IMX7ULP_CLK_DSI                        71
+#define IMX7ULP_CLK_LCDIF              72
+#define IMX7ULP_CLK_MMDC               73
+#define IMX7ULP_CLK_PCTLC              74
+#define IMX7ULP_CLK_PCTLD              75
+#define IMX7ULP_CLK_PCTLE              76
+#define IMX7ULP_CLK_PCTLF              77
+#define IMX7ULP_CLK_GPU3D              78
+#define IMX7ULP_CLK_GPU2D              79
+
+#define IMX7ULP_CLK_MIPI_PLL           80
+#define IMX7ULP_CLK_SIRC               81
+
+#define IMX7ULP_CLK_END                        82
+
+#endif /* __DT_BINDINGS_CLOCK_IMX7ULP_H */