i.MX3: introduce clock API
Sascha Hauer [Sat, 5 Jul 2008 08:02:48 +0000 (10:02 +0200)]
This patch introduces the clock API for for arch-mxc

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

arch/arm/mach-mx3/Makefile
arch/arm/mach-mx3/clock.c [new file with mode: 0644]
arch/arm/mach-mx3/crm_regs.h [new file with mode: 0644]
include/asm-arm/arch-mxc/common.h

index cbec997..febb37f 100644 (file)
@@ -4,5 +4,5 @@
 
 # Object file lists.
 
-obj-y                  := mm.o time.o
+obj-y                  := mm.o time.o clock.o
 obj-$(CONFIG_MACH_MX31ADS)     += mx31ads.o
diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c
new file mode 100644 (file)
index 0000000..2f36359
--- /dev/null
@@ -0,0 +1,1147 @@
+/*
+ * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ *
+ * 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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <asm/arch/clock.h>
+#include <asm/div64.h>
+
+#include "crm_regs.h"
+
+#define PRE_DIV_MIN_FREQ    10000000 /* Minimum Frequency after Predivider */
+
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
+{
+       u32 min_pre, temp_pre, old_err, err;
+
+       if (div >= 512) {
+               *pre = 8;
+               *post = 64;
+       } else if (div >= 64) {
+               min_pre = (div - 1) / 64 + 1;
+               old_err = 8;
+               for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
+                       err = div % temp_pre;
+                       if (err == 0) {
+                               *pre = temp_pre;
+                               break;
+                       }
+                       err = temp_pre - err;
+                       if (err < old_err) {
+                               old_err = err;
+                               *pre = temp_pre;
+                       }
+               }
+               *post = (div + *pre - 1) / *pre;
+       } else if (div <= 8) {
+               *pre = div;
+               *post = 1;
+       } else {
+               *pre = 1;
+               *post = div;
+       }
+}
+
+static struct clk mcu_pll_clk;
+static struct clk mcu_main_clk;
+static struct clk usb_pll_clk;
+static struct clk serial_pll_clk;
+static struct clk ipg_clk;
+static struct clk ckih_clk;
+static struct clk ahb_clk;
+
+static int _clk_enable(struct clk *clk)
+{
+       u32 reg;
+
+       reg = __raw_readl(clk->enable_reg);
+       reg |= 3 << clk->enable_shift;
+       __raw_writel(reg, clk->enable_reg);
+
+       return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+       u32 reg;
+
+       reg = __raw_readl(clk->enable_reg);
+       reg &= ~(3 << clk->enable_shift);
+       __raw_writel(reg, clk->enable_reg);
+}
+
+static void _clk_emi_disable(struct clk *clk)
+{
+       u32 reg;
+
+       reg = __raw_readl(clk->enable_reg);
+       reg &= ~(3 << clk->enable_shift);
+       reg |= (1 << clk->enable_shift);
+       __raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg;
+       signed long pd = 1;     /* Pre-divider */
+       signed long mfi;        /* Multiplication Factor (Integer part) */
+       signed long mfn;        /* Multiplication Factor (Integer part) */
+       signed long mfd;        /* Multiplication Factor (Denominator Part) */
+       signed long tmp;
+       u32 ref_freq = clk_get_rate(clk->parent);
+
+       while (((ref_freq / pd) * 10) > rate)
+               pd++;
+
+       if ((ref_freq / pd) < PRE_DIV_MIN_FREQ)
+               return -EINVAL;
+
+       /* the ref_freq/2 in the following is to round up */
+       mfi = (((rate / 2) * pd) + (ref_freq / 2)) / ref_freq;
+       if (mfi < 5 || mfi > 15)
+               return -EINVAL;
+
+       /* pick a mfd value that will work
+        * then solve for mfn */
+       mfd = ref_freq / 50000;
+
+       /*
+        *          pll_freq * pd * mfd
+        *   mfn = --------------------  -  (mfi * mfd)
+        *           2 * ref_freq
+        */
+       /* the tmp/2 is for rounding */
+       tmp = ref_freq / 10000;
+       mfn =
+           ((((((rate / 2) + (tmp / 2)) / tmp) * pd) * mfd) / 10000) -
+           (mfi * mfd);
+
+       mfn = mfn & 0x3ff;
+       pd--;
+       mfd--;
+
+       /* Change the Pll value */
+       reg = (mfi << MXC_CCM_PCTL_MFI_OFFSET) |
+           (mfn << MXC_CCM_PCTL_MFN_OFFSET) |
+           (mfd << MXC_CCM_PCTL_MFD_OFFSET) | (pd << MXC_CCM_PCTL_PD_OFFSET);
+
+       if (clk == &mcu_pll_clk)
+               __raw_writel(reg, MXC_CCM_MPCTL);
+       else if (clk == &usb_pll_clk)
+               __raw_writel(reg, MXC_CCM_UPCTL);
+       else if (clk == &serial_pll_clk)
+               __raw_writel(reg, MXC_CCM_SRPCTL);
+
+       return 0;
+}
+
+static unsigned long _clk_pll_get_rate(struct clk *clk)
+{
+       long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
+       unsigned long reg, ccmr;
+       s64 temp;
+       unsigned int prcs;
+
+       ccmr = __raw_readl(MXC_CCM_CCMR);
+       prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
+       if (prcs == 0x1)
+               ref_clk = CKIL_CLK_FREQ * 1024;
+       else
+               ref_clk = clk_get_rate(&ckih_clk);
+
+       if (clk == &mcu_pll_clk) {
+               if ((ccmr & MXC_CCM_CCMR_MPE) == 0)
+                       return ref_clk;
+               if ((ccmr & MXC_CCM_CCMR_MDS) != 0)
+                       return ref_clk;
+               reg = __raw_readl(MXC_CCM_MPCTL);
+       } else if (clk == &usb_pll_clk)
+               reg = __raw_readl(MXC_CCM_UPCTL);
+       else if (clk == &serial_pll_clk)
+               reg = __raw_readl(MXC_CCM_SRPCTL);
+       else {
+               BUG();
+               return 0;
+       }
+
+       pdf = (reg & MXC_CCM_PCTL_PD_MASK) >> MXC_CCM_PCTL_PD_OFFSET;
+       mfd = (reg & MXC_CCM_PCTL_MFD_MASK) >> MXC_CCM_PCTL_MFD_OFFSET;
+       mfi = (reg & MXC_CCM_PCTL_MFI_MASK) >> MXC_CCM_PCTL_MFI_OFFSET;
+       mfi = (mfi <= 5) ? 5 : mfi;
+       mfn = mfn_abs = reg & MXC_CCM_PCTL_MFN_MASK;
+
+       if (mfn >= 0x200) {
+               mfn |= 0xFFFFFE00;
+               mfn_abs = -mfn;
+       }
+
+       ref_clk *= 2;
+       ref_clk /= pdf + 1;
+
+       temp = (u64) ref_clk * mfn_abs;
+       do_div(temp, mfd + 1);
+       if (mfn < 0)
+               temp = -temp;
+       temp = (ref_clk * mfi) + temp;
+
+       return temp;
+}
+
+static int _clk_usb_pll_enable(struct clk *clk)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CCMR);
+       reg |= MXC_CCM_CCMR_UPE;
+       __raw_writel(reg, MXC_CCM_CCMR);
+
+       /* No lock bit on MX31, so using max time from spec */
+       udelay(80);
+
+       return 0;
+}
+
+static void _clk_usb_pll_disable(struct clk *clk)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CCMR);
+       reg &= ~MXC_CCM_CCMR_UPE;
+       __raw_writel(reg, MXC_CCM_CCMR);
+}
+
+static int _clk_serial_pll_enable(struct clk *clk)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CCMR);
+       reg |= MXC_CCM_CCMR_SPE;
+       __raw_writel(reg, MXC_CCM_CCMR);
+
+       /* No lock bit on MX31, so using max time from spec */
+       udelay(80);
+
+       return 0;
+}
+
+static void _clk_serial_pll_disable(struct clk *clk)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CCMR);
+       reg &= ~MXC_CCM_CCMR_SPE;
+       __raw_writel(reg, MXC_CCM_CCMR);
+}
+
+#define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off)
+#define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
+#define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
+
+static unsigned long _clk_mcu_main_get_rate(struct clk *clk)
+{
+       u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0);
+
+       if ((pmcr0 & MXC_CCM_PMCR0_DFSUP1) == MXC_CCM_PMCR0_DFSUP1_SPLL)
+               return clk_get_rate(&serial_pll_clk);
+       else
+               return clk_get_rate(&mcu_pll_clk);
+}
+
+static unsigned long _clk_hclk_get_rate(struct clk *clk)
+{
+       unsigned long max_pdf;
+
+       max_pdf = PDR0(MXC_CCM_PDR0_MAX_PODF_MASK,
+                      MXC_CCM_PDR0_MAX_PODF_OFFSET);
+       return clk_get_rate(clk->parent) / (max_pdf + 1);
+}
+
+static unsigned long _clk_ipg_get_rate(struct clk *clk)
+{
+       unsigned long ipg_pdf;
+
+       ipg_pdf = PDR0(MXC_CCM_PDR0_IPG_PODF_MASK,
+                      MXC_CCM_PDR0_IPG_PODF_OFFSET);
+       return clk_get_rate(clk->parent) / (ipg_pdf + 1);
+}
+
+static unsigned long _clk_nfc_get_rate(struct clk *clk)
+{
+       unsigned long nfc_pdf;
+
+       nfc_pdf = PDR0(MXC_CCM_PDR0_NFC_PODF_MASK,
+                      MXC_CCM_PDR0_NFC_PODF_OFFSET);
+       return clk_get_rate(clk->parent) / (nfc_pdf + 1);
+}
+
+static unsigned long _clk_hsp_get_rate(struct clk *clk)
+{
+       unsigned long hsp_pdf;
+
+       hsp_pdf = PDR0(MXC_CCM_PDR0_HSP_PODF_MASK,
+                      MXC_CCM_PDR0_HSP_PODF_OFFSET);
+       return clk_get_rate(clk->parent) / (hsp_pdf + 1);
+}
+
+static unsigned long _clk_usb_get_rate(struct clk *clk)
+{
+       unsigned long usb_pdf, usb_prepdf;
+
+       usb_pdf = PDR1(MXC_CCM_PDR1_USB_PODF_MASK,
+                      MXC_CCM_PDR1_USB_PODF_OFFSET);
+       usb_prepdf = PDR1(MXC_CCM_PDR1_USB_PRDF_MASK,
+                         MXC_CCM_PDR1_USB_PRDF_OFFSET);
+       return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1);
+}
+
+static unsigned long _clk_csi_get_rate(struct clk *clk)
+{
+       u32 reg, pre, post;
+
+       reg = __raw_readl(MXC_CCM_PDR0);
+       pre = (reg & MXC_CCM_PDR0_CSI_PRDF_MASK) >>
+           MXC_CCM_PDR0_CSI_PRDF_OFFSET;
+       pre++;
+       post = (reg & MXC_CCM_PDR0_CSI_PODF_MASK) >>
+           MXC_CCM_PDR0_CSI_PODF_OFFSET;
+       post++;
+       return clk_get_rate(clk->parent) / (pre * post);
+}
+
+static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate)
+{
+       u32 pre, post, parent = clk_get_rate(clk->parent);
+       u32 div = parent / rate;
+
+       if (parent % rate)
+               div++;
+
+       __calc_pre_post_dividers(div, &pre, &post);
+
+       return parent / (pre * post);
+}
+
+static int _clk_csi_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
+
+       div = parent / rate;
+
+       if ((parent / div) != rate)
+               return -EINVAL;
+
+       __calc_pre_post_dividers(div, &pre, &post);
+
+       /* Set CSI clock divider */
+       reg = __raw_readl(MXC_CCM_PDR0) &
+           ~(MXC_CCM_PDR0_CSI_PODF_MASK | MXC_CCM_PDR0_CSI_PRDF_MASK);
+       reg |= (post - 1) << MXC_CCM_PDR0_CSI_PODF_OFFSET;
+       reg |= (pre - 1) << MXC_CCM_PDR0_CSI_PRDF_OFFSET;
+       __raw_writel(reg, MXC_CCM_PDR0);
+
+       return 0;
+}
+
+static unsigned long _clk_per_get_rate(struct clk *clk)
+{
+       unsigned long per_pdf;
+
+       per_pdf = PDR0(MXC_CCM_PDR0_PER_PODF_MASK,
+                      MXC_CCM_PDR0_PER_PODF_OFFSET);
+       return clk_get_rate(clk->parent) / (per_pdf + 1);
+}
+
+static unsigned long _clk_ssi1_get_rate(struct clk *clk)
+{
+       unsigned long ssi1_pdf, ssi1_prepdf;
+
+       ssi1_pdf = PDR1(MXC_CCM_PDR1_SSI1_PODF_MASK,
+                       MXC_CCM_PDR1_SSI1_PODF_OFFSET);
+       ssi1_prepdf = PDR1(MXC_CCM_PDR1_SSI1_PRE_PODF_MASK,
+                          MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET);
+       return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1);
+}
+
+static unsigned long _clk_ssi2_get_rate(struct clk *clk)
+{
+       unsigned long ssi2_pdf, ssi2_prepdf;
+
+       ssi2_pdf = PDR1(MXC_CCM_PDR1_SSI2_PODF_MASK,
+                       MXC_CCM_PDR1_SSI2_PODF_OFFSET);
+       ssi2_prepdf = PDR1(MXC_CCM_PDR1_SSI2_PRE_PODF_MASK,
+                          MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET);
+       return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1);
+}
+
+static unsigned long _clk_firi_get_rate(struct clk *clk)
+{
+       unsigned long firi_pdf, firi_prepdf;
+
+       firi_pdf = PDR1(MXC_CCM_PDR1_FIRI_PODF_MASK,
+                       MXC_CCM_PDR1_FIRI_PODF_OFFSET);
+       firi_prepdf = PDR1(MXC_CCM_PDR1_FIRI_PRE_PODF_MASK,
+                          MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET);
+       return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1);
+}
+
+static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate)
+{
+       u32 pre, post;
+       u32 parent = clk_get_rate(clk->parent);
+       u32 div = parent / rate;
+
+       if (parent % rate)
+               div++;
+
+       __calc_pre_post_dividers(div, &pre, &post);
+
+       return parent / (pre * post);
+
+}
+
+static int _clk_firi_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
+
+       div = parent / rate;
+
+       if ((parent / div) != rate)
+               return -EINVAL;
+
+       __calc_pre_post_dividers(div, &pre, &post);
+
+       /* Set FIRI clock divider */
+       reg = __raw_readl(MXC_CCM_PDR1) &
+           ~(MXC_CCM_PDR1_FIRI_PODF_MASK | MXC_CCM_PDR1_FIRI_PRE_PODF_MASK);
+       reg |= (pre - 1) << MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET;
+       reg |= (post - 1) << MXC_CCM_PDR1_FIRI_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_PDR1);
+
+       return 0;
+}
+
+static unsigned long _clk_mbx_get_rate(struct clk *clk)
+{
+       return clk_get_rate(clk->parent) / 2;
+}
+
+static unsigned long _clk_mstick1_get_rate(struct clk *clk)
+{
+       unsigned long msti_pdf;
+
+       msti_pdf = PDR2(MXC_CCM_PDR2_MST1_PDF_MASK,
+                       MXC_CCM_PDR2_MST1_PDF_OFFSET);
+       return clk_get_rate(clk->parent) / (msti_pdf + 1);
+}
+
+static unsigned long _clk_mstick2_get_rate(struct clk *clk)
+{
+       unsigned long msti_pdf;
+
+       msti_pdf = PDR2(MXC_CCM_PDR2_MST2_PDF_MASK,
+                       MXC_CCM_PDR2_MST2_PDF_OFFSET);
+       return clk_get_rate(clk->parent) / (msti_pdf + 1);
+}
+
+static unsigned long ckih_rate;
+
+static unsigned long clk_ckih_get_rate(struct clk *clk)
+{
+       return ckih_rate;
+}
+
+static struct clk ckih_clk = {
+       .name = "ckih",
+       .get_rate = clk_ckih_get_rate,
+};
+
+static unsigned long clk_ckil_get_rate(struct clk *clk)
+{
+       return CKIL_CLK_FREQ;
+}
+
+static struct clk ckil_clk = {
+       .name = "ckil",
+       .get_rate = clk_ckil_get_rate,
+};
+
+static struct clk mcu_pll_clk = {
+       .name = "mcu_pll",
+       .parent = &ckih_clk,
+       .set_rate = _clk_pll_set_rate,
+       .get_rate = _clk_pll_get_rate,
+};
+
+static struct clk mcu_main_clk = {
+       .name = "mcu_main_clk",
+       .parent = &mcu_pll_clk,
+       .get_rate = _clk_mcu_main_get_rate,
+};
+
+static struct clk serial_pll_clk = {
+       .name = "serial_pll",
+       .parent = &ckih_clk,
+       .set_rate = _clk_pll_set_rate,
+       .get_rate = _clk_pll_get_rate,
+       .enable = _clk_serial_pll_enable,
+       .disable = _clk_serial_pll_disable,
+};
+
+static struct clk usb_pll_clk = {
+       .name = "usb_pll",
+       .parent = &ckih_clk,
+       .set_rate = _clk_pll_set_rate,
+       .get_rate = _clk_pll_get_rate,
+       .enable = _clk_usb_pll_enable,
+       .disable = _clk_usb_pll_disable,
+};
+
+static struct clk ahb_clk = {
+       .name = "ahb_clk",
+       .parent = &mcu_main_clk,
+       .get_rate = _clk_hclk_get_rate,
+};
+
+static struct clk per_clk = {
+       .name = "per_clk",
+       .parent = &usb_pll_clk,
+       .get_rate = _clk_per_get_rate,
+};
+
+static struct clk perclk_clk = {
+       .name = "perclk_clk",
+       .parent = &ipg_clk,
+};
+
+static struct clk cspi_clk[] = {
+       {
+        .name = "cspi_clk",
+        .id = 0,
+        .parent = &ipg_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR2,
+        .enable_shift = MXC_CCM_CGR2_CSPI1_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "cspi_clk",
+        .id = 1,
+        .parent = &ipg_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR2,
+        .enable_shift = MXC_CCM_CGR2_CSPI2_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "cspi_clk",
+        .id = 2,
+        .parent = &ipg_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_CSPI3_OFFSET,
+        .disable = _clk_disable,},
+};
+
+static struct clk ipg_clk = {
+       .name = "ipg_clk",
+       .parent = &ahb_clk,
+       .get_rate = _clk_ipg_get_rate,
+};
+
+static struct clk emi_clk = {
+       .name = "emi_clk",
+       .parent = &ahb_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR2,
+       .enable_shift = MXC_CCM_CGR2_EMI_OFFSET,
+       .disable = _clk_emi_disable,
+};
+
+static struct clk gpt_clk = {
+       .name = "gpt_clk",
+       .parent = &perclk_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR0,
+       .enable_shift = MXC_CCM_CGR0_GPT_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk pwm_clk = {
+       .name = "pwm_clk",
+       .parent = &perclk_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR0,
+       .enable_shift = MXC_CCM_CGR1_PWM_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk epit_clk[] = {
+       {
+        .name = "epit_clk",
+        .id = 0,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_EPIT1_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "epit_clk",
+        .id = 1,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_EPIT2_OFFSET,
+        .disable = _clk_disable,},
+};
+
+static struct clk nfc_clk = {
+       .name = "nfc_clk",
+       .parent = &ahb_clk,
+       .get_rate = _clk_nfc_get_rate,
+};
+
+static struct clk scc_clk = {
+       .name = "scc_clk",
+       .parent = &ipg_clk,
+};
+
+static struct clk ipu_clk = {
+       .name = "ipu_clk",
+       .parent = &mcu_main_clk,
+       .get_rate = _clk_hsp_get_rate,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR1,
+       .enable_shift = MXC_CCM_CGR1_IPU_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk kpp_clk = {
+       .name = "kpp_clk",
+       .parent = &ipg_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR1,
+       .enable_shift = MXC_CCM_CGR1_KPP_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk wdog_clk = {
+       .name = "wdog_clk",
+       .parent = &ipg_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR1,
+       .enable_shift = MXC_CCM_CGR1_WDOG_OFFSET,
+       .disable = _clk_disable,
+};
+static struct clk rtc_clk = {
+       .name = "rtc_clk",
+       .parent = &ipg_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR1,
+       .enable_shift = MXC_CCM_CGR1_RTC_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk usb_clk[] = {
+       {
+        .name = "usb_clk",
+        .parent = &usb_pll_clk,
+        .get_rate = _clk_usb_get_rate,},
+       {
+        .name = "usb_ahb_clk",
+        .parent = &ahb_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR1,
+        .enable_shift = MXC_CCM_CGR1_USBOTG_OFFSET,
+        .disable = _clk_disable,},
+};
+
+static struct clk csi_clk = {
+       .name = "csi_clk",
+       .parent = &serial_pll_clk,
+       .get_rate = _clk_csi_get_rate,
+       .round_rate = _clk_csi_round_rate,
+       .set_rate = _clk_csi_set_rate,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR1,
+       .enable_shift = MXC_CCM_CGR1_CSI_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk uart_clk[] = {
+       {
+        .name = "uart_clk",
+        .id = 0,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_UART1_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "uart_clk",
+        .id = 1,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_UART2_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "uart_clk",
+        .id = 2,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR1,
+        .enable_shift = MXC_CCM_CGR1_UART3_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "uart_clk",
+        .id = 3,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR1,
+        .enable_shift = MXC_CCM_CGR1_UART4_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "uart_clk",
+        .id = 4,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR1,
+        .enable_shift = MXC_CCM_CGR1_UART5_OFFSET,
+        .disable = _clk_disable,},
+};
+
+static struct clk i2c_clk[] = {
+       {
+        .name = "i2c_clk",
+        .id = 0,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_I2C1_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "i2c_clk",
+        .id = 1,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_I2C2_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "i2c_clk",
+        .id = 2,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_I2C3_OFFSET,
+        .disable = _clk_disable,},
+};
+
+static struct clk owire_clk = {
+       .name = "owire_clk",
+       .parent = &perclk_clk,
+       .enable_reg = MXC_CCM_CGR1,
+       .enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+};
+
+static struct clk sdhc_clk[] = {
+       {
+        .name = "sdhc_clk",
+        .id = 0,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_SD_MMC1_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "sdhc_clk",
+        .id = 1,
+        .parent = &perclk_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_SD_MMC2_OFFSET,
+        .disable = _clk_disable,},
+};
+
+static struct clk ssi_clk[] = {
+       {
+        .name = "ssi_clk",
+        .parent = &serial_pll_clk,
+        .get_rate = _clk_ssi1_get_rate,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_SSI1_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "ssi_clk",
+        .id = 1,
+        .parent = &serial_pll_clk,
+        .get_rate = _clk_ssi2_get_rate,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR2,
+        .enable_shift = MXC_CCM_CGR2_SSI2_OFFSET,
+        .disable = _clk_disable,},
+};
+
+static struct clk firi_clk = {
+       .name = "firi_clk",
+       .parent = &usb_pll_clk,
+       .round_rate = _clk_firi_round_rate,
+       .set_rate = _clk_firi_set_rate,
+       .get_rate = _clk_firi_get_rate,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR2,
+       .enable_shift = MXC_CCM_CGR2_FIRI_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk ata_clk = {
+       .name = "ata_clk",
+       .parent = &ipg_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR0,
+       .enable_shift = MXC_CCM_CGR0_ATA_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk mbx_clk = {
+       .name = "mbx_clk",
+       .parent = &ahb_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR2,
+       .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
+       .get_rate = _clk_mbx_get_rate,
+};
+
+static struct clk vpu_clk = {
+       .name = "vpu_clk",
+       .parent = &ahb_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR2,
+       .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
+       .get_rate = _clk_mbx_get_rate,
+};
+
+static struct clk rtic_clk = {
+       .name = "rtic_clk",
+       .parent = &ahb_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR2,
+       .enable_shift = MXC_CCM_CGR2_RTIC_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk rng_clk = {
+       .name = "rng_clk",
+       .parent = &ipg_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR0,
+       .enable_shift = MXC_CCM_CGR0_RNG_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk sdma_clk[] = {
+       {
+        .name = "sdma_ahb_clk",
+        .parent = &ahb_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR0,
+        .enable_shift = MXC_CCM_CGR0_SDMA_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "sdma_ipg_clk",
+        .parent = &ipg_clk,}
+};
+
+static struct clk mpeg4_clk = {
+       .name = "mpeg4_clk",
+       .parent = &ahb_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR1,
+       .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk vl2cc_clk = {
+       .name = "vl2cc_clk",
+       .parent = &ahb_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR1,
+       .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
+       .disable = _clk_disable,
+};
+
+static struct clk mstick_clk[] = {
+       {
+        .name = "mstick_clk",
+        .id = 0,
+        .parent = &usb_pll_clk,
+        .get_rate = _clk_mstick1_get_rate,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR1,
+        .enable_shift = MXC_CCM_CGR1_MEMSTICK1_OFFSET,
+        .disable = _clk_disable,},
+       {
+        .name = "mstick_clk",
+        .id = 1,
+        .parent = &usb_pll_clk,
+        .get_rate = _clk_mstick2_get_rate,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CGR1,
+        .enable_shift = MXC_CCM_CGR1_MEMSTICK2_OFFSET,
+        .disable = _clk_disable,},
+};
+
+static struct clk iim_clk = {
+       .name = "iim_clk",
+       .parent = &ipg_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CGR0,
+       .enable_shift = MXC_CCM_CGR0_IIM_OFFSET,
+       .disable = _clk_disable,
+};
+
+static unsigned long _clk_cko1_round_rate(struct clk *clk, unsigned long rate)
+{
+       u32 div, parent = clk_get_rate(clk->parent);
+
+       div = parent / rate;
+       if (parent % rate)
+               div++;
+
+       if (div > 8)
+               div = 16;
+       else if (div > 4)
+               div = 8;
+       else if (div > 2)
+               div = 4;
+
+       return parent / div;
+}
+
+static int _clk_cko1_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, parent = clk_get_rate(clk->parent);
+
+       div = parent / rate;
+
+       if (div == 16)
+               div = 4;
+       else if (div == 8)
+               div = 3;
+       else if (div == 4)
+               div = 2;
+       else if (div == 2)
+               div = 1;
+       else if (div == 1)
+               div = 0;
+       else
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOUTDIV_MASK;
+       reg |= div << MXC_CCM_COSR_CLKOUTDIV_OFFSET;
+       __raw_writel(reg, MXC_CCM_COSR);
+
+       return 0;
+}
+
+static unsigned long _clk_cko1_get_rate(struct clk *clk)
+{
+       u32 div;
+
+       div = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_CLKOUTDIV_MASK >>
+           MXC_CCM_COSR_CLKOUTDIV_OFFSET;
+
+       return clk_get_rate(clk->parent) / (1 << div);
+}
+
+static int _clk_cko1_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOSEL_MASK;
+
+       if (parent == &mcu_main_clk)
+               reg |= 0 << MXC_CCM_COSR_CLKOSEL_OFFSET;
+       else if (parent == &ipg_clk)
+               reg |= 1 << MXC_CCM_COSR_CLKOSEL_OFFSET;
+       else if (parent == &usb_pll_clk)
+               reg |= 2 << MXC_CCM_COSR_CLKOSEL_OFFSET;
+       else if (parent == mcu_main_clk.parent)
+               reg |= 3 << MXC_CCM_COSR_CLKOSEL_OFFSET;
+       else if (parent == &ahb_clk)
+               reg |= 5 << MXC_CCM_COSR_CLKOSEL_OFFSET;
+       else if (parent == &serial_pll_clk)
+               reg |= 7 << MXC_CCM_COSR_CLKOSEL_OFFSET;
+       else if (parent == &ckih_clk)
+               reg |= 8 << MXC_CCM_COSR_CLKOSEL_OFFSET;
+       else if (parent == &emi_clk)
+               reg |= 9 << MXC_CCM_COSR_CLKOSEL_OFFSET;
+       else if (parent == &ipu_clk)
+               reg |= 0xA << MXC_CCM_COSR_CLKOSEL_OFFSET;
+       else if (parent == &nfc_clk)
+               reg |= 0xB << MXC_CCM_COSR_CLKOSEL_OFFSET;
+       else if (parent == &uart_clk[0])
+               reg |= 0xC << MXC_CCM_COSR_CLKOSEL_OFFSET;
+       else
+               return -EINVAL;
+
+       __raw_writel(reg, MXC_CCM_COSR);
+
+       return 0;
+}
+
+static int _clk_cko1_enable(struct clk *clk)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_COSR) | MXC_CCM_COSR_CLKOEN;
+       __raw_writel(reg, MXC_CCM_COSR);
+
+       return 0;
+}
+
+static void _clk_cko1_disable(struct clk *clk)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOEN;
+       __raw_writel(reg, MXC_CCM_COSR);
+}
+
+static struct clk cko1_clk = {
+       .name = "cko1_clk",
+       .get_rate = _clk_cko1_get_rate,
+       .set_rate = _clk_cko1_set_rate,
+       .round_rate = _clk_cko1_round_rate,
+       .set_parent = _clk_cko1_set_parent,
+       .enable = _clk_cko1_enable,
+       .disable = _clk_cko1_disable,
+};
+
+static struct clk *mxc_clks[] = {
+       &ckih_clk,
+       &ckil_clk,
+       &mcu_pll_clk,
+       &usb_pll_clk,
+       &serial_pll_clk,
+       &mcu_main_clk,
+       &ahb_clk,
+       &per_clk,
+       &perclk_clk,
+       &cko1_clk,
+       &emi_clk,
+       &cspi_clk[0],
+       &cspi_clk[1],
+       &cspi_clk[2],
+       &ipg_clk,
+       &gpt_clk,
+       &pwm_clk,
+       &wdog_clk,
+       &rtc_clk,
+       &epit_clk[0],
+       &epit_clk[1],
+       &nfc_clk,
+       &ipu_clk,
+       &kpp_clk,
+       &usb_clk[0],
+       &usb_clk[1],
+       &csi_clk,
+       &uart_clk[0],
+       &uart_clk[1],
+       &uart_clk[2],
+       &uart_clk[3],
+       &uart_clk[4],
+       &i2c_clk[0],
+       &i2c_clk[1],
+       &i2c_clk[2],
+       &owire_clk,
+       &sdhc_clk[0],
+       &sdhc_clk[1],
+       &ssi_clk[0],
+       &ssi_clk[1],
+       &firi_clk,
+       &ata_clk,
+       &rtic_clk,
+       &rng_clk,
+       &sdma_clk[0],
+       &sdma_clk[1],
+       &mstick_clk[0],
+       &mstick_clk[1],
+       &scc_clk,
+       &iim_clk,
+};
+
+int __init mxc_clocks_init(unsigned long fref)
+{
+       u32 reg;
+       struct clk **clkp;
+
+       ckih_rate = fref;
+
+       for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
+               clk_register(*clkp);
+
+       if (cpu_is_mx31()) {
+               clk_register(&mpeg4_clk);
+               clk_register(&mbx_clk);
+       } else {
+               clk_register(&vpu_clk);
+               clk_register(&vl2cc_clk);
+       }
+
+       /* Turn off all possible clocks */
+       __raw_writel(MXC_CCM_CGR0_GPT_MASK, MXC_CCM_CGR0);
+       __raw_writel(0, MXC_CCM_CGR1);
+
+       __raw_writel(MXC_CCM_CGR2_EMI_MASK |
+                    MXC_CCM_CGR2_IPMUX1_MASK |
+                    MXC_CCM_CGR2_IPMUX2_MASK |
+                    MXC_CCM_CGR2_MXCCLKENSEL_MASK |    /* for MX32 */
+                    MXC_CCM_CGR2_CHIKCAMPEN_MASK |     /* for MX32 */
+                    MXC_CCM_CGR2_OVRVPUBUSY_MASK |     /* for MX32 */
+                    1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
+                                          MX32, but still required to be set */
+                    MXC_CCM_CGR2);
+
+       clk_disable(&cko1_clk);
+       clk_disable(&usb_pll_clk);
+
+       pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
+
+       clk_enable(&gpt_clk);
+       clk_enable(&emi_clk);
+       clk_enable(&iim_clk);
+
+       clk_enable(&serial_pll_clk);
+
+       if (mx31_revision() >= CHIP_REV_2_0) {
+               reg = __raw_readl(MXC_CCM_PMCR1);
+               /* No PLL restart on DVFS switch; enable auto EMI handshake */
+               reg |= MXC_CCM_PMCR1_PLLRDIS | MXC_CCM_PMCR1_EMIRQ_EN;
+               __raw_writel(reg, MXC_CCM_PMCR1);
+       }
+
+       return 0;
+}
+
diff --git a/arch/arm/mach-mx3/crm_regs.h b/arch/arm/mach-mx3/crm_regs.h
new file mode 100644 (file)
index 0000000..4a0e0ed
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ *
+ * 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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __ARCH_ARM_MACH_MX3_CRM_REGS_H__
+#define __ARCH_ARM_MACH_MX3_CRM_REGS_H__
+
+#define CKIH_CLK_FREQ           26000000
+#define CKIH_CLK_FREQ_27MHZ     27000000
+#define CKIL_CLK_FREQ           32768
+
+#define MXC_CCM_BASE           IO_ADDRESS(CCM_BASE_ADDR)
+
+/* Register addresses */
+#define MXC_CCM_CCMR           (MXC_CCM_BASE + 0x00)
+#define MXC_CCM_PDR0           (MXC_CCM_BASE + 0x04)
+#define MXC_CCM_PDR1           (MXC_CCM_BASE + 0x08)
+#define MXC_CCM_RCSR           (MXC_CCM_BASE + 0x0C)
+#define MXC_CCM_MPCTL          (MXC_CCM_BASE + 0x10)
+#define MXC_CCM_UPCTL          (MXC_CCM_BASE + 0x14)
+#define MXC_CCM_SRPCTL         (MXC_CCM_BASE + 0x18)
+#define MXC_CCM_COSR           (MXC_CCM_BASE + 0x1C)
+#define MXC_CCM_CGR0           (MXC_CCM_BASE + 0x20)
+#define MXC_CCM_CGR1           (MXC_CCM_BASE + 0x24)
+#define MXC_CCM_CGR2           (MXC_CCM_BASE + 0x28)
+#define MXC_CCM_WIMR           (MXC_CCM_BASE + 0x2C)
+#define MXC_CCM_LDC            (MXC_CCM_BASE + 0x30)
+#define MXC_CCM_DCVR0          (MXC_CCM_BASE + 0x34)
+#define MXC_CCM_DCVR1          (MXC_CCM_BASE + 0x38)
+#define MXC_CCM_DCVR2          (MXC_CCM_BASE + 0x3C)
+#define MXC_CCM_DCVR3          (MXC_CCM_BASE + 0x40)
+#define MXC_CCM_LTR0           (MXC_CCM_BASE + 0x44)
+#define MXC_CCM_LTR1           (MXC_CCM_BASE + 0x48)
+#define MXC_CCM_LTR2           (MXC_CCM_BASE + 0x4C)
+#define MXC_CCM_LTR3           (MXC_CCM_BASE + 0x50)
+#define MXC_CCM_LTBR0          (MXC_CCM_BASE + 0x54)
+#define MXC_CCM_LTBR1          (MXC_CCM_BASE + 0x58)
+#define MXC_CCM_PMCR0          (MXC_CCM_BASE + 0x5C)
+#define MXC_CCM_PMCR1          (MXC_CCM_BASE + 0x60)
+#define MXC_CCM_PDR2           (MXC_CCM_BASE + 0x64)
+
+/* Register bit definitions */
+#define MXC_CCM_CCMR_WBEN                       (1 << 27)
+#define MXC_CCM_CCMR_CSCS                       (1 << 25)
+#define MXC_CCM_CCMR_PERCS                      (1 << 24)
+#define MXC_CCM_CCMR_SSI1S_OFFSET               18
+#define MXC_CCM_CCMR_SSI1S_MASK                 (0x3 << 18)
+#define MXC_CCM_CCMR_SSI2S_OFFSET               21
+#define MXC_CCM_CCMR_SSI2S_MASK                 (0x3 << 21)
+#define MXC_CCM_CCMR_LPM_OFFSET                 14
+#define MXC_CCM_CCMR_LPM_MASK                   (0x3 << 14)
+#define MXC_CCM_CCMR_FIRS_OFFSET                11
+#define MXC_CCM_CCMR_FIRS_MASK                  (0x3 << 11)
+#define MXC_CCM_CCMR_UPE                        (1 << 9)
+#define MXC_CCM_CCMR_SPE                        (1 << 8)
+#define MXC_CCM_CCMR_MDS                        (1 << 7)
+#define MXC_CCM_CCMR_SBYCS                      (1 << 4)
+#define MXC_CCM_CCMR_MPE                        (1 << 3)
+#define MXC_CCM_CCMR_PRCS_OFFSET                1
+#define MXC_CCM_CCMR_PRCS_MASK                  (0x3 << 1)
+
+#define MXC_CCM_PDR0_CSI_PODF_OFFSET            26
+#define MXC_CCM_PDR0_CSI_PODF_MASK              (0x3F << 26)
+#define MXC_CCM_PDR0_CSI_PRDF_OFFSET            23
+#define MXC_CCM_PDR0_CSI_PRDF_MASK              (0x7 << 23)
+#define MXC_CCM_PDR0_PER_PODF_OFFSET            16
+#define MXC_CCM_PDR0_PER_PODF_MASK              (0x1F << 16)
+#define MXC_CCM_PDR0_HSP_PODF_OFFSET            11
+#define MXC_CCM_PDR0_HSP_PODF_MASK              (0x7 << 11)
+#define MXC_CCM_PDR0_NFC_PODF_OFFSET            8
+#define MXC_CCM_PDR0_NFC_PODF_MASK              (0x7 << 8)
+#define MXC_CCM_PDR0_IPG_PODF_OFFSET            6
+#define MXC_CCM_PDR0_IPG_PODF_MASK              (0x3 << 6)
+#define MXC_CCM_PDR0_MAX_PODF_OFFSET            3
+#define MXC_CCM_PDR0_MAX_PODF_MASK              (0x7 << 3)
+#define MXC_CCM_PDR0_MCU_PODF_OFFSET            0
+#define MXC_CCM_PDR0_MCU_PODF_MASK              0x7
+
+#define MXC_CCM_PDR0_HSP_DIV_1                  (0x0 << 11)
+#define MXC_CCM_PDR0_HSP_DIV_2                  (0x1 << 11)
+#define MXC_CCM_PDR0_HSP_DIV_3                  (0x2 << 11)
+#define MXC_CCM_PDR0_HSP_DIV_4                  (0x3 << 11)
+#define MXC_CCM_PDR0_HSP_DIV_5                  (0x4 << 11)
+#define MXC_CCM_PDR0_HSP_DIV_6                  (0x5 << 11)
+#define MXC_CCM_PDR0_HSP_DIV_7                  (0x6 << 11)
+#define MXC_CCM_PDR0_HSP_DIV_8                  (0x7 << 11)
+
+#define MXC_CCM_PDR0_IPG_DIV_1                  (0x0 << 6)
+#define MXC_CCM_PDR0_IPG_DIV_2                  (0x1 << 6)
+#define MXC_CCM_PDR0_IPG_DIV_3                  (0x2 << 6)
+#define MXC_CCM_PDR0_IPG_DIV_4                  (0x3 << 6)
+
+#define MXC_CCM_PDR0_MAX_DIV_1                  (0x0 << 3)
+#define MXC_CCM_PDR0_MAX_DIV_2                  (0x1 << 3)
+#define MXC_CCM_PDR0_MAX_DIV_3                  (0x2 << 3)
+#define MXC_CCM_PDR0_MAX_DIV_4                  (0x3 << 3)
+#define MXC_CCM_PDR0_MAX_DIV_5                  (0x4 << 3)
+#define MXC_CCM_PDR0_MAX_DIV_6                  (0x5 << 3)
+#define MXC_CCM_PDR0_MAX_DIV_7                  (0x6 << 3)
+#define MXC_CCM_PDR0_MAX_DIV_8                  (0x7 << 3)
+
+#define MXC_CCM_PDR0_NFC_DIV_1                  (0x0 << 8)
+#define MXC_CCM_PDR0_NFC_DIV_2                  (0x1 << 8)
+#define MXC_CCM_PDR0_NFC_DIV_3                  (0x2 << 8)
+#define MXC_CCM_PDR0_NFC_DIV_4                  (0x3 << 8)
+#define MXC_CCM_PDR0_NFC_DIV_5                  (0x4 << 8)
+#define MXC_CCM_PDR0_NFC_DIV_6                  (0x5 << 8)
+#define MXC_CCM_PDR0_NFC_DIV_7                  (0x6 << 8)
+#define MXC_CCM_PDR0_NFC_DIV_8                  (0x7 << 8)
+
+#define MXC_CCM_PDR0_MCU_DIV_1                  0x0
+#define MXC_CCM_PDR0_MCU_DIV_2                  0x1
+#define MXC_CCM_PDR0_MCU_DIV_3                  0x2
+#define MXC_CCM_PDR0_MCU_DIV_4                  0x3
+#define MXC_CCM_PDR0_MCU_DIV_5                  0x4
+#define MXC_CCM_PDR0_MCU_DIV_6                  0x5
+#define MXC_CCM_PDR0_MCU_DIV_7                  0x6
+#define MXC_CCM_PDR0_MCU_DIV_8                  0x7
+
+#define MXC_CCM_PDR1_USB_PRDF_OFFSET            30
+#define MXC_CCM_PDR1_USB_PRDF_MASK              (0x3 << 30)
+#define MXC_CCM_PDR1_USB_PODF_OFFSET            27
+#define MXC_CCM_PDR1_USB_PODF_MASK              (0x7 << 27)
+#define MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET       24
+#define MXC_CCM_PDR1_FIRI_PRE_PODF_MASK         (0x7 << 24)
+#define MXC_CCM_PDR1_FIRI_PODF_OFFSET           18
+#define MXC_CCM_PDR1_FIRI_PODF_MASK             (0x3F << 18)
+#define MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET       15
+#define MXC_CCM_PDR1_SSI2_PRE_PODF_MASK         (0x7 << 15)
+#define MXC_CCM_PDR1_SSI2_PODF_OFFSET           9
+#define MXC_CCM_PDR1_SSI2_PODF_MASK             (0x3F << 9)
+#define MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET       6
+#define MXC_CCM_PDR1_SSI1_PRE_PODF_MASK         (0x7 << 6)
+#define MXC_CCM_PDR1_SSI1_PODF_OFFSET           0
+#define MXC_CCM_PDR1_SSI1_PODF_MASK             0x3F
+
+/* Bit definitions for RCSR */
+#define MXC_CCM_RCSR_NF16B                     0x80000000
+
+/* Bit definitions for both MCU, USB and SR PLL control registers */
+#define MXC_CCM_PCTL_BRM                        0x80000000
+#define MXC_CCM_PCTL_PD_OFFSET                  26
+#define MXC_CCM_PCTL_PD_MASK                    (0xF << 26)
+#define MXC_CCM_PCTL_MFD_OFFSET                 16
+#define MXC_CCM_PCTL_MFD_MASK                   (0x3FF << 16)
+#define MXC_CCM_PCTL_MFI_OFFSET                 10
+#define MXC_CCM_PCTL_MFI_MASK                   (0xF << 10)
+#define MXC_CCM_PCTL_MFN_OFFSET                 0
+#define MXC_CCM_PCTL_MFN_MASK                   0x3FF
+
+#define MXC_CCM_CGR0_SD_MMC1_OFFSET             0
+#define MXC_CCM_CGR0_SD_MMC1_MASK               (0x3 << 0)
+#define MXC_CCM_CGR0_SD_MMC2_OFFSET             2
+#define MXC_CCM_CGR0_SD_MMC2_MASK               (0x3 << 2)
+#define MXC_CCM_CGR0_GPT_OFFSET                 4
+#define MXC_CCM_CGR0_GPT_MASK                   (0x3 << 4)
+#define MXC_CCM_CGR0_EPIT1_OFFSET               6
+#define MXC_CCM_CGR0_EPIT1_MASK                 (0x3 << 6)
+#define MXC_CCM_CGR0_EPIT2_OFFSET               8
+#define MXC_CCM_CGR0_EPIT2_MASK                 (0x3 << 8)
+#define MXC_CCM_CGR0_IIM_OFFSET                 10
+#define MXC_CCM_CGR0_IIM_MASK                   (0x3 << 10)
+#define MXC_CCM_CGR0_ATA_OFFSET                 12
+#define MXC_CCM_CGR0_ATA_MASK                   (0x3 << 12)
+#define MXC_CCM_CGR0_SDMA_OFFSET                14
+#define MXC_CCM_CGR0_SDMA_MASK                  (0x3 << 14)
+#define MXC_CCM_CGR0_CSPI3_OFFSET               16
+#define MXC_CCM_CGR0_CSPI3_MASK                 (0x3 << 16)
+#define MXC_CCM_CGR0_RNG_OFFSET                 18
+#define MXC_CCM_CGR0_RNG_MASK                   (0x3 << 18)
+#define MXC_CCM_CGR0_UART1_OFFSET               20
+#define MXC_CCM_CGR0_UART1_MASK                 (0x3 << 20)
+#define MXC_CCM_CGR0_UART2_OFFSET               22
+#define MXC_CCM_CGR0_UART2_MASK                 (0x3 << 22)
+#define MXC_CCM_CGR0_SSI1_OFFSET                24
+#define MXC_CCM_CGR0_SSI1_MASK                  (0x3 << 24)
+#define MXC_CCM_CGR0_I2C1_OFFSET                26
+#define MXC_CCM_CGR0_I2C1_MASK                  (0x3 << 26)
+#define MXC_CCM_CGR0_I2C2_OFFSET                28
+#define MXC_CCM_CGR0_I2C2_MASK                  (0x3 << 28)
+#define MXC_CCM_CGR0_I2C3_OFFSET                30
+#define MXC_CCM_CGR0_I2C3_MASK                  (0x3 << 30)
+
+#define MXC_CCM_CGR1_HANTRO_OFFSET              0
+#define MXC_CCM_CGR1_HANTRO_MASK                (0x3 << 0)
+#define MXC_CCM_CGR1_MEMSTICK1_OFFSET           2
+#define MXC_CCM_CGR1_MEMSTICK1_MASK             (0x3 << 2)
+#define MXC_CCM_CGR1_MEMSTICK2_OFFSET           4
+#define MXC_CCM_CGR1_MEMSTICK2_MASK             (0x3 << 4)
+#define MXC_CCM_CGR1_CSI_OFFSET                 6
+#define MXC_CCM_CGR1_CSI_MASK                   (0x3 << 6)
+#define MXC_CCM_CGR1_RTC_OFFSET                 8
+#define MXC_CCM_CGR1_RTC_MASK                   (0x3 << 8)
+#define MXC_CCM_CGR1_WDOG_OFFSET                10
+#define MXC_CCM_CGR1_WDOG_MASK                  (0x3 << 10)
+#define MXC_CCM_CGR1_PWM_OFFSET                 12
+#define MXC_CCM_CGR1_PWM_MASK                   (0x3 << 12)
+#define MXC_CCM_CGR1_SIM_OFFSET                 14
+#define MXC_CCM_CGR1_SIM_MASK                   (0x3 << 14)
+#define MXC_CCM_CGR1_ECT_OFFSET                 16
+#define MXC_CCM_CGR1_ECT_MASK                   (0x3 << 16)
+#define MXC_CCM_CGR1_USBOTG_OFFSET              18
+#define MXC_CCM_CGR1_USBOTG_MASK                (0x3 << 18)
+#define MXC_CCM_CGR1_KPP_OFFSET                 20
+#define MXC_CCM_CGR1_KPP_MASK                   (0x3 << 20)
+#define MXC_CCM_CGR1_IPU_OFFSET                 22
+#define MXC_CCM_CGR1_IPU_MASK                   (0x3 << 22)
+#define MXC_CCM_CGR1_UART3_OFFSET               24
+#define MXC_CCM_CGR1_UART3_MASK                 (0x3 << 24)
+#define MXC_CCM_CGR1_UART4_OFFSET               26
+#define MXC_CCM_CGR1_UART4_MASK                 (0x3 << 26)
+#define MXC_CCM_CGR1_UART5_OFFSET               28
+#define MXC_CCM_CGR1_UART5_MASK                 (0x3 << 28)
+#define MXC_CCM_CGR1_OWIRE_OFFSET               30
+#define MXC_CCM_CGR1_OWIRE_MASK                 (0x3 << 30)
+
+#define MXC_CCM_CGR2_SSI2_OFFSET                0
+#define MXC_CCM_CGR2_SSI2_MASK                  (0x3 << 0)
+#define MXC_CCM_CGR2_CSPI1_OFFSET               2
+#define MXC_CCM_CGR2_CSPI1_MASK                 (0x3 << 2)
+#define MXC_CCM_CGR2_CSPI2_OFFSET               4
+#define MXC_CCM_CGR2_CSPI2_MASK                 (0x3 << 4)
+#define MXC_CCM_CGR2_GACC_OFFSET                6
+#define MXC_CCM_CGR2_GACC_MASK                  (0x3 << 6)
+#define MXC_CCM_CGR2_EMI_OFFSET                 8
+#define MXC_CCM_CGR2_EMI_MASK                   (0x3 << 8)
+#define MXC_CCM_CGR2_RTIC_OFFSET                10
+#define MXC_CCM_CGR2_RTIC_MASK                  (0x3 << 10)
+#define MXC_CCM_CGR2_FIRI_OFFSET                12
+#define MXC_CCM_CGR2_FIRI_MASK                  (0x3 << 12)
+#define MXC_CCM_CGR2_IPMUX1_OFFSET              14
+#define MXC_CCM_CGR2_IPMUX1_MASK                (0x3 << 14)
+#define MXC_CCM_CGR2_IPMUX2_OFFSET              16
+#define MXC_CCM_CGR2_IPMUX2_MASK                (0x3 << 16)
+
+/* These new CGR2 bits are added in MX32 */
+#define MXC_CCM_CGR2_APMSYSCLKSEL_OFFSET       18
+#define MXC_CCM_CGR2_APMSYSCLKSEL_MASK         (0x3 << 18)
+#define MXC_CCM_CGR2_APMSSICLKSEL_OFFSET       20
+#define MXC_CCM_CGR2_APMSSICLKSEL_MASK         (0x3 << 20)
+#define MXC_CCM_CGR2_APMPERCLKSEL_OFFSET       22
+#define MXC_CCM_CGR2_APMPERCLKSEL_MASK         (0x3 << 22)
+#define MXC_CCM_CGR2_MXCCLKENSEL_OFFSET                24
+#define MXC_CCM_CGR2_MXCCLKENSEL_MASK          (0x1 << 24)
+#define MXC_CCM_CGR2_CHIKCAMPEN_OFFSET         25
+#define MXC_CCM_CGR2_CHIKCAMPEN_MASK           (0x1 << 25)
+#define MXC_CCM_CGR2_OVRVPUBUSY_OFFSET         26
+#define MXC_CCM_CGR2_OVRVPUBUSY_MASK           (0x1 << 26)
+#define MXC_CCM_CGR2_APMENA_OFFSET             30
+#define MXC_CCM_CGR2_AOMENA_MASK               (0x1 << 30)
+
+/*
+ * LTR0 register offsets
+ */
+#define MXC_CCM_LTR0_DIV3CK_OFFSET              1
+#define MXC_CCM_LTR0_DIV3CK_MASK                (0x3 << 1)
+#define MXC_CCM_LTR0_DNTHR_OFFSET               16
+#define MXC_CCM_LTR0_DNTHR_MASK                 (0x3F << 16)
+#define MXC_CCM_LTR0_UPTHR_OFFSET               22
+#define MXC_CCM_LTR0_UPTHR_MASK                 (0x3F << 22)
+
+/*
+ * LTR1 register offsets
+ */
+#define MXC_CCM_LTR1_PNCTHR_OFFSET              0
+#define MXC_CCM_LTR1_PNCTHR_MASK                0x3F
+#define MXC_CCM_LTR1_UPCNT_OFFSET               6
+#define MXC_CCM_LTR1_UPCNT_MASK                 (0xFF << 6)
+#define MXC_CCM_LTR1_DNCNT_OFFSET               14
+#define MXC_CCM_LTR1_DNCNT_MASK                 (0xFF << 14)
+#define MXC_CCM_LTR1_LTBRSR_MASK                0x400000
+#define MXC_CCM_LTR1_LTBRSR_OFFSET              22
+#define MXC_CCM_LTR1_LTBRSR                     0x400000
+#define MXC_CCM_LTR1_LTBRSH                     0x800000
+
+/*
+ * LTR2 bit definitions. x ranges from 0 for WSW9 to 6 for WSW15
+ */
+#define MXC_CCM_LTR2_WSW_OFFSET(x)              (11 + (x) * 3)
+#define MXC_CCM_LTR2_WSW_MASK(x)                (0x7 << \
+                                       MXC_CCM_LTR2_WSW_OFFSET((x)))
+#define MXC_CCM_LTR2_EMAC_OFFSET                0
+#define MXC_CCM_LTR2_EMAC_MASK                  0x1FF
+
+/*
+ * LTR3 bit definitions. x ranges from 0 for WSW0 to 8 for WSW8
+ */
+#define MXC_CCM_LTR3_WSW_OFFSET(x)              (5 + (x) * 3)
+#define MXC_CCM_LTR3_WSW_MASK(x)                (0x7 << \
+                                       MXC_CCM_LTR3_WSW_OFFSET((x)))
+
+#define MXC_CCM_PMCR0_DFSUP1                    0x80000000
+#define MXC_CCM_PMCR0_DFSUP1_SPLL               (0 << 31)
+#define MXC_CCM_PMCR0_DFSUP1_MPLL               (1 << 31)
+#define MXC_CCM_PMCR0_DFSUP0                    0x40000000
+#define MXC_CCM_PMCR0_DFSUP0_PLL                (0 << 30)
+#define MXC_CCM_PMCR0_DFSUP0_PDR                (1 << 30)
+#define MXC_CCM_PMCR0_DFSUP_MASK                (0x3 << 30)
+
+#define DVSUP_TURBO                            0
+#define DVSUP_HIGH                             1
+#define DVSUP_MEDIUM                           2
+#define DVSUP_LOW                              3
+#define MXC_CCM_PMCR0_DVSUP_TURBO               (DVSUP_TURBO << 28)
+#define MXC_CCM_PMCR0_DVSUP_HIGH                (DVSUP_HIGH << 28)
+#define MXC_CCM_PMCR0_DVSUP_MEDIUM              (DVSUP_MEDIUM << 28)
+#define MXC_CCM_PMCR0_DVSUP_LOW                 (DVSUP_LOW << 28)
+#define MXC_CCM_PMCR0_DVSUP_OFFSET              28
+#define MXC_CCM_PMCR0_DVSUP_MASK                (0x3 << 28)
+#define MXC_CCM_PMCR0_UDSC                      0x08000000
+#define MXC_CCM_PMCR0_UDSC_MASK                 (1 << 27)
+#define MXC_CCM_PMCR0_UDSC_UP                   (1 << 27)
+#define MXC_CCM_PMCR0_UDSC_DOWN                 (0 << 27)
+
+#define MXC_CCM_PMCR0_VSCNT_1                   (0x0 << 24)
+#define MXC_CCM_PMCR0_VSCNT_2                   (0x1 << 24)
+#define MXC_CCM_PMCR0_VSCNT_3                   (0x2 << 24)
+#define MXC_CCM_PMCR0_VSCNT_4                   (0x3 << 24)
+#define MXC_CCM_PMCR0_VSCNT_5                   (0x4 << 24)
+#define MXC_CCM_PMCR0_VSCNT_6                   (0x5 << 24)
+#define MXC_CCM_PMCR0_VSCNT_7                   (0x6 << 24)
+#define MXC_CCM_PMCR0_VSCNT_8                   (0x7 << 24)
+#define MXC_CCM_PMCR0_VSCNT_OFFSET              24
+#define MXC_CCM_PMCR0_VSCNT_MASK                (0x7 << 24)
+#define MXC_CCM_PMCR0_DVFEV                     0x00800000
+#define MXC_CCM_PMCR0_DVFIS                     0x00400000
+#define MXC_CCM_PMCR0_LBMI                      0x00200000
+#define MXC_CCM_PMCR0_LBFL                      0x00100000
+#define MXC_CCM_PMCR0_LBCF_4                    (0x0 << 18)
+#define MXC_CCM_PMCR0_LBCF_8                    (0x1 << 18)
+#define MXC_CCM_PMCR0_LBCF_12                   (0x2 << 18)
+#define MXC_CCM_PMCR0_LBCF_16                   (0x3 << 18)
+#define MXC_CCM_PMCR0_LBCF_OFFSET               18
+#define MXC_CCM_PMCR0_LBCF_MASK                 (0x3 << 18)
+#define MXC_CCM_PMCR0_PTVIS                     0x00020000
+#define MXC_CCM_PMCR0_UPDTEN                    0x00010000
+#define MXC_CCM_PMCR0_UPDTEN_MASK               (0x1 << 16)
+#define MXC_CCM_PMCR0_FSVAIM                    0x00008000
+#define MXC_CCM_PMCR0_FSVAI_OFFSET              13
+#define MXC_CCM_PMCR0_FSVAI_MASK                (0x3 << 13)
+#define MXC_CCM_PMCR0_DPVCR                     0x00001000
+#define MXC_CCM_PMCR0_DPVV                      0x00000800
+#define MXC_CCM_PMCR0_WFIM                      0x00000400
+#define MXC_CCM_PMCR0_DRCE3                     0x00000200
+#define MXC_CCM_PMCR0_DRCE2                     0x00000100
+#define MXC_CCM_PMCR0_DRCE1                     0x00000080
+#define MXC_CCM_PMCR0_DRCE0                     0x00000040
+#define MXC_CCM_PMCR0_DCR                       0x00000020
+#define MXC_CCM_PMCR0_DVFEN                     0x00000010
+#define MXC_CCM_PMCR0_PTVAIM                    0x00000008
+#define MXC_CCM_PMCR0_PTVAI_OFFSET              1
+#define MXC_CCM_PMCR0_PTVAI_MASK                (0x3 << 1)
+#define MXC_CCM_PMCR0_DPTEN                     0x00000001
+
+#define MXC_CCM_PMCR1_DVGP_OFFSET               0
+#define MXC_CCM_PMCR1_DVGP_MASK                 (0xF)
+
+#define MXC_CCM_PMCR1_PLLRDIS                      (0x1 << 7)
+#define MXC_CCM_PMCR1_EMIRQ_EN                      (0x1 << 8)
+
+#define MXC_CCM_DCVR_ULV_MASK                   (0x3FF << 22)
+#define MXC_CCM_DCVR_ULV_OFFSET                 22
+#define MXC_CCM_DCVR_LLV_MASK                   (0x3FF << 12)
+#define MXC_CCM_DCVR_LLV_OFFSET                 12
+#define MXC_CCM_DCVR_ELV_MASK                   (0x3FF << 2)
+#define MXC_CCM_DCVR_ELV_OFFSET                 2
+
+#define MXC_CCM_PDR2_MST2_PDF_MASK              (0x3F << 7)
+#define MXC_CCM_PDR2_MST2_PDF_OFFSET            7
+#define MXC_CCM_PDR2_MST1_PDF_MASK              0x3F
+#define MXC_CCM_PDR2_MST1_PDF_OFFSET            0
+
+#define MXC_CCM_COSR_CLKOSEL_MASK               0x0F
+#define MXC_CCM_COSR_CLKOSEL_OFFSET             0
+#define MXC_CCM_COSR_CLKOUTDIV_MASK             (0x07 << 6)
+#define MXC_CCM_COSR_CLKOUTDIV_OFFSET           6
+#define MXC_CCM_COSR_CLKOEN                     (1 << 9)
+
+/*
+ * PMCR0 register offsets
+ */
+#define MXC_CCM_PMCR0_LBFL_OFFSET   20
+#define MXC_CCM_PMCR0_DFSUP0_OFFSET 30
+#define MXC_CCM_PMCR0_DFSUP1_OFFSET 31
+
+#endif                         /* __ARCH_ARM_MACH_MX3_CRM_REGS_H__ */
index 23b4350..c6d4aa3 100644 (file)
@@ -16,5 +16,6 @@ struct sys_timer;
 extern void mxc_map_io(void);
 extern void mxc_init_irq(void);
 extern struct sys_timer mxc_timer;
+extern int mxc_clocks_init(unsigned long fref);
 
 #endif