[PATCH v4 03/12] clk: exynos4: register clocks using common clock framework

Thomas Abraham thomas.abraham at linaro.org
Sat Nov 24 16:17:56 EST 2012


The Exynos4 clocks are statically listed and registered using the Samsung
specific common clock helper functions. Both device tree based clock lookup
and clkdev based clock lookups are supported.

Cc: Mike Turquette <mturquette at linaro.org>
Cc: Kukjin Kim <kgene.kim at samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham at linaro.org>
---
 .../devicetree/bindings/clock/exynos4-clock.txt    |  215 +++++++
 drivers/clk/samsung/Makefile                       |    1 +
 drivers/clk/samsung/clk-exynos4.c                  |  655 ++++++++++++++++++++
 3 files changed, 871 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/exynos4-clock.txt
 create mode 100644 drivers/clk/samsung/clk-exynos4.c

diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
new file mode 100644
index 0000000..e874add
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
@@ -0,0 +1,215 @@
+* Samsung Exynos4 Clock Controller
+
+The Exynos4 clock controller generates and supplies clock to various controllers
+within the Exynos4 SoC. The clock binding described here is applicable to all
+SoC's in the Exynos4 family.
+
+Required Properties:
+
+- comptible: should be one of the following.
+  - "samsung,exynos4210-clock" - controller compatible with Exynos4210 SoC.
+  - "samsung,exynos4412-clock" - controller compatible with Exynos4412 SoC.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+The following is the list of clocks generated by the controller. Each clock is
+assigned an identifier and client nodes use this identifier to specify the
+clock which they consume. Some of the clocks are available only on a particular
+Exynos4 SoC and this is specified where applicable.
+
+
+		 [Core Clocks]
+
+  Clock               ID      SoC (if specific)
+  -----------------------------------------------
+
+  xxti                1
+  xusbxti             2
+  fin_pll             3
+  fout_apll           4
+  fout_mpll           5
+  fout_epll           6
+  fout_vpll           7
+  sclk_apll           8
+  sclk_mpll           9
+  sclk_epll           10
+  sclk_vpll           11
+  arm_clk             12
+  aclk200             13
+  aclk100             14
+  aclk160             15
+  aclk133             16
+
+
+            [Clock Gate for Special Clocks]
+
+  Clock               ID      SoC (if specific)
+  -----------------------------------------------
+
+  sclk_fimc0          128
+  sclk_fimc1          129
+  sclk_fimc2          130
+  sclk_fimc3          131
+  sclk_cam0           132
+  sclk_cam1           133
+  sclk_csis0          134
+  sclk_csis1          135
+  sclk_hdmi           136
+  sclk_mixer          137
+  sclk_dac            138
+  sclk_pixel          139
+  sclk_fimd0          140
+  sclk_mdnie0         141     Exynos4412
+  sclk_mdnie_pwm0 12  142     Exynos4412
+  sclk_mipi0          143
+  sclk_audio0         144
+  sclk_mmc0           145
+  sclk_mmc1           146
+  sclk_mmc2           147
+  sclk_mmc3           148
+  sclk_mmc4           149
+  sclk_sata           150     Exynos4210
+  sclk_uart0          151
+  sclk_uart1          152
+  sclk_uart2          153
+  sclk_uart3          154
+  sclk_uart4          155
+  sclk_audio1         156
+  sclk_audio2         157
+  sclk_spdif          158
+  sclk_spi0           159
+  sclk_spi1           160
+  sclk_spi2           161
+  sclk_slimbus        162
+  sclk_fimd1          163     Exynos4210
+  sclk_mipi1          164     Exynos4210
+  sclk_pcm1           165
+  sclk_pcm2           166
+  sclk_i2s1           167
+  sclk_i2s2           168
+  sclk_mipihsi        169     Exynos4412
+
+
+	      [Peripheral Clock Gates]
+
+  Clock               ID      SoC (if specific)
+  -----------------------------------------------
+
+  fimc0               256
+  fimc1               257
+  fimc2               258
+  fimc3               259
+  csis0               260
+  csis1               261
+  jpeg                262
+  smmu_fimc0          263
+  smmu_fimc1          264
+  smmu_fimc2          265
+  smmu_fimc3          266
+  smmu_jpeg           267
+  vp                  268
+  mixer               269
+  tvenc               270     Exynos4210
+  hdmi                271
+  smmu_tv             272
+  mfc                 273
+  smmu_mfcl           274
+  smmu_mfcr           275
+  g3d                 276
+  g2d                 277     Exynos4210
+  rotator             278     Exynos4210
+  mdma                279     Exynos4210
+  smmu_g2d            280     Exynos4210
+  smmu_rotator        281     Exynos4210
+  smmu_mdma           282     Exynos4210
+  fimd0               283
+  mie0                284
+  mdnie0              285     Exynos4412
+  dsim0               286
+  smmu_fimd0          287
+  fimd1               288     Exynos4210
+  mie1                289     Exynos4210
+  dsim1               290     Exynos4210
+  smmu_fimd1          291     Exynos4210
+  pdma0               292
+  pdma1               293
+  pcie_phy            294
+  sata_phy            295     Exynos4210
+  tsi                 296
+  sdmmc0              297
+  sdmmc1              298
+  sdmmc2              299
+  sdmmc3              300
+  sdmmc4              301
+  sata                302     Exynos4210
+  sromc               303
+  usb_host            304
+  usb_device          305
+  pcie                306
+  onenand             307
+  nfcon               308
+  smmu_pcie           309
+  gps                 310
+  smmu_gps            311
+  uart0               312
+  uart1               313
+  uart2               314
+  uart3               315
+  uart4               316
+  i2c0                317
+  i2c1                318
+  i2c2                319
+  i2c3                320
+  i2c4                321
+  i2c5                322
+  i2c6                323
+  i2c7                324
+  i2c_hdmi            325
+  tsadc               326
+  spi0                327
+  spi1                328
+  spi2                329
+  i2s1                330
+  i2s2                331
+  pcm0                332
+  i2s0                333
+  pcm1                334
+  pcm2                335
+  pwm                 336
+  slimbus             337
+  spdif               338
+  ac97                339
+  modemif             340
+  chipid              341
+  sysreg              342
+  hdmi_cec            343
+  mct                 344
+  wdt                 345
+  rtc                 346
+  keyif               347
+  audss               348
+  mipi_hsi            349     Exynos4210
+  mdma2               350     Exynos4210
+
+Example 1: An example of a clock controller node is listed below.
+
+	clock: clock-controller at 0x10030000 {
+		compatible = "samsung,exynos4210-clock";
+		reg = <0x10030000 0x20000>;
+		#clock-cells = <1>;
+	};
+
+Example 2: UART controller node that consumes the clock generated by the clock
+	   controller. Refer to the standard clock bindings for information
+	   about 'clocks' and 'clock-names' property.
+
+	serial at 13820000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0x13820000 0x100>;
+		interrupts = <0 54 0>;
+		clocks = <&clock 314>, <&clock 153>;
+		clock-names = "uart", "clk_uart_baud0";
+	};
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 78e5aaa..8862f0d 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-pll.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..233e963
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -0,0 +1,655 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab at samsung.com>
+ *
+ * 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 SoC's.
+*/
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <plat/cpu.h>
+#include "clk.h"
+#include "clk-pll.h"
+
+/* the exynos4 soc type */
+enum exynos4_soc {
+	EXYNOS4210,
+	EXYNOS4X12,
+};
+
+/*
+ * Let each supported clock get a unique id. This id is used to lookup the clock
+ * for device tree based platforms. The clocks are categorized into three
+ * sections: core, sclk gate and bus interface gate clocks.
+ *
+ * When adding a new clock to this list, it is advised to choose a clock
+ * category and add it to the end of that category. That is because the the
+ * device tree source file is referring to these ids and any change in the
+ * sequence number of existing clocks will require corresponding change in the
+ * device tree files. This limitation would go away when pre-processor support
+ * for dtc would be available.
+ */
+enum exynos4_clks {
+	none,
+
+	/* core clocks */
+	xxti, xusbxti, fin_pll, fout_apll, fout_mpll, fout_epll, fout_vpll,
+	sclk_apll, sclk_mpll, sclk_epll, sclk_vpll, arm_clk, aclk200, aclk100,
+	aclk160, aclk133,
+
+	/* gate for special clocks (sclk) */
+	sclk_fimc0 = 128, sclk_fimc1, sclk_fimc2, sclk_fimc3, sclk_cam0,
+	sclk_cam1, sclk_csis0, sclk_csis1, sclk_hdmi, sclk_mixer, sclk_dac,
+	sclk_pixel, sclk_fimd0, sclk_mdnie0, sclk_mdnie_pwm0, sclk_mipi0,
+	sclk_audio0, sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_mmc4,
+	sclk_sata, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_uart4,
+	sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2,
+	sclk_slimbus, sclk_fimd1, sclk_mipi1, sclk_pcm1, sclk_pcm2, sclk_i2s1,
+	sclk_i2s2, sclk_mipihsi,
+
+	/* gate clocks */
+	fimc0 = 256, fimc1, fimc2, fimc3, csis0, csis1, jpeg, smmu_fimc0,
+	smmu_fimc1, smmu_fimc2, smmu_fimc3, smmu_jpeg, vp, mixer, tvenc, hdmi,
+	smmu_tv, mfc, smmu_mfcl, smmu_mfcr, g3d, g2d, rotator, mdma, smmu_g2d,
+	smmu_rotator, smmu_mdma, fimd0, mie0, mdnie0, dsim0, smmu_fimd0, fimd1,
+	mie1, dsim1, smmu_fimd1, pdma0, pdma1, pcie_phy, sata_phy, tsi, sdmmc0,
+	sdmmc1, sdmmc2, sdmmc3, sdmmc4, sata, sromc, usb_host, usb_device, pcie,
+	onenand, nfcon, smmu_pcie, gps, smmu_gps, uart0, uart1, uart2, uart3,
+	uart4, i2c0, i2c1, i2c2, i2c3, i2c4, i2c5, i2c6, i2c7, i2c_hdmi, tsadc,
+	spi0, spi1, spi2, i2s1, i2s2, pcm0, i2s0, pcm1, pcm2, pwm, slimbus,
+	spdif, ac97, modemif, chipid, sysreg, hdmi_cec, mct, wdt, rtc, keyif,
+	audss, mipi_hsi, mdma2,
+
+	nr_clks,
+};
+
+/* list of all parent clock list */
+PNAME(mout_apll_p)	= { "fin_pll", "fout_apll", };
+PNAME(mout_mpll_p)	= { "fin_pll", "fout_mpll", };
+PNAME(mout_epll_p)	= { "fin_pll", "fout_epll", };
+PNAME(mout_vpllsrc_p)	= { "fin_pll", "sclk_hdmi24m", };
+PNAME(sclk_vpll_p4210)	= { "mout_vpllsrc", "fout_vpll", };
+PNAME(mout_vpll_p)	= { "fin_pll", "fout_vpll", };
+PNAME(mout_core_p)	= { "mout_apll", "sclk_mpll", };
+PNAME(sclk_ampll_p)	= { "sclk_mpll", "sclk_apll", };
+PNAME(mout_mpll_user_p)	= { "fin_pll", "sclk_mpll", };
+PNAME(aclk_p4412)	= { "mout_mpll_user", "sclk_apll", };
+PNAME(sclk_evpll_p)	= { "sclk_epll", "sclk_vpll", };
+PNAME(mout_mfc_p)	= { "mout_mfc0", "mout_mfc1", };
+PNAME(mout_g3d_p)	= { "mout_g3d0", "mout_g3d1", };
+PNAME(mout_g2d_p)	= { "mout_g2d0", "mout_g2d1", };
+PNAME(mout_mixer_p4210)	= { "sclk_dac", "sclk_hdmi", };
+PNAME(mout_dac_p4210)	= { "sclk_vpll", "sclk_hdmiphy", };
+PNAME(mout_hdmi_p)	= { "sclk_pixel", "sclk_hdmiphy", };
+PNAME(mout_jpeg_p)	= { "mout_jpeg0", "mout_jpeg1", };
+PNAME(group1_p)		= { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+				"none",	"sclk_hdmiphy", "sclk_mpll",
+				"mout_epll", "mout_vpll", };
+PNAME(mout_audio0_p)	= { "cdclk0", "none", "sclk_hdmi24m", "sclk_usbphy0",
+				"xxti", "xusbxti", "sclk_mpll", "sclk_epll",
+				"sclk_vpll" };
+PNAME(mout_audio1_p)	= { "cdclk1", "none", "sclk_hdmi24m", "sclk_usbphy0",
+				"xxti", "xusbxti", "sclk_mpll", "mout_epll",
+				"mout_vpll", };
+PNAME(mout_audio2_p)	= { "cdclk2", "none", "sclk_hdmi24m", "sclk_usbphy0",
+				"xxti", "xusbxti", "sclk_mpll", "mout_epll",
+				"mout_vpll", };
+PNAME(mout_spdif_p)	= { "sclk_audio0", "sclk_audio1", "sclk_audio2",
+				"spdif_extclk", };
+
+/* fixed rate clocks generated outside the soc */
+struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
+	FRATE(xxti, "xxti", NULL, CLK_IS_ROOT, 0),
+	FRATE(xusbxti, "xusbxti", NULL, CLK_IS_ROOT, 0),
+};
+
+/* fixed rate clocks generated inside the soc */
+struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
+	FRATE(none, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
+	FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
+	FRATE(none, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
+};
+
+struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
+	FRATE(none, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* list of mux clocks supported in all exynos4 soc's */
+struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
+	MUX(none, "mout_apll", mout_apll_p, 0x14200, 0, 1),
+	MUX(none, "mout_core", mout_core_p, 0x14200, 16, 1),
+	MUX_A(sclk_epll, "sclk_epll", mout_epll_p, 0xc210, 4, 1, "sclk_epll"),
+	MUX(none, "mout_fimc0", group1_p, 0xc220, 0, 4),
+	MUX(none, "mout_fimc1", group1_p, 0xc220, 4, 4),
+	MUX(none, "mout_fimc2", group1_p, 0xc220, 8, 4),
+	MUX(none, "mout_fimc3", group1_p, 0xc220, 12, 4),
+	MUX(none, "mout_cam0", group1_p, 0xc220, 16, 4),
+	MUX(none, "mout_cam1", group1_p, 0xc220, 20, 4),
+	MUX(none, "mout_csis0", group1_p, 0xc220, 24, 4),
+	MUX(none, "mout_csis1", group1_p, 0xc220, 28, 4),
+	MUX(none, "mout_hdmi", mout_hdmi_p, 0xc224, 0, 1),
+	MUX(none, "mout_mfc0", sclk_ampll_p, 0xc228, 0, 1),
+	MUX(none, "mout_mfc1", sclk_evpll_p, 0xc228, 4, 1),
+	MUX(none, "mout_mfc", mout_mfc_p, 0xc228, 8, 1),
+	MUX(none, "mout_g3d0", sclk_ampll_p, 0xc22c, 0, 1),
+	MUX(none, "mout_g3d1", sclk_evpll_p, 0xc22c, 4, 1),
+	MUX(none, "mout_g3d", mout_g3d_p, 0xc22c, 8, 1),
+	MUX(none, "mout_fimd0", group1_p, 0xc234, 0, 4),
+	MUX(none, "mout_mipi0", group1_p, 0xc234, 12, 4),
+	MUX(none, "mout_audio0", mout_audio0_p, 0xc23c, 0, 4),
+	MUX(none, "mout_mmc0", group1_p, 0xc240, 0, 4),
+	MUX(none, "mout_mmc1", group1_p, 0xc240, 4, 4),
+	MUX(none, "mout_mmc2", group1_p, 0xc240, 8, 4),
+	MUX(none, "mout_mmc3", group1_p, 0xc240, 12, 4),
+	MUX(none, "mout_mmc4", group1_p, 0xc240, 16, 4),
+	MUX(none, "mout_uart0", group1_p, 0xc250, 0, 4),
+	MUX(none, "mout_uart1", group1_p, 0xc250, 4, 4),
+	MUX(none, "mout_uart2", group1_p, 0xc250, 8, 4),
+	MUX(none, "mout_uart3", group1_p, 0xc250, 12, 4),
+	MUX(none, "mout_uart4", group1_p, 0xc250, 16, 4),
+	MUX(none, "mout_audio1", mout_audio1_p, 0xc254, 0, 4),
+	MUX(none, "mout_audio2", mout_audio2_p, 0xc254, 4, 4),
+	MUX(none, "mout_spdif", mout_spdif_p, 0xc254, 8, 2),
+	MUX(none, "mout_spi0", group1_p, 0xc254, 16, 4),
+	MUX(none, "mout_spi1", group1_p, 0xc254, 20, 4),
+	MUX(none, "mout_spi2", group1_p, 0xc254, 24, 4),
+};
+
+/* list of mux clocks supported in exynos4210 soc */
+struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
+	MUX(none, "mout_aclk200", sclk_ampll_p, 0xc210, 12, 1),
+	MUX(none, "mout_aclk100", sclk_ampll_p, 0xc210, 16, 1),
+	MUX(none, "mout_aclk160", sclk_ampll_p, 0xc210, 20, 1),
+	MUX(none, "mout_aclk133", sclk_ampll_p, 0xc210, 24, 1),
+	MUX(none, "mout_vpllsrc", mout_vpllsrc_p, 0xc214, 0, 1),
+	MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p, 0x14200, 8, 1, "sclk_mpll"),
+	MUX_A(sclk_vpll, "sclk_vpll", sclk_vpll_p4210, 0xc210, 8, 1, "sclk_vpll"),
+	MUX(none, "mout_mixer", mout_mixer_p4210, 0xc224, 4, 1),
+	MUX(none, "mout_dac", mout_dac_p4210, 0xc224, 8, 1),
+	MUX(none, "mout_g2d0", sclk_ampll_p, 0xc230, 0, 1),
+	MUX(none, "mout_g2d1", sclk_evpll_p, 0xc230, 4, 1),
+	MUX(none, "mout_g2d", mout_g2d_p, 0xc230, 8, 1),
+	MUX(none, "mout_fimd1", group1_p, 0xc238, 0, 4),
+	MUX(none, "mout_mipi1", group1_p, 0xc238, 12, 4),
+};
+
+/* list of mux clocks supported in exynos4x12 soc */
+struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
+	MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p, 0x10200, 12, 1, "sclk_mpll"),
+	MUX(none, "mout_mpll_user", mout_mpll_user_p, 0x4200, 4, 1),
+	MUX_A(sclk_vpll, "sclk_vpll", mout_vpll_p, 0xc210, 8, 1, "sclk_vpll"),
+	MUX(none, "mout_aclk200", aclk_p4412, 0xc210, 12, 1),
+	MUX(none, "mout_aclk100", aclk_p4412, 0xc210, 16, 1),
+	MUX(none, "mout_aclk160", aclk_p4412, 0xc210, 20, 1),
+	MUX(none, "mout_aclk133", aclk_p4412, 0xc210, 24, 1),
+	MUX(none, "mout_mdnie0", group1_p, 0xc234, 4, 4),
+	MUX(none, "mout_mdnie_pwm0", group1_p, 0xc234, 8, 4),
+	MUX(none, "mout_sata", sclk_ampll_p, 0xc240, 24, 1),
+	MUX(none, "mout_jpeg0", sclk_ampll_p, 0xc258, 0, 1),
+	MUX(none, "mout_jpeg1", sclk_evpll_p, 0xc258, 4, 1),
+	MUX(none, "mout_jpeg", mout_jpeg_p, 0xc258, 8, 1),
+};
+
+/* list of divider clocks supported in all exynos4 soc's */
+struct samsung_div_clock exynos4_div_clks[] __initdata = {
+	DIV_A(sclk_apll, "sclk_apll", "mout_apll", 0x14500, 24, 3, "sclk_apll"),
+	DIV(none, "div_core", "mout_core", 0x14500, 0, 3),
+	DIV(none, "div_core2", "div_core", 0x14500, 28, 3),
+	DIV_A(arm_clk, "arm_clk", "div_core2", 0x14500, 28, 3, "arm_clk"),
+	DIV(aclk200, "aclk200", "mout_aclk200", 0xc510, 0, 3),
+	DIV(aclk100, "aclk100", "mout_aclk100", 0xc510, 4, 4),
+	DIV(aclk160, "aclk160", "mout_aclk160", 0xc510, 8, 3),
+	DIV(aclk133, "aclk133", "mout_aclk133", 0xc510, 12, 3),
+	DIV(none, "div_fimc0", "mout_fimc0", 0xc520, 0, 4),
+	DIV(none, "div_fimc1", "mout_fimc1", 0xc520, 4, 4),
+	DIV(none, "div_fimc2", "mout_fimc2", 0xc520, 8, 4),
+	DIV(none, "div_fimc3", "mout_fimc3", 0xc520, 12, 4),
+	DIV(none, "div_cam0", "mout_cam0", 0xc520, 16, 4),
+	DIV(none, "div_cam1", "mout_cam1", 0xc520, 20, 4),
+	DIV(none, "div_csis0", "mout_csis0", 0xc520, 24, 4),
+	DIV(none, "div_csis1", "mout_csis1", 0xc520, 28, 4),
+	DIV(sclk_pixel, "sclk_pixel", "sclk_vpll", 0xc524, 0, 4),
+	DIV(none, "div_mfc", "mout_mfc", 0xc528, 0, 4),
+	DIV(none, "div_g3d", "mout_g3d", 0xc52c, 0, 4),
+	DIV(none, "div_fimd0", "mout_fimd0", 0xc534, 0, 4),
+	DIV(none, "div_mipi0", "mout_mipi0", 0xc534, 16, 4),
+	DIV(none, "div_mipi_pre0", "div_mipi0", 0xc534, 20, 4),
+	DIV(none, "div_audio0", "mout_audio0", 0xc53c, 0, 4),
+	DIV(none, "div_pcm0", "sclk_audio0", 0xc53c, 4, 8),
+	DIV(none, "div_mmc0", "mout_mmc0", 0xc544, 0, 4),
+	DIV(none, "div_mmc_pre0", "div_mmc0", 0xc544, 8, 8),
+	DIV(none, "div_mmc1", "mout_mmc1", 0xc544, 16, 4),
+	DIV(none, "div_mmc_pre1", "div_mmc1", 0xc544, 24, 8),
+	DIV(none, "div_mmc2", "mout_mmc2", 0xc548, 0, 4),
+	DIV(none, "div_mmc_pre2", "div_mmc2", 0xc548, 8, 8),
+	DIV(none, "div_mmc3", "mout_mmc3", 0xc548, 16, 4),
+	DIV(none, "div_mmc_pre3", "div_mmc3", 0xc548, 24, 8),
+	DIV(none, "div_mmc4", "mout_mmc4", 0xc54c, 0, 4),
+	DIV(none, "div_mmc_pre4", "div_mmc4", 0xc54c, 8, 8),
+	DIV(none, "div_uart0", "mout_uart0", 0xc550, 0, 4),
+	DIV(none, "div_uart1", "mout_uart1", 0xc550, 4, 4),
+	DIV(none, "div_uart2", "mout_uart2", 0xc550, 8, 4),
+	DIV(none, "div_uart3", "mout_uart3", 0xc550, 12, 4),
+	DIV(none, "div_uart4", "mout_uart4", 0xc550, 16, 4),
+	DIV(none, "div_spi0", "mout_spi0", 0xc554, 0, 4),
+	DIV(none, "div_spi_pre0", "div_spi0", 0xc554, 8, 8),
+	DIV(none, "div_spi1", "mout_spi1", 0xc554, 16, 4),
+	DIV(none, "div_spi_pre1", "div_spi1", 0xc554, 24, 8),
+	DIV(none, "div_spi2", "mout_spi2", 0xc558, 0, 4),
+	DIV(none, "div_spi_pre2", "div_spi2", 0xc558, 8, 8),
+	DIV(sclk_slimbus, "sclk_slimbus", "sclk_epll", 0xc55c, 4, 4),
+	DIV(none, "div_audio1", "mout_audio1", 0xc560, 0, 4),
+	DIV(sclk_pcm1, "sclk_pcm1", "sclk_audio1", 0xc560, 4, 8),
+	DIV(none, "div_audio2", "mout_audio2", 0xc560, 16, 4),
+	DIV(sclk_pcm2, "sclk_pcm2", "sclk_audio2", 0xc560, 20, 8),
+	DIV(sclk_i2s1, "sclk_i2s1", "sclk_audio1", 0xc564, 0, 6),
+	DIV(sclk_i2s2, "sclk_i2s2", "sclk_audio2", 0xc564, 8, 6),
+};
+
+/* list of divider clocks supported in exynos4210 soc */
+struct samsung_div_clock exynos4210_div_clks[] __initdata = {
+	DIV(none, "div_g2d", "mout_g2d", 0xc530, 0, 4),
+	DIV(none, "div_fimd1", "mout_fimd1", 0xc538, 0, 4),
+	DIV(none, "div_mipi1", "mout_mipi1", 0xc538, 16, 4),
+	DIV(none, "div_mipi_pre1", "div_mipi1", 0xc538, 20, 4),
+	DIV(none, "div_sata", "mout_sata", 0xc540, 20, 4),
+};
+
+/* list of divider clocks supported in exynos4x12 soc */
+struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
+	DIV(none, "div_mdnie0", "mout_mdnie0", 0xc534, 4, 4),
+	DIV(none, "div_mdnie_pwm0", "mout_mdnie_pwm0", 0xc534, 8, 4),
+	DIV(none, "div_mdnie_pwm_pre0", "div_mdnie_pwm0", 0xc534, 12, 4),
+	DIV(none, "div_mipihsi", "mout_mipihsi", 0xc540, 20, 4),
+	DIV(none, "div_jpeg", "mout_jpeg", 0xc568, 0, 4),
+};
+
+/* list of gate clocks supported in all exynos4 soc's */
+struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
+	/*
+	 * After all Exynos4 based platforms are migrated to use device tree,
+	 * the device name and clock alias names specified below for some
+	 * of the clocks can be removed.
+	 */
+	GATE_DA(sclk_fimc0, "exynos4-fimc.0", "sclk_fimc0", "div_fimc0",
+			0xc320, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+	GATE_DA(sclk_fimc1, "exynos4-fimc.1", "sclk_fimc1", "div_fimc1",
+			0xc320, 4, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+	GATE_DA(sclk_fimc2, "exynos4-fimc.2", "sclk_fimc2", "div_fimc2",
+			0xc320, 8, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+	GATE_DA(sclk_fimc3, "exynos4-fimc.3", "sclk_fimc3", "div_fimc3",
+			0xc320, 12, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+	GATE_DA(sclk_csis0, "s5p-mipi-csis.0", "sclk_csis0", "div_csis0",
+			0xc320, 24, CLK_SET_RATE_PARENT, 0, "sclk_csis"),
+	GATE_DA(sclk_csis1, "s5p-mipi-csis.1", "sclk_csis1", "div_csis1",
+			0xc320, 28, CLK_SET_RATE_PARENT, 0, "sclk_csis"),
+	GATE(sclk_hdmi, "sclk_hdmi", "mout_hdmi", 0xc324, 0, 0, 0),
+	GATE(sclk_mixer, "sclk_mixer", "mout_mixer", 0xc324, 4, 0, 0),
+	GATE(sclk_dac, "sclk_dac", "mout_dac", 0xc324, 8, 0, 0),
+	GATE_DA(sclk_fimd0, "exynos4-fb.0", "sclk_fimd0", "div_fimd0",
+			0xc334, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"),
+	GATE(sclk_mipi0, "sclk_mipi0", "div_mipi_pre0",
+			0xc334, 12, CLK_SET_RATE_PARENT, 0),
+	GATE_DA(sclk_mmc0, "exynos4-sdhci.0", "sclk_mmc0", "div_mmc-pre0",
+			0xc340, 0, CLK_SET_RATE_PARENT, 0, "mmc_busclk.2"),
+	GATE_DA(sclk_mmc1, "exynos4-sdhci.1", "sclk_mmc1", "div_mmc-pre1",
+			0xc340, 4, CLK_SET_RATE_PARENT, 0, "mmc_busclk.2"),
+	GATE_DA(sclk_mmc2, "exynos4-sdhci.2", "sclk_mmc2", "div_mmc-pre2",
+			0xc340, 8, CLK_SET_RATE_PARENT, 0, "mmc_busclk.2"),
+	GATE_DA(sclk_mmc3, "exynos4-sdhci.3", "sclk_mmc3", "div_mmc-pre3",
+			0xc340, 12, CLK_SET_RATE_PARENT, 0, "mmc_busclk.2"),
+	GATE_DA(sclk_mmc4, NULL, "sclk_mmc4", "div_mmc-pre4",
+			0xc340, 16, CLK_SET_RATE_PARENT, 0, "ciu"),
+	GATE_DA(sclk_uart0, "exynos4210-uart.0", "uclk0", "div_uart0",
+			0xc350, 0, CLK_SET_RATE_PARENT, 0, "clk_uart_baud0"),
+	GATE_DA(sclk_uart1, "exynos4210-uart.1", "uclk1", "div_uart1",
+			0xc350, 4, CLK_SET_RATE_PARENT, 0, "clk_uart_baud0"),
+	GATE_DA(sclk_uart2, "exynos4210-uart.2", "uclk2", "div_uart2",
+			0xc350, 8, CLK_SET_RATE_PARENT, 0, "clk_uart_baud0"),
+	GATE_DA(sclk_uart3, "exynos4210-uart.3", "uclk3", "div_uart3",
+			0xc350, 12, CLK_SET_RATE_PARENT, 0, "clk_uart_baud0"),
+	GATE_DA(sclk_uart4, "exynos4210-uart.4", "uclk4", "div_uart4",
+			0xc350, 16, CLK_SET_RATE_PARENT, 0, "clk_uart_baud0"),
+	GATE(sclk_audio1, "sclk_audio1", "div_audio1", 0xc354, 0, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_audio2, "sclk_audio2", "div_audio2", 0xc354, 4, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_spdif, "sclk_spdif", "mout_spdif", 0xc354, 8, 0, 0),
+	GATE_DA(sclk_spi0, "exynos4210-spi.0", "sclk_spi0", "div_spi_pre0",
+			0xc354, 16, CLK_SET_RATE_PARENT, 0, "spi_busclk0"),
+	GATE_DA(sclk_spi1, "exynos4210-spi.1", "sclk_spi1", "div_spi_pre1",
+			0xc354, 20, CLK_SET_RATE_PARENT, 0, "spi_busclk0"),
+	GATE_DA(sclk_spi2, "exynos4210-spi.2", "sclk_spi2", "div_spi_pre2",
+			0xc354, 24, CLK_SET_RATE_PARENT, 0, "spi_busclk0"),
+	GATE_DA(fimc0, "exynos4-fimc.0", "fimc0", "aclk160", 0xc920, 0, 0, 0, "fimc"),
+	GATE_DA(fimc1, "exynos4-fimc.1", "fimc1", "aclk160", 0xc920, 1, 0, 0, "fimc"),
+	GATE_DA(fimc2, "exynos4-fimc.2", "fimc2", "aclk160", 0xc920, 2, 0, 0, "fimc"),
+	GATE_DA(fimc3, "exynos4-fimc.3", "fimc3", "aclk160", 0xc920, 3, 0, 0, "fimc"),
+	GATE_DA(csis0, "s5p-mipi-csis.0", "csis0", "aclk160", 0xc920, 4, 0, 0, "fimc"),
+	GATE_DA(csis1, "s5p-mipi-csis.1", "csis1", "aclk160", 0xc920, 5, 0, 0, "fimc"),
+	GATE(jpeg, "jpeg", "aclk160", 0xc920, 6, 0, 0),
+	GATE_DA(smmu_fimc0, "exynos-sysmmu.5", "smmu_fimc0", "aclk160",
+			0xc920, 7, 0, 0, "sysmmu"),
+	GATE_DA(smmu_fimc1, "exynos-sysmmu.6", "smmu_fimc1", "aclk160",
+			0xc920, 8, 0, 0, "sysmmu"),
+	GATE_DA(smmu_fimc2, "exynos-sysmmu.7", "smmu_fimc2", "aclk160",
+			0xc920, 9, 0, 0, "sysmmu"),
+	GATE_DA(smmu_fimc3, "exynos-sysmmu.8", "smmu_fimc3", "aclk160",
+			0xc920, 10, 0, 0, "sysmmu"),
+	GATE_DA(smmu_jpeg, "exynos-sysmmu.3", "smmu_jpeg", "aclk160", 0xc920, 11, 0, 0, "sysmmu"),
+	GATE_D(vp, "s5p-mixer", "vp", "aclk160", 0xc924, 0, 0, 0),
+	GATE_D(mixer, "s5p-mixer", "mixer", "aclk160", 0xc924, 1, 0, 0),
+	GATE_D(hdmi, "exynos4-hdmi", "hdmi", "aclk160", 0xc924, 3, 0, 0),
+	GATE_DA(smmu_tv, "exynos-sysmmu.2", "smmu_tv", "aclk160", 0xc924, 4, 0, 0, "sysmmu"),
+	GATE_DA(mfc, "s5p-mfc", "mfc", "aclk100", 0xc928, 0, 0, 0, "mfc"),
+	GATE_DA(smmu_mfcl, "exynos-sysmmu.0", "smmu_mfcl", "aclk100", 0xc928, 1, 0, 0, "sysmmu"),
+	GATE_DA(smmu_mfcr, "exynos-sysmmu.1", "smmu_mfcr", "aclk100", 0xc928, 2, 0, 0, "sysmmu"),
+	GATE(g3d, "g3d", "aclk200", 0xc92c, 0, 0, 0),
+	GATE_DA(fimd0, "exynos4-fb.0", "fimd0", "aclk160", 0xc934, 0, 0, 0, "fimd"),
+	GATE(mie0, "mie0", "aclk160", 0xc934, 1, 0, 0),
+	GATE(dsim0, "dsim0", "aclk160", 0xc934, 3, 0, 0),
+	GATE_DA(smmu_fimd0, "exynos-sysmmu.10", "smmu_fimd0", "aclk160",
+			0xc934, 4, 0, 0, "sysmmu"),
+	GATE(fimd1, "fimd1", "aclk160", 0xc938, 0, 0, 0),
+	GATE(mie1, "mie1", "aclk160", 0xc938, 1, 0, 0),
+	GATE(dsim1, "dsim1", "aclk160", 0xc938, 3, 0, 0),
+	GATE(smmu_fimd1, "smmu_fimd1", "aclk160", 0xc938, 4, 0, 0),
+	GATE_DA(pdma0, "dma-pl330.0", "pdma0", "aclk133", 0xc940, 0, 0, 0, "dma"),
+	GATE_DA(pdma1, "dma-pl330.1", "pdma1", "aclk133", 0xc940, 1, 0, 0, "dma"),
+	GATE(tsi, "tsi", "aclk133", 0xc940, 4, 0, 0),
+	GATE_DA(sdmmc0, "exynos4-sdhci.0", "sdmmc0", "aclk133", 0xc940, 5, 0, 0, "hsmmc"),
+	GATE_DA(sdmmc1, "exynos4-sdhci.1", "sdmmc1", "aclk133", 0xc940, 6, 0, 0, "hsmmc"),
+	GATE_DA(sdmmc2, "exynos4-sdhci.2", "sdmmc2", "aclk133", 0xc940, 7, 0, 0, "hsmmc"),
+	GATE_DA(sdmmc3, "exynos4-sdhci.3", "sdmmc3", "aclk133", 0xc940, 8, 0, 0, "hsmmc"),
+	GATE_A(sdmmc4, "sdmmc4", "aclk133", 0xc940, 9, 0, 0, "biu"),
+	GATE(sromc, "sromc", "aclk133", 0xc940, 11, 0, 0),
+	GATE_A(usb_host, "usb_host", "aclk133", 0xc940, 12, 0, 0, "usbhost"),
+	GATE(usb_device, "usb_device", "aclk133", 0xc940, 13, 0, 0),
+	GATE(onenand, "onenand", "aclk133", 0xc940, 15, 0, 0),
+	GATE(nfcon, "nfcon", "aclk133", 0xc940, 16, 0, 0),
+	GATE(gps, "gps", "aclk133", 0xc94c, 0, 0, 0),
+	GATE(smmu_gps, "smmu_gps", "aclk133", 0xc94c, 1, 0, 0),
+	GATE_DA(uart0, "exynos4210-uart.0", "uart0", "aclk100", 0xc950, 0, 0, 0, "uart"),
+	GATE_DA(uart1, "exynos4210-uart.1", "uart1", "aclk100", 0xc950, 1, 0, 0, "uart"),
+	GATE_DA(uart2, "exynos4210-uart.2", "uart2", "aclk100", 0xc950, 2, 0, 0, "uart"),
+	GATE_DA(uart3, "exynos4210-uart.3", "uart3", "aclk100", 0xc950, 3, 0, 0, "uart"),
+	GATE_DA(uart4, "exynos4210-uart.4", "uart4", "aclk100", 0xc950, 4, 0, 0, "uart"),
+	GATE_DA(i2c0, "s3c2440-i2c.0", "i2c0", "aclk100", 0xc950, 6, 0, 0, "i2c"),
+	GATE_DA(i2c1, "s3c2440-i2c.1", "i2c1", "aclk100", 0xc950, 7, 0, 0, "i2c"),
+	GATE_DA(i2c2, "s3c2440-i2c.2", "i2c2", "aclk100", 0xc950, 8, 0, 0, "i2c"),
+	GATE_DA(i2c3, "s3c2440-i2c.3", "i2c3", "aclk100", 0xc950, 9, 0, 0, "i2c"),
+	GATE_DA(i2c4, "s3c2440-i2c.4", "i2c4", "aclk100", 0xc950, 10, 0, 0, "i2c"),
+	GATE_DA(i2c5, "s3c2440-i2c.5", "i2c5", "aclk100", 0xc950, 11, 0, 0, "i2c"),
+	GATE_DA(i2c6, "s3c2440-i2c.6", "i2c6", "aclk100", 0xc950, 12, 0, 0, "i2c"),
+	GATE_DA(i2c7, "s3c2440-i2c.7", "i2c7", "aclk100", 0xc950, 13, 0, 0, "i2c"),
+	GATE_DA(i2c_hdmi, "s3c2440-hdmiphy-i2c", "i2c-hdmi", "aclk100", 0xc950, 14, 0, 0, "i2c"),
+	GATE_DA(spi0, "exynos4210-spi.0", "spi0", "aclk100", 0xc950, 16, 0, 0, "spi"),
+	GATE_DA(spi1, "exynos4210-spi.1", "spi1", "aclk100", 0xc950, 17, 0, 0, "spi"),
+	GATE_DA(spi2, "exynos4210-spi.2", "spi2", "aclk100", 0xc950, 18, 0, 0, "spi"),
+	GATE_DA(i2s1, "samsung-i2s.1", "i2s1", "aclk100", 0xc950, 20, 0, 0, "iis"),
+	GATE_DA(i2s2, "samsung-i2s.2", "i2s2", "aclk100", 0xc950, 21, 0, 0, "iis"),
+	GATE_DA(pcm1, "samsung-pcm.1", "pcm1", "aclk100", 0xc950, 22, 0, 0, "pcm"),
+	GATE_DA(pcm2, "samsung-pcm.2", "pcm2", "aclk100", 0xc950, 23, 0, 0, "pcm"),
+	GATE_A(pwm, "pwm", "aclk100", 0xc950, 24, 0, 0, "timers"),
+	GATE(slimbus, "slimbus", "aclk100", 0xc950, 25, 0, 0),
+	GATE_DA(spdif, "samsung-spdif", "spdif", "aclk100", 0xc950, 26, 0, 0, "spdif"),
+	GATE_DA(ac97, "samsung-ac97", "ac97", "aclk100", 0xc950, 27, 0, 0, "ac97"),
+};
+
+/* list of gate clocks supported in exynos4210 soc */
+struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
+	GATE_DA(sclk_fimd1, "exynos4-fb.1", "sclk_fimd1", "div_fimd1",
+			0xc338, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"),
+	GATE(sclk_mipi1, "sclk_mipi1", "div_mipi_pre1", 0xc338, 12, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_sata, "sclk_sata", "div_sata", 0xc340, 24, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_cam0, "sclk_cam0", "div_cam0", 0xc820, 4, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_cam1, "sclk_cam1", "div_cam1", 0xc820, 5, CLK_SET_RATE_PARENT, 0),
+	GATE(tvenc, "tvenc", "aclk160", 0xc924, 2, 0, 0),
+	GATE(g2d, "g2d", "aclk200", 0xc930, 0, 0, 0),
+	GATE(rotator, "rotator", "aclk200", 0xc930, 1, 0, 0),
+	GATE(mdma, "mdma", "aclk200", 0xc930, 2, 0, 0),
+	GATE(smmu_g2d, "smmu_g2d", "aclk200", 0xc930, 3, 0, 0),
+	GATE(smmu_rotator, "smmu_rotator", "aclk200", 0xc930, 4, 0, 0),
+	GATE(smmu_mdma, "smmu_mdma", "aclk200", 0xc930, 5, 0, 0),
+	GATE(pcie_phy, "pcie_phy", "aclk133", 0xc940, 2, 0, 0),
+	GATE(sata_phy, "sata_phy", "aclk133", 0xc940, 3, 0, 0),
+	GATE(sata, "sata", "aclk133", 0xc940, 10, 0, 0),
+	GATE(pcie, "pcie", "aclk133", 0xc940, 14, 0, 0),
+	GATE(smmu_pcie, "smmu_pcie", "aclk133", 0xc940, 18, 0, 0),
+	GATE_A(tsadc, "tsadc", "aclk100", 0xc950, 15, 0, 0, "adc"),
+	GATE(modemif, "modemif", "aclk100", 0xc950, 28, 0, 0),
+	GATE(chipid, "chipid", "aclk100", 0xc960, 0, 0, 0),
+	GATE(sysreg, "sysreg", "aclk100", 0xc960, 0, 0, 0),
+	GATE(hdmi_cec, "hdmi_cec", "aclk100", 0xc960, 11, 0, 0),
+	GATE_A(mct, "mct", "aclk100", 0xc960, 13, 0, 0, "mct"),
+	GATE_A(wdt, "watchdog", "aclk100", 0xc960, 14, 0, 0, "watchdog"),
+	GATE_A(rtc, "rtc", "aclk100", 0xc960, 15, 0, 0, "rtc"),
+	GATE_A(keyif, "keyif", "aclk100", 0xc960, 16, 0, 0, "keypad"),
+};
+
+/* list of gate clocks supported in exynos4x12 soc */
+struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
+	GATE(sclk_mdnie0, "sclk_mdnie0", "div_mdnie0", 0xc334, 4, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_mdnie_pwm0, "sclk_mdnie_pwm0", "div_mdnie_pwm_pre0",
+			0xc334, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_mipihsi, "sclk_mipihsi", "div_mipihsi", 0xc340, 24, CLK_SET_RATE_PARENT, 0),
+	GATE(audss, "audss", "sclk_epll", 0xc93c, 0, 0, 0),
+	GATE(mdnie0, "mdnie0", "aclk160", 0xc934, 2, 0, 0),
+	GATE_DA(pcm0, "samsung-pcm.0", "pcm0", "aclk100", 0xc93c, 2, 0, 0, "pcm"),
+	GATE_DA(i2s0, "samsung-i2s.0", "i2s0", "aclk100", 0xc93c, 3, 0, 0, "iis"),
+	GATE(mipi_hsi, "mipi_hsi", "aclk133", 0xc940, 10, 0, 0),
+	GATE(chipid, "chipid", "aclk100", 0x8960, 0, 0, 0),
+	GATE(sysreg, "sysreg", "aclk100", 0x8960, 1, 0, 0),
+	GATE(hdmi_cec, "hdmi_cec", "aclk100", 0x8960, 11, 0, 0),
+	GATE_A(mct, "mct", "aclk100", 0x8960, 13, 0, 0, "mct"),
+	GATE_A(wdt, "watchdog", "aclk100", 0x8960, 14, 0, 0, "watchdog"),
+	GATE_A(rtc, "rtc", "aclk100", 0x8960, 15, 0, 0, "rtc"),
+	GATE_A(keyif, "keyif", "aclk100", 0x8960, 16, 0, 0, "keypad"),
+	GATE(rotator, "rotator", "aclk200", 0x4930, 1, 0, 0),
+	GATE(mdma2, "mdma2", "aclk200", 0x4930, 2, 0, 0),
+	GATE(smmu_rotator, "smmu_rotator", "aclk200", 0x4930, 4, 0, 0),
+	GATE(smmu_mdma, "smmu_mdma", "aclk200", 0x4930, 5, 0, 0),
+};
+
+#ifdef CONFIG_OF
+static struct of_device_id exynos4_clk_ids[] __initdata = {
+	{ .compatible = "samsung,exynos4210-clock",
+			.data = (void *)EXYNOS4210, },
+	{ .compatible = "samsung,exynos4412-clock",
+			.data = (void *)EXYNOS4X12, },
+	{ },
+};
+#endif
+
+/*
+ * The parent of the fin_pll clock is selected by the XOM[0] bit. This bit
+ * resides in chipid register space, outside of the clock controller memory
+ * mapped space. So to determine the parent of fin_pll clock, the chipid
+ * controller is first remapped and the value of XOM[0] bit is read to
+ * determine the parent clock.
+ */
+static void __init exynos4_clk_register_finpll(void)
+{
+	struct samsung_fixed_rate_clock fclk;
+	struct device_node *np;
+	struct clk *clk;
+	void __iomem *chipid_base = S5P_VA_CHIPID;
+	unsigned long xom, finpll_f = 24000000;
+	char *parent_name;
+
+	np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-chipid");
+	if (np)
+		chipid_base = of_iomap(np, 0);
+
+	if (chipid_base) {
+		xom = readl(chipid_base + 8);
+		parent_name = xom & 1 ? "xusbxti" : "xxti";
+		clk = clk_get(NULL, parent_name);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to lookup parent clock %s, assuming "
+				"fin_pll clock frequency is 24MHz\n", __func__,
+				parent_name);
+		} else {
+			finpll_f = clk_get_rate(clk);
+		}
+	} else {
+		pr_err("%s: failed to map chipid registers, assuming "
+			"fin_pll clock frequency is 24MHz\n", __func__);
+	}
+
+	fclk.id = fin_pll;
+	fclk.name = "fin_pll";
+	fclk.parent_name = NULL;
+	fclk.flags = CLK_IS_ROOT;
+	fclk.fixed_rate = finpll_f;
+	samsung_clk_register_fixed_rate(&fclk, 1);
+
+	if (np)
+		iounmap(chipid_base);
+}
+
+/*
+ * This function allows non-dt platforms to specify the clock speed of the
+ * xxti and xusbxti clocks. These clocks are then registered with the specified
+ * clock speed.
+ */
+void __init exynos4_clk_register_fixed_ext(unsigned long xxti_f,
+						unsigned long xusbxti_f)
+{
+	exynos4_fixed_rate_ext_clks[0].fixed_rate = xxti_f;
+	exynos4_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
+	samsung_clk_register_fixed_rate(exynos4_fixed_rate_ext_clks,
+			ARRAY_SIZE(exynos4_fixed_rate_ext_clks));
+}
+
+#ifdef CONFIG_OF
+/*
+ * For device tree based platforms, obtain the clock speed of the xxti and
+ * xusbxti clock from device tree and register them.
+ */
+static void __init exynos4_clk_of_register_fixed_ext(void)
+{
+	struct device_node *np;
+	unsigned long xxti_f = 0, xusbxti_f = 0;
+	u32 freq;
+
+	for_each_compatible_node(np, NULL, "fixed-clock") {
+		if (of_property_read_u32(np, "clock-frequency", &freq))
+			continue;
+		if (of_device_is_compatible(np, "samsung,clock-xxti"))
+			xxti_f = freq;
+		else if (of_device_is_compatible(np, "samsung,clock-xusbxti"))
+			xusbxti_f = freq;
+	}
+	exynos4_clk_register_fixed_ext(xxti_f, xusbxti_f);
+}
+#else
+/*
+ * todo: remove this non-dt code after adding dt support for existing non-dt
+ * exynos4 platforms.
+ */
+static void __init exynos4_clk_of_register_fixed_ext(void)
+{
+}
+#endif
+
+/* register exynos4 clocks */
+void __init exynos4_clk_init(void)
+{
+	void __iomem *reg_base;
+	struct device_node *np = NULL;
+	struct clk *apll, *mpll, *epll, *vpll;
+	u32 exynos4_soc;
+
+#ifdef CONFIG_OF
+	np = of_find_matching_node(NULL, exynos4_clk_ids);
+#endif
+	if (np) {
+		const struct of_device_id *match;
+		match = of_match_node(exynos4_clk_ids, np);
+		exynos4_soc = (u32)match->data;
+
+		reg_base = of_iomap(np, 0);
+		if (!reg_base)
+			panic("%s: failed to map registers\n", __func__);
+	} else {
+		reg_base = S5P_VA_CMU;
+		if (soc_is_exynos4210())
+			exynos4_soc = EXYNOS4210;
+		else if (soc_is_exynos4212() || soc_is_exynos4412())
+			exynos4_soc = EXYNOS4X12;
+		else
+			panic("%s: unable to determine soc\n", __func__);
+	}
+
+	samsung_clk_init(np, reg_base, nr_clks);
+	if (np)
+		exynos4_clk_of_register_fixed_ext();
+	exynos4_clk_register_finpll();
+
+	if (exynos4_soc == EXYNOS4210) {
+		apll = samsung_clk_register_pll45xx("fout_apll", "fin_pll",
+					reg_base + 0x14100, pll_4508);
+		mpll = samsung_clk_register_pll45xx("fout_mpll", "fin_pll",
+					reg_base + 0x14108, pll_4508);
+		epll = samsung_clk_register_pll46xx("fout_epll", "fin_pll",
+					reg_base + 0xc110, pll_4600);
+		vpll = samsung_clk_register_pll46xx("fout_vpll", "mout_vpllsrc",
+					reg_base + 0xc120, pll_4650c);
+	} else {
+		apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
+					reg_base + 0x14100);
+		mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
+					reg_base + 0x10108);
+		epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
+					reg_base + 0xc110);
+		vpll = samsung_clk_register_pll36xx("fout_vpll", "fin_pll",
+					reg_base + 0xc120);
+	}
+
+	samsung_clk_add_lookup(apll, fout_apll);
+	samsung_clk_add_lookup(mpll, fout_mpll);
+	samsung_clk_add_lookup(epll, fout_epll);
+	samsung_clk_add_lookup(vpll, fout_vpll);
+
+	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));
+
+	if (exynos4_soc == EXYNOS4210) {
+		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));
+		samsung_clk_register_div(exynos4210_div_clks,
+			ARRAY_SIZE(exynos4210_div_clks));
+		samsung_clk_register_gate(exynos4210_gate_clks,
+			ARRAY_SIZE(exynos4210_gate_clks));
+	} else {
+		samsung_clk_register_mux(exynos4x12_mux_clks,
+			ARRAY_SIZE(exynos4x12_mux_clks));
+		samsung_clk_register_div(exynos4x12_div_clks,
+			ARRAY_SIZE(exynos4x12_div_clks));
+		samsung_clk_register_gate(exynos4x12_gate_clks,
+			ARRAY_SIZE(exynos4x12_gate_clks));
+	}
+
+	pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
+		"\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
+		exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
+		_get_rate("sclk_apll"),	_get_rate("sclk_mpll"),
+		_get_rate("sclk_epll"), _get_rate("sclk_vpll"),
+		_get_rate("arm_clk"));
+}
-- 
1.7.4.4




More information about the linux-arm-kernel mailing list