2012-10-01 12:09:36

by Chander Kashyap

[permalink] [raw]
Subject: [PATCH 0/2] ARM: Exynos4: Migrate to common clock framework.

From: Thomas Abraham <[email protected]>

This patch series migrates Exynos4 clock support to common clock framework.
The first patch in this series removes the existing Exynos4 clock support
that uses the Samsung specific clock framework. The second patch in this
series add Exynos4 clock support using common clock framework.

Thomas Abraham (2):
ARM: Exynos4: Remove Samsung clock type support
ARM: Exynos4: Register clocks via common clock framework

arch/arm/mach-exynos/Kconfig | 1 +
arch/arm/mach-exynos/Makefile | 3 -
arch/arm/mach-exynos/clock-exynos4.c | 1572 ----------------------------
arch/arm/mach-exynos/clock-exynos4.h | 35 -
arch/arm/mach-exynos/clock-exynos4210.c | 188 ----
arch/arm/mach-exynos/clock-exynos4212.c | 192 ----
arch/arm/mach-exynos/common.c | 18 +-
arch/arm/mach-exynos/common.h | 3 +
arch/arm/mach-exynos/mach-armlex4210.c | 1 -
arch/arm/mach-exynos/mach-exynos4-dt.c | 1 -
arch/arm/mach-exynos/mach-nuri.c | 1 -
arch/arm/mach-exynos/mach-origen.c | 1 -
arch/arm/mach-exynos/mach-smdk4x12.c | 1 -
arch/arm/mach-exynos/mach-smdkv310.c | 1 -
arch/arm/mach-exynos/mach-universal_c210.c | 1 -
arch/arm/mach-exynos/mct.c | 11 +-
arch/arm/plat-samsung/Kconfig | 4 +-
drivers/clk/Makefile | 1 +
drivers/clk/clk.c | 12 +-
drivers/clk/samsung/Makefile | 6 +
drivers/clk/samsung/clk-exynos4.c | 585 +++++++++++
drivers/clk/samsung/clk.c | 231 ++++
drivers/clk/samsung/clk.h | 190 ++++
23 files changed, 1043 insertions(+), 2016 deletions(-)
delete mode 100644 arch/arm/mach-exynos/clock-exynos4.c
delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c
create mode 100644 drivers/clk/samsung/Makefile
create mode 100644 drivers/clk/samsung/clk-exynos4.c
create mode 100644 drivers/clk/samsung/clk.c
create mode 100644 drivers/clk/samsung/clk.h


2012-10-01 12:09:43

by Chander Kashyap

[permalink] [raw]
Subject: [PATCH 1/2] ARM: Exynos4: Remove Samsung clock type support

From: Thomas Abraham <[email protected]>

In preparation to migrate Exynos4 based platforms to commom clock framework,
remove the support for Samsung type clock support.

Cc: Kukjin Kim <[email protected]>
Signed-off-by: Thomas Abraham <[email protected]>
---
arch/arm/mach-exynos/Makefile | 3 -
arch/arm/mach-exynos/clock-exynos4.c | 1572 ----------------------------
arch/arm/mach-exynos/clock-exynos4.h | 35 -
arch/arm/mach-exynos/clock-exynos4210.c | 188 ----
arch/arm/mach-exynos/clock-exynos4212.c | 192 ----
arch/arm/mach-exynos/common.c | 18 +-
arch/arm/mach-exynos/mach-armlex4210.c | 1 -
arch/arm/mach-exynos/mach-exynos4-dt.c | 1 -
arch/arm/mach-exynos/mach-nuri.c | 1 -
arch/arm/mach-exynos/mach-origen.c | 1 -
arch/arm/mach-exynos/mach-smdk4x12.c | 1 -
arch/arm/mach-exynos/mach-smdkv310.c | 1 -
arch/arm/mach-exynos/mach-universal_c210.c | 1 -
13 files changed, 6 insertions(+), 2009 deletions(-)
delete mode 100644 arch/arm/mach-exynos/clock-exynos4.c
delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c

diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 9b58024..ad66c9f 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -13,10 +13,7 @@ obj- :=
# Core

obj-$(CONFIG_ARCH_EXYNOS) += common.o
-obj-$(CONFIG_ARCH_EXYNOS4) += clock-exynos4.o
obj-$(CONFIG_ARCH_EXYNOS5) += clock-exynos5.o
-obj-$(CONFIG_CPU_EXYNOS4210) += clock-exynos4210.o
-obj-$(CONFIG_SOC_EXYNOS4212) += clock-exynos4212.o

obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
deleted file mode 100644
index 2f51293..0000000
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ /dev/null
@@ -1,1572 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS4 - 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/kernel.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.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/pm.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4_clock_save[] = {
- SAVE_ITEM(EXYNOS4_CLKDIV_LEFTBUS),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_LEFTBUS),
- SAVE_ITEM(EXYNOS4_CLKDIV_RIGHTBUS),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_RIGHTBUS),
- SAVE_ITEM(EXYNOS4_CLKSRC_TOP0),
- SAVE_ITEM(EXYNOS4_CLKSRC_TOP1),
- SAVE_ITEM(EXYNOS4_CLKSRC_CAM),
- SAVE_ITEM(EXYNOS4_CLKSRC_TV),
- SAVE_ITEM(EXYNOS4_CLKSRC_MFC),
- SAVE_ITEM(EXYNOS4_CLKSRC_G3D),
- SAVE_ITEM(EXYNOS4_CLKSRC_LCD0),
- SAVE_ITEM(EXYNOS4_CLKSRC_MAUDIO),
- SAVE_ITEM(EXYNOS4_CLKSRC_FSYS),
- SAVE_ITEM(EXYNOS4_CLKSRC_PERIL0),
- SAVE_ITEM(EXYNOS4_CLKSRC_PERIL1),
- SAVE_ITEM(EXYNOS4_CLKDIV_CAM),
- SAVE_ITEM(EXYNOS4_CLKDIV_TV),
- SAVE_ITEM(EXYNOS4_CLKDIV_MFC),
- SAVE_ITEM(EXYNOS4_CLKDIV_G3D),
- SAVE_ITEM(EXYNOS4_CLKDIV_LCD0),
- SAVE_ITEM(EXYNOS4_CLKDIV_MAUDIO),
- SAVE_ITEM(EXYNOS4_CLKDIV_FSYS0),
- SAVE_ITEM(EXYNOS4_CLKDIV_FSYS1),
- SAVE_ITEM(EXYNOS4_CLKDIV_FSYS2),
- SAVE_ITEM(EXYNOS4_CLKDIV_FSYS3),
- SAVE_ITEM(EXYNOS4_CLKDIV_PERIL0),
- SAVE_ITEM(EXYNOS4_CLKDIV_PERIL1),
- SAVE_ITEM(EXYNOS4_CLKDIV_PERIL2),
- SAVE_ITEM(EXYNOS4_CLKDIV_PERIL3),
- SAVE_ITEM(EXYNOS4_CLKDIV_PERIL4),
- SAVE_ITEM(EXYNOS4_CLKDIV_PERIL5),
- SAVE_ITEM(EXYNOS4_CLKDIV_TOP),
- SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TOP),
- SAVE_ITEM(EXYNOS4_CLKSRC_MASK_CAM),
- SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TV),
- SAVE_ITEM(EXYNOS4_CLKSRC_MASK_LCD0),
- SAVE_ITEM(EXYNOS4_CLKSRC_MASK_MAUDIO),
- SAVE_ITEM(EXYNOS4_CLKSRC_MASK_FSYS),
- SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL0),
- SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL1),
- SAVE_ITEM(EXYNOS4_CLKDIV2_RATIO),
- SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCAM),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_CAM),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_TV),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_MFC),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_G3D),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_LCD0),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_FSYS),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_GPS),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_PERIL),
- SAVE_ITEM(EXYNOS4_CLKGATE_BLOCK),
- SAVE_ITEM(EXYNOS4_CLKSRC_MASK_DMC),
- SAVE_ITEM(EXYNOS4_CLKSRC_DMC),
- SAVE_ITEM(EXYNOS4_CLKDIV_DMC0),
- SAVE_ITEM(EXYNOS4_CLKDIV_DMC1),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_DMC),
- SAVE_ITEM(EXYNOS4_CLKSRC_CPU),
- SAVE_ITEM(EXYNOS4_CLKDIV_CPU),
- SAVE_ITEM(EXYNOS4_CLKDIV_CPU + 0x4),
- SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCPU),
- SAVE_ITEM(EXYNOS4_CLKGATE_IP_CPU),
-};
-#endif
-
-static struct clk exynos4_clk_sclk_hdmi27m = {
- .name = "sclk_hdmi27m",
- .rate = 27000000,
-};
-
-static struct clk exynos4_clk_sclk_hdmiphy = {
- .name = "sclk_hdmiphy",
-};
-
-static struct clk exynos4_clk_sclk_usbphy0 = {
- .name = "sclk_usbphy0",
- .rate = 27000000,
-};
-
-static struct clk exynos4_clk_sclk_usbphy1 = {
- .name = "sclk_usbphy1",
-};
-
-static struct clk dummy_apb_pclk = {
- .name = "apb_pclk",
- .id = -1,
-};
-
-static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TOP, clk, enable);
-}
-
-static int exynos4_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_CAM, clk, enable);
-}
-
-static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_LCD0, clk, enable);
-}
-
-int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_FSYS, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL0, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL1, clk, enable);
-}
-
-static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKGATE_IP_MFC, clk, enable);
-}
-
-static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TV, clk, enable);
-}
-
-static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKGATE_IP_CAM, clk, enable);
-}
-
-static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable);
-}
-
-int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable);
-}
-
-static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKGATE_IP_LCD0, clk, enable);
-}
-
-int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4210_CLKGATE_IP_LCD1, clk, enable);
-}
-
-int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKGATE_IP_FSYS, clk, enable);
-}
-
-static int exynos4_clk_ip_peril_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIL, clk, enable);
-}
-
-static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable);
-}
-
-int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKGATE_IP_DMC, clk, enable);
-}
-
-static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
-}
-
-static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
-}
-
-/* Core list of CMU_CPU side */
-
-static struct clksrc_clk exynos4_clk_mout_apll = {
- .clk = {
- .name = "mout_apll",
- },
- .sources = &clk_src_apll,
- .reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_apll = {
- .clk = {
- .name = "sclk_apll",
- .parent = &exynos4_clk_mout_apll.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_mout_epll = {
- .clk = {
- .name = "mout_epll",
- },
- .sources = &clk_src_epll,
- .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 4, .size = 1 },
-};
-
-struct clksrc_clk exynos4_clk_mout_mpll = {
- .clk = {
- .name = "mout_mpll",
- },
- .sources = &clk_src_mpll,
-
- /* reg_src will be added in each SoCs' clock */
-};
-
-static struct clk *exynos4_clkset_moutcore_list[] = {
- [0] = &exynos4_clk_mout_apll.clk,
- [1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_moutcore = {
- .sources = exynos4_clkset_moutcore_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_moutcore_list),
-};
-
-static struct clksrc_clk exynos4_clk_moutcore = {
- .clk = {
- .name = "moutcore",
- },
- .sources = &exynos4_clkset_moutcore,
- .reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_coreclk = {
- .clk = {
- .name = "core_clk",
- .parent = &exynos4_clk_moutcore.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_armclk = {
- .clk = {
- .name = "armclk",
- .parent = &exynos4_clk_coreclk.clk,
- },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem0 = {
- .clk = {
- .name = "aclk_corem0",
- .parent = &exynos4_clk_coreclk.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cores = {
- .clk = {
- .name = "aclk_cores",
- .parent = &exynos4_clk_coreclk.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem1 = {
- .clk = {
- .name = "aclk_corem1",
- .parent = &exynos4_clk_coreclk.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_periphclk = {
- .clk = {
- .name = "periphclk",
- .parent = &exynos4_clk_coreclk.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 12, .size = 3 },
-};
-
-/* Core list of CMU_CORE side */
-
-static struct clk *exynos4_clkset_corebus_list[] = {
- [0] = &exynos4_clk_mout_mpll.clk,
- [1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_corebus = {
- .sources = exynos4_clkset_corebus_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_corebus_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_corebus = {
- .clk = {
- .name = "mout_corebus",
- },
- .sources = &exynos4_clkset_mout_corebus,
- .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dmc = {
- .clk = {
- .name = "sclk_dmc",
- .parent = &exynos4_clk_mout_corebus.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cored = {
- .clk = {
- .name = "aclk_cored",
- .parent = &exynos4_clk_sclk_dmc.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corep = {
- .clk = {
- .name = "aclk_corep",
- .parent = &exynos4_clk_aclk_cored.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_acp = {
- .clk = {
- .name = "aclk_acp",
- .parent = &exynos4_clk_mout_corebus.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_pclk_acp = {
- .clk = {
- .name = "pclk_acp",
- .parent = &exynos4_clk_aclk_acp.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 4, .size = 3 },
-};
-
-/* Core list of CMU_TOP side */
-
-struct clk *exynos4_clkset_aclk_top_list[] = {
- [0] = &exynos4_clk_mout_mpll.clk,
- [1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_aclk = {
- .sources = exynos4_clkset_aclk_top_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_aclk_top_list),
-};
-
-static struct clksrc_clk exynos4_clk_aclk_200 = {
- .clk = {
- .name = "aclk_200",
- },
- .sources = &exynos4_clkset_aclk,
- .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 12, .size = 1 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_100 = {
- .clk = {
- .name = "aclk_100",
- },
- .sources = &exynos4_clkset_aclk,
- .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 16, .size = 1 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_160 = {
- .clk = {
- .name = "aclk_160",
- },
- .sources = &exynos4_clkset_aclk,
- .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 20, .size = 1 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 8, .size = 3 },
-};
-
-struct clksrc_clk exynos4_clk_aclk_133 = {
- .clk = {
- .name = "aclk_133",
- },
- .sources = &exynos4_clkset_aclk,
- .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 24, .size = 1 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 12, .size = 3 },
-};
-
-static struct clk *exynos4_clkset_vpllsrc_list[] = {
- [0] = &clk_fin_vpll,
- [1] = &exynos4_clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources exynos4_clkset_vpllsrc = {
- .sources = exynos4_clkset_vpllsrc_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk exynos4_clk_vpllsrc = {
- .clk = {
- .name = "vpll_src",
- .enable = exynos4_clksrc_mask_top_ctrl,
- .ctrlbit = (1 << 0),
- },
- .sources = &exynos4_clkset_vpllsrc,
- .reg_src = { .reg = EXYNOS4_CLKSRC_TOP1, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_vpll_list[] = {
- [0] = &exynos4_clk_vpllsrc.clk,
- [1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_vpll = {
- .sources = exynos4_clkset_sclk_vpll_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_vpll = {
- .clk = {
- .name = "sclk_vpll",
- },
- .sources = &exynos4_clkset_sclk_vpll,
- .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 8, .size = 1 },
-};
-
-static struct clk exynos4_init_clocks_off[] = {
- {
- .name = "timers",
- .parent = &exynos4_clk_aclk_100.clk,
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1<<24),
- }, {
- .name = "csis",
- .devname = "s5p-mipi-csis.0",
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "csis",
- .devname = "s5p-mipi-csis.1",
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 5),
- }, {
- .name = "jpeg",
- .id = 0,
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 6),
- }, {
- .name = "fimc",
- .devname = "exynos4-fimc.0",
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "fimc",
- .devname = "exynos4-fimc.1",
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "fimc",
- .devname = "exynos4-fimc.2",
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "fimc",
- .devname = "exynos4-fimc.3",
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "hsmmc",
- .devname = "exynos4-sdhci.0",
- .parent = &exynos4_clk_aclk_133.clk,
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 5),
- }, {
- .name = "hsmmc",
- .devname = "exynos4-sdhci.1",
- .parent = &exynos4_clk_aclk_133.clk,
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 6),
- }, {
- .name = "hsmmc",
- .devname = "exynos4-sdhci.2",
- .parent = &exynos4_clk_aclk_133.clk,
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 7),
- }, {
- .name = "hsmmc",
- .devname = "exynos4-sdhci.3",
- .parent = &exynos4_clk_aclk_133.clk,
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = "dwmmc",
- .parent = &exynos4_clk_aclk_133.clk,
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 9),
- }, {
- .name = "dac",
- .devname = "s5p-sdo",
- .enable = exynos4_clk_ip_tv_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "mixer",
- .devname = "s5p-mixer",
- .enable = exynos4_clk_ip_tv_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "vp",
- .devname = "s5p-mixer",
- .enable = exynos4_clk_ip_tv_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "hdmi",
- .devname = "exynos4-hdmi",
- .enable = exynos4_clk_ip_tv_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "hdmiphy",
- .devname = "exynos4-hdmi",
- .enable = exynos4_clk_hdmiphy_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "dacphy",
- .devname = "s5p-sdo",
- .enable = exynos4_clk_dac_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "adc",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 15),
- }, {
- .name = "keypad",
- .enable = exynos4_clk_ip_perir_ctrl,
- .ctrlbit = (1 << 16),
- }, {
- .name = "rtc",
- .enable = exynos4_clk_ip_perir_ctrl,
- .ctrlbit = (1 << 15),
- }, {
- .name = "watchdog",
- .parent = &exynos4_clk_aclk_100.clk,
- .enable = exynos4_clk_ip_perir_ctrl,
- .ctrlbit = (1 << 14),
- }, {
- .name = "usbhost",
- .enable = exynos4_clk_ip_fsys_ctrl ,
- .ctrlbit = (1 << 12),
- }, {
- .name = "otg",
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 13),
- }, {
- .name = "spi",
- .devname = "exynos4210-spi.0",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 16),
- }, {
- .name = "spi",
- .devname = "exynos4210-spi.1",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 17),
- }, {
- .name = "spi",
- .devname = "exynos4210-spi.2",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 18),
- }, {
- .name = "iis",
- .devname = "samsung-i2s.0",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 19),
- }, {
- .name = "iis",
- .devname = "samsung-i2s.1",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 20),
- }, {
- .name = "iis",
- .devname = "samsung-i2s.2",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 21),
- }, {
- .name = "ac97",
- .devname = "samsung-ac97",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 27),
- }, {
- .name = "mfc",
- .devname = "s5p-mfc",
- .enable = exynos4_clk_ip_mfc_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.0",
- .parent = &exynos4_clk_aclk_100.clk,
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 6),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.1",
- .parent = &exynos4_clk_aclk_100.clk,
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 7),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.2",
- .parent = &exynos4_clk_aclk_100.clk,
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.3",
- .parent = &exynos4_clk_aclk_100.clk,
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 9),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.4",
- .parent = &exynos4_clk_aclk_100.clk,
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 10),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.5",
- .parent = &exynos4_clk_aclk_100.clk,
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 11),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.6",
- .parent = &exynos4_clk_aclk_100.clk,
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 12),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.7",
- .parent = &exynos4_clk_aclk_100.clk,
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 13),
- }, {
- .name = "i2c",
- .devname = "s3c2440-hdmiphy-i2c",
- .parent = &exynos4_clk_aclk_100.clk,
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 14),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
- .enable = exynos4_clk_ip_mfc_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(mfc_r, 1),
- .enable = exynos4_clk_ip_mfc_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(tv, 2),
- .enable = exynos4_clk_ip_tv_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(jpeg, 3),
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 11),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(rot, 4),
- .enable = exynos4_clk_ip_image_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(fimc0, 5),
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 7),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(fimc1, 6),
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(fimc2, 7),
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 9),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(fimc3, 8),
- .enable = exynos4_clk_ip_cam_ctrl,
- .ctrlbit = (1 << 10),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(fimd0, 10),
- .enable = exynos4_clk_ip_lcd0_ctrl,
- .ctrlbit = (1 << 4),
- }
-};
-
-static struct clk exynos4_init_clocks_on[] = {
- {
- .name = "uart",
- .devname = "s5pv210-uart.0",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "uart",
- .devname = "s5pv210-uart.1",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "uart",
- .devname = "s5pv210-uart.2",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "uart",
- .devname = "s5pv210-uart.3",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "uart",
- .devname = "s5pv210-uart.4",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "uart",
- .devname = "s5pv210-uart.5",
- .enable = exynos4_clk_ip_peril_ctrl,
- .ctrlbit = (1 << 5),
- }
-};
-
-static struct clk exynos4_clk_pdma0 = {
- .name = "dma",
- .devname = "dma-pl330.0",
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 0),
-};
-
-static struct clk exynos4_clk_pdma1 = {
- .name = "dma",
- .devname = "dma-pl330.1",
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 1),
-};
-
-static struct clk exynos4_clk_mdma1 = {
- .name = "dma",
- .devname = "dma-pl330.2",
- .enable = exynos4_clk_ip_image_ctrl,
- .ctrlbit = ((1 << 8) | (1 << 5) | (1 << 2)),
-};
-
-static struct clk exynos4_clk_fimd0 = {
- .name = "fimd",
- .devname = "exynos4-fb.0",
- .enable = exynos4_clk_ip_lcd0_ctrl,
- .ctrlbit = (1 << 0),
-};
-
-struct clk *exynos4_clkset_group_list[] = {
- [0] = &clk_ext_xtal_mux,
- [1] = &clk_xusbxti,
- [2] = &exynos4_clk_sclk_hdmi27m,
- [3] = &exynos4_clk_sclk_usbphy0,
- [4] = &exynos4_clk_sclk_usbphy1,
- [5] = &exynos4_clk_sclk_hdmiphy,
- [6] = &exynos4_clk_mout_mpll.clk,
- [7] = &exynos4_clk_mout_epll.clk,
- [8] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_group = {
- .sources = exynos4_clkset_group_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_group_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d0_list[] = {
- [0] = &exynos4_clk_mout_mpll.clk,
- [1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d0 = {
- .sources = exynos4_clkset_mout_g2d0_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_g2d0_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d1_list[] = {
- [0] = &exynos4_clk_mout_epll.clk,
- [1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d1 = {
- .sources = exynos4_clkset_mout_g2d1_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_g2d1_list),
-};
-
-static struct clk *exynos4_clkset_mout_mfc0_list[] = {
- [0] = &exynos4_clk_mout_mpll.clk,
- [1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc0 = {
- .sources = exynos4_clkset_mout_mfc0_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_mfc0_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc0 = {
- .clk = {
- .name = "mout_mfc0",
- },
- .sources = &exynos4_clkset_mout_mfc0,
- .reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc1_list[] = {
- [0] = &exynos4_clk_mout_epll.clk,
- [1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc1 = {
- .sources = exynos4_clkset_mout_mfc1_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_mfc1_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc1 = {
- .clk = {
- .name = "mout_mfc1",
- },
- .sources = &exynos4_clkset_mout_mfc1,
- .reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc_list[] = {
- [0] = &exynos4_clk_mout_mfc0.clk,
- [1] = &exynos4_clk_mout_mfc1.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc = {
- .sources = exynos4_clkset_mout_mfc_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_mfc_list),
-};
-
-static struct clk *exynos4_clkset_sclk_dac_list[] = {
- [0] = &exynos4_clk_sclk_vpll.clk,
- [1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_dac = {
- .sources = exynos4_clkset_sclk_dac_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_sclk_dac_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dac = {
- .clk = {
- .name = "sclk_dac",
- .enable = exynos4_clksrc_mask_tv_ctrl,
- .ctrlbit = (1 << 8),
- },
- .sources = &exynos4_clkset_sclk_dac,
- .reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_pixel = {
- .clk = {
- .name = "sclk_pixel",
- .parent = &exynos4_clk_sclk_vpll.clk,
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_TV, .shift = 0, .size = 4 },
-};
-
-static struct clk *exynos4_clkset_sclk_hdmi_list[] = {
- [0] = &exynos4_clk_sclk_pixel.clk,
- [1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_hdmi = {
- .sources = exynos4_clkset_sclk_hdmi_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_sclk_hdmi_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_hdmi = {
- .clk = {
- .name = "sclk_hdmi",
- .enable = exynos4_clksrc_mask_tv_ctrl,
- .ctrlbit = (1 << 0),
- },
- .sources = &exynos4_clkset_sclk_hdmi,
- .reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_mixer_list[] = {
- [0] = &exynos4_clk_sclk_dac.clk,
- [1] = &exynos4_clk_sclk_hdmi.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_mixer = {
- .sources = exynos4_clkset_sclk_mixer_list,
- .nr_sources = ARRAY_SIZE(exynos4_clkset_sclk_mixer_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mixer = {
- .clk = {
- .name = "sclk_mixer",
- .enable = exynos4_clksrc_mask_tv_ctrl,
- .ctrlbit = (1 << 4),
- },
- .sources = &exynos4_clkset_sclk_mixer,
- .reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk *exynos4_sclk_tv[] = {
- &exynos4_clk_sclk_dac,
- &exynos4_clk_sclk_pixel,
- &exynos4_clk_sclk_hdmi,
- &exynos4_clk_sclk_mixer,
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc0 = {
- .clk = {
- .name = "dout_mmc0",
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 0, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc1 = {
- .clk = {
- .name = "dout_mmc1",
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 4, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc2 = {
- .clk = {
- .name = "dout_mmc2",
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 8, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc3 = {
- .clk = {
- .name = "dout_mmc3",
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 12, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc4 = {
- .clk = {
- .name = "dout_mmc4",
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 16, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clksrcs[] = {
- {
- .clk = {
- .name = "sclk_pwm",
- .enable = exynos4_clksrc_mask_peril0_ctrl,
- .ctrlbit = (1 << 24),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 24, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL3, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_csis",
- .devname = "s5p-mipi-csis.0",
- .enable = exynos4_clksrc_mask_cam_ctrl,
- .ctrlbit = (1 << 24),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 24, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 24, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_csis",
- .devname = "s5p-mipi-csis.1",
- .enable = exynos4_clksrc_mask_cam_ctrl,
- .ctrlbit = (1 << 28),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 28, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 28, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_cam0",
- .enable = exynos4_clksrc_mask_cam_ctrl,
- .ctrlbit = (1 << 16),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 16, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 16, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_cam1",
- .enable = exynos4_clksrc_mask_cam_ctrl,
- .ctrlbit = (1 << 20),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 20, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 20, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimc",
- .devname = "exynos4-fimc.0",
- .enable = exynos4_clksrc_mask_cam_ctrl,
- .ctrlbit = (1 << 0),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 0, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimc",
- .devname = "exynos4-fimc.1",
- .enable = exynos4_clksrc_mask_cam_ctrl,
- .ctrlbit = (1 << 4),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 4, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 4, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimc",
- .devname = "exynos4-fimc.2",
- .enable = exynos4_clksrc_mask_cam_ctrl,
- .ctrlbit = (1 << 8),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 8, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 8, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimc",
- .devname = "exynos4-fimc.3",
- .enable = exynos4_clksrc_mask_cam_ctrl,
- .ctrlbit = (1 << 12),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 12, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 12, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimd",
- .devname = "exynos4-fb.0",
- .enable = exynos4_clksrc_mask_lcd0_ctrl,
- .ctrlbit = (1 << 0),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_LCD0, .shift = 0, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_LCD0, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_mfc",
- .devname = "s5p-mfc",
- },
- .sources = &exynos4_clkset_mout_mfc,
- .reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 8, .size = 1 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_MFC, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_dwmmc",
- .parent = &exynos4_clk_dout_mmc4.clk,
- .enable = exynos4_clksrc_mask_fsys_ctrl,
- .ctrlbit = (1 << 16),
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 8, .size = 8 },
- }
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart0 = {
- .clk = {
- .name = "uclk1",
- .devname = "exynos4210-uart.0",
- .enable = exynos4_clksrc_mask_peril0_ctrl,
- .ctrlbit = (1 << 0),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 0, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart1 = {
- .clk = {
- .name = "uclk1",
- .devname = "exynos4210-uart.1",
- .enable = exynos4_clksrc_mask_peril0_ctrl,
- .ctrlbit = (1 << 4),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 4, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart2 = {
- .clk = {
- .name = "uclk1",
- .devname = "exynos4210-uart.2",
- .enable = exynos4_clksrc_mask_peril0_ctrl,
- .ctrlbit = (1 << 8),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 8, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart3 = {
- .clk = {
- .name = "uclk1",
- .devname = "exynos4210-uart.3",
- .enable = exynos4_clksrc_mask_peril0_ctrl,
- .ctrlbit = (1 << 12),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 12, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 12, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc0 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "exynos4-sdhci.0",
- .parent = &exynos4_clk_dout_mmc0.clk,
- .enable = exynos4_clksrc_mask_fsys_ctrl,
- .ctrlbit = (1 << 0),
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc1 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "exynos4-sdhci.1",
- .parent = &exynos4_clk_dout_mmc1.clk,
- .enable = exynos4_clksrc_mask_fsys_ctrl,
- .ctrlbit = (1 << 4),
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc2 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "exynos4-sdhci.2",
- .parent = &exynos4_clk_dout_mmc2.clk,
- .enable = exynos4_clksrc_mask_fsys_ctrl,
- .ctrlbit = (1 << 8),
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc3 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "exynos4-sdhci.3",
- .parent = &exynos4_clk_dout_mmc3.clk,
- .enable = exynos4_clksrc_mask_fsys_ctrl,
- .ctrlbit = (1 << 12),
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi0 = {
- .clk = {
- .name = "mdout_spi",
- .devname = "exynos4210-spi.0",
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 16, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi1 = {
- .clk = {
- .name = "mdout_spi",
- .devname = "exynos4210-spi.1",
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 20, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi2 = {
- .clk = {
- .name = "mdout_spi",
- .devname = "exynos4210-spi.2",
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 24, .size = 4 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi0 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "exynos4210-spi.0",
- .parent = &exynos4_clk_mdout_spi0.clk,
- .enable = exynos4_clksrc_mask_peril1_ctrl,
- .ctrlbit = (1 << 16),
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi1 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "exynos4210-spi.1",
- .parent = &exynos4_clk_mdout_spi1.clk,
- .enable = exynos4_clksrc_mask_peril1_ctrl,
- .ctrlbit = (1 << 20),
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi2 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "exynos4210-spi.2",
- .parent = &exynos4_clk_mdout_spi2.clk,
- .enable = exynos4_clksrc_mask_peril1_ctrl,
- .ctrlbit = (1 << 24),
- },
- .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 8, .size = 8 },
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *exynos4_sysclks[] = {
- &exynos4_clk_mout_apll,
- &exynos4_clk_sclk_apll,
- &exynos4_clk_mout_epll,
- &exynos4_clk_mout_mpll,
- &exynos4_clk_moutcore,
- &exynos4_clk_coreclk,
- &exynos4_clk_armclk,
- &exynos4_clk_aclk_corem0,
- &exynos4_clk_aclk_cores,
- &exynos4_clk_aclk_corem1,
- &exynos4_clk_periphclk,
- &exynos4_clk_mout_corebus,
- &exynos4_clk_sclk_dmc,
- &exynos4_clk_aclk_cored,
- &exynos4_clk_aclk_corep,
- &exynos4_clk_aclk_acp,
- &exynos4_clk_pclk_acp,
- &exynos4_clk_vpllsrc,
- &exynos4_clk_sclk_vpll,
- &exynos4_clk_aclk_200,
- &exynos4_clk_aclk_100,
- &exynos4_clk_aclk_160,
- &exynos4_clk_aclk_133,
- &exynos4_clk_dout_mmc0,
- &exynos4_clk_dout_mmc1,
- &exynos4_clk_dout_mmc2,
- &exynos4_clk_dout_mmc3,
- &exynos4_clk_dout_mmc4,
- &exynos4_clk_mout_mfc0,
- &exynos4_clk_mout_mfc1,
-};
-
-static struct clk *exynos4_clk_cdev[] = {
- &exynos4_clk_pdma0,
- &exynos4_clk_pdma1,
- &exynos4_clk_mdma1,
- &exynos4_clk_fimd0,
-};
-
-static struct clksrc_clk *exynos4_clksrc_cdev[] = {
- &exynos4_clk_sclk_uart0,
- &exynos4_clk_sclk_uart1,
- &exynos4_clk_sclk_uart2,
- &exynos4_clk_sclk_uart3,
- &exynos4_clk_sclk_mmc0,
- &exynos4_clk_sclk_mmc1,
- &exynos4_clk_sclk_mmc2,
- &exynos4_clk_sclk_mmc3,
- &exynos4_clk_sclk_spi0,
- &exynos4_clk_sclk_spi1,
- &exynos4_clk_sclk_spi2,
- &exynos4_clk_mdout_spi0,
- &exynos4_clk_mdout_spi1,
- &exynos4_clk_mdout_spi2,
-};
-
-static struct clk_lookup exynos4_clk_lookup[] = {
- CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &exynos4_clk_sclk_uart0.clk),
- CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos4_clk_sclk_uart1.clk),
- CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos4_clk_sclk_uart2.clk),
- CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos4_clk_sclk_uart3.clk),
- CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos4_clk_sclk_mmc0.clk),
- CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk),
- CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk),
- CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
- CLKDEV_INIT("exynos4-fb.0", "lcd", &exynos4_clk_fimd0),
- CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0),
- CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1),
- CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos4_clk_mdma1),
- CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
- CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
- CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),
-};
-
-static int xtal_rate;
-
-static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
-{
- if (soc_is_exynos4210())
- return s5p_get_pll45xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0),
- pll_4508);
- else if (soc_is_exynos4212() || soc_is_exynos4412())
- return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
- else
- return 0;
-}
-
-static struct clk_ops exynos4_fout_apll_ops = {
- .get_rate = exynos4_fout_apll_get_rate,
-};
-
-static u32 exynos4_vpll_div[][8] = {
- { 54000000, 3, 53, 3, 1024, 0, 17, 0 },
- { 108000000, 3, 53, 2, 1024, 0, 17, 0 },
-};
-
-static unsigned long exynos4_vpll_get_rate(struct clk *clk)
-{
- return clk->rate;
-}
-
-static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned int vpll_con0, vpll_con1 = 0;
- unsigned int i;
-
- /* Return if nothing changed */
- if (clk->rate == rate)
- return 0;
-
- vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
- vpll_con0 &= ~(0x1 << 27 | \
- PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \
- PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
- PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
-
- vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
- vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT | \
- PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT | \
- PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
-
- for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
- if (exynos4_vpll_div[i][0] == rate) {
- vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
- vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
- vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
- vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
- vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
- vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
- vpll_con0 |= exynos4_vpll_div[i][7] << 27;
- break;
- }
- }
-
- if (i == ARRAY_SIZE(exynos4_vpll_div)) {
- printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
- __func__);
- return -EINVAL;
- }
-
- __raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
- __raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
-
- /* Wait for VPLL lock */
- while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
- continue;
-
- clk->rate = rate;
- return 0;
-}
-
-static struct clk_ops exynos4_vpll_ops = {
- .get_rate = exynos4_vpll_get_rate,
- .set_rate = exynos4_vpll_set_rate,
-};
-
-void __init_or_cpufreq exynos4_setup_clocks(void)
-{
- struct clk *xtal_clk;
- unsigned long apll = 0;
- unsigned long mpll = 0;
- unsigned long epll = 0;
- unsigned long vpll = 0;
- unsigned long vpllsrc;
- unsigned long xtal;
- unsigned long armclk;
- unsigned long sclk_dmc;
- unsigned long aclk_200;
- unsigned long aclk_100;
- unsigned long aclk_160;
- unsigned long aclk_133;
- unsigned int ptr;
-
- printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
- xtal_clk = clk_get(NULL, "xtal");
- BUG_ON(IS_ERR(xtal_clk));
-
- xtal = clk_get_rate(xtal_clk);
-
- xtal_rate = xtal;
-
- clk_put(xtal_clk);
-
- printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
- if (soc_is_exynos4210()) {
- apll = s5p_get_pll45xx(xtal, __raw_readl(EXYNOS4_APLL_CON0),
- pll_4508);
- mpll = s5p_get_pll45xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0),
- pll_4508);
- epll = s5p_get_pll46xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
- __raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
-
- vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
- vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
- __raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
- } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
- apll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_APLL_CON0));
- mpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0));
- epll = s5p_get_pll36xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
- __raw_readl(EXYNOS4_EPLL_CON1));
-
- vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
- vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
- __raw_readl(EXYNOS4_VPLL_CON1));
- } else {
- /* nothing */
- }
-
- clk_fout_apll.ops = &exynos4_fout_apll_ops;
- clk_fout_mpll.rate = mpll;
- clk_fout_epll.rate = epll;
- clk_fout_vpll.ops = &exynos4_vpll_ops;
- clk_fout_vpll.rate = vpll;
-
- printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
- apll, mpll, epll, vpll);
-
- armclk = clk_get_rate(&exynos4_clk_armclk.clk);
- sclk_dmc = clk_get_rate(&exynos4_clk_sclk_dmc.clk);
-
- aclk_200 = clk_get_rate(&exynos4_clk_aclk_200.clk);
- aclk_100 = clk_get_rate(&exynos4_clk_aclk_100.clk);
- aclk_160 = clk_get_rate(&exynos4_clk_aclk_160.clk);
- aclk_133 = clk_get_rate(&exynos4_clk_aclk_133.clk);
-
- printk(KERN_INFO "EXYNOS4: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n"
- "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n",
- armclk, sclk_dmc, aclk_200,
- aclk_100, aclk_160, aclk_133);
-
- clk_f.rate = armclk;
- clk_h.rate = sclk_dmc;
- clk_p.rate = aclk_100;
-
- for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrcs); ptr++)
- s3c_set_clksrc(&exynos4_clksrcs[ptr], true);
-}
-
-static struct clk *exynos4_clks[] __initdata = {
- &exynos4_clk_sclk_hdmi27m,
- &exynos4_clk_sclk_hdmiphy,
- &exynos4_clk_sclk_usbphy0,
- &exynos4_clk_sclk_usbphy1,
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4_clock_suspend(void)
-{
- s3c_pm_do_save(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
- return 0;
-}
-
-static void exynos4_clock_resume(void)
-{
- s3c_pm_do_restore_core(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
-}
-
-#else
-#define exynos4_clock_suspend NULL
-#define exynos4_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4_clock_syscore_ops = {
- .suspend = exynos4_clock_suspend,
- .resume = exynos4_clock_resume,
-};
-
-void __init exynos4_register_clocks(void)
-{
- int ptr;
-
- s3c24xx_register_clocks(exynos4_clks, ARRAY_SIZE(exynos4_clks));
-
- for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sysclks); ptr++)
- s3c_register_clksrc(exynos4_sysclks[ptr], 1);
-
- for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sclk_tv); ptr++)
- s3c_register_clksrc(exynos4_sclk_tv[ptr], 1);
-
- for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrc_cdev); ptr++)
- s3c_register_clksrc(exynos4_clksrc_cdev[ptr], 1);
-
- s3c_register_clksrc(exynos4_clksrcs, ARRAY_SIZE(exynos4_clksrcs));
- s3c_register_clocks(exynos4_init_clocks_on, ARRAY_SIZE(exynos4_init_clocks_on));
-
- s3c24xx_register_clocks(exynos4_clk_cdev, ARRAY_SIZE(exynos4_clk_cdev));
- for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clk_cdev); ptr++)
- s3c_disable_clocks(exynos4_clk_cdev[ptr], 1);
-
- s3c_register_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
- s3c_disable_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
- clkdev_add_table(exynos4_clk_lookup, ARRAY_SIZE(exynos4_clk_lookup));
-
- register_syscore_ops(&exynos4_clock_syscore_ops);
- s3c24xx_register_clock(&dummy_apb_pclk);
-
- s3c_pwmclk_init();
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4.h b/arch/arm/mach-exynos/clock-exynos4.h
deleted file mode 100644
index bd12d5f..0000000
--- a/arch/arm/mach-exynos/clock-exynos4.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Header file for exynos4 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.
-*/
-
-#ifndef __ASM_ARCH_CLOCK_H
-#define __ASM_ARCH_CLOCK_H __FILE__
-
-#include <linux/clk.h>
-
-extern struct clksrc_clk exynos4_clk_aclk_133;
-extern struct clksrc_clk exynos4_clk_mout_mpll;
-
-extern struct clksrc_sources exynos4_clkset_mout_corebus;
-extern struct clksrc_sources exynos4_clkset_group;
-
-extern struct clk *exynos4_clkset_aclk_top_list[];
-extern struct clk *exynos4_clkset_group_list[];
-
-extern struct clksrc_sources exynos4_clkset_mout_g2d0;
-extern struct clksrc_sources exynos4_clkset_mout_g2d1;
-
-extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable);
-
-#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-exynos/clock-exynos4210.c b/arch/arm/mach-exynos/clock-exynos4210.c
deleted file mode 100644
index fed4c26..0000000
--- a/arch/arm/mach-exynos/clock-exynos4210.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS4210 - 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/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.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/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4210_clock_save[] = {
- SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
- SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
- SAVE_ITEM(EXYNOS4210_CLKSRC_LCD1),
- SAVE_ITEM(EXYNOS4210_CLKDIV_LCD1),
- SAVE_ITEM(EXYNOS4210_CLKSRC_MASK_LCD1),
- SAVE_ITEM(EXYNOS4210_CLKGATE_IP_IMAGE),
- SAVE_ITEM(EXYNOS4210_CLKGATE_IP_LCD1),
- SAVE_ITEM(EXYNOS4210_CLKGATE_IP_PERIR),
-};
-#endif
-
-static struct clksrc_clk *sysclks[] = {
- /* nothing here yet */
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d0 = {
- .clk = {
- .name = "mout_g2d0",
- },
- .sources = &exynos4_clkset_mout_g2d0,
- .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d1 = {
- .clk = {
- .name = "mout_g2d1",
- },
- .sources = &exynos4_clkset_mout_g2d1,
- .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4210_clkset_mout_g2d_list[] = {
- [0] = &exynos4210_clk_mout_g2d0.clk,
- [1] = &exynos4210_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4210_clkset_mout_g2d = {
- .sources = exynos4210_clkset_mout_g2d_list,
- .nr_sources = ARRAY_SIZE(exynos4210_clkset_mout_g2d_list),
-};
-
-static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4210_CLKSRC_MASK_LCD1, clk, enable);
-}
-
-static struct clksrc_clk clksrcs[] = {
- {
- .clk = {
- .name = "sclk_sata",
- .id = -1,
- .enable = exynos4_clksrc_mask_fsys_ctrl,
- .ctrlbit = (1 << 24),
- },
- .sources = &exynos4_clkset_mout_corebus,
- .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 24, .size = 1 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS0, .shift = 20, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimd",
- .devname = "exynos4-fb.1",
- .enable = exynos4_clksrc_mask_lcd1_ctrl,
- .ctrlbit = (1 << 0),
- },
- .sources = &exynos4_clkset_group,
- .reg_src = { .reg = EXYNOS4210_CLKSRC_LCD1, .shift = 0, .size = 4 },
- .reg_div = { .reg = EXYNOS4210_CLKDIV_LCD1, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimg2d",
- },
- .sources = &exynos4210_clkset_mout_g2d,
- .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 8, .size = 1 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_IMAGE, .shift = 0, .size = 4 },
- },
-};
-
-static struct clk init_clocks_off[] = {
- {
- .name = "sataphy",
- .id = -1,
- .parent = &exynos4_clk_aclk_133.clk,
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "sata",
- .id = -1,
- .parent = &exynos4_clk_aclk_133.clk,
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 10),
- }, {
- .name = "fimd",
- .devname = "exynos4-fb.1",
- .enable = exynos4_clk_ip_lcd1_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(2d, 14),
- .enable = exynos4_clk_ip_image_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(fimd1, 11),
- .enable = exynos4_clk_ip_lcd1_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "fimg2d",
- .enable = exynos4_clk_ip_image_ctrl,
- .ctrlbit = (1 << 0),
- },
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4210_clock_suspend(void)
-{
- s3c_pm_do_save(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-
- return 0;
-}
-
-static void exynos4210_clock_resume(void)
-{
- s3c_pm_do_restore_core(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-}
-
-#else
-#define exynos4210_clock_suspend NULL
-#define exynos4210_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4210_clock_syscore_ops = {
- .suspend = exynos4210_clock_suspend,
- .resume = exynos4210_clock_resume,
-};
-
-void __init exynos4210_register_clocks(void)
-{
- int ptr;
-
- exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_CPU;
- exynos4_clk_mout_mpll.reg_src.shift = 8;
- exynos4_clk_mout_mpll.reg_src.size = 1;
-
- for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
- s3c_register_clksrc(sysclks[ptr], 1);
-
- s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
- s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
- s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
- register_syscore_ops(&exynos4210_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4212.c b/arch/arm/mach-exynos/clock-exynos4212.c
deleted file mode 100644
index 8fba0b5..0000000
--- a/arch/arm/mach-exynos/clock-exynos4212.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS4212 - 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/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.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/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4212_clock_save[] = {
- SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
- SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
- SAVE_ITEM(EXYNOS4212_CLKGATE_IP_IMAGE),
- SAVE_ITEM(EXYNOS4212_CLKGATE_IP_PERIR),
-};
-#endif
-
-static int exynos4212_clk_ip_isp0_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP0, clk, enable);
-}
-
-static int exynos4212_clk_ip_isp1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP1, clk, enable);
-}
-
-static struct clk *clk_src_mpll_user_list[] = {
- [0] = &clk_fin_mpll,
- [1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clk_src_mpll_user = {
- .sources = clk_src_mpll_user_list,
- .nr_sources = ARRAY_SIZE(clk_src_mpll_user_list),
-};
-
-static struct clksrc_clk clk_mout_mpll_user = {
- .clk = {
- .name = "mout_mpll_user",
- },
- .sources = &clk_src_mpll_user,
- .reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d0 = {
- .clk = {
- .name = "mout_g2d0",
- },
- .sources = &exynos4_clkset_mout_g2d0,
- .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 20, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d1 = {
- .clk = {
- .name = "mout_g2d1",
- },
- .sources = &exynos4_clkset_mout_g2d1,
- .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 24, .size = 1 },
-};
-
-static struct clk *exynos4x12_clkset_mout_g2d_list[] = {
- [0] = &exynos4x12_clk_mout_g2d0.clk,
- [1] = &exynos4x12_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4x12_clkset_mout_g2d = {
- .sources = exynos4x12_clkset_mout_g2d_list,
- .nr_sources = ARRAY_SIZE(exynos4x12_clkset_mout_g2d_list),
-};
-
-static struct clksrc_clk *sysclks[] = {
- &clk_mout_mpll_user,
-};
-
-static struct clksrc_clk clksrcs[] = {
- {
- .clk = {
- .name = "sclk_fimg2d",
- },
- .sources = &exynos4x12_clkset_mout_g2d,
- .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 28, .size = 1 },
- .reg_div = { .reg = EXYNOS4_CLKDIV_DMC1, .shift = 0, .size = 4 },
- },
-};
-
-static struct clk init_clocks_off[] = {
- {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(2d, 14),
- .enable = exynos4_clk_ip_dmc_ctrl,
- .ctrlbit = (1 << 24),
- }, {
- .name = SYSMMU_CLOCK_NAME,
- .devname = SYSMMU_CLOCK_DEVNAME(isp, 9),
- .enable = exynos4212_clk_ip_isp0_ctrl,
- .ctrlbit = (7 << 8),
- }, {
- .name = SYSMMU_CLOCK_NAME2,
- .devname = SYSMMU_CLOCK_DEVNAME(isp, 9),
- .enable = exynos4212_clk_ip_isp1_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "flite",
- .devname = "exynos-fimc-lite.0",
- .enable = exynos4212_clk_ip_isp0_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "flite",
- .devname = "exynos-fimc-lite.1",
- .enable = exynos4212_clk_ip_isp0_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "fimg2d",
- .enable = exynos4_clk_ip_dmc_ctrl,
- .ctrlbit = (1 << 23),
- },
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4212_clock_suspend(void)
-{
- s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-
- return 0;
-}
-
-static void exynos4212_clock_resume(void)
-{
- s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-}
-
-#else
-#define exynos4212_clock_suspend NULL
-#define exynos4212_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4212_clock_syscore_ops = {
- .suspend = exynos4212_clock_suspend,
- .resume = exynos4212_clock_resume,
-};
-
-void __init exynos4212_register_clocks(void)
-{
- int ptr;
-
- /* usbphy1 is removed */
- exynos4_clkset_group_list[4] = NULL;
-
- /* mout_mpll_user is used */
- exynos4_clkset_group_list[6] = &clk_mout_mpll_user.clk;
- exynos4_clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk;
-
- exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_DMC;
- exynos4_clk_mout_mpll.reg_src.shift = 12;
- exynos4_clk_mout_mpll.reg_src.size = 1;
-
- for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
- s3c_register_clksrc(sysclks[ptr], 1);
-
- s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
- s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
- s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
- register_syscore_ops(&exynos4212_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 4eb39cd..864adce 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -370,29 +370,23 @@ static void __init exynos5_map_io(void)

static void __init exynos4_init_clocks(int xtal)
{
- printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
- s3c24xx_register_baseclocks(xtal);
- s5p_register_clocks(xtal);
-
- if (soc_is_exynos4210())
- exynos4210_register_clocks();
- else if (soc_is_exynos4212() || soc_is_exynos4412())
- exynos4212_register_clocks();
-
- exynos4_register_clocks();
- exynos4_setup_clocks();
+ /*
+ * TODO: Remove this function after migrating all Samsung platforms
+ * to common clock framework.
+ */
}

static void __init exynos5_init_clocks(int xtal)
{
printk(KERN_DEBUG "%s: initializing clocks\n", __func__);

+#ifndef CONFIG_COMMON_CLK
s3c24xx_register_baseclocks(xtal);
s5p_register_clocks(xtal);

exynos5_register_clocks();
exynos5_setup_clocks();
+#endif
}

#define COMBINER_ENABLE_SET 0x0
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c
index 5a3daa0..83e2410 100644
--- a/arch/arm/mach-exynos/mach-armlex4210.c
+++ b/arch/arm/mach-exynos/mach-armlex4210.c
@@ -179,7 +179,6 @@ static void __init armlex4210_smsc911x_init(void)
static void __init armlex4210_map_io(void)
{
exynos_init_io(NULL, 0);
- s3c24xx_init_clocks(24000000);
s3c24xx_init_uarts(armlex4210_uartcfgs,
ARRAY_SIZE(armlex4210_uartcfgs));
}
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index b2b5d5f..c851b13 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -69,7 +69,6 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
static void __init exynos4210_dt_map_io(void)
{
exynos_init_io(NULL, 0);
- s3c24xx_init_clocks(24000000);
}

static void __init exynos4210_dt_machine_init(void)
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index ea785fc..976ec4c 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -1338,7 +1338,6 @@ static struct platform_device *nuri_devices[] __initdata = {
static void __init nuri_map_io(void)
{
exynos_init_io(NULL, 0);
- s3c24xx_init_clocks(clk_xusbxti.rate);
s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
}

diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 5ca8030..3addaf9 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -745,7 +745,6 @@ static void s5p_tv_setup(void)
static void __init origen_map_io(void)
{
exynos_init_io(NULL, 0);
- s3c24xx_init_clocks(clk_xusbxti.rate);
s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
}

diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index b26beb1..00809fe 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -321,7 +321,6 @@ static struct platform_device *smdk4x12_devices[] __initdata = {
static void __init smdk4x12_map_io(void)
{
exynos_init_io(NULL, 0);
- s3c24xx_init_clocks(clk_xusbxti.rate);
s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
}

diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index 3cfa688..fd59f1f 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -365,7 +365,6 @@ static void s5p_tv_setup(void)
static void __init smdkv310_map_io(void)
{
exynos_init_io(NULL, 0);
- s3c24xx_init_clocks(clk_xusbxti.rate);
s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
}

diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 4d1f40d..80ddb0a 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -1100,7 +1100,6 @@ static struct platform_device *universal_devices[] __initdata = {
static void __init universal_map_io(void)
{
exynos_init_io(NULL, 0);
- s3c24xx_init_clocks(clk_xusbxti.rate);
s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
}
--
1.7.1

2012-10-01 12:09:56

by Chander Kashyap

[permalink] [raw]
Subject: [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework

From: Thomas Abraham <[email protected]>

Register clocks for Exynos4 platfotms using common clock framework.
Also included are set of helper functions for clock registration
that can be reused on other Samsung platforms as well.

Cc: Mike Turquette <[email protected]>
Cc: Kukjin Kim <[email protected]>
Signed-off-by: Thomas Abraham <[email protected]>
---
arch/arm/mach-exynos/Kconfig | 1 +
arch/arm/mach-exynos/common.h | 3 +
arch/arm/mach-exynos/mct.c | 11 +-
arch/arm/plat-samsung/Kconfig | 4 +-
drivers/clk/Makefile | 1 +
drivers/clk/clk.c | 12 +-
drivers/clk/samsung/Makefile | 6 +
drivers/clk/samsung/clk-exynos4.c | 585 +++++++++++++++++++++++++++++++++++++
drivers/clk/samsung/clk.c | 231 +++++++++++++++
drivers/clk/samsung/clk.h | 190 ++++++++++++
10 files changed, 1037 insertions(+), 7 deletions(-)
create mode 100644 drivers/clk/samsung/Makefile
create mode 100644 drivers/clk/samsung/clk-exynos4.c
create mode 100644 drivers/clk/samsung/clk.c
create mode 100644 drivers/clk/samsung/clk.h

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index b5b4c8c..4866ec7 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -15,6 +15,7 @@ config ARCH_EXYNOS4
bool "SAMSUNG EXYNOS4"
default y
select HAVE_SMP
+ select COMMON_CLK
select MIGHT_HAVE_CACHE_L2X0
help
Samsung EXYNOS4 SoCs based systems
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index aed2eeb..2274431 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -21,6 +21,9 @@ void exynos4_restart(char mode, const char *cmd);
void exynos5_restart(char mode, const char *cmd);
void exynos_init_late(void);

+void exynos4210_clk_init(void);
+void exynos4212_clk_init(void);
+
#ifdef CONFIG_PM_GENERIC_DOMAINS
int exynos_pm_late_initcall(void);
#else
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index b601fb8..a7cace0 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -30,6 +30,8 @@
#include <mach/regs-mct.h>
#include <asm/mach/time.h>

+#include "common.h"
+
#define TICK_BASE_CNT 1

enum {
@@ -457,7 +459,7 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
static void __init exynos4_timer_resources(void)
{
struct clk *mct_clk;
- mct_clk = clk_get(NULL, "xtal");
+ mct_clk = clk_get(NULL, "fin_pll");

clk_rate = clk_get_rate(mct_clk);

@@ -478,6 +480,13 @@ static void __init exynos4_timer_resources(void)

static void __init exynos4_timer_init(void)
{
+#ifdef CONFIG_COMMON_CLK
+ if (soc_is_exynos4210())
+ exynos4210_clk_init();
+ else if (soc_is_exynos4212() || soc_is_exynos4412())
+ exynos4212_clk_init();
+#endif
+
if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
mct_int_type = MCT_INT_SPI;
else
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 9c3b90c..35b4cb8 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -26,7 +26,7 @@ config PLAT_S5P
select S5P_GPIO_DRVSTR
select SAMSUNG_GPIOLIB_4BIT
select PLAT_SAMSUNG
- select SAMSUNG_CLKSRC
+ select SAMSUNG_CLKSRC if !COMMON_CLK
select SAMSUNG_IRQ_VIC_TIMER
help
Base platform code for Samsung's S5P series SoC.
@@ -89,7 +89,7 @@ config SAMSUNG_CLKSRC
used by newer systems such as the S3C64XX.

config S5P_CLOCK
- def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
+ def_bool ((ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) && !COMMON_CLK)
help
Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 6327536..5f5b060 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_ARCH_MMP) += mmp/
endif
obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
obj-$(CONFIG_ARCH_U8500) += ux500/
+obj-$(CONFIG_PLAT_SAMSUNG) += samsung/

# Chip specific
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 56e4495..456c50b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1196,6 +1196,7 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
int __clk_init(struct device *dev, struct clk *clk)
{
int i, ret = 0;
+ u8 index;
struct clk *orphan;
struct hlist_node *tmp, *tmp2;

@@ -1259,6 +1260,7 @@ int __clk_init(struct device *dev, struct clk *clk)
__clk_lookup(clk->parent_names[i]);
}

+
clk->parent = __clk_init_parent(clk);

/*
@@ -1298,11 +1300,13 @@ int __clk_init(struct device *dev, struct clk *clk)
* this clock
*/
hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node)
- for (i = 0; i < orphan->num_parents; i++)
- if (!strcmp(clk->name, orphan->parent_names[i])) {
+ if (orphan->num_parents > 1) {
+ index = orphan->ops->get_parent(orphan->hw);
+ if (!strcmp(clk->name, orphan->parent_names[index]))
__clk_reparent(orphan, clk);
- break;
- }
+ } else if (!strcmp(clk->name, orphan->parent_names[0])) {
+ __clk_reparent(orphan, clk);
+ }

/*
* optional platform-specific magic
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
new file mode 100644
index 0000000..69487f7
--- /dev/null
+++ b/drivers/clk/samsung/Makefile
@@ -0,0 +1,6 @@
+#
+# Samsung Clock specific Makefile
+#
+
+obj-$(CONFIG_PLAT_SAMSUNG) += clk.o
+obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
new file mode 100644
index 0000000..74a6f03
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 Linaro Ltd.
+ *
+ * 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.
+ *
+ * Common Clock Framework support for all Exynos4 platforms
+*/
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+#include <plat/pll.h>
+#include <plat/cpu.h>
+#include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
+#include <plat/map-s5p.h>
+
+#include "clk.h"
+
+#define EXYNOS4_OP_MODE (S5P_VA_CHIPID + 8)
+
+static const char *pll_parent_names[] __initdata = { "fin_pll" };
+static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
+static const char *mout_apll_parents[] __initdata = { "fin_pll", "fout_apll", };
+static const char *mout_mpll_parents[] __initdata = { "fin_pll", "fout_mpll", };
+static const char *mout_epll_parents[] __initdata = { "fin_pll", "fout_epll", };
+
+static const char *sclk_ampll_parents[] __initdata = {
+ "mout_mpll", "sclk_apll", };
+
+static const char *sclk_evpll_parents[] __initdata = {
+ "mout_epll", "mout_vpll", };
+
+static const char *mout_core_parents[] __initdata = {
+ "mout_apll", "mout_mpll", };
+
+static const char *mout_mfc_parents[] __initdata = {
+ "mout_mfc0", "mout_mfc1", };
+
+static const char *mout_dac_parents[] __initdata = {
+ "mout_vpll", "sclk_hdmiphy", };
+
+static const char *mout_hdmi_parents[] __initdata = {
+ "sclk_pixel", "sclk_hdmiphy", };
+
+static const char *mout_mixer_parents[] __initdata = {
+ "sclk_dac", "sclk_hdmi", };
+
+static const char *group1_parents[] __initdata = {
+ "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+ "none", "sclk_hdmiphy", "mout_mpll", "mout_epll",
+ "mout_vpll" };
+
+static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
+ FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
+ FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),
+ FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
+ FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
+ FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
+};
+
+static struct samsung_mux_clock exynos4_mux_clks[] = {
+ MUXCLK(NULL, "fin_pll", fin_pll_parents, 0,
+ EXYNOS4_OP_MODE, 0, 1, 0),
+ MUXCLK(NULL, "mout_apll", mout_apll_parents, 0,
+ EXYNOS4_CLKSRC_CPU, 0, 1, 0),
+ MUXCLK(NULL, "mout_epll", mout_epll_parents, 0,
+ EXYNOS4_CLKSRC_TOP0, 4, 1, 0),
+ MUXCLK(NULL, "mout_core", mout_core_parents, 0,
+ EXYNOS4_CLKSRC_CPU, 16, 1, 0),
+ MUXCLK(NULL, "mout_aclk_200", sclk_ampll_parents, 0,
+ EXYNOS4_CLKSRC_TOP0, 12, 1, 0),
+ MUXCLK(NULL, "mout_aclk_100", sclk_ampll_parents, 0,
+ EXYNOS4_CLKSRC_TOP0, 16, 1, 0),
+ MUXCLK(NULL, "mout_aclk_160", sclk_ampll_parents, 0,
+ EXYNOS4_CLKSRC_TOP0, 20, 1, 0),
+ MUXCLK(NULL, "mout_aclk_133", sclk_ampll_parents, 0,
+ EXYNOS4_CLKSRC_TOP0, 24, 1, 0),
+ MUXCLK("exynos4210-uart.0", "mout_uart0", group1_parents, 0,
+ EXYNOS4_CLKSRC_PERIL0, 0, 4, 0),
+ MUXCLK("exynos4210-uart.1", "mout_uart1", group1_parents, 0,
+ EXYNOS4_CLKSRC_PERIL0, 4, 4, 0),
+ MUXCLK("exynos4210-uart.2", "mout_uart2", group1_parents, 0,
+ EXYNOS4_CLKSRC_PERIL0, 8, 4, 0),
+ MUXCLK("exynos4210-uart.3", "mout_uart3", group1_parents, 0,
+ EXYNOS4_CLKSRC_PERIL0, 12, 4, 0),
+ MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
+ EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
+ MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
+ EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
+ MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
+ EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
+ MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
+ EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
+ MUXCLK("exynos4210-spi.0", "mout_spi0", group1_parents, 0,
+ EXYNOS4_CLKSRC_PERIL1, 16, 4, 0),
+ MUXCLK("exynos4210-spi.1", "mout_spi1", group1_parents, 0,
+ EXYNOS4_CLKSRC_PERIL1, 20, 4, 0),
+ MUXCLK("exynos4210-spi.2", "mout_spi2", group1_parents, 0,
+ EXYNOS4_CLKSRC_PERIL1, 24, 4, 0),
+ MUXCLK(NULL, "mout_sata", sclk_ampll_parents, 0,
+ EXYNOS4_CLKSRC_FSYS, 24, 1, 0),
+ MUXCLK(NULL, "mout_mfc0", sclk_ampll_parents, 0,
+ EXYNOS4_CLKSRC_MFC, 0, 1, 0),
+ MUXCLK(NULL, "mout_mfc1", sclk_evpll_parents, 0,
+ EXYNOS4_CLKSRC_MFC, 4, 1, 0),
+ MUXCLK("s5p-mfc", "mout_mfc", mout_mfc_parents, 0,
+ EXYNOS4_CLKSRC_MFC, 8, 1, 0),
+ MUXCLK("s5p-mipi-csis.0", "mout_csis0", group1_parents, 0,
+ EXYNOS4_CLKSRC_CAM, 24, 4, 0),
+ MUXCLK("s5p-mipi-csis.1", "mout_csis1", group1_parents, 0,
+ EXYNOS4_CLKSRC_CAM, 28, 4, 0),
+ MUXCLK(NULL, "mout_cam0", group1_parents, 0,
+ EXYNOS4_CLKSRC_CAM, 16, 4, 0),
+ MUXCLK(NULL, "mout_cam1", group1_parents, 0,
+ EXYNOS4_CLKSRC_CAM, 20, 4, 0),
+ MUXCLK("exynos4-fimc.0", "mout_fimc0", group1_parents, 0,
+ EXYNOS4_CLKSRC_CAM, 0, 4, 0),
+ MUXCLK("exynos4-fimc.1", "mout_fimc1", group1_parents, 0,
+ EXYNOS4_CLKSRC_CAM, 4, 4, 0),
+ MUXCLK("exynos4-fimc.2", "mout_fimc2", group1_parents, 0,
+ EXYNOS4_CLKSRC_CAM, 8, 4, 0),
+ MUXCLK("exynos4-fimc.3", "mout_fimc3", group1_parents, 0,
+ EXYNOS4_CLKSRC_CAM, 12, 4, 0),
+ MUXCLK("exynos4-fb.0", "mout_fimd0", group1_parents, 0,
+ EXYNOS4_CLKSRC_LCD0, 0, 4, 0),
+ MUXCLK(NULL, "sclk_dac", mout_dac_parents, 0,
+ EXYNOS4_CLKSRC_TV, 8, 1, 0),
+ MUXCLK(NULL, "sclk_hdmi", mout_hdmi_parents, 0,
+ EXYNOS4_CLKSRC_TV, 0, 1, 0),
+ MUXCLK(NULL, "sclk_mixer", mout_mixer_parents, 0,
+ EXYNOS4_CLKSRC_TV, 4, 1, 0),
+};
+
+static struct samsung_div_clock exynos4_div_clks[] = {
+ DIVCLK(NULL, "sclk_apll", "mout_apll", 0,
+ EXYNOS4_CLKDIV_CPU, 24, 3, 0),
+ DIVCLK(NULL, "div_core", "mout_core", 0,
+ EXYNOS4_CLKDIV_CPU, 0, 3, 0),
+ DIVCLK(NULL, "armclk", "div_core", 0,
+ EXYNOS4_CLKDIV_CPU, 28, 3, 0),
+ DIVCLK(NULL, "aclk_200", "mout_aclk_200", 0,
+ EXYNOS4_CLKDIV_TOP, 0, 3, 0),
+ DIVCLK(NULL, "aclk_100", "mout_aclk_100", 0,
+ EXYNOS4_CLKDIV_TOP, 4, 4, 0),
+ DIVCLK(NULL, "aclk_160", "mout_aclk_160", 0,
+ EXYNOS4_CLKDIV_TOP, 8, 3, 0),
+ DIVCLK(NULL, "aclk_133", "mout_aclk_133", 0,
+ EXYNOS4_CLKDIV_TOP, 12, 3, 0),
+ DIVCLK("exynos4210-uart.0", "div_uart0", "mout_uart0", 0,
+ EXYNOS4_CLKDIV_PERIL0, 0, 4, 0),
+ DIVCLK("exynos4210-uart.1", "div_uart1", "mout_uart1", 0,
+ EXYNOS4_CLKDIV_PERIL0, 4, 4, 0),
+ DIVCLK("exynos4210-uart.2", "div_uart2", "mout_uart2", 0,
+ EXYNOS4_CLKDIV_PERIL0, 8, 4, 0),
+ DIVCLK("exynos4210-uart.3", "div_uart3", "mout_uart3", 0,
+ EXYNOS4_CLKDIV_PERIL0, 12, 4, 0),
+ DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
+ EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
+ DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
+ EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
+ DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
+ EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
+ DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
+ EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
+ DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
+ EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
+ DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
+ EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
+ DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
+ EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
+ DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
+ EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
+ DIVCLK("exynos4210-spi.0", "div_spi0", "mout_spi0", 0,
+ EXYNOS4_CLKDIV_PERIL1, 0, 4, 0),
+ DIVCLK("exynos4210-spi.1", "div_spi1", "mout_spi1", 0,
+ EXYNOS4_CLKDIV_PERIL1, 16, 4, 0),
+ DIVCLK("exynos4210-spi.2", "div_spi2", "mout_spi2", 0,
+ EXYNOS4_CLKDIV_PERIL2, 0, 4, 0),
+ DIVCLK("exynos4210-spi.0", "div_spi0_pre", "div_spi0", 0,
+ EXYNOS4_CLKDIV_PERIL1, 8, 8, 0),
+ DIVCLK("exynos4210-spi.1", "div_spi1_pre", "div_spi1", 0,
+ EXYNOS4_CLKDIV_PERIL1, 24, 8, 0),
+ DIVCLK("exynos4210-spi.2", "div_spi2_pre", "div_spi2", 0,
+ EXYNOS4_CLKDIV_PERIL2, 8, 8, 0),
+ DIVCLK(NULL, "div_sata", "mout_sata", 0,
+ EXYNOS4_CLKDIV_FSYS0, 20, 4, 0),
+ DIVCLK("s5p-mfc", "div_mfc", "mout_mfc", 0,
+ EXYNOS4_CLKDIV_MFC, 0, 4, 0),
+ DIVCLK("s5p-mipi-csis.0", "div_csis0", "mout_csis0", 0,
+ EXYNOS4_CLKDIV_CAM, 24, 4, 0),
+ DIVCLK("s5p-mipi-csis.1", "div_csis1", "mout_csis1", 0,
+ EXYNOS4_CLKDIV_CAM, 28, 4, 0),
+ DIVCLK(NULL, "div_cam0", "mout_cam0", 0,
+ EXYNOS4_CLKDIV_CAM, 16, 4, 0),
+ DIVCLK(NULL, "div_cam1", "mout_cam1", 0,
+ EXYNOS4_CLKDIV_CAM, 20, 4, 0),
+ DIVCLK("exynos4-fimc.0", "div_fimc0", "mout_fimc0", 0,
+ EXYNOS4_CLKDIV_CAM, 0, 4, 0),
+ DIVCLK("exynos4-fimc.1", "div_fimc1", "mout_fimc1", 0,
+ EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+ DIVCLK("exynos4-fimc.2", "div_fimc2", "mout_fimc2", 0,
+ EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+ DIVCLK("exynos4-fimc.3", "div_fimc3", "mout_fimc3", 0,
+ EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+ DIVCLK("exynos4-fb.0", "div_fimd0", "mout_fimd0", 0,
+ EXYNOS4_CLKDIV_LCD0, 0, 4, 0),
+ DIVCLK(NULL, "sclk_pixel", "mout_vpll", 0,
+ EXYNOS4_CLKDIV_TV, 0, 4, 0),
+};
+
+struct samsung_gate_clock exynos4_gate_clks[] = {
+ GATECLK("exynos4210-uart.0", "uart0", "aclk_100", CLK_SET_RATE_PARENT,
+ EXYNOS4_CLKGATE_IP_PERIL, 0, "uart"),
+ GATECLK("exynos4210-uart.1", "uart1", "aclk_100", CLK_SET_RATE_PARENT,
+ EXYNOS4_CLKGATE_IP_PERIL, 1, "uart"),
+ GATECLK("exynos4210-uart.2", "uart2", "aclk_100", CLK_SET_RATE_PARENT,
+ EXYNOS4_CLKGATE_IP_PERIL, 2, "uart"),
+ GATECLK("exynos4210-uart.3", "uart3", "aclk_100", CLK_SET_RATE_PARENT,
+ EXYNOS4_CLKGATE_IP_PERIL, 3, "uart"),
+ GATECLK("exynos4210-uart.4", "uart4", "aclk_100", CLK_SET_RATE_PARENT,
+ EXYNOS4_CLKGATE_IP_PERIL, 4, "uart"),
+ GATECLK("exynos4210-uart.5", "uart5", "aclk_100", CLK_SET_RATE_PARENT,
+ EXYNOS4_CLKGATE_IP_PERIL, 5, "uart"),
+ GATECLK("exynos4210-uart.0", "uclk0", "div_uart0", CLK_SET_RATE_PARENT,
+ EXYNOS4_CLKSRC_MASK_PERIL0, 0, "clk_uart_baud0"),
+ GATECLK("exynos4210-uart.1", "uclk1", "div_uart1", CLK_SET_RATE_PARENT,
+ EXYNOS4_CLKSRC_MASK_PERIL0, 4, "clk_uart_baud0"),
+ GATECLK("exynos4210-uart.2", "uclk2", "div_uart2", CLK_SET_RATE_PARENT,
+ EXYNOS4_CLKSRC_MASK_PERIL0, 8, "clk_uart_baud0"),
+ GATECLK("exynos4210-uart.3", "uclk3", "div_uart3", CLK_SET_RATE_PARENT,
+ EXYNOS4_CLKSRC_MASK_PERIL0, 12, "clk_uart_baud0"),
+ GATECLK(NULL, "timers", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 24, NULL),
+ GATECLK("s5p-mipi-csis.0", "csis", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_CAM, 5, NULL),
+ GATECLK(NULL, "jpeg", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_CAM, 6, NULL),
+ GATECLK("exynos4-fimc.0", "fimc0", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_CAM, 0, "fimc"),
+ GATECLK("exynos4-fimc.1", "fimc1", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_CAM, 1, "fimc"),
+ GATECLK("exynos4-fimc.2", "fimc2", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_CAM, 2, "fimc"),
+ GATECLK("exynos4-fimc.3", "fimc3", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_CAM, 3, "fimc"),
+ GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
+ EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
+ GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
+ EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
+ GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
+ EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
+ GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
+ EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
+ GATECLK(NULL, "dwmmc", "aclk_133", 0,
+ EXYNOS4_CLKGATE_IP_FSYS, 9, NULL),
+ GATECLK("s5p-sdo", "dac", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_TV, 2, NULL),
+ GATECLK("s5p-mixer", "mixer", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_TV, 1, NULL),
+ GATECLK("s5p-mixer", "vp", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_TV, 0, NULL),
+ GATECLK("exynos4-hdmi", "hdmi", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_TV, 3, NULL),
+ GATECLK("exynos4-hdmi", "hdmiphy", "aclk_160", 0,
+ S5P_HDMI_PHY_CONTROL, 0, NULL),
+ GATECLK("s5p-sdo", "dacphy", "aclk_160", 0,
+ S5P_DAC_PHY_CONTROL, 0, NULL),
+ GATECLK(NULL, "adc", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 15, NULL),
+ GATECLK(NULL, "keypad", "aclk_100", 0,
+ EXYNOS4210_CLKGATE_IP_PERIR, 16, NULL),
+ GATECLK(NULL, "rtc", "aclk_100", 0,
+ EXYNOS4210_CLKGATE_IP_PERIR, 15, NULL),
+ GATECLK(NULL, "watchdog", "aclk_100", 0,
+ EXYNOS4210_CLKGATE_IP_PERIR, 14, NULL),
+ GATECLK(NULL, "usbhost", "aclk_133", 0,
+ EXYNOS4_CLKGATE_IP_FSYS, 12, NULL),
+ GATECLK(NULL, "otg", "aclk_133", 0,
+ EXYNOS4_CLKGATE_IP_FSYS, 13, NULL),
+ GATECLK("exynos4210-spi.0", "spi0", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 16, "spi"),
+ GATECLK("exynos4210-spi.1", "spi1", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 17, "spi"),
+ GATECLK("exynos4210-spi.2", "spi2", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 18, "spi"),
+ GATECLK("samsung-i2s.0", "iis0", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 19, "iis"),
+ GATECLK("samsung-i2s.1", "iis1", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 20, "iis"),
+ GATECLK("samsung-i2s.2", "iis2", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 21, "iis"),
+ GATECLK("samsung-ac97", "ac97", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 27, NULL),
+ GATECLK("s5p-mfc", "mfc", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_MFC, 0, NULL),
+ GATECLK("s3c2440-i2c.0", "i2c0", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 6, "i2c"),
+ GATECLK("s3c2440-i2c.1", "i2c1", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 7, "i2c"),
+ GATECLK("s3c2440-i2c.2", "i2c2", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 8, "i2c"),
+ GATECLK("s3c2440-i2c.3", "i2c3", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 9, "i2c"),
+ GATECLK("s3c2440-i2c.4", "i2c4", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 10, "i2c"),
+ GATECLK("s3c2440-i2c.5", "i2c5", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 11, "i2c"),
+ GATECLK("s3c2440-i2c.6", "i2c6", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 12, "i2c"),
+ GATECLK("s3c2440-i2c.7", "i2c7", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 13, "i2c"),
+ GATECLK("s3c2440-hdmiphy-i2c", "i2c", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_PERIL, 14, NULL),
+ GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_l, 0), "sysmmu0", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_MFC, 1, "sysmmu"),
+ GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_r, 1), "sysmmu1", "aclk_100", 0,
+ EXYNOS4_CLKGATE_IP_MFC, 2, "sysmmu"),
+ GATECLK(SYSMMU_CLOCK_DEVNAME(tv, 2), "sysmmu2", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_TV, 4, "sysmmu"),
+ GATECLK(SYSMMU_CLOCK_DEVNAME(jpeg, 3), "sysmmu3", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_CAM, 11, "sysmmu"),
+ GATECLK(SYSMMU_CLOCK_DEVNAME(rot, 4), "sysmmu4", "aclk_200", 0,
+ EXYNOS4210_CLKGATE_IP_IMAGE, 4, "sysmmu"),
+ GATECLK(SYSMMU_CLOCK_DEVNAME(fimc0, 5), "sysmmu5", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_CAM, 7, "sysmmu"),
+ GATECLK(SYSMMU_CLOCK_DEVNAME(fimc1, 6), "sysmmu6", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_CAM, 8, "sysmmu"),
+ GATECLK(SYSMMU_CLOCK_DEVNAME(fimc2, 7), "sysmmu7", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_CAM, 9, "sysmmu"),
+ GATECLK(SYSMMU_CLOCK_DEVNAME(fimc3, 8), "sysmmu8", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_CAM, 10, "sysmmu"),
+ GATECLK(SYSMMU_CLOCK_DEVNAME(fimd, 10), "sysmmu10", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_LCD0, 4, "sysmmu"),
+ GATECLK("dma-pl330.0", "dma0", "aclk_133", 0,
+ EXYNOS4_CLKGATE_IP_FSYS, 0, "dma"),
+ GATECLK("dma-pl330.1", "dma1", "aclk_133", 0,
+ EXYNOS4_CLKGATE_IP_FSYS, 1, "dma"),
+ GATECLK("exynos4-fb.0", "fimd", "aclk_160", 0,
+ EXYNOS4_CLKGATE_IP_LCD0, 0, "lcd"),
+ GATECLK("exynos4210-spi.0", "sclk_spi0", "div_spi0_pre", 0,
+ EXYNOS4_CLKSRC_MASK_PERIL1, 16, "spi_busclk0"),
+ GATECLK("exynos4210-spi.1", "sclk_spi1", "div_spi1_pre", 0,
+ EXYNOS4_CLKSRC_MASK_PERIL1, 20, "spi_busclk0"),
+ GATECLK("exynos4210-spi.2", "sclk_spi2", "div_spi2_pre", 0,
+ EXYNOS4_CLKSRC_MASK_PERIL1, 24, "spi_busclk0"),
+ GATECLK("exynos4-sdhci.0", "sclk_mmc0", "div_mmc0_pre", 0,
+ EXYNOS4_CLKSRC_MASK_FSYS, 0, "mmc_busclk.2"),
+ GATECLK("exynos4-sdhci.1", "sclk_mmc1", "div_mmc1_pre", 0,
+ EXYNOS4_CLKSRC_MASK_FSYS, 4, "mmc_busclk.2"),
+ GATECLK("exynos4-sdhci.2", "sclk_mmc2", "div_mmc2_pre", 0,
+ EXYNOS4_CLKSRC_MASK_FSYS, 8, "mmc_busclk.2"),
+ GATECLK("exynos4-sdhci.3", "sclk_mmc3", "div_mmc3_pre", 0,
+ EXYNOS4_CLKSRC_MASK_FSYS, 12, "mmc_busclk.2"),
+ GATECLK("s5p-mipi-csis.0", "sclk_csis0", "div_csis0", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 24, "sclk_csis"),
+ GATECLK("s5p-mipi-csis.1", "sclk_csis1", "div_csis1", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
+ GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
+ GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
+ GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
+ GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
+ GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
+ GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
+ GATECLK("exynos4-fb.0", "sclk_fimd", "div_fimd0", 0,
+ EXYNOS4_CLKSRC_MASK_LCD0, 0, "sclk_fimd"),
+};
+
+/* register clock common to all Exynos4 platforms */
+void __init exynos4_clk_init(void)
+{
+ samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
+ ARRAY_SIZE(exynos4_fixed_rate_clks));
+ samsung_clk_register_mux(exynos4_mux_clks,
+ ARRAY_SIZE(exynos4_mux_clks));
+ samsung_clk_register_div(exynos4_div_clks,
+ ARRAY_SIZE(exynos4_div_clks));
+ samsung_clk_register_gate(exynos4_gate_clks,
+ ARRAY_SIZE(exynos4_gate_clks));
+}
+
+/*
+ * Exynos4210 Specific Clocks
+ */
+
+static const char *exynos4210_vpll_parent_names[] __initdata = {
+ "mout_vpll_src" };
+static const char *mout_vpll_src_parents[] __initdata = {
+ "fin_pll", "sclk_hdmi24m" };
+static const char *exynos4210_mout_vpll_parents[] __initdata = {
+ "mout_vpll_src", "fout_vpll", };
+
+/* Exynos4210 specific fixed rate clocks */
+static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] = {
+ FRATE_CLK(NULL, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* Exynos4210 specific mux-type clocks */
+static struct samsung_mux_clock exynos4210_mux_clks[] = {
+ MUXCLK(NULL, "mout_vpll_src", mout_vpll_src_parents, 0,
+ EXYNOS4_CLKSRC_TOP1, 0, 1, 0),
+ MUXCLK(NULL, "mout_vpll", exynos4210_mout_vpll_parents, 0,
+ EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
+ MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
+ EXYNOS4_CLKSRC_CPU, 8, 1, 0),
+};
+
+static unsigned long exynos4210_get_rate_apll(unsigned long xtal_rate)
+{
+ return s5p_get_pll45xx(xtal_rate,
+ __raw_readl(EXYNOS4_APLL_CON0), pll_4508);
+}
+
+static unsigned long exynos4210_get_rate_mpll(unsigned long xtal_rate)
+{
+ return s5p_get_pll45xx(xtal_rate,
+ __raw_readl(EXYNOS4_MPLL_CON0), pll_4508);
+}
+
+static unsigned long exynos4210_get_rate_epll(unsigned long xtal_rate)
+{
+ return s5p_get_pll46xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
+ __raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
+}
+
+static unsigned long exynos4210_get_rate_vpll(unsigned long vpllsrc_rate)
+{
+ return s5p_get_pll46xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
+ __raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
+}
+
+static u32 exynos4_vpll_div[][8] = {
+ { 54000000, 3, 53, 3, 1024, 0, 17, 0 },
+ { 108000000, 3, 53, 2, 1024, 0, 17, 0 },
+};
+
+static int exynos4210_vpll_set_rate(unsigned long rate)
+{
+ unsigned int vpll_con0, vpll_con1 = 0;
+ unsigned int i;
+
+ vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
+ vpll_con0 &= ~(0x1 << 27 | \
+ PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \
+ PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
+ PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+ vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
+ vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT | \
+ PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT | \
+ PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
+
+ for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
+ if (exynos4_vpll_div[i][0] == rate) {
+ vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
+ vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
+ vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
+ vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
+ vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
+ vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
+ vpll_con0 |= exynos4_vpll_div[i][7] << 27;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(exynos4_vpll_div)) {
+ pr_err("%s: Invalid Clock VPLL Frequency\n", __func__);
+ return -EINVAL;
+ }
+
+ __raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
+ __raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
+
+ /* Wait for VPLL lock */
+ while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
+ continue;
+
+ return 0;
+}
+
+/* Exynos4210 specific clock registration */
+void __init exynos4210_clk_init(void)
+{
+ group1_parents[4] = "sclk_usbphy1";
+
+ exynos4_clk_init();
+
+ samsung_clk_register_pll("fout_apll", pll_parent_names,
+ NULL, exynos4210_get_rate_apll);
+ samsung_clk_register_pll("fout_mpll", pll_parent_names,
+ NULL, exynos4210_get_rate_mpll);
+ samsung_clk_register_pll("fout_epll", pll_parent_names,
+ NULL, exynos4210_get_rate_epll);
+ samsung_clk_register_pll("fout_vpll", exynos4210_vpll_parent_names,
+ exynos4210_vpll_set_rate, exynos4210_get_rate_vpll);
+
+ samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks,
+ ARRAY_SIZE(exynos4210_fixed_rate_clks));
+ samsung_clk_register_mux(exynos4210_mux_clks,
+ ARRAY_SIZE(exynos4210_mux_clks));
+
+ pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
+ _get_rate("fout_apll"), _get_rate("fout_mpll"),
+ _get_rate("fout_epll"), _get_rate("fout_vpll"));
+
+ pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
+ " ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
+ _get_rate("aclk_200"), _get_rate("aclk_100"),
+ _get_rate("aclk_160"), _get_rate("aclk_133"));
+}
+
+/*
+ * Exynos4212 Specific Clocks
+ */
+
+static const char *exynos4212_mout_vpll_parents[] __initdata = {
+ "fin_pll", "fout_vpll", };
+
+/* Exynos4212 specific mux clocks */
+static struct samsung_mux_clock exynos4212_mux_clks[] = {
+ MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
+ EXYNOS4_CLKSRC_DMC, 12, 1, 0),
+ MUXCLK(NULL, "mout_vpll", exynos4212_mout_vpll_parents, 0,
+ EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
+};
+
+static unsigned long exynos4212_get_rate_apll(unsigned long xtal_rate)
+{
+ return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
+}
+
+static unsigned long exynos4212_get_rate_mpll(unsigned long xtal_rate)
+{
+ return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_MPLL_CON0));
+}
+
+static unsigned long exynos4212_get_rate_epll(unsigned long xtal_rate)
+{
+ return s5p_get_pll36xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
+ __raw_readl(EXYNOS4_EPLL_CON1));
+}
+
+static unsigned long exynos4212_get_rate_vpll(unsigned long vpllsrc_rate)
+{
+ return s5p_get_pll36xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
+ __raw_readl(EXYNOS4_VPLL_CON1));
+}
+
+/* Exynos4212 specific clock registeration */
+void __init exynos4212_clk_init(void)
+{
+ exynos4_clk_init();
+
+ samsung_clk_register_pll("fout_apll", pll_parent_names,
+ NULL, exynos4212_get_rate_apll);
+ samsung_clk_register_pll("fout_mpll", pll_parent_names,
+ NULL, exynos4212_get_rate_mpll);
+ samsung_clk_register_pll("fout_epll", pll_parent_names,
+ NULL, exynos4212_get_rate_epll);
+ samsung_clk_register_pll("fout_vpll", pll_parent_names,
+ NULL, exynos4212_get_rate_vpll);
+
+ samsung_clk_register_mux(exynos4212_mux_clks,
+ ARRAY_SIZE(exynos4212_mux_clks));
+
+ pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
+ _get_rate("fout_apll"), _get_rate("fout_mpll"),
+ _get_rate("fout_epll"), _get_rate("fout_vpll"));
+
+ pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
+ " ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
+ _get_rate("aclk_200"), _get_rate("aclk_100"),
+ _get_rate("aclk_160"), _get_rate("aclk_133"));
+}
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
new file mode 100644
index 0000000..65156b9
--- /dev/null
+++ b/drivers/clk/samsung/clk.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 Linaro Ltd.
+ *
+ * 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 file includes utility functions to register clocks to common
+ * clock framework for Samsung platforms. This includes an implementation
+ * of Samsung 'pll type' clock to represent the implementation of the
+ * pll found on Samsung platforms. In addition to that, utility functions
+ * to register mux, div, gate and fixed rate types of clocks are included.
+*/
+
+#include "clk.h"
+
+static DEFINE_SPINLOCK(lock);
+
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+
+/* determine the output clock speed of the pll */
+static unsigned long samsung_clk_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
+
+ if (clk_pll->get_rate)
+ return to_clk_pll(hw)->get_rate(parent_rate);
+
+ return 0;
+}
+
+/* round operation not supported */
+static long samsung_clk_pll_round_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long *prate)
+{
+ return samsung_clk_pll_recalc_rate(hw, *prate);
+}
+
+/* set the clock output rate of the pll */
+static int samsung_clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
+
+ if (clk_pll->set_rate)
+ return to_clk_pll(hw)->set_rate(drate);
+
+ return 0;
+}
+
+/* clock operations for samsung pll clock type */
+static const struct clk_ops samsung_clk_pll_ops = {
+ .recalc_rate = samsung_clk_pll_recalc_rate,
+ .round_rate = samsung_clk_pll_round_rate,
+ .set_rate = samsung_clk_pll_set_rate,
+};
+
+/* register a samsung pll type clock */
+void __init samsung_clk_register_pll(const char *name, const char **pnames,
+ int (*set_rate)(unsigned long rate),
+ unsigned long (*get_rate)(unsigned long rate))
+{
+ struct samsung_clk_pll *clk_pll;
+ struct clk *clk;
+ struct clk_init_data init;
+ int ret;
+
+ clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
+ if (!clk_pll) {
+ pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+ return;
+ }
+
+ init.name = name;
+ init.ops = &samsung_clk_pll_ops;
+ init.flags = CLK_GET_RATE_NOCACHE;
+ init.parent_names = pnames;
+ init.num_parents = 1;
+
+ clk_pll->set_rate = set_rate;
+ clk_pll->get_rate = get_rate;
+ clk_pll->hw.init = &init;
+
+ /* register the clock */
+ clk = clk_register(NULL, &clk_pll->hw);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register pll clock %s\n", __func__,
+ name);
+ kfree(clk_pll);
+ return;
+ }
+
+ ret = clk_register_clkdev(clk, name, NULL);
+ if (ret)
+ pr_err("%s: failed to register clock lookup for %s", __func__,
+ name);
+}
+
+/* register a list of fixed clocks */
+void __init samsung_clk_register_fixed_rate(
+ struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
+{
+ struct clk *clk;
+ unsigned int idx, ret;
+
+ for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+ clk = clk_register_fixed_rate(NULL, clk_list->name,
+ clk_list->parent_name, clk_list->flags,
+ clk_list->fixed_rate);
+ if (IS_ERR_OR_NULL(clk)) {
+ pr_err("clock: failed to register clock %s\n",
+ clk_list->name);
+ continue;
+ }
+
+ ret = clk_register_clkdev(clk, clk_list->name,
+ clk_list->dev_name);
+ if (ret)
+ pr_err("clock: failed to register clock lookup for %s",
+ clk_list->name);
+ }
+}
+
+/* register a list of mux clocks */
+void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
+ unsigned int nr_clk)
+{
+ struct clk *clk;
+ unsigned int idx, ret;
+
+ for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+ clk = clk_register_mux(NULL, clk_list->name,
+ clk_list->parent_names, clk_list->num_parents,
+ clk_list->flags, clk_list->reg, clk_list->shift,
+ clk_list->width, clk_list->mux_flags, &lock);
+ if (IS_ERR_OR_NULL(clk)) {
+ pr_err("clock: failed to register clock %s\n",
+ clk_list->name);
+ continue;
+ }
+
+ ret = clk_register_clkdev(clk, clk_list->name,
+ clk_list->dev_name);
+ if (ret)
+ pr_err("clock: failed to register clock lookup for %s",
+ clk_list->name);
+
+ if (clk_list->alias)
+ clk_register_clkdev(clk, clk_list->alias,
+ clk_list->dev_name);
+ }
+}
+
+/* reguster a list of div clocks */
+void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
+ unsigned int nr_clk)
+{
+ struct clk *clk;
+ unsigned int idx, ret;
+
+ for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+ clk = clk_register_divider(NULL, clk_list->name,
+ clk_list->parent_name, clk_list->flags, clk_list->reg,
+ clk_list->shift, clk_list->width, clk_list->div_flags,
+ &lock);
+ if (IS_ERR_OR_NULL(clk)) {
+ pr_err("clock: failed to register clock %s\n",
+ clk_list->name);
+ continue;
+ }
+
+ ret = clk_register_clkdev(clk, clk_list->name,
+ clk_list->dev_name);
+ if (ret)
+ pr_err("clock: failed to register clock lookup for %s",
+ clk_list->name);
+
+ if (clk_list->alias)
+ clk_register_clkdev(clk, clk_list->alias,
+ clk_list->dev_name);
+ }
+}
+
+/* register a list of gate clocks */
+void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
+ unsigned int nr_clk)
+{
+ struct clk *clk;
+ unsigned int idx, ret;
+
+ for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+ clk = clk_register_gate(NULL, clk_list->name,
+ clk_list->parent_name, clk_list->flags, clk_list->reg,
+ clk_list->bit_idx, clk_list->gate_flags, &lock);
+ if (IS_ERR_OR_NULL(clk)) {
+ pr_err("clock: failed to register clock %s\n",
+ clk_list->name);
+ continue;
+ }
+
+ ret = clk_register_clkdev(clk, clk_list->name,
+ clk_list->dev_name);
+ if (ret) {
+ pr_err("clock: failed to register clock lookup for %s",
+ clk_list->name);
+ continue;
+ }
+
+ ret = clk_register_clkdev(clk, clk_list->alias,
+ clk_list->dev_name);
+ if (ret)
+ pr_err("clock: failed to register alias %s for clock "
+ " %s", clk_list->alias, clk_list->name);
+ }
+}
+
+/* utility function to get the rate of a specified clock */
+unsigned long _get_rate(const char *clk_name)
+{
+ struct clk *clk;
+ unsigned long rate;
+
+ clk = clk_get(NULL, clk_name);
+ if (IS_ERR(clk))
+ return 0;
+ rate = clk_get_rate(clk);
+ clk_put(clk);
+ return rate;
+}
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
new file mode 100644
index 0000000..40bdff9
--- /dev/null
+++ b/drivers/clk/samsung/clk.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 Linaro Ltd.
+ *
+ * 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.
+ *
+ * Common Clock Framework support for all Samsung platforms
+*/
+
+#ifndef __SAMSUNG_CLK_H
+#define __SAMSUNG_CLK_H
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <mach/regs-clock.h>
+
+/**
+ * struct samsung_clk_pll: represents a samsung pll type clock
+ * @hw: connection to struct clk.
+ * @set_rate: callback for setting the pll clock rate
+ * @get_rate: callback for determing the pll clock rate
+ *
+ * Internal representation of the pll type clock. Platform specific
+ * implementation can instantiate clocks of this type by calling
+ * samsung_clk_register_pll() function.
+ */
+struct samsung_clk_pll {
+ struct clk_hw hw;
+ int (*set_rate)(unsigned long rate);
+ unsigned long (*get_rate)(unsigned long xtal_rate);
+};
+
+/**
+ * struct samsung_fixed_rate_clock: information about fixed-rate clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this fixed-rate clock.
+ * @parent_name: optional parent clock name.
+ * @flags: optional fixed-rate clock flags.
+ * @fixed-rate: fixed clock rate of this clock.
+ */
+struct samsung_fixed_rate_clock {
+ const char *dev_name;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ unsigned long fixed_rate;
+};
+
+#define FRATE_CLK(dname, cname, pname, f, frate) \
+ { \
+ .dev_name = dname, \
+ .name = cname, \
+ .parent_name = pname, \
+ .flags = f, \
+ .fixed_rate = frate, \
+ }
+
+/**
+ * struct samsung_mux_clock: information about mux clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this mux clock.
+ * @parent_names: array of pointer to parent clock names.
+ * @num_parents: number of parents listed in @parent_names.
+ * @flags: optional flags for basic clock.
+ * @reg: address of register for configuring the mux.
+ * @shift: starting bit location of the mux control bit-field in @reg.
+ * @width: width of the mux control bit-field in @reg.
+ * @mux_flags: flags for mux-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_mux_clock {
+ const char *dev_name;
+ const char *name;
+ const char **parent_names;
+ u8 num_parents;
+ unsigned long flags;
+ void __iomem *reg;
+ u8 shift;
+ u8 width;
+ u8 mux_flags;
+ const char *alias;
+};
+
+#define MUXCLK(dname, cname, pnames, f, r, s, w, mf) \
+ { \
+ .dev_name = dname, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ .reg = r, \
+ .shift = s, \
+ .width = w, \
+ .mux_flags = mf, \
+ }
+
+/**
+ * struct samsung_div_clock: information about div clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this div clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @reg: address of register for configuring the div.
+ * @shift: starting bit location of the div control bit-field in @reg.
+ * @div_flags: flags for div-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_div_clock {
+ const char *dev_name;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ void __iomem *reg;
+ u8 shift;
+ u8 width;
+ u8 div_flags;
+ const char *alias;
+};
+
+#define DIVCLK(dname, cname, pname, f, r, s, w, df) \
+ { \
+ .dev_name = dname, \
+ .name = cname, \
+ .parent_name = pname, \
+ .flags = f, \
+ .reg = r, \
+ .shift = s, \
+ .width = w, \
+ .div_flags = df, \
+ }
+
+/**
+ * struct samsung_gate_clock: information about gate clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this gate clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @reg: address of register for configuring the gate.
+ * @bit_idx: bit index of the gate control bit-field in @reg.
+ * @gate_flags: flags for gate-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_gate_clock {
+ const char *dev_name;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ void __iomem *reg;
+ u8 bit_idx;
+ u8 gate_flags;
+ const char *alias;
+};
+
+#define GATECLK(dname, cname, pname, f, r, b, a) \
+ { \
+ .dev_name = dname, \
+ .name = cname, \
+ .parent_name = pname, \
+ .flags = f, \
+ .reg = r, \
+ .bit_idx = b, \
+ .alias = a, \
+ }
+
+extern void __init samsung_clk_register_pll(const char *name,
+ const char **parent_names,
+ int (*set_rate)(unsigned long rate),
+ unsigned long (*get_rate)(unsigned long rate));
+
+extern void __init samsung_clk_register_fixed_rate(
+ struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
+
+extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
+ unsigned int nr_clk);
+
+extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
+ unsigned int nr_clk);
+
+extern void __init samsung_clk_register_gate(
+ struct samsung_gate_clock *clk_list, unsigned int nr_clk);
+
+extern unsigned long samsung_get_rate_xtal(void);
+
+extern unsigned long _get_rate(const char *clk_name);
+
+#endif /* __SAMSUNG_CLK_H */
--
1.7.1

2012-10-03 07:27:07

by Tomasz Figa

[permalink] [raw]
Subject: Re: [PATCH 0/2] ARM: Exynos4: Migrate to common clock framework.

Hi Chander, Thomas,

On Monday 01 of October 2012 17:39:19 [email protected] wrote:
> From: Thomas Abraham <[email protected]>
>
> This patch series migrates Exynos4 clock support to common clock
> framework. The first patch in this series removes the existing Exynos4
> clock support that uses the Samsung specific clock framework. The second
> patch in this series add Exynos4 clock support using common clock
> framework.
>
> Thomas Abraham (2):
> ARM: Exynos4: Remove Samsung clock type support
> ARM: Exynos4: Register clocks via common clock framework

I think the order of changes is a little bit off here:
- patch 1 will break all exynos4-based boards (what about bisects?)
- patch 2 will be still broken until all related drivers get converted to
use clk_prepare(_enable) and clk_(disable_)unprepare.

Shouldn't the order be exactly opposite, i.e.:
- all the patches for prepare/unprepare first
- then the patch adding common clock frameworks support for exynos4
(disabling the old clock code)
- and finally the patch removing remaining (disabled by previous patch)
code.

Also, I assume that these patches doesn't consider native device tree
support (without auxdata, using OF-based clock lookup), correct me if I'm
wrong. If I'm right, since Exynos SoCs are going to be DT-only, is there
really a point for adding common clock framework support for non-DT
platforms (which are going to be eventually dropped anyway)?

Best regards,
--
Tomasz Figa
Samsung Poland R&D Center

2012-10-03 08:25:25

by Tomasz Figa

[permalink] [raw]
Subject: Re: [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework

Hi Chander, Thomas,

I think this patch could be split into several smaller, while retaining logical integrity of particular patches, e.g.:
- the change introduced to __clk_init (with proper description and rationale why the generic code is being touched)
- generic exynos4 code
- exynos4210-specific code
- exynos4x12-specific code
- patch enabling common clock framework on exynos4.

Also, see some nitpicks inline.

On Monday 01 of October 2012 17:39:21 [email protected] wrote:
> From: Thomas Abraham <[email protected]>
>
> Register clocks for Exynos4 platfotms using common clock framework.
> Also included are set of helper functions for clock registration
> that can be reused on other Samsung platforms as well.
>
> Cc: Mike Turquette <[email protected]>
> Cc: Kukjin Kim <[email protected]>
> Signed-off-by: Thomas Abraham <[email protected]>
> ---
> arch/arm/mach-exynos/Kconfig | 1 +
> arch/arm/mach-exynos/common.h | 3 +
> arch/arm/mach-exynos/mct.c | 11 +-
> arch/arm/plat-samsung/Kconfig | 4 +-
> drivers/clk/Makefile | 1 +
> drivers/clk/clk.c | 12 +-
> drivers/clk/samsung/Makefile | 6 +
> drivers/clk/samsung/clk-exynos4.c | 585
> +++++++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk.c
> | 231 +++++++++++++++
> drivers/clk/samsung/clk.h | 190 ++++++++++++
> 10 files changed, 1037 insertions(+), 7 deletions(-)
> create mode 100644 drivers/clk/samsung/Makefile
> create mode 100644 drivers/clk/samsung/clk-exynos4.c
> create mode 100644 drivers/clk/samsung/clk.c
> create mode 100644 drivers/clk/samsung/clk.h
>
> diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
> index b5b4c8c..4866ec7 100644
> --- a/arch/arm/mach-exynos/Kconfig
> +++ b/arch/arm/mach-exynos/Kconfig
> @@ -15,6 +15,7 @@ config ARCH_EXYNOS4
> bool "SAMSUNG EXYNOS4"
> default y
> select HAVE_SMP
> + select COMMON_CLK
> select MIGHT_HAVE_CACHE_L2X0
> help
> Samsung EXYNOS4 SoCs based systems
> diff --git a/arch/arm/mach-exynos/common.h
> b/arch/arm/mach-exynos/common.h index aed2eeb..2274431 100644
> --- a/arch/arm/mach-exynos/common.h
> +++ b/arch/arm/mach-exynos/common.h
> @@ -21,6 +21,9 @@ void exynos4_restart(char mode, const char *cmd);
> void exynos5_restart(char mode, const char *cmd);
> void exynos_init_late(void);
>
> +void exynos4210_clk_init(void);
> +void exynos4212_clk_init(void);

exynos4x12_clk_init?

> +
> #ifdef CONFIG_PM_GENERIC_DOMAINS
> int exynos_pm_late_initcall(void);
> #else
> diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
> index b601fb8..a7cace0 100644
> --- a/arch/arm/mach-exynos/mct.c
> +++ b/arch/arm/mach-exynos/mct.c
> @@ -30,6 +30,8 @@
> #include <mach/regs-mct.h>
> #include <asm/mach/time.h>
>
> +#include "common.h"
> +
> #define TICK_BASE_CNT 1
>
> enum {
> @@ -457,7 +459,7 @@ static struct local_timer_ops exynos4_mct_tick_ops
> __cpuinitdata = { static void __init exynos4_timer_resources(void)
> {
> struct clk *mct_clk;
> - mct_clk = clk_get(NULL, "xtal");
> + mct_clk = clk_get(NULL, "fin_pll");
>
> clk_rate = clk_get_rate(mct_clk);
>
> @@ -478,6 +480,13 @@ static void __init exynos4_timer_resources(void)
>
> static void __init exynos4_timer_init(void)
> {
> +#ifdef CONFIG_COMMON_CLK
> + if (soc_is_exynos4210())
> + exynos4210_clk_init();
> + else if (soc_is_exynos4212() || soc_is_exynos4412())
> + exynos4212_clk_init();

exynos4x12_clk_init?

> +#endif
> +
> if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
> mct_int_type = MCT_INT_SPI;
> else
> diff --git a/arch/arm/plat-samsung/Kconfig
> b/arch/arm/plat-samsung/Kconfig index 9c3b90c..35b4cb8 100644
> --- a/arch/arm/plat-samsung/Kconfig
> +++ b/arch/arm/plat-samsung/Kconfig
> @@ -26,7 +26,7 @@ config PLAT_S5P
> select S5P_GPIO_DRVSTR
> select SAMSUNG_GPIOLIB_4BIT
> select PLAT_SAMSUNG
> - select SAMSUNG_CLKSRC
> + select SAMSUNG_CLKSRC if !COMMON_CLK
> select SAMSUNG_IRQ_VIC_TIMER
> help
> Base platform code for Samsung's S5P series SoC.
> @@ -89,7 +89,7 @@ config SAMSUNG_CLKSRC
> used by newer systems such as the S3C64XX.
>
> config S5P_CLOCK
> - def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
> + def_bool ((ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
> && !COMMON_CLK) help
> Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
>
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 6327536..5f5b060 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -16,6 +16,7 @@ obj-$(CONFIG_ARCH_MMP) += mmp/
> endif
> obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
> obj-$(CONFIG_ARCH_U8500) += ux500/
> +obj-$(CONFIG_PLAT_SAMSUNG) += samsung/
>
> # Chip specific
> obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 56e4495..456c50b 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1196,6 +1196,7 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
> int __clk_init(struct device *dev, struct clk *clk)
> {
> int i, ret = 0;
> + u8 index;
> struct clk *orphan;
> struct hlist_node *tmp, *tmp2;
>
> @@ -1259,6 +1260,7 @@ int __clk_init(struct device *dev, struct clk *clk)
> __clk_lookup(clk->parent_names[i]);
> }
>
> +


Unnecessary extra blank line?

> clk->parent = __clk_init_parent(clk);
>
> /*
> @@ -1298,11 +1300,13 @@ int __clk_init(struct device *dev, struct clk
> *clk) * this clock
> */
> hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list,
> child_node) - for (i = 0; i < orphan->num_parents; i++)
> - if (!strcmp(clk->name, orphan->parent_names[i])) {
> + if (orphan->num_parents > 1) {
> + index = orphan->ops->get_parent(orphan->hw);
> + if (!strcmp(clk->name, orphan->parent_names[index]))
> __clk_reparent(orphan, clk);
> - break;
> - }
> + } else if (!strcmp(clk->name, orphan->parent_names[0])) {
> + __clk_reparent(orphan, clk);
> + }
>
> /*
> * optional platform-specific magic
> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
> new file mode 100644
> index 0000000..69487f7
> --- /dev/null
> +++ b/drivers/clk/samsung/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Samsung Clock specific Makefile
> +#
> +
> +obj-$(CONFIG_PLAT_SAMSUNG) += clk.o
> +obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
> diff --git a/drivers/clk/samsung/clk-exynos4.c
> b/drivers/clk/samsung/clk-exynos4.c new file mode 100644
> index 0000000..74a6f03
> --- /dev/null
> +++ b/drivers/clk/samsung/clk-exynos4.c
> @@ -0,0 +1,585 @@
> +/*
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * Copyright (c) 2012 Linaro Ltd.
> + *
> + * 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.
> + *
> + * Common Clock Framework support for all Exynos4 platforms
> +*/
> +
> +#include <linux/clk.h>
> +#include <linux/clkdev.h>
> +#include <linux/io.h>
> +#include <linux/clk-provider.h>
> +
> +#include <plat/pll.h>
> +#include <plat/cpu.h>
> +#include <mach/regs-clock.h>
> +#include <mach/sysmmu.h>
> +#include <plat/map-s5p.h>
> +
> +#include "clk.h"
> +
> +#define EXYNOS4_OP_MODE (S5P_VA_CHIPID + 8)
> +
> +static const char *pll_parent_names[] __initdata = { "fin_pll" };
> +static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
> +static const char *mout_apll_parents[] __initdata = { "fin_pll",
> "fout_apll", }; +static const char *mout_mpll_parents[] __initdata = {
> "fin_pll", "fout_mpll", }; +static const char *mout_epll_parents[]
> __initdata = { "fin_pll", "fout_epll", }; +
> +static const char *sclk_ampll_parents[] __initdata = {
> + "mout_mpll", "sclk_apll", };
> +
> +static const char *sclk_evpll_parents[] __initdata = {
> + "mout_epll", "mout_vpll", };
> +
> +static const char *mout_core_parents[] __initdata = {
> + "mout_apll", "mout_mpll", };
> +
> +static const char *mout_mfc_parents[] __initdata = {
> + "mout_mfc0", "mout_mfc1", };
> +
> +static const char *mout_dac_parents[] __initdata = {
> + "mout_vpll", "sclk_hdmiphy", };
> +
> +static const char *mout_hdmi_parents[] __initdata = {
> + "sclk_pixel", "sclk_hdmiphy", };
> +
> +static const char *mout_mixer_parents[] __initdata = {
> + "sclk_dac", "sclk_hdmi", };
> +
> +static const char *group1_parents[] __initdata = {
> + "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
> + "none", "sclk_hdmiphy", "mout_mpll", "mout_epll",
> + "mout_vpll" };
> +
> +static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
> + FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
> + FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),
> + FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
> + FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
> + FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
> +};
> +
> +static struct samsung_mux_clock exynos4_mux_clks[] = {
> + MUXCLK(NULL, "fin_pll", fin_pll_parents, 0,
> + EXYNOS4_OP_MODE, 0, 1, 0),
> + MUXCLK(NULL, "mout_apll", mout_apll_parents, 0,
> + EXYNOS4_CLKSRC_CPU, 0, 1, 0),
> + MUXCLK(NULL, "mout_epll", mout_epll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 4, 1, 0),
> + MUXCLK(NULL, "mout_core", mout_core_parents, 0,
> + EXYNOS4_CLKSRC_CPU, 16, 1, 0),
> + MUXCLK(NULL, "mout_aclk_200", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 12, 1, 0),
> + MUXCLK(NULL, "mout_aclk_100", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 16, 1, 0),
> + MUXCLK(NULL, "mout_aclk_160", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 20, 1, 0),
> + MUXCLK(NULL, "mout_aclk_133", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 24, 1, 0),
> + MUXCLK("exynos4210-uart.0", "mout_uart0", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 0, 4, 0),
> + MUXCLK("exynos4210-uart.1", "mout_uart1", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 4, 4, 0),
> + MUXCLK("exynos4210-uart.2", "mout_uart2", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 8, 4, 0),
> + MUXCLK("exynos4210-uart.3", "mout_uart3", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 12, 4, 0),
> + MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
> + MUXCLK("exynos4210-spi.0", "mout_spi0", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL1, 16, 4, 0),
> + MUXCLK("exynos4210-spi.1", "mout_spi1", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL1, 20, 4, 0),
> + MUXCLK("exynos4210-spi.2", "mout_spi2", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL1, 24, 4, 0),
> + MUXCLK(NULL, "mout_sata", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 24, 1, 0),
> + MUXCLK(NULL, "mout_mfc0", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_MFC, 0, 1, 0),
> + MUXCLK(NULL, "mout_mfc1", sclk_evpll_parents, 0,
> + EXYNOS4_CLKSRC_MFC, 4, 1, 0),
> + MUXCLK("s5p-mfc", "mout_mfc", mout_mfc_parents, 0,
> + EXYNOS4_CLKSRC_MFC, 8, 1, 0),
> + MUXCLK("s5p-mipi-csis.0", "mout_csis0", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 24, 4, 0),
> + MUXCLK("s5p-mipi-csis.1", "mout_csis1", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 28, 4, 0),
> + MUXCLK(NULL, "mout_cam0", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 16, 4, 0),
> + MUXCLK(NULL, "mout_cam1", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 20, 4, 0),
> + MUXCLK("exynos4-fimc.0", "mout_fimc0", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 0, 4, 0),
> + MUXCLK("exynos4-fimc.1", "mout_fimc1", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 4, 4, 0),
> + MUXCLK("exynos4-fimc.2", "mout_fimc2", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 8, 4, 0),
> + MUXCLK("exynos4-fimc.3", "mout_fimc3", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 12, 4, 0),
> + MUXCLK("exynos4-fb.0", "mout_fimd0", group1_parents, 0,
> + EXYNOS4_CLKSRC_LCD0, 0, 4, 0),
> + MUXCLK(NULL, "sclk_dac", mout_dac_parents, 0,
> + EXYNOS4_CLKSRC_TV, 8, 1, 0),
> + MUXCLK(NULL, "sclk_hdmi", mout_hdmi_parents, 0,
> + EXYNOS4_CLKSRC_TV, 0, 1, 0),
> + MUXCLK(NULL, "sclk_mixer", mout_mixer_parents, 0,
> + EXYNOS4_CLKSRC_TV, 4, 1, 0),
> +};
> +
> +static struct samsung_div_clock exynos4_div_clks[] = {
> + DIVCLK(NULL, "sclk_apll", "mout_apll", 0,
> + EXYNOS4_CLKDIV_CPU, 24, 3, 0),
> + DIVCLK(NULL, "div_core", "mout_core", 0,
> + EXYNOS4_CLKDIV_CPU, 0, 3, 0),
> + DIVCLK(NULL, "armclk", "div_core", 0,
> + EXYNOS4_CLKDIV_CPU, 28, 3, 0),
> + DIVCLK(NULL, "aclk_200", "mout_aclk_200", 0,
> + EXYNOS4_CLKDIV_TOP, 0, 3, 0),
> + DIVCLK(NULL, "aclk_100", "mout_aclk_100", 0,
> + EXYNOS4_CLKDIV_TOP, 4, 4, 0),
> + DIVCLK(NULL, "aclk_160", "mout_aclk_160", 0,
> + EXYNOS4_CLKDIV_TOP, 8, 3, 0),
> + DIVCLK(NULL, "aclk_133", "mout_aclk_133", 0,
> + EXYNOS4_CLKDIV_TOP, 12, 3, 0),
> + DIVCLK("exynos4210-uart.0", "div_uart0", "mout_uart0", 0,
> + EXYNOS4_CLKDIV_PERIL0, 0, 4, 0),
> + DIVCLK("exynos4210-uart.1", "div_uart1", "mout_uart1", 0,
> + EXYNOS4_CLKDIV_PERIL0, 4, 4, 0),
> + DIVCLK("exynos4210-uart.2", "div_uart2", "mout_uart2", 0,
> + EXYNOS4_CLKDIV_PERIL0, 8, 4, 0),
> + DIVCLK("exynos4210-uart.3", "div_uart3", "mout_uart3", 0,
> + EXYNOS4_CLKDIV_PERIL0, 12, 4, 0),
> + DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
> + EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
> + DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
> + EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
> + DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
> + EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
> + DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
> + EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
> + DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
> + EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
> + DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
> + EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
> + DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
> + EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
> + DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
> + EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
> + DIVCLK("exynos4210-spi.0", "div_spi0", "mout_spi0", 0,
> + EXYNOS4_CLKDIV_PERIL1, 0, 4, 0),
> + DIVCLK("exynos4210-spi.1", "div_spi1", "mout_spi1", 0,
> + EXYNOS4_CLKDIV_PERIL1, 16, 4, 0),
> + DIVCLK("exynos4210-spi.2", "div_spi2", "mout_spi2", 0,
> + EXYNOS4_CLKDIV_PERIL2, 0, 4, 0),
> + DIVCLK("exynos4210-spi.0", "div_spi0_pre", "div_spi0", 0,
> + EXYNOS4_CLKDIV_PERIL1, 8, 8, 0),
> + DIVCLK("exynos4210-spi.1", "div_spi1_pre", "div_spi1", 0,
> + EXYNOS4_CLKDIV_PERIL1, 24, 8, 0),
> + DIVCLK("exynos4210-spi.2", "div_spi2_pre", "div_spi2", 0,
> + EXYNOS4_CLKDIV_PERIL2, 8, 8, 0),
> + DIVCLK(NULL, "div_sata", "mout_sata", 0,
> + EXYNOS4_CLKDIV_FSYS0, 20, 4, 0),
> + DIVCLK("s5p-mfc", "div_mfc", "mout_mfc", 0,
> + EXYNOS4_CLKDIV_MFC, 0, 4, 0),
> + DIVCLK("s5p-mipi-csis.0", "div_csis0", "mout_csis0", 0,
> + EXYNOS4_CLKDIV_CAM, 24, 4, 0),
> + DIVCLK("s5p-mipi-csis.1", "div_csis1", "mout_csis1", 0,
> + EXYNOS4_CLKDIV_CAM, 28, 4, 0),
> + DIVCLK(NULL, "div_cam0", "mout_cam0", 0,
> + EXYNOS4_CLKDIV_CAM, 16, 4, 0),
> + DIVCLK(NULL, "div_cam1", "mout_cam1", 0,
> + EXYNOS4_CLKDIV_CAM, 20, 4, 0),
> + DIVCLK("exynos4-fimc.0", "div_fimc0", "mout_fimc0", 0,
> + EXYNOS4_CLKDIV_CAM, 0, 4, 0),
> + DIVCLK("exynos4-fimc.1", "div_fimc1", "mout_fimc1", 0,
> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
> + DIVCLK("exynos4-fimc.2", "div_fimc2", "mout_fimc2", 0,
> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
> + DIVCLK("exynos4-fimc.3", "div_fimc3", "mout_fimc3", 0,
> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
> + DIVCLK("exynos4-fb.0", "div_fimd0", "mout_fimd0", 0,
> + EXYNOS4_CLKDIV_LCD0, 0, 4, 0),
> + DIVCLK(NULL, "sclk_pixel", "mout_vpll", 0,
> + EXYNOS4_CLKDIV_TV, 0, 4, 0),
> +};
> +
> +struct samsung_gate_clock exynos4_gate_clks[] = {
> + GATECLK("exynos4210-uart.0", "uart0", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 0, "uart"),
> + GATECLK("exynos4210-uart.1", "uart1", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 1, "uart"),
> + GATECLK("exynos4210-uart.2", "uart2", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 2, "uart"),
> + GATECLK("exynos4210-uart.3", "uart3", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 3, "uart"),
> + GATECLK("exynos4210-uart.4", "uart4", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 4, "uart"),
> + GATECLK("exynos4210-uart.5", "uart5", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 5, "uart"),
> + GATECLK("exynos4210-uart.0", "uclk0", "div_uart0", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 0, "clk_uart_baud0"),
> + GATECLK("exynos4210-uart.1", "uclk1", "div_uart1", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 4, "clk_uart_baud0"),
> + GATECLK("exynos4210-uart.2", "uclk2", "div_uart2", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 8, "clk_uart_baud0"),
> + GATECLK("exynos4210-uart.3", "uclk3", "div_uart3", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 12, "clk_uart_baud0"),
> + GATECLK(NULL, "timers", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 24, NULL),
> + GATECLK("s5p-mipi-csis.0", "csis", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 5, NULL),
> + GATECLK(NULL, "jpeg", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 6, NULL),
> + GATECLK("exynos4-fimc.0", "fimc0", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 0, "fimc"),
> + GATECLK("exynos4-fimc.1", "fimc1", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 1, "fimc"),
> + GATECLK("exynos4-fimc.2", "fimc2", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 2, "fimc"),
> + GATECLK("exynos4-fimc.3", "fimc3", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 3, "fimc"),
> + GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
> + GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
> + GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
> + GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
> + GATECLK(NULL, "dwmmc", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 9, NULL),
> + GATECLK("s5p-sdo", "dac", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 2, NULL),
> + GATECLK("s5p-mixer", "mixer", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 1, NULL),
> + GATECLK("s5p-mixer", "vp", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 0, NULL),
> + GATECLK("exynos4-hdmi", "hdmi", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 3, NULL),
> + GATECLK("exynos4-hdmi", "hdmiphy", "aclk_160", 0,
> + S5P_HDMI_PHY_CONTROL, 0, NULL),
> + GATECLK("s5p-sdo", "dacphy", "aclk_160", 0,
> + S5P_DAC_PHY_CONTROL, 0, NULL),
> + GATECLK(NULL, "adc", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 15, NULL),
> + GATECLK(NULL, "keypad", "aclk_100", 0,
> + EXYNOS4210_CLKGATE_IP_PERIR, 16, NULL),
> + GATECLK(NULL, "rtc", "aclk_100", 0,
> + EXYNOS4210_CLKGATE_IP_PERIR, 15, NULL),
> + GATECLK(NULL, "watchdog", "aclk_100", 0,
> + EXYNOS4210_CLKGATE_IP_PERIR, 14, NULL),
> + GATECLK(NULL, "usbhost", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 12, NULL),
> + GATECLK(NULL, "otg", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 13, NULL),
> + GATECLK("exynos4210-spi.0", "spi0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 16, "spi"),
> + GATECLK("exynos4210-spi.1", "spi1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 17, "spi"),
> + GATECLK("exynos4210-spi.2", "spi2", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 18, "spi"),
> + GATECLK("samsung-i2s.0", "iis0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 19, "iis"),
> + GATECLK("samsung-i2s.1", "iis1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 20, "iis"),
> + GATECLK("samsung-i2s.2", "iis2", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 21, "iis"),
> + GATECLK("samsung-ac97", "ac97", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 27, NULL),
> + GATECLK("s5p-mfc", "mfc", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_MFC, 0, NULL),
> + GATECLK("s3c2440-i2c.0", "i2c0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 6, "i2c"),
> + GATECLK("s3c2440-i2c.1", "i2c1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 7, "i2c"),
> + GATECLK("s3c2440-i2c.2", "i2c2", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 8, "i2c"),
> + GATECLK("s3c2440-i2c.3", "i2c3", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 9, "i2c"),
> + GATECLK("s3c2440-i2c.4", "i2c4", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 10, "i2c"),
> + GATECLK("s3c2440-i2c.5", "i2c5", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 11, "i2c"),
> + GATECLK("s3c2440-i2c.6", "i2c6", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 12, "i2c"),
> + GATECLK("s3c2440-i2c.7", "i2c7", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 13, "i2c"),
> + GATECLK("s3c2440-hdmiphy-i2c", "i2c", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 14, NULL),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_l, 0), "sysmmu0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_MFC, 1, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_r, 1), "sysmmu1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_MFC, 2, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(tv, 2), "sysmmu2", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 4, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(jpeg, 3), "sysmmu3", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 11, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(rot, 4), "sysmmu4", "aclk_200", 0,
> + EXYNOS4210_CLKGATE_IP_IMAGE, 4, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc0, 5), "sysmmu5", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 7, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc1, 6), "sysmmu6", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 8, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc2, 7), "sysmmu7", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 9, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc3, 8), "sysmmu8", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 10, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimd, 10), "sysmmu10", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_LCD0, 4, "sysmmu"),
> + GATECLK("dma-pl330.0", "dma0", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 0, "dma"),
> + GATECLK("dma-pl330.1", "dma1", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 1, "dma"),
> + GATECLK("exynos4-fb.0", "fimd", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_LCD0, 0, "lcd"),
> + GATECLK("exynos4210-spi.0", "sclk_spi0", "div_spi0_pre", 0,
> + EXYNOS4_CLKSRC_MASK_PERIL1, 16, "spi_busclk0"),
> + GATECLK("exynos4210-spi.1", "sclk_spi1", "div_spi1_pre", 0,
> + EXYNOS4_CLKSRC_MASK_PERIL1, 20, "spi_busclk0"),
> + GATECLK("exynos4210-spi.2", "sclk_spi2", "div_spi2_pre", 0,
> + EXYNOS4_CLKSRC_MASK_PERIL1, 24, "spi_busclk0"),
> + GATECLK("exynos4-sdhci.0", "sclk_mmc0", "div_mmc0_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 0, "mmc_busclk.2"),
> + GATECLK("exynos4-sdhci.1", "sclk_mmc1", "div_mmc1_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 4, "mmc_busclk.2"),
> + GATECLK("exynos4-sdhci.2", "sclk_mmc2", "div_mmc2_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 8, "mmc_busclk.2"),
> + GATECLK("exynos4-sdhci.3", "sclk_mmc3", "div_mmc3_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 12, "mmc_busclk.2"),
> + GATECLK("s5p-mipi-csis.0", "sclk_csis0", "div_csis0", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 24, "sclk_csis"),
> + GATECLK("s5p-mipi-csis.1", "sclk_csis1", "div_csis1", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
> + GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
> + GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
> + GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),

+ GATECLK("exynos4-fimc.0", "sclk_fimc0", "div_fimc0", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),

> + GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),

+ GATECLK("exynos4-fimc.1", "sclk_fimc1", "div_fimc1", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),

> + GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),

+ GATECLK("exynos4-fimc.2", "sclk_fimc2", "div_fimc2", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),

> + GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),

+ GATECLK("exynos4-fimc.3", "sclk_fimc3", "div_fimc3", 0,
+ EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),

> + GATECLK("exynos4-fb.0", "sclk_fimd", "div_fimd0", 0,
> + EXYNOS4_CLKSRC_MASK_LCD0, 0, "sclk_fimd"),
> +};
> +
> +/* register clock common to all Exynos4 platforms */
> +void __init exynos4_clk_init(void)
> +{
> + samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
> + ARRAY_SIZE(exynos4_fixed_rate_clks));
> + samsung_clk_register_mux(exynos4_mux_clks,
> + ARRAY_SIZE(exynos4_mux_clks));
> + samsung_clk_register_div(exynos4_div_clks,
> + ARRAY_SIZE(exynos4_div_clks));
> + samsung_clk_register_gate(exynos4_gate_clks,
> + ARRAY_SIZE(exynos4_gate_clks));
> +}
> +
> +/*
> + * Exynos4210 Specific Clocks
> + */
> +
> +static const char *exynos4210_vpll_parent_names[] __initdata = {
> + "mout_vpll_src" };
> +static const char *mout_vpll_src_parents[] __initdata = {
> + "fin_pll", "sclk_hdmi24m" };
> +static const char *exynos4210_mout_vpll_parents[] __initdata = {
> + "mout_vpll_src", "fout_vpll", };
> +
> +/* Exynos4210 specific fixed rate clocks */
> +static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] = {
> + FRATE_CLK(NULL, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
> +};
> +
> +/* Exynos4210 specific mux-type clocks */
> +static struct samsung_mux_clock exynos4210_mux_clks[] = {
> + MUXCLK(NULL, "mout_vpll_src", mout_vpll_src_parents, 0,
> + EXYNOS4_CLKSRC_TOP1, 0, 1, 0),
> + MUXCLK(NULL, "mout_vpll", exynos4210_mout_vpll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
> + MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
> + EXYNOS4_CLKSRC_CPU, 8, 1, 0),
> +};
> +
> +static unsigned long exynos4210_get_rate_apll(unsigned long xtal_rate)
> +{
> + return s5p_get_pll45xx(xtal_rate,
> + __raw_readl(EXYNOS4_APLL_CON0), pll_4508);
> +}
> +
> +static unsigned long exynos4210_get_rate_mpll(unsigned long xtal_rate)
> +{
> + return s5p_get_pll45xx(xtal_rate,
> + __raw_readl(EXYNOS4_MPLL_CON0), pll_4508);
> +}
> +
> +static unsigned long exynos4210_get_rate_epll(unsigned long xtal_rate)
> +{
> + return s5p_get_pll46xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
> + __raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
> +}
> +
> +static unsigned long exynos4210_get_rate_vpll(unsigned long
> vpllsrc_rate) +{
> + return s5p_get_pll46xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
> + __raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
> +}
> +
> +static u32 exynos4_vpll_div[][8] = {
> + { 54000000, 3, 53, 3, 1024, 0, 17, 0 },
> + { 108000000, 3, 53, 2, 1024, 0, 17, 0 },
> +};
> +
> +static int exynos4210_vpll_set_rate(unsigned long rate)
> +{
> + unsigned int vpll_con0, vpll_con1 = 0;
> + unsigned int i;
> +
> + vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
> + vpll_con0 &= ~(0x1 << 27 | \
> + PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \
> + PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
> + PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
> +
> + vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
> + vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT | \
> + PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT | \
> + PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
> +
> + for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
> + if (exynos4_vpll_div[i][0] == rate) {
> + vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
> + vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
> + vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
> + vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
> + vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
> + vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
> + vpll_con0 |= exynos4_vpll_div[i][7] << 27;
> + break;
> + }
> + }
> +
> + if (i == ARRAY_SIZE(exynos4_vpll_div)) {
> + pr_err("%s: Invalid Clock VPLL Frequency\n", __func__);
> + return -EINVAL;
> + }
> +
> + __raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
> + __raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
> +
> + /* Wait for VPLL lock */
> + while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
> + continue;

Is it guaranteed to lock in some reasonable time? Maybe some kind of
timeout should be added?

> +
> + return 0;
> +}
> +
> +/* Exynos4210 specific clock registration */
> +void __init exynos4210_clk_init(void)
> +{
> + group1_parents[4] = "sclk_usbphy1";
> +
> + exynos4_clk_init();
> +
> + samsung_clk_register_pll("fout_apll", pll_parent_names,
> + NULL, exynos4210_get_rate_apll);
> + samsung_clk_register_pll("fout_mpll", pll_parent_names,
> + NULL, exynos4210_get_rate_mpll);
> + samsung_clk_register_pll("fout_epll", pll_parent_names,
> + NULL, exynos4210_get_rate_epll);
> + samsung_clk_register_pll("fout_vpll", exynos4210_vpll_parent_names,
> + exynos4210_vpll_set_rate, exynos4210_get_rate_vpll);
> +
> + samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks,
> + ARRAY_SIZE(exynos4210_fixed_rate_clks));
> + samsung_clk_register_mux(exynos4210_mux_clks,
> + ARRAY_SIZE(exynos4210_mux_clks));
> +
> + pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
> + _get_rate("fout_apll"), _get_rate("fout_mpll"),
> + _get_rate("fout_epll"), _get_rate("fout_vpll"));
> +
> + pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
> + " ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
> + _get_rate("aclk_200"), _get_rate("aclk_100"),
> + _get_rate("aclk_160"), _get_rate("aclk_133"));
> +}
> +
> +/*
> + * Exynos4212 Specific Clocks
> + */
> +
> +static const char *exynos4212_mout_vpll_parents[] __initdata = {
> + "fin_pll", "fout_vpll", };
> +
> +/* Exynos4212 specific mux clocks */
> +static struct samsung_mux_clock exynos4212_mux_clks[] = {
> + MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
> + EXYNOS4_CLKSRC_DMC, 12, 1, 0),
> + MUXCLK(NULL, "mout_vpll", exynos4212_mout_vpll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
> +};
> +
> +static unsigned long exynos4212_get_rate_apll(unsigned long xtal_rate)
> +{
> + return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
> +}
> +
> +static unsigned long exynos4212_get_rate_mpll(unsigned long xtal_rate)
> +{
> + return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_MPLL_CON0));
> +}
> +
> +static unsigned long exynos4212_get_rate_epll(unsigned long xtal_rate)
> +{
> + return s5p_get_pll36xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
> + __raw_readl(EXYNOS4_EPLL_CON1));
> +}
> +
> +static unsigned long exynos4212_get_rate_vpll(unsigned long
> vpllsrc_rate) +{
> + return s5p_get_pll36xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
> + __raw_readl(EXYNOS4_VPLL_CON1));
> +}
> +
> +/* Exynos4212 specific clock registeration */
> +void __init exynos4212_clk_init(void)
> +{
> + exynos4_clk_init();
> +
> + samsung_clk_register_pll("fout_apll", pll_parent_names,
> + NULL, exynos4212_get_rate_apll);
> + samsung_clk_register_pll("fout_mpll", pll_parent_names,
> + NULL, exynos4212_get_rate_mpll);
> + samsung_clk_register_pll("fout_epll", pll_parent_names,
> + NULL, exynos4212_get_rate_epll);
> + samsung_clk_register_pll("fout_vpll", pll_parent_names,
> + NULL, exynos4212_get_rate_vpll);
> +
> + samsung_clk_register_mux(exynos4212_mux_clks,
> + ARRAY_SIZE(exynos4212_mux_clks));
> +
> + pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
> + _get_rate("fout_apll"), _get_rate("fout_mpll"),
> + _get_rate("fout_epll"), _get_rate("fout_vpll"));
> +
> + pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
> + " ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
> + _get_rate("aclk_200"), _get_rate("aclk_100"),
> + _get_rate("aclk_160"), _get_rate("aclk_133"));
> +}
> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
> new file mode 100644
> index 0000000..65156b9
> --- /dev/null
> +++ b/drivers/clk/samsung/clk.c
> @@ -0,0 +1,231 @@
> +/*
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * Copyright (c) 2012 Linaro Ltd.
> + *
> + * 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 file includes utility functions to register clocks to common
> + * clock framework for Samsung platforms. This includes an
> implementation + * of Samsung 'pll type' clock to represent the
> implementation of the + * pll found on Samsung platforms. In addition to
> that, utility functions + * to register mux, div, gate and fixed rate
> types of clocks are included. +*/
> +
> +#include "clk.h"
> +
> +static DEFINE_SPINLOCK(lock);
> +
> +#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
> +
> +/* determine the output clock speed of the pll */
> +static unsigned long samsung_clk_pll_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
> +
> + if (clk_pll->get_rate)
> + return to_clk_pll(hw)->get_rate(parent_rate);
> +
> + return 0;
> +}
> +
> +/* round operation not supported */
> +static long samsung_clk_pll_round_rate(struct clk_hw *hw, unsigned long
> drate, + unsigned long *prate)
> +{
> + return samsung_clk_pll_recalc_rate(hw, *prate);
> +}
> +
> +/* set the clock output rate of the pll */
> +static int samsung_clk_pll_set_rate(struct clk_hw *hw, unsigned long
> drate, + unsigned long prate)
> +{
> + struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
> +
> + if (clk_pll->set_rate)
> + return to_clk_pll(hw)->set_rate(drate);
> +
> + return 0;
> +}
> +
> +/* clock operations for samsung pll clock type */
> +static const struct clk_ops samsung_clk_pll_ops = {
> + .recalc_rate = samsung_clk_pll_recalc_rate,
> + .round_rate = samsung_clk_pll_round_rate,
> + .set_rate = samsung_clk_pll_set_rate,
> +};
> +
> +/* register a samsung pll type clock */
> +void __init samsung_clk_register_pll(const char *name, const char
> **pnames, + int (*set_rate)(unsigned long rate),
> + unsigned long (*get_rate)(unsigned long rate))
> +{
> + struct samsung_clk_pll *clk_pll;
> + struct clk *clk;
> + struct clk_init_data init;
> + int ret;
> +
> + clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
> + if (!clk_pll) {
> + pr_err("%s: could not allocate pll clk %s\n", __func__, name);
> + return;
> + }
> +
> + init.name = name;
> + init.ops = &samsung_clk_pll_ops;
> + init.flags = CLK_GET_RATE_NOCACHE;
> + init.parent_names = pnames;
> + init.num_parents = 1;
> +
> + clk_pll->set_rate = set_rate;
> + clk_pll->get_rate = get_rate;
> + clk_pll->hw.init = &init;
> +
> + /* register the clock */
> + clk = clk_register(NULL, &clk_pll->hw);
> + if (IS_ERR(clk)) {
> + pr_err("%s: failed to register pll clock %s\n", __func__,
> + name);
> + kfree(clk_pll);
> + return;
> + }
> +
> + ret = clk_register_clkdev(clk, name, NULL);
> + if (ret)
> + pr_err("%s: failed to register clock lookup for %s", __func__,
> + name);
> +}
> +
> +/* register a list of fixed clocks */
> +void __init samsung_clk_register_fixed_rate(
> + struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> + clk = clk_register_fixed_rate(NULL, clk_list->name,
> + clk_list->parent_name, clk_list->flags,
> + clk_list->fixed_rate);
> + if (IS_ERR_OR_NULL(clk)) {

Is the check for NULL needed here? Looking at samsung_fixed_rate_clock
and clk_register, the convention is to always return ERR_PTR on error.

> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> + }
> +}
> +
> +/* register a list of mux clocks */
> +void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
> + unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> + clk = clk_register_mux(NULL, clk_list->name,
> + clk_list->parent_names, clk_list->num_parents,
> + clk_list->flags, clk_list->reg, clk_list->shift,
> + clk_list->width, clk_list->mux_flags, &lock);
> + if (IS_ERR_OR_NULL(clk)) {

See my comment for samsung_clk_register_fixed_rate .

> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> +
> + if (clk_list->alias)
> + clk_register_clkdev(clk, clk_list->alias,
> + clk_list->dev_name);
> + }
> +}
> +
> +/* reguster a list of div clocks */
> +void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
> + unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> + clk = clk_register_divider(NULL, clk_list->name,
> + clk_list->parent_name, clk_list->flags, clk_list->reg,
> + clk_list->shift, clk_list->width, clk_list->div_flags,
> + &lock);
> + if (IS_ERR_OR_NULL(clk)) {

See my comment for samsung_clk_register_fixed_rate .

> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> +
> + if (clk_list->alias)
> + clk_register_clkdev(clk, clk_list->alias,
> + clk_list->dev_name);
> + }
> +}
> +
> +/* register a list of gate clocks */
> +void __init samsung_clk_register_gate(struct samsung_gate_clock
> *clk_list, + unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> + clk = clk_register_gate(NULL, clk_list->name,
> + clk_list->parent_name, clk_list->flags, clk_list->reg,
> + clk_list->bit_idx, clk_list->gate_flags, &lock);
> + if (IS_ERR_OR_NULL(clk)) {

See my comment for samsung_clk_register_fixed_rate .

> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret) {
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->alias,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register alias %s for clock "
> + " %s", clk_list->alias, clk_list->name);
> + }
> +}
> +
> +/* utility function to get the rate of a specified clock */
> +unsigned long _get_rate(const char *clk_name)
> +{
> + struct clk *clk;
> + unsigned long rate;
> +
> + clk = clk_get(NULL, clk_name);
> + if (IS_ERR(clk))
> + return 0;
> + rate = clk_get_rate(clk);
> + clk_put(clk);
> + return rate;
> +}

Shouldn't it be moved to clk-exynos4.c and made static?

Best regards,
--
Tomasz Figa
Samsung Poland R&D Center

2012-10-03 10:40:31

by Tomasz Figa

[permalink] [raw]
Subject: Re: [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework

Hi Chander, Thomas,

I can see one more problem here.

Based on the fact that sdhci-s3c driver receives only the endpoint gate
clock (hsmmc), doesn't the following setup make the driver unable to change
the frequency of this clock?

On Monday 01 of October 2012 17:39:21 [email protected] wrote:
> +static struct samsung_mux_clock exynos4_mux_clks[] = {
[snip]
> + MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
[snip]
> +};
> +
> +static struct samsung_div_clock exynos4_div_clks[] = {
[snip]
> + DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
> + EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
> + DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
> + EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
> + DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
> + EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
> + DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
> + EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
> + DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
> + EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
> + DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
> + EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
> + DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
> + EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
> + DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
> + EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
[snip]
> +};
> +
> +struct samsung_gate_clock exynos4_gate_clks[] = {
[snip]
> + GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
> + GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
> + GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
> + GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
[snip]
> +};

Best regards,
--
Tomasz Figa
Samsung Poland R&D Center

2012-10-05 15:21:49

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework

Hello,

On 10/01/2012 02:09 PM, [email protected] wrote:
> From: Thomas Abraham<[email protected]>
>
> Register clocks for Exynos4 platfotms using common clock framework.
> Also included are set of helper functions for clock registration
> that can be reused on other Samsung platforms as well.
>
> Cc: Mike Turquette<[email protected]>
> Cc: Kukjin Kim<[email protected]>
> Signed-off-by: Thomas Abraham<[email protected]>
> ---
> arch/arm/mach-exynos/Kconfig | 1 +
> arch/arm/mach-exynos/common.h | 3 +
> arch/arm/mach-exynos/mct.c | 11 +-
> arch/arm/plat-samsung/Kconfig | 4 +-
> drivers/clk/Makefile | 1 +
> drivers/clk/clk.c | 12 +-
> drivers/clk/samsung/Makefile | 6 +
> drivers/clk/samsung/clk-exynos4.c | 585 +++++++++++++++++++++++++++++++++++++
> drivers/clk/samsung/clk.c | 231 +++++++++++++++
> drivers/clk/samsung/clk.h | 190 ++++++++++++
> 10 files changed, 1037 insertions(+), 7 deletions(-)
> create mode 100644 drivers/clk/samsung/Makefile
> create mode 100644 drivers/clk/samsung/clk-exynos4.c
> create mode 100644 drivers/clk/samsung/clk.c
> create mode 100644 drivers/clk/samsung/clk.h
...
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 56e4495..456c50b 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1196,6 +1196,7 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
> int __clk_init(struct device *dev, struct clk *clk)
> {
> int i, ret = 0;
> + u8 index;
> struct clk *orphan;
> struct hlist_node *tmp, *tmp2;
>
> @@ -1259,6 +1260,7 @@ int __clk_init(struct device *dev, struct clk *clk)
> __clk_lookup(clk->parent_names[i]);
> }
>
> +
> clk->parent = __clk_init_parent(clk);
>
> /*
> @@ -1298,11 +1300,13 @@ int __clk_init(struct device *dev, struct clk *clk)
> * this clock
> */
> hlist_for_each_entry_safe(orphan, tmp, tmp2,&clk_orphan_list, child_node)
> - for (i = 0; i< orphan->num_parents; i++)
> - if (!strcmp(clk->name, orphan->parent_names[i])) {
> + if (orphan->num_parents> 1) {
> + index = orphan->ops->get_parent(orphan->hw);
> + if (!strcmp(clk->name, orphan->parent_names[index]))
> __clk_reparent(orphan, clk);
> - break;
> - }
> + } else if (!strcmp(clk->name, orphan->parent_names[0])) {
> + __clk_reparent(orphan, clk);
> + }

As this touches generic code it should rather be put into a separate patch,
along with an explanation why such a change is needed.

>
> /*
> * optional platform-specific magic
> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
> new file mode 100644
> index 0000000..69487f7
> --- /dev/null
> +++ b/drivers/clk/samsung/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Samsung Clock specific Makefile
> +#
> +
> +obj-$(CONFIG_PLAT_SAMSUNG) += clk.o
> +obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
> diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
> new file mode 100644
> index 0000000..74a6f03
> --- /dev/null
> +++ b/drivers/clk/samsung/clk-exynos4.c
> @@ -0,0 +1,585 @@
> +/*
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * Copyright (c) 2012 Linaro Ltd.
> + *
> + * 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.
> + *
> + * Common Clock Framework support for all Exynos4 platforms
> +*/
> +
> +#include<linux/clk.h>
> +#include<linux/clkdev.h>
> +#include<linux/io.h>
> +#include<linux/clk-provider.h>
> +
> +#include<plat/pll.h>
> +#include<plat/cpu.h>
> +#include<mach/regs-clock.h>
> +#include<mach/sysmmu.h>
> +#include<plat/map-s5p.h>
> +
> +#include "clk.h"
> +
> +#define EXYNOS4_OP_MODE (S5P_VA_CHIPID + 8)
> +
> +static const char *pll_parent_names[] __initdata = { "fin_pll" };
> +static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
> +static const char *mout_apll_parents[] __initdata = { "fin_pll", "fout_apll", };
> +static const char *mout_mpll_parents[] __initdata = { "fin_pll", "fout_mpll", };
> +static const char *mout_epll_parents[] __initdata = { "fin_pll", "fout_epll", };
> +
> +static const char *sclk_ampll_parents[] __initdata = {
> + "mout_mpll", "sclk_apll", };
> +
> +static const char *sclk_evpll_parents[] __initdata = {
> + "mout_epll", "mout_vpll", };
> +
> +static const char *mout_core_parents[] __initdata = {
> + "mout_apll", "mout_mpll", };
> +
> +static const char *mout_mfc_parents[] __initdata = {
> + "mout_mfc0", "mout_mfc1", };
> +
> +static const char *mout_dac_parents[] __initdata = {
> + "mout_vpll", "sclk_hdmiphy", };
> +
> +static const char *mout_hdmi_parents[] __initdata = {
> + "sclk_pixel", "sclk_hdmiphy", };
> +
> +static const char *mout_mixer_parents[] __initdata = {
> + "sclk_dac", "sclk_hdmi", };
> +
> +static const char *group1_parents[] __initdata = {
> + "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
> + "none", "sclk_hdmiphy", "mout_mpll", "mout_epll",
> + "mout_vpll" };
> +
> +static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
> + FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
> + FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),
> + FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
> + FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
> + FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
> +};
> +
> +static struct samsung_mux_clock exynos4_mux_clks[] = {
> + MUXCLK(NULL, "fin_pll", fin_pll_parents, 0,
> + EXYNOS4_OP_MODE, 0, 1, 0),
> + MUXCLK(NULL, "mout_apll", mout_apll_parents, 0,
> + EXYNOS4_CLKSRC_CPU, 0, 1, 0),
> + MUXCLK(NULL, "mout_epll", mout_epll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 4, 1, 0),
> + MUXCLK(NULL, "mout_core", mout_core_parents, 0,
> + EXYNOS4_CLKSRC_CPU, 16, 1, 0),
> + MUXCLK(NULL, "mout_aclk_200", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 12, 1, 0),
> + MUXCLK(NULL, "mout_aclk_100", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 16, 1, 0),
> + MUXCLK(NULL, "mout_aclk_160", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 20, 1, 0),
> + MUXCLK(NULL, "mout_aclk_133", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 24, 1, 0),
> + MUXCLK("exynos4210-uart.0", "mout_uart0", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 0, 4, 0),
> + MUXCLK("exynos4210-uart.1", "mout_uart1", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 4, 4, 0),
> + MUXCLK("exynos4210-uart.2", "mout_uart2", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 8, 4, 0),
> + MUXCLK("exynos4210-uart.3", "mout_uart3", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 12, 4, 0),
> + MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
> + MUXCLK("exynos4210-spi.0", "mout_spi0", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL1, 16, 4, 0),
> + MUXCLK("exynos4210-spi.1", "mout_spi1", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL1, 20, 4, 0),
> + MUXCLK("exynos4210-spi.2", "mout_spi2", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL1, 24, 4, 0),
> + MUXCLK(NULL, "mout_sata", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 24, 1, 0),
> + MUXCLK(NULL, "mout_mfc0", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_MFC, 0, 1, 0),
> + MUXCLK(NULL, "mout_mfc1", sclk_evpll_parents, 0,
> + EXYNOS4_CLKSRC_MFC, 4, 1, 0),
> + MUXCLK("s5p-mfc", "mout_mfc", mout_mfc_parents, 0,
> + EXYNOS4_CLKSRC_MFC, 8, 1, 0),
> + MUXCLK("s5p-mipi-csis.0", "mout_csis0", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 24, 4, 0),
> + MUXCLK("s5p-mipi-csis.1", "mout_csis1", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 28, 4, 0),
> + MUXCLK(NULL, "mout_cam0", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 16, 4, 0),
> + MUXCLK(NULL, "mout_cam1", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 20, 4, 0),
> + MUXCLK("exynos4-fimc.0", "mout_fimc0", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 0, 4, 0),
> + MUXCLK("exynos4-fimc.1", "mout_fimc1", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 4, 4, 0),
> + MUXCLK("exynos4-fimc.2", "mout_fimc2", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 8, 4, 0),
> + MUXCLK("exynos4-fimc.3", "mout_fimc3", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 12, 4, 0),
> + MUXCLK("exynos4-fb.0", "mout_fimd0", group1_parents, 0,
> + EXYNOS4_CLKSRC_LCD0, 0, 4, 0),
> + MUXCLK(NULL, "sclk_dac", mout_dac_parents, 0,
> + EXYNOS4_CLKSRC_TV, 8, 1, 0),
> + MUXCLK(NULL, "sclk_hdmi", mout_hdmi_parents, 0,
> + EXYNOS4_CLKSRC_TV, 0, 1, 0),
> + MUXCLK(NULL, "sclk_mixer", mout_mixer_parents, 0,
> + EXYNOS4_CLKSRC_TV, 4, 1, 0),
> +};
> +
> +static struct samsung_div_clock exynos4_div_clks[] = {
> + DIVCLK(NULL, "sclk_apll", "mout_apll", 0,
> + EXYNOS4_CLKDIV_CPU, 24, 3, 0),
> + DIVCLK(NULL, "div_core", "mout_core", 0,
> + EXYNOS4_CLKDIV_CPU, 0, 3, 0),
> + DIVCLK(NULL, "armclk", "div_core", 0,
> + EXYNOS4_CLKDIV_CPU, 28, 3, 0),
> + DIVCLK(NULL, "aclk_200", "mout_aclk_200", 0,
> + EXYNOS4_CLKDIV_TOP, 0, 3, 0),
> + DIVCLK(NULL, "aclk_100", "mout_aclk_100", 0,
> + EXYNOS4_CLKDIV_TOP, 4, 4, 0),
> + DIVCLK(NULL, "aclk_160", "mout_aclk_160", 0,
> + EXYNOS4_CLKDIV_TOP, 8, 3, 0),
> + DIVCLK(NULL, "aclk_133", "mout_aclk_133", 0,
> + EXYNOS4_CLKDIV_TOP, 12, 3, 0),
> + DIVCLK("exynos4210-uart.0", "div_uart0", "mout_uart0", 0,
> + EXYNOS4_CLKDIV_PERIL0, 0, 4, 0),
> + DIVCLK("exynos4210-uart.1", "div_uart1", "mout_uart1", 0,
> + EXYNOS4_CLKDIV_PERIL0, 4, 4, 0),
> + DIVCLK("exynos4210-uart.2", "div_uart2", "mout_uart2", 0,
> + EXYNOS4_CLKDIV_PERIL0, 8, 4, 0),
> + DIVCLK("exynos4210-uart.3", "div_uart3", "mout_uart3", 0,
> + EXYNOS4_CLKDIV_PERIL0, 12, 4, 0),
> + DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
> + EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
> + DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
> + EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
> + DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
> + EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
> + DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
> + EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
> + DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
> + EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
> + DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
> + EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
> + DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
> + EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
> + DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
> + EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
> + DIVCLK("exynos4210-spi.0", "div_spi0", "mout_spi0", 0,
> + EXYNOS4_CLKDIV_PERIL1, 0, 4, 0),
> + DIVCLK("exynos4210-spi.1", "div_spi1", "mout_spi1", 0,
> + EXYNOS4_CLKDIV_PERIL1, 16, 4, 0),
> + DIVCLK("exynos4210-spi.2", "div_spi2", "mout_spi2", 0,
> + EXYNOS4_CLKDIV_PERIL2, 0, 4, 0),
> + DIVCLK("exynos4210-spi.0", "div_spi0_pre", "div_spi0", 0,
> + EXYNOS4_CLKDIV_PERIL1, 8, 8, 0),
> + DIVCLK("exynos4210-spi.1", "div_spi1_pre", "div_spi1", 0,
> + EXYNOS4_CLKDIV_PERIL1, 24, 8, 0),
> + DIVCLK("exynos4210-spi.2", "div_spi2_pre", "div_spi2", 0,
> + EXYNOS4_CLKDIV_PERIL2, 8, 8, 0),
> + DIVCLK(NULL, "div_sata", "mout_sata", 0,
> + EXYNOS4_CLKDIV_FSYS0, 20, 4, 0),
> + DIVCLK("s5p-mfc", "div_mfc", "mout_mfc", 0,
> + EXYNOS4_CLKDIV_MFC, 0, 4, 0),
> + DIVCLK("s5p-mipi-csis.0", "div_csis0", "mout_csis0", 0,
> + EXYNOS4_CLKDIV_CAM, 24, 4, 0),
> + DIVCLK("s5p-mipi-csis.1", "div_csis1", "mout_csis1", 0,
> + EXYNOS4_CLKDIV_CAM, 28, 4, 0),
> + DIVCLK(NULL, "div_cam0", "mout_cam0", 0,
> + EXYNOS4_CLKDIV_CAM, 16, 4, 0),
> + DIVCLK(NULL, "div_cam1", "mout_cam1", 0,
> + EXYNOS4_CLKDIV_CAM, 20, 4, 0),
> + DIVCLK("exynos4-fimc.0", "div_fimc0", "mout_fimc0", 0,
> + EXYNOS4_CLKDIV_CAM, 0, 4, 0),
> + DIVCLK("exynos4-fimc.1", "div_fimc1", "mout_fimc1", 0,
> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
> + DIVCLK("exynos4-fimc.2", "div_fimc2", "mout_fimc2", 0,
> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
> + DIVCLK("exynos4-fimc.3", "div_fimc3", "mout_fimc3", 0,
> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
> + DIVCLK("exynos4-fb.0", "div_fimd0", "mout_fimd0", 0,
> + EXYNOS4_CLKDIV_LCD0, 0, 4, 0),
> + DIVCLK(NULL, "sclk_pixel", "mout_vpll", 0,
> + EXYNOS4_CLKDIV_TV, 0, 4, 0),
> +};
> +
> +struct samsung_gate_clock exynos4_gate_clks[] = {
> + GATECLK("exynos4210-uart.0", "uart0", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 0, "uart"),
> + GATECLK("exynos4210-uart.1", "uart1", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 1, "uart"),
> + GATECLK("exynos4210-uart.2", "uart2", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 2, "uart"),
> + GATECLK("exynos4210-uart.3", "uart3", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 3, "uart"),
> + GATECLK("exynos4210-uart.4", "uart4", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 4, "uart"),
> + GATECLK("exynos4210-uart.5", "uart5", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 5, "uart"),
> + GATECLK("exynos4210-uart.0", "uclk0", "div_uart0", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 0, "clk_uart_baud0"),
> + GATECLK("exynos4210-uart.1", "uclk1", "div_uart1", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 4, "clk_uart_baud0"),
> + GATECLK("exynos4210-uart.2", "uclk2", "div_uart2", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 8, "clk_uart_baud0"),
> + GATECLK("exynos4210-uart.3", "uclk3", "div_uart3", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 12, "clk_uart_baud0"),
> + GATECLK(NULL, "timers", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 24, NULL),
> + GATECLK("s5p-mipi-csis.0", "csis", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 5, NULL),
> + GATECLK(NULL, "jpeg", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 6, NULL),
> + GATECLK("exynos4-fimc.0", "fimc0", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 0, "fimc"),
> + GATECLK("exynos4-fimc.1", "fimc1", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 1, "fimc"),
> + GATECLK("exynos4-fimc.2", "fimc2", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 2, "fimc"),
> + GATECLK("exynos4-fimc.3", "fimc3", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 3, "fimc"),
> + GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
> + GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
> + GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
> + GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
> + GATECLK(NULL, "dwmmc", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 9, NULL),
> + GATECLK("s5p-sdo", "dac", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 2, NULL),
> + GATECLK("s5p-mixer", "mixer", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 1, NULL),
> + GATECLK("s5p-mixer", "vp", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 0, NULL),
> + GATECLK("exynos4-hdmi", "hdmi", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 3, NULL),
> + GATECLK("exynos4-hdmi", "hdmiphy", "aclk_160", 0,
> + S5P_HDMI_PHY_CONTROL, 0, NULL),
> + GATECLK("s5p-sdo", "dacphy", "aclk_160", 0,
> + S5P_DAC_PHY_CONTROL, 0, NULL),
> + GATECLK(NULL, "adc", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 15, NULL),
> + GATECLK(NULL, "keypad", "aclk_100", 0,
> + EXYNOS4210_CLKGATE_IP_PERIR, 16, NULL),
> + GATECLK(NULL, "rtc", "aclk_100", 0,
> + EXYNOS4210_CLKGATE_IP_PERIR, 15, NULL),
> + GATECLK(NULL, "watchdog", "aclk_100", 0,
> + EXYNOS4210_CLKGATE_IP_PERIR, 14, NULL),
> + GATECLK(NULL, "usbhost", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 12, NULL),
> + GATECLK(NULL, "otg", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 13, NULL),
> + GATECLK("exynos4210-spi.0", "spi0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 16, "spi"),
> + GATECLK("exynos4210-spi.1", "spi1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 17, "spi"),
> + GATECLK("exynos4210-spi.2", "spi2", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 18, "spi"),
> + GATECLK("samsung-i2s.0", "iis0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 19, "iis"),
> + GATECLK("samsung-i2s.1", "iis1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 20, "iis"),
> + GATECLK("samsung-i2s.2", "iis2", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 21, "iis"),
> + GATECLK("samsung-ac97", "ac97", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 27, NULL),
> + GATECLK("s5p-mfc", "mfc", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_MFC, 0, NULL),
> + GATECLK("s3c2440-i2c.0", "i2c0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 6, "i2c"),
> + GATECLK("s3c2440-i2c.1", "i2c1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 7, "i2c"),
> + GATECLK("s3c2440-i2c.2", "i2c2", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 8, "i2c"),
> + GATECLK("s3c2440-i2c.3", "i2c3", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 9, "i2c"),
> + GATECLK("s3c2440-i2c.4", "i2c4", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 10, "i2c"),
> + GATECLK("s3c2440-i2c.5", "i2c5", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 11, "i2c"),
> + GATECLK("s3c2440-i2c.6", "i2c6", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 12, "i2c"),
> + GATECLK("s3c2440-i2c.7", "i2c7", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 13, "i2c"),
> + GATECLK("s3c2440-hdmiphy-i2c", "i2c", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 14, NULL),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_l, 0), "sysmmu0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_MFC, 1, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_r, 1), "sysmmu1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_MFC, 2, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(tv, 2), "sysmmu2", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 4, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(jpeg, 3), "sysmmu3", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 11, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(rot, 4), "sysmmu4", "aclk_200", 0,
> + EXYNOS4210_CLKGATE_IP_IMAGE, 4, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc0, 5), "sysmmu5", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 7, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc1, 6), "sysmmu6", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 8, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc2, 7), "sysmmu7", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 9, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc3, 8), "sysmmu8", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 10, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimd, 10), "sysmmu10", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_LCD0, 4, "sysmmu"),
> + GATECLK("dma-pl330.0", "dma0", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 0, "dma"),
> + GATECLK("dma-pl330.1", "dma1", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 1, "dma"),
> + GATECLK("exynos4-fb.0", "fimd", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_LCD0, 0, "lcd"),
> + GATECLK("exynos4210-spi.0", "sclk_spi0", "div_spi0_pre", 0,
> + EXYNOS4_CLKSRC_MASK_PERIL1, 16, "spi_busclk0"),
> + GATECLK("exynos4210-spi.1", "sclk_spi1", "div_spi1_pre", 0,
> + EXYNOS4_CLKSRC_MASK_PERIL1, 20, "spi_busclk0"),
> + GATECLK("exynos4210-spi.2", "sclk_spi2", "div_spi2_pre", 0,
> + EXYNOS4_CLKSRC_MASK_PERIL1, 24, "spi_busclk0"),
> + GATECLK("exynos4-sdhci.0", "sclk_mmc0", "div_mmc0_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 0, "mmc_busclk.2"),
> + GATECLK("exynos4-sdhci.1", "sclk_mmc1", "div_mmc1_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 4, "mmc_busclk.2"),
> + GATECLK("exynos4-sdhci.2", "sclk_mmc2", "div_mmc2_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 8, "mmc_busclk.2"),
> + GATECLK("exynos4-sdhci.3", "sclk_mmc3", "div_mmc3_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 12, "mmc_busclk.2"),
> + GATECLK("s5p-mipi-csis.0", "sclk_csis0", "div_csis0", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 24, "sclk_csis"),
> + GATECLK("s5p-mipi-csis.1", "sclk_csis1", "div_csis1", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
> + GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
> + GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
> + GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
> + GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
> + GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
> + GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
> + GATECLK("exynos4-fb.0", "sclk_fimd", "div_fimd0", 0,
> + EXYNOS4_CLKSRC_MASK_LCD0, 0, "sclk_fimd"),
> +};
> +
> +/* register clock common to all Exynos4 platforms */
> +void __init exynos4_clk_init(void)
> +{
> + samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
> + ARRAY_SIZE(exynos4_fixed_rate_clks));
> + samsung_clk_register_mux(exynos4_mux_clks,
> + ARRAY_SIZE(exynos4_mux_clks));
> + samsung_clk_register_div(exynos4_div_clks,
> + ARRAY_SIZE(exynos4_div_clks));
> + samsung_clk_register_gate(exynos4_gate_clks,
> + ARRAY_SIZE(exynos4_gate_clks));
> +}
...
> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
> new file mode 100644
> index 0000000..65156b9
> --- /dev/null
> +++ b/drivers/clk/samsung/clk.c
> @@ -0,0 +1,231 @@
> +/*
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * Copyright (c) 2012 Linaro Ltd.
> + *
> + * 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 file includes utility functions to register clocks to common
> + * clock framework for Samsung platforms. This includes an implementation
> + * of Samsung 'pll type' clock to represent the implementation of the
> + * pll found on Samsung platforms. In addition to that, utility functions
> + * to register mux, div, gate and fixed rate types of clocks are included.
> +*/
> +
> +#include "clk.h"
> +
> +static DEFINE_SPINLOCK(lock);
> +
> +#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
> +
> +/* determine the output clock speed of the pll */
> +static unsigned long samsung_clk_pll_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
> +
> + if (clk_pll->get_rate)
> + return to_clk_pll(hw)->get_rate(parent_rate);
> +
> + return 0;
> +}
> +
> +/* round operation not supported */
> +static long samsung_clk_pll_round_rate(struct clk_hw *hw, unsigned long drate,
> + unsigned long *prate)
> +{
> + return samsung_clk_pll_recalc_rate(hw, *prate);
> +}
> +
> +/* set the clock output rate of the pll */
> +static int samsung_clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
> + unsigned long prate)
> +{
> + struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
> +
> + if (clk_pll->set_rate)
> + return to_clk_pll(hw)->set_rate(drate);
> +
> + return 0;
> +}
> +
> +/* clock operations for samsung pll clock type */
> +static const struct clk_ops samsung_clk_pll_ops = {
> + .recalc_rate = samsung_clk_pll_recalc_rate,
> + .round_rate = samsung_clk_pll_round_rate,
> + .set_rate = samsung_clk_pll_set_rate,
> +};
> +
> +/* register a samsung pll type clock */
> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
> + int (*set_rate)(unsigned long rate),
> + unsigned long (*get_rate)(unsigned long rate))
> +{
> + struct samsung_clk_pll *clk_pll;
> + struct clk *clk;
> + struct clk_init_data init;
> + int ret;
> +
> + clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
> + if (!clk_pll) {
> + pr_err("%s: could not allocate pll clk %s\n", __func__, name);
> + return;
> + }
> +
> + init.name = name;
> + init.ops =&samsung_clk_pll_ops;
> + init.flags = CLK_GET_RATE_NOCACHE;
> + init.parent_names = pnames;
> + init.num_parents = 1;
> +
> + clk_pll->set_rate = set_rate;
> + clk_pll->get_rate = get_rate;
> + clk_pll->hw.init =&init;
> +
> + /* register the clock */
> + clk = clk_register(NULL,&clk_pll->hw);
> + if (IS_ERR(clk)) {
> + pr_err("%s: failed to register pll clock %s\n", __func__,
> + name);
> + kfree(clk_pll);
> + return;
> + }
> +
> + ret = clk_register_clkdev(clk, name, NULL);
> + if (ret)
> + pr_err("%s: failed to register clock lookup for %s", __func__,
> + name);
> +}
> +
> +/* register a list of fixed clocks */
> +void __init samsung_clk_register_fixed_rate(
> + struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
> + clk = clk_register_fixed_rate(NULL, clk_list->name,
> + clk_list->parent_name, clk_list->flags,
> + clk_list->fixed_rate);
> + if (IS_ERR_OR_NULL(clk)) {

clk_register_fixed_rate() always returns an error code (ERR_PTR()), i.e. never
NULL, thus IS_ERR(clk) is more appropriate here.

> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> + }
> +}
> +
> +/* register a list of mux clocks */
> +void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
> + unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
> + clk = clk_register_mux(NULL, clk_list->name,
> + clk_list->parent_names, clk_list->num_parents,
> + clk_list->flags, clk_list->reg, clk_list->shift,
> + clk_list->width, clk_list->mux_flags,&lock);
> + if (IS_ERR_OR_NULL(clk)) {

Ditto.

> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> +
> + if (clk_list->alias)
> + clk_register_clkdev(clk, clk_list->alias,
> + clk_list->dev_name);
> + }
> +}
> +
> +/* reguster a list of div clocks */
> +void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
> + unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
> + clk = clk_register_divider(NULL, clk_list->name,
> + clk_list->parent_name, clk_list->flags, clk_list->reg,
> + clk_list->shift, clk_list->width, clk_list->div_flags,
> + &lock);
> + if (IS_ERR_OR_NULL(clk)) {

Ditto.

> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> +
> + if (clk_list->alias)
> + clk_register_clkdev(clk, clk_list->alias,
> + clk_list->dev_name);
> + }
> +}
> +
> +/* register a list of gate clocks */
> +void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
> + unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
> + clk = clk_register_gate(NULL, clk_list->name,
> + clk_list->parent_name, clk_list->flags, clk_list->reg,
> + clk_list->bit_idx, clk_list->gate_flags,&lock);
> + if (IS_ERR_OR_NULL(clk)) {

Ditto.

> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret) {
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->alias,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register alias %s for clock "
> + " %s", clk_list->alias, clk_list->name);
> + }
> +}


Do we really need all these clock lookup entries registered for each clk
primitive ? There seem to be more struck clk objects than with the original
samsung clock code, now when each instance of struct clk_clksrc has been
replaced with a corresponding div and mux clock object. All these are not
needed to be referenced from drivers, so why do we see so many
clk_register_clkdev() here ?

Couldn't this be avoided by instantiating all platform clocks first and
then creating required clock object - device associations by adding the
clkdev lookup entries ? Something like this is done in case of
arch/arm/mach-imx for instance. I think this would result in less data
and more clear implementation.


> +/* utility function to get the rate of a specified clock */
> +unsigned long _get_rate(const char *clk_name)
> +{
> + struct clk *clk;
> + unsigned long rate;
> +
> + clk = clk_get(NULL, clk_name);
> + if (IS_ERR(clk))
> + return 0;
> + rate = clk_get_rate(clk);
> + clk_put(clk);
> + return rate;
> +}
> diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
> new file mode 100644
> index 0000000..40bdff9
> --- /dev/null
> +++ b/drivers/clk/samsung/clk.h
> @@ -0,0 +1,190 @@
> +/*
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * Copyright (c) 2012 Linaro Ltd.
> + *
> + * 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.
> + *
> + * Common Clock Framework support for all Samsung platforms
> +*/
> +
> +#ifndef __SAMSUNG_CLK_H
> +#define __SAMSUNG_CLK_H
> +
> +#include<linux/clk.h>
> +#include<linux/clkdev.h>
> +#include<linux/io.h>
> +#include<linux/clk-provider.h>
> +#include<mach/regs-clock.h>
> +
> +/**
> + * struct samsung_clk_pll: represents a samsung pll type clock
> + * @hw: connection to struct clk.
> + * @set_rate: callback for setting the pll clock rate
> + * @get_rate: callback for determing the pll clock rate
> + *
> + * Internal representation of the pll type clock. Platform specific
> + * implementation can instantiate clocks of this type by calling
> + * samsung_clk_register_pll() function.
> + */
> +struct samsung_clk_pll {
> + struct clk_hw hw;
> + int (*set_rate)(unsigned long rate);
> + unsigned long (*get_rate)(unsigned long xtal_rate);
> +};
> +
> +/**
> + * struct samsung_fixed_rate_clock: information about fixed-rate clock
> + * @dev_name: name of the device to which this clock belongs.
> + * @name: name of this fixed-rate clock.
> + * @parent_name: optional parent clock name.
> + * @flags: optional fixed-rate clock flags.
> + * @fixed-rate: fixed clock rate of this clock.
> + */
> +struct samsung_fixed_rate_clock {
> + const char *dev_name;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + unsigned long fixed_rate;
> +};
> +
> +#define FRATE_CLK(dname, cname, pname, f, frate) \
> + { \
> + .dev_name = dname, \
> + .name = cname, \
> + .parent_name = pname, \
> + .flags = f, \
> + .fixed_rate = frate, \
> + }
> +
> +/**
> + * struct samsung_mux_clock: information about mux clock
> + * @dev_name: name of the device to which this clock belongs.
> + * @name: name of this mux clock.
> + * @parent_names: array of pointer to parent clock names.
> + * @num_parents: number of parents listed in @parent_names.
> + * @flags: optional flags for basic clock.
> + * @reg: address of register for configuring the mux.
> + * @shift: starting bit location of the mux control bit-field in @reg.
> + * @width: width of the mux control bit-field in @reg.
> + * @mux_flags: flags for mux-type clock.
> + * @alias: optional clock alias name to be assigned to this clock.
> + */
> +struct samsung_mux_clock {
> + const char *dev_name;
> + const char *name;
> + const char **parent_names;
> + u8 num_parents;
> + unsigned long flags;
> + void __iomem *reg;
> + u8 shift;
> + u8 width;
> + u8 mux_flags;
> + const char *alias;
> +};
> +
> +#define MUXCLK(dname, cname, pnames, f, r, s, w, mf) \
> + { \
> + .dev_name = dname, \
> + .name = cname, \
> + .parent_names = pnames, \
> + .num_parents = ARRAY_SIZE(pnames), \
> + .flags = f, \
> + .reg = r, \
> + .shift = s, \
> + .width = w, \
> + .mux_flags = mf, \
> + }
> +
> +/**
> + * struct samsung_div_clock: information about div clock
> + * @dev_name: name of the device to which this clock belongs.
> + * @name: name of this div clock.
> + * @parent_name: name of the parent clock.
> + * @flags: optional flags for basic clock.
> + * @reg: address of register for configuring the div.
> + * @shift: starting bit location of the div control bit-field in @reg.
> + * @div_flags: flags for div-type clock.
> + * @alias: optional clock alias name to be assigned to this clock.
> + */
> +struct samsung_div_clock {
> + const char *dev_name;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + void __iomem *reg;
> + u8 shift;
> + u8 width;
> + u8 div_flags;
> + const char *alias;
> +};
> +
> +#define DIVCLK(dname, cname, pname, f, r, s, w, df) \
> + { \
> + .dev_name = dname, \
> + .name = cname, \
> + .parent_name = pname, \
> + .flags = f, \
> + .reg = r, \
> + .shift = s, \
> + .width = w, \
> + .div_flags = df, \
> + }
> +
> +/**
> + * struct samsung_gate_clock: information about gate clock
> + * @dev_name: name of the device to which this clock belongs.
> + * @name: name of this gate clock.
> + * @parent_name: name of the parent clock.
> + * @flags: optional flags for basic clock.
> + * @reg: address of register for configuring the gate.
> + * @bit_idx: bit index of the gate control bit-field in @reg.
> + * @gate_flags: flags for gate-type clock.
> + * @alias: optional clock alias name to be assigned to this clock.
> + */
> +struct samsung_gate_clock {
> + const char *dev_name;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + void __iomem *reg;
> + u8 bit_idx;
> + u8 gate_flags;
> + const char *alias;
> +};
> +
> +#define GATECLK(dname, cname, pname, f, r, b, a) \
> + { \
> + .dev_name = dname, \
> + .name = cname, \
> + .parent_name = pname, \
> + .flags = f, \
> + .reg = r, \
> + .bit_idx = b, \
> + .alias = a, \
> + }

--

Regards,
Sylwester

2012-10-08 06:32:21

by Thomas Abraham

[permalink] [raw]
Subject: Re: [PATCH 0/2] ARM: Exynos4: Migrate to common clock framework.

Hi Tomasz,

Thanks for reviewing this patch series.

On 3 October 2012 16:26, Tomasz Figa <[email protected]> wrote:
> Hi Chander, Thomas,
>
> On Monday 01 of October 2012 17:39:19 [email protected] wrote:
>> From: Thomas Abraham <[email protected]>
>>
>> This patch series migrates Exynos4 clock support to common clock
>> framework. The first patch in this series removes the existing Exynos4
>> clock support that uses the Samsung specific clock framework. The second
>> patch in this series add Exynos4 clock support using common clock
>> framework.
>>
>> Thomas Abraham (2):
>> ARM: Exynos4: Remove Samsung clock type support
>> ARM: Exynos4: Register clocks via common clock framework
>
> I think the order of changes is a little bit off here:
> - patch 1 will break all exynos4-based boards (what about bisects?)
> - patch 2 will be still broken until all related drivers get converted to
> use clk_prepare(_enable) and clk_(disable_)unprepare.

Ok. I got the sequence wrong and I have fixed this in the next version.

>
> Shouldn't the order be exactly opposite, i.e.:
> - all the patches for prepare/unprepare first
> - then the patch adding common clock frameworks support for exynos4
> (disabling the old clock code)
> - and finally the patch removing remaining (disabled by previous patch)
> code.

Right.

>
> Also, I assume that these patches doesn't consider native device tree
> support (without auxdata, using OF-based clock lookup), correct me if I'm
> wrong. If I'm right, since Exynos SoCs are going to be DT-only, is there
> really a point for adding common clock framework support for non-DT
> platforms (which are going to be eventually dropped anyway)?

The non-dt Exynos4 platforms require some effort to get basic device
tree support into them. Until then, the common clock support for them
are required. I have added device tree support as well in the second
version of this patch series.

Thanks,
Thomas.

>
> Best regards,
> --
> Tomasz Figa
> Samsung Poland R&D Center
>

2012-10-08 06:34:08

by Thomas Abraham

[permalink] [raw]
Subject: Re: [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework

Hi Tomasz,

On 3 October 2012 17:25, Tomasz Figa <[email protected]> wrote:
> Hi Chander, Thomas,
>
> I think this patch could be split into several smaller, while retaining logical integrity of particular patches, e.g.:
> - the change introduced to __clk_init (with proper description and rationale why the generic code is being touched)
> - generic exynos4 code
> - exynos4210-specific code
> - exynos4x12-specific code
> - patch enabling common clock framework on exynos4.
>
> Also, see some nitpicks inline.
>
> On Monday 01 of October 2012 17:39:21 [email protected] wrote:
>> From: Thomas Abraham <[email protected]>
>>
>> Register clocks for Exynos4 platfotms using common clock framework.
>> Also included are set of helper functions for clock registration
>> that can be reused on other Samsung platforms as well.
>>
>> Cc: Mike Turquette <[email protected]>
>> Cc: Kukjin Kim <[email protected]>
>> Signed-off-by: Thomas Abraham <[email protected]>
>> ---
>> arch/arm/mach-exynos/Kconfig | 1 +
>> arch/arm/mach-exynos/common.h | 3 +
>> arch/arm/mach-exynos/mct.c | 11 +-
>> arch/arm/plat-samsung/Kconfig | 4 +-
>> drivers/clk/Makefile | 1 +
>> drivers/clk/clk.c | 12 +-
>> drivers/clk/samsung/Makefile | 6 +
>> drivers/clk/samsung/clk-exynos4.c | 585
>> +++++++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk.c
>> | 231 +++++++++++++++
>> drivers/clk/samsung/clk.h | 190 ++++++++++++
>> 10 files changed, 1037 insertions(+), 7 deletions(-)
>> create mode 100644 drivers/clk/samsung/Makefile
>> create mode 100644 drivers/clk/samsung/clk-exynos4.c
>> create mode 100644 drivers/clk/samsung/clk.c
>> create mode 100644 drivers/clk/samsung/clk.h
>>
>> diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
>> index b5b4c8c..4866ec7 100644
>> --- a/arch/arm/mach-exynos/Kconfig
>> +++ b/arch/arm/mach-exynos/Kconfig
>> @@ -15,6 +15,7 @@ config ARCH_EXYNOS4
>> bool "SAMSUNG EXYNOS4"
>> default y
>> select HAVE_SMP
>> + select COMMON_CLK
>> select MIGHT_HAVE_CACHE_L2X0
>> help
>> Samsung EXYNOS4 SoCs based systems
>> diff --git a/arch/arm/mach-exynos/common.h
>> b/arch/arm/mach-exynos/common.h index aed2eeb..2274431 100644
>> --- a/arch/arm/mach-exynos/common.h
>> +++ b/arch/arm/mach-exynos/common.h
>> @@ -21,6 +21,9 @@ void exynos4_restart(char mode, const char *cmd);
>> void exynos5_restart(char mode, const char *cmd);
>> void exynos_init_late(void);
>>
>> +void exynos4210_clk_init(void);
>> +void exynos4212_clk_init(void);
>
> exynos4x12_clk_init?
>
>> +
>> #ifdef CONFIG_PM_GENERIC_DOMAINS
>> int exynos_pm_late_initcall(void);
>> #else
>> diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
>> index b601fb8..a7cace0 100644
>> --- a/arch/arm/mach-exynos/mct.c
>> +++ b/arch/arm/mach-exynos/mct.c
>> @@ -30,6 +30,8 @@
>> #include <mach/regs-mct.h>
>> #include <asm/mach/time.h>
>>
>> +#include "common.h"
>> +
>> #define TICK_BASE_CNT 1
>>
>> enum {
>> @@ -457,7 +459,7 @@ static struct local_timer_ops exynos4_mct_tick_ops
>> __cpuinitdata = { static void __init exynos4_timer_resources(void)
>> {
>> struct clk *mct_clk;
>> - mct_clk = clk_get(NULL, "xtal");
>> + mct_clk = clk_get(NULL, "fin_pll");
>>
>> clk_rate = clk_get_rate(mct_clk);
>>
>> @@ -478,6 +480,13 @@ static void __init exynos4_timer_resources(void)
>>
>> static void __init exynos4_timer_init(void)
>> {
>> +#ifdef CONFIG_COMMON_CLK
>> + if (soc_is_exynos4210())
>> + exynos4210_clk_init();
>> + else if (soc_is_exynos4212() || soc_is_exynos4412())
>> + exynos4212_clk_init();
>
> exynos4x12_clk_init?

Ok.

>
>> +#endif
>> +
>> if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
>> mct_int_type = MCT_INT_SPI;
>> else
>> diff --git a/arch/arm/plat-samsung/Kconfig
>> b/arch/arm/plat-samsung/Kconfig index 9c3b90c..35b4cb8 100644
>> --- a/arch/arm/plat-samsung/Kconfig
>> +++ b/arch/arm/plat-samsung/Kconfig
>> @@ -26,7 +26,7 @@ config PLAT_S5P
>> select S5P_GPIO_DRVSTR
>> select SAMSUNG_GPIOLIB_4BIT
>> select PLAT_SAMSUNG
>> - select SAMSUNG_CLKSRC
>> + select SAMSUNG_CLKSRC if !COMMON_CLK
>> select SAMSUNG_IRQ_VIC_TIMER
>> help
>> Base platform code for Samsung's S5P series SoC.
>> @@ -89,7 +89,7 @@ config SAMSUNG_CLKSRC
>> used by newer systems such as the S3C64XX.
>>
>> config S5P_CLOCK
>> - def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
>> + def_bool ((ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
>> && !COMMON_CLK) help
>> Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
>>
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 6327536..5f5b060 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -16,6 +16,7 @@ obj-$(CONFIG_ARCH_MMP) += mmp/
>> endif
>> obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
>> obj-$(CONFIG_ARCH_U8500) += ux500/
>> +obj-$(CONFIG_PLAT_SAMSUNG) += samsung/
>>
>> # Chip specific
>> obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
>> index 56e4495..456c50b 100644
>> --- a/drivers/clk/clk.c
>> +++ b/drivers/clk/clk.c
>> @@ -1196,6 +1196,7 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
>> int __clk_init(struct device *dev, struct clk *clk)
>> {
>> int i, ret = 0;
>> + u8 index;
>> struct clk *orphan;
>> struct hlist_node *tmp, *tmp2;
>>
>> @@ -1259,6 +1260,7 @@ int __clk_init(struct device *dev, struct clk *clk)
>> __clk_lookup(clk->parent_names[i]);
>> }
>>
>> +
>
>
> Unnecessary extra blank line?

Ok.

>
>> clk->parent = __clk_init_parent(clk);
>>
>> /*
>> @@ -1298,11 +1300,13 @@ int __clk_init(struct device *dev, struct clk
>> *clk) * this clock
>> */
>> hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list,
>> child_node) - for (i = 0; i < orphan->num_parents; i++)
>> - if (!strcmp(clk->name, orphan->parent_names[i])) {
>> + if (orphan->num_parents > 1) {
>> + index = orphan->ops->get_parent(orphan->hw);
>> + if (!strcmp(clk->name, orphan->parent_names[index]))
>> __clk_reparent(orphan, clk);
>> - break;
>> - }
>> + } else if (!strcmp(clk->name, orphan->parent_names[0])) {
>> + __clk_reparent(orphan, clk);
>> + }
>>
>> /*
>> * optional platform-specific magic
>> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
>> new file mode 100644
>> index 0000000..69487f7
>> --- /dev/null
>> +++ b/drivers/clk/samsung/Makefile
>> @@ -0,0 +1,6 @@
>> +#
>> +# Samsung Clock specific Makefile
>> +#
>> +
>> +obj-$(CONFIG_PLAT_SAMSUNG) += clk.o
>> +obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
>> diff --git a/drivers/clk/samsung/clk-exynos4.c
>> b/drivers/clk/samsung/clk-exynos4.c new file mode 100644
>> index 0000000..74a6f03
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk-exynos4.c
>> @@ -0,0 +1,585 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 Linaro Ltd.
>> + *
>> + * 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.
>> + *
>> + * Common Clock Framework support for all Exynos4 platforms
>> +*/
>> +
>> +#include <linux/clk.h>
>> +#include <linux/clkdev.h>
>> +#include <linux/io.h>
>> +#include <linux/clk-provider.h>
>> +
>> +#include <plat/pll.h>
>> +#include <plat/cpu.h>
>> +#include <mach/regs-clock.h>
>> +#include <mach/sysmmu.h>
>> +#include <plat/map-s5p.h>
>> +
>> +#include "clk.h"
>> +
>> +#define EXYNOS4_OP_MODE (S5P_VA_CHIPID + 8)
>> +
>> +static const char *pll_parent_names[] __initdata = { "fin_pll" };
>> +static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
>> +static const char *mout_apll_parents[] __initdata = { "fin_pll",
>> "fout_apll", }; +static const char *mout_mpll_parents[] __initdata = {
>> "fin_pll", "fout_mpll", }; +static const char *mout_epll_parents[]
>> __initdata = { "fin_pll", "fout_epll", }; +
>> +static const char *sclk_ampll_parents[] __initdata = {
>> + "mout_mpll", "sclk_apll", };
>> +
>> +static const char *sclk_evpll_parents[] __initdata = {
>> + "mout_epll", "mout_vpll", };
>> +
>> +static const char *mout_core_parents[] __initdata = {
>> + "mout_apll", "mout_mpll", };
>> +
>> +static const char *mout_mfc_parents[] __initdata = {
>> + "mout_mfc0", "mout_mfc1", };
>> +
>> +static const char *mout_dac_parents[] __initdata = {
>> + "mout_vpll", "sclk_hdmiphy", };
>> +
>> +static const char *mout_hdmi_parents[] __initdata = {
>> + "sclk_pixel", "sclk_hdmiphy", };
>> +
>> +static const char *mout_mixer_parents[] __initdata = {
>> + "sclk_dac", "sclk_hdmi", };
>> +
>> +static const char *group1_parents[] __initdata = {
>> + "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
>> + "none", "sclk_hdmiphy", "mout_mpll", "mout_epll",
>> + "mout_vpll" };
>> +
>> +static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
>> + FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
>> + FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),
>> + FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
>> + FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
>> + FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
>> +};
>> +
>> +static struct samsung_mux_clock exynos4_mux_clks[] = {
>> + MUXCLK(NULL, "fin_pll", fin_pll_parents, 0,
>> + EXYNOS4_OP_MODE, 0, 1, 0),
>> + MUXCLK(NULL, "mout_apll", mout_apll_parents, 0,
>> + EXYNOS4_CLKSRC_CPU, 0, 1, 0),
>> + MUXCLK(NULL, "mout_epll", mout_epll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 4, 1, 0),
>> + MUXCLK(NULL, "mout_core", mout_core_parents, 0,
>> + EXYNOS4_CLKSRC_CPU, 16, 1, 0),
>> + MUXCLK(NULL, "mout_aclk_200", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 12, 1, 0),
>> + MUXCLK(NULL, "mout_aclk_100", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 16, 1, 0),
>> + MUXCLK(NULL, "mout_aclk_160", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 20, 1, 0),
>> + MUXCLK(NULL, "mout_aclk_133", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 24, 1, 0),
>> + MUXCLK("exynos4210-uart.0", "mout_uart0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL0, 0, 4, 0),
>> + MUXCLK("exynos4210-uart.1", "mout_uart1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL0, 4, 4, 0),
>> + MUXCLK("exynos4210-uart.2", "mout_uart2", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL0, 8, 4, 0),
>> + MUXCLK("exynos4210-uart.3", "mout_uart3", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL0, 12, 4, 0),
>> + MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
>> + MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
>> + MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
>> + MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
>> + MUXCLK("exynos4210-spi.0", "mout_spi0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL1, 16, 4, 0),
>> + MUXCLK("exynos4210-spi.1", "mout_spi1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL1, 20, 4, 0),
>> + MUXCLK("exynos4210-spi.2", "mout_spi2", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL1, 24, 4, 0),
>> + MUXCLK(NULL, "mout_sata", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 24, 1, 0),
>> + MUXCLK(NULL, "mout_mfc0", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_MFC, 0, 1, 0),
>> + MUXCLK(NULL, "mout_mfc1", sclk_evpll_parents, 0,
>> + EXYNOS4_CLKSRC_MFC, 4, 1, 0),
>> + MUXCLK("s5p-mfc", "mout_mfc", mout_mfc_parents, 0,
>> + EXYNOS4_CLKSRC_MFC, 8, 1, 0),
>> + MUXCLK("s5p-mipi-csis.0", "mout_csis0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 24, 4, 0),
>> + MUXCLK("s5p-mipi-csis.1", "mout_csis1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 28, 4, 0),
>> + MUXCLK(NULL, "mout_cam0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 16, 4, 0),
>> + MUXCLK(NULL, "mout_cam1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 20, 4, 0),
>> + MUXCLK("exynos4-fimc.0", "mout_fimc0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 0, 4, 0),
>> + MUXCLK("exynos4-fimc.1", "mout_fimc1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 4, 4, 0),
>> + MUXCLK("exynos4-fimc.2", "mout_fimc2", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 8, 4, 0),
>> + MUXCLK("exynos4-fimc.3", "mout_fimc3", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 12, 4, 0),
>> + MUXCLK("exynos4-fb.0", "mout_fimd0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_LCD0, 0, 4, 0),
>> + MUXCLK(NULL, "sclk_dac", mout_dac_parents, 0,
>> + EXYNOS4_CLKSRC_TV, 8, 1, 0),
>> + MUXCLK(NULL, "sclk_hdmi", mout_hdmi_parents, 0,
>> + EXYNOS4_CLKSRC_TV, 0, 1, 0),
>> + MUXCLK(NULL, "sclk_mixer", mout_mixer_parents, 0,
>> + EXYNOS4_CLKSRC_TV, 4, 1, 0),
>> +};
>> +
>> +static struct samsung_div_clock exynos4_div_clks[] = {
>> + DIVCLK(NULL, "sclk_apll", "mout_apll", 0,
>> + EXYNOS4_CLKDIV_CPU, 24, 3, 0),
>> + DIVCLK(NULL, "div_core", "mout_core", 0,
>> + EXYNOS4_CLKDIV_CPU, 0, 3, 0),
>> + DIVCLK(NULL, "armclk", "div_core", 0,
>> + EXYNOS4_CLKDIV_CPU, 28, 3, 0),
>> + DIVCLK(NULL, "aclk_200", "mout_aclk_200", 0,
>> + EXYNOS4_CLKDIV_TOP, 0, 3, 0),
>> + DIVCLK(NULL, "aclk_100", "mout_aclk_100", 0,
>> + EXYNOS4_CLKDIV_TOP, 4, 4, 0),
>> + DIVCLK(NULL, "aclk_160", "mout_aclk_160", 0,
>> + EXYNOS4_CLKDIV_TOP, 8, 3, 0),
>> + DIVCLK(NULL, "aclk_133", "mout_aclk_133", 0,
>> + EXYNOS4_CLKDIV_TOP, 12, 3, 0),
>> + DIVCLK("exynos4210-uart.0", "div_uart0", "mout_uart0", 0,
>> + EXYNOS4_CLKDIV_PERIL0, 0, 4, 0),
>> + DIVCLK("exynos4210-uart.1", "div_uart1", "mout_uart1", 0,
>> + EXYNOS4_CLKDIV_PERIL0, 4, 4, 0),
>> + DIVCLK("exynos4210-uart.2", "div_uart2", "mout_uart2", 0,
>> + EXYNOS4_CLKDIV_PERIL0, 8, 4, 0),
>> + DIVCLK("exynos4210-uart.3", "div_uart3", "mout_uart3", 0,
>> + EXYNOS4_CLKDIV_PERIL0, 12, 4, 0),
>> + DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
>> + DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
>> + DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
>> + DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
>> + DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
>> + DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
>> + DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
>> + DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
>> + DIVCLK("exynos4210-spi.0", "div_spi0", "mout_spi0", 0,
>> + EXYNOS4_CLKDIV_PERIL1, 0, 4, 0),
>> + DIVCLK("exynos4210-spi.1", "div_spi1", "mout_spi1", 0,
>> + EXYNOS4_CLKDIV_PERIL1, 16, 4, 0),
>> + DIVCLK("exynos4210-spi.2", "div_spi2", "mout_spi2", 0,
>> + EXYNOS4_CLKDIV_PERIL2, 0, 4, 0),
>> + DIVCLK("exynos4210-spi.0", "div_spi0_pre", "div_spi0", 0,
>> + EXYNOS4_CLKDIV_PERIL1, 8, 8, 0),
>> + DIVCLK("exynos4210-spi.1", "div_spi1_pre", "div_spi1", 0,
>> + EXYNOS4_CLKDIV_PERIL1, 24, 8, 0),
>> + DIVCLK("exynos4210-spi.2", "div_spi2_pre", "div_spi2", 0,
>> + EXYNOS4_CLKDIV_PERIL2, 8, 8, 0),
>> + DIVCLK(NULL, "div_sata", "mout_sata", 0,
>> + EXYNOS4_CLKDIV_FSYS0, 20, 4, 0),
>> + DIVCLK("s5p-mfc", "div_mfc", "mout_mfc", 0,
>> + EXYNOS4_CLKDIV_MFC, 0, 4, 0),
>> + DIVCLK("s5p-mipi-csis.0", "div_csis0", "mout_csis0", 0,
>> + EXYNOS4_CLKDIV_CAM, 24, 4, 0),
>> + DIVCLK("s5p-mipi-csis.1", "div_csis1", "mout_csis1", 0,
>> + EXYNOS4_CLKDIV_CAM, 28, 4, 0),
>> + DIVCLK(NULL, "div_cam0", "mout_cam0", 0,
>> + EXYNOS4_CLKDIV_CAM, 16, 4, 0),
>> + DIVCLK(NULL, "div_cam1", "mout_cam1", 0,
>> + EXYNOS4_CLKDIV_CAM, 20, 4, 0),
>> + DIVCLK("exynos4-fimc.0", "div_fimc0", "mout_fimc0", 0,
>> + EXYNOS4_CLKDIV_CAM, 0, 4, 0),
>> + DIVCLK("exynos4-fimc.1", "div_fimc1", "mout_fimc1", 0,
>> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> + DIVCLK("exynos4-fimc.2", "div_fimc2", "mout_fimc2", 0,
>> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> + DIVCLK("exynos4-fimc.3", "div_fimc3", "mout_fimc3", 0,
>> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> + DIVCLK("exynos4-fb.0", "div_fimd0", "mout_fimd0", 0,
>> + EXYNOS4_CLKDIV_LCD0, 0, 4, 0),
>> + DIVCLK(NULL, "sclk_pixel", "mout_vpll", 0,
>> + EXYNOS4_CLKDIV_TV, 0, 4, 0),
>> +};
>> +
>> +struct samsung_gate_clock exynos4_gate_clks[] = {
>> + GATECLK("exynos4210-uart.0", "uart0", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 0, "uart"),
>> + GATECLK("exynos4210-uart.1", "uart1", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 1, "uart"),
>> + GATECLK("exynos4210-uart.2", "uart2", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 2, "uart"),
>> + GATECLK("exynos4210-uart.3", "uart3", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 3, "uart"),
>> + GATECLK("exynos4210-uart.4", "uart4", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 4, "uart"),
>> + GATECLK("exynos4210-uart.5", "uart5", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 5, "uart"),
>> + GATECLK("exynos4210-uart.0", "uclk0", "div_uart0", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKSRC_MASK_PERIL0, 0, "clk_uart_baud0"),
>> + GATECLK("exynos4210-uart.1", "uclk1", "div_uart1", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKSRC_MASK_PERIL0, 4, "clk_uart_baud0"),
>> + GATECLK("exynos4210-uart.2", "uclk2", "div_uart2", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKSRC_MASK_PERIL0, 8, "clk_uart_baud0"),
>> + GATECLK("exynos4210-uart.3", "uclk3", "div_uart3", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKSRC_MASK_PERIL0, 12, "clk_uart_baud0"),
>> + GATECLK(NULL, "timers", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 24, NULL),
>> + GATECLK("s5p-mipi-csis.0", "csis", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 5, NULL),
>> + GATECLK(NULL, "jpeg", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 6, NULL),
>> + GATECLK("exynos4-fimc.0", "fimc0", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 0, "fimc"),
>> + GATECLK("exynos4-fimc.1", "fimc1", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 1, "fimc"),
>> + GATECLK("exynos4-fimc.2", "fimc2", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 2, "fimc"),
>> + GATECLK("exynos4-fimc.3", "fimc3", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 3, "fimc"),
>> + GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
>> + GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
>> + GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
>> + GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
>> + GATECLK(NULL, "dwmmc", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 9, NULL),
>> + GATECLK("s5p-sdo", "dac", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_TV, 2, NULL),
>> + GATECLK("s5p-mixer", "mixer", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_TV, 1, NULL),
>> + GATECLK("s5p-mixer", "vp", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_TV, 0, NULL),
>> + GATECLK("exynos4-hdmi", "hdmi", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_TV, 3, NULL),
>> + GATECLK("exynos4-hdmi", "hdmiphy", "aclk_160", 0,
>> + S5P_HDMI_PHY_CONTROL, 0, NULL),
>> + GATECLK("s5p-sdo", "dacphy", "aclk_160", 0,
>> + S5P_DAC_PHY_CONTROL, 0, NULL),
>> + GATECLK(NULL, "adc", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 15, NULL),
>> + GATECLK(NULL, "keypad", "aclk_100", 0,
>> + EXYNOS4210_CLKGATE_IP_PERIR, 16, NULL),
>> + GATECLK(NULL, "rtc", "aclk_100", 0,
>> + EXYNOS4210_CLKGATE_IP_PERIR, 15, NULL),
>> + GATECLK(NULL, "watchdog", "aclk_100", 0,
>> + EXYNOS4210_CLKGATE_IP_PERIR, 14, NULL),
>> + GATECLK(NULL, "usbhost", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 12, NULL),
>> + GATECLK(NULL, "otg", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 13, NULL),
>> + GATECLK("exynos4210-spi.0", "spi0", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 16, "spi"),
>> + GATECLK("exynos4210-spi.1", "spi1", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 17, "spi"),
>> + GATECLK("exynos4210-spi.2", "spi2", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 18, "spi"),
>> + GATECLK("samsung-i2s.0", "iis0", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 19, "iis"),
>> + GATECLK("samsung-i2s.1", "iis1", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 20, "iis"),
>> + GATECLK("samsung-i2s.2", "iis2", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 21, "iis"),
>> + GATECLK("samsung-ac97", "ac97", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 27, NULL),
>> + GATECLK("s5p-mfc", "mfc", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_MFC, 0, NULL),
>> + GATECLK("s3c2440-i2c.0", "i2c0", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 6, "i2c"),
>> + GATECLK("s3c2440-i2c.1", "i2c1", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 7, "i2c"),
>> + GATECLK("s3c2440-i2c.2", "i2c2", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 8, "i2c"),
>> + GATECLK("s3c2440-i2c.3", "i2c3", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 9, "i2c"),
>> + GATECLK("s3c2440-i2c.4", "i2c4", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 10, "i2c"),
>> + GATECLK("s3c2440-i2c.5", "i2c5", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 11, "i2c"),
>> + GATECLK("s3c2440-i2c.6", "i2c6", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 12, "i2c"),
>> + GATECLK("s3c2440-i2c.7", "i2c7", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 13, "i2c"),
>> + GATECLK("s3c2440-hdmiphy-i2c", "i2c", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 14, NULL),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_l, 0), "sysmmu0", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_MFC, 1, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_r, 1), "sysmmu1", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_MFC, 2, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(tv, 2), "sysmmu2", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_TV, 4, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(jpeg, 3), "sysmmu3", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 11, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(rot, 4), "sysmmu4", "aclk_200", 0,
>> + EXYNOS4210_CLKGATE_IP_IMAGE, 4, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc0, 5), "sysmmu5", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 7, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc1, 6), "sysmmu6", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 8, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc2, 7), "sysmmu7", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 9, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc3, 8), "sysmmu8", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 10, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimd, 10), "sysmmu10", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_LCD0, 4, "sysmmu"),
>> + GATECLK("dma-pl330.0", "dma0", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 0, "dma"),
>> + GATECLK("dma-pl330.1", "dma1", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 1, "dma"),
>> + GATECLK("exynos4-fb.0", "fimd", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_LCD0, 0, "lcd"),
>> + GATECLK("exynos4210-spi.0", "sclk_spi0", "div_spi0_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_PERIL1, 16, "spi_busclk0"),
>> + GATECLK("exynos4210-spi.1", "sclk_spi1", "div_spi1_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_PERIL1, 20, "spi_busclk0"),
>> + GATECLK("exynos4210-spi.2", "sclk_spi2", "div_spi2_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_PERIL1, 24, "spi_busclk0"),
>> + GATECLK("exynos4-sdhci.0", "sclk_mmc0", "div_mmc0_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_FSYS, 0, "mmc_busclk.2"),
>> + GATECLK("exynos4-sdhci.1", "sclk_mmc1", "div_mmc1_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_FSYS, 4, "mmc_busclk.2"),
>> + GATECLK("exynos4-sdhci.2", "sclk_mmc2", "div_mmc2_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_FSYS, 8, "mmc_busclk.2"),
>> + GATECLK("exynos4-sdhci.3", "sclk_mmc3", "div_mmc3_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_FSYS, 12, "mmc_busclk.2"),
>> + GATECLK("s5p-mipi-csis.0", "sclk_csis0", "div_csis0", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 24, "sclk_csis"),
>> + GATECLK("s5p-mipi-csis.1", "sclk_csis1", "div_csis1", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
>> + GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
>> + GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
>> + GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
>
> + GATECLK("exynos4-fimc.0", "sclk_fimc0", "div_fimc0", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
>
>> + GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
>
> + GATECLK("exynos4-fimc.1", "sclk_fimc1", "div_fimc1", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
>
>> + GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
>
> + GATECLK("exynos4-fimc.2", "sclk_fimc2", "div_fimc2", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
>
>> + GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
>
> + GATECLK("exynos4-fimc.3", "sclk_fimc3", "div_fimc3", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
>
>> + GATECLK("exynos4-fb.0", "sclk_fimd", "div_fimd0", 0,
>> + EXYNOS4_CLKSRC_MASK_LCD0, 0, "sclk_fimd"),
>> +};
>> +
>> +/* register clock common to all Exynos4 platforms */
>> +void __init exynos4_clk_init(void)
>> +{
>> + samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
>> + ARRAY_SIZE(exynos4_fixed_rate_clks));
>> + samsung_clk_register_mux(exynos4_mux_clks,
>> + ARRAY_SIZE(exynos4_mux_clks));
>> + samsung_clk_register_div(exynos4_div_clks,
>> + ARRAY_SIZE(exynos4_div_clks));
>> + samsung_clk_register_gate(exynos4_gate_clks,
>> + ARRAY_SIZE(exynos4_gate_clks));
>> +}
>> +
>> +/*
>> + * Exynos4210 Specific Clocks
>> + */
>> +
>> +static const char *exynos4210_vpll_parent_names[] __initdata = {
>> + "mout_vpll_src" };
>> +static const char *mout_vpll_src_parents[] __initdata = {
>> + "fin_pll", "sclk_hdmi24m" };
>> +static const char *exynos4210_mout_vpll_parents[] __initdata = {
>> + "mout_vpll_src", "fout_vpll", };
>> +
>> +/* Exynos4210 specific fixed rate clocks */
>> +static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] = {
>> + FRATE_CLK(NULL, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
>> +};
>> +
>> +/* Exynos4210 specific mux-type clocks */
>> +static struct samsung_mux_clock exynos4210_mux_clks[] = {
>> + MUXCLK(NULL, "mout_vpll_src", mout_vpll_src_parents, 0,
>> + EXYNOS4_CLKSRC_TOP1, 0, 1, 0),
>> + MUXCLK(NULL, "mout_vpll", exynos4210_mout_vpll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
>> + MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
>> + EXYNOS4_CLKSRC_CPU, 8, 1, 0),
>> +};
>> +
>> +static unsigned long exynos4210_get_rate_apll(unsigned long xtal_rate)
>> +{
>> + return s5p_get_pll45xx(xtal_rate,
>> + __raw_readl(EXYNOS4_APLL_CON0), pll_4508);
>> +}
>> +
>> +static unsigned long exynos4210_get_rate_mpll(unsigned long xtal_rate)
>> +{
>> + return s5p_get_pll45xx(xtal_rate,
>> + __raw_readl(EXYNOS4_MPLL_CON0), pll_4508);
>> +}
>> +
>> +static unsigned long exynos4210_get_rate_epll(unsigned long xtal_rate)
>> +{
>> + return s5p_get_pll46xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
>> + __raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
>> +}
>> +
>> +static unsigned long exynos4210_get_rate_vpll(unsigned long
>> vpllsrc_rate) +{
>> + return s5p_get_pll46xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
>> + __raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
>> +}
>> +
>> +static u32 exynos4_vpll_div[][8] = {
>> + { 54000000, 3, 53, 3, 1024, 0, 17, 0 },
>> + { 108000000, 3, 53, 2, 1024, 0, 17, 0 },
>> +};
>> +
>> +static int exynos4210_vpll_set_rate(unsigned long rate)
>> +{
>> + unsigned int vpll_con0, vpll_con1 = 0;
>> + unsigned int i;
>> +
>> + vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
>> + vpll_con0 &= ~(0x1 << 27 | \
>> + PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \
>> + PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
>> + PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
>> +
>> + vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
>> + vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT | \
>> + PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT | \
>> + PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
>> +
>> + for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
>> + if (exynos4_vpll_div[i][0] == rate) {
>> + vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
>> + vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
>> + vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
>> + vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
>> + vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
>> + vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
>> + vpll_con0 |= exynos4_vpll_div[i][7] << 27;
>> + break;
>> + }
>> + }
>> +
>> + if (i == ARRAY_SIZE(exynos4_vpll_div)) {
>> + pr_err("%s: Invalid Clock VPLL Frequency\n", __func__);
>> + return -EINVAL;
>> + }
>> +
>> + __raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
>> + __raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
>> +
>> + /* Wait for VPLL lock */
>> + while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
>> + continue;
>
> Is it guaranteed to lock in some reasonable time? Maybe some kind of
> timeout should be added?

Yes, a timeout mechanism is needed here. I have just migrated the
existing clock code over to common clock framework.

>
>> +
>> + return 0;
>> +}
>> +
>> +/* Exynos4210 specific clock registration */
>> +void __init exynos4210_clk_init(void)
>> +{
>> + group1_parents[4] = "sclk_usbphy1";
>> +
>> + exynos4_clk_init();
>> +
>> + samsung_clk_register_pll("fout_apll", pll_parent_names,
>> + NULL, exynos4210_get_rate_apll);
>> + samsung_clk_register_pll("fout_mpll", pll_parent_names,
>> + NULL, exynos4210_get_rate_mpll);
>> + samsung_clk_register_pll("fout_epll", pll_parent_names,
>> + NULL, exynos4210_get_rate_epll);
>> + samsung_clk_register_pll("fout_vpll", exynos4210_vpll_parent_names,
>> + exynos4210_vpll_set_rate, exynos4210_get_rate_vpll);
>> +
>> + samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks,
>> + ARRAY_SIZE(exynos4210_fixed_rate_clks));
>> + samsung_clk_register_mux(exynos4210_mux_clks,
>> + ARRAY_SIZE(exynos4210_mux_clks));
>> +
>> + pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
>> + _get_rate("fout_apll"), _get_rate("fout_mpll"),
>> + _get_rate("fout_epll"), _get_rate("fout_vpll"));
>> +
>> + pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
>> + " ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
>> + _get_rate("aclk_200"), _get_rate("aclk_100"),
>> + _get_rate("aclk_160"), _get_rate("aclk_133"));
>> +}
>> +
>> +/*
>> + * Exynos4212 Specific Clocks
>> + */
>> +
>> +static const char *exynos4212_mout_vpll_parents[] __initdata = {
>> + "fin_pll", "fout_vpll", };
>> +
>> +/* Exynos4212 specific mux clocks */
>> +static struct samsung_mux_clock exynos4212_mux_clks[] = {
>> + MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
>> + EXYNOS4_CLKSRC_DMC, 12, 1, 0),
>> + MUXCLK(NULL, "mout_vpll", exynos4212_mout_vpll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
>> +};
>> +
>> +static unsigned long exynos4212_get_rate_apll(unsigned long xtal_rate)
>> +{
>> + return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
>> +}
>> +
>> +static unsigned long exynos4212_get_rate_mpll(unsigned long xtal_rate)
>> +{
>> + return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_MPLL_CON0));
>> +}
>> +
>> +static unsigned long exynos4212_get_rate_epll(unsigned long xtal_rate)
>> +{
>> + return s5p_get_pll36xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
>> + __raw_readl(EXYNOS4_EPLL_CON1));
>> +}
>> +
>> +static unsigned long exynos4212_get_rate_vpll(unsigned long
>> vpllsrc_rate) +{
>> + return s5p_get_pll36xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
>> + __raw_readl(EXYNOS4_VPLL_CON1));
>> +}
>> +
>> +/* Exynos4212 specific clock registeration */
>> +void __init exynos4212_clk_init(void)
>> +{
>> + exynos4_clk_init();
>> +
>> + samsung_clk_register_pll("fout_apll", pll_parent_names,
>> + NULL, exynos4212_get_rate_apll);
>> + samsung_clk_register_pll("fout_mpll", pll_parent_names,
>> + NULL, exynos4212_get_rate_mpll);
>> + samsung_clk_register_pll("fout_epll", pll_parent_names,
>> + NULL, exynos4212_get_rate_epll);
>> + samsung_clk_register_pll("fout_vpll", pll_parent_names,
>> + NULL, exynos4212_get_rate_vpll);
>> +
>> + samsung_clk_register_mux(exynos4212_mux_clks,
>> + ARRAY_SIZE(exynos4212_mux_clks));
>> +
>> + pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
>> + _get_rate("fout_apll"), _get_rate("fout_mpll"),
>> + _get_rate("fout_epll"), _get_rate("fout_vpll"));
>> +
>> + pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
>> + " ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
>> + _get_rate("aclk_200"), _get_rate("aclk_100"),
>> + _get_rate("aclk_160"), _get_rate("aclk_133"));
>> +}
>> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
>> new file mode 100644
>> index 0000000..65156b9
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk.c
>> @@ -0,0 +1,231 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 Linaro Ltd.
>> + *
>> + * 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 file includes utility functions to register clocks to common
>> + * clock framework for Samsung platforms. This includes an
>> implementation + * of Samsung 'pll type' clock to represent the
>> implementation of the + * pll found on Samsung platforms. In addition to
>> that, utility functions + * to register mux, div, gate and fixed rate
>> types of clocks are included. +*/
>> +
>> +#include "clk.h"
>> +
>> +static DEFINE_SPINLOCK(lock);
>> +
>> +#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
>> +
>> +/* determine the output clock speed of the pll */
>> +static unsigned long samsung_clk_pll_recalc_rate(struct clk_hw *hw,
>> + unsigned long parent_rate)
>> +{
>> + struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
>> +
>> + if (clk_pll->get_rate)
>> + return to_clk_pll(hw)->get_rate(parent_rate);
>> +
>> + return 0;
>> +}
>> +
>> +/* round operation not supported */
>> +static long samsung_clk_pll_round_rate(struct clk_hw *hw, unsigned long
>> drate, + unsigned long *prate)
>> +{
>> + return samsung_clk_pll_recalc_rate(hw, *prate);
>> +}
>> +
>> +/* set the clock output rate of the pll */
>> +static int samsung_clk_pll_set_rate(struct clk_hw *hw, unsigned long
>> drate, + unsigned long prate)
>> +{
>> + struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
>> +
>> + if (clk_pll->set_rate)
>> + return to_clk_pll(hw)->set_rate(drate);
>> +
>> + return 0;
>> +}
>> +
>> +/* clock operations for samsung pll clock type */
>> +static const struct clk_ops samsung_clk_pll_ops = {
>> + .recalc_rate = samsung_clk_pll_recalc_rate,
>> + .round_rate = samsung_clk_pll_round_rate,
>> + .set_rate = samsung_clk_pll_set_rate,
>> +};
>> +
>> +/* register a samsung pll type clock */
>> +void __init samsung_clk_register_pll(const char *name, const char
>> **pnames, + int (*set_rate)(unsigned long rate),
>> + unsigned long (*get_rate)(unsigned long rate))
>> +{
>> + struct samsung_clk_pll *clk_pll;
>> + struct clk *clk;
>> + struct clk_init_data init;
>> + int ret;
>> +
>> + clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>> + if (!clk_pll) {
>> + pr_err("%s: could not allocate pll clk %s\n", __func__, name);
>> + return;
>> + }
>> +
>> + init.name = name;
>> + init.ops = &samsung_clk_pll_ops;
>> + init.flags = CLK_GET_RATE_NOCACHE;
>> + init.parent_names = pnames;
>> + init.num_parents = 1;
>> +
>> + clk_pll->set_rate = set_rate;
>> + clk_pll->get_rate = get_rate;
>> + clk_pll->hw.init = &init;
>> +
>> + /* register the clock */
>> + clk = clk_register(NULL, &clk_pll->hw);
>> + if (IS_ERR(clk)) {
>> + pr_err("%s: failed to register pll clock %s\n", __func__,
>> + name);
>> + kfree(clk_pll);
>> + return;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, name, NULL);
>> + if (ret)
>> + pr_err("%s: failed to register clock lookup for %s", __func__,
>> + name);
>> +}
>> +
>> +/* register a list of fixed clocks */
>> +void __init samsung_clk_register_fixed_rate(
>> + struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
>> +{
>> + struct clk *clk;
>> + unsigned int idx, ret;
>> +
>> + for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> + clk = clk_register_fixed_rate(NULL, clk_list->name,
>> + clk_list->parent_name, clk_list->flags,
>> + clk_list->fixed_rate);
>> + if (IS_ERR_OR_NULL(clk)) {
>
> Is the check for NULL needed here? Looking at samsung_fixed_rate_clock
> and clk_register, the convention is to always return ERR_PTR on error.

Ok, check for NULL is not really required. I will remove it.

>
>> + pr_err("clock: failed to register clock %s\n",
>> + clk_list->name);
>> + continue;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, clk_list->name,
>> + clk_list->dev_name);
>> + if (ret)
>> + pr_err("clock: failed to register clock lookup for %s",
>> + clk_list->name);
>> + }
>> +}
>> +
>> +/* register a list of mux clocks */
>> +void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
>> + unsigned int nr_clk)
>> +{
>> + struct clk *clk;
>> + unsigned int idx, ret;
>> +
>> + for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> + clk = clk_register_mux(NULL, clk_list->name,
>> + clk_list->parent_names, clk_list->num_parents,
>> + clk_list->flags, clk_list->reg, clk_list->shift,
>> + clk_list->width, clk_list->mux_flags, &lock);
>> + if (IS_ERR_OR_NULL(clk)) {
>
> See my comment for samsung_clk_register_fixed_rate .
>
>> + pr_err("clock: failed to register clock %s\n",
>> + clk_list->name);
>> + continue;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, clk_list->name,
>> + clk_list->dev_name);
>> + if (ret)
>> + pr_err("clock: failed to register clock lookup for %s",
>> + clk_list->name);
>> +
>> + if (clk_list->alias)
>> + clk_register_clkdev(clk, clk_list->alias,
>> + clk_list->dev_name);
>> + }
>> +}
>> +
>> +/* reguster a list of div clocks */
>> +void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
>> + unsigned int nr_clk)
>> +{
>> + struct clk *clk;
>> + unsigned int idx, ret;
>> +
>> + for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> + clk = clk_register_divider(NULL, clk_list->name,
>> + clk_list->parent_name, clk_list->flags, clk_list->reg,
>> + clk_list->shift, clk_list->width, clk_list->div_flags,
>> + &lock);
>> + if (IS_ERR_OR_NULL(clk)) {
>
> See my comment for samsung_clk_register_fixed_rate .
>
>> + pr_err("clock: failed to register clock %s\n",
>> + clk_list->name);
>> + continue;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, clk_list->name,
>> + clk_list->dev_name);
>> + if (ret)
>> + pr_err("clock: failed to register clock lookup for %s",
>> + clk_list->name);
>> +
>> + if (clk_list->alias)
>> + clk_register_clkdev(clk, clk_list->alias,
>> + clk_list->dev_name);
>> + }
>> +}
>> +
>> +/* register a list of gate clocks */
>> +void __init samsung_clk_register_gate(struct samsung_gate_clock
>> *clk_list, + unsigned int nr_clk)
>> +{
>> + struct clk *clk;
>> + unsigned int idx, ret;
>> +
>> + for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> + clk = clk_register_gate(NULL, clk_list->name,
>> + clk_list->parent_name, clk_list->flags, clk_list->reg,
>> + clk_list->bit_idx, clk_list->gate_flags, &lock);
>> + if (IS_ERR_OR_NULL(clk)) {
>
> See my comment for samsung_clk_register_fixed_rate .
>
>> + pr_err("clock: failed to register clock %s\n",
>> + clk_list->name);
>> + continue;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, clk_list->name,
>> + clk_list->dev_name);
>> + if (ret) {
>> + pr_err("clock: failed to register clock lookup for %s",
>> + clk_list->name);
>> + continue;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, clk_list->alias,
>> + clk_list->dev_name);
>> + if (ret)
>> + pr_err("clock: failed to register alias %s for clock "
>> + " %s", clk_list->alias, clk_list->name);
>> + }
>> +}
>> +
>> +/* utility function to get the rate of a specified clock */
>> +unsigned long _get_rate(const char *clk_name)
>> +{
>> + struct clk *clk;
>> + unsigned long rate;
>> +
>> + clk = clk_get(NULL, clk_name);
>> + if (IS_ERR(clk))
>> + return 0;
>> + rate = clk_get_rate(clk);
>> + clk_put(clk);
>> + return rate;
>> +}
>
> Shouldn't it be moved to clk-exynos4.c and made static?

This can be used on any platform and not just specific to Exynos4.

Thanks,
Thomas.

>
> Best regards,
> --
> Tomasz Figa
> Samsung Poland R&D Center
>

2012-10-08 06:34:22

by Thomas Abraham

[permalink] [raw]
Subject: Re: [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework

Hi Tomasz,

On 3 October 2012 19:40, Tomasz Figa <[email protected]> wrote:
> Hi Chander, Thomas,
>
> I can see one more problem here.
>
> Based on the fact that sdhci-s3c driver receives only the endpoint gate
> clock (hsmmc), doesn't the following setup make the driver unable to change
> the frequency of this clock?

The driver never changes the clock frequency of the core system clocks
nor of the endpoint. There are internal dividers inside the sdhci
controller which are divide to acheive required clock speed.

Thanks,
Thomas.

>
> On Monday 01 of October 2012 17:39:21 [email protected] wrote:
>> +static struct samsung_mux_clock exynos4_mux_clks[] = {
> [snip]
>> + MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
>> + MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
>> + MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
>> + MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
> [snip]
>> +};
>> +
>> +static struct samsung_div_clock exynos4_div_clks[] = {
> [snip]
>> + DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
>> + DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
>> + DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
>> + DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
>> + DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
>> + DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
>> + DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
>> + DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
> [snip]
>> +};
>> +
>> +struct samsung_gate_clock exynos4_gate_clks[] = {
> [snip]
>> + GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
>> + GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
>> + GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
>> + GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
> [snip]
>> +};
>
> Best regards,
> --
> Tomasz Figa
> Samsung Poland R&D Center
>

2012-10-08 06:34:35

by Thomas Abraham

[permalink] [raw]
Subject: Re: [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework

Hi Sylwester,

Thanks for reviewing this patch series.

On 6 October 2012 00:21, Sylwester Nawrocki
<[email protected]> wrote:
> Hello,
>
> On 10/01/2012 02:09 PM, [email protected] wrote:
>> From: Thomas Abraham<[email protected]>
>>
>> Register clocks for Exynos4 platfotms using common clock framework.
>> Also included are set of helper functions for clock registration
>> that can be reused on other Samsung platforms as well.
>>
>> Cc: Mike Turquette<[email protected]>
>> Cc: Kukjin Kim<[email protected]>
>> Signed-off-by: Thomas Abraham<[email protected]>
>> ---
>> arch/arm/mach-exynos/Kconfig | 1 +
>> arch/arm/mach-exynos/common.h | 3 +
>> arch/arm/mach-exynos/mct.c | 11 +-
>> arch/arm/plat-samsung/Kconfig | 4 +-
>> drivers/clk/Makefile | 1 +
>> drivers/clk/clk.c | 12 +-
>> drivers/clk/samsung/Makefile | 6 +
>> drivers/clk/samsung/clk-exynos4.c | 585 +++++++++++++++++++++++++++++++++++++
>> drivers/clk/samsung/clk.c | 231 +++++++++++++++
>> drivers/clk/samsung/clk.h | 190 ++++++++++++
>> 10 files changed, 1037 insertions(+), 7 deletions(-)
>> create mode 100644 drivers/clk/samsung/Makefile
>> create mode 100644 drivers/clk/samsung/clk-exynos4.c
>> create mode 100644 drivers/clk/samsung/clk.c
>> create mode 100644 drivers/clk/samsung/clk.h
> ...
>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
>> index 56e4495..456c50b 100644
>> --- a/drivers/clk/clk.c
>> +++ b/drivers/clk/clk.c
>> @@ -1196,6 +1196,7 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
>> int __clk_init(struct device *dev, struct clk *clk)
>> {
>> int i, ret = 0;
>> + u8 index;
>> struct clk *orphan;
>> struct hlist_node *tmp, *tmp2;
>>
>> @@ -1259,6 +1260,7 @@ int __clk_init(struct device *dev, struct clk *clk)
>> __clk_lookup(clk->parent_names[i]);
>> }
>>
>> +
>> clk->parent = __clk_init_parent(clk);
>>
>> /*
>> @@ -1298,11 +1300,13 @@ int __clk_init(struct device *dev, struct clk *clk)
>> * this clock
>> */
>> hlist_for_each_entry_safe(orphan, tmp, tmp2,&clk_orphan_list, child_node)
>> - for (i = 0; i< orphan->num_parents; i++)
>> - if (!strcmp(clk->name, orphan->parent_names[i])) {
>> + if (orphan->num_parents> 1) {
>> + index = orphan->ops->get_parent(orphan->hw);
>> + if (!strcmp(clk->name, orphan->parent_names[index]))
>> __clk_reparent(orphan, clk);
>> - break;
>> - }
>> + } else if (!strcmp(clk->name, orphan->parent_names[0])) {
>> + __clk_reparent(orphan, clk);
>> + }
>
> As this touches generic code it should rather be put into a separate patch,
> along with an explanation why such a change is needed.

There is fix for this in mainline now.

>
>>
>> /*
>> * optional platform-specific magic
>> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
>> new file mode 100644
>> index 0000000..69487f7
>> --- /dev/null
>> +++ b/drivers/clk/samsung/Makefile
>> @@ -0,0 +1,6 @@
>> +#
>> +# Samsung Clock specific Makefile
>> +#
>> +
>> +obj-$(CONFIG_PLAT_SAMSUNG) += clk.o
>> +obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
>> diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
>> new file mode 100644
>> index 0000000..74a6f03
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk-exynos4.c
>> @@ -0,0 +1,585 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 Linaro Ltd.
>> + *
>> + * 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.
>> + *
>> + * Common Clock Framework support for all Exynos4 platforms
>> +*/
>> +
>> +#include<linux/clk.h>
>> +#include<linux/clkdev.h>
>> +#include<linux/io.h>
>> +#include<linux/clk-provider.h>
>> +
>> +#include<plat/pll.h>
>> +#include<plat/cpu.h>
>> +#include<mach/regs-clock.h>
>> +#include<mach/sysmmu.h>
>> +#include<plat/map-s5p.h>
>> +
>> +#include "clk.h"
>> +
>> +#define EXYNOS4_OP_MODE (S5P_VA_CHIPID + 8)
>> +
>> +static const char *pll_parent_names[] __initdata = { "fin_pll" };
>> +static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
>> +static const char *mout_apll_parents[] __initdata = { "fin_pll", "fout_apll", };
>> +static const char *mout_mpll_parents[] __initdata = { "fin_pll", "fout_mpll", };
>> +static const char *mout_epll_parents[] __initdata = { "fin_pll", "fout_epll", };
>> +
>> +static const char *sclk_ampll_parents[] __initdata = {
>> + "mout_mpll", "sclk_apll", };
>> +
>> +static const char *sclk_evpll_parents[] __initdata = {
>> + "mout_epll", "mout_vpll", };
>> +
>> +static const char *mout_core_parents[] __initdata = {
>> + "mout_apll", "mout_mpll", };
>> +
>> +static const char *mout_mfc_parents[] __initdata = {
>> + "mout_mfc0", "mout_mfc1", };
>> +
>> +static const char *mout_dac_parents[] __initdata = {
>> + "mout_vpll", "sclk_hdmiphy", };
>> +
>> +static const char *mout_hdmi_parents[] __initdata = {
>> + "sclk_pixel", "sclk_hdmiphy", };
>> +
>> +static const char *mout_mixer_parents[] __initdata = {
>> + "sclk_dac", "sclk_hdmi", };
>> +
>> +static const char *group1_parents[] __initdata = {
>> + "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
>> + "none", "sclk_hdmiphy", "mout_mpll", "mout_epll",
>> + "mout_vpll" };
>> +
>> +static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
>> + FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
>> + FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),
>> + FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
>> + FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
>> + FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
>> +};
>> +
>> +static struct samsung_mux_clock exynos4_mux_clks[] = {
>> + MUXCLK(NULL, "fin_pll", fin_pll_parents, 0,
>> + EXYNOS4_OP_MODE, 0, 1, 0),
>> + MUXCLK(NULL, "mout_apll", mout_apll_parents, 0,
>> + EXYNOS4_CLKSRC_CPU, 0, 1, 0),
>> + MUXCLK(NULL, "mout_epll", mout_epll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 4, 1, 0),
>> + MUXCLK(NULL, "mout_core", mout_core_parents, 0,
>> + EXYNOS4_CLKSRC_CPU, 16, 1, 0),
>> + MUXCLK(NULL, "mout_aclk_200", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 12, 1, 0),
>> + MUXCLK(NULL, "mout_aclk_100", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 16, 1, 0),
>> + MUXCLK(NULL, "mout_aclk_160", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 20, 1, 0),
>> + MUXCLK(NULL, "mout_aclk_133", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_TOP0, 24, 1, 0),
>> + MUXCLK("exynos4210-uart.0", "mout_uart0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL0, 0, 4, 0),
>> + MUXCLK("exynos4210-uart.1", "mout_uart1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL0, 4, 4, 0),
>> + MUXCLK("exynos4210-uart.2", "mout_uart2", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL0, 8, 4, 0),
>> + MUXCLK("exynos4210-uart.3", "mout_uart3", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL0, 12, 4, 0),
>> + MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
>> + MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
>> + MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
>> + MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
>> + MUXCLK("exynos4210-spi.0", "mout_spi0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL1, 16, 4, 0),
>> + MUXCLK("exynos4210-spi.1", "mout_spi1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL1, 20, 4, 0),
>> + MUXCLK("exynos4210-spi.2", "mout_spi2", group1_parents, 0,
>> + EXYNOS4_CLKSRC_PERIL1, 24, 4, 0),
>> + MUXCLK(NULL, "mout_sata", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_FSYS, 24, 1, 0),
>> + MUXCLK(NULL, "mout_mfc0", sclk_ampll_parents, 0,
>> + EXYNOS4_CLKSRC_MFC, 0, 1, 0),
>> + MUXCLK(NULL, "mout_mfc1", sclk_evpll_parents, 0,
>> + EXYNOS4_CLKSRC_MFC, 4, 1, 0),
>> + MUXCLK("s5p-mfc", "mout_mfc", mout_mfc_parents, 0,
>> + EXYNOS4_CLKSRC_MFC, 8, 1, 0),
>> + MUXCLK("s5p-mipi-csis.0", "mout_csis0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 24, 4, 0),
>> + MUXCLK("s5p-mipi-csis.1", "mout_csis1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 28, 4, 0),
>> + MUXCLK(NULL, "mout_cam0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 16, 4, 0),
>> + MUXCLK(NULL, "mout_cam1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 20, 4, 0),
>> + MUXCLK("exynos4-fimc.0", "mout_fimc0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 0, 4, 0),
>> + MUXCLK("exynos4-fimc.1", "mout_fimc1", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 4, 4, 0),
>> + MUXCLK("exynos4-fimc.2", "mout_fimc2", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 8, 4, 0),
>> + MUXCLK("exynos4-fimc.3", "mout_fimc3", group1_parents, 0,
>> + EXYNOS4_CLKSRC_CAM, 12, 4, 0),
>> + MUXCLK("exynos4-fb.0", "mout_fimd0", group1_parents, 0,
>> + EXYNOS4_CLKSRC_LCD0, 0, 4, 0),
>> + MUXCLK(NULL, "sclk_dac", mout_dac_parents, 0,
>> + EXYNOS4_CLKSRC_TV, 8, 1, 0),
>> + MUXCLK(NULL, "sclk_hdmi", mout_hdmi_parents, 0,
>> + EXYNOS4_CLKSRC_TV, 0, 1, 0),
>> + MUXCLK(NULL, "sclk_mixer", mout_mixer_parents, 0,
>> + EXYNOS4_CLKSRC_TV, 4, 1, 0),
>> +};
>> +
>> +static struct samsung_div_clock exynos4_div_clks[] = {
>> + DIVCLK(NULL, "sclk_apll", "mout_apll", 0,
>> + EXYNOS4_CLKDIV_CPU, 24, 3, 0),
>> + DIVCLK(NULL, "div_core", "mout_core", 0,
>> + EXYNOS4_CLKDIV_CPU, 0, 3, 0),
>> + DIVCLK(NULL, "armclk", "div_core", 0,
>> + EXYNOS4_CLKDIV_CPU, 28, 3, 0),
>> + DIVCLK(NULL, "aclk_200", "mout_aclk_200", 0,
>> + EXYNOS4_CLKDIV_TOP, 0, 3, 0),
>> + DIVCLK(NULL, "aclk_100", "mout_aclk_100", 0,
>> + EXYNOS4_CLKDIV_TOP, 4, 4, 0),
>> + DIVCLK(NULL, "aclk_160", "mout_aclk_160", 0,
>> + EXYNOS4_CLKDIV_TOP, 8, 3, 0),
>> + DIVCLK(NULL, "aclk_133", "mout_aclk_133", 0,
>> + EXYNOS4_CLKDIV_TOP, 12, 3, 0),
>> + DIVCLK("exynos4210-uart.0", "div_uart0", "mout_uart0", 0,
>> + EXYNOS4_CLKDIV_PERIL0, 0, 4, 0),
>> + DIVCLK("exynos4210-uart.1", "div_uart1", "mout_uart1", 0,
>> + EXYNOS4_CLKDIV_PERIL0, 4, 4, 0),
>> + DIVCLK("exynos4210-uart.2", "div_uart2", "mout_uart2", 0,
>> + EXYNOS4_CLKDIV_PERIL0, 8, 4, 0),
>> + DIVCLK("exynos4210-uart.3", "div_uart3", "mout_uart3", 0,
>> + EXYNOS4_CLKDIV_PERIL0, 12, 4, 0),
>> + DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
>> + DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
>> + DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
>> + DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
>> + EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
>> + DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
>> + DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
>> + DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
>> + DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
>> + EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
>> + DIVCLK("exynos4210-spi.0", "div_spi0", "mout_spi0", 0,
>> + EXYNOS4_CLKDIV_PERIL1, 0, 4, 0),
>> + DIVCLK("exynos4210-spi.1", "div_spi1", "mout_spi1", 0,
>> + EXYNOS4_CLKDIV_PERIL1, 16, 4, 0),
>> + DIVCLK("exynos4210-spi.2", "div_spi2", "mout_spi2", 0,
>> + EXYNOS4_CLKDIV_PERIL2, 0, 4, 0),
>> + DIVCLK("exynos4210-spi.0", "div_spi0_pre", "div_spi0", 0,
>> + EXYNOS4_CLKDIV_PERIL1, 8, 8, 0),
>> + DIVCLK("exynos4210-spi.1", "div_spi1_pre", "div_spi1", 0,
>> + EXYNOS4_CLKDIV_PERIL1, 24, 8, 0),
>> + DIVCLK("exynos4210-spi.2", "div_spi2_pre", "div_spi2", 0,
>> + EXYNOS4_CLKDIV_PERIL2, 8, 8, 0),
>> + DIVCLK(NULL, "div_sata", "mout_sata", 0,
>> + EXYNOS4_CLKDIV_FSYS0, 20, 4, 0),
>> + DIVCLK("s5p-mfc", "div_mfc", "mout_mfc", 0,
>> + EXYNOS4_CLKDIV_MFC, 0, 4, 0),
>> + DIVCLK("s5p-mipi-csis.0", "div_csis0", "mout_csis0", 0,
>> + EXYNOS4_CLKDIV_CAM, 24, 4, 0),
>> + DIVCLK("s5p-mipi-csis.1", "div_csis1", "mout_csis1", 0,
>> + EXYNOS4_CLKDIV_CAM, 28, 4, 0),
>> + DIVCLK(NULL, "div_cam0", "mout_cam0", 0,
>> + EXYNOS4_CLKDIV_CAM, 16, 4, 0),
>> + DIVCLK(NULL, "div_cam1", "mout_cam1", 0,
>> + EXYNOS4_CLKDIV_CAM, 20, 4, 0),
>> + DIVCLK("exynos4-fimc.0", "div_fimc0", "mout_fimc0", 0,
>> + EXYNOS4_CLKDIV_CAM, 0, 4, 0),
>> + DIVCLK("exynos4-fimc.1", "div_fimc1", "mout_fimc1", 0,
>> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> + DIVCLK("exynos4-fimc.2", "div_fimc2", "mout_fimc2", 0,
>> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> + DIVCLK("exynos4-fimc.3", "div_fimc3", "mout_fimc3", 0,
>> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> + DIVCLK("exynos4-fb.0", "div_fimd0", "mout_fimd0", 0,
>> + EXYNOS4_CLKDIV_LCD0, 0, 4, 0),
>> + DIVCLK(NULL, "sclk_pixel", "mout_vpll", 0,
>> + EXYNOS4_CLKDIV_TV, 0, 4, 0),
>> +};
>> +
>> +struct samsung_gate_clock exynos4_gate_clks[] = {
>> + GATECLK("exynos4210-uart.0", "uart0", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 0, "uart"),
>> + GATECLK("exynos4210-uart.1", "uart1", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 1, "uart"),
>> + GATECLK("exynos4210-uart.2", "uart2", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 2, "uart"),
>> + GATECLK("exynos4210-uart.3", "uart3", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 3, "uart"),
>> + GATECLK("exynos4210-uart.4", "uart4", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 4, "uart"),
>> + GATECLK("exynos4210-uart.5", "uart5", "aclk_100", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKGATE_IP_PERIL, 5, "uart"),
>> + GATECLK("exynos4210-uart.0", "uclk0", "div_uart0", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKSRC_MASK_PERIL0, 0, "clk_uart_baud0"),
>> + GATECLK("exynos4210-uart.1", "uclk1", "div_uart1", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKSRC_MASK_PERIL0, 4, "clk_uart_baud0"),
>> + GATECLK("exynos4210-uart.2", "uclk2", "div_uart2", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKSRC_MASK_PERIL0, 8, "clk_uart_baud0"),
>> + GATECLK("exynos4210-uart.3", "uclk3", "div_uart3", CLK_SET_RATE_PARENT,
>> + EXYNOS4_CLKSRC_MASK_PERIL0, 12, "clk_uart_baud0"),
>> + GATECLK(NULL, "timers", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 24, NULL),
>> + GATECLK("s5p-mipi-csis.0", "csis", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 5, NULL),
>> + GATECLK(NULL, "jpeg", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 6, NULL),
>> + GATECLK("exynos4-fimc.0", "fimc0", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 0, "fimc"),
>> + GATECLK("exynos4-fimc.1", "fimc1", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 1, "fimc"),
>> + GATECLK("exynos4-fimc.2", "fimc2", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 2, "fimc"),
>> + GATECLK("exynos4-fimc.3", "fimc3", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 3, "fimc"),
>> + GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
>> + GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
>> + GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
>> + GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
>> + GATECLK(NULL, "dwmmc", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 9, NULL),
>> + GATECLK("s5p-sdo", "dac", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_TV, 2, NULL),
>> + GATECLK("s5p-mixer", "mixer", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_TV, 1, NULL),
>> + GATECLK("s5p-mixer", "vp", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_TV, 0, NULL),
>> + GATECLK("exynos4-hdmi", "hdmi", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_TV, 3, NULL),
>> + GATECLK("exynos4-hdmi", "hdmiphy", "aclk_160", 0,
>> + S5P_HDMI_PHY_CONTROL, 0, NULL),
>> + GATECLK("s5p-sdo", "dacphy", "aclk_160", 0,
>> + S5P_DAC_PHY_CONTROL, 0, NULL),
>> + GATECLK(NULL, "adc", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 15, NULL),
>> + GATECLK(NULL, "keypad", "aclk_100", 0,
>> + EXYNOS4210_CLKGATE_IP_PERIR, 16, NULL),
>> + GATECLK(NULL, "rtc", "aclk_100", 0,
>> + EXYNOS4210_CLKGATE_IP_PERIR, 15, NULL),
>> + GATECLK(NULL, "watchdog", "aclk_100", 0,
>> + EXYNOS4210_CLKGATE_IP_PERIR, 14, NULL),
>> + GATECLK(NULL, "usbhost", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 12, NULL),
>> + GATECLK(NULL, "otg", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 13, NULL),
>> + GATECLK("exynos4210-spi.0", "spi0", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 16, "spi"),
>> + GATECLK("exynos4210-spi.1", "spi1", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 17, "spi"),
>> + GATECLK("exynos4210-spi.2", "spi2", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 18, "spi"),
>> + GATECLK("samsung-i2s.0", "iis0", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 19, "iis"),
>> + GATECLK("samsung-i2s.1", "iis1", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 20, "iis"),
>> + GATECLK("samsung-i2s.2", "iis2", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 21, "iis"),
>> + GATECLK("samsung-ac97", "ac97", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 27, NULL),
>> + GATECLK("s5p-mfc", "mfc", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_MFC, 0, NULL),
>> + GATECLK("s3c2440-i2c.0", "i2c0", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 6, "i2c"),
>> + GATECLK("s3c2440-i2c.1", "i2c1", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 7, "i2c"),
>> + GATECLK("s3c2440-i2c.2", "i2c2", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 8, "i2c"),
>> + GATECLK("s3c2440-i2c.3", "i2c3", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 9, "i2c"),
>> + GATECLK("s3c2440-i2c.4", "i2c4", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 10, "i2c"),
>> + GATECLK("s3c2440-i2c.5", "i2c5", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 11, "i2c"),
>> + GATECLK("s3c2440-i2c.6", "i2c6", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 12, "i2c"),
>> + GATECLK("s3c2440-i2c.7", "i2c7", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 13, "i2c"),
>> + GATECLK("s3c2440-hdmiphy-i2c", "i2c", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_PERIL, 14, NULL),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_l, 0), "sysmmu0", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_MFC, 1, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_r, 1), "sysmmu1", "aclk_100", 0,
>> + EXYNOS4_CLKGATE_IP_MFC, 2, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(tv, 2), "sysmmu2", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_TV, 4, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(jpeg, 3), "sysmmu3", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 11, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(rot, 4), "sysmmu4", "aclk_200", 0,
>> + EXYNOS4210_CLKGATE_IP_IMAGE, 4, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc0, 5), "sysmmu5", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 7, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc1, 6), "sysmmu6", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 8, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc2, 7), "sysmmu7", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 9, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc3, 8), "sysmmu8", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_CAM, 10, "sysmmu"),
>> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimd, 10), "sysmmu10", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_LCD0, 4, "sysmmu"),
>> + GATECLK("dma-pl330.0", "dma0", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 0, "dma"),
>> + GATECLK("dma-pl330.1", "dma1", "aclk_133", 0,
>> + EXYNOS4_CLKGATE_IP_FSYS, 1, "dma"),
>> + GATECLK("exynos4-fb.0", "fimd", "aclk_160", 0,
>> + EXYNOS4_CLKGATE_IP_LCD0, 0, "lcd"),
>> + GATECLK("exynos4210-spi.0", "sclk_spi0", "div_spi0_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_PERIL1, 16, "spi_busclk0"),
>> + GATECLK("exynos4210-spi.1", "sclk_spi1", "div_spi1_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_PERIL1, 20, "spi_busclk0"),
>> + GATECLK("exynos4210-spi.2", "sclk_spi2", "div_spi2_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_PERIL1, 24, "spi_busclk0"),
>> + GATECLK("exynos4-sdhci.0", "sclk_mmc0", "div_mmc0_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_FSYS, 0, "mmc_busclk.2"),
>> + GATECLK("exynos4-sdhci.1", "sclk_mmc1", "div_mmc1_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_FSYS, 4, "mmc_busclk.2"),
>> + GATECLK("exynos4-sdhci.2", "sclk_mmc2", "div_mmc2_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_FSYS, 8, "mmc_busclk.2"),
>> + GATECLK("exynos4-sdhci.3", "sclk_mmc3", "div_mmc3_pre", 0,
>> + EXYNOS4_CLKSRC_MASK_FSYS, 12, "mmc_busclk.2"),
>> + GATECLK("s5p-mipi-csis.0", "sclk_csis0", "div_csis0", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 24, "sclk_csis"),
>> + GATECLK("s5p-mipi-csis.1", "sclk_csis1", "div_csis1", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
>> + GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
>> + GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
>> + GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
>> + GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
>> + GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
>> + GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
>> + EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
>> + GATECLK("exynos4-fb.0", "sclk_fimd", "div_fimd0", 0,
>> + EXYNOS4_CLKSRC_MASK_LCD0, 0, "sclk_fimd"),
>> +};
>> +
>> +/* register clock common to all Exynos4 platforms */
>> +void __init exynos4_clk_init(void)
>> +{
>> + samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
>> + ARRAY_SIZE(exynos4_fixed_rate_clks));
>> + samsung_clk_register_mux(exynos4_mux_clks,
>> + ARRAY_SIZE(exynos4_mux_clks));
>> + samsung_clk_register_div(exynos4_div_clks,
>> + ARRAY_SIZE(exynos4_div_clks));
>> + samsung_clk_register_gate(exynos4_gate_clks,
>> + ARRAY_SIZE(exynos4_gate_clks));
>> +}
> ...
>> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
>> new file mode 100644
>> index 0000000..65156b9
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk.c
>> @@ -0,0 +1,231 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 Linaro Ltd.
>> + *
>> + * 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 file includes utility functions to register clocks to common
>> + * clock framework for Samsung platforms. This includes an implementation
>> + * of Samsung 'pll type' clock to represent the implementation of the
>> + * pll found on Samsung platforms. In addition to that, utility functions
>> + * to register mux, div, gate and fixed rate types of clocks are included.
>> +*/
>> +
>> +#include "clk.h"
>> +
>> +static DEFINE_SPINLOCK(lock);
>> +
>> +#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
>> +
>> +/* determine the output clock speed of the pll */
>> +static unsigned long samsung_clk_pll_recalc_rate(struct clk_hw *hw,
>> + unsigned long parent_rate)
>> +{
>> + struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
>> +
>> + if (clk_pll->get_rate)
>> + return to_clk_pll(hw)->get_rate(parent_rate);
>> +
>> + return 0;
>> +}
>> +
>> +/* round operation not supported */
>> +static long samsung_clk_pll_round_rate(struct clk_hw *hw, unsigned long drate,
>> + unsigned long *prate)
>> +{
>> + return samsung_clk_pll_recalc_rate(hw, *prate);
>> +}
>> +
>> +/* set the clock output rate of the pll */
>> +static int samsung_clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
>> + unsigned long prate)
>> +{
>> + struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
>> +
>> + if (clk_pll->set_rate)
>> + return to_clk_pll(hw)->set_rate(drate);
>> +
>> + return 0;
>> +}
>> +
>> +/* clock operations for samsung pll clock type */
>> +static const struct clk_ops samsung_clk_pll_ops = {
>> + .recalc_rate = samsung_clk_pll_recalc_rate,
>> + .round_rate = samsung_clk_pll_round_rate,
>> + .set_rate = samsung_clk_pll_set_rate,
>> +};
>> +
>> +/* register a samsung pll type clock */
>> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
>> + int (*set_rate)(unsigned long rate),
>> + unsigned long (*get_rate)(unsigned long rate))
>> +{
>> + struct samsung_clk_pll *clk_pll;
>> + struct clk *clk;
>> + struct clk_init_data init;
>> + int ret;
>> +
>> + clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>> + if (!clk_pll) {
>> + pr_err("%s: could not allocate pll clk %s\n", __func__, name);
>> + return;
>> + }
>> +
>> + init.name = name;
>> + init.ops =&samsung_clk_pll_ops;
>> + init.flags = CLK_GET_RATE_NOCACHE;
>> + init.parent_names = pnames;
>> + init.num_parents = 1;
>> +
>> + clk_pll->set_rate = set_rate;
>> + clk_pll->get_rate = get_rate;
>> + clk_pll->hw.init =&init;
>> +
>> + /* register the clock */
>> + clk = clk_register(NULL,&clk_pll->hw);
>> + if (IS_ERR(clk)) {
>> + pr_err("%s: failed to register pll clock %s\n", __func__,
>> + name);
>> + kfree(clk_pll);
>> + return;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, name, NULL);
>> + if (ret)
>> + pr_err("%s: failed to register clock lookup for %s", __func__,
>> + name);
>> +}
>> +
>> +/* register a list of fixed clocks */
>> +void __init samsung_clk_register_fixed_rate(
>> + struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
>> +{
>> + struct clk *clk;
>> + unsigned int idx, ret;
>> +
>> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
>> + clk = clk_register_fixed_rate(NULL, clk_list->name,
>> + clk_list->parent_name, clk_list->flags,
>> + clk_list->fixed_rate);
>> + if (IS_ERR_OR_NULL(clk)) {
>
> clk_register_fixed_rate() always returns an error code (ERR_PTR()), i.e. never
> NULL, thus IS_ERR(clk) is more appropriate here.

Ok. I will change it.

>
>> + pr_err("clock: failed to register clock %s\n",
>> + clk_list->name);
>> + continue;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, clk_list->name,
>> + clk_list->dev_name);
>> + if (ret)
>> + pr_err("clock: failed to register clock lookup for %s",
>> + clk_list->name);
>> + }
>> +}
>> +
>> +/* register a list of mux clocks */
>> +void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
>> + unsigned int nr_clk)
>> +{
>> + struct clk *clk;
>> + unsigned int idx, ret;
>> +
>> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
>> + clk = clk_register_mux(NULL, clk_list->name,
>> + clk_list->parent_names, clk_list->num_parents,
>> + clk_list->flags, clk_list->reg, clk_list->shift,
>> + clk_list->width, clk_list->mux_flags,&lock);
>> + if (IS_ERR_OR_NULL(clk)) {
>
> Ditto.
>
>> + pr_err("clock: failed to register clock %s\n",
>> + clk_list->name);
>> + continue;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, clk_list->name,
>> + clk_list->dev_name);
>> + if (ret)
>> + pr_err("clock: failed to register clock lookup for %s",
>> + clk_list->name);
>> +
>> + if (clk_list->alias)
>> + clk_register_clkdev(clk, clk_list->alias,
>> + clk_list->dev_name);
>> + }
>> +}
>> +
>> +/* reguster a list of div clocks */
>> +void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
>> + unsigned int nr_clk)
>> +{
>> + struct clk *clk;
>> + unsigned int idx, ret;
>> +
>> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
>> + clk = clk_register_divider(NULL, clk_list->name,
>> + clk_list->parent_name, clk_list->flags, clk_list->reg,
>> + clk_list->shift, clk_list->width, clk_list->div_flags,
>> + &lock);
>> + if (IS_ERR_OR_NULL(clk)) {
>
> Ditto.
>
>> + pr_err("clock: failed to register clock %s\n",
>> + clk_list->name);
>> + continue;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, clk_list->name,
>> + clk_list->dev_name);
>> + if (ret)
>> + pr_err("clock: failed to register clock lookup for %s",
>> + clk_list->name);
>> +
>> + if (clk_list->alias)
>> + clk_register_clkdev(clk, clk_list->alias,
>> + clk_list->dev_name);
>> + }
>> +}
>> +
>> +/* register a list of gate clocks */
>> +void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
>> + unsigned int nr_clk)
>> +{
>> + struct clk *clk;
>> + unsigned int idx, ret;
>> +
>> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
>> + clk = clk_register_gate(NULL, clk_list->name,
>> + clk_list->parent_name, clk_list->flags, clk_list->reg,
>> + clk_list->bit_idx, clk_list->gate_flags,&lock);
>> + if (IS_ERR_OR_NULL(clk)) {
>
> Ditto.
>
>> + pr_err("clock: failed to register clock %s\n",
>> + clk_list->name);
>> + continue;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, clk_list->name,
>> + clk_list->dev_name);
>> + if (ret) {
>> + pr_err("clock: failed to register clock lookup for %s",
>> + clk_list->name);
>> + continue;
>> + }
>> +
>> + ret = clk_register_clkdev(clk, clk_list->alias,
>> + clk_list->dev_name);
>> + if (ret)
>> + pr_err("clock: failed to register alias %s for clock "
>> + " %s", clk_list->alias, clk_list->name);
>> + }
>> +}
>
>
> Do we really need all these clock lookup entries registered for each clk
> primitive ? There seem to be more struck clk objects than with the original
> samsung clock code, now when each instance of struct clk_clksrc has been
> replaced with a corresponding div and mux clock object. All these are not
> needed to be referenced from drivers, so why do we see so many
> clk_register_clkdev() here ?
>
> Couldn't this be avoided by instantiating all platform clocks first and
> then creating required clock object - device associations by adding the
> clkdev lookup entries ? Something like this is done in case of
> arch/arm/mach-imx for instance. I think this would result in less data
> and more clear implementation.

Ok. But the platform code can lookup these clocks (for displaying the
clock speed on the console) and hence all the clocks are registered.
Anyway, these are required only for non-dt platforms and would go away
after switching over to device tree based clock registration.

Thanks,
Thomas.

>
>
>> +/* utility function to get the rate of a specified clock */
>> +unsigned long _get_rate(const char *clk_name)
>> +{
>> + struct clk *clk;
>> + unsigned long rate;
>> +
>> + clk = clk_get(NULL, clk_name);
>> + if (IS_ERR(clk))
>> + return 0;
>> + rate = clk_get_rate(clk);
>> + clk_put(clk);
>> + return rate;
>> +}
>> diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
>> new file mode 100644
>> index 0000000..40bdff9
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk.h
>> @@ -0,0 +1,190 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 Linaro Ltd.
>> + *
>> + * 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.
>> + *
>> + * Common Clock Framework support for all Samsung platforms
>> +*/
>> +
>> +#ifndef __SAMSUNG_CLK_H
>> +#define __SAMSUNG_CLK_H
>> +
>> +#include<linux/clk.h>
>> +#include<linux/clkdev.h>
>> +#include<linux/io.h>
>> +#include<linux/clk-provider.h>
>> +#include<mach/regs-clock.h>
>> +
>> +/**
>> + * struct samsung_clk_pll: represents a samsung pll type clock
>> + * @hw: connection to struct clk.
>> + * @set_rate: callback for setting the pll clock rate
>> + * @get_rate: callback for determing the pll clock rate
>> + *
>> + * Internal representation of the pll type clock. Platform specific
>> + * implementation can instantiate clocks of this type by calling
>> + * samsung_clk_register_pll() function.
>> + */
>> +struct samsung_clk_pll {
>> + struct clk_hw hw;
>> + int (*set_rate)(unsigned long rate);
>> + unsigned long (*get_rate)(unsigned long xtal_rate);
>> +};
>> +
>> +/**
>> + * struct samsung_fixed_rate_clock: information about fixed-rate clock
>> + * @dev_name: name of the device to which this clock belongs.
>> + * @name: name of this fixed-rate clock.
>> + * @parent_name: optional parent clock name.
>> + * @flags: optional fixed-rate clock flags.
>> + * @fixed-rate: fixed clock rate of this clock.
>> + */
>> +struct samsung_fixed_rate_clock {
>> + const char *dev_name;
>> + const char *name;
>> + const char *parent_name;
>> + unsigned long flags;
>> + unsigned long fixed_rate;
>> +};
>> +
>> +#define FRATE_CLK(dname, cname, pname, f, frate) \
>> + { \
>> + .dev_name = dname, \
>> + .name = cname, \
>> + .parent_name = pname, \
>> + .flags = f, \
>> + .fixed_rate = frate, \
>> + }
>> +
>> +/**
>> + * struct samsung_mux_clock: information about mux clock
>> + * @dev_name: name of the device to which this clock belongs.
>> + * @name: name of this mux clock.
>> + * @parent_names: array of pointer to parent clock names.
>> + * @num_parents: number of parents listed in @parent_names.
>> + * @flags: optional flags for basic clock.
>> + * @reg: address of register for configuring the mux.
>> + * @shift: starting bit location of the mux control bit-field in @reg.
>> + * @width: width of the mux control bit-field in @reg.
>> + * @mux_flags: flags for mux-type clock.
>> + * @alias: optional clock alias name to be assigned to this clock.
>> + */
>> +struct samsung_mux_clock {
>> + const char *dev_name;
>> + const char *name;
>> + const char **parent_names;
>> + u8 num_parents;
>> + unsigned long flags;
>> + void __iomem *reg;
>> + u8 shift;
>> + u8 width;
>> + u8 mux_flags;
>> + const char *alias;
>> +};
>> +
>> +#define MUXCLK(dname, cname, pnames, f, r, s, w, mf) \
>> + { \
>> + .dev_name = dname, \
>> + .name = cname, \
>> + .parent_names = pnames, \
>> + .num_parents = ARRAY_SIZE(pnames), \
>> + .flags = f, \
>> + .reg = r, \
>> + .shift = s, \
>> + .width = w, \
>> + .mux_flags = mf, \
>> + }
>> +
>> +/**
>> + * struct samsung_div_clock: information about div clock
>> + * @dev_name: name of the device to which this clock belongs.
>> + * @name: name of this div clock.
>> + * @parent_name: name of the parent clock.
>> + * @flags: optional flags for basic clock.
>> + * @reg: address of register for configuring the div.
>> + * @shift: starting bit location of the div control bit-field in @reg.
>> + * @div_flags: flags for div-type clock.
>> + * @alias: optional clock alias name to be assigned to this clock.
>> + */
>> +struct samsung_div_clock {
>> + const char *dev_name;
>> + const char *name;
>> + const char *parent_name;
>> + unsigned long flags;
>> + void __iomem *reg;
>> + u8 shift;
>> + u8 width;
>> + u8 div_flags;
>> + const char *alias;
>> +};
>> +
>> +#define DIVCLK(dname, cname, pname, f, r, s, w, df) \
>> + { \
>> + .dev_name = dname, \
>> + .name = cname, \
>> + .parent_name = pname, \
>> + .flags = f, \
>> + .reg = r, \
>> + .shift = s, \
>> + .width = w, \
>> + .div_flags = df, \
>> + }
>> +
>> +/**
>> + * struct samsung_gate_clock: information about gate clock
>> + * @dev_name: name of the device to which this clock belongs.
>> + * @name: name of this gate clock.
>> + * @parent_name: name of the parent clock.
>> + * @flags: optional flags for basic clock.
>> + * @reg: address of register for configuring the gate.
>> + * @bit_idx: bit index of the gate control bit-field in @reg.
>> + * @gate_flags: flags for gate-type clock.
>> + * @alias: optional clock alias name to be assigned to this clock.
>> + */
>> +struct samsung_gate_clock {
>> + const char *dev_name;
>> + const char *name;
>> + const char *parent_name;
>> + unsigned long flags;
>> + void __iomem *reg;
>> + u8 bit_idx;
>> + u8 gate_flags;
>> + const char *alias;
>> +};
>> +
>> +#define GATECLK(dname, cname, pname, f, r, b, a) \
>> + { \
>> + .dev_name = dname, \
>> + .name = cname, \
>> + .parent_name = pname, \
>> + .flags = f, \
>> + .reg = r, \
>> + .bit_idx = b, \
>> + .alias = a, \
>> + }
>
> --
>
> Regards,
> Sylwester

2012-10-08 07:31:26

by Tomasz Figa

[permalink] [raw]
Subject: Re: [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework

On Monday 08 of October 2012 12:04:18 Thomas Abraham wrote:
> Hi Tomasz,
>
> On 3 October 2012 19:40, Tomasz Figa <[email protected]> wrote:
> > Hi Chander, Thomas,
> >
> > I can see one more problem here.
> >
> > Based on the fact that sdhci-s3c driver receives only the endpoint gate
> > clock (hsmmc), doesn't the following setup make the driver unable to
> > change the frequency of this clock?
>
> The driver never changes the clock frequency of the core system clocks
> nor of the endpoint. There are internal dividers inside the sdhci
> controller which are divide to acheive required clock speed.

What is the use of sdhci_cmu_set_clock (which calls clk_set_rate) in sdhci-
s3c, then?

I think you are missing CLK_SET_RATE_PARENT flags in clocks of which rate
can be changed by the driver.

Best regards,
--
Tomasz Figa
Samsung Poland R&D Center