extern bool enable_wait_mode;
void __iomem *apll_base;
+
+static void __iomem *timer_base;
static struct clk ipu1_clk;
static struct clk ipu2_clk;
static struct clk axi_clk;
static struct clk enfc_clk;
static struct clk usdhc3_clk;
static struct clk ipg_clk;
+static struct clk gpt_clk[];
static struct cpu_op *cpu_op_tbl;
static int cpu_op_nr;
#define AUDIO_VIDEO_MIN_CLK_FREQ 650000000
#define AUDIO_VIDEO_MAX_CLK_FREQ 1300000000
DEFINE_SPINLOCK(clk_lock);
+#define V2_TCN 0x24
+#define V2_TSTAT 0x08
+#define V2_TSTAT_ROV (1 << 5)
/* We need to check the exp status again after timer expiration,
* as there might be interrupt coming between the first time exp
* timer expiration. */
#define WAIT(exp, timeout) \
({ \
- struct timespec nstimeofday; \
- struct timespec curtime; \
+ u32 gpt_rate; \
+ u32 gpt_ticks; \
+ u32 gpt_cnt; \
+ u32 reg; \
int result = 1; \
- getnstimeofday(&nstimeofday); \
+ gpt_rate = clk_get_rate(&gpt_clk[0]); \
+ gpt_ticks = timeout / (1000000000 / gpt_rate); \
+ reg = __raw_readl(timer_base + V2_TSTAT);\
+ /* Clear the GPT roll over interrupt. */ \
+ if (reg & V2_TSTAT_ROV) { \
+ reg |= V2_TSTAT_ROV;\
+ __raw_writel(reg, timer_base + V2_TSTAT);\
+ } \
+ gpt_cnt = __raw_readl(timer_base + V2_TCN); \
while (!(exp)) { \
- getnstimeofday(&curtime); \
- if ((curtime.tv_nsec - nstimeofday.tv_nsec) > (timeout)) { \
- if (!(exp)) \
+ if ((__raw_readl(timer_base + V2_TCN) - gpt_cnt) > gpt_ticks) { \
+ if (!exp) \
result = 0; \
break; \
+ } else { \
+ reg = __raw_readl(timer_base + V2_TSTAT);\
+ if (reg & V2_TSTAT_ROV) { \
+ u32 old_cnt = gpt_cnt; \
+ /* Timer has rolled over. \
+ * Calculate the new tcik count. \
+ */ \
+ gpt_cnt = __raw_readl(timer_base + V2_TCN); \
+ gpt_ticks -= (0xFFFFFFFF - old_cnt + gpt_cnt); \
+ /* Clear the roll over interrupt. */ \
+ reg |= V2_TSTAT_ROV;\
+ __raw_writel(reg, timer_base + V2_TSTAT);\
+ } \
} \
} \
result; \
__raw_writel(BM_ANADIG_ANA_MISC2_CONTROL0, apll_base + HW_ANADIG_ANA_MISC2_CLR);
/* Wait for PLL to lock */
- if (!WAIT(__raw_readl(pllbase) & ANADIG_PLL_LOCK,
+ if (!WAIT((__raw_readl(pllbase) & ANADIG_PLL_LOCK),
SPIN_DELAY))
panic("pll enable failed\n");
__raw_writel(reg, PLL1_SYS_BASE_ADDR);
/* Wait for PLL1 to lock */
- if (!WAIT(__raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_LOCK,
+ if (!WAIT((__raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_LOCK),
SPIN_DELAY))
panic("pll1 enable failed\n");
ckih2_reference = ckih2;
oscillator_reference = osc;
+ timer_base = ioremap(GPT_BASE_ADDR, SZ_4K);
+
apll_base = ioremap(ANATOP_BASE_ADDR, SZ_4K);
for (i = 0; i < ARRAY_SIZE(lookups); i++) {
clk_debug_register(lookups[i].clk);
}
- /* Disable un-necessary PFDs & PLLs */
+ /* Timer needs to be initialized first as the
+ * the WAIT routines use GPT counter as
+ * a delay.
+ */
+ if (mx6q_revision() == IMX_CHIP_REVISION_1_0) {
+ gpt_clk[0].parent = &ipg_perclk;
+ gpt_clk[0].get_rate = NULL;
+ } else {
+ /* Here we use OSC 24M as GPT's clock source, no need to
+ enable gpt serial clock*/
+ gpt_clk[0].secondary = NULL;
+ }
+
+ mxc_timer_init(&gpt_clk[0], timer_base, MXC_INT_GPT);
+
+ clk_tree_init();
/* keep correct count. */
clk_enable(&cpu_clk);
clk_enable(&periph_clk);
- clk_tree_init();
-
+ /* Disable un-necessary PFDs & PLLs */
if (pll2_pfd_400M.usecount == 0 && cpu_is_mx6q())
pll2_pfd_400M.disable(&pll2_pfd_400M);
pll2_pfd_352M.disable(&pll2_pfd_352M);
if (cpu_is_mx6dl())
clk_set_parent(&mlb150_clk, &pll3_sw_clk);
- if (mx6q_revision() == IMX_CHIP_REVISION_1_0) {
- gpt_clk[0].parent = &ipg_perclk;
- gpt_clk[0].get_rate = NULL;
- } else {
- /* Here we use OSC 24M as GPT's clock source, no need to
- enable gpt serial clock*/
- gpt_clk[0].secondary = NULL;
- }
if (cpu_is_mx6dl()) {
/* pxp & epdc */
clk_set_parent(&ipu2_di_clk[1], &pll3_pfd_540M);
}
- base = ioremap(GPT_BASE_ADDR, SZ_4K);
- mxc_timer_init(&gpt_clk[0], base, MXC_INT_GPT);
-
lp_high_freq = 0;
lp_med_freq = 0;
lp_audio_freq = 0;
extern int cur_arm_podf;
static void __iomem *apll_base;
+static void __iomem *timer_base;
static struct clk pll1_sys_main_clk;
static struct clk pll2_528_bus_main_clk;
static struct clk pll2_pfd2_400M;
static struct clk pll7_usb_host_main_clk;
static struct clk usdhc3_clk;
static struct clk ipg_clk;
+static struct clk gpt_clk[];
static struct cpu_op *cpu_op_tbl;
static int cpu_op_nr;
#define AUDIO_VIDEO_MIN_CLK_FREQ 650000000
#define AUDIO_VIDEO_MAX_CLK_FREQ 1300000000
#define MAX_ARM_CLK_IN_WAIT 158000000
+#define V2_TCN 0x24
+#define V2_TSTAT 0x08
+#define V2_TSTAT_ROV (1 << 5)
/* We need to check the exp status again after timer expiration,
* as there might be interrupt coming between the first time exp
* timer expiration. */
#define WAIT(exp, timeout) \
({ \
- struct timespec nstimeofday; \
- struct timespec curtime; \
+ u32 gpt_rate; \
+ u32 gpt_ticks; \
+ u32 gpt_cnt; \
+ u32 reg; \
int result = 1; \
- getnstimeofday(&nstimeofday); \
+ gpt_rate = clk_get_rate(&gpt_clk[0]); \
+ gpt_ticks = timeout / (1000000000 / gpt_rate); \
+ reg = __raw_readl(timer_base + V2_TSTAT);\
+ /* Clear the GPT roll over interrupt. */ \
+ if (reg & V2_TSTAT_ROV) { \
+ reg |= V2_TSTAT_ROV;\
+ __raw_writel(reg, timer_base + V2_TSTAT);\
+ } \
+ gpt_cnt = __raw_readl(timer_base + V2_TCN); \
while (!(exp)) { \
- getnstimeofday(&curtime); \
- if ((curtime.tv_nsec - nstimeofday.tv_nsec) > (timeout)) { \
- if (!(exp)) \
+ if ((__raw_readl(timer_base + V2_TCN) - gpt_cnt) > gpt_ticks) { \
+ if (!exp) \
result = 0; \
break; \
+ } else { \
+ reg = __raw_readl(timer_base + V2_TSTAT);\
+ if (reg & V2_TSTAT_ROV) { \
+ u32 old_cnt = gpt_cnt; \
+ /* Timer has rolled over. \
+ * Calculate the new tcik count. \
+ */ \
+ gpt_cnt = __raw_readl(timer_base + V2_TCN); \
+ gpt_ticks -= (0xFFFFFFFF - old_cnt + gpt_cnt); \
+ /* Clear the roll over interrupt. */ \
+ reg |= V2_TSTAT_ROV;\
+ __raw_writel(reg, timer_base + V2_TSTAT);\
+ } \
} \
} \
result; \
__raw_writel(BM_ANADIG_ANA_MISC2_CONTROL0, apll_base + HW_ANADIG_ANA_MISC2_CLR);
/* Wait for PLL to lock */
- if (!WAIT(__raw_readl(pllbase) & ANADIG_PLL_LOCK,
+ if (!WAIT((__raw_readl(pllbase) & ANADIG_PLL_LOCK),
SPIN_DELAY))
panic("pll enable failed\n");
__raw_writel(reg, PLL1_SYS_BASE_ADDR);
/* Wait for PLL1 to lock */
- if (!WAIT(__raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_LOCK,
+ if (!WAIT((__raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_LOCK),
SPIN_DELAY))
panic("pll1 enable failed\n");
int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc,
unsigned long ckih1, unsigned long ckih2)
{
- __iomem void *base;
int i;
external_low_reference = ckil;
ckih2_reference = ckih2;
oscillator_reference = osc;
+ timer_base = ioremap(GPT_BASE_ADDR, SZ_4K);
apll_base = ioremap(ANATOP_BASE_ADDR, SZ_4K);
for (i = 0; i < ARRAY_SIZE(lookups); i++) {
clk_debug_register(lookups[i].clk);
}
- /* Disable un-necessary PFDs & PLLs */
+ /* GPT will source from perclk, hence ipg_perclk
+ * should be from OSC24M */
+ clk_set_parent(&ipg_perclk, &osc_clk);
+
+ gpt_clk[0].parent = &ipg_perclk;
+ gpt_clk[0].get_rate = NULL;
+
+ mxc_timer_init(&gpt_clk[0], timer_base, MXC_INT_GPT);
+
+ clk_tree_init();
/* keep correct count. */
clk_enable(&cpu_clk);
clk_enable(&periph_clk);
- clk_tree_init();
-
/* Set AHB to 132MHz. */
clk_set_rate(&ahb_clk, clk_round_rate(&ahb_clk, 132000000));
+ /* Disable un-necessary PFDs & PLLs */
pll2_pfd0_352M.disable(&pll2_pfd0_352M);
pll2_pfd1_594M.disable(&pll2_pfd1_594M);
/* lcdif pix - PLL5 as parent */
clk_set_parent(&lcdif_pix_clk, &pll5_video_main_clk);
- gpt_clk[0].parent = &ipg_perclk;
- gpt_clk[0].get_rate = NULL;
-
- /* GPT will source from perclk, hence ipg_perclk
- * should be from OSC24M */
- clk_set_parent(&ipg_perclk, &osc_clk);
-
- base = ioremap(GPT_BASE_ADDR, SZ_4K);
- mxc_timer_init(&gpt_clk[0], base, MXC_INT_GPT);
-
lp_high_freq = 0;
lp_med_freq = 0;
have to do this, so use macro to decrease the impact on
released code, the 1Ghz issue should be fixed in the future*/
if (pre_suspend_rate != (imx_freq_table[0].frequency * 1000))
- #ifdef CONFIG_MX6_INTER_LDO_BYPASS
set_cpu_freq(imx_freq_table[0].frequency * 1000);
- #else
- set_cpu_freq(imx_freq_table[0].frequency);
- #endif
return 0;
}