Based on analogous code from Linux kernel Signed-off-by: Andrey Smirnov <andrew.smirnov@xxxxxxxxx> --- drivers/clk/imx/Makefile | 1 + drivers/clk/imx/clk-vf610.c | 1224 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1225 insertions(+) create mode 100644 drivers/clk/imx/clk-vf610.c diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 0303c0b..2665f49 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -1 +1,2 @@ obj-y += clk.o +obj-$(CONFIG_ARCH_VF610) += clk-vf610.o diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c new file mode 100644 index 0000000..2fbdbb3 --- /dev/null +++ b/drivers/clk/imx/clk-vf610.c @@ -0,0 +1,1224 @@ +/* + * Copyright (c) 2016 Zodiac Inflight Innovations + * Author: Andrey Smirnov <andrew.smirnov@xxxxxxxxx> + * + * Based on analogous code from Linux kernel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <common.h> +#include <init.h> +#include <driver.h> +#include <linux/clk.h> +#include <io.h> +#include <of.h> +#include <of_address.h> +#include <linux/clkdev.h> +#include <linux/err.h> +#include <mfd/syscon.h> +#include <dt-bindings/clock/vf610-clock.h> + +#include "../../../arch/arm/mach-imx/clk.h" + +enum { + CCM_CCR = 0x00, + CCM_CSR = 0x04, + CCM_CCSR = 0x08, + CCM_CACRR = 0x0c, + CCM_CSCMR1 = 0x10, + CCM_CSCDR1 = 0x14, + CCM_CSCDR2 = 0x18, + CCM_CSCDR3 = 0x1c, + CCM_CSCMR2 = 0x20, + CCM_CSCDR4 = 0x24, + CCM_CLPCR = 0x2c, + CCM_CISR = 0x30, + CCM_CIMR = 0x34, + CCM_CGPR = 0x3c, + CCM_CCGR0 = 0x40, + CCM_CCGR1 = 0x44, + CCM_CCGR2 = 0x48, + CCM_CCGR3 = 0x4c, + CCM_CCGR4 = 0x50, + CCM_CCGR5 = 0x54, + CCM_CCGR6 = 0x58, + CCM_CCGR7 = 0x5c, + CCM_CCGR8 = 0x60, + CCM_CCGR9 = 0x64, + CCM_CCGR10 = 0x68, + CCM_CCGR11 = 0x6c, + + CCM_CMEOR0 = 0x70, + CCM_CMEOR1 = 0x74, + CCM_CMEOR2 = 0x78, + CCM_CMEOR3 = 0x7c, + CCM_CMEOR4 = 0x80, + CCM_CMEOR5 = 0x84, + CCM_CPPDSR = 0x88, + CCM_CCOWR = 0x8c, + CCM_CCPGR0 = 0x90, + CCM_CCPGR1 = 0x94, + CCM_CCPGR2 = 0x98, + CCM_CCPGR3 = 0x9c, +}; + +/* CCM_CCGRx(x) (CCM_CCGR0 + (x) * 4) */ + +static int vf610_ccm_ccgrx_cgn(int n) { + return n * 2; +} + + +enum { + PFD_PLL1_BASE = 0x2b0, + PFD_PLL2_BASE = 0x100, + PFD_PLL3_BASE = 0x0f0, + ANA_MISC1 = 0x160, +}; + +static const unsigned int PLL_CTRL[7] = { + 0x270, + 0x030, + 0x010, + 0x070, + 0x0e0, + 0x0a0, + 0x020, +}; + + +static struct clk *clk[VF610_CLK_END]; +struct clk_onecell_data clk_data; + +static struct clk * __init vf610_get_fixed_clock(struct device_node *np, + const char *name) +{ + struct clk *clk = of_clk_get_by_name(np, name); + + /* Backward compatibility if device tree is missing clks assignments */ + if (IS_ERR(clk)) + clk = imx_obtain_fixed_clock(name, 0); + + return clk; +}; + +static void vf610_ccm_setup_fixed(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_DUMMY] = clk_fixed("dummy", 0); + clk[VF610_CLK_SIRC_128K] = clk_fixed("sirc_128k", 128000); + clk[VF610_CLK_SIRC_32K] = clk_fixed("sirc_32k", 32000); + clk[VF610_CLK_FIRC] = clk_fixed("firc", 24000000); +} + +static void vf610_ccm_setup_from_dt(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_SXOSC] = vf610_get_fixed_clock(np, "sxosc"); + clk[VF610_CLK_FXOSC] = vf610_get_fixed_clock(np, "fxosc"); + clk[VF610_CLK_AUDIO_EXT] = vf610_get_fixed_clock(np, "audio_ext"); + clk[VF610_CLK_ENET_EXT] = vf610_get_fixed_clock(np, "enet_ext"); + + /* Clock source from external clock via LVDs PAD */ + clk[VF610_CLK_ANACLK1] = vf610_get_fixed_clock(np, "anaclk1"); + + clk[VF610_CLK_FXOSC_HALF] = imx_clk_fixed_factor("fxosc_half", + "fxosc", 1, 2); +} + +static void vf610_ccm_setup_slow_clk(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "sirc_32k", + "sxosc", + }; + + clk[VF610_CLK_SLOW_CLK_SEL] = imx_clk_mux("slow_clk_sel", + ccm + CCM_CCSR, + 4, 1, + sources, + ARRAY_SIZE(sources)); +} + +static void vf610_ccm_setup_fast_clk(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "firc", + "fxosc", + }; + + clk[VF610_CLK_FASK_CLK_SEL] = imx_clk_mux("fast_clk_sel", + ccm + CCM_CCSR, + 5, 1, + sources, + ARRAY_SIZE(sources)); +} + +static void vf610_ccm_setup_pll_bypass_srcs(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + size_t i; + + static const char *parents[] = { + "fast_clk_sel", + "lvds1_in", + }; + +#define VF610_CLK_PLL_BYPASS_SRC(n) \ + { VF610_CLK_PLL##n##_BYPASS_SRC, "pll" #n "_bypass_src" } + + static const struct { + int id; + const char *name; + } clocks[] = { + VF610_CLK_PLL_BYPASS_SRC(1), + VF610_CLK_PLL_BYPASS_SRC(2), + VF610_CLK_PLL_BYPASS_SRC(3), + VF610_CLK_PLL_BYPASS_SRC(4), + VF610_CLK_PLL_BYPASS_SRC(5), + VF610_CLK_PLL_BYPASS_SRC(6), + VF610_CLK_PLL_BYPASS_SRC(7), + }; + +#undef VF610_CLK_PLL_BYPASS_SRC + + for (i = 0; i < ARRAY_SIZE(clocks); i++) { + const char *name = clocks[i].name; + const int id = clocks[i].id; + + clk[id] = imx_clk_mux(name, anatop + PLL_CTRL[i], + 14, 1, + parents, ARRAY_SIZE(parents)); + } +} + +static void vf610_ccm_setup_plls(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + size_t i; + +#define VF610_CLK_PLL(n, type, mask) \ + { VF610_CLK_PLL##n, type, "pll" #n, "pll" #n "_bypass_src", mask } + + static const struct { + int id; + int type; + const char *name; + const char *parent; + u32 mask; + } clocks[] = { + VF610_CLK_PLL(1, IMX_PLLV3_GENERIC, 0x01), + VF610_CLK_PLL(2, IMX_PLLV3_GENERIC, 0x01), + VF610_CLK_PLL(3, IMX_PLLV3_USB_VF610, 0x02), + VF610_CLK_PLL(4, IMX_PLLV3_AV, 0x7f), + VF610_CLK_PLL(5, IMX_PLLV3_ENET, 0x03), + VF610_CLK_PLL(6, IMX_PLLV3_AV, 0x7f), + VF610_CLK_PLL(7, IMX_PLLV3_USB_VF610, 0x02), + }; + +#undef VF610_CLK_PLL + + for (i = 0; i < ARRAY_SIZE(clocks); i++) { + const char *name = clocks[i].name; + const int id = clocks[i].id; + + clk[id] = imx_clk_pllv3(clocks[i].type, + name, + clocks[i].parent, + anatop + PLL_CTRL[i], + clocks[i].mask); + } +} + +static void vf610_ccm_setup_pll_bypass(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + size_t i; + static const char *pll_bypass_parents[][2] = { + { "pll1", "pll1_bypass_src" }, + { "pll2", "pll2_bypass_src" }, + { "pll3", "pll3_bypass_src" }, + { "pll4", "pll4_bypass_src" }, + { "pll5", "pll5_bypass_src" }, + { "pll6", "pll6_bypass_src" }, + { "pll7", "pll7_bypass_src" }, + }; + +#define VF610_PLL_BYPASS(n) \ + { VF610_PLL##n##_BYPASS, "pll" #n "_bypass" } + + static const struct { + int id; + const char *name; + } clocks[] = { + VF610_PLL_BYPASS(1), + VF610_PLL_BYPASS(2), + VF610_PLL_BYPASS(3), + VF610_PLL_BYPASS(4), + VF610_PLL_BYPASS(5), + VF610_PLL_BYPASS(6), + VF610_PLL_BYPASS(7), + }; + +#undef VF610_PLL_BYPASS + + for (i = 0; i < ARRAY_SIZE(clocks); i++) { + const char *name = clocks[i].name; + const int id = clocks[i].id; + + clk[id] = imx_clk_mux_p(name, + anatop + PLL_CTRL[i], + 16, 1, + pll_bypass_parents[i], + ARRAY_SIZE(pll_bypass_parents[i])); + } +} + +static void vf610_ccm_setup_group1(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + size_t i; + + static const struct { + int id; + const char *name; + const char *parent; + unsigned int reg; + } clocks[] = { + { VF610_CLK_PLL1_SYS, "pll1_sys", "pll1_bypass" }, + { VF610_CLK_PLL2_BUS, "pll2_bus", "pll2_bypass" }, + { VF610_CLK_PLL3_USB_OTG, "pll3_usb_otg", "pll3_bypass" }, + { VF610_CLK_PLL4_AUDIO, "pll4_audio", "pll4_bypass" }, + { VF610_CLK_PLL5_ENET, "pll5_enet", "pll5_bypass" }, + { VF610_CLK_PLL6_VIDEO, "pll6_video", "pll6_bypass" }, + { VF610_CLK_PLL7_USB_HOST, "pll7_usb_host", "pll7_bypass" }, + }; + + for (i = 0; i < ARRAY_SIZE(clocks); i++) { + const char *name = clocks[i].name; + const int id = clocks[i].id; + + clk[id] = imx_clk_gate(name, clocks[i].parent, + anatop + PLL_CTRL[i], 13); + } +} + +static void vf610_ccm_setup_pfds(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + size_t i; + +#define VF610_CLK_PLL_PFD(n, m) \ + { VF610_CLK_PLL##n##_PFD##m, "pll" #n "_pfd" #m, \ + "pll" #n "_sys", PFD_PLL##n##_BASE, m - 1 } + + const static struct { + int id; + const char *name; + const char *parent; + unsigned int reg; + u8 idx; + } clocks[] = { + VF610_CLK_PLL_PFD(1, 1), + VF610_CLK_PLL_PFD(1, 2), + VF610_CLK_PLL_PFD(1, 3), + VF610_CLK_PLL_PFD(1, 4), + + VF610_CLK_PLL_PFD(2, 1), + VF610_CLK_PLL_PFD(2, 2), + VF610_CLK_PLL_PFD(2, 3), + VF610_CLK_PLL_PFD(2, 4), + + VF610_CLK_PLL_PFD(3, 1), + VF610_CLK_PLL_PFD(3, 2), + VF610_CLK_PLL_PFD(3, 3), + VF610_CLK_PLL_PFD(3, 4), + }; + +#undef VF610_CLK_PLL_PFD + + for (i = 0; i < ARRAY_SIZE(clocks); i++) { + const char *name = clocks[i].name; + const int id = clocks[i].id; + + clk[id] = imx_clk_pfd(name, + clocks[i].parent, + anatop + clocks[i].reg, + clocks[i].idx); + } +} + +static void vf610_ccm_setup_pll1_pfd_out(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "pll1_sys", + "pll1_pfd1", + "pll1_pfd2", + "pll1_pfd3", + "pll1_pfd4", + }; + + clk[VF610_CLK_PLL1_PFD_SEL] = imx_clk_mux("pll1_pfd_sel", + ccm + CCM_CCSR, + 16, 3, + sources, ARRAY_SIZE(sources)); +} + +static void vf610_ccm_setup_pll2_pfd_out(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "pll2_bus", + "pll2_pfd1", + "pll2_pfd2", + "pll2_pfd3", + "pll2_pfd4", + }; + + clk[VF610_CLK_PLL2_PFD_SEL] = imx_clk_mux("pll2_pfd_sel", + ccm + CCM_CCSR, + 19, 3, + sources, ARRAY_SIZE(sources)); +} + +static void vf610_ccm_setup_sys_out(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "fast_clk_sel", + "slow_clk_sel", + "pll2_pfd_sel", + "pll2_bus", + "pll1_pfd_sel", + "pll3_usb_otg", + }; + + clk[VF610_CLK_SYS_SEL] = imx_clk_mux("sys_sel", + ccm + CCM_CCSR, + 0, 3, + sources, ARRAY_SIZE(sources)); +} + +static void vf610_ccm_setup_ddr_out(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "pll2_pfd2", + "sys_sel", + }; + + clk[VF610_CLK_DDR_SEL] = imx_clk_mux("ddr_sel", + ccm + CCM_CCSR, + 6, 1, + sources, ARRAY_SIZE(sources)); +} + +static void vf610_ccm_setup_dividers(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + size_t i; + + static const struct { + int id; + const char *name; + const char *parent; + u8 shift; + u8 width; + } clocks[] = { + { + .id = VF610_CLK_SYS_BUS, + .name = "sys_bus", + .parent = "sys_sel", + .shift = 0, + .width = 3, + }, + { + .id = VF610_CLK_PLATFORM_BUS, + .name = "platform_bus", + .parent = "sys_bus", + .shift = 3, + .width = 3, + }, + { + .id = VF610_CLK_IPG_BUS, + .name = "ipg_bus", + .parent = "platform_bus", + .shift = 11, + .width = 2, + }, + { + .id = VF610_CLK_PLL3_MAIN_DIV, + .name = "pll3_usb_otg_div", + .parent = "pll3_usb_otg", + .shift = 20, + .width = 1, + }, + { + .id = VF610_CLK_PLL6_MAIN_DIV, + .name = "pll6_video_div", + .parent = "pll6_video", + .shift = 21, + .width = 1, + }, + }; + + for (i = 0; i < ARRAY_SIZE(clocks); i++) + clk[clocks[i].id] = imx_clk_divider(clocks[i].name, + clocks[i].parent, + ccm + CCM_CACRR, + clocks[i].shift, + clocks[i].width); +} + +static void vf610_ccm_setup_pll4_main_div(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const struct clk_div_table div_table[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 6 }, + { .val = 3, .div = 8 }, + { .val = 4, .div = 10 }, + { .val = 5, .div = 12 }, + { .val = 6, .div = 14 }, + { .val = 7, .div = 16 }, + { } + }; + + clk[VF610_CLK_PLL4_MAIN_DIV] = clk_divider_table("pll4_audio_div", + "pll4_audio", + ccm + CCM_CACRR, 6, 3, + div_table, 0); +} + +static void vf610_ccm_setup_ddrmc(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc", + "ddr_sel", + ccm + CCM_CCGR6, + vf610_ccm_ccgrx_cgn(14), + 0x2); +} + +static void vf610_ccm_setup_wkpu(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_WKPU] = imx_clk_gate2_cgr("wkpu", + "ipg_bus", + ccm + CCM_CCGR4, + vf610_ccm_ccgrx_cgn(10), + 0x2); +} + +static void vf610_ccm_setup_usbphys(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg", + anatop + PLL_CTRL[2], 6); + clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host", + anatop + PLL_CTRL[6], 6); +} + +static void vf610_ccm_setup_usbcs(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) + +{ + + clk[VF610_CLK_USBC0] = imx_clk_gate2("usbc0", "ipg_bus", + ccm + CCM_CCGR1, + vf610_ccm_ccgrx_cgn(4)); + clk[VF610_CLK_USBC1] = imx_clk_gate2("usbc1", "ipg_bus", + ccm + CCM_CCGR7, + vf610_ccm_ccgrx_cgn(4)); + +} + +static void vf610_ccm_setup_qspis(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "pll3_usb_otg", + "pll3_pfd4", + "pll2_pfd4", + "pll1_pfd4", + }; + + clk[VF610_CLK_QSPI0_SEL] = imx_clk_mux("qspi0_sel", + ccm + CCM_CSCMR1, + 22, 2, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_QSPI0_EN] = imx_clk_gate("qspi0_en", "qspi0_sel", + ccm + CCM_CSCDR3, 4); + clk[VF610_CLK_QSPI0_X4_DIV] = imx_clk_divider("qspi0_x4", "qspi0_en", + ccm + CCM_CSCDR3, 0, 2); + clk[VF610_CLK_QSPI0_X2_DIV] = imx_clk_divider("qspi0_x2", "qspi0_x4", + ccm + CCM_CSCDR3, 2, 1); + clk[VF610_CLK_QSPI0_X1_DIV] = imx_clk_divider("qspi0_x1", "qspi0_x2", + ccm + CCM_CSCDR3, 3, 1); + clk[VF610_CLK_QSPI0] = imx_clk_gate2("qspi0", "qspi0_x1", + ccm + CCM_CCGR2, + vf610_ccm_ccgrx_cgn(4)); + + clk[VF610_CLK_QSPI1_SEL] = imx_clk_mux("qspi1_sel", + ccm + CCM_CSCMR1, + 24, 2, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_QSPI1_EN] = imx_clk_gate("qspi1_en", "qspi1_sel", + ccm + CCM_CSCDR3, 12); + clk[VF610_CLK_QSPI1_X4_DIV] = imx_clk_divider("qspi1_x4", "qspi1_en", + ccm + CCM_CSCDR3, 8, 2); + clk[VF610_CLK_QSPI1_X2_DIV] = imx_clk_divider("qspi1_x2", "qspi1_x4", + ccm + CCM_CSCDR3, 10, 1); + clk[VF610_CLK_QSPI1_X1_DIV] = imx_clk_divider("qspi1_x1", "qspi1_x2", + ccm + CCM_CSCDR3, 11, 1); + clk[VF610_CLK_QSPI1] = imx_clk_gate2("qspi1", "qspi1_x1", + ccm + CCM_CCGR8, + vf610_ccm_ccgrx_cgn(4)); +} + +static void vf610_ccm_setup_enets(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *enet_sels[] = { + "enet_ext", + "audio_ext", + "enet_50m", + "enet_25m", + }; + + static const char *enet_ts_sels[] = { + "enet_ext", + "fxosc", + "audio_ext", + "usb", + "enet_ts", + "enet_25m", + "enet_50m", + }; + + clk[VF610_CLK_ENET_50M] = imx_clk_fixed_factor("enet_50m", + "pll5_enet", 1, 10); + clk[VF610_CLK_ENET_25M] = imx_clk_fixed_factor("enet_25m", + "pll5_enet", 1, 20); + clk[VF610_CLK_ENET_SEL] = imx_clk_mux("enet_sel", + ccm + CCM_CSCMR2, 4, 2, + enet_sels, + ARRAY_SIZE(enet_sels)); + clk[VF610_CLK_ENET_TS_SEL] = imx_clk_mux("enet_ts_sel", + ccm + CCM_CSCMR2, 0, 3, + enet_ts_sels, + ARRAY_SIZE(enet_ts_sels)); + clk[VF610_CLK_ENET] = imx_clk_gate("enet", "enet_sel", + ccm + CCM_CSCDR1, 24); + clk[VF610_CLK_ENET_TS] = imx_clk_gate("enet_ts", "enet_ts_sel", + ccm + CCM_CSCDR1, 23); + clk[VF610_CLK_ENET0] = imx_clk_gate2("enet0", "ipg_bus", + ccm + CCM_CCGR9, + vf610_ccm_ccgrx_cgn(0)); + clk[VF610_CLK_ENET1] = imx_clk_gate2("enet1", "ipg_bus", + ccm + CCM_CCGR9, + vf610_ccm_ccgrx_cgn(1)); +} + +static void vf610_ccm_setup_pit(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_PIT] = imx_clk_gate2("pit", "ipg_bus", + ccm + CCM_CCGR1, + vf610_ccm_ccgrx_cgn(7)); +} + +static void vf610_ccm_setup_uarts(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_UART0] = imx_clk_gate2("uart0", "ipg_bus", + ccm + CCM_CCGR0, + vf610_ccm_ccgrx_cgn(7)); + clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", + ccm + CCM_CCGR0, + vf610_ccm_ccgrx_cgn(8)); + clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", + ccm + CCM_CCGR0, + vf610_ccm_ccgrx_cgn(9)); + clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", + ccm + CCM_CCGR0, + vf610_ccm_ccgrx_cgn(10)); + clk[VF610_CLK_UART4] = imx_clk_gate2("uart4", "ipg_bus", + ccm + CCM_CCGR6, + vf610_ccm_ccgrx_cgn(9)); + clk[VF610_CLK_UART5] = imx_clk_gate2("uart5", "ipg_bus", + ccm + CCM_CCGR6, + vf610_ccm_ccgrx_cgn(10)); +} + +static void vf610_ccm_setup_i2cs(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) + +{ + clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", + ccm + CCM_CCGR4, + vf610_ccm_ccgrx_cgn(6)); + clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", + ccm + CCM_CCGR4, + vf610_ccm_ccgrx_cgn(7)); + clk[VF610_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_bus", + ccm + CCM_CCGR10, + vf610_ccm_ccgrx_cgn(6)); + clk[VF610_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_bus", + ccm + CCM_CCGR10, + vf610_ccm_ccgrx_cgn(7)); +} + +static void vf610_ccm_setup_dspis(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_DSPI0] = imx_clk_gate2("dspi0", "ipg_bus", + ccm + CCM_CCGR0, + vf610_ccm_ccgrx_cgn(12)); + clk[VF610_CLK_DSPI1] = imx_clk_gate2("dspi1", "ipg_bus", + ccm + CCM_CCGR0, + vf610_ccm_ccgrx_cgn(13)); + clk[VF610_CLK_DSPI2] = imx_clk_gate2("dspi2", "ipg_bus", + ccm + CCM_CCGR6, + vf610_ccm_ccgrx_cgn(12)); + clk[VF610_CLK_DSPI3] = imx_clk_gate2("dspi3", "ipg_bus", + ccm + CCM_CCGR6, + vf610_ccm_ccgrx_cgn(13)); +} + +static void vf610_ccm_setup_wdt(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_WDT] = imx_clk_gate2("wdt", "ipg_bus", + ccm + CCM_CCGR1, + vf610_ccm_ccgrx_cgn(14)); +} + +static void vf610_ccm_setup_esdhcs(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "pll3_usb_otg", + "pll3_pfd3", + "pll1_pfd3", + "platform_bus", + }; + + clk[VF610_CLK_ESDHC0_SEL] = imx_clk_mux("esdhc0_sel", + ccm + CCM_CSCMR1, 16, 2, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_ESDHC0_EN] = imx_clk_gate("esdhc0_en", "esdhc0_sel", + ccm + CCM_CSCDR2, 28); + clk[VF610_CLK_ESDHC0_DIV] = imx_clk_divider("esdhc0_div", "esdhc0_en", + ccm +CCM_CSCDR2, 16, 4); + clk[VF610_CLK_ESDHC0] = imx_clk_gate2("eshc0", "esdhc0_div", + ccm + CCM_CCGR7, + vf610_ccm_ccgrx_cgn(1)); + + clk[VF610_CLK_ESDHC1_SEL] = imx_clk_mux("esdhc1_sel", + ccm + CCM_CSCMR1, 18, 2, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_ESDHC1_EN] = imx_clk_gate("esdhc1_en", "esdhc1_sel", + ccm + CCM_CSCDR2, 29); + clk[VF610_CLK_ESDHC1_DIV] = imx_clk_divider("esdhc1_div", "esdhc1_en", + ccm + CCM_CSCDR2, 20, 4); + clk[VF610_CLK_ESDHC1] = imx_clk_gate2("eshc1", "esdhc1_div", + ccm + CCM_CCGR7, + vf610_ccm_ccgrx_cgn(2)); +} + +static void vf610_ccm_setup_ftms(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + /* FTM counter clock source, not module clock */ + static const char *ftm_ext_sels[] = { + "sirc_128k", + "sxosc", + "fxosc_half", + "audio_ext", + }; + + static const char *ftm_fix_sels[] = { + "sxosc", + "ipg_bus", + }; + + /* + * ftm_ext_clk and ftm_fix_clk are FTM timer counter's + * selectable clock sources, both use a common enable bit + * in CCM_CSCDR1, selecting "dummy" clock as parent of + * "ftm0_ext_fix" make it serve only for enable/disable. + */ + clk[VF610_CLK_FTM0_EXT_SEL] = imx_clk_mux("ftm0_ext_sel", + ccm + CCM_CSCMR2, 6, 2, + ftm_ext_sels, + ARRAY_SIZE(ftm_ext_sels)); + clk[VF610_CLK_FTM0_FIX_SEL] = imx_clk_mux("ftm0_fix_sel", + ccm + CCM_CSCMR2, 14, 1, + ftm_fix_sels, + ARRAY_SIZE(ftm_fix_sels)); + clk[VF610_CLK_FTM0_EXT_FIX_EN] = imx_clk_gate("ftm0_ext_fix_en", + "dummy", + ccm + CCM_CSCDR1, 25); + clk[VF610_CLK_FTM1_EXT_SEL] = imx_clk_mux("ftm1_ext_sel", + ccm + CCM_CSCMR2, 8, 2, + ftm_ext_sels, + ARRAY_SIZE(ftm_ext_sels)); + clk[VF610_CLK_FTM1_FIX_SEL] = imx_clk_mux("ftm1_fix_sel", + ccm + CCM_CSCMR2, 15, 1, + ftm_fix_sels, + ARRAY_SIZE(ftm_fix_sels)); + clk[VF610_CLK_FTM1_EXT_FIX_EN] = imx_clk_gate("ftm1_ext_fix_en", + "dummy", + ccm + CCM_CSCDR1, 26); + clk[VF610_CLK_FTM2_EXT_SEL] = imx_clk_mux("ftm2_ext_sel", + ccm + CCM_CSCMR2, 10, 2, + ftm_ext_sels, + ARRAY_SIZE(ftm_ext_sels)); + clk[VF610_CLK_FTM2_FIX_SEL] = imx_clk_mux("ftm2_fix_sel", + ccm + CCM_CSCMR2, 16, 1, + ftm_fix_sels, + ARRAY_SIZE(ftm_fix_sels)); + clk[VF610_CLK_FTM2_EXT_FIX_EN] = imx_clk_gate("ftm2_ext_fix_en", + "dummy", + ccm + CCM_CSCDR1, 27); + clk[VF610_CLK_FTM3_EXT_SEL] = imx_clk_mux("ftm3_ext_sel", + ccm + CCM_CSCMR2, 12, 2, + ftm_ext_sels, + ARRAY_SIZE(ftm_ext_sels)); + clk[VF610_CLK_FTM3_FIX_SEL] = imx_clk_mux("ftm3_fix_sel", + ccm + CCM_CSCMR2, 17, 1, + ftm_fix_sels, + ARRAY_SIZE(ftm_fix_sels)); + clk[VF610_CLK_FTM3_EXT_FIX_EN] = imx_clk_gate("ftm3_ext_fix_en", + "dummy", + ccm + CCM_CSCDR1, 28); + + /* ftm(n)_clk are FTM module operation clock */ + clk[VF610_CLK_FTM0] = imx_clk_gate2("ftm0", "ipg_bus", + ccm + CCM_CCGR1, + vf610_ccm_ccgrx_cgn(8)); + clk[VF610_CLK_FTM1] = imx_clk_gate2("ftm1", "ipg_bus", + ccm + CCM_CCGR1, + vf610_ccm_ccgrx_cgn(9)); + clk[VF610_CLK_FTM2] = imx_clk_gate2("ftm2", "ipg_bus", + ccm + CCM_CCGR7, + vf610_ccm_ccgrx_cgn(8)); + clk[VF610_CLK_FTM3] = imx_clk_gate2("ftm3", "ipg_bus", + ccm + CCM_CCGR7, + vf610_ccm_ccgrx_cgn(9)); +} + +static void vf610_ccm_setup_dcus(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "pll1_pfd2", + "pll3_usb_otg", + }; + + clk[VF610_CLK_DCU0_SEL] = imx_clk_mux("dcu0_sel", + ccm + CCM_CSCMR1, 28, 1, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_DCU0_EN] = imx_clk_gate("dcu0_en", "dcu0_sel", + ccm + CCM_CSCDR3, 19); + clk[VF610_CLK_DCU0_DIV] = imx_clk_divider("dcu0_div", "dcu0_en", + ccm + CCM_CSCDR3, 16, 3); + clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "ipg_bus", + ccm + CCM_CCGR3, + vf610_ccm_ccgrx_cgn(8)); + clk[VF610_CLK_DCU1_SEL] = imx_clk_mux("dcu1_sel", + ccm + CCM_CSCMR1, 29, 1, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_DCU1_EN] = imx_clk_gate("dcu1_en", "dcu1_sel", + ccm + CCM_CSCDR3, 23); + clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", + ccm + CCM_CSCDR3, 20, 3); + clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "ipg_bus", + ccm + CCM_CCGR9, + vf610_ccm_ccgrx_cgn(8)); +} + +static void vf610_ccm_setup_tcons(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_TCON0] = imx_clk_gate2("tcon0", "platform_bus", + ccm + CCM_CCGR1, + vf610_ccm_ccgrx_cgn(13)); + clk[VF610_CLK_TCON1] = imx_clk_gate2("tcon1", "platform_bus", + ccm + CCM_CCGR7, + vf610_ccm_ccgrx_cgn(13)); +} + + +static void vf610_ccm_setup_esai(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "audio_ext", + "mlb", + "spdif_rx", + "pll4_audio_div", + }; + + clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", + ccm + CCM_CSCMR1, 20, 2, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", + ccm + CCM_CSCDR2, 30); + clk[VF610_CLK_ESAI_DIV] = imx_clk_divider("esai_div", "esai_en", + ccm + CCM_CSCDR2, 24, 4); + clk[VF610_CLK_ESAI] = imx_clk_gate2("esai", "esai_div", + ccm + CCM_CCGR4, + vf610_ccm_ccgrx_cgn(2)); +} + +static void vf610_ccm_setup_sais(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "audio_ext", + "mlb", + "spdif_rx", + "pll4_audio_div", + }; + + clk[VF610_CLK_SAI0_SEL] = imx_clk_mux("sai0_sel", + ccm + CCM_CSCMR1, 0, 2, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_SAI0_EN] = imx_clk_gate("sai0_en", "sai0_sel", + ccm + CCM_CSCDR1, 16); + clk[VF610_CLK_SAI0_DIV] = imx_clk_divider("sai0_div", "sai0_en", + ccm + CCM_CSCDR1, 0, 4); + clk[VF610_CLK_SAI0] = imx_clk_gate2("sai0", "ipg_bus", + ccm + CCM_CCGR0, + vf610_ccm_ccgrx_cgn(15)); + + clk[VF610_CLK_SAI1_SEL] = imx_clk_mux("sai1_sel", + ccm + CCM_CSCMR1, 2, 2, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_SAI1_EN] = imx_clk_gate("sai1_en", "sai1_sel", + ccm + CCM_CSCDR1, 17); + clk[VF610_CLK_SAI1_DIV] = imx_clk_divider("sai1_div", "sai1_en", + ccm + CCM_CSCDR1, 4, 4); + clk[VF610_CLK_SAI1] = imx_clk_gate2("sai1", "ipg_bus", + ccm + CCM_CCGR1, + vf610_ccm_ccgrx_cgn(0)); + + clk[VF610_CLK_SAI2_SEL] = imx_clk_mux("sai2_sel", + ccm + CCM_CSCMR1, 4, 2, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_SAI2_EN] = imx_clk_gate("sai2_en", "sai2_sel", + ccm + CCM_CSCDR1, 18); + clk[VF610_CLK_SAI2_DIV] = imx_clk_divider("sai2_div", "sai2_en", + ccm + CCM_CSCDR1, 8, 4); + clk[VF610_CLK_SAI2] = imx_clk_gate2("sai2", "ipg_bus", + ccm + CCM_CCGR1, + vf610_ccm_ccgrx_cgn(1)); + + clk[VF610_CLK_SAI3_SEL] = imx_clk_mux("sai3_sel", + ccm + CCM_CSCMR1, 6, 2, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_SAI3_EN] = imx_clk_gate("sai3_en", "sai3_sel", + ccm + CCM_CSCDR1, 19); + clk[VF610_CLK_SAI3_DIV] = imx_clk_divider("sai3_div", "sai3_en", + ccm + CCM_CSCDR1, 12, 4); + clk[VF610_CLK_SAI3] = imx_clk_gate2("sai3", "ipg_bus", + ccm + CCM_CCGR1, + vf610_ccm_ccgrx_cgn(2)); +} + +static void vf610_ccm_setup_nfc(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "platform_bus", + "pll1_pfd1", + "pll3_pfd1", + "pll3_pfd3", + }; + + clk[VF610_CLK_NFC_SEL] = imx_clk_mux("nfc_sel", + ccm + CCM_CSCMR1, 12, 2, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_NFC_EN] = imx_clk_gate("nfc_en", "nfc_sel", + ccm + CCM_CSCDR2, 9); + clk[VF610_CLK_NFC_PRE_DIV] = imx_clk_divider("nfc_pre_div", "nfc_en", + ccm + CCM_CSCDR3, 13, 3); + clk[VF610_CLK_NFC_FRAC_DIV] = imx_clk_divider("nfc_frac_div", + "nfc_pre_div", + ccm + CCM_CSCDR2, 4, 4); + clk[VF610_CLK_NFC] = imx_clk_gate2("nfc", "nfc_frac_div", + ccm + CCM_CCGR10, + vf610_ccm_ccgrx_cgn(0)); +} + +static void vf610_ccm_setup_gpu(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "pll2_pfd2", + "pll3_pfd2", + }; + + clk[VF610_CLK_GPU_SEL] = imx_clk_mux("gpu_sel", + ccm + CCM_CSCMR1, 14, 1, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_GPU_EN] = imx_clk_gate("gpu_en", "gpu_sel", + ccm + CCM_CSCDR2, 10); + clk[VF610_CLK_GPU2D] = imx_clk_gate2("gpu", "gpu_en", + ccm + CCM_CCGR8, + vf610_ccm_ccgrx_cgn(15)); +} + +static void vf610_ccm_setup_vadc(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + static const char *sources[] = { + "pll6_video_div", + "pll3_usb_otg_div", + "pll3_usb_otg", + }; + + clk[VF610_CLK_VADC_SEL] = imx_clk_mux("vadc_sel", + ccm + CCM_CSCMR1, 8, 2, + sources, ARRAY_SIZE(sources)); + clk[VF610_CLK_VADC_EN] = imx_clk_gate("vadc_en", "vadc_sel", + ccm + CCM_CSCDR1, 22); + clk[VF610_CLK_VADC_DIV] = imx_clk_divider("vadc_div", "vadc_en", + ccm + CCM_CSCDR1, 20, 2); + clk[VF610_CLK_VADC_DIV_HALF] = imx_clk_fixed_factor("vadc_div_half", + "vadc_div", + 1, 2); + clk[VF610_CLK_VADC] = imx_clk_gate2("vadc", "vadc_div", + ccm + CCM_CCGR8, + vf610_ccm_ccgrx_cgn(7)); +} + + +static void vf610_ccm_setup_adcs(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_ADC0] = imx_clk_gate2("adc0", "ipg_bus", + ccm + CCM_CCGR1, + vf610_ccm_ccgrx_cgn(11)); + clk[VF610_CLK_ADC1] = imx_clk_gate2("adc1", "ipg_bus", + ccm + CCM_CCGR7, + vf610_ccm_ccgrx_cgn(11)); + clk[VF610_CLK_DAC0] = imx_clk_gate2("dac0", "ipg_bus", + ccm + CCM_CCGR8, + vf610_ccm_ccgrx_cgn(12)); + clk[VF610_CLK_DAC1] = imx_clk_gate2("dac1", "ipg_bus", + ccm + CCM_CCGR8, + vf610_ccm_ccgrx_cgn(13)); +} + +static void vf610_ccm_setup_flexcans(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_FLEXCAN0_EN] = imx_clk_gate("flexcan0_en", "ipg_bus", + ccm + CCM_CSCDR2, 11); + clk[VF610_CLK_FLEXCAN0] = imx_clk_gate2("flexcan0", "flexcan0_en", + ccm + CCM_CCGR0, + vf610_ccm_ccgrx_cgn(0)); + clk[VF610_CLK_FLEXCAN1_EN] = imx_clk_gate("flexcan1_en", "ipg_bus", + ccm + CCM_CSCDR2, 12); + clk[VF610_CLK_FLEXCAN1] = imx_clk_gate2("flexcan1", "flexcan1_en", + ccm + CCM_CCGR9, + vf610_ccm_ccgrx_cgn(4)); +} + +static void vf610_ccm_setup_dmas(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_DMAMUX0] = imx_clk_gate2("dmamux0", "platform_bus", + ccm + CCM_CCGR0, + vf610_ccm_ccgrx_cgn(4)); + clk[VF610_CLK_DMAMUX1] = imx_clk_gate2("dmamux1", "platform_bus", + ccm + CCM_CCGR0, + vf610_ccm_ccgrx_cgn(5)); + clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", + ccm + CCM_CCGR6, + vf610_ccm_ccgrx_cgn(1)); + clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", + ccm + CCM_CCGR6, + vf610_ccm_ccgrx_cgn(2)); +} + +static void vf610_ccm_setup_misc(struct device_node *np, + void __iomem *anatop, + void __iomem *ccm) +{ + clk[VF610_CLK_ASRC] = imx_clk_gate2("asrc", "ipg_bus", + ccm + CCM_CCGR4, + vf610_ccm_ccgrx_cgn(1)); + clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", + ccm + CCM_CCGR6, + vf610_ccm_ccgrx_cgn(7)); + clk[VF610_CLK_DAP] = imx_clk_gate("dap", "platform_bus", + ccm + CCM_CCSR, 24); + clk[VF610_CLK_OCOTP] = imx_clk_gate("ocotp", "ipg_bus", + ccm + CCM_CCGR6, + vf610_ccm_ccgrx_cgn(5)); + + clk[VF610_CLK_LVDS1_IN] = imx_clk_gate_exclusive("lvds1_in", + "anaclk1", + anatop + ANA_MISC1, + 12, BIT(10)); +} + +typedef void (*vf610_ccm_group_setup_func) (struct device_node *np, + void __iomem *anatop, + void __iomem *ccm); + +static void __init vf610_clocks_init(struct device_node *np) +{ + size_t i; + struct device_node *node; + void __iomem *anatop; + void __iomem *ccm; + + static const vf610_ccm_group_setup_func group_setup_funcs[] = { + vf610_ccm_setup_fixed, + vf610_ccm_setup_from_dt, + vf610_ccm_setup_slow_clk, + vf610_ccm_setup_fast_clk, + vf610_ccm_setup_pll_bypass_srcs, + vf610_ccm_setup_plls, + vf610_ccm_setup_pll_bypass, + vf610_ccm_setup_group1, + vf610_ccm_setup_pfds, + vf610_ccm_setup_pll1_pfd_out, + vf610_ccm_setup_pll2_pfd_out, + vf610_ccm_setup_sys_out, + vf610_ccm_setup_ddr_out, + vf610_ccm_setup_dividers, + vf610_ccm_setup_pll4_main_div, + vf610_ccm_setup_ddrmc, + vf610_ccm_setup_wkpu, + vf610_ccm_setup_usbphys, + vf610_ccm_setup_usbcs, + vf610_ccm_setup_qspis, + vf610_ccm_setup_enets, + vf610_ccm_setup_pit, + vf610_ccm_setup_uarts, + vf610_ccm_setup_i2cs, + vf610_ccm_setup_dspis, + vf610_ccm_setup_wdt, + vf610_ccm_setup_esdhcs, + vf610_ccm_setup_ftms, + vf610_ccm_setup_dcus, + vf610_ccm_setup_tcons, + vf610_ccm_setup_esai, + vf610_ccm_setup_sais, + vf610_ccm_setup_nfc, + vf610_ccm_setup_gpu, + vf610_ccm_setup_vadc, + vf610_ccm_setup_adcs, + vf610_ccm_setup_flexcans, + vf610_ccm_setup_dmas, + vf610_ccm_setup_misc, + }; + + ccm = of_iomap(np, 0); + BUG_ON(!ccm); + + node = of_find_compatible_node(NULL, NULL, "fsl,vf610-anatop"); + anatop = of_iomap(node, 0); + /* anatop = syscon_base_lookup_by_phandle(np, "fsl,anatop"); */ + BUG_ON(IS_ERR(anatop)); + + for (i = 0; i < ARRAY_SIZE(group_setup_funcs); i++) + group_setup_funcs[i](np, anatop, ccm); + + imx_check_clocks(clk, VF610_CLK_END); + + /* Do not bypass PLLs initially */ + + clk_set_parent(clk[VF610_PLL1_BYPASS], clk[VF610_CLK_PLL1]); + clk_set_parent(clk[VF610_PLL2_BYPASS], clk[VF610_CLK_PLL2]); + clk_set_parent(clk[VF610_PLL3_BYPASS], clk[VF610_CLK_PLL3]); + clk_set_parent(clk[VF610_PLL4_BYPASS], clk[VF610_CLK_PLL4]); + clk_set_parent(clk[VF610_PLL5_BYPASS], clk[VF610_CLK_PLL5]); + clk_set_parent(clk[VF610_PLL6_BYPASS], clk[VF610_CLK_PLL6]); + clk_set_parent(clk[VF610_PLL7_BYPASS], clk[VF610_CLK_PLL7]); + + clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]); + clk_set_rate(clk[VF610_CLK_QSPI0_X4_DIV], + clk_get_rate(clk[VF610_CLK_QSPI0_SEL]) / 2); + clk_set_rate(clk[VF610_CLK_QSPI0_X2_DIV], + clk_get_rate(clk[VF610_CLK_QSPI0_X4_DIV]) / 2); + clk_set_rate(clk[VF610_CLK_QSPI0_X1_DIV], + clk_get_rate(clk[VF610_CLK_QSPI0_X2_DIV]) / 2); + + clk_set_parent(clk[VF610_CLK_QSPI1_SEL], clk[VF610_CLK_PLL1_PFD4]); + clk_set_rate(clk[VF610_CLK_QSPI1_X4_DIV], + clk_get_rate(clk[VF610_CLK_QSPI1_SEL]) / 2); + clk_set_rate(clk[VF610_CLK_QSPI1_X2_DIV], + clk_get_rate(clk[VF610_CLK_QSPI1_X4_DIV]) / 2); + clk_set_rate(clk[VF610_CLK_QSPI1_X1_DIV], + clk_get_rate(clk[VF610_CLK_QSPI1_X2_DIV]) / 2); + + clk_set_parent(clk[VF610_CLK_SAI0_SEL], clk[VF610_CLK_AUDIO_EXT]); + clk_set_parent(clk[VF610_CLK_SAI1_SEL], clk[VF610_CLK_AUDIO_EXT]); + clk_set_parent(clk[VF610_CLK_SAI2_SEL], clk[VF610_CLK_AUDIO_EXT]); + clk_set_parent(clk[VF610_CLK_SAI3_SEL], clk[VF610_CLK_AUDIO_EXT]); + + clk_enable(clk[VF610_CLK_SYS_BUS]); + clk_enable(clk[VF610_CLK_DDR_SEL]); + clk_enable(clk[VF610_CLK_DAP]); + clk_enable(clk[VF610_CLK_DDRMC]); + clk_enable(clk[VF610_CLK_WKPU]); + + clk_data.clks = clk; + clk_data.clk_num = ARRAY_SIZE(clk); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); +} +CLK_OF_DECLARE(vf610, "fsl,vf610-ccm", vf610_clocks_init); -- 2.5.5 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox