[PATCH 2/7] clk: samsung: Add clock driver for S3C64xx SoCs
Tomasz Figa
tomasz.figa at gmail.com
Wed Jun 12 02:26:54 EDT 2013
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 at 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 at 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 at 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 */
More information about the linux-arm-kernel
mailing list