diff mbox

[2/7] clk: samsung: Add clock driver for S3C64xx SoCs

Message ID 1370476651-6743-3-git-send-email-tomasz.figa@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tomasz Figa June 5, 2013, 11:57 p.m. UTC
This patch adds new, Common Clock Framework-based clock driver for Samsung
S3C64xx SoCs. The driver is just added, without actually letting the
platforms use it yet, since this requires more intermediate steps.

Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 .../bindings/clock/samsung,s3c64xx-clock.txt       |  48 ++
 drivers/clk/samsung/Makefile                       |   3 +
 drivers/clk/samsung/clk-s3c64xx.c                  | 503 +++++++++++++++++++++
 include/dt-bindings/clock/samsung,s3c64xx-clock.h  | 144 ++++++
 4 files changed, 698 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
 create mode 100644 drivers/clk/samsung/clk-s3c64xx.c
 create mode 100644 include/dt-bindings/clock/samsung,s3c64xx-clock.h

Comments

Mike Turquette June 12, 2013, 2:54 a.m. UTC | #1
Quoting Tomasz Figa (2013-06-05 16:57:26)
> This patch adds new, Common Clock Framework-based clock driver for Samsung
> S3C64xx SoCs. The driver is just added, without actually letting the
> platforms use it yet, since this requires more intermediate steps.
> 

It seems like there is an awful lot of clock data here that exists
alongside the stuff in DT.  Is this how you plan to keep things going
forward or is this conversion just an intermediate step?

Regards,
Mike

> Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
> ---
>  .../bindings/clock/samsung,s3c64xx-clock.txt       |  48 ++
>  drivers/clk/samsung/Makefile                       |   3 +
>  drivers/clk/samsung/clk-s3c64xx.c                  | 503 +++++++++++++++++++++
>  include/dt-bindings/clock/samsung,s3c64xx-clock.h  | 144 ++++++
>  4 files changed, 698 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
>  create mode 100644 drivers/clk/samsung/clk-s3c64xx.c
>  create mode 100644 include/dt-bindings/clock/samsung,s3c64xx-clock.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
> new file mode 100644
> index 0000000..278ab6e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
> @@ -0,0 +1,48 @@
> +* Samsung S3C64xx Clock Controller
> +
> +The S3C64xx clock controller generates and supplies clock to various controllers
> +within the SoC. The clock binding described here is applicable to all SoCs in
> +the S3C64xx family.
> +
> +Required Properties:
> +
> +- comptible: should be one of the following.
> +  - "samsung,s3c6400-clock" - controller compatible with S3C6400 SoC.
> +  - "samsung,s3c6410-clock" - controller compatible with S3C6410 SoC.
> +
> +- reg: physical base address of the controller and length of memory mapped
> +  region.
> +
> +- #clock-cells: should be 1.
> +
> +Each clock is assigned an identifier and client nodes can use this identifier
> +to specify the clock which they consume. Some of the clocks are available only
> +on a particular S3C64xx SoC and this is specified where applicable.
> +
> +All available clocks are defined as preprocessor macros in
> +dt-bindings/clock/samsung,s3c64xx-clock.h header and can be used in device
> +tree sources.
> +
> +Example: Clock controller node:
> +
> +       clocks: clock-controller@7e00f000 {
> +               compatible = "samsung,s3c6410-clock";
> +               reg = <0x7e00f000 0x1000>;
> +               #clock-cells = <1>;
> +       };
> +
> +Example: 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" properties):
> +
> +               uart0: serial@7f005000 {
> +                       compatible = "samsung,s3c6400-uart";
> +                       reg = <0x7f005000 0x100>;
> +                       interrupt-parent = <&vic1>;
> +                       interrupts = <5>;
> +                       clock-names = "uart", "clk_uart_baud2",
> +                                       "clk_uart_baud3";
> +                       clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>,
> +                                       <&clocks SCLK_UART>;
> +                       status = "disabled";
> +               };
> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
> index b7c232e..c023474 100644
> --- a/drivers/clk/samsung/Makefile
> +++ b/drivers/clk/samsung/Makefile
> @@ -6,3 +6,6 @@ obj-$(CONFIG_COMMON_CLK)        += clk.o clk-pll.o
>  obj-$(CONFIG_ARCH_EXYNOS4)     += clk-exynos4.o
>  obj-$(CONFIG_SOC_EXYNOS5250)   += clk-exynos5250.o
>  obj-$(CONFIG_SOC_EXYNOS5440)   += clk-exynos5440.o
> +ifdef CONFIG_COMMON_CLK
> +obj-$(CONFIG_ARCH_S3C64XX)     += clk-s3c64xx.o
> +endif
> diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
> new file mode 100644
> index 0000000..253a972
> --- /dev/null
> +++ b/drivers/clk/samsung/clk-s3c64xx.c
> @@ -0,0 +1,503 @@
> +/*
> + * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.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 S3C64xx SoCs.
> +*/
> +
> +#include <linux/clk.h>
> +#include <linux/clkdev.h>
> +#include <linux/clk-provider.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +
> +#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
> +
> +#include "clk.h"
> +#include "clk-pll.h"
> +
> +/* S3C64xx clock controller register offsets. */
> +#define APLL_LOCK              0x000
> +#define MPLL_LOCK              0x004
> +#define EPLL_LOCK              0x008
> +#define APLL_CON               0x00c
> +#define MPLL_CON               0x010
> +#define EPLL_CON0              0x014
> +#define EPLL_CON1              0x018
> +#define CLK_SRC                        0x01c
> +#define CLK_DIV0               0x020
> +#define CLK_DIV1               0x024
> +#define CLK_DIV2               0x028
> +#define HCLK_GATE              0x030
> +#define PCLK_GATE              0x034
> +#define SCLK_GATE              0x038
> +#define MEM0_GATE              0x03c
> +#define CLK_SRC2               0x10c
> +#define OTHERS                 0x900
> +
> +/* Special bitfields used in the driver. */
> +#define OTHERS_SYNCMUXSEL      (1 << 6)
> +
> +/* Helper macros to define clock arrays. */
> +#define FIXED_RATE_CLOCKS(name)        \
> +               static struct samsung_fixed_rate_clock name[]
> +#define MUX_CLOCKS(name)       \
> +               static struct samsung_mux_clock name[]
> +#define DIV_CLOCKS(name)       \
> +               static struct samsung_div_clock name[]
> +#define GATE_CLOCKS(name)      \
> +               static struct samsung_gate_clock name[]
> +
> +/* Helper macros for gate types present on S3C64xx. */
> +#define GATE_BUS(_id, cname, pname, o, b) \
> +               GATE(_id, cname, pname, o, b, 0, 0)
> +#define GATE_SCLK(_id, cname, pname, o, b) \
> +               GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT, 0)
> +#define GATE_ON(_id, cname, pname, o, b) \
> +               GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0)
> +
> +/*
> + * List of controller registers to be saved and restored during
> + * a suspend/resume cycle.
> + */
> +static __initdata unsigned long s3c64xx_clk_regs[] = {
> +       APLL_LOCK,
> +       MPLL_LOCK,
> +       EPLL_LOCK,
> +       APLL_CON,
> +       MPLL_CON,
> +       EPLL_CON0,
> +       EPLL_CON1,
> +       CLK_SRC,
> +       CLK_DIV0,
> +       CLK_DIV1,
> +       CLK_DIV2,
> +       HCLK_GATE,
> +       PCLK_GATE,
> +       SCLK_GATE,
> +};
> +
> +static __initdata unsigned long s3c6410_clk_regs[] = {
> +       CLK_SRC2,
> +       MEM0_GATE,
> +};
> +
> +/* List of parent clocks common for all S3C64xx SoCs. */
> +PNAME(spi_mmc_p)       = { "mout_epll", "dout_mpll", "fin_pll", "clk27m" };
> +PNAME(uart_p)          = { "mout_epll", "dout_mpll" };
> +PNAME(audio0_p)                = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk0",
> +                               "pcmcdclk0", "none", "none", "none" };
> +PNAME(audio1_p)                = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk1",
> +                               "pcmcdclk0", "none", "none", "none" };
> +PNAME(mfc_p)           = { "hclkx2", "mout_epll" };
> +PNAME(apll_p)          = { "fin_pll", "fout_apll" };
> +PNAME(mpll_p)          = { "fin_pll", "fout_mpll" };
> +PNAME(epll_p)          = { "fin_pll", "fout_epll" };
> +
> +/* S3C6400-specific parent clocks. */
> +PNAME(scaler_lcd_p6400)        = { "mout_epll", "dout_mpll", "none", "none" };
> +PNAME(irda_p6400)      = { "mout_epll", "dout_mpll", "none", "clk48m" };
> +PNAME(uhost_p6400)     = { "clk48m", "mout_epll", "dout_mpll", "none" };
> +
> +/* S3C6410-specific parent clocks. */
> +PNAME(clk27_p6410)     = { "clk27m", "fin_pll" };
> +PNAME(scaler_lcd_p6410)        = { "mout_epll", "dout_mpll", "fin_pll", "none" };
> +PNAME(irda_p6410)      = { "mout_epll", "dout_mpll", "fin_pll", "clk48m" };
> +PNAME(uhost_p6410)     = { "clk48m", "mout_epll", "dout_mpll", "fin_pll" };
> +PNAME(audio2_p6410)    = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk2",
> +                               "pcmcdclk1", "none", "none", "none" };
> +
> +/* Fixed rate clocks generated outside the SoC. */
> +FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_ext_clks) __initdata = {
> +       FRATE(FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0),
> +       FRATE(0, "xusbxti", NULL, CLK_IS_ROOT, 0),
> +};
> +
> +/* Fixed rate clocks generated inside the SoC. */
> +FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_clks) __initdata = {
> +       FRATE(CLK27M, "clk27m", NULL, CLK_IS_ROOT, 27000000),
> +       FRATE(CLK48M, "clk48m", NULL, CLK_IS_ROOT, 48000000),
> +};
> +
> +/* List of clock muxes present on all S3C64xx SoCs. */
> +MUX_CLOCKS(s3c64xx_mux_clks) __initdata = {
> +       MUX(0, "mout_apll", apll_p, CLK_SRC, 0, 1),
> +       MUX(0, "mout_mpll", mpll_p, CLK_SRC, 1, 1),
> +       MUX(MOUT_EPLL, "mout_epll", epll_p, CLK_SRC, 2, 1),
> +       MUX(0, "mout_mfc", mfc_p, CLK_SRC, 4, 1),
> +       MUX(0, "mout_audio0", audio0_p, CLK_SRC, 7, 3),
> +       MUX(0, "mout_audio1", audio1_p, CLK_SRC, 10, 3),
> +       MUX(0, "mout_uart", uart_p, CLK_SRC, 13, 1),
> +       MUX(0, "mout_spi0", spi_mmc_p, CLK_SRC, 14, 2),
> +       MUX(0, "mout_spi1", spi_mmc_p, CLK_SRC, 16, 2),
> +       MUX(0, "mout_mmc0", spi_mmc_p, CLK_SRC, 18, 2),
> +       MUX(0, "mout_mmc1", spi_mmc_p, CLK_SRC, 20, 2),
> +       MUX(0, "mout_mmc2", spi_mmc_p, CLK_SRC, 22, 2),
> +};
> +
> +/* List of clock muxes present on S3C6400. */
> +MUX_CLOCKS(s3c6400_mux_clks) __initdata = {
> +       MUX(0, "mout_uhost", uhost_p6400, CLK_SRC, 5, 2),
> +       MUX(0, "mout_irda", irda_p6400, CLK_SRC, 24, 2),
> +       MUX(0, "mout_lcd", scaler_lcd_p6400, CLK_SRC, 26, 2),
> +       MUX(0, "mout_scaler", scaler_lcd_p6400, CLK_SRC, 28, 2),
> +};
> +
> +/* List of clock muxes present on S3C6410. */
> +MUX_CLOCKS(s3c6410_mux_clks) __initdata = {
> +       MUX(0, "mout_uhost", uhost_p6410, CLK_SRC, 5, 2),
> +       MUX(0, "mout_irda", irda_p6410, CLK_SRC, 24, 2),
> +       MUX(0, "mout_lcd", scaler_lcd_p6410, CLK_SRC, 26, 2),
> +       MUX(0, "mout_scaler", scaler_lcd_p6410, CLK_SRC, 28, 2),
> +       MUX(0, "mout_dac27", clk27_p6410, CLK_SRC, 30, 1),
> +       MUX(0, "mout_tv27", clk27_p6410, CLK_SRC, 31, 1),
> +       MUX(0, "mout_audio2", audio2_p6410, CLK_SRC2, 0, 3),
> +};
> +
> +/* List of clock dividers present on all S3C64xx SoCs. */
> +DIV_CLOCKS(s3c64xx_div_clks) __initdata = {
> +       DIV(DOUT_MPLL, "dout_mpll", "mout_mpll", CLK_DIV0, 4, 1),
> +       DIV(HCLK, "hclk", "hclkx2", CLK_DIV0, 8, 1),
> +       DIV(PCLK, "pclk", "hclkx2", CLK_DIV0, 12, 4),
> +       DIV(0, "dout_secur", "hclkx2", CLK_DIV0, 18, 2),
> +       DIV(0, "dout_cam", "hclkx2", CLK_DIV0, 20, 4),
> +       DIV(0, "dout_jpeg", "hclkx2", CLK_DIV0, 24, 4),
> +       DIV(0, "dout_mfc", "mout_mfc", CLK_DIV0, 28, 4),
> +       DIV(0, "dout_mmc0", "mout_mmc0", CLK_DIV1, 0, 4),
> +       DIV(0, "dout_mmc1", "mout_mmc1", CLK_DIV1, 4, 4),
> +       DIV(0, "dout_mmc2", "mout_mmc2", CLK_DIV1, 8, 4),
> +       DIV(0, "dout_lcd", "mout_lcd", CLK_DIV1, 12, 4),
> +       DIV(0, "dout_scaler", "mout_scaler", CLK_DIV1, 16, 4),
> +       DIV(0, "dout_uhost", "mout_uhost", CLK_DIV1, 20, 4),
> +       DIV(0, "dout_spi0", "mout_spi0", CLK_DIV2, 0, 4),
> +       DIV(0, "dout_spi1", "mout_spi1", CLK_DIV2, 4, 4),
> +       DIV(0, "dout_audio0", "mout_audio0", CLK_DIV2, 8, 4),
> +       DIV(0, "dout_audio1", "mout_audio1", CLK_DIV2, 12, 4),
> +       DIV(0, "dout_uart", "mout_uart", CLK_DIV2, 16, 4),
> +       DIV(0, "dout_irda", "mout_irda", CLK_DIV2, 20, 4),
> +};
> +
> +/* List of clock dividers present on S3C6400. */
> +DIV_CLOCKS(s3c6400_div_clks) __initdata = {
> +       DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 3),
> +};
> +
> +/* List of clock dividers present on S3C6410. */
> +DIV_CLOCKS(s3c6410_div_clks) __initdata = {
> +       DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 4),
> +       DIV(0, "dout_fimc", "hclk", CLK_DIV1, 24, 4),
> +       DIV(0, "dout_audio2", "mout_audio2", CLK_DIV2, 24, 4),
> +};
> +
> +/* List of clock gates present on all S3C64xx SoCs. */
> +GATE_CLOCKS(s3c64xx_gate_clks) __initdata = {
> +       GATE_BUS(HCLK_UHOST, "hclk_uhost", "hclk", HCLK_GATE, 29),
> +       GATE_BUS(HCLK_SECUR, "hclk_secur", "hclk", HCLK_GATE, 28),
> +       GATE_BUS(HCLK_SDMA1, "hclk_sdma1", "hclk", HCLK_GATE, 27),
> +       GATE_BUS(HCLK_SDMA0, "hclk_sdma0", "hclk", HCLK_GATE, 26),
> +       GATE_ON(HCLK_DDR1, "hclk_ddr1", "hclk", HCLK_GATE, 24),
> +       GATE_BUS(HCLK_USB, "hclk_usb", "hclk", HCLK_GATE, 20),
> +       GATE_BUS(HCLK_HSMMC2, "hclk_hsmmc2", "hclk", HCLK_GATE, 19),
> +       GATE_BUS(HCLK_HSMMC1, "hclk_hsmmc1", "hclk", HCLK_GATE, 18),
> +       GATE_BUS(HCLK_HSMMC0, "hclk_hsmmc0", "hclk", HCLK_GATE, 17),
> +       GATE_BUS(HCLK_MDP, "hclk_mdp", "hclk", HCLK_GATE, 16),
> +       GATE_BUS(HCLK_DHOST, "hclk_dhost", "hclk", HCLK_GATE, 15),
> +       GATE_BUS(HCLK_IHOST, "hclk_ihost", "hclk", HCLK_GATE, 14),
> +       GATE_BUS(HCLK_DMA1, "hclk_dma1", "hclk", HCLK_GATE, 13),
> +       GATE_BUS(HCLK_DMA0, "hclk_dma0", "hclk", HCLK_GATE, 12),
> +       GATE_BUS(HCLK_JPEG, "hclk_jpeg", "hclk", HCLK_GATE, 11),
> +       GATE_BUS(HCLK_CAMIF, "hclk_camif", "hclk", HCLK_GATE, 10),
> +       GATE_BUS(HCLK_SCALER, "hclk_scaler", "hclk", HCLK_GATE, 9),
> +       GATE_BUS(HCLK_2D, "hclk_2d", "hclk", HCLK_GATE, 8),
> +       GATE_BUS(HCLK_TV, "hclk_tv", "hclk", HCLK_GATE, 7),
> +       GATE_BUS(HCLK_POST0, "hclk_post0", "hclk", HCLK_GATE, 5),
> +       GATE_BUS(HCLK_ROT, "hclk_rot", "hclk", HCLK_GATE, 4),
> +       GATE_BUS(HCLK_LCD, "hclk_lcd", "hclk", HCLK_GATE, 3),
> +       GATE_BUS(HCLK_TZIC, "hclk_tzic", "hclk", HCLK_GATE, 2),
> +       GATE_ON(HCLK_INTC, "hclk_intc", "hclk", HCLK_GATE, 1),
> +       GATE_ON(PCLK_SKEY, "pclk_skey", "pclk", PCLK_GATE, 24),
> +       GATE_ON(PCLK_CHIPID, "pclk_chipid", "pclk", PCLK_GATE, 23),
> +       GATE_BUS(PCLK_SPI1, "pclk_spi1", "pclk", PCLK_GATE, 22),
> +       GATE_BUS(PCLK_SPI0, "pclk_spi0", "pclk", PCLK_GATE, 21),
> +       GATE_BUS(PCLK_HSIRX, "pclk_hsirx", "pclk", PCLK_GATE, 20),
> +       GATE_BUS(PCLK_HSITX, "pclk_hsitx", "pclk", PCLK_GATE, 19),
> +       GATE_ON(PCLK_GPIO, "pclk_gpio", "pclk", PCLK_GATE, 18),
> +       GATE_BUS(PCLK_IIC0, "pclk_iic0", "pclk", PCLK_GATE, 17),
> +       GATE_BUS(PCLK_IIS1, "pclk_iis1", "pclk", PCLK_GATE, 16),
> +       GATE_BUS(PCLK_IIS0, "pclk_iis0", "pclk", PCLK_GATE, 15),
> +       GATE_BUS(PCLK_AC97, "pclk_ac97", "pclk", PCLK_GATE, 14),
> +       GATE_BUS(PCLK_TZPC, "pclk_tzpc", "pclk", PCLK_GATE, 13),
> +       GATE_BUS(PCLK_TSADC, "pclk_tsadc", "pclk", PCLK_GATE, 12),
> +       GATE_BUS(PCLK_KEYPAD, "pclk_keypad", "pclk", PCLK_GATE, 11),
> +       GATE_BUS(PCLK_IRDA, "pclk_irda", "pclk", PCLK_GATE, 10),
> +       GATE_BUS(PCLK_PCM1, "pclk_pcm1", "pclk", PCLK_GATE, 9),
> +       GATE_BUS(PCLK_PCM0, "pclk_pcm0", "pclk", PCLK_GATE, 8),
> +       GATE_BUS(PCLK_PWM, "pclk_pwm", "pclk", PCLK_GATE, 7),
> +       GATE_BUS(PCLK_RTC, "pclk_rtc", "pclk", PCLK_GATE, 6),
> +       GATE_BUS(PCLK_WDT, "pclk_wdt", "pclk", PCLK_GATE, 5),
> +       GATE_BUS(PCLK_UART3, "pclk_uart3", "pclk", PCLK_GATE, 4),
> +       GATE_BUS(PCLK_UART2, "pclk_uart2", "pclk", PCLK_GATE, 3),
> +       GATE_BUS(PCLK_UART1, "pclk_uart1", "pclk", PCLK_GATE, 2),
> +       GATE_BUS(PCLK_UART0, "pclk_uart0", "pclk", PCLK_GATE, 1),
> +       GATE_BUS(PCLK_MFC, "pclk_mfc", "pclk", PCLK_GATE, 0),
> +       GATE_SCLK(SCLK_UHOST, "sclk_uhost", "dout_uhost", SCLK_GATE, 30),
> +       GATE_SCLK(SCLK_MMC2_48, "sclk_mmc2_48", "clk48m", SCLK_GATE, 29),
> +       GATE_SCLK(SCLK_MMC1_48, "sclk_mmc1_48", "clk48m", SCLK_GATE, 28),
> +       GATE_SCLK(SCLK_MMC0_48, "sclk_mmc0_48", "clk48m", SCLK_GATE, 27),
> +       GATE_SCLK(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", SCLK_GATE, 26),
> +       GATE_SCLK(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", SCLK_GATE, 25),
> +       GATE_SCLK(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", SCLK_GATE, 24),
> +       GATE_SCLK(SCLK_SPI1_48, "sclk_spi1_48", "clk48m", SCLK_GATE, 23),
> +       GATE_SCLK(SCLK_SPI0_48, "sclk_spi0_48", "clk48m", SCLK_GATE, 22),
> +       GATE_SCLK(SCLK_SPI1, "sclk_spi1", "dout_spi1", SCLK_GATE, 21),
> +       GATE_SCLK(SCLK_SPI0, "sclk_spi0", "dout_spi0", SCLK_GATE, 20),
> +       GATE_SCLK(SCLK_DAC27, "sclk_dac27", "mout_dac27", SCLK_GATE, 19),
> +       GATE_SCLK(SCLK_TV27, "sclk_tv27", "mout_tv27", SCLK_GATE, 18),
> +       GATE_SCLK(SCLK_SCALER27, "sclk_scaler27", "clk27m", SCLK_GATE, 17),
> +       GATE_SCLK(SCLK_SCALER, "sclk_scaler", "dout_scaler", SCLK_GATE, 16),
> +       GATE_SCLK(SCLK_LCD27, "sclk_lcd27", "clk27m", SCLK_GATE, 15),
> +       GATE_SCLK(SCLK_LCD, "sclk_lcd", "dout_lcd", SCLK_GATE, 14),
> +       GATE_SCLK(SCLK_POST0_27, "sclk_post0_27", "clk27m", SCLK_GATE, 12),
> +       GATE_SCLK(SCLK_POST0, "sclk_post0", "dout_lcd", SCLK_GATE, 10),
> +       GATE_SCLK(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", SCLK_GATE, 9),
> +       GATE_SCLK(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", SCLK_GATE, 8),
> +       GATE_SCLK(SCLK_SECUR, "sclk_secur", "dout_secur", SCLK_GATE, 7),
> +       GATE_SCLK(SCLK_IRDA, "sclk_irda", "dout_irda", SCLK_GATE, 6),
> +       GATE_SCLK(SCLK_UART, "sclk_uart", "dout_uart", SCLK_GATE, 5),
> +       GATE_SCLK(SCLK_MFC, "sclk_mfc", "dout_mfc", SCLK_GATE, 3),
> +       GATE_SCLK(SCLK_CAM, "sclk_cam", "dout_cam", SCLK_GATE, 2),
> +       GATE_SCLK(SCLK_JPEG, "sclk_jpeg", "dout_jpeg", SCLK_GATE, 1),
> +};
> +
> +/* List of clock gates present on S3C6400. */
> +GATE_CLOCKS(s3c6400_gate_clks) __initdata = {
> +       GATE_ON(HCLK_DDR0, "hclk_ddr0", "hclk", HCLK_GATE, 23),
> +       GATE_SCLK(SCLK_ONENAND, "sclk_onenand", "parent", SCLK_GATE, 4),
> +};
> +
> +/* List of clock gates present on S3C6410. */
> +GATE_CLOCKS(s3c6410_gate_clks) __initdata = {
> +       GATE_BUS(HCLK_3DSE, "hclk_3dse", "hclk", HCLK_GATE, 31),
> +       GATE_ON(HCLK_IROM, "hclk_irom", "hclk", HCLK_GATE, 25),
> +       GATE_ON(HCLK_MEM1, "hclk_mem1", "hclk", HCLK_GATE, 22),
> +       GATE_ON(HCLK_MEM0, "hclk_mem0", "hclk", HCLK_GATE, 21),
> +       GATE_BUS(HCLK_MFC, "hclk_mfc", "hclk", HCLK_GATE, 0),
> +       GATE_BUS(PCLK_IIC1, "pclk_iic1", "pclk", PCLK_GATE, 27),
> +       GATE_BUS(PCLK_IIS2, "pclk_iis2", "pclk", PCLK_GATE, 26),
> +       GATE_SCLK(SCLK_FIMC, "sclk_fimc", "dout_fimc", SCLK_GATE, 13),
> +       GATE_SCLK(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", SCLK_GATE, 11),
> +       GATE_BUS(MEM0_CFCON, "mem0_cfcon", "hclk_mem0", MEM0_GATE, 5),
> +       GATE_BUS(MEM0_ONENAND1, "mem0_onenand1", "hclk_mem0", MEM0_GATE, 4),
> +       GATE_BUS(MEM0_ONENAND0, "mem0_onenand0", "hclk_mem0", MEM0_GATE, 3),
> +       GATE_BUS(MEM0_NFCON, "mem0_nfcon", "hclk_mem0", MEM0_GATE, 2),
> +       GATE_ON(MEM0_SROM, "mem0_srom", "hclk_mem0", MEM0_GATE, 1),
> +};
> +
> +/* Aliases for common s3c64xx clocks. */
> +static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
> +       ALIAS(MOUT_EPLL, NULL, "mout_epll"),
> +       ALIAS(DOUT_MPLL, NULL, "dout_mpll"),
> +       ALIAS(HCLKX2, NULL, "hclk2"),
> +       ALIAS(HCLK, NULL, "hclk"),
> +       ALIAS(PCLK, NULL, "pclk"),
> +       ALIAS(PCLK, NULL, "clk_uart_baud2"),
> +       ALIAS(ARMCLK, NULL, "armclk"),
> +       ALIAS(HCLK_UHOST, "s3c2410-ohci", "usb-host"),
> +       ALIAS(HCLK_USB, "s3c-hsotg", "otg"),
> +       ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "hsmmc"),
> +       ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "mmc_busclk.0"),
> +       ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
> +       ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
> +       ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
> +       ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
> +       ALIAS(HCLK_DMA1, NULL, "dma1"),
> +       ALIAS(HCLK_DMA0, NULL, "dma0"),
> +       ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
> +       ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
> +       ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
> +       ALIAS(PCLK_SPI0, "s3c6410-spi.0", "spi"),
> +       ALIAS(PCLK_IIC0, "s3c2440-i2c.0", "i2c"),
> +       ALIAS(PCLK_IIS1, "samsung-i2s.1", "iis"),
> +       ALIAS(PCLK_IIS0, "samsung-i2s.0", "iis"),
> +       ALIAS(PCLK_AC97, "samsung-ac97", "ac97"),
> +       ALIAS(PCLK_TSADC, "s3c64xx-adc", "adc"),
> +       ALIAS(PCLK_KEYPAD, "samsung-keypad", "keypad"),
> +       ALIAS(PCLK_PCM1, "samsung-pcm.1", "pcm"),
> +       ALIAS(PCLK_PCM0, "samsung-pcm.0", "pcm"),
> +       ALIAS(PCLK_PWM, NULL, "timers"),
> +       ALIAS(PCLK_RTC, "s3c64xx-rtc", "rtc"),
> +       ALIAS(PCLK_WDT, NULL, "watchdog"),
> +       ALIAS(PCLK_UART3, "s3c6400-uart.3", "uart"),
> +       ALIAS(PCLK_UART2, "s3c6400-uart.2", "uart"),
> +       ALIAS(PCLK_UART1, "s3c6400-uart.1", "uart"),
> +       ALIAS(PCLK_UART0, "s3c6400-uart.0", "uart"),
> +       ALIAS(SCLK_UHOST, "s3c2410-ohci", "usb-bus-host"),
> +       ALIAS(SCLK_MMC2, "s3c-sdhci.2", "mmc_busclk.2"),
> +       ALIAS(SCLK_MMC1, "s3c-sdhci.1", "mmc_busclk.2"),
> +       ALIAS(SCLK_MMC0, "s3c-sdhci.0", "mmc_busclk.2"),
> +       ALIAS(SCLK_SPI1, "s3c6410-spi.1", "spi-bus"),
> +       ALIAS(SCLK_SPI0, "s3c6410-spi.0", "spi-bus"),
> +       ALIAS(SCLK_AUDIO1, "samsung-pcm.1", "audio-bus"),
> +       ALIAS(SCLK_AUDIO1, "samsung-i2s.1", "audio-bus"),
> +       ALIAS(SCLK_AUDIO0, "samsung-pcm.0", "audio-bus"),
> +       ALIAS(SCLK_AUDIO0, "samsung-i2s.0", "audio-bus"),
> +       ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
> +       ALIAS(SCLK_CAM, "s3c-camif", "camera"),
> +};
> +
> +/* Aliases for s3c6400-specific clocks. */
> +static struct samsung_clock_alias s3c6400_clock_aliases[] = {
> +       /* Nothing to place here yet. */
> +};
> +
> +/* Aliases for s3c6410-specific clocks. */
> +static struct samsung_clock_alias s3c6410_clock_aliases[] = {
> +       ALIAS(PCLK_IIC1, "s3c2440-i2c.1", "i2c"),
> +       ALIAS(PCLK_IIS2, "samsung-i2s.2", "iis"),
> +       ALIAS(SCLK_FIMC, "s3c-camif", "fimc"),
> +       ALIAS(SCLK_AUDIO2, "samsung-i2s.2", "audio-bus"),
> +       ALIAS(MEM0_SROM, NULL, "srom"),
> +};
> +
> +/*
> + * Parent of the hclkx2 clock depends on whether the SoC is operating in
> + * synchronous or asynchronous mode. Depending on value of OTHERS[6]
> + * (SYNCMUXSEL) bit, it can be either mout_mpll or mout_apll.
> + */
> +static void __init s3c64xx_clk_register_hclkx2(void __iomem *reg_base)
> +{
> +       struct samsung_div_clock hclkx2;
> +       u32 others;
> +
> +       memset(&hclkx2, 0, sizeof(hclkx2));
> +
> +       hclkx2.id = HCLKX2;
> +       hclkx2.name = "hclkx2";
> +       hclkx2.offset = CLK_DIV0;
> +       hclkx2.shift = 9;
> +       hclkx2.width = 3;
> +
> +       others = readl(reg_base + OTHERS);
> +       if (others & OTHERS_SYNCMUXSEL)
> +               hclkx2.parent_name = "mout_apll";
> +       else
> +               hclkx2.parent_name = "mout_mpll";
> +
> +       samsung_clk_register_div(&hclkx2, 1);
> +}
> +
> +static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f,
> +                                                       unsigned long xusbxti_f)
> +{
> +       s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f;
> +       s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
> +       samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks,
> +                               ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks));
> +}
> +
> +static __initdata struct of_device_id ext_clk_match[] = {
> +       { .compatible = "samsung,clock-fin-pll", .data = (void *)0, },
> +       { .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
> +       {},
> +};
> +
> +/* Register s3c64xx clocks. */
> +void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
> +               unsigned long xusbxti_f, bool is_s3c6400, void __iomem *reg_base)
> +{
> +       struct clk *clk;
> +       unsigned long *soc_regs = NULL;
> +       unsigned long nr_soc_regs = 0;
> +
> +       if (np) {
> +               reg_base = of_iomap(np, 0);
> +               if (!reg_base)
> +                       panic("%s: failed to map registers\n", __func__);
> +       }
> +
> +       if (!is_s3c6400) {
> +               soc_regs = s3c6410_clk_regs;
> +               nr_soc_regs = ARRAY_SIZE(s3c6410_clk_regs);
> +       }
> +
> +       samsung_clk_init(np, reg_base, NR_CLKS, s3c64xx_clk_regs,
> +                       ARRAY_SIZE(s3c64xx_clk_regs), soc_regs, nr_soc_regs);
> +
> +       /* Register external clocks. */
> +       if (np)
> +               samsung_clk_of_register_fixed_ext(s3c64xx_fixed_rate_ext_clks,
> +                       ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks),
> +                       ext_clk_match);
> +       else
> +               s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f);
> +
> +       /* Register PLLs. */
> +       clk = samsung_clk_register_pll6552("fout_apll",
> +                                       "fin_pll", reg_base + APLL_LOCK);
> +       samsung_clk_add_lookup(clk, FOUT_APLL);
> +
> +       clk = samsung_clk_register_pll6552("fout_mpll",
> +                                       "fin_pll", reg_base + MPLL_LOCK);
> +       samsung_clk_add_lookup(clk, FOUT_MPLL);
> +
> +       clk = samsung_clk_register_pll6553("fout_epll",
> +                                       "fin_pll", reg_base + EPLL_LOCK);
> +       samsung_clk_add_lookup(clk, FOUT_EPLL);
> +
> +       /* Register common internal clocks. */
> +       s3c64xx_clk_register_hclkx2(reg_base);
> +
> +       samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks,
> +                                       ARRAY_SIZE(s3c64xx_fixed_rate_clks));
> +       samsung_clk_register_mux(s3c64xx_mux_clks,
> +                                       ARRAY_SIZE(s3c64xx_mux_clks));
> +       samsung_clk_register_div(s3c64xx_div_clks,
> +                                       ARRAY_SIZE(s3c64xx_div_clks));
> +       samsung_clk_register_gate(s3c64xx_gate_clks,
> +                                       ARRAY_SIZE(s3c64xx_gate_clks));
> +
> +       /* Register SoC-specific clocks. */
> +       if (is_s3c6400) {
> +               samsung_clk_register_mux(s3c6400_mux_clks,
> +                                       ARRAY_SIZE(s3c6400_mux_clks));
> +               samsung_clk_register_div(s3c6400_div_clks,
> +                                       ARRAY_SIZE(s3c6400_div_clks));
> +               samsung_clk_register_gate(s3c6400_gate_clks,
> +                                       ARRAY_SIZE(s3c6400_gate_clks));
> +               samsung_clk_register_alias(s3c6400_clock_aliases,
> +                                       ARRAY_SIZE(s3c6400_clock_aliases));
> +       } else {
> +               samsung_clk_register_mux(s3c6410_mux_clks,
> +                                       ARRAY_SIZE(s3c6410_mux_clks));
> +               samsung_clk_register_div(s3c6410_div_clks,
> +                                       ARRAY_SIZE(s3c6410_div_clks));
> +               samsung_clk_register_gate(s3c6410_gate_clks,
> +                                       ARRAY_SIZE(s3c6410_gate_clks));
> +               samsung_clk_register_alias(s3c6410_clock_aliases,
> +                                       ARRAY_SIZE(s3c6410_clock_aliases));
> +       }
> +
> +       samsung_clk_register_alias(s3c64xx_clock_aliases,
> +                                       ARRAY_SIZE(s3c64xx_clock_aliases));
> +
> +       pr_info("%s clocks: apll = %lu, mpll = %lu\n"
> +               "    epll = %lu, arm_clk = %lu\n",
> +               is_s3c6400 ? "S3C6400" : "S3C6410",
> +               _get_rate("fout_apll"), _get_rate("fout_mpll"),
> +               _get_rate("fout_epll"), _get_rate("armclk"));
> +}
> +
> +static void __init s3c6400_clk_init(struct device_node *np)
> +{
> +       s3c64xx_clk_init(np, 0, 0, true, NULL);
> +}
> +CLK_OF_DECLARE(s3c6400_clk, "samsung,s3c6400-clock", s3c6400_clk_init);
> +
> +static void __init s3c6410_clk_init(struct device_node *np)
> +{
> +       s3c64xx_clk_init(np, 0, 0, false, NULL);
> +}
> +CLK_OF_DECLARE(s3c6410_clk, "samsung,s3c6410-clock", s3c6410_clk_init);
> diff --git a/include/dt-bindings/clock/samsung,s3c64xx-clock.h b/include/dt-bindings/clock/samsung,s3c64xx-clock.h
> new file mode 100644
> index 0000000..3e9a1f9
> --- /dev/null
> +++ b/include/dt-bindings/clock/samsung,s3c64xx-clock.h
> @@ -0,0 +1,144 @@
> +/*
> + * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.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.
> + *
> + * Device Tree binding constants for Samsung S3C64xx clock controller.
> +*/
> +
> +#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
> +#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
> +
> +/*
> + * Let each exported clock get a unique index, which is used on DT-enabled
> + * platforms to lookup the clock from a clock specifier. These indices are
> + * therefore considered an ABI and so must not be changed. This implies
> + * that new clocks should be added either in free spaces between clock groups
> + * or at the end.
> + */
> +
> +/* Core clocks. */
> +#define IISCDCLK0              3
> +#define PCMCDCLK0              4
> +#define IISCDCLK1              5
> +#define PCMCDCLK1              6
> +#define IISCDCLK2              7
> +#define CLK27M                 8
> +#define CLK48M                 9
> +#define FIN_PLL                        10
> +#define FOUT_APLL              11
> +#define FOUT_MPLL              12
> +#define FOUT_EPLL              13
> +#define ARMCLK                 14
> +#define HCLKX2                 15
> +#define HCLK                   16
> +#define PCLK                   17
> +#define MOUT_EPLL              18
> +#define DOUT_MPLL              19
> +
> +/* HCLK bus clocks. */
> +#define HCLK_3DSE              32
> +#define HCLK_UHOST             33
> +#define HCLK_SECUR             34
> +#define HCLK_SDMA1             35
> +#define HCLK_SDMA0             36
> +#define HCLK_IROM              37
> +#define HCLK_DDR1              38
> +#define HCLK_MEM1              39
> +#define HCLK_MEM0              40
> +#define HCLK_USB               41
> +#define HCLK_HSMMC2            42
> +#define HCLK_HSMMC1            43
> +#define HCLK_HSMMC0            44
> +#define HCLK_MDP               45
> +#define HCLK_DHOST             46
> +#define HCLK_IHOST             47
> +#define HCLK_DMA1              48
> +#define HCLK_DMA0              49
> +#define HCLK_JPEG              50
> +#define HCLK_CAMIF             51
> +#define HCLK_SCALER            52
> +#define HCLK_2D                        53
> +#define HCLK_TV                        54
> +#define HCLK_POST0             55
> +#define HCLK_ROT               56
> +#define HCLK_LCD               57
> +#define HCLK_TZIC              58
> +#define HCLK_INTC              59
> +#define HCLK_MFC               60
> +#define HCLK_DDR0              61
> +
> +/* PCLK bus clocks. */
> +#define PCLK_IIC1              64
> +#define PCLK_IIS2              65
> +#define PCLK_SKEY              66
> +#define PCLK_CHIPID            67
> +#define PCLK_SPI1              68
> +#define PCLK_SPI0              69
> +#define PCLK_HSIRX             70
> +#define PCLK_HSITX             71
> +#define PCLK_GPIO              72
> +#define PCLK_IIC0              73
> +#define PCLK_IIS1              74
> +#define PCLK_IIS0              75
> +#define PCLK_AC97              76
> +#define PCLK_TZPC              77
> +#define PCLK_TSADC             78
> +#define PCLK_KEYPAD            79
> +#define PCLK_IRDA              80
> +#define PCLK_PCM1              81
> +#define PCLK_PCM0              82
> +#define PCLK_PWM               83
> +#define PCLK_RTC               84
> +#define PCLK_WDT               85
> +#define PCLK_UART3             86
> +#define PCLK_UART2             87
> +#define PCLK_UART1             88
> +#define PCLK_UART0             89
> +#define PCLK_MFC               90
> +
> +/* Special clocks. */
> +#define SCLK_UHOST             96
> +#define SCLK_MMC2_48           97
> +#define SCLK_MMC1_48           98
> +#define SCLK_MMC0_48           99
> +#define SCLK_MMC2              100
> +#define SCLK_MMC1              101
> +#define SCLK_MMC0              102
> +#define SCLK_SPI1_48           103
> +#define SCLK_SPI0_48           104
> +#define SCLK_SPI1              105
> +#define SCLK_SPI0              106
> +#define SCLK_DAC27             107
> +#define SCLK_TV27              108
> +#define SCLK_SCALER27          109
> +#define SCLK_SCALER            110
> +#define SCLK_LCD27             111
> +#define SCLK_LCD               112
> +#define SCLK_FIMC              113
> +#define SCLK_POST0_27          114
> +#define SCLK_AUDIO2            115
> +#define SCLK_POST0             116
> +#define SCLK_AUDIO1            117
> +#define SCLK_AUDIO0            118
> +#define SCLK_SECUR             119
> +#define SCLK_IRDA              120
> +#define SCLK_UART              121
> +#define SCLK_MFC               122
> +#define SCLK_CAM               123
> +#define SCLK_JPEG              124
> +#define SCLK_ONENAND           125
> +
> +/* MEM0 bus clocks - S3C6410-specific. */
> +#define MEM0_CFCON             128
> +#define MEM0_ONENAND1          129
> +#define MEM0_ONENAND0          130
> +#define MEM0_NFCON             131
> +#define MEM0_SROM              132
> +
> +/* Total number of clocks. */
> +#define NR_CLKS                        (MEM0_SROM + 1)
> +
> +#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H */
> -- 
> 1.8.2.1
Tomasz Figa June 12, 2013, 6:26 a.m. UTC | #2
Hi Mike,

On Tuesday 11 of June 2013 19:54:51 Mike Turquette wrote:
> Quoting Tomasz Figa (2013-06-05 16:57:26)
> 
> > This patch adds new, Common Clock Framework-based clock driver for
> > Samsung S3C64xx SoCs. The driver is just added, without actually
> > letting the platforms use it yet, since this requires more
> > intermediate steps.
> It seems like there is an awful lot of clock data here that exists
> alongside the stuff in DT.  Is this how you plan to keep things going
> forward or is this conversion just an intermediate step?

Current S3C64xx support contains a lot of boards, for which I don't see 
any chance for DT conversion in any time soon, so the driver must cover 
both DT and non-DT cases. (Not even saying that DT support for S3C64xx is 
not yet submitted, as I want to get all the dependencies merged, or at 
least acked, first.)

Also, personally, I don't see anything wrong with having those clocks 
defined in the driver. The binding specifies the exact mapping between 
clock IDs inside the clock provider and hardware clocks and not all clocks 
need to be exported (most of muxes and divs don't need to), so I find it 
more reasonable to define them in the driver instead.

Another thing is that it's unlikely for any new SoC from S3C64xx series to 
show up, so basically the clock list is fixed.

Best regards,
Tomasz

> Regards,
> Mike
> 
> > Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
> > ---
> > 
> >  .../bindings/clock/samsung,s3c64xx-clock.txt       |  48 ++
> >  drivers/clk/samsung/Makefile                       |   3 +
> >  drivers/clk/samsung/clk-s3c64xx.c                  | 503
> >  +++++++++++++++++++++
> >  include/dt-bindings/clock/samsung,s3c64xx-clock.h  | 144 ++++++ 4
> >  files changed, 698 insertions(+)
> >  create mode 100644
> >  Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
> >  create mode 100644 drivers/clk/samsung/clk-s3c64xx.c
> >  create mode 100644 include/dt-bindings/clock/samsung,s3c64xx-clock.h
> > 
> > diff --git
> > a/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
> > b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
> > new file mode 100644
> > index 0000000..278ab6e
> > --- /dev/null
> > +++
> > b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
> > @@ -0,0 +1,48 @@
> > +* Samsung S3C64xx Clock Controller
> > +
> > +The S3C64xx clock controller generates and supplies clock to various
> > controllers +within the SoC. The clock binding described here is
> > applicable to all SoCs in +the S3C64xx family.
> > +
> > +Required Properties:
> > +
> > +- comptible: should be one of the following.
> > +  - "samsung,s3c6400-clock" - controller compatible with S3C6400 SoC.
> > +  - "samsung,s3c6410-clock" - controller compatible with S3C6410 SoC.
> > +
> > +- reg: physical base address of the controller and length of memory
> > mapped +  region.
> > +
> > +- #clock-cells: should be 1.
> > +
> > +Each clock is assigned an identifier and client nodes can use this
> > identifier +to specify the clock which they consume. Some of the
> > clocks are available only +on a particular S3C64xx SoC and this is
> > specified where applicable. +
> > +All available clocks are defined as preprocessor macros in
> > +dt-bindings/clock/samsung,s3c64xx-clock.h header and can be used in
> > device +tree sources.
> > +
> > +Example: Clock controller node:
> > +
> > +       clocks: clock-controller@7e00f000 {
> > +               compatible = "samsung,s3c6410-clock";
> > +               reg = <0x7e00f000 0x1000>;
> > +               #clock-cells = <1>;
> > +       };
> > +
> > +Example: 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" properties):
> > +
> > +               uart0: serial@7f005000 {
> > +                       compatible = "samsung,s3c6400-uart";
> > +                       reg = <0x7f005000 0x100>;
> > +                       interrupt-parent = <&vic1>;
> > +                       interrupts = <5>;
> > +                       clock-names = "uart", "clk_uart_baud2",
> > +                                       "clk_uart_baud3";
> > +                       clocks = <&clocks PCLK_UART0>, <&clocks
> > PCLK_UART0>, +                                       <&clocks
> > SCLK_UART>;
> > +                       status = "disabled";
> > +               };
> > diff --git a/drivers/clk/samsung/Makefile
> > b/drivers/clk/samsung/Makefile index b7c232e..c023474 100644
> > --- a/drivers/clk/samsung/Makefile
> > +++ b/drivers/clk/samsung/Makefile
> > @@ -6,3 +6,6 @@ obj-$(CONFIG_COMMON_CLK)        += clk.o clk-pll.o
> > 
> >  obj-$(CONFIG_ARCH_EXYNOS4)     += clk-exynos4.o
> >  obj-$(CONFIG_SOC_EXYNOS5250)   += clk-exynos5250.o
> >  obj-$(CONFIG_SOC_EXYNOS5440)   += clk-exynos5440.o
> > 
> > +ifdef CONFIG_COMMON_CLK
> > +obj-$(CONFIG_ARCH_S3C64XX)     += clk-s3c64xx.o
> > +endif
> > diff --git a/drivers/clk/samsung/clk-s3c64xx.c
> > b/drivers/clk/samsung/clk-s3c64xx.c new file mode 100644
> > index 0000000..253a972
> > --- /dev/null
> > +++ b/drivers/clk/samsung/clk-s3c64xx.c
> > @@ -0,0 +1,503 @@
> > +/*
> > + * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.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 S3C64xx SoCs.
> > +*/
> > +
> > +#include <linux/clk.h>
> > +#include <linux/clkdev.h>
> > +#include <linux/clk-provider.h>
> > +#include <linux/of.h>
> > +#include <linux/of_address.h>
> > +
> > +#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
> > +
> > +#include "clk.h"
> > +#include "clk-pll.h"
> > +
> > +/* S3C64xx clock controller register offsets. */
> > +#define APLL_LOCK              0x000
> > +#define MPLL_LOCK              0x004
> > +#define EPLL_LOCK              0x008
> > +#define APLL_CON               0x00c
> > +#define MPLL_CON               0x010
> > +#define EPLL_CON0              0x014
> > +#define EPLL_CON1              0x018
> > +#define CLK_SRC                        0x01c
> > +#define CLK_DIV0               0x020
> > +#define CLK_DIV1               0x024
> > +#define CLK_DIV2               0x028
> > +#define HCLK_GATE              0x030
> > +#define PCLK_GATE              0x034
> > +#define SCLK_GATE              0x038
> > +#define MEM0_GATE              0x03c
> > +#define CLK_SRC2               0x10c
> > +#define OTHERS                 0x900
> > +
> > +/* Special bitfields used in the driver. */
> > +#define OTHERS_SYNCMUXSEL      (1 << 6)
> > +
> > +/* Helper macros to define clock arrays. */
> > +#define FIXED_RATE_CLOCKS(name)        \
> > +               static struct samsung_fixed_rate_clock name[]
> > +#define MUX_CLOCKS(name)       \
> > +               static struct samsung_mux_clock name[]
> > +#define DIV_CLOCKS(name)       \
> > +               static struct samsung_div_clock name[]
> > +#define GATE_CLOCKS(name)      \
> > +               static struct samsung_gate_clock name[]
> > +
> > +/* Helper macros for gate types present on S3C64xx. */
> > +#define GATE_BUS(_id, cname, pname, o, b) \
> > +               GATE(_id, cname, pname, o, b, 0, 0)
> > +#define GATE_SCLK(_id, cname, pname, o, b) \
> > +               GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT, 0)
> > +#define GATE_ON(_id, cname, pname, o, b) \
> > +               GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0)
> > +
> > +/*
> > + * List of controller registers to be saved and restored during
> > + * a suspend/resume cycle.
> > + */
> > +static __initdata unsigned long s3c64xx_clk_regs[] = {
> > +       APLL_LOCK,
> > +       MPLL_LOCK,
> > +       EPLL_LOCK,
> > +       APLL_CON,
> > +       MPLL_CON,
> > +       EPLL_CON0,
> > +       EPLL_CON1,
> > +       CLK_SRC,
> > +       CLK_DIV0,
> > +       CLK_DIV1,
> > +       CLK_DIV2,
> > +       HCLK_GATE,
> > +       PCLK_GATE,
> > +       SCLK_GATE,
> > +};
> > +
> > +static __initdata unsigned long s3c6410_clk_regs[] = {
> > +       CLK_SRC2,
> > +       MEM0_GATE,
> > +};
> > +
> > +/* List of parent clocks common for all S3C64xx SoCs. */
> > +PNAME(spi_mmc_p)       = { "mout_epll", "dout_mpll", "fin_pll",
> > "clk27m" }; +PNAME(uart_p)          = { "mout_epll", "dout_mpll" };
> > +PNAME(audio0_p)                = { "mout_epll", "dout_mpll",
> > "fin_pll", "iiscdclk0", +                               "pcmcdclk0",
> > "none", "none", "none" }; +PNAME(audio1_p)                = {
> > "mout_epll", "dout_mpll", "fin_pll", "iiscdclk1", +                  
> >             "pcmcdclk0", "none", "none", "none" }; +PNAME(mfc_p)     
> >      = { "hclkx2", "mout_epll" };
> > +PNAME(apll_p)          = { "fin_pll", "fout_apll" };
> > +PNAME(mpll_p)          = { "fin_pll", "fout_mpll" };
> > +PNAME(epll_p)          = { "fin_pll", "fout_epll" };
> > +
> > +/* S3C6400-specific parent clocks. */
> > +PNAME(scaler_lcd_p6400)        = { "mout_epll", "dout_mpll", "none",
> > "none" }; +PNAME(irda_p6400)      = { "mout_epll", "dout_mpll",
> > "none", "clk48m" }; +PNAME(uhost_p6400)     = { "clk48m",
> > "mout_epll", "dout_mpll", "none" }; +
> > +/* S3C6410-specific parent clocks. */
> > +PNAME(clk27_p6410)     = { "clk27m", "fin_pll" };
> > +PNAME(scaler_lcd_p6410)        = { "mout_epll", "dout_mpll",
> > "fin_pll", "none" }; +PNAME(irda_p6410)      = { "mout_epll",
> > "dout_mpll", "fin_pll", "clk48m" }; +PNAME(uhost_p6410)     = {
> > "clk48m", "mout_epll", "dout_mpll", "fin_pll" }; +PNAME(audio2_p6410)
> >    = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk2", +           
> >                    "pcmcdclk1", "none", "none", "none" }; +
> > +/* Fixed rate clocks generated outside the SoC. */
> > +FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_ext_clks) __initdata = {
> > +       FRATE(FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0),
> > +       FRATE(0, "xusbxti", NULL, CLK_IS_ROOT, 0),
> > +};
> > +
> > +/* Fixed rate clocks generated inside the SoC. */
> > +FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_clks) __initdata = {
> > +       FRATE(CLK27M, "clk27m", NULL, CLK_IS_ROOT, 27000000),
> > +       FRATE(CLK48M, "clk48m", NULL, CLK_IS_ROOT, 48000000),
> > +};
> > +
> > +/* List of clock muxes present on all S3C64xx SoCs. */
> > +MUX_CLOCKS(s3c64xx_mux_clks) __initdata = {
> > +       MUX(0, "mout_apll", apll_p, CLK_SRC, 0, 1),
> > +       MUX(0, "mout_mpll", mpll_p, CLK_SRC, 1, 1),
> > +       MUX(MOUT_EPLL, "mout_epll", epll_p, CLK_SRC, 2, 1),
> > +       MUX(0, "mout_mfc", mfc_p, CLK_SRC, 4, 1),
> > +       MUX(0, "mout_audio0", audio0_p, CLK_SRC, 7, 3),
> > +       MUX(0, "mout_audio1", audio1_p, CLK_SRC, 10, 3),
> > +       MUX(0, "mout_uart", uart_p, CLK_SRC, 13, 1),
> > +       MUX(0, "mout_spi0", spi_mmc_p, CLK_SRC, 14, 2),
> > +       MUX(0, "mout_spi1", spi_mmc_p, CLK_SRC, 16, 2),
> > +       MUX(0, "mout_mmc0", spi_mmc_p, CLK_SRC, 18, 2),
> > +       MUX(0, "mout_mmc1", spi_mmc_p, CLK_SRC, 20, 2),
> > +       MUX(0, "mout_mmc2", spi_mmc_p, CLK_SRC, 22, 2),
> > +};
> > +
> > +/* List of clock muxes present on S3C6400. */
> > +MUX_CLOCKS(s3c6400_mux_clks) __initdata = {
> > +       MUX(0, "mout_uhost", uhost_p6400, CLK_SRC, 5, 2),
> > +       MUX(0, "mout_irda", irda_p6400, CLK_SRC, 24, 2),
> > +       MUX(0, "mout_lcd", scaler_lcd_p6400, CLK_SRC, 26, 2),
> > +       MUX(0, "mout_scaler", scaler_lcd_p6400, CLK_SRC, 28, 2),
> > +};
> > +
> > +/* List of clock muxes present on S3C6410. */
> > +MUX_CLOCKS(s3c6410_mux_clks) __initdata = {
> > +       MUX(0, "mout_uhost", uhost_p6410, CLK_SRC, 5, 2),
> > +       MUX(0, "mout_irda", irda_p6410, CLK_SRC, 24, 2),
> > +       MUX(0, "mout_lcd", scaler_lcd_p6410, CLK_SRC, 26, 2),
> > +       MUX(0, "mout_scaler", scaler_lcd_p6410, CLK_SRC, 28, 2),
> > +       MUX(0, "mout_dac27", clk27_p6410, CLK_SRC, 30, 1),
> > +       MUX(0, "mout_tv27", clk27_p6410, CLK_SRC, 31, 1),
> > +       MUX(0, "mout_audio2", audio2_p6410, CLK_SRC2, 0, 3),
> > +};
> > +
> > +/* List of clock dividers present on all S3C64xx SoCs. */
> > +DIV_CLOCKS(s3c64xx_div_clks) __initdata = {
> > +       DIV(DOUT_MPLL, "dout_mpll", "mout_mpll", CLK_DIV0, 4, 1),
> > +       DIV(HCLK, "hclk", "hclkx2", CLK_DIV0, 8, 1),
> > +       DIV(PCLK, "pclk", "hclkx2", CLK_DIV0, 12, 4),
> > +       DIV(0, "dout_secur", "hclkx2", CLK_DIV0, 18, 2),
> > +       DIV(0, "dout_cam", "hclkx2", CLK_DIV0, 20, 4),
> > +       DIV(0, "dout_jpeg", "hclkx2", CLK_DIV0, 24, 4),
> > +       DIV(0, "dout_mfc", "mout_mfc", CLK_DIV0, 28, 4),
> > +       DIV(0, "dout_mmc0", "mout_mmc0", CLK_DIV1, 0, 4),
> > +       DIV(0, "dout_mmc1", "mout_mmc1", CLK_DIV1, 4, 4),
> > +       DIV(0, "dout_mmc2", "mout_mmc2", CLK_DIV1, 8, 4),
> > +       DIV(0, "dout_lcd", "mout_lcd", CLK_DIV1, 12, 4),
> > +       DIV(0, "dout_scaler", "mout_scaler", CLK_DIV1, 16, 4),
> > +       DIV(0, "dout_uhost", "mout_uhost", CLK_DIV1, 20, 4),
> > +       DIV(0, "dout_spi0", "mout_spi0", CLK_DIV2, 0, 4),
> > +       DIV(0, "dout_spi1", "mout_spi1", CLK_DIV2, 4, 4),
> > +       DIV(0, "dout_audio0", "mout_audio0", CLK_DIV2, 8, 4),
> > +       DIV(0, "dout_audio1", "mout_audio1", CLK_DIV2, 12, 4),
> > +       DIV(0, "dout_uart", "mout_uart", CLK_DIV2, 16, 4),
> > +       DIV(0, "dout_irda", "mout_irda", CLK_DIV2, 20, 4),
> > +};
> > +
> > +/* List of clock dividers present on S3C6400. */
> > +DIV_CLOCKS(s3c6400_div_clks) __initdata = {
> > +       DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 3),
> > +};
> > +
> > +/* List of clock dividers present on S3C6410. */
> > +DIV_CLOCKS(s3c6410_div_clks) __initdata = {
> > +       DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 4),
> > +       DIV(0, "dout_fimc", "hclk", CLK_DIV1, 24, 4),
> > +       DIV(0, "dout_audio2", "mout_audio2", CLK_DIV2, 24, 4),
> > +};
> > +
> > +/* List of clock gates present on all S3C64xx SoCs. */
> > +GATE_CLOCKS(s3c64xx_gate_clks) __initdata = {
> > +       GATE_BUS(HCLK_UHOST, "hclk_uhost", "hclk", HCLK_GATE, 29),
> > +       GATE_BUS(HCLK_SECUR, "hclk_secur", "hclk", HCLK_GATE, 28),
> > +       GATE_BUS(HCLK_SDMA1, "hclk_sdma1", "hclk", HCLK_GATE, 27),
> > +       GATE_BUS(HCLK_SDMA0, "hclk_sdma0", "hclk", HCLK_GATE, 26),
> > +       GATE_ON(HCLK_DDR1, "hclk_ddr1", "hclk", HCLK_GATE, 24),
> > +       GATE_BUS(HCLK_USB, "hclk_usb", "hclk", HCLK_GATE, 20),
> > +       GATE_BUS(HCLK_HSMMC2, "hclk_hsmmc2", "hclk", HCLK_GATE, 19),
> > +       GATE_BUS(HCLK_HSMMC1, "hclk_hsmmc1", "hclk", HCLK_GATE, 18),
> > +       GATE_BUS(HCLK_HSMMC0, "hclk_hsmmc0", "hclk", HCLK_GATE, 17),
> > +       GATE_BUS(HCLK_MDP, "hclk_mdp", "hclk", HCLK_GATE, 16),
> > +       GATE_BUS(HCLK_DHOST, "hclk_dhost", "hclk", HCLK_GATE, 15),
> > +       GATE_BUS(HCLK_IHOST, "hclk_ihost", "hclk", HCLK_GATE, 14),
> > +       GATE_BUS(HCLK_DMA1, "hclk_dma1", "hclk", HCLK_GATE, 13),
> > +       GATE_BUS(HCLK_DMA0, "hclk_dma0", "hclk", HCLK_GATE, 12),
> > +       GATE_BUS(HCLK_JPEG, "hclk_jpeg", "hclk", HCLK_GATE, 11),
> > +       GATE_BUS(HCLK_CAMIF, "hclk_camif", "hclk", HCLK_GATE, 10),
> > +       GATE_BUS(HCLK_SCALER, "hclk_scaler", "hclk", HCLK_GATE, 9),
> > +       GATE_BUS(HCLK_2D, "hclk_2d", "hclk", HCLK_GATE, 8),
> > +       GATE_BUS(HCLK_TV, "hclk_tv", "hclk", HCLK_GATE, 7),
> > +       GATE_BUS(HCLK_POST0, "hclk_post0", "hclk", HCLK_GATE, 5),
> > +       GATE_BUS(HCLK_ROT, "hclk_rot", "hclk", HCLK_GATE, 4),
> > +       GATE_BUS(HCLK_LCD, "hclk_lcd", "hclk", HCLK_GATE, 3),
> > +       GATE_BUS(HCLK_TZIC, "hclk_tzic", "hclk", HCLK_GATE, 2),
> > +       GATE_ON(HCLK_INTC, "hclk_intc", "hclk", HCLK_GATE, 1),
> > +       GATE_ON(PCLK_SKEY, "pclk_skey", "pclk", PCLK_GATE, 24),
> > +       GATE_ON(PCLK_CHIPID, "pclk_chipid", "pclk", PCLK_GATE, 23),
> > +       GATE_BUS(PCLK_SPI1, "pclk_spi1", "pclk", PCLK_GATE, 22),
> > +       GATE_BUS(PCLK_SPI0, "pclk_spi0", "pclk", PCLK_GATE, 21),
> > +       GATE_BUS(PCLK_HSIRX, "pclk_hsirx", "pclk", PCLK_GATE, 20),
> > +       GATE_BUS(PCLK_HSITX, "pclk_hsitx", "pclk", PCLK_GATE, 19),
> > +       GATE_ON(PCLK_GPIO, "pclk_gpio", "pclk", PCLK_GATE, 18),
> > +       GATE_BUS(PCLK_IIC0, "pclk_iic0", "pclk", PCLK_GATE, 17),
> > +       GATE_BUS(PCLK_IIS1, "pclk_iis1", "pclk", PCLK_GATE, 16),
> > +       GATE_BUS(PCLK_IIS0, "pclk_iis0", "pclk", PCLK_GATE, 15),
> > +       GATE_BUS(PCLK_AC97, "pclk_ac97", "pclk", PCLK_GATE, 14),
> > +       GATE_BUS(PCLK_TZPC, "pclk_tzpc", "pclk", PCLK_GATE, 13),
> > +       GATE_BUS(PCLK_TSADC, "pclk_tsadc", "pclk", PCLK_GATE, 12),
> > +       GATE_BUS(PCLK_KEYPAD, "pclk_keypad", "pclk", PCLK_GATE, 11),
> > +       GATE_BUS(PCLK_IRDA, "pclk_irda", "pclk", PCLK_GATE, 10),
> > +       GATE_BUS(PCLK_PCM1, "pclk_pcm1", "pclk", PCLK_GATE, 9),
> > +       GATE_BUS(PCLK_PCM0, "pclk_pcm0", "pclk", PCLK_GATE, 8),
> > +       GATE_BUS(PCLK_PWM, "pclk_pwm", "pclk", PCLK_GATE, 7),
> > +       GATE_BUS(PCLK_RTC, "pclk_rtc", "pclk", PCLK_GATE, 6),
> > +       GATE_BUS(PCLK_WDT, "pclk_wdt", "pclk", PCLK_GATE, 5),
> > +       GATE_BUS(PCLK_UART3, "pclk_uart3", "pclk", PCLK_GATE, 4),
> > +       GATE_BUS(PCLK_UART2, "pclk_uart2", "pclk", PCLK_GATE, 3),
> > +       GATE_BUS(PCLK_UART1, "pclk_uart1", "pclk", PCLK_GATE, 2),
> > +       GATE_BUS(PCLK_UART0, "pclk_uart0", "pclk", PCLK_GATE, 1),
> > +       GATE_BUS(PCLK_MFC, "pclk_mfc", "pclk", PCLK_GATE, 0),
> > +       GATE_SCLK(SCLK_UHOST, "sclk_uhost", "dout_uhost", SCLK_GATE,
> > 30), +       GATE_SCLK(SCLK_MMC2_48, "sclk_mmc2_48", "clk48m",
> > SCLK_GATE, 29), +       GATE_SCLK(SCLK_MMC1_48, "sclk_mmc1_48",
> > "clk48m", SCLK_GATE, 28), +       GATE_SCLK(SCLK_MMC0_48,
> > "sclk_mmc0_48", "clk48m", SCLK_GATE, 27), +      
> > GATE_SCLK(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", SCLK_GATE, 26), +     
> >  GATE_SCLK(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", SCLK_GATE, 25), +    
> >   GATE_SCLK(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", SCLK_GATE, 24), +   
> >    GATE_SCLK(SCLK_SPI1_48, "sclk_spi1_48", "clk48m", SCLK_GATE, 23),
> > +       GATE_SCLK(SCLK_SPI0_48, "sclk_spi0_48", "clk48m", SCLK_GATE,
> > 22), +       GATE_SCLK(SCLK_SPI1, "sclk_spi1", "dout_spi1",
> > SCLK_GATE, 21), +       GATE_SCLK(SCLK_SPI0, "sclk_spi0",
> > "dout_spi0", SCLK_GATE, 20), +       GATE_SCLK(SCLK_DAC27,
> > "sclk_dac27", "mout_dac27", SCLK_GATE, 19), +      
> > GATE_SCLK(SCLK_TV27, "sclk_tv27", "mout_tv27", SCLK_GATE, 18), +     
> >  GATE_SCLK(SCLK_SCALER27, "sclk_scaler27", "clk27m", SCLK_GATE, 17),
> > +       GATE_SCLK(SCLK_SCALER, "sclk_scaler", "dout_scaler",
> > SCLK_GATE, 16), +       GATE_SCLK(SCLK_LCD27, "sclk_lcd27", "clk27m",
> > SCLK_GATE, 15), +       GATE_SCLK(SCLK_LCD, "sclk_lcd", "dout_lcd",
> > SCLK_GATE, 14), +       GATE_SCLK(SCLK_POST0_27, "sclk_post0_27",
> > "clk27m", SCLK_GATE, 12), +       GATE_SCLK(SCLK_POST0, "sclk_post0",
> > "dout_lcd", SCLK_GATE, 10), +       GATE_SCLK(SCLK_AUDIO1,
> > "sclk_audio1", "dout_audio1", SCLK_GATE, 9), +      
> > GATE_SCLK(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", SCLK_GATE, 8), +
> >       GATE_SCLK(SCLK_SECUR, "sclk_secur", "dout_secur", SCLK_GATE,
> > 7), +       GATE_SCLK(SCLK_IRDA, "sclk_irda", "dout_irda", SCLK_GATE,
> > 6), +       GATE_SCLK(SCLK_UART, "sclk_uart", "dout_uart", SCLK_GATE,
> > 5), +       GATE_SCLK(SCLK_MFC, "sclk_mfc", "dout_mfc", SCLK_GATE,
> > 3), +       GATE_SCLK(SCLK_CAM, "sclk_cam", "dout_cam", SCLK_GATE,
> > 2), +       GATE_SCLK(SCLK_JPEG, "sclk_jpeg", "dout_jpeg", SCLK_GATE,
> > 1), +};
> > +
> > +/* List of clock gates present on S3C6400. */
> > +GATE_CLOCKS(s3c6400_gate_clks) __initdata = {
> > +       GATE_ON(HCLK_DDR0, "hclk_ddr0", "hclk", HCLK_GATE, 23),
> > +       GATE_SCLK(SCLK_ONENAND, "sclk_onenand", "parent", SCLK_GATE,
> > 4), +};
> > +
> > +/* List of clock gates present on S3C6410. */
> > +GATE_CLOCKS(s3c6410_gate_clks) __initdata = {
> > +       GATE_BUS(HCLK_3DSE, "hclk_3dse", "hclk", HCLK_GATE, 31),
> > +       GATE_ON(HCLK_IROM, "hclk_irom", "hclk", HCLK_GATE, 25),
> > +       GATE_ON(HCLK_MEM1, "hclk_mem1", "hclk", HCLK_GATE, 22),
> > +       GATE_ON(HCLK_MEM0, "hclk_mem0", "hclk", HCLK_GATE, 21),
> > +       GATE_BUS(HCLK_MFC, "hclk_mfc", "hclk", HCLK_GATE, 0),
> > +       GATE_BUS(PCLK_IIC1, "pclk_iic1", "pclk", PCLK_GATE, 27),
> > +       GATE_BUS(PCLK_IIS2, "pclk_iis2", "pclk", PCLK_GATE, 26),
> > +       GATE_SCLK(SCLK_FIMC, "sclk_fimc", "dout_fimc", SCLK_GATE, 13),
> > +       GATE_SCLK(SCLK_AUDIO2, "sclk_audio2", "dout_audio2",
> > SCLK_GATE, 11), +       GATE_BUS(MEM0_CFCON, "mem0_cfcon",
> > "hclk_mem0", MEM0_GATE, 5), +       GATE_BUS(MEM0_ONENAND1,
> > "mem0_onenand1", "hclk_mem0", MEM0_GATE, 4), +      
> > GATE_BUS(MEM0_ONENAND0, "mem0_onenand0", "hclk_mem0", MEM0_GATE, 3),
> > +       GATE_BUS(MEM0_NFCON, "mem0_nfcon", "hclk_mem0", MEM0_GATE,
> > 2), +       GATE_ON(MEM0_SROM, "mem0_srom", "hclk_mem0", MEM0_GATE,
> > 1), +};
> > +
> > +/* Aliases for common s3c64xx clocks. */
> > +static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
> > +       ALIAS(MOUT_EPLL, NULL, "mout_epll"),
> > +       ALIAS(DOUT_MPLL, NULL, "dout_mpll"),
> > +       ALIAS(HCLKX2, NULL, "hclk2"),
> > +       ALIAS(HCLK, NULL, "hclk"),
> > +       ALIAS(PCLK, NULL, "pclk"),
> > +       ALIAS(PCLK, NULL, "clk_uart_baud2"),
> > +       ALIAS(ARMCLK, NULL, "armclk"),
> > +       ALIAS(HCLK_UHOST, "s3c2410-ohci", "usb-host"),
> > +       ALIAS(HCLK_USB, "s3c-hsotg", "otg"),
> > +       ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "hsmmc"),
> > +       ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "mmc_busclk.0"),
> > +       ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
> > +       ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
> > +       ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
> > +       ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
> > +       ALIAS(HCLK_DMA1, NULL, "dma1"),
> > +       ALIAS(HCLK_DMA0, NULL, "dma0"),
> > +       ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
> > +       ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
> > +       ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
> > +       ALIAS(PCLK_SPI0, "s3c6410-spi.0", "spi"),
> > +       ALIAS(PCLK_IIC0, "s3c2440-i2c.0", "i2c"),
> > +       ALIAS(PCLK_IIS1, "samsung-i2s.1", "iis"),
> > +       ALIAS(PCLK_IIS0, "samsung-i2s.0", "iis"),
> > +       ALIAS(PCLK_AC97, "samsung-ac97", "ac97"),
> > +       ALIAS(PCLK_TSADC, "s3c64xx-adc", "adc"),
> > +       ALIAS(PCLK_KEYPAD, "samsung-keypad", "keypad"),
> > +       ALIAS(PCLK_PCM1, "samsung-pcm.1", "pcm"),
> > +       ALIAS(PCLK_PCM0, "samsung-pcm.0", "pcm"),
> > +       ALIAS(PCLK_PWM, NULL, "timers"),
> > +       ALIAS(PCLK_RTC, "s3c64xx-rtc", "rtc"),
> > +       ALIAS(PCLK_WDT, NULL, "watchdog"),
> > +       ALIAS(PCLK_UART3, "s3c6400-uart.3", "uart"),
> > +       ALIAS(PCLK_UART2, "s3c6400-uart.2", "uart"),
> > +       ALIAS(PCLK_UART1, "s3c6400-uart.1", "uart"),
> > +       ALIAS(PCLK_UART0, "s3c6400-uart.0", "uart"),
> > +       ALIAS(SCLK_UHOST, "s3c2410-ohci", "usb-bus-host"),
> > +       ALIAS(SCLK_MMC2, "s3c-sdhci.2", "mmc_busclk.2"),
> > +       ALIAS(SCLK_MMC1, "s3c-sdhci.1", "mmc_busclk.2"),
> > +       ALIAS(SCLK_MMC0, "s3c-sdhci.0", "mmc_busclk.2"),
> > +       ALIAS(SCLK_SPI1, "s3c6410-spi.1", "spi-bus"),
> > +       ALIAS(SCLK_SPI0, "s3c6410-spi.0", "spi-bus"),
> > +       ALIAS(SCLK_AUDIO1, "samsung-pcm.1", "audio-bus"),
> > +       ALIAS(SCLK_AUDIO1, "samsung-i2s.1", "audio-bus"),
> > +       ALIAS(SCLK_AUDIO0, "samsung-pcm.0", "audio-bus"),
> > +       ALIAS(SCLK_AUDIO0, "samsung-i2s.0", "audio-bus"),
> > +       ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
> > +       ALIAS(SCLK_CAM, "s3c-camif", "camera"),
> > +};
> > +
> > +/* Aliases for s3c6400-specific clocks. */
> > +static struct samsung_clock_alias s3c6400_clock_aliases[] = {
> > +       /* Nothing to place here yet. */
> > +};
> > +
> > +/* Aliases for s3c6410-specific clocks. */
> > +static struct samsung_clock_alias s3c6410_clock_aliases[] = {
> > +       ALIAS(PCLK_IIC1, "s3c2440-i2c.1", "i2c"),
> > +       ALIAS(PCLK_IIS2, "samsung-i2s.2", "iis"),
> > +       ALIAS(SCLK_FIMC, "s3c-camif", "fimc"),
> > +       ALIAS(SCLK_AUDIO2, "samsung-i2s.2", "audio-bus"),
> > +       ALIAS(MEM0_SROM, NULL, "srom"),
> > +};
> > +
> > +/*
> > + * Parent of the hclkx2 clock depends on whether the SoC is operating
> > in + * synchronous or asynchronous mode. Depending on value of
> > OTHERS[6] + * (SYNCMUXSEL) bit, it can be either mout_mpll or
> > mout_apll. + */
> > +static void __init s3c64xx_clk_register_hclkx2(void __iomem
> > *reg_base)
> > +{
> > +       struct samsung_div_clock hclkx2;
> > +       u32 others;
> > +
> > +       memset(&hclkx2, 0, sizeof(hclkx2));
> > +
> > +       hclkx2.id = HCLKX2;
> > +       hclkx2.name = "hclkx2";
> > +       hclkx2.offset = CLK_DIV0;
> > +       hclkx2.shift = 9;
> > +       hclkx2.width = 3;
> > +
> > +       others = readl(reg_base + OTHERS);
> > +       if (others & OTHERS_SYNCMUXSEL)
> > +               hclkx2.parent_name = "mout_apll";
> > +       else
> > +               hclkx2.parent_name = "mout_mpll";
> > +
> > +       samsung_clk_register_div(&hclkx2, 1);
> > +}
> > +
> > +static void __init s3c64xx_clk_register_fixed_ext(unsigned long
> > fin_pll_f, +                                                      
> > unsigned long xusbxti_f) +{
> > +       s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f;
> > +       s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
> > +       samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks,
> > +                              
> > ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks)); +}
> > +
> > +static __initdata struct of_device_id ext_clk_match[] = {
> > +       { .compatible = "samsung,clock-fin-pll", .data = (void *)0, },
> > +       { .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
> > +       {},
> > +};
> > +
> > +/* Register s3c64xx clocks. */
> > +void __init s3c64xx_clk_init(struct device_node *np, unsigned long
> > xtal_f, +               unsigned long xusbxti_f, bool is_s3c6400,
> > void __iomem *reg_base) +{
> > +       struct clk *clk;
> > +       unsigned long *soc_regs = NULL;
> > +       unsigned long nr_soc_regs = 0;
> > +
> > +       if (np) {
> > +               reg_base = of_iomap(np, 0);
> > +               if (!reg_base)
> > +                       panic("%s: failed to map registers\n",
> > __func__); +       }
> > +
> > +       if (!is_s3c6400) {
> > +               soc_regs = s3c6410_clk_regs;
> > +               nr_soc_regs = ARRAY_SIZE(s3c6410_clk_regs);
> > +       }
> > +
> > +       samsung_clk_init(np, reg_base, NR_CLKS, s3c64xx_clk_regs,
> > +                       ARRAY_SIZE(s3c64xx_clk_regs), soc_regs,
> > nr_soc_regs); +
> > +       /* Register external clocks. */
> > +       if (np)
> > +              
> > samsung_clk_of_register_fixed_ext(s3c64xx_fixed_rate_ext_clks, +     
> >                  ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks), +          
> >             ext_clk_match);
> > +       else
> > +               s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f);
> > +
> > +       /* Register PLLs. */
> > +       clk = samsung_clk_register_pll6552("fout_apll",
> > +                                       "fin_pll", reg_base +
> > APLL_LOCK); +       samsung_clk_add_lookup(clk, FOUT_APLL);
> > +
> > +       clk = samsung_clk_register_pll6552("fout_mpll",
> > +                                       "fin_pll", reg_base +
> > MPLL_LOCK); +       samsung_clk_add_lookup(clk, FOUT_MPLL);
> > +
> > +       clk = samsung_clk_register_pll6553("fout_epll",
> > +                                       "fin_pll", reg_base +
> > EPLL_LOCK); +       samsung_clk_add_lookup(clk, FOUT_EPLL);
> > +
> > +       /* Register common internal clocks. */
> > +       s3c64xx_clk_register_hclkx2(reg_base);
> > +
> > +       samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks,
> > +                                      
> > ARRAY_SIZE(s3c64xx_fixed_rate_clks)); +      
> > samsung_clk_register_mux(s3c64xx_mux_clks,
> > +                                       ARRAY_SIZE(s3c64xx_mux_clks));
> > +       samsung_clk_register_div(s3c64xx_div_clks,
> > +                                       ARRAY_SIZE(s3c64xx_div_clks));
> > +       samsung_clk_register_gate(s3c64xx_gate_clks,
> > +                                      
> > ARRAY_SIZE(s3c64xx_gate_clks));
> > +
> > +       /* Register SoC-specific clocks. */
> > +       if (is_s3c6400) {
> > +               samsung_clk_register_mux(s3c6400_mux_clks,
> > +                                       ARRAY_SIZE(s3c6400_mux_clks));
> > +               samsung_clk_register_div(s3c6400_div_clks,
> > +                                       ARRAY_SIZE(s3c6400_div_clks));
> > +               samsung_clk_register_gate(s3c6400_gate_clks,
> > +                                      
> > ARRAY_SIZE(s3c6400_gate_clks));
> > +               samsung_clk_register_alias(s3c6400_clock_aliases,
> > +                                      
> > ARRAY_SIZE(s3c6400_clock_aliases)); +       } else {
> > +               samsung_clk_register_mux(s3c6410_mux_clks,
> > +                                       ARRAY_SIZE(s3c6410_mux_clks));
> > +               samsung_clk_register_div(s3c6410_div_clks,
> > +                                       ARRAY_SIZE(s3c6410_div_clks));
> > +               samsung_clk_register_gate(s3c6410_gate_clks,
> > +                                      
> > ARRAY_SIZE(s3c6410_gate_clks));
> > +               samsung_clk_register_alias(s3c6410_clock_aliases,
> > +                                      
> > ARRAY_SIZE(s3c6410_clock_aliases)); +       }
> > +
> > +       samsung_clk_register_alias(s3c64xx_clock_aliases,
> > +                                      
> > ARRAY_SIZE(s3c64xx_clock_aliases)); +
> > +       pr_info("%s clocks: apll = %lu, mpll = %lu\n"
> > +               "    epll = %lu, arm_clk = %lu\n",
> > +               is_s3c6400 ? "S3C6400" : "S3C6410",
> > +               _get_rate("fout_apll"), _get_rate("fout_mpll"),
> > +               _get_rate("fout_epll"), _get_rate("armclk"));
> > +}
> > +
> > +static void __init s3c6400_clk_init(struct device_node *np)
> > +{
> > +       s3c64xx_clk_init(np, 0, 0, true, NULL);
> > +}
> > +CLK_OF_DECLARE(s3c6400_clk, "samsung,s3c6400-clock",
> > s3c6400_clk_init); +
> > +static void __init s3c6410_clk_init(struct device_node *np)
> > +{
> > +       s3c64xx_clk_init(np, 0, 0, false, NULL);
> > +}
> > +CLK_OF_DECLARE(s3c6410_clk, "samsung,s3c6410-clock",
> > s3c6410_clk_init); diff --git
> > a/include/dt-bindings/clock/samsung,s3c64xx-clock.h
> > b/include/dt-bindings/clock/samsung,s3c64xx-clock.h new file mode
> > 100644
> > index 0000000..3e9a1f9
> > --- /dev/null
> > +++ b/include/dt-bindings/clock/samsung,s3c64xx-clock.h
> > @@ -0,0 +1,144 @@
> > +/*
> > + * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.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.
> > + *
> > + * Device Tree binding constants for Samsung S3C64xx clock
> > controller.
> > +*/
> > +
> > +#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
> > +#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
> > +
> > +/*
> > + * Let each exported clock get a unique index, which is used on
> > DT-enabled + * platforms to lookup the clock from a clock specifier.
> > These indices are + * therefore considered an ABI and so must not be
> > changed. This implies + * that new clocks should be added either in
> > free spaces between clock groups + * or at the end.
> > + */
> > +
> > +/* Core clocks. */
> > +#define IISCDCLK0              3
> > +#define PCMCDCLK0              4
> > +#define IISCDCLK1              5
> > +#define PCMCDCLK1              6
> > +#define IISCDCLK2              7
> > +#define CLK27M                 8
> > +#define CLK48M                 9
> > +#define FIN_PLL                        10
> > +#define FOUT_APLL              11
> > +#define FOUT_MPLL              12
> > +#define FOUT_EPLL              13
> > +#define ARMCLK                 14
> > +#define HCLKX2                 15
> > +#define HCLK                   16
> > +#define PCLK                   17
> > +#define MOUT_EPLL              18
> > +#define DOUT_MPLL              19
> > +
> > +/* HCLK bus clocks. */
> > +#define HCLK_3DSE              32
> > +#define HCLK_UHOST             33
> > +#define HCLK_SECUR             34
> > +#define HCLK_SDMA1             35
> > +#define HCLK_SDMA0             36
> > +#define HCLK_IROM              37
> > +#define HCLK_DDR1              38
> > +#define HCLK_MEM1              39
> > +#define HCLK_MEM0              40
> > +#define HCLK_USB               41
> > +#define HCLK_HSMMC2            42
> > +#define HCLK_HSMMC1            43
> > +#define HCLK_HSMMC0            44
> > +#define HCLK_MDP               45
> > +#define HCLK_DHOST             46
> > +#define HCLK_IHOST             47
> > +#define HCLK_DMA1              48
> > +#define HCLK_DMA0              49
> > +#define HCLK_JPEG              50
> > +#define HCLK_CAMIF             51
> > +#define HCLK_SCALER            52
> > +#define HCLK_2D                        53
> > +#define HCLK_TV                        54
> > +#define HCLK_POST0             55
> > +#define HCLK_ROT               56
> > +#define HCLK_LCD               57
> > +#define HCLK_TZIC              58
> > +#define HCLK_INTC              59
> > +#define HCLK_MFC               60
> > +#define HCLK_DDR0              61
> > +
> > +/* PCLK bus clocks. */
> > +#define PCLK_IIC1              64
> > +#define PCLK_IIS2              65
> > +#define PCLK_SKEY              66
> > +#define PCLK_CHIPID            67
> > +#define PCLK_SPI1              68
> > +#define PCLK_SPI0              69
> > +#define PCLK_HSIRX             70
> > +#define PCLK_HSITX             71
> > +#define PCLK_GPIO              72
> > +#define PCLK_IIC0              73
> > +#define PCLK_IIS1              74
> > +#define PCLK_IIS0              75
> > +#define PCLK_AC97              76
> > +#define PCLK_TZPC              77
> > +#define PCLK_TSADC             78
> > +#define PCLK_KEYPAD            79
> > +#define PCLK_IRDA              80
> > +#define PCLK_PCM1              81
> > +#define PCLK_PCM0              82
> > +#define PCLK_PWM               83
> > +#define PCLK_RTC               84
> > +#define PCLK_WDT               85
> > +#define PCLK_UART3             86
> > +#define PCLK_UART2             87
> > +#define PCLK_UART1             88
> > +#define PCLK_UART0             89
> > +#define PCLK_MFC               90
> > +
> > +/* Special clocks. */
> > +#define SCLK_UHOST             96
> > +#define SCLK_MMC2_48           97
> > +#define SCLK_MMC1_48           98
> > +#define SCLK_MMC0_48           99
> > +#define SCLK_MMC2              100
> > +#define SCLK_MMC1              101
> > +#define SCLK_MMC0              102
> > +#define SCLK_SPI1_48           103
> > +#define SCLK_SPI0_48           104
> > +#define SCLK_SPI1              105
> > +#define SCLK_SPI0              106
> > +#define SCLK_DAC27             107
> > +#define SCLK_TV27              108
> > +#define SCLK_SCALER27          109
> > +#define SCLK_SCALER            110
> > +#define SCLK_LCD27             111
> > +#define SCLK_LCD               112
> > +#define SCLK_FIMC              113
> > +#define SCLK_POST0_27          114
> > +#define SCLK_AUDIO2            115
> > +#define SCLK_POST0             116
> > +#define SCLK_AUDIO1            117
> > +#define SCLK_AUDIO0            118
> > +#define SCLK_SECUR             119
> > +#define SCLK_IRDA              120
> > +#define SCLK_UART              121
> > +#define SCLK_MFC               122
> > +#define SCLK_CAM               123
> > +#define SCLK_JPEG              124
> > +#define SCLK_ONENAND           125
> > +
> > +/* MEM0 bus clocks - S3C6410-specific. */
> > +#define MEM0_CFCON             128
> > +#define MEM0_ONENAND1          129
> > +#define MEM0_ONENAND0          130
> > +#define MEM0_NFCON             131
> > +#define MEM0_SROM              132
> > +
> > +/* Total number of clocks. */
> > +#define NR_CLKS                        (MEM0_SROM + 1)
> > +
> > +#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H */
Mike Turquette June 12, 2013, 4:51 p.m. UTC | #3
Quoting Tomasz Figa (2013-06-11 23:26:54)
> Hi Mike,
> 
> On Tuesday 11 of June 2013 19:54:51 Mike Turquette wrote:
> > Quoting Tomasz Figa (2013-06-05 16:57:26)
> > 
> > > This patch adds new, Common Clock Framework-based clock driver for
> > > Samsung S3C64xx SoCs. The driver is just added, without actually
> > > letting the platforms use it yet, since this requires more
> > > intermediate steps.
> > It seems like there is an awful lot of clock data here that exists
> > alongside the stuff in DT.  Is this how you plan to keep things going
> > forward or is this conversion just an intermediate step?
> 
> Current S3C64xx support contains a lot of boards, for which I don't see 
> any chance for DT conversion in any time soon, so the driver must cover 
> both DT and non-DT cases. (Not even saying that DT support for S3C64xx is 
> not yet submitted, as I want to get all the dependencies merged, or at 
> least acked, first.)
> 

Ah right, you're concerned about both DT and non-DT.

> Also, personally, I don't see anything wrong with having those clocks 
> defined in the driver. The binding specifies the exact mapping between 
> clock IDs inside the clock provider and hardware clocks and not all clocks 
> need to be exported (most of muxes and divs don't need to), so I find it 
> more reasonable to define them in the driver instead.

I'm not saying there is anything wrong with it. Other platforms are
doing similar things.

> 
> Another thing is that it's unlikely for any new SoC from S3C64xx series to 
> show up, so basically the clock list is fixed.
> 

Sure.  I can take this into clk-next along with patch #1, or if you
prefer:

Acked-by: Mike Turquette <mturquette@linaro.org>

> Best regards,
> Tomasz
> 
> > Regards,
> > Mike
> > 
> > > Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
> > > ---
> > > 
> > >  .../bindings/clock/samsung,s3c64xx-clock.txt       |  48 ++
> > >  drivers/clk/samsung/Makefile                       |   3 +
> > >  drivers/clk/samsung/clk-s3c64xx.c                  | 503
> > >  +++++++++++++++++++++
> > >  include/dt-bindings/clock/samsung,s3c64xx-clock.h  | 144 ++++++ 4
> > >  files changed, 698 insertions(+)
> > >  create mode 100644
> > >  Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
> > >  create mode 100644 drivers/clk/samsung/clk-s3c64xx.c
> > >  create mode 100644 include/dt-bindings/clock/samsung,s3c64xx-clock.h
> > > 
> > > diff --git
> > > a/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
> > > b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
> > > new file mode 100644
> > > index 0000000..278ab6e
> > > --- /dev/null
> > > +++
> > > b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
> > > @@ -0,0 +1,48 @@
> > > +* Samsung S3C64xx Clock Controller
> > > +
> > > +The S3C64xx clock controller generates and supplies clock to various
> > > controllers +within the SoC. The clock binding described here is
> > > applicable to all SoCs in +the S3C64xx family.
> > > +
> > > +Required Properties:
> > > +
> > > +- comptible: should be one of the following.
> > > +  - "samsung,s3c6400-clock" - controller compatible with S3C6400 SoC.
> > > +  - "samsung,s3c6410-clock" - controller compatible with S3C6410 SoC.
> > > +
> > > +- reg: physical base address of the controller and length of memory
> > > mapped +  region.
> > > +
> > > +- #clock-cells: should be 1.
> > > +
> > > +Each clock is assigned an identifier and client nodes can use this
> > > identifier +to specify the clock which they consume. Some of the
> > > clocks are available only +on a particular S3C64xx SoC and this is
> > > specified where applicable. +
> > > +All available clocks are defined as preprocessor macros in
> > > +dt-bindings/clock/samsung,s3c64xx-clock.h header and can be used in
> > > device +tree sources.
> > > +
> > > +Example: Clock controller node:
> > > +
> > > +       clocks: clock-controller@7e00f000 {
> > > +               compatible = "samsung,s3c6410-clock";
> > > +               reg = <0x7e00f000 0x1000>;
> > > +               #clock-cells = <1>;
> > > +       };
> > > +
> > > +Example: 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" properties):
> > > +
> > > +               uart0: serial@7f005000 {
> > > +                       compatible = "samsung,s3c6400-uart";
> > > +                       reg = <0x7f005000 0x100>;
> > > +                       interrupt-parent = <&vic1>;
> > > +                       interrupts = <5>;
> > > +                       clock-names = "uart", "clk_uart_baud2",
> > > +                                       "clk_uart_baud3";
> > > +                       clocks = <&clocks PCLK_UART0>, <&clocks
> > > PCLK_UART0>, +                                       <&clocks
> > > SCLK_UART>;
> > > +                       status = "disabled";
> > > +               };
> > > diff --git a/drivers/clk/samsung/Makefile
> > > b/drivers/clk/samsung/Makefile index b7c232e..c023474 100644
> > > --- a/drivers/clk/samsung/Makefile
> > > +++ b/drivers/clk/samsung/Makefile
> > > @@ -6,3 +6,6 @@ obj-$(CONFIG_COMMON_CLK)        += clk.o clk-pll.o
> > > 
> > >  obj-$(CONFIG_ARCH_EXYNOS4)     += clk-exynos4.o
> > >  obj-$(CONFIG_SOC_EXYNOS5250)   += clk-exynos5250.o
> > >  obj-$(CONFIG_SOC_EXYNOS5440)   += clk-exynos5440.o
> > > 
> > > +ifdef CONFIG_COMMON_CLK
> > > +obj-$(CONFIG_ARCH_S3C64XX)     += clk-s3c64xx.o
> > > +endif
> > > diff --git a/drivers/clk/samsung/clk-s3c64xx.c
> > > b/drivers/clk/samsung/clk-s3c64xx.c new file mode 100644
> > > index 0000000..253a972
> > > --- /dev/null
> > > +++ b/drivers/clk/samsung/clk-s3c64xx.c
> > > @@ -0,0 +1,503 @@
> > > +/*
> > > + * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.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 S3C64xx SoCs.
> > > +*/
> > > +
> > > +#include <linux/clk.h>
> > > +#include <linux/clkdev.h>
> > > +#include <linux/clk-provider.h>
> > > +#include <linux/of.h>
> > > +#include <linux/of_address.h>
> > > +
> > > +#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
> > > +
> > > +#include "clk.h"
> > > +#include "clk-pll.h"
> > > +
> > > +/* S3C64xx clock controller register offsets. */
> > > +#define APLL_LOCK              0x000
> > > +#define MPLL_LOCK              0x004
> > > +#define EPLL_LOCK              0x008
> > > +#define APLL_CON               0x00c
> > > +#define MPLL_CON               0x010
> > > +#define EPLL_CON0              0x014
> > > +#define EPLL_CON1              0x018
> > > +#define CLK_SRC                        0x01c
> > > +#define CLK_DIV0               0x020
> > > +#define CLK_DIV1               0x024
> > > +#define CLK_DIV2               0x028
> > > +#define HCLK_GATE              0x030
> > > +#define PCLK_GATE              0x034
> > > +#define SCLK_GATE              0x038
> > > +#define MEM0_GATE              0x03c
> > > +#define CLK_SRC2               0x10c
> > > +#define OTHERS                 0x900
> > > +
> > > +/* Special bitfields used in the driver. */
> > > +#define OTHERS_SYNCMUXSEL      (1 << 6)
> > > +
> > > +/* Helper macros to define clock arrays. */
> > > +#define FIXED_RATE_CLOCKS(name)        \
> > > +               static struct samsung_fixed_rate_clock name[]
> > > +#define MUX_CLOCKS(name)       \
> > > +               static struct samsung_mux_clock name[]
> > > +#define DIV_CLOCKS(name)       \
> > > +               static struct samsung_div_clock name[]
> > > +#define GATE_CLOCKS(name)      \
> > > +               static struct samsung_gate_clock name[]
> > > +
> > > +/* Helper macros for gate types present on S3C64xx. */
> > > +#define GATE_BUS(_id, cname, pname, o, b) \
> > > +               GATE(_id, cname, pname, o, b, 0, 0)
> > > +#define GATE_SCLK(_id, cname, pname, o, b) \
> > > +               GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT, 0)
> > > +#define GATE_ON(_id, cname, pname, o, b) \
> > > +               GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0)
> > > +
> > > +/*
> > > + * List of controller registers to be saved and restored during
> > > + * a suspend/resume cycle.
> > > + */
> > > +static __initdata unsigned long s3c64xx_clk_regs[] = {
> > > +       APLL_LOCK,
> > > +       MPLL_LOCK,
> > > +       EPLL_LOCK,
> > > +       APLL_CON,
> > > +       MPLL_CON,
> > > +       EPLL_CON0,
> > > +       EPLL_CON1,
> > > +       CLK_SRC,
> > > +       CLK_DIV0,
> > > +       CLK_DIV1,
> > > +       CLK_DIV2,
> > > +       HCLK_GATE,
> > > +       PCLK_GATE,
> > > +       SCLK_GATE,
> > > +};
> > > +
> > > +static __initdata unsigned long s3c6410_clk_regs[] = {
> > > +       CLK_SRC2,
> > > +       MEM0_GATE,
> > > +};
> > > +
> > > +/* List of parent clocks common for all S3C64xx SoCs. */
> > > +PNAME(spi_mmc_p)       = { "mout_epll", "dout_mpll", "fin_pll",
> > > "clk27m" }; +PNAME(uart_p)          = { "mout_epll", "dout_mpll" };
> > > +PNAME(audio0_p)                = { "mout_epll", "dout_mpll",
> > > "fin_pll", "iiscdclk0", +                               "pcmcdclk0",
> > > "none", "none", "none" }; +PNAME(audio1_p)                = {
> > > "mout_epll", "dout_mpll", "fin_pll", "iiscdclk1", +                  
> > >             "pcmcdclk0", "none", "none", "none" }; +PNAME(mfc_p)     
> > >      = { "hclkx2", "mout_epll" };
> > > +PNAME(apll_p)          = { "fin_pll", "fout_apll" };
> > > +PNAME(mpll_p)          = { "fin_pll", "fout_mpll" };
> > > +PNAME(epll_p)          = { "fin_pll", "fout_epll" };
> > > +
> > > +/* S3C6400-specific parent clocks. */
> > > +PNAME(scaler_lcd_p6400)        = { "mout_epll", "dout_mpll", "none",
> > > "none" }; +PNAME(irda_p6400)      = { "mout_epll", "dout_mpll",
> > > "none", "clk48m" }; +PNAME(uhost_p6400)     = { "clk48m",
> > > "mout_epll", "dout_mpll", "none" }; +
> > > +/* S3C6410-specific parent clocks. */
> > > +PNAME(clk27_p6410)     = { "clk27m", "fin_pll" };
> > > +PNAME(scaler_lcd_p6410)        = { "mout_epll", "dout_mpll",
> > > "fin_pll", "none" }; +PNAME(irda_p6410)      = { "mout_epll",
> > > "dout_mpll", "fin_pll", "clk48m" }; +PNAME(uhost_p6410)     = {
> > > "clk48m", "mout_epll", "dout_mpll", "fin_pll" }; +PNAME(audio2_p6410)
> > >    = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk2", +           
> > >                    "pcmcdclk1", "none", "none", "none" }; +
> > > +/* Fixed rate clocks generated outside the SoC. */
> > > +FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_ext_clks) __initdata = {
> > > +       FRATE(FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0),
> > > +       FRATE(0, "xusbxti", NULL, CLK_IS_ROOT, 0),
> > > +};
> > > +
> > > +/* Fixed rate clocks generated inside the SoC. */
> > > +FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_clks) __initdata = {
> > > +       FRATE(CLK27M, "clk27m", NULL, CLK_IS_ROOT, 27000000),
> > > +       FRATE(CLK48M, "clk48m", NULL, CLK_IS_ROOT, 48000000),
> > > +};
> > > +
> > > +/* List of clock muxes present on all S3C64xx SoCs. */
> > > +MUX_CLOCKS(s3c64xx_mux_clks) __initdata = {
> > > +       MUX(0, "mout_apll", apll_p, CLK_SRC, 0, 1),
> > > +       MUX(0, "mout_mpll", mpll_p, CLK_SRC, 1, 1),
> > > +       MUX(MOUT_EPLL, "mout_epll", epll_p, CLK_SRC, 2, 1),
> > > +       MUX(0, "mout_mfc", mfc_p, CLK_SRC, 4, 1),
> > > +       MUX(0, "mout_audio0", audio0_p, CLK_SRC, 7, 3),
> > > +       MUX(0, "mout_audio1", audio1_p, CLK_SRC, 10, 3),
> > > +       MUX(0, "mout_uart", uart_p, CLK_SRC, 13, 1),
> > > +       MUX(0, "mout_spi0", spi_mmc_p, CLK_SRC, 14, 2),
> > > +       MUX(0, "mout_spi1", spi_mmc_p, CLK_SRC, 16, 2),
> > > +       MUX(0, "mout_mmc0", spi_mmc_p, CLK_SRC, 18, 2),
> > > +       MUX(0, "mout_mmc1", spi_mmc_p, CLK_SRC, 20, 2),
> > > +       MUX(0, "mout_mmc2", spi_mmc_p, CLK_SRC, 22, 2),
> > > +};
> > > +
> > > +/* List of clock muxes present on S3C6400. */
> > > +MUX_CLOCKS(s3c6400_mux_clks) __initdata = {
> > > +       MUX(0, "mout_uhost", uhost_p6400, CLK_SRC, 5, 2),
> > > +       MUX(0, "mout_irda", irda_p6400, CLK_SRC, 24, 2),
> > > +       MUX(0, "mout_lcd", scaler_lcd_p6400, CLK_SRC, 26, 2),
> > > +       MUX(0, "mout_scaler", scaler_lcd_p6400, CLK_SRC, 28, 2),
> > > +};
> > > +
> > > +/* List of clock muxes present on S3C6410. */
> > > +MUX_CLOCKS(s3c6410_mux_clks) __initdata = {
> > > +       MUX(0, "mout_uhost", uhost_p6410, CLK_SRC, 5, 2),
> > > +       MUX(0, "mout_irda", irda_p6410, CLK_SRC, 24, 2),
> > > +       MUX(0, "mout_lcd", scaler_lcd_p6410, CLK_SRC, 26, 2),
> > > +       MUX(0, "mout_scaler", scaler_lcd_p6410, CLK_SRC, 28, 2),
> > > +       MUX(0, "mout_dac27", clk27_p6410, CLK_SRC, 30, 1),
> > > +       MUX(0, "mout_tv27", clk27_p6410, CLK_SRC, 31, 1),
> > > +       MUX(0, "mout_audio2", audio2_p6410, CLK_SRC2, 0, 3),
> > > +};
> > > +
> > > +/* List of clock dividers present on all S3C64xx SoCs. */
> > > +DIV_CLOCKS(s3c64xx_div_clks) __initdata = {
> > > +       DIV(DOUT_MPLL, "dout_mpll", "mout_mpll", CLK_DIV0, 4, 1),
> > > +       DIV(HCLK, "hclk", "hclkx2", CLK_DIV0, 8, 1),
> > > +       DIV(PCLK, "pclk", "hclkx2", CLK_DIV0, 12, 4),
> > > +       DIV(0, "dout_secur", "hclkx2", CLK_DIV0, 18, 2),
> > > +       DIV(0, "dout_cam", "hclkx2", CLK_DIV0, 20, 4),
> > > +       DIV(0, "dout_jpeg", "hclkx2", CLK_DIV0, 24, 4),
> > > +       DIV(0, "dout_mfc", "mout_mfc", CLK_DIV0, 28, 4),
> > > +       DIV(0, "dout_mmc0", "mout_mmc0", CLK_DIV1, 0, 4),
> > > +       DIV(0, "dout_mmc1", "mout_mmc1", CLK_DIV1, 4, 4),
> > > +       DIV(0, "dout_mmc2", "mout_mmc2", CLK_DIV1, 8, 4),
> > > +       DIV(0, "dout_lcd", "mout_lcd", CLK_DIV1, 12, 4),
> > > +       DIV(0, "dout_scaler", "mout_scaler", CLK_DIV1, 16, 4),
> > > +       DIV(0, "dout_uhost", "mout_uhost", CLK_DIV1, 20, 4),
> > > +       DIV(0, "dout_spi0", "mout_spi0", CLK_DIV2, 0, 4),
> > > +       DIV(0, "dout_spi1", "mout_spi1", CLK_DIV2, 4, 4),
> > > +       DIV(0, "dout_audio0", "mout_audio0", CLK_DIV2, 8, 4),
> > > +       DIV(0, "dout_audio1", "mout_audio1", CLK_DIV2, 12, 4),
> > > +       DIV(0, "dout_uart", "mout_uart", CLK_DIV2, 16, 4),
> > > +       DIV(0, "dout_irda", "mout_irda", CLK_DIV2, 20, 4),
> > > +};
> > > +
> > > +/* List of clock dividers present on S3C6400. */
> > > +DIV_CLOCKS(s3c6400_div_clks) __initdata = {
> > > +       DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 3),
> > > +};
> > > +
> > > +/* List of clock dividers present on S3C6410. */
> > > +DIV_CLOCKS(s3c6410_div_clks) __initdata = {
> > > +       DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 4),
> > > +       DIV(0, "dout_fimc", "hclk", CLK_DIV1, 24, 4),
> > > +       DIV(0, "dout_audio2", "mout_audio2", CLK_DIV2, 24, 4),
> > > +};
> > > +
> > > +/* List of clock gates present on all S3C64xx SoCs. */
> > > +GATE_CLOCKS(s3c64xx_gate_clks) __initdata = {
> > > +       GATE_BUS(HCLK_UHOST, "hclk_uhost", "hclk", HCLK_GATE, 29),
> > > +       GATE_BUS(HCLK_SECUR, "hclk_secur", "hclk", HCLK_GATE, 28),
> > > +       GATE_BUS(HCLK_SDMA1, "hclk_sdma1", "hclk", HCLK_GATE, 27),
> > > +       GATE_BUS(HCLK_SDMA0, "hclk_sdma0", "hclk", HCLK_GATE, 26),
> > > +       GATE_ON(HCLK_DDR1, "hclk_ddr1", "hclk", HCLK_GATE, 24),
> > > +       GATE_BUS(HCLK_USB, "hclk_usb", "hclk", HCLK_GATE, 20),
> > > +       GATE_BUS(HCLK_HSMMC2, "hclk_hsmmc2", "hclk", HCLK_GATE, 19),
> > > +       GATE_BUS(HCLK_HSMMC1, "hclk_hsmmc1", "hclk", HCLK_GATE, 18),
> > > +       GATE_BUS(HCLK_HSMMC0, "hclk_hsmmc0", "hclk", HCLK_GATE, 17),
> > > +       GATE_BUS(HCLK_MDP, "hclk_mdp", "hclk", HCLK_GATE, 16),
> > > +       GATE_BUS(HCLK_DHOST, "hclk_dhost", "hclk", HCLK_GATE, 15),
> > > +       GATE_BUS(HCLK_IHOST, "hclk_ihost", "hclk", HCLK_GATE, 14),
> > > +       GATE_BUS(HCLK_DMA1, "hclk_dma1", "hclk", HCLK_GATE, 13),
> > > +       GATE_BUS(HCLK_DMA0, "hclk_dma0", "hclk", HCLK_GATE, 12),
> > > +       GATE_BUS(HCLK_JPEG, "hclk_jpeg", "hclk", HCLK_GATE, 11),
> > > +       GATE_BUS(HCLK_CAMIF, "hclk_camif", "hclk", HCLK_GATE, 10),
> > > +       GATE_BUS(HCLK_SCALER, "hclk_scaler", "hclk", HCLK_GATE, 9),
> > > +       GATE_BUS(HCLK_2D, "hclk_2d", "hclk", HCLK_GATE, 8),
> > > +       GATE_BUS(HCLK_TV, "hclk_tv", "hclk", HCLK_GATE, 7),
> > > +       GATE_BUS(HCLK_POST0, "hclk_post0", "hclk", HCLK_GATE, 5),
> > > +       GATE_BUS(HCLK_ROT, "hclk_rot", "hclk", HCLK_GATE, 4),
> > > +       GATE_BUS(HCLK_LCD, "hclk_lcd", "hclk", HCLK_GATE, 3),
> > > +       GATE_BUS(HCLK_TZIC, "hclk_tzic", "hclk", HCLK_GATE, 2),
> > > +       GATE_ON(HCLK_INTC, "hclk_intc", "hclk", HCLK_GATE, 1),
> > > +       GATE_ON(PCLK_SKEY, "pclk_skey", "pclk", PCLK_GATE, 24),
> > > +       GATE_ON(PCLK_CHIPID, "pclk_chipid", "pclk", PCLK_GATE, 23),
> > > +       GATE_BUS(PCLK_SPI1, "pclk_spi1", "pclk", PCLK_GATE, 22),
> > > +       GATE_BUS(PCLK_SPI0, "pclk_spi0", "pclk", PCLK_GATE, 21),
> > > +       GATE_BUS(PCLK_HSIRX, "pclk_hsirx", "pclk", PCLK_GATE, 20),
> > > +       GATE_BUS(PCLK_HSITX, "pclk_hsitx", "pclk", PCLK_GATE, 19),
> > > +       GATE_ON(PCLK_GPIO, "pclk_gpio", "pclk", PCLK_GATE, 18),
> > > +       GATE_BUS(PCLK_IIC0, "pclk_iic0", "pclk", PCLK_GATE, 17),
> > > +       GATE_BUS(PCLK_IIS1, "pclk_iis1", "pclk", PCLK_GATE, 16),
> > > +       GATE_BUS(PCLK_IIS0, "pclk_iis0", "pclk", PCLK_GATE, 15),
> > > +       GATE_BUS(PCLK_AC97, "pclk_ac97", "pclk", PCLK_GATE, 14),
> > > +       GATE_BUS(PCLK_TZPC, "pclk_tzpc", "pclk", PCLK_GATE, 13),
> > > +       GATE_BUS(PCLK_TSADC, "pclk_tsadc", "pclk", PCLK_GATE, 12),
> > > +       GATE_BUS(PCLK_KEYPAD, "pclk_keypad", "pclk", PCLK_GATE, 11),
> > > +       GATE_BUS(PCLK_IRDA, "pclk_irda", "pclk", PCLK_GATE, 10),
> > > +       GATE_BUS(PCLK_PCM1, "pclk_pcm1", "pclk", PCLK_GATE, 9),
> > > +       GATE_BUS(PCLK_PCM0, "pclk_pcm0", "pclk", PCLK_GATE, 8),
> > > +       GATE_BUS(PCLK_PWM, "pclk_pwm", "pclk", PCLK_GATE, 7),
> > > +       GATE_BUS(PCLK_RTC, "pclk_rtc", "pclk", PCLK_GATE, 6),
> > > +       GATE_BUS(PCLK_WDT, "pclk_wdt", "pclk", PCLK_GATE, 5),
> > > +       GATE_BUS(PCLK_UART3, "pclk_uart3", "pclk", PCLK_GATE, 4),
> > > +       GATE_BUS(PCLK_UART2, "pclk_uart2", "pclk", PCLK_GATE, 3),
> > > +       GATE_BUS(PCLK_UART1, "pclk_uart1", "pclk", PCLK_GATE, 2),
> > > +       GATE_BUS(PCLK_UART0, "pclk_uart0", "pclk", PCLK_GATE, 1),
> > > +       GATE_BUS(PCLK_MFC, "pclk_mfc", "pclk", PCLK_GATE, 0),
> > > +       GATE_SCLK(SCLK_UHOST, "sclk_uhost", "dout_uhost", SCLK_GATE,
> > > 30), +       GATE_SCLK(SCLK_MMC2_48, "sclk_mmc2_48", "clk48m",
> > > SCLK_GATE, 29), +       GATE_SCLK(SCLK_MMC1_48, "sclk_mmc1_48",
> > > "clk48m", SCLK_GATE, 28), +       GATE_SCLK(SCLK_MMC0_48,
> > > "sclk_mmc0_48", "clk48m", SCLK_GATE, 27), +      
> > > GATE_SCLK(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", SCLK_GATE, 26), +     
> > >  GATE_SCLK(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", SCLK_GATE, 25), +    
> > >   GATE_SCLK(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", SCLK_GATE, 24), +   
> > >    GATE_SCLK(SCLK_SPI1_48, "sclk_spi1_48", "clk48m", SCLK_GATE, 23),
> > > +       GATE_SCLK(SCLK_SPI0_48, "sclk_spi0_48", "clk48m", SCLK_GATE,
> > > 22), +       GATE_SCLK(SCLK_SPI1, "sclk_spi1", "dout_spi1",
> > > SCLK_GATE, 21), +       GATE_SCLK(SCLK_SPI0, "sclk_spi0",
> > > "dout_spi0", SCLK_GATE, 20), +       GATE_SCLK(SCLK_DAC27,
> > > "sclk_dac27", "mout_dac27", SCLK_GATE, 19), +      
> > > GATE_SCLK(SCLK_TV27, "sclk_tv27", "mout_tv27", SCLK_GATE, 18), +     
> > >  GATE_SCLK(SCLK_SCALER27, "sclk_scaler27", "clk27m", SCLK_GATE, 17),
> > > +       GATE_SCLK(SCLK_SCALER, "sclk_scaler", "dout_scaler",
> > > SCLK_GATE, 16), +       GATE_SCLK(SCLK_LCD27, "sclk_lcd27", "clk27m",
> > > SCLK_GATE, 15), +       GATE_SCLK(SCLK_LCD, "sclk_lcd", "dout_lcd",
> > > SCLK_GATE, 14), +       GATE_SCLK(SCLK_POST0_27, "sclk_post0_27",
> > > "clk27m", SCLK_GATE, 12), +       GATE_SCLK(SCLK_POST0, "sclk_post0",
> > > "dout_lcd", SCLK_GATE, 10), +       GATE_SCLK(SCLK_AUDIO1,
> > > "sclk_audio1", "dout_audio1", SCLK_GATE, 9), +      
> > > GATE_SCLK(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", SCLK_GATE, 8), +
> > >       GATE_SCLK(SCLK_SECUR, "sclk_secur", "dout_secur", SCLK_GATE,
> > > 7), +       GATE_SCLK(SCLK_IRDA, "sclk_irda", "dout_irda", SCLK_GATE,
> > > 6), +       GATE_SCLK(SCLK_UART, "sclk_uart", "dout_uart", SCLK_GATE,
> > > 5), +       GATE_SCLK(SCLK_MFC, "sclk_mfc", "dout_mfc", SCLK_GATE,
> > > 3), +       GATE_SCLK(SCLK_CAM, "sclk_cam", "dout_cam", SCLK_GATE,
> > > 2), +       GATE_SCLK(SCLK_JPEG, "sclk_jpeg", "dout_jpeg", SCLK_GATE,
> > > 1), +};
> > > +
> > > +/* List of clock gates present on S3C6400. */
> > > +GATE_CLOCKS(s3c6400_gate_clks) __initdata = {
> > > +       GATE_ON(HCLK_DDR0, "hclk_ddr0", "hclk", HCLK_GATE, 23),
> > > +       GATE_SCLK(SCLK_ONENAND, "sclk_onenand", "parent", SCLK_GATE,
> > > 4), +};
> > > +
> > > +/* List of clock gates present on S3C6410. */
> > > +GATE_CLOCKS(s3c6410_gate_clks) __initdata = {
> > > +       GATE_BUS(HCLK_3DSE, "hclk_3dse", "hclk", HCLK_GATE, 31),
> > > +       GATE_ON(HCLK_IROM, "hclk_irom", "hclk", HCLK_GATE, 25),
> > > +       GATE_ON(HCLK_MEM1, "hclk_mem1", "hclk", HCLK_GATE, 22),
> > > +       GATE_ON(HCLK_MEM0, "hclk_mem0", "hclk", HCLK_GATE, 21),
> > > +       GATE_BUS(HCLK_MFC, "hclk_mfc", "hclk", HCLK_GATE, 0),
> > > +       GATE_BUS(PCLK_IIC1, "pclk_iic1", "pclk", PCLK_GATE, 27),
> > > +       GATE_BUS(PCLK_IIS2, "pclk_iis2", "pclk", PCLK_GATE, 26),
> > > +       GATE_SCLK(SCLK_FIMC, "sclk_fimc", "dout_fimc", SCLK_GATE, 13),
> > > +       GATE_SCLK(SCLK_AUDIO2, "sclk_audio2", "dout_audio2",
> > > SCLK_GATE, 11), +       GATE_BUS(MEM0_CFCON, "mem0_cfcon",
> > > "hclk_mem0", MEM0_GATE, 5), +       GATE_BUS(MEM0_ONENAND1,
> > > "mem0_onenand1", "hclk_mem0", MEM0_GATE, 4), +      
> > > GATE_BUS(MEM0_ONENAND0, "mem0_onenand0", "hclk_mem0", MEM0_GATE, 3),
> > > +       GATE_BUS(MEM0_NFCON, "mem0_nfcon", "hclk_mem0", MEM0_GATE,
> > > 2), +       GATE_ON(MEM0_SROM, "mem0_srom", "hclk_mem0", MEM0_GATE,
> > > 1), +};
> > > +
> > > +/* Aliases for common s3c64xx clocks. */
> > > +static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
> > > +       ALIAS(MOUT_EPLL, NULL, "mout_epll"),
> > > +       ALIAS(DOUT_MPLL, NULL, "dout_mpll"),
> > > +       ALIAS(HCLKX2, NULL, "hclk2"),
> > > +       ALIAS(HCLK, NULL, "hclk"),
> > > +       ALIAS(PCLK, NULL, "pclk"),
> > > +       ALIAS(PCLK, NULL, "clk_uart_baud2"),
> > > +       ALIAS(ARMCLK, NULL, "armclk"),
> > > +       ALIAS(HCLK_UHOST, "s3c2410-ohci", "usb-host"),
> > > +       ALIAS(HCLK_USB, "s3c-hsotg", "otg"),
> > > +       ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "hsmmc"),
> > > +       ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "mmc_busclk.0"),
> > > +       ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
> > > +       ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
> > > +       ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
> > > +       ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
> > > +       ALIAS(HCLK_DMA1, NULL, "dma1"),
> > > +       ALIAS(HCLK_DMA0, NULL, "dma0"),
> > > +       ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
> > > +       ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
> > > +       ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
> > > +       ALIAS(PCLK_SPI0, "s3c6410-spi.0", "spi"),
> > > +       ALIAS(PCLK_IIC0, "s3c2440-i2c.0", "i2c"),
> > > +       ALIAS(PCLK_IIS1, "samsung-i2s.1", "iis"),
> > > +       ALIAS(PCLK_IIS0, "samsung-i2s.0", "iis"),
> > > +       ALIAS(PCLK_AC97, "samsung-ac97", "ac97"),
> > > +       ALIAS(PCLK_TSADC, "s3c64xx-adc", "adc"),
> > > +       ALIAS(PCLK_KEYPAD, "samsung-keypad", "keypad"),
> > > +       ALIAS(PCLK_PCM1, "samsung-pcm.1", "pcm"),
> > > +       ALIAS(PCLK_PCM0, "samsung-pcm.0", "pcm"),
> > > +       ALIAS(PCLK_PWM, NULL, "timers"),
> > > +       ALIAS(PCLK_RTC, "s3c64xx-rtc", "rtc"),
> > > +       ALIAS(PCLK_WDT, NULL, "watchdog"),
> > > +       ALIAS(PCLK_UART3, "s3c6400-uart.3", "uart"),
> > > +       ALIAS(PCLK_UART2, "s3c6400-uart.2", "uart"),
> > > +       ALIAS(PCLK_UART1, "s3c6400-uart.1", "uart"),
> > > +       ALIAS(PCLK_UART0, "s3c6400-uart.0", "uart"),
> > > +       ALIAS(SCLK_UHOST, "s3c2410-ohci", "usb-bus-host"),
> > > +       ALIAS(SCLK_MMC2, "s3c-sdhci.2", "mmc_busclk.2"),
> > > +       ALIAS(SCLK_MMC1, "s3c-sdhci.1", "mmc_busclk.2"),
> > > +       ALIAS(SCLK_MMC0, "s3c-sdhci.0", "mmc_busclk.2"),
> > > +       ALIAS(SCLK_SPI1, "s3c6410-spi.1", "spi-bus"),
> > > +       ALIAS(SCLK_SPI0, "s3c6410-spi.0", "spi-bus"),
> > > +       ALIAS(SCLK_AUDIO1, "samsung-pcm.1", "audio-bus"),
> > > +       ALIAS(SCLK_AUDIO1, "samsung-i2s.1", "audio-bus"),
> > > +       ALIAS(SCLK_AUDIO0, "samsung-pcm.0", "audio-bus"),
> > > +       ALIAS(SCLK_AUDIO0, "samsung-i2s.0", "audio-bus"),
> > > +       ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
> > > +       ALIAS(SCLK_CAM, "s3c-camif", "camera"),
> > > +};
> > > +
> > > +/* Aliases for s3c6400-specific clocks. */
> > > +static struct samsung_clock_alias s3c6400_clock_aliases[] = {
> > > +       /* Nothing to place here yet. */
> > > +};
> > > +
> > > +/* Aliases for s3c6410-specific clocks. */
> > > +static struct samsung_clock_alias s3c6410_clock_aliases[] = {
> > > +       ALIAS(PCLK_IIC1, "s3c2440-i2c.1", "i2c"),
> > > +       ALIAS(PCLK_IIS2, "samsung-i2s.2", "iis"),
> > > +       ALIAS(SCLK_FIMC, "s3c-camif", "fimc"),
> > > +       ALIAS(SCLK_AUDIO2, "samsung-i2s.2", "audio-bus"),
> > > +       ALIAS(MEM0_SROM, NULL, "srom"),
> > > +};
> > > +
> > > +/*
> > > + * Parent of the hclkx2 clock depends on whether the SoC is operating
> > > in + * synchronous or asynchronous mode. Depending on value of
> > > OTHERS[6] + * (SYNCMUXSEL) bit, it can be either mout_mpll or
> > > mout_apll. + */
> > > +static void __init s3c64xx_clk_register_hclkx2(void __iomem
> > > *reg_base)
> > > +{
> > > +       struct samsung_div_clock hclkx2;
> > > +       u32 others;
> > > +
> > > +       memset(&hclkx2, 0, sizeof(hclkx2));
> > > +
> > > +       hclkx2.id = HCLKX2;
> > > +       hclkx2.name = "hclkx2";
> > > +       hclkx2.offset = CLK_DIV0;
> > > +       hclkx2.shift = 9;
> > > +       hclkx2.width = 3;
> > > +
> > > +       others = readl(reg_base + OTHERS);
> > > +       if (others & OTHERS_SYNCMUXSEL)
> > > +               hclkx2.parent_name = "mout_apll";
> > > +       else
> > > +               hclkx2.parent_name = "mout_mpll";
> > > +
> > > +       samsung_clk_register_div(&hclkx2, 1);
> > > +}
> > > +
> > > +static void __init s3c64xx_clk_register_fixed_ext(unsigned long
> > > fin_pll_f, +                                                      
> > > unsigned long xusbxti_f) +{
> > > +       s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f;
> > > +       s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
> > > +       samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks,
> > > +                              
> > > ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks)); +}
> > > +
> > > +static __initdata struct of_device_id ext_clk_match[] = {
> > > +       { .compatible = "samsung,clock-fin-pll", .data = (void *)0, },
> > > +       { .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
> > > +       {},
> > > +};
> > > +
> > > +/* Register s3c64xx clocks. */
> > > +void __init s3c64xx_clk_init(struct device_node *np, unsigned long
> > > xtal_f, +               unsigned long xusbxti_f, bool is_s3c6400,
> > > void __iomem *reg_base) +{
> > > +       struct clk *clk;
> > > +       unsigned long *soc_regs = NULL;
> > > +       unsigned long nr_soc_regs = 0;
> > > +
> > > +       if (np) {
> > > +               reg_base = of_iomap(np, 0);
> > > +               if (!reg_base)
> > > +                       panic("%s: failed to map registers\n",
> > > __func__); +       }
> > > +
> > > +       if (!is_s3c6400) {
> > > +               soc_regs = s3c6410_clk_regs;
> > > +               nr_soc_regs = ARRAY_SIZE(s3c6410_clk_regs);
> > > +       }
> > > +
> > > +       samsung_clk_init(np, reg_base, NR_CLKS, s3c64xx_clk_regs,
> > > +                       ARRAY_SIZE(s3c64xx_clk_regs), soc_regs,
> > > nr_soc_regs); +
> > > +       /* Register external clocks. */
> > > +       if (np)
> > > +              
> > > samsung_clk_of_register_fixed_ext(s3c64xx_fixed_rate_ext_clks, +     
> > >                  ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks), +          
> > >             ext_clk_match);
> > > +       else
> > > +               s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f);
> > > +
> > > +       /* Register PLLs. */
> > > +       clk = samsung_clk_register_pll6552("fout_apll",
> > > +                                       "fin_pll", reg_base +
> > > APLL_LOCK); +       samsung_clk_add_lookup(clk, FOUT_APLL);
> > > +
> > > +       clk = samsung_clk_register_pll6552("fout_mpll",
> > > +                                       "fin_pll", reg_base +
> > > MPLL_LOCK); +       samsung_clk_add_lookup(clk, FOUT_MPLL);
> > > +
> > > +       clk = samsung_clk_register_pll6553("fout_epll",
> > > +                                       "fin_pll", reg_base +
> > > EPLL_LOCK); +       samsung_clk_add_lookup(clk, FOUT_EPLL);
> > > +
> > > +       /* Register common internal clocks. */
> > > +       s3c64xx_clk_register_hclkx2(reg_base);
> > > +
> > > +       samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks,
> > > +                                      
> > > ARRAY_SIZE(s3c64xx_fixed_rate_clks)); +      
> > > samsung_clk_register_mux(s3c64xx_mux_clks,
> > > +                                       ARRAY_SIZE(s3c64xx_mux_clks));
> > > +       samsung_clk_register_div(s3c64xx_div_clks,
> > > +                                       ARRAY_SIZE(s3c64xx_div_clks));
> > > +       samsung_clk_register_gate(s3c64xx_gate_clks,
> > > +                                      
> > > ARRAY_SIZE(s3c64xx_gate_clks));
> > > +
> > > +       /* Register SoC-specific clocks. */
> > > +       if (is_s3c6400) {
> > > +               samsung_clk_register_mux(s3c6400_mux_clks,
> > > +                                       ARRAY_SIZE(s3c6400_mux_clks));
> > > +               samsung_clk_register_div(s3c6400_div_clks,
> > > +                                       ARRAY_SIZE(s3c6400_div_clks));
> > > +               samsung_clk_register_gate(s3c6400_gate_clks,
> > > +                                      
> > > ARRAY_SIZE(s3c6400_gate_clks));
> > > +               samsung_clk_register_alias(s3c6400_clock_aliases,
> > > +                                      
> > > ARRAY_SIZE(s3c6400_clock_aliases)); +       } else {
> > > +               samsung_clk_register_mux(s3c6410_mux_clks,
> > > +                                       ARRAY_SIZE(s3c6410_mux_clks));
> > > +               samsung_clk_register_div(s3c6410_div_clks,
> > > +                                       ARRAY_SIZE(s3c6410_div_clks));
> > > +               samsung_clk_register_gate(s3c6410_gate_clks,
> > > +                                      
> > > ARRAY_SIZE(s3c6410_gate_clks));
> > > +               samsung_clk_register_alias(s3c6410_clock_aliases,
> > > +                                      
> > > ARRAY_SIZE(s3c6410_clock_aliases)); +       }
> > > +
> > > +       samsung_clk_register_alias(s3c64xx_clock_aliases,
> > > +                                      
> > > ARRAY_SIZE(s3c64xx_clock_aliases)); +
> > > +       pr_info("%s clocks: apll = %lu, mpll = %lu\n"
> > > +               "    epll = %lu, arm_clk = %lu\n",
> > > +               is_s3c6400 ? "S3C6400" : "S3C6410",
> > > +               _get_rate("fout_apll"), _get_rate("fout_mpll"),
> > > +               _get_rate("fout_epll"), _get_rate("armclk"));
> > > +}
> > > +
> > > +static void __init s3c6400_clk_init(struct device_node *np)
> > > +{
> > > +       s3c64xx_clk_init(np, 0, 0, true, NULL);
> > > +}
> > > +CLK_OF_DECLARE(s3c6400_clk, "samsung,s3c6400-clock",
> > > s3c6400_clk_init); +
> > > +static void __init s3c6410_clk_init(struct device_node *np)
> > > +{
> > > +       s3c64xx_clk_init(np, 0, 0, false, NULL);
> > > +}
> > > +CLK_OF_DECLARE(s3c6410_clk, "samsung,s3c6410-clock",
> > > s3c6410_clk_init); diff --git
> > > a/include/dt-bindings/clock/samsung,s3c64xx-clock.h
> > > b/include/dt-bindings/clock/samsung,s3c64xx-clock.h new file mode
> > > 100644
> > > index 0000000..3e9a1f9
> > > --- /dev/null
> > > +++ b/include/dt-bindings/clock/samsung,s3c64xx-clock.h
> > > @@ -0,0 +1,144 @@
> > > +/*
> > > + * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.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.
> > > + *
> > > + * Device Tree binding constants for Samsung S3C64xx clock
> > > controller.
> > > +*/
> > > +
> > > +#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
> > > +#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
> > > +
> > > +/*
> > > + * Let each exported clock get a unique index, which is used on
> > > DT-enabled + * platforms to lookup the clock from a clock specifier.
> > > These indices are + * therefore considered an ABI and so must not be
> > > changed. This implies + * that new clocks should be added either in
> > > free spaces between clock groups + * or at the end.
> > > + */
> > > +
> > > +/* Core clocks. */
> > > +#define IISCDCLK0              3
> > > +#define PCMCDCLK0              4
> > > +#define IISCDCLK1              5
> > > +#define PCMCDCLK1              6
> > > +#define IISCDCLK2              7
> > > +#define CLK27M                 8
> > > +#define CLK48M                 9
> > > +#define FIN_PLL                        10
> > > +#define FOUT_APLL              11
> > > +#define FOUT_MPLL              12
> > > +#define FOUT_EPLL              13
> > > +#define ARMCLK                 14
> > > +#define HCLKX2                 15
> > > +#define HCLK                   16
> > > +#define PCLK                   17
> > > +#define MOUT_EPLL              18
> > > +#define DOUT_MPLL              19
> > > +
> > > +/* HCLK bus clocks. */
> > > +#define HCLK_3DSE              32
> > > +#define HCLK_UHOST             33
> > > +#define HCLK_SECUR             34
> > > +#define HCLK_SDMA1             35
> > > +#define HCLK_SDMA0             36
> > > +#define HCLK_IROM              37
> > > +#define HCLK_DDR1              38
> > > +#define HCLK_MEM1              39
> > > +#define HCLK_MEM0              40
> > > +#define HCLK_USB               41
> > > +#define HCLK_HSMMC2            42
> > > +#define HCLK_HSMMC1            43
> > > +#define HCLK_HSMMC0            44
> > > +#define HCLK_MDP               45
> > > +#define HCLK_DHOST             46
> > > +#define HCLK_IHOST             47
> > > +#define HCLK_DMA1              48
> > > +#define HCLK_DMA0              49
> > > +#define HCLK_JPEG              50
> > > +#define HCLK_CAMIF             51
> > > +#define HCLK_SCALER            52
> > > +#define HCLK_2D                        53
> > > +#define HCLK_TV                        54
> > > +#define HCLK_POST0             55
> > > +#define HCLK_ROT               56
> > > +#define HCLK_LCD               57
> > > +#define HCLK_TZIC              58
> > > +#define HCLK_INTC              59
> > > +#define HCLK_MFC               60
> > > +#define HCLK_DDR0              61
> > > +
> > > +/* PCLK bus clocks. */
> > > +#define PCLK_IIC1              64
> > > +#define PCLK_IIS2              65
> > > +#define PCLK_SKEY              66
> > > +#define PCLK_CHIPID            67
> > > +#define PCLK_SPI1              68
> > > +#define PCLK_SPI0              69
> > > +#define PCLK_HSIRX             70
> > > +#define PCLK_HSITX             71
> > > +#define PCLK_GPIO              72
> > > +#define PCLK_IIC0              73
> > > +#define PCLK_IIS1              74
> > > +#define PCLK_IIS0              75
> > > +#define PCLK_AC97              76
> > > +#define PCLK_TZPC              77
> > > +#define PCLK_TSADC             78
> > > +#define PCLK_KEYPAD            79
> > > +#define PCLK_IRDA              80
> > > +#define PCLK_PCM1              81
> > > +#define PCLK_PCM0              82
> > > +#define PCLK_PWM               83
> > > +#define PCLK_RTC               84
> > > +#define PCLK_WDT               85
> > > +#define PCLK_UART3             86
> > > +#define PCLK_UART2             87
> > > +#define PCLK_UART1             88
> > > +#define PCLK_UART0             89
> > > +#define PCLK_MFC               90
> > > +
> > > +/* Special clocks. */
> > > +#define SCLK_UHOST             96
> > > +#define SCLK_MMC2_48           97
> > > +#define SCLK_MMC1_48           98
> > > +#define SCLK_MMC0_48           99
> > > +#define SCLK_MMC2              100
> > > +#define SCLK_MMC1              101
> > > +#define SCLK_MMC0              102
> > > +#define SCLK_SPI1_48           103
> > > +#define SCLK_SPI0_48           104
> > > +#define SCLK_SPI1              105
> > > +#define SCLK_SPI0              106
> > > +#define SCLK_DAC27             107
> > > +#define SCLK_TV27              108
> > > +#define SCLK_SCALER27          109
> > > +#define SCLK_SCALER            110
> > > +#define SCLK_LCD27             111
> > > +#define SCLK_LCD               112
> > > +#define SCLK_FIMC              113
> > > +#define SCLK_POST0_27          114
> > > +#define SCLK_AUDIO2            115
> > > +#define SCLK_POST0             116
> > > +#define SCLK_AUDIO1            117
> > > +#define SCLK_AUDIO0            118
> > > +#define SCLK_SECUR             119
> > > +#define SCLK_IRDA              120
> > > +#define SCLK_UART              121
> > > +#define SCLK_MFC               122
> > > +#define SCLK_CAM               123
> > > +#define SCLK_JPEG              124
> > > +#define SCLK_ONENAND           125
> > > +
> > > +/* MEM0 bus clocks - S3C6410-specific. */
> > > +#define MEM0_CFCON             128
> > > +#define MEM0_ONENAND1          129
> > > +#define MEM0_ONENAND0          130
> > > +#define MEM0_NFCON             131
> > > +#define MEM0_SROM              132
> > > +
> > > +/* Total number of clocks. */
> > > +#define NR_CLKS                        (MEM0_SROM + 1)
> > > +
> > > +#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H */
Tomasz Figa June 12, 2013, 9:38 p.m. UTC | #4
On Wednesday 12 of June 2013 09:51:08 Mike Turquette wrote:
> Quoting Tomasz Figa (2013-06-11 23:26:54)
> 
> > Hi Mike,
> > 
> > On Tuesday 11 of June 2013 19:54:51 Mike Turquette wrote:
> > > Quoting Tomasz Figa (2013-06-05 16:57:26)
> > > 
> > > > This patch adds new, Common Clock Framework-based clock driver for
> > > > Samsung S3C64xx SoCs. The driver is just added, without actually
> > > > letting the platforms use it yet, since this requires more
> > > > intermediate steps.
> > > 
> > > It seems like there is an awful lot of clock data here that exists
> > > alongside the stuff in DT.  Is this how you plan to keep things
> > > going
> > > forward or is this conversion just an intermediate step?
> > 
> > Current S3C64xx support contains a lot of boards, for which I don't
> > see
> > any chance for DT conversion in any time soon, so the driver must
> > cover
> > both DT and non-DT cases. (Not even saying that DT support for S3C64xx
> > is not yet submitted, as I want to get all the dependencies merged,
> > or at least acked, first.)
> 
> Ah right, you're concerned about both DT and non-DT.
> 
> > Also, personally, I don't see anything wrong with having those clocks
> > defined in the driver. The binding specifies the exact mapping between
> > clock IDs inside the clock provider and hardware clocks and not all
> > clocks need to be exported (most of muxes and divs don't need to), so
> > I find it more reasonable to define them in the driver instead.
> 
> I'm not saying there is anything wrong with it. Other platforms are
> doing similar things.

OK. I have observed some signs of moving all clock definitions to DT in 
case of some platforms, which ends up with a lot of nodes, phandles and 
data to parse in general without any specific need or advantage.

Good to hear that you are fine with the solution I used for this driver as 
well.

> > Another thing is that it's unlikely for any new SoC from S3C64xx
> > series to show up, so basically the clock list is fixed.
> 
> Sure.  I can take this into clk-next along with patch #1, or if you
> prefer:
> 
> Acked-by: Mike Turquette <mturquette@linaro.org>

Thanks.

IMHO with all the remaining platform patches in this series, it should go 
through Samsung tree.

Best regards,
Tomasz

> > Best regards,
> > Tomasz
> > 
> > > Regards,
> > > Mike
> > > 
> > > > Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
> > > > ---
> > > > 
> > > >  .../bindings/clock/samsung,s3c64xx-clock.txt       |  48 ++
> > > >  drivers/clk/samsung/Makefile                       |   3 +
> > > >  drivers/clk/samsung/clk-s3c64xx.c                  | 503
> > > >  +++++++++++++++++++++
> > > >  include/dt-bindings/clock/samsung,s3c64xx-clock.h  | 144 ++++++ 4
> > > >  files changed, 698 insertions(+)
> > > >  create mode 100644
> > > >  Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
> > > >  create mode 100644 drivers/clk/samsung/clk-s3c64xx.c
> > > >  create mode 100644
> > > >  include/dt-bindings/clock/samsung,s3c64xx-clock.h
> > > > 
> > > > diff --git
> > > > a/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.tx
> > > > t
> > > > b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.tx
> > > > t
> > > > new file mode 100644
> > > > index 0000000..278ab6e
> > > > --- /dev/null
> > > > +++
> > > > b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.tx
> > > > t
> > > > @@ -0,0 +1,48 @@
> > > > +* Samsung S3C64xx Clock Controller
> > > > +
> > > > +The S3C64xx clock controller generates and supplies clock to
> > > > various
> > > > controllers +within the SoC. The clock binding described here is
> > > > applicable to all SoCs in +the S3C64xx family.
> > > > +
> > > > +Required Properties:
> > > > +
> > > > +- comptible: should be one of the following.
> > > > +  - "samsung,s3c6400-clock" - controller compatible with S3C6400
> > > > SoC.
> > > > +  - "samsung,s3c6410-clock" - controller compatible with S3C6410
> > > > SoC.
> > > > +
> > > > +- reg: physical base address of the controller and length of
> > > > memory
> > > > mapped +  region.
> > > > +
> > > > +- #clock-cells: should be 1.
> > > > +
> > > > +Each clock is assigned an identifier and client nodes can use
> > > > this
> > > > identifier +to specify the clock which they consume. Some of the
> > > > clocks are available only +on a particular S3C64xx SoC and this is
> > > > specified where applicable. +
> > > > +All available clocks are defined as preprocessor macros in
> > > > +dt-bindings/clock/samsung,s3c64xx-clock.h header and can be used
> > > > in
> > > > device +tree sources.
> > > > +
> > > > +Example: Clock controller node:
> > > > +
> > > > +       clocks: clock-controller@7e00f000 {
> > > > +               compatible = "samsung,s3c6410-clock";
> > > > +               reg = <0x7e00f000 0x1000>;
> > > > +               #clock-cells = <1>;
> > > > +       };
> > > > +
> > > > +Example: 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" properties):
> > > > +
> > > > +               uart0: serial@7f005000 {
> > > > +                       compatible = "samsung,s3c6400-uart";
> > > > +                       reg = <0x7f005000 0x100>;
> > > > +                       interrupt-parent = <&vic1>;
> > > > +                       interrupts = <5>;
> > > > +                       clock-names = "uart", "clk_uart_baud2",
> > > > +                                       "clk_uart_baud3";
> > > > +                       clocks = <&clocks PCLK_UART0>, <&clocks
> > > > PCLK_UART0>, +                                       <&clocks
> > > > SCLK_UART>;
> > > > +                       status = "disabled";
> > > > +               };
> > > > diff --git a/drivers/clk/samsung/Makefile
> > > > b/drivers/clk/samsung/Makefile index b7c232e..c023474 100644
> > > > --- a/drivers/clk/samsung/Makefile
> > > > +++ b/drivers/clk/samsung/Makefile
> > > > @@ -6,3 +6,6 @@ obj-$(CONFIG_COMMON_CLK)        += clk.o clk-pll.o
> > > > 
> > > >  obj-$(CONFIG_ARCH_EXYNOS4)     += clk-exynos4.o
> > > >  obj-$(CONFIG_SOC_EXYNOS5250)   += clk-exynos5250.o
> > > >  obj-$(CONFIG_SOC_EXYNOS5440)   += clk-exynos5440.o
> > > > 
> > > > +ifdef CONFIG_COMMON_CLK
> > > > +obj-$(CONFIG_ARCH_S3C64XX)     += clk-s3c64xx.o
> > > > +endif
> > > > diff --git a/drivers/clk/samsung/clk-s3c64xx.c
> > > > b/drivers/clk/samsung/clk-s3c64xx.c new file mode 100644
> > > > index 0000000..253a972
> > > > --- /dev/null
> > > > +++ b/drivers/clk/samsung/clk-s3c64xx.c
> > > > @@ -0,0 +1,503 @@
> > > > +/*
> > > > + * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.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 S3C64xx SoCs.
> > > > +*/
> > > > +
> > > > +#include <linux/clk.h>
> > > > +#include <linux/clkdev.h>
> > > > +#include <linux/clk-provider.h>
> > > > +#include <linux/of.h>
> > > > +#include <linux/of_address.h>
> > > > +
> > > > +#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
> > > > +
> > > > +#include "clk.h"
> > > > +#include "clk-pll.h"
> > > > +
> > > > +/* S3C64xx clock controller register offsets. */
> > > > +#define APLL_LOCK              0x000
> > > > +#define MPLL_LOCK              0x004
> > > > +#define EPLL_LOCK              0x008
> > > > +#define APLL_CON               0x00c
> > > > +#define MPLL_CON               0x010
> > > > +#define EPLL_CON0              0x014
> > > > +#define EPLL_CON1              0x018
> > > > +#define CLK_SRC                        0x01c
> > > > +#define CLK_DIV0               0x020
> > > > +#define CLK_DIV1               0x024
> > > > +#define CLK_DIV2               0x028
> > > > +#define HCLK_GATE              0x030
> > > > +#define PCLK_GATE              0x034
> > > > +#define SCLK_GATE              0x038
> > > > +#define MEM0_GATE              0x03c
> > > > +#define CLK_SRC2               0x10c
> > > > +#define OTHERS                 0x900
> > > > +
> > > > +/* Special bitfields used in the driver. */
> > > > +#define OTHERS_SYNCMUXSEL      (1 << 6)
> > > > +
> > > > +/* Helper macros to define clock arrays. */
> > > > +#define FIXED_RATE_CLOCKS(name)        \
> > > > +               static struct samsung_fixed_rate_clock name[]
> > > > +#define MUX_CLOCKS(name)       \
> > > > +               static struct samsung_mux_clock name[]
> > > > +#define DIV_CLOCKS(name)       \
> > > > +               static struct samsung_div_clock name[]
> > > > +#define GATE_CLOCKS(name)      \
> > > > +               static struct samsung_gate_clock name[]
> > > > +
> > > > +/* Helper macros for gate types present on S3C64xx. */
> > > > +#define GATE_BUS(_id, cname, pname, o, b) \
> > > > +               GATE(_id, cname, pname, o, b, 0, 0)
> > > > +#define GATE_SCLK(_id, cname, pname, o, b) \
> > > > +               GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT,
> > > > 0)
> > > > +#define GATE_ON(_id, cname, pname, o, b) \
> > > > +               GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED,
> > > > 0)
> > > > +
> > > > +/*
> > > > + * List of controller registers to be saved and restored during
> > > > + * a suspend/resume cycle.
> > > > + */
> > > > +static __initdata unsigned long s3c64xx_clk_regs[] = {
> > > > +       APLL_LOCK,
> > > > +       MPLL_LOCK,
> > > > +       EPLL_LOCK,
> > > > +       APLL_CON,
> > > > +       MPLL_CON,
> > > > +       EPLL_CON0,
> > > > +       EPLL_CON1,
> > > > +       CLK_SRC,
> > > > +       CLK_DIV0,
> > > > +       CLK_DIV1,
> > > > +       CLK_DIV2,
> > > > +       HCLK_GATE,
> > > > +       PCLK_GATE,
> > > > +       SCLK_GATE,
> > > > +};
> > > > +
> > > > +static __initdata unsigned long s3c6410_clk_regs[] = {
> > > > +       CLK_SRC2,
> > > > +       MEM0_GATE,
> > > > +};
> > > > +
> > > > +/* List of parent clocks common for all S3C64xx SoCs. */
> > > > +PNAME(spi_mmc_p)       = { "mout_epll", "dout_mpll", "fin_pll",
> > > > "clk27m" }; +PNAME(uart_p)          = { "mout_epll", "dout_mpll"
> > > > };
> > > > +PNAME(audio0_p)                = { "mout_epll", "dout_mpll",
> > > > "fin_pll", "iiscdclk0", +                              
> > > > "pcmcdclk0",
> > > > "none", "none", "none" }; +PNAME(audio1_p)                = {
> > > > "mout_epll", "dout_mpll", "fin_pll", "iiscdclk1", +
> > > > 
> > > >             "pcmcdclk0", "none", "none", "none" }; +PNAME(mfc_p)
> > > >      
> > > >      = { "hclkx2", "mout_epll" };
> > > > 
> > > > +PNAME(apll_p)          = { "fin_pll", "fout_apll" };
> > > > +PNAME(mpll_p)          = { "fin_pll", "fout_mpll" };
> > > > +PNAME(epll_p)          = { "fin_pll", "fout_epll" };
> > > > +
> > > > +/* S3C6400-specific parent clocks. */
> > > > +PNAME(scaler_lcd_p6400)        = { "mout_epll", "dout_mpll",
> > > > "none",
> > > > "none" }; +PNAME(irda_p6400)      = { "mout_epll", "dout_mpll",
> > > > "none", "clk48m" }; +PNAME(uhost_p6400)     = { "clk48m",
> > > > "mout_epll", "dout_mpll", "none" }; +
> > > > +/* S3C6410-specific parent clocks. */
> > > > +PNAME(clk27_p6410)     = { "clk27m", "fin_pll" };
> > > > +PNAME(scaler_lcd_p6410)        = { "mout_epll", "dout_mpll",
> > > > "fin_pll", "none" }; +PNAME(irda_p6410)      = { "mout_epll",
> > > > "dout_mpll", "fin_pll", "clk48m" }; +PNAME(uhost_p6410)     = {
> > > > "clk48m", "mout_epll", "dout_mpll", "fin_pll" };
> > > > +PNAME(audio2_p6410)
> > > > 
> > > >    = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk2", +
> > > >    
> > > >                    "pcmcdclk1", "none", "none", "none" }; +
> > > > 
> > > > +/* Fixed rate clocks generated outside the SoC. */
> > > > +FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_ext_clks) __initdata = {
> > > > +       FRATE(FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0),
> > > > +       FRATE(0, "xusbxti", NULL, CLK_IS_ROOT, 0),
> > > > +};
> > > > +
> > > > +/* Fixed rate clocks generated inside the SoC. */
> > > > +FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_clks) __initdata = {
> > > > +       FRATE(CLK27M, "clk27m", NULL, CLK_IS_ROOT, 27000000),
> > > > +       FRATE(CLK48M, "clk48m", NULL, CLK_IS_ROOT, 48000000),
> > > > +};
> > > > +
> > > > +/* List of clock muxes present on all S3C64xx SoCs. */
> > > > +MUX_CLOCKS(s3c64xx_mux_clks) __initdata = {
> > > > +       MUX(0, "mout_apll", apll_p, CLK_SRC, 0, 1),
> > > > +       MUX(0, "mout_mpll", mpll_p, CLK_SRC, 1, 1),
> > > > +       MUX(MOUT_EPLL, "mout_epll", epll_p, CLK_SRC, 2, 1),
> > > > +       MUX(0, "mout_mfc", mfc_p, CLK_SRC, 4, 1),
> > > > +       MUX(0, "mout_audio0", audio0_p, CLK_SRC, 7, 3),
> > > > +       MUX(0, "mout_audio1", audio1_p, CLK_SRC, 10, 3),
> > > > +       MUX(0, "mout_uart", uart_p, CLK_SRC, 13, 1),
> > > > +       MUX(0, "mout_spi0", spi_mmc_p, CLK_SRC, 14, 2),
> > > > +       MUX(0, "mout_spi1", spi_mmc_p, CLK_SRC, 16, 2),
> > > > +       MUX(0, "mout_mmc0", spi_mmc_p, CLK_SRC, 18, 2),
> > > > +       MUX(0, "mout_mmc1", spi_mmc_p, CLK_SRC, 20, 2),
> > > > +       MUX(0, "mout_mmc2", spi_mmc_p, CLK_SRC, 22, 2),
> > > > +};
> > > > +
> > > > +/* List of clock muxes present on S3C6400. */
> > > > +MUX_CLOCKS(s3c6400_mux_clks) __initdata = {
> > > > +       MUX(0, "mout_uhost", uhost_p6400, CLK_SRC, 5, 2),
> > > > +       MUX(0, "mout_irda", irda_p6400, CLK_SRC, 24, 2),
> > > > +       MUX(0, "mout_lcd", scaler_lcd_p6400, CLK_SRC, 26, 2),
> > > > +       MUX(0, "mout_scaler", scaler_lcd_p6400, CLK_SRC, 28, 2),
> > > > +};
> > > > +
> > > > +/* List of clock muxes present on S3C6410. */
> > > > +MUX_CLOCKS(s3c6410_mux_clks) __initdata = {
> > > > +       MUX(0, "mout_uhost", uhost_p6410, CLK_SRC, 5, 2),
> > > > +       MUX(0, "mout_irda", irda_p6410, CLK_SRC, 24, 2),
> > > > +       MUX(0, "mout_lcd", scaler_lcd_p6410, CLK_SRC, 26, 2),
> > > > +       MUX(0, "mout_scaler", scaler_lcd_p6410, CLK_SRC, 28, 2),
> > > > +       MUX(0, "mout_dac27", clk27_p6410, CLK_SRC, 30, 1),
> > > > +       MUX(0, "mout_tv27", clk27_p6410, CLK_SRC, 31, 1),
> > > > +       MUX(0, "mout_audio2", audio2_p6410, CLK_SRC2, 0, 3),
> > > > +};
> > > > +
> > > > +/* List of clock dividers present on all S3C64xx SoCs. */
> > > > +DIV_CLOCKS(s3c64xx_div_clks) __initdata = {
> > > > +       DIV(DOUT_MPLL, "dout_mpll", "mout_mpll", CLK_DIV0, 4, 1),
> > > > +       DIV(HCLK, "hclk", "hclkx2", CLK_DIV0, 8, 1),
> > > > +       DIV(PCLK, "pclk", "hclkx2", CLK_DIV0, 12, 4),
> > > > +       DIV(0, "dout_secur", "hclkx2", CLK_DIV0, 18, 2),
> > > > +       DIV(0, "dout_cam", "hclkx2", CLK_DIV0, 20, 4),
> > > > +       DIV(0, "dout_jpeg", "hclkx2", CLK_DIV0, 24, 4),
> > > > +       DIV(0, "dout_mfc", "mout_mfc", CLK_DIV0, 28, 4),
> > > > +       DIV(0, "dout_mmc0", "mout_mmc0", CLK_DIV1, 0, 4),
> > > > +       DIV(0, "dout_mmc1", "mout_mmc1", CLK_DIV1, 4, 4),
> > > > +       DIV(0, "dout_mmc2", "mout_mmc2", CLK_DIV1, 8, 4),
> > > > +       DIV(0, "dout_lcd", "mout_lcd", CLK_DIV1, 12, 4),
> > > > +       DIV(0, "dout_scaler", "mout_scaler", CLK_DIV1, 16, 4),
> > > > +       DIV(0, "dout_uhost", "mout_uhost", CLK_DIV1, 20, 4),
> > > > +       DIV(0, "dout_spi0", "mout_spi0", CLK_DIV2, 0, 4),
> > > > +       DIV(0, "dout_spi1", "mout_spi1", CLK_DIV2, 4, 4),
> > > > +       DIV(0, "dout_audio0", "mout_audio0", CLK_DIV2, 8, 4),
> > > > +       DIV(0, "dout_audio1", "mout_audio1", CLK_DIV2, 12, 4),
> > > > +       DIV(0, "dout_uart", "mout_uart", CLK_DIV2, 16, 4),
> > > > +       DIV(0, "dout_irda", "mout_irda", CLK_DIV2, 20, 4),
> > > > +};
> > > > +
> > > > +/* List of clock dividers present on S3C6400. */
> > > > +DIV_CLOCKS(s3c6400_div_clks) __initdata = {
> > > > +       DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 3),
> > > > +};
> > > > +
> > > > +/* List of clock dividers present on S3C6410. */
> > > > +DIV_CLOCKS(s3c6410_div_clks) __initdata = {
> > > > +       DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 4),
> > > > +       DIV(0, "dout_fimc", "hclk", CLK_DIV1, 24, 4),
> > > > +       DIV(0, "dout_audio2", "mout_audio2", CLK_DIV2, 24, 4),
> > > > +};
> > > > +
> > > > +/* List of clock gates present on all S3C64xx SoCs. */
> > > > +GATE_CLOCKS(s3c64xx_gate_clks) __initdata = {
> > > > +       GATE_BUS(HCLK_UHOST, "hclk_uhost", "hclk", HCLK_GATE, 29),
> > > > +       GATE_BUS(HCLK_SECUR, "hclk_secur", "hclk", HCLK_GATE, 28),
> > > > +       GATE_BUS(HCLK_SDMA1, "hclk_sdma1", "hclk", HCLK_GATE, 27),
> > > > +       GATE_BUS(HCLK_SDMA0, "hclk_sdma0", "hclk", HCLK_GATE, 26),
> > > > +       GATE_ON(HCLK_DDR1, "hclk_ddr1", "hclk", HCLK_GATE, 24),
> > > > +       GATE_BUS(HCLK_USB, "hclk_usb", "hclk", HCLK_GATE, 20),
> > > > +       GATE_BUS(HCLK_HSMMC2, "hclk_hsmmc2", "hclk", HCLK_GATE,
> > > > 19),
> > > > +       GATE_BUS(HCLK_HSMMC1, "hclk_hsmmc1", "hclk", HCLK_GATE,
> > > > 18),
> > > > +       GATE_BUS(HCLK_HSMMC0, "hclk_hsmmc0", "hclk", HCLK_GATE,
> > > > 17),
> > > > +       GATE_BUS(HCLK_MDP, "hclk_mdp", "hclk", HCLK_GATE, 16),
> > > > +       GATE_BUS(HCLK_DHOST, "hclk_dhost", "hclk", HCLK_GATE, 15),
> > > > +       GATE_BUS(HCLK_IHOST, "hclk_ihost", "hclk", HCLK_GATE, 14),
> > > > +       GATE_BUS(HCLK_DMA1, "hclk_dma1", "hclk", HCLK_GATE, 13),
> > > > +       GATE_BUS(HCLK_DMA0, "hclk_dma0", "hclk", HCLK_GATE, 12),
> > > > +       GATE_BUS(HCLK_JPEG, "hclk_jpeg", "hclk", HCLK_GATE, 11),
> > > > +       GATE_BUS(HCLK_CAMIF, "hclk_camif", "hclk", HCLK_GATE, 10),
> > > > +       GATE_BUS(HCLK_SCALER, "hclk_scaler", "hclk", HCLK_GATE,
> > > > 9),
> > > > +       GATE_BUS(HCLK_2D, "hclk_2d", "hclk", HCLK_GATE, 8),
> > > > +       GATE_BUS(HCLK_TV, "hclk_tv", "hclk", HCLK_GATE, 7),
> > > > +       GATE_BUS(HCLK_POST0, "hclk_post0", "hclk", HCLK_GATE, 5),
> > > > +       GATE_BUS(HCLK_ROT, "hclk_rot", "hclk", HCLK_GATE, 4),
> > > > +       GATE_BUS(HCLK_LCD, "hclk_lcd", "hclk", HCLK_GATE, 3),
> > > > +       GATE_BUS(HCLK_TZIC, "hclk_tzic", "hclk", HCLK_GATE, 2),
> > > > +       GATE_ON(HCLK_INTC, "hclk_intc", "hclk", HCLK_GATE, 1),
> > > > +       GATE_ON(PCLK_SKEY, "pclk_skey", "pclk", PCLK_GATE, 24),
> > > > +       GATE_ON(PCLK_CHIPID, "pclk_chipid", "pclk", PCLK_GATE,
> > > > 23),
> > > > +       GATE_BUS(PCLK_SPI1, "pclk_spi1", "pclk", PCLK_GATE, 22),
> > > > +       GATE_BUS(PCLK_SPI0, "pclk_spi0", "pclk", PCLK_GATE, 21),
> > > > +       GATE_BUS(PCLK_HSIRX, "pclk_hsirx", "pclk", PCLK_GATE, 20),
> > > > +       GATE_BUS(PCLK_HSITX, "pclk_hsitx", "pclk", PCLK_GATE, 19),
> > > > +       GATE_ON(PCLK_GPIO, "pclk_gpio", "pclk", PCLK_GATE, 18),
> > > > +       GATE_BUS(PCLK_IIC0, "pclk_iic0", "pclk", PCLK_GATE, 17),
> > > > +       GATE_BUS(PCLK_IIS1, "pclk_iis1", "pclk", PCLK_GATE, 16),
> > > > +       GATE_BUS(PCLK_IIS0, "pclk_iis0", "pclk", PCLK_GATE, 15),
> > > > +       GATE_BUS(PCLK_AC97, "pclk_ac97", "pclk", PCLK_GATE, 14),
> > > > +       GATE_BUS(PCLK_TZPC, "pclk_tzpc", "pclk", PCLK_GATE, 13),
> > > > +       GATE_BUS(PCLK_TSADC, "pclk_tsadc", "pclk", PCLK_GATE, 12),
> > > > +       GATE_BUS(PCLK_KEYPAD, "pclk_keypad", "pclk", PCLK_GATE,
> > > > 11),
> > > > +       GATE_BUS(PCLK_IRDA, "pclk_irda", "pclk", PCLK_GATE, 10),
> > > > +       GATE_BUS(PCLK_PCM1, "pclk_pcm1", "pclk", PCLK_GATE, 9),
> > > > +       GATE_BUS(PCLK_PCM0, "pclk_pcm0", "pclk", PCLK_GATE, 8),
> > > > +       GATE_BUS(PCLK_PWM, "pclk_pwm", "pclk", PCLK_GATE, 7),
> > > > +       GATE_BUS(PCLK_RTC, "pclk_rtc", "pclk", PCLK_GATE, 6),
> > > > +       GATE_BUS(PCLK_WDT, "pclk_wdt", "pclk", PCLK_GATE, 5),
> > > > +       GATE_BUS(PCLK_UART3, "pclk_uart3", "pclk", PCLK_GATE, 4),
> > > > +       GATE_BUS(PCLK_UART2, "pclk_uart2", "pclk", PCLK_GATE, 3),
> > > > +       GATE_BUS(PCLK_UART1, "pclk_uart1", "pclk", PCLK_GATE, 2),
> > > > +       GATE_BUS(PCLK_UART0, "pclk_uart0", "pclk", PCLK_GATE, 1),
> > > > +       GATE_BUS(PCLK_MFC, "pclk_mfc", "pclk", PCLK_GATE, 0),
> > > > +       GATE_SCLK(SCLK_UHOST, "sclk_uhost", "dout_uhost",
> > > > SCLK_GATE,
> > > > 30), +       GATE_SCLK(SCLK_MMC2_48, "sclk_mmc2_48", "clk48m",
> > > > SCLK_GATE, 29), +       GATE_SCLK(SCLK_MMC1_48, "sclk_mmc1_48",
> > > > "clk48m", SCLK_GATE, 28), +       GATE_SCLK(SCLK_MMC0_48,
> > > > "sclk_mmc0_48", "clk48m", SCLK_GATE, 27), +
> > > > GATE_SCLK(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", SCLK_GATE, 26), +
> > > > 
> > > >  GATE_SCLK(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", SCLK_GATE, 25), +
> > > >  
> > > >   GATE_SCLK(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", SCLK_GATE, 24), +
> > > >   
> > > >    GATE_SCLK(SCLK_SPI1_48, "sclk_spi1_48", "clk48m", SCLK_GATE,
> > > >    23),
> > > > 
> > > > +       GATE_SCLK(SCLK_SPI0_48, "sclk_spi0_48", "clk48m",
> > > > SCLK_GATE,
> > > > 22), +       GATE_SCLK(SCLK_SPI1, "sclk_spi1", "dout_spi1",
> > > > SCLK_GATE, 21), +       GATE_SCLK(SCLK_SPI0, "sclk_spi0",
> > > > "dout_spi0", SCLK_GATE, 20), +       GATE_SCLK(SCLK_DAC27,
> > > > "sclk_dac27", "mout_dac27", SCLK_GATE, 19), +
> > > > GATE_SCLK(SCLK_TV27, "sclk_tv27", "mout_tv27", SCLK_GATE, 18), +
> > > > 
> > > >  GATE_SCLK(SCLK_SCALER27, "sclk_scaler27", "clk27m", SCLK_GATE,
> > > >  17),
> > > > 
> > > > +       GATE_SCLK(SCLK_SCALER, "sclk_scaler", "dout_scaler",
> > > > SCLK_GATE, 16), +       GATE_SCLK(SCLK_LCD27, "sclk_lcd27",
> > > > "clk27m",
> > > > SCLK_GATE, 15), +       GATE_SCLK(SCLK_LCD, "sclk_lcd",
> > > > "dout_lcd",
> > > > SCLK_GATE, 14), +       GATE_SCLK(SCLK_POST0_27, "sclk_post0_27",
> > > > "clk27m", SCLK_GATE, 12), +       GATE_SCLK(SCLK_POST0,
> > > > "sclk_post0",
> > > > "dout_lcd", SCLK_GATE, 10), +       GATE_SCLK(SCLK_AUDIO1,
> > > > "sclk_audio1", "dout_audio1", SCLK_GATE, 9), +
> > > > GATE_SCLK(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", SCLK_GATE,
> > > > 8), +
> > > > 
> > > >       GATE_SCLK(SCLK_SECUR, "sclk_secur", "dout_secur", SCLK_GATE,
> > > > 
> > > > 7), +       GATE_SCLK(SCLK_IRDA, "sclk_irda", "dout_irda",
> > > > SCLK_GATE,
> > > > 6), +       GATE_SCLK(SCLK_UART, "sclk_uart", "dout_uart",
> > > > SCLK_GATE,
> > > > 5), +       GATE_SCLK(SCLK_MFC, "sclk_mfc", "dout_mfc", SCLK_GATE,
> > > > 3), +       GATE_SCLK(SCLK_CAM, "sclk_cam", "dout_cam", SCLK_GATE,
> > > > 2), +       GATE_SCLK(SCLK_JPEG, "sclk_jpeg", "dout_jpeg",
> > > > SCLK_GATE,
> > > > 1), +};
> > > > +
> > > > +/* List of clock gates present on S3C6400. */
> > > > +GATE_CLOCKS(s3c6400_gate_clks) __initdata = {
> > > > +       GATE_ON(HCLK_DDR0, "hclk_ddr0", "hclk", HCLK_GATE, 23),
> > > > +       GATE_SCLK(SCLK_ONENAND, "sclk_onenand", "parent",
> > > > SCLK_GATE,
> > > > 4), +};
> > > > +
> > > > +/* List of clock gates present on S3C6410. */
> > > > +GATE_CLOCKS(s3c6410_gate_clks) __initdata = {
> > > > +       GATE_BUS(HCLK_3DSE, "hclk_3dse", "hclk", HCLK_GATE, 31),
> > > > +       GATE_ON(HCLK_IROM, "hclk_irom", "hclk", HCLK_GATE, 25),
> > > > +       GATE_ON(HCLK_MEM1, "hclk_mem1", "hclk", HCLK_GATE, 22),
> > > > +       GATE_ON(HCLK_MEM0, "hclk_mem0", "hclk", HCLK_GATE, 21),
> > > > +       GATE_BUS(HCLK_MFC, "hclk_mfc", "hclk", HCLK_GATE, 0),
> > > > +       GATE_BUS(PCLK_IIC1, "pclk_iic1", "pclk", PCLK_GATE, 27),
> > > > +       GATE_BUS(PCLK_IIS2, "pclk_iis2", "pclk", PCLK_GATE, 26),
> > > > +       GATE_SCLK(SCLK_FIMC, "sclk_fimc", "dout_fimc", SCLK_GATE,
> > > > 13),
> > > > +       GATE_SCLK(SCLK_AUDIO2, "sclk_audio2", "dout_audio2",
> > > > SCLK_GATE, 11), +       GATE_BUS(MEM0_CFCON, "mem0_cfcon",
> > > > "hclk_mem0", MEM0_GATE, 5), +       GATE_BUS(MEM0_ONENAND1,
> > > > "mem0_onenand1", "hclk_mem0", MEM0_GATE, 4), +
> > > > GATE_BUS(MEM0_ONENAND0, "mem0_onenand0", "hclk_mem0", MEM0_GATE,
> > > > 3),
> > > > +       GATE_BUS(MEM0_NFCON, "mem0_nfcon", "hclk_mem0", MEM0_GATE,
> > > > 2), +       GATE_ON(MEM0_SROM, "mem0_srom", "hclk_mem0",
> > > > MEM0_GATE,
> > > > 1), +};
> > > > +
> > > > +/* Aliases for common s3c64xx clocks. */
> > > > +static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
> > > > +       ALIAS(MOUT_EPLL, NULL, "mout_epll"),
> > > > +       ALIAS(DOUT_MPLL, NULL, "dout_mpll"),
> > > > +       ALIAS(HCLKX2, NULL, "hclk2"),
> > > > +       ALIAS(HCLK, NULL, "hclk"),
> > > > +       ALIAS(PCLK, NULL, "pclk"),
> > > > +       ALIAS(PCLK, NULL, "clk_uart_baud2"),
> > > > +       ALIAS(ARMCLK, NULL, "armclk"),
> > > > +       ALIAS(HCLK_UHOST, "s3c2410-ohci", "usb-host"),
> > > > +       ALIAS(HCLK_USB, "s3c-hsotg", "otg"),
> > > > +       ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "hsmmc"),
> > > > +       ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "mmc_busclk.0"),
> > > > +       ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
> > > > +       ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
> > > > +       ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
> > > > +       ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
> > > > +       ALIAS(HCLK_DMA1, NULL, "dma1"),
> > > > +       ALIAS(HCLK_DMA0, NULL, "dma0"),
> > > > +       ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
> > > > +       ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
> > > > +       ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
> > > > +       ALIAS(PCLK_SPI0, "s3c6410-spi.0", "spi"),
> > > > +       ALIAS(PCLK_IIC0, "s3c2440-i2c.0", "i2c"),
> > > > +       ALIAS(PCLK_IIS1, "samsung-i2s.1", "iis"),
> > > > +       ALIAS(PCLK_IIS0, "samsung-i2s.0", "iis"),
> > > > +       ALIAS(PCLK_AC97, "samsung-ac97", "ac97"),
> > > > +       ALIAS(PCLK_TSADC, "s3c64xx-adc", "adc"),
> > > > +       ALIAS(PCLK_KEYPAD, "samsung-keypad", "keypad"),
> > > > +       ALIAS(PCLK_PCM1, "samsung-pcm.1", "pcm"),
> > > > +       ALIAS(PCLK_PCM0, "samsung-pcm.0", "pcm"),
> > > > +       ALIAS(PCLK_PWM, NULL, "timers"),
> > > > +       ALIAS(PCLK_RTC, "s3c64xx-rtc", "rtc"),
> > > > +       ALIAS(PCLK_WDT, NULL, "watchdog"),
> > > > +       ALIAS(PCLK_UART3, "s3c6400-uart.3", "uart"),
> > > > +       ALIAS(PCLK_UART2, "s3c6400-uart.2", "uart"),
> > > > +       ALIAS(PCLK_UART1, "s3c6400-uart.1", "uart"),
> > > > +       ALIAS(PCLK_UART0, "s3c6400-uart.0", "uart"),
> > > > +       ALIAS(SCLK_UHOST, "s3c2410-ohci", "usb-bus-host"),
> > > > +       ALIAS(SCLK_MMC2, "s3c-sdhci.2", "mmc_busclk.2"),
> > > > +       ALIAS(SCLK_MMC1, "s3c-sdhci.1", "mmc_busclk.2"),
> > > > +       ALIAS(SCLK_MMC0, "s3c-sdhci.0", "mmc_busclk.2"),
> > > > +       ALIAS(SCLK_SPI1, "s3c6410-spi.1", "spi-bus"),
> > > > +       ALIAS(SCLK_SPI0, "s3c6410-spi.0", "spi-bus"),
> > > > +       ALIAS(SCLK_AUDIO1, "samsung-pcm.1", "audio-bus"),
> > > > +       ALIAS(SCLK_AUDIO1, "samsung-i2s.1", "audio-bus"),
> > > > +       ALIAS(SCLK_AUDIO0, "samsung-pcm.0", "audio-bus"),
> > > > +       ALIAS(SCLK_AUDIO0, "samsung-i2s.0", "audio-bus"),
> > > > +       ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
> > > > +       ALIAS(SCLK_CAM, "s3c-camif", "camera"),
> > > > +};
> > > > +
> > > > +/* Aliases for s3c6400-specific clocks. */
> > > > +static struct samsung_clock_alias s3c6400_clock_aliases[] = {
> > > > +       /* Nothing to place here yet. */
> > > > +};
> > > > +
> > > > +/* Aliases for s3c6410-specific clocks. */
> > > > +static struct samsung_clock_alias s3c6410_clock_aliases[] = {
> > > > +       ALIAS(PCLK_IIC1, "s3c2440-i2c.1", "i2c"),
> > > > +       ALIAS(PCLK_IIS2, "samsung-i2s.2", "iis"),
> > > > +       ALIAS(SCLK_FIMC, "s3c-camif", "fimc"),
> > > > +       ALIAS(SCLK_AUDIO2, "samsung-i2s.2", "audio-bus"),
> > > > +       ALIAS(MEM0_SROM, NULL, "srom"),
> > > > +};
> > > > +
> > > > +/*
> > > > + * Parent of the hclkx2 clock depends on whether the SoC is
> > > > operating
> > > > in + * synchronous or asynchronous mode. Depending on value of
> > > > OTHERS[6] + * (SYNCMUXSEL) bit, it can be either mout_mpll or
> > > > mout_apll. + */
> > > > +static void __init s3c64xx_clk_register_hclkx2(void __iomem
> > > > *reg_base)
> > > > +{
> > > > +       struct samsung_div_clock hclkx2;
> > > > +       u32 others;
> > > > +
> > > > +       memset(&hclkx2, 0, sizeof(hclkx2));
> > > > +
> > > > +       hclkx2.id = HCLKX2;
> > > > +       hclkx2.name = "hclkx2";
> > > > +       hclkx2.offset = CLK_DIV0;
> > > > +       hclkx2.shift = 9;
> > > > +       hclkx2.width = 3;
> > > > +
> > > > +       others = readl(reg_base + OTHERS);
> > > > +       if (others & OTHERS_SYNCMUXSEL)
> > > > +               hclkx2.parent_name = "mout_apll";
> > > > +       else
> > > > +               hclkx2.parent_name = "mout_mpll";
> > > > +
> > > > +       samsung_clk_register_div(&hclkx2, 1);
> > > > +}
> > > > +
> > > > +static void __init s3c64xx_clk_register_fixed_ext(unsigned long
> > > > fin_pll_f, +
> > > > unsigned long xusbxti_f) +{
> > > > +       s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f;
> > > > +       s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
> > > > +      
> > > > samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks,
> > > > +
> > > > ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks)); +}
> > > > +
> > > > +static __initdata struct of_device_id ext_clk_match[] = {
> > > > +       { .compatible = "samsung,clock-fin-pll", .data = (void
> > > > *)0, },
> > > > +       { .compatible = "samsung,clock-xusbxti", .data = (void
> > > > *)1, },
> > > > +       {},
> > > > +};
> > > > +
> > > > +/* Register s3c64xx clocks. */
> > > > +void __init s3c64xx_clk_init(struct device_node *np, unsigned
> > > > long
> > > > xtal_f, +               unsigned long xusbxti_f, bool is_s3c6400,
> > > > void __iomem *reg_base) +{
> > > > +       struct clk *clk;
> > > > +       unsigned long *soc_regs = NULL;
> > > > +       unsigned long nr_soc_regs = 0;
> > > > +
> > > > +       if (np) {
> > > > +               reg_base = of_iomap(np, 0);
> > > > +               if (!reg_base)
> > > > +                       panic("%s: failed to map registers\n",
> > > > __func__); +       }
> > > > +
> > > > +       if (!is_s3c6400) {
> > > > +               soc_regs = s3c6410_clk_regs;
> > > > +               nr_soc_regs = ARRAY_SIZE(s3c6410_clk_regs);
> > > > +       }
> > > > +
> > > > +       samsung_clk_init(np, reg_base, NR_CLKS, s3c64xx_clk_regs,
> > > > +                       ARRAY_SIZE(s3c64xx_clk_regs), soc_regs,
> > > > nr_soc_regs); +
> > > > +       /* Register external clocks. */
> > > > +       if (np)
> > > > +
> > > > samsung_clk_of_register_fixed_ext(s3c64xx_fixed_rate_ext_clks, +
> > > > 
> > > >                  ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks), +
> > > >             
> > > >             ext_clk_match);
> > > > 
> > > > +       else
> > > > +               s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f);
> > > > +
> > > > +       /* Register PLLs. */
> > > > +       clk = samsung_clk_register_pll6552("fout_apll",
> > > > +                                       "fin_pll", reg_base +
> > > > APLL_LOCK); +       samsung_clk_add_lookup(clk, FOUT_APLL);
> > > > +
> > > > +       clk = samsung_clk_register_pll6552("fout_mpll",
> > > > +                                       "fin_pll", reg_base +
> > > > MPLL_LOCK); +       samsung_clk_add_lookup(clk, FOUT_MPLL);
> > > > +
> > > > +       clk = samsung_clk_register_pll6553("fout_epll",
> > > > +                                       "fin_pll", reg_base +
> > > > EPLL_LOCK); +       samsung_clk_add_lookup(clk, FOUT_EPLL);
> > > > +
> > > > +       /* Register common internal clocks. */
> > > > +       s3c64xx_clk_register_hclkx2(reg_base);
> > > > +
> > > > +       samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks,
> > > > +
> > > > ARRAY_SIZE(s3c64xx_fixed_rate_clks)); +
> > > > samsung_clk_register_mux(s3c64xx_mux_clks,
> > > > +                                      
> > > > ARRAY_SIZE(s3c64xx_mux_clks));
> > > > +       samsung_clk_register_div(s3c64xx_div_clks,
> > > > +                                      
> > > > ARRAY_SIZE(s3c64xx_div_clks));
> > > > +       samsung_clk_register_gate(s3c64xx_gate_clks,
> > > > +
> > > > ARRAY_SIZE(s3c64xx_gate_clks));
> > > > +
> > > > +       /* Register SoC-specific clocks. */
> > > > +       if (is_s3c6400) {
> > > > +               samsung_clk_register_mux(s3c6400_mux_clks,
> > > > +                                      
> > > > ARRAY_SIZE(s3c6400_mux_clks));
> > > > +               samsung_clk_register_div(s3c6400_div_clks,
> > > > +                                      
> > > > ARRAY_SIZE(s3c6400_div_clks));
> > > > +               samsung_clk_register_gate(s3c6400_gate_clks,
> > > > +
> > > > ARRAY_SIZE(s3c6400_gate_clks));
> > > > +               samsung_clk_register_alias(s3c6400_clock_aliases,
> > > > +
> > > > ARRAY_SIZE(s3c6400_clock_aliases)); +       } else {
> > > > +               samsung_clk_register_mux(s3c6410_mux_clks,
> > > > +                                      
> > > > ARRAY_SIZE(s3c6410_mux_clks));
> > > > +               samsung_clk_register_div(s3c6410_div_clks,
> > > > +                                      
> > > > ARRAY_SIZE(s3c6410_div_clks));
> > > > +               samsung_clk_register_gate(s3c6410_gate_clks,
> > > > +
> > > > ARRAY_SIZE(s3c6410_gate_clks));
> > > > +               samsung_clk_register_alias(s3c6410_clock_aliases,
> > > > +
> > > > ARRAY_SIZE(s3c6410_clock_aliases)); +       }
> > > > +
> > > > +       samsung_clk_register_alias(s3c64xx_clock_aliases,
> > > > +
> > > > ARRAY_SIZE(s3c64xx_clock_aliases)); +
> > > > +       pr_info("%s clocks: apll = %lu, mpll = %lu\n"
> > > > +               "    epll = %lu, arm_clk = %lu\n",
> > > > +               is_s3c6400 ? "S3C6400" : "S3C6410",
> > > > +               _get_rate("fout_apll"), _get_rate("fout_mpll"),
> > > > +               _get_rate("fout_epll"), _get_rate("armclk"));
> > > > +}
> > > > +
> > > > +static void __init s3c6400_clk_init(struct device_node *np)
> > > > +{
> > > > +       s3c64xx_clk_init(np, 0, 0, true, NULL);
> > > > +}
> > > > +CLK_OF_DECLARE(s3c6400_clk, "samsung,s3c6400-clock",
> > > > s3c6400_clk_init); +
> > > > +static void __init s3c6410_clk_init(struct device_node *np)
> > > > +{
> > > > +       s3c64xx_clk_init(np, 0, 0, false, NULL);
> > > > +}
> > > > +CLK_OF_DECLARE(s3c6410_clk, "samsung,s3c6410-clock",
> > > > s3c6410_clk_init); diff --git
> > > > a/include/dt-bindings/clock/samsung,s3c64xx-clock.h
> > > > b/include/dt-bindings/clock/samsung,s3c64xx-clock.h new file mode
> > > > 100644
> > > > index 0000000..3e9a1f9
> > > > --- /dev/null
> > > > +++ b/include/dt-bindings/clock/samsung,s3c64xx-clock.h
> > > > @@ -0,0 +1,144 @@
> > > > +/*
> > > > + * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.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.
> > > > + *
> > > > + * Device Tree binding constants for Samsung S3C64xx clock
> > > > controller.
> > > > +*/
> > > > +
> > > > +#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
> > > > +#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
> > > > +
> > > > +/*
> > > > + * Let each exported clock get a unique index, which is used on
> > > > DT-enabled + * platforms to lookup the clock from a clock
> > > > specifier.
> > > > These indices are + * therefore considered an ABI and so must not
> > > > be
> > > > changed. This implies + * that new clocks should be added either
> > > > in
> > > > free spaces between clock groups + * or at the end.
> > > > + */
> > > > +
> > > > +/* Core clocks. */
> > > > +#define IISCDCLK0              3
> > > > +#define PCMCDCLK0              4
> > > > +#define IISCDCLK1              5
> > > > +#define PCMCDCLK1              6
> > > > +#define IISCDCLK2              7
> > > > +#define CLK27M                 8
> > > > +#define CLK48M                 9
> > > > +#define FIN_PLL                        10
> > > > +#define FOUT_APLL              11
> > > > +#define FOUT_MPLL              12
> > > > +#define FOUT_EPLL              13
> > > > +#define ARMCLK                 14
> > > > +#define HCLKX2                 15
> > > > +#define HCLK                   16
> > > > +#define PCLK                   17
> > > > +#define MOUT_EPLL              18
> > > > +#define DOUT_MPLL              19
> > > > +
> > > > +/* HCLK bus clocks. */
> > > > +#define HCLK_3DSE              32
> > > > +#define HCLK_UHOST             33
> > > > +#define HCLK_SECUR             34
> > > > +#define HCLK_SDMA1             35
> > > > +#define HCLK_SDMA0             36
> > > > +#define HCLK_IROM              37
> > > > +#define HCLK_DDR1              38
> > > > +#define HCLK_MEM1              39
> > > > +#define HCLK_MEM0              40
> > > > +#define HCLK_USB               41
> > > > +#define HCLK_HSMMC2            42
> > > > +#define HCLK_HSMMC1            43
> > > > +#define HCLK_HSMMC0            44
> > > > +#define HCLK_MDP               45
> > > > +#define HCLK_DHOST             46
> > > > +#define HCLK_IHOST             47
> > > > +#define HCLK_DMA1              48
> > > > +#define HCLK_DMA0              49
> > > > +#define HCLK_JPEG              50
> > > > +#define HCLK_CAMIF             51
> > > > +#define HCLK_SCALER            52
> > > > +#define HCLK_2D                        53
> > > > +#define HCLK_TV                        54
> > > > +#define HCLK_POST0             55
> > > > +#define HCLK_ROT               56
> > > > +#define HCLK_LCD               57
> > > > +#define HCLK_TZIC              58
> > > > +#define HCLK_INTC              59
> > > > +#define HCLK_MFC               60
> > > > +#define HCLK_DDR0              61
> > > > +
> > > > +/* PCLK bus clocks. */
> > > > +#define PCLK_IIC1              64
> > > > +#define PCLK_IIS2              65
> > > > +#define PCLK_SKEY              66
> > > > +#define PCLK_CHIPID            67
> > > > +#define PCLK_SPI1              68
> > > > +#define PCLK_SPI0              69
> > > > +#define PCLK_HSIRX             70
> > > > +#define PCLK_HSITX             71
> > > > +#define PCLK_GPIO              72
> > > > +#define PCLK_IIC0              73
> > > > +#define PCLK_IIS1              74
> > > > +#define PCLK_IIS0              75
> > > > +#define PCLK_AC97              76
> > > > +#define PCLK_TZPC              77
> > > > +#define PCLK_TSADC             78
> > > > +#define PCLK_KEYPAD            79
> > > > +#define PCLK_IRDA              80
> > > > +#define PCLK_PCM1              81
> > > > +#define PCLK_PCM0              82
> > > > +#define PCLK_PWM               83
> > > > +#define PCLK_RTC               84
> > > > +#define PCLK_WDT               85
> > > > +#define PCLK_UART3             86
> > > > +#define PCLK_UART2             87
> > > > +#define PCLK_UART1             88
> > > > +#define PCLK_UART0             89
> > > > +#define PCLK_MFC               90
> > > > +
> > > > +/* Special clocks. */
> > > > +#define SCLK_UHOST             96
> > > > +#define SCLK_MMC2_48           97
> > > > +#define SCLK_MMC1_48           98
> > > > +#define SCLK_MMC0_48           99
> > > > +#define SCLK_MMC2              100
> > > > +#define SCLK_MMC1              101
> > > > +#define SCLK_MMC0              102
> > > > +#define SCLK_SPI1_48           103
> > > > +#define SCLK_SPI0_48           104
> > > > +#define SCLK_SPI1              105
> > > > +#define SCLK_SPI0              106
> > > > +#define SCLK_DAC27             107
> > > > +#define SCLK_TV27              108
> > > > +#define SCLK_SCALER27          109
> > > > +#define SCLK_SCALER            110
> > > > +#define SCLK_LCD27             111
> > > > +#define SCLK_LCD               112
> > > > +#define SCLK_FIMC              113
> > > > +#define SCLK_POST0_27          114
> > > > +#define SCLK_AUDIO2            115
> > > > +#define SCLK_POST0             116
> > > > +#define SCLK_AUDIO1            117
> > > > +#define SCLK_AUDIO0            118
> > > > +#define SCLK_SECUR             119
> > > > +#define SCLK_IRDA              120
> > > > +#define SCLK_UART              121
> > > > +#define SCLK_MFC               122
> > > > +#define SCLK_CAM               123
> > > > +#define SCLK_JPEG              124
> > > > +#define SCLK_ONENAND           125
> > > > +
> > > > +/* MEM0 bus clocks - S3C6410-specific. */
> > > > +#define MEM0_CFCON             128
> > > > +#define MEM0_ONENAND1          129
> > > > +#define MEM0_ONENAND0          130
> > > > +#define MEM0_NFCON             131
> > > > +#define MEM0_SROM              132
> > > > +
> > > > +/* Total number of clocks. */
> > > > +#define NR_CLKS                        (MEM0_SROM + 1)
> > > > +
> > > > +#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H */
Kim Kukjin June 19, 2013, 2:18 p.m. UTC | #5
On 06/13/13 06:38, Tomasz Figa wrote:

[...]

>>> Another thing is that it's unlikely for any new SoC from S3C64xx
>>> series to show up, so basically the clock list is fixed.
>>
>> Sure.  I can take this into clk-next along with patch #1, or if you
>> prefer:
>>
>> Acked-by: Mike Turquette<mturquette@linaro.org>
>
> Thanks.
>
> IMHO with all the remaining platform patches in this series, it should go
> through Samsung tree.
>

Mike, thanks for your ack. Let me take this whole series into samsung 
tree when ready for other dependencies like PWM...

- Kukjin
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
new file mode 100644
index 0000000..278ab6e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt
@@ -0,0 +1,48 @@ 
+* Samsung S3C64xx Clock Controller
+
+The S3C64xx clock controller generates and supplies clock to various controllers
+within the SoC. The clock binding described here is applicable to all SoCs in
+the S3C64xx family.
+
+Required Properties:
+
+- comptible: should be one of the following.
+  - "samsung,s3c6400-clock" - controller compatible with S3C6400 SoC.
+  - "samsung,s3c6410-clock" - controller compatible with S3C6410 SoC.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. Some of the clocks are available only
+on a particular S3C64xx SoC and this is specified where applicable.
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/samsung,s3c64xx-clock.h header and can be used in device
+tree sources.
+
+Example: Clock controller node:
+
+	clocks: clock-controller@7e00f000 {
+		compatible = "samsung,s3c6410-clock";
+		reg = <0x7e00f000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+Example: 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" properties):
+
+		uart0: serial@7f005000 {
+			compatible = "samsung,s3c6400-uart";
+			reg = <0x7f005000 0x100>;
+			interrupt-parent = <&vic1>;
+			interrupts = <5>;
+			clock-names = "uart", "clk_uart_baud2",
+					"clk_uart_baud3";
+			clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>,
+					<&clocks SCLK_UART>;
+			status = "disabled";
+		};
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index b7c232e..c023474 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -6,3 +6,6 @@  obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-pll.o
 obj-$(CONFIG_ARCH_EXYNOS4)	+= clk-exynos4.o
 obj-$(CONFIG_SOC_EXYNOS5250)	+= clk-exynos5250.o
 obj-$(CONFIG_SOC_EXYNOS5440)	+= clk-exynos5440.o
+ifdef CONFIG_COMMON_CLK
+obj-$(CONFIG_ARCH_S3C64XX)	+= clk-s3c64xx.o
+endif
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
new file mode 100644
index 0000000..253a972
--- /dev/null
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -0,0 +1,503 @@ 
+/*
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.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 S3C64xx SoCs.
+*/
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+/* S3C64xx clock controller register offsets. */
+#define APLL_LOCK		0x000
+#define MPLL_LOCK		0x004
+#define EPLL_LOCK		0x008
+#define APLL_CON		0x00c
+#define MPLL_CON		0x010
+#define EPLL_CON0		0x014
+#define EPLL_CON1		0x018
+#define CLK_SRC			0x01c
+#define CLK_DIV0		0x020
+#define CLK_DIV1		0x024
+#define CLK_DIV2		0x028
+#define HCLK_GATE		0x030
+#define PCLK_GATE		0x034
+#define SCLK_GATE		0x038
+#define MEM0_GATE		0x03c
+#define CLK_SRC2		0x10c
+#define OTHERS			0x900
+
+/* Special bitfields used in the driver. */
+#define OTHERS_SYNCMUXSEL	(1 << 6)
+
+/* Helper macros to define clock arrays. */
+#define FIXED_RATE_CLOCKS(name)	\
+		static struct samsung_fixed_rate_clock name[]
+#define MUX_CLOCKS(name)	\
+		static struct samsung_mux_clock name[]
+#define DIV_CLOCKS(name)	\
+		static struct samsung_div_clock name[]
+#define GATE_CLOCKS(name)	\
+		static struct samsung_gate_clock name[]
+
+/* Helper macros for gate types present on S3C64xx. */
+#define GATE_BUS(_id, cname, pname, o, b) \
+		GATE(_id, cname, pname, o, b, 0, 0)
+#define GATE_SCLK(_id, cname, pname, o, b) \
+		GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT, 0)
+#define GATE_ON(_id, cname, pname, o, b) \
+		GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0)
+
+/*
+ * List of controller registers to be saved and restored during
+ * a suspend/resume cycle.
+ */
+static __initdata unsigned long s3c64xx_clk_regs[] = {
+	APLL_LOCK,
+	MPLL_LOCK,
+	EPLL_LOCK,
+	APLL_CON,
+	MPLL_CON,
+	EPLL_CON0,
+	EPLL_CON1,
+	CLK_SRC,
+	CLK_DIV0,
+	CLK_DIV1,
+	CLK_DIV2,
+	HCLK_GATE,
+	PCLK_GATE,
+	SCLK_GATE,
+};
+
+static __initdata unsigned long s3c6410_clk_regs[] = {
+	CLK_SRC2,
+	MEM0_GATE,
+};
+
+/* List of parent clocks common for all S3C64xx SoCs. */
+PNAME(spi_mmc_p)	= { "mout_epll", "dout_mpll", "fin_pll", "clk27m" };
+PNAME(uart_p)		= { "mout_epll", "dout_mpll" };
+PNAME(audio0_p)		= { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk0",
+				"pcmcdclk0", "none", "none", "none" };
+PNAME(audio1_p)		= { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk1",
+				"pcmcdclk0", "none", "none", "none" };
+PNAME(mfc_p)		= { "hclkx2", "mout_epll" };
+PNAME(apll_p)		= { "fin_pll", "fout_apll" };
+PNAME(mpll_p)		= { "fin_pll", "fout_mpll" };
+PNAME(epll_p)		= { "fin_pll", "fout_epll" };
+
+/* S3C6400-specific parent clocks. */
+PNAME(scaler_lcd_p6400)	= { "mout_epll", "dout_mpll", "none", "none" };
+PNAME(irda_p6400)	= { "mout_epll", "dout_mpll", "none", "clk48m" };
+PNAME(uhost_p6400)	= { "clk48m", "mout_epll", "dout_mpll", "none" };
+
+/* S3C6410-specific parent clocks. */
+PNAME(clk27_p6410)	= { "clk27m", "fin_pll" };
+PNAME(scaler_lcd_p6410)	= { "mout_epll", "dout_mpll", "fin_pll", "none" };
+PNAME(irda_p6410)	= { "mout_epll", "dout_mpll", "fin_pll", "clk48m" };
+PNAME(uhost_p6410)	= { "clk48m", "mout_epll", "dout_mpll", "fin_pll" };
+PNAME(audio2_p6410)	= { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk2",
+				"pcmcdclk1", "none", "none", "none" };
+
+/* Fixed rate clocks generated outside the SoC. */
+FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_ext_clks) __initdata = {
+	FRATE(FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0),
+	FRATE(0, "xusbxti", NULL, CLK_IS_ROOT, 0),
+};
+
+/* Fixed rate clocks generated inside the SoC. */
+FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_clks) __initdata = {
+	FRATE(CLK27M, "clk27m", NULL, CLK_IS_ROOT, 27000000),
+	FRATE(CLK48M, "clk48m", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* List of clock muxes present on all S3C64xx SoCs. */
+MUX_CLOCKS(s3c64xx_mux_clks) __initdata = {
+	MUX(0, "mout_apll", apll_p, CLK_SRC, 0, 1),
+	MUX(0, "mout_mpll", mpll_p, CLK_SRC, 1, 1),
+	MUX(MOUT_EPLL, "mout_epll", epll_p, CLK_SRC, 2, 1),
+	MUX(0, "mout_mfc", mfc_p, CLK_SRC, 4, 1),
+	MUX(0, "mout_audio0", audio0_p, CLK_SRC, 7, 3),
+	MUX(0, "mout_audio1", audio1_p, CLK_SRC, 10, 3),
+	MUX(0, "mout_uart", uart_p, CLK_SRC, 13, 1),
+	MUX(0, "mout_spi0", spi_mmc_p, CLK_SRC, 14, 2),
+	MUX(0, "mout_spi1", spi_mmc_p, CLK_SRC, 16, 2),
+	MUX(0, "mout_mmc0", spi_mmc_p, CLK_SRC, 18, 2),
+	MUX(0, "mout_mmc1", spi_mmc_p, CLK_SRC, 20, 2),
+	MUX(0, "mout_mmc2", spi_mmc_p, CLK_SRC, 22, 2),
+};
+
+/* List of clock muxes present on S3C6400. */
+MUX_CLOCKS(s3c6400_mux_clks) __initdata = {
+	MUX(0, "mout_uhost", uhost_p6400, CLK_SRC, 5, 2),
+	MUX(0, "mout_irda", irda_p6400, CLK_SRC, 24, 2),
+	MUX(0, "mout_lcd", scaler_lcd_p6400, CLK_SRC, 26, 2),
+	MUX(0, "mout_scaler", scaler_lcd_p6400, CLK_SRC, 28, 2),
+};
+
+/* List of clock muxes present on S3C6410. */
+MUX_CLOCKS(s3c6410_mux_clks) __initdata = {
+	MUX(0, "mout_uhost", uhost_p6410, CLK_SRC, 5, 2),
+	MUX(0, "mout_irda", irda_p6410, CLK_SRC, 24, 2),
+	MUX(0, "mout_lcd", scaler_lcd_p6410, CLK_SRC, 26, 2),
+	MUX(0, "mout_scaler", scaler_lcd_p6410, CLK_SRC, 28, 2),
+	MUX(0, "mout_dac27", clk27_p6410, CLK_SRC, 30, 1),
+	MUX(0, "mout_tv27", clk27_p6410, CLK_SRC, 31, 1),
+	MUX(0, "mout_audio2", audio2_p6410, CLK_SRC2, 0, 3),
+};
+
+/* List of clock dividers present on all S3C64xx SoCs. */
+DIV_CLOCKS(s3c64xx_div_clks) __initdata = {
+	DIV(DOUT_MPLL, "dout_mpll", "mout_mpll", CLK_DIV0, 4, 1),
+	DIV(HCLK, "hclk", "hclkx2", CLK_DIV0, 8, 1),
+	DIV(PCLK, "pclk", "hclkx2", CLK_DIV0, 12, 4),
+	DIV(0, "dout_secur", "hclkx2", CLK_DIV0, 18, 2),
+	DIV(0, "dout_cam", "hclkx2", CLK_DIV0, 20, 4),
+	DIV(0, "dout_jpeg", "hclkx2", CLK_DIV0, 24, 4),
+	DIV(0, "dout_mfc", "mout_mfc", CLK_DIV0, 28, 4),
+	DIV(0, "dout_mmc0", "mout_mmc0", CLK_DIV1, 0, 4),
+	DIV(0, "dout_mmc1", "mout_mmc1", CLK_DIV1, 4, 4),
+	DIV(0, "dout_mmc2", "mout_mmc2", CLK_DIV1, 8, 4),
+	DIV(0, "dout_lcd", "mout_lcd", CLK_DIV1, 12, 4),
+	DIV(0, "dout_scaler", "mout_scaler", CLK_DIV1, 16, 4),
+	DIV(0, "dout_uhost", "mout_uhost", CLK_DIV1, 20, 4),
+	DIV(0, "dout_spi0", "mout_spi0", CLK_DIV2, 0, 4),
+	DIV(0, "dout_spi1", "mout_spi1", CLK_DIV2, 4, 4),
+	DIV(0, "dout_audio0", "mout_audio0", CLK_DIV2, 8, 4),
+	DIV(0, "dout_audio1", "mout_audio1", CLK_DIV2, 12, 4),
+	DIV(0, "dout_uart", "mout_uart", CLK_DIV2, 16, 4),
+	DIV(0, "dout_irda", "mout_irda", CLK_DIV2, 20, 4),
+};
+
+/* List of clock dividers present on S3C6400. */
+DIV_CLOCKS(s3c6400_div_clks) __initdata = {
+	DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 3),
+};
+
+/* List of clock dividers present on S3C6410. */
+DIV_CLOCKS(s3c6410_div_clks) __initdata = {
+	DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 4),
+	DIV(0, "dout_fimc", "hclk", CLK_DIV1, 24, 4),
+	DIV(0, "dout_audio2", "mout_audio2", CLK_DIV2, 24, 4),
+};
+
+/* List of clock gates present on all S3C64xx SoCs. */
+GATE_CLOCKS(s3c64xx_gate_clks) __initdata = {
+	GATE_BUS(HCLK_UHOST, "hclk_uhost", "hclk", HCLK_GATE, 29),
+	GATE_BUS(HCLK_SECUR, "hclk_secur", "hclk", HCLK_GATE, 28),
+	GATE_BUS(HCLK_SDMA1, "hclk_sdma1", "hclk", HCLK_GATE, 27),
+	GATE_BUS(HCLK_SDMA0, "hclk_sdma0", "hclk", HCLK_GATE, 26),
+	GATE_ON(HCLK_DDR1, "hclk_ddr1", "hclk", HCLK_GATE, 24),
+	GATE_BUS(HCLK_USB, "hclk_usb", "hclk", HCLK_GATE, 20),
+	GATE_BUS(HCLK_HSMMC2, "hclk_hsmmc2", "hclk", HCLK_GATE, 19),
+	GATE_BUS(HCLK_HSMMC1, "hclk_hsmmc1", "hclk", HCLK_GATE, 18),
+	GATE_BUS(HCLK_HSMMC0, "hclk_hsmmc0", "hclk", HCLK_GATE, 17),
+	GATE_BUS(HCLK_MDP, "hclk_mdp", "hclk", HCLK_GATE, 16),
+	GATE_BUS(HCLK_DHOST, "hclk_dhost", "hclk", HCLK_GATE, 15),
+	GATE_BUS(HCLK_IHOST, "hclk_ihost", "hclk", HCLK_GATE, 14),
+	GATE_BUS(HCLK_DMA1, "hclk_dma1", "hclk", HCLK_GATE, 13),
+	GATE_BUS(HCLK_DMA0, "hclk_dma0", "hclk", HCLK_GATE, 12),
+	GATE_BUS(HCLK_JPEG, "hclk_jpeg", "hclk", HCLK_GATE, 11),
+	GATE_BUS(HCLK_CAMIF, "hclk_camif", "hclk", HCLK_GATE, 10),
+	GATE_BUS(HCLK_SCALER, "hclk_scaler", "hclk", HCLK_GATE, 9),
+	GATE_BUS(HCLK_2D, "hclk_2d", "hclk", HCLK_GATE, 8),
+	GATE_BUS(HCLK_TV, "hclk_tv", "hclk", HCLK_GATE, 7),
+	GATE_BUS(HCLK_POST0, "hclk_post0", "hclk", HCLK_GATE, 5),
+	GATE_BUS(HCLK_ROT, "hclk_rot", "hclk", HCLK_GATE, 4),
+	GATE_BUS(HCLK_LCD, "hclk_lcd", "hclk", HCLK_GATE, 3),
+	GATE_BUS(HCLK_TZIC, "hclk_tzic", "hclk", HCLK_GATE, 2),
+	GATE_ON(HCLK_INTC, "hclk_intc", "hclk", HCLK_GATE, 1),
+	GATE_ON(PCLK_SKEY, "pclk_skey", "pclk", PCLK_GATE, 24),
+	GATE_ON(PCLK_CHIPID, "pclk_chipid", "pclk", PCLK_GATE, 23),
+	GATE_BUS(PCLK_SPI1, "pclk_spi1", "pclk", PCLK_GATE, 22),
+	GATE_BUS(PCLK_SPI0, "pclk_spi0", "pclk", PCLK_GATE, 21),
+	GATE_BUS(PCLK_HSIRX, "pclk_hsirx", "pclk", PCLK_GATE, 20),
+	GATE_BUS(PCLK_HSITX, "pclk_hsitx", "pclk", PCLK_GATE, 19),
+	GATE_ON(PCLK_GPIO, "pclk_gpio", "pclk", PCLK_GATE, 18),
+	GATE_BUS(PCLK_IIC0, "pclk_iic0", "pclk", PCLK_GATE, 17),
+	GATE_BUS(PCLK_IIS1, "pclk_iis1", "pclk", PCLK_GATE, 16),
+	GATE_BUS(PCLK_IIS0, "pclk_iis0", "pclk", PCLK_GATE, 15),
+	GATE_BUS(PCLK_AC97, "pclk_ac97", "pclk", PCLK_GATE, 14),
+	GATE_BUS(PCLK_TZPC, "pclk_tzpc", "pclk", PCLK_GATE, 13),
+	GATE_BUS(PCLK_TSADC, "pclk_tsadc", "pclk", PCLK_GATE, 12),
+	GATE_BUS(PCLK_KEYPAD, "pclk_keypad", "pclk", PCLK_GATE, 11),
+	GATE_BUS(PCLK_IRDA, "pclk_irda", "pclk", PCLK_GATE, 10),
+	GATE_BUS(PCLK_PCM1, "pclk_pcm1", "pclk", PCLK_GATE, 9),
+	GATE_BUS(PCLK_PCM0, "pclk_pcm0", "pclk", PCLK_GATE, 8),
+	GATE_BUS(PCLK_PWM, "pclk_pwm", "pclk", PCLK_GATE, 7),
+	GATE_BUS(PCLK_RTC, "pclk_rtc", "pclk", PCLK_GATE, 6),
+	GATE_BUS(PCLK_WDT, "pclk_wdt", "pclk", PCLK_GATE, 5),
+	GATE_BUS(PCLK_UART3, "pclk_uart3", "pclk", PCLK_GATE, 4),
+	GATE_BUS(PCLK_UART2, "pclk_uart2", "pclk", PCLK_GATE, 3),
+	GATE_BUS(PCLK_UART1, "pclk_uart1", "pclk", PCLK_GATE, 2),
+	GATE_BUS(PCLK_UART0, "pclk_uart0", "pclk", PCLK_GATE, 1),
+	GATE_BUS(PCLK_MFC, "pclk_mfc", "pclk", PCLK_GATE, 0),
+	GATE_SCLK(SCLK_UHOST, "sclk_uhost", "dout_uhost", SCLK_GATE, 30),
+	GATE_SCLK(SCLK_MMC2_48, "sclk_mmc2_48", "clk48m", SCLK_GATE, 29),
+	GATE_SCLK(SCLK_MMC1_48, "sclk_mmc1_48", "clk48m", SCLK_GATE, 28),
+	GATE_SCLK(SCLK_MMC0_48, "sclk_mmc0_48", "clk48m", SCLK_GATE, 27),
+	GATE_SCLK(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", SCLK_GATE, 26),
+	GATE_SCLK(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", SCLK_GATE, 25),
+	GATE_SCLK(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", SCLK_GATE, 24),
+	GATE_SCLK(SCLK_SPI1_48, "sclk_spi1_48", "clk48m", SCLK_GATE, 23),
+	GATE_SCLK(SCLK_SPI0_48, "sclk_spi0_48", "clk48m", SCLK_GATE, 22),
+	GATE_SCLK(SCLK_SPI1, "sclk_spi1", "dout_spi1", SCLK_GATE, 21),
+	GATE_SCLK(SCLK_SPI0, "sclk_spi0", "dout_spi0", SCLK_GATE, 20),
+	GATE_SCLK(SCLK_DAC27, "sclk_dac27", "mout_dac27", SCLK_GATE, 19),
+	GATE_SCLK(SCLK_TV27, "sclk_tv27", "mout_tv27", SCLK_GATE, 18),
+	GATE_SCLK(SCLK_SCALER27, "sclk_scaler27", "clk27m", SCLK_GATE, 17),
+	GATE_SCLK(SCLK_SCALER, "sclk_scaler", "dout_scaler", SCLK_GATE, 16),
+	GATE_SCLK(SCLK_LCD27, "sclk_lcd27", "clk27m", SCLK_GATE, 15),
+	GATE_SCLK(SCLK_LCD, "sclk_lcd", "dout_lcd", SCLK_GATE, 14),
+	GATE_SCLK(SCLK_POST0_27, "sclk_post0_27", "clk27m", SCLK_GATE, 12),
+	GATE_SCLK(SCLK_POST0, "sclk_post0", "dout_lcd", SCLK_GATE, 10),
+	GATE_SCLK(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", SCLK_GATE, 9),
+	GATE_SCLK(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", SCLK_GATE, 8),
+	GATE_SCLK(SCLK_SECUR, "sclk_secur", "dout_secur", SCLK_GATE, 7),
+	GATE_SCLK(SCLK_IRDA, "sclk_irda", "dout_irda", SCLK_GATE, 6),
+	GATE_SCLK(SCLK_UART, "sclk_uart", "dout_uart", SCLK_GATE, 5),
+	GATE_SCLK(SCLK_MFC, "sclk_mfc", "dout_mfc", SCLK_GATE, 3),
+	GATE_SCLK(SCLK_CAM, "sclk_cam", "dout_cam", SCLK_GATE, 2),
+	GATE_SCLK(SCLK_JPEG, "sclk_jpeg", "dout_jpeg", SCLK_GATE, 1),
+};
+
+/* List of clock gates present on S3C6400. */
+GATE_CLOCKS(s3c6400_gate_clks) __initdata = {
+	GATE_ON(HCLK_DDR0, "hclk_ddr0", "hclk", HCLK_GATE, 23),
+	GATE_SCLK(SCLK_ONENAND, "sclk_onenand", "parent", SCLK_GATE, 4),
+};
+
+/* List of clock gates present on S3C6410. */
+GATE_CLOCKS(s3c6410_gate_clks) __initdata = {
+	GATE_BUS(HCLK_3DSE, "hclk_3dse", "hclk", HCLK_GATE, 31),
+	GATE_ON(HCLK_IROM, "hclk_irom", "hclk", HCLK_GATE, 25),
+	GATE_ON(HCLK_MEM1, "hclk_mem1", "hclk", HCLK_GATE, 22),
+	GATE_ON(HCLK_MEM0, "hclk_mem0", "hclk", HCLK_GATE, 21),
+	GATE_BUS(HCLK_MFC, "hclk_mfc", "hclk", HCLK_GATE, 0),
+	GATE_BUS(PCLK_IIC1, "pclk_iic1", "pclk", PCLK_GATE, 27),
+	GATE_BUS(PCLK_IIS2, "pclk_iis2", "pclk", PCLK_GATE, 26),
+	GATE_SCLK(SCLK_FIMC, "sclk_fimc", "dout_fimc", SCLK_GATE, 13),
+	GATE_SCLK(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", SCLK_GATE, 11),
+	GATE_BUS(MEM0_CFCON, "mem0_cfcon", "hclk_mem0", MEM0_GATE, 5),
+	GATE_BUS(MEM0_ONENAND1, "mem0_onenand1", "hclk_mem0", MEM0_GATE, 4),
+	GATE_BUS(MEM0_ONENAND0, "mem0_onenand0", "hclk_mem0", MEM0_GATE, 3),
+	GATE_BUS(MEM0_NFCON, "mem0_nfcon", "hclk_mem0", MEM0_GATE, 2),
+	GATE_ON(MEM0_SROM, "mem0_srom", "hclk_mem0", MEM0_GATE, 1),
+};
+
+/* Aliases for common s3c64xx clocks. */
+static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
+	ALIAS(MOUT_EPLL, NULL, "mout_epll"),
+	ALIAS(DOUT_MPLL, NULL, "dout_mpll"),
+	ALIAS(HCLKX2, NULL, "hclk2"),
+	ALIAS(HCLK, NULL, "hclk"),
+	ALIAS(PCLK, NULL, "pclk"),
+	ALIAS(PCLK, NULL, "clk_uart_baud2"),
+	ALIAS(ARMCLK, NULL, "armclk"),
+	ALIAS(HCLK_UHOST, "s3c2410-ohci", "usb-host"),
+	ALIAS(HCLK_USB, "s3c-hsotg", "otg"),
+	ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "hsmmc"),
+	ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "mmc_busclk.0"),
+	ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
+	ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
+	ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
+	ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
+	ALIAS(HCLK_DMA1, NULL, "dma1"),
+	ALIAS(HCLK_DMA0, NULL, "dma0"),
+	ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
+	ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
+	ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
+	ALIAS(PCLK_SPI0, "s3c6410-spi.0", "spi"),
+	ALIAS(PCLK_IIC0, "s3c2440-i2c.0", "i2c"),
+	ALIAS(PCLK_IIS1, "samsung-i2s.1", "iis"),
+	ALIAS(PCLK_IIS0, "samsung-i2s.0", "iis"),
+	ALIAS(PCLK_AC97, "samsung-ac97", "ac97"),
+	ALIAS(PCLK_TSADC, "s3c64xx-adc", "adc"),
+	ALIAS(PCLK_KEYPAD, "samsung-keypad", "keypad"),
+	ALIAS(PCLK_PCM1, "samsung-pcm.1", "pcm"),
+	ALIAS(PCLK_PCM0, "samsung-pcm.0", "pcm"),
+	ALIAS(PCLK_PWM, NULL, "timers"),
+	ALIAS(PCLK_RTC, "s3c64xx-rtc", "rtc"),
+	ALIAS(PCLK_WDT, NULL, "watchdog"),
+	ALIAS(PCLK_UART3, "s3c6400-uart.3", "uart"),
+	ALIAS(PCLK_UART2, "s3c6400-uart.2", "uart"),
+	ALIAS(PCLK_UART1, "s3c6400-uart.1", "uart"),
+	ALIAS(PCLK_UART0, "s3c6400-uart.0", "uart"),
+	ALIAS(SCLK_UHOST, "s3c2410-ohci", "usb-bus-host"),
+	ALIAS(SCLK_MMC2, "s3c-sdhci.2", "mmc_busclk.2"),
+	ALIAS(SCLK_MMC1, "s3c-sdhci.1", "mmc_busclk.2"),
+	ALIAS(SCLK_MMC0, "s3c-sdhci.0", "mmc_busclk.2"),
+	ALIAS(SCLK_SPI1, "s3c6410-spi.1", "spi-bus"),
+	ALIAS(SCLK_SPI0, "s3c6410-spi.0", "spi-bus"),
+	ALIAS(SCLK_AUDIO1, "samsung-pcm.1", "audio-bus"),
+	ALIAS(SCLK_AUDIO1, "samsung-i2s.1", "audio-bus"),
+	ALIAS(SCLK_AUDIO0, "samsung-pcm.0", "audio-bus"),
+	ALIAS(SCLK_AUDIO0, "samsung-i2s.0", "audio-bus"),
+	ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
+	ALIAS(SCLK_CAM, "s3c-camif", "camera"),
+};
+
+/* Aliases for s3c6400-specific clocks. */
+static struct samsung_clock_alias s3c6400_clock_aliases[] = {
+	/* Nothing to place here yet. */
+};
+
+/* Aliases for s3c6410-specific clocks. */
+static struct samsung_clock_alias s3c6410_clock_aliases[] = {
+	ALIAS(PCLK_IIC1, "s3c2440-i2c.1", "i2c"),
+	ALIAS(PCLK_IIS2, "samsung-i2s.2", "iis"),
+	ALIAS(SCLK_FIMC, "s3c-camif", "fimc"),
+	ALIAS(SCLK_AUDIO2, "samsung-i2s.2", "audio-bus"),
+	ALIAS(MEM0_SROM, NULL, "srom"),
+};
+
+/*
+ * Parent of the hclkx2 clock depends on whether the SoC is operating in
+ * synchronous or asynchronous mode. Depending on value of OTHERS[6]
+ * (SYNCMUXSEL) bit, it can be either mout_mpll or mout_apll.
+ */
+static void __init s3c64xx_clk_register_hclkx2(void __iomem *reg_base)
+{
+	struct samsung_div_clock hclkx2;
+	u32 others;
+
+	memset(&hclkx2, 0, sizeof(hclkx2));
+
+	hclkx2.id = HCLKX2;
+	hclkx2.name = "hclkx2";
+	hclkx2.offset = CLK_DIV0;
+	hclkx2.shift = 9;
+	hclkx2.width = 3;
+
+	others = readl(reg_base + OTHERS);
+	if (others & OTHERS_SYNCMUXSEL)
+		hclkx2.parent_name = "mout_apll";
+	else
+		hclkx2.parent_name = "mout_mpll";
+
+	samsung_clk_register_div(&hclkx2, 1);
+}
+
+static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f,
+							unsigned long xusbxti_f)
+{
+	s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f;
+	s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
+	samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks,
+				ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks));
+}
+
+static __initdata struct of_device_id ext_clk_match[] = {
+	{ .compatible = "samsung,clock-fin-pll", .data = (void *)0, },
+	{ .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
+	{},
+};
+
+/* Register s3c64xx clocks. */
+void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
+		unsigned long xusbxti_f, bool is_s3c6400, void __iomem *reg_base)
+{
+	struct clk *clk;
+	unsigned long *soc_regs = NULL;
+	unsigned long nr_soc_regs = 0;
+
+	if (np) {
+		reg_base = of_iomap(np, 0);
+		if (!reg_base)
+			panic("%s: failed to map registers\n", __func__);
+	}
+
+	if (!is_s3c6400) {
+		soc_regs = s3c6410_clk_regs;
+		nr_soc_regs = ARRAY_SIZE(s3c6410_clk_regs);
+	}
+
+	samsung_clk_init(np, reg_base, NR_CLKS, s3c64xx_clk_regs,
+			ARRAY_SIZE(s3c64xx_clk_regs), soc_regs, nr_soc_regs);
+
+	/* Register external clocks. */
+	if (np)
+		samsung_clk_of_register_fixed_ext(s3c64xx_fixed_rate_ext_clks,
+			ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks),
+			ext_clk_match);
+	else
+		s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f);
+
+	/* Register PLLs. */
+	clk = samsung_clk_register_pll6552("fout_apll",
+					"fin_pll", reg_base + APLL_LOCK);
+	samsung_clk_add_lookup(clk, FOUT_APLL);
+
+	clk = samsung_clk_register_pll6552("fout_mpll",
+					"fin_pll", reg_base + MPLL_LOCK);
+	samsung_clk_add_lookup(clk, FOUT_MPLL);
+
+	clk = samsung_clk_register_pll6553("fout_epll",
+					"fin_pll", reg_base + EPLL_LOCK);
+	samsung_clk_add_lookup(clk, FOUT_EPLL);
+
+	/* Register common internal clocks. */
+	s3c64xx_clk_register_hclkx2(reg_base);
+
+	samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks,
+					ARRAY_SIZE(s3c64xx_fixed_rate_clks));
+	samsung_clk_register_mux(s3c64xx_mux_clks,
+					ARRAY_SIZE(s3c64xx_mux_clks));
+	samsung_clk_register_div(s3c64xx_div_clks,
+					ARRAY_SIZE(s3c64xx_div_clks));
+	samsung_clk_register_gate(s3c64xx_gate_clks,
+					ARRAY_SIZE(s3c64xx_gate_clks));
+
+	/* Register SoC-specific clocks. */
+	if (is_s3c6400) {
+		samsung_clk_register_mux(s3c6400_mux_clks,
+					ARRAY_SIZE(s3c6400_mux_clks));
+		samsung_clk_register_div(s3c6400_div_clks,
+					ARRAY_SIZE(s3c6400_div_clks));
+		samsung_clk_register_gate(s3c6400_gate_clks,
+					ARRAY_SIZE(s3c6400_gate_clks));
+		samsung_clk_register_alias(s3c6400_clock_aliases,
+					ARRAY_SIZE(s3c6400_clock_aliases));
+	} else {
+		samsung_clk_register_mux(s3c6410_mux_clks,
+					ARRAY_SIZE(s3c6410_mux_clks));
+		samsung_clk_register_div(s3c6410_div_clks,
+					ARRAY_SIZE(s3c6410_div_clks));
+		samsung_clk_register_gate(s3c6410_gate_clks,
+					ARRAY_SIZE(s3c6410_gate_clks));
+		samsung_clk_register_alias(s3c6410_clock_aliases,
+					ARRAY_SIZE(s3c6410_clock_aliases));
+	}
+
+	samsung_clk_register_alias(s3c64xx_clock_aliases,
+					ARRAY_SIZE(s3c64xx_clock_aliases));
+
+	pr_info("%s clocks: apll = %lu, mpll = %lu\n"
+		"\tepll = %lu, arm_clk = %lu\n",
+		is_s3c6400 ? "S3C6400" : "S3C6410",
+		_get_rate("fout_apll"),	_get_rate("fout_mpll"),
+		_get_rate("fout_epll"), _get_rate("armclk"));
+}
+
+static void __init s3c6400_clk_init(struct device_node *np)
+{
+	s3c64xx_clk_init(np, 0, 0, true, NULL);
+}
+CLK_OF_DECLARE(s3c6400_clk, "samsung,s3c6400-clock", s3c6400_clk_init);
+
+static void __init s3c6410_clk_init(struct device_node *np)
+{
+	s3c64xx_clk_init(np, 0, 0, false, NULL);
+}
+CLK_OF_DECLARE(s3c6410_clk, "samsung,s3c6410-clock", s3c6410_clk_init);
diff --git a/include/dt-bindings/clock/samsung,s3c64xx-clock.h b/include/dt-bindings/clock/samsung,s3c64xx-clock.h
new file mode 100644
index 0000000..3e9a1f9
--- /dev/null
+++ b/include/dt-bindings/clock/samsung,s3c64xx-clock.h
@@ -0,0 +1,144 @@ 
+/*
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.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.
+ *
+ * Device Tree binding constants for Samsung S3C64xx clock controller.
+*/
+
+#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
+#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
+
+/*
+ * Let each exported clock get a unique index, which is used on DT-enabled
+ * platforms to lookup the clock from a clock specifier. These indices are
+ * therefore considered an ABI and so must not be changed. This implies
+ * that new clocks should be added either in free spaces between clock groups
+ * or at the end.
+ */
+
+/* Core clocks. */
+#define IISCDCLK0		3
+#define PCMCDCLK0		4
+#define IISCDCLK1		5
+#define PCMCDCLK1		6
+#define IISCDCLK2		7
+#define CLK27M			8
+#define CLK48M			9
+#define FIN_PLL			10
+#define FOUT_APLL		11
+#define FOUT_MPLL		12
+#define FOUT_EPLL		13
+#define ARMCLK			14
+#define HCLKX2			15
+#define HCLK			16
+#define PCLK			17
+#define MOUT_EPLL		18
+#define DOUT_MPLL		19
+
+/* HCLK bus clocks. */
+#define HCLK_3DSE		32
+#define HCLK_UHOST		33
+#define HCLK_SECUR		34
+#define HCLK_SDMA1		35
+#define HCLK_SDMA0		36
+#define HCLK_IROM		37
+#define HCLK_DDR1		38
+#define HCLK_MEM1		39
+#define HCLK_MEM0		40
+#define HCLK_USB		41
+#define HCLK_HSMMC2		42
+#define HCLK_HSMMC1		43
+#define HCLK_HSMMC0		44
+#define HCLK_MDP		45
+#define HCLK_DHOST		46
+#define HCLK_IHOST		47
+#define HCLK_DMA1		48
+#define HCLK_DMA0		49
+#define HCLK_JPEG		50
+#define HCLK_CAMIF		51
+#define HCLK_SCALER		52
+#define HCLK_2D			53
+#define HCLK_TV			54
+#define HCLK_POST0		55
+#define HCLK_ROT		56
+#define HCLK_LCD		57
+#define HCLK_TZIC		58
+#define HCLK_INTC		59
+#define HCLK_MFC		60
+#define HCLK_DDR0		61
+
+/* PCLK bus clocks. */
+#define PCLK_IIC1		64
+#define PCLK_IIS2		65
+#define PCLK_SKEY		66
+#define PCLK_CHIPID		67
+#define PCLK_SPI1		68
+#define PCLK_SPI0		69
+#define PCLK_HSIRX		70
+#define PCLK_HSITX		71
+#define PCLK_GPIO		72
+#define PCLK_IIC0		73
+#define PCLK_IIS1		74
+#define PCLK_IIS0		75
+#define PCLK_AC97		76
+#define PCLK_TZPC		77
+#define PCLK_TSADC		78
+#define PCLK_KEYPAD		79
+#define PCLK_IRDA		80
+#define PCLK_PCM1		81
+#define PCLK_PCM0		82
+#define PCLK_PWM		83
+#define PCLK_RTC		84
+#define PCLK_WDT		85
+#define PCLK_UART3		86
+#define PCLK_UART2		87
+#define PCLK_UART1		88
+#define PCLK_UART0		89
+#define PCLK_MFC		90
+
+/* Special clocks. */
+#define SCLK_UHOST		96
+#define SCLK_MMC2_48		97
+#define SCLK_MMC1_48		98
+#define SCLK_MMC0_48		99
+#define SCLK_MMC2		100
+#define SCLK_MMC1		101
+#define SCLK_MMC0		102
+#define SCLK_SPI1_48		103
+#define SCLK_SPI0_48		104
+#define SCLK_SPI1		105
+#define SCLK_SPI0		106
+#define SCLK_DAC27		107
+#define SCLK_TV27		108
+#define SCLK_SCALER27		109
+#define SCLK_SCALER		110
+#define SCLK_LCD27		111
+#define SCLK_LCD		112
+#define SCLK_FIMC		113
+#define SCLK_POST0_27		114
+#define SCLK_AUDIO2		115
+#define SCLK_POST0		116
+#define SCLK_AUDIO1		117
+#define SCLK_AUDIO0		118
+#define SCLK_SECUR		119
+#define SCLK_IRDA		120
+#define SCLK_UART		121
+#define SCLK_MFC		122
+#define SCLK_CAM		123
+#define SCLK_JPEG		124
+#define SCLK_ONENAND		125
+
+/* MEM0 bus clocks - S3C6410-specific. */
+#define MEM0_CFCON		128
+#define MEM0_ONENAND1		129
+#define MEM0_ONENAND0		130
+#define MEM0_NFCON		131
+#define MEM0_SROM		132
+
+/* Total number of clocks. */
+#define NR_CLKS			(MEM0_SROM + 1)
+
+#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H */