[PATCH v3 03/11] clk: exynos4: register clocks using common clock framework
Thomas Abraham
thomas.abraham at linaro.org
Thu Nov 15 09:07:25 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 | 641 ++++++++++++++++++++
3 files changed, 857 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 a5bf189..5d98904 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -3,3 +3,4 @@
#
obj-$(CONFIG_PLAT_SAMSUNG) += 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..6f0b6a7
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -0,0 +1,641 @@
+/*
+ * 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[] = {
+ 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[] = {
+ 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[] = {
+ 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[] = {
+ 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[] = {
+ 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[] = {
+ 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[] = {
+ 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[] = {
+ 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[] = {
+ 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[] = {
+ /*
+ * 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[] = {
+ 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[] = {
+ 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),
+};
+
+static struct of_device_id exynos4_clk_ids[] = {
+ { .compatible = "samsung,exynos4210-clock",
+ .data = (void *)EXYNOS4210, },
+ { .compatible = "samsung,exynos4412-clock",
+ .data = (void *)EXYNOS4X12, },
+ { },
+};
+
+/*
+ * 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));
+}
+
+/*
+ * 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);
+}
+
+/* register exynos4 clocks */
+void __init exynos4_clk_init(void)
+{
+ void __iomem *reg_base;
+ struct device_node *np;
+ struct clk *apll, *mpll, *epll, *vpll;
+ u32 exynos4_soc;
+
+ np = of_find_matching_node(NULL, exynos4_clk_ids);
+ 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 devicetree-discuss
mailing list