summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx25/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx25/clock.c')
-rw-r--r--arch/arm/mach-mx25/clock.c1737
1 files changed, 1737 insertions, 0 deletions
diff --git a/arch/arm/mach-mx25/clock.c b/arch/arm/mach-mx25/clock.c
new file mode 100644
index 000000000000..31ab725e1ba8
--- /dev/null
+++ b/arch/arm/mach-mx25/clock.c
@@ -0,0 +1,1737 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * 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
+ */
+
+/* based on mach-mx27/clock.c */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/clock.h>
+#include "crm_regs.h"
+
+#define OSC24M_CLK_FREQ 24000000 /* 24M reference clk */
+#define OSC32K_CLK_FREQ 32768 /* 32.768k oscillator in */
+
+#if defined CONFIG_CPU_FREQ_IMX
+#define AHB_CLK_DEFAULT 133000000
+#define ARM_SRC_DEFAULT 532000000
+#endif
+
+static struct clk mpll_clk;
+static struct clk upll_clk;
+static struct clk ahb_clk;
+static struct clk upll_24610k_clk;
+int cpu_wp_nr;
+
+static int _clk_enable(struct clk *clk)
+{
+ unsigned long reg;
+
+ reg = __raw_readl(clk->enable_reg);
+ reg |= 1 << clk->enable_shift;
+ __raw_writel(reg, clk->enable_reg);
+
+ return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+ unsigned long reg;
+
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(1 << clk->enable_shift);
+ __raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_upll_enable(struct clk *clk)
+{
+ unsigned long reg;
+
+ reg = __raw_readl(MXC_CCM_CCTL);
+ reg &= ~MXC_CCM_CCTL_UPLL_DISABLE;
+ __raw_writel(reg, MXC_CCM_CCTL);
+
+ while ((__raw_readl(MXC_CCM_UPCTL) & MXC_CCM_UPCTL_LF) == 0) ;
+
+ return 0;
+}
+
+static void _clk_upll_disable(struct clk *clk)
+{
+ unsigned long reg;
+
+ reg = __raw_readl(MXC_CCM_CCTL);
+ reg |= MXC_CCM_CCTL_UPLL_DISABLE;
+ __raw_writel(reg, MXC_CCM_CCTL);
+}
+
+static int _perclk_enable(struct clk *clk)
+{
+ unsigned long reg;
+
+ reg = __raw_readl(MXC_CCM_CGCR0);
+ reg |= 1 << clk->id;
+ __raw_writel(reg, MXC_CCM_CGCR0);
+
+ return 0;
+}
+
+static void _perclk_disable(struct clk *clk)
+{
+ unsigned long reg;
+
+ reg = __raw_readl(MXC_CCM_CGCR0);
+ reg &= ~(1 << clk->id);
+ __raw_writel(reg, MXC_CCM_CGCR0);
+}
+
+static void _clk_pll_recalc(struct clk *clk)
+{
+ unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
+ unsigned long ref_clk;
+ unsigned long reg;
+ unsigned long long temp;
+
+ ref_clk = clk->parent->rate;
+
+ if (clk == &mpll_clk) {
+ reg = __raw_readl(MXC_CCM_MPCTL);
+ pdf = (reg & MXC_CCM_MPCTL_PD_MASK) >> MXC_CCM_MPCTL_PD_OFFSET;
+ mfd =
+ (reg & MXC_CCM_MPCTL_MFD_MASK) >> MXC_CCM_MPCTL_MFD_OFFSET;
+ mfi =
+ (reg & MXC_CCM_MPCTL_MFI_MASK) >> MXC_CCM_MPCTL_MFI_OFFSET;
+ mfn =
+ (reg & MXC_CCM_MPCTL_MFN_MASK) >> MXC_CCM_MPCTL_MFN_OFFSET;
+ } else if (clk == &upll_clk) {
+ reg = __raw_readl(MXC_CCM_UPCTL);
+ pdf = (reg & MXC_CCM_UPCTL_PD_MASK) >> MXC_CCM_UPCTL_PD_OFFSET;
+ mfd =
+ (reg & MXC_CCM_UPCTL_MFD_MASK) >> MXC_CCM_UPCTL_MFD_OFFSET;
+ mfi =
+ (reg & MXC_CCM_UPCTL_MFI_MASK) >> MXC_CCM_UPCTL_MFI_OFFSET;
+ mfn =
+ (reg & MXC_CCM_UPCTL_MFN_MASK) >> MXC_CCM_UPCTL_MFN_OFFSET;
+ } else {
+ BUG(); /* oops */
+ }
+
+ mfi = (mfi <= 5) ? 5 : mfi;
+ temp = 2LL * ref_clk * mfn;
+ do_div(temp, mfd + 1);
+ temp = 2LL * ref_clk * mfi + temp;
+ do_div(temp, pdf + 1);
+
+ clk->rate = temp;
+}
+
+static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate)
+{
+ int div = clk->parent->rate / rate;
+
+ if (clk->parent->rate % rate)
+ div++;
+
+ if (div > 4)
+ div = 4;
+
+ return clk->parent->rate / div;
+}
+
+static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long div = 0x0, reg = 0x0;
+ unsigned long cctl = __raw_readl(MXC_CCM_CCTL);
+
+#if defined CONFIG_CPU_FREQ_IMX
+ struct cpu_wp *cpu_wp;
+ unsigned long ahb_clk_div = 0;
+ unsigned long arm_src = 0;
+ int i;
+
+ cpu_wp = get_cpu_wp(&cpu_wp_nr);
+ for (i = 0; i < cpu_wp_nr; i++) {
+ if (cpu_wp[i].cpu_rate == rate) {
+ div = cpu_wp[i].cpu_podf;
+ ahb_clk_div = cpu_wp[i].cpu_rate / AHB_CLK_DEFAULT - 1;
+ arm_src =
+ (cpu_wp[i].pll_rate == ARM_SRC_DEFAULT) ? 0 : 1;
+ break;
+ }
+ }
+ if (i == cpu_wp_nr)
+ return -EINVAL;
+ reg = (cctl & ~MXC_CCM_CCTL_ARM_MASK) |
+ (div << MXC_CCM_CCTL_ARM_OFFSET);
+ reg = (reg & ~MXC_CCM_CCTL_AHB_MASK) |
+ (ahb_clk_div << MXC_CCM_CCTL_AHB_OFFSET);
+ reg = (reg & ~MXC_CCM_CCTL_ARM_SRC) |
+ (arm_src << MXC_CCM_CCTL_ARM_SRC_OFFSET);
+ __raw_writel(reg, MXC_CCM_CCTL);
+ clk->rate = rate;
+#else
+ div = clk->parent->rate / rate;
+
+ if (div > 4 || div < 1 || ((clk->parent->rate / div) != rate))
+ return -EINVAL;
+ div--;
+
+ reg =
+ (cctl & ~MXC_CCM_CCTL_ARM_MASK) | (div << MXC_CCM_CCTL_ARM_OFFSET);
+ __raw_writel(reg, MXC_CCM_CCTL);
+ clk->rate = rate;
+#endif
+
+ return 0;
+}
+
+static void _clk_cpu_recalc(struct clk *clk)
+{
+ unsigned long div;
+ unsigned long cctl = __raw_readl(MXC_CCM_CCTL);
+
+ div = (cctl & MXC_CCM_CCTL_ARM_MASK) >> MXC_CCM_CCTL_ARM_OFFSET;
+
+ clk->rate = clk->parent->rate / (div + 1);
+
+ if (cctl & MXC_CCM_CCTL_ARM_SRC) {
+ clk->rate *= 3;
+ clk->rate /= 4;
+ }
+}
+
+static void _clk_ahb_recalc(struct clk *clk)
+{
+ unsigned long div;
+ unsigned long cctl = __raw_readl(MXC_CCM_CCTL);
+
+ div = (cctl & MXC_CCM_CCTL_AHB_MASK) >> MXC_CCM_CCTL_AHB_OFFSET;
+
+ clk->rate = clk->parent->rate / (div + 1);
+}
+
+static void *pcdr_a[4] = {
+ MXC_CCM_PCDR0, MXC_CCM_PCDR1, MXC_CCM_PCDR2, MXC_CCM_PCDR3
+};
+static void _clk_perclkx_recalc(struct clk *clk)
+{
+ unsigned long perclk_pdf;
+ unsigned long pcdr;
+
+ if (clk->id < 0 || clk->id > 15)
+ return;
+
+ pcdr = __raw_readl(pcdr_a[clk->id >> 2]);
+
+ perclk_pdf =
+ (pcdr >> ((clk->id & 3) << 3)) & MXC_CCM_PCDR1_PERDIV1_MASK;
+
+ clk->rate = clk->parent->rate / (perclk_pdf + 1);
+}
+
+static unsigned long _clk_perclkx_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ unsigned long div;
+
+ div = clk->parent->rate / rate;
+ if (clk->parent->rate % rate)
+ div++;
+
+ if (div > 64)
+ div = 64;
+
+ return clk->parent->rate / div;
+}
+
+static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long reg;
+ unsigned long div;
+
+ if (clk->id < 0 || clk->id > 15)
+ return -EINVAL;
+
+ div = clk->parent->rate / rate;
+ if (div > 64 || div < 1 || ((clk->parent->rate / div) != rate))
+ return -EINVAL;
+ div--;
+
+ reg =
+ __raw_readl(pcdr_a[clk->id >> 2]) & ~(MXC_CCM_PCDR1_PERDIV1_MASK <<
+ ((clk->id & 3) << 3));
+ reg |= div << ((clk->id & 3) << 3);
+ __raw_writel(reg, pcdr_a[clk->id >> 2]);
+
+ clk->rate = rate;
+
+ return 0;
+}
+
+static int _clk_perclkx_set_parent(struct clk *clk, struct clk *parent)
+{
+ unsigned long mcr;
+
+ if (parent != &upll_clk && parent != &ahb_clk)
+ return -EINVAL;
+
+ clk->parent = parent;
+ mcr = __raw_readl(MXC_CCM_MCR);
+ if (parent == &upll_clk)
+ mcr |= (1 << clk->id);
+ else
+ mcr &= ~(1 << clk->id);
+
+ __raw_writel(mcr, MXC_CCM_MCR);
+
+ return 0;
+}
+
+static int _clk_perclkx_set_parent3(struct clk *clk, struct clk *parent)
+{
+ unsigned long mcr = __raw_readl(MXC_CCM_MCR);
+ int bit;
+
+ if (parent != &upll_clk && parent != &ahb_clk &&
+ parent != &upll_24610k_clk)
+ return -EINVAL;
+
+ switch (clk->id) {
+ case 2:
+ bit = MXC_CCM_MCR_ESAI_CLK_MUX_OFFSET;
+ break;
+ case 13:
+ bit = MXC_CCM_MCR_SSI1_CLK_MUX_OFFSET;
+ break;
+ case 14:
+ bit = MXC_CCM_MCR_SSI2_CLK_MUX_OFFSET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (parent == &upll_24610k_clk) {
+ mcr |= 1 << bit;
+ __raw_writel(mcr, MXC_CCM_MCR);
+ clk->parent = parent;
+ } else {
+ mcr &= ~(1 << bit);
+ __raw_writel(mcr, MXC_CCM_MCR);
+ return _clk_perclkx_set_parent(clk, parent);
+ }
+
+ return 0;
+}
+
+static void _clk_ipg_recalc(struct clk *clk)
+{
+ clk->rate = clk->parent->rate / 2; /* Always AHB / 2 */
+}
+
+static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
+{
+ return clk->parent->round_rate(clk->parent, rate);
+}
+
+static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret;
+
+ ret = clk->parent->set_rate(clk->parent, rate);
+ if (ret == 0)
+ clk->rate = rate;
+ return ret;
+}
+
+/* Top-level clocks */
+
+static struct clk osc24m_clk = {
+ .name = "osc24m",
+ .rate = OSC24M_CLK_FREQ,
+ .flags = RATE_PROPAGATES,
+};
+
+static struct clk osc32k_clk = {
+ .name = "osc32k",
+ .rate = OSC32K_CLK_FREQ,
+ .flags = RATE_PROPAGATES,
+};
+
+static struct clk mpll_clk = {
+ .name = "mpll",
+ .parent = &osc24m_clk,
+ .recalc = _clk_pll_recalc,
+ .flags = RATE_PROPAGATES,
+};
+
+static struct clk upll_clk = {
+ .name = "upll",
+ .parent = &osc24m_clk,
+ .recalc = _clk_pll_recalc,
+ .enable = _clk_upll_enable,
+ .disable = _clk_upll_disable,
+ .flags = RATE_PROPAGATES,
+};
+
+static void _clk_24610k_recalc(struct clk *clk)
+{
+ long long temp = clk->parent->rate * 2461LL;
+
+ do_div(temp, 24000);
+
+ clk->rate = temp; /* Always (UPLL * 24.61 / 240) */
+}
+
+static struct clk upll_24610k_clk = {
+ .name = "upll_24610k",
+ .parent = &upll_clk,
+ .recalc = _clk_24610k_recalc,
+ .flags = RATE_PROPAGATES,
+};
+
+/* Mid-level clocks */
+
+static struct clk cpu_clk = { /* ARM clock */
+ .name = "cpu_clk",
+ .parent = &mpll_clk,
+ .set_rate = _clk_cpu_set_rate,
+ .recalc = _clk_cpu_recalc,
+ .round_rate = _clk_cpu_round_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static struct clk ahb_clk = { /* a.k.a. HCLK */
+ .name = "ahb_clk",
+ .parent = &cpu_clk,
+ .recalc = _clk_ahb_recalc,
+ .flags = RATE_PROPAGATES,
+};
+
+static struct clk ipg_clk = {
+ .name = "ipg_clk",
+ .parent = &ahb_clk,
+ .recalc = _clk_ipg_recalc,
+ .flags = RATE_PROPAGATES,
+};
+
+/* Bottom-level clocks */
+
+struct clk usb_ahb_clk = {
+ .name = "usb_ahb_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_USBOTG_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk rtic_clk = {
+ .name = "rtic_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_RTIC_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk emi_clk = {
+ .name = "emi_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_EMI_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk brom_clk = {
+ .name = "brom_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_BROM_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk per_clk[] = {
+ {
+ .name = "per_csi_clk",
+ .id = 0,
+ .parent = &upll_clk, /* can be AHB or UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_epit_clk",
+ .id = 1,
+ .parent = &ahb_clk, /* can be AHB or UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_esai_clk",
+ .id = 2,
+ .parent = &ahb_clk, /* can be AHB or UPLL or 24.61MHz */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent3,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_esdhc1_clk",
+ .id = 3,
+ .parent = &ahb_clk, /* can be AHB or UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_esdhc2_clk",
+ .id = 4,
+ .parent = &ahb_clk, /* can be AHB or UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_gpt_clk",
+ .id = 5,
+ .parent = &ahb_clk, /* Must be AHB */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_i2c_clk",
+ .id = 6,
+ .parent = &ahb_clk, /* can be AHB or UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_lcdc_clk",
+ .id = 7,
+ .parent = &upll_clk, /* Must be UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_nfc_clk",
+ .id = 8,
+ .parent = &ahb_clk, /* can be AHB or UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_owire_clk",
+ .id = 9,
+ .parent = &ahb_clk, /* can be AHB or UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_pwm_clk",
+ .id = 10,
+ .parent = &ahb_clk, /* can be AHB or UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_sim1_clk",
+ .id = 11,
+ .parent = &ahb_clk, /* can be AHB or UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_sim2_clk",
+ .id = 12,
+ .parent = &ahb_clk, /* can be AHB or UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_ssi1_clk",
+ .id = 13,
+ .parent = &ahb_clk, /* can be AHB or UPLL or 24.61MHz */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent3,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_ssi2_clk",
+ .id = 14,
+ .parent = &ahb_clk, /* can be AHB or UPLL or 24.61MHz */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent3,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+ {
+ .name = "per_uart_clk",
+ .id = 15,
+ .parent = &ahb_clk, /* can be AHB or UPLL */
+ .round_rate = _clk_perclkx_round_rate,
+ .set_rate = _clk_perclkx_set_rate,
+ .set_parent = _clk_perclkx_set_parent,
+ .recalc = _clk_perclkx_recalc,
+ .enable = _perclk_enable,
+ .disable = _perclk_disable,
+ .flags = RATE_PROPAGATES,},
+};
+
+struct clk nfc_clk = {
+ .name = "nfc_clk",
+ .id = 0,
+ .parent = &per_clk[8],
+};
+
+struct clk audmux_clk = {
+ .name = "audmux_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_AUDMUX_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk ata_clk[] = {
+ {
+ .name = "ata_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_ATA_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &ata_clk[1],},
+ {
+ .name = "ata_ahb_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_ATA_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk can_clk[] = {
+ {
+ .name = "can_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_CAN1_OFFSET,
+ .disable = _clk_disable,},
+ {
+ .name = "can_clk",
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_CAN2_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk csi_clk[] = {
+ {
+ .name = "csi_clk",
+ .id = 0,
+ .parent = &per_clk[0],
+ .secondary = &csi_clk[1],},
+ {
+ .name = "csi_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_CSI_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &csi_clk[2],},
+ {
+ .name = "csi_ahb_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_CSI_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk cspi_clk[] = {
+ {
+ .name = "cspi_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_CSPI1_OFFSET,
+ .disable = _clk_disable,},
+ {
+ .name = "cspi_clk",
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_CSPI2_OFFSET,
+ .disable = _clk_disable,},
+ {
+ .name = "cspi_clk",
+ .id = 2,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_CSPI3_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk dryice_clk = {
+ .name = "dryice_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_DRYICE_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk ect_clk = {
+ .name = "ect_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_ECT_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk epit1_clk[] = {
+ {
+ .name = "epit_clk",
+ .id = 0,
+ .parent = &per_clk[1],
+ .secondary = &epit1_clk[1],},
+ {
+ .name = "epit_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_EPIT1_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk epit2_clk[] = {
+ {
+ .name = "epit_clk",
+ .id = 1,
+ .parent = &per_clk[1],
+ .secondary = &epit2_clk[1],},
+ {
+ .name = "epit_ipg_clk",
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_EPIT2_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk esai_clk[] = {
+ {
+ .name = "esai_clk",
+ .id = 0,
+ .parent = &per_clk[2],
+ .secondary = &esai_clk[1],},
+ {
+ .name = "esai_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_ESAI_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &esai_clk[2],},
+ {
+ .name = "esai_ahb_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_ESAI_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk esdhc1_clk[] = {
+ {
+ .name = "esdhc_clk",
+ .id = 0,
+ .parent = &per_clk[3],
+ .secondary = &esdhc1_clk[1],},
+ {
+ .name = "esdhc_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_ESDHC1_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &esdhc1_clk[2],},
+ {
+ .name = "esdhc_ahb_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_ESDHC1_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk esdhc2_clk[] = {
+ {
+ .name = "esdhc_clk",
+ .id = 1,
+ .parent = &per_clk[4],
+ .secondary = &esdhc2_clk[1],},
+ {
+ .name = "esdhc_ipg_clk",
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_ESDHC2_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &esdhc2_clk[2],},
+ {
+ .name = "esdhc_ahb_clk",
+ .id = 1,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_ESDHC2_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk fec_clk[] = {
+ {
+ .name = "fec_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_FEC_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &fec_clk[1],},
+ {
+ .name = "fec_ahb_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_FEC_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk gpio_clk[] = {
+ {
+ .name = "gpio_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_GPIO1_OFFSET,
+ .disable = _clk_disable,},
+ {
+ .name = "gpio_clk",
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_GPIO2_OFFSET,
+ .disable = _clk_disable,},
+ {
+ .name = "gpio_clk",
+ .id = 2,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_GPIO3_OFFSET,
+ .disable = _clk_disable,},
+};
+
+static struct clk gpt1_clk[] = {
+ {
+ .name = "gpt_clk",
+ .id = 0,
+ .parent = &per_clk[5],
+ .secondary = &gpt1_clk[1],},
+ {
+ .name = "gpt_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_GPT1_OFFSET,
+ .disable = _clk_disable,},
+};
+
+static struct clk gpt2_clk[] = {
+ {
+ .name = "gpt_clk",
+ .id = 1,
+ .parent = &per_clk[5],
+ .secondary = &gpt1_clk[1],},
+ {
+ .name = "gpt_ipg_clk",
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_GPT2_OFFSET,
+ .disable = _clk_disable,},
+};
+
+static struct clk gpt3_clk[] = {
+ {
+ .name = "gpt_clk",
+ .id = 2,
+ .parent = &per_clk[5],
+ .secondary = &gpt1_clk[1],},
+ {
+ .name = "gpt_ipg_clk",
+ .id = 2,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_GPT3_OFFSET,
+ .disable = _clk_disable,},
+};
+
+static struct clk gpt4_clk[] = {
+ {
+ .name = "gpt_clk",
+ .id = 3,
+ .parent = &per_clk[5],
+ .secondary = &gpt1_clk[1],},
+ {
+ .name = "gpt_ipg_clk",
+ .id = 3,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_GPT4_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk i2c_clk[] = {
+ {
+ .name = "i2c_clk",
+ .id = 0,
+ .parent = &per_clk[6],},
+ {
+ .name = "i2c_clk",
+ .id = 1,
+ .parent = &per_clk[6],},
+ {
+ .name = "i2c_clk",
+ .id = 2,
+ .parent = &per_clk[6],},
+};
+
+struct clk iim_clk = {
+ .name = "iim_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_IIM_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk iomuxc_clk = {
+ .name = "iomuxc_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_IOMUXC_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk kpp_clk = {
+ .name = "kpp_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_KPP_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk lcdc_clk[] = {
+ {
+ .name = "lcdc_clk",
+ .id = 0,
+ .parent = &per_clk[7],
+ .secondary = &lcdc_clk[1],
+ .round_rate = _clk_parent_round_rate,
+ .set_rate = _clk_parent_set_rate,},
+ {
+ .name = "lcdc_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_LCDC_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &lcdc_clk[2],},
+ {
+ .name = "lcdc_ahb_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_LCDC_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk owire_clk[] = {
+ {
+ .name = "owire_clk",
+ .id = 0,
+ .parent = &per_clk[9],
+ .secondary = &owire_clk[1],},
+ {
+ .name = "owire_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_OWIRE_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk pwm1_clk[] = {
+ {
+ .name = "pwm_clk",
+ .id = 0,
+ .parent = &per_clk[10],
+ .secondary = &pwm1_clk[1],},
+ {
+ .name = "pwm_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR1,
+ .enable_shift = MXC_CCM_CGCR1_PWM1_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk pwm2_clk[] = {
+ {
+ .name = "pwm_clk",
+ .id = 1,
+ .parent = &per_clk[10],
+ .secondary = &pwm2_clk[1],},
+ {
+ .name = "pwm_ipg_clk",
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_PWM2_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk pwm3_clk[] = {
+ {
+ .name = "pwm_clk",
+ .id = 2,
+ .parent = &per_clk[10],
+ .secondary = &pwm3_clk[1],},
+ {
+ .name = "pwm_ipg_clk",
+ .id = 2,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_PWM3_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk pwm4_clk[] = {
+ {
+ .name = "pwm_clk",
+ .id = 3,
+ .parent = &per_clk[10],
+ .secondary = &pwm4_clk[1],},
+ {
+ .name = "pwm_ipg_clk",
+ .id = 3,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_PWM3_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk rng_clk = {
+ .name = "rng_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_RNGB_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk scc_clk = {
+ .name = "scc_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_SCC_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk sdma_clk[] = {
+ {
+ .name = "sdma_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_SDMA_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &sdma_clk[1],},
+ {
+ .name = "sdma_ahb_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_SDMA_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk sim1_clk[] = {
+ {
+ .name = "sim1_clk",
+ .id = 0,
+ .parent = &per_clk[11],
+ .secondary = &sim1_clk[1],},
+ {
+ .name = "sim_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_SIM1_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk sim2_clk[] = {
+ {
+ .name = "sim2_clk",
+ .id = 1,
+ .parent = &per_clk[12],
+ .secondary = &sim2_clk[1],},
+ {
+ .name = "sim_ipg_clk",
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_SIM2_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk slcdc_clk[] = {
+ {
+ .name = "slcdc_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_SLCDC_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &slcdc_clk[1],},
+ {
+ .name = "slcdc_ahb_clk",
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR0,
+ .enable_shift = MXC_CCM_CGCR0_HCLK_SLCDC_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk spba_clk = {
+ .name = "spba_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_SPBA_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk ssi1_clk[] = {
+ {
+ .name = "ssi_clk",
+ .id = 0,
+ .parent = &per_clk[13],
+ .secondary = &ssi1_clk[1],},
+ {
+ .name = "ssi_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_SSI1_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk ssi2_clk[] = {
+ {
+ .name = "ssi_clk",
+ .id = 1,
+ .parent = &per_clk[14],
+ .secondary = &ssi2_clk[1],},
+ {
+ .name = "ssi_ipg_clk",
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_SSI2_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk tchscrn_clk = {
+ .name = "tchscrn_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_TCHSCRN_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk uart1_clk[] = {
+ {
+ .name = "uart_clk",
+ .id = 0,
+ .parent = &per_clk[15],
+ .secondary = &uart1_clk[1],},
+ {
+ .name = "uart_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_UART1_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk uart2_clk[] = {
+ {
+ .name = "uart_clk",
+ .id = 1,
+ .parent = &per_clk[15],
+ .secondary = &uart2_clk[1],},
+ {
+ .name = "uart_ipg_clk",
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_UART2_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk uart3_clk[] = {
+ {
+ .name = "uart_clk",
+ .id = 2,
+ .parent = &per_clk[15],
+ .secondary = &uart3_clk[1],},
+ {
+ .name = "uart_ipg_clk",
+ .id = 2,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_UART3_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk uart4_clk[] = {
+ {
+ .name = "uart_clk",
+ .id = 3,
+ .parent = &per_clk[15],
+ .secondary = &uart4_clk[1],},
+ {
+ .name = "uart_ipg_clk",
+ .id = 3,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_UART4_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk uart5_clk[] = {
+ {
+ .name = "uart_clk",
+ .id = 4,
+ .parent = &per_clk[15],
+ .secondary = &uart5_clk[1],},
+ {
+ .name = "uart_ipg_clk",
+ .id = 4,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_UART5_OFFSET,
+ .disable = _clk_disable,},
+};
+
+struct clk wdog_clk = {
+ .name = "wdog_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CGCR2,
+ .enable_shift = MXC_CCM_CGCR2_WDOG_OFFSET,
+ .disable = _clk_disable,
+};
+
+static unsigned long _clk_usb_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long div;
+
+ div = clk->parent->rate / rate;
+ if (clk->parent->rate % rate)
+ div++;
+
+ if (div > 64)
+ return -EINVAL;
+
+ return clk->parent->rate / div;
+}
+
+static int _clk_usb_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long reg;
+ unsigned long div;
+
+ div = clk->parent->rate / rate;
+
+ if (clk->parent->rate / div != rate)
+ return -EINVAL;
+ if (div > 64)
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCTL) & ~MXC_CCM_CCTL_USB_DIV_MASK;
+ reg |= (div - 1) << MXC_CCM_CCTL_USB_DIV_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCTL);
+
+ return 0;
+}
+
+static void _clk_usb_recalc(struct clk *clk)
+{
+ unsigned long div =
+ __raw_readl(MXC_CCM_CCTL) & MXC_CCM_CCTL_USB_DIV_MASK;
+
+ div >>= MXC_CCM_CCTL_USB_DIV_OFFSET;
+
+ clk->rate = clk->parent->rate / (div + 1);
+}
+
+static int _clk_usb_set_parent(struct clk *clk, struct clk *parent)
+{
+ unsigned long mcr;
+
+ if (parent != &upll_clk && parent != &ahb_clk)
+ return -EINVAL;
+
+ clk->parent = parent;
+ mcr = __raw_readl(MXC_CCM_MCR);
+ if (parent == &ahb_clk)
+ mcr |= (1 << MXC_CCM_MCR_USB_CLK_MUX_OFFSET);
+ else
+ mcr &= ~(1 << MXC_CCM_MCR_USB_CLK_MUX_OFFSET);
+
+ __raw_writel(mcr, MXC_CCM_MCR);
+
+ return 0;
+}
+
+static struct clk usb_clk = {
+ .name = "usb_clk",
+ .parent = &upll_clk,
+ .recalc = _clk_usb_recalc,
+ .set_rate = _clk_usb_set_rate,
+ .round_rate = _clk_usb_round_rate,
+ .set_parent = _clk_usb_set_parent,
+};
+
+/* CLKO */
+
+static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long div;
+
+ div = clk->parent->rate / rate;
+ if (clk->parent->rate % rate)
+ div++;
+
+ if (div > 64)
+ return -EINVAL;
+
+ return clk->parent->rate / div;
+}
+
+static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long reg;
+ unsigned long div;
+
+ div = clk->parent->rate / rate;
+
+ if ((clk->parent->rate / div) != rate)
+ return -EINVAL;
+ if (div > 64)
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_MCR) & ~MXC_CCM_MCR_CLKO_DIV_MASK;
+ reg |= (div - 1) << MXC_CCM_MCR_CLKO_DIV_OFFSET;
+ __raw_writel(reg, MXC_CCM_MCR);
+
+ return 0;
+}
+
+static void _clk_clko_recalc(struct clk *clk)
+{
+ unsigned long div =
+ __raw_readl(MXC_CCM_MCR) & MXC_CCM_MCR_CLKO_DIV_MASK;
+
+ div >>= MXC_CCM_MCR_CLKO_DIV_OFFSET;
+
+ clk->rate = clk->parent->rate / (div + 1);
+}
+
+static struct clk *clko_sources[] = {
+ &osc32k_clk, /* 0x0 */
+ &osc24m_clk, /* 0x1 */
+ &cpu_clk, /* 0x2 */
+ &ahb_clk, /* 0x3 */
+ &ipg_clk, /* 0x4 */
+ NULL, /* 0x5 */
+ NULL, /* 0x6 */
+ NULL, /* 0x7 */
+ NULL, /* 0x8 */
+ NULL, /* 0x9 */
+ &per_clk[0], /* 0xA */
+ &per_clk[2], /* 0xB */
+ &per_clk[13], /* 0xC */
+ &per_clk[14], /* 0xD */
+ &usb_clk, /* 0xE */
+ NULL, /* 0xF */
+};
+
+#define NR_CLKO_SOURCES (sizeof(clko_sources) / sizeof(struct clk *))
+
+static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
+{
+ unsigned long reg =
+ __raw_readl(MXC_CCM_MCR) & ~MXC_CCM_MCR_CLKO_SEL_MASK;
+ struct clk **src;
+ int i;
+
+ for (i = 0, src = clko_sources; i < NR_CLKO_SOURCES; i++, src++)
+ if (*src == parent)
+ break;
+
+ if (i == NR_CLKO_SOURCES)
+ return -EINVAL;
+
+ clk->parent = parent;
+
+ reg |= i << MXC_CCM_MCR_CLKO_SEL_OFFSET;
+
+ __raw_writel(reg, MXC_CCM_MCR);
+
+ return 0;
+}
+
+static struct clk clko_clk = {
+ .name = "clko_clk",
+ .recalc = _clk_clko_recalc,
+ .set_rate = _clk_clko_set_rate,
+ .round_rate = _clk_clko_round_rate,
+ .set_parent = _clk_clko_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_MCR,
+ .enable_shift = MXC_CCM_MCR_CLKO_EN_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk *mxc_clks[] = {
+ &osc24m_clk,
+ &osc32k_clk,
+ &mpll_clk,
+ &upll_clk,
+ &cpu_clk,
+ &ahb_clk,
+ &ipg_clk,
+ &usb_ahb_clk,
+ &per_clk[0],
+ &per_clk[1],
+ &per_clk[2],
+ &per_clk[3],
+ &per_clk[4],
+ &per_clk[5],
+ &per_clk[6],
+ &per_clk[7],
+ &per_clk[8],
+ &per_clk[9],
+ &per_clk[10],
+ &per_clk[11],
+ &per_clk[12],
+ &per_clk[13],
+ &per_clk[14],
+ &per_clk[15],
+ &nfc_clk,
+ &audmux_clk,
+ &ata_clk[0],
+ &ata_clk[1],
+ &can_clk[0],
+ &can_clk[1],
+ &csi_clk[0],
+ &csi_clk[1],
+ &csi_clk[2],
+ &cspi_clk[0],
+ &cspi_clk[1],
+ &cspi_clk[2],
+ &dryice_clk,
+ &ect_clk,
+ &epit1_clk[0],
+ &epit1_clk[1],
+ &epit2_clk[0],
+ &epit2_clk[1],
+ &esai_clk[0],
+ &esai_clk[1],
+ &esai_clk[2],
+ &esdhc1_clk[0],
+ &esdhc1_clk[1],
+ &esdhc1_clk[2],
+ &esdhc2_clk[0],
+ &esdhc2_clk[1],
+ &esdhc2_clk[2],
+ &fec_clk[0],
+ &fec_clk[1],
+ &gpio_clk[0],
+ &gpio_clk[1],
+ &gpio_clk[2],
+ &gpt1_clk[0],
+ &gpt1_clk[1],
+ &gpt2_clk[0],
+ &gpt2_clk[1],
+ &gpt3_clk[0],
+ &gpt3_clk[1],
+ &gpt4_clk[0],
+ &gpt4_clk[1],
+ &i2c_clk[0],
+ &i2c_clk[1],
+ &i2c_clk[2],
+ &iim_clk,
+ &iomuxc_clk,
+ &kpp_clk,
+ &lcdc_clk[0],
+ &lcdc_clk[1],
+ &lcdc_clk[2],
+ &owire_clk[0],
+ &owire_clk[1],
+ &pwm1_clk[0],
+ &pwm1_clk[1],
+ &pwm2_clk[0],
+ &pwm2_clk[1],
+ &pwm3_clk[0],
+ &pwm3_clk[1],
+ &pwm4_clk[0],
+ &pwm4_clk[1],
+ &rng_clk,
+ &scc_clk,
+ &sdma_clk[0],
+ &sdma_clk[1],
+ &sim1_clk[0],
+ &sim1_clk[1],
+ &sim2_clk[0],
+ &sim2_clk[1],
+ &slcdc_clk[0],
+ &slcdc_clk[1],
+ &spba_clk,
+ &ssi1_clk[0],
+ &ssi1_clk[1],
+ &ssi2_clk[0],
+ &ssi2_clk[1],
+ &tchscrn_clk,
+ &uart1_clk[0],
+ &uart1_clk[1],
+ &uart2_clk[0],
+ &uart2_clk[1],
+ &uart3_clk[0],
+ &uart3_clk[1],
+ &uart4_clk[0],
+ &uart4_clk[1],
+ &uart5_clk[0],
+ &uart5_clk[1],
+ &wdog_clk,
+ &usb_clk,
+ &clko_clk,
+};
+
+/*!
+ * Function to get timer clock rate early in boot process before clock tree is
+ * initialized.
+ *
+ * @return Clock rate for timer
+ */
+unsigned long __init clk_early_get_timer_rate(void)
+{
+ upll_clk.recalc(&upll_clk);
+ per_clk[5].recalc(&per_clk[5]);
+ per_clk[5].enable(&per_clk[5]);
+
+ return per_clk[5].rate;
+}
+
+extern void propagate_rate(struct clk *tclk);
+
+int __init mxc_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2)
+{
+ int i;
+ struct clk **clkp;
+
+ for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
+ clk_register(*clkp);
+
+ /* Turn off all possible clocks */
+ __raw_writel((1 << MXC_CCM_CGCR0_HCLK_EMI_OFFSET), MXC_CCM_CGCR0);
+
+ __raw_writel((1 << MXC_CCM_CGCR1_GPT1_OFFSET) |
+ (1 << MXC_CCM_CGCR1_IIM_OFFSET), MXC_CCM_CGCR1);
+ __raw_writel(1 << MXC_CCM_CGCR2_SCC_OFFSET, MXC_CCM_CGCR2);
+
+ /* Init all perclk sources to ahb clock*/
+ for (i = 0; i < (sizeof(per_clk) / sizeof(struct clk)); i++)
+ per_clk[i].set_parent(&per_clk[i], &ahb_clk);
+
+ /* This will propagate to all children and init all the clock rates */
+ propagate_rate(&osc24m_clk);
+ propagate_rate(&osc32k_clk);
+
+ /* GPT clock must be derived from AHB clock */
+ clk_set_rate(&per_clk[5], ahb_clk.rate / 10);
+
+ /* LCDC clock must be derived from UPLL clock */
+ clk_set_parent(&per_clk[7], &upll_clk);
+ clk_set_rate(&per_clk[7], upll_clk.rate);
+
+ /* the NFC clock must be derived from AHB clock */
+ clk_set_parent(&per_clk[8], &ahb_clk);
+ clk_set_rate(&per_clk[8], ahb_clk.rate / 6);
+
+ /* sim clock */
+ clk_set_rate(&per_clk[11], ahb_clk.rate / 2);
+
+ /* the csi clock must be derived from UPLL clock */
+ clk_set_parent(&per_clk[0], &upll_clk);
+ clk_set_rate(&per_clk[0], upll_clk.rate / 5);
+
+ pr_info("Clock input source is %ld\n", osc24m_clk.rate);
+
+ clk_enable(&emi_clk);
+ clk_enable(&gpio_clk[0]);
+ clk_enable(&gpio_clk[1]);
+ clk_enable(&gpio_clk[2]);
+ clk_enable(&iim_clk);
+ clk_enable(&gpt1_clk[0]);
+ clk_enable(&iomuxc_clk);
+ clk_enable(&scc_clk);
+
+ return 0;
+}