Commit ea01d31a authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'imx-common-clk' of git://git.pengutronix.de/git/imx/linux-2.6 into next/clock

Sascha Hauer <s.hauer@pengutronix.de> writes:

 ARM i.MX common clock framework support

 Same as with Shawns series this one depends on:
   git://git.linaro.org/people/mturquette/linux.git clk-next
   http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-arm.git clkdev

* tag 'imx-common-clk' of git://git.pengutronix.de/git/imx/linux-2.6: (34 commits)
  ARM i.MX: remove now unused clock files
  ARM: i.MX6: implement clocks using common clock framework
  ARM i.MX35: implement clocks using common clock framework
  ARM i.MX5: implement clocks using common clock framework
  ARM i.MX31: implement clocks using common clock framework
  ARM i.MX27: implement clocks using common clock framework
  ARM i.MX21: implement clocks using common clock framework
  ARM i.MX1: implement clocks using common clock framework
  ARM i.MX25: implement clocks using common clock framework
  ARM: imx: add common clock support for clk busy
  ARM: imx: add common clock support for pfd
  ARM i.MX: Add common clock support for 2bit gate
  ARM: imx: add common clock support for pllv3
  ARM i.MX: Add common clock support for pllv2
  ARM i.MX: Add common clock support for pllv1
  ARM i.MX: prepare for common clock framework
  ARM i.MX3: Make ccm base address a variable
  ARM i.MX timer: request correct clock
  ARM i.MX5: prepare gpc_dvfs_clk
  rtc: imx dryice: Add missing clk_prepare
  ...
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents e12ff344 c818f97b
......@@ -34,6 +34,7 @@ config ARCH_MX53
config SOC_IMX1
bool
select ARCH_MX1
select COMMON_CLK
select CPU_ARM920T
select IMX_HAVE_IOMUX_V1
select MXC_AVIC
......@@ -42,12 +43,14 @@ config SOC_IMX21
bool
select MACH_MX21
select CPU_ARM926T
select COMMON_CLK
select IMX_HAVE_IOMUX_V1
select MXC_AVIC
config SOC_IMX25
bool
select ARCH_MX25
select COMMON_CLK
select CPU_ARM926T
select ARCH_MXC_IOMUX_V3
select MXC_AVIC
......@@ -56,6 +59,7 @@ config SOC_IMX27
bool
select MACH_MX27
select CPU_ARM926T
select COMMON_CLK
select IMX_HAVE_IOMUX_V1
select MXC_AVIC
......@@ -64,12 +68,14 @@ config SOC_IMX31
select CPU_V6
select IMX_HAVE_PLATFORM_MXC_RNGA
select MXC_AVIC
select COMMON_CLK
select SMP_ON_UP if SMP
config SOC_IMX35
bool
select CPU_V6
select ARCH_MXC_IOMUX_V3
select COMMON_CLK
select HAVE_EPIT
select MXC_AVIC
select SMP_ON_UP if SMP
......@@ -77,6 +83,7 @@ config SOC_IMX35
config SOC_IMX5
select CPU_V7
select MXC_TZIC
select COMMON_CLK
select ARCH_MXC_IOMUX_V3
select ARCH_HAS_CPUFREQ
select ARCH_MX5
......@@ -836,6 +843,7 @@ config SOC_IMX6Q
bool "i.MX6 Quad support"
select ARM_CPU_SUSPEND if PM
select ARM_GIC
select COMMON_CLK
select CPU_V7
select HAVE_ARM_SCU
select HAVE_IMX_GPC
......
obj-$(CONFIG_SOC_IMX1) += clock-imx1.o mm-imx1.o
obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
obj-$(CONFIG_SOC_IMX25) += clock-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-imx3.o
obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
clk-pfd.o clk-busy.o
# Support for CMOS sensor interface
obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
......@@ -70,7 +73,7 @@ obj-$(CONFIG_CPU_V7) += head-v7.o
AFLAGS_head-v7.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SMP) += platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o
obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
ifeq ($(CONFIG_PM),y)
obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o
......
/*
* Copyright 2012 Freescale Semiconductor, Inc.
* Copyright 2012 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/err.h>
#include "clk.h"
static int clk_busy_wait(void __iomem *reg, u8 shift)
{
unsigned long timeout = jiffies + msecs_to_jiffies(10);
while (readl_relaxed(reg) & (1 << shift))
if (time_after(jiffies, timeout))
return -ETIMEDOUT;
return 0;
}
struct clk_busy_divider {
struct clk_divider div;
const struct clk_ops *div_ops;
void __iomem *reg;
u8 shift;
};
static inline struct clk_busy_divider *to_clk_busy_divider(struct clk_hw *hw)
{
struct clk_divider *div = container_of(hw, struct clk_divider, hw);
return container_of(div, struct clk_busy_divider, div);
}
static unsigned long clk_busy_divider_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_busy_divider *busy = to_clk_busy_divider(hw);
return busy->div_ops->recalc_rate(&busy->div.hw, parent_rate);
}
static long clk_busy_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_busy_divider *busy = to_clk_busy_divider(hw);
return busy->div_ops->round_rate(&busy->div.hw, rate, prate);
}
static int clk_busy_divider_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_busy_divider *busy = to_clk_busy_divider(hw);
int ret;
ret = busy->div_ops->set_rate(&busy->div.hw, rate, parent_rate);
if (!ret)
ret = clk_busy_wait(busy->reg, busy->shift);
return ret;
}
static struct clk_ops clk_busy_divider_ops = {
.recalc_rate = clk_busy_divider_recalc_rate,
.round_rate = clk_busy_divider_round_rate,
.set_rate = clk_busy_divider_set_rate,
};
struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
void __iomem *reg, u8 shift, u8 width,
void __iomem *busy_reg, u8 busy_shift)
{
struct clk_busy_divider *busy;
struct clk *clk;
struct clk_init_data init;
busy = kzalloc(sizeof(*busy), GFP_KERNEL);
if (!busy)
return ERR_PTR(-ENOMEM);
busy->reg = busy_reg;
busy->shift = busy_shift;
busy->div.reg = reg;
busy->div.shift = shift;
busy->div.width = width;
busy->div.lock = &imx_ccm_lock;
busy->div_ops = &clk_divider_ops;
init.name = name;
init.ops = &clk_busy_divider_ops;
init.flags = CLK_SET_RATE_PARENT;
init.parent_names = &parent_name;
init.num_parents = 1;
busy->div.hw.init = &init;
clk = clk_register(NULL, &busy->div.hw);
if (!clk)
kfree(busy);
return clk;
}
struct clk_busy_mux {
struct clk_mux mux;
const struct clk_ops *mux_ops;
void __iomem *reg;
u8 shift;
};
static inline struct clk_busy_mux *to_clk_busy_mux(struct clk_hw *hw)
{
struct clk_mux *mux = container_of(hw, struct clk_mux, hw);
return container_of(mux, struct clk_busy_mux, mux);
}
static u8 clk_busy_mux_get_parent(struct clk_hw *hw)
{
struct clk_busy_mux *busy = to_clk_busy_mux(hw);
return busy->mux_ops->get_parent(&busy->mux.hw);
}
static int clk_busy_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_busy_mux *busy = to_clk_busy_mux(hw);
int ret;
ret = busy->mux_ops->set_parent(&busy->mux.hw, index);
if (!ret)
ret = clk_busy_wait(busy->reg, busy->shift);
return ret;
}
struct clk_ops clk_busy_mux_ops = {
.get_parent = clk_busy_mux_get_parent,
.set_parent = clk_busy_mux_set_parent,
};
struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
u8 width, void __iomem *busy_reg, u8 busy_shift,
const char **parent_names, int num_parents)
{
struct clk_busy_mux *busy;
struct clk *clk;
struct clk_init_data init;
busy = kzalloc(sizeof(*busy), GFP_KERNEL);
if (!busy)
return ERR_PTR(-ENOMEM);
busy->reg = busy_reg;
busy->shift = busy_shift;
busy->mux.reg = reg;
busy->mux.shift = shift;
busy->mux.width = width;
busy->mux.lock = &imx_ccm_lock;
busy->mux_ops = &clk_mux_ops;
init.name = name;
init.ops = &clk_busy_mux_ops;
init.flags = 0;
init.parent_names = parent_names;
init.num_parents = num_parents;
busy->mux.hw.init = &init;
clk = clk_register(NULL, &busy->mux.hw);
if (IS_ERR(clk))
kfree(busy);
return clk;
}
/*
* Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
* Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Gated clock implementation
*/
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/string.h>
/**
* DOC: basic gatable clock which can gate and ungate it's ouput
*
* Traits of this clock:
* prepare - clk_(un)prepare only ensures parent is (un)prepared
* enable - clk_enable and clk_disable are functional & control gating
* rate - inherits rate from parent. No clk_set_rate support
* parent - fixed parent. No clk_set_parent support
*/
#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
static int clk_gate2_enable(struct clk_hw *hw)
{
struct clk_gate *gate = to_clk_gate(hw);
u32 reg;
unsigned long flags = 0;
if (gate->lock)
spin_lock_irqsave(gate->lock, flags);
reg = readl(gate->reg);
reg |= 3 << gate->bit_idx;
writel(reg, gate->reg);
if (gate->lock)
spin_unlock_irqrestore(gate->lock, flags);
return 0;
}
static void clk_gate2_disable(struct clk_hw *hw)
{
struct clk_gate *gate = to_clk_gate(hw);
u32 reg;
unsigned long flags = 0;
if (gate->lock)
spin_lock_irqsave(gate->lock, flags);
reg = readl(gate->reg);
reg &= ~(3 << gate->bit_idx);
writel(reg, gate->reg);
if (gate->lock)
spin_unlock_irqrestore(gate->lock, flags);
}
static int clk_gate2_is_enabled(struct clk_hw *hw)
{
u32 reg;
struct clk_gate *gate = to_clk_gate(hw);
reg = readl(gate->reg);
if (((reg >> gate->bit_idx) & 3) == 3)
return 1;
return 0;
}
static struct clk_ops clk_gate2_ops = {
.enable = clk_gate2_enable,
.disable = clk_gate2_disable,
.is_enabled = clk_gate2_is_enabled,
};
struct clk *clk_register_gate2(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 bit_idx,
u8 clk_gate2_flags, spinlock_t *lock)
{
struct clk_gate *gate;
struct clk *clk;
struct clk_init_data init;
gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
if (!gate)
return ERR_PTR(-ENOMEM);
/* struct clk_gate assignments */
gate->reg = reg;
gate->bit_idx = bit_idx;
gate->flags = clk_gate2_flags;
gate->lock = lock;
init.name = name;
init.ops = &clk_gate2_ops;
init.flags = flags;
init.parent_names = parent_name ? &parent_name : NULL;
init.num_parents = parent_name ? 1 : 0;
gate->hw.init = &init;
clk = clk_register(dev, &gate->hw);
if (IS_ERR(clk))
kfree(clk);
return clk;
}
/*
* Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include "clk.h"
/* CCM register addresses */
#define IO_ADDR_CCM(off) (MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR + (off)))
#define CCM_CSCR IO_ADDR_CCM(0x0)
#define CCM_MPCTL0 IO_ADDR_CCM(0x4)
#define CCM_SPCTL0 IO_ADDR_CCM(0xc)
#define CCM_PCDR IO_ADDR_CCM(0x20)
/* SCM register addresses */
#define IO_ADDR_SCM(off) (MX1_IO_ADDRESS(MX1_SCM_BASE_ADDR + (off)))
#define SCM_GCCR IO_ADDR_SCM(0xc)
static const char *prem_sel_clks[] = { "clk32_premult", "clk16m", };
static const char *clko_sel_clks[] = { "per1", "hclk", "clk48m", "clk16m", "prem",
"fclk", };
enum imx1_clks {
dummy, clk32, clk16m_ext, clk16m, clk32_premult, prem, mpll, spll, mcu,
fclk, hclk, clk48m, per1, per2, per3, clko, dma_gate, csi_gate,
mma_gate, usbd_gate, clk_max
};
static struct clk *clk[clk_max];
int __init mx1_clocks_init(unsigned long fref)
{
int i;
clk[dummy] = imx_clk_fixed("dummy", 0);
clk[clk32] = imx_clk_fixed("clk32", fref);
clk[clk16m_ext] = imx_clk_fixed("clk16m_ext", 16000000);
clk[clk16m] = imx_clk_gate("clk16m", "clk16m_ext", CCM_CSCR, 17);
clk[clk32_premult] = imx_clk_fixed_factor("clk32_premult", "clk32", 512, 1);
clk[prem] = imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks,
ARRAY_SIZE(prem_sel_clks));
clk[mpll] = imx_clk_pllv1("mpll", "clk32_premult", CCM_MPCTL0);
clk[spll] = imx_clk_pllv1("spll", "prem", CCM_SPCTL0);
clk[mcu] = imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1);
clk[fclk] = imx_clk_divider("fclk", "mpll", CCM_CSCR, 15, 1);
clk[hclk] = imx_clk_divider("hclk", "spll", CCM_CSCR, 10, 4);
clk[clk48m] = imx_clk_divider("clk48m", "spll", CCM_CSCR, 26, 3);
clk[per1] = imx_clk_divider("per1", "spll", CCM_PCDR, 0, 4);
clk[per2] = imx_clk_divider("per2", "spll", CCM_PCDR, 4, 4);
clk[per3] = imx_clk_divider("per3", "spll", CCM_PCDR, 16, 7);
clk[clko] = imx_clk_mux("clko", CCM_CSCR, 29, 3, clko_sel_clks,
ARRAY_SIZE(clko_sel_clks));
clk[dma_gate] = imx_clk_gate("dma_gate", "hclk", SCM_GCCR, 4);
clk[csi_gate] = imx_clk_gate("csi_gate", "hclk", SCM_GCCR, 2);
clk[mma_gate] = imx_clk_gate("mma_gate", "hclk", SCM_GCCR, 1);
clk[usbd_gate] = imx_clk_gate("usbd_gate", "clk48m", SCM_GCCR, 0);
for (i = 0; i < ARRAY_SIZE(clk); i++)
if (IS_ERR(clk[i]))
pr_err("imx1 clk %d: register failed with %ld\n",
i, PTR_ERR(clk[i]));
clk_register_clkdev(clk[dma_gate], "ahb", "imx-dma");
clk_register_clkdev(clk[csi_gate], NULL, "mx1-camera.0");
clk_register_clkdev(clk[mma_gate], "mma", NULL);
clk_register_clkdev(clk[usbd_gate], NULL, "imx_udc.0");
clk_register_clkdev(clk[per1], "per", "imx-gpt.0");
clk_register_clkdev(clk[hclk], "ipg", "imx-gpt.0");
clk_register_clkdev(clk[per1], "per", "imx1-uart.0");
clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.0");
clk_register_clkdev(clk[per1], "per", "imx1-uart.1");
clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.1");
clk_register_clkdev(clk[per1], "per", "imx1-uart.2");
clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.2");
clk_register_clkdev(clk[hclk], NULL, "imx-i2c.0");
clk_register_clkdev(clk[per2], "per", "imx1-cspi.0");
clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.0");
clk_register_clkdev(clk[per2], "per", "imx1-cspi.1");
clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.1");
clk_register_clkdev(clk[per2], NULL, "imx-mmc.0");
clk_register_clkdev(clk[per2], "per", "imx-fb.0");
clk_register_clkdev(clk[dummy], "ipg", "imx-fb.0");
clk_register_clkdev(clk[dummy], "ahb", "imx-fb.0");
clk_register_clkdev(clk[hclk], "mshc", NULL);
clk_register_clkdev(clk[per3], "ssi", NULL);
clk_register_clkdev(clk[clk32], NULL, "mxc_rtc.0");
clk_register_clkdev(clk[clko], "clko", NULL);
mxc_timer_init(NULL, MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR),
MX1_TIM1_INT);
return 0;
}
/*
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
* Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com
*
* 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/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include "clk.h"
#define IO_ADDR_CCM(off) (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
/* Register offsets */
#define CCM_CSCR IO_ADDR_CCM(0x0)
#define CCM_MPCTL0 IO_ADDR_CCM(0x4)
#define CCM_MPCTL1 IO_ADDR_CCM(0x8)
#define CCM_SPCTL0 IO_ADDR_CCM(0xc)
#define CCM_SPCTL1 IO_ADDR_CCM(0x10)
#define CCM_OSC26MCTL IO_ADDR_CCM(0x14)
#define CCM_PCDR0 IO_ADDR_CCM(0x18)
#define CCM_PCDR1 IO_ADDR_CCM(0x1c)
#define CCM_PCCR0 IO_ADDR_CCM(0x20)
#define CCM_PCCR1 IO_ADDR_CCM(0x24)
#define CCM_CCSR IO_ADDR_CCM(0x28)
#define CCM_PMCTL IO_ADDR_CCM(0x2c)
#define CCM_PMCOUNT IO_ADDR_CCM(0x30)
#define CCM_WKGDCTL IO_ADDR_CCM(0x34)
static const char *mpll_sel_clks[] = { "fpm", "ckih", };
static const char *spll_sel_clks[] = { "fpm", "ckih", };
enum imx21_clks {
ckil, ckih, fpm, mpll_sel, spll_sel, mpll, spll, fclk, hclk, ipg, per1,
per2, per3, per4, uart1_ipg_gate, uart2_ipg_gate, uart3_ipg_gate,
uart4_ipg_gate, gpt1_ipg_gate, gpt2_ipg_gate, gpt3_ipg_gate,
pwm_ipg_gate, sdhc1_ipg_gate, sdhc2_ipg_gate, lcdc_ipg_gate,
lcdc_hclk_gate, cspi3_ipg_gate, cspi2_ipg_gate, cspi1_ipg_gate,
per4_gate, csi_hclk_gate, usb_div, usb_gate, usb_hclk_gate, ssi1_gate,
ssi2_gate, nfc_div, nfc_gate, dma_gate, dma_hclk_gate, brom_gate,
emma_gate, emma_hclk_gate, slcdc_gate, slcdc_hclk_gate, wdog_gate,
gpio_gate, i2c_gate, kpp_gate, owire_gate, rtc_gate, clk_max
};
static struct clk *clk[clk_max];
/*
* must be called very early to get information about the
* available clock rate when the timer framework starts
*/
int __init mx21_clocks_init(unsigned long lref, unsigned long href)
{
int i;
clk[ckil] = imx_clk_fixed("ckil", lref);
clk[ckih] = imx_clk_fixed("ckih", href);
clk[fpm] = imx_clk_fixed_factor("fpm", "ckil", 512, 1);
clk[mpll_sel] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks,
ARRAY_SIZE(mpll_sel_clks));
clk[spll_sel] = imx_clk_mux("spll_sel", CCM_CSCR, 17, 1, spll_sel_clks,
ARRAY_SIZE(spll_sel_clks));
clk[mpll] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
clk[spll] = imx_clk_pllv1("spll", "spll_sel", CCM_SPCTL0);
clk[fclk] = imx_clk_divider("fclk", "mpll", CCM_CSCR, 29, 3);
clk[hclk] = imx_clk_divider("hclk", "fclk", CCM_CSCR, 10, 4);
clk[ipg] = imx_clk_divider("ipg", "hclk", CCM_CSCR, 9, 1);
clk[per1] = imx_clk_divider("per1", "mpll", CCM_PCDR1, 0, 6);
clk[per2] = imx_clk_divider("per2", "mpll", CCM_PCDR1, 8, 6);
clk[per3] = imx_clk_divider("per3", "mpll", CCM_PCDR1, 16, 6);
clk[per4] = imx_clk_divider("per4", "mpll", CCM_PCDR1, 24, 6);
clk[uart1_ipg_gate] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR0, 0);
clk[uart2_ipg_gate] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR0, 1);
clk[uart3_ipg_gate] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR0, 2);
clk[uart4_ipg_gate] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR0, 3);
clk[gpt1_ipg_gate] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR1, 25);
clk[gpt2_ipg_gate] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR1, 26);
clk[gpt3_ipg_gate] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR1, 27);
clk[pwm_ipg_gate] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR1, 28);
clk[sdhc1_ipg_gate] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 9);
clk[sdhc2_ipg_gate] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 10);
clk[lcdc_ipg_gate] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 18);
clk[lcdc_hclk_gate] = imx_clk_gate("lcdc_hclk_gate", "hclk", CCM_PCCR0, 26);
clk[cspi3_ipg_gate] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR1, 23);
clk[cspi2_ipg_gate] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 5);
clk[cspi1_ipg_gate] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 4);
clk[per4_gate] = imx_clk_gate("per4_gate", "per4", CCM_PCCR0, 22);
clk[csi_hclk_gate] = imx_clk_gate("csi_hclk_gate", "hclk", CCM_PCCR0, 31);
clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 26, 3);
clk[usb_gate] = imx_clk_gate("usb_gate", "usb_div", CCM_PCCR0, 14);
clk[usb_hclk_gate] = imx_clk_gate("usb_hclk_gate", "hclk", CCM_PCCR0, 24);
clk[ssi1_gate] = imx_clk_gate("ssi1_gate", "ipg", CCM_PCCR0, 6);
clk[ssi2_gate] = imx_clk_gate("ssi2_gate", "ipg", CCM_PCCR0, 7);
clk[nfc_div] = imx_clk_divider("nfc_div", "ipg", CCM_PCDR0, 12, 4);
clk[nfc_gate] = imx_clk_gate("nfc_gate", "nfc_div", CCM_PCCR0, 19);
clk[dma_gate] = imx_clk_gate("dma_gate", "ipg", CCM_PCCR0, 13);
clk[dma_hclk_gate] = imx_clk_gate("dma_hclk_gate", "hclk", CCM_PCCR0, 30);
clk[brom_gate] = imx_clk_gate("brom_gate", "hclk", CCM_PCCR0, 28);
clk[emma_gate] = imx_clk_gate("emma_gate", "ipg", CCM_PCCR0, 15);
clk[emma_hclk_gate] = imx_clk_gate("emma_hclk_gate", "hclk", CCM_PCCR0, 27);
clk[slcdc_gate] = imx_clk_gate("slcdc_gate", "ipg", CCM_PCCR0, 25);
clk[slcdc_hclk_gate] = imx_clk_gate("slcdc_hclk_gate", "hclk", CCM_PCCR0, 21);
clk[wdog_gate] = imx_clk_gate("wdog_gate", "ipg", CCM_PCCR1, 24);
clk[gpio_gate] = imx_clk_gate("gpio_gate", "ipg", CCM_PCCR0, 11);
clk[i2c_gate] = imx_clk_gate("i2c_gate", "ipg", CCM_PCCR0, 12);
clk[kpp_gate] = imx_clk_gate("kpp_gate", "ipg", CCM_PCCR1, 30);
clk[owire_gate] = imx_clk_gate("owire_gate", "ipg", CCM_PCCR1, 31);
clk[rtc_gate] = imx_clk_gate("rtc_gate", "ipg", CCM_PCCR1, 29);
for (i = 0; i < ARRAY_SIZE(clk); i++)
if (IS_ERR(clk[i]))
pr_err("i.MX21 clk %d: register failed with %ld\n",
i, PTR_ERR(clk[i]));
clk_register_clkdev(clk[per1], "per1", NULL);
clk_register_clkdev(clk[per2], "per2", NULL);
clk_register_clkdev(clk[per3], "per3", NULL);
clk_register_clkdev(clk[per4], "per4", NULL);
clk_register_clkdev(clk[per1], "per", "imx21-uart.0");
clk_register_clkdev(clk[uart1_ipg_gate], "ipg", "imx21-uart.0");
clk_register_clkdev(clk[per1], "per", "imx21-uart.1");
clk_register_clkdev(clk[uart2_ipg_gate], "ipg", "imx21-uart.1");
clk_register_clkdev(clk[per1], "per", "imx21-uart.2");
clk_register_clkdev(clk[uart3_ipg_gate], "ipg", "imx21-uart.2");
clk_register_clkdev(clk[per1], "per", "imx21-uart.3");
clk_register_clkdev(clk[uart4_ipg_gate], "ipg", "imx21-uart.3");
clk_register_clkdev(clk[gpt1_ipg_gate], "ipg", "imx-gpt.0");
clk_register_clkdev(clk[per1], "per", "imx-gpt.0");
clk_register_clkdev(clk[gpt2_ipg_gate], "ipg", "imx-gpt.1");
clk_register_clkdev(clk[per1], "per", "imx-gpt.1");
clk_register_clkdev(clk[gpt3_ipg_gate], "ipg", "imx-gpt.2");
clk_register_clkdev(clk[per1], "per", "imx-gpt.2");
clk_register_clkdev(clk[pwm_ipg_gate], "pwm", "mxc_pwm.0");
clk_register_clkdev(clk[per2], "per", "imx21-cspi.0");
clk_register_clkdev(clk[cspi1_ipg_gate], "ipg", "imx21-cspi.0");
clk_register_clkdev(clk[per2], "per", "imx21-cspi.1");
clk_register_clkdev(clk[cspi2_ipg_gate], "ipg", "imx21-cspi.1");
clk_register_clkdev(clk[per2], "per", "imx21-cspi.2");
clk_register_clkdev(clk[cspi3_ipg_gate], "ipg", "imx21-cspi.2");
clk_register_clkdev(clk[per3], "per", "imx-fb.0");
clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx-fb.0");
clk_register_clkdev(clk[lcdc_hclk_gate], "ahb", "imx-fb.0");
clk_register_clkdev(clk[usb_gate], "per", "imx21-hcd.0");
clk_register_clkdev(clk[usb_hclk_gate], "ahb", "imx21-hcd.0");
clk_register_clkdev(clk[nfc_gate], NULL, "mxc_nand.0");
clk_register_clkdev(clk[dma_hclk_gate], "ahb", "imx-dma");
clk_register_clkdev(clk[dma_gate], "ipg", "imx-dma");
clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
clk_register_clkdev(clk[i2c_gate], NULL, "imx-i2c.0");
clk_register_clkdev(clk[kpp_gate], NULL, "mxc-keypad");
clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1.0");
clk_register_clkdev(clk[brom_gate], "brom", NULL);
clk_register_clkdev(clk[emma_gate], "emma", NULL);
clk_register_clkdev(clk[slcdc_gate], "slcdc", NULL);
clk_register_clkdev(clk[gpio_gate], "gpio", NULL);
clk_register_clkdev(clk[rtc_gate], "rtc", NULL);
clk_register_clkdev(clk[csi_hclk_gate], "csi", NULL);
clk_register_clkdev(clk[ssi1_gate], "ssi1", NULL);
clk_register_clkdev(clk[ssi2_gate], "ssi2", NULL);
clk_register_clkdev(clk[sdhc1_ipg_gate], "sdhc1", NULL);
clk_register_clkdev(clk[sdhc2_ipg_gate], "sdhc2", NULL);
mxc_timer_init(NULL, MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR),
MX21_INT_GPT1);
return 0;
}
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (C) 2012 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.
*/
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/err.h>
#include <mach/hardware.h>
#include <mach/mx31.h>
#include <mach/common.h>
#include "clk.h"
#include "crmregs-imx3.h"
static const char *mcu_main_sel[] = { "spll", "mpll", };
static const char *per_sel[] = { "per_div", "ipg", };
static const char *csi_sel[] = { "upll", "spll", };
static const char *fir_sel[] = { "mcu_main", "upll", "spll" };
enum mx31_clks {
ckih, ckil, mpll, spll, upll, mcu_main, hsp, ahb, nfc, ipg, per_div,
per, csi, fir, csi_div, usb_div_pre, usb_div_post, fir_div_pre,
fir_div_post, sdhc1_gate, sdhc2_gate, gpt_gate, epit1_gate, epit2_gate,
iim_gate, ata_gate, sdma_gate, cspi3_gate, rng_gate, uart1_gate,
uart2_gate, ssi1_gate, i2c1_gate, i2c2_gate, i2c3_gate, hantro_gate,
mstick1_gate, mstick2_gate, csi_gate, rtc_gate, wdog_gate, pwm_gate,
sim_gate, ect_gate, usb_gate, kpp_gate, ipu_gate, uart3_gate,
uart4_gate, uart5_gate, owire_gate, ssi2_gate, cspi1_gate, cspi2_gate,
gacc_gate, emi_gate, rtic_gate, firi_gate, clk_max
};
static struct clk *clk[clk_max];
int __init mx31_clocks_init(unsigned long fref)
{
void __iomem *base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR);
int i;
clk[ckih] = imx_clk_fixed("ckih", fref);
clk[ckil] = imx_clk_fixed("ckil", 32768);
clk[mpll] = imx_clk_pllv1("mpll", "ckih", base + MXC_CCM_MPCTL);
clk[spll] = imx_clk_pllv1("spll", "ckih", base + MXC_CCM_SRPCTL);
clk[upll] = imx_clk_pllv1("upll", "ckih", base + MXC_CCM_UPCTL);
clk[mcu_main] = imx_clk_mux("mcu_main", base + MXC_CCM_PMCR0, 31, 1, mcu_main_sel, ARRAY_SIZE(mcu_main_sel));
clk[hsp] = imx_clk_divider("hsp", "mcu_main", base + MXC_CCM_PDR0, 11, 3);
clk[ahb] = imx_clk_divider("ahb", "mcu_main", base + MXC_CCM_PDR0, 3, 3);
clk[nfc] = imx_clk_divider("nfc", "ahb", base + MXC_CCM_PDR0, 8, 3);
clk[ipg] = imx_clk_divider("ipg", "ahb", base + MXC_CCM_PDR0, 6, 2);
clk[per_div] = imx_clk_divider("per_div", "upll", base + MXC_CCM_PDR0, 16, 5);
clk[per] = imx_clk_mux("per", base + MXC_CCM_CCMR, 24, 1, per_sel, ARRAY_SIZE(per_sel));
clk[csi] = imx_clk_mux("csi_sel", base + MXC_CCM_CCMR, 25, 1, csi_sel, ARRAY_SIZE(csi_sel));
clk[fir] = imx_clk_mux("fir_sel", base + MXC_CCM_CCMR, 11, 2, fir_sel, ARRAY_SIZE(fir_sel));
clk[csi_div] = imx_clk_divider("csi_div", "csi_sel", base + MXC_CCM_PDR0, 23, 9);
clk[usb_div_pre] = imx_clk_divider("usb_div_pre", "upll", base + MXC_CCM_PDR1, 30, 2);
clk[usb_div_post] = imx_clk_divider("usb_div_post", "usb_div_pre", base + MXC_CCM_PDR1, 27, 3);
clk[fir_div_pre] = imx_clk_divider("fir_div_pre", "fir_sel", base + MXC_CCM_PDR1, 24, 3);
clk[fir_div_post] = imx_clk_divider("fir_div_post", "fir_div_pre", base + MXC_CCM_PDR1, 23, 6);
clk[sdhc1_gate] = imx_clk_gate2("sdhc1_gate", "per", base + MXC_CCM_CGR0, 0);
clk[sdhc2_gate] = imx_clk_gate2("sdhc2_gate", "per", base + MXC_CCM_CGR0, 2);
clk[gpt_gate] = imx_clk_gate2("gpt_gate", "per", base + MXC_CCM_CGR0, 4);
clk[epit1_gate] = imx_clk_gate2("epit1_gate", "per", base + MXC_CCM_CGR0, 6);
clk[epit2_gate] = imx_clk_gate2("epit2_gate", "per", base + MXC_CCM_CGR0, 8);
clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", base + MXC_CCM_CGR0, 10);
clk[ata_gate] = imx_clk_gate2("ata_gate", "ipg", base + MXC_CCM_CGR0, 12);
clk[sdma_gate] = imx_clk_gate2("sdma_gate", "ahb", base + MXC_CCM_CGR0, 14);
clk[cspi3_gate] = imx_clk_gate2("cspi3_gate", "ipg", base + MXC_CCM_CGR0, 16);
clk[rng_gate] = imx_clk_gate2("rng_gate", "ipg", base + MXC_CCM_CGR0, 18);
clk[uart1_gate] = imx_clk_gate2("uart1_gate", "per", base + MXC_CCM_CGR0, 20);
clk[uart2_gate] = imx_clk_gate2("uart2_gate", "per", base + MXC_CCM_CGR0, 22);
clk[ssi1_gate] = imx_clk_gate2("ssi1_gate", "spll", base + MXC_CCM_CGR0, 24);
clk[i2c1_gate] = imx_clk_gate2("i2c1_gate", "per", base + MXC_CCM_CGR0, 26);
clk[i2c2_gate] = imx_clk_gate2("i2c2_gate", "per", base + MXC_CCM_CGR0, 28);
clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per", base + MXC_CCM_CGR0, 30);
clk[hantro_gate] = imx_clk_gate2("hantro_gate", "per", base + MXC_CCM_CGR1, 0);
clk[mstick1_gate] = imx_clk_gate2("mstick1_gate", "per", base + MXC_CCM_CGR1, 2);
clk[mstick2_gate] = imx_clk_gate2("mstick2_gate", "per", base + MXC_CCM_CGR1, 4);
clk[csi_gate] = imx_clk_gate2("csi_gate", "csi_div", base + MXC_CCM_CGR1, 6);
clk[rtc_gate] = imx_clk_gate2("rtc_gate", "ipg", base + MXC_CCM_CGR1, 8);
clk[wdog_gate] = imx_clk_gate2("wdog_gate", "ipg", base + MXC_CCM_CGR1, 10);
clk[pwm_gate] = imx_clk_gate2("pwm_gate", "per", base + MXC_CCM_CGR1, 12);
clk[sim_gate] = imx_clk_gate2("sim_gate", "per", base + MXC_CCM_CGR1, 14);
clk[ect_gate] = imx_clk_gate2("ect_gate", "per", base + MXC_CCM_CGR1, 16);
clk[usb_gate] = imx_clk_gate2("usb_gate", "ahb", base + MXC_CCM_CGR1, 18);
clk[kpp_gate] = imx_clk_gate2("kpp_gate", "ipg", base + MXC_CCM_CGR1, 20);
clk[ipu_gate] = imx_clk_gate2("ipu_gate", "hsp", base + MXC_CCM_CGR1, 22);
clk[uart3_gate] = imx_clk_gate2("uart3_gate", "per", base + MXC_CCM_CGR1, 24);
clk[uart4_gate] = imx_clk_gate2("uart4_gate", "per", base + MXC_CCM_CGR1, 26);
clk[uart5_gate] = imx_clk_gate2("uart5_gate", "per", base + MXC_CCM_CGR1, 28);
clk[owire_gate] = imx_clk_gate2("owire_gate", "per", base + MXC_CCM_CGR1, 30);
clk[ssi2_gate] = imx_clk_gate2("ssi2_gate", "spll", base + MXC_CCM_CGR2, 0);
clk[cspi1_gate] = imx_clk_gate2("cspi1_gate", "ipg", base + MXC_CCM_CGR2, 2);
clk[cspi2_gate] = imx_clk_gate2("cspi2_gate", "ipg", base + MXC_CCM_CGR2, 4);
clk[gacc_gate] = imx_clk_gate2("gacc_gate", "per", base + MXC_CCM_CGR2, 6);
clk[emi_gate] = imx_clk_gate2("emi_gate", "ahb", base + MXC_CCM_CGR2, 8);
clk[rtic_gate] = imx_clk_gate2("rtic_gate", "ahb", base + MXC_CCM_CGR2, 10);
clk[firi_gate] = imx_clk_gate2("firi_gate", "upll", base+MXC_CCM_CGR2, 12);
for (i = 0; i < ARRAY_SIZE(clk); i++)
if (IS_ERR(clk[i]))
pr_err("imx31 clk %d: register failed with %ld\n",
i, PTR_ERR(clk[i]));
clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
clk_register_clkdev(clk[cspi1_gate], NULL, "imx31-cspi.0");
clk_register_clkdev(clk[cspi2_gate], NULL, "imx31-cspi.1");
clk_register_clkdev(clk[cspi3_gate], NULL, "imx31-cspi.2");
clk_register_clkdev(clk[pwm_gate], "pwm", NULL);
clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
clk_register_clkdev(clk[rtc_gate], "rtc", NULL);
clk_register_clkdev(clk[epit1_gate], "epit", NULL);
clk_register_clkdev(clk[epit2_gate], "epit", NULL);
clk_register_clkdev(clk[nfc], NULL, "mxc_nand.0");
clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core");
clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb");
clk_register_clkdev(clk[kpp_gate], "kpp", NULL);
clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.0");
clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.0");
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0");
clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.1");
clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.1");
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.1");
clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.2");
clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.2");
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
clk_register_clkdev(clk[usb_div_post], "per", "fsl-usb2-udc");
clk_register_clkdev(clk[usb_gate], "ahb", "fsl-usb2-udc");
clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
/* i.mx31 has the i.mx21 type uart */
clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0");
clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.0");
clk_register_clkdev(clk[uart2_gate], "per", "imx21-uart.1");
clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.1");
clk_register_clkdev(clk[uart3_gate], "per", "imx21-uart.2");
clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.2");
clk_register_clkdev(clk[uart4_gate], "per", "imx21-uart.3");
clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.3");
clk_register_clkdev(clk[uart5_gate], "per", "imx21-uart.4");
clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.4");
clk_register_clkdev(clk[i2c1_gate], NULL, "imx-i2c.0");
clk_register_clkdev(clk[i2c2_gate], NULL, "imx-i2c.1");
clk_register_clkdev(clk[i2c3_gate], NULL, "imx-i2c.2");
clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1.0");
clk_register_clkdev(clk[sdhc1_gate], NULL, "mxc-mmc.0");
clk_register_clkdev(clk[sdhc2_gate], NULL, "mxc-mmc.1");
clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0");
clk_register_clkdev(clk[ssi2_gate], NULL, "imx-ssi.1");
clk_register_clkdev(clk[firi_gate], "firi", NULL);
clk_register_clkdev(clk[ata_gate], NULL, "pata_imx");
clk_register_clkdev(clk[rtic_gate], "rtic", NULL);
clk_register_clkdev(clk[rng_gate], "rng", NULL);
clk_register_clkdev(clk[sdma_gate], NULL, "imx31-sdma");
clk_register_clkdev(clk[iim_gate], "iim", NULL);
clk_set_parent(clk[csi], clk[upll]);
clk_prepare_enable(clk[emi_gate]);
clk_prepare_enable(clk[iim_gate]);
mx31_revision();
clk_disable_unprepare(clk[iim_gate]);
mxc_timer_init(NULL, MX31_IO_ADDRESS(MX31_GPT1_BASE_ADDR),
MX31_INT_GPT);
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright 2012 Freescale Semiconductor, Inc.
* Copyright 2012 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/err.h>
#include "clk.h"
/**
* struct clk_pfd - IMX PFD clock
* @clk_hw: clock source
* @reg: PFD register address
* @idx: the index of PFD encoded in the register
*
* PFD clock found on i.MX6 series. Each register for PFD has 4 clk_pfd
* data encoded, and member idx is used to specify the one. And each
* register has SET, CLR and TOG registers at offset 0x4 0x8 and 0xc.
*/
struct clk_pfd {
struct clk_hw hw;
void __iomem *reg;
u8 idx;
};
#define to_clk_pfd(_hw) container_of(_hw, struct clk_pfd, hw)
#define SET 0x4
#define CLR 0x8
#define OTG 0xc
static int clk_pfd_enable(struct clk_hw *hw)
{
struct clk_pfd *pfd = to_clk_pfd(hw);
writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + CLR);
return 0;
}
static void clk_pfd_disable(struct clk_hw *hw)
{
struct clk_pfd *pfd = to_clk_pfd(hw);
writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + SET);
}
static unsigned long clk_pfd_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pfd *pfd = to_clk_pfd(hw);
u64 tmp = parent_rate;
u8 frac = (readl_relaxed(pfd->reg) >> (pfd->idx * 8)) & 0x3f;
tmp *= 18;
do_div(tmp, frac);
return tmp;
}
static long clk_pfd_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
u64 tmp = *prate;
u8 frac;
tmp = tmp * 18 + rate / 2;
do_div(tmp, rate);
frac = tmp;
if (frac < 12)
frac = 12;
else if (frac > 35)
frac = 35;
tmp = *prate;
tmp *= 18;
do_div(tmp, frac);
return tmp;
}
static int clk_pfd_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_pfd *pfd = to_clk_pfd(hw);
u64 tmp = parent_rate;
u8 frac;
tmp = tmp * 18 + rate / 2;
do_div(tmp, rate);
frac = tmp;
if (frac < 12)
frac = 12;
else if (frac > 35)
frac = 35;
writel_relaxed(0x3f << (pfd->idx * 8), pfd->reg + CLR);
writel_relaxed(frac << (pfd->idx * 8), pfd->reg + SET);
return 0;
}
static const struct clk_ops clk_pfd_ops = {
.enable = clk_pfd_enable,
.disable = clk_pfd_disable,
.recalc_rate = clk_pfd_recalc_rate,
.round_rate = clk_pfd_round_rate,
.set_rate = clk_pfd_set_rate,
};
struct clk *imx_clk_pfd(const char *name, const char *parent_name,
void __iomem *reg, u8 idx)
{
struct clk_pfd *pfd;
struct clk *clk;
struct clk_init_data init;
pfd = kzalloc(sizeof(*pfd), GFP_KERNEL);
if (!pfd)
return ERR_PTR(-ENOMEM);
pfd->reg = reg;
pfd->idx = idx;
init.name = name;
init.ops = &clk_pfd_ops;
init.flags = 0;
init.parent_names = &parent_name;
init.num_parents = 1;
pfd->hw.init = &init;
clk = clk_register(NULL, &pfd->hw);
if (IS_ERR(clk))
kfree(pfd);
return clk;
}
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <mach/common.h>
#include <mach/hardware.h>
#include <mach/clock.h>
#include "clk.h"
/**
* pll v1
*
* @clk_hw clock source
* @parent the parent clock name
* @base base address of pll registers
*
* PLL clock version 1, found on i.MX1/21/25/27/31/35
*/
struct clk_pllv1 {
struct clk_hw hw;
void __iomem *base;
};
#define to_clk_pllv1(clk) (container_of(clk, struct clk_pllv1, clk))
static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pllv1 *pll = to_clk_pllv1(hw);
return mxc_decode_pll(readl(pll->base), parent_rate);
}
struct clk_ops clk_pllv1_ops = {
.recalc_rate = clk_pllv1_recalc_rate,
};
struct clk *imx_clk_pllv1(const char *name, const char *parent,
void __iomem *base)
{
struct clk_pllv1 *pll;
struct clk *clk;
struct clk_init_data init;
pll = kmalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
pll->base = base;
init.name = name;
init.ops = &clk_pllv1_ops;
init.flags = 0;
init.parent_names = &parent;
init.num_parents = 1;
pll->hw.init = &init;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk))
kfree(pll);
return clk;
}
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <asm/div64.h>
#include "clk.h"
#define to_clk_pllv2(clk) (container_of(clk, struct clk_pllv2, clk))
/* PLL Register Offsets */
#define MXC_PLL_DP_CTL 0x00
#define MXC_PLL_DP_CONFIG 0x04
#define MXC_PLL_DP_OP 0x08
#define MXC_PLL_DP_MFD 0x0C
#define MXC_PLL_DP_MFN 0x10
#define MXC_PLL_DP_MFNMINUS 0x14
#define MXC_PLL_DP_MFNPLUS 0x18
#define MXC_PLL_DP_HFS_OP 0x1C
#define MXC_PLL_DP_HFS_MFD 0x20
#define MXC_PLL_DP_HFS_MFN 0x24
#define MXC_PLL_DP_MFN_TOGC 0x28
#define MXC_PLL_DP_DESTAT 0x2c
/* PLL Register Bit definitions */
#define MXC_PLL_DP_CTL_MUL_CTRL 0x2000
#define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000
#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12
#define MXC_PLL_DP_CTL_ADE 0x800
#define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400
#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8)
#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET 8
#define MXC_PLL_DP_CTL_HFSM 0x80
#define MXC_PLL_DP_CTL_PRE 0x40
#define MXC_PLL_DP_CTL_UPEN 0x20
#define MXC_PLL_DP_CTL_RST 0x10
#define MXC_PLL_DP_CTL_RCP 0x8
#define MXC_PLL_DP_CTL_PLM 0x4
#define MXC_PLL_DP_CTL_BRM0 0x2
#define MXC_PLL_DP_CTL_LRF 0x1
#define MXC_PLL_DP_CONFIG_BIST 0x8
#define MXC_PLL_DP_CONFIG_SJC_CE 0x4
#define MXC_PLL_DP_CONFIG_AREN 0x2
#define MXC_PLL_DP_CONFIG_LDREQ 0x1
#define MXC_PLL_DP_OP_MFI_OFFSET 4
#define MXC_PLL_DP_OP_MFI_MASK (0xF << 4)
#define MXC_PLL_DP_OP_PDF_OFFSET 0
#define MXC_PLL_DP_OP_PDF_MASK 0xF
#define MXC_PLL_DP_MFD_OFFSET 0
#define MXC_PLL_DP_MFD_MASK 0x07FFFFFF
#define MXC_PLL_DP_MFN_OFFSET 0x0
#define MXC_PLL_DP_MFN_MASK 0x07FFFFFF
#define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17)
#define MXC_PLL_DP_MFN_TOGC_TOG_EN (1 << 16)
#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0
#define MXC_PLL_DP_MFN_TOGC_CNT_MASK 0xFFFF
#define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31)
#define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF
#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
struct clk_pllv2 {
struct clk_hw hw;
void __iomem *base;
};
static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
void __iomem *pllbase;
s64 temp;
struct clk_pllv2 *pll = to_clk_pllv2(hw);
pllbase = pll->base;
dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
if (pll_hfsm == 0) {
dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
} else {
dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
}
pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
mfi = (mfi <= 5) ? 5 : mfi;
mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
/* Sign extend to 32-bits */
if (mfn >= 0x04000000) {
mfn |= 0xFC000000;
mfn_abs = -mfn;
}
ref_clk = 2 * parent_rate;
if (dbl != 0)
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_pllv2_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_pllv2 *pll = to_clk_pllv2(hw);
u32 reg;
void __iomem *pllbase;
long mfi, pdf, mfn, mfd = 999999;
s64 temp64;
unsigned long quad_parent_rate;
unsigned long pll_hfsm, dp_ctl;
pllbase = pll->base;
quad_parent_rate = 4 * parent_rate;
pdf = mfi = -1;
while (++pdf < 16 && mfi < 5)
mfi = rate * (pdf+1) / quad_parent_rate;
if (mfi > 15)
return -EINVAL;
pdf--;
temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
do_div(temp64, quad_parent_rate/1000000);
mfn = (long)temp64;
dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
/* use dpdck0_2 */
__raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
if (pll_hfsm == 0) {
reg = mfi << 4 | pdf;
__raw_writel(reg, pllbase + MXC_PLL_DP_OP);
__raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
__raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
} else {
reg = mfi << 4 | pdf;
__raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
__raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
__raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
}
return 0;
}
static long clk_pllv2_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
return rate;
}
static int clk_pllv2_prepare(struct clk_hw *hw)
{
struct clk_pllv2 *pll = to_clk_pllv2(hw);
u32 reg;
void __iomem *pllbase;
int i = 0;
pllbase = pll->base;
reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN;
__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
/* Wait for lock */
do {
reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
if (reg & MXC_PLL_DP_CTL_LRF)
break;
udelay(1);
} while (++i < MAX_DPLL_WAIT_TRIES);
if (i == MAX_DPLL_WAIT_TRIES) {
pr_err("MX5: pll locking failed\n");
return -EINVAL;
}
return 0;
}
static void clk_pllv2_unprepare(struct clk_hw *hw)
{
struct clk_pllv2 *pll = to_clk_pllv2(hw);
u32 reg;
void __iomem *pllbase;
pllbase = pll->base;
reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
}
struct clk_ops clk_pllv2_ops = {
.prepare = clk_pllv2_prepare,
.unprepare = clk_pllv2_unprepare,
.recalc_rate = clk_pllv2_recalc_rate,
.round_rate = clk_pllv2_round_rate,
.set_rate = clk_pllv2_set_rate,
};
struct clk *imx_clk_pllv2(const char *name, const char *parent,
void __iomem *base)
{
struct clk_pllv2 *pll;
struct clk *clk;
struct clk_init_data init;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
pll->base = base;
init.name = name;
init.ops = &clk_pllv2_ops;
init.flags = 0;
init.parent_names = &parent;
init.num_parents = 1;
pll->hw.init = &init;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk))
kfree(pll);
return clk;
}
/*
* Copyright 2012 Freescale Semiconductor, Inc.
* Copyright 2012 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/err.h>
#include "clk.h"
#define PLL_NUM_OFFSET 0x10
#define PLL_DENOM_OFFSET 0x20
#define BM_PLL_POWER (0x1 << 12)
#define BM_PLL_ENABLE (0x1 << 13)
#define BM_PLL_BYPASS (0x1 << 16)
#define BM_PLL_LOCK (0x1 << 31)
/**
* struct clk_pllv3 - IMX PLL clock version 3
* @clk_hw: clock source
* @base: base address of PLL registers
* @powerup_set: set POWER bit to power up the PLL
* @gate_mask: mask of gate bits
* @div_mask: mask of divider bits
*
* IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3
* is actually a multiplier, and always sits at bit 0.
*/
struct clk_pllv3 {
struct clk_hw hw;
void __iomem *base;
bool powerup_set;
u32 gate_mask;
u32 div_mask;
};
#define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
static int clk_pllv3_prepare(struct clk_hw *hw)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
unsigned long timeout = jiffies + msecs_to_jiffies(10);
u32 val;
val = readl_relaxed(pll->base);
val &= ~BM_PLL_BYPASS;
if (pll->powerup_set)
val |= BM_PLL_POWER;
else
val &= ~BM_PLL_POWER;
writel_relaxed(val, pll->base);
/* Wait for PLL to lock */
while (!(readl_relaxed(pll->base) & BM_PLL_LOCK))
if (time_after(jiffies, timeout))
return -ETIMEDOUT;
return 0;
}
static void clk_pllv3_unprepare(struct clk_hw *hw)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 val;
val = readl_relaxed(pll->base);
val |= BM_PLL_BYPASS;
if (pll->powerup_set)
val &= ~BM_PLL_POWER;
else
val |= BM_PLL_POWER;
writel_relaxed(val, pll->base);
}
static int clk_pllv3_enable(struct clk_hw *hw)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 val;
val = readl_relaxed(pll->base);
val |= pll->gate_mask;
writel_relaxed(val, pll->base);
return 0;
}
static void clk_pllv3_disable(struct clk_hw *hw)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 val;
val = readl_relaxed(pll->base);
val &= ~pll->gate_mask;
writel_relaxed(val, pll->base);
}
static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 div = readl_relaxed(pll->base) & pll->div_mask;
return (div == 1) ? parent_rate * 22 : parent_rate * 20;
}
static long clk_pllv3_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
unsigned long parent_rate = *prate;
return (rate >= parent_rate * 22) ? parent_rate * 22 :
parent_rate * 20;
}
static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 val, div;
if (rate == parent_rate * 22)
div = 1;
else if (rate == parent_rate * 20)
div = 0;
else
return -EINVAL;
val = readl_relaxed(pll->base);
val &= ~pll->div_mask;
val |= div;
writel_relaxed(val, pll->base);
return 0;
}
static const struct clk_ops clk_pllv3_ops = {
.prepare = clk_pllv3_prepare,
.unprepare = clk_pllv3_unprepare,
.enable = clk_pllv3_enable,
.disable = clk_pllv3_disable,
.recalc_rate = clk_pllv3_recalc_rate,
.round_rate = clk_pllv3_round_rate,
.set_rate = clk_pllv3_set_rate,
};
static unsigned long clk_pllv3_sys_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 div = readl_relaxed(pll->base) & pll->div_mask;
return parent_rate * div / 2;
}
static long clk_pllv3_sys_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
unsigned long parent_rate = *prate;
unsigned long min_rate = parent_rate * 54 / 2;
unsigned long max_rate = parent_rate * 108 / 2;
u32 div;
if (rate > max_rate)
rate = max_rate;
else if (rate < min_rate)
rate = min_rate;
div = rate * 2 / parent_rate;
return parent_rate * div / 2;
}
static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
unsigned long min_rate = parent_rate * 54 / 2;
unsigned long max_rate = parent_rate * 108 / 2;
u32 val, div;
if (rate < min_rate || rate > max_rate)
return -EINVAL;
div = rate * 2 / parent_rate;
val = readl_relaxed(pll->base);
val &= ~pll->div_mask;
val |= div;
writel_relaxed(val, pll->base);
return 0;
}
static const struct clk_ops clk_pllv3_sys_ops = {
.prepare = clk_pllv3_prepare,
.unprepare = clk_pllv3_unprepare,
.enable = clk_pllv3_enable,
.disable = clk_pllv3_disable,
.recalc_rate = clk_pllv3_sys_recalc_rate,
.round_rate = clk_pllv3_sys_round_rate,
.set_rate = clk_pllv3_sys_set_rate,
};
static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET);
u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET);
u32 div = readl_relaxed(pll->base) & pll->div_mask;
return (parent_rate * div) + ((parent_rate / mfd) * mfn);
}
static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
unsigned long parent_rate = *prate;
unsigned long min_rate = parent_rate * 27;
unsigned long max_rate = parent_rate * 54;
u32 div;
u32 mfn, mfd = 1000000;
s64 temp64;
if (rate > max_rate)
rate = max_rate;
else if (rate < min_rate)
rate = min_rate;
div = rate / parent_rate;
temp64 = (u64) (rate - div * parent_rate);
temp64 *= mfd;
do_div(temp64, parent_rate);
mfn = temp64;
return parent_rate * div + parent_rate / mfd * mfn;
}
static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
unsigned long min_rate = parent_rate * 27;
unsigned long max_rate = parent_rate * 54;
u32 val, div;
u32 mfn, mfd = 1000000;
s64 temp64;
if (rate < min_rate || rate > max_rate)
return -EINVAL;
div = rate / parent_rate;
temp64 = (u64) (rate - div * parent_rate);
temp64 *= mfd;
do_div(temp64, parent_rate);
mfn = temp64;
val = readl_relaxed(pll->base);
val &= ~pll->div_mask;
val |= div;
writel_relaxed(val, pll->base);
writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
return 0;
}
static const struct clk_ops clk_pllv3_av_ops = {
.prepare = clk_pllv3_prepare,
.unprepare = clk_pllv3_unprepare,
.enable = clk_pllv3_enable,
.disable = clk_pllv3_disable,
.recalc_rate = clk_pllv3_av_recalc_rate,
.round_rate = clk_pllv3_av_round_rate,
.set_rate = clk_pllv3_av_set_rate,
};
static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 div = readl_relaxed(pll->base) & pll->div_mask;
switch (div) {
case 0:
return 25000000;
case 1:
return 50000000;
case 2:
return 100000000;
case 3:
return 125000000;
}
return 0;
}
static long clk_pllv3_enet_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
if (rate >= 125000000)
rate = 125000000;
else if (rate >= 100000000)
rate = 100000000;
else if (rate >= 50000000)
rate = 50000000;
else
rate = 25000000;
return rate;
}
static int clk_pllv3_enet_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 val, div;
switch (rate) {
case 25000000:
div = 0;
break;
case 50000000:
div = 1;
break;
case 100000000:
div = 2;
break;
case 125000000:
div = 3;
break;
default:
return -EINVAL;
}
val = readl_relaxed(pll->base);
val &= ~pll->div_mask;
val |= div;
writel_relaxed(val, pll->base);
return 0;
}
static const struct clk_ops clk_pllv3_enet_ops = {
.prepare = clk_pllv3_prepare,
.unprepare = clk_pllv3_unprepare,
.enable = clk_pllv3_enable,
.disable = clk_pllv3_disable,
.recalc_rate = clk_pllv3_enet_recalc_rate,
.round_rate = clk_pllv3_enet_round_rate,
.set_rate = clk_pllv3_enet_set_rate,
};
static const struct clk_ops clk_pllv3_mlb_ops = {
.prepare = clk_pllv3_prepare,
.unprepare = clk_pllv3_unprepare,
.enable = clk_pllv3_enable,
.disable = clk_pllv3_disable,
};
struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
const char *parent_name, void __iomem *base,
u32 gate_mask, u32 div_mask)
{
struct clk_pllv3 *pll;
const struct clk_ops *ops;
struct clk *clk;
struct clk_init_data init;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
switch (type) {
case IMX_PLLV3_SYS:
ops = &clk_pllv3_sys_ops;
break;
case IMX_PLLV3_USB:
ops = &clk_pllv3_ops;
pll->powerup_set = true;
break;
case IMX_PLLV3_AV:
ops = &clk_pllv3_av_ops;
break;
case IMX_PLLV3_ENET:
ops = &clk_pllv3_enet_ops;
break;
case IMX_PLLV3_MLB:
ops = &clk_pllv3_mlb_ops;
break;
default:
ops = &clk_pllv3_ops;
}
pll->base = base;
pll->gate_mask = gate_mask;
pll->div_mask = div_mask;
init.name = name;
init.ops = ops;
init.flags = 0;
init.parent_names = &parent_name;
init.num_parents = 1;
pll->hw.init = &init;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk))
kfree(pll);
return clk;
}
#ifndef __MACH_IMX_CLK_H
#define __MACH_IMX_CLK_H
#include <linux/spinlock.h>
#include <linux/clk-provider.h>
#include <mach/clock.h>
struct clk *imx_clk_pllv1(const char *name, const char *parent,
void __iomem *base);
struct clk *imx_clk_pllv2(const char *name, const char *parent,
void __iomem *base);
enum imx_pllv3_type {
IMX_PLLV3_GENERIC,
IMX_PLLV3_SYS,
IMX_PLLV3_USB,
IMX_PLLV3_AV,
IMX_PLLV3_ENET,
IMX_PLLV3_MLB,
};
struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
const char *parent_name, void __iomem *base, u32 gate_mask,
u32 div_mask);
struct clk *clk_register_gate2(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 bit_idx,
u8 clk_gate_flags, spinlock_t *lock);
static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
void __iomem *reg, u8 shift)
{
return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
shift, 0, &imx_ccm_lock);
}
struct clk *imx_clk_pfd(const char *name, const char *parent_name,
void __iomem *reg, u8 idx);
struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
void __iomem *reg, u8 shift, u8 width,
void __iomem *busy_reg, u8 busy_shift);
struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
u8 width, void __iomem *busy_reg, u8 busy_shift,
const char **parent_names, int num_parents);
static inline struct clk *imx_clk_fixed(const char *name, int rate)
{
return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
}
static inline struct clk *imx_clk_divider(const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width)
{
return clk_register_divider(NULL, name, parent, CLK_SET_RATE_PARENT,
reg, shift, width, 0, &imx_ccm_lock);
}
static inline struct clk *imx_clk_gate(const char *name, const char *parent,
void __iomem *reg, u8 shift)
{
return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
shift, 0, &imx_ccm_lock);
}
static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
u8 shift, u8 width, const char **parents, int num_parents)
{
return clk_register_mux(NULL, name, parents, num_parents, 0, reg, shift,
width, 0, &imx_ccm_lock);
}
static inline struct clk *imx_clk_fixed_factor(const char *name,
const char *parent, unsigned int mult, unsigned int div)
{
return clk_register_fixed_factor(NULL, name, parent,
CLK_SET_RATE_PARENT, mult, div);
}
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -24,48 +24,47 @@
#define CKIH_CLK_FREQ_27MHZ 27000000
#define CKIL_CLK_FREQ 32768
#define MXC_CCM_BASE (cpu_is_mx31() ? \
MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR) : MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR))
extern void __iomem *mx3_ccm_base;
/* 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 MX35_CCM_PDR2 (MXC_CCM_BASE + 0x0C)
#define MXC_CCM_RCSR (MXC_CCM_BASE + 0x0C)
#define MX35_CCM_PDR3 (MXC_CCM_BASE + 0x10)
#define MXC_CCM_MPCTL (MXC_CCM_BASE + 0x10)
#define MX35_CCM_PDR4 (MXC_CCM_BASE + 0x14)
#define MXC_CCM_UPCTL (MXC_CCM_BASE + 0x14)
#define MX35_CCM_RCSR (MXC_CCM_BASE + 0x18)
#define MXC_CCM_SRPCTL (MXC_CCM_BASE + 0x18)
#define MX35_CCM_MPCTL (MXC_CCM_BASE + 0x1C)
#define MXC_CCM_COSR (MXC_CCM_BASE + 0x1C)
#define MX35_CCM_PPCTL (MXC_CCM_BASE + 0x20)
#define MXC_CCM_CGR0 (MXC_CCM_BASE + 0x20)
#define MX35_CCM_ACMR (MXC_CCM_BASE + 0x24)
#define MXC_CCM_CGR1 (MXC_CCM_BASE + 0x24)
#define MX35_CCM_COSR (MXC_CCM_BASE + 0x28)
#define MXC_CCM_CGR2 (MXC_CCM_BASE + 0x28)
#define MX35_CCM_CGR0 (MXC_CCM_BASE + 0x2C)
#define MXC_CCM_WIMR (MXC_CCM_BASE + 0x2C)
#define MX35_CCM_CGR1 (MXC_CCM_BASE + 0x30)
#define MXC_CCM_LDC (MXC_CCM_BASE + 0x30)
#define MX35_CCM_CGR2 (MXC_CCM_BASE + 0x34)
#define MXC_CCM_DCVR0 (MXC_CCM_BASE + 0x34)
#define MX35_CCM_CGR3 (MXC_CCM_BASE + 0x38)
#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)
#define MXC_CCM_CCMR 0x00
#define MXC_CCM_PDR0 0x04
#define MXC_CCM_PDR1 0x08
#define MX35_CCM_PDR2 0x0C
#define MXC_CCM_RCSR 0x0C
#define MX35_CCM_PDR3 0x10
#define MXC_CCM_MPCTL 0x10
#define MX35_CCM_PDR4 0x14
#define MXC_CCM_UPCTL 0x14
#define MX35_CCM_RCSR 0x18
#define MXC_CCM_SRPCTL 0x18
#define MX35_CCM_MPCTL 0x1C
#define MXC_CCM_COSR 0x1C
#define MX35_CCM_PPCTL 0x20
#define MXC_CCM_CGR0 0x20
#define MX35_CCM_ACMR 0x24
#define MXC_CCM_CGR1 0x24
#define MX35_CCM_COSR 0x28
#define MXC_CCM_CGR2 0x28
#define MX35_CCM_CGR0 0x2C
#define MXC_CCM_WIMR 0x2C
#define MX35_CCM_CGR1 0x30
#define MXC_CCM_LDC 0x30
#define MX35_CCM_CGR2 0x34
#define MXC_CCM_DCVR0 0x34
#define MX35_CCM_CGR3 0x38
#define MXC_CCM_DCVR1 0x38
#define MXC_CCM_DCVR2 0x3C
#define MXC_CCM_DCVR3 0x40
#define MXC_CCM_LTR0 0x44
#define MXC_CCM_LTR1 0x48
#define MXC_CCM_LTR2 0x4C
#define MXC_CCM_LTR3 0x50
#define MXC_CCM_LTBR0 0x54
#define MXC_CCM_LTBR1 0x58
#define MXC_CCM_PMCR0 0x5C
#define MXC_CCM_PMCR1 0x60
#define MXC_CCM_PDR2 0x64
/* Register bit definitions */
#define MXC_CCM_CCMR_WBEN (1 << 27)
......
......@@ -31,6 +31,10 @@
#include <mach/iomux-v3.h>
#include <mach/irqs.h>
#include "crmregs-imx3.h"
void __iomem *mx3_ccm_base;
static void imx3_idle(void)
{
unsigned long reg = 0;
......@@ -137,6 +141,7 @@ void __init imx31_init_early(void)
mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
arch_ioremap_caller = imx3_ioremap_caller;
arm_pm_idle = imx3_idle;
mx3_ccm_base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR);
}
void __init mx31_init_irq(void)
......@@ -210,6 +215,7 @@ void __init imx35_init_early(void)
mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
arm_pm_idle = imx3_idle;
arch_ioremap_caller = imx3_ioremap_caller;
mx3_ccm_base = MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR);
}
void __init mx35_init_irq(void)
......
......@@ -32,6 +32,7 @@ static void imx5_idle(void)
gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
if (IS_ERR(gpc_dvfs_clk))
return;
clk_prepare(gpc_dvfs_clk);
}
clk_enable(gpc_dvfs_clk);
mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
......
......@@ -21,14 +21,14 @@
*/
void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode)
{
int reg = __raw_readl(MXC_CCM_CCMR);
int reg = __raw_readl(mx3_ccm_base + MXC_CCM_CCMR);
reg &= ~MXC_CCM_CCMR_LPM_MASK;
switch (mode) {
case MX3_WAIT:
if (cpu_is_mx35())
reg |= MXC_CCM_CCMR_LPM_WAIT_MX35;
__raw_writel(reg, MXC_CCM_CCMR);
__raw_writel(reg, mx3_ccm_base + MXC_CCM_CCMR);
break;
default:
pr_err("Unknown cpu power mode: %d\n", mode);
......
......@@ -41,6 +41,7 @@
#include <mach/clock.h>
#include <mach/hardware.h>
#ifndef CONFIG_COMMON_CLK
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
......@@ -200,6 +201,16 @@ struct clk *clk_get_parent(struct clk *clk)
}
EXPORT_SYMBOL(clk_get_parent);
#else
/*
* Lock to protect the clock module (ccm) registers. Used
* on all i.MXs
*/
DEFINE_SPINLOCK(imx_ccm_lock);
#endif /* CONFIG_COMMON_CLK */
/*
* Get the resulting clock rate from a PLL register value and the input
* frequency. PLLs with this register layout can at least be found on
......
......@@ -23,6 +23,7 @@
#ifndef __ASSEMBLY__
#include <linux/list.h>
#ifndef CONFIG_COMMON_CLK
struct module;
struct clk {
......@@ -59,6 +60,9 @@ struct clk {
int clk_register(struct clk *clk);
void clk_unregister(struct clk *clk);
#endif /* CONFIG_COMMON_CLK */
extern spinlock_t imx_ccm_lock;
unsigned long mxc_decode_pll(unsigned int pll, u32 f_ref);
......
......@@ -25,6 +25,7 @@
#include <linux/irq.h>
#include <linux/clockchips.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <mach/hardware.h>
#include <asm/sched_clock.h>
......@@ -282,6 +283,19 @@ static int __init mxc_clockevent_init(struct clk *timer_clk)
void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
{
uint32_t tctl_val;
struct clk *timer_ipg_clk;
if (!timer_clk) {
timer_clk = clk_get_sys("imx-gpt.0", "per");
if (IS_ERR(timer_clk)) {
pr_err("i.MX timer: unable to get clk\n");
return;
}
timer_ipg_clk = clk_get_sys("imx-gpt.0", "ipg");
if (!IS_ERR(timer_ipg_clk))
clk_prepare_enable(timer_ipg_clk);
}
clk_prepare_enable(timer_clk);
......
......@@ -322,7 +322,8 @@ struct sdma_engine {
struct sdma_context_data *context;
dma_addr_t context_phys;
struct dma_device dma_device;
struct clk *clk;
struct clk *clk_ipg;
struct clk *clk_ahb;
struct mutex channel_0_lock;
struct sdma_script_start_addrs *script_addrs;
};
......@@ -859,7 +860,8 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
sdmac->peripheral_type = data->peripheral_type;
sdmac->event_id0 = data->dma_request;
clk_enable(sdmac->sdma->clk);
clk_enable(sdmac->sdma->clk_ipg);
clk_enable(sdmac->sdma->clk_ahb);
ret = sdma_request_channel(sdmac);
if (ret)
......@@ -896,7 +898,8 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);
clk_disable(sdma->clk);
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
}
static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
......@@ -1169,12 +1172,14 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
addr = (void *)header + header->script_addrs_start;
ram_code = (void *)header + header->ram_code_start;
clk_enable(sdma->clk);
clk_enable(sdma->clk_ipg);
clk_enable(sdma->clk_ahb);
/* download the RAM image for SDMA */
sdma_load_script(sdma, ram_code,
header->ram_code_size,
addr->ram_code_start_addr);
clk_disable(sdma->clk);
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
sdma_add_scripts(sdma, addr);
......@@ -1216,7 +1221,8 @@ static int __init sdma_init(struct sdma_engine *sdma)
return -ENODEV;
}
clk_enable(sdma->clk);
clk_enable(sdma->clk_ipg);
clk_enable(sdma->clk_ahb);
/* Be sure SDMA has not started yet */
writel_relaxed(0, sdma->regs + SDMA_H_C0PTR);
......@@ -1269,12 +1275,14 @@ static int __init sdma_init(struct sdma_engine *sdma)
/* Initializes channel's priorities */
sdma_set_channel_priority(&sdma->channel[0], 7);
clk_disable(sdma->clk);
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
return 0;
err_dma_alloc:
clk_disable(sdma->clk);
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
dev_err(sdma->dev, "initialisation failed with %d\n", ret);
return ret;
}
......@@ -1313,12 +1321,21 @@ static int __init sdma_probe(struct platform_device *pdev)
goto err_request_region;
}
sdma->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(sdma->clk)) {
ret = PTR_ERR(sdma->clk);
sdma->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(sdma->clk_ipg)) {
ret = PTR_ERR(sdma->clk_ipg);
goto err_clk;
}
sdma->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
if (IS_ERR(sdma->clk_ahb)) {
ret = PTR_ERR(sdma->clk_ahb);
goto err_clk;
}
clk_prepare(sdma->clk_ipg);
clk_prepare(sdma->clk_ahb);
sdma->regs = ioremap(iores->start, resource_size(iores));
if (!sdma->regs) {
ret = -ENOMEM;
......@@ -1426,7 +1443,6 @@ static int __init sdma_probe(struct platform_device *pdev)
err_request_irq:
iounmap(sdma->regs);
err_ioremap:
clk_put(sdma->clk);
err_clk:
release_mem_region(iores->start, resource_size(iores));
err_request_region:
......
......@@ -1715,7 +1715,7 @@ static int __init ipu_probe(struct platform_device *pdev)
}
/* Make sure IPU HSP clock is running */
clk_enable(ipu_data.ipu_clk);
clk_prepare_enable(ipu_data.ipu_clk);
/* Disable all interrupts */
idmac_write_ipureg(&ipu_data, 0, IPU_INT_CTRL_1);
......@@ -1747,7 +1747,7 @@ static int __init ipu_probe(struct platform_device *pdev)
err_idmac_init:
err_attach_irq:
ipu_irq_detach_irq(&ipu_data, pdev);
clk_disable(ipu_data.ipu_clk);
clk_disable_unprepare(ipu_data.ipu_clk);
clk_put(ipu_data.ipu_clk);
err_clk_get:
iounmap(ipu_data.reg_ic);
......@@ -1765,7 +1765,7 @@ static int __exit ipu_remove(struct platform_device *pdev)
ipu_idmac_exit(ipu);
ipu_irq_detach_irq(ipu, pdev);
clk_disable(ipu->ipu_clk);
clk_disable_unprepare(ipu->ipu_clk);
clk_put(ipu->ipu_clk);
iounmap(ipu->reg_ic);
iounmap(ipu->reg_ipu);
......
......@@ -508,7 +508,7 @@ static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam,
/* ipu_csi_init_interface() */
csi_reg_write(mx3_cam, conf, CSI_SENS_CONF);
clk_enable(mx3_cam->clk);
clk_prepare_enable(mx3_cam->clk);
rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk);
dev_dbg(icd->parent, "Set SENS_CONF to %x, rate %ld\n", conf, rate);
if (rate)
......@@ -549,7 +549,7 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd)
*ichan = NULL;
}
clk_disable(mx3_cam->clk);
clk_disable_unprepare(mx3_cam->clk);
mx3_cam->icd = NULL;
......
......@@ -136,7 +136,8 @@ struct mxcmci_host {
u16 rev_no;
unsigned int cmdat;
struct clk *clk;
struct clk *clk_ipg;
struct clk *clk_per;
int clock;
......@@ -672,7 +673,7 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
{
unsigned int divider;
int prescaler = 0;
unsigned int clk_in = clk_get_rate(host->clk);
unsigned int clk_in = clk_get_rate(host->clk_per);
while (prescaler <= 0x800) {
for (divider = 1; divider <= 0xF; divider++) {
......@@ -900,12 +901,20 @@ static int mxcmci_probe(struct platform_device *pdev)
host->res = r;
host->irq = irq;
host->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(host->clk)) {
ret = PTR_ERR(host->clk);
host->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(host->clk_ipg)) {
ret = PTR_ERR(host->clk_ipg);
goto out_iounmap;
}
clk_enable(host->clk);
host->clk_per = devm_clk_get(&pdev->dev, "per");
if (IS_ERR(host->clk_per)) {
ret = PTR_ERR(host->clk_per);
goto out_iounmap;
}
clk_prepare_enable(host->clk_per);
clk_prepare_enable(host->clk_ipg);
mxcmci_softreset(host);
......@@ -917,8 +926,8 @@ static int mxcmci_probe(struct platform_device *pdev)
goto out_clk_put;
}
mmc->f_min = clk_get_rate(host->clk) >> 16;
mmc->f_max = clk_get_rate(host->clk) >> 1;
mmc->f_min = clk_get_rate(host->clk_per) >> 16;
mmc->f_max = clk_get_rate(host->clk_per) >> 1;
/* recommended in data sheet */
writew(0x2db4, host->base + MMC_REG_READ_TO);
......@@ -967,8 +976,8 @@ static int mxcmci_probe(struct platform_device *pdev)
if (host->dma)
dma_release_channel(host->dma);
out_clk_put:
clk_disable(host->clk);
clk_put(host->clk);
clk_disable_unprepare(host->clk_per);
clk_disable_unprepare(host->clk_ipg);
out_iounmap:
iounmap(host->base);
out_free:
......@@ -999,8 +1008,8 @@ static int mxcmci_remove(struct platform_device *pdev)
if (host->dma)
dma_release_channel(host->dma);
clk_disable(host->clk);
clk_put(host->clk);
clk_disable_unprepare(host->clk_per);
clk_disable_unprepare(host->clk_ipg);
release_mem_region(host->res->start, resource_size(host->res));
......@@ -1018,7 +1027,8 @@ static int mxcmci_suspend(struct device *dev)
if (mmc)
ret = mmc_suspend_host(mmc);
clk_disable(host->clk);
clk_disable_unprepare(host->clk_per);
clk_disable_unprepare(host->clk_ipg);
return ret;
}
......@@ -1029,7 +1039,8 @@ static int mxcmci_resume(struct device *dev)
struct mxcmci_host *host = mmc_priv(mmc);
int ret = 0;
clk_enable(host->clk);
clk_prepare_enable(host->clk_per);
clk_prepare_enable(host->clk_ipg);
if (mmc)
ret = mmc_resume_host(mmc);
......
This diff is collapsed.
......@@ -690,7 +690,7 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
if (chip == -1) {
/* Disable the NFC clock */
if (host->clk_act) {
clk_disable(host->clk);
clk_disable_unprepare(host->clk);
host->clk_act = 0;
}
return;
......@@ -698,7 +698,7 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
if (!host->clk_act) {
/* Enable the NFC clock */
clk_enable(host->clk);
clk_prepare_enable(host->clk);
host->clk_act = 1;
}
......@@ -1078,7 +1078,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
goto eclk;
}
clk_enable(host->clk);
clk_prepare_enable(host->clk);
host->clk_act = 1;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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