arm-soc: clock driver changes

The new clock subsystem was merged in linux-3.4 without any users, this
 now moves the first three platforms over to it: imx, mxs and spear.
 
 The series also contains the changes for the clock subsystem itself,
 since Mike preferred to have it together with the platforms that require
 these changes, in order to avoid interdependencies and conflicts.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJPuexPAAoJEIwa5zzehBx3YBsP/0nFhXjb5t1PdLfFzGKtcZVB
 j4zXWXMHQ1fA7wIfEpZF3Nnco6MQkufF5wJPoPdn1+wmkzCn3D6IwNVWVtW4U5i9
 VGyShSbgusAAYXUe/9yYj8eN+bbRQSvdN4eWYWU6+rRXShGZ5dZZmp+IPNl54dnW
 6F8uCnHX0cnIMCpGqV+41zZgZ/4wL2k9gdqu0LO6pi07o4tGd0Z4gcySgUFAnn1R
 kofNHueYIP4UgOg8DREoBzVKlpRqMou3S2kSZUfMeb3Q9ryF7UIvaGqIILyi7PKL
 kWd3nptg0EPavfL21SwXHiGpnDpB/Gj/F70kcPLus5RYujB24C9bvBmc26z68NZx
 Sz9mbElkkIU5duZsl1nxBWJ8IZ/tSWdtmC2xQMznmV7gHyGgVwr4j47f4Uv5sBvM
 14JHDO7mqN6E6FnTFZu/oPAN5pDjgL+TVNK5BU6Wkq0zitrA6eyKDqCvBCqkO6Nn
 tNzOuyRDzMOwM7HzqXhxqtzJWXylO1Mldc4bM8X4Cocf4pnLna/X6uP6dgE6A+JY
 azVYx4I/0NdEPerDTzIcEhBDgZeBVROhUQr+kHxc4rf6WzUUbu/wEo1UKXWV66oW
 1jb1yAFFWqYjkQuQc2PD4JSx35sFJaoSaoneRtmzBzRDfzSr5KjKj1E0e1skyMFq
 7ZVLCqZD0cB9DhmMDkWP
 =rwFF
 -----END PGP SIGNATURE-----

Merge tag 'clock' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull arm-soc clock driver changes from Olof Johansson:
 "The new clock subsystem was merged in linux-3.4 without any users,
  this now moves the first three platforms over to it: imx, mxs and
  spear.

  The series also contains the changes for the clock subsystem itself,
  since Mike preferred to have it together with the platforms that
  require these changes, in order to avoid interdependencies and
  conflicts."

Fix up trivial conflicts in arch/arm/mach-kirkwood/common.c (code
removed in one branch, added OF support in another) and
drivers/dma/imx-sdma.c (independent changes next to each other).

* tag 'clock' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (97 commits)
  clk: Fix CLK_SET_RATE_GATE flag validation in clk_set_rate().
  clk: Provide dummy clk_unregister()
  SPEAr: Update defconfigs
  SPEAr: Add SMI NOR partition info in dts files
  SPEAr: Switch to common clock framework
  SPEAr: Call clk_prepare() before calling clk_enable
  SPEAr: clk: Add General Purpose Timer Synthesizer clock
  SPEAr: clk: Add Fractional Synthesizer clock
  SPEAr: clk: Add Auxiliary Synthesizer clock
  SPEAr: clk: Add VCO-PLL Synthesizer clock
  SPEAr: Add DT bindings for SPEAr's timer
  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: Kirkwood: Replace clock gating
  ARM: Orion: Audio: Add clk/clkdev support
  ARM: Orion: PCIE: Add support for clk
  ARM: Orion: XOR: Add support for clk
  ARM: Orion: CESA: Add support for clk
  ...
This commit is contained in:
Linus Torvalds 2012-05-26 12:42:29 -07:00
commit 2795343705
151 changed files with 8310 additions and 14193 deletions

View File

@ -0,0 +1,18 @@
* SPEAr ARM Timer
** Timer node required properties:
- compatible : Should be:
"st,spear-timer"
- reg: Address range of the timer registers
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupt: Should contain the timer interrupt number
Example:
timer@f0000000 {
compatible = "st,spear-timer";
reg = <0xf0000000 0x400>;
interrupts = <2>;
};

View File

@ -1905,6 +1905,16 @@ F: Documentation/filesystems/coda.txt
F: fs/coda/
F: include/linux/coda*.h
COMMON CLK FRAMEWORK
M: Mike Turquette <mturquette@ti.com>
M: Mike Turquette <mturquette@linaro.org>
L: linux-arm-kernel@lists.infradead.org (same as CLK API & CLKDEV)
T: git git://git.linaro.org/people/mturquette/linux.git
S: Maintained
F: drivers/clk/clk.c
F: drivers/clk/clk-*
F: include/linux/clk-pr*
COMMON INTERNET FILE SYSTEM (CIFS)
M: Steve French <sfrench@samba.org>
L: linux-cifs@vger.kernel.org
@ -6368,9 +6378,7 @@ L: spear-devel@list.st.com
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.st.com/spear
S: Maintained
F: arch/arm/mach-spear*/clock.c
F: arch/arm/plat-spear/clock.c
F: arch/arm/plat-spear/include/plat/clock.h
F: drivers/clk/spear/
SPI SUBSYSTEM
M: Grant Likely <grant.likely@secretlab.ca>

View File

@ -456,6 +456,7 @@ config ARCH_MXS
select ARCH_REQUIRE_GPIOLIB
select CLKDEV_LOOKUP
select CLKSRC_MMIO
select COMMON_CLK
select HAVE_CLK_PREPARE
select PINCTRL
help
@ -947,6 +948,7 @@ config PLAT_SPEAR
select ARM_AMBA
select ARCH_REQUIRE_GPIOLIB
select CLKDEV_LOOKUP
select COMMON_CLK
select CLKSRC_MMIO
select GENERIC_CLOCKEVENTS
select HAVE_CLK
@ -1101,6 +1103,7 @@ config PLAT_ORION
bool
select CLKSRC_MMIO
select GENERIC_IRQ_CHIP
select COMMON_CLK
config PLAT_PXA
bool

View File

@ -87,6 +87,31 @@ sdhci@70000000 {
smi: flash@fc000000 {
status = "okay";
clock-rate=<50000000>;
flash@f8000000 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0xf8000000 0x800000>;
st,smi-fast-mode;
partition@0 {
label = "xloader";
reg = <0x0 0x10000>;
};
partition@10000 {
label = "u-boot";
reg = <0x10000 0x40000>;
};
partition@50000 {
label = "linux";
reg = <0x50000 0x2c0000>;
};
partition@310000 {
label = "rootfs";
reg = <0x310000 0x4f0000>;
};
};
};
spi0: spi@d0100000 {

View File

@ -103,11 +103,27 @@ smi: flash@fc000000 {
clock-rate=<50000000>;
flash@f8000000 {
label = "m25p64";
reg = <0xf8000000 0x800000>;
#address-cells = <1>;
#size-cells = <1>;
reg = <0xf8000000 0x800000>;
st,smi-fast-mode;
partition@0 {
label = "xloader";
reg = <0x0 0x10000>;
};
partition@10000 {
label = "u-boot";
reg = <0x10000 0x40000>;
};
partition@50000 {
label = "linux";
reg = <0x50000 0x2c0000>;
};
partition@310000 {
label = "rootfs";
reg = <0x310000 0x4f0000>;
};
};
};

View File

@ -110,6 +110,31 @@ sdhci@70000000 {
smi: flash@fc000000 {
status = "okay";
clock-rate=<50000000>;
flash@f8000000 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0xf8000000 0x800000>;
st,smi-fast-mode;
partition@0 {
label = "xloader";
reg = <0x0 0x10000>;
};
partition@10000 {
label = "u-boot";
reg = <0x10000 0x40000>;
};
partition@50000 {
label = "linux";
reg = <0x50000 0x2c0000>;
};
partition@310000 {
label = "rootfs";
reg = <0x310000 0x4f0000>;
};
};
};
spi0: spi@d0100000 {

View File

@ -139,6 +139,12 @@ wdt@fc880000 {
interrupts = <12>;
status = "disabled";
};
timer@f0000000 {
compatible = "st,spear-timer";
reg = <0xf0000000 0x400>;
interrupts = <2>;
};
};
};
};

View File

@ -33,6 +33,35 @@ gmac: ethernet@e0800000 {
status = "okay";
};
smi: flash@fc000000 {
status = "okay";
clock-rate=<50000000>;
flash@f8000000 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0xf8000000 0x800000>;
st,smi-fast-mode;
partition@0 {
label = "xloader";
reg = <0x0 0x10000>;
};
partition@10000 {
label = "u-boot";
reg = <0x10000 0x40000>;
};
partition@50000 {
label = "linux";
reg = <0x50000 0x2c0000>;
};
partition@310000 {
label = "rootfs";
reg = <0x310000 0x4f0000>;
};
};
};
apb {
serial@d0000000 {
status = "okay";

View File

@ -177,6 +177,12 @@ i2c@d0200000 {
interrupts = <28>;
status = "disabled";
};
timer@f0000000 {
compatible = "st,spear-timer";
reg = <0xf0000000 0x400>;
interrupts = <16>;
};
};
};
};

View File

@ -14,6 +14,9 @@ CONFIG_BINFMT_MISC=y
CONFIG_NET=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_MTD=y
CONFIG_MTD_OF_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_FSMC=y
CONFIG_BLK_DEV_RAM=y
@ -73,6 +76,7 @@ CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
CONFIG_TMPFS=y
CONFIG_JFFS2_FS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=m

View File

@ -8,11 +8,13 @@ CONFIG_MODVERSIONS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_PLAT_SPEAR=y
CONFIG_ARCH_SPEAR6XX=y
CONFIG_BOARD_SPEAR600_DT=y
CONFIG_BINFMT_MISC=y
CONFIG_NET=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_MTD=y
CONFIG_MTD_OF_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_FSMC=y
CONFIG_BLK_DEV_RAM=y
@ -64,6 +66,7 @@ CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
CONFIG_TMPFS=y
CONFIG_JFFS2_FS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=m

View File

@ -13,7 +13,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/ata_platform.h>
#include <linux/gpio.h>
#include <asm/page.h>
@ -67,6 +67,19 @@ void __init dove_map_io(void)
iotable_init(dove_io_desc, ARRAY_SIZE(dove_io_desc));
}
/*****************************************************************************
* CLK tree
****************************************************************************/
static struct clk *tclk;
static void __init clk_init(void)
{
tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
get_tclk());
orion_clkdev_init(tclk);
}
/*****************************************************************************
* EHCI0
****************************************************************************/
@ -89,8 +102,7 @@ void __init dove_ehci1_init(void)
void __init dove_ge00_init(struct mv643xx_eth_platform_data *eth_data)
{
orion_ge00_init(eth_data,
DOVE_GE00_PHYS_BASE, IRQ_DOVE_GE00_SUM,
0, get_tclk());
DOVE_GE00_PHYS_BASE, IRQ_DOVE_GE00_SUM, 0);
}
/*****************************************************************************
@ -116,7 +128,7 @@ void __init dove_sata_init(struct mv_sata_platform_data *sata_data)
void __init dove_uart0_init(void)
{
orion_uart0_init(DOVE_UART0_VIRT_BASE, DOVE_UART0_PHYS_BASE,
IRQ_DOVE_UART_0, get_tclk());
IRQ_DOVE_UART_0, tclk);
}
/*****************************************************************************
@ -125,7 +137,7 @@ void __init dove_uart0_init(void)
void __init dove_uart1_init(void)
{
orion_uart1_init(DOVE_UART1_VIRT_BASE, DOVE_UART1_PHYS_BASE,
IRQ_DOVE_UART_1, get_tclk());
IRQ_DOVE_UART_1, tclk);
}
/*****************************************************************************
@ -134,7 +146,7 @@ void __init dove_uart1_init(void)
void __init dove_uart2_init(void)
{
orion_uart2_init(DOVE_UART2_VIRT_BASE, DOVE_UART2_PHYS_BASE,
IRQ_DOVE_UART_2, get_tclk());
IRQ_DOVE_UART_2, tclk);
}
/*****************************************************************************
@ -143,7 +155,7 @@ void __init dove_uart2_init(void)
void __init dove_uart3_init(void)
{
orion_uart3_init(DOVE_UART3_VIRT_BASE, DOVE_UART3_PHYS_BASE,
IRQ_DOVE_UART_3, get_tclk());
IRQ_DOVE_UART_3, tclk);
}
/*****************************************************************************
@ -151,12 +163,12 @@ void __init dove_uart3_init(void)
****************************************************************************/
void __init dove_spi0_init(void)
{
orion_spi_init(DOVE_SPI0_PHYS_BASE, get_tclk());
orion_spi_init(DOVE_SPI0_PHYS_BASE);
}
void __init dove_spi1_init(void)
{
orion_spi_1_init(DOVE_SPI1_PHYS_BASE, get_tclk());
orion_spi_1_init(DOVE_SPI1_PHYS_BASE);
}
/*****************************************************************************
@ -272,18 +284,17 @@ void __init dove_sdio1_init(void)
void __init dove_init(void)
{
int tclk;
tclk = get_tclk();
printk(KERN_INFO "Dove 88AP510 SoC, ");
printk(KERN_INFO "TCLK = %dMHz\n", (tclk + 499999) / 1000000);
printk(KERN_INFO "TCLK = %dMHz\n", (get_tclk() + 499999) / 1000000);
#ifdef CONFIG_CACHE_TAUROS2
tauros2_init();
#endif
dove_setup_cpu_mbus();
/* Setup root of clk tree */
clk_init();
/* internal devices that every board has */
dove_rtc_init();
dove_xor0_init();

View File

@ -20,7 +20,6 @@
#include <linux/i2c.h>
#include <linux/pci.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <linux/spi/flash.h>
#include <linux/gpio.h>
#include <asm/mach-types.h>

View File

@ -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
@ -815,6 +822,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

View File

@ -1,15 +1,18 @@
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

View File

@ -0,0 +1,189 @@
/*
* 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;
}

View File

@ -0,0 +1,118 @@
/*
* 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;
}

View File

@ -0,0 +1,115 @@
/*
* 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;
}

View File

@ -0,0 +1,186 @@
/*
* 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;
}

View File

@ -0,0 +1,248 @@
/*
* Copyright (C) 2009 by Sascha Hauer, Pengutronix
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/list.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 <mach/mx25.h>
#include "clk.h"
#define CRM_BASE MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR)
#define CCM_MPCTL 0x00
#define CCM_UPCTL 0x04
#define CCM_CCTL 0x08
#define CCM_CGCR0 0x0C
#define CCM_CGCR1 0x10
#define CCM_CGCR2 0x14
#define CCM_PCDR0 0x18
#define CCM_PCDR1 0x1C
#define CCM_PCDR2 0x20
#define CCM_PCDR3 0x24
#define CCM_RCSR 0x28
#define CCM_CRDR 0x2C
#define CCM_DCVR0 0x30
#define CCM_DCVR1 0x34
#define CCM_DCVR2 0x38
#define CCM_DCVR3 0x3c
#define CCM_LTR0 0x40
#define CCM_LTR1 0x44
#define CCM_LTR2 0x48
#define CCM_LTR3 0x4c
#define CCM_MCR 0x64
#define ccm(x) (CRM_BASE + (x))
static const char *cpu_sel_clks[] = { "mpll", "mpll_cpu_3_4", };
static const char *per_sel_clks[] = { "ahb", "upll", };
enum mx25_clks {
dummy, osc, mpll, upll, mpll_cpu_3_4, cpu_sel, cpu, ahb, usb_div, ipg,
per0_sel, per1_sel, per2_sel, per3_sel, per4_sel, per5_sel, per6_sel,
per7_sel, per8_sel, per9_sel, per10_sel, per11_sel, per12_sel,
per13_sel, per14_sel, per15_sel, per0, per1, per2, per3, per4, per5,
per6, per7, per8, per9, per10, per11, per12, per13, per14, per15,
csi_ipg_per, esdhc1_ipg_per, esdhc2_ipg_per, gpt_ipg_per, i2c_ipg_per,
lcdc_ipg_per, nfc_ipg_per, ssi1_ipg_per, ssi2_ipg_per, uart_ipg_per,
csi_ahb, esdhc1_ahb, esdhc2_ahb, fec_ahb, lcdc_ahb, sdma_ahb,
usbotg_ahb, can1_ipg, can2_ipg, csi_ipg, cspi1_ipg, cspi2_ipg,
cspi3_ipg, dryice_ipg, esdhc1_ipg, esdhc2_ipg, fec_ipg, iim_ipg,
kpp_ipg, lcdc_ipg, pwm1_ipg, pwm2_ipg, pwm3_ipg, pwm4_ipg, sdma_ipg,
ssi1_ipg, ssi2_ipg, tsc_ipg, uart1_ipg, uart2_ipg, uart3_ipg,
uart4_ipg, uart5_ipg, wdt_ipg, clk_max
};
static struct clk *clk[clk_max];
int __init mx25_clocks_init(void)
{
int i;
clk[dummy] = imx_clk_fixed("dummy", 0);
clk[osc] = imx_clk_fixed("osc", 24000000);
clk[mpll] = imx_clk_pllv1("mpll", "osc", ccm(CCM_MPCTL));
clk[upll] = imx_clk_pllv1("upll", "osc", ccm(CCM_UPCTL));
clk[mpll_cpu_3_4] = imx_clk_fixed_factor("mpll_cpu_3_4", "mpll", 3, 4);
clk[cpu_sel] = imx_clk_mux("cpu_sel", ccm(CCM_CCTL), 14, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
clk[cpu] = imx_clk_divider("cpu", "cpu_sel", ccm(CCM_CCTL), 30, 2);
clk[ahb] = imx_clk_divider("ahb", "cpu", ccm(CCM_CCTL), 28, 2);
clk[usb_div] = imx_clk_divider("usb_div", "upll", ccm(CCM_CCTL), 16, 6);
clk[ipg] = imx_clk_fixed_factor("ipg", "ahb", 1, 2);
clk[per0_sel] = imx_clk_mux("per0_sel", ccm(CCM_MCR), 0, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per1_sel] = imx_clk_mux("per1_sel", ccm(CCM_MCR), 1, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per2_sel] = imx_clk_mux("per2_sel", ccm(CCM_MCR), 2, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per3_sel] = imx_clk_mux("per3_sel", ccm(CCM_MCR), 3, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per4_sel] = imx_clk_mux("per4_sel", ccm(CCM_MCR), 4, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per5_sel] = imx_clk_mux("per5_sel", ccm(CCM_MCR), 5, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per6_sel] = imx_clk_mux("per6_sel", ccm(CCM_MCR), 6, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per7_sel] = imx_clk_mux("per7_sel", ccm(CCM_MCR), 7, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per8_sel] = imx_clk_mux("per8_sel", ccm(CCM_MCR), 8, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per9_sel] = imx_clk_mux("per9_sel", ccm(CCM_MCR), 9, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per10_sel] = imx_clk_mux("per10_sel", ccm(CCM_MCR), 10, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per11_sel] = imx_clk_mux("per11_sel", ccm(CCM_MCR), 11, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per12_sel] = imx_clk_mux("per12_sel", ccm(CCM_MCR), 12, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per13_sel] = imx_clk_mux("per13_sel", ccm(CCM_MCR), 13, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per14_sel] = imx_clk_mux("per14_sel", ccm(CCM_MCR), 14, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per15_sel] = imx_clk_mux("per15_sel", ccm(CCM_MCR), 15, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
clk[per0] = imx_clk_divider("per0", "per0_sel", ccm(CCM_PCDR0), 0, 6);
clk[per1] = imx_clk_divider("per1", "per1_sel", ccm(CCM_PCDR0), 8, 6);
clk[per2] = imx_clk_divider("per2", "per2_sel", ccm(CCM_PCDR0), 16, 6);
clk[per3] = imx_clk_divider("per3", "per3_sel", ccm(CCM_PCDR0), 24, 6);
clk[per4] = imx_clk_divider("per4", "per4_sel", ccm(CCM_PCDR1), 0, 6);
clk[per5] = imx_clk_divider("per5", "per5_sel", ccm(CCM_PCDR1), 8, 6);
clk[per6] = imx_clk_divider("per6", "per6_sel", ccm(CCM_PCDR1), 16, 6);
clk[per7] = imx_clk_divider("per7", "per7_sel", ccm(CCM_PCDR1), 24, 6);
clk[per8] = imx_clk_divider("per8", "per8_sel", ccm(CCM_PCDR2), 0, 6);
clk[per9] = imx_clk_divider("per9", "per9_sel", ccm(CCM_PCDR2), 8, 6);
clk[per10] = imx_clk_divider("per10", "per10_sel", ccm(CCM_PCDR2), 16, 6);
clk[per11] = imx_clk_divider("per11", "per11_sel", ccm(CCM_PCDR2), 24, 6);
clk[per12] = imx_clk_divider("per12", "per12_sel", ccm(CCM_PCDR3), 0, 6);
clk[per13] = imx_clk_divider("per13", "per13_sel", ccm(CCM_PCDR3), 8, 6);
clk[per14] = imx_clk_divider("per14", "per14_sel", ccm(CCM_PCDR3), 16, 6);
clk[per15] = imx_clk_divider("per15", "per15_sel", ccm(CCM_PCDR3), 24, 6);
clk[csi_ipg_per] = imx_clk_gate("csi_ipg_per", "per0", ccm(CCM_CGCR0), 0);
clk[esdhc1_ipg_per] = imx_clk_gate("esdhc1_ipg_per", "per3", ccm(CCM_CGCR0), 3);
clk[esdhc2_ipg_per] = imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0), 4);
clk[gpt_ipg_per] = imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0), 5);
clk[i2c_ipg_per] = imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0), 6);
clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per8", ccm(CCM_CGCR0), 7);
clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "ipg_per", ccm(CCM_CGCR0), 8);
clk[ssi1_ipg_per] = imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13);
clk[ssi2_ipg_per] = imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14);
clk[uart_ipg_per] = imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15);
clk[csi_ahb] = imx_clk_gate("csi_ahb", "ahb", ccm(CCM_CGCR0), 18);
clk[esdhc1_ahb] = imx_clk_gate("esdhc1_ahb", "ahb", ccm(CCM_CGCR0), 21);
clk[esdhc2_ahb] = imx_clk_gate("esdhc2_ahb", "ahb", ccm(CCM_CGCR0), 22);
clk[fec_ahb] = imx_clk_gate("fec_ahb", "ahb", ccm(CCM_CGCR0), 23);
clk[lcdc_ahb] = imx_clk_gate("lcdc_ahb", "ahb", ccm(CCM_CGCR0), 24);
clk[sdma_ahb] = imx_clk_gate("sdma_ahb", "ahb", ccm(CCM_CGCR0), 26);
clk[usbotg_ahb] = imx_clk_gate("usbotg_ahb", "ahb", ccm(CCM_CGCR0), 28);
clk[can1_ipg] = imx_clk_gate("can1_ipg", "ipg", ccm(CCM_CGCR1), 2);
clk[can2_ipg] = imx_clk_gate("can2_ipg", "ipg", ccm(CCM_CGCR1), 3);
clk[csi_ipg] = imx_clk_gate("csi_ipg", "ipg", ccm(CCM_CGCR1), 4);
clk[cspi1_ipg] = imx_clk_gate("cspi1_ipg", "ipg", ccm(CCM_CGCR1), 5);
clk[cspi2_ipg] = imx_clk_gate("cspi2_ipg", "ipg", ccm(CCM_CGCR1), 6);
clk[cspi3_ipg] = imx_clk_gate("cspi3_ipg", "ipg", ccm(CCM_CGCR1), 7);
clk[dryice_ipg] = imx_clk_gate("dryice_ipg", "ipg", ccm(CCM_CGCR1), 8);
clk[esdhc1_ipg] = imx_clk_gate("esdhc1_ipg", "ipg", ccm(CCM_CGCR1), 13);
clk[esdhc2_ipg] = imx_clk_gate("esdhc2_ipg", "ipg", ccm(CCM_CGCR1), 14);
clk[fec_ipg] = imx_clk_gate("fec_ipg", "ipg", ccm(CCM_CGCR1), 15);
clk[iim_ipg] = imx_clk_gate("iim_ipg", "ipg", ccm(CCM_CGCR1), 26);
clk[kpp_ipg] = imx_clk_gate("kpp_ipg", "ipg", ccm(CCM_CGCR1), 28);
clk[lcdc_ipg] = imx_clk_gate("lcdc_ipg", "ipg", ccm(CCM_CGCR1), 29);
clk[pwm1_ipg] = imx_clk_gate("pwm1_ipg", "ipg", ccm(CCM_CGCR1), 31);
clk[pwm2_ipg] = imx_clk_gate("pwm2_ipg", "ipg", ccm(CCM_CGCR2), 0);
clk[pwm3_ipg] = imx_clk_gate("pwm3_ipg", "ipg", ccm(CCM_CGCR2), 1);
clk[pwm4_ipg] = imx_clk_gate("pwm4_ipg", "ipg", ccm(CCM_CGCR2), 2);
clk[sdma_ipg] = imx_clk_gate("sdma_ipg", "ipg", ccm(CCM_CGCR2), 6);
clk[ssi1_ipg] = imx_clk_gate("ssi1_ipg", "ipg", ccm(CCM_CGCR2), 11);
clk[ssi2_ipg] = imx_clk_gate("ssi2_ipg", "ipg", ccm(CCM_CGCR2), 12);
clk[tsc_ipg] = imx_clk_gate("tsc_ipg", "ipg", ccm(CCM_CGCR2), 13);
clk[uart1_ipg] = imx_clk_gate("uart1_ipg", "ipg", ccm(CCM_CGCR2), 14);
clk[uart2_ipg] = imx_clk_gate("uart2_ipg", "ipg", ccm(CCM_CGCR2), 15);
clk[uart3_ipg] = imx_clk_gate("uart3_ipg", "ipg", ccm(CCM_CGCR2), 16);
clk[uart4_ipg] = imx_clk_gate("uart4_ipg", "ipg", ccm(CCM_CGCR2), 17);
clk[uart5_ipg] = imx_clk_gate("uart5_ipg", "ipg", ccm(CCM_CGCR2), 18);
clk[wdt_ipg] = imx_clk_gate("wdt_ipg", "ipg", ccm(CCM_CGCR2), 19);
for (i = 0; i < ARRAY_SIZE(clk); i++)
if (IS_ERR(clk[i]))
pr_err("i.MX25 clk %d: register failed with %ld\n",
i, PTR_ERR(clk[i]));
/* i.mx25 has the i.mx21 type uart */
clk_register_clkdev(clk[uart1_ipg], "ipg", "imx21-uart.0");
clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.0");
clk_register_clkdev(clk[uart2_ipg], "ipg", "imx21-uart.1");
clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.1");
clk_register_clkdev(clk[uart3_ipg], "ipg", "imx21-uart.2");
clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.2");
clk_register_clkdev(clk[uart4_ipg], "ipg", "imx21-uart.3");
clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.3");
clk_register_clkdev(clk[uart5_ipg], "ipg", "imx21-uart.4");
clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.4");
clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0");
clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.0");
clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.1");
clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.1");
clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.1");
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.2");
clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
clk_register_clkdev(clk[usbotg_ahb], "ahb", "fsl-usb2-udc");
clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
clk_register_clkdev(clk[nfc_ipg_per], NULL, "mxc_nand.0");
/* i.mx25 has the i.mx35 type cspi */
clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0");
clk_register_clkdev(clk[cspi2_ipg], NULL, "imx35-cspi.1");
clk_register_clkdev(clk[cspi3_ipg], NULL, "imx35-cspi.2");
clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.0");
clk_register_clkdev(clk[per10], "per", "mxc_pwm.0");
clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.1");
clk_register_clkdev(clk[per10], "per", "mxc_pwm.1");
clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.2");
clk_register_clkdev(clk[per10], "per", "mxc_pwm.2");
clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.3");
clk_register_clkdev(clk[per10], "per", "mxc_pwm.3");
clk_register_clkdev(clk[kpp_ipg], NULL, "imx-keypad");
clk_register_clkdev(clk[tsc_ipg], NULL, "mx25-adc");
clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx-i2c.0");
clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx-i2c.1");
clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx-i2c.2");
clk_register_clkdev(clk[fec_ipg], "ipg", "imx25-fec.0");
clk_register_clkdev(clk[fec_ahb], "ahb", "imx25-fec.0");
clk_register_clkdev(clk[dryice_ipg], NULL, "imxdi_rtc.0");
clk_register_clkdev(clk[lcdc_ipg_per], "per", "imx-fb.0");
clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx-fb.0");
clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx-fb.0");
clk_register_clkdev(clk[wdt_ipg], NULL, "imx2-wdt.0");
clk_register_clkdev(clk[ssi1_ipg_per], "per", "imx-ssi.0");
clk_register_clkdev(clk[ssi1_ipg], "ipg", "imx-ssi.0");
clk_register_clkdev(clk[ssi2_ipg_per], "per", "imx-ssi.1");
clk_register_clkdev(clk[ssi2_ipg], "ipg", "imx-ssi.1");
clk_register_clkdev(clk[esdhc1_ipg_per], "per", "sdhci-esdhc-imx25.0");
clk_register_clkdev(clk[esdhc1_ipg], "ipg", "sdhci-esdhc-imx25.0");
clk_register_clkdev(clk[esdhc1_ahb], "ahb", "sdhci-esdhc-imx25.0");
clk_register_clkdev(clk[esdhc2_ipg_per], "per", "sdhci-esdhc-imx25.1");
clk_register_clkdev(clk[esdhc2_ipg], "ipg", "sdhci-esdhc-imx25.1");
clk_register_clkdev(clk[esdhc2_ahb], "ahb", "sdhci-esdhc-imx25.1");
clk_register_clkdev(clk[csi_ipg_per], "per", "mx2-camera.0");
clk_register_clkdev(clk[csi_ipg], "ipg", "mx2-camera.0");
clk_register_clkdev(clk[csi_ahb], "ahb", "mx2-camera.0");
clk_register_clkdev(clk[dummy], "audmux", NULL);
clk_register_clkdev(clk[can1_ipg], NULL, "flexcan.0");
clk_register_clkdev(clk[can2_ipg], NULL, "flexcan.1");
/* i.mx25 has the i.mx35 type sdma */
clk_register_clkdev(clk[sdma_ipg], "ipg", "imx35-sdma");
clk_register_clkdev(clk[sdma_ahb], "ahb", "imx35-sdma");
clk_register_clkdev(clk[iim_ipg], "iim", NULL);
mxc_timer_init(NULL, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
return 0;
}

View File

@ -0,0 +1,290 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <mach/common.h>
#include <mach/hardware.h>
#include "clk.h"
#define IO_ADDR_CCM(off) (MX27_IO_ADDRESS(MX27_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)
#define CCM_CSCR_UPDATE_DIS (1 << 31)
#define CCM_CSCR_SSI2 (1 << 23)
#define CCM_CSCR_SSI1 (1 << 22)
#define CCM_CSCR_VPU (1 << 21)
#define CCM_CSCR_MSHC (1 << 20)
#define CCM_CSCR_SPLLRES (1 << 19)
#define CCM_CSCR_MPLLRES (1 << 18)
#define CCM_CSCR_SP (1 << 17)
#define CCM_CSCR_MCU (1 << 16)
#define CCM_CSCR_OSC26MDIV (1 << 4)
#define CCM_CSCR_OSC26M (1 << 3)
#define CCM_CSCR_FPM (1 << 2)
#define CCM_CSCR_SPEN (1 << 1)
#define CCM_CSCR_MPEN (1 << 0)
/* i.MX27 TO 2+ */
#define CCM_CSCR_ARM_SRC (1 << 15)
#define CCM_SPCTL1_LF (1 << 15)
#define CCM_SPCTL1_BRMO (1 << 6)
static const char *vpu_sel_clks[] = { "spll", "mpll_main2", };
static const char *cpu_sel_clks[] = { "mpll_main2", "mpll", };
static const char *clko_sel_clks[] = {
"ckil", "prem", "ckih", "ckih",
"ckih", "mpll", "spll", "cpu_div",
"ahb", "ipg", "per1_div", "per2_div",
"per3_div", "per4_div", "ssi1_div", "ssi2_div",
"nfc_div", "mshc_div", "vpu_div", "60m",
"32k", "usb_div", "dptc",
};
static const char *ssi_sel_clks[] = { "spll", "mpll", };
enum mx27_clks {
dummy, ckih, ckil, mpll, spll, mpll_main2, ahb, ipg, nfc_div, per1_div,
per2_div, per3_div, per4_div, vpu_sel, vpu_div, usb_div, cpu_sel,
clko_sel, cpu_div, clko_div, ssi1_sel, ssi2_sel, ssi1_div, ssi2_div,
clko_en, ssi2_ipg_gate, ssi1_ipg_gate, slcdc_ipg_gate, sdhc3_ipg_gate,
sdhc2_ipg_gate, sdhc1_ipg_gate, scc_ipg_gate, sahara_ipg_gate,
rtc_ipg_gate, pwm_ipg_gate, owire_ipg_gate, lcdc_ipg_gate,
kpp_ipg_gate, iim_ipg_gate, i2c2_ipg_gate, i2c1_ipg_gate,
gpt6_ipg_gate, gpt5_ipg_gate, gpt4_ipg_gate, gpt3_ipg_gate,
gpt2_ipg_gate, gpt1_ipg_gate, gpio_ipg_gate, fec_ipg_gate,
emma_ipg_gate, dma_ipg_gate, cspi3_ipg_gate, cspi2_ipg_gate,
cspi1_ipg_gate, nfc_baud_gate, ssi2_baud_gate, ssi1_baud_gate,
vpu_baud_gate, per4_gate, per3_gate, per2_gate, per1_gate,
usb_ahb_gate, slcdc_ahb_gate, sahara_ahb_gate, lcdc_ahb_gate,
vpu_ahb_gate, fec_ahb_gate, emma_ahb_gate, emi_ahb_gate, dma_ahb_gate,
csi_ahb_gate, brom_ahb_gate, ata_ahb_gate, wdog_ipg_gate, usb_ipg_gate,
uart6_ipg_gate, uart5_ipg_gate, uart4_ipg_gate, uart3_ipg_gate,
uart2_ipg_gate, uart1_ipg_gate, clk_max
};
static struct clk *clk[clk_max];
int __init mx27_clocks_init(unsigned long fref)
{
int i;
clk[dummy] = imx_clk_fixed("dummy", 0);
clk[ckih] = imx_clk_fixed("ckih", fref);
clk[ckil] = imx_clk_fixed("ckil", 32768);
clk[mpll] = imx_clk_pllv1("mpll", "ckih", CCM_MPCTL0);
clk[spll] = imx_clk_pllv1("spll", "ckih", CCM_SPCTL0);
clk[mpll_main2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
clk[ahb] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 8, 2);
clk[ipg] = imx_clk_fixed_factor("ipg", "ahb", 1, 2);
} else {
clk[ahb] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 9, 4);
clk[ipg] = imx_clk_divider("ipg", "ahb", CCM_CSCR, 8, 1);
}
clk[nfc_div] = imx_clk_divider("nfc_div", "ahb", CCM_PCDR0, 6, 4);
clk[per1_div] = imx_clk_divider("per1_div", "mpll_main2", CCM_PCDR1, 0, 6);
clk[per2_div] = imx_clk_divider("per2_div", "mpll_main2", CCM_PCDR1, 8, 6);
clk[per3_div] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);
clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 3);
clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3);
clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
clk[cpu_div] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 12, 2);
else
clk[cpu_div] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 13, 3);
clk[clko_div] = imx_clk_divider("clko_div", "clko_sel", CCM_PCDR0, 22, 3);
clk[ssi1_sel] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
clk[ssi2_sel] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
clk[ssi1_div] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 3);
clk[clko_en] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0);
clk[ssi2_ipg_gate] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);
clk[ssi1_ipg_gate] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1);
clk[slcdc_ipg_gate] = imx_clk_gate("slcdc_ipg_gate", "ipg", CCM_PCCR0, 2);
clk[sdhc3_ipg_gate] = imx_clk_gate("sdhc3_ipg_gate", "ipg", CCM_PCCR0, 3);
clk[sdhc2_ipg_gate] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 4);
clk[sdhc1_ipg_gate] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 5);
clk[scc_ipg_gate] = imx_clk_gate("scc_ipg_gate", "ipg", CCM_PCCR0, 6);
clk[sahara_ipg_gate] = imx_clk_gate("sahara_ipg_gate", "ipg", CCM_PCCR0, 7);
clk[rtc_ipg_gate] = imx_clk_gate("rtc_ipg_gate", "ipg", CCM_PCCR0, 9);
clk[pwm_ipg_gate] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR0, 11);
clk[owire_ipg_gate] = imx_clk_gate("owire_ipg_gate", "ipg", CCM_PCCR0, 12);
clk[lcdc_ipg_gate] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 14);
clk[kpp_ipg_gate] = imx_clk_gate("kpp_ipg_gate", "ipg", CCM_PCCR0, 15);
clk[iim_ipg_gate] = imx_clk_gate("iim_ipg_gate", "ipg", CCM_PCCR0, 16);
clk[i2c2_ipg_gate] = imx_clk_gate("i2c2_ipg_gate", "ipg", CCM_PCCR0, 17);
clk[i2c1_ipg_gate] = imx_clk_gate("i2c1_ipg_gate", "ipg", CCM_PCCR0, 18);
clk[gpt6_ipg_gate] = imx_clk_gate("gpt6_ipg_gate", "ipg", CCM_PCCR0, 19);
clk[gpt5_ipg_gate] = imx_clk_gate("gpt5_ipg_gate", "ipg", CCM_PCCR0, 20);
clk[gpt4_ipg_gate] = imx_clk_gate("gpt4_ipg_gate", "ipg", CCM_PCCR0, 21);
clk[gpt3_ipg_gate] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR0, 22);
clk[gpt2_ipg_gate] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR0, 23);
clk[gpt1_ipg_gate] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR0, 24);
clk[gpio_ipg_gate] = imx_clk_gate("gpio_ipg_gate", "ipg", CCM_PCCR0, 25);
clk[fec_ipg_gate] = imx_clk_gate("fec_ipg_gate", "ipg", CCM_PCCR0, 26);
clk[emma_ipg_gate] = imx_clk_gate("emma_ipg_gate", "ipg", CCM_PCCR0, 27);
clk[dma_ipg_gate] = imx_clk_gate("dma_ipg_gate", "ipg", CCM_PCCR0, 28);
clk[cspi3_ipg_gate] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR0, 29);
clk[cspi2_ipg_gate] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 30);
clk[cspi1_ipg_gate] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 31);
clk[nfc_baud_gate] = imx_clk_gate("nfc_baud_gate", "nfc_div", CCM_PCCR1, 3);
clk[ssi2_baud_gate] = imx_clk_gate("ssi2_baud_gate", "ssi2_div", CCM_PCCR1, 4);
clk[ssi1_baud_gate] = imx_clk_gate("ssi1_baud_gate", "ssi1_div", CCM_PCCR1, 5);
clk[vpu_baud_gate] = imx_clk_gate("vpu_baud_gate", "vpu_div", CCM_PCCR1, 6);
clk[per4_gate] = imx_clk_gate("per4_gate", "per4_div", CCM_PCCR1, 7);
clk[per3_gate] = imx_clk_gate("per3_gate", "per3_div", CCM_PCCR1, 8);
clk[per2_gate] = imx_clk_gate("per2_gate", "per2_div", CCM_PCCR1, 9);
clk[per1_gate] = imx_clk_gate("per1_gate", "per1_div", CCM_PCCR1, 10);
clk[usb_ahb_gate] = imx_clk_gate("usb_ahb_gate", "ahb", CCM_PCCR1, 11);
clk[slcdc_ahb_gate] = imx_clk_gate("slcdc_ahb_gate", "ahb", CCM_PCCR1, 12);
clk[sahara_ahb_gate] = imx_clk_gate("sahara_ahb_gate", "ahb", CCM_PCCR1, 13);
clk[lcdc_ahb_gate] = imx_clk_gate("lcdc_ahb_gate", "ahb", CCM_PCCR1, 15);
clk[vpu_ahb_gate] = imx_clk_gate("vpu_ahb_gate", "ahb", CCM_PCCR1, 16);
clk[fec_ahb_gate] = imx_clk_gate("fec_ahb_gate", "ahb", CCM_PCCR1, 17);
clk[emma_ahb_gate] = imx_clk_gate("emma_ahb_gate", "ahb", CCM_PCCR1, 18);
clk[emi_ahb_gate] = imx_clk_gate("emi_ahb_gate", "ahb", CCM_PCCR1, 19);
clk[dma_ahb_gate] = imx_clk_gate("dma_ahb_gate", "ahb", CCM_PCCR1, 20);
clk[csi_ahb_gate] = imx_clk_gate("csi_ahb_gate", "ahb", CCM_PCCR1, 21);
clk[brom_ahb_gate] = imx_clk_gate("brom_ahb_gate", "ahb", CCM_PCCR1, 22);
clk[ata_ahb_gate] = imx_clk_gate("ata_ahb_gate", "ahb", CCM_PCCR1, 23);
clk[wdog_ipg_gate] = imx_clk_gate("wdog_ipg_gate", "ipg", CCM_PCCR1, 24);
clk[usb_ipg_gate] = imx_clk_gate("usb_ipg_gate", "ipg", CCM_PCCR1, 25);
clk[uart6_ipg_gate] = imx_clk_gate("uart6_ipg_gate", "ipg", CCM_PCCR1, 26);
clk[uart5_ipg_gate] = imx_clk_gate("uart5_ipg_gate", "ipg", CCM_PCCR1, 27);
clk[uart4_ipg_gate] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR1, 28);
clk[uart3_ipg_gate] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR1, 29);
clk[uart2_ipg_gate] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR1, 30);
clk[uart1_ipg_gate] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR1, 31);
for (i = 0; i < ARRAY_SIZE(clk); i++)
if (IS_ERR(clk[i]))
pr_err("i.MX27 clk %d: register failed with %ld\n",
i, PTR_ERR(clk[i]));
clk_register_clkdev(clk[uart1_ipg_gate], "ipg", "imx21-uart.0");
clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.0");
clk_register_clkdev(clk[uart2_ipg_gate], "ipg", "imx21-uart.1");
clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.1");
clk_register_clkdev(clk[uart3_ipg_gate], "ipg", "imx21-uart.2");
clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.2");
clk_register_clkdev(clk[uart4_ipg_gate], "ipg", "imx21-uart.3");
clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.3");
clk_register_clkdev(clk[uart5_ipg_gate], "ipg", "imx21-uart.4");
clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.4");
clk_register_clkdev(clk[uart6_ipg_gate], "ipg", "imx21-uart.5");
clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.5");
clk_register_clkdev(clk[gpt1_ipg_gate], "ipg", "imx-gpt.0");
clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.0");
clk_register_clkdev(clk[gpt2_ipg_gate], "ipg", "imx-gpt.1");
clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.1");
clk_register_clkdev(clk[gpt3_ipg_gate], "ipg", "imx-gpt.2");
clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.2");
clk_register_clkdev(clk[gpt4_ipg_gate], "ipg", "imx-gpt.3");
clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.3");
clk_register_clkdev(clk[gpt5_ipg_gate], "ipg", "imx-gpt.4");
clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.4");
clk_register_clkdev(clk[gpt6_ipg_gate], "ipg", "imx-gpt.5");
clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.5");
clk_register_clkdev(clk[pwm_ipg_gate], NULL, "mxc_pwm.0");
clk_register_clkdev(clk[per2_gate], "per", "mxc-mmc.0");
clk_register_clkdev(clk[sdhc1_ipg_gate], "ipg", "mxc-mmc.0");
clk_register_clkdev(clk[per2_gate], "per", "mxc-mmc.1");
clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "mxc-mmc.1");
clk_register_clkdev(clk[per2_gate], "per", "mxc-mmc.2");
clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "mxc-mmc.2");
clk_register_clkdev(clk[cspi1_ipg_gate], NULL, "imx27-cspi.0");
clk_register_clkdev(clk[cspi2_ipg_gate], NULL, "imx27-cspi.1");
clk_register_clkdev(clk[cspi3_ipg_gate], NULL, "imx27-cspi.2");
clk_register_clkdev(clk[per3_gate], "per", "imx-fb.0");
clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx-fb.0");
clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx-fb.0");
clk_register_clkdev(clk[csi_ahb_gate], NULL, "mx2-camera.0");
clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
clk_register_clkdev(clk[usb_ipg_gate], "ipg", "fsl-usb2-udc");
clk_register_clkdev(clk[usb_ahb_gate], "ahb", "fsl-usb2-udc");
clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.0");
clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.0");
clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.1");
clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.1");
clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.1");
clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.2");
clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.2");
clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
clk_register_clkdev(clk[nfc_baud_gate], NULL, "mxc_nand.0");
clk_register_clkdev(clk[vpu_baud_gate], "per", "imx-vpu");
clk_register_clkdev(clk[vpu_ahb_gate], "ahb", "imx-vpu");
clk_register_clkdev(clk[dma_ahb_gate], "ahb", "imx-dma");
clk_register_clkdev(clk[dma_ipg_gate], "ipg", "imx-dma");
clk_register_clkdev(clk[fec_ipg_gate], "ipg", "imx27-fec.0");
clk_register_clkdev(clk[fec_ahb_gate], "ahb", "imx27-fec.0");
clk_register_clkdev(clk[wdog_ipg_gate], NULL, "imx2-wdt.0");
clk_register_clkdev(clk[i2c1_ipg_gate], NULL, "imx-i2c.0");
clk_register_clkdev(clk[i2c2_ipg_gate], NULL, "imx-i2c.1");
clk_register_clkdev(clk[owire_ipg_gate], NULL, "mxc_w1.0");
clk_register_clkdev(clk[kpp_ipg_gate], NULL, "imx-keypad");
clk_register_clkdev(clk[emma_ahb_gate], "ahb", "imx-emma");
clk_register_clkdev(clk[emma_ipg_gate], "ipg", "imx-emma");
clk_register_clkdev(clk[iim_ipg_gate], "iim", NULL);
clk_register_clkdev(clk[gpio_ipg_gate], "gpio", NULL);
clk_register_clkdev(clk[brom_ahb_gate], "brom", NULL);
clk_register_clkdev(clk[ata_ahb_gate], "ata", NULL);
clk_register_clkdev(clk[rtc_ipg_gate], "rtc", NULL);
clk_register_clkdev(clk[scc_ipg_gate], "scc", NULL);
clk_register_clkdev(clk[cpu_div], "cpu", NULL);
clk_register_clkdev(clk[emi_ahb_gate], "emi_ahb" , NULL);
clk_register_clkdev(clk[ssi1_baud_gate], "bitrate" , "imx-ssi.0");
clk_register_clkdev(clk[ssi2_baud_gate], "bitrate" , "imx-ssi.1");
mxc_timer_init(NULL, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
MX27_INT_GPT1);
clk_prepare_enable(clk[emi_ahb_gate]);
return 0;
}
#ifdef CONFIG_OF
int __init mx27_clocks_init_dt(void)
{
struct device_node *np;
u32 fref = 26000000; /* default */
for_each_compatible_node(np, NULL, "fixed-clock") {
if (!of_device_is_compatible(np, "fsl,imx-osc26m"))
continue;
if (!of_property_read_u32(np, "clock-frequency", &fref))
break;
}
return mx27_clocks_init(fref);
}
#endif

View File

@ -0,0 +1,182 @@
/*
* 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;
}

View File

@ -0,0 +1,278 @@
/*
* Copyright (C) 2012 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
*
* 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.
*
*/
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/err.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include "crmregs-imx3.h"
#include "clk.h"
struct arm_ahb_div {
unsigned char arm, ahb, sel;
};
static struct arm_ahb_div clk_consumer[] = {
{ .arm = 1, .ahb = 4, .sel = 0},
{ .arm = 1, .ahb = 3, .sel = 1},
{ .arm = 2, .ahb = 2, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 4, .ahb = 1, .sel = 0},
{ .arm = 1, .ahb = 5, .sel = 0},
{ .arm = 1, .ahb = 8, .sel = 0},
{ .arm = 1, .ahb = 6, .sel = 1},
{ .arm = 2, .ahb = 4, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 4, .ahb = 2, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
};
static char hsp_div_532[] = { 4, 8, 3, 0 };
static char hsp_div_400[] = { 3, 6, 3, 0 };
static const char *std_sel[] = {"ppll", "arm"};
static const char *ipg_per_sel[] = {"ahb_per_div", "arm_per_div"};
enum mx35_clks {
ckih, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg,
arm_per_div, ahb_per_div, ipg_per, uart_sel, uart_div, esdhc_sel,
esdhc1_div, esdhc2_div, esdhc3_div, spdif_sel, spdif_div_pre,
spdif_div_post, ssi_sel, ssi1_div_pre, ssi1_div_post, ssi2_div_pre,
ssi2_div_post, usb_sel, usb_div, nfc_div, asrc_gate, pata_gate,
audmux_gate, can1_gate, can2_gate, cspi1_gate, cspi2_gate, ect_gate,
edio_gate, emi_gate, epit1_gate, epit2_gate, esai_gate, esdhc1_gate,
esdhc2_gate, esdhc3_gate, fec_gate, gpio1_gate, gpio2_gate, gpio3_gate,
gpt_gate, i2c1_gate, i2c2_gate, i2c3_gate, iomuxc_gate, ipu_gate,
kpp_gate, mlb_gate, mshc_gate, owire_gate, pwm_gate, rngc_gate,
rtc_gate, rtic_gate, scc_gate, sdma_gate, spba_gate, spdif_gate,
ssi1_gate, ssi2_gate, uart1_gate, uart2_gate, uart3_gate, usbotg_gate,
wdog_gate, max_gate, admux_gate, csi_gate, iim_gate, gpu2d_gate,
clk_max
};
static struct clk *clk[clk_max];
int __init mx35_clocks_init()
{
void __iomem *base = MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR);
u32 pdr0, consumer_sel, hsp_sel;
struct arm_ahb_div *aad;
unsigned char *hsp_div;
int i;
pdr0 = __raw_readl(base + MXC_CCM_PDR0);
consumer_sel = (pdr0 >> 16) & 0xf;
aad = &clk_consumer[consumer_sel];
if (!aad->arm) {
pr_err("i.MX35 clk: illegal consumer mux selection 0x%x\n", consumer_sel);
/*
* We are basically stuck. Continue with a default entry and hope we
* get far enough to actually show the above message
*/
aad = &clk_consumer[0];
}
clk[ckih] = imx_clk_fixed("ckih", 24000000);
clk[mpll] = imx_clk_pllv1("mpll", "ckih", base + MX35_CCM_MPCTL);
clk[ppll] = imx_clk_pllv1("ppll", "ckih", base + MX35_CCM_PPCTL);
clk[mpll] = imx_clk_fixed_factor("mpll_075", "mpll", 3, 4);
if (aad->sel)
clk[arm] = imx_clk_fixed_factor("arm", "mpll_075", 1, aad->arm);
else
clk[arm] = imx_clk_fixed_factor("arm", "mpll", 1, aad->arm);
if (clk_get_rate(clk[arm]) > 400000000)
hsp_div = hsp_div_532;
else
hsp_div = hsp_div_400;
hsp_sel = (pdr0 >> 20) & 0x3;
if (!hsp_div[hsp_sel]) {
pr_err("i.MX35 clk: illegal hsp clk selection 0x%x\n", hsp_sel);
hsp_sel = 0;
}
clk[hsp] = imx_clk_fixed_factor("hsp", "arm", 1, hsp_div[hsp_sel]);
clk[ahb] = imx_clk_fixed_factor("ahb", "arm", 1, aad->ahb);
clk[ipg] = imx_clk_fixed_factor("ipg", "ahb", 1, 2);
clk[arm_per_div] = imx_clk_divider("arm_per_div", "arm", base + MX35_CCM_PDR4, 16, 6);
clk[ahb_per_div] = imx_clk_divider("ahb_per_div", "ahb", base + MXC_CCM_PDR0, 12, 3);
clk[ipg_per] = imx_clk_mux("ipg_per", base + MXC_CCM_PDR0, 26, 1, ipg_per_sel, ARRAY_SIZE(ipg_per_sel));
clk[uart_sel] = imx_clk_mux("uart_sel", base + MX35_CCM_PDR3, 14, 1, std_sel, ARRAY_SIZE(std_sel));
clk[uart_div] = imx_clk_divider("uart_div", "uart_sel", base + MX35_CCM_PDR4, 10, 6);
clk[esdhc_sel] = imx_clk_mux("esdhc_sel", base + MX35_CCM_PDR4, 9, 1, std_sel, ARRAY_SIZE(std_sel));
clk[esdhc1_div] = imx_clk_divider("esdhc1_div", "esdhc_sel", base + MX35_CCM_PDR3, 0, 6);
clk[esdhc2_div] = imx_clk_divider("esdhc2_div", "esdhc_sel", base + MX35_CCM_PDR3, 8, 6);
clk[esdhc3_div] = imx_clk_divider("esdhc3_div", "esdhc_sel", base + MX35_CCM_PDR3, 16, 6);
clk[spdif_sel] = imx_clk_mux("spdif_sel", base + MX35_CCM_PDR3, 22, 1, std_sel, ARRAY_SIZE(std_sel));
clk[spdif_div_pre] = imx_clk_divider("spdif_div_pre", "spdif_sel", base + MX35_CCM_PDR3, 29, 3); /* divide by 1 not allowed */
clk[spdif_div_post] = imx_clk_divider("spdif_div_post", "spdif_div_pre", base + MX35_CCM_PDR3, 23, 6);
clk[ssi_sel] = imx_clk_mux("ssi_sel", base + MX35_CCM_PDR2, 6, 1, std_sel, ARRAY_SIZE(std_sel));
clk[ssi1_div_pre] = imx_clk_divider("ssi1_div_pre", "ssi_sel", base + MX35_CCM_PDR2, 24, 3);
clk[ssi1_div_post] = imx_clk_divider("ssi1_div_post", "ssi1_div_pre", base + MX35_CCM_PDR2, 0, 6);
clk[ssi2_div_pre] = imx_clk_divider("ssi2_div_pre", "ssi_sel", base + MX35_CCM_PDR2, 27, 3);
clk[ssi2_div_post] = imx_clk_divider("ssi2_div_post", "ssi2_div_pre", base + MX35_CCM_PDR2, 8, 6);
clk[usb_sel] = imx_clk_mux("usb_sel", base + MX35_CCM_PDR4, 9, 1, std_sel, ARRAY_SIZE(std_sel));
clk[usb_div] = imx_clk_divider("usb_div", "usb_sel", base + MX35_CCM_PDR4, 22, 6);
clk[nfc_div] = imx_clk_divider("nfc_div", "ahb", base + MX35_CCM_PDR4, 28, 4);
clk[asrc_gate] = imx_clk_gate2("asrc_gate", "ipg", base + MX35_CCM_CGR0, 0);
clk[pata_gate] = imx_clk_gate2("pata_gate", "ipg", base + MX35_CCM_CGR0, 2);
clk[audmux_gate] = imx_clk_gate2("audmux_gate", "ipg", base + MX35_CCM_CGR0, 4);
clk[can1_gate] = imx_clk_gate2("can1_gate", "ipg", base + MX35_CCM_CGR0, 6);
clk[can2_gate] = imx_clk_gate2("can2_gate", "ipg", base + MX35_CCM_CGR0, 8);
clk[cspi1_gate] = imx_clk_gate2("cspi1_gate", "ipg", base + MX35_CCM_CGR0, 10);
clk[cspi2_gate] = imx_clk_gate2("cspi2_gate", "ipg", base + MX35_CCM_CGR0, 12);
clk[ect_gate] = imx_clk_gate2("ect_gate", "ipg", base + MX35_CCM_CGR0, 14);
clk[edio_gate] = imx_clk_gate2("edio_gate", "ipg", base + MX35_CCM_CGR0, 16);
clk[emi_gate] = imx_clk_gate2("emi_gate", "ipg", base + MX35_CCM_CGR0, 18);
clk[epit1_gate] = imx_clk_gate2("epit1_gate", "ipg", base + MX35_CCM_CGR0, 20);
clk[epit2_gate] = imx_clk_gate2("epit2_gate", "ipg", base + MX35_CCM_CGR0, 22);
clk[esai_gate] = imx_clk_gate2("esai_gate", "ipg", base + MX35_CCM_CGR0, 24);
clk[esdhc1_gate] = imx_clk_gate2("esdhc1_gate", "esdhc1_div", base + MX35_CCM_CGR0, 26);
clk[esdhc2_gate] = imx_clk_gate2("esdhc2_gate", "esdhc2_div", base + MX35_CCM_CGR0, 28);
clk[esdhc3_gate] = imx_clk_gate2("esdhc3_gate", "esdhc3_div", base + MX35_CCM_CGR0, 30);
clk[fec_gate] = imx_clk_gate2("fec_gate", "ipg", base + MX35_CCM_CGR1, 0);
clk[gpio1_gate] = imx_clk_gate2("gpio1_gate", "ipg", base + MX35_CCM_CGR1, 2);
clk[gpio2_gate] = imx_clk_gate2("gpio2_gate", "ipg", base + MX35_CCM_CGR1, 4);
clk[gpio3_gate] = imx_clk_gate2("gpio3_gate", "ipg", base + MX35_CCM_CGR1, 6);
clk[gpt_gate] = imx_clk_gate2("gpt_gate", "ipg", base + MX35_CCM_CGR1, 8);
clk[i2c1_gate] = imx_clk_gate2("i2c1_gate", "ipg_per", base + MX35_CCM_CGR1, 10);
clk[i2c2_gate] = imx_clk_gate2("i2c2_gate", "ipg_per", base + MX35_CCM_CGR1, 12);
clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "ipg_per", base + MX35_CCM_CGR1, 14);
clk[iomuxc_gate] = imx_clk_gate2("iomuxc_gate", "ipg", base + MX35_CCM_CGR1, 16);
clk[ipu_gate] = imx_clk_gate2("ipu_gate", "hsp", base + MX35_CCM_CGR1, 18);
clk[kpp_gate] = imx_clk_gate2("kpp_gate", "ipg", base + MX35_CCM_CGR1, 20);
clk[mlb_gate] = imx_clk_gate2("mlb_gate", "ahb", base + MX35_CCM_CGR1, 22);
clk[mshc_gate] = imx_clk_gate2("mshc_gate", "dummy", base + MX35_CCM_CGR1, 24);
clk[owire_gate] = imx_clk_gate2("owire_gate", "ipg_per", base + MX35_CCM_CGR1, 26);
clk[pwm_gate] = imx_clk_gate2("pwm_gate", "ipg_per", base + MX35_CCM_CGR1, 28);
clk[rngc_gate] = imx_clk_gate2("rngc_gate", "ipg", base + MX35_CCM_CGR1, 30);
clk[rtc_gate] = imx_clk_gate2("rtc_gate", "ipg", base + MX35_CCM_CGR2, 0);
clk[rtic_gate] = imx_clk_gate2("rtic_gate", "ahb", base + MX35_CCM_CGR2, 2);
clk[scc_gate] = imx_clk_gate2("scc_gate", "ipg", base + MX35_CCM_CGR2, 4);
clk[sdma_gate] = imx_clk_gate2("sdma_gate", "ahb", base + MX35_CCM_CGR2, 6);
clk[spba_gate] = imx_clk_gate2("spba_gate", "ipg", base + MX35_CCM_CGR2, 8);
clk[spdif_gate] = imx_clk_gate2("spdif_gate", "spdif_div_post", base + MX35_CCM_CGR2, 10);
clk[ssi1_gate] = imx_clk_gate2("ssi1_gate", "ssi1_div_post", base + MX35_CCM_CGR2, 12);
clk[ssi2_gate] = imx_clk_gate2("ssi2_gate", "ssi2_div_post", base + MX35_CCM_CGR2, 14);
clk[uart1_gate] = imx_clk_gate2("uart1_gate", "uart_div", base + MX35_CCM_CGR2, 16);
clk[uart2_gate] = imx_clk_gate2("uart2_gate", "uart_div", base + MX35_CCM_CGR2, 18);
clk[uart3_gate] = imx_clk_gate2("uart3_gate", "uart_div", base + MX35_CCM_CGR2, 20);
clk[usbotg_gate] = imx_clk_gate2("usbotg_gate", "ahb", base + MX35_CCM_CGR2, 22);
clk[wdog_gate] = imx_clk_gate2("wdog_gate", "ipg", base + MX35_CCM_CGR2, 24);
clk[max_gate] = imx_clk_gate2("max_gate", "dummy", base + MX35_CCM_CGR2, 26);
clk[admux_gate] = imx_clk_gate2("admux_gate", "ipg", base + MX35_CCM_CGR2, 30);
clk[csi_gate] = imx_clk_gate2("csi_gate", "ipg", base + MX35_CCM_CGR3, 0);
clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", base + MX35_CCM_CGR3, 2);
clk[gpu2d_gate] = imx_clk_gate2("gpu2d_gate", "ahb", base + MX35_CCM_CGR3, 4);
for (i = 0; i < ARRAY_SIZE(clk); i++)
if (IS_ERR(clk[i]))
pr_err("i.MX35 clk %d: register failed with %ld\n",
i, PTR_ERR(clk[i]));
clk_register_clkdev(clk[pata_gate], NULL, "pata_imx");
clk_register_clkdev(clk[can1_gate], NULL, "flexcan.0");
clk_register_clkdev(clk[can2_gate], NULL, "flexcan.1");
clk_register_clkdev(clk[cspi1_gate], "per", "imx35-cspi.0");
clk_register_clkdev(clk[cspi1_gate], "ipg", "imx35-cspi.0");
clk_register_clkdev(clk[cspi2_gate], "per", "imx35-cspi.1");
clk_register_clkdev(clk[cspi2_gate], "ipg", "imx35-cspi.1");
clk_register_clkdev(clk[epit1_gate], NULL, "imx-epit.0");
clk_register_clkdev(clk[epit2_gate], NULL, "imx-epit.1");
clk_register_clkdev(clk[esdhc1_gate], "per", "sdhci-esdhc-imx35.0");
clk_register_clkdev(clk[ipg], "ipg", "sdhci-esdhc-imx35.0");
clk_register_clkdev(clk[ahb], "ahb", "sdhci-esdhc-imx35.0");
clk_register_clkdev(clk[esdhc2_gate], "per", "sdhci-esdhc-imx35.1");
clk_register_clkdev(clk[ipg], "ipg", "sdhci-esdhc-imx35.1");
clk_register_clkdev(clk[ahb], "ahb", "sdhci-esdhc-imx35.1");
clk_register_clkdev(clk[esdhc3_gate], "per", "sdhci-esdhc-imx35.2");
clk_register_clkdev(clk[ipg], "ipg", "sdhci-esdhc-imx35.2");
clk_register_clkdev(clk[ahb], "ahb", "sdhci-esdhc-imx35.2");
/* i.mx35 has the i.mx27 type fec */
clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0");
clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
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[ipu_gate], NULL, "ipu-core");
clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb");
clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1");
clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma");
clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.0");
clk_register_clkdev(clk[ssi1_div_post], "per", "imx-ssi.0");
clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.1");
clk_register_clkdev(clk[ssi2_div_post], "per", "imx-ssi.1");
/* i.mx35 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[usb_div], "per", "mxc-ehci.0");
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0");
clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.0");
clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.1");
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.1");
clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.1");
clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.2");
clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
clk_register_clkdev(clk[usbotg_gate], "ahb", "fsl-usb2-udc");
clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
clk_register_clkdev(clk[nfc_div], NULL, "mxc_nand.0");
clk_prepare_enable(clk[spba_gate]);
clk_prepare_enable(clk[gpio1_gate]);
clk_prepare_enable(clk[gpio2_gate]);
clk_prepare_enable(clk[gpio3_gate]);
clk_prepare_enable(clk[iim_gate]);
clk_prepare_enable(clk[emi_gate]);
imx_print_silicon_rev("i.MX35", mx35_revision());
#ifdef CONFIG_MXC_USE_EPIT
epit_timer_init(&epit1_clk,
MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1);
#else
mxc_timer_init(NULL, MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR),
MX35_INT_GPT);
#endif
return 0;
}

View File

@ -0,0 +1,466 @@
/*
* Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
*
* 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.
*
*/
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/err.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include "crm-regs-imx5.h"
#include "clk.h"
/* Low-power Audio Playback Mode clock */
static const char *lp_apm_sel[] = { "osc", };
/* This is used multiple times */
static const char *standard_pll_sel[] = { "pll1_sw", "pll2_sw", "pll3_sw", "lp_apm", };
static const char *periph_apm_sel[] = { "pll1_sw", "pll3_sw", "lp_apm", };
static const char *main_bus_sel[] = { "pll2_sw", "periph_apm", };
static const char *per_lp_apm_sel[] = { "main_bus", "lp_apm", };
static const char *per_root_sel[] = { "per_podf", "ipg", };
static const char *esdhc_c_sel[] = { "esdhc_a_podf", "esdhc_b_podf", };
static const char *esdhc_d_sel[] = { "esdhc_a_podf", "esdhc_b_podf", };
static const char *emi_slow_sel[] = { "main_bus", "ahb", };
static const char *usb_phy_sel_str[] = { "osc", "usb_phy_podf", };
static const char *mx51_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "tve_di", };
static const char *mx53_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "di_pll4_podf", "dummy", "ldb_di0", };
static const char *mx53_ldb_di0_sel[] = { "pll3_sw", "pll4_sw", };
static const char *mx51_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", };
static const char *mx53_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", "ldb_di1", };
static const char *mx53_ldb_di1_sel[] = { "pll3_sw", "pll4_sw", };
static const char *mx51_tve_ext_sel[] = { "osc", "ckih1", };
static const char *mx53_tve_ext_sel[] = { "pll4_sw", "ckih1", };
static const char *tve_sel[] = { "tve_pred", "tve_ext_sel", };
static const char *ipu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
static const char *vpu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
enum imx5_clks {
dummy, ckil, osc, ckih1, ckih2, ahb, ipg, axi_a, axi_b, uart_pred,
uart_root, esdhc_a_pred, esdhc_b_pred, esdhc_c_s, esdhc_d_s,
emi_sel, emi_slow_podf, nfc_podf, ecspi_pred, ecspi_podf, usboh3_pred,
usboh3_podf, usb_phy_pred, usb_phy_podf, cpu_podf, di_pred, tve_di,
tve_s, uart1_ipg_gate, uart1_per_gate, uart2_ipg_gate,
uart2_per_gate, uart3_ipg_gate, uart3_per_gate, i2c1_gate, i2c2_gate,
gpt_ipg_gate, pwm1_ipg_gate, pwm1_hf_gate, pwm2_ipg_gate, pwm2_hf_gate,
gpt_gate, fec_gate, usboh3_per_gate, esdhc1_ipg_gate, esdhc2_ipg_gate,
esdhc3_ipg_gate, esdhc4_ipg_gate, ssi1_ipg_gate, ssi2_ipg_gate,
ssi3_ipg_gate, ecspi1_ipg_gate, ecspi1_per_gate, ecspi2_ipg_gate,
ecspi2_per_gate, cspi_ipg_gate, sdma_gate, emi_slow_gate, ipu_s,
ipu_gate, nfc_gate, ipu_di1_gate, vpu_s, vpu_gate,
vpu_reference_gate, uart4_ipg_gate, uart4_per_gate, uart5_ipg_gate,
uart5_per_gate, tve_gate, tve_pred, esdhc1_per_gate, esdhc2_per_gate,
esdhc3_per_gate, esdhc4_per_gate, usb_phy_gate, hsi2c_gate,
mipi_hsc1_gate, mipi_hsc2_gate, mipi_esc_gate, mipi_hsp_gate,
ldb_di1_div_3_5, ldb_di1_div, ldb_di0_div_3_5, ldb_di0_div,
ldb_di1_gate, can2_serial_gate, can2_ipg_gate, i2c3_gate, lp_apm,
periph_apm, main_bus, ahb_max, aips_tz1, aips_tz2, tmax1, tmax2,
tmax3, spba, uart_sel, esdhc_a_sel, esdhc_b_sel, esdhc_a_podf,
esdhc_b_podf, ecspi_sel, usboh3_sel, usb_phy_sel, iim_gate,
usboh3_gate, emi_fast_gate, ipu_di0_gate,gpc_dvfs, pll1_sw, pll2_sw,
pll3_sw, ipu_di0_sel, ipu_di1_sel, tve_ext_sel, mx51_mipi, pll4_sw,
ldb_di1_sel, di_pll4_podf, ldb_di0_sel, ldb_di0_gate, usb_phy1_gate,
usb_phy2_gate, per_lp_apm, per_pred1, per_pred2, per_podf, per_root,
clk_max
};
static struct clk *clk[clk_max];
static void __init mx5_clocks_common_init(unsigned long rate_ckil,
unsigned long rate_osc, unsigned long rate_ckih1,
unsigned long rate_ckih2)
{
int i;
clk[dummy] = imx_clk_fixed("dummy", 0);
clk[ckil] = imx_clk_fixed("ckil", rate_ckil);
clk[osc] = imx_clk_fixed("osc", rate_osc);
clk[ckih1] = imx_clk_fixed("ckih1", rate_ckih1);
clk[ckih2] = imx_clk_fixed("ckih2", rate_ckih2);
clk[lp_apm] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1,
lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
clk[periph_apm] = imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2,
periph_apm_sel, ARRAY_SIZE(periph_apm_sel));
clk[main_bus] = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1,
main_bus_sel, ARRAY_SIZE(main_bus_sel));
clk[per_lp_apm] = imx_clk_mux("per_lp_apm", MXC_CCM_CBCDR, 1, 1,
per_lp_apm_sel, ARRAY_SIZE(per_lp_apm_sel));
clk[per_pred1] = imx_clk_divider("per_pred1", "per_lp_apm", MXC_CCM_CBCDR, 6, 2);
clk[per_pred2] = imx_clk_divider("per_pred2", "per_pred1", MXC_CCM_CBCDR, 3, 3);
clk[per_podf] = imx_clk_divider("per_podf", "per_pred2", MXC_CCM_CBCDR, 0, 3);
clk[per_root] = imx_clk_mux("per_root", MXC_CCM_CBCDR, 1, 0,
per_root_sel, ARRAY_SIZE(per_root_sel));
clk[ahb] = imx_clk_divider("ahb", "main_bus", MXC_CCM_CBCDR, 10, 3);
clk[ahb_max] = imx_clk_gate2("ahb_max", "ahb", MXC_CCM_CCGR0, 28);
clk[aips_tz1] = imx_clk_gate2("aips_tz1", "ahb", MXC_CCM_CCGR0, 24);
clk[aips_tz2] = imx_clk_gate2("aips_tz2", "ahb", MXC_CCM_CCGR0, 26);
clk[tmax1] = imx_clk_gate2("tmax1", "ahb", MXC_CCM_CCGR1, 0);
clk[tmax2] = imx_clk_gate2("tmax2", "ahb", MXC_CCM_CCGR1, 2);
clk[tmax3] = imx_clk_gate2("tmax3", "ahb", MXC_CCM_CCGR1, 4);
clk[spba] = imx_clk_gate2("spba", "ipg", MXC_CCM_CCGR5, 0);
clk[ipg] = imx_clk_divider("ipg", "ahb", MXC_CCM_CBCDR, 8, 2);
clk[axi_a] = imx_clk_divider("axi_a", "main_bus", MXC_CCM_CBCDR, 16, 3);
clk[axi_b] = imx_clk_divider("axi_b", "main_bus", MXC_CCM_CBCDR, 19, 3);
clk[uart_sel] = imx_clk_mux("uart_sel", MXC_CCM_CSCMR1, 24, 2,
standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
clk[uart_pred] = imx_clk_divider("uart_pred", "uart_sel", MXC_CCM_CSCDR1, 3, 3);
clk[uart_root] = imx_clk_divider("uart_root", "uart_pred", MXC_CCM_CSCDR1, 0, 3);
clk[esdhc_a_sel] = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2,
standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
clk[esdhc_b_sel] = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2,
standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
clk[esdhc_a_pred] = imx_clk_divider("esdhc_a_pred", "esdhc_a_sel", MXC_CCM_CSCDR1, 16, 3);
clk[esdhc_a_podf] = imx_clk_divider("esdhc_a_podf", "esdhc_a_pred", MXC_CCM_CSCDR1, 11, 3);
clk[esdhc_b_pred] = imx_clk_divider("esdhc_b_pred", "esdhc_b_sel", MXC_CCM_CSCDR1, 22, 3);
clk[esdhc_b_podf] = imx_clk_divider("esdhc_b_podf", "esdhc_b_pred", MXC_CCM_CSCDR1, 19, 3);
clk[esdhc_c_s] = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel));
clk[esdhc_d_s] = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel));
clk[emi_sel] = imx_clk_mux("emi_sel", MXC_CCM_CBCDR, 26, 1,
emi_slow_sel, ARRAY_SIZE(emi_slow_sel));
clk[emi_slow_podf] = imx_clk_divider("emi_slow_podf", "emi_sel", MXC_CCM_CBCDR, 22, 3);
clk[nfc_podf] = imx_clk_divider("nfc_podf", "emi_slow_podf", MXC_CCM_CBCDR, 13, 3);
clk[ecspi_sel] = imx_clk_mux("ecspi_sel", MXC_CCM_CSCMR1, 4, 2,
standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
clk[ecspi_pred] = imx_clk_divider("ecspi_pred", "ecspi_sel", MXC_CCM_CSCDR2, 25, 3);
clk[ecspi_podf] = imx_clk_divider("ecspi_podf", "ecspi_pred", MXC_CCM_CSCDR2, 19, 6);
clk[usboh3_sel] = imx_clk_mux("usboh3_sel", MXC_CCM_CSCMR1, 22, 2,
standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
clk[usboh3_pred] = imx_clk_divider("usboh3_pred", "usboh3_sel", MXC_CCM_CSCDR1, 8, 3);
clk[usboh3_podf] = imx_clk_divider("usboh3_podf", "usboh3_pred", MXC_CCM_CSCDR1, 6, 2);
clk[usb_phy_pred] = imx_clk_divider("usb_phy_pred", "pll3_sw", MXC_CCM_CDCDR, 3, 3);
clk[usb_phy_podf] = imx_clk_divider("usb_phy_podf", "usb_phy_pred", MXC_CCM_CDCDR, 0, 3);
clk[usb_phy_sel] = imx_clk_mux("usb_phy_sel", MXC_CCM_CSCMR1, 26, 1,
usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str));
clk[cpu_podf] = imx_clk_divider("cpu_podf", "pll1_sw", MXC_CCM_CACRR, 0, 3);
clk[di_pred] = imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3);
clk[tve_di] = imx_clk_fixed("tve_di", 65000000); /* FIXME */
clk[tve_s] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1, tve_sel, ARRAY_SIZE(tve_sel));
clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30);
clk[uart1_ipg_gate] = imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6);
clk[uart1_per_gate] = imx_clk_gate2("uart1_per_gate", "uart_root", MXC_CCM_CCGR1, 8);
clk[uart2_ipg_gate] = imx_clk_gate2("uart2_ipg_gate", "ipg", MXC_CCM_CCGR1, 10);
clk[uart2_per_gate] = imx_clk_gate2("uart2_per_gate", "uart_root", MXC_CCM_CCGR1, 12);
clk[uart3_ipg_gate] = imx_clk_gate2("uart3_ipg_gate", "ipg", MXC_CCM_CCGR1, 14);
clk[uart3_per_gate] = imx_clk_gate2("uart3_per_gate", "uart_root", MXC_CCM_CCGR1, 16);
clk[i2c1_gate] = imx_clk_gate2("i2c1_gate", "per_root", MXC_CCM_CCGR1, 18);
clk[i2c2_gate] = imx_clk_gate2("i2c2_gate", "per_root", MXC_CCM_CCGR1, 20);
clk[gpt_ipg_gate] = imx_clk_gate2("gpt_ipg_gate", "ipg", MXC_CCM_CCGR2, 20);
clk[pwm1_ipg_gate] = imx_clk_gate2("pwm1_ipg_gate", "ipg", MXC_CCM_CCGR2, 10);
clk[pwm1_hf_gate] = imx_clk_gate2("pwm1_hf_gate", "ipg", MXC_CCM_CCGR2, 12);
clk[pwm2_ipg_gate] = imx_clk_gate2("pwm2_ipg_gate", "ipg", MXC_CCM_CCGR2, 14);
clk[pwm2_hf_gate] = imx_clk_gate2("pwm2_hf_gate", "ipg", MXC_CCM_CCGR2, 16);
clk[gpt_gate] = imx_clk_gate2("gpt_gate", "ipg", MXC_CCM_CCGR2, 18);
clk[fec_gate] = imx_clk_gate2("fec_gate", "ipg", MXC_CCM_CCGR2, 24);
clk[usboh3_gate] = imx_clk_gate2("usboh3_gate", "ipg", MXC_CCM_CCGR2, 26);
clk[usboh3_per_gate] = imx_clk_gate2("usboh3_per_gate", "usboh3_podf", MXC_CCM_CCGR2, 28);
clk[esdhc1_ipg_gate] = imx_clk_gate2("esdhc1_ipg_gate", "ipg", MXC_CCM_CCGR3, 0);
clk[esdhc2_ipg_gate] = imx_clk_gate2("esdhc2_ipg_gate", "ipg", MXC_CCM_CCGR3, 4);
clk[esdhc3_ipg_gate] = imx_clk_gate2("esdhc3_ipg_gate", "ipg", MXC_CCM_CCGR3, 8);
clk[esdhc4_ipg_gate] = imx_clk_gate2("esdhc4_ipg_gate", "ipg", MXC_CCM_CCGR3, 12);
clk[ssi1_ipg_gate] = imx_clk_gate2("ssi1_ipg_gate", "ipg", MXC_CCM_CCGR3, 16);
clk[ssi2_ipg_gate] = imx_clk_gate2("ssi2_ipg_gate", "ipg", MXC_CCM_CCGR3, 20);
clk[ssi3_ipg_gate] = imx_clk_gate2("ssi3_ipg_gate", "ipg", MXC_CCM_CCGR3, 24);
clk[ecspi1_ipg_gate] = imx_clk_gate2("ecspi1_ipg_gate", "ipg", MXC_CCM_CCGR4, 18);
clk[ecspi1_per_gate] = imx_clk_gate2("ecspi1_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 20);
clk[ecspi2_ipg_gate] = imx_clk_gate2("ecspi2_ipg_gate", "ipg", MXC_CCM_CCGR4, 22);
clk[ecspi2_per_gate] = imx_clk_gate2("ecspi2_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 24);
clk[cspi_ipg_gate] = imx_clk_gate2("cspi_ipg_gate", "ipg", MXC_CCM_CCGR4, 26);
clk[sdma_gate] = imx_clk_gate2("sdma_gate", "ipg", MXC_CCM_CCGR4, 30);
clk[emi_fast_gate] = imx_clk_gate2("emi_fast_gate", "dummy", MXC_CCM_CCGR5, 14);
clk[emi_slow_gate] = imx_clk_gate2("emi_slow_gate", "emi_slow_podf", MXC_CCM_CCGR5, 16);
clk[ipu_s] = imx_clk_mux("ipu_sel", MXC_CCM_CBCMR, 6, 2, ipu_sel, ARRAY_SIZE(ipu_sel));
clk[ipu_gate] = imx_clk_gate2("ipu_gate", "ipu_sel", MXC_CCM_CCGR5, 10);
clk[nfc_gate] = imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20);
clk[ipu_di0_gate] = imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10);
clk[ipu_di1_gate] = imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12);
clk[vpu_s] = imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel));
clk[vpu_gate] = imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6);
clk[vpu_reference_gate] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8);
clk[uart4_ipg_gate] = imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
clk[uart4_per_gate] = imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
clk[uart5_ipg_gate] = imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
clk[uart5_per_gate] = imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
clk[gpc_dvfs] = imx_clk_gate2("gpc_dvfs", "dummy", MXC_CCM_CCGR5, 24);
for (i = 0; i < ARRAY_SIZE(clk); i++)
if (IS_ERR(clk[i]))
pr_err("i.MX5 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[gpt_ipg_gate], "ipg", "imx-gpt.0");
clk_register_clkdev(clk[uart1_per_gate], "per", "imx21-uart.0");
clk_register_clkdev(clk[uart1_ipg_gate], "ipg", "imx21-uart.0");
clk_register_clkdev(clk[uart2_per_gate], "per", "imx21-uart.1");
clk_register_clkdev(clk[uart2_ipg_gate], "ipg", "imx21-uart.1");
clk_register_clkdev(clk[uart3_per_gate], "per", "imx21-uart.2");
clk_register_clkdev(clk[uart3_ipg_gate], "ipg", "imx21-uart.2");
clk_register_clkdev(clk[uart4_per_gate], "per", "imx21-uart.3");
clk_register_clkdev(clk[uart4_ipg_gate], "ipg", "imx21-uart.3");
clk_register_clkdev(clk[uart5_per_gate], "per", "imx21-uart.4");
clk_register_clkdev(clk[uart5_ipg_gate], "ipg", "imx21-uart.4");
clk_register_clkdev(clk[ecspi1_per_gate], "per", "imx51-ecspi.0");
clk_register_clkdev(clk[ecspi1_ipg_gate], "ipg", "imx51-ecspi.0");
clk_register_clkdev(clk[ecspi2_per_gate], "per", "imx51-ecspi.1");
clk_register_clkdev(clk[ecspi2_ipg_gate], "ipg", "imx51-ecspi.1");
clk_register_clkdev(clk[cspi_ipg_gate], NULL, "imx51-cspi.0");
clk_register_clkdev(clk[pwm1_ipg_gate], "pwm", "mxc_pwm.0");
clk_register_clkdev(clk[pwm2_ipg_gate], "pwm", "mxc_pwm.1");
clk_register_clkdev(clk[i2c1_gate], NULL, "imx-i2c.0");
clk_register_clkdev(clk[i2c2_gate], NULL, "imx-i2c.1");
clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.0");
clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.0");
clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.0");
clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.1");
clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.1");
clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.1");
clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.2");
clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.2");
clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.2");
clk_register_clkdev(clk[usboh3_per_gate], "per", "fsl-usb2-udc");
clk_register_clkdev(clk[usboh3_gate], "ipg", "fsl-usb2-udc");
clk_register_clkdev(clk[usboh3_gate], "ahb", "fsl-usb2-udc");
clk_register_clkdev(clk[nfc_gate], NULL, "mxc_nand");
clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "imx-ssi.2");
clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma");
clk_register_clkdev(clk[cpu_podf], "cpu", NULL);
clk_register_clkdev(clk[iim_gate], "iim", NULL);
clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.0");
clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.1");
clk_register_clkdev(clk[dummy], NULL, "imx-keypad");
clk_register_clkdev(clk[tve_gate], NULL, "imx-tve.0");
clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx-tve.0");
/* Set SDHC parents to be PLL2 */
clk_set_parent(clk[esdhc_a_sel], clk[pll2_sw]);
clk_set_parent(clk[esdhc_b_sel], clk[pll2_sw]);
/* move usb phy clk to 24MHz */
clk_set_parent(clk[usb_phy_sel], clk[osc]);
clk_prepare_enable(clk[gpc_dvfs]);
clk_prepare_enable(clk[ahb_max]); /* esdhc3 */
clk_prepare_enable(clk[aips_tz1]);
clk_prepare_enable(clk[aips_tz2]); /* fec */
clk_prepare_enable(clk[spba]);
clk_prepare_enable(clk[emi_fast_gate]); /* fec */
clk_prepare_enable(clk[tmax1]);
clk_prepare_enable(clk[tmax2]); /* esdhc2, fec */
clk_prepare_enable(clk[tmax3]); /* esdhc1, esdhc4 */
}
int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
unsigned long rate_ckih1, unsigned long rate_ckih2)
{
int i;
clk[pll1_sw] = imx_clk_pllv2("pll1_sw", "osc", MX51_DPLL1_BASE);
clk[pll2_sw] = imx_clk_pllv2("pll2_sw", "osc", MX51_DPLL2_BASE);
clk[pll3_sw] = imx_clk_pllv2("pll3_sw", "osc", MX51_DPLL3_BASE);
clk[ipu_di0_sel] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel));
clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel));
clk[tve_ext_sel] = imx_clk_mux("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel));
clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30);
clk[tve_pred] = imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3);
clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
clk[esdhc2_per_gate] = imx_clk_gate2("esdhc2_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 6);
clk[esdhc3_per_gate] = imx_clk_gate2("esdhc3_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 10);
clk[esdhc4_per_gate] = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
clk[usb_phy_gate] = imx_clk_gate2("usb_phy_gate", "usb_phy_sel", MXC_CCM_CCGR2, 0);
clk[hsi2c_gate] = imx_clk_gate2("hsi2c_gate", "ipg", MXC_CCM_CCGR1, 22);
clk[mipi_hsc1_gate] = imx_clk_gate2("mipi_hsc1_gate", "ipg", MXC_CCM_CCGR4, 6);
clk[mipi_hsc2_gate] = imx_clk_gate2("mipi_hsc2_gate", "ipg", MXC_CCM_CCGR4, 8);
clk[mipi_esc_gate] = imx_clk_gate2("mipi_esc_gate", "ipg", MXC_CCM_CCGR4, 10);
clk[mipi_hsp_gate] = imx_clk_gate2("mipi_hsp_gate", "ipg", MXC_CCM_CCGR4, 12);
for (i = 0; i < ARRAY_SIZE(clk); i++)
if (IS_ERR(clk[i]))
pr_err("i.MX51 clk %d: register failed with %ld\n",
i, PTR_ERR(clk[i]));
mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
clk_register_clkdev(clk[hsi2c_gate], NULL, "imx-i2c.2");
clk_register_clkdev(clk[mx51_mipi], "mipi_hsp", NULL);
clk_register_clkdev(clk[vpu_gate], NULL, "imx51-vpu.0");
clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0");
clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL);
clk_register_clkdev(clk[ipu_gate], "bus", "imx51-ipu");
clk_register_clkdev(clk[ipu_di0_gate], "di0", "imx51-ipu");
clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx51-ipu");
clk_register_clkdev(clk[ipu_gate], "hsp", "imx51-ipu");
clk_register_clkdev(clk[usb_phy_gate], "phy", "mxc-ehci.0");
clk_register_clkdev(clk[esdhc1_ipg_gate], "ipg", "sdhci-esdhc-imx51.0");
clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx51.0");
clk_register_clkdev(clk[esdhc1_per_gate], "per", "sdhci-esdhc-imx51.0");
clk_register_clkdev(clk[esdhc2_ipg_gate], "ipg", "sdhci-esdhc-imx51.1");
clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx51.1");
clk_register_clkdev(clk[esdhc2_per_gate], "per", "sdhci-esdhc-imx51.1");
clk_register_clkdev(clk[esdhc3_ipg_gate], "ipg", "sdhci-esdhc-imx51.2");
clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx51.2");
clk_register_clkdev(clk[esdhc3_per_gate], "per", "sdhci-esdhc-imx51.2");
clk_register_clkdev(clk[esdhc4_ipg_gate], "ipg", "sdhci-esdhc-imx51.3");
clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx51.3");
clk_register_clkdev(clk[esdhc4_per_gate], "per", "sdhci-esdhc-imx51.3");
/* set the usboh3 parent to pll2_sw */
clk_set_parent(clk[usboh3_sel], clk[pll2_sw]);
/* set SDHC root clock to 166.25MHZ*/
clk_set_rate(clk[esdhc_a_podf], 166250000);
clk_set_rate(clk[esdhc_b_podf], 166250000);
/* System timer */
mxc_timer_init(NULL, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
MX51_INT_GPT);
clk_prepare_enable(clk[iim_gate]);
imx_print_silicon_rev("i.MX51", mx51_revision());
clk_disable_unprepare(clk[iim_gate]);
return 0;
}
int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
unsigned long rate_ckih1, unsigned long rate_ckih2)
{
int i;
unsigned long r;
clk[pll1_sw] = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
clk[pll2_sw] = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
clk[pll3_sw] = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE);
clk[pll4_sw] = imx_clk_pllv2("pll4_sw", "osc", MX53_DPLL4_BASE);
clk[ldb_di1_sel] = imx_clk_mux("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1,
mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel));
clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
clk[ldb_di1_div] = imx_clk_divider("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1);
clk[di_pll4_podf] = imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3);
clk[ldb_di0_sel] = imx_clk_mux("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1,
mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel));
clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
clk[ldb_di0_div] = imx_clk_divider("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1);
clk[ldb_di0_gate] = imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28);
clk[ldb_di1_gate] = imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30);
clk[ipu_di0_sel] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel));
clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel));
clk[tve_ext_sel] = imx_clk_mux("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel));
clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30);
clk[tve_pred] = imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3);
clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
clk[esdhc2_per_gate] = imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6);
clk[esdhc3_per_gate] = imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10);
clk[esdhc4_per_gate] = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
clk[usb_phy1_gate] = imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
clk[usb_phy2_gate] = imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
clk[can2_serial_gate] = imx_clk_gate2("can2_serial_gate", "ipg", MXC_CCM_CCGR4, 6);
clk[can2_ipg_gate] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 8);
clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
for (i = 0; i < ARRAY_SIZE(clk); i++)
if (IS_ERR(clk[i]))
pr_err("i.MX53 clk %d: register failed with %ld\n",
i, PTR_ERR(clk[i]));
mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
clk_register_clkdev(clk[vpu_gate], NULL, "imx53-vpu.0");
clk_register_clkdev(clk[i2c3_gate], NULL, "imx-i2c.2");
clk_register_clkdev(clk[fec_gate], NULL, "imx25-fec.0");
clk_register_clkdev(clk[ipu_gate], "bus", "imx53-ipu");
clk_register_clkdev(clk[ipu_di0_gate], "di0", "imx53-ipu");
clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx53-ipu");
clk_register_clkdev(clk[ipu_gate], "hsp", "imx53-ipu");
clk_register_clkdev(clk[usb_phy1_gate], "usb_phy1", "mxc-ehci.0");
clk_register_clkdev(clk[esdhc1_ipg_gate], "ipg", "sdhci-esdhc-imx53.0");
clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx53.0");
clk_register_clkdev(clk[esdhc1_per_gate], "per", "sdhci-esdhc-imx53.0");
clk_register_clkdev(clk[esdhc2_ipg_gate], "ipg", "sdhci-esdhc-imx53.1");
clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx53.1");
clk_register_clkdev(clk[esdhc2_per_gate], "per", "sdhci-esdhc-imx53.1");
clk_register_clkdev(clk[esdhc3_ipg_gate], "ipg", "sdhci-esdhc-imx53.2");
clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx53.2");
clk_register_clkdev(clk[esdhc3_per_gate], "per", "sdhci-esdhc-imx53.2");
clk_register_clkdev(clk[esdhc4_ipg_gate], "ipg", "sdhci-esdhc-imx53.3");
clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx53.3");
clk_register_clkdev(clk[esdhc4_per_gate], "per", "sdhci-esdhc-imx53.3");
/* set SDHC root clock to 200MHZ*/
clk_set_rate(clk[esdhc_a_podf], 200000000);
clk_set_rate(clk[esdhc_b_podf], 200000000);
/* System timer */
mxc_timer_init(NULL, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
MX53_INT_GPT);
clk_prepare_enable(clk[iim_gate]);
imx_print_silicon_rev("i.MX53", mx53_revision());
clk_disable_unprepare(clk[iim_gate]);
r = clk_round_rate(clk[usboh3_per_gate], 54000000);
clk_set_rate(clk[usboh3_per_gate], r);
return 0;
}
#ifdef CONFIG_OF
static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
unsigned long *ckih1, unsigned long *ckih2)
{
struct device_node *np;
/* retrieve the freqency of fixed clocks from device tree */
for_each_compatible_node(np, NULL, "fixed-clock") {
u32 rate;
if (of_property_read_u32(np, "clock-frequency", &rate))
continue;
if (of_device_is_compatible(np, "fsl,imx-ckil"))
*ckil = rate;
else if (of_device_is_compatible(np, "fsl,imx-osc"))
*osc = rate;
else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
*ckih1 = rate;
else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
*ckih2 = rate;
}
}
int __init mx51_clocks_init_dt(void)
{
unsigned long ckil, osc, ckih1, ckih2;
clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
return mx51_clocks_init(ckil, osc, ckih1, ckih2);
}
int __init mx53_clocks_init_dt(void)
{
unsigned long ckil, osc, ckih1, ckih2;
clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
return mx53_clocks_init(ckil, osc, ckih1, ckih2);
}
#endif

View File

@ -0,0 +1,439 @@
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 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/init.h>
#include <linux/types.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <mach/common.h>
#include "clk.h"
#define CCGR0 0x68
#define CCGR1 0x6c
#define CCGR2 0x70
#define CCGR3 0x74
#define CCGR4 0x78
#define CCGR5 0x7c
#define CCGR6 0x80
#define CCGR7 0x84
#define CLPCR 0x54
#define BP_CLPCR_LPM 0
#define BM_CLPCR_LPM (0x3 << 0)
#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
#define BM_CLPCR_SBYOS (0x1 << 6)
#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
#define BM_CLPCR_VSTBY (0x1 << 8)
#define BP_CLPCR_STBY_COUNT 9
#define BM_CLPCR_STBY_COUNT (0x3 << 9)
#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
static void __iomem *ccm_base;
void __init imx6q_clock_map_io(void) { }
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
{
u32 val = readl_relaxed(ccm_base + CLPCR);
val &= ~BM_CLPCR_LPM;
switch (mode) {
case WAIT_CLOCKED:
break;
case WAIT_UNCLOCKED:
val |= 0x1 << BP_CLPCR_LPM;
break;
case STOP_POWER_ON:
val |= 0x2 << BP_CLPCR_LPM;
break;
case WAIT_UNCLOCKED_POWER_OFF:
val |= 0x1 << BP_CLPCR_LPM;
val &= ~BM_CLPCR_VSTBY;
val &= ~BM_CLPCR_SBYOS;
break;
case STOP_POWER_OFF:
val |= 0x2 << BP_CLPCR_LPM;
val |= 0x3 << BP_CLPCR_STBY_COUNT;
val |= BM_CLPCR_VSTBY;
val |= BM_CLPCR_SBYOS;
break;
default:
return -EINVAL;
}
writel_relaxed(val, ccm_base + CLPCR);
return 0;
}
static const char *step_sels[] = { "osc", "pll2_pfd2_396m", };
static const char *pll1_sw_sels[] = { "pll1_sys", "step", };
static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", };
static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
static const char *axi_sels[] = { "periph", "pll2_pfd2_396m", "pll3_pfd1_540m", };
static const char *audio_sels[] = { "pll4_audio", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
static const char *gpu_axi_sels[] = { "axi", "ahb", };
static const char *gpu2d_core_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", };
static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", };
static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
static const char *ldb_di_sels[] = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
static const char *ipu2_di0_sels[] = { "ipu2_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
static const char *ipu2_di1_sels[] = { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
static const char *hsi_tx_sels[] = { "pll3_120m", "pll2_pfd2_396m", };
static const char *pcie_axi_sels[] = { "axi", "ahb", };
static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio", };
static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", };
static const char *emi_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", };
static const char *vdo_axi_sels[] = { "axi", "ahb", };
static const char *vpu_axi_sels[] = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", };
static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video",
"dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
"ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio", };
static const char * const clks_init_on[] __initconst = {
"mmdc_ch0_axi", "mmdc_ch1_axi", "usboh3",
};
enum mx6q_clks {
dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
pll3_pfd0_720m, pll3_pfd1_540m, pll3_pfd2_508m, pll3_pfd3_454m,
pll2_198m, pll3_120m, pll3_80m, pll3_60m, twd, step, pll1_sw,
periph_pre, periph2_pre, periph_clk2_sel, periph2_clk2_sel, axi_sel,
esai_sel, asrc_sel, spdif_sel, gpu2d_axi, gpu3d_axi, gpu2d_core_sel,
gpu3d_core_sel, gpu3d_shader_sel, ipu1_sel, ipu2_sel, ldb_di0_sel,
ldb_di1_sel, ipu1_di0_pre_sel, ipu1_di1_pre_sel, ipu2_di0_pre_sel,
ipu2_di1_pre_sel, ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel,
ipu2_di1_sel, hsi_tx_sel, pcie_axi_sel, ssi1_sel, ssi2_sel, ssi3_sel,
usdhc1_sel, usdhc2_sel, usdhc3_sel, usdhc4_sel, enfc_sel, emi_sel,
emi_slow_sel, vdo_axi_sel, vpu_axi_sel, cko1_sel, periph, periph2,
periph_clk2, periph2_clk2, ipg, ipg_per, esai_pred, esai_podf,
asrc_pred, asrc_podf, spdif_pred, spdif_podf, can_root, ecspi_root,
gpu2d_core_podf, gpu3d_core_podf, gpu3d_shader, ipu1_podf, ipu2_podf,
ldb_di0_podf, ldb_di1_podf, ipu1_di0_pre, ipu1_di1_pre, ipu2_di0_pre,
ipu2_di1_pre, hsi_tx_podf, ssi1_pred, ssi1_podf, ssi2_pred, ssi2_podf,
ssi3_pred, ssi3_podf, uart_serial_podf, usdhc1_podf, usdhc2_podf,
usdhc3_podf, usdhc4_podf, enfc_pred, enfc_podf, emi_podf,
emi_slow_podf, vpu_axi_podf, cko1_podf, axi, mmdc_ch0_axi_podf,
mmdc_ch1_axi_podf, arm, ahb, apbh_dma, asrc, can1_ipg, can1_serial,
can2_ipg, can2_serial, ecspi1, ecspi2, ecspi3, ecspi4, ecspi5, enet,
esai, gpt_ipg, gpt_ipg_per, gpu2d_core, gpu3d_core, hdmi_iahb,
hdmi_isfr, i2c1, i2c2, i2c3, iim, enfc, ipu1, ipu1_di0, ipu1_di1, ipu2,
ipu2_di0, ldb_di0, ldb_di1, ipu2_di1, hsi_tx, mlb, mmdc_ch0_axi,
mmdc_ch1_axi, ocram, openvg_axi, pcie_axi, pwm1, pwm2, pwm3, pwm4,
gpmi_bch_apb, gpmi_bch, gpmi_io, gpmi_apb, sata, sdma, spba, ssi1,
ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3,
usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg,
pll4_audio, pll5_video, pll6_mlb, pll7_usb_host, pll8_enet, clk_max
};
static struct clk *clk[clk_max];
int __init mx6q_clocks_init(void)
{
struct device_node *np;
void __iomem *base;
struct clk *c;
int i, irq;
clk[dummy] = imx_clk_fixed("dummy", 0);
/* retrieve the freqency of fixed clocks from device tree */
for_each_compatible_node(np, NULL, "fixed-clock") {
u32 rate;
if (of_property_read_u32(np, "clock-frequency", &rate))
continue;
if (of_device_is_compatible(np, "fsl,imx-ckil"))
clk[ckil] = imx_clk_fixed("ckil", rate);
else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
clk[ckih] = imx_clk_fixed("ckih", rate);
else if (of_device_is_compatible(np, "fsl,imx-osc"))
clk[osc] = imx_clk_fixed("osc", rate);
}
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
base = of_iomap(np, 0);
WARN_ON(!base);
/* type name parent_name base gate_mask div_mask */
clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x2000, 0x7f);
clk[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x2000, 0x1);
clk[pll3_usb_otg] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x2000, 0x3);
clk[pll4_audio] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x2000, 0x7f);
clk[pll5_video] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x2000, 0x7f);
clk[pll6_mlb] = imx_clk_pllv3(IMX_PLLV3_MLB, "pll6_mlb", "osc", base + 0xd0, 0x2000, 0x0);
clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host","osc", base + 0x20, 0x2000, 0x3);
clk[pll8_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll8_enet", "osc", base + 0xe0, 0x182000, 0x3);
/* name parent_name reg idx */
clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0);
clk[pll2_pfd1_594m] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1);
clk[pll2_pfd2_396m] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2);
clk[pll3_pfd0_720m] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0, 0);
clk[pll3_pfd1_540m] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0, 1);
clk[pll3_pfd2_508m] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0, 2);
clk[pll3_pfd3_454m] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0, 3);
/* name parent_name mult div */
clk[pll2_198m] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2);
clk[pll3_120m] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4);
clk[pll3_80m] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6);
clk[pll3_60m] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8);
clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2);
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm");
base = of_iomap(np, 0);
WARN_ON(!base);
ccm_base = base;
/* name reg shift width parent_names num_parents */
clk[step] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
clk[pll1_sw] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
clk[periph_pre] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
clk[periph2_pre] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
clk[periph_clk2_sel] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 1, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
clk[periph2_clk2_sel] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
clk[axi_sel] = imx_clk_mux("axi_sel", base + 0x14, 6, 2, axi_sels, ARRAY_SIZE(axi_sels));
clk[esai_sel] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels));
clk[asrc_sel] = imx_clk_mux("asrc_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels));
clk[spdif_sel] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels));
clk[gpu2d_axi] = imx_clk_mux("gpu2d_axi", base + 0x18, 0, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels));
clk[gpu3d_axi] = imx_clk_mux("gpu3d_axi", base + 0x18, 1, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels));
clk[gpu2d_core_sel] = imx_clk_mux("gpu2d_core_sel", base + 0x18, 16, 2, gpu2d_core_sels, ARRAY_SIZE(gpu2d_core_sels));
clk[gpu3d_core_sel] = imx_clk_mux("gpu3d_core_sel", base + 0x18, 4, 2, gpu3d_core_sels, ARRAY_SIZE(gpu3d_core_sels));
clk[gpu3d_shader_sel] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
clk[ipu1_sel] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
clk[ipu2_sel] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
clk[ldb_di0_sel] = imx_clk_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
clk[ldb_di1_sel] = imx_clk_mux("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
clk[ipu1_di0_pre_sel] = imx_clk_mux("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
clk[ipu1_di1_pre_sel] = imx_clk_mux("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
clk[ipu2_di0_pre_sel] = imx_clk_mux("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
clk[ipu2_di1_pre_sel] = imx_clk_mux("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
clk[ipu1_di0_sel] = imx_clk_mux("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels));
clk[ipu1_di1_sel] = imx_clk_mux("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels));
clk[ipu2_di0_sel] = imx_clk_mux("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels));
clk[ipu2_di1_sel] = imx_clk_mux("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels));
clk[hsi_tx_sel] = imx_clk_mux("hsi_tx_sel", base + 0x30, 28, 1, hsi_tx_sels, ARRAY_SIZE(hsi_tx_sels));
clk[pcie_axi_sel] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels));
clk[ssi1_sel] = imx_clk_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
clk[ssi2_sel] = imx_clk_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
clk[ssi3_sel] = imx_clk_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
clk[usdhc1_sel] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
clk[usdhc2_sel] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
clk[usdhc3_sel] = imx_clk_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
clk[usdhc4_sel] = imx_clk_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
clk[enfc_sel] = imx_clk_mux("enfc_sel", base + 0x2c, 16, 2, enfc_sels, ARRAY_SIZE(enfc_sels));
clk[emi_sel] = imx_clk_mux("emi_sel", base + 0x1c, 27, 2, emi_sels, ARRAY_SIZE(emi_sels));
clk[emi_slow_sel] = imx_clk_mux("emi_slow_sel", base + 0x1c, 29, 2, emi_sels, ARRAY_SIZE(emi_sels));
clk[vdo_axi_sel] = imx_clk_mux("vdo_axi_sel", base + 0x18, 11, 1, vdo_axi_sels, ARRAY_SIZE(vdo_axi_sels));
clk[vpu_axi_sel] = imx_clk_mux("vpu_axi_sel", base + 0x18, 14, 2, vpu_axi_sels, ARRAY_SIZE(vpu_axi_sels));
clk[cko1_sel] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels));
/* name reg shift width busy: reg, shift parent_names num_parents */
clk[periph] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
clk[periph2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
/* name parent_name reg shift width */
clk[periph_clk2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3);
clk[periph2_clk2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3);
clk[ipg] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2);
clk[ipg_per] = imx_clk_divider("ipg_per", "ipg", base + 0x1c, 0, 6);
clk[esai_pred] = imx_clk_divider("esai_pred", "esai_sel", base + 0x28, 9, 3);
clk[esai_podf] = imx_clk_divider("esai_podf", "esai_pred", base + 0x28, 25, 3);
clk[asrc_pred] = imx_clk_divider("asrc_pred", "asrc_sel", base + 0x30, 12, 3);
clk[asrc_podf] = imx_clk_divider("asrc_podf", "asrc_pred", base + 0x30, 9, 3);
clk[spdif_pred] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3);
clk[spdif_podf] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3);
clk[can_root] = imx_clk_divider("can_root", "pll3_usb_otg", base + 0x20, 2, 6);
clk[ecspi_root] = imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6);
clk[gpu2d_core_podf] = imx_clk_divider("gpu2d_core_podf", "gpu2d_core_sel", base + 0x18, 23, 3);
clk[gpu3d_core_podf] = imx_clk_divider("gpu3d_core_podf", "gpu3d_core_sel", base + 0x18, 26, 3);
clk[gpu3d_shader] = imx_clk_divider("gpu3d_shader", "gpu3d_shader_sel", base + 0x18, 29, 3);
clk[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3);
clk[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3);
clk[ldb_di0_podf] = imx_clk_divider("ldb_di0_podf", "ldb_di0_sel", base + 0x20, 10, 1);
clk[ldb_di1_podf] = imx_clk_divider("ldb_di1_podf", "ldb_di1_sel", base + 0x20, 11, 1);
clk[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3);
clk[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3);
clk[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3);
clk[ipu2_di1_pre] = imx_clk_divider("ipu2_di1_pre", "ipu2_di1_pre_sel", base + 0x38, 12, 3);
clk[hsi_tx_podf] = imx_clk_divider("hsi_tx_podf", "hsi_tx_sel", base + 0x30, 29, 3);
clk[ssi1_pred] = imx_clk_divider("ssi1_pred", "ssi1_sel", base + 0x28, 6, 3);
clk[ssi1_podf] = imx_clk_divider("ssi1_podf", "ssi1_pred", base + 0x28, 0, 6);
clk[ssi2_pred] = imx_clk_divider("ssi2_pred", "ssi2_sel", base + 0x2c, 6, 3);
clk[ssi2_podf] = imx_clk_divider("ssi2_podf", "ssi2_pred", base + 0x2c, 0, 6);
clk[ssi3_pred] = imx_clk_divider("ssi3_pred", "ssi3_sel", base + 0x28, 22, 3);
clk[ssi3_podf] = imx_clk_divider("ssi3_podf", "ssi3_pred", base + 0x28, 16, 6);
clk[uart_serial_podf] = imx_clk_divider("uart_serial_podf", "pll3_80m", base + 0x24, 0, 6);
clk[usdhc1_podf] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3);
clk[usdhc2_podf] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3);
clk[usdhc3_podf] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3);
clk[usdhc4_podf] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3);
clk[enfc_pred] = imx_clk_divider("enfc_pred", "enfc_sel", base + 0x2c, 18, 3);
clk[enfc_podf] = imx_clk_divider("enfc_podf", "enfc_pred", base + 0x2c, 21, 6);
clk[emi_podf] = imx_clk_divider("emi_podf", "emi_sel", base + 0x1c, 20, 3);
clk[emi_slow_podf] = imx_clk_divider("emi_slow_podf", "emi_slow_sel", base + 0x1c, 23, 3);
clk[vpu_axi_podf] = imx_clk_divider("vpu_axi_podf", "vpu_axi_sel", base + 0x24, 25, 3);
clk[cko1_podf] = imx_clk_divider("cko1_podf", "cko1_sel", base + 0x60, 4, 3);
/* name parent_name reg shift width busy: reg, shift */
clk[axi] = imx_clk_busy_divider("axi", "axi_sel", base + 0x14, 16, 3, base + 0x48, 0);
clk[mmdc_ch0_axi_podf] = imx_clk_busy_divider("mmdc_ch0_axi_podf", "periph", base + 0x14, 19, 3, base + 0x48, 4);
clk[mmdc_ch1_axi_podf] = imx_clk_busy_divider("mmdc_ch1_axi_podf", "periph2", base + 0x14, 3, 3, base + 0x48, 2);
clk[arm] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16);
clk[ahb] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1);
/* name parent_name reg shift */
clk[apbh_dma] = imx_clk_gate2("apbh_dma", "ahb", base + 0x68, 4);
clk[asrc] = imx_clk_gate2("asrc", "asrc_podf", base + 0x68, 6);
clk[can1_ipg] = imx_clk_gate2("can1_ipg", "ipg", base + 0x68, 14);
clk[can1_serial] = imx_clk_gate2("can1_serial", "can_root", base + 0x68, 16);
clk[can2_ipg] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18);
clk[can2_serial] = imx_clk_gate2("can2_serial", "can_root", base + 0x68, 20);
clk[ecspi1] = imx_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0);
clk[ecspi2] = imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2);
clk[ecspi3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4);
clk[ecspi4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6);
clk[ecspi5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8);
clk[enet] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10);
clk[esai] = imx_clk_gate2("esai", "esai_podf", base + 0x6c, 16);
clk[gpt_ipg] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20);
clk[gpt_ipg_per] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22);
clk[gpu2d_core] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24);
clk[gpu3d_core] = imx_clk_gate2("gpu3d_core", "gpu3d_core_podf", base + 0x6c, 26);
clk[hdmi_iahb] = imx_clk_gate2("hdmi_iahb", "ahb", base + 0x70, 0);
clk[hdmi_isfr] = imx_clk_gate2("hdmi_isfr", "pll3_pfd1_540m", base + 0x70, 4);
clk[i2c1] = imx_clk_gate2("i2c1", "ipg_per", base + 0x70, 6);
clk[i2c2] = imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8);
clk[i2c3] = imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10);
clk[iim] = imx_clk_gate2("iim", "ipg", base + 0x70, 12);
clk[enfc] = imx_clk_gate2("enfc", "enfc_podf", base + 0x70, 14);
clk[ipu1] = imx_clk_gate2("ipu1", "ipu1_podf", base + 0x74, 0);
clk[ipu1_di0] = imx_clk_gate2("ipu1_di0", "ipu1_di0_sel", base + 0x74, 2);
clk[ipu1_di1] = imx_clk_gate2("ipu1_di1", "ipu1_di1_sel", base + 0x74, 4);
clk[ipu2] = imx_clk_gate2("ipu2", "ipu2_podf", base + 0x74, 6);
clk[ipu2_di0] = imx_clk_gate2("ipu2_di0", "ipu2_di0_sel", base + 0x74, 8);
clk[ldb_di0] = imx_clk_gate2("ldb_di0", "ldb_di0_podf", base + 0x74, 12);
clk[ldb_di1] = imx_clk_gate2("ldb_di1", "ldb_di1_podf", base + 0x74, 14);
clk[ipu2_di1] = imx_clk_gate2("ipu2_di1", "ipu2_di1_sel", base + 0x74, 10);
clk[hsi_tx] = imx_clk_gate2("hsi_tx", "hsi_tx_podf", base + 0x74, 16);
clk[mlb] = imx_clk_gate2("mlb", "pll6_mlb", base + 0x74, 18);
clk[mmdc_ch0_axi] = imx_clk_gate2("mmdc_ch0_axi", "mmdc_ch0_axi_podf", base + 0x74, 20);
clk[mmdc_ch1_axi] = imx_clk_gate2("mmdc_ch1_axi", "mmdc_ch1_axi_podf", base + 0x74, 22);
clk[ocram] = imx_clk_gate2("ocram", "ahb", base + 0x74, 28);
clk[openvg_axi] = imx_clk_gate2("openvg_axi", "axi", base + 0x74, 30);
clk[pcie_axi] = imx_clk_gate2("pcie_axi", "pcie_axi_sel", base + 0x78, 0);
clk[pwm1] = imx_clk_gate2("pwm1", "ipg_per", base + 0x78, 16);
clk[pwm2] = imx_clk_gate2("pwm2", "ipg_per", base + 0x78, 18);
clk[pwm3] = imx_clk_gate2("pwm3", "ipg_per", base + 0x78, 20);
clk[pwm4] = imx_clk_gate2("pwm4", "ipg_per", base + 0x78, 22);
clk[gpmi_bch_apb] = imx_clk_gate2("gpmi_bch_apb", "usdhc3", base + 0x78, 24);
clk[gpmi_bch] = imx_clk_gate2("gpmi_bch", "usdhc4", base + 0x78, 26);
clk[gpmi_io] = imx_clk_gate2("gpmi_io", "enfc", base + 0x78, 28);
clk[gpmi_apb] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30);
clk[sata] = imx_clk_gate2("sata", "ipg", base + 0x7c, 4);
clk[sdma] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6);
clk[spba] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
clk[ssi1] = imx_clk_gate2("ssi1", "ssi1_podf", base + 0x7c, 18);
clk[ssi2] = imx_clk_gate2("ssi2", "ssi2_podf", base + 0x7c, 20);
clk[ssi3] = imx_clk_gate2("ssi3", "ssi3_podf", base + 0x7c, 22);
clk[uart_ipg] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24);
clk[uart_serial] = imx_clk_gate2("uart_serial", "uart_serial_podf", base + 0x7c, 26);
clk[usboh3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0);
clk[usdhc1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2);
clk[usdhc2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4);
clk[usdhc3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6);
clk[usdhc4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8);
clk[vdo_axi] = imx_clk_gate2("vdo_axi", "vdo_axi_sel", base + 0x80, 12);
clk[vpu_axi] = imx_clk_gate2("vpu_axi", "vpu_axi_podf", base + 0x80, 14);
clk[cko1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7);
for (i = 0; i < ARRAY_SIZE(clk); i++)
if (IS_ERR(clk[i]))
pr_err("i.MX6q clk %d: register failed with %ld\n",
i, PTR_ERR(clk[i]));
clk_register_clkdev(clk[mmdc_ch0_axi], NULL, "mmdc_ch0_axi");
clk_register_clkdev(clk[mmdc_ch1_axi], NULL, "mmdc_ch1_axi");
clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
clk_register_clkdev(clk[twd], NULL, "smp_twd");
clk_register_clkdev(clk[usboh3], NULL, "usboh3");
clk_register_clkdev(clk[uart_serial], "per", "2020000.uart");
clk_register_clkdev(clk[uart_ipg], "ipg", "2020000.uart");
clk_register_clkdev(clk[uart_serial], "per", "21e8000.uart");
clk_register_clkdev(clk[uart_ipg], "ipg", "21e8000.uart");
clk_register_clkdev(clk[uart_serial], "per", "21ec000.uart");
clk_register_clkdev(clk[uart_ipg], "ipg", "21ec000.uart");
clk_register_clkdev(clk[uart_serial], "per", "21f0000.uart");
clk_register_clkdev(clk[uart_ipg], "ipg", "21f0000.uart");
clk_register_clkdev(clk[uart_serial], "per", "21f4000.uart");
clk_register_clkdev(clk[uart_ipg], "ipg", "21f4000.uart");
clk_register_clkdev(clk[enet], NULL, "2188000.enet");
clk_register_clkdev(clk[usdhc1], NULL, "2190000.usdhc");
clk_register_clkdev(clk[usdhc2], NULL, "2194000.usdhc");
clk_register_clkdev(clk[usdhc3], NULL, "2198000.usdhc");
clk_register_clkdev(clk[usdhc4], NULL, "219c000.usdhc");
clk_register_clkdev(clk[i2c1], NULL, "21a0000.i2c");
clk_register_clkdev(clk[i2c2], NULL, "21a4000.i2c");
clk_register_clkdev(clk[i2c3], NULL, "21a8000.i2c");
clk_register_clkdev(clk[ecspi1], NULL, "2008000.ecspi");
clk_register_clkdev(clk[ecspi2], NULL, "200c000.ecspi");
clk_register_clkdev(clk[ecspi3], NULL, "2010000.ecspi");
clk_register_clkdev(clk[ecspi4], NULL, "2014000.ecspi");
clk_register_clkdev(clk[ecspi5], NULL, "2018000.ecspi");
clk_register_clkdev(clk[sdma], NULL, "20ec000.sdma");
clk_register_clkdev(clk[dummy], NULL, "20bc000.wdog");
clk_register_clkdev(clk[dummy], NULL, "20c0000.wdog");
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) {
c = clk_get_sys(clks_init_on[i], NULL);
if (IS_ERR(c)) {
pr_err("%s: failed to get clk %s", __func__,
clks_init_on[i]);
return PTR_ERR(c);
}
clk_prepare_enable(c);
}
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
base = of_iomap(np, 0);
WARN_ON(!base);
irq = irq_of_parse_and_map(np, 0);
mxc_timer_init(NULL, base, irq);
return 0;
}

147
arch/arm/mach-imx/clk-pfd.c Normal file
View File

@ -0,0 +1,147 @@
/*
* 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;
}

View File

@ -0,0 +1,66 @@
#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;
}

View File

@ -0,0 +1,249 @@
#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;
}

View File

@ -0,0 +1,419 @@
/*
* 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;
}

83
arch/arm/mach-imx/clk.h Normal file
View File

@ -0,0 +1,83 @@
#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

View File

@ -1,636 +0,0 @@
/*
* 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/list.h>
#include <linux/math64.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <mach/clock.h>
#include <mach/hardware.h>
#include <mach/common.h>
#define IO_ADDR_CCM(off) (MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR + (off)))
/* CCM register addresses */
#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)
#define CCM_CSCR_CLKO_OFFSET 29
#define CCM_CSCR_CLKO_MASK (0x7 << 29)
#define CCM_CSCR_USB_OFFSET 26
#define CCM_CSCR_USB_MASK (0x7 << 26)
#define CCM_CSCR_OSC_EN_SHIFT 17
#define CCM_CSCR_SYSTEM_SEL (1 << 16)
#define CCM_CSCR_BCLK_OFFSET 10
#define CCM_CSCR_BCLK_MASK (0xf << 10)
#define CCM_CSCR_PRESC (1 << 15)
#define CCM_PCDR_PCLK3_OFFSET 16
#define CCM_PCDR_PCLK3_MASK (0x7f << 16)
#define CCM_PCDR_PCLK2_OFFSET 4
#define CCM_PCDR_PCLK2_MASK (0xf << 4)
#define CCM_PCDR_PCLK1_OFFSET 0
#define CCM_PCDR_PCLK1_MASK 0xf
#define IO_ADDR_SCM(off) (MX1_IO_ADDRESS(MX1_SCM_BASE_ADDR + (off)))
/* SCM register addresses */
#define SCM_GCCR IO_ADDR_SCM(0xc)
#define SCM_GCCR_DMA_CLK_EN_OFFSET 3
#define SCM_GCCR_CSI_CLK_EN_OFFSET 2
#define SCM_GCCR_MMA_CLK_EN_OFFSET 1
#define SCM_GCCR_USBD_CLK_EN_OFFSET 0
static int _clk_enable(struct clk *clk)
{
unsigned int reg;
reg = __raw_readl(clk->enable_reg);
reg |= 1 << clk->enable_shift;
__raw_writel(reg, clk->enable_reg);
return 0;
}
static void _clk_disable(struct clk *clk)
{
unsigned int reg;
reg = __raw_readl(clk->enable_reg);
reg &= ~(1 << clk->enable_shift);
__raw_writel(reg, clk->enable_reg);
}
static int _clk_can_use_parent(const struct clk *clk_arr[], unsigned int size,
struct clk *parent)
{
int i;
for (i = 0; i < size; i++)
if (parent == clk_arr[i])
return i;
return -EINVAL;
}
static unsigned long
_clk_simple_round_rate(struct clk *clk, unsigned long rate, unsigned int limit)
{
int div;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
div = parent_rate / rate;
if (parent_rate % rate)
div++;
if (div > limit)
div = limit;
return parent_rate / div;
}
static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
{
return clk->parent->round_rate(clk->parent, rate);
}
static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
{
return clk->parent->set_rate(clk->parent, rate);
}
static unsigned long clk16m_get_rate(struct clk *clk)
{
return 16000000;
}
static struct clk clk16m = {
.get_rate = clk16m_get_rate,
.enable = _clk_enable,
.enable_reg = CCM_CSCR,
.enable_shift = CCM_CSCR_OSC_EN_SHIFT,
.disable = _clk_disable,
};
/* in Hz */
static unsigned long clk32_rate;
static unsigned long clk32_get_rate(struct clk *clk)
{
return clk32_rate;
}
static struct clk clk32 = {
.get_rate = clk32_get_rate,
};
static unsigned long clk32_premult_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) * 512;
}
static struct clk clk32_premult = {
.parent = &clk32,
.get_rate = clk32_premult_get_rate,
};
static const struct clk *prem_clk_clocks[] = {
&clk32_premult,
&clk16m,
};
static int prem_clk_set_parent(struct clk *clk, struct clk *parent)
{
int i;
unsigned int reg = __raw_readl(CCM_CSCR);
i = _clk_can_use_parent(prem_clk_clocks, ARRAY_SIZE(prem_clk_clocks),
parent);
switch (i) {
case 0:
reg &= ~CCM_CSCR_SYSTEM_SEL;
break;
case 1:
reg |= CCM_CSCR_SYSTEM_SEL;
break;
default:
return i;
}
__raw_writel(reg, CCM_CSCR);
return 0;
}
static struct clk prem_clk = {
.set_parent = prem_clk_set_parent,
};
static unsigned long system_clk_get_rate(struct clk *clk)
{
return mxc_decode_pll(__raw_readl(CCM_SPCTL0),
clk_get_rate(clk->parent));
}
static struct clk system_clk = {
.parent = &prem_clk,
.get_rate = system_clk_get_rate,
};
static unsigned long mcu_clk_get_rate(struct clk *clk)
{
return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
clk_get_rate(clk->parent));
}
static struct clk mcu_clk = {
.parent = &clk32_premult,
.get_rate = mcu_clk_get_rate,
};
static unsigned long fclk_get_rate(struct clk *clk)
{
unsigned long fclk = clk_get_rate(clk->parent);
if (__raw_readl(CCM_CSCR) & CCM_CSCR_PRESC)
fclk /= 2;
return fclk;
}
static struct clk fclk = {
.parent = &mcu_clk,
.get_rate = fclk_get_rate,
};
/*
* get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
*/
static unsigned long hclk_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) &
CCM_CSCR_BCLK_MASK) >> CCM_CSCR_BCLK_OFFSET) + 1);
}
static unsigned long hclk_round_rate(struct clk *clk, unsigned long rate)
{
return _clk_simple_round_rate(clk, rate, 16);
}
static int hclk_set_rate(struct clk *clk, unsigned long rate)
{
unsigned int div;
unsigned int reg;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
div = parent_rate / rate;
if (div > 16 || div < 1 || ((parent_rate / div) != rate))
return -EINVAL;
div--;
reg = __raw_readl(CCM_CSCR);
reg &= ~CCM_CSCR_BCLK_MASK;
reg |= div << CCM_CSCR_BCLK_OFFSET;
__raw_writel(reg, CCM_CSCR);
return 0;
}
static struct clk hclk = {
.parent = &system_clk,
.get_rate = hclk_get_rate,
.round_rate = hclk_round_rate,
.set_rate = hclk_set_rate,
};
static unsigned long clk48m_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) &
CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET) + 1);
}
static unsigned long clk48m_round_rate(struct clk *clk, unsigned long rate)
{
return _clk_simple_round_rate(clk, rate, 8);
}
static int clk48m_set_rate(struct clk *clk, unsigned long rate)
{
unsigned int div;
unsigned int reg;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
div = parent_rate / rate;
if (div > 8 || div < 1 || ((parent_rate / div) != rate))
return -EINVAL;
div--;
reg = __raw_readl(CCM_CSCR);
reg &= ~CCM_CSCR_USB_MASK;
reg |= div << CCM_CSCR_USB_OFFSET;
__raw_writel(reg, CCM_CSCR);
return 0;
}
static struct clk clk48m = {
.parent = &system_clk,
.get_rate = clk48m_get_rate,
.round_rate = clk48m_round_rate,
.set_rate = clk48m_set_rate,
};
/*
* get peripheral clock 1 ( UART[12], Timer[12], PWM )
*/
static unsigned long perclk1_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
CCM_PCDR_PCLK1_MASK) >> CCM_PCDR_PCLK1_OFFSET) + 1);
}
static unsigned long perclk1_round_rate(struct clk *clk, unsigned long rate)
{
return _clk_simple_round_rate(clk, rate, 16);
}
static int perclk1_set_rate(struct clk *clk, unsigned long rate)
{
unsigned int div;
unsigned int reg;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
div = parent_rate / rate;
if (div > 16 || div < 1 || ((parent_rate / div) != rate))
return -EINVAL;
div--;
reg = __raw_readl(CCM_PCDR);
reg &= ~CCM_PCDR_PCLK1_MASK;
reg |= div << CCM_PCDR_PCLK1_OFFSET;
__raw_writel(reg, CCM_PCDR);
return 0;
}
/*
* get peripheral clock 2 ( LCD, SD, SPI[12] )
*/
static unsigned long perclk2_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
CCM_PCDR_PCLK2_MASK) >> CCM_PCDR_PCLK2_OFFSET) + 1);
}
static unsigned long perclk2_round_rate(struct clk *clk, unsigned long rate)
{
return _clk_simple_round_rate(clk, rate, 16);
}
static int perclk2_set_rate(struct clk *clk, unsigned long rate)
{
unsigned int div;
unsigned int reg;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
div = parent_rate / rate;
if (div > 16 || div < 1 || ((parent_rate / div) != rate))
return -EINVAL;
div--;
reg = __raw_readl(CCM_PCDR);
reg &= ~CCM_PCDR_PCLK2_MASK;
reg |= div << CCM_PCDR_PCLK2_OFFSET;
__raw_writel(reg, CCM_PCDR);
return 0;
}
/*
* get peripheral clock 3 ( SSI )
*/
static unsigned long perclk3_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
CCM_PCDR_PCLK3_MASK) >> CCM_PCDR_PCLK3_OFFSET) + 1);
}
static unsigned long perclk3_round_rate(struct clk *clk, unsigned long rate)
{
return _clk_simple_round_rate(clk, rate, 128);
}
static int perclk3_set_rate(struct clk *clk, unsigned long rate)
{
unsigned int div;
unsigned int reg;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
div = parent_rate / rate;
if (div > 128 || div < 1 || ((parent_rate / div) != rate))
return -EINVAL;
div--;
reg = __raw_readl(CCM_PCDR);
reg &= ~CCM_PCDR_PCLK3_MASK;
reg |= div << CCM_PCDR_PCLK3_OFFSET;
__raw_writel(reg, CCM_PCDR);
return 0;
}
static struct clk perclk[] = {
{
.id = 0,
.parent = &system_clk,
.get_rate = perclk1_get_rate,
.round_rate = perclk1_round_rate,
.set_rate = perclk1_set_rate,
}, {
.id = 1,
.parent = &system_clk,
.get_rate = perclk2_get_rate,
.round_rate = perclk2_round_rate,
.set_rate = perclk2_set_rate,
}, {
.id = 2,
.parent = &system_clk,
.get_rate = perclk3_get_rate,
.round_rate = perclk3_round_rate,
.set_rate = perclk3_set_rate,
}
};
static const struct clk *clko_clocks[] = {
&perclk[0],
&hclk,
&clk48m,
&clk16m,
&prem_clk,
&fclk,
};
static int clko_set_parent(struct clk *clk, struct clk *parent)
{
int i;
unsigned int reg;
i = _clk_can_use_parent(clko_clocks, ARRAY_SIZE(clko_clocks), parent);
if (i < 0)
return i;
reg = __raw_readl(CCM_CSCR) & ~CCM_CSCR_CLKO_MASK;
reg |= i << CCM_CSCR_CLKO_OFFSET;
__raw_writel(reg, CCM_CSCR);
if (clko_clocks[i]->set_rate && clko_clocks[i]->round_rate) {
clk->set_rate = _clk_parent_set_rate;
clk->round_rate = _clk_parent_round_rate;
} else {
clk->set_rate = NULL;
clk->round_rate = NULL;
}
return 0;
}
static struct clk clko_clk = {
.set_parent = clko_set_parent,
};
static struct clk dma_clk = {
.parent = &hclk,
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
.enable = _clk_enable,
.enable_reg = SCM_GCCR,
.enable_shift = SCM_GCCR_DMA_CLK_EN_OFFSET,
.disable = _clk_disable,
};
static struct clk csi_clk = {
.parent = &hclk,
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
.enable = _clk_enable,
.enable_reg = SCM_GCCR,
.enable_shift = SCM_GCCR_CSI_CLK_EN_OFFSET,
.disable = _clk_disable,
};
static struct clk mma_clk = {
.parent = &hclk,
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
.enable = _clk_enable,
.enable_reg = SCM_GCCR,
.enable_shift = SCM_GCCR_MMA_CLK_EN_OFFSET,
.disable = _clk_disable,
};
static struct clk usbd_clk = {
.parent = &clk48m,
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
.enable = _clk_enable,
.enable_reg = SCM_GCCR,
.enable_shift = SCM_GCCR_USBD_CLK_EN_OFFSET,
.disable = _clk_disable,
};
static struct clk gpt_clk = {
.parent = &perclk[0],
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
};
static struct clk uart_clk = {
.parent = &perclk[0],
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
};
static struct clk i2c_clk = {
.parent = &hclk,
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
};
static struct clk spi_clk = {
.parent = &perclk[1],
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
};
static struct clk sdhc_clk = {
.parent = &perclk[1],
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
};
static struct clk lcdc_clk = {
.parent = &perclk[1],
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
};
static struct clk mshc_clk = {
.parent = &hclk,
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
};
static struct clk ssi_clk = {
.parent = &perclk[2],
.round_rate = _clk_parent_round_rate,
.set_rate = _clk_parent_set_rate,
};
static struct clk rtc_clk = {
.parent = &clk32,
};
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static struct clk_lookup lookups[] __initdata = {
_REGISTER_CLOCK(NULL, "dma", dma_clk)
_REGISTER_CLOCK("mx1-camera.0", NULL, csi_clk)
_REGISTER_CLOCK(NULL, "mma", mma_clk)
_REGISTER_CLOCK("imx_udc.0", NULL, usbd_clk)
_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
_REGISTER_CLOCK("imx1-uart.0", NULL, uart_clk)
_REGISTER_CLOCK("imx1-uart.1", NULL, uart_clk)
_REGISTER_CLOCK("imx1-uart.2", NULL, uart_clk)
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
_REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk)
_REGISTER_CLOCK("imx1-cspi.1", NULL, spi_clk)
_REGISTER_CLOCK("imx-mmc.0", NULL, sdhc_clk)
_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
_REGISTER_CLOCK(NULL, "mshc", mshc_clk)
_REGISTER_CLOCK(NULL, "ssi", ssi_clk)
_REGISTER_CLOCK("mxc_rtc.0", NULL, rtc_clk)
};
int __init mx1_clocks_init(unsigned long fref)
{
unsigned int reg;
/* disable clocks we are able to */
__raw_writel(0, SCM_GCCR);
clk32_rate = fref;
reg = __raw_readl(CCM_CSCR);
/* detect clock reference for system PLL */
if (reg & CCM_CSCR_SYSTEM_SEL) {
prem_clk.parent = &clk16m;
} else {
/* ensure that oscillator is disabled */
reg &= ~(1 << CCM_CSCR_OSC_EN_SHIFT);
__raw_writel(reg, CCM_CSCR);
prem_clk.parent = &clk32_premult;
}
/* detect reference for CLKO */
reg = (reg & CCM_CSCR_CLKO_MASK) >> CCM_CSCR_CLKO_OFFSET;
clko_clk.parent = (struct clk *)clko_clocks[reg];
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
clk_enable(&hclk);
clk_enable(&fclk);
mxc_timer_init(&gpt_clk, MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR),
MX1_TIM1_INT);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,346 +0,0 @@
/*
* Copyright (C) 2009 by Sascha Hauer, Pengutronix
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <mach/clock.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/mx25.h>
#define CRM_BASE MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR)
#define CCM_MPCTL 0x00
#define CCM_UPCTL 0x04
#define CCM_CCTL 0x08
#define CCM_CGCR0 0x0C
#define CCM_CGCR1 0x10
#define CCM_CGCR2 0x14
#define CCM_PCDR0 0x18
#define CCM_PCDR1 0x1C
#define CCM_PCDR2 0x20
#define CCM_PCDR3 0x24
#define CCM_RCSR 0x28
#define CCM_CRDR 0x2C
#define CCM_DCVR0 0x30
#define CCM_DCVR1 0x34
#define CCM_DCVR2 0x38
#define CCM_DCVR3 0x3c
#define CCM_LTR0 0x40
#define CCM_LTR1 0x44
#define CCM_LTR2 0x48
#define CCM_LTR3 0x4c
static unsigned long get_rate_mpll(void)
{
ulong mpctl = __raw_readl(CRM_BASE + CCM_MPCTL);
return mxc_decode_pll(mpctl, 24000000);
}
static unsigned long get_rate_upll(void)
{
ulong mpctl = __raw_readl(CRM_BASE + CCM_UPCTL);
return mxc_decode_pll(mpctl, 24000000);
}
unsigned long get_rate_arm(struct clk *clk)
{
unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
unsigned long rate = get_rate_mpll();
if (cctl & (1 << 14))
rate = (rate * 3) >> 2;
return rate / ((cctl >> 30) + 1);
}
static unsigned long get_rate_ahb(struct clk *clk)
{
unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
return get_rate_arm(NULL) / (((cctl >> 28) & 0x3) + 1);
}
static unsigned long get_rate_ipg(struct clk *clk)
{
return get_rate_ahb(NULL) >> 1;
}
static unsigned long get_rate_per(int per)
{
unsigned long ofs = (per & 0x3) * 8;
unsigned long reg = per & ~0x3;
unsigned long val = (readl(CRM_BASE + CCM_PCDR0 + reg) >> ofs) & 0x3f;
unsigned long fref;
if (readl(CRM_BASE + 0x64) & (1 << per))
fref = get_rate_upll();
else
fref = get_rate_ahb(NULL);
return fref / (val + 1);
}
static unsigned long get_rate_uart(struct clk *clk)
{
return get_rate_per(15);
}
static unsigned long get_rate_ssi2(struct clk *clk)
{
return get_rate_per(14);
}
static unsigned long get_rate_ssi1(struct clk *clk)
{
return get_rate_per(13);
}
static unsigned long get_rate_i2c(struct clk *clk)
{
return get_rate_per(6);
}
static unsigned long get_rate_nfc(struct clk *clk)
{
return get_rate_per(8);
}
static unsigned long get_rate_gpt(struct clk *clk)
{
return get_rate_per(5);
}
static unsigned long get_rate_lcdc(struct clk *clk)
{
return get_rate_per(7);
}
static unsigned long get_rate_esdhc1(struct clk *clk)
{
return get_rate_per(3);
}
static unsigned long get_rate_esdhc2(struct clk *clk)
{
return get_rate_per(4);
}
static unsigned long get_rate_csi(struct clk *clk)
{
return get_rate_per(0);
}
static unsigned long get_rate_otg(struct clk *clk)
{
unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
unsigned long rate = get_rate_upll();
return (cctl & (1 << 23)) ? 0 : rate / ((0x3F & (cctl >> 16)) + 1);
}
static int clk_cgcr_enable(struct clk *clk)
{
u32 reg;
reg = __raw_readl(clk->enable_reg);
reg |= 1 << clk->enable_shift;
__raw_writel(reg, clk->enable_reg);
return 0;
}
static void clk_cgcr_disable(struct clk *clk)
{
u32 reg;
reg = __raw_readl(clk->enable_reg);
reg &= ~(1 << clk->enable_shift);
__raw_writel(reg, clk->enable_reg);
}
#define DEFINE_CLOCK(name, i, er, es, gr, sr, s) \
static struct clk name = { \
.id = i, \
.enable_reg = CRM_BASE + er, \
.enable_shift = es, \
.get_rate = gr, \
.set_rate = sr, \
.enable = clk_cgcr_enable, \
.disable = clk_cgcr_disable, \
.secondary = s, \
}
/*
* Note: the following IPG clock gating bits are wrongly marked "Reserved" in
* the i.MX25 Reference Manual Rev 1, table 15-13. The information below is
* taken from the Freescale released BSP.
*
* bit reg offset clock
*
* 0 CGCR1 0 AUDMUX
* 12 CGCR1 12 ESAI
* 16 CGCR1 16 GPIO1
* 17 CGCR1 17 GPIO2
* 18 CGCR1 18 GPIO3
* 23 CGCR1 23 I2C1
* 24 CGCR1 24 I2C2
* 25 CGCR1 25 I2C3
* 27 CGCR1 27 IOMUXC
* 28 CGCR1 28 KPP
* 30 CGCR1 30 OWIRE
* 36 CGCR2 4 RTIC
* 51 CGCR2 19 WDOG
*/
DEFINE_CLOCK(gpt_clk, 0, CCM_CGCR0, 5, get_rate_gpt, NULL, NULL);
DEFINE_CLOCK(uart_per_clk, 0, CCM_CGCR0, 15, get_rate_uart, NULL, NULL);
DEFINE_CLOCK(ssi1_per_clk, 0, CCM_CGCR0, 13, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(ssi2_per_clk, 0, CCM_CGCR0, 14, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(cspi1_clk, 0, CCM_CGCR1, 5, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(cspi2_clk, 0, CCM_CGCR1, 6, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(cspi3_clk, 0, CCM_CGCR1, 7, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(esdhc1_ahb_clk, 0, CCM_CGCR0, 21, get_rate_esdhc1, NULL, NULL);
DEFINE_CLOCK(esdhc1_per_clk, 0, CCM_CGCR0, 3, get_rate_esdhc1, NULL,
&esdhc1_ahb_clk);
DEFINE_CLOCK(esdhc2_ahb_clk, 0, CCM_CGCR0, 22, get_rate_esdhc2, NULL, NULL);
DEFINE_CLOCK(esdhc2_per_clk, 0, CCM_CGCR0, 4, get_rate_esdhc2, NULL,
&esdhc2_ahb_clk);
DEFINE_CLOCK(sdma_ahb_clk, 0, CCM_CGCR0, 26, NULL, NULL, NULL);
DEFINE_CLOCK(fec_ahb_clk, 0, CCM_CGCR0, 23, NULL, NULL, NULL);
DEFINE_CLOCK(lcdc_ahb_clk, 0, CCM_CGCR0, 24, NULL, NULL, NULL);
DEFINE_CLOCK(lcdc_per_clk, 0, CCM_CGCR0, 7, NULL, NULL, &lcdc_ahb_clk);
DEFINE_CLOCK(csi_ahb_clk, 0, CCM_CGCR0, 18, get_rate_csi, NULL, NULL);
DEFINE_CLOCK(csi_per_clk, 0, CCM_CGCR0, 0, get_rate_csi, NULL, &csi_ahb_clk);
DEFINE_CLOCK(uart1_clk, 0, CCM_CGCR2, 14, get_rate_uart, NULL, &uart_per_clk);
DEFINE_CLOCK(uart2_clk, 0, CCM_CGCR2, 15, get_rate_uart, NULL, &uart_per_clk);
DEFINE_CLOCK(uart3_clk, 0, CCM_CGCR2, 16, get_rate_uart, NULL, &uart_per_clk);
DEFINE_CLOCK(uart4_clk, 0, CCM_CGCR2, 17, get_rate_uart, NULL, &uart_per_clk);
DEFINE_CLOCK(uart5_clk, 0, CCM_CGCR2, 18, get_rate_uart, NULL, &uart_per_clk);
DEFINE_CLOCK(nfc_clk, 0, CCM_CGCR0, 8, get_rate_nfc, NULL, NULL);
DEFINE_CLOCK(usbotg_clk, 0, CCM_CGCR0, 28, get_rate_otg, NULL, NULL);
DEFINE_CLOCK(pwm1_clk, 0, CCM_CGCR1, 31, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(pwm2_clk, 0, CCM_CGCR2, 0, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(pwm3_clk, 0, CCM_CGCR2, 1, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(pwm4_clk, 0, CCM_CGCR2, 2, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(kpp_clk, 0, CCM_CGCR1, 28, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(tsc_clk, 0, CCM_CGCR2, 13, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(i2c_clk, 0, CCM_CGCR0, 6, get_rate_i2c, NULL, NULL);
DEFINE_CLOCK(fec_clk, 0, CCM_CGCR1, 15, get_rate_ipg, NULL, &fec_ahb_clk);
DEFINE_CLOCK(dryice_clk, 0, CCM_CGCR1, 8, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(lcdc_clk, 0, CCM_CGCR1, 29, get_rate_lcdc, NULL, &lcdc_per_clk);
DEFINE_CLOCK(wdt_clk, 0, CCM_CGCR2, 19, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(ssi1_clk, 0, CCM_CGCR2, 11, get_rate_ssi1, NULL, &ssi1_per_clk);
DEFINE_CLOCK(ssi2_clk, 1, CCM_CGCR2, 12, get_rate_ssi2, NULL, &ssi2_per_clk);
DEFINE_CLOCK(sdma_clk, 0, CCM_CGCR2, 6, get_rate_ipg, NULL, &sdma_ahb_clk);
DEFINE_CLOCK(esdhc1_clk, 0, CCM_CGCR1, 13, get_rate_esdhc1, NULL,
&esdhc1_per_clk);
DEFINE_CLOCK(esdhc2_clk, 1, CCM_CGCR1, 14, get_rate_esdhc2, NULL,
&esdhc2_per_clk);
DEFINE_CLOCK(audmux_clk, 0, CCM_CGCR1, 0, NULL, NULL, NULL);
DEFINE_CLOCK(csi_clk, 0, CCM_CGCR1, 4, get_rate_csi, NULL, &csi_per_clk);
DEFINE_CLOCK(can1_clk, 0, CCM_CGCR1, 2, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(can2_clk, 1, CCM_CGCR1, 3, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(iim_clk, 0, CCM_CGCR1, 26, NULL, NULL, NULL);
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static struct clk_lookup lookups[] = {
/* i.mx25 has the i.mx21 type uart */
_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
_REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk)
_REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
/* i.mx25 has the i.mx35 type cspi */
_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
_REGISTER_CLOCK("imx35-cspi.1", NULL, cspi2_clk)
_REGISTER_CLOCK("imx35-cspi.2", NULL, cspi3_clk)
_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk)
_REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk)
_REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk)
_REGISTER_CLOCK("mxc_pwm.3", NULL, pwm4_clk)
_REGISTER_CLOCK("imx-keypad", NULL, kpp_clk)
_REGISTER_CLOCK("mx25-adc", NULL, tsc_clk)
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
_REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk)
_REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk)
_REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
_REGISTER_CLOCK("imxdi_rtc.0", NULL, dryice_clk)
_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
_REGISTER_CLOCK("imx2-wdt.0", NULL, wdt_clk)
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx25.0", NULL, esdhc1_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx25.1", NULL, esdhc2_clk)
_REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
/* i.mx25 has the i.mx35 type sdma */
_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
_REGISTER_CLOCK(NULL, "iim", iim_clk)
};
int __init mx25_clocks_init(void)
{
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
/* Turn off all clocks except the ones we need to survive, namely:
* EMI, GPIO1-3 (CCM_CGCR1[18:16]), GPT1, IOMUXC (CCM_CGCR1[27]), IIM,
* SCC
*/
__raw_writel((1 << 19), CRM_BASE + CCM_CGCR0);
__raw_writel((0xf << 16) | (3 << 26), CRM_BASE + CCM_CGCR1);
__raw_writel((1 << 5), CRM_BASE + CCM_CGCR2);
#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
clk_enable(&uart1_clk);
#endif
/* Clock source for lcdc and csi is upll */
__raw_writel(__raw_readl(CRM_BASE+0x64) | (1 << 7) | (1 << 0),
CRM_BASE + 0x64);
/* Clock source for gpt is ahb_div */
__raw_writel(__raw_readl(CRM_BASE+0x64) & ~(1 << 5), CRM_BASE + 0x64);
clk_enable(&iim_clk);
imx_print_silicon_rev("i.MX25", mx25_revision());
clk_disable(&iim_clk);
mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
return 0;
}

View File

@ -1,785 +0,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/io.h>
#include <linux/module.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <asm/div64.h>
#include <mach/clock.h>
#include <mach/common.h>
#include <mach/hardware.h>
#define IO_ADDR_CCM(off) (MX27_IO_ADDRESS(MX27_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)
#define CCM_CSCR_UPDATE_DIS (1 << 31)
#define CCM_CSCR_SSI2 (1 << 23)
#define CCM_CSCR_SSI1 (1 << 22)
#define CCM_CSCR_VPU (1 << 21)
#define CCM_CSCR_MSHC (1 << 20)
#define CCM_CSCR_SPLLRES (1 << 19)
#define CCM_CSCR_MPLLRES (1 << 18)
#define CCM_CSCR_SP (1 << 17)
#define CCM_CSCR_MCU (1 << 16)
#define CCM_CSCR_OSC26MDIV (1 << 4)
#define CCM_CSCR_OSC26M (1 << 3)
#define CCM_CSCR_FPM (1 << 2)
#define CCM_CSCR_SPEN (1 << 1)
#define CCM_CSCR_MPEN (1 << 0)
/* i.MX27 TO 2+ */
#define CCM_CSCR_ARM_SRC (1 << 15)
#define CCM_SPCTL1_LF (1 << 15)
#define CCM_SPCTL1_BRMO (1 << 6)
static struct clk mpll_main1_clk, mpll_main2_clk;
static int clk_pccr_enable(struct clk *clk)
{
unsigned long reg;
if (!clk->enable_reg)
return 0;
reg = __raw_readl(clk->enable_reg);
reg |= 1 << clk->enable_shift;
__raw_writel(reg, clk->enable_reg);
return 0;
}
static void clk_pccr_disable(struct clk *clk)
{
unsigned long reg;
if (!clk->enable_reg)
return;
reg = __raw_readl(clk->enable_reg);
reg &= ~(1 << clk->enable_shift);
__raw_writel(reg, clk->enable_reg);
}
static int clk_spll_enable(struct clk *clk)
{
unsigned long reg;
reg = __raw_readl(CCM_CSCR);
reg |= CCM_CSCR_SPEN;
__raw_writel(reg, CCM_CSCR);
while (!(__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF));
return 0;
}
static void clk_spll_disable(struct clk *clk)
{
unsigned long reg;
reg = __raw_readl(CCM_CSCR);
reg &= ~CCM_CSCR_SPEN;
__raw_writel(reg, CCM_CSCR);
}
static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
{
int cscr = __raw_readl(CCM_CSCR);
if (clk->parent == parent)
return 0;
if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
if (parent == &mpll_main1_clk) {
cscr |= CCM_CSCR_ARM_SRC;
} else {
if (parent == &mpll_main2_clk)
cscr &= ~CCM_CSCR_ARM_SRC;
else
return -EINVAL;
}
__raw_writel(cscr, CCM_CSCR);
clk->parent = parent;
return 0;
}
return -ENODEV;
}
static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate)
{
int div;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
div = parent_rate / rate;
if (parent_rate % rate)
div++;
if (div > 4)
div = 4;
return parent_rate / div;
}
static int set_rate_cpu(struct clk *clk, unsigned long rate)
{
unsigned int div;
uint32_t reg;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
div = parent_rate / rate;
if (div > 4 || div < 1 || ((parent_rate / div) != rate))
return -EINVAL;
div--;
reg = __raw_readl(CCM_CSCR);
if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
reg &= ~(3 << 12);
reg |= div << 12;
reg &= ~(CCM_CSCR_FPM | CCM_CSCR_SPEN);
__raw_writel(reg | CCM_CSCR_UPDATE_DIS, CCM_CSCR);
} else {
printk(KERN_ERR "Can't set CPU frequency!\n");
}
return 0;
}
static unsigned long round_rate_per(struct clk *clk, unsigned long rate)
{
u32 div;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
div = parent_rate / rate;
if (parent_rate % rate)
div++;
if (div > 64)
div = 64;
return parent_rate / div;
}
static int set_rate_per(struct clk *clk, unsigned long rate)
{
u32 reg;
u32 div;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
if (clk->id < 0 || clk->id > 3)
return -EINVAL;
div = parent_rate / rate;
if (div > 64 || div < 1 || ((parent_rate / div) != rate))
return -EINVAL;
div--;
reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk->id << 3));
reg |= div << (clk->id << 3);
__raw_writel(reg, CCM_PCDR1);
return 0;
}
static unsigned long get_rate_usb(struct clk *clk)
{
unsigned long usb_pdf;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
usb_pdf = (__raw_readl(CCM_CSCR) >> 28) & 0x7;
return parent_rate / (usb_pdf + 1U);
}
static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)
{
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
pdf += 4; /* MX27 TO2+ */
else
pdf = (pdf < 2) ? 124UL : pdf; /* MX21 & MX27 TO1 */
return 2UL * parent_rate / pdf;
}
static unsigned long get_rate_ssi1(struct clk *clk)
{
return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
}
static unsigned long get_rate_ssi2(struct clk *clk)
{
return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
}
static unsigned long get_rate_nfc(struct clk *clk)
{
unsigned long nfc_pdf;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf;
else
nfc_pdf = (__raw_readl(CCM_PCDR0) >> 12) & 0xf;
return parent_rate / (nfc_pdf + 1);
}
static unsigned long get_rate_vpu(struct clk *clk)
{
unsigned long vpu_pdf;
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f;
vpu_pdf += 4;
} else {
vpu_pdf = (__raw_readl(CCM_PCDR0) >> 8) & 0xf;
vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf;
}
return 2UL * parent_rate / vpu_pdf;
}
static unsigned long round_rate_parent(struct clk *clk, unsigned long rate)
{
return clk->parent->round_rate(clk->parent, rate);
}
static unsigned long get_rate_parent(struct clk *clk)
{
return clk_get_rate(clk->parent);
}
static int set_rate_parent(struct clk *clk, unsigned long rate)
{
return clk->parent->set_rate(clk->parent, rate);
}
/* in Hz */
static unsigned long external_high_reference = 26000000;
static unsigned long get_rate_high_reference(struct clk *clk)
{
return external_high_reference;
}
/* in Hz */
static unsigned long external_low_reference = 32768;
static unsigned long get_rate_low_reference(struct clk *clk)
{
return external_low_reference;
}
static unsigned long get_rate_fpm(struct clk *clk)
{
return clk_get_rate(clk->parent) * 1024;
}
static unsigned long get_rate_mpll(struct clk *clk)
{
return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
clk_get_rate(clk->parent));
}
static unsigned long get_rate_mpll_main(struct clk *clk)
{
unsigned long parent_rate;
parent_rate = clk_get_rate(clk->parent);
/* i.MX27 TO2:
* clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2
* clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3
*/
if (mx27_revision() >= IMX_CHIP_REVISION_2_0 && clk->id == 1)
return 2UL * parent_rate / 3UL;
return parent_rate;
}
static unsigned long get_rate_spll(struct clk *clk)
{
uint32_t reg;
unsigned long rate;
rate = clk_get_rate(clk->parent);
reg = __raw_readl(CCM_SPCTL0);
/* On TO2 we have to write the value back. Otherwise we
* read 0 from this register the next time.
*/
if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
__raw_writel(reg, CCM_SPCTL0);
return mxc_decode_pll(reg, rate);
}
static unsigned long get_rate_cpu(struct clk *clk)
{
u32 div;
unsigned long rate;
if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
div = (__raw_readl(CCM_CSCR) >> 12) & 0x3;
else
div = (__raw_readl(CCM_CSCR) >> 13) & 0x7;
rate = clk_get_rate(clk->parent);
return rate / (div + 1);
}
static unsigned long get_rate_ahb(struct clk *clk)
{
unsigned long rate, bclk_pdf;
if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
bclk_pdf = (__raw_readl(CCM_CSCR) >> 8) & 0x3;
else
bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf;
rate = clk_get_rate(clk->parent);
return rate / (bclk_pdf + 1);
}
static unsigned long get_rate_ipg(struct clk *clk)
{
unsigned long rate, ipg_pdf;
if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
return clk_get_rate(clk->parent);
else
ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1;
rate = clk_get_rate(clk->parent);
return rate / (ipg_pdf + 1);
}
static unsigned long get_rate_per(struct clk *clk)
{
unsigned long perclk_pdf, parent_rate;
parent_rate = clk_get_rate(clk->parent);
if (clk->id < 0 || clk->id > 3)
return 0;
perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk->id << 3)) & 0x3f;
return parent_rate / (perclk_pdf + 1);
}
/*
* the high frequency external clock reference
* Default case is 26MHz. Could be changed at runtime
* with a call to change_external_high_reference()
*/
static struct clk ckih_clk = {
.get_rate = get_rate_high_reference,
};
static struct clk mpll_clk = {
.parent = &ckih_clk,
.get_rate = get_rate_mpll,
};
/* For i.MX27 TO2, it is the MPLL path 1 of ARM core
* It provides the clock source whose rate is same as MPLL
*/
static struct clk mpll_main1_clk = {
.id = 0,
.parent = &mpll_clk,
.get_rate = get_rate_mpll_main,
};
/* For i.MX27 TO2, it is the MPLL path 2 of ARM core
* It provides the clock source whose rate is same MPLL * 2 / 3
*/
static struct clk mpll_main2_clk = {
.id = 1,
.parent = &mpll_clk,
.get_rate = get_rate_mpll_main,
};
static struct clk ahb_clk = {
.parent = &mpll_main2_clk,
.get_rate = get_rate_ahb,
};
static struct clk ipg_clk = {
.parent = &ahb_clk,
.get_rate = get_rate_ipg,
};
static struct clk cpu_clk = {
.parent = &mpll_main2_clk,
.set_parent = clk_cpu_set_parent,
.round_rate = round_rate_cpu,
.get_rate = get_rate_cpu,
.set_rate = set_rate_cpu,
};
static struct clk spll_clk = {
.parent = &ckih_clk,
.get_rate = get_rate_spll,
.enable = clk_spll_enable,
.disable = clk_spll_disable,
};
/*
* the low frequency external clock reference
* Default case is 32.768kHz.
*/
static struct clk ckil_clk = {
.get_rate = get_rate_low_reference,
};
/* Output of frequency pre multiplier */
static struct clk fpm_clk = {
.parent = &ckil_clk,
.get_rate = get_rate_fpm,
};
#define PCCR0 CCM_PCCR0
#define PCCR1 CCM_PCCR1
#define DEFINE_CLOCK(name, i, er, es, gr, s, p) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = gr, \
.enable = clk_pccr_enable, \
.disable = clk_pccr_disable, \
.secondary = s, \
.parent = p, \
}
#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = get_rate_##getsetround, \
.set_rate = set_rate_##getsetround, \
.round_rate = round_rate_##getsetround, \
.enable = clk_pccr_enable, \
.disable = clk_pccr_disable, \
.secondary = s, \
.parent = p, \
}
/* Forward declaration to keep the following list in order */
static struct clk slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1,
dma_clk1, lcdc_clk2, vpu_clk1;
/* All clocks we can gate through PCCRx in the order of PCCRx bits */
DEFINE_CLOCK(ssi2_clk1, 1, PCCR0, 0, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(ssi1_clk1, 0, PCCR0, 1, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(slcdc_clk, 0, PCCR0, 2, NULL, &slcdc_clk1, &ahb_clk);
DEFINE_CLOCK(sdhc3_clk1, 0, PCCR0, 3, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(sdhc2_clk1, 0, PCCR0, 4, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(sdhc1_clk1, 0, PCCR0, 5, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(scc_clk, 0, PCCR0, 6, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(sahara2_clk, 0, PCCR0, 7, NULL, &sahara2_clk1, &ahb_clk);
DEFINE_CLOCK(rtic_clk, 0, PCCR0, 8, NULL, &rtic_clk1, &ahb_clk);
DEFINE_CLOCK(rtc_clk, 0, PCCR0, 9, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(pwm_clk1, 0, PCCR0, 11, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(owire_clk, 0, PCCR0, 12, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(mstick_clk1, 0, PCCR0, 13, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(lcdc_clk1, 0, PCCR0, 14, NULL, &lcdc_clk2, &ipg_clk);
DEFINE_CLOCK(kpp_clk, 0, PCCR0, 15, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(iim_clk, 0, PCCR0, 16, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(i2c2_clk, 1, PCCR0, 17, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(i2c1_clk, 0, PCCR0, 18, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(gpt6_clk1, 0, PCCR0, 29, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(gpt5_clk1, 0, PCCR0, 20, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(gpt4_clk1, 0, PCCR0, 21, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(gpt3_clk1, 0, PCCR0, 22, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(gpt2_clk1, 0, PCCR0, 23, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(gpt1_clk1, 0, PCCR0, 24, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(gpio_clk, 0, PCCR0, 25, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(fec_clk, 0, PCCR0, 26, NULL, &fec_clk1, &ahb_clk);
DEFINE_CLOCK(emma_clk, 0, PCCR0, 27, NULL, &emma_clk1, &ahb_clk);
DEFINE_CLOCK(dma_clk, 0, PCCR0, 28, NULL, &dma_clk1, &ahb_clk);
DEFINE_CLOCK(cspi13_clk1, 0, PCCR0, 29, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(cspi2_clk1, 0, PCCR0, 30, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(cspi1_clk1, 0, PCCR0, 31, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(mstick_clk, 0, PCCR1, 2, NULL, &mstick_clk1, &ipg_clk);
DEFINE_CLOCK(nfc_clk, 0, PCCR1, 3, get_rate_nfc, NULL, &cpu_clk);
DEFINE_CLOCK(ssi2_clk, 1, PCCR1, 4, get_rate_ssi2, &ssi2_clk1, &mpll_main2_clk);
DEFINE_CLOCK(ssi1_clk, 0, PCCR1, 5, get_rate_ssi1, &ssi1_clk1, &mpll_main2_clk);
DEFINE_CLOCK(vpu_clk, 0, PCCR1, 6, get_rate_vpu, &vpu_clk1, &mpll_main2_clk);
DEFINE_CLOCK1(per4_clk, 3, PCCR1, 7, per, NULL, &mpll_main2_clk);
DEFINE_CLOCK1(per3_clk, 2, PCCR1, 8, per, NULL, &mpll_main2_clk);
DEFINE_CLOCK1(per2_clk, 1, PCCR1, 9, per, NULL, &mpll_main2_clk);
DEFINE_CLOCK1(per1_clk, 0, PCCR1, 10, per, NULL, &mpll_main2_clk);
DEFINE_CLOCK(usb_clk1, 0, PCCR1, 11, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(slcdc_clk1, 0, PCCR1, 12, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(sahara2_clk1, 0, PCCR1, 13, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(rtic_clk1, 0, PCCR1, 14, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(lcdc_clk2, 0, PCCR1, 15, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(vpu_clk1, 0, PCCR1, 16, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(fec_clk1, 0, PCCR1, 17, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(emma_clk1, 0, PCCR1, 18, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(emi_clk, 0, PCCR1, 19, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(dma_clk1, 0, PCCR1, 20, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(csi_clk1, 0, PCCR1, 21, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(brom_clk, 0, PCCR1, 22, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(pata_clk, 0, PCCR1, 23, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(wdog_clk, 0, PCCR1, 24, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(usb_clk, 0, PCCR1, 25, get_rate_usb, &usb_clk1, &spll_clk);
DEFINE_CLOCK(uart6_clk1, 0, PCCR1, 26, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(uart5_clk1, 0, PCCR1, 27, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(uart4_clk1, 0, PCCR1, 28, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(uart3_clk1, 0, PCCR1, 29, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(uart2_clk1, 0, PCCR1, 30, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(uart1_clk1, 0, PCCR1, 31, NULL, NULL, &ipg_clk);
/* Clocks we cannot directly gate, but drivers need their rates */
DEFINE_CLOCK(cspi1_clk, 0, NULL, 0, NULL, &cspi1_clk1, &per2_clk);
DEFINE_CLOCK(cspi2_clk, 1, NULL, 0, NULL, &cspi2_clk1, &per2_clk);
DEFINE_CLOCK(cspi3_clk, 2, NULL, 0, NULL, &cspi13_clk1, &per2_clk);
DEFINE_CLOCK(sdhc1_clk, 0, NULL, 0, NULL, &sdhc1_clk1, &per2_clk);
DEFINE_CLOCK(sdhc2_clk, 1, NULL, 0, NULL, &sdhc2_clk1, &per2_clk);
DEFINE_CLOCK(sdhc3_clk, 2, NULL, 0, NULL, &sdhc3_clk1, &per2_clk);
DEFINE_CLOCK(pwm_clk, 0, NULL, 0, NULL, &pwm_clk1, &per1_clk);
DEFINE_CLOCK(gpt1_clk, 0, NULL, 0, NULL, &gpt1_clk1, &per1_clk);
DEFINE_CLOCK(gpt2_clk, 1, NULL, 0, NULL, &gpt2_clk1, &per1_clk);
DEFINE_CLOCK(gpt3_clk, 2, NULL, 0, NULL, &gpt3_clk1, &per1_clk);
DEFINE_CLOCK(gpt4_clk, 3, NULL, 0, NULL, &gpt4_clk1, &per1_clk);
DEFINE_CLOCK(gpt5_clk, 4, NULL, 0, NULL, &gpt5_clk1, &per1_clk);
DEFINE_CLOCK(gpt6_clk, 5, NULL, 0, NULL, &gpt6_clk1, &per1_clk);
DEFINE_CLOCK(uart1_clk, 0, NULL, 0, NULL, &uart1_clk1, &per1_clk);
DEFINE_CLOCK(uart2_clk, 1, NULL, 0, NULL, &uart2_clk1, &per1_clk);
DEFINE_CLOCK(uart3_clk, 2, NULL, 0, NULL, &uart3_clk1, &per1_clk);
DEFINE_CLOCK(uart4_clk, 3, NULL, 0, NULL, &uart4_clk1, &per1_clk);
DEFINE_CLOCK(uart5_clk, 4, NULL, 0, NULL, &uart5_clk1, &per1_clk);
DEFINE_CLOCK(uart6_clk, 5, NULL, 0, NULL, &uart6_clk1, &per1_clk);
DEFINE_CLOCK1(lcdc_clk, 0, NULL, 0, parent, &lcdc_clk1, &per3_clk);
DEFINE_CLOCK1(csi_clk, 0, NULL, 0, parent, &csi_clk1, &per4_clk);
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static struct clk_lookup lookups[] = {
/* i.mx27 has the i.mx21 type uart */
_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
_REGISTER_CLOCK("imx21-uart.5", NULL, uart6_clk)
_REGISTER_CLOCK(NULL, "gpt1", gpt1_clk)
_REGISTER_CLOCK(NULL, "gpt2", gpt2_clk)
_REGISTER_CLOCK(NULL, "gpt3", gpt3_clk)
_REGISTER_CLOCK(NULL, "gpt4", gpt4_clk)
_REGISTER_CLOCK(NULL, "gpt5", gpt5_clk)
_REGISTER_CLOCK(NULL, "gpt6", gpt6_clk)
_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm_clk)
_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
_REGISTER_CLOCK("mxc-mmc.2", NULL, sdhc3_clk)
_REGISTER_CLOCK("imx27-cspi.0", NULL, cspi1_clk)
_REGISTER_CLOCK("imx27-cspi.1", NULL, cspi2_clk)
_REGISTER_CLOCK("imx27-cspi.2", NULL, cspi3_clk)
_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
_REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk1)
_REGISTER_CLOCK("mxc-ehci.0", "usb", usb_clk)
_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_clk1)
_REGISTER_CLOCK("mxc-ehci.1", "usb", usb_clk)
_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1)
_REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk)
_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1)
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
_REGISTER_CLOCK(NULL, "vpu", vpu_clk)
_REGISTER_CLOCK(NULL, "dma", dma_clk)
_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
_REGISTER_CLOCK(NULL, "brom", brom_clk)
_REGISTER_CLOCK(NULL, "emma", emma_clk)
_REGISTER_CLOCK("m2m-emmaprp.0", NULL, emma_clk)
_REGISTER_CLOCK(NULL, "slcdc", slcdc_clk)
_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
_REGISTER_CLOCK(NULL, "emi", emi_clk)
_REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
_REGISTER_CLOCK(NULL, "mstick", mstick_clk)
_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
_REGISTER_CLOCK(NULL, "gpio", gpio_clk)
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
_REGISTER_CLOCK(NULL, "iim", iim_clk)
_REGISTER_CLOCK(NULL, "kpp", kpp_clk)
_REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)
_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
_REGISTER_CLOCK(NULL, "scc", scc_clk)
};
/* Adjust the clock path for TO2 and later */
static void __init to2_adjust_clocks(void)
{
unsigned long cscr = __raw_readl(CCM_CSCR);
if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
if (cscr & CCM_CSCR_ARM_SRC)
cpu_clk.parent = &mpll_main1_clk;
if (!(cscr & CCM_CSCR_SSI2))
ssi1_clk.parent = &spll_clk;
if (!(cscr & CCM_CSCR_SSI1))
ssi1_clk.parent = &spll_clk;
if (!(cscr & CCM_CSCR_VPU))
vpu_clk.parent = &spll_clk;
} else {
cpu_clk.parent = &mpll_clk;
cpu_clk.set_parent = NULL;
cpu_clk.round_rate = NULL;
cpu_clk.set_rate = NULL;
ahb_clk.parent = &mpll_clk;
per1_clk.parent = &mpll_clk;
per2_clk.parent = &mpll_clk;
per3_clk.parent = &mpll_clk;
per4_clk.parent = &mpll_clk;
ssi1_clk.parent = &mpll_clk;
ssi2_clk.parent = &mpll_clk;
vpu_clk.parent = &mpll_clk;
}
}
/*
* must be called very early to get information about the
* available clock rate when the timer framework starts
*/
int __init mx27_clocks_init(unsigned long fref)
{
u32 cscr = __raw_readl(CCM_CSCR);
external_high_reference = fref;
/* detect clock reference for both system PLLs */
if (cscr & CCM_CSCR_MCU)
mpll_clk.parent = &ckih_clk;
else
mpll_clk.parent = &fpm_clk;
if (cscr & CCM_CSCR_SP)
spll_clk.parent = &ckih_clk;
else
spll_clk.parent = &fpm_clk;
to2_adjust_clocks();
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
/* Turn off all clocks we do not need */
__raw_writel(0, CCM_PCCR0);
__raw_writel((1 << 10) | (1 << 19), CCM_PCCR1);
spll_clk.disable(&spll_clk);
/* enable basic clocks */
clk_enable(&per1_clk);
clk_enable(&gpio_clk);
clk_enable(&emi_clk);
clk_enable(&iim_clk);
imx_print_silicon_rev("i.MX27", mx27_revision());
clk_disable(&iim_clk);
#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
clk_enable(&uart1_clk);
#endif
mxc_timer_init(&gpt1_clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
MX27_INT_GPT1);
return 0;
}
#ifdef CONFIG_OF
int __init mx27_clocks_init_dt(void)
{
struct device_node *np;
u32 fref = 26000000; /* default */
for_each_compatible_node(np, NULL, "fixed-clock") {
if (!of_device_is_compatible(np, "fsl,imx-osc26m"))
continue;
if (!of_property_read_u32(np, "clock-frequency", &fref))
break;
}
return mx27_clocks_init(fref);
}
#endif

View File

@ -1,630 +0,0 @@
/*
* 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 <linux/clkdev.h>
#include <asm/div64.h>
#include <mach/clock.h>
#include <mach/hardware.h>
#include <mach/mx31.h>
#include <mach/common.h>
#include "crmregs-imx3.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 serial_pll_clk;
static struct clk ipg_clk;
static struct clk ckih_clk;
static int cgr_enable(struct clk *clk)
{
u32 reg;
if (!clk->enable_reg)
return 0;
reg = __raw_readl(clk->enable_reg);
reg |= 3 << clk->enable_shift;
__raw_writel(reg, clk->enable_reg);
return 0;
}
static void cgr_disable(struct clk *clk)
{
u32 reg;
if (!clk->enable_reg)
return;
reg = __raw_readl(clk->enable_reg);
reg &= ~(3 << clk->enable_shift);
/* special case for EMI clock */
if (clk->enable_reg == MXC_CCM_CGR2 && clk->enable_shift == 8)
reg |= (1 << clk->enable_shift);
__raw_writel(reg, clk->enable_reg);
}
static unsigned long pll_ref_get_rate(void)
{
unsigned long ccmr;
unsigned int prcs;
ccmr = __raw_readl(MXC_CCM_CCMR);
prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
if (prcs == 0x1)
return CKIL_CLK_FREQ * 1024;
else
return clk_get_rate(&ckih_clk);
}
static unsigned long usb_pll_get_rate(struct clk *clk)
{
unsigned long reg;
reg = __raw_readl(MXC_CCM_UPCTL);
return mxc_decode_pll(reg, pll_ref_get_rate());
}
static unsigned long serial_pll_get_rate(struct clk *clk)
{
unsigned long reg;
reg = __raw_readl(MXC_CCM_SRPCTL);
return mxc_decode_pll(reg, pll_ref_get_rate());
}
static unsigned long mcu_pll_get_rate(struct clk *clk)
{
unsigned long reg, ccmr;
ccmr = __raw_readl(MXC_CCM_CCMR);
if (!(ccmr & MXC_CCM_CCMR_MPE) || (ccmr & MXC_CCM_CCMR_MDS))
return clk_get_rate(&ckih_clk);
reg = __raw_readl(MXC_CCM_MPCTL);
return mxc_decode_pll(reg, pll_ref_get_rate());
}
static int 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 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 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 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 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 ahb_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 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 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 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 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 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 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 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 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 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 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 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 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 mbx_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 2;
}
static unsigned long 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 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 unsigned long clk_ckil_get_rate(struct clk *clk)
{
return CKIL_CLK_FREQ;
}
static struct clk ckih_clk = {
.get_rate = clk_ckih_get_rate,
};
static struct clk mcu_pll_clk = {
.parent = &ckih_clk,
.get_rate = mcu_pll_get_rate,
};
static struct clk mcu_main_clk = {
.parent = &mcu_pll_clk,
.get_rate = mcu_main_get_rate,
};
static struct clk serial_pll_clk = {
.parent = &ckih_clk,
.get_rate = serial_pll_get_rate,
.enable = serial_pll_enable,
.disable = serial_pll_disable,
};
static struct clk usb_pll_clk = {
.parent = &ckih_clk,
.get_rate = usb_pll_get_rate,
.enable = usb_pll_enable,
.disable = usb_pll_disable,
};
static struct clk ahb_clk = {
.parent = &mcu_main_clk,
.get_rate = ahb_get_rate,
};
#define DEFINE_CLOCK(name, i, er, es, gr, s, p) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = gr, \
.enable = cgr_enable, \
.disable = cgr_disable, \
.secondary = s, \
.parent = p, \
}
#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = getsetround##_get_rate, \
.set_rate = getsetround##_set_rate, \
.round_rate = getsetround##_round_rate, \
.enable = cgr_enable, \
.disable = cgr_disable, \
.secondary = s, \
.parent = p, \
}
DEFINE_CLOCK(perclk_clk, 0, NULL, 0, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(ckil_clk, 0, NULL, 0, clk_ckil_get_rate, NULL, NULL);
DEFINE_CLOCK(sdhc1_clk, 0, MXC_CCM_CGR0, 0, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(sdhc2_clk, 1, MXC_CCM_CGR0, 2, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CGR0, 4, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(epit1_clk, 0, MXC_CCM_CGR0, 6, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(epit2_clk, 1, MXC_CCM_CGR0, 8, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(iim_clk, 0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(sdma_clk1, 0, MXC_CCM_CGR0, 14, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(cspi3_clk, 2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(rng_clk, 0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CGR0, 20, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CGR0, 22, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CGR0, 24, ssi1_get_rate, NULL, &serial_pll_clk);
DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CGR0, 26, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CGR0, 28, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(i2c3_clk, 2, MXC_CCM_CGR0, 30, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(mpeg4_clk, 0, MXC_CCM_CGR1, 0, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(mstick1_clk, 0, MXC_CCM_CGR1, 2, mstick1_get_rate, NULL, &usb_pll_clk);
DEFINE_CLOCK(mstick2_clk, 1, MXC_CCM_CGR1, 4, mstick2_get_rate, NULL, &usb_pll_clk);
DEFINE_CLOCK1(csi_clk, 0, MXC_CCM_CGR1, 6, csi, NULL, &serial_pll_clk);
DEFINE_CLOCK(rtc_clk, 0, MXC_CCM_CGR1, 8, NULL, NULL, &ckil_clk);
DEFINE_CLOCK(wdog_clk, 0, MXC_CCM_CGR1, 10, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(pwm_clk, 0, MXC_CCM_CGR1, 12, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(usb_clk2, 0, MXC_CCM_CGR1, 18, usb_get_rate, NULL, &ahb_clk);
DEFINE_CLOCK(kpp_clk, 0, MXC_CCM_CGR1, 20, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(ipu_clk, 0, MXC_CCM_CGR1, 22, hsp_get_rate, NULL, &mcu_main_clk);
DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CGR1, 24, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CGR1, 26, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CGR1, 28, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(owire_clk, 0, MXC_CCM_CGR1, 30, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CGR2, 0, ssi2_get_rate, NULL, &serial_pll_clk);
DEFINE_CLOCK(cspi1_clk, 0, MXC_CCM_CGR2, 2, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(cspi2_clk, 1, MXC_CCM_CGR2, 4, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(mbx_clk, 0, MXC_CCM_CGR2, 6, mbx_get_rate, NULL, &ahb_clk);
DEFINE_CLOCK(emi_clk, 0, MXC_CCM_CGR2, 8, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(rtic_clk, 0, MXC_CCM_CGR2, 10, NULL, NULL, &ahb_clk);
DEFINE_CLOCK1(firi_clk, 0, MXC_CCM_CGR2, 12, firi, NULL, &usb_pll_clk);
DEFINE_CLOCK(sdma_clk2, 0, NULL, 0, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(usb_clk1, 0, NULL, 0, usb_get_rate, NULL, &usb_pll_clk);
DEFINE_CLOCK(nfc_clk, 0, NULL, 0, nfc_get_rate, NULL, &ahb_clk);
DEFINE_CLOCK(scc_clk, 0, NULL, 0, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(ipg_clk, 0, NULL, 0, ipg_get_rate, NULL, &ahb_clk);
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "emi", emi_clk)
_REGISTER_CLOCK("imx31-cspi.0", NULL, cspi1_clk)
_REGISTER_CLOCK("imx31-cspi.1", NULL, cspi2_clk)
_REGISTER_CLOCK("imx31-cspi.2", NULL, cspi3_clk)
_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
_REGISTER_CLOCK(NULL, "epit", epit1_clk)
_REGISTER_CLOCK(NULL, "epit", epit2_clk)
_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
_REGISTER_CLOCK("ipu-core", NULL, ipu_clk)
_REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk)
_REGISTER_CLOCK(NULL, "kpp", kpp_clk)
_REGISTER_CLOCK("mxc-ehci.0", "usb", usb_clk1)
_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_clk2)
_REGISTER_CLOCK("mxc-ehci.1", "usb", usb_clk1)
_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk2)
_REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk1)
_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk2)
_REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk1)
_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk2)
_REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk)
/* i.mx31 has the i.mx21 type uart */
_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
_REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)
_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
_REGISTER_CLOCK(NULL, "firi", firi_clk)
_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
_REGISTER_CLOCK(NULL, "rng", rng_clk)
_REGISTER_CLOCK("imx31-sdma", NULL, sdma_clk1)
_REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
_REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
_REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
_REGISTER_CLOCK(NULL, "scc", scc_clk)
_REGISTER_CLOCK(NULL, "iim", iim_clk)
_REGISTER_CLOCK(NULL, "mpeg4", mpeg4_clk)
_REGISTER_CLOCK(NULL, "mbx", mbx_clk)
};
int __init mx31_clocks_init(unsigned long fref)
{
u32 reg;
ckih_rate = fref;
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
/* change the csi_clk parent if necessary */
reg = __raw_readl(MXC_CCM_CCMR);
if (!(reg & MXC_CCM_CCMR_CSCS))
if (clk_set_parent(&csi_clk, &usb_pll_clk))
pr_err("%s: error changing csi_clk parent\n", __func__);
/* Turn off all possible clocks */
__raw_writel((3 << 4), MXC_CCM_CGR0);
__raw_writel(0, MXC_CCM_CGR1);
__raw_writel((3 << 8) | (3 << 14) | (3 << 16)|
1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
MX32, but still required to be set */
MXC_CCM_CGR2);
/*
* Before turning off usb_pll make sure ipg_per_clk is generated
* by ipg_clk and not usb_pll.
*/
__raw_writel(__raw_readl(MXC_CCM_CCMR) | (1 << 24), MXC_CCM_CCMR);
usb_pll_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);
mx31_revision();
clk_disable(&iim_clk);
clk_enable(&serial_pll_clk);
if (mx31_revision() >= IMX_CHIP_REVISION_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);
}
mxc_timer_init(&ipg_clk, MX31_IO_ADDRESS(MX31_GPT1_BASE_ADDR),
MX31_INT_GPT);
return 0;
}

View File

@ -1,536 +0,0 @@
/*
* Copyright (C) 2009 by Sascha Hauer, Pengutronix
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <mach/clock.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include "crmregs-imx3.h"
#ifdef HAVE_SET_RATE_SUPPORT
static void calc_dividers(u32 div, u32 *pre, u32 *post, u32 maxpost)
{
u32 min_pre, temp_pre, old_err, err;
min_pre = (div - 1) / maxpost + 1;
old_err = 8;
for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
if (div > (temp_pre * maxpost))
break;
if (div < (temp_pre * temp_pre))
continue;
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;
}
/* get the best values for a 3-bit divider combined with a 6-bit divider */
static void calc_dividers_3_6(u32 div, u32 *pre, u32 *post)
{
if (div >= 512) {
*pre = 8;
*post = 64;
} else if (div >= 64) {
calc_dividers(div, pre, post, 64);
} else if (div <= 8) {
*pre = div;
*post = 1;
} else {
*pre = 1;
*post = div;
}
}
/* get the best values for two cascaded 3-bit dividers */
static void calc_dividers_3_3(u32 div, u32 *pre, u32 *post)
{
if (div >= 64) {
*pre = *post = 8;
} else if (div > 8) {
calc_dividers(div, pre, post, 8);
} else {
*pre = 1;
*post = div;
}
}
#endif
static unsigned long get_rate_mpll(void)
{
ulong mpctl = __raw_readl(MX35_CCM_MPCTL);
return mxc_decode_pll(mpctl, 24000000);
}
static unsigned long get_rate_ppll(void)
{
ulong ppctl = __raw_readl(MX35_CCM_PPCTL);
return mxc_decode_pll(ppctl, 24000000);
}
struct arm_ahb_div {
unsigned char arm, ahb, sel;
};
static struct arm_ahb_div clk_consumer[] = {
{ .arm = 1, .ahb = 4, .sel = 0},
{ .arm = 1, .ahb = 3, .sel = 1},
{ .arm = 2, .ahb = 2, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 4, .ahb = 1, .sel = 0},
{ .arm = 1, .ahb = 5, .sel = 0},
{ .arm = 1, .ahb = 8, .sel = 0},
{ .arm = 1, .ahb = 6, .sel = 1},
{ .arm = 2, .ahb = 4, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
{ .arm = 4, .ahb = 2, .sel = 0},
{ .arm = 0, .ahb = 0, .sel = 0},
};
static unsigned long get_rate_arm(void)
{
unsigned long pdr0 = __raw_readl(MXC_CCM_PDR0);
struct arm_ahb_div *aad;
unsigned long fref = get_rate_mpll();
aad = &clk_consumer[(pdr0 >> 16) & 0xf];
if (aad->sel)
fref = fref * 3 / 4;
return fref / aad->arm;
}
static unsigned long get_rate_ahb(struct clk *clk)
{
unsigned long pdr0 = __raw_readl(MXC_CCM_PDR0);
struct arm_ahb_div *aad;
unsigned long fref = get_rate_arm();
aad = &clk_consumer[(pdr0 >> 16) & 0xf];
return fref / aad->ahb;
}
static unsigned long get_rate_ipg(struct clk *clk)
{
return get_rate_ahb(NULL) >> 1;
}
static unsigned long get_rate_uart(struct clk *clk)
{
unsigned long pdr3 = __raw_readl(MX35_CCM_PDR3);
unsigned long pdr4 = __raw_readl(MX35_CCM_PDR4);
unsigned long div = ((pdr4 >> 10) & 0x3f) + 1;
if (pdr3 & (1 << 14))
return get_rate_arm() / div;
else
return get_rate_ppll() / div;
}
static unsigned long get_rate_sdhc(struct clk *clk)
{
unsigned long pdr3 = __raw_readl(MX35_CCM_PDR3);
unsigned long div, rate;
if (pdr3 & (1 << 6))
rate = get_rate_arm();
else
rate = get_rate_ppll();
switch (clk->id) {
default:
case 0:
div = pdr3 & 0x3f;
break;
case 1:
div = (pdr3 >> 8) & 0x3f;
break;
case 2:
div = (pdr3 >> 16) & 0x3f;
break;
}
return rate / (div + 1);
}
static unsigned long get_rate_mshc(struct clk *clk)
{
unsigned long pdr1 = __raw_readl(MXC_CCM_PDR1);
unsigned long div1, div2, rate;
if (pdr1 & (1 << 7))
rate = get_rate_arm();
else
rate = get_rate_ppll();
div1 = (pdr1 >> 29) & 0x7;
div2 = (pdr1 >> 22) & 0x3f;
return rate / ((div1 + 1) * (div2 + 1));
}
static unsigned long get_rate_ssi(struct clk *clk)
{
unsigned long pdr2 = __raw_readl(MX35_CCM_PDR2);
unsigned long div1, div2, rate;
if (pdr2 & (1 << 6))
rate = get_rate_arm();
else
rate = get_rate_ppll();
switch (clk->id) {
default:
case 0:
div1 = pdr2 & 0x3f;
div2 = (pdr2 >> 24) & 0x7;
break;
case 1:
div1 = (pdr2 >> 8) & 0x3f;
div2 = (pdr2 >> 27) & 0x7;
break;
}
return rate / ((div1 + 1) * (div2 + 1));
}
static unsigned long get_rate_csi(struct clk *clk)
{
unsigned long pdr2 = __raw_readl(MX35_CCM_PDR2);
unsigned long rate;
if (pdr2 & (1 << 7))
rate = get_rate_arm();
else
rate = get_rate_ppll();
return rate / (((pdr2 >> 16) & 0x3f) + 1);
}
static unsigned long get_rate_otg(struct clk *clk)
{
unsigned long pdr4 = __raw_readl(MX35_CCM_PDR4);
unsigned long rate;
if (pdr4 & (1 << 9))
rate = get_rate_arm();
else
rate = get_rate_ppll();
return rate / (((pdr4 >> 22) & 0x3f) + 1);
}
static unsigned long get_rate_ipg_per(struct clk *clk)
{
unsigned long pdr0 = __raw_readl(MXC_CCM_PDR0);
unsigned long pdr4 = __raw_readl(MX35_CCM_PDR4);
unsigned long div;
if (pdr0 & (1 << 26)) {
div = (pdr4 >> 16) & 0x3f;
return get_rate_arm() / (div + 1);
} else {
div = (pdr0 >> 12) & 0x7;
return get_rate_ahb(NULL) / (div + 1);
}
}
static unsigned long get_rate_hsp(struct clk *clk)
{
unsigned long hsp_podf = (__raw_readl(MXC_CCM_PDR0) >> 20) & 0x03;
unsigned long fref = get_rate_mpll();
if (fref > 400 * 1000 * 1000) {
switch (hsp_podf) {
case 0:
return fref >> 2;
case 1:
return fref >> 3;
case 2:
return fref / 3;
}
} else {
switch (hsp_podf) {
case 0:
case 2:
return fref / 3;
case 1:
return fref / 6;
}
}
return 0;
}
static int clk_cgr_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_cgr_disable(struct clk *clk)
{
u32 reg;
reg = __raw_readl(clk->enable_reg);
reg &= ~(3 << clk->enable_shift);
__raw_writel(reg, clk->enable_reg);
}
#define DEFINE_CLOCK(name, i, er, es, gr, sr) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = gr, \
.set_rate = sr, \
.enable = clk_cgr_enable, \
.disable = clk_cgr_disable, \
}
DEFINE_CLOCK(asrc_clk, 0, MX35_CCM_CGR0, 0, NULL, NULL);
DEFINE_CLOCK(pata_clk, 0, MX35_CCM_CGR0, 2, get_rate_ipg, NULL);
/* DEFINE_CLOCK(audmux_clk, 0, MX35_CCM_CGR0, 4, NULL, NULL); */
DEFINE_CLOCK(can1_clk, 0, MX35_CCM_CGR0, 6, get_rate_ipg, NULL);
DEFINE_CLOCK(can2_clk, 1, MX35_CCM_CGR0, 8, get_rate_ipg, NULL);
DEFINE_CLOCK(cspi1_clk, 0, MX35_CCM_CGR0, 10, get_rate_ipg, NULL);
DEFINE_CLOCK(cspi2_clk, 1, MX35_CCM_CGR0, 12, get_rate_ipg, NULL);
DEFINE_CLOCK(ect_clk, 0, MX35_CCM_CGR0, 14, get_rate_ipg, NULL);
DEFINE_CLOCK(edio_clk, 0, MX35_CCM_CGR0, 16, NULL, NULL);
DEFINE_CLOCK(emi_clk, 0, MX35_CCM_CGR0, 18, get_rate_ipg, NULL);
DEFINE_CLOCK(epit1_clk, 0, MX35_CCM_CGR0, 20, get_rate_ipg, NULL);
DEFINE_CLOCK(epit2_clk, 1, MX35_CCM_CGR0, 22, get_rate_ipg, NULL);
DEFINE_CLOCK(esai_clk, 0, MX35_CCM_CGR0, 24, NULL, NULL);
DEFINE_CLOCK(esdhc1_clk, 0, MX35_CCM_CGR0, 26, get_rate_sdhc, NULL);
DEFINE_CLOCK(esdhc2_clk, 1, MX35_CCM_CGR0, 28, get_rate_sdhc, NULL);
DEFINE_CLOCK(esdhc3_clk, 2, MX35_CCM_CGR0, 30, get_rate_sdhc, NULL);
DEFINE_CLOCK(fec_clk, 0, MX35_CCM_CGR1, 0, get_rate_ipg, NULL);
DEFINE_CLOCK(gpio1_clk, 0, MX35_CCM_CGR1, 2, NULL, NULL);
DEFINE_CLOCK(gpio2_clk, 1, MX35_CCM_CGR1, 4, NULL, NULL);
DEFINE_CLOCK(gpio3_clk, 2, MX35_CCM_CGR1, 6, NULL, NULL);
DEFINE_CLOCK(gpt_clk, 0, MX35_CCM_CGR1, 8, get_rate_ipg, NULL);
DEFINE_CLOCK(i2c1_clk, 0, MX35_CCM_CGR1, 10, get_rate_ipg_per, NULL);
DEFINE_CLOCK(i2c2_clk, 1, MX35_CCM_CGR1, 12, get_rate_ipg_per, NULL);
DEFINE_CLOCK(i2c3_clk, 2, MX35_CCM_CGR1, 14, get_rate_ipg_per, NULL);
DEFINE_CLOCK(iomuxc_clk, 0, MX35_CCM_CGR1, 16, NULL, NULL);
DEFINE_CLOCK(ipu_clk, 0, MX35_CCM_CGR1, 18, get_rate_hsp, NULL);
DEFINE_CLOCK(kpp_clk, 0, MX35_CCM_CGR1, 20, get_rate_ipg, NULL);
DEFINE_CLOCK(mlb_clk, 0, MX35_CCM_CGR1, 22, get_rate_ahb, NULL);
DEFINE_CLOCK(mshc_clk, 0, MX35_CCM_CGR1, 24, get_rate_mshc, NULL);
DEFINE_CLOCK(owire_clk, 0, MX35_CCM_CGR1, 26, get_rate_ipg_per, NULL);
DEFINE_CLOCK(pwm_clk, 0, MX35_CCM_CGR1, 28, get_rate_ipg_per, NULL);
DEFINE_CLOCK(rngc_clk, 0, MX35_CCM_CGR1, 30, get_rate_ipg, NULL);
DEFINE_CLOCK(rtc_clk, 0, MX35_CCM_CGR2, 0, get_rate_ipg, NULL);
DEFINE_CLOCK(rtic_clk, 0, MX35_CCM_CGR2, 2, get_rate_ahb, NULL);
DEFINE_CLOCK(scc_clk, 0, MX35_CCM_CGR2, 4, get_rate_ipg, NULL);
DEFINE_CLOCK(sdma_clk, 0, MX35_CCM_CGR2, 6, NULL, NULL);
DEFINE_CLOCK(spba_clk, 0, MX35_CCM_CGR2, 8, get_rate_ipg, NULL);
DEFINE_CLOCK(spdif_clk, 0, MX35_CCM_CGR2, 10, NULL, NULL);
DEFINE_CLOCK(ssi1_clk, 0, MX35_CCM_CGR2, 12, get_rate_ssi, NULL);
DEFINE_CLOCK(ssi2_clk, 1, MX35_CCM_CGR2, 14, get_rate_ssi, NULL);
DEFINE_CLOCK(uart1_clk, 0, MX35_CCM_CGR2, 16, get_rate_uart, NULL);
DEFINE_CLOCK(uart2_clk, 1, MX35_CCM_CGR2, 18, get_rate_uart, NULL);
DEFINE_CLOCK(uart3_clk, 2, MX35_CCM_CGR2, 20, get_rate_uart, NULL);
DEFINE_CLOCK(usbotg_clk, 0, MX35_CCM_CGR2, 22, get_rate_otg, NULL);
DEFINE_CLOCK(wdog_clk, 0, MX35_CCM_CGR2, 24, NULL, NULL);
DEFINE_CLOCK(max_clk, 0, MX35_CCM_CGR2, 26, NULL, NULL);
DEFINE_CLOCK(audmux_clk, 0, MX35_CCM_CGR2, 30, NULL, NULL);
DEFINE_CLOCK(csi_clk, 0, MX35_CCM_CGR3, 0, get_rate_csi, NULL);
DEFINE_CLOCK(iim_clk, 0, MX35_CCM_CGR3, 2, NULL, NULL);
DEFINE_CLOCK(gpu2d_clk, 0, MX35_CCM_CGR3, 4, NULL, NULL);
DEFINE_CLOCK(usbahb_clk, 0, 0, 0, get_rate_ahb, NULL);
static int clk_dummy_enable(struct clk *clk)
{
return 0;
}
static void clk_dummy_disable(struct clk *clk)
{
}
static unsigned long get_rate_nfc(struct clk *clk)
{
unsigned long div1;
div1 = (__raw_readl(MX35_CCM_PDR4) >> 28) + 1;
return get_rate_ahb(NULL) / div1;
}
/* NAND Controller: It seems it can't be disabled */
static struct clk nfc_clk = {
.id = 0,
.enable_reg = 0,
.enable_shift = 0,
.get_rate = get_rate_nfc,
.set_rate = NULL, /* set_rate_nfc, */
.enable = clk_dummy_enable,
.disable = clk_dummy_disable
};
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "asrc", asrc_clk)
_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
_REGISTER_CLOCK("imx35-cspi.1", NULL, cspi2_clk)
_REGISTER_CLOCK(NULL, "ect", ect_clk)
_REGISTER_CLOCK(NULL, "edio", edio_clk)
_REGISTER_CLOCK(NULL, "emi", emi_clk)
_REGISTER_CLOCK("imx-epit.0", NULL, epit1_clk)
_REGISTER_CLOCK("imx-epit.1", NULL, epit2_clk)
_REGISTER_CLOCK(NULL, "esai", esai_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx35.0", NULL, esdhc1_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx35.1", NULL, esdhc2_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx35.2", NULL, esdhc3_clk)
/* i.mx35 has the i.mx27 type fec */
_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
_REGISTER_CLOCK(NULL, "gpio", gpio1_clk)
_REGISTER_CLOCK(NULL, "gpio", gpio2_clk)
_REGISTER_CLOCK(NULL, "gpio", gpio3_clk)
_REGISTER_CLOCK("gpt.0", NULL, gpt_clk)
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
_REGISTER_CLOCK(NULL, "iomuxc", iomuxc_clk)
_REGISTER_CLOCK("ipu-core", NULL, ipu_clk)
_REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk)
_REGISTER_CLOCK(NULL, "kpp", kpp_clk)
_REGISTER_CLOCK(NULL, "mlb", mlb_clk)
_REGISTER_CLOCK(NULL, "mshc", mshc_clk)
_REGISTER_CLOCK("mxc_w1", NULL, owire_clk)
_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
_REGISTER_CLOCK(NULL, "rngc", rngc_clk)
_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
_REGISTER_CLOCK(NULL, "scc", scc_clk)
_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
_REGISTER_CLOCK(NULL, "spba", spba_clk)
_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
/* i.mx35 has the i.mx21 type uart */
_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
_REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk)
_REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usbahb_clk)
_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
_REGISTER_CLOCK(NULL, "max", max_clk)
_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
_REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk)
_REGISTER_CLOCK(NULL, "iim", iim_clk)
_REGISTER_CLOCK(NULL, "gpu2d", gpu2d_clk)
_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
};
int __init mx35_clocks_init()
{
unsigned int cgr2 = 3 << 26;
#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
cgr2 |= 3 << 16;
#endif
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
/* Turn off all clocks except the ones we need to survive, namely:
* EMI, GPIO1/2/3, GPT, IOMUX, MAX and eventually uart
*/
__raw_writel((3 << 18), MX35_CCM_CGR0);
__raw_writel((3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 16),
MX35_CCM_CGR1);
__raw_writel(cgr2, MX35_CCM_CGR2);
__raw_writel(0, MX35_CCM_CGR3);
clk_enable(&iim_clk);
imx_print_silicon_rev("i.MX35", mx35_revision());
clk_disable(&iim_clk);
/*
* Check if we came up in internal boot mode. If yes, we need some
* extra clocks turned on, otherwise the MX35 boot ROM code will
* hang after a watchdog reset.
*/
if (!(__raw_readl(MX35_CCM_RCSR) & (3 << 10))) {
/* Additionally turn on UART1, SCC, and IIM clocks */
clk_enable(&iim_clk);
clk_enable(&uart1_clk);
clk_enable(&scc_clk);
}
#ifdef CONFIG_MXC_USE_EPIT
epit_timer_init(&epit1_clk,
MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1);
#else
mxc_timer_init(&gpt_clk,
MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT);
#endif
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -32,6 +32,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;
@ -138,6 +142,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)
@ -211,6 +216,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)

View File

@ -33,6 +33,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);

View File

@ -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);

View File

@ -27,7 +27,6 @@
#include <linux/mtd/physmap.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>

View File

@ -43,6 +43,9 @@ static void __init kirkwood_dt_init(void)
kirkwood_l2_init();
#endif
/* Setup root of clk tree */
kirkwood_clk_init();
/* internal devices that every board has */
kirkwood_wdt_init();
kirkwood_xor0_init();

View File

@ -15,7 +15,8 @@
#include <linux/ata_platform.h>
#include <linux/mtd/nand.h>
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/clk-provider.h>
#include <linux/spinlock.h>
#include <net/dsa.h>
#include <asm/page.h>
#include <asm/timex.h>
@ -32,6 +33,7 @@
#include <plat/common.h>
#include <plat/time.h>
#include <plat/addr-map.h>
#include <plat/mv_xor.h>
#include "common.h"
/*****************************************************************************
@ -61,20 +63,188 @@ void __init kirkwood_map_io(void)
iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc));
}
/*
* Default clock control bits. Any bit _not_ set in this variable
* will be cleared from the hardware after platform devices have been
* registered. Some reserved bits must be set to 1.
*/
unsigned int kirkwood_clk_ctrl = CGC_DUNIT | CGC_RESERVED;
/*****************************************************************************
* CLK tree
****************************************************************************/
static void disable_sata0(void)
{
/* Disable PLL and IVREF */
writel(readl(SATA0_PHY_MODE_2) & ~0xf, SATA0_PHY_MODE_2);
/* Disable PHY */
writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL);
}
static void disable_sata1(void)
{
/* Disable PLL and IVREF */
writel(readl(SATA1_PHY_MODE_2) & ~0xf, SATA1_PHY_MODE_2);
/* Disable PHY */
writel(readl(SATA1_IF_CTRL) | 0x200, SATA1_IF_CTRL);
}
static void disable_pcie0(void)
{
writel(readl(PCIE_LINK_CTRL) | 0x10, PCIE_LINK_CTRL);
while (1)
if (readl(PCIE_STATUS) & 0x1)
break;
writel(readl(PCIE_LINK_CTRL) & ~0x10, PCIE_LINK_CTRL);
}
static void disable_pcie1(void)
{
u32 dev, rev;
kirkwood_pcie_id(&dev, &rev);
if (dev == MV88F6282_DEV_ID) {
writel(readl(PCIE1_LINK_CTRL) | 0x10, PCIE1_LINK_CTRL);
while (1)
if (readl(PCIE1_STATUS) & 0x1)
break;
writel(readl(PCIE1_LINK_CTRL) & ~0x10, PCIE1_LINK_CTRL);
}
}
/* An extended version of the gated clk. This calls fn() before
* disabling the clock. We use this to turn off PHYs etc. */
struct clk_gate_fn {
struct clk_gate gate;
void (*fn)(void);
};
#define to_clk_gate_fn(_gate) container_of(_gate, struct clk_gate_fn, gate)
#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
static void clk_gate_fn_disable(struct clk_hw *hw)
{
struct clk_gate *gate = to_clk_gate(hw);
struct clk_gate_fn *gate_fn = to_clk_gate_fn(gate);
if (gate_fn->fn)
gate_fn->fn();
clk_gate_ops.disable(hw);
}
static struct clk_ops clk_gate_fn_ops;
static struct clk __init *clk_register_gate_fn(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,
void (*fn)(void))
{
struct clk_gate_fn *gate_fn;
struct clk *clk;
struct clk_init_data init;
gate_fn = kzalloc(sizeof(struct clk_gate_fn), GFP_KERNEL);
if (!gate_fn) {
pr_err("%s: could not allocate gated clk\n", __func__);
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &clk_gate_fn_ops;
init.flags = flags;
init.parent_names = (parent_name ? &parent_name : NULL);
init.num_parents = (parent_name ? 1 : 0);
/* struct clk_gate assignments */
gate_fn->gate.reg = reg;
gate_fn->gate.bit_idx = bit_idx;
gate_fn->gate.flags = clk_gate_flags;
gate_fn->gate.lock = lock;
gate_fn->gate.hw.init = &init;
/* ops is the gate ops, but with our disable function */
if (clk_gate_fn_ops.disable != clk_gate_fn_disable) {
clk_gate_fn_ops = clk_gate_ops;
clk_gate_fn_ops.disable = clk_gate_fn_disable;
}
clk = clk_register(dev, &gate_fn->gate.hw);
if (IS_ERR(clk))
kfree(gate_fn);
return clk;
}
static DEFINE_SPINLOCK(gating_lock);
static struct clk *tclk;
static struct clk __init *kirkwood_register_gate(const char *name, u8 bit_idx)
{
return clk_register_gate(NULL, name, "tclk", 0,
(void __iomem *)CLOCK_GATING_CTRL,
bit_idx, 0, &gating_lock);
}
static struct clk __init *kirkwood_register_gate_fn(const char *name,
u8 bit_idx,
void (*fn)(void))
{
return clk_register_gate_fn(NULL, name, "tclk", 0,
(void __iomem *)CLOCK_GATING_CTRL,
bit_idx, 0, &gating_lock, fn);
}
void __init kirkwood_clk_init(void)
{
struct clk *runit, *ge0, *ge1, *sata0, *sata1, *usb0, *sdio;
struct clk *crypto, *xor0, *xor1, *pex0, *pex1, *audio;
tclk = clk_register_fixed_rate(NULL, "tclk", NULL,
CLK_IS_ROOT, kirkwood_tclk);
runit = kirkwood_register_gate("runit", CGC_BIT_RUNIT);
ge0 = kirkwood_register_gate("ge0", CGC_BIT_GE0);
ge1 = kirkwood_register_gate("ge1", CGC_BIT_GE1);
sata0 = kirkwood_register_gate_fn("sata0", CGC_BIT_SATA0,
disable_sata0);
sata1 = kirkwood_register_gate_fn("sata1", CGC_BIT_SATA1,
disable_sata1);
usb0 = kirkwood_register_gate("usb0", CGC_BIT_USB0);
sdio = kirkwood_register_gate("sdio", CGC_BIT_SDIO);
crypto = kirkwood_register_gate("crypto", CGC_BIT_CRYPTO);
xor0 = kirkwood_register_gate("xor0", CGC_BIT_XOR0);
xor1 = kirkwood_register_gate("xor1", CGC_BIT_XOR1);
pex0 = kirkwood_register_gate_fn("pex0", CGC_BIT_PEX0,
disable_pcie0);
pex1 = kirkwood_register_gate_fn("pex1", CGC_BIT_PEX1,
disable_pcie1);
audio = kirkwood_register_gate("audio", CGC_BIT_AUDIO);
kirkwood_register_gate("tdm", CGC_BIT_TDM);
kirkwood_register_gate("tsu", CGC_BIT_TSU);
/* clkdev entries, mapping clks to devices */
orion_clkdev_add(NULL, "orion_spi.0", runit);
orion_clkdev_add(NULL, "orion_spi.1", runit);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".0", ge0);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".1", ge1);
orion_clkdev_add(NULL, "orion_wdt", tclk);
orion_clkdev_add("0", "sata_mv.0", sata0);
orion_clkdev_add("1", "sata_mv.0", sata1);
orion_clkdev_add(NULL, "orion-ehci.0", usb0);
orion_clkdev_add(NULL, "orion_nand", runit);
orion_clkdev_add(NULL, "mvsdio", sdio);
orion_clkdev_add(NULL, "mv_crypto", crypto);
orion_clkdev_add(NULL, MV_XOR_SHARED_NAME ".0", xor0);
orion_clkdev_add(NULL, MV_XOR_SHARED_NAME ".1", xor1);
orion_clkdev_add("0", "pcie", pex0);
orion_clkdev_add("1", "pcie", pex1);
orion_clkdev_add(NULL, "kirkwood-i2s", audio);
}
/*****************************************************************************
* EHCI0
****************************************************************************/
void __init kirkwood_ehci_init(void)
{
kirkwood_clk_ctrl |= CGC_USB0;
orion_ehci_init(USB_PHYS_BASE, IRQ_KIRKWOOD_USB, EHCI_PHY_NA);
}
@ -84,11 +254,9 @@ void __init kirkwood_ehci_init(void)
****************************************************************************/
void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data)
{
kirkwood_clk_ctrl |= CGC_GE0;
orion_ge00_init(eth_data,
GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM,
IRQ_KIRKWOOD_GE00_ERR, kirkwood_tclk);
IRQ_KIRKWOOD_GE00_ERR);
}
@ -97,12 +265,9 @@ void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data)
****************************************************************************/
void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data)
{
kirkwood_clk_ctrl |= CGC_GE1;
orion_ge01_init(eth_data,
GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM,
IRQ_KIRKWOOD_GE01_ERR, kirkwood_tclk);
IRQ_KIRKWOOD_GE01_ERR);
}
@ -144,7 +309,6 @@ static struct platform_device kirkwood_nand_flash = {
void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts,
int chip_delay)
{
kirkwood_clk_ctrl |= CGC_RUNIT;
kirkwood_nand_data.parts = parts;
kirkwood_nand_data.nr_parts = nr_parts;
kirkwood_nand_data.chip_delay = chip_delay;
@ -154,7 +318,6 @@ void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts,
void __init kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts,
int (*dev_ready)(struct mtd_info *))
{
kirkwood_clk_ctrl |= CGC_RUNIT;
kirkwood_nand_data.parts = parts;
kirkwood_nand_data.nr_parts = nr_parts;
kirkwood_nand_data.dev_ready = dev_ready;
@ -175,10 +338,6 @@ static void __init kirkwood_rtc_init(void)
****************************************************************************/
void __init kirkwood_sata_init(struct mv_sata_platform_data *sata_data)
{
kirkwood_clk_ctrl |= CGC_SATA0;
if (sata_data->n_ports > 1)
kirkwood_clk_ctrl |= CGC_SATA1;
orion_sata_init(sata_data, SATA_PHYS_BASE, IRQ_KIRKWOOD_SATA);
}
@ -221,7 +380,6 @@ void __init kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data)
mvsdio_data->clock = 100000000;
else
mvsdio_data->clock = 200000000;
kirkwood_clk_ctrl |= CGC_SDIO;
kirkwood_sdio.dev.platform_data = mvsdio_data;
platform_device_register(&kirkwood_sdio);
}
@ -232,8 +390,7 @@ void __init kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data)
****************************************************************************/
void __init kirkwood_spi_init()
{
kirkwood_clk_ctrl |= CGC_RUNIT;
orion_spi_init(SPI_PHYS_BASE, kirkwood_tclk);
orion_spi_init(SPI_PHYS_BASE);
}
@ -253,7 +410,7 @@ void __init kirkwood_i2c_init(void)
void __init kirkwood_uart0_init(void)
{
orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
IRQ_KIRKWOOD_UART_0, kirkwood_tclk);
IRQ_KIRKWOOD_UART_0, tclk);
}
@ -263,7 +420,7 @@ void __init kirkwood_uart0_init(void)
void __init kirkwood_uart1_init(void)
{
orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
IRQ_KIRKWOOD_UART_1, kirkwood_tclk);
IRQ_KIRKWOOD_UART_1, tclk);
}
/*****************************************************************************
@ -271,7 +428,6 @@ void __init kirkwood_uart1_init(void)
****************************************************************************/
void __init kirkwood_crypto_init(void)
{
kirkwood_clk_ctrl |= CGC_CRYPTO;
orion_crypto_init(CRYPTO_PHYS_BASE, KIRKWOOD_SRAM_PHYS_BASE,
KIRKWOOD_SRAM_SIZE, IRQ_KIRKWOOD_CRYPTO);
}
@ -282,8 +438,6 @@ void __init kirkwood_crypto_init(void)
****************************************************************************/
void __init kirkwood_xor0_init(void)
{
kirkwood_clk_ctrl |= CGC_XOR0;
orion_xor0_init(XOR0_PHYS_BASE, XOR0_HIGH_PHYS_BASE,
IRQ_KIRKWOOD_XOR_00, IRQ_KIRKWOOD_XOR_01);
}
@ -294,8 +448,6 @@ void __init kirkwood_xor0_init(void)
****************************************************************************/
void __init kirkwood_xor1_init(void)
{
kirkwood_clk_ctrl |= CGC_XOR1;
orion_xor1_init(XOR1_PHYS_BASE, XOR1_HIGH_PHYS_BASE,
IRQ_KIRKWOOD_XOR_10, IRQ_KIRKWOOD_XOR_11);
}
@ -306,7 +458,7 @@ void __init kirkwood_xor1_init(void)
****************************************************************************/
void __init kirkwood_wdt_init(void)
{
orion_wdt_init(kirkwood_tclk);
orion_wdt_init();
}
@ -382,7 +534,6 @@ static struct platform_device kirkwood_pcm_device = {
void __init kirkwood_audio_init(void)
{
kirkwood_clk_ctrl |= CGC_AUDIO;
platform_device_register(&kirkwood_i2s_device);
platform_device_register(&kirkwood_pcm_device);
}
@ -466,6 +617,9 @@ void __init kirkwood_init(void)
kirkwood_l2_init();
#endif
/* Setup root of clk tree */
kirkwood_clk_init();
/* internal devices that every board has */
kirkwood_rtc_init();
kirkwood_wdt_init();
@ -478,72 +632,6 @@ void __init kirkwood_init(void)
#endif
}
static int __init kirkwood_clock_gate(void)
{
unsigned int curr = readl(CLOCK_GATING_CTRL);
u32 dev, rev;
#ifdef CONFIG_OF
struct device_node *np;
#endif
kirkwood_pcie_id(&dev, &rev);
printk(KERN_DEBUG "Gating clock of unused units\n");
printk(KERN_DEBUG "before: 0x%08x\n", curr);
/* Make sure those units are accessible */
writel(curr | CGC_SATA0 | CGC_SATA1 | CGC_PEX0 | CGC_PEX1, CLOCK_GATING_CTRL);
#ifdef CONFIG_OF
np = of_find_compatible_node(NULL, NULL, "mrvl,orion-nand");
if (np && of_device_is_available(np)) {
kirkwood_clk_ctrl |= CGC_RUNIT;
of_node_put(np);
}
#endif
/* For SATA: first shutdown the phy */
if (!(kirkwood_clk_ctrl & CGC_SATA0)) {
/* Disable PLL and IVREF */
writel(readl(SATA0_PHY_MODE_2) & ~0xf, SATA0_PHY_MODE_2);
/* Disable PHY */
writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL);
}
if (!(kirkwood_clk_ctrl & CGC_SATA1)) {
/* Disable PLL and IVREF */
writel(readl(SATA1_PHY_MODE_2) & ~0xf, SATA1_PHY_MODE_2);
/* Disable PHY */
writel(readl(SATA1_IF_CTRL) | 0x200, SATA1_IF_CTRL);
}
/* For PCIe: first shutdown the phy */
if (!(kirkwood_clk_ctrl & CGC_PEX0)) {
writel(readl(PCIE_LINK_CTRL) | 0x10, PCIE_LINK_CTRL);
while (1)
if (readl(PCIE_STATUS) & 0x1)
break;
writel(readl(PCIE_LINK_CTRL) & ~0x10, PCIE_LINK_CTRL);
}
/* For PCIe 1: first shutdown the phy */
if (dev == MV88F6282_DEV_ID) {
if (!(kirkwood_clk_ctrl & CGC_PEX1)) {
writel(readl(PCIE1_LINK_CTRL) | 0x10, PCIE1_LINK_CTRL);
while (1)
if (readl(PCIE1_STATUS) & 0x1)
break;
writel(readl(PCIE1_LINK_CTRL) & ~0x10, PCIE1_LINK_CTRL);
}
} else /* keep this bit set for devices that don't have PCIe1 */
kirkwood_clk_ctrl |= CGC_PEX1;
/* Now gate clock the required units */
writel(kirkwood_clk_ctrl, CLOCK_GATING_CTRL);
printk(KERN_DEBUG " after: 0x%08x\n", readl(CLOCK_GATING_CTRL));
return 0;
}
late_initcall(kirkwood_clock_gate);
void kirkwood_restart(char mode, const char *cmd)
{
/*

View File

@ -50,6 +50,7 @@ void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay);
void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts, int (*dev_ready)(struct mtd_info *));
void kirkwood_audio_init(void);
void kirkwood_restart(char, const char *);
void kirkwood_clk_init(void);
/* board init functions for boards not fully converted to fdt */
#ifdef CONFIG_MACH_DREAMPLUG_DT

View File

@ -43,6 +43,22 @@
#define L2_WRITETHROUGH 0x00000010
#define CLOCK_GATING_CTRL (BRIDGE_VIRT_BASE | 0x11c)
#define CGC_BIT_GE0 (0)
#define CGC_BIT_PEX0 (2)
#define CGC_BIT_USB0 (3)
#define CGC_BIT_SDIO (4)
#define CGC_BIT_TSU (5)
#define CGC_BIT_DUNIT (6)
#define CGC_BIT_RUNIT (7)
#define CGC_BIT_XOR0 (8)
#define CGC_BIT_AUDIO (9)
#define CGC_BIT_SATA0 (14)
#define CGC_BIT_SATA1 (15)
#define CGC_BIT_XOR1 (16)
#define CGC_BIT_CRYPTO (17)
#define CGC_BIT_PEX1 (18)
#define CGC_BIT_GE1 (19)
#define CGC_BIT_TDM (20)
#define CGC_GE0 (1 << 0)
#define CGC_PEX0 (1 << 2)
#define CGC_USB0 (1 << 3)

View File

@ -23,7 +23,6 @@
#include <linux/gpio_keys.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <net/dsa.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>

View File

@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <video/vga.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
@ -19,6 +20,23 @@
#include <plat/addr-map.h>
#include "common.h"
static void kirkwood_enable_pcie_clk(const char *port)
{
struct clk *clk;
clk = clk_get_sys("pcie", port);
if (IS_ERR(clk)) {
printk(KERN_ERR "PCIE clock %s missing\n", port);
return;
}
clk_prepare_enable(clk);
clk_put(clk);
}
/* This function is called very early in the boot when probing the
hardware to determine what we actually are, and what rate tclk is
ticking at. Hence calling kirkwood_enable_pcie_clk() is not
possible since the clk tree has not been created yet. */
void kirkwood_enable_pcie(void)
{
u32 curr = readl(CLOCK_GATING_CTRL);
@ -26,7 +44,7 @@ void kirkwood_enable_pcie(void)
writel(curr | CGC_PEX0, CLOCK_GATING_CTRL);
}
void __init kirkwood_pcie_id(u32 *dev, u32 *rev)
void kirkwood_pcie_id(u32 *dev, u32 *rev)
{
kirkwood_enable_pcie();
*dev = orion_pcie_dev_id((void __iomem *)PCIE_VIRT_BASE);
@ -159,7 +177,6 @@ static void __init pcie1_ioresources_init(struct pcie_port *pp)
static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
{
extern unsigned int kirkwood_clk_ctrl;
struct pcie_port *pp;
int index;
@ -178,11 +195,11 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
switch (index) {
case 0:
kirkwood_clk_ctrl |= CGC_PEX0;
kirkwood_enable_pcie_clk("0");
pcie0_ioresources_init(pp);
break;
case 1:
kirkwood_clk_ctrl |= CGC_PEX1;
kirkwood_enable_pcie_clk("1");
pcie1_ioresources_init(pp);
break;
default:

View File

@ -16,7 +16,6 @@
#include <linux/gpio.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/kirkwood.h>

View File

@ -16,7 +16,6 @@
#include <linux/mtd/physmap.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <linux/i2c.h>
#include <linux/mv643xx_eth.h>
#include <linux/ata_platform.h>

View File

@ -4,7 +4,6 @@
#include <linux/mtd/physmap.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <linux/serial_reg.h>
#include <mach/kirkwood.h>
#include "common.h"

View File

@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
#include <linux/ata_platform.h>
#include <linux/clk-provider.h>
#include <linux/ethtool.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
@ -103,24 +104,24 @@ static void get_pclk_l2clk(int hclk, int core_index, int *pclk, int *l2clk)
static int get_tclk(void)
{
int tclk;
int tclk_freq;
/*
* TCLK tick rate is configured by DEV_A[2:0] strap pins.
*/
switch ((readl(SAMPLE_AT_RESET_HIGH) >> 6) & 7) {
case 1:
tclk = 166666667;
tclk_freq = 166666667;
break;
case 3:
tclk = 200000000;
tclk_freq = 200000000;
break;
default:
panic("unknown TCLK PLL setting: %.8x\n",
readl(SAMPLE_AT_RESET_HIGH));
}
return tclk;
return tclk_freq;
}
@ -165,6 +166,19 @@ void __init mv78xx0_map_io(void)
}
/*****************************************************************************
* CLK tree
****************************************************************************/
static struct clk *tclk;
static void __init clk_init(void)
{
tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
get_tclk());
orion_clkdev_init(tclk);
}
/*****************************************************************************
* EHCI
****************************************************************************/
@ -199,7 +213,7 @@ void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data)
{
orion_ge00_init(eth_data,
GE00_PHYS_BASE, IRQ_MV78XX0_GE00_SUM,
IRQ_MV78XX0_GE_ERR, get_tclk());
IRQ_MV78XX0_GE_ERR);
}
@ -210,7 +224,7 @@ void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data)
{
orion_ge01_init(eth_data,
GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM,
NO_IRQ, get_tclk());
NO_IRQ);
}
@ -234,7 +248,7 @@ void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data)
orion_ge10_init(eth_data,
GE10_PHYS_BASE, IRQ_MV78XX0_GE10_SUM,
NO_IRQ, get_tclk());
NO_IRQ);
}
@ -258,7 +272,7 @@ void __init mv78xx0_ge11_init(struct mv643xx_eth_platform_data *eth_data)
orion_ge11_init(eth_data,
GE11_PHYS_BASE, IRQ_MV78XX0_GE11_SUM,
NO_IRQ, get_tclk());
NO_IRQ);
}
/*****************************************************************************
@ -285,7 +299,7 @@ void __init mv78xx0_sata_init(struct mv_sata_platform_data *sata_data)
void __init mv78xx0_uart0_init(void)
{
orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
IRQ_MV78XX0_UART_0, get_tclk());
IRQ_MV78XX0_UART_0, tclk);
}
@ -295,7 +309,7 @@ void __init mv78xx0_uart0_init(void)
void __init mv78xx0_uart1_init(void)
{
orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
IRQ_MV78XX0_UART_1, get_tclk());
IRQ_MV78XX0_UART_1, tclk);
}
@ -305,7 +319,7 @@ void __init mv78xx0_uart1_init(void)
void __init mv78xx0_uart2_init(void)
{
orion_uart2_init(UART2_VIRT_BASE, UART2_PHYS_BASE,
IRQ_MV78XX0_UART_2, get_tclk());
IRQ_MV78XX0_UART_2, tclk);
}
/*****************************************************************************
@ -314,7 +328,7 @@ void __init mv78xx0_uart2_init(void)
void __init mv78xx0_uart3_init(void)
{
orion_uart3_init(UART3_VIRT_BASE, UART3_PHYS_BASE,
IRQ_MV78XX0_UART_3, get_tclk());
IRQ_MV78XX0_UART_3, tclk);
}
/*****************************************************************************
@ -378,25 +392,26 @@ void __init mv78xx0_init(void)
int hclk;
int pclk;
int l2clk;
int tclk;
core_index = mv78xx0_core_index();
hclk = get_hclk();
get_pclk_l2clk(hclk, core_index, &pclk, &l2clk);
tclk = get_tclk();
printk(KERN_INFO "%s ", mv78xx0_id());
printk("core #%d, ", core_index);
printk("PCLK = %dMHz, ", (pclk + 499999) / 1000000);
printk("L2 = %dMHz, ", (l2clk + 499999) / 1000000);
printk("HCLK = %dMHz, ", (hclk + 499999) / 1000000);
printk("TCLK = %dMHz\n", (tclk + 499999) / 1000000);
printk("TCLK = %dMHz\n", (get_tclk() + 499999) / 1000000);
mv78xx0_setup_cpu_mbus();
#ifdef CONFIG_CACHE_FEROCEON_L2
feroceon_l2_init(is_l2_writethrough());
#endif
/* Setup root of clk tree */
clk_init();
}
void mv78xx0_restart(char mode, const char *cmd)

View File

@ -1,12 +1,9 @@
# Common support
obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o mm.o
obj-y := devices.o icoll.o iomux.o system.o timer.o mm.o
obj-$(CONFIG_MXS_OCOTP) += ocotp.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_SOC_IMX23) += clock-mx23.o
obj-$(CONFIG_SOC_IMX28) += clock-mx28.o
obj-$(CONFIG_MACH_STMP378X_DEVB) += mach-stmp378x_devb.o
obj-$(CONFIG_MACH_MX23EVK) += mach-mx23evk.o
obj-$(CONFIG_MACH_MX28EVK) += mach-mx28evk.o

View File

@ -1,536 +0,0 @@
/*
* Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
* 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/mm.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <asm/div64.h>
#include <mach/mx23.h>
#include <mach/common.h>
#include <mach/clock.h>
#include "regs-clkctrl-mx23.h"
#define CLKCTRL_BASE_ADDR MX23_IO_ADDRESS(MX23_CLKCTRL_BASE_ADDR)
#define DIGCTRL_BASE_ADDR MX23_IO_ADDRESS(MX23_DIGCTL_BASE_ADDR)
#define PARENT_RATE_SHIFT 8
static int _raw_clk_enable(struct clk *clk)
{
u32 reg;
if (clk->enable_reg) {
reg = __raw_readl(clk->enable_reg);
reg &= ~(1 << clk->enable_shift);
__raw_writel(reg, clk->enable_reg);
}
return 0;
}
static void _raw_clk_disable(struct clk *clk)
{
u32 reg;
if (clk->enable_reg) {
reg = __raw_readl(clk->enable_reg);
reg |= 1 << clk->enable_shift;
__raw_writel(reg, clk->enable_reg);
}
}
/*
* ref_xtal_clk
*/
static unsigned long ref_xtal_clk_get_rate(struct clk *clk)
{
return 24000000;
}
static struct clk ref_xtal_clk = {
.get_rate = ref_xtal_clk_get_rate,
};
/*
* pll_clk
*/
static unsigned long pll_clk_get_rate(struct clk *clk)
{
return 480000000;
}
static int pll_clk_enable(struct clk *clk)
{
__raw_writel(BM_CLKCTRL_PLLCTRL0_POWER |
BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS,
CLKCTRL_BASE_ADDR + HW_CLKCTRL_PLLCTRL0_SET);
/* Only a 10us delay is need. PLLCTRL1 LOCK bitfied is only a timer
* and is incorrect (excessive). Per definition of the PLLCTRL0
* POWER field, waiting at least 10us.
*/
udelay(10);
return 0;
}
static void pll_clk_disable(struct clk *clk)
{
__raw_writel(BM_CLKCTRL_PLLCTRL0_POWER |
BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS,
CLKCTRL_BASE_ADDR + HW_CLKCTRL_PLLCTRL0_CLR);
}
static struct clk pll_clk = {
.get_rate = pll_clk_get_rate,
.enable = pll_clk_enable,
.disable = pll_clk_disable,
.parent = &ref_xtal_clk,
};
/*
* ref_clk
*/
#define _CLK_GET_RATE_REF(name, sr, ss) \
static unsigned long name##_get_rate(struct clk *clk) \
{ \
unsigned long parent_rate; \
u32 reg, div; \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##sr); \
div = (reg >> BP_CLKCTRL_##sr##_##ss##FRAC) & 0x3f; \
parent_rate = clk_get_rate(clk->parent); \
\
return SH_DIV((parent_rate >> PARENT_RATE_SHIFT) * 18, \
div, PARENT_RATE_SHIFT); \
}
_CLK_GET_RATE_REF(ref_cpu_clk, FRAC, CPU)
_CLK_GET_RATE_REF(ref_emi_clk, FRAC, EMI)
_CLK_GET_RATE_REF(ref_pix_clk, FRAC, PIX)
_CLK_GET_RATE_REF(ref_io_clk, FRAC, IO)
#define _DEFINE_CLOCK_REF(name, er, es) \
static struct clk name = { \
.enable_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_##er, \
.enable_shift = BP_CLKCTRL_##er##_CLKGATE##es, \
.get_rate = name##_get_rate, \
.enable = _raw_clk_enable, \
.disable = _raw_clk_disable, \
.parent = &pll_clk, \
}
_DEFINE_CLOCK_REF(ref_cpu_clk, FRAC, CPU);
_DEFINE_CLOCK_REF(ref_emi_clk, FRAC, EMI);
_DEFINE_CLOCK_REF(ref_pix_clk, FRAC, PIX);
_DEFINE_CLOCK_REF(ref_io_clk, FRAC, IO);
/*
* General clocks
*
* clk_get_rate
*/
static unsigned long rtc_clk_get_rate(struct clk *clk)
{
/* ref_xtal_clk is implemented as the only parent */
return clk_get_rate(clk->parent) / 768;
}
static unsigned long clk32k_clk_get_rate(struct clk *clk)
{
return clk->parent->get_rate(clk->parent) / 750;
}
#define _CLK_GET_RATE(name, rs) \
static unsigned long name##_get_rate(struct clk *clk) \
{ \
u32 reg, div; \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \
\
if (clk->parent == &ref_xtal_clk) \
div = (reg & BM_CLKCTRL_##rs##_DIV_XTAL) >> \
BP_CLKCTRL_##rs##_DIV_XTAL; \
else \
div = (reg & BM_CLKCTRL_##rs##_DIV_##rs) >> \
BP_CLKCTRL_##rs##_DIV_##rs; \
\
if (!div) \
return -EINVAL; \
\
return clk_get_rate(clk->parent) / div; \
}
_CLK_GET_RATE(cpu_clk, CPU)
_CLK_GET_RATE(emi_clk, EMI)
#define _CLK_GET_RATE1(name, rs) \
static unsigned long name##_get_rate(struct clk *clk) \
{ \
u32 reg, div; \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \
div = (reg & BM_CLKCTRL_##rs##_DIV) >> BP_CLKCTRL_##rs##_DIV; \
\
if (!div) \
return -EINVAL; \
\
return clk_get_rate(clk->parent) / div; \
}
_CLK_GET_RATE1(hbus_clk, HBUS)
_CLK_GET_RATE1(xbus_clk, XBUS)
_CLK_GET_RATE1(ssp_clk, SSP)
_CLK_GET_RATE1(gpmi_clk, GPMI)
_CLK_GET_RATE1(lcdif_clk, PIX)
#define _CLK_GET_RATE_STUB(name) \
static unsigned long name##_get_rate(struct clk *clk) \
{ \
return clk_get_rate(clk->parent); \
}
_CLK_GET_RATE_STUB(uart_clk)
_CLK_GET_RATE_STUB(audio_clk)
_CLK_GET_RATE_STUB(pwm_clk)
/*
* clk_set_rate
*/
static int cpu_clk_set_rate(struct clk *clk, unsigned long rate)
{
u32 reg, bm_busy, div_max, d, f, div, frac;
unsigned long diff, parent_rate, calc_rate;
parent_rate = clk_get_rate(clk->parent);
if (clk->parent == &ref_xtal_clk) {
div_max = BM_CLKCTRL_CPU_DIV_XTAL >> BP_CLKCTRL_CPU_DIV_XTAL;
bm_busy = BM_CLKCTRL_CPU_BUSY_REF_XTAL;
div = DIV_ROUND_UP(parent_rate, rate);
if (div == 0 || div > div_max)
return -EINVAL;
} else {
div_max = BM_CLKCTRL_CPU_DIV_CPU >> BP_CLKCTRL_CPU_DIV_CPU;
bm_busy = BM_CLKCTRL_CPU_BUSY_REF_CPU;
rate >>= PARENT_RATE_SHIFT;
parent_rate >>= PARENT_RATE_SHIFT;
diff = parent_rate;
div = frac = 1;
for (d = 1; d <= div_max; d++) {
f = parent_rate * 18 / d / rate;
if ((parent_rate * 18 / d) % rate)
f++;
if (f < 18 || f > 35)
continue;
calc_rate = parent_rate * 18 / f / d;
if (calc_rate > rate)
continue;
if (rate - calc_rate < diff) {
frac = f;
div = d;
diff = rate - calc_rate;
}
if (diff == 0)
break;
}
if (diff == parent_rate)
return -EINVAL;
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
reg &= ~BM_CLKCTRL_FRAC_CPUFRAC;
reg |= frac;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
}
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU);
reg &= ~BM_CLKCTRL_CPU_DIV_CPU;
reg |= div << BP_CLKCTRL_CPU_DIV_CPU;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU);
mxs_clkctrl_timeout(HW_CLKCTRL_CPU, bm_busy);
return 0;
}
#define _CLK_SET_RATE(name, dr) \
static int name##_set_rate(struct clk *clk, unsigned long rate) \
{ \
u32 reg, div_max, div; \
unsigned long parent_rate; \
\
parent_rate = clk_get_rate(clk->parent); \
div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV; \
\
div = DIV_ROUND_UP(parent_rate, rate); \
if (div == 0 || div > div_max) \
return -EINVAL; \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \
reg &= ~BM_CLKCTRL_##dr##_DIV; \
reg |= div << BP_CLKCTRL_##dr##_DIV; \
if (reg & (1 << clk->enable_shift)) { \
pr_err("%s: clock is gated\n", __func__); \
return -EINVAL; \
} \
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \
\
mxs_clkctrl_timeout(HW_CLKCTRL_##dr, BM_CLKCTRL_##dr##_BUSY); \
return 0; \
}
_CLK_SET_RATE(xbus_clk, XBUS)
_CLK_SET_RATE(ssp_clk, SSP)
_CLK_SET_RATE(gpmi_clk, GPMI)
_CLK_SET_RATE(lcdif_clk, PIX)
#define _CLK_SET_RATE_STUB(name) \
static int name##_set_rate(struct clk *clk, unsigned long rate) \
{ \
return -EINVAL; \
}
_CLK_SET_RATE_STUB(emi_clk)
_CLK_SET_RATE_STUB(uart_clk)
_CLK_SET_RATE_STUB(audio_clk)
_CLK_SET_RATE_STUB(pwm_clk)
_CLK_SET_RATE_STUB(clk32k_clk)
/*
* clk_set_parent
*/
#define _CLK_SET_PARENT(name, bit) \
static int name##_set_parent(struct clk *clk, struct clk *parent) \
{ \
if (parent != clk->parent) { \
__raw_writel(BM_CLKCTRL_CLKSEQ_BYPASS_##bit, \
CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ_TOG); \
clk->parent = parent; \
} \
\
return 0; \
}
_CLK_SET_PARENT(cpu_clk, CPU)
_CLK_SET_PARENT(emi_clk, EMI)
_CLK_SET_PARENT(ssp_clk, SSP)
_CLK_SET_PARENT(gpmi_clk, GPMI)
_CLK_SET_PARENT(lcdif_clk, PIX)
#define _CLK_SET_PARENT_STUB(name) \
static int name##_set_parent(struct clk *clk, struct clk *parent) \
{ \
if (parent != clk->parent) \
return -EINVAL; \
else \
return 0; \
}
_CLK_SET_PARENT_STUB(uart_clk)
_CLK_SET_PARENT_STUB(audio_clk)
_CLK_SET_PARENT_STUB(pwm_clk)
_CLK_SET_PARENT_STUB(clk32k_clk)
/*
* clk definition
*/
static struct clk cpu_clk = {
.get_rate = cpu_clk_get_rate,
.set_rate = cpu_clk_set_rate,
.set_parent = cpu_clk_set_parent,
.parent = &ref_cpu_clk,
};
static struct clk hbus_clk = {
.get_rate = hbus_clk_get_rate,
.parent = &cpu_clk,
};
static struct clk xbus_clk = {
.get_rate = xbus_clk_get_rate,
.set_rate = xbus_clk_set_rate,
.parent = &ref_xtal_clk,
};
static struct clk rtc_clk = {
.get_rate = rtc_clk_get_rate,
.parent = &ref_xtal_clk,
};
/* usb_clk gate is controlled in DIGCTRL other than CLKCTRL */
static struct clk usb_clk = {
.enable_reg = DIGCTRL_BASE_ADDR,
.enable_shift = 2,
.enable = _raw_clk_enable,
.disable = _raw_clk_disable,
.parent = &pll_clk,
};
#define _DEFINE_CLOCK(name, er, es, p) \
static struct clk name = { \
.enable_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_##er, \
.enable_shift = BP_CLKCTRL_##er##_##es, \
.get_rate = name##_get_rate, \
.set_rate = name##_set_rate, \
.set_parent = name##_set_parent, \
.enable = _raw_clk_enable, \
.disable = _raw_clk_disable, \
.parent = p, \
}
_DEFINE_CLOCK(emi_clk, EMI, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(ssp_clk, SSP, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(gpmi_clk, GPMI, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(lcdif_clk, PIX, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(uart_clk, XTAL, UART_CLK_GATE, &ref_xtal_clk);
_DEFINE_CLOCK(audio_clk, XTAL, FILT_CLK24M_GATE, &ref_xtal_clk);
_DEFINE_CLOCK(pwm_clk, XTAL, PWM_CLK24M_GATE, &ref_xtal_clk);
_DEFINE_CLOCK(clk32k_clk, XTAL, TIMROT_CLK32K_GATE, &ref_xtal_clk);
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static struct clk_lookup lookups[] = {
/* for amba bus driver */
_REGISTER_CLOCK("duart", "apb_pclk", xbus_clk)
/* for amba-pl011 driver */
_REGISTER_CLOCK("duart", NULL, uart_clk)
_REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
_REGISTER_CLOCK("rtc", NULL, rtc_clk)
_REGISTER_CLOCK("mxs-dma-apbh", NULL, hbus_clk)
_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
_REGISTER_CLOCK("mxs-mmc.0", NULL, ssp_clk)
_REGISTER_CLOCK("mxs-mmc.1", NULL, ssp_clk)
_REGISTER_CLOCK(NULL, "usb", usb_clk)
_REGISTER_CLOCK(NULL, "audio", audio_clk)
_REGISTER_CLOCK("mxs-pwm.0", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.1", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.2", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.3", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.4", NULL, pwm_clk)
_REGISTER_CLOCK("imx23-fb", NULL, lcdif_clk)
_REGISTER_CLOCK("imx23-gpmi-nand", NULL, gpmi_clk)
};
static int clk_misc_init(void)
{
u32 reg;
int ret;
/* Fix up parent per register setting */
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
cpu_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_CPU) ?
&ref_xtal_clk : &ref_cpu_clk;
emi_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_EMI) ?
&ref_xtal_clk : &ref_emi_clk;
ssp_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SSP) ?
&ref_xtal_clk : &ref_io_clk;
gpmi_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_GPMI) ?
&ref_xtal_clk : &ref_io_clk;
lcdif_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_PIX) ?
&ref_xtal_clk : &ref_pix_clk;
/* Use int div over frac when both are available */
__raw_writel(BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN,
CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_CLR);
__raw_writel(BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN,
CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_CLR);
__raw_writel(BM_CLKCTRL_HBUS_DIV_FRAC_EN,
CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS_CLR);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_XBUS);
reg &= ~BM_CLKCTRL_XBUS_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_XBUS);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP);
reg &= ~BM_CLKCTRL_SSP_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_GPMI);
reg &= ~BM_CLKCTRL_GPMI_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_GPMI);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_PIX);
reg &= ~BM_CLKCTRL_PIX_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_PIX);
/*
* Set safe hbus clock divider. A divider of 3 ensure that
* the Vddd voltage required for the cpu clock is sufficiently
* high for the hbus clock.
*/
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
reg &= BM_CLKCTRL_HBUS_DIV;
reg |= 3 << BP_CLKCTRL_HBUS_DIV;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
ret = mxs_clkctrl_timeout(HW_CLKCTRL_HBUS, BM_CLKCTRL_HBUS_BUSY);
/* Gate off cpu clock in WFI for power saving */
__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET);
/*
* 480 MHz seems too high to be ssp clock source directly,
* so set frac to get a 288 MHz ref_io.
*/
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
reg &= ~BM_CLKCTRL_FRAC_IOFRAC;
reg |= 30 << BP_CLKCTRL_FRAC_IOFRAC;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
return ret;
}
int __init mx23_clocks_init(void)
{
clk_misc_init();
/*
* source ssp clock from ref_io than ref_xtal,
* as ref_xtal only provides 24 MHz as maximum.
*/
clk_set_parent(&ssp_clk, &ref_io_clk);
clk_prepare_enable(&cpu_clk);
clk_prepare_enable(&hbus_clk);
clk_prepare_enable(&xbus_clk);
clk_prepare_enable(&emi_clk);
clk_prepare_enable(&uart_clk);
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
mxs_timer_init(&clk32k_clk, MX23_INT_TIMER0);
return 0;
}

View File

@ -1,803 +0,0 @@
/*
* Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
* 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/mm.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/clkdev.h>
#include <linux/spinlock.h>
#include <asm/clkdev.h>
#include <asm/div64.h>
#include <mach/mx28.h>
#include <mach/common.h>
#include <mach/clock.h>
#include <mach/digctl.h>
#include "regs-clkctrl-mx28.h"
#define CLKCTRL_BASE_ADDR MX28_IO_ADDRESS(MX28_CLKCTRL_BASE_ADDR)
#define DIGCTRL_BASE_ADDR MX28_IO_ADDRESS(MX28_DIGCTL_BASE_ADDR)
#define PARENT_RATE_SHIFT 8
static struct clk pll2_clk;
static struct clk cpu_clk;
static struct clk emi_clk;
static struct clk saif0_clk;
static struct clk saif1_clk;
static struct clk clk32k_clk;
static DEFINE_SPINLOCK(clkmux_lock);
/*
* HW_SAIF_CLKMUX_SEL:
* DIRECT(0x0): SAIF0 clock pins selected for SAIF0 input clocks, and SAIF1
* clock pins selected for SAIF1 input clocks.
* CROSSINPUT(0x1): SAIF1 clock inputs selected for SAIF0 input clocks, and
* SAIF0 clock inputs selected for SAIF1 input clocks.
* EXTMSTR0(0x2): SAIF0 clock pin selected for both SAIF0 and SAIF1 input
* clocks.
* EXTMSTR1(0x3): SAIF1 clock pin selected for both SAIF0 and SAIF1 input
* clocks.
*/
int mxs_saif_clkmux_select(unsigned int clkmux)
{
if (clkmux > 0x3)
return -EINVAL;
spin_lock(&clkmux_lock);
__raw_writel(BM_DIGCTL_CTRL_SAIF_CLKMUX,
DIGCTRL_BASE_ADDR + HW_DIGCTL_CTRL + MXS_CLR_ADDR);
__raw_writel(clkmux << BP_DIGCTL_CTRL_SAIF_CLKMUX,
DIGCTRL_BASE_ADDR + HW_DIGCTL_CTRL + MXS_SET_ADDR);
spin_unlock(&clkmux_lock);
return 0;
}
static int _raw_clk_enable(struct clk *clk)
{
u32 reg;
if (clk->enable_reg) {
reg = __raw_readl(clk->enable_reg);
reg &= ~(1 << clk->enable_shift);
__raw_writel(reg, clk->enable_reg);
}
return 0;
}
static void _raw_clk_disable(struct clk *clk)
{
u32 reg;
if (clk->enable_reg) {
reg = __raw_readl(clk->enable_reg);
reg |= 1 << clk->enable_shift;
__raw_writel(reg, clk->enable_reg);
}
}
/*
* ref_xtal_clk
*/
static unsigned long ref_xtal_clk_get_rate(struct clk *clk)
{
return 24000000;
}
static struct clk ref_xtal_clk = {
.get_rate = ref_xtal_clk_get_rate,
};
/*
* pll_clk
*/
static unsigned long pll0_clk_get_rate(struct clk *clk)
{
return 480000000;
}
static unsigned long pll1_clk_get_rate(struct clk *clk)
{
return 480000000;
}
static unsigned long pll2_clk_get_rate(struct clk *clk)
{
return 50000000;
}
#define _CLK_ENABLE_PLL(name, r, g) \
static int name##_enable(struct clk *clk) \
{ \
__raw_writel(BM_CLKCTRL_##r##CTRL0_POWER, \
CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_SET); \
udelay(10); \
\
if (clk == &pll2_clk) \
__raw_writel(BM_CLKCTRL_##r##CTRL0_##g, \
CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_CLR); \
else \
__raw_writel(BM_CLKCTRL_##r##CTRL0_##g, \
CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_SET); \
\
return 0; \
}
_CLK_ENABLE_PLL(pll0_clk, PLL0, EN_USB_CLKS)
_CLK_ENABLE_PLL(pll1_clk, PLL1, EN_USB_CLKS)
_CLK_ENABLE_PLL(pll2_clk, PLL2, CLKGATE)
#define _CLK_DISABLE_PLL(name, r, g) \
static void name##_disable(struct clk *clk) \
{ \
__raw_writel(BM_CLKCTRL_##r##CTRL0_POWER, \
CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_CLR); \
\
if (clk == &pll2_clk) \
__raw_writel(BM_CLKCTRL_##r##CTRL0_##g, \
CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_SET); \
else \
__raw_writel(BM_CLKCTRL_##r##CTRL0_##g, \
CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_CLR); \
\
}
_CLK_DISABLE_PLL(pll0_clk, PLL0, EN_USB_CLKS)
_CLK_DISABLE_PLL(pll1_clk, PLL1, EN_USB_CLKS)
_CLK_DISABLE_PLL(pll2_clk, PLL2, CLKGATE)
#define _DEFINE_CLOCK_PLL(name) \
static struct clk name = { \
.get_rate = name##_get_rate, \
.enable = name##_enable, \
.disable = name##_disable, \
.parent = &ref_xtal_clk, \
}
_DEFINE_CLOCK_PLL(pll0_clk);
_DEFINE_CLOCK_PLL(pll1_clk);
_DEFINE_CLOCK_PLL(pll2_clk);
/*
* ref_clk
*/
#define _CLK_GET_RATE_REF(name, sr, ss) \
static unsigned long name##_get_rate(struct clk *clk) \
{ \
unsigned long parent_rate; \
u32 reg, div; \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##sr); \
div = (reg >> BP_CLKCTRL_##sr##_##ss##FRAC) & 0x3f; \
parent_rate = clk_get_rate(clk->parent); \
\
return SH_DIV((parent_rate >> PARENT_RATE_SHIFT) * 18, \
div, PARENT_RATE_SHIFT); \
}
_CLK_GET_RATE_REF(ref_cpu_clk, FRAC0, CPU)
_CLK_GET_RATE_REF(ref_emi_clk, FRAC0, EMI)
_CLK_GET_RATE_REF(ref_io0_clk, FRAC0, IO0)
_CLK_GET_RATE_REF(ref_io1_clk, FRAC0, IO1)
_CLK_GET_RATE_REF(ref_pix_clk, FRAC1, PIX)
_CLK_GET_RATE_REF(ref_gpmi_clk, FRAC1, GPMI)
#define _DEFINE_CLOCK_REF(name, er, es) \
static struct clk name = { \
.enable_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_##er, \
.enable_shift = BP_CLKCTRL_##er##_CLKGATE##es, \
.get_rate = name##_get_rate, \
.enable = _raw_clk_enable, \
.disable = _raw_clk_disable, \
.parent = &pll0_clk, \
}
_DEFINE_CLOCK_REF(ref_cpu_clk, FRAC0, CPU);
_DEFINE_CLOCK_REF(ref_emi_clk, FRAC0, EMI);
_DEFINE_CLOCK_REF(ref_io0_clk, FRAC0, IO0);
_DEFINE_CLOCK_REF(ref_io1_clk, FRAC0, IO1);
_DEFINE_CLOCK_REF(ref_pix_clk, FRAC1, PIX);
_DEFINE_CLOCK_REF(ref_gpmi_clk, FRAC1, GPMI);
/*
* General clocks
*
* clk_get_rate
*/
static unsigned long lradc_clk_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 16;
}
static unsigned long rtc_clk_get_rate(struct clk *clk)
{
/* ref_xtal_clk is implemented as the only parent */
return clk_get_rate(clk->parent) / 768;
}
static unsigned long clk32k_clk_get_rate(struct clk *clk)
{
return clk->parent->get_rate(clk->parent) / 750;
}
static unsigned long spdif_clk_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 4;
}
#define _CLK_GET_RATE(name, rs) \
static unsigned long name##_get_rate(struct clk *clk) \
{ \
u32 reg, div; \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \
\
if (clk->parent == &ref_xtal_clk) \
div = (reg & BM_CLKCTRL_##rs##_DIV_XTAL) >> \
BP_CLKCTRL_##rs##_DIV_XTAL; \
else \
div = (reg & BM_CLKCTRL_##rs##_DIV_##rs) >> \
BP_CLKCTRL_##rs##_DIV_##rs; \
\
if (!div) \
return -EINVAL; \
\
return clk_get_rate(clk->parent) / div; \
}
_CLK_GET_RATE(cpu_clk, CPU)
_CLK_GET_RATE(emi_clk, EMI)
#define _CLK_GET_RATE1(name, rs) \
static unsigned long name##_get_rate(struct clk *clk) \
{ \
u32 reg, div; \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \
div = (reg & BM_CLKCTRL_##rs##_DIV) >> BP_CLKCTRL_##rs##_DIV; \
\
if (!div) \
return -EINVAL; \
\
if (clk == &saif0_clk || clk == &saif1_clk) \
return clk_get_rate(clk->parent) >> 16 * div; \
else \
return clk_get_rate(clk->parent) / div; \
}
_CLK_GET_RATE1(hbus_clk, HBUS)
_CLK_GET_RATE1(xbus_clk, XBUS)
_CLK_GET_RATE1(ssp0_clk, SSP0)
_CLK_GET_RATE1(ssp1_clk, SSP1)
_CLK_GET_RATE1(ssp2_clk, SSP2)
_CLK_GET_RATE1(ssp3_clk, SSP3)
_CLK_GET_RATE1(gpmi_clk, GPMI)
_CLK_GET_RATE1(lcdif_clk, DIS_LCDIF)
_CLK_GET_RATE1(saif0_clk, SAIF0)
_CLK_GET_RATE1(saif1_clk, SAIF1)
#define _CLK_GET_RATE_STUB(name) \
static unsigned long name##_get_rate(struct clk *clk) \
{ \
return clk_get_rate(clk->parent); \
}
_CLK_GET_RATE_STUB(uart_clk)
_CLK_GET_RATE_STUB(pwm_clk)
_CLK_GET_RATE_STUB(can0_clk)
_CLK_GET_RATE_STUB(can1_clk)
_CLK_GET_RATE_STUB(fec_clk)
/*
* clk_set_rate
*/
/* fool compiler */
#define BM_CLKCTRL_CPU_DIV 0
#define BP_CLKCTRL_CPU_DIV 0
#define BM_CLKCTRL_CPU_BUSY 0
#define _CLK_SET_RATE(name, dr, fr, fs) \
static int name##_set_rate(struct clk *clk, unsigned long rate) \
{ \
u32 reg, bm_busy, div_max, d, f, div, frac; \
unsigned long diff, parent_rate, calc_rate; \
\
div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV; \
bm_busy = BM_CLKCTRL_##dr##_BUSY; \
\
if (clk->parent == &ref_xtal_clk) { \
parent_rate = clk_get_rate(clk->parent); \
div = DIV_ROUND_UP(parent_rate, rate); \
if (clk == &cpu_clk) { \
div_max = BM_CLKCTRL_CPU_DIV_XTAL >> \
BP_CLKCTRL_CPU_DIV_XTAL; \
bm_busy = BM_CLKCTRL_CPU_BUSY_REF_XTAL; \
} \
if (div == 0 || div > div_max) \
return -EINVAL; \
} else { \
/* \
* hack alert: this block modifies clk->parent, too, \
* so the base to use it the grand parent. \
*/ \
parent_rate = clk_get_rate(clk->parent->parent); \
rate >>= PARENT_RATE_SHIFT; \
parent_rate >>= PARENT_RATE_SHIFT; \
diff = parent_rate; \
div = frac = 1; \
if (clk == &cpu_clk) { \
div_max = BM_CLKCTRL_CPU_DIV_CPU >> \
BP_CLKCTRL_CPU_DIV_CPU; \
bm_busy = BM_CLKCTRL_CPU_BUSY_REF_CPU; \
} \
for (d = 1; d <= div_max; d++) { \
f = parent_rate * 18 / d / rate; \
if ((parent_rate * 18 / d) % rate) \
f++; \
if (f < 18 || f > 35) \
continue; \
\
calc_rate = parent_rate * 18 / f / d; \
if (calc_rate > rate) \
continue; \
\
if (rate - calc_rate < diff) { \
frac = f; \
div = d; \
diff = rate - calc_rate; \
} \
\
if (diff == 0) \
break; \
} \
\
if (diff == parent_rate) \
return -EINVAL; \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr); \
reg &= ~BM_CLKCTRL_##fr##_##fs##FRAC; \
reg |= frac << BP_CLKCTRL_##fr##_##fs##FRAC; \
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr); \
} \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \
if (clk == &cpu_clk) { \
reg &= ~BM_CLKCTRL_CPU_DIV_CPU; \
reg |= div << BP_CLKCTRL_CPU_DIV_CPU; \
} else { \
reg &= ~BM_CLKCTRL_##dr##_DIV; \
reg |= div << BP_CLKCTRL_##dr##_DIV; \
if (reg & (1 << clk->enable_shift)) { \
pr_err("%s: clock is gated\n", __func__); \
return -EINVAL; \
} \
} \
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \
\
return mxs_clkctrl_timeout(HW_CLKCTRL_##dr, bm_busy); \
}
_CLK_SET_RATE(cpu_clk, CPU, FRAC0, CPU)
_CLK_SET_RATE(ssp0_clk, SSP0, FRAC0, IO0)
_CLK_SET_RATE(ssp1_clk, SSP1, FRAC0, IO0)
_CLK_SET_RATE(ssp2_clk, SSP2, FRAC0, IO1)
_CLK_SET_RATE(ssp3_clk, SSP3, FRAC0, IO1)
_CLK_SET_RATE(lcdif_clk, DIS_LCDIF, FRAC1, PIX)
_CLK_SET_RATE(gpmi_clk, GPMI, FRAC1, GPMI)
#define _CLK_SET_RATE1(name, dr) \
static int name##_set_rate(struct clk *clk, unsigned long rate) \
{ \
u32 reg, div_max, div; \
unsigned long parent_rate; \
\
parent_rate = clk_get_rate(clk->parent); \
div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV; \
\
div = DIV_ROUND_UP(parent_rate, rate); \
if (div == 0 || div > div_max) \
return -EINVAL; \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \
reg &= ~BM_CLKCTRL_##dr##_DIV; \
reg |= div << BP_CLKCTRL_##dr##_DIV; \
if (reg & (1 << clk->enable_shift)) { \
pr_err("%s: clock is gated\n", __func__); \
return -EINVAL; \
} \
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \
\
return mxs_clkctrl_timeout(HW_CLKCTRL_##dr, BM_CLKCTRL_##dr##_BUSY);\
}
_CLK_SET_RATE1(xbus_clk, XBUS)
/* saif clock uses 16 bits frac div */
#define _CLK_SET_RATE_SAIF(name, rs) \
static int name##_set_rate(struct clk *clk, unsigned long rate) \
{ \
u16 div; \
u32 reg; \
u64 lrate; \
unsigned long parent_rate; \
\
parent_rate = clk_get_rate(clk->parent); \
if (rate > parent_rate) \
return -EINVAL; \
\
lrate = (u64)rate << 16; \
do_div(lrate, parent_rate); \
div = (u16)lrate; \
\
if (!div) \
return -EINVAL; \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \
reg &= ~BM_CLKCTRL_##rs##_DIV; \
reg |= div << BP_CLKCTRL_##rs##_DIV; \
if (reg & (1 << clk->enable_shift)) { \
pr_err("%s: clock is gated\n", __func__); \
return -EINVAL; \
} \
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs); \
\
return mxs_clkctrl_timeout(HW_CLKCTRL_##rs, BM_CLKCTRL_##rs##_BUSY);\
}
_CLK_SET_RATE_SAIF(saif0_clk, SAIF0)
_CLK_SET_RATE_SAIF(saif1_clk, SAIF1)
#define _CLK_SET_RATE_STUB(name) \
static int name##_set_rate(struct clk *clk, unsigned long rate) \
{ \
return -EINVAL; \
}
_CLK_SET_RATE_STUB(emi_clk)
_CLK_SET_RATE_STUB(uart_clk)
_CLK_SET_RATE_STUB(pwm_clk)
_CLK_SET_RATE_STUB(spdif_clk)
_CLK_SET_RATE_STUB(clk32k_clk)
_CLK_SET_RATE_STUB(can0_clk)
_CLK_SET_RATE_STUB(can1_clk)
_CLK_SET_RATE_STUB(fec_clk)
/*
* clk_set_parent
*/
#define _CLK_SET_PARENT(name, bit) \
static int name##_set_parent(struct clk *clk, struct clk *parent) \
{ \
if (parent != clk->parent) { \
__raw_writel(BM_CLKCTRL_CLKSEQ_BYPASS_##bit, \
CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ_TOG); \
clk->parent = parent; \
} \
\
return 0; \
}
_CLK_SET_PARENT(cpu_clk, CPU)
_CLK_SET_PARENT(emi_clk, EMI)
_CLK_SET_PARENT(ssp0_clk, SSP0)
_CLK_SET_PARENT(ssp1_clk, SSP1)
_CLK_SET_PARENT(ssp2_clk, SSP2)
_CLK_SET_PARENT(ssp3_clk, SSP3)
_CLK_SET_PARENT(lcdif_clk, DIS_LCDIF)
_CLK_SET_PARENT(gpmi_clk, GPMI)
_CLK_SET_PARENT(saif0_clk, SAIF0)
_CLK_SET_PARENT(saif1_clk, SAIF1)
#define _CLK_SET_PARENT_STUB(name) \
static int name##_set_parent(struct clk *clk, struct clk *parent) \
{ \
if (parent != clk->parent) \
return -EINVAL; \
else \
return 0; \
}
_CLK_SET_PARENT_STUB(pwm_clk)
_CLK_SET_PARENT_STUB(uart_clk)
_CLK_SET_PARENT_STUB(clk32k_clk)
_CLK_SET_PARENT_STUB(spdif_clk)
_CLK_SET_PARENT_STUB(fec_clk)
_CLK_SET_PARENT_STUB(can0_clk)
_CLK_SET_PARENT_STUB(can1_clk)
/*
* clk definition
*/
static struct clk cpu_clk = {
.get_rate = cpu_clk_get_rate,
.set_rate = cpu_clk_set_rate,
.set_parent = cpu_clk_set_parent,
.parent = &ref_cpu_clk,
};
static struct clk hbus_clk = {
.get_rate = hbus_clk_get_rate,
.parent = &cpu_clk,
};
static struct clk xbus_clk = {
.get_rate = xbus_clk_get_rate,
.set_rate = xbus_clk_set_rate,
.parent = &ref_xtal_clk,
};
static struct clk lradc_clk = {
.get_rate = lradc_clk_get_rate,
.parent = &clk32k_clk,
};
static struct clk rtc_clk = {
.get_rate = rtc_clk_get_rate,
.parent = &ref_xtal_clk,
};
/* usb_clk gate is controlled in DIGCTRL other than CLKCTRL */
static struct clk usb0_clk = {
.enable_reg = DIGCTRL_BASE_ADDR,
.enable_shift = 2,
.enable = _raw_clk_enable,
.disable = _raw_clk_disable,
.parent = &pll0_clk,
};
static struct clk usb1_clk = {
.enable_reg = DIGCTRL_BASE_ADDR,
.enable_shift = 16,
.enable = _raw_clk_enable,
.disable = _raw_clk_disable,
.parent = &pll1_clk,
};
#define _DEFINE_CLOCK(name, er, es, p) \
static struct clk name = { \
.enable_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_##er, \
.enable_shift = BP_CLKCTRL_##er##_##es, \
.get_rate = name##_get_rate, \
.set_rate = name##_set_rate, \
.set_parent = name##_set_parent, \
.enable = _raw_clk_enable, \
.disable = _raw_clk_disable, \
.parent = p, \
}
_DEFINE_CLOCK(emi_clk, EMI, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(ssp0_clk, SSP0, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(ssp1_clk, SSP1, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(ssp2_clk, SSP2, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(ssp3_clk, SSP3, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(lcdif_clk, DIS_LCDIF, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(gpmi_clk, GPMI, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(saif0_clk, SAIF0, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(saif1_clk, SAIF1, CLKGATE, &ref_xtal_clk);
_DEFINE_CLOCK(can0_clk, FLEXCAN, STOP_CAN0, &ref_xtal_clk);
_DEFINE_CLOCK(can1_clk, FLEXCAN, STOP_CAN1, &ref_xtal_clk);
_DEFINE_CLOCK(pwm_clk, XTAL, PWM_CLK24M_GATE, &ref_xtal_clk);
_DEFINE_CLOCK(uart_clk, XTAL, UART_CLK_GATE, &ref_xtal_clk);
_DEFINE_CLOCK(clk32k_clk, XTAL, TIMROT_CLK32K_GATE, &ref_xtal_clk);
_DEFINE_CLOCK(spdif_clk, SPDIF, CLKGATE, &pll0_clk);
_DEFINE_CLOCK(fec_clk, ENET, DISABLE, &hbus_clk);
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static struct clk_lookup lookups[] = {
/* for amba bus driver */
_REGISTER_CLOCK("duart", "apb_pclk", xbus_clk)
/* for amba-pl011 driver */
_REGISTER_CLOCK("duart", NULL, uart_clk)
_REGISTER_CLOCK("imx28-fec.0", NULL, fec_clk)
_REGISTER_CLOCK("imx28-fec.1", NULL, fec_clk)
_REGISTER_CLOCK("imx28-gpmi-nand", NULL, gpmi_clk)
_REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
_REGISTER_CLOCK("mxs-auart.1", NULL, uart_clk)
_REGISTER_CLOCK("mxs-auart.2", NULL, uart_clk)
_REGISTER_CLOCK("mxs-auart.3", NULL, uart_clk)
_REGISTER_CLOCK("mxs-auart.4", NULL, uart_clk)
_REGISTER_CLOCK("rtc", NULL, rtc_clk)
_REGISTER_CLOCK("pll2", NULL, pll2_clk)
_REGISTER_CLOCK("mxs-dma-apbh", NULL, hbus_clk)
_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
_REGISTER_CLOCK("mxs-mmc.0", NULL, ssp0_clk)
_REGISTER_CLOCK("mxs-mmc.1", NULL, ssp1_clk)
_REGISTER_CLOCK("mxs-mmc.2", NULL, ssp2_clk)
_REGISTER_CLOCK("mxs-mmc.3", NULL, ssp3_clk)
_REGISTER_CLOCK("flexcan.0", NULL, can0_clk)
_REGISTER_CLOCK("flexcan.1", NULL, can1_clk)
_REGISTER_CLOCK(NULL, "usb0", usb0_clk)
_REGISTER_CLOCK(NULL, "usb1", usb1_clk)
_REGISTER_CLOCK("mxs-pwm.0", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.1", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.2", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.3", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.4", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.5", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.6", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.7", NULL, pwm_clk)
_REGISTER_CLOCK(NULL, "lradc", lradc_clk)
_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
_REGISTER_CLOCK("imx28-fb", NULL, lcdif_clk)
_REGISTER_CLOCK("mxs-saif.0", NULL, saif0_clk)
_REGISTER_CLOCK("mxs-saif.1", NULL, saif1_clk)
};
static int clk_misc_init(void)
{
u32 reg;
int ret;
/* Fix up parent per register setting */
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
cpu_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_CPU) ?
&ref_xtal_clk : &ref_cpu_clk;
emi_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_EMI) ?
&ref_xtal_clk : &ref_emi_clk;
ssp0_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SSP0) ?
&ref_xtal_clk : &ref_io0_clk;
ssp1_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SSP1) ?
&ref_xtal_clk : &ref_io0_clk;
ssp2_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SSP2) ?
&ref_xtal_clk : &ref_io1_clk;
ssp3_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SSP3) ?
&ref_xtal_clk : &ref_io1_clk;
lcdif_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF) ?
&ref_xtal_clk : &ref_pix_clk;
gpmi_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_GPMI) ?
&ref_xtal_clk : &ref_gpmi_clk;
saif0_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SAIF0) ?
&ref_xtal_clk : &pll0_clk;
saif1_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SAIF1) ?
&ref_xtal_clk : &pll0_clk;
/* Use int div over frac when both are available */
__raw_writel(BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN,
CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_CLR);
__raw_writel(BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN,
CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_CLR);
__raw_writel(BM_CLKCTRL_HBUS_DIV_FRAC_EN,
CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS_CLR);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_XBUS);
reg &= ~BM_CLKCTRL_XBUS_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_XBUS);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP0);
reg &= ~BM_CLKCTRL_SSP0_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP0);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP1);
reg &= ~BM_CLKCTRL_SSP1_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP1);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP2);
reg &= ~BM_CLKCTRL_SSP2_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP2);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP3);
reg &= ~BM_CLKCTRL_SSP3_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP3);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_GPMI);
reg &= ~BM_CLKCTRL_GPMI_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_GPMI);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_DIS_LCDIF);
reg &= ~BM_CLKCTRL_DIS_LCDIF_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_DIS_LCDIF);
/* SAIF has to use frac div for functional operation */
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0);
reg |= BM_CLKCTRL_SAIF0_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1);
reg |= BM_CLKCTRL_SAIF1_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1);
/*
* Set safe hbus clock divider. A divider of 3 ensure that
* the Vddd voltage required for the cpu clock is sufficiently
* high for the hbus clock.
*/
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
reg &= BM_CLKCTRL_HBUS_DIV;
reg |= 3 << BP_CLKCTRL_HBUS_DIV;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
ret = mxs_clkctrl_timeout(HW_CLKCTRL_HBUS, BM_CLKCTRL_HBUS_ASM_BUSY);
/* Gate off cpu clock in WFI for power saving */
__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET);
/*
* Extra fec clock setting
* The DENX M28 uses an external clock source
* and the clock output must not be enabled
*/
if (!machine_is_m28evk()) {
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
reg &= ~BM_CLKCTRL_ENET_SLEEP;
reg |= BM_CLKCTRL_ENET_CLK_OUT_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
}
/*
* 480 MHz seems too high to be ssp clock source directly,
* so set frac0 to get a 288 MHz ref_io0.
*/
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0);
reg &= ~BM_CLKCTRL_FRAC0_IO0FRAC;
reg |= 30 << BP_CLKCTRL_FRAC0_IO0FRAC;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0);
return ret;
}
int __init mx28_clocks_init(void)
{
clk_misc_init();
/*
* source ssp clock from ref_io0 than ref_xtal,
* as ref_xtal only provides 24 MHz as maximum.
*/
clk_set_parent(&ssp0_clk, &ref_io0_clk);
clk_set_parent(&ssp1_clk, &ref_io0_clk);
clk_set_parent(&ssp2_clk, &ref_io1_clk);
clk_set_parent(&ssp3_clk, &ref_io1_clk);
clk_prepare_enable(&cpu_clk);
clk_prepare_enable(&hbus_clk);
clk_prepare_enable(&xbus_clk);
clk_prepare_enable(&emi_clk);
clk_prepare_enable(&uart_clk);
clk_set_parent(&lcdif_clk, &ref_pix_clk);
clk_set_parent(&saif0_clk, &pll0_clk);
clk_set_parent(&saif1_clk, &pll0_clk);
/*
* Set an initial clock rate for the saif internal logic to work
* properly. This is important when working in EXTMASTER mode that
* uses the other saif's BITCLK&LRCLK but it still needs a basic
* clock which should be fast enough for the internal logic.
*/
clk_set_rate(&saif0_clk, 24000000);
clk_set_rate(&saif1_clk, 24000000);
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
mxs_timer_init(&clk32k_clk, MX28_INT_TIMER0);
return 0;
}

View File

@ -1,211 +0,0 @@
/*
* Based on arch/arm/plat-omap/clock.c
*
* Copyright (C) 2004 - 2005 Nokia corporation
* Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
* Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
* Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, 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.
*/
/* #define DEBUG */
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/semaphore.h>
#include <linux/string.h>
#include <mach/clock.h>
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
/*-------------------------------------------------------------------------
* Standard clock functions defined in include/linux/clk.h
*-------------------------------------------------------------------------*/
static void __clk_disable(struct clk *clk)
{
if (clk == NULL || IS_ERR(clk))
return;
WARN_ON(!clk->usecount);
if (!(--clk->usecount)) {
if (clk->disable)
clk->disable(clk);
__clk_disable(clk->parent);
}
}
static int __clk_enable(struct clk *clk)
{
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
if (clk->usecount++ == 0) {
__clk_enable(clk->parent);
if (clk->enable)
clk->enable(clk);
}
return 0;
}
/*
* The clk_enable/clk_disable could be called by drivers in atomic context,
* so they should not really hold mutex. Instead, clk_prepare/clk_unprepare
* can hold a mutex, as the pair will only be called in non-atomic context.
* Before migrating to common clk framework, we can have __clk_enable and
* __clk_disable called in clk_prepare/clk_unprepare with mutex held and
* leave clk_enable/clk_disable as the dummy functions.
*/
int clk_prepare(struct clk *clk)
{
int ret = 0;
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
mutex_lock(&clocks_mutex);
ret = __clk_enable(clk);
mutex_unlock(&clocks_mutex);
return ret;
}
EXPORT_SYMBOL(clk_prepare);
void clk_unprepare(struct clk *clk)
{
if (clk == NULL || IS_ERR(clk))
return;
mutex_lock(&clocks_mutex);
__clk_disable(clk);
mutex_unlock(&clocks_mutex);
}
EXPORT_SYMBOL(clk_unprepare);
int clk_enable(struct clk *clk)
{
return 0;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
/* nothing to do */
}
EXPORT_SYMBOL(clk_disable);
/* Retrieve the *current* clock rate. If the clock itself
* does not provide a special calculation routine, ask
* its parent and so on, until one is able to return
* a valid clock rate
*/
unsigned long clk_get_rate(struct clk *clk)
{
if (clk == NULL || IS_ERR(clk))
return 0UL;
if (clk->get_rate)
return clk->get_rate(clk);
return clk_get_rate(clk->parent);
}
EXPORT_SYMBOL(clk_get_rate);
/* Round the requested clock rate to the nearest supported
* rate that is less than or equal to the requested rate.
* This is dependent on the clock's current parent.
*/
long clk_round_rate(struct clk *clk, unsigned long rate)
{
if (clk == NULL || IS_ERR(clk) || !clk->round_rate)
return 0;
return clk->round_rate(clk, rate);
}
EXPORT_SYMBOL(clk_round_rate);
/* Set the clock to the requested clock rate. The rate must
* match a supported rate exactly based on what clk_round_rate returns
*/
int clk_set_rate(struct clk *clk, unsigned long rate)
{
int ret = -EINVAL;
if (clk == NULL || IS_ERR(clk) || clk->set_rate == NULL || rate == 0)
return ret;
mutex_lock(&clocks_mutex);
ret = clk->set_rate(clk, rate);
mutex_unlock(&clocks_mutex);
return ret;
}
EXPORT_SYMBOL(clk_set_rate);
/* Set the clock's parent to another clock source */
int clk_set_parent(struct clk *clk, struct clk *parent)
{
int ret = -EINVAL;
struct clk *old;
if (clk == NULL || IS_ERR(clk) || parent == NULL ||
IS_ERR(parent) || clk->set_parent == NULL)
return ret;
if (clk->usecount)
clk_prepare_enable(parent);
mutex_lock(&clocks_mutex);
ret = clk->set_parent(clk, parent);
if (ret == 0) {
old = clk->parent;
clk->parent = parent;
} else {
old = parent;
}
mutex_unlock(&clocks_mutex);
if (clk->usecount)
clk_disable(old);
return ret;
}
EXPORT_SYMBOL(clk_set_parent);
/* Retrieve the clock's parent clock source */
struct clk *clk_get_parent(struct clk *clk)
{
struct clk *ret = NULL;
if (clk == NULL || IS_ERR(clk))
return ret;
return clk->parent;
}
EXPORT_SYMBOL(clk_get_parent);

View File

@ -1,62 +0,0 @@
/*
* Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, 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 __MACH_MXS_CLOCK_H__
#define __MACH_MXS_CLOCK_H__
#ifndef __ASSEMBLY__
#include <linux/list.h>
struct module;
struct clk {
int id;
/* Source clock this clk depends on */
struct clk *parent;
/* Reference count of clock enable/disable */
__s8 usecount;
/* Register bit position for clock's enable/disable control. */
u8 enable_shift;
/* Register address for clock's enable/disable control. */
void __iomem *enable_reg;
u32 flags;
/* get the current clock rate (always a fresh value) */
unsigned long (*get_rate) (struct clk *);
/* Function ptr to set the clock to a new rate. The rate must match a
supported rate returned from round_rate. Leave blank if clock is not
programmable */
int (*set_rate) (struct clk *, unsigned long);
/* Function ptr to round the requested clock rate to the nearest
supported rate that is less than or equal to the requested rate. */
unsigned long (*round_rate) (struct clk *, unsigned long);
/* Function ptr to enable the clock. Leave blank if clock can not
be gated. */
int (*enable) (struct clk *);
/* Function ptr to disable the clock. Leave blank if clock can not
be gated. */
void (*disable) (struct clk *);
/* Function ptr to set the parent clock of the clock. */
int (*set_parent) (struct clk *, struct clk *);
};
int clk_register(struct clk *clk);
void clk_unregister(struct clk *clk);
#endif /* __ASSEMBLY__ */
#endif /* __MACH_MXS_CLOCK_H__ */

View File

@ -11,11 +11,9 @@
#ifndef __MACH_MXS_COMMON_H__
#define __MACH_MXS_COMMON_H__
struct clk;
extern const u32 *mxs_get_ocotp(void);
extern int mxs_reset_block(void __iomem *);
extern void mxs_timer_init(struct clk *, int);
extern void mxs_timer_init(int);
extern void mxs_restart(char, const char *);
extern int mxs_saif_clkmux_select(unsigned int clkmux);
@ -33,6 +31,4 @@ extern void mx28_init_irq(void);
extern void icoll_init_irq(void);
extern int mxs_clkctrl_timeout(unsigned int reg_offset, unsigned int mask);
#endif /* __MACH_MXS_COMMON_H__ */

View File

@ -226,7 +226,7 @@ static void __init mx28evk_fec_reset(void)
struct clk *clk;
/* Enable fec phy clock */
clk = clk_get_sys("pll2", NULL);
clk = clk_get_sys("enet_out", NULL);
if (!IS_ERR(clk))
clk_prepare_enable(clk);

View File

@ -1,331 +0,0 @@
/*
* Freescale CLKCTRL Register Definitions
*
* Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
* Copyright 2008-2010 Freescale Semiconductor, Inc.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This file is created by xml file. Don't Edit it.
*
* Xml Revision: 1.48
* Template revision: 26195
*/
#ifndef __REGS_CLKCTRL_MX23_H__
#define __REGS_CLKCTRL_MX23_H__
#define HW_CLKCTRL_PLLCTRL0 (0x00000000)
#define HW_CLKCTRL_PLLCTRL0_SET (0x00000004)
#define HW_CLKCTRL_PLLCTRL0_CLR (0x00000008)
#define HW_CLKCTRL_PLLCTRL0_TOG (0x0000000c)
#define BP_CLKCTRL_PLLCTRL0_LFR_SEL 28
#define BM_CLKCTRL_PLLCTRL0_LFR_SEL 0x30000000
#define BF_CLKCTRL_PLLCTRL0_LFR_SEL(v) \
(((v) << 28) & BM_CLKCTRL_PLLCTRL0_LFR_SEL)
#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__DEFAULT 0x0
#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__TIMES_2 0x1
#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__TIMES_05 0x2
#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__UNDEFINED 0x3
#define BP_CLKCTRL_PLLCTRL0_CP_SEL 24
#define BM_CLKCTRL_PLLCTRL0_CP_SEL 0x03000000
#define BF_CLKCTRL_PLLCTRL0_CP_SEL(v) \
(((v) << 24) & BM_CLKCTRL_PLLCTRL0_CP_SEL)
#define BV_CLKCTRL_PLLCTRL0_CP_SEL__DEFAULT 0x0
#define BV_CLKCTRL_PLLCTRL0_CP_SEL__TIMES_2 0x1
#define BV_CLKCTRL_PLLCTRL0_CP_SEL__TIMES_05 0x2
#define BV_CLKCTRL_PLLCTRL0_CP_SEL__UNDEFINED 0x3
#define BP_CLKCTRL_PLLCTRL0_DIV_SEL 20
#define BM_CLKCTRL_PLLCTRL0_DIV_SEL 0x00300000
#define BF_CLKCTRL_PLLCTRL0_DIV_SEL(v) \
(((v) << 20) & BM_CLKCTRL_PLLCTRL0_DIV_SEL)
#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__DEFAULT 0x0
#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__LOWER 0x1
#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__LOWEST 0x2
#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__UNDEFINED 0x3
#define BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS 0x00040000
#define BM_CLKCTRL_PLLCTRL0_POWER 0x00010000
#define HW_CLKCTRL_PLLCTRL1 (0x00000010)
#define BM_CLKCTRL_PLLCTRL1_LOCK 0x80000000
#define BM_CLKCTRL_PLLCTRL1_FORCE_LOCK 0x40000000
#define BP_CLKCTRL_PLLCTRL1_LOCK_COUNT 0
#define BM_CLKCTRL_PLLCTRL1_LOCK_COUNT 0x0000FFFF
#define BF_CLKCTRL_PLLCTRL1_LOCK_COUNT(v) \
(((v) << 0) & BM_CLKCTRL_PLLCTRL1_LOCK_COUNT)
#define HW_CLKCTRL_CPU (0x00000020)
#define HW_CLKCTRL_CPU_SET (0x00000024)
#define HW_CLKCTRL_CPU_CLR (0x00000028)
#define HW_CLKCTRL_CPU_TOG (0x0000002c)
#define BM_CLKCTRL_CPU_BUSY_REF_XTAL 0x20000000
#define BM_CLKCTRL_CPU_BUSY_REF_CPU 0x10000000
#define BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN 0x04000000
#define BP_CLKCTRL_CPU_DIV_XTAL 16
#define BM_CLKCTRL_CPU_DIV_XTAL 0x03FF0000
#define BF_CLKCTRL_CPU_DIV_XTAL(v) \
(((v) << 16) & BM_CLKCTRL_CPU_DIV_XTAL)
#define BM_CLKCTRL_CPU_INTERRUPT_WAIT 0x00001000
#define BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN 0x00000400
#define BP_CLKCTRL_CPU_DIV_CPU 0
#define BM_CLKCTRL_CPU_DIV_CPU 0x0000003F
#define BF_CLKCTRL_CPU_DIV_CPU(v) \
(((v) << 0) & BM_CLKCTRL_CPU_DIV_CPU)
#define HW_CLKCTRL_HBUS (0x00000030)
#define HW_CLKCTRL_HBUS_SET (0x00000034)
#define HW_CLKCTRL_HBUS_CLR (0x00000038)
#define HW_CLKCTRL_HBUS_TOG (0x0000003c)
#define BM_CLKCTRL_HBUS_BUSY 0x20000000
#define BM_CLKCTRL_HBUS_DCP_AS_ENABLE 0x10000000
#define BM_CLKCTRL_HBUS_PXP_AS_ENABLE 0x08000000
#define BM_CLKCTRL_HBUS_APBHDMA_AS_ENABLE 0x04000000
#define BM_CLKCTRL_HBUS_APBXDMA_AS_ENABLE 0x02000000
#define BM_CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE 0x01000000
#define BM_CLKCTRL_HBUS_TRAFFIC_AS_ENABLE 0x00800000
#define BM_CLKCTRL_HBUS_CPU_DATA_AS_ENABLE 0x00400000
#define BM_CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE 0x00200000
#define BM_CLKCTRL_HBUS_AUTO_SLOW_MODE 0x00100000
#define BP_CLKCTRL_HBUS_SLOW_DIV 16
#define BM_CLKCTRL_HBUS_SLOW_DIV 0x00070000
#define BF_CLKCTRL_HBUS_SLOW_DIV(v) \
(((v) << 16) & BM_CLKCTRL_HBUS_SLOW_DIV)
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY1 0x0
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY2 0x1
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY4 0x2
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY8 0x3
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY16 0x4
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY32 0x5
#define BM_CLKCTRL_HBUS_DIV_FRAC_EN 0x00000020
#define BP_CLKCTRL_HBUS_DIV 0
#define BM_CLKCTRL_HBUS_DIV 0x0000001F
#define BF_CLKCTRL_HBUS_DIV(v) \
(((v) << 0) & BM_CLKCTRL_HBUS_DIV)
#define HW_CLKCTRL_XBUS (0x00000040)
#define BM_CLKCTRL_XBUS_BUSY 0x80000000
#define BM_CLKCTRL_XBUS_DIV_FRAC_EN 0x00000400
#define BP_CLKCTRL_XBUS_DIV 0
#define BM_CLKCTRL_XBUS_DIV 0x000003FF
#define BF_CLKCTRL_XBUS_DIV(v) \
(((v) << 0) & BM_CLKCTRL_XBUS_DIV)
#define HW_CLKCTRL_XTAL (0x00000050)
#define HW_CLKCTRL_XTAL_SET (0x00000054)
#define HW_CLKCTRL_XTAL_CLR (0x00000058)
#define HW_CLKCTRL_XTAL_TOG (0x0000005c)
#define BP_CLKCTRL_XTAL_UART_CLK_GATE 31
#define BM_CLKCTRL_XTAL_UART_CLK_GATE 0x80000000
#define BP_CLKCTRL_XTAL_FILT_CLK24M_GATE 30
#define BM_CLKCTRL_XTAL_FILT_CLK24M_GATE 0x40000000
#define BP_CLKCTRL_XTAL_PWM_CLK24M_GATE 29
#define BM_CLKCTRL_XTAL_PWM_CLK24M_GATE 0x20000000
#define BM_CLKCTRL_XTAL_DRI_CLK24M_GATE 0x10000000
#define BM_CLKCTRL_XTAL_DIGCTRL_CLK1M_GATE 0x08000000
#define BP_CLKCTRL_XTAL_TIMROT_CLK32K_GATE 26
#define BM_CLKCTRL_XTAL_TIMROT_CLK32K_GATE 0x04000000
#define BP_CLKCTRL_XTAL_DIV_UART 0
#define BM_CLKCTRL_XTAL_DIV_UART 0x00000003
#define BF_CLKCTRL_XTAL_DIV_UART(v) \
(((v) << 0) & BM_CLKCTRL_XTAL_DIV_UART)
#define HW_CLKCTRL_PIX (0x00000060)
#define BP_CLKCTRL_PIX_CLKGATE 31
#define BM_CLKCTRL_PIX_CLKGATE 0x80000000
#define BM_CLKCTRL_PIX_BUSY 0x20000000
#define BM_CLKCTRL_PIX_DIV_FRAC_EN 0x00001000
#define BP_CLKCTRL_PIX_DIV 0
#define BM_CLKCTRL_PIX_DIV 0x00000FFF
#define BF_CLKCTRL_PIX_DIV(v) \
(((v) << 0) & BM_CLKCTRL_PIX_DIV)
#define HW_CLKCTRL_SSP (0x00000070)
#define BP_CLKCTRL_SSP_CLKGATE 31
#define BM_CLKCTRL_SSP_CLKGATE 0x80000000
#define BM_CLKCTRL_SSP_BUSY 0x20000000
#define BM_CLKCTRL_SSP_DIV_FRAC_EN 0x00000200
#define BP_CLKCTRL_SSP_DIV 0
#define BM_CLKCTRL_SSP_DIV 0x000001FF
#define BF_CLKCTRL_SSP_DIV(v) \
(((v) << 0) & BM_CLKCTRL_SSP_DIV)
#define HW_CLKCTRL_GPMI (0x00000080)
#define BP_CLKCTRL_GPMI_CLKGATE 31
#define BM_CLKCTRL_GPMI_CLKGATE 0x80000000
#define BM_CLKCTRL_GPMI_BUSY 0x20000000
#define BM_CLKCTRL_GPMI_DIV_FRAC_EN 0x00000400
#define BP_CLKCTRL_GPMI_DIV 0
#define BM_CLKCTRL_GPMI_DIV 0x000003FF
#define BF_CLKCTRL_GPMI_DIV(v) \
(((v) << 0) & BM_CLKCTRL_GPMI_DIV)
#define HW_CLKCTRL_SPDIF (0x00000090)
#define BM_CLKCTRL_SPDIF_CLKGATE 0x80000000
#define HW_CLKCTRL_EMI (0x000000a0)
#define BP_CLKCTRL_EMI_CLKGATE 31
#define BM_CLKCTRL_EMI_CLKGATE 0x80000000
#define BM_CLKCTRL_EMI_SYNC_MODE_EN 0x40000000
#define BM_CLKCTRL_EMI_BUSY_REF_XTAL 0x20000000
#define BM_CLKCTRL_EMI_BUSY_REF_EMI 0x10000000
#define BM_CLKCTRL_EMI_BUSY_REF_CPU 0x08000000
#define BM_CLKCTRL_EMI_BUSY_SYNC_MODE 0x04000000
#define BM_CLKCTRL_EMI_BUSY_DCC_RESYNC 0x00020000
#define BM_CLKCTRL_EMI_DCC_RESYNC_ENABLE 0x00010000
#define BP_CLKCTRL_EMI_DIV_XTAL 8
#define BM_CLKCTRL_EMI_DIV_XTAL 0x00000F00
#define BF_CLKCTRL_EMI_DIV_XTAL(v) \
(((v) << 8) & BM_CLKCTRL_EMI_DIV_XTAL)
#define BP_CLKCTRL_EMI_DIV_EMI 0
#define BM_CLKCTRL_EMI_DIV_EMI 0x0000003F
#define BF_CLKCTRL_EMI_DIV_EMI(v) \
(((v) << 0) & BM_CLKCTRL_EMI_DIV_EMI)
#define HW_CLKCTRL_IR (0x000000b0)
#define BM_CLKCTRL_IR_CLKGATE 0x80000000
#define BM_CLKCTRL_IR_AUTO_DIV 0x20000000
#define BM_CLKCTRL_IR_IR_BUSY 0x10000000
#define BM_CLKCTRL_IR_IROV_BUSY 0x08000000
#define BP_CLKCTRL_IR_IROV_DIV 16
#define BM_CLKCTRL_IR_IROV_DIV 0x01FF0000
#define BF_CLKCTRL_IR_IROV_DIV(v) \
(((v) << 16) & BM_CLKCTRL_IR_IROV_DIV)
#define BP_CLKCTRL_IR_IR_DIV 0
#define BM_CLKCTRL_IR_IR_DIV 0x000003FF
#define BF_CLKCTRL_IR_IR_DIV(v) \
(((v) << 0) & BM_CLKCTRL_IR_IR_DIV)
#define HW_CLKCTRL_SAIF (0x000000c0)
#define BM_CLKCTRL_SAIF_CLKGATE 0x80000000
#define BM_CLKCTRL_SAIF_BUSY 0x20000000
#define BM_CLKCTRL_SAIF_DIV_FRAC_EN 0x00010000
#define BP_CLKCTRL_SAIF_DIV 0
#define BM_CLKCTRL_SAIF_DIV 0x0000FFFF
#define BF_CLKCTRL_SAIF_DIV(v) \
(((v) << 0) & BM_CLKCTRL_SAIF_DIV)
#define HW_CLKCTRL_TV (0x000000d0)
#define BM_CLKCTRL_TV_CLK_TV108M_GATE 0x80000000
#define BM_CLKCTRL_TV_CLK_TV_GATE 0x40000000
#define HW_CLKCTRL_ETM (0x000000e0)
#define BM_CLKCTRL_ETM_CLKGATE 0x80000000
#define BM_CLKCTRL_ETM_BUSY 0x20000000
#define BM_CLKCTRL_ETM_DIV_FRAC_EN 0x00000040
#define BP_CLKCTRL_ETM_DIV 0
#define BM_CLKCTRL_ETM_DIV 0x0000003F
#define BF_CLKCTRL_ETM_DIV(v) \
(((v) << 0) & BM_CLKCTRL_ETM_DIV)
#define HW_CLKCTRL_FRAC (0x000000f0)
#define HW_CLKCTRL_FRAC_SET (0x000000f4)
#define HW_CLKCTRL_FRAC_CLR (0x000000f8)
#define HW_CLKCTRL_FRAC_TOG (0x000000fc)
#define BP_CLKCTRL_FRAC_CLKGATEIO 31
#define BM_CLKCTRL_FRAC_CLKGATEIO 0x80000000
#define BM_CLKCTRL_FRAC_IO_STABLE 0x40000000
#define BP_CLKCTRL_FRAC_IOFRAC 24
#define BM_CLKCTRL_FRAC_IOFRAC 0x3F000000
#define BF_CLKCTRL_FRAC_IOFRAC(v) \
(((v) << 24) & BM_CLKCTRL_FRAC_IOFRAC)
#define BP_CLKCTRL_FRAC_CLKGATEPIX 23
#define BM_CLKCTRL_FRAC_CLKGATEPIX 0x00800000
#define BM_CLKCTRL_FRAC_PIX_STABLE 0x00400000
#define BP_CLKCTRL_FRAC_PIXFRAC 16
#define BM_CLKCTRL_FRAC_PIXFRAC 0x003F0000
#define BF_CLKCTRL_FRAC_PIXFRAC(v) \
(((v) << 16) & BM_CLKCTRL_FRAC_PIXFRAC)
#define BP_CLKCTRL_FRAC_CLKGATEEMI 15
#define BM_CLKCTRL_FRAC_CLKGATEEMI 0x00008000
#define BM_CLKCTRL_FRAC_EMI_STABLE 0x00004000
#define BP_CLKCTRL_FRAC_EMIFRAC 8
#define BM_CLKCTRL_FRAC_EMIFRAC 0x00003F00
#define BF_CLKCTRL_FRAC_EMIFRAC(v) \
(((v) << 8) & BM_CLKCTRL_FRAC_EMIFRAC)
#define BP_CLKCTRL_FRAC_CLKGATECPU 7
#define BM_CLKCTRL_FRAC_CLKGATECPU 0x00000080
#define BM_CLKCTRL_FRAC_CPU_STABLE 0x00000040
#define BP_CLKCTRL_FRAC_CPUFRAC 0
#define BM_CLKCTRL_FRAC_CPUFRAC 0x0000003F
#define BF_CLKCTRL_FRAC_CPUFRAC(v) \
(((v) << 0) & BM_CLKCTRL_FRAC_CPUFRAC)
#define HW_CLKCTRL_FRAC1 (0x00000100)
#define HW_CLKCTRL_FRAC1_SET (0x00000104)
#define HW_CLKCTRL_FRAC1_CLR (0x00000108)
#define HW_CLKCTRL_FRAC1_TOG (0x0000010c)
#define BM_CLKCTRL_FRAC1_CLKGATEVID 0x80000000
#define BM_CLKCTRL_FRAC1_VID_STABLE 0x40000000
#define HW_CLKCTRL_CLKSEQ (0x00000110)
#define HW_CLKCTRL_CLKSEQ_SET (0x00000114)
#define HW_CLKCTRL_CLKSEQ_CLR (0x00000118)
#define HW_CLKCTRL_CLKSEQ_TOG (0x0000011c)
#define BM_CLKCTRL_CLKSEQ_BYPASS_ETM 0x00000100
#define BM_CLKCTRL_CLKSEQ_BYPASS_CPU 0x00000080
#define BM_CLKCTRL_CLKSEQ_BYPASS_EMI 0x00000040
#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP 0x00000020
#define BM_CLKCTRL_CLKSEQ_BYPASS_GPMI 0x00000010
#define BM_CLKCTRL_CLKSEQ_BYPASS_IR 0x00000008
#define BM_CLKCTRL_CLKSEQ_BYPASS_PIX 0x00000002
#define BM_CLKCTRL_CLKSEQ_BYPASS_SAIF 0x00000001
#define HW_CLKCTRL_RESET (0x00000120)
#define BM_CLKCTRL_RESET_CHIP 0x00000002
#define BM_CLKCTRL_RESET_DIG 0x00000001
#define HW_CLKCTRL_STATUS (0x00000130)
#define BP_CLKCTRL_STATUS_CPU_LIMIT 30
#define BM_CLKCTRL_STATUS_CPU_LIMIT 0xC0000000
#define BF_CLKCTRL_STATUS_CPU_LIMIT(v) \
(((v) << 30) & BM_CLKCTRL_STATUS_CPU_LIMIT)
#define HW_CLKCTRL_VERSION (0x00000140)
#define BP_CLKCTRL_VERSION_MAJOR 24
#define BM_CLKCTRL_VERSION_MAJOR 0xFF000000
#define BF_CLKCTRL_VERSION_MAJOR(v) \
(((v) << 24) & BM_CLKCTRL_VERSION_MAJOR)
#define BP_CLKCTRL_VERSION_MINOR 16
#define BM_CLKCTRL_VERSION_MINOR 0x00FF0000
#define BF_CLKCTRL_VERSION_MINOR(v) \
(((v) << 16) & BM_CLKCTRL_VERSION_MINOR)
#define BP_CLKCTRL_VERSION_STEP 0
#define BM_CLKCTRL_VERSION_STEP 0x0000FFFF
#define BF_CLKCTRL_VERSION_STEP(v) \
(((v) << 0) & BM_CLKCTRL_VERSION_STEP)
#endif /* __REGS_CLKCTRL_MX23_H__ */

View File

@ -1,486 +0,0 @@
/*
* Freescale CLKCTRL Register Definitions
*
* Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This file is created by xml file. Don't Edit it.
*
* Xml Revision: 1.48
* Template revision: 26195
*/
#ifndef __REGS_CLKCTRL_MX28_H__
#define __REGS_CLKCTRL_MX28_H__
#define HW_CLKCTRL_PLL0CTRL0 (0x00000000)
#define HW_CLKCTRL_PLL0CTRL0_SET (0x00000004)
#define HW_CLKCTRL_PLL0CTRL0_CLR (0x00000008)
#define HW_CLKCTRL_PLL0CTRL0_TOG (0x0000000c)
#define BP_CLKCTRL_PLL0CTRL0_LFR_SEL 28
#define BM_CLKCTRL_PLL0CTRL0_LFR_SEL 0x30000000
#define BF_CLKCTRL_PLL0CTRL0_LFR_SEL(v) \
(((v) << 28) & BM_CLKCTRL_PLL0CTRL0_LFR_SEL)
#define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__DEFAULT 0x0
#define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__TIMES_2 0x1
#define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__TIMES_05 0x2
#define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__UNDEFINED 0x3
#define BP_CLKCTRL_PLL0CTRL0_CP_SEL 24
#define BM_CLKCTRL_PLL0CTRL0_CP_SEL 0x03000000
#define BF_CLKCTRL_PLL0CTRL0_CP_SEL(v) \
(((v) << 24) & BM_CLKCTRL_PLL0CTRL0_CP_SEL)
#define BV_CLKCTRL_PLL0CTRL0_CP_SEL__DEFAULT 0x0
#define BV_CLKCTRL_PLL0CTRL0_CP_SEL__TIMES_2 0x1
#define BV_CLKCTRL_PLL0CTRL0_CP_SEL__TIMES_05 0x2
#define BV_CLKCTRL_PLL0CTRL0_CP_SEL__UNDEFINED 0x3
#define BP_CLKCTRL_PLL0CTRL0_DIV_SEL 20
#define BM_CLKCTRL_PLL0CTRL0_DIV_SEL 0x00300000
#define BF_CLKCTRL_PLL0CTRL0_DIV_SEL(v) \
(((v) << 20) & BM_CLKCTRL_PLL0CTRL0_DIV_SEL)
#define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__DEFAULT 0x0
#define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__LOWER 0x1
#define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__LOWEST 0x2
#define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__UNDEFINED 0x3
#define BM_CLKCTRL_PLL0CTRL0_EN_USB_CLKS 0x00040000
#define BM_CLKCTRL_PLL0CTRL0_POWER 0x00020000
#define HW_CLKCTRL_PLL0CTRL1 (0x00000010)
#define BM_CLKCTRL_PLL0CTRL1_LOCK 0x80000000
#define BM_CLKCTRL_PLL0CTRL1_FORCE_LOCK 0x40000000
#define BP_CLKCTRL_PLL0CTRL1_LOCK_COUNT 0
#define BM_CLKCTRL_PLL0CTRL1_LOCK_COUNT 0x0000FFFF
#define BF_CLKCTRL_PLL0CTRL1_LOCK_COUNT(v) \
(((v) << 0) & BM_CLKCTRL_PLL0CTRL1_LOCK_COUNT)
#define HW_CLKCTRL_PLL1CTRL0 (0x00000020)
#define HW_CLKCTRL_PLL1CTRL0_SET (0x00000024)
#define HW_CLKCTRL_PLL1CTRL0_CLR (0x00000028)
#define HW_CLKCTRL_PLL1CTRL0_TOG (0x0000002c)
#define BM_CLKCTRL_PLL1CTRL0_CLKGATEEMI 0x80000000
#define BP_CLKCTRL_PLL1CTRL0_LFR_SEL 28
#define BM_CLKCTRL_PLL1CTRL0_LFR_SEL 0x30000000
#define BF_CLKCTRL_PLL1CTRL0_LFR_SEL(v) \
(((v) << 28) & BM_CLKCTRL_PLL1CTRL0_LFR_SEL)
#define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__DEFAULT 0x0
#define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__TIMES_2 0x1
#define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__TIMES_05 0x2
#define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__UNDEFINED 0x3
#define BP_CLKCTRL_PLL1CTRL0_CP_SEL 24
#define BM_CLKCTRL_PLL1CTRL0_CP_SEL 0x03000000
#define BF_CLKCTRL_PLL1CTRL0_CP_SEL(v) \
(((v) << 24) & BM_CLKCTRL_PLL1CTRL0_CP_SEL)
#define BV_CLKCTRL_PLL1CTRL0_CP_SEL__DEFAULT 0x0
#define BV_CLKCTRL_PLL1CTRL0_CP_SEL__TIMES_2 0x1
#define BV_CLKCTRL_PLL1CTRL0_CP_SEL__TIMES_05 0x2
#define BV_CLKCTRL_PLL1CTRL0_CP_SEL__UNDEFINED 0x3
#define BP_CLKCTRL_PLL1CTRL0_DIV_SEL 20
#define BM_CLKCTRL_PLL1CTRL0_DIV_SEL 0x00300000
#define BF_CLKCTRL_PLL1CTRL0_DIV_SEL(v) \
(((v) << 20) & BM_CLKCTRL_PLL1CTRL0_DIV_SEL)
#define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__DEFAULT 0x0
#define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__LOWER 0x1
#define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__LOWEST 0x2
#define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__UNDEFINED 0x3
#define BM_CLKCTRL_PLL1CTRL0_EN_USB_CLKS 0x00040000
#define BM_CLKCTRL_PLL1CTRL0_POWER 0x00020000
#define HW_CLKCTRL_PLL1CTRL1 (0x00000030)
#define BM_CLKCTRL_PLL1CTRL1_LOCK 0x80000000
#define BM_CLKCTRL_PLL1CTRL1_FORCE_LOCK 0x40000000
#define BP_CLKCTRL_PLL1CTRL1_LOCK_COUNT 0
#define BM_CLKCTRL_PLL1CTRL1_LOCK_COUNT 0x0000FFFF
#define BF_CLKCTRL_PLL1CTRL1_LOCK_COUNT(v) \
(((v) << 0) & BM_CLKCTRL_PLL1CTRL1_LOCK_COUNT)
#define HW_CLKCTRL_PLL2CTRL0 (0x00000040)
#define HW_CLKCTRL_PLL2CTRL0_SET (0x00000044)
#define HW_CLKCTRL_PLL2CTRL0_CLR (0x00000048)
#define HW_CLKCTRL_PLL2CTRL0_TOG (0x0000004c)
#define BM_CLKCTRL_PLL2CTRL0_CLKGATE 0x80000000
#define BP_CLKCTRL_PLL2CTRL0_LFR_SEL 28
#define BM_CLKCTRL_PLL2CTRL0_LFR_SEL 0x30000000
#define BF_CLKCTRL_PLL2CTRL0_LFR_SEL(v) \
(((v) << 28) & BM_CLKCTRL_PLL2CTRL0_LFR_SEL)
#define BM_CLKCTRL_PLL2CTRL0_HOLD_RING_OFF_B 0x04000000
#define BP_CLKCTRL_PLL2CTRL0_CP_SEL 24
#define BM_CLKCTRL_PLL2CTRL0_CP_SEL 0x03000000
#define BF_CLKCTRL_PLL2CTRL0_CP_SEL(v) \
(((v) << 24) & BM_CLKCTRL_PLL2CTRL0_CP_SEL)
#define BM_CLKCTRL_PLL2CTRL0_POWER 0x00800000
#define HW_CLKCTRL_CPU (0x00000050)
#define HW_CLKCTRL_CPU_SET (0x00000054)
#define HW_CLKCTRL_CPU_CLR (0x00000058)
#define HW_CLKCTRL_CPU_TOG (0x0000005c)
#define BM_CLKCTRL_CPU_BUSY_REF_XTAL 0x20000000
#define BM_CLKCTRL_CPU_BUSY_REF_CPU 0x10000000
#define BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN 0x04000000
#define BP_CLKCTRL_CPU_DIV_XTAL 16
#define BM_CLKCTRL_CPU_DIV_XTAL 0x03FF0000
#define BF_CLKCTRL_CPU_DIV_XTAL(v) \
(((v) << 16) & BM_CLKCTRL_CPU_DIV_XTAL)
#define BM_CLKCTRL_CPU_INTERRUPT_WAIT 0x00001000
#define BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN 0x00000400
#define BP_CLKCTRL_CPU_DIV_CPU 0
#define BM_CLKCTRL_CPU_DIV_CPU 0x0000003F
#define BF_CLKCTRL_CPU_DIV_CPU(v) \
(((v) << 0) & BM_CLKCTRL_CPU_DIV_CPU)
#define HW_CLKCTRL_HBUS (0x00000060)
#define HW_CLKCTRL_HBUS_SET (0x00000064)
#define HW_CLKCTRL_HBUS_CLR (0x00000068)
#define HW_CLKCTRL_HBUS_TOG (0x0000006c)
#define BM_CLKCTRL_HBUS_ASM_BUSY 0x80000000
#define BM_CLKCTRL_HBUS_DCP_AS_ENABLE 0x40000000
#define BM_CLKCTRL_HBUS_PXP_AS_ENABLE 0x20000000
#define BM_CLKCTRL_HBUS_ASM_EMIPORT_AS_ENABLE 0x08000000
#define BM_CLKCTRL_HBUS_APBHDMA_AS_ENABLE 0x04000000
#define BM_CLKCTRL_HBUS_APBXDMA_AS_ENABLE 0x02000000
#define BM_CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE 0x01000000
#define BM_CLKCTRL_HBUS_TRAFFIC_AS_ENABLE 0x00800000
#define BM_CLKCTRL_HBUS_CPU_DATA_AS_ENABLE 0x00400000
#define BM_CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE 0x00200000
#define BM_CLKCTRL_HBUS_ASM_ENABLE 0x00100000
#define BM_CLKCTRL_HBUS_AUTO_CLEAR_DIV_ENABLE 0x00080000
#define BP_CLKCTRL_HBUS_SLOW_DIV 16
#define BM_CLKCTRL_HBUS_SLOW_DIV 0x00070000
#define BF_CLKCTRL_HBUS_SLOW_DIV(v) \
(((v) << 16) & BM_CLKCTRL_HBUS_SLOW_DIV)
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY1 0x0
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY2 0x1
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY4 0x2
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY8 0x3
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY16 0x4
#define BV_CLKCTRL_HBUS_SLOW_DIV__BY32 0x5
#define BM_CLKCTRL_HBUS_DIV_FRAC_EN 0x00000020
#define BP_CLKCTRL_HBUS_DIV 0
#define BM_CLKCTRL_HBUS_DIV 0x0000001F
#define BF_CLKCTRL_HBUS_DIV(v) \
(((v) << 0) & BM_CLKCTRL_HBUS_DIV)
#define HW_CLKCTRL_XBUS (0x00000070)
#define BM_CLKCTRL_XBUS_BUSY 0x80000000
#define BM_CLKCTRL_XBUS_AUTO_CLEAR_DIV_ENABLE 0x00000800
#define BM_CLKCTRL_XBUS_DIV_FRAC_EN 0x00000400
#define BP_CLKCTRL_XBUS_DIV 0
#define BM_CLKCTRL_XBUS_DIV 0x000003FF
#define BF_CLKCTRL_XBUS_DIV(v) \
(((v) << 0) & BM_CLKCTRL_XBUS_DIV)
#define HW_CLKCTRL_XTAL (0x00000080)
#define HW_CLKCTRL_XTAL_SET (0x00000084)
#define HW_CLKCTRL_XTAL_CLR (0x00000088)
#define HW_CLKCTRL_XTAL_TOG (0x0000008c)
#define BP_CLKCTRL_XTAL_UART_CLK_GATE 31
#define BM_CLKCTRL_XTAL_UART_CLK_GATE 0x80000000
#define BP_CLKCTRL_XTAL_PWM_CLK24M_GATE 29
#define BM_CLKCTRL_XTAL_PWM_CLK24M_GATE 0x20000000
#define BP_CLKCTRL_XTAL_TIMROT_CLK32K_GATE 26
#define BM_CLKCTRL_XTAL_TIMROT_CLK32K_GATE 0x04000000
#define BP_CLKCTRL_XTAL_DIV_UART 0
#define BM_CLKCTRL_XTAL_DIV_UART 0x00000003
#define BF_CLKCTRL_XTAL_DIV_UART(v) \
(((v) << 0) & BM_CLKCTRL_XTAL_DIV_UART)
#define HW_CLKCTRL_SSP0 (0x00000090)
#define BP_CLKCTRL_SSP0_CLKGATE 31
#define BM_CLKCTRL_SSP0_CLKGATE 0x80000000
#define BM_CLKCTRL_SSP0_BUSY 0x20000000
#define BM_CLKCTRL_SSP0_DIV_FRAC_EN 0x00000200
#define BP_CLKCTRL_SSP0_DIV 0
#define BM_CLKCTRL_SSP0_DIV 0x000001FF
#define BF_CLKCTRL_SSP0_DIV(v) \
(((v) << 0) & BM_CLKCTRL_SSP0_DIV)
#define HW_CLKCTRL_SSP1 (0x000000a0)
#define BP_CLKCTRL_SSP1_CLKGATE 31
#define BM_CLKCTRL_SSP1_CLKGATE 0x80000000
#define BM_CLKCTRL_SSP1_BUSY 0x20000000
#define BM_CLKCTRL_SSP1_DIV_FRAC_EN 0x00000200
#define BP_CLKCTRL_SSP1_DIV 0
#define BM_CLKCTRL_SSP1_DIV 0x000001FF
#define BF_CLKCTRL_SSP1_DIV(v) \
(((v) << 0) & BM_CLKCTRL_SSP1_DIV)
#define HW_CLKCTRL_SSP2 (0x000000b0)
#define BP_CLKCTRL_SSP2_CLKGATE 31
#define BM_CLKCTRL_SSP2_CLKGATE 0x80000000
#define BM_CLKCTRL_SSP2_BUSY 0x20000000
#define BM_CLKCTRL_SSP2_DIV_FRAC_EN 0x00000200
#define BP_CLKCTRL_SSP2_DIV 0
#define BM_CLKCTRL_SSP2_DIV 0x000001FF
#define BF_CLKCTRL_SSP2_DIV(v) \
(((v) << 0) & BM_CLKCTRL_SSP2_DIV)
#define HW_CLKCTRL_SSP3 (0x000000c0)
#define BP_CLKCTRL_SSP3_CLKGATE 31
#define BM_CLKCTRL_SSP3_CLKGATE 0x80000000
#define BM_CLKCTRL_SSP3_BUSY 0x20000000
#define BM_CLKCTRL_SSP3_DIV_FRAC_EN 0x00000200
#define BP_CLKCTRL_SSP3_DIV 0
#define BM_CLKCTRL_SSP3_DIV 0x000001FF
#define BF_CLKCTRL_SSP3_DIV(v) \
(((v) << 0) & BM_CLKCTRL_SSP3_DIV)
#define HW_CLKCTRL_GPMI (0x000000d0)
#define BP_CLKCTRL_GPMI_CLKGATE 31
#define BM_CLKCTRL_GPMI_CLKGATE 0x80000000
#define BM_CLKCTRL_GPMI_BUSY 0x20000000
#define BM_CLKCTRL_GPMI_DIV_FRAC_EN 0x00000400
#define BP_CLKCTRL_GPMI_DIV 0
#define BM_CLKCTRL_GPMI_DIV 0x000003FF
#define BF_CLKCTRL_GPMI_DIV(v) \
(((v) << 0) & BM_CLKCTRL_GPMI_DIV)
#define HW_CLKCTRL_SPDIF (0x000000e0)
#define BP_CLKCTRL_SPDIF_CLKGATE 31
#define BM_CLKCTRL_SPDIF_CLKGATE 0x80000000
#define HW_CLKCTRL_EMI (0x000000f0)
#define BP_CLKCTRL_EMI_CLKGATE 31
#define BM_CLKCTRL_EMI_CLKGATE 0x80000000
#define BM_CLKCTRL_EMI_SYNC_MODE_EN 0x40000000
#define BM_CLKCTRL_EMI_BUSY_REF_XTAL 0x20000000
#define BM_CLKCTRL_EMI_BUSY_REF_EMI 0x10000000
#define BM_CLKCTRL_EMI_BUSY_REF_CPU 0x08000000
#define BM_CLKCTRL_EMI_BUSY_SYNC_MODE 0x04000000
#define BM_CLKCTRL_EMI_BUSY_DCC_RESYNC 0x00020000
#define BM_CLKCTRL_EMI_DCC_RESYNC_ENABLE 0x00010000
#define BP_CLKCTRL_EMI_DIV_XTAL 8
#define BM_CLKCTRL_EMI_DIV_XTAL 0x00000F00
#define BF_CLKCTRL_EMI_DIV_XTAL(v) \
(((v) << 8) & BM_CLKCTRL_EMI_DIV_XTAL)
#define BP_CLKCTRL_EMI_DIV_EMI 0
#define BM_CLKCTRL_EMI_DIV_EMI 0x0000003F
#define BF_CLKCTRL_EMI_DIV_EMI(v) \
(((v) << 0) & BM_CLKCTRL_EMI_DIV_EMI)
#define HW_CLKCTRL_SAIF0 (0x00000100)
#define BP_CLKCTRL_SAIF0_CLKGATE 31
#define BM_CLKCTRL_SAIF0_CLKGATE 0x80000000
#define BM_CLKCTRL_SAIF0_BUSY 0x20000000
#define BM_CLKCTRL_SAIF0_DIV_FRAC_EN 0x00010000
#define BP_CLKCTRL_SAIF0_DIV 0
#define BM_CLKCTRL_SAIF0_DIV 0x0000FFFF
#define BF_CLKCTRL_SAIF0_DIV(v) \
(((v) << 0) & BM_CLKCTRL_SAIF0_DIV)
#define HW_CLKCTRL_SAIF1 (0x00000110)
#define BP_CLKCTRL_SAIF1_CLKGATE 31
#define BM_CLKCTRL_SAIF1_CLKGATE 0x80000000
#define BM_CLKCTRL_SAIF1_BUSY 0x20000000
#define BM_CLKCTRL_SAIF1_DIV_FRAC_EN 0x00010000
#define BP_CLKCTRL_SAIF1_DIV 0
#define BM_CLKCTRL_SAIF1_DIV 0x0000FFFF
#define BF_CLKCTRL_SAIF1_DIV(v) \
(((v) << 0) & BM_CLKCTRL_SAIF1_DIV)
#define HW_CLKCTRL_DIS_LCDIF (0x00000120)
#define BP_CLKCTRL_DIS_LCDIF_CLKGATE 31
#define BM_CLKCTRL_DIS_LCDIF_CLKGATE 0x80000000
#define BM_CLKCTRL_DIS_LCDIF_BUSY 0x20000000
#define BM_CLKCTRL_DIS_LCDIF_DIV_FRAC_EN 0x00002000
#define BP_CLKCTRL_DIS_LCDIF_DIV 0
#define BM_CLKCTRL_DIS_LCDIF_DIV 0x00001FFF
#define BF_CLKCTRL_DIS_LCDIF_DIV(v) \
(((v) << 0) & BM_CLKCTRL_DIS_LCDIF_DIV)
#define HW_CLKCTRL_ETM (0x00000130)
#define BM_CLKCTRL_ETM_CLKGATE 0x80000000
#define BM_CLKCTRL_ETM_BUSY 0x20000000
#define BM_CLKCTRL_ETM_DIV_FRAC_EN 0x00000080
#define BP_CLKCTRL_ETM_DIV 0
#define BM_CLKCTRL_ETM_DIV 0x0000007F
#define BF_CLKCTRL_ETM_DIV(v) \
(((v) << 0) & BM_CLKCTRL_ETM_DIV)
#define HW_CLKCTRL_ENET (0x00000140)
#define BM_CLKCTRL_ENET_SLEEP 0x80000000
#define BP_CLKCTRL_ENET_DISABLE 30
#define BM_CLKCTRL_ENET_DISABLE 0x40000000
#define BM_CLKCTRL_ENET_STATUS 0x20000000
#define BM_CLKCTRL_ENET_BUSY_TIME 0x08000000
#define BP_CLKCTRL_ENET_DIV_TIME 21
#define BM_CLKCTRL_ENET_DIV_TIME 0x07E00000
#define BF_CLKCTRL_ENET_DIV_TIME(v) \
(((v) << 21) & BM_CLKCTRL_ENET_DIV_TIME)
#define BM_CLKCTRL_ENET_BUSY 0x08000000
#define BP_CLKCTRL_ENET_DIV 21
#define BM_CLKCTRL_ENET_DIV 0x07E00000
#define BF_CLKCTRL_ENET_DIV(v) \
(((v) << 21) & BM_CLKCTRL_ENET_DIV)
#define BP_CLKCTRL_ENET_TIME_SEL 19
#define BM_CLKCTRL_ENET_TIME_SEL 0x00180000
#define BF_CLKCTRL_ENET_TIME_SEL(v) \
(((v) << 19) & BM_CLKCTRL_ENET_TIME_SEL)
#define BV_CLKCTRL_ENET_TIME_SEL__XTAL 0x0
#define BV_CLKCTRL_ENET_TIME_SEL__PLL 0x1
#define BV_CLKCTRL_ENET_TIME_SEL__RMII_CLK 0x2
#define BV_CLKCTRL_ENET_TIME_SEL__UNDEFINED 0x3
#define BM_CLKCTRL_ENET_CLK_OUT_EN 0x00040000
#define BM_CLKCTRL_ENET_RESET_BY_SW_CHIP 0x00020000
#define BM_CLKCTRL_ENET_RESET_BY_SW 0x00010000
#define HW_CLKCTRL_HSADC (0x00000150)
#define BM_CLKCTRL_HSADC_RESETB 0x40000000
#define BP_CLKCTRL_HSADC_FREQDIV 28
#define BM_CLKCTRL_HSADC_FREQDIV 0x30000000
#define BF_CLKCTRL_HSADC_FREQDIV(v) \
(((v) << 28) & BM_CLKCTRL_HSADC_FREQDIV)
#define HW_CLKCTRL_FLEXCAN (0x00000160)
#define BP_CLKCTRL_FLEXCAN_STOP_CAN0 30
#define BM_CLKCTRL_FLEXCAN_STOP_CAN0 0x40000000
#define BM_CLKCTRL_FLEXCAN_CAN0_STATUS 0x20000000
#define BP_CLKCTRL_FLEXCAN_STOP_CAN1 28
#define BM_CLKCTRL_FLEXCAN_STOP_CAN1 0x10000000
#define BM_CLKCTRL_FLEXCAN_CAN1_STATUS 0x08000000
#define HW_CLKCTRL_FRAC0 (0x000001b0)
#define HW_CLKCTRL_FRAC0_SET (0x000001b4)
#define HW_CLKCTRL_FRAC0_CLR (0x000001b8)
#define HW_CLKCTRL_FRAC0_TOG (0x000001bc)
#define BP_CLKCTRL_FRAC0_CLKGATEIO0 31
#define BM_CLKCTRL_FRAC0_CLKGATEIO0 0x80000000
#define BM_CLKCTRL_FRAC0_IO0_STABLE 0x40000000
#define BP_CLKCTRL_FRAC0_IO0FRAC 24
#define BM_CLKCTRL_FRAC0_IO0FRAC 0x3F000000
#define BF_CLKCTRL_FRAC0_IO0FRAC(v) \
(((v) << 24) & BM_CLKCTRL_FRAC0_IO0FRAC)
#define BP_CLKCTRL_FRAC0_CLKGATEIO1 23
#define BM_CLKCTRL_FRAC0_CLKGATEIO1 0x00800000
#define BM_CLKCTRL_FRAC0_IO1_STABLE 0x00400000
#define BP_CLKCTRL_FRAC0_IO1FRAC 16
#define BM_CLKCTRL_FRAC0_IO1FRAC 0x003F0000
#define BF_CLKCTRL_FRAC0_IO1FRAC(v) \
(((v) << 16) & BM_CLKCTRL_FRAC0_IO1FRAC)
#define BP_CLKCTRL_FRAC0_CLKGATEEMI 15
#define BM_CLKCTRL_FRAC0_CLKGATEEMI 0x00008000
#define BM_CLKCTRL_FRAC0_EMI_STABLE 0x00004000
#define BP_CLKCTRL_FRAC0_EMIFRAC 8
#define BM_CLKCTRL_FRAC0_EMIFRAC 0x00003F00
#define BF_CLKCTRL_FRAC0_EMIFRAC(v) \
(((v) << 8) & BM_CLKCTRL_FRAC0_EMIFRAC)
#define BP_CLKCTRL_FRAC0_CLKGATECPU 7
#define BM_CLKCTRL_FRAC0_CLKGATECPU 0x00000080
#define BM_CLKCTRL_FRAC0_CPU_STABLE 0x00000040
#define BP_CLKCTRL_FRAC0_CPUFRAC 0
#define BM_CLKCTRL_FRAC0_CPUFRAC 0x0000003F
#define BF_CLKCTRL_FRAC0_CPUFRAC(v) \
(((v) << 0) & BM_CLKCTRL_FRAC0_CPUFRAC)
#define HW_CLKCTRL_FRAC1 (0x000001c0)
#define HW_CLKCTRL_FRAC1_SET (0x000001c4)
#define HW_CLKCTRL_FRAC1_CLR (0x000001c8)
#define HW_CLKCTRL_FRAC1_TOG (0x000001cc)
#define BP_CLKCTRL_FRAC1_CLKGATEGPMI 23
#define BM_CLKCTRL_FRAC1_CLKGATEGPMI 0x00800000
#define BM_CLKCTRL_FRAC1_GPMI_STABLE 0x00400000
#define BP_CLKCTRL_FRAC1_GPMIFRAC 16
#define BM_CLKCTRL_FRAC1_GPMIFRAC 0x003F0000
#define BF_CLKCTRL_FRAC1_GPMIFRAC(v) \
(((v) << 16) & BM_CLKCTRL_FRAC1_GPMIFRAC)
#define BP_CLKCTRL_FRAC1_CLKGATEHSADC 15
#define BM_CLKCTRL_FRAC1_CLKGATEHSADC 0x00008000
#define BM_CLKCTRL_FRAC1_HSADC_STABLE 0x00004000
#define BP_CLKCTRL_FRAC1_HSADCFRAC 8
#define BM_CLKCTRL_FRAC1_HSADCFRAC 0x00003F00
#define BF_CLKCTRL_FRAC1_HSADCFRAC(v) \
(((v) << 8) & BM_CLKCTRL_FRAC1_HSADCFRAC)
#define BP_CLKCTRL_FRAC1_CLKGATEPIX 7
#define BM_CLKCTRL_FRAC1_CLKGATEPIX 0x00000080
#define BM_CLKCTRL_FRAC1_PIX_STABLE 0x00000040
#define BP_CLKCTRL_FRAC1_PIXFRAC 0
#define BM_CLKCTRL_FRAC1_PIXFRAC 0x0000003F
#define BF_CLKCTRL_FRAC1_PIXFRAC(v) \
(((v) << 0) & BM_CLKCTRL_FRAC1_PIXFRAC)
#define HW_CLKCTRL_CLKSEQ (0x000001d0)
#define HW_CLKCTRL_CLKSEQ_SET (0x000001d4)
#define HW_CLKCTRL_CLKSEQ_CLR (0x000001d8)
#define HW_CLKCTRL_CLKSEQ_TOG (0x000001dc)
#define BM_CLKCTRL_CLKSEQ_BYPASS_CPU 0x00040000
#define BM_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF 0x00004000
#define BV_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF__BYPASS 0x1
#define BV_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF__PFD 0x0
#define BM_CLKCTRL_CLKSEQ_BYPASS_ETM 0x00000100
#define BM_CLKCTRL_CLKSEQ_BYPASS_EMI 0x00000080
#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP3 0x00000040
#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP2 0x00000020
#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP1 0x00000010
#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP0 0x00000008
#define BM_CLKCTRL_CLKSEQ_BYPASS_GPMI 0x00000004
#define BM_CLKCTRL_CLKSEQ_BYPASS_SAIF1 0x00000002
#define BM_CLKCTRL_CLKSEQ_BYPASS_SAIF0 0x00000001
#define HW_CLKCTRL_RESET (0x000001e0)
#define BM_CLKCTRL_RESET_WDOG_POR_DISABLE 0x00000020
#define BM_CLKCTRL_RESET_EXTERNAL_RESET_ENABLE 0x00000010
#define BM_CLKCTRL_RESET_THERMAL_RESET_ENABLE 0x00000008
#define BM_CLKCTRL_RESET_THERMAL_RESET_DEFAULT 0x00000004
#define BM_CLKCTRL_RESET_CHIP 0x00000002
#define BM_CLKCTRL_RESET_DIG 0x00000001
#define HW_CLKCTRL_STATUS (0x000001f0)
#define BP_CLKCTRL_STATUS_CPU_LIMIT 30
#define BM_CLKCTRL_STATUS_CPU_LIMIT 0xC0000000
#define BF_CLKCTRL_STATUS_CPU_LIMIT(v) \
(((v) << 30) & BM_CLKCTRL_STATUS_CPU_LIMIT)
#define HW_CLKCTRL_VERSION (0x00000200)
#define BP_CLKCTRL_VERSION_MAJOR 24
#define BM_CLKCTRL_VERSION_MAJOR 0xFF000000
#define BF_CLKCTRL_VERSION_MAJOR(v) \
(((v) << 24) & BM_CLKCTRL_VERSION_MAJOR)
#define BP_CLKCTRL_VERSION_MINOR 16
#define BM_CLKCTRL_VERSION_MINOR 0x00FF0000
#define BF_CLKCTRL_VERSION_MINOR(v) \
(((v) << 16) & BM_CLKCTRL_VERSION_MINOR)
#define BP_CLKCTRL_VERSION_STEP 0
#define BM_CLKCTRL_VERSION_STEP 0x0000FFFF
#define BF_CLKCTRL_VERSION_STEP(v) \
(((v) << 0) & BM_CLKCTRL_VERSION_STEP)
#endif /* __REGS_CLKCTRL_MX28_H__ */

View File

@ -37,8 +37,6 @@
#define MXS_MODULE_CLKGATE (1 << 30)
#define MXS_MODULE_SFTRST (1 << 31)
#define CLKCTRL_TIMEOUT 10 /* 10 ms */
static void __iomem *mxs_clkctrl_reset_addr;
/*
@ -139,17 +137,3 @@ int mxs_reset_block(void __iomem *reset_addr)
return -ETIMEDOUT;
}
EXPORT_SYMBOL(mxs_reset_block);
int mxs_clkctrl_timeout(unsigned int reg_offset, unsigned int mask)
{
unsigned long timeout = jiffies + msecs_to_jiffies(CLKCTRL_TIMEOUT);
while (readl_relaxed(MXS_IO_ADDRESS(MXS_CLKCTRL_BASE_ADDR)
+ reg_offset) & mask) {
if (time_after(jiffies, timeout)) {
pr_err("Timeout at CLKCTRL + 0x%x\n", reg_offset);
return -ETIMEDOUT;
}
}
return 0;
}

View File

@ -20,6 +20,7 @@
* MA 02110-1301, USA.
*/
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/clockchips.h>
@ -243,8 +244,16 @@ static int __init mxs_clocksource_init(struct clk *timer_clk)
return 0;
}
void __init mxs_timer_init(struct clk *timer_clk, int irq)
void __init mxs_timer_init(int irq)
{
struct clk *timer_clk;
timer_clk = clk_get_sys("timrot", NULL);
if (IS_ERR(timer_clk)) {
pr_err("%s: failed to get clk\n", __func__);
return;
}
clk_prepare_enable(timer_clk);
/*

View File

@ -18,6 +18,7 @@
#include <linux/mv643xx_i2c.h>
#include <linux/ata_platform.h>
#include <linux/delay.h>
#include <linux/clk-provider.h>
#include <net/dsa.h>
#include <asm/page.h>
#include <asm/setup.h>
@ -69,6 +70,19 @@ void __init orion5x_map_io(void)
}
/*****************************************************************************
* CLK tree
****************************************************************************/
static struct clk *tclk;
static void __init clk_init(void)
{
tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
orion5x_tclk);
orion_clkdev_init(tclk);
}
/*****************************************************************************
* EHCI0
****************************************************************************/
@ -95,7 +109,7 @@ void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
{
orion_ge00_init(eth_data,
ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM,
IRQ_ORION5X_ETH_ERR, orion5x_tclk);
IRQ_ORION5X_ETH_ERR);
}
@ -132,7 +146,7 @@ void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
****************************************************************************/
void __init orion5x_spi_init()
{
orion_spi_init(SPI_PHYS_BASE, orion5x_tclk);
orion_spi_init(SPI_PHYS_BASE);
}
@ -142,7 +156,7 @@ void __init orion5x_spi_init()
void __init orion5x_uart0_init(void)
{
orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
IRQ_ORION5X_UART0, orion5x_tclk);
IRQ_ORION5X_UART0, tclk);
}
/*****************************************************************************
@ -151,7 +165,7 @@ void __init orion5x_uart0_init(void)
void __init orion5x_uart1_init(void)
{
orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
IRQ_ORION5X_UART1, orion5x_tclk);
IRQ_ORION5X_UART1, tclk);
}
/*****************************************************************************
@ -179,7 +193,7 @@ static void __init orion5x_crypto_init(void)
****************************************************************************/
void __init orion5x_wdt_init(void)
{
orion_wdt_init(orion5x_tclk);
orion_wdt_init();
}
@ -276,6 +290,9 @@ void __init orion5x_init(void)
*/
orion5x_setup_cpu_mbus_bridge();
/* Setup root of clk tree */
clk_init();
/*
* Don't issue "Wait for Interrupt" instruction if we are
* running on D0 5281 silicon.

View File

@ -16,7 +16,6 @@
#include <linux/mtd/physmap.h>
#include <linux/mv643xx_eth.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <linux/spi/flash.h>
#include <linux/ethtool.h>
#include <net/dsa.h>

View File

@ -3,7 +3,7 @@
#
# common files
obj-$(CONFIG_ARCH_SPEAR3XX) += spear3xx.o clock.o
obj-$(CONFIG_ARCH_SPEAR3XX) += spear3xx.o
# spear300 specific files
obj-$(CONFIG_MACH_SPEAR300) += spear300.o

View File

@ -1,892 +0,0 @@
/*
* arch/arm/mach-spear3xx/clock.c
*
* SPEAr3xx machines clock framework source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/clkdev.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of_platform.h>
#include <asm/mach-types.h>
#include <plat/clock.h>
#include <mach/misc_regs.h>
#include <mach/spear.h>
#define PLL1_CTR (MISC_BASE + 0x008)
#define PLL1_FRQ (MISC_BASE + 0x00C)
#define PLL1_MOD (MISC_BASE + 0x010)
#define PLL2_CTR (MISC_BASE + 0x014)
/* PLL_CTR register masks */
#define PLL_ENABLE 2
#define PLL_MODE_SHIFT 4
#define PLL_MODE_MASK 0x3
#define PLL_MODE_NORMAL 0
#define PLL_MODE_FRACTION 1
#define PLL_MODE_DITH_DSB 2
#define PLL_MODE_DITH_SSB 3
#define PLL2_FRQ (MISC_BASE + 0x018)
/* PLL FRQ register masks */
#define PLL_DIV_N_SHIFT 0
#define PLL_DIV_N_MASK 0xFF
#define PLL_DIV_P_SHIFT 8
#define PLL_DIV_P_MASK 0x7
#define PLL_NORM_FDBK_M_SHIFT 24
#define PLL_NORM_FDBK_M_MASK 0xFF
#define PLL_DITH_FDBK_M_SHIFT 16
#define PLL_DITH_FDBK_M_MASK 0xFFFF
#define PLL2_MOD (MISC_BASE + 0x01C)
#define PLL_CLK_CFG (MISC_BASE + 0x020)
#define CORE_CLK_CFG (MISC_BASE + 0x024)
/* CORE CLK CFG register masks */
#define PLL_HCLK_RATIO_SHIFT 10
#define PLL_HCLK_RATIO_MASK 0x3
#define HCLK_PCLK_RATIO_SHIFT 8
#define HCLK_PCLK_RATIO_MASK 0x3
#define PERIP_CLK_CFG (MISC_BASE + 0x028)
/* PERIP_CLK_CFG register masks */
#define UART_CLK_SHIFT 4
#define UART_CLK_MASK 0x1
#define FIRDA_CLK_SHIFT 5
#define FIRDA_CLK_MASK 0x3
#define GPT0_CLK_SHIFT 8
#define GPT1_CLK_SHIFT 11
#define GPT2_CLK_SHIFT 12
#define GPT_CLK_MASK 0x1
#define AUX_CLK_PLL3_VAL 0
#define AUX_CLK_PLL1_VAL 1
#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
/* PERIP1_CLK_ENB register masks */
#define UART_CLK_ENB 3
#define SSP_CLK_ENB 5
#define I2C_CLK_ENB 7
#define JPEG_CLK_ENB 8
#define FIRDA_CLK_ENB 10
#define GPT1_CLK_ENB 11
#define GPT2_CLK_ENB 12
#define ADC_CLK_ENB 15
#define RTC_CLK_ENB 17
#define GPIO_CLK_ENB 18
#define DMA_CLK_ENB 19
#define SMI_CLK_ENB 21
#define GMAC_CLK_ENB 23
#define USBD_CLK_ENB 24
#define USBH_CLK_ENB 25
#define C3_CLK_ENB 31
#define RAS_CLK_ENB (MISC_BASE + 0x034)
#define PRSC1_CLK_CFG (MISC_BASE + 0x044)
#define PRSC2_CLK_CFG (MISC_BASE + 0x048)
#define PRSC3_CLK_CFG (MISC_BASE + 0x04C)
/* gpt synthesizer register masks */
#define GPT_MSCALE_SHIFT 0
#define GPT_MSCALE_MASK 0xFFF
#define GPT_NSCALE_SHIFT 12
#define GPT_NSCALE_MASK 0xF
#define AMEM_CLK_CFG (MISC_BASE + 0x050)
#define EXPI_CLK_CFG (MISC_BASE + 0x054)
#define CLCD_CLK_SYNT (MISC_BASE + 0x05C)
#define FIRDA_CLK_SYNT (MISC_BASE + 0x060)
#define UART_CLK_SYNT (MISC_BASE + 0x064)
#define GMAC_CLK_SYNT (MISC_BASE + 0x068)
#define RAS1_CLK_SYNT (MISC_BASE + 0x06C)
#define RAS2_CLK_SYNT (MISC_BASE + 0x070)
#define RAS3_CLK_SYNT (MISC_BASE + 0x074)
#define RAS4_CLK_SYNT (MISC_BASE + 0x078)
/* aux clk synthesiser register masks for irda to ras4 */
#define AUX_SYNT_ENB 31
#define AUX_EQ_SEL_SHIFT 30
#define AUX_EQ_SEL_MASK 1
#define AUX_EQ1_SEL 0
#define AUX_EQ2_SEL 1
#define AUX_XSCALE_SHIFT 16
#define AUX_XSCALE_MASK 0xFFF
#define AUX_YSCALE_SHIFT 0
#define AUX_YSCALE_MASK 0xFFF
/* root clks */
/* 32 KHz oscillator clock */
static struct clk osc_32k_clk = {
.flags = ALWAYS_ENABLED,
.rate = 32000,
};
/* 24 MHz oscillator clock */
static struct clk osc_24m_clk = {
.flags = ALWAYS_ENABLED,
.rate = 24000000,
};
/* clock derived from 32 KHz osc clk */
/* rtc clock */
static struct clk rtc_clk = {
.pclk = &osc_32k_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = RTC_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from 24 MHz osc clk */
/* pll masks structure */
static struct pll_clk_masks pll1_masks = {
.mode_mask = PLL_MODE_MASK,
.mode_shift = PLL_MODE_SHIFT,
.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
.norm_fdbk_m_shift = PLL_NORM_FDBK_M_SHIFT,
.dith_fdbk_m_mask = PLL_DITH_FDBK_M_MASK,
.dith_fdbk_m_shift = PLL_DITH_FDBK_M_SHIFT,
.div_p_mask = PLL_DIV_P_MASK,
.div_p_shift = PLL_DIV_P_SHIFT,
.div_n_mask = PLL_DIV_N_MASK,
.div_n_shift = PLL_DIV_N_SHIFT,
};
/* pll1 configuration structure */
static struct pll_clk_config pll1_config = {
.mode_reg = PLL1_CTR,
.cfg_reg = PLL1_FRQ,
.masks = &pll1_masks,
};
/* pll rate configuration table, in ascending order of rates */
struct pll_rate_tbl pll_rtbl[] = {
{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
};
/* PLL1 clock */
static struct clk pll1_clk = {
.flags = ENABLED_ON_INIT,
.pclk = &osc_24m_clk,
.en_reg = PLL1_CTR,
.en_reg_bit = PLL_ENABLE,
.calc_rate = &pll_calc_rate,
.recalc = &pll_clk_recalc,
.set_rate = &pll_clk_set_rate,
.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
.private_data = &pll1_config,
};
/* PLL3 48 MHz clock */
static struct clk pll3_48m_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &osc_24m_clk,
.rate = 48000000,
};
/* watch dog timer clock */
static struct clk wdt_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &osc_24m_clk,
.recalc = &follow_parent,
};
/* clock derived from pll1 clk */
/* cpu clock */
static struct clk cpu_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.recalc = &follow_parent,
};
/* ahb masks structure */
static struct bus_clk_masks ahb_masks = {
.mask = PLL_HCLK_RATIO_MASK,
.shift = PLL_HCLK_RATIO_SHIFT,
};
/* ahb configuration structure */
static struct bus_clk_config ahb_config = {
.reg = CORE_CLK_CFG,
.masks = &ahb_masks,
};
/* ahb rate configuration table, in ascending order of rates */
struct bus_rate_tbl bus_rtbl[] = {
{.div = 3}, /* == parent divided by 4 */
{.div = 2}, /* == parent divided by 3 */
{.div = 1}, /* == parent divided by 2 */
{.div = 0}, /* == parent divided by 1 */
};
/* ahb clock */
static struct clk ahb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
.set_rate = &bus_clk_set_rate,
.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &ahb_config,
};
/* auxiliary synthesizers masks */
static struct aux_clk_masks aux_masks = {
.eq_sel_mask = AUX_EQ_SEL_MASK,
.eq_sel_shift = AUX_EQ_SEL_SHIFT,
.eq1_mask = AUX_EQ1_SEL,
.eq2_mask = AUX_EQ2_SEL,
.xscale_sel_mask = AUX_XSCALE_MASK,
.xscale_sel_shift = AUX_XSCALE_SHIFT,
.yscale_sel_mask = AUX_YSCALE_MASK,
.yscale_sel_shift = AUX_YSCALE_SHIFT,
};
/* uart synth configurations */
static struct aux_clk_config uart_synth_config = {
.synth_reg = UART_CLK_SYNT,
.masks = &aux_masks,
};
/* aux rate configuration table, in ascending order of rates */
struct aux_rate_tbl aux_rtbl[] = {
/* For PLL1 = 332 MHz */
{.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */
{.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */
{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
};
/* uart synth clock */
static struct clk uart_synth_clk = {
.en_reg = UART_CLK_SYNT,
.en_reg_bit = AUX_SYNT_ENB,
.pclk = &pll1_clk,
.calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
.set_rate = &aux_clk_set_rate,
.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
.private_data = &uart_synth_config,
};
/* uart parents */
static struct pclk_info uart_pclk_info[] = {
{
.pclk = &uart_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* uart parent select structure */
static struct pclk_sel uart_pclk_sel = {
.pclk_info = uart_pclk_info,
.pclk_count = ARRAY_SIZE(uart_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = UART_CLK_MASK,
};
/* uart clock */
static struct clk uart_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = UART_CLK_ENB,
.pclk_sel = &uart_pclk_sel,
.pclk_sel_shift = UART_CLK_SHIFT,
.recalc = &follow_parent,
};
/* firda configurations */
static struct aux_clk_config firda_synth_config = {
.synth_reg = FIRDA_CLK_SYNT,
.masks = &aux_masks,
};
/* firda synth clock */
static struct clk firda_synth_clk = {
.en_reg = FIRDA_CLK_SYNT,
.en_reg_bit = AUX_SYNT_ENB,
.pclk = &pll1_clk,
.calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
.set_rate = &aux_clk_set_rate,
.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
.private_data = &firda_synth_config,
};
/* firda parents */
static struct pclk_info firda_pclk_info[] = {
{
.pclk = &firda_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* firda parent select structure */
static struct pclk_sel firda_pclk_sel = {
.pclk_info = firda_pclk_info,
.pclk_count = ARRAY_SIZE(firda_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = FIRDA_CLK_MASK,
};
/* firda clock */
static struct clk firda_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = FIRDA_CLK_ENB,
.pclk_sel = &firda_pclk_sel,
.pclk_sel_shift = FIRDA_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt synthesizer masks */
static struct gpt_clk_masks gpt_masks = {
.mscale_sel_mask = GPT_MSCALE_MASK,
.mscale_sel_shift = GPT_MSCALE_SHIFT,
.nscale_sel_mask = GPT_NSCALE_MASK,
.nscale_sel_shift = GPT_NSCALE_SHIFT,
};
/* gpt rate configuration table, in ascending order of rates */
struct gpt_rate_tbl gpt_rtbl[] = {
/* For pll1 = 332 MHz */
{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
{.mscale = 1, .nscale = 0}, /* 83 MHz */
};
/* gpt0 synth clk config*/
static struct gpt_clk_config gpt0_synth_config = {
.synth_reg = PRSC1_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt synth clock */
static struct clk gpt0_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt0_synth_config,
};
/* gpt parents */
static struct pclk_info gpt0_pclk_info[] = {
{
.pclk = &gpt0_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt0_pclk_sel = {
.pclk_info = gpt0_pclk_info,
.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt0 timer clock */
static struct clk gpt0_clk = {
.flags = ALWAYS_ENABLED,
.pclk_sel = &gpt0_pclk_sel,
.pclk_sel_shift = GPT0_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt1 synth clk configurations */
static struct gpt_clk_config gpt1_synth_config = {
.synth_reg = PRSC2_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt1 synth clock */
static struct clk gpt1_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt1_synth_config,
};
static struct pclk_info gpt1_pclk_info[] = {
{
.pclk = &gpt1_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt1_pclk_sel = {
.pclk_info = gpt1_pclk_info,
.pclk_count = ARRAY_SIZE(gpt1_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt1 timer clock */
static struct clk gpt1_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPT1_CLK_ENB,
.pclk_sel = &gpt1_pclk_sel,
.pclk_sel_shift = GPT1_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt2 synth clk configurations */
static struct gpt_clk_config gpt2_synth_config = {
.synth_reg = PRSC3_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt1 synth clock */
static struct clk gpt2_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt2_synth_config,
};
static struct pclk_info gpt2_pclk_info[] = {
{
.pclk = &gpt2_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt2_pclk_sel = {
.pclk_info = gpt2_pclk_info,
.pclk_count = ARRAY_SIZE(gpt2_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt2 timer clock */
static struct clk gpt2_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPT2_CLK_ENB,
.pclk_sel = &gpt2_pclk_sel,
.pclk_sel_shift = GPT2_CLK_SHIFT,
.recalc = &follow_parent,
};
/* clock derived from pll3 clk */
/* usbh clock */
static struct clk usbh_clk = {
.pclk = &pll3_48m_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = USBH_CLK_ENB,
.recalc = &follow_parent,
};
/* usbd clock */
static struct clk usbd_clk = {
.pclk = &pll3_48m_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = USBD_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from usbh clk */
/* usbh0 clock */
static struct clk usbh0_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &usbh_clk,
.recalc = &follow_parent,
};
/* usbh1 clock */
static struct clk usbh1_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &usbh_clk,
.recalc = &follow_parent,
};
/* clock derived from ahb clk */
/* apb masks structure */
static struct bus_clk_masks apb_masks = {
.mask = HCLK_PCLK_RATIO_MASK,
.shift = HCLK_PCLK_RATIO_SHIFT,
};
/* apb configuration structure */
static struct bus_clk_config apb_config = {
.reg = CORE_CLK_CFG,
.masks = &apb_masks,
};
/* apb clock */
static struct clk apb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
.set_rate = &bus_clk_set_rate,
.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &apb_config,
};
/* i2c clock */
static struct clk i2c_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = I2C_CLK_ENB,
.recalc = &follow_parent,
};
/* dma clock */
static struct clk dma_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = DMA_CLK_ENB,
.recalc = &follow_parent,
};
/* jpeg clock */
static struct clk jpeg_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = JPEG_CLK_ENB,
.recalc = &follow_parent,
};
/* gmac clock */
static struct clk gmac_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GMAC_CLK_ENB,
.recalc = &follow_parent,
};
/* smi clock */
static struct clk smi_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SMI_CLK_ENB,
.recalc = &follow_parent,
};
/* c3 clock */
static struct clk c3_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = C3_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from apb clk */
/* adc clock */
static struct clk adc_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = ADC_CLK_ENB,
.recalc = &follow_parent,
};
#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
/* emi clock */
static struct clk emi_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.recalc = &follow_parent,
};
#endif
/* ssp clock */
static struct clk ssp0_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SSP_CLK_ENB,
.recalc = &follow_parent,
};
/* gpio clock */
static struct clk gpio_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPIO_CLK_ENB,
.recalc = &follow_parent,
};
static struct clk dummy_apb_pclk;
#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \
defined(CONFIG_MACH_SPEAR320)
/* fsmc clock */
static struct clk fsmc_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.recalc = &follow_parent,
};
#endif
/* common clocks to spear310 and spear320 */
#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
/* uart1 clock */
static struct clk uart1_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* uart2 clock */
static struct clk uart2_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
#endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */
/* common clocks to spear300 and spear320 */
#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320)
/* clcd clock */
static struct clk clcd_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll3_48m_clk,
.recalc = &follow_parent,
};
/* sdhci clock */
static struct clk sdhci_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.recalc = &follow_parent,
};
#endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */
/* spear300 machine specific clock structures */
#ifdef CONFIG_MACH_SPEAR300
/* gpio1 clock */
static struct clk gpio1_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* keyboard clock */
static struct clk kbd_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
#endif
/* spear310 machine specific clock structures */
#ifdef CONFIG_MACH_SPEAR310
/* uart3 clock */
static struct clk uart3_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* uart4 clock */
static struct clk uart4_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* uart5 clock */
static struct clk uart5_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
#endif
/* spear320 machine specific clock structures */
#ifdef CONFIG_MACH_SPEAR320
/* can0 clock */
static struct clk can0_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* can1 clock */
static struct clk can1_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* i2c1 clock */
static struct clk i2c1_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.recalc = &follow_parent,
};
/* ssp1 clock */
static struct clk ssp1_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* ssp2 clock */
static struct clk ssp2_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* pwm clock */
static struct clk pwm_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
#endif
/* array of all spear 3xx clock lookups */
static struct clk_lookup spear_clk_lookups[] = {
CLKDEV_INIT(NULL, "apb_pclk", &dummy_apb_pclk),
/* root clks */
CLKDEV_INIT(NULL, "osc_32k_clk", &osc_32k_clk),
CLKDEV_INIT(NULL, "osc_24m_clk", &osc_24m_clk),
/* clock derived from 32 KHz osc clk */
CLKDEV_INIT("fc900000.rtc", NULL, &rtc_clk),
/* clock derived from 24 MHz osc clk */
CLKDEV_INIT(NULL, "pll1_clk", &pll1_clk),
CLKDEV_INIT(NULL, "pll3_48m_clk", &pll3_48m_clk),
CLKDEV_INIT("fc880000.wdt", NULL, &wdt_clk),
/* clock derived from pll1 clk */
CLKDEV_INIT(NULL, "cpu_clk", &cpu_clk),
CLKDEV_INIT(NULL, "ahb_clk", &ahb_clk),
CLKDEV_INIT(NULL, "uart_synth_clk", &uart_synth_clk),
CLKDEV_INIT(NULL, "firda_synth_clk", &firda_synth_clk),
CLKDEV_INIT(NULL, "gpt0_synth_clk", &gpt0_synth_clk),
CLKDEV_INIT(NULL, "gpt1_synth_clk", &gpt1_synth_clk),
CLKDEV_INIT(NULL, "gpt2_synth_clk", &gpt2_synth_clk),
CLKDEV_INIT("d0000000.serial", NULL, &uart_clk),
CLKDEV_INIT("firda", NULL, &firda_clk),
CLKDEV_INIT("gpt0", NULL, &gpt0_clk),
CLKDEV_INIT("gpt1", NULL, &gpt1_clk),
CLKDEV_INIT("gpt2", NULL, &gpt2_clk),
/* clock derived from pll3 clk */
CLKDEV_INIT("designware_udc", NULL, &usbd_clk),
CLKDEV_INIT(NULL, "usbh_clk", &usbh_clk),
/* clock derived from usbh clk */
CLKDEV_INIT(NULL, "usbh.0_clk", &usbh0_clk),
CLKDEV_INIT(NULL, "usbh.1_clk", &usbh1_clk),
/* clock derived from ahb clk */
CLKDEV_INIT(NULL, "apb_clk", &apb_clk),
CLKDEV_INIT("d0180000.i2c", NULL, &i2c_clk),
CLKDEV_INIT("fc400000.dma", NULL, &dma_clk),
CLKDEV_INIT("jpeg", NULL, &jpeg_clk),
CLKDEV_INIT("e0800000.eth", NULL, &gmac_clk),
CLKDEV_INIT("fc000000.flash", NULL, &smi_clk),
CLKDEV_INIT("c3", NULL, &c3_clk),
/* clock derived from apb clk */
CLKDEV_INIT("adc", NULL, &adc_clk),
CLKDEV_INIT("d0100000.spi", NULL, &ssp0_clk),
CLKDEV_INIT("fc980000.gpio", NULL, &gpio_clk),
};
/* array of all spear 300 clock lookups */
#ifdef CONFIG_MACH_SPEAR300
static struct clk_lookup spear300_clk_lookups[] = {
CLKDEV_INIT("60000000.clcd", NULL, &clcd_clk),
CLKDEV_INIT("94000000.flash", NULL, &fsmc_clk),
CLKDEV_INIT("a9000000.gpio", NULL, &gpio1_clk),
CLKDEV_INIT("a0000000.kbd", NULL, &kbd_clk),
CLKDEV_INIT("70000000.sdhci", NULL, &sdhci_clk),
};
void __init spear300_clk_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
clk_register(&spear_clk_lookups[i]);
for (i = 0; i < ARRAY_SIZE(spear300_clk_lookups); i++)
clk_register(&spear300_clk_lookups[i]);
clk_init();
}
#endif
/* array of all spear 310 clock lookups */
#ifdef CONFIG_MACH_SPEAR310
static struct clk_lookup spear310_clk_lookups[] = {
CLKDEV_INIT("44000000.flash", NULL, &fsmc_clk),
CLKDEV_INIT(NULL, "emi", &emi_clk),
CLKDEV_INIT("b2000000.serial", NULL, &uart1_clk),
CLKDEV_INIT("b2080000.serial", NULL, &uart2_clk),
CLKDEV_INIT("b2100000.serial", NULL, &uart3_clk),
CLKDEV_INIT("b2180000.serial", NULL, &uart4_clk),
CLKDEV_INIT("b2200000.serial", NULL, &uart5_clk),
};
void __init spear310_clk_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
clk_register(&spear_clk_lookups[i]);
for (i = 0; i < ARRAY_SIZE(spear310_clk_lookups); i++)
clk_register(&spear310_clk_lookups[i]);
clk_init();
}
#endif
/* array of all spear 320 clock lookups */
#ifdef CONFIG_MACH_SPEAR320
static struct clk_lookup spear320_clk_lookups[] = {
CLKDEV_INIT("90000000.clcd", NULL, &clcd_clk),
CLKDEV_INIT("4c000000.flash", NULL, &fsmc_clk),
CLKDEV_INIT("a7000000.i2c", NULL, &i2c1_clk),
CLKDEV_INIT(NULL, "emi", &emi_clk),
CLKDEV_INIT("pwm", NULL, &pwm_clk),
CLKDEV_INIT("70000000.sdhci", NULL, &sdhci_clk),
CLKDEV_INIT("c_can_platform.0", NULL, &can0_clk),
CLKDEV_INIT("c_can_platform.1", NULL, &can1_clk),
CLKDEV_INIT("a5000000.spi", NULL, &ssp1_clk),
CLKDEV_INIT("a6000000.spi", NULL, &ssp2_clk),
CLKDEV_INIT("a3000000.serial", NULL, &uart1_clk),
CLKDEV_INIT("a4000000.serial", NULL, &uart2_clk),
};
void __init spear320_clk_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
clk_register(&spear_clk_lookups[i]);
for (i = 0; i < ARRAY_SIZE(spear320_clk_lookups); i++)
clk_register(&spear320_clk_lookups[i]);
clk_init();
}
#endif

View File

@ -27,28 +27,11 @@ extern struct pl022_ssp_controller pl022_plat_data;
extern struct pl08x_platform_data pl080_plat_data;
/* Add spear3xx family function declarations here */
void __init spear_setup_timer(resource_size_t base, int irq);
void __init spear_setup_of_timer(void);
void __init spear3xx_clk_init(void);
void __init spear3xx_map_io(void);
void __init spear3xx_dt_init_irq(void);
void spear_restart(char, const char *);
/* spear300 declarations */
#ifdef CONFIG_MACH_SPEAR300
void __init spear300_clk_init(void);
#endif /* CONFIG_MACH_SPEAR300 */
/* spear310 declarations */
#ifdef CONFIG_MACH_SPEAR310
void __init spear310_clk_init(void);
#endif /* CONFIG_MACH_SPEAR310 */
/* spear320 declarations */
#ifdef CONFIG_MACH_SPEAR320
void __init spear320_clk_init(void);
#endif /* CONFIG_MACH_SPEAR320 */
#endif /* __MACH_GENERIC_H */

View File

@ -16,7 +16,6 @@
/* FIXME: probe all these from DT */
#define SPEAR3XX_IRQ_INTRCOMM_RAS_ARM 1
#define SPEAR3XX_IRQ_CPU_GPT1_1 2
#define SPEAR3XX_IRQ_GEN_RAS_1 28
#define SPEAR3XX_IRQ_GEN_RAS_2 29
#define SPEAR3XX_IRQ_GEN_RAS_3 30

View File

@ -14,6 +14,8 @@
#ifndef __MACH_MISC_REGS_H
#define __MACH_MISC_REGS_H
#include <mach/spear.h>
#define MISC_BASE IOMEM(VA_SPEAR3XX_ICM3_MISC_REG_BASE)
#define DMA_CHN_CFG (MISC_BASE + 0x0A0)

View File

@ -26,7 +26,6 @@
/* ML1 - Multi Layer CPU Subsystem */
#define SPEAR3XX_ICM3_ML1_2_BASE UL(0xF0000000)
#define VA_SPEAR6XX_ML_CPU_BASE UL(0xF0000000)
#define SPEAR3XX_CPU_TMR_BASE UL(0xF0000000)
/* ICM3 - Basic Subsystem */
#define SPEAR3XX_ICM3_SMI_CTRL_BASE UL(0xFC000000)
@ -45,4 +44,17 @@
#define SPEAR_SYS_CTRL_BASE SPEAR3XX_ICM3_SYS_CTRL_BASE
#define VA_SPEAR_SYS_CTRL_BASE VA_SPEAR3XX_ICM3_SYS_CTRL_BASE
/* SPEAr320 Macros */
#define SPEAR320_SOC_CONFIG_BASE UL(0xB3000000)
#define VA_SPEAR320_SOC_CONFIG_BASE UL(0xFE000000)
#define SPEAR320_CONTROL_REG IOMEM(VA_SPEAR320_SOC_CONFIG_BASE)
#define SPEAR320_EXT_CTRL_REG IOMEM(VA_SPEAR320_SOC_CONFIG_BASE + 0x0018)
#define SPEAR320_UARTX_PCLK_MASK 0x1
#define SPEAR320_UART2_PCLK_SHIFT 8
#define SPEAR320_UART3_PCLK_SHIFT 9
#define SPEAR320_UART4_PCLK_SHIFT 10
#define SPEAR320_UART5_PCLK_SHIFT 11
#define SPEAR320_UART6_PCLK_SHIFT 12
#define SPEAR320_RS485_PCLK_SHIFT 13
#endif /* __MACH_SPEAR3XX_H */

View File

@ -337,7 +337,6 @@ static const char * const spear300_dt_board_compat[] = {
static void __init spear300_map_io(void)
{
spear3xx_map_io();
spear300_clk_init();
}
DT_MACHINE_START(SPEAR300_DT, "ST SPEAr300 SoC with Flattened Device Tree")

View File

@ -478,7 +478,6 @@ static const char * const spear310_dt_board_compat[] = {
static void __init spear310_map_io(void)
{
spear3xx_map_io();
spear310_clk_init();
}
DT_MACHINE_START(SPEAR310_DT, "ST SPEAr310 SoC with Flattened Device Tree")

View File

@ -27,7 +27,6 @@
#define SPEAR320_UART2_BASE UL(0xA4000000)
#define SPEAR320_SSP0_BASE UL(0xA5000000)
#define SPEAR320_SSP1_BASE UL(0xA6000000)
#define SPEAR320_SOC_CONFIG_BASE UL(0xB3000000)
/* Interrupt registers offsets and masks */
#define SPEAR320_INT_STS_MASK_REG 0x04
@ -481,10 +480,19 @@ static const char * const spear320_dt_board_compat[] = {
NULL,
};
struct map_desc spear320_io_desc[] __initdata = {
{
.virtual = VA_SPEAR320_SOC_CONFIG_BASE,
.pfn = __phys_to_pfn(SPEAR320_SOC_CONFIG_BASE),
.length = SZ_16M,
.type = MT_DEVICE
},
};
static void __init spear320_map_io(void)
{
iotable_init(spear320_io_desc, ARRAY_SIZE(spear320_io_desc));
spear3xx_map_io();
spear320_clk_init();
}
DT_MACHINE_START(SPEAR320_DT, "ST SPEAr320 SoC with Flattened Device Tree")

View File

@ -90,6 +90,8 @@ static void __init spear3xx_timer_init(void)
char pclk_name[] = "pll3_48m_clk";
struct clk *gpt_clk, *pclk;
spear3xx_clk_init();
/* get the system timer clock */
gpt_clk = clk_get_sys("gpt0", NULL);
if (IS_ERR(gpt_clk)) {
@ -109,7 +111,7 @@ static void __init spear3xx_timer_init(void)
clk_put(gpt_clk);
clk_put(pclk);
spear_setup_timer(SPEAR3XX_CPU_TMR_BASE, SPEAR3XX_IRQ_CPU_GPT1_1);
spear_setup_of_timer();
}
struct sys_timer spear3xx_timer = {

View File

@ -3,4 +3,4 @@
#
# common files
obj-y += clock.o spear6xx.o
obj-y += spear6xx.o

View File

@ -1,789 +0,0 @@
/*
* arch/arm/mach-spear6xx/clock.c
*
* SPEAr6xx machines clock framework source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <plat/clock.h>
#include <mach/misc_regs.h>
#include <mach/spear.h>
#define PLL1_CTR (MISC_BASE + 0x008)
#define PLL1_FRQ (MISC_BASE + 0x00C)
#define PLL1_MOD (MISC_BASE + 0x010)
#define PLL2_CTR (MISC_BASE + 0x014)
/* PLL_CTR register masks */
#define PLL_ENABLE 2
#define PLL_MODE_SHIFT 4
#define PLL_MODE_MASK 0x3
#define PLL_MODE_NORMAL 0
#define PLL_MODE_FRACTION 1
#define PLL_MODE_DITH_DSB 2
#define PLL_MODE_DITH_SSB 3
#define PLL2_FRQ (MISC_BASE + 0x018)
/* PLL FRQ register masks */
#define PLL_DIV_N_SHIFT 0
#define PLL_DIV_N_MASK 0xFF
#define PLL_DIV_P_SHIFT 8
#define PLL_DIV_P_MASK 0x7
#define PLL_NORM_FDBK_M_SHIFT 24
#define PLL_NORM_FDBK_M_MASK 0xFF
#define PLL_DITH_FDBK_M_SHIFT 16
#define PLL_DITH_FDBK_M_MASK 0xFFFF
#define PLL2_MOD (MISC_BASE + 0x01C)
#define PLL_CLK_CFG (MISC_BASE + 0x020)
#define CORE_CLK_CFG (MISC_BASE + 0x024)
/* CORE CLK CFG register masks */
#define PLL_HCLK_RATIO_SHIFT 10
#define PLL_HCLK_RATIO_MASK 0x3
#define HCLK_PCLK_RATIO_SHIFT 8
#define HCLK_PCLK_RATIO_MASK 0x3
#define PERIP_CLK_CFG (MISC_BASE + 0x028)
/* PERIP_CLK_CFG register masks */
#define CLCD_CLK_SHIFT 2
#define CLCD_CLK_MASK 0x3
#define UART_CLK_SHIFT 4
#define UART_CLK_MASK 0x1
#define FIRDA_CLK_SHIFT 5
#define FIRDA_CLK_MASK 0x3
#define GPT0_CLK_SHIFT 8
#define GPT1_CLK_SHIFT 10
#define GPT2_CLK_SHIFT 11
#define GPT3_CLK_SHIFT 12
#define GPT_CLK_MASK 0x1
#define AUX_CLK_PLL3_VAL 0
#define AUX_CLK_PLL1_VAL 1
#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
/* PERIP1_CLK_ENB register masks */
#define UART0_CLK_ENB 3
#define UART1_CLK_ENB 4
#define SSP0_CLK_ENB 5
#define SSP1_CLK_ENB 6
#define I2C_CLK_ENB 7
#define JPEG_CLK_ENB 8
#define FSMC_CLK_ENB 9
#define FIRDA_CLK_ENB 10
#define GPT2_CLK_ENB 11
#define GPT3_CLK_ENB 12
#define GPIO2_CLK_ENB 13
#define SSP2_CLK_ENB 14
#define ADC_CLK_ENB 15
#define GPT1_CLK_ENB 11
#define RTC_CLK_ENB 17
#define GPIO1_CLK_ENB 18
#define DMA_CLK_ENB 19
#define SMI_CLK_ENB 21
#define CLCD_CLK_ENB 22
#define GMAC_CLK_ENB 23
#define USBD_CLK_ENB 24
#define USBH0_CLK_ENB 25
#define USBH1_CLK_ENB 26
#define PRSC1_CLK_CFG (MISC_BASE + 0x044)
#define PRSC2_CLK_CFG (MISC_BASE + 0x048)
#define PRSC3_CLK_CFG (MISC_BASE + 0x04C)
/* gpt synthesizer register masks */
#define GPT_MSCALE_SHIFT 0
#define GPT_MSCALE_MASK 0xFFF
#define GPT_NSCALE_SHIFT 12
#define GPT_NSCALE_MASK 0xF
#define AMEM_CLK_CFG (MISC_BASE + 0x050)
#define EXPI_CLK_CFG (MISC_BASE + 0x054)
#define CLCD_CLK_SYNT (MISC_BASE + 0x05C)
#define FIRDA_CLK_SYNT (MISC_BASE + 0x060)
#define UART_CLK_SYNT (MISC_BASE + 0x064)
#define GMAC_CLK_SYNT (MISC_BASE + 0x068)
#define RAS1_CLK_SYNT (MISC_BASE + 0x06C)
#define RAS2_CLK_SYNT (MISC_BASE + 0x070)
#define RAS3_CLK_SYNT (MISC_BASE + 0x074)
#define RAS4_CLK_SYNT (MISC_BASE + 0x078)
/* aux clk synthesiser register masks for irda to ras4 */
#define AUX_SYNT_ENB 31
#define AUX_EQ_SEL_SHIFT 30
#define AUX_EQ_SEL_MASK 1
#define AUX_EQ1_SEL 0
#define AUX_EQ2_SEL 1
#define AUX_XSCALE_SHIFT 16
#define AUX_XSCALE_MASK 0xFFF
#define AUX_YSCALE_SHIFT 0
#define AUX_YSCALE_MASK 0xFFF
/* root clks */
/* 32 KHz oscillator clock */
static struct clk osc_32k_clk = {
.flags = ALWAYS_ENABLED,
.rate = 32000,
};
/* 30 MHz oscillator clock */
static struct clk osc_30m_clk = {
.flags = ALWAYS_ENABLED,
.rate = 30000000,
};
/* clock derived from 32 KHz osc clk */
/* rtc clock */
static struct clk rtc_clk = {
.pclk = &osc_32k_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = RTC_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from 30 MHz osc clk */
/* pll masks structure */
static struct pll_clk_masks pll1_masks = {
.mode_mask = PLL_MODE_MASK,
.mode_shift = PLL_MODE_SHIFT,
.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
.norm_fdbk_m_shift = PLL_NORM_FDBK_M_SHIFT,
.dith_fdbk_m_mask = PLL_DITH_FDBK_M_MASK,
.dith_fdbk_m_shift = PLL_DITH_FDBK_M_SHIFT,
.div_p_mask = PLL_DIV_P_MASK,
.div_p_shift = PLL_DIV_P_SHIFT,
.div_n_mask = PLL_DIV_N_MASK,
.div_n_shift = PLL_DIV_N_SHIFT,
};
/* pll1 configuration structure */
static struct pll_clk_config pll1_config = {
.mode_reg = PLL1_CTR,
.cfg_reg = PLL1_FRQ,
.masks = &pll1_masks,
};
/* pll rate configuration table, in ascending order of rates */
struct pll_rate_tbl pll_rtbl[] = {
{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
};
/* PLL1 clock */
static struct clk pll1_clk = {
.flags = ENABLED_ON_INIT,
.pclk = &osc_30m_clk,
.en_reg = PLL1_CTR,
.en_reg_bit = PLL_ENABLE,
.calc_rate = &pll_calc_rate,
.recalc = &pll_clk_recalc,
.set_rate = &pll_clk_set_rate,
.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
.private_data = &pll1_config,
};
/* PLL3 48 MHz clock */
static struct clk pll3_48m_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &osc_30m_clk,
.rate = 48000000,
};
/* watch dog timer clock */
static struct clk wdt_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &osc_30m_clk,
.recalc = &follow_parent,
};
/* clock derived from pll1 clk */
/* cpu clock */
static struct clk cpu_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.recalc = &follow_parent,
};
/* ahb masks structure */
static struct bus_clk_masks ahb_masks = {
.mask = PLL_HCLK_RATIO_MASK,
.shift = PLL_HCLK_RATIO_SHIFT,
};
/* ahb configuration structure */
static struct bus_clk_config ahb_config = {
.reg = CORE_CLK_CFG,
.masks = &ahb_masks,
};
/* ahb rate configuration table, in ascending order of rates */
struct bus_rate_tbl bus_rtbl[] = {
{.div = 3}, /* == parent divided by 4 */
{.div = 2}, /* == parent divided by 3 */
{.div = 1}, /* == parent divided by 2 */
{.div = 0}, /* == parent divided by 1 */
};
/* ahb clock */
static struct clk ahb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
.set_rate = &bus_clk_set_rate,
.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &ahb_config,
};
/* auxiliary synthesizers masks */
static struct aux_clk_masks aux_masks = {
.eq_sel_mask = AUX_EQ_SEL_MASK,
.eq_sel_shift = AUX_EQ_SEL_SHIFT,
.eq1_mask = AUX_EQ1_SEL,
.eq2_mask = AUX_EQ2_SEL,
.xscale_sel_mask = AUX_XSCALE_MASK,
.xscale_sel_shift = AUX_XSCALE_SHIFT,
.yscale_sel_mask = AUX_YSCALE_MASK,
.yscale_sel_shift = AUX_YSCALE_SHIFT,
};
/* uart configurations */
static struct aux_clk_config uart_synth_config = {
.synth_reg = UART_CLK_SYNT,
.masks = &aux_masks,
};
/* aux rate configuration table, in ascending order of rates */
struct aux_rate_tbl aux_rtbl[] = {
/* For PLL1 = 332 MHz */
{.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */
{.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */
{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
};
/* uart synth clock */
static struct clk uart_synth_clk = {
.en_reg = UART_CLK_SYNT,
.en_reg_bit = AUX_SYNT_ENB,
.pclk = &pll1_clk,
.calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
.set_rate = &aux_clk_set_rate,
.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
.private_data = &uart_synth_config,
};
/* uart parents */
static struct pclk_info uart_pclk_info[] = {
{
.pclk = &uart_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* uart parent select structure */
static struct pclk_sel uart_pclk_sel = {
.pclk_info = uart_pclk_info,
.pclk_count = ARRAY_SIZE(uart_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = UART_CLK_MASK,
};
/* uart0 clock */
static struct clk uart0_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = UART0_CLK_ENB,
.pclk_sel = &uart_pclk_sel,
.pclk_sel_shift = UART_CLK_SHIFT,
.recalc = &follow_parent,
};
/* uart1 clock */
static struct clk uart1_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = UART1_CLK_ENB,
.pclk_sel = &uart_pclk_sel,
.pclk_sel_shift = UART_CLK_SHIFT,
.recalc = &follow_parent,
};
/* firda configurations */
static struct aux_clk_config firda_synth_config = {
.synth_reg = FIRDA_CLK_SYNT,
.masks = &aux_masks,
};
/* firda synth clock */
static struct clk firda_synth_clk = {
.en_reg = FIRDA_CLK_SYNT,
.en_reg_bit = AUX_SYNT_ENB,
.pclk = &pll1_clk,
.calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
.set_rate = &aux_clk_set_rate,
.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
.private_data = &firda_synth_config,
};
/* firda parents */
static struct pclk_info firda_pclk_info[] = {
{
.pclk = &firda_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* firda parent select structure */
static struct pclk_sel firda_pclk_sel = {
.pclk_info = firda_pclk_info,
.pclk_count = ARRAY_SIZE(firda_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = FIRDA_CLK_MASK,
};
/* firda clock */
static struct clk firda_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = FIRDA_CLK_ENB,
.pclk_sel = &firda_pclk_sel,
.pclk_sel_shift = FIRDA_CLK_SHIFT,
.recalc = &follow_parent,
};
/* clcd configurations */
static struct aux_clk_config clcd_synth_config = {
.synth_reg = CLCD_CLK_SYNT,
.masks = &aux_masks,
};
/* firda synth clock */
static struct clk clcd_synth_clk = {
.en_reg = CLCD_CLK_SYNT,
.en_reg_bit = AUX_SYNT_ENB,
.pclk = &pll1_clk,
.calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
.set_rate = &aux_clk_set_rate,
.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
.private_data = &clcd_synth_config,
};
/* clcd parents */
static struct pclk_info clcd_pclk_info[] = {
{
.pclk = &clcd_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* clcd parent select structure */
static struct pclk_sel clcd_pclk_sel = {
.pclk_info = clcd_pclk_info,
.pclk_count = ARRAY_SIZE(clcd_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = CLCD_CLK_MASK,
};
/* clcd clock */
static struct clk clcd_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = CLCD_CLK_ENB,
.pclk_sel = &clcd_pclk_sel,
.pclk_sel_shift = CLCD_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt synthesizer masks */
static struct gpt_clk_masks gpt_masks = {
.mscale_sel_mask = GPT_MSCALE_MASK,
.mscale_sel_shift = GPT_MSCALE_SHIFT,
.nscale_sel_mask = GPT_NSCALE_MASK,
.nscale_sel_shift = GPT_NSCALE_SHIFT,
};
/* gpt rate configuration table, in ascending order of rates */
struct gpt_rate_tbl gpt_rtbl[] = {
/* For pll1 = 332 MHz */
{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
{.mscale = 1, .nscale = 0}, /* 83 MHz */
};
/* gpt0 synth clk config*/
static struct gpt_clk_config gpt0_synth_config = {
.synth_reg = PRSC1_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt synth clock */
static struct clk gpt0_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt0_synth_config,
};
/* gpt parents */
static struct pclk_info gpt0_pclk_info[] = {
{
.pclk = &gpt0_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt0_pclk_sel = {
.pclk_info = gpt0_pclk_info,
.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt0 ARM1 subsystem timer clock */
static struct clk gpt0_clk = {
.flags = ALWAYS_ENABLED,
.pclk_sel = &gpt0_pclk_sel,
.pclk_sel_shift = GPT0_CLK_SHIFT,
.recalc = &follow_parent,
};
/* Note: gpt0 and gpt1 share same parent clocks */
/* gpt parent select structure */
static struct pclk_sel gpt1_pclk_sel = {
.pclk_info = gpt0_pclk_info,
.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt1 timer clock */
static struct clk gpt1_clk = {
.flags = ALWAYS_ENABLED,
.pclk_sel = &gpt1_pclk_sel,
.pclk_sel_shift = GPT1_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt2 synth clk config*/
static struct gpt_clk_config gpt2_synth_config = {
.synth_reg = PRSC2_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt synth clock */
static struct clk gpt2_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt2_synth_config,
};
/* gpt parents */
static struct pclk_info gpt2_pclk_info[] = {
{
.pclk = &gpt2_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt2_pclk_sel = {
.pclk_info = gpt2_pclk_info,
.pclk_count = ARRAY_SIZE(gpt2_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt2 timer clock */
static struct clk gpt2_clk = {
.flags = ALWAYS_ENABLED,
.pclk_sel = &gpt2_pclk_sel,
.pclk_sel_shift = GPT2_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt3 synth clk config*/
static struct gpt_clk_config gpt3_synth_config = {
.synth_reg = PRSC3_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt synth clock */
static struct clk gpt3_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt3_synth_config,
};
/* gpt parents */
static struct pclk_info gpt3_pclk_info[] = {
{
.pclk = &gpt3_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt3_pclk_sel = {
.pclk_info = gpt3_pclk_info,
.pclk_count = ARRAY_SIZE(gpt3_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt3 timer clock */
static struct clk gpt3_clk = {
.flags = ALWAYS_ENABLED,
.pclk_sel = &gpt3_pclk_sel,
.pclk_sel_shift = GPT3_CLK_SHIFT,
.recalc = &follow_parent,
};
/* clock derived from pll3 clk */
/* usbh0 clock */
static struct clk usbh0_clk = {
.pclk = &pll3_48m_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = USBH0_CLK_ENB,
.recalc = &follow_parent,
};
/* usbh1 clock */
static struct clk usbh1_clk = {
.pclk = &pll3_48m_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = USBH1_CLK_ENB,
.recalc = &follow_parent,
};
/* usbd clock */
static struct clk usbd_clk = {
.pclk = &pll3_48m_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = USBD_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from ahb clk */
/* apb masks structure */
static struct bus_clk_masks apb_masks = {
.mask = HCLK_PCLK_RATIO_MASK,
.shift = HCLK_PCLK_RATIO_SHIFT,
};
/* apb configuration structure */
static struct bus_clk_config apb_config = {
.reg = CORE_CLK_CFG,
.masks = &apb_masks,
};
/* apb clock */
static struct clk apb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
.set_rate = &bus_clk_set_rate,
.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &apb_config,
};
/* i2c clock */
static struct clk i2c_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = I2C_CLK_ENB,
.recalc = &follow_parent,
};
/* dma clock */
static struct clk dma_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = DMA_CLK_ENB,
.recalc = &follow_parent,
};
/* jpeg clock */
static struct clk jpeg_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = JPEG_CLK_ENB,
.recalc = &follow_parent,
};
/* gmac clock */
static struct clk gmac_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GMAC_CLK_ENB,
.recalc = &follow_parent,
};
/* smi clock */
static struct clk smi_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SMI_CLK_ENB,
.recalc = &follow_parent,
};
/* fsmc clock */
static struct clk fsmc_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = FSMC_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from apb clk */
/* adc clock */
static struct clk adc_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = ADC_CLK_ENB,
.recalc = &follow_parent,
};
/* ssp0 clock */
static struct clk ssp0_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SSP0_CLK_ENB,
.recalc = &follow_parent,
};
/* ssp1 clock */
static struct clk ssp1_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SSP1_CLK_ENB,
.recalc = &follow_parent,
};
/* ssp2 clock */
static struct clk ssp2_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SSP2_CLK_ENB,
.recalc = &follow_parent,
};
/* gpio0 ARM subsystem clock */
static struct clk gpio0_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* gpio1 clock */
static struct clk gpio1_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPIO1_CLK_ENB,
.recalc = &follow_parent,
};
/* gpio2 clock */
static struct clk gpio2_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPIO2_CLK_ENB,
.recalc = &follow_parent,
};
static struct clk dummy_apb_pclk;
/* array of all spear 6xx clock lookups */
static struct clk_lookup spear_clk_lookups[] = {
CLKDEV_INIT(NULL, "apb_pclk", &dummy_apb_pclk),
/* root clks */
CLKDEV_INIT(NULL, "osc_32k_clk", &osc_32k_clk),
CLKDEV_INIT(NULL, "osc_30m_clk", &osc_30m_clk),
/* clock derived from 32 KHz os clk */
CLKDEV_INIT("rtc-spear", NULL, &rtc_clk),
/* clock derived from 30 MHz os clk */
CLKDEV_INIT(NULL, "pll1_clk", &pll1_clk),
CLKDEV_INIT(NULL, "pll3_48m_clk", &pll3_48m_clk),
CLKDEV_INIT("wdt", NULL, &wdt_clk),
/* clock derived from pll1 clk */
CLKDEV_INIT(NULL, "cpu_clk", &cpu_clk),
CLKDEV_INIT(NULL, "ahb_clk", &ahb_clk),
CLKDEV_INIT(NULL, "uart_synth_clk", &uart_synth_clk),
CLKDEV_INIT(NULL, "firda_synth_clk", &firda_synth_clk),
CLKDEV_INIT(NULL, "clcd_synth_clk", &clcd_synth_clk),
CLKDEV_INIT(NULL, "gpt0_synth_clk", &gpt0_synth_clk),
CLKDEV_INIT(NULL, "gpt2_synth_clk", &gpt2_synth_clk),
CLKDEV_INIT(NULL, "gpt3_synth_clk", &gpt3_synth_clk),
CLKDEV_INIT("d0000000.serial", NULL, &uart0_clk),
CLKDEV_INIT("d0080000.serial", NULL, &uart1_clk),
CLKDEV_INIT("firda", NULL, &firda_clk),
CLKDEV_INIT("clcd", NULL, &clcd_clk),
CLKDEV_INIT("gpt0", NULL, &gpt0_clk),
CLKDEV_INIT("gpt1", NULL, &gpt1_clk),
CLKDEV_INIT("gpt2", NULL, &gpt2_clk),
CLKDEV_INIT("gpt3", NULL, &gpt3_clk),
/* clock derived from pll3 clk */
CLKDEV_INIT("designware_udc", NULL, &usbd_clk),
CLKDEV_INIT(NULL, "usbh.0_clk", &usbh0_clk),
CLKDEV_INIT(NULL, "usbh.1_clk", &usbh1_clk),
/* clock derived from ahb clk */
CLKDEV_INIT(NULL, "apb_clk", &apb_clk),
CLKDEV_INIT("d0200000.i2c", NULL, &i2c_clk),
CLKDEV_INIT("fc400000.dma", NULL, &dma_clk),
CLKDEV_INIT("jpeg", NULL, &jpeg_clk),
CLKDEV_INIT("gmac", NULL, &gmac_clk),
CLKDEV_INIT("fc000000.flash", NULL, &smi_clk),
CLKDEV_INIT("d1800000.flash", NULL, &fsmc_clk),
/* clock derived from apb clk */
CLKDEV_INIT("adc", NULL, &adc_clk),
CLKDEV_INIT("ssp-pl022.0", NULL, &ssp0_clk),
CLKDEV_INIT("ssp-pl022.1", NULL, &ssp1_clk),
CLKDEV_INIT("ssp-pl022.2", NULL, &ssp2_clk),
CLKDEV_INIT("f0100000.gpio", NULL, &gpio0_clk),
CLKDEV_INIT("fc980000.gpio", NULL, &gpio1_clk),
CLKDEV_INIT("d8100000.gpio", NULL, &gpio2_clk),
};
void __init spear6xx_clk_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
clk_register(&spear_clk_lookups[i]);
clk_init();
}

View File

@ -16,7 +16,7 @@
#include <linux/init.h>
void __init spear_setup_timer(resource_size_t base, int irq);
void __init spear_setup_of_timer(void);
void spear_restart(char, const char *);
void __init spear6xx_clk_init(void);

View File

@ -16,9 +16,6 @@
/* IRQ definitions */
/* VIC 1 */
/* FIXME: probe this from DT */
#define IRQ_CPU_GPT1_1 16
#define IRQ_VIC_END 64
/* GPIO pins virtual irqs */

View File

@ -14,6 +14,8 @@
#ifndef __MACH_MISC_REGS_H
#define __MACH_MISC_REGS_H
#include <mach/spear.h>
#define MISC_BASE IOMEM(VA_SPEAR6XX_ICM3_MISC_REG_BASE)
#define DMA_CHN_CFG (MISC_BASE + 0x0A0)

View File

@ -25,7 +25,6 @@
/* ML-1, 2 - Multi Layer CPU Subsystem */
#define SPEAR6XX_ML_CPU_BASE UL(0xF0000000)
#define VA_SPEAR6XX_ML_CPU_BASE UL(0xF0000000)
#define SPEAR6XX_CPU_TMR_BASE UL(0xF0000000)
/* ICM3 - Basic Subsystem */
#define SPEAR6XX_ICM3_SMI_CTRL_BASE UL(0xFC000000)

View File

@ -419,9 +419,6 @@ struct map_desc spear6xx_io_desc[] __initdata = {
void __init spear6xx_map_io(void)
{
iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc));
/* This will initialize clock framework */
spear6xx_clk_init();
}
static void __init spear6xx_timer_init(void)
@ -429,6 +426,8 @@ static void __init spear6xx_timer_init(void)
char pclk_name[] = "pll3_48m_clk";
struct clk *gpt_clk, *pclk;
spear6xx_clk_init();
/* get the system timer clock */
gpt_clk = clk_get_sys("gpt0", NULL);
if (IS_ERR(gpt_clk)) {
@ -448,7 +447,7 @@ static void __init spear6xx_timer_init(void)
clk_put(gpt_clk);
clk_put(pclk);
spear_setup_timer(SPEAR6XX_CPU_TMR_BASE, IRQ_CPU_GPT1_1);
spear_setup_of_timer();
}
struct sys_timer spear6xx_timer = {

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -14,15 +14,41 @@
#include <linux/dma-mapping.h>
#include <linux/serial_8250.h>
#include <linux/ata_platform.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/mv643xx_eth.h>
#include <linux/mv643xx_i2c.h>
#include <net/dsa.h>
#include <linux/spi/orion_spi.h>
#include <plat/orion_wdt.h>
#include <plat/mv_xor.h>
#include <plat/ehci-orion.h>
#include <mach/bridge-regs.h>
/* Create a clkdev entry for a given device/clk */
void __init orion_clkdev_add(const char *con_id, const char *dev_id,
struct clk *clk)
{
struct clk_lookup *cl;
cl = clkdev_alloc(clk, con_id, dev_id);
if (cl)
clkdev_add(cl);
}
/* Create clkdev entries for all orion platforms except kirkwood.
Kirkwood has gated clocks for some of its peripherals, so creates
its own clkdev entries. For all the other orion devices, create
clkdev entries to the tclk. */
void __init orion_clkdev_init(struct clk *tclk)
{
orion_clkdev_add(NULL, "orion_spi.0", tclk);
orion_clkdev_add(NULL, "orion_spi.1", tclk);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".0", tclk);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".1", tclk);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".2", tclk);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".3", tclk);
orion_clkdev_add(NULL, "orion_wdt", tclk);
}
/* Fill in the resources structure and link it into the platform
device structure. There is always a memory region, and nearly
always an interrupt.*/
@ -49,6 +75,12 @@ static void fill_resources(struct platform_device *device,
/*****************************************************************************
* UART
****************************************************************************/
static unsigned long __init uart_get_clk_rate(struct clk *clk)
{
clk_prepare_enable(clk);
return clk_get_rate(clk);
}
static void __init uart_complete(
struct platform_device *orion_uart,
struct plat_serial8250_port *data,
@ -56,12 +88,12 @@ static void __init uart_complete(
unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk)
struct clk *clk)
{
data->mapbase = mapbase;
data->membase = (void __iomem *)membase;
data->irq = irq;
data->uartclk = uartclk;
data->uartclk = uart_get_clk_rate(clk);
orion_uart->dev.platform_data = data;
fill_resources(orion_uart, resources, mapbase, 0xff, irq);
@ -90,10 +122,10 @@ static struct platform_device orion_uart0 = {
void __init orion_uart0_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk)
struct clk *clk)
{
uart_complete(&orion_uart0, orion_uart0_data, orion_uart0_resources,
membase, mapbase, irq, uartclk);
membase, mapbase, irq, clk);
}
/*****************************************************************************
@ -118,10 +150,10 @@ static struct platform_device orion_uart1 = {
void __init orion_uart1_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk)
struct clk *clk)
{
uart_complete(&orion_uart1, orion_uart1_data, orion_uart1_resources,
membase, mapbase, irq, uartclk);
membase, mapbase, irq, clk);
}
/*****************************************************************************
@ -146,10 +178,10 @@ static struct platform_device orion_uart2 = {
void __init orion_uart2_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk)
struct clk *clk)
{
uart_complete(&orion_uart2, orion_uart2_data, orion_uart2_resources,
membase, mapbase, irq, uartclk);
membase, mapbase, irq, clk);
}
/*****************************************************************************
@ -174,10 +206,10 @@ static struct platform_device orion_uart3 = {
void __init orion_uart3_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk)
struct clk *clk)
{
uart_complete(&orion_uart3, orion_uart3_data, orion_uart3_resources,
membase, mapbase, irq, uartclk);
membase, mapbase, irq, clk);
}
/*****************************************************************************
@ -203,13 +235,11 @@ void __init orion_rtc_init(unsigned long mapbase,
****************************************************************************/
static __init void ge_complete(
struct mv643xx_eth_shared_platform_data *orion_ge_shared_data,
int tclk,
struct resource *orion_ge_resource, unsigned long irq,
struct platform_device *orion_ge_shared,
struct mv643xx_eth_platform_data *eth_data,
struct platform_device *orion_ge)
{
orion_ge_shared_data->t_clk = tclk;
orion_ge_resource->start = irq;
orion_ge_resource->end = irq;
eth_data->shared = orion_ge_shared;
@ -260,12 +290,11 @@ static struct platform_device orion_ge00 = {
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk)
unsigned long irq_err)
{
fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
ge_complete(&orion_ge00_shared_data, tclk,
ge_complete(&orion_ge00_shared_data,
orion_ge00_resources, irq, &orion_ge00_shared,
eth_data, &orion_ge00);
}
@ -313,12 +342,11 @@ static struct platform_device orion_ge01 = {
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk)
unsigned long irq_err)
{
fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
ge_complete(&orion_ge01_shared_data, tclk,
ge_complete(&orion_ge01_shared_data,
orion_ge01_resources, irq, &orion_ge01_shared,
eth_data, &orion_ge01);
}
@ -366,12 +394,11 @@ static struct platform_device orion_ge10 = {
void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk)
unsigned long irq_err)
{
fill_resources(&orion_ge10_shared, orion_ge10_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
ge_complete(&orion_ge10_shared_data, tclk,
ge_complete(&orion_ge10_shared_data,
orion_ge10_resources, irq, &orion_ge10_shared,
eth_data, &orion_ge10);
}
@ -419,12 +446,11 @@ static struct platform_device orion_ge11 = {
void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk)
unsigned long irq_err)
{
fill_resources(&orion_ge11_shared, orion_ge11_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
ge_complete(&orion_ge11_shared_data, tclk,
ge_complete(&orion_ge11_shared_data,
orion_ge11_resources, irq, &orion_ge11_shared,
eth_data, &orion_ge11);
}
@ -521,44 +547,32 @@ void __init orion_i2c_1_init(unsigned long mapbase,
/*****************************************************************************
* SPI
****************************************************************************/
static struct orion_spi_info orion_spi_plat_data;
static struct resource orion_spi_resources;
static struct platform_device orion_spi = {
.name = "orion_spi",
.id = 0,
.dev = {
.platform_data = &orion_spi_plat_data,
},
};
static struct orion_spi_info orion_spi_1_plat_data;
static struct resource orion_spi_1_resources;
static struct platform_device orion_spi_1 = {
.name = "orion_spi",
.id = 1,
.dev = {
.platform_data = &orion_spi_1_plat_data,
},
};
/* Note: The SPI silicon core does have interrupts. However the
* current Linux software driver does not use interrupts. */
void __init orion_spi_init(unsigned long mapbase,
unsigned long tclk)
void __init orion_spi_init(unsigned long mapbase)
{
orion_spi_plat_data.tclk = tclk;
fill_resources(&orion_spi, &orion_spi_resources,
mapbase, SZ_512 - 1, NO_IRQ);
platform_device_register(&orion_spi);
}
void __init orion_spi_1_init(unsigned long mapbase,
unsigned long tclk)
void __init orion_spi_1_init(unsigned long mapbase)
{
orion_spi_1_plat_data.tclk = tclk;
fill_resources(&orion_spi_1, &orion_spi_1_resources,
mapbase, SZ_512 - 1, NO_IRQ);
platform_device_register(&orion_spi_1);
@ -567,24 +581,18 @@ void __init orion_spi_1_init(unsigned long mapbase,
/*****************************************************************************
* Watchdog
****************************************************************************/
static struct orion_wdt_platform_data orion_wdt_data;
static struct resource orion_wdt_resource =
DEFINE_RES_MEM(TIMER_VIRT_BASE, 0x28);
static struct platform_device orion_wdt_device = {
.name = "orion_wdt",
.id = -1,
.dev = {
.platform_data = &orion_wdt_data,
},
.resource = &orion_wdt_resource,
.num_resources = 1,
.resource = &orion_wdt_resource,
};
void __init orion_wdt_init(unsigned long tclk)
void __init orion_wdt_init(void)
{
orion_wdt_data.tclk = tclk;
platform_device_register(&orion_wdt_device);
}

View File

@ -16,22 +16,22 @@ struct dsa_platform_data;
void __init orion_uart0_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk);
struct clk *clk);
void __init orion_uart1_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk);
struct clk *clk);
void __init orion_uart2_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk);
struct clk *clk);
void __init orion_uart3_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk);
struct clk *clk);
void __init orion_rtc_init(unsigned long mapbase,
unsigned long irq);
@ -39,29 +39,26 @@ void __init orion_rtc_init(unsigned long mapbase,
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk);
unsigned long irq_err);
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk);
unsigned long irq_err);
void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk);
unsigned long irq_err);
void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk);
unsigned long irq_err);
void __init orion_ge00_switch_init(struct dsa_platform_data *d,
int irq);
void __init orion_i2c_init(unsigned long mapbase,
unsigned long irq,
unsigned long freq_m);
@ -70,13 +67,11 @@ void __init orion_i2c_1_init(unsigned long mapbase,
unsigned long irq,
unsigned long freq_m);
void __init orion_spi_init(unsigned long mapbase,
unsigned long tclk);
void __init orion_spi_init(unsigned long mapbase);
void __init orion_spi_1_init(unsigned long mapbase,
unsigned long tclk);
void __init orion_spi_1_init(unsigned long mapbase);
void __init orion_wdt_init(unsigned long tclk);
void __init orion_wdt_init(void);
void __init orion_xor0_init(unsigned long mapbase_low,
unsigned long mapbase_high,
@ -106,4 +101,9 @@ void __init orion_crypto_init(unsigned long mapbase,
unsigned long srambase,
unsigned long sram_size,
unsigned long irq);
void __init orion_clkdev_add(const char *con_id, const char *dev_id,
struct clk *clk);
void __init orion_clkdev_init(struct clk *tclk);
#endif

View File

@ -1,18 +0,0 @@
/*
* arch/arm/plat-orion/include/plat/orion_wdt.h
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef __PLAT_ORION_WDT_H
#define __PLAT_ORION_WDT_H
struct orion_wdt_platform_data {
u32 tclk; /* no <linux/clk.h> support yet */
};
#endif

View File

@ -52,12 +52,12 @@
#define PCIE_DEBUG_SOFT_RESET (1<<20)
u32 __init orion_pcie_dev_id(void __iomem *base)
u32 orion_pcie_dev_id(void __iomem *base)
{
return readl(base + PCIE_DEV_ID_OFF) >> 16;
}
u32 __init orion_pcie_rev(void __iomem *base)
u32 orion_pcie_rev(void __iomem *base)
{
return readl(base + PCIE_DEV_REV_OFF) & 0xff;
}

View File

@ -3,6 +3,6 @@
#
# Common support
obj-y := clock.o restart.o time.o pl080.o
obj-y := restart.o time.o pl080.o
obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o

File diff suppressed because it is too large Load Diff

View File

@ -1,249 +0,0 @@
/*
* arch/arm/plat-spear/include/plat/clock.h
*
* Clock framework definitions for SPEAr platform
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef __PLAT_CLOCK_H
#define __PLAT_CLOCK_H
#include <linux/list.h>
#include <linux/clkdev.h>
#include <linux/types.h>
/* clk structure flags */
#define ALWAYS_ENABLED (1 << 0) /* clock always enabled */
#define RESET_TO_ENABLE (1 << 1) /* reset register bit to enable clk */
#define ENABLED_ON_INIT (1 << 2) /* clocks enabled at init */
/**
* struct clkops - clock operations
* @enable: pointer to clock enable function
* @disable: pointer to clock disable function
*/
struct clkops {
int (*enable) (struct clk *);
void (*disable) (struct clk *);
};
/**
* struct pclk_info - parents info
* @pclk: pointer to parent clk
* @pclk_val: value to be written for selecting this parent
*/
struct pclk_info {
struct clk *pclk;
u8 pclk_val;
};
/**
* struct pclk_sel - parents selection configuration
* @pclk_info: pointer to array of parent clock info
* @pclk_count: number of parents
* @pclk_sel_reg: register for selecting a parent
* @pclk_sel_mask: mask for selecting parent (can be used to clear bits also)
*/
struct pclk_sel {
struct pclk_info *pclk_info;
u8 pclk_count;
void __iomem *pclk_sel_reg;
unsigned int pclk_sel_mask;
};
/**
* struct rate_config - clk rate configurations
* @tbls: array of device specific clk rate tables, in ascending order of rates
* @count: size of tbls array
* @default_index: default setting when originally disabled
*/
struct rate_config {
void *tbls;
u8 count;
u8 default_index;
};
/**
* struct clk - clock structure
* @usage_count: num of users who enabled this clock
* @flags: flags for clock properties
* @rate: programmed clock rate in Hz
* @en_reg: clk enable/disable reg
* @en_reg_bit: clk enable/disable bit
* @ops: clk enable/disable ops - generic_clkops selected if NULL
* @recalc: pointer to clock rate recalculate function
* @set_rate: pointer to clock set rate function
* @calc_rate: pointer to clock get rate function for index
* @rate_config: rate configuration information, used by set_rate
* @div_factor: division factor to parent clock.
* @pclk: current parent clk
* @pclk_sel: pointer to parent selection structure
* @pclk_sel_shift: register shift for selecting parent of this clock
* @children: list for childrens or this clock
* @sibling: node for list of clocks having same parents
* @private_data: clock specific private data
* @node: list to maintain clocks linearly
* @cl: clocklook up associated with this clock
* @dent: object for debugfs
*/
struct clk {
unsigned int usage_count;
unsigned int flags;
unsigned long rate;
void __iomem *en_reg;
u8 en_reg_bit;
const struct clkops *ops;
int (*recalc) (struct clk *);
int (*set_rate) (struct clk *, unsigned long rate);
unsigned long (*calc_rate)(struct clk *, int index);
struct rate_config rate_config;
unsigned int div_factor;
struct clk *pclk;
struct pclk_sel *pclk_sel;
unsigned int pclk_sel_shift;
struct list_head children;
struct list_head sibling;
void *private_data;
#ifdef CONFIG_DEBUG_FS
struct list_head node;
struct clk_lookup *cl;
struct dentry *dent;
#endif
};
/* pll configuration structure */
struct pll_clk_masks {
u32 mode_mask;
u32 mode_shift;
u32 norm_fdbk_m_mask;
u32 norm_fdbk_m_shift;
u32 dith_fdbk_m_mask;
u32 dith_fdbk_m_shift;
u32 div_p_mask;
u32 div_p_shift;
u32 div_n_mask;
u32 div_n_shift;
};
struct pll_clk_config {
void __iomem *mode_reg;
void __iomem *cfg_reg;
struct pll_clk_masks *masks;
};
/* pll clk rate config structure */
struct pll_rate_tbl {
u8 mode;
u16 m;
u8 n;
u8 p;
};
/* ahb and apb bus configuration structure */
struct bus_clk_masks {
u32 mask;
u32 shift;
};
struct bus_clk_config {
void __iomem *reg;
struct bus_clk_masks *masks;
};
/* ahb and apb clk bus rate config structure */
struct bus_rate_tbl {
u8 div;
};
/* Aux clk configuration structure: applicable to UART and FIRDA */
struct aux_clk_masks {
u32 eq_sel_mask;
u32 eq_sel_shift;
u32 eq1_mask;
u32 eq2_mask;
u32 xscale_sel_mask;
u32 xscale_sel_shift;
u32 yscale_sel_mask;
u32 yscale_sel_shift;
};
struct aux_clk_config {
void __iomem *synth_reg;
struct aux_clk_masks *masks;
};
/* aux clk rate config structure */
struct aux_rate_tbl {
u16 xscale;
u16 yscale;
u8 eq;
};
/* GPT clk configuration structure */
struct gpt_clk_masks {
u32 mscale_sel_mask;
u32 mscale_sel_shift;
u32 nscale_sel_mask;
u32 nscale_sel_shift;
};
struct gpt_clk_config {
void __iomem *synth_reg;
struct gpt_clk_masks *masks;
};
/* gpt clk rate config structure */
struct gpt_rate_tbl {
u16 mscale;
u16 nscale;
};
/* clcd clk configuration structure */
struct clcd_synth_masks {
u32 div_factor_mask;
u32 div_factor_shift;
};
struct clcd_clk_config {
void __iomem *synth_reg;
struct clcd_synth_masks *masks;
};
/* clcd clk rate config structure */
struct clcd_rate_tbl {
u16 div;
};
/* platform specific clock functions */
void __init clk_init(void);
void clk_register(struct clk_lookup *cl);
void recalc_root_clocks(void);
/* clock recalc & set rate functions */
int follow_parent(struct clk *clk);
unsigned long pll_calc_rate(struct clk *clk, int index);
int pll_clk_recalc(struct clk *clk);
int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate);
unsigned long bus_calc_rate(struct clk *clk, int index);
int bus_clk_recalc(struct clk *clk);
int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate);
unsigned long gpt_calc_rate(struct clk *clk, int index);
int gpt_clk_recalc(struct clk *clk);
int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate);
unsigned long aux_calc_rate(struct clk *clk, int index);
int aux_clk_recalc(struct clk *clk);
int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate);
unsigned long clcd_calc_rate(struct clk *clk, int index);
int clcd_clk_recalc(struct clk *clk);
int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate);
#endif /* __PLAT_CLOCK_H */

View File

@ -18,6 +18,8 @@
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/time.h>
#include <linux/irq.h>
#include <asm/mach/time.h>
@ -197,19 +199,32 @@ static void __init spear_clockevent_init(int irq)
setup_irq(irq, &spear_timer_irq);
}
void __init spear_setup_timer(resource_size_t base, int irq)
{
int ret;
const static struct of_device_id timer_of_match[] __initconst = {
{ .compatible = "st,spear-timer", },
{ },
};
if (!request_mem_region(base, SZ_1K, "gpt0")) {
pr_err("%s:cannot get IO addr\n", __func__);
void __init spear_setup_of_timer(void)
{
struct device_node *np;
int irq, ret;
np = of_find_matching_node(NULL, timer_of_match);
if (!np) {
pr_err("%s: No timer passed via DT\n", __func__);
return;
}
gpt_base = ioremap(base, SZ_1K);
irq = irq_of_parse_and_map(np, 0);
if (!irq) {
pr_err("%s: No irq passed for timer via DT\n", __func__);
return;
}
gpt_base = of_iomap(np, 0);
if (!gpt_base) {
pr_err("%s:ioremap failed for gpt\n", __func__);
goto err_mem;
pr_err("%s: of iomap failed\n", __func__);
return;
}
gpt_clk = clk_get_sys("gpt0", NULL);
@ -218,10 +233,10 @@ void __init spear_setup_timer(resource_size_t base, int irq)
goto err_iomap;
}
ret = clk_enable(gpt_clk);
ret = clk_prepare_enable(gpt_clk);
if (ret < 0) {
pr_err("%s:couldn't enable gpt clock\n", __func__);
goto err_clk;
pr_err("%s:couldn't prepare-enable gpt clock\n", __func__);
goto err_prepare_enable_clk;
}
spear_clockevent_init(irq);
@ -229,10 +244,8 @@ void __init spear_setup_timer(resource_size_t base, int irq)
return;
err_clk:
err_prepare_enable_clk:
clk_put(gpt_clk);
err_iomap:
iounmap(gpt_base);
err_mem:
release_mem_region(base, SZ_1K);
}

View File

@ -553,6 +553,7 @@ struct mv_host_priv {
#if defined(CONFIG_HAVE_CLK)
struct clk *clk;
struct clk **port_clks;
#endif
/*
* These consistent DMA memory pools give us guaranteed
@ -4027,6 +4028,9 @@ static int mv_platform_probe(struct platform_device *pdev)
struct resource *res;
int n_ports = 0;
int rc;
#if defined(CONFIG_HAVE_CLK)
int port;
#endif
ata_print_version_once(&pdev->dev, DRV_VERSION);
@ -4054,6 +4058,13 @@ static int mv_platform_probe(struct platform_device *pdev)
if (!host || !hpriv)
return -ENOMEM;
#if defined(CONFIG_HAVE_CLK)
hpriv->port_clks = devm_kzalloc(&pdev->dev,
sizeof(struct clk *) * n_ports,
GFP_KERNEL);
if (!hpriv->port_clks)
return -ENOMEM;
#endif
host->private_data = hpriv;
hpriv->n_ports = n_ports;
hpriv->board_idx = chip_soc;
@ -4066,9 +4077,17 @@ static int mv_platform_probe(struct platform_device *pdev)
#if defined(CONFIG_HAVE_CLK)
hpriv->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(hpriv->clk))
dev_notice(&pdev->dev, "cannot get clkdev\n");
dev_notice(&pdev->dev, "cannot get optional clkdev\n");
else
clk_enable(hpriv->clk);
clk_prepare_enable(hpriv->clk);
for (port = 0; port < n_ports; port++) {
char port_number[16];
sprintf(port_number, "%d", port);
hpriv->port_clks[port] = clk_get(&pdev->dev, port_number);
if (!IS_ERR(hpriv->port_clks[port]))
clk_prepare_enable(hpriv->port_clks[port]);
}
#endif
/*
@ -4098,9 +4117,15 @@ static int mv_platform_probe(struct platform_device *pdev)
err:
#if defined(CONFIG_HAVE_CLK)
if (!IS_ERR(hpriv->clk)) {
clk_disable(hpriv->clk);
clk_disable_unprepare(hpriv->clk);
clk_put(hpriv->clk);
}
for (port = 0; port < n_ports; port++) {
if (!IS_ERR(hpriv->port_clks[port])) {
clk_disable_unprepare(hpriv->port_clks[port]);
clk_put(hpriv->port_clks[port]);
}
}
#endif
return rc;
@ -4119,14 +4144,21 @@ static int __devexit mv_platform_remove(struct platform_device *pdev)
struct ata_host *host = platform_get_drvdata(pdev);
#if defined(CONFIG_HAVE_CLK)
struct mv_host_priv *hpriv = host->private_data;
int port;
#endif
ata_host_detach(host);
#if defined(CONFIG_HAVE_CLK)
if (!IS_ERR(hpriv->clk)) {
clk_disable(hpriv->clk);
clk_disable_unprepare(hpriv->clk);
clk_put(hpriv->clk);
}
for (port = 0; port < host->n_ports; port++) {
if (!IS_ERR(hpriv->port_clks[port])) {
clk_disable_unprepare(hpriv->port_clks[port]);
clk_put(hpriv->port_clks[port]);
}
}
#endif
return 0;
}

View File

@ -12,6 +12,7 @@ config HAVE_MACH_CLKDEV
config COMMON_CLK
bool
select HAVE_CLK_PREPARE
select CLKDEV_LOOKUP
---help---
The common clock framework is a single definition of struct
clk, useful across many platforms, as well as an
@ -22,17 +23,6 @@ config COMMON_CLK
menu "Common Clock Framework"
depends on COMMON_CLK
config COMMON_CLK_DISABLE_UNUSED
bool "Disabled unused clocks at boot"
depends on COMMON_CLK
---help---
Traverses the entire clock tree and disables any clocks that are
enabled in hardware but have not been enabled by any device drivers.
This saves power and keeps the software model of the clock in line
with reality.
If in doubt, say "N".
config COMMON_CLK_DEBUG
bool "DebugFS representation of clock tree"
depends on COMMON_CLK

View File

@ -1,4 +1,7 @@
obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o
obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \
clk-mux.o clk-divider.o
clk-mux.o clk-divider.o clk-fixed-factor.o
# SoCs specific
obj-$(CONFIG_ARCH_MXS) += mxs/
obj-$(CONFIG_PLAT_SPEAR) += spear/

View File

@ -45,7 +45,6 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
return parent_rate / div;
}
EXPORT_SYMBOL_GPL(clk_divider_recalc_rate);
/*
* The reverse of DIV_ROUND_UP: The maximum number which
@ -68,8 +67,8 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
if (divider->flags & CLK_DIVIDER_ONE_BASED)
maxdiv--;
if (!best_parent_rate) {
parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
parent_rate = *best_parent_rate;
bestdiv = DIV_ROUND_UP(parent_rate, rate);
bestdiv = bestdiv == 0 ? 1 : bestdiv;
bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
@ -109,24 +108,18 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
int div;
div = clk_divider_bestdiv(hw, rate, prate);
if (prate)
return *prate / div;
else {
unsigned long r;
r = __clk_get_rate(__clk_get_parent(hw->clk));
return r / div;
}
return *prate / div;
}
EXPORT_SYMBOL_GPL(clk_divider_round_rate);
static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate)
static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_divider *divider = to_clk_divider(hw);
unsigned int div;
unsigned long flags = 0;
u32 val;
div = __clk_get_rate(__clk_get_parent(hw->clk)) / rate;
div = parent_rate / rate;
if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
div--;
@ -147,15 +140,26 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate)
return 0;
}
EXPORT_SYMBOL_GPL(clk_divider_set_rate);
struct clk_ops clk_divider_ops = {
const struct clk_ops clk_divider_ops = {
.recalc_rate = clk_divider_recalc_rate,
.round_rate = clk_divider_round_rate,
.set_rate = clk_divider_set_rate,
};
EXPORT_SYMBOL_GPL(clk_divider_ops);
/**
* clk_register_divider - register a divider clock with the clock framework
* @dev: device registering this clock
* @name: name of this clock
* @parent_name: name of clock's parent
* @flags: framework-specific flags
* @reg: register address to adjust divider
* @shift: number of bits to shift the bitfield
* @width: width of the bitfield
* @clk_divider_flags: divider-specific flags for this clock
* @lock: shared register lock for this clock
*/
struct clk *clk_register_divider(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width,
@ -163,38 +167,34 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
{
struct clk_divider *div;
struct clk *clk;
struct clk_init_data init;
/* allocate the divider */
div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
if (!div) {
pr_err("%s: could not allocate divider clk\n", __func__);
return NULL;
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &clk_divider_ops;
init.flags = flags;
init.parent_names = (parent_name ? &parent_name: NULL);
init.num_parents = (parent_name ? 1 : 0);
/* struct clk_divider assignments */
div->reg = reg;
div->shift = shift;
div->width = width;
div->flags = clk_divider_flags;
div->lock = lock;
div->hw.init = &init;
if (parent_name) {
div->parent[0] = kstrdup(parent_name, GFP_KERNEL);
if (!div->parent[0])
goto out;
}
/* register the clock */
clk = clk_register(dev, &div->hw);
clk = clk_register(dev, name,
&clk_divider_ops, &div->hw,
div->parent,
(parent_name ? 1 : 0),
flags);
if (clk)
return clk;
if (IS_ERR(clk))
kfree(div);
out:
kfree(div->parent[0]);
kfree(div);
return NULL;
return clk;
}

View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
*
* 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.
*
* Standard functionality for the common clock API.
*/
#include <linux/module.h>
#include <linux/clk-provider.h>
#include <linux/slab.h>
#include <linux/err.h>
/*
* DOC: basic fixed multiplier and divider clock that cannot gate
*
* Traits of this clock:
* prepare - clk_prepare only ensures that parents are prepared
* enable - clk_enable only ensures that parents are enabled
* rate - rate is fixed. clk->rate = parent->rate / div * mult
* parent - fixed parent. No clk_set_parent support
*/
#define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw)
static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
return parent_rate * fix->mult / fix->div;
}
static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
unsigned long best_parent;
best_parent = (rate / fix->mult) * fix->div;
*prate = __clk_round_rate(__clk_get_parent(hw->clk),
best_parent);
}
return (*prate / fix->div) * fix->mult;
}
static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
return 0;
}
struct clk_ops clk_fixed_factor_ops = {
.round_rate = clk_factor_round_rate,
.set_rate = clk_factor_set_rate,
.recalc_rate = clk_factor_recalc_rate,
};
EXPORT_SYMBOL_GPL(clk_fixed_factor_ops);
struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
unsigned int mult, unsigned int div)
{
struct clk_fixed_factor *fix;
struct clk_init_data init;
struct clk *clk;
fix = kmalloc(sizeof(*fix), GFP_KERNEL);
if (!fix) {
pr_err("%s: could not allocate fixed factor clk\n", __func__);
return ERR_PTR(-ENOMEM);
}
/* struct clk_fixed_factor assignments */
fix->mult = mult;
fix->div = div;
fix->hw.init = &init;
init.name = name;
init.ops = &clk_fixed_factor_ops;
init.flags = flags;
init.parent_names = &parent_name;
init.num_parents = 1;
clk = clk_register(dev, &fix->hw);
if (IS_ERR(clk))
kfree(fix);
return clk;
}

View File

@ -32,51 +32,50 @@ static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw,
{
return to_clk_fixed_rate(hw)->fixed_rate;
}
EXPORT_SYMBOL_GPL(clk_fixed_rate_recalc_rate);
struct clk_ops clk_fixed_rate_ops = {
const struct clk_ops clk_fixed_rate_ops = {
.recalc_rate = clk_fixed_rate_recalc_rate,
};
EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
/**
* clk_register_fixed_rate - register fixed-rate clock with the clock framework
* @dev: device that is registering this clock
* @name: name of this clock
* @parent_name: name of clock's parent
* @flags: framework-specific flags
* @fixed_rate: non-adjustable clock rate
*/
struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
unsigned long fixed_rate)
{
struct clk_fixed_rate *fixed;
char **parent_names = NULL;
u8 len;
struct clk *clk;
struct clk_init_data init;
/* allocate fixed-rate clock */
fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
if (!fixed) {
pr_err("%s: could not allocate fixed clk\n", __func__);
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &clk_fixed_rate_ops;
init.flags = flags;
init.parent_names = (parent_name ? &parent_name: NULL);
init.num_parents = (parent_name ? 1 : 0);
/* struct clk_fixed_rate assignments */
fixed->fixed_rate = fixed_rate;
fixed->hw.init = &init;
if (parent_name) {
parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
/* register the clock */
clk = clk_register(dev, &fixed->hw);
if (! parent_names)
goto out;
if (IS_ERR(clk))
kfree(fixed);
len = sizeof(char) * strlen(parent_name);
parent_names[0] = kmalloc(len, GFP_KERNEL);
if (!parent_names[0])
goto out;
strncpy(parent_names[0], parent_name, len);
}
out:
return clk_register(dev, name,
&clk_fixed_rate_ops, &fixed->hw,
parent_names,
(parent_name ? 1 : 0),
flags);
return clk;
}

Some files were not shown because too many files have changed in this diff Show More