Commit df1bf4bd authored by Sascha Hauer's avatar Sascha Hauer Committed by Robert Schwebel

i.MX3: introduce clock API

This patch introduces the clock API for for arch-mxc
Signed-off-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
parent c0db2ea4
......@@ -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
/*
* 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;
}
/*
* 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__ */
......@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment