[PATCH v3 2/9] ARM: S5PV210: Add clock support for S5PV210
Kukjin Kim
kgene.kim at samsung.com
Thu Jan 21 19:17:04 EST 2010
This patch adds clock support for S5PV210. This patch adds the clock
register definitions and the various system clocks in S5PV210.
Clocks that are common to other S5P SoC'c are added in the common
S5P clock support.
Signed-off-by: Kukjin Kim <kgene.kim at samsung.com>
---
arch/arm/mach-s5pv210/include/mach/regs-clock.h | 169 +++++++++
arch/arm/mach-s5pv210/s5pv210-clock.c | 454 +++++++++++++++++++++++
arch/arm/plat-s5p/clock.c | 17 +-
arch/arm/plat-s5p/include/plat/s5p-clock.h | 2 +
4 files changed, 640 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/mach-s5pv210/include/mach/regs-clock.h
create mode 100755 arch/arm/mach-s5pv210/s5pv210-clock.c
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
new file mode 100644
index 0000000..3a6536f
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
@@ -0,0 +1,169 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5PV210 - Clock register definitions
+ *
+ * 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.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_CLKREG(x) (S5P_VA_SYSCON + (x))
+
+#define S5P_APLL_LOCK S5P_CLKREG(0x00)
+#define S5P_MPLL_LOCK S5P_CLKREG(0x08)
+#define S5P_EPLL_LOCK S5P_CLKREG(0x10)
+#define S5P_VPLL_LOCK S5P_CLKREG(0x20)
+
+#define S5P_APLL_CON S5P_CLKREG(0x100)
+#define S5P_MPLL_CON S5P_CLKREG(0x108)
+#define S5P_EPLL_CON S5P_CLKREG(0x110)
+#define S5P_VPLL_CON S5P_CLKREG(0x120)
+
+#define S5P_CLK_SRC0 S5P_CLKREG(0x200)
+#define S5P_CLK_SRC1 S5P_CLKREG(0x204)
+#define S5P_CLK_SRC2 S5P_CLKREG(0x208)
+#define S5P_CLK_SRC3 S5P_CLKREG(0x20C)
+#define S5P_CLK_SRC4 S5P_CLKREG(0x210)
+#define S5P_CLK_SRC5 S5P_CLKREG(0x214)
+#define S5P_CLK_SRC6 S5P_CLKREG(0x218)
+
+#define S5P_CLK_SRC_MASK0 S5P_CLKREG(0x280)
+#define S5P_CLK_SRC_MASK1 S5P_CLKREG(0x284)
+
+#define S5P_CLK_DIV0 S5P_CLKREG(0x300)
+#define S5P_CLK_DIV1 S5P_CLKREG(0x304)
+#define S5P_CLK_DIV2 S5P_CLKREG(0x308)
+#define S5P_CLK_DIV3 S5P_CLKREG(0x30C)
+#define S5P_CLK_DIV4 S5P_CLKREG(0x310)
+#define S5P_CLK_DIV5 S5P_CLKREG(0x314)
+#define S5P_CLK_DIV6 S5P_CLKREG(0x318)
+#define S5P_CLK_DIV7 S5P_CLKREG(0x31C)
+
+#define S5P_CLKGATE_MAIN0 S5P_CLKREG(0x400)
+#define S5P_CLKGATE_MAIN1 S5P_CLKREG(0x404)
+#define S5P_CLKGATE_MAIN2 S5P_CLKREG(0x408)
+
+#define S5P_CLKGATE_PERI0 S5P_CLKREG(0x420)
+#define S5P_CLKGATE_PERI1 S5P_CLKREG(0x424)
+
+#define S5P_CLKGATE_SCLK0 S5P_CLKREG(0x440)
+#define S5P_CLKGATE_SCLK1 S5P_CLKREG(0x444)
+#define S5P_CLKGATE_IP0 S5P_CLKREG(0x460)
+#define S5P_CLKGATE_IP1 S5P_CLKREG(0x464)
+#define S5P_CLKGATE_IP2 S5P_CLKREG(0x468)
+#define S5P_CLKGATE_IP3 S5P_CLKREG(0x46C)
+#define S5P_CLKGATE_IP4 S5P_CLKREG(0x470)
+
+#define S5P_CLKGATE_BLOCK S5P_CLKREG(0x480)
+#define S5P_CLKGATE_BUS0 S5P_CLKREG(0x484)
+#define S5P_CLKGATE_BUS1 S5P_CLKREG(0x488)
+#define S5P_CLK_OUT S5P_CLKREG(0x500)
+
+/* CLKSRC0 */
+#define S5P_CLKSRC0_MUX200_MASK (0x1<<16)
+#define S5P_CLKSRC0_MUX166_MASK (0x1<<20)
+#define S5P_CLKSRC0_MUX133_MASK (0x1<<24)
+
+/* CLKDIV0 */
+#define S5P_CLKDIV0_APLL_SHIFT (0)
+#define S5P_CLKDIV0_APLL_MASK (0x7 << S5P_CLKDIV0_APLL_SHIFT)
+#define S5P_CLKDIV0_A2M_SHIFT (4)
+#define S5P_CLKDIV0_A2M_MASK (0x7 << S5P_CLKDIV0_A2M_SHIFT)
+#define S5P_CLKDIV0_HCLK200_SHIFT (8)
+#define S5P_CLKDIV0_HCLK200_MASK (0x7 << S5P_CLKDIV0_HCLK200_SHIFT)
+#define S5P_CLKDIV0_PCLK100_SHIFT (12)
+#define S5P_CLKDIV0_PCLK100_MASK (0x7 << S5P_CLKDIV0_PCLK100_SHIFT)
+#define S5P_CLKDIV0_HCLK166_SHIFT (16)
+#define S5P_CLKDIV0_HCLK166_MASK (0xF << S5P_CLKDIV0_HCLK166_SHIFT)
+#define S5P_CLKDIV0_PCLK83_SHIFT (20)
+#define S5P_CLKDIV0_PCLK83_MASK (0x7 << S5P_CLKDIV0_PCLK83_SHIFT)
+#define S5P_CLKDIV0_HCLK133_SHIFT (24)
+#define S5P_CLKDIV0_HCLK133_MASK (0xF << S5P_CLKDIV0_HCLK133_SHIFT)
+#define S5P_CLKDIV0_PCLK66_SHIFT (28)
+#define S5P_CLKDIV0_PCLK66_MASK (0x7 << S5P_CLKDIV0_PCLK66_SHIFT)
+
+/* Registers related to power management */
+#define S5P_PWR_CFG S5P_CLKREG(0xC000)
+#define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0xC004)
+#define S5P_WAKEUP_MASK S5P_CLKREG(0xC008)
+#define S5P_PWR_MODE S5P_CLKREG(0xC00C)
+#define S5P_NORMAL_CFG S5P_CLKREG(0xC010)
+#define S5P_IDLE_CFG S5P_CLKREG(0xC020)
+#define S5P_STOP_CFG S5P_CLKREG(0xC030)
+#define S5P_STOP_MEM_CFG S5P_CLKREG(0xC034)
+#define S5P_SLEEP_CFG S5P_CLKREG(0xC040)
+
+#define S5P_OSC_FREQ S5P_CLKREG(0xC100)
+#define S5P_OSC_STABLE S5P_CLKREG(0xC104)
+#define S5P_PWR_STABLE S5P_CLKREG(0xC108)
+#define S5P_MTC_STABLE S5P_CLKREG(0xC110)
+#define S5P_CLAMP_STABLE S5P_CLKREG(0xC114)
+
+#define S5P_WAKEUP_STAT S5P_CLKREG(0xC200)
+#define S5P_BLK_PWR_STAT S5P_CLKREG(0xC204)
+
+#define S5P_OTHERS S5P_CLKREG(0xE000)
+#define S5P_OM_STAT S5P_CLKREG(0xE100)
+#define S5P_USB_PHY_CONTROL S5P_CLKREG(0xE80C)
+#define S5P_DAC_CONTROL S5P_CLKREG(0xE810)
+
+#define S5P_INFORM0 S5P_CLKREG(0xF000)
+#define S5P_INFORM1 S5P_CLKREG(0xF004)
+#define S5P_INFORM2 S5P_CLKREG(0xF008)
+#define S5P_INFORM3 S5P_CLKREG(0xF00C)
+#define S5P_INFORM4 S5P_CLKREG(0xF010)
+#define S5P_INFORM5 S5P_CLKREG(0xF014)
+#define S5P_INFORM6 S5P_CLKREG(0xF018)
+#define S5P_INFORM7 S5P_CLKREG(0xF01C)
+
+#define S5P_RST_STAT S5P_CLKREG(0xA000)
+#define S5P_OSC_CON S5P_CLKREG(0x8000)
+#define S5P_MIPI_PHY_CON0 S5P_CLKREG(0x7200)
+#define S5P_MIPI_PHY_CON1 S5P_CLKREG(0x7204)
+#define S5P_MIPI_CONTROL S5P_CLKREG(0xE814)
+
+#define S5P_IDLE_CFG_TL_MASK (3 << 30)
+#define S5P_IDLE_CFG_TM_MASK (3 << 28)
+#define S5P_IDLE_CFG_TL_ON (2 << 30)
+#define S5P_IDLE_CFG_TM_ON (2 << 28)
+#define S5P_IDLE_CFG_DIDLE (1 << 0)
+
+#define S5P_CFG_WFI_CLEAN (~(3 << 8))
+#define S5P_CFG_WFI_IDLE (1 << 8)
+#define S5P_CFG_WFI_STOP (2 << 8)
+#define S5P_CFG_WFI_SLEEP (3 << 8)
+
+#define S5P_OTHER_SYS_INT 24
+#define S5P_OTHER_STA_TYPE 23
+#define S5P_OTHER_SYSC_INTOFF (1 << 0)
+#define STA_TYPE_EXPON 0
+#define STA_TYPE_SFR 1
+
+#define S5P_PWR_STA_EXP_SCALE 0
+#define S5P_PWR_STA_CNT 4
+
+#define S5P_PWR_STABLE_COUNT 85500
+
+#define S5P_SLEEP_CFG_OSC_EN (1 << 0)
+#define S5P_SLEEP_CFG_USBOSC_EN (1 << 1)
+
+/* OTHERS Resgister */
+#define S5P_OTHERS_USB_SIG_MASK (1 << 16)
+#define S5P_OTHERS_MIPI_DPHY_EN (1 << 28)
+
+/* MIPI */
+#define S5P_MIPI_DPHY_EN (3)
+
+/* S5P_DAC_CONTROL */
+#define S5P_DAC_ENABLE (1)
+#define S5P_DAC_DISABLE (0)
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5pv210/s5pv210-clock.c b/arch/arm/mach-s5pv210/s5pv210-clock.c
new file mode 100755
index 0000000..8d51a10
--- /dev/null
+++ b/arch/arm/mach-s5pv210/s5pv210-clock.c
@@ -0,0 +1,454 @@
+/* linux/arch/arm/mach-s5pv210/s5pv210-clock.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5PV210 - Clock support
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+
+#include <plat/cpu-freq.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5pv210.h>
+
+static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);
+}
+
+static int s5pv210_clk_ip1_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP1, clk, enable);
+}
+
+static int s5pv210_clk_ip2_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP2, clk, enable);
+}
+
+static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
+}
+
+static struct clk clk_h200 = {
+ .name = "hclk200",
+ .id = -1,
+};
+
+static struct clk clk_h100 = {
+ .name = "hclk100",
+ .id = -1,
+};
+
+static struct clk clk_h166 = {
+ .name = "hclk166",
+ .id = -1,
+};
+
+static struct clk clk_h133 = {
+ .name = "hclk133",
+ .id = -1,
+};
+
+static struct clk clk_p100 = {
+ .name = "pclk100",
+ .id = -1,
+};
+
+static struct clk clk_p83 = {
+ .name = "pclk83",
+ .id = -1,
+};
+
+static struct clk clk_p66 = {
+ .name = "pclk66",
+ .id = -1,
+};
+
+static struct clk *sys_clks[] = {
+ &clk_h200,
+ &clk_h100,
+ &clk_h166,
+ &clk_h133,
+ &clk_p100,
+ &clk_p83,
+ &clk_p66
+};
+
+static struct clk init_clocks_disable[] = {
+ {
+ .name = "rot",
+ .id = -1,
+ .parent = &clk_h166,
+ .enable = s5pv210_clk_ip0_ctrl,
+ .ctrlbit = (1<<29),
+ }, {
+ .name = "otg",
+ .id = -1,
+ .parent = &clk_h133,
+ .enable = s5pv210_clk_ip1_ctrl,
+ .ctrlbit = (1<<16),
+ }, {
+ .name = "usb-host",
+ .id = -1,
+ .parent = &clk_h133,
+ .enable = s5pv210_clk_ip1_ctrl,
+ .ctrlbit = (1<<17),
+ }, {
+ .name = "lcd",
+ .id = -1,
+ .parent = &clk_h166,
+ .enable = s5pv210_clk_ip1_ctrl,
+ .ctrlbit = (1<<0),
+ }, {
+ .name = "cfcon",
+ .id = 0,
+ .parent = &clk_h133,
+ .enable = s5pv210_clk_ip1_ctrl,
+ .ctrlbit = (1<<25),
+ }, {
+ .name = "hsmmc",
+ .id = 0,
+ .parent = &clk_h133,
+ .enable = s5pv210_clk_ip2_ctrl,
+ .ctrlbit = (1<<16),
+ }, {
+ .name = "hsmmc",
+ .id = 1,
+ .parent = &clk_h133,
+ .enable = s5pv210_clk_ip2_ctrl,
+ .ctrlbit = (1<<17),
+ }, {
+ .name = "hsmmc",
+ .id = 2,
+ .parent = &clk_h133,
+ .enable = s5pv210_clk_ip2_ctrl,
+ .ctrlbit = (1<<18),
+ }, {
+ .name = "hsmmc",
+ .id = 3,
+ .parent = &clk_h133,
+ .enable = s5pv210_clk_ip2_ctrl,
+ .ctrlbit = (1<<19),
+ }, {
+ .name = "systimer",
+ .id = -1,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<16),
+ }, {
+ .name = "watchdog",
+ .id = -1,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<22),
+ }, {
+ .name = "rtc",
+ .id = -1,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<15),
+ }, {
+ .name = "i2c",
+ .id = 0,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<7),
+ }, {
+ .name = "i2c",
+ .id = 1,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<8),
+ }, {
+ .name = "i2c",
+ .id = 2,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<9),
+ }, {
+ .name = "spi",
+ .id = 0,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<12),
+ }, {
+ .name = "spi",
+ .id = 1,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<13),
+ }, {
+ .name = "spi",
+ .id = 2,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<14),
+ }, {
+ .name = "timers",
+ .id = -1,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<23),
+ }, {
+ .name = "adc",
+ .id = -1,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<24),
+ }, {
+ .name = "keypad",
+ .id = -1,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<21),
+ }, {
+ .name = "i2s_v50",
+ .id = 0,
+ .parent = &clk_p,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<4),
+ }, {
+ .name = "i2s_v32",
+ .id = 0,
+ .parent = &clk_p,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<4),
+ }, {
+ .name = "i2s_v32",
+ .id = 1,
+ .parent = &clk_p,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<4),
+ }
+};
+
+static struct clk init_clocks[] = {
+ {
+ .name = "uart",
+ .id = 0,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<7),
+ }, {
+ .name = "uart",
+ .id = 1,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<8),
+ }, {
+ .name = "uart",
+ .id = 2,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<9),
+ }, {
+ .name = "uart",
+ .id = 3,
+ .parent = &clk_p66,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<10),
+ },
+};
+
+static struct clksrc_clk clk_mout_apll = {
+ .clk = {
+ .name = "mout_apll",
+ .id = -1,
+ },
+ .sources = &clk_src_apll,
+ .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
+};
+
+static struct clksrc_clk clk_mout_epll = {
+ .clk = {
+ .name = "mout_epll",
+ .id = -1,
+ },
+ .sources = &clk_src_epll,
+ .reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
+};
+
+static struct clksrc_clk clk_mout_mpll = {
+ .clk = {
+ .name = "mout_mpll",
+ .id = -1,
+ },
+ .sources = &clk_src_mpll,
+ .reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_uart_list[] = {
+ [6] = &clk_mout_mpll.clk,
+ [7] = &clk_mout_epll.clk,
+};
+
+static struct clksrc_sources clkset_uart = {
+ .sources = clkset_uart_list,
+ .nr_sources = ARRAY_SIZE(clkset_uart_list),
+};
+
+static struct clksrc_clk clksrcs[] = {
+ {
+ .clk = {
+ .name = "uclk1",
+ .id = -1,
+ .ctrlbit = (1<<17),
+ .enable = s5pv210_clk_ip3_ctrl,
+ },
+ .sources = &clkset_uart,
+ .reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
+ .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
+ }
+};
+
+/* Clock initialisation code */
+static struct clksrc_clk *init_parents[] = {
+ &clk_mout_apll,
+ &clk_mout_epll,
+ &clk_mout_mpll,
+};
+
+#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
+
+void __init_or_cpufreq s5pv210_setup_clocks(void)
+{
+ struct clk *xtal_clk;
+ unsigned long xtal;
+ unsigned long armclk;
+ unsigned long hclk200;
+ unsigned long hclk166;
+ unsigned long hclk133;
+ unsigned long pclk100;
+ unsigned long pclk83;
+ unsigned long pclk66;
+ unsigned long apll;
+ unsigned long mpll;
+ unsigned long epll;
+ unsigned int ptr;
+ u32 clkdiv0, clkdiv1;
+
+ printk(KERN_DEBUG "%s: registering clocks\n", __func__);
+
+ clkdiv0 = __raw_readl(S5P_CLK_DIV0);
+ clkdiv1 = __raw_readl(S5P_CLK_DIV1);
+
+ printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
+ __func__, clkdiv0, clkdiv1);
+
+ xtal_clk = clk_get(NULL, "xtal");
+ BUG_ON(IS_ERR(xtal_clk));
+
+ xtal = clk_get_rate(xtal_clk);
+ clk_put(xtal_clk);
+
+ printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
+
+ apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
+ mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
+ epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500);
+
+ printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld",
+ apll, mpll, epll);
+
+ armclk = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_APLL);
+ if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX200_MASK)
+ hclk200 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200);
+ else
+ hclk200 = armclk / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200);
+
+ if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX166_MASK) {
+ hclk166 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M);
+ hclk166 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166);
+ } else
+ hclk166 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166);
+
+ if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX133_MASK) {
+ hclk133 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M);
+ hclk133 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133);
+ } else
+ hclk133 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133);
+
+ pclk100 = hclk200 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK100);
+ pclk83 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK83);
+ pclk66 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66);
+
+ printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld, \
+ HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
+ armclk, hclk200, hclk166, hclk133, pclk100, pclk83, pclk66);
+
+ clk_fout_apll.rate = apll;
+ clk_fout_mpll.rate = mpll;
+ clk_fout_epll.rate = epll;
+
+ clk_f.rate = armclk;
+ clk_h.rate = hclk133;
+ clk_p.rate = pclk66;
+ clk_p66.rate = pclk66;
+ clk_p83.rate = pclk83;
+ clk_h133.rate = hclk133;
+ clk_h166.rate = hclk166;
+ clk_h200.rate = hclk200;
+
+ for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
+ s3c_set_clksrc(init_parents[ptr], true);
+
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+ s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks[] __initdata = {
+ &clk_mout_epll.clk,
+ &clk_mout_mpll.clk,
+};
+
+void __init s5pv210_register_clocks(void)
+{
+ struct clk *clkp;
+ int ret;
+ int ptr;
+
+ ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+ if (ret > 0)
+ printk(KERN_ERR "Failed to register %u clocks\n", ret);
+
+ s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+ s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+ ret = s3c24xx_register_clocks(sys_clks, ARRAY_SIZE(sys_clks));
+ if (ret > 0)
+ printk(KERN_ERR "Failed to register system clocks\n");
+
+ clkp = init_clocks_disable;
+ for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+ ret = s3c24xx_register_clock(clkp);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register clock %s (%d)\n",
+ clkp->name, ret);
+ }
+ (clkp->enable)(clkp, 0);
+ }
+
+ s3c_pwmclk_init();
+}
diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c
index 3d3c0f1..7ceb1c9 100644
--- a/arch/arm/plat-s5p/clock.c
+++ b/arch/arm/plat-s5p/clock.c
@@ -33,8 +33,14 @@ struct clk clk_ext_xtal_mux = {
.id = -1,
};
+static struct clk s5p_clk_27m = {
+ .name = "clk_27m",
+ .id = -1,
+ .rate = 27000000,
+};
+
/* 48MHz USB Phy clock output */
-struct clk clk_48m = {
+static struct clk s5p_clk_48m = {
.name = "clk_48m",
.id = -1,
.rate = 48000000,
@@ -104,6 +110,11 @@ struct clksrc_sources clk_src_epll = {
.nr_sources = ARRAY_SIZE(clk_src_epll_list),
};
+struct clk clk_vpll = {
+ .name = "vpll",
+ .id = -1,
+};
+
int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable)
{
unsigned int ctrlbit = clk->ctrlbit;
@@ -117,11 +128,13 @@ int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable)
static struct clk *s5p_clks[] __initdata = {
&clk_ext_xtal_mux,
- &clk_48m,
+ &s5p_clk_48m,
+ &s5p_clk_27m,
&clk_fout_apll,
&clk_fout_mpll,
&clk_fout_epll,
&clk_arm,
+ &clk_vpll,
};
void __init s5p_register_clocks(unsigned long xtal_freq)
diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h
index e1a7444..56fb8b4 100644
--- a/arch/arm/plat-s5p/include/plat/s5p-clock.h
+++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h
@@ -20,6 +20,7 @@
#define clk_fin_apll clk_ext_xtal_mux
#define clk_fin_mpll clk_ext_xtal_mux
#define clk_fin_epll clk_ext_xtal_mux
+#define clk_fin_vpll clk_ext_xtal_mux
extern struct clk clk_ext_xtal_mux;
extern struct clk clk_48m;
@@ -27,6 +28,7 @@ extern struct clk clk_fout_apll;
extern struct clk clk_fout_mpll;
extern struct clk clk_fout_epll;
extern struct clk clk_arm;
+extern struct clk clk_vpll;
extern struct clksrc_sources clk_src_apll;
extern struct clksrc_sources clk_src_mpll;
--
1.6.2.5
More information about the linux-arm-kernel
mailing list