From 06654acb6698a92bb7e6deb6897006ed501cdc47 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:25:36 +0900 Subject: [PATCH 01/23] clk: samsung: add pll_6552 variant for s3c2416 According to the manual s3c2416 and s3c2450 use a pll 6552 and 6553 and while the pll_6553 matches exactly the one already implemented the pll_6552 differs to the one from the s3c64xx series. The change is solely in the bit locations of the mdiv and pdiv values. All calculations are the same for both implementatons and even the proposed divider-values for specific frequencies in the manuals are the same. Therefore implement a variant that simply uses the changed bit locations if necessary. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Acked-by: Mike Turquette Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-pll.c | 12 ++++++++++-- drivers/clk/samsung/clk-pll.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 81e6d2f49aa0..f9a35a612705 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -564,7 +564,9 @@ static const struct clk_ops samsung_pll46xx_clk_min_ops = { #define PLL6552_PDIV_MASK 0x3f #define PLL6552_SDIV_MASK 0x7 #define PLL6552_MDIV_SHIFT 16 +#define PLL6552_MDIV_SHIFT_2416 14 #define PLL6552_PDIV_SHIFT 8 +#define PLL6552_PDIV_SHIFT_2416 5 #define PLL6552_SDIV_SHIFT 0 static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, @@ -575,8 +577,13 @@ static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, u64 fvco = parent_rate; pll_con = __raw_readl(pll->con_reg); - mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; - pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; + if (pll->type == pll_6552_s3c2416) { + mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK; + pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK; + } else { + mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; + pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; + } sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK; fvco *= mdiv; @@ -773,6 +780,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, init.ops = &samsung_pll36xx_clk_ops; break; case pll_6552: + case pll_6552_s3c2416: init.ops = &samsung_pll6552_clk_ops; break; case pll_6553: diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 6c39030080fb..ddf9029c13c9 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -24,6 +24,7 @@ enum samsung_pll_type { pll_4650, pll_4650c, pll_6552, + pll_6552_s3c2416, pll_6553, }; From a951b1d91dcca8d373c92666c5e006de8234d34b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:25:41 +0900 Subject: [PATCH 02/23] clk: samsung: add plls used by the s3c2443 The s3c2443 uses different plls that are not present yet. Therefore add the two needed types. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Acked-by: Mike Turquette Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-pll.c | 72 +++++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk-pll.h | 2 + 2 files changed, 74 insertions(+) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index f9a35a612705..8c9c015a4538 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -58,6 +58,72 @@ static long samsung_pll_round_rate(struct clk_hw *hw, return rate_table[i - 1].rate; } +/* + * PLL2126 Clock Type + */ + +#define PLL2126_MDIV_MASK (0xff) +#define PLL2126_PDIV_MASK (0x3f) +#define PLL2126_SDIV_MASK (0x3) +#define PLL2126_MDIV_SHIFT (16) +#define PLL2126_PDIV_SHIFT (8) +#define PLL2126_SDIV_SHIFT (0) + +static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK; + pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK; + sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK; + + fvco *= (mdiv + 8); + do_div(fvco, (pdiv + 2) << sdiv); + + return (unsigned long)fvco; +} + +static const struct clk_ops samsung_pll2126_clk_ops = { + .recalc_rate = samsung_pll2126_recalc_rate, +}; + +/* + * PLL3000 Clock Type + */ + +#define PLL3000_MDIV_MASK (0xff) +#define PLL3000_PDIV_MASK (0x3) +#define PLL3000_SDIV_MASK (0x3) +#define PLL3000_MDIV_SHIFT (16) +#define PLL3000_PDIV_SHIFT (8) +#define PLL3000_SDIV_SHIFT (0) + +static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK; + pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK; + sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK; + + fvco *= (2 * (mdiv + 8)); + do_div(fvco, pdiv << sdiv); + + return (unsigned long)fvco; +} + +static const struct clk_ops samsung_pll3000_clk_ops = { + .recalc_rate = samsung_pll3000_recalc_rate, +}; + /* * PLL35xx Clock Type */ @@ -753,6 +819,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, } switch (pll_clk->type) { + case pll_2126: + init.ops = &samsung_pll2126_clk_ops; + break; + case pll_3000: + init.ops = &samsung_pll3000_clk_ops; + break; /* clk_ops for 35xx and 2550 are similar */ case pll_35xx: case pll_2550: diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index ddf9029c13c9..5b64bdbb0906 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -13,6 +13,8 @@ #define __SAMSUNG_CLK_PLL_H enum samsung_pll_type { + pll_2126, + pll_3000, pll_35xx, pll_36xx, pll_2550, From 78435c812afa70b8ddee789c7f37fc88738079a0 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:25:45 +0900 Subject: [PATCH 03/23] dt-bindings: add binding for clock-controller of s3c2443 and following Starting with the s3c2443 the s3c24xx series got a new clock tree compared to the previous s3c24xx socs. This binding describes the clock controller found in the s3c2443, s3c2416 and s3c2450 socs. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Signed-off-by: Kukjin Kim --- .../bindings/clock/samsung,s3c2443-clock.txt | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt new file mode 100644 index 000000000000..e67bb05478af --- /dev/null +++ b/Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt @@ -0,0 +1,56 @@ +* Samsung S3C2443 Clock Controller + +The S3C2443 clock controller generates and supplies clock to various controllers +within the SoC. The clock binding described here is applicable to all SoCs in +the s3c24x family starting with the s3c2443. + +Required Properties: + +- compatible: should be one of the following. + - "samsung,s3c2416-clock" - controller compatible with S3C2416 SoC. + - "samsung,s3c2443-clock" - controller compatible with S3C2443 SoC. + - "samsung,s3c2450-clock" - controller compatible with S3C2450 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 SoC. + +All available clocks are defined as preprocessor macros in +dt-bindings/clock/s3c2443.h header and can be used in device +tree sources. + +External clocks: + +There are several clocks that are generated outside the SoC. It is expected +that they are defined using standard clock bindings with following +clock-output-names: + - "xti" - crystal input - required, + - "ext" - external clock source - optional, + - "ext_i2s" - external I2S clock - optional, + - "ext_uart" - external uart clock - optional, + +Example: Clock controller node: + + clocks: clock-controller@4c000000 { + compatible = "samsung,s3c2416-clock"; + reg = <0x4c000000 0x40>; + #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): + + serial@50004000 { + compatible = "samsung,s3c2440-uart"; + reg = <0x50004000 0x4000>; + interrupts = <1 23 3 4>, <1 23 4 4>; + clock-names = "uart", "clk_uart_baud2", + "clk_uart_baud3"; + clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>, + <&clocks SCLK_UART>; + status = "disabled"; + }; From 61fbb1d278cf09f29d67629b139b3ca08acbf177 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:25:49 +0900 Subject: [PATCH 04/23] clk: samsung: add clock-driver for s3c2416, s3c2443 and s3c2450 The three SoCs share a common clock tree which only differs in the existence of some special clocks. As with all parts common to these three SoCs the driver is named after the s3c2443, as it was the first SoC introducing this structure and there exists no other label to describe this s3c24xx epoch. The clock structure is built according to the manuals of the included SoCs and might include changes in comparison to the previous clock structure. As an example the sclk_uart gate was never handled previously and the div_uart was made to be the clock used by the serial driver. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 6 + drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-s3c2443.c | 462 ++++++++++++++++++++++++++++ include/dt-bindings/clock/s3c2443.h | 92 ++++++ 4 files changed, 561 insertions(+) create mode 100644 drivers/clk/samsung/clk-s3c2443.c create mode 100644 include/dt-bindings/clock/s3c2443.h diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 40cf50b9940c..abf9179c9d03 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -647,6 +647,12 @@ config S3C2443_COMMON Common code for the S3C2443 and similar processors, which includes the S3C2416 and S3C2450. +config S3C2443_COMMON_CLK + bool + help + Temporary symbol to build the clock driver based on the common clock + framework. + config S3C2443_DMA bool help diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 8eb4799237f0..4c892c63a8dd 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -8,4 +8,5 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o +obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c new file mode 100644 index 000000000000..8e4f4517e95c --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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 S3C2443 and following SoCs. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "clk-pll.h" + +/* S3C2416 clock controller register offsets */ +#define LOCKCON0 0x00 +#define LOCKCON1 0x04 +#define MPLLCON 0x10 +#define EPLLCON 0x18 +#define EPLLCON_K 0x1C +#define CLKSRC 0x20 +#define CLKDIV0 0x24 +#define CLKDIV1 0x28 +#define CLKDIV2 0x2C +#define HCLKCON 0x30 +#define PCLKCON 0x34 +#define SCLKCON 0x38 + +/* the soc types */ +enum supported_socs { + S3C2416, + S3C2443, + S3C2450, +}; + +/* list of PLLs to be registered */ +enum s3c2443_plls { + mpll, epll, +}; + +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *s3c2443_save; + +/* + * list of controller registers to be saved and restored during a + * suspend/resume cycle. + */ +static unsigned long s3c2443_clk_regs[] __initdata = { + LOCKCON0, + LOCKCON1, + MPLLCON, + EPLLCON, + EPLLCON_K, + CLKSRC, + CLKDIV0, + CLKDIV1, + CLKDIV2, + PCLKCON, + HCLKCON, + SCLKCON, +}; + +static int s3c2443_clk_suspend(void) +{ + samsung_clk_save(reg_base, s3c2443_save, + ARRAY_SIZE(s3c2443_clk_regs)); + + return 0; +} + +static void s3c2443_clk_resume(void) +{ + samsung_clk_restore(reg_base, s3c2443_save, + ARRAY_SIZE(s3c2443_clk_regs)); +} + +static struct syscore_ops s3c2443_clk_syscore_ops = { + .suspend = s3c2443_clk_suspend, + .resume = s3c2443_clk_resume, +}; + +static void s3c2443_clk_sleep_init(void) +{ + s3c2443_save = samsung_clk_alloc_reg_dump(s3c2443_clk_regs, + ARRAY_SIZE(s3c2443_clk_regs)); + if (!s3c2443_save) { + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; + } + + register_syscore_ops(&s3c2443_clk_syscore_ops); + return; +} +#else +static void s3c2443_clk_sleep_init(void) {} +#endif + +PNAME(epllref_p) = { "mpllref", "mpllref", "xti", "ext" }; +PNAME(esysclk_p) = { "epllref", "epll" }; +PNAME(mpllref_p) = { "xti", "mdivclk" }; +PNAME(msysclk_p) = { "mpllref", "mpll" }; +PNAME(armclk_p) = { "armdiv" , "hclk" }; +PNAME(i2s0_p) = { "div_i2s0", "ext_i2s", "epllref", "epllref" }; + +struct samsung_mux_clock s3c2443_common_muxes[] __initdata = { + MUX(0, "epllref", epllref_p, CLKSRC, 7, 2), + MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1), + MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1), + MUX_A(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1, "msysclk"), + MUX_A(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1, "armclk"), + MUX(0, "mux_i2s0", i2s0_p, CLKSRC, 14, 2), +}; + +static struct clk_div_table hclk_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 3, .div = 4 }, + { /* sentinel */ }, +}; + +static struct clk_div_table mdivclk_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 3 }, + { .val = 2, .div = 5 }, + { .val = 3, .div = 7 }, + { .val = 4, .div = 9 }, + { .val = 5, .div = 11 }, + { .val = 6, .div = 13 }, + { .val = 7, .div = 15 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2443_common_dividers[] __initdata = { + DIV_T(0, "mdivclk", "xti", CLKDIV0, 6, 3, mdivclk_d), + DIV(0, "prediv", "msysclk", CLKDIV0, 4, 2), + DIV_T(HCLK, "hclk", "prediv", CLKDIV0, 0, 2, hclk_d), + DIV(PCLK, "pclk", "hclk", CLKDIV0, 2, 1), + DIV(0, "div_hsspi0_epll", "esysclk", CLKDIV1, 24, 2), + DIV(0, "div_fimd", "esysclk", CLKDIV1, 16, 8), + DIV(0, "div_i2s0", "esysclk", CLKDIV1, 12, 4), + DIV(0, "div_uart", "esysclk", CLKDIV1, 8, 4), + DIV(0, "div_hsmmc1", "esysclk", CLKDIV1, 6, 2), + DIV(0, "div_usbhost", "esysclk", CLKDIV1, 4, 2), +}; + +struct samsung_gate_clock s3c2443_common_gates[] __initdata = { + GATE(SCLK_HSMMC_EXT, "sclk_hsmmcext", "ext", SCLKCON, 13, 0, 0), + GATE(SCLK_HSMMC1, "sclk_hsmmc1", "div_hsmmc1", SCLKCON, 12, 0, 0), + GATE(SCLK_FIMD, "sclk_fimd", "div_fimd", SCLKCON, 10, 0, 0), + GATE(SCLK_I2S0, "sclk_i2s0", "mux_i2s0", SCLKCON, 9, 0, 0), + GATE(SCLK_UART, "sclk_uart", "div_uart", SCLKCON, 8, 0, 0), + GATE(SCLK_USBH, "sclk_usbhost", "div_usbhost", SCLKCON, 1, 0, 0), + GATE(HCLK_DRAM, "dram", "hclk", HCLKCON, 19, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_SSMC, "ssmc", "hclk", HCLKCON, 18, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_HSMMC1, "hsmmc1", "hclk", HCLKCON, 16, 0, 0), + GATE(HCLK_USBD, "usb-device", "hclk", HCLKCON, 12, 0, 0), + GATE(HCLK_USBH, "usb-host", "hclk", HCLKCON, 11, 0, 0), + GATE(HCLK_LCD, "lcd", "hclk", HCLKCON, 9, 0, 0), + GATE(HCLK_DMA5, "dma5", "hclk", HCLKCON, 5, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA4, "dma4", "hclk", HCLKCON, 4, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA3, "dma3", "hclk", HCLKCON, 3, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA2, "dma2", "hclk", HCLKCON, 2, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA1, "dma1", "hclk", HCLKCON, 1, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA0, "dma0", "hclk", HCLKCON, 0, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_GPIO, "gpio", "pclk", PCLKCON, 13, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_RTC, "rtc", "pclk", PCLKCON, 12, 0, 0), + GATE(PCLK_WDT, "wdt", "pclk", PCLKCON, 11, 0, 0), + GATE(PCLK_PWM, "pwm", "pclk", PCLKCON, 10, 0, 0), + GATE(PCLK_I2S0, "i2s0", "pclk", PCLKCON, 9, 0, 0), + GATE(PCLK_AC97, "ac97", "pclk", PCLKCON, 8, 0, 0), + GATE(PCLK_ADC, "adc", "pclk", PCLKCON, 7, 0, 0), + GATE(PCLK_SPI0, "spi0", "pclk", PCLKCON, 6, 0, 0), + GATE(PCLK_I2C0, "i2c0", "pclk", PCLKCON, 4, 0, 0), + GATE(PCLK_UART3, "uart3", "pclk", PCLKCON, 3, 0, 0), + GATE(PCLK_UART2, "uart2", "pclk", PCLKCON, 2, 0, 0), + GATE(PCLK_UART1, "uart1", "pclk", PCLKCON, 1, 0, 0), + GATE(PCLK_UART0, "uart0", "pclk", PCLKCON, 0, 0, 0), +}; + +struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { + ALIAS(HCLK, NULL, "hclk"), + ALIAS(HCLK_SSMC, NULL, "nand"), + ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"), + ALIAS(PCLK_UART3, "s3c2440-uart.3", "uart"), + ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"), + ALIAS(PCLK_UART3, "s3c2440-uart.3", "clk_uart_baud2"), + ALIAS(SCLK_UART, NULL, "clk_uart_baud3"), + ALIAS(PCLK_PWM, NULL, "timers"), + ALIAS(PCLK_RTC, NULL, "rtc"), + ALIAS(PCLK_WDT, NULL, "watchdog"), + ALIAS(PCLK_ADC, NULL, "adc"), + ALIAS(PCLK_I2C0, "s3c2410-i2c.0", "i2c"), + ALIAS(HCLK_USBD, NULL, "usb-device"), + ALIAS(HCLK_USBH, NULL, "usb-host"), + ALIAS(SCLK_USBH, NULL, "usb-bus-host"), + ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi"), + ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi_busclk0"), + ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"), + ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"), + ALIAS(PCLK_I2S0, "samsung-i2s.0", "iis"), + ALIAS(SCLK_I2S0, NULL, "i2s-if"), + ALIAS(HCLK_LCD, NULL, "lcd"), + ALIAS(SCLK_FIMD, NULL, "sclk_fimd"), +}; + +/* S3C2416 specific clocks */ + +static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = { + [mpll] = PLL(pll_6552_s3c2416, 0, "mpll", "mpllref", + LOCKCON0, MPLLCON, NULL), + [epll] = PLL(pll_6553, 0, "epll", "epllref", + LOCKCON1, EPLLCON, NULL), +}; + +PNAME(s3c2416_hsmmc0_p) = { "sclk_hsmmc0", "sclk_hsmmcext" }; +PNAME(s3c2416_hsmmc1_p) = { "sclk_hsmmc1", "sclk_hsmmcext" }; +PNAME(s3c2416_hsspi0_p) = { "hsspi0_epll", "hsspi0_mpll" }; + +static struct clk_div_table armdiv_s3c2416_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 3 }, + { .val = 3, .div = 4 }, + { .val = 5, .div = 6 }, + { .val = 7, .div = 8 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2416_dividers[] __initdata = { + DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 3, armdiv_s3c2416_d), + DIV(0, "div_hsspi0_mpll", "msysclk", CLKDIV2, 0, 4), + DIV(0, "div_hsmmc0", "esysclk", CLKDIV2, 6, 2), +}; + +struct samsung_mux_clock s3c2416_muxes[] __initdata = { + MUX(MUX_HSMMC0, "mux_hsmmc0", s3c2416_hsmmc0_p, CLKSRC, 16, 1), + MUX(MUX_HSMMC1, "mux_hsmmc1", s3c2416_hsmmc1_p, CLKSRC, 17, 1), + MUX(MUX_HSSPI0, "mux_hsspi0", s3c2416_hsspi0_p, CLKSRC, 18, 1), +}; + +struct samsung_gate_clock s3c2416_gates[] __initdata = { + GATE(0, "hsspi0_mpll", "div_hsspi0_mpll", SCLKCON, 19, 0, 0), + GATE(0, "hsspi0_epll", "div_hsspi0_epll", SCLKCON, 14, 0, 0), + GATE(0, "sclk_hsmmc0", "div_hsmmc0", SCLKCON, 6, 0, 0), + GATE(HCLK_2D, "2d", "hclk", HCLKCON, 20, 0, 0), + GATE(HCLK_HSMMC0, "hsmmc0", "hclk", HCLKCON, 15, 0, 0), + GATE(HCLK_IROM, "irom", "hclk", HCLKCON, 13, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_PCM, "pcm", "pclk", PCLKCON, 19, 0, 0), +}; + +struct samsung_clock_alias s3c2416_aliases[] __initdata = { + ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"), + ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"), + ALIAS(MUX_HSMMC0, "s3c-sdhci.0", "mmc_busclk.2"), + ALIAS(MUX_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"), + ALIAS(MUX_HSSPI0, "s3c2443-spi.0", "spi_busclk2"), + ALIAS(ARMDIV, NULL, "armdiv"), +}; + +/* S3C2443 specific clocks */ + +static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = { + [mpll] = PLL(pll_3000, 0, "mpll", "mpllref", + LOCKCON0, MPLLCON, NULL), + [epll] = PLL(pll_2126, 0, "epll", "epllref", + LOCKCON1, EPLLCON, NULL), +}; + +static struct clk_div_table armdiv_s3c2443_d[] = { + { .val = 0, .div = 1 }, + { .val = 8, .div = 2 }, + { .val = 2, .div = 3 }, + { .val = 9, .div = 4 }, + { .val = 10, .div = 6 }, + { .val = 11, .div = 8 }, + { .val = 13, .div = 12 }, + { .val = 15, .div = 16 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2443_dividers[] __initdata = { + DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 4, armdiv_s3c2443_d), + DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4), +}; + +struct samsung_gate_clock s3c2443_gates[] __initdata = { + GATE(SCLK_HSSPI0, "sclk_hsspi0", "div_hsspi0_epll", SCLKCON, 14, 0, 0), + GATE(SCLK_CAM, "sclk_cam", "div_cam", SCLKCON, 11, 0, 0), + GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0), + GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 15, 0, 0), + GATE(PCLK_SDI, "sdi", "pclk", PCLKCON, 5, 0, 0), +}; + +struct samsung_clock_alias s3c2443_aliases[] __initdata = { + ALIAS(SCLK_HSSPI0, "s3c2443-spi.0", "spi_busclk2"), + ALIAS(SCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"), + ALIAS(SCLK_CAM, NULL, "camif-upll"), + ALIAS(PCLK_SPI1, "s3c2410-spi.0", "spi"), + ALIAS(PCLK_SDI, NULL, "sdi"), + ALIAS(HCLK_CFC, NULL, "cfc"), + ALIAS(ARMDIV, NULL, "armdiv"), +}; + +/* S3C2450 specific clocks */ + +PNAME(s3c2450_cam_p) = { "div_cam", "hclk" }; +PNAME(s3c2450_hsspi1_p) = { "hsspi1_epll", "hsspi1_mpll" }; +PNAME(i2s1_p) = { "div_i2s1", "ext_i2s", "epllref", "epllref" }; + +struct samsung_div_clock s3c2450_dividers[] __initdata = { + DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4), + DIV(0, "div_hsspi1_epll", "esysclk", CLKDIV2, 24, 2), + DIV(0, "div_hsspi1_mpll", "msysclk", CLKDIV2, 16, 4), + DIV(0, "div_i2s1", "esysclk", CLKDIV2, 12, 4), +}; + +struct samsung_mux_clock s3c2450_muxes[] __initdata = { + MUX(0, "mux_cam", s3c2450_cam_p, CLKSRC, 20, 1), + MUX(MUX_HSSPI1, "mux_hsspi1", s3c2450_hsspi1_p, CLKSRC, 19, 1), + MUX(0, "mux_i2s1", i2s1_p, CLKSRC, 12, 2), +}; + +struct samsung_gate_clock s3c2450_gates[] __initdata = { + GATE(SCLK_I2S1, "sclk_i2s1", "div_i2s1", SCLKCON, 5, 0, 0), + GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, 0, 0), + GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0), + GATE(HCLK_DMA7, "dma7", "hclk", HCLKCON, 7, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA6, "dma6", "hclk", HCLKCON, 6, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_I2S1, "i2s1", "pclk", PCLKCON, 17, 0, 0), + GATE(PCLK_I2C1, "i2c1", "pclk", PCLKCON, 16, 0, 0), + GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 14, 0, 0), +}; + +struct samsung_clock_alias s3c2450_aliases[] __initdata = { + ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi"), + ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi_busclk0"), + ALIAS(MUX_HSSPI1, "s3c2443-spi.1", "spi_busclk2"), + ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"), +}; + +/* + * fixed rate clocks generated outside the soc + * Only necessary until the devicetree-move is complete + */ +struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = { + FRATE(0, "xti", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext_i2s", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext_uart", NULL, CLK_IS_ROOT, 0), +}; + +static void __init s3c2443_common_clk_register_fixed_ext(unsigned long xti_f) +{ + s3c2443_common_frate_clks[0].fixed_rate = xti_f; + samsung_clk_register_fixed_rate(s3c2443_common_frate_clks, + ARRAY_SIZE(s3c2443_common_frate_clks)); +} + +void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, + int current_soc, + void __iomem *base) +{ + reg_base = base; + + if (np) { + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + } + + samsung_clk_init(np, reg_base, NR_CLKS); + + /* Register external clocks only in non-dt cases */ + if (!np) + s3c2443_common_clk_register_fixed_ext(xti_f); + + /* Register PLLs. */ + if (current_soc == S3C2416 || current_soc == S3C2450) + samsung_clk_register_pll(s3c2416_pll_clks, + ARRAY_SIZE(s3c2416_pll_clks), reg_base); + else + samsung_clk_register_pll(s3c2443_pll_clks, + ARRAY_SIZE(s3c2443_pll_clks), reg_base); + + /* Register common internal clocks. */ + samsung_clk_register_mux(s3c2443_common_muxes, + ARRAY_SIZE(s3c2443_common_muxes)); + samsung_clk_register_div(s3c2443_common_dividers, + ARRAY_SIZE(s3c2443_common_dividers)); + samsung_clk_register_gate(s3c2443_common_gates, + ARRAY_SIZE(s3c2443_common_gates)); + samsung_clk_register_alias(s3c2443_common_aliases, + ARRAY_SIZE(s3c2443_common_aliases)); + + /* Register SoC-specific clocks. */ + switch (current_soc) { + case S3C2450: + samsung_clk_register_div(s3c2450_dividers, + ARRAY_SIZE(s3c2450_dividers)); + samsung_clk_register_mux(s3c2450_muxes, + ARRAY_SIZE(s3c2450_muxes)); + samsung_clk_register_gate(s3c2450_gates, + ARRAY_SIZE(s3c2450_gates)); + samsung_clk_register_alias(s3c2450_aliases, + ARRAY_SIZE(s3c2450_aliases)); + /* fall through, as s3c2450 extends the s3c2416 clocks */ + case S3C2416: + samsung_clk_register_div(s3c2416_dividers, + ARRAY_SIZE(s3c2416_dividers)); + samsung_clk_register_mux(s3c2416_muxes, + ARRAY_SIZE(s3c2416_muxes)); + samsung_clk_register_gate(s3c2416_gates, + ARRAY_SIZE(s3c2416_gates)); + samsung_clk_register_alias(s3c2416_aliases, + ARRAY_SIZE(s3c2416_aliases)); + break; + case S3C2443: + samsung_clk_register_div(s3c2443_dividers, + ARRAY_SIZE(s3c2443_dividers)); + samsung_clk_register_gate(s3c2443_gates, + ARRAY_SIZE(s3c2443_gates)); + samsung_clk_register_alias(s3c2443_aliases, + ARRAY_SIZE(s3c2443_aliases)); + break; + } + + s3c2443_clk_sleep_init(); +} + +static void __init s3c2416_clk_init(struct device_node *np) +{ + s3c2443_common_clk_init(np, 0, S3C2416, 0); +} +CLK_OF_DECLARE(s3c2416_clk, "samsung,s3c2416-clock", s3c2416_clk_init); + +static void __init s3c2443_clk_init(struct device_node *np) +{ + s3c2443_common_clk_init(np, 0, S3C2443, 0); +} +CLK_OF_DECLARE(s3c2443_clk, "samsung,s3c2443-clock", s3c2443_clk_init); + +static void __init s3c2450_clk_init(struct device_node *np) +{ + s3c2443_common_clk_init(np, 0, S3C2450, 0); +} +CLK_OF_DECLARE(s3c2450_clk, "samsung,s3c2450-clock", s3c2450_clk_init); diff --git a/include/dt-bindings/clock/s3c2443.h b/include/dt-bindings/clock/s3c2443.h new file mode 100644 index 000000000000..37e66b054d64 --- /dev/null +++ b/include/dt-bindings/clock/s3c2443.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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 clock controllers of Samsung S3C2443 and later. + */ + +#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H +#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_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 MSYSCLK 1 +#define ESYSCLK 2 +#define ARMDIV 3 +#define ARMCLK 4 +#define HCLK 5 +#define PCLK 6 + +/* Special clocks */ +#define SCLK_HSSPI0 16 +#define SCLK_FIMD 17 +#define SCLK_I2S0 18 +#define SCLK_I2S1 19 +#define SCLK_HSMMC1 20 +#define SCLK_HSMMC_EXT 21 +#define SCLK_CAM 22 +#define SCLK_UART 23 +#define SCLK_USBH 24 + +/* Muxes */ +#define MUX_HSSPI0 32 +#define MUX_HSSPI1 33 +#define MUX_HSMMC0 34 +#define MUX_HSMMC1 35 + +/* hclk-gates */ +#define HCLK_DMA0 48 +#define HCLK_DMA1 49 +#define HCLK_DMA2 50 +#define HCLK_DMA3 51 +#define HCLK_DMA4 52 +#define HCLK_DMA5 53 +#define HCLK_DMA6 54 +#define HCLK_DMA7 55 +#define HCLK_CAM 56 +#define HCLK_LCD 57 +#define HCLK_USBH 58 +#define HCLK_USBD 59 +#define HCLK_IROM 60 +#define HCLK_HSMMC0 61 +#define HCLK_HSMMC1 62 +#define HCLK_CFC 63 +#define HCLK_SSMC 64 +#define HCLK_DRAM 65 +#define HCLK_2D 66 + +/* pclk-gates */ +#define PCLK_UART0 72 +#define PCLK_UART1 73 +#define PCLK_UART2 74 +#define PCLK_UART3 75 +#define PCLK_I2C0 76 +#define PCLK_SDI 77 +#define PCLK_SPI0 78 +#define PCLK_ADC 79 +#define PCLK_AC97 80 +#define PCLK_I2S0 81 +#define PCLK_PWM 82 +#define PCLK_WDT 83 +#define PCLK_RTC 84 +#define PCLK_GPIO 85 +#define PCLK_SPI1 86 +#define PCLK_CHIPID 87 +#define PCLK_I2C1 88 +#define PCLK_I2S1 89 +#define PCLK_PCM 90 + +/* Total number of clocks. */ +#define NR_CLKS (PCLK_PCM + 1) + +#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H */ From 5ab9a428cf1d118779554b6a20161d7b339310db Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:25:54 +0900 Subject: [PATCH 05/23] ARM: S3C24XX: prevent conflicts between ccf and non-ccf s3c24xx-socs As the conversion to the common-clock-framework is done in multiple steps, it is necessary to prevent conflicts between the different struct clk implementations. For this include the s3c24xx_setup_clocks function only when SAMSUNG_CLOCK is selected and make the socs we don't convert this time explicitly depend on SAMSUNG_CLOCK, which gets only selected automatically if COMMON_CLK is not enabled. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 4 ++++ arch/arm/mach-s3c24xx/common.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index abf9179c9d03..f10af7faec98 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -25,6 +25,7 @@ comment "S3C24XX SoCs" config CPU_S3C2410 bool "SAMSUNG S3C2410" default y + depends on SAMSUNG_CLOCK select CPU_ARM920T select CPU_LLSERIAL_S3C2410 select S3C2410_CLOCK @@ -38,6 +39,7 @@ config CPU_S3C2410 config CPU_S3C2412 bool "SAMSUNG S3C2412" + depends on SAMSUNG_CLOCK select CPU_ARM926T select CPU_LLSERIAL_S3C2440 select S3C2412_DMA if S3C24XX_DMA @@ -58,6 +60,7 @@ config CPU_S3C2416 config CPU_S3C2440 bool "SAMSUNG S3C2440" + depends on SAMSUNG_CLOCK select CPU_ARM920T select CPU_LLSERIAL_S3C2440 select S3C2410_CLOCK @@ -68,6 +71,7 @@ config CPU_S3C2440 config CPU_S3C2442 bool "SAMSUNG S3C2442" + depends on SAMSUNG_CLOCK select CPU_ARM920T select CPU_LLSERIAL_S3C2440 select S3C2410_CLOCK diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 1bc8e73c94f9..0fc6641ac57d 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -318,6 +318,7 @@ struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = { /* initialise all the clocks */ +#ifdef CONFIG_SAMSUNG_CLOCK void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk, unsigned long hclk, unsigned long pclk) @@ -330,6 +331,7 @@ void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk, clk_p.rate = pclk; clk_f.rate = fclk; } +#endif #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \ defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) From 8cb28748154db139180ea4e24252530aecc3745b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:26:17 +0900 Subject: [PATCH 06/23] ARM: dts: add clock data for s3c2416 This adds the clock controller itself, the xti clock on the smdk2416 as well as the clock references in the individual device nodes. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/s3c2416-smdk2416.dts | 13 ++++++++ arch/arm/boot/dts/s3c2416.dtsi | 42 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/arch/arm/boot/dts/s3c2416-smdk2416.dts b/arch/arm/boot/dts/s3c2416-smdk2416.dts index 59594cf15998..ea92fd69529a 100644 --- a/arch/arm/boot/dts/s3c2416-smdk2416.dts +++ b/arch/arm/boot/dts/s3c2416-smdk2416.dts @@ -19,6 +19,19 @@ reg = <0x30000000 0x4000000>; }; + clocks { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + xti: xti { + compatible = "fixed-clock"; + clock-frequency = <12000000>; + clock-output-names = "xti"; + #clock-cells = <0>; + }; + }; + serial@50000000 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/s3c2416.dtsi b/arch/arm/boot/dts/s3c2416.dtsi index e6555bdd81b8..955e4a4f8c31 100644 --- a/arch/arm/boot/dts/s3c2416.dtsi +++ b/arch/arm/boot/dts/s3c2416.dtsi @@ -8,6 +8,7 @@ * published by the Free Software Foundation. */ +#include #include "s3c24xx.dtsi" #include "s3c2416-pinctrl.dtsi" @@ -28,26 +29,53 @@ compatible = "samsung,s3c2416-irq"; }; + clocks: clock-controller@0x4c000000 { + compatible = "samsung,s3c2416-clock"; + reg = <0x4c000000 0x40>; + #clock-cells = <1>; + }; + pinctrl@56000000 { compatible = "samsung,s3c2416-pinctrl"; }; + timer@51000000 { + clocks = <&clocks PCLK_PWM>; + clock-names = "timers"; + }; + serial@50000000 { compatible = "samsung,s3c2440-uart"; + clock-names = "uart", "clk_uart_baud2", + "clk_uart_baud3"; + clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>, + <&clocks SCLK_UART>; }; serial@50004000 { compatible = "samsung,s3c2440-uart"; + clock-names = "uart", "clk_uart_baud2", + "clk_uart_baud3"; + clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>, + <&clocks SCLK_UART>; }; serial@50008000 { compatible = "samsung,s3c2440-uart"; + clock-names = "uart", "clk_uart_baud2", + "clk_uart_baud3"; + clocks = <&clocks PCLK_UART2>, <&clocks PCLK_UART2>, + <&clocks SCLK_UART>; }; serial@5000C000 { compatible = "samsung,s3c2440-uart"; reg = <0x5000C000 0x4000>; interrupts = <1 18 24 4>, <1 18 25 4>; + clock-names = "uart", "clk_uart_baud2", + "clk_uart_baud3"; + clocks = <&clocks PCLK_UART3>, <&clocks PCLK_UART3>, + <&clocks SCLK_UART>; status = "disabled"; }; @@ -55,6 +83,10 @@ compatible = "samsung,s3c6410-sdhci"; reg = <0x4AC00000 0x100>; interrupts = <0 0 21 3>; + clock-names = "hsmmc", "mmc_busclk.0", + "mmc_busclk.2"; + clocks = <&clocks HCLK_HSMMC0>, <&clocks HCLK_HSMMC0>, + <&clocks MUX_HSMMC0>; status = "disabled"; }; @@ -62,18 +94,28 @@ compatible = "samsung,s3c6410-sdhci"; reg = <0x4A800000 0x100>; interrupts = <0 0 20 3>; + clock-names = "hsmmc", "mmc_busclk.0", + "mmc_busclk.2"; + clocks = <&clocks HCLK_HSMMC1>, <&clocks HCLK_HSMMC1>, + <&clocks MUX_HSMMC1>; status = "disabled"; }; watchdog@53000000 { interrupts = <1 9 27 3>; + clocks = <&clocks PCLK_WDT>; + clock-names = "watchdog"; }; rtc@57000000 { compatible = "samsung,s3c2416-rtc"; + clocks = <&clocks PCLK_RTC>; + clock-names = "rtc"; }; i2c@54000000 { compatible = "samsung,s3c2440-i2c"; + clocks = <&clocks PCLK_I2C0>; + clock-names = "i2c"; }; }; From dfc0f5099a83f8633fc4480e2f0e8e5f6ac1331d Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:26:21 +0900 Subject: [PATCH 07/23] ARM: S3C24XX: Convert s3c2416 and s3c2443 to common clock framework This converts the mentioned platforms to use the newly introduced driver for the common clock framework for them. With this the whole legacy clock structure can go away too. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 14 +- arch/arm/mach-s3c24xx/Makefile | 5 +- arch/arm/mach-s3c24xx/clock-s3c2416.c | 171 ------ arch/arm/mach-s3c24xx/clock-s3c2443.c | 212 -------- arch/arm/mach-s3c24xx/common-s3c2443.c | 675 ------------------------ arch/arm/mach-s3c24xx/common.c | 16 +- arch/arm/mach-s3c24xx/common.h | 6 + arch/arm/mach-s3c24xx/mach-s3c2416-dt.c | 38 +- arch/arm/mach-s3c24xx/mach-smdk2416.c | 9 +- arch/arm/mach-s3c24xx/mach-smdk2443.c | 9 +- 10 files changed, 41 insertions(+), 1114 deletions(-) delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2416.c delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2443.c delete mode 100644 arch/arm/mach-s3c24xx/common-s3c2443.c diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index f10af7faec98..52f1c40ccf07 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -49,12 +49,12 @@ config CPU_S3C2412 config CPU_S3C2416 bool "SAMSUNG S3C2416/S3C2450" + select COMMON_CLK select CPU_ARM926T select CPU_LLSERIAL_S3C2440 select S3C2416_PM if PM - select S3C2443_COMMON + select S3C2443_COMMON_CLK select S3C2443_DMA if S3C24XX_DMA - select SAMSUNG_CLKSRC help Support for the S3C2416 SoC from the S3C24XX line @@ -87,11 +87,11 @@ config CPU_S3C244X config CPU_S3C2443 bool "SAMSUNG S3C2443" + select COMMON_CLK select CPU_ARM920T select CPU_LLSERIAL_S3C2440 - select S3C2443_COMMON + select S3C2443_COMMON_CLK select S3C2443_DMA if S3C24XX_DMA - select SAMSUNG_CLKSRC help Support for the S3C2443 SoC from the S3C24XX line @@ -645,12 +645,6 @@ endif # CPU_S3C2442 if CPU_S3C2443 || CPU_S3C2416 -config S3C2443_COMMON - bool - help - Common code for the S3C2443 and similar processors, which includes - the S3C2416 and S3C2450. - config S3C2443_COMMON_CLK bool help diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index 7f54e5b954ca..ba0e5475a807 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o -obj-$(CONFIG_CPU_S3C2416) += s3c2416.o clock-s3c2416.o +obj-$(CONFIG_CPU_S3C2416) += s3c2416.o obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o obj-$(CONFIG_CPU_S3C2440) += s3c2440.o clock-s3c2440.o @@ -36,7 +36,7 @@ obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o -obj-$(CONFIG_CPU_S3C2443) += s3c2443.o clock-s3c2443.o +obj-$(CONFIG_CPU_S3C2443) += s3c2443.o # PM @@ -53,7 +53,6 @@ obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o obj-$(CONFIG_S3C2410_IOTIMING) += iotiming-s3c2410.o obj-$(CONFIG_S3C2412_IOTIMING) += iotiming-s3c2412.o -obj-$(CONFIG_S3C2443_COMMON) += common-s3c2443.o obj-$(CONFIG_S3C2443_DMA) += dma-s3c2443.o # diff --git a/arch/arm/mach-s3c24xx/clock-s3c2416.c b/arch/arm/mach-s3c24xx/clock-s3c2416.c deleted file mode 100644 index d421a72920a5..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c2416.c +++ /dev/null @@ -1,171 +0,0 @@ -/* linux/arch/arm/mach-s3c2416/clock.c - * - * Copyright (c) 2010 Simtec Electronics - * Copyright (c) 2010 Ben Dooks - * - * S3C2416 Clock control support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include -#include - -/* armdiv - * - * this clock is sourced from msysclk and can have a number of - * divider values applied to it to then be fed into armclk. - * The real clock definition is done in s3c2443-clock.c, - * only the armdiv divisor table must be defined here. -*/ - -static unsigned int armdiv[8] = { - [0] = 1, - [1] = 2, - [2] = 3, - [3] = 4, - [5] = 6, - [7] = 8, -}; - -static struct clksrc_clk hsspi_eplldiv = { - .clk = { - .name = "hsspi-eplldiv", - .parent = &clk_esysclk.clk, - .ctrlbit = (1 << 14), - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 24 }, -}; - -static struct clk *hsspi_sources[] = { - [0] = &hsspi_eplldiv.clk, - [1] = NULL, /* to fix */ -}; - -static struct clksrc_clk hsspi_mux = { - .clk = { - .name = "hsspi-if", - }, - .sources = &(struct clksrc_sources) { - .sources = hsspi_sources, - .nr_sources = ARRAY_SIZE(hsspi_sources), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 18 }, -}; - -static struct clksrc_clk hsmmc_div[] = { - [0] = { - .clk = { - .name = "hsmmc-div", - .devname = "s3c-sdhci.0", - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2416_CLKDIV2, .size = 2, .shift = 6 }, - }, - [1] = { - .clk = { - .name = "hsmmc-div", - .devname = "s3c-sdhci.1", - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 }, - }, -}; - -static struct clksrc_clk hsmmc_mux0 = { - .clk = { - .name = "hsmmc-if", - .devname = "s3c-sdhci.0", - .ctrlbit = (1 << 6), - .enable = s3c2443_clkcon_enable_s, - }, - .sources = &(struct clksrc_sources) { - .nr_sources = 2, - .sources = (struct clk * []) { - [0] = &hsmmc_div[0].clk, - [1] = NULL, /* to fix */ - }, - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 16 }, -}; - -static struct clksrc_clk hsmmc_mux1 = { - .clk = { - .name = "hsmmc-if", - .devname = "s3c-sdhci.1", - .ctrlbit = (1 << 12), - .enable = s3c2443_clkcon_enable_s, - }, - .sources = &(struct clksrc_sources) { - .nr_sources = 2, - .sources = (struct clk * []) { - [0] = &hsmmc_div[1].clk, - [1] = NULL, /* to fix */ - }, - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 17 }, -}; - -static struct clk hsmmc0_clk = { - .name = "hsmmc", - .devname = "s3c-sdhci.0", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2416_HCLKCON_HSMMC0, -}; - -static struct clksrc_clk *clksrcs[] __initdata = { - &hsspi_eplldiv, - &hsspi_mux, - &hsmmc_div[0], - &hsmmc_div[1], - &hsmmc_mux0, - &hsmmc_mux1, -}; - -static struct clk_lookup s3c2416_clk_lookup[] = { - CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &hsmmc0_clk), - CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &hsmmc_mux0.clk), - CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &hsmmc_mux1.clk), - /* s3c2443-spi.0 is used on s3c2416 and s3c2450 as well */ - CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &hsspi_mux.clk), -}; - -void __init s3c2416_init_clocks(int xtal) -{ - u32 epllcon = __raw_readl(S3C2443_EPLLCON); - u32 epllcon1 = __raw_readl(S3C2443_EPLLCON+4); - int ptr; - - /* s3c2416 EPLL compatible with s3c64xx */ - clk_epll.rate = s3c_get_pll6553x(xtal, epllcon, epllcon1); - - clk_epll.parent = &clk_epllref.clk; - - s3c2443_common_init_clocks(xtal, s3c2416_get_pll, - armdiv, ARRAY_SIZE(armdiv), - S3C2416_CLKDIV0_ARMDIV_MASK); - - for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) - s3c_register_clksrc(clksrcs[ptr], 1); - - s3c24xx_register_clock(&hsmmc0_clk); - clkdev_add_table(s3c2416_clk_lookup, ARRAY_SIZE(s3c2416_clk_lookup)); - -} diff --git a/arch/arm/mach-s3c24xx/clock-s3c2443.c b/arch/arm/mach-s3c24xx/clock-s3c2443.c deleted file mode 100644 index 76cd31f7804e..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c2443.c +++ /dev/null @@ -1,212 +0,0 @@ -/* linux/arch/arm/mach-s3c2443/clock.c - * - * Copyright (c) 2007, 2010 Simtec Electronics - * Ben Dooks - * - * S3C2443 Clock control support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#include - -#include -#include -#include - -/* We currently have to assume that the system is running - * from the XTPll input, and that all ***REFCLKs are being - * fed from it, as we cannot read the state of OM[4] from - * software. - * - * It would be possible for each board initialisation to - * set the correct muxing at initialisation -*/ - -/* clock selections */ - -/* armdiv - * - * this clock is sourced from msysclk and can have a number of - * divider values applied to it to then be fed into armclk. - * The real clock definition is done in s3c2443-clock.c, - * only the armdiv divisor table must be defined here. -*/ - -static unsigned int armdiv[16] = { - [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1, - [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2, - [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3, - [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4, - [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6, - [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8, - [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12, - [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16, -}; - -/* hsspi - * - * high-speed spi clock, sourced from esysclk -*/ - -static struct clksrc_clk clk_hsspi = { - .clk = { - .name = "hsspi-if", - .parent = &clk_esysclk.clk, - .ctrlbit = S3C2443_SCLKCON_HSSPICLK, - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 }, -}; - - -/* clk_hsmcc_div - * - * this clock is sourced from epll, and is fed through a divider, - * to a mux controlled by sclkcon where either it or a extclk can - * be fed to the hsmmc block -*/ - -static struct clksrc_clk clk_hsmmc_div = { - .clk = { - .name = "hsmmc-div", - .devname = "s3c-sdhci.1", - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 }, -}; - -static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2443_SCLKCON); - - clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT | - S3C2443_SCLKCON_HSMMCCLK_EPLL); - - if (parent == &clk_epll) - clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL; - else if (parent == &clk_ext) - clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT; - else - return -EINVAL; - - if (clk->usage > 0) { - __raw_writel(clksrc, S3C2443_SCLKCON); - } - - clk->parent = parent; - return 0; -} - -static int s3c2443_enable_hsmmc(struct clk *clk, int enable) -{ - return s3c2443_setparent_hsmmc(clk, clk->parent); -} - -static struct clk clk_hsmmc = { - .name = "hsmmc-if", - .devname = "s3c-sdhci.1", - .parent = &clk_hsmmc_div.clk, - .enable = s3c2443_enable_hsmmc, - .ops = &(struct clk_ops) { - .set_parent = s3c2443_setparent_hsmmc, - }, -}; - -/* standard clock definitions */ - -static struct clk init_clocks_off[] = { - { - .name = "sdi", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_SDI, - }, { - .name = "spi", - .devname = "s3c2410-spi.0", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_SPI1, - } -}; - -/* clocks to add straight away */ - -static struct clksrc_clk *clksrcs[] __initdata = { - &clk_hsspi, - &clk_hsmmc_div, -}; - -static struct clk *clks[] __initdata = { - &clk_hsmmc, -}; - -static struct clk_lookup s3c2443_clk_lookup[] = { - CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_hsmmc), - CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &clk_hsspi.clk), -}; - -void __init s3c2443_init_clocks(int xtal) -{ - unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); - int ptr; - - clk_epll.rate = s3c2443_get_epll(epllcon, xtal); - clk_epll.parent = &clk_epllref.clk; - - s3c2443_common_init_clocks(xtal, s3c2443_get_mpll, - armdiv, ARRAY_SIZE(armdiv), - S3C2443_CLKDIV0_ARMDIV_MASK); - - s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); - - for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) - s3c_register_clksrc(clksrcs[ptr], 1); - - /* We must be careful disabling the clocks we are not intending to - * be using at boot time, as subsystems such as the LCD which do - * their own DMA requests to the bus can cause the system to lockup - * if they where in the middle of requesting bus access. - * - * Disabling the LCD clock if the LCD is active is very dangerous, - * and therefore the bootloader should be careful to not enable - * the LCD clock if it is not needed. - */ - - /* install (and disable) the clocks we do not need immediately */ - - s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - clkdev_add_table(s3c2443_clk_lookup, ARRAY_SIZE(s3c2443_clk_lookup)); -} diff --git a/arch/arm/mach-s3c24xx/common-s3c2443.c b/arch/arm/mach-s3c24xx/common-s3c2443.c deleted file mode 100644 index 65d3eef73090..000000000000 --- a/arch/arm/mach-s3c24xx/common-s3c2443.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * Common code for SoCs starting with the S3C2443 - * - * Copyright (c) 2007, 2010 Simtec Electronics - * Ben Dooks - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include - -#include - -#include -#include -#include - -#include - - -static int s3c2443_gate(void __iomem *reg, struct clk *clk, int enable) -{ - u32 ctrlbit = clk->ctrlbit; - u32 con = __raw_readl(reg); - - if (enable) - con |= ctrlbit; - else - con &= ~ctrlbit; - - __raw_writel(con, reg); - return 0; -} - -int s3c2443_clkcon_enable_h(struct clk *clk, int enable) -{ - return s3c2443_gate(S3C2443_HCLKCON, clk, enable); -} - -int s3c2443_clkcon_enable_p(struct clk *clk, int enable) -{ - return s3c2443_gate(S3C2443_PCLKCON, clk, enable); -} - -int s3c2443_clkcon_enable_s(struct clk *clk, int enable) -{ - return s3c2443_gate(S3C2443_SCLKCON, clk, enable); -} - -/* mpllref is a direct descendant of clk_xtal by default, but it is not - * elided as the EPLL can be either sourced by the XTAL or EXTCLK and as - * such directly equating the two source clocks is impossible. - */ -static struct clk clk_mpllref = { - .name = "mpllref", - .parent = &clk_xtal, -}; - -static struct clk *clk_epllref_sources[] = { - [0] = &clk_mpllref, - [1] = &clk_mpllref, - [2] = &clk_xtal, - [3] = &clk_ext, -}; - -struct clksrc_clk clk_epllref = { - .clk = { - .name = "epllref", - }, - .sources = &(struct clksrc_sources) { - .sources = clk_epllref_sources, - .nr_sources = ARRAY_SIZE(clk_epllref_sources), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 }, -}; - -/* esysclk - * - * this is sourced from either the EPLL or the EPLLref clock -*/ - -static struct clk *clk_sysclk_sources[] = { - [0] = &clk_epllref.clk, - [1] = &clk_epll, -}; - -struct clksrc_clk clk_esysclk = { - .clk = { - .name = "esysclk", - .parent = &clk_epll, - }, - .sources = &(struct clksrc_sources) { - .sources = clk_sysclk_sources, - .nr_sources = ARRAY_SIZE(clk_sysclk_sources), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 6 }, -}; - -static unsigned long s3c2443_getrate_mdivclk(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long div = __raw_readl(S3C2443_CLKDIV0); - - div &= S3C2443_CLKDIV0_EXTDIV_MASK; - div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1); /* x2 */ - - return parent_rate / (div + 1); -} - -static struct clk clk_mdivclk = { - .name = "mdivclk", - .parent = &clk_mpllref, - .ops = &(struct clk_ops) { - .get_rate = s3c2443_getrate_mdivclk, - }, -}; - -static struct clk *clk_msysclk_sources[] = { - [0] = &clk_mpllref, - [1] = &clk_mpll, - [2] = &clk_mdivclk, - [3] = &clk_mpllref, -}; - -static struct clksrc_clk clk_msysclk = { - .clk = { - .name = "msysclk", - .parent = &clk_xtal, - }, - .sources = &(struct clksrc_sources) { - .sources = clk_msysclk_sources, - .nr_sources = ARRAY_SIZE(clk_msysclk_sources), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 3 }, -}; - -/* prediv - * - * this divides the msysclk down to pass to h/p/etc. - */ - -static unsigned long s3c2443_prediv_getrate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); - - clkdiv0 &= S3C2443_CLKDIV0_PREDIV_MASK; - clkdiv0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT; - - return rate / (clkdiv0 + 1); -} - -static struct clk clk_prediv = { - .name = "prediv", - .parent = &clk_msysclk.clk, - .ops = &(struct clk_ops) { - .get_rate = s3c2443_prediv_getrate, - }, -}; - -/* hclk divider - * - * divides the prediv and provides the hclk. - */ - -static unsigned long s3c2443_hclkdiv_getrate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); - - clkdiv0 &= S3C2443_CLKDIV0_HCLKDIV_MASK; - - return rate / (clkdiv0 + 1); -} - -static struct clk_ops clk_h_ops = { - .get_rate = s3c2443_hclkdiv_getrate, -}; - -/* pclk divider - * - * divides the hclk and provides the pclk. - */ - -static unsigned long s3c2443_pclkdiv_getrate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); - - clkdiv0 = ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 1 : 0); - - return rate / (clkdiv0 + 1); -} - -static struct clk_ops clk_p_ops = { - .get_rate = s3c2443_pclkdiv_getrate, -}; - -/* armdiv - * - * this clock is sourced from msysclk and can have a number of - * divider values applied to it to then be fed into armclk. -*/ - -static unsigned int *armdiv; -static int nr_armdiv; -static int armdivmask; - -static unsigned long s3c2443_armclk_roundrate(struct clk *clk, - unsigned long rate) -{ - unsigned long parent = clk_get_rate(clk->parent); - unsigned long calc; - unsigned best = 256; /* bigger than any value */ - unsigned div; - int ptr; - - if (!nr_armdiv) - return -EINVAL; - - for (ptr = 0; ptr < nr_armdiv; ptr++) { - div = armdiv[ptr]; - if (div) { - /* cpufreq provides 266mhz as 266666000 not 266666666 */ - calc = (parent / div / 1000) * 1000; - if (calc <= rate && div < best) - best = div; - } - } - - return parent / best; -} - -static unsigned long s3c2443_armclk_getrate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - unsigned long clkcon0; - int val; - - if (!nr_armdiv || !armdivmask) - return -EINVAL; - - clkcon0 = __raw_readl(S3C2443_CLKDIV0); - clkcon0 &= armdivmask; - val = clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT; - - return rate / armdiv[val]; -} - -static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate) -{ - unsigned long parent = clk_get_rate(clk->parent); - unsigned long calc; - unsigned div; - unsigned best = 256; /* bigger than any value */ - int ptr; - int val = -1; - - if (!nr_armdiv || !armdivmask) - return -EINVAL; - - for (ptr = 0; ptr < nr_armdiv; ptr++) { - div = armdiv[ptr]; - if (div) { - /* cpufreq provides 266mhz as 266666000 not 266666666 */ - calc = (parent / div / 1000) * 1000; - if (calc <= rate && div < best) { - best = div; - val = ptr; - } - } - } - - if (val >= 0) { - unsigned long clkcon0; - - clkcon0 = __raw_readl(S3C2443_CLKDIV0); - clkcon0 &= ~armdivmask; - clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT; - __raw_writel(clkcon0, S3C2443_CLKDIV0); - } - - return (val == -1) ? -EINVAL : 0; -} - -static struct clk clk_armdiv = { - .name = "armdiv", - .parent = &clk_msysclk.clk, - .ops = &(struct clk_ops) { - .round_rate = s3c2443_armclk_roundrate, - .get_rate = s3c2443_armclk_getrate, - .set_rate = s3c2443_armclk_setrate, - }, -}; - -/* armclk - * - * this is the clock fed into the ARM core itself, from armdiv or from hclk. - */ - -static struct clk *clk_arm_sources[] = { - [0] = &clk_armdiv, - [1] = &clk_h, -}; - -static struct clksrc_clk clk_arm = { - .clk = { - .name = "armclk", - }, - .sources = &(struct clksrc_sources) { - .sources = clk_arm_sources, - .nr_sources = ARRAY_SIZE(clk_arm_sources), - }, - .reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 }, -}; - -/* usbhost - * - * usb host bus-clock, usually 48MHz to provide USB bus clock timing -*/ - -static struct clksrc_clk clk_usb_bus_host = { - .clk = { - .name = "usb-bus-host-parent", - .parent = &clk_esysclk.clk, - .ctrlbit = S3C2443_SCLKCON_USBHOST, - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 }, -}; - -/* common clksrc clocks */ - -static struct clksrc_clk clksrc_clks[] = { - { - /* camera interface bus-clock, divided down from esysclk */ - .clk = { - .name = "camif-upll", /* same as 2440 name */ - .parent = &clk_esysclk.clk, - .ctrlbit = S3C2443_SCLKCON_CAMCLK, - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 }, - }, { - .clk = { - .name = "display-if", - .parent = &clk_esysclk.clk, - .ctrlbit = S3C2443_SCLKCON_DISPCLK, - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 }, - }, -}; - -static struct clksrc_clk clk_esys_uart = { - /* ART baud-rate clock sourced from esysclk via a divisor */ - .clk = { - .name = "uartclk", - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 }, -}; - -static struct clk clk_i2s_ext = { - .name = "i2s-ext", -}; - -/* i2s_eplldiv - * - * This clock is the output from the I2S divisor of ESYSCLK, and is separate - * from the mux that comes after it (cannot merge into one single clock) -*/ - -static struct clksrc_clk clk_i2s_eplldiv = { - .clk = { - .name = "i2s-eplldiv", - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, }, -}; - -/* i2s-ref - * - * i2s bus reference clock, selectable from external, esysclk or epllref - * - * Note, this used to be two clocks, but was compressed into one. -*/ - -static struct clk *clk_i2s_srclist[] = { - [0] = &clk_i2s_eplldiv.clk, - [1] = &clk_i2s_ext, - [2] = &clk_epllref.clk, - [3] = &clk_epllref.clk, -}; - -static struct clksrc_clk clk_i2s = { - .clk = { - .name = "i2s-if", - .ctrlbit = S3C2443_SCLKCON_I2SCLK, - .enable = s3c2443_clkcon_enable_s, - - }, - .sources = &(struct clksrc_sources) { - .sources = clk_i2s_srclist, - .nr_sources = ARRAY_SIZE(clk_i2s_srclist), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 }, -}; - -static struct clk init_clocks_off[] = { - { - .name = "iis", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_IIS, - }, { - .name = "adc", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_ADC, - }, { - .name = "i2c", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_IIC, - } -}; - -static struct clk init_clocks[] = { - { - .name = "dma.0", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA0, - }, { - .name = "dma.1", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA1, - }, { - .name = "dma.2", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA2, - }, { - .name = "dma.3", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA3, - }, { - .name = "dma.4", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA4, - }, { - .name = "dma.5", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA5, - }, { - .name = "gpio", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_GPIO, - }, { - .name = "usb-host", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_USBH, - }, { - .name = "usb-device", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_USBD, - }, { - .name = "lcd", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_LCDC, - - }, { - .name = "timers", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_PWMT, - }, { - .name = "cfc", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_CFC, - }, { - .name = "ssmc", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_SSMC, - }, { - .name = "uart", - .devname = "s3c2440-uart.0", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART0, - }, { - .name = "uart", - .devname = "s3c2440-uart.1", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART1, - }, { - .name = "uart", - .devname = "s3c2440-uart.2", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART2, - }, { - .name = "uart", - .devname = "s3c2440-uart.3", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART3, - }, { - .name = "rtc", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_RTC, - }, { - .name = "watchdog", - .parent = &clk_p, - .ctrlbit = S3C2443_PCLKCON_WDT, - }, { - .name = "ac97", - .parent = &clk_p, - .ctrlbit = S3C2443_PCLKCON_AC97, - }, { - .name = "nand", - .parent = &clk_h, - }, { - .name = "usb-bus-host", - .parent = &clk_usb_bus_host.clk, - } -}; - -static struct clk hsmmc1_clk = { - .name = "hsmmc", - .devname = "s3c-sdhci.1", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_HSMMC, -}; - -static struct clk hsspi_clk = { - .name = "spi", - .devname = "s3c2443-spi.0", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_HSSPI, -}; - -/* EPLLCON compatible enough to get on/off information */ - -void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll) -{ - unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); - unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON); - struct clk *xtal_clk; - unsigned long xtal; - unsigned long pll; - int ptr; - - xtal_clk = clk_get(NULL, "xtal"); - xtal = clk_get_rate(xtal_clk); - clk_put(xtal_clk); - - pll = get_mpll(mpllcon, xtal); - clk_msysclk.clk.rate = pll; - clk_mpll.rate = pll; - - printk("CPU: MPLL %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n", - (mpllcon & S3C2443_PLLCON_OFF) ? "off" : "on", - print_mhz(pll), print_mhz(clk_get_rate(&clk_armdiv)), - print_mhz(clk_get_rate(&clk_h)), - print_mhz(clk_get_rate(&clk_p))); - - for (ptr = 0; ptr < ARRAY_SIZE(clksrc_clks); ptr++) - s3c_set_clksrc(&clksrc_clks[ptr], true); - - /* ensure usb bus clock is within correct rate of 48MHz */ - - if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) { - printk(KERN_INFO "Warning: USB host bus not at 48MHz\n"); - clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000); - } - - printk("CPU: EPLL %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", - (epllcon & S3C2443_PLLCON_OFF) ? "off" : "on", - print_mhz(clk_get_rate(&clk_epll)), - print_mhz(clk_get_rate(&clk_usb_bus))); -} - -static struct clk *clks[] __initdata = { - &clk_prediv, - &clk_mpllref, - &clk_mdivclk, - &clk_ext, - &clk_epll, - &clk_usb_bus, - &clk_armdiv, - &hsmmc1_clk, - &hsspi_clk, -}; - -static struct clksrc_clk *clksrcs[] __initdata = { - &clk_i2s_eplldiv, - &clk_i2s, - &clk_usb_bus_host, - &clk_epllref, - &clk_esysclk, - &clk_msysclk, - &clk_arm, -}; - -static struct clk_lookup s3c2443_clk_lookup[] = { - CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), - CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p), - CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_esys_uart.clk), - CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &hsmmc1_clk), - CLKDEV_INIT("s3c2443-spi.0", "spi_busclk0", &hsspi_clk), -}; - -void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, - unsigned int *divs, int nr_divs, - int divmask) -{ - int ptr; - - armdiv = divs; - nr_armdiv = nr_divs; - armdivmask = divmask; - - /* s3c2443 parents h clock from prediv */ - clk_h.parent = &clk_prediv; - clk_h.ops = &clk_h_ops; - - /* and p clock from h clock */ - clk_p.parent = &clk_h; - clk_p.ops = &clk_p_ops; - - clk_usb_bus.parent = &clk_usb_bus_host.clk; - clk_epll.parent = &clk_epllref.clk; - - s3c24xx_register_baseclocks(xtal); - s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); - - for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) - s3c_register_clksrc(clksrcs[ptr], 1); - - s3c_register_clksrc(clksrc_clks, ARRAY_SIZE(clksrc_clks)); - s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); - - /* See s3c2443/etc notes on disabling clocks at init time */ - s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - clkdev_add_table(s3c2443_clk_lookup, ARRAY_SIZE(s3c2443_clk_lookup)); - - s3c2443_common_setup_clocks(get_mpll); -} diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 0fc6641ac57d..412ca006fcce 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -145,7 +145,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32450003, .idmask = 0xffffffff, .map_io = s3c2416_map_io, - .init_clocks = s3c2416_init_clocks, .init_uarts = s3c2416_init_uarts, .init = s3c2416_init, .name = name_s3c2416, @@ -154,7 +153,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32443001, .idmask = 0xffffffff, .map_io = s3c2443_map_io, - .init_clocks = s3c2443_init_clocks, .init_uarts = s3c2443_init_uarts, .init = s3c2443_init, .name = name_s3c2443, @@ -536,3 +534,17 @@ struct platform_device s3c2443_device_dma = { }, }; #endif + +#ifdef CONFIG_CPU_S3C2416 +void __init s3c2416_init_clocks(int xtal) +{ + s3c2443_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR); +} +#endif + +#ifdef CONFIG_CPU_S3C2443 +void __init s3c2443_init_clocks(int xtal) +{ + s3c2443_common_clk_init(NULL, xtal, 1, S3C24XX_VA_CLKPWR); +} +#endif diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index e46c10417216..d7323f16427f 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h @@ -114,4 +114,10 @@ extern struct platform_device s3c2412_device_dma; extern struct platform_device s3c2440_device_dma; extern struct platform_device s3c2443_device_dma; +#ifdef CONFIG_S3C2443_COMMON_CLK +void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, + int current_soc, + void __iomem *reg_base); +#endif + #endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */ diff --git a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c index 70f0900d4bca..e4dcb9aa2ca2 100644 --- a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c +++ b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -29,48 +28,14 @@ #include "common.h" -/* - * The following lookup table is used to override device names when devices - * are registered from device tree. This is temporarily added to enable - * device tree support addition for the S3C2416 architecture. - * - * For drivers that require platform data to be provided from the machine - * file, a platform data pointer can also be supplied along with the - * devices names. Usually, the platform data elements that cannot be parsed - * from the device tree by the drivers (example: function pointers) are - * supplied. But it should be noted that this is a temporary mechanism and - * at some point, the drivers should be capable of parsing all the platform - * data from the device tree. - */ -static const struct of_dev_auxdata s3c2416_auxdata_lookup[] __initconst = { - OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART, - "s3c2440-uart.0", NULL), - OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0x4000, - "s3c2440-uart.1", NULL), - OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0x8000, - "s3c2440-uart.2", NULL), - OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0xC000, - "s3c2440-uart.3", NULL), - OF_DEV_AUXDATA("samsung,s3c6410-sdhci", S3C_PA_HSMMC0, - "s3c-sdhci.0", NULL), - OF_DEV_AUXDATA("samsung,s3c6410-sdhci", S3C_PA_HSMMC1, - "s3c-sdhci.1", NULL), - OF_DEV_AUXDATA("samsung,s3c2440-i2c", S3C_PA_IIC, - "s3c2440-i2c.0", NULL), - {}, -}; - static void __init s3c2416_dt_map_io(void) { s3c24xx_init_io(NULL, 0); - s3c24xx_init_clocks(12000000); } static void __init s3c2416_dt_machine_init(void) { - of_platform_populate(NULL, of_default_bus_match_table, - s3c2416_auxdata_lookup, NULL); - + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); s3c_pm_init(); } @@ -86,6 +51,5 @@ DT_MACHINE_START(S3C2416_DT, "Samsung S3C2416 (Flattened Device Tree)") .map_io = s3c2416_dt_map_io, .init_irq = irqchip_init, .init_machine = s3c2416_dt_machine_init, - .init_time = clocksource_of_init, .restart = s3c2416_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c index b3b54d8e1410..fa6f30d23601 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2416.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c @@ -219,10 +219,15 @@ static struct platform_device *smdk2416_devices[] __initdata = { &s3c2443_device_dma, }; +static void __init smdk2416_init_time(void) +{ + s3c2416_init_clocks(12000000); + samsung_timer_init(); +} + static void __init smdk2416_map_io(void) { s3c24xx_init_io(smdk2416_iodesc, ARRAY_SIZE(smdk2416_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(smdk2416_uartcfgs, ARRAY_SIZE(smdk2416_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } @@ -257,6 +262,6 @@ MACHINE_START(SMDK2416, "SMDK2416") .init_irq = s3c2416_init_irq, .map_io = smdk2416_map_io, .init_machine = smdk2416_machine_init, - .init_time = samsung_timer_init, + .init_time = smdk2416_init_time, .restart = s3c2416_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c index 06c4d77de3a5..ef5d5ea33182 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2443.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c @@ -121,11 +121,16 @@ static struct platform_device *smdk2443_devices[] __initdata = { static void __init smdk2443_map_io(void) { s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init smdk2443_init_time(void) +{ + s3c2443_init_clocks(12000000); + samsung_timer_init(); +} + static void __init smdk2443_machine_init(void) { s3c_i2c0_set_platdata(NULL); @@ -145,6 +150,6 @@ MACHINE_START(SMDK2443, "SMDK2443") .init_irq = s3c2443_init_irq, .map_io = smdk2443_map_io, .init_machine = smdk2443_machine_init, - .init_time = samsung_timer_init, + .init_time = smdk2443_init_time, .restart = s3c2443_restart, MACHINE_END From 42637c59f36198a58069f94676007c62477321b7 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 25 Feb 2014 09:50:43 +0900 Subject: [PATCH 08/23] ARM: S3C24XX: only store clock registers when old clock code is active The Samsung ccf driver already handles the save and restore of the clock registers on suspend and resume. The architecture code should not duplicate this when the ccf is active. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/pm.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-s3c24xx/pm.c b/arch/arm/mach-s3c24xx/pm.c index 68ea5b7e5dc7..16281bdc750a 100644 --- a/arch/arm/mach-s3c24xx/pm.c +++ b/arch/arm/mach-s3c24xx/pm.c @@ -51,9 +51,6 @@ #define PFX "s3c24xx-pm: " static struct sleep_save core_save[] = { - SAVE_ITEM(S3C2410_LOCKTIME), - SAVE_ITEM(S3C2410_CLKCON), - /* we restore the timings here, with the proviso that the board * brings the system up in an slower, or equal frequency setting * to the original system. @@ -70,6 +67,9 @@ static struct sleep_save core_save[] = { SAVE_ITEM(S3C2410_BANKCON4), SAVE_ITEM(S3C2410_BANKCON5), +#ifdef CONFIG_SAMSUNG_CLOCK + SAVE_ITEM(S3C2410_LOCKTIME), + SAVE_ITEM(S3C2410_CLKCON), #ifndef CONFIG_CPU_FREQ SAVE_ITEM(S3C2410_CLKDIVN), SAVE_ITEM(S3C2410_MPLLCON), @@ -77,11 +77,14 @@ static struct sleep_save core_save[] = { #endif SAVE_ITEM(S3C2410_UPLLCON), SAVE_ITEM(S3C2410_CLKSLOW), +#endif /* CONFIG_SAMSUNG_CLOCK */ }; +#ifdef CONFIG_SAMSUNG_CLOCK static struct sleep_save misc_save[] = { SAVE_ITEM(S3C2410_DCLKCON), }; +#endif /* s3c_pm_check_resume_pin * @@ -140,12 +143,16 @@ void s3c_pm_configure_extint(void) void s3c_pm_restore_core(void) { s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); +#ifdef CONFIG_SAMSUNG_CLOCK s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save)); +#endif } void s3c_pm_save_core(void) { +#ifdef CONFIG_SAMSUNG_CLOCK s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save)); +#endif s3c_pm_do_save(core_save, ARRAY_SIZE(core_save)); } From ea5d6a8d3ee606086118d3b4d4b3a49693e92960 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 25 Feb 2014 09:50:43 +0900 Subject: [PATCH 09/23] clk: samsung: add plls used by the early s3c24xx cpus The manuals do not give them explicit names like in later socs, so more generic names with a s3c2410-prefix were used for them. As it was common to do so in the previous implementation, functionality to change the pll rate is already included. Signed-off-by: Heiko Stuebner Acked-by: Mike Turquette Acked-by: Tomasz Figa Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-pll.c | 182 ++++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk-pll.h | 3 + 2 files changed, 185 insertions(+) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 8c9c015a4538..7fb0a28e65d5 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -11,6 +11,7 @@ #include #include +#include #include "clk.h" #include "clk-pll.h" @@ -700,6 +701,169 @@ static const struct clk_ops samsung_pll6553_clk_ops = { .recalc_rate = samsung_pll6553_recalc_rate, }; +/* + * PLL Clock Type of S3C24XX before S3C2443 + */ + +#define PLLS3C2410_MDIV_MASK (0xff) +#define PLLS3C2410_PDIV_MASK (0x1f) +#define PLLS3C2410_SDIV_MASK (0x3) +#define PLLS3C2410_MDIV_SHIFT (12) +#define PLLS3C2410_PDIV_SHIFT (4) +#define PLLS3C2410_SDIV_SHIFT (0) + +#define PLLS3C2410_ENABLE_REG_OFFSET 0x10 + +static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK; + pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK; + sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK; + + fvco *= (mdiv + 8); + do_div(fvco, (pdiv + 2) << sdiv); + + return (unsigned int)fvco; +} + +static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK; + pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK; + sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK; + + fvco *= (2 * (mdiv + 8)); + do_div(fvco, (pdiv + 2) << sdiv); + + return (unsigned int)fvco; +} + +static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + const struct samsung_pll_rate_table *rate; + u32 tmp; + + /* Get required rate settings from table */ + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw->clk)); + return -EINVAL; + } + + tmp = __raw_readl(pll->con_reg); + + /* Change PLL PMS values */ + tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) | + (PLLS3C2410_PDIV_MASK << PLLS3C2410_PDIV_SHIFT) | + (PLLS3C2410_SDIV_MASK << PLLS3C2410_SDIV_SHIFT)); + tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) | + (rate->pdiv << PLLS3C2410_PDIV_SHIFT) | + (rate->sdiv << PLLS3C2410_SDIV_SHIFT); + __raw_writel(tmp, pll->con_reg); + + /* Time to settle according to the manual */ + udelay(300); + + return 0; +} + +static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_en = __raw_readl(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET); + u32 pll_en_orig = pll_en; + + if (enable) + pll_en &= ~BIT(bit); + else + pll_en |= BIT(bit); + + __raw_writel(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET); + + /* if we started the UPLL, then allow to settle */ + if (enable && (pll_en_orig & BIT(bit))) + udelay(300); + + return 0; +} + +static int samsung_s3c2410_mpll_enable(struct clk_hw *hw) +{ + return samsung_s3c2410_pll_enable(hw, 5, true); +} + +static void samsung_s3c2410_mpll_disable(struct clk_hw *hw) +{ + samsung_s3c2410_pll_enable(hw, 5, false); +} + +static int samsung_s3c2410_upll_enable(struct clk_hw *hw) +{ + return samsung_s3c2410_pll_enable(hw, 7, true); +} + +static void samsung_s3c2410_upll_disable(struct clk_hw *hw) +{ + samsung_s3c2410_pll_enable(hw, 7, false); +} + +static const struct clk_ops samsung_s3c2410_mpll_clk_min_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, +}; + +static const struct clk_ops samsung_s3c2410_upll_clk_min_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_upll_enable, + .disable = samsung_s3c2410_upll_disable, +}; + +static const struct clk_ops samsung_s3c2440_mpll_clk_min_ops = { + .recalc_rate = samsung_s3c2440_mpll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, +}; + +static const struct clk_ops samsung_s3c2410_mpll_clk_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_s3c2410_pll_set_rate, +}; + +static const struct clk_ops samsung_s3c2410_upll_clk_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_upll_enable, + .disable = samsung_s3c2410_upll_disable, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_s3c2410_pll_set_rate, +}; + +static const struct clk_ops samsung_s3c2440_mpll_clk_ops = { + .recalc_rate = samsung_s3c2440_mpll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_s3c2410_pll_set_rate, +}; + /* * PLL2550x Clock Type */ @@ -866,6 +1030,24 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, else init.ops = &samsung_pll46xx_clk_ops; break; + case pll_s3c2410_mpll: + if (!pll->rate_table) + init.ops = &samsung_s3c2410_mpll_clk_min_ops; + else + init.ops = &samsung_s3c2410_mpll_clk_ops; + break; + case pll_s3c2410_upll: + if (!pll->rate_table) + init.ops = &samsung_s3c2410_upll_clk_min_ops; + else + init.ops = &samsung_s3c2410_upll_clk_ops; + break; + case pll_s3c2440_mpll: + if (!pll->rate_table) + init.ops = &samsung_s3c2440_mpll_clk_min_ops; + else + init.ops = &samsung_s3c2440_mpll_clk_ops; + break; default: pr_warn("%s: Unknown pll type for pll clk %s\n", __func__, pll_clk->name); diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 5b64bdbb0906..6428bcc6df6f 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -28,6 +28,9 @@ enum samsung_pll_type { pll_6552, pll_6552_s3c2416, pll_6553, + pll_s3c2410_mpll, + pll_s3c2410_upll, + pll_s3c2440_mpll, }; #define PLL_35XX_RATE(_rate, _m, _p, _s) \ From 7d03fed8e56ba5ffdae67c64d181a010a2a56d9b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 25 Feb 2014 09:50:44 +0900 Subject: [PATCH 10/23] dt-bindings: add documentation for s3c2412 clock controller Describe the clock controller of the s3c2412. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- .../bindings/clock/samsung,s3c2412-clock.txt | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt new file mode 100644 index 000000000000..2b430960ba47 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt @@ -0,0 +1,50 @@ +* Samsung S3C2412 Clock Controller + +The S3C2412 clock controller generates and supplies clock to various controllers +within the SoC. The clock binding described here is applicable to the s3c2412 +and s3c2413 SoCs in the s3c24x family. + +Required Properties: + +- compatible: should be "samsung,s3c2412-clock" +- 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 SoC. + +All available clocks are defined as preprocessor macros in +dt-bindings/clock/s3c2412.h header and can be used in device +tree sources. + +External clocks: + +There are several clocks that are generated outside the SoC. It is expected +that they are defined using standard clock bindings with following +clock-output-names: + - "xti" - crystal input - required, + - "ext" - external clock source - optional, + +Example: Clock controller node: + + clocks: clock-controller@4c000000 { + compatible = "samsung,s3c2412-clock"; + reg = <0x4c000000 0x20>; + #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): + + serial@50004000 { + compatible = "samsung,s3c2412-uart"; + reg = <0x50004000 0x4000>; + interrupts = <1 23 3 4>, <1 23 4 4>; + clock-names = "uart", "clk_uart_baud2", "clk_uart_baud3"; + clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>, + <&clocks SCLK_UART>; + status = "disabled"; + }; From ca2e90ac1809c49c2306df4e23e17dad67c785b6 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 25 Feb 2014 09:50:44 +0900 Subject: [PATCH 11/23] clk: samsung: add clock controller driver for s3c2412 This driver can handle the clock controller in the s3c2412 soc. The clock structure is built according to the manuals of the included SoCs and might include changes in comparison to the previous clock structure. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Acked-by: Mike Turquette Signed-off-by: Kukjin Kim --- drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-s3c2412.c | 269 ++++++++++++++++++++++++++++ include/dt-bindings/clock/s3c2412.h | 73 ++++++++ 3 files changed, 343 insertions(+) create mode 100644 drivers/clk/samsung/clk-s3c2412.c create mode 100644 include/dt-bindings/clock/s3c2412.h diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 4c892c63a8dd..77313e27bc39 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -8,5 +8,6 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o +obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c new file mode 100644 index 000000000000..0f11a07d5c01 --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2412.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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 S3C2412 and S3C2413. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "clk-pll.h" + +#define LOCKTIME 0x00 +#define MPLLCON 0x04 +#define UPLLCON 0x08 +#define CLKCON 0x0c +#define CLKDIVN 0x14 +#define CLKSRC 0x1c + +/* list of PLLs to be registered */ +enum s3c2412_plls { + mpll, upll, +}; + +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *s3c2412_save; + +/* + * list of controller registers to be saved and restored during a + * suspend/resume cycle. + */ +static unsigned long s3c2412_clk_regs[] __initdata = { + LOCKTIME, + MPLLCON, + UPLLCON, + CLKCON, + CLKDIVN, + CLKSRC, +}; + +static int s3c2412_clk_suspend(void) +{ + samsung_clk_save(reg_base, s3c2412_save, + ARRAY_SIZE(s3c2412_clk_regs)); + + return 0; +} + +static void s3c2412_clk_resume(void) +{ + samsung_clk_restore(reg_base, s3c2412_save, + ARRAY_SIZE(s3c2412_clk_regs)); +} + +static struct syscore_ops s3c2412_clk_syscore_ops = { + .suspend = s3c2412_clk_suspend, + .resume = s3c2412_clk_resume, +}; + +static void s3c2412_clk_sleep_init(void) +{ + s3c2412_save = samsung_clk_alloc_reg_dump(s3c2412_clk_regs, + ARRAY_SIZE(s3c2412_clk_regs)); + if (!s3c2412_save) { + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; + } + + register_syscore_ops(&s3c2412_clk_syscore_ops); + return; +} +#else +static void s3c2412_clk_sleep_init(void) {} +#endif + +static struct clk_div_table divxti_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 6 }, + { .val = 4, .div = 8 }, + { .val = 5, .div = 10 }, + { .val = 6, .div = 12 }, + { .val = 7, .div = 14 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2412_dividers[] __initdata = { + DIV_T(0, "div_xti", "xti", CLKSRC, 0, 3, divxti_d), + DIV(0, "div_cam", "mux_cam", CLKDIVN, 16, 4), + DIV(0, "div_i2s", "mux_i2s", CLKDIVN, 12, 4), + DIV(0, "div_uart", "mux_uart", CLKDIVN, 8, 4), + DIV(0, "div_usb", "mux_usb", CLKDIVN, 6, 1), + DIV(0, "div_hclk_half", "hclk", CLKDIVN, 5, 1), + DIV(ARMDIV, "armdiv", "msysclk", CLKDIVN, 3, 1), + DIV(PCLK, "pclk", "hclk", CLKDIVN, 2, 1), + DIV(HCLK, "hclk", "armdiv", CLKDIVN, 0, 2), +}; + +struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = { + FFACTOR(0, "ff_hclk", "hclk", 2, 1, CLK_SET_RATE_PARENT), +}; + +/* + * The first two use the OM[4] setting, which is not readable from + * software, so assume it is set to xti. + */ +PNAME(erefclk_p) = { "xti", "xti", "xti", "ext" }; +PNAME(urefclk_p) = { "xti", "xti", "xti", "ext" }; + +PNAME(camclk_p) = { "usysclk", "hclk" }; +PNAME(usbclk_p) = { "usysclk", "hclk" }; +PNAME(i2sclk_p) = { "erefclk", "mpll" }; +PNAME(uartclk_p) = { "erefclk", "mpll" }; +PNAME(usysclk_p) = { "urefclk", "upll" }; +PNAME(msysclk_p) = { "mdivclk", "mpll" }; +PNAME(mdivclk_p) = { "xti", "div_xti" }; +PNAME(armclk_p) = { "armdiv", "hclk" }; + +struct samsung_mux_clock s3c2412_muxes[] __initdata = { + MUX(0, "erefclk", erefclk_p, CLKSRC, 14, 2), + MUX(0, "urefclk", urefclk_p, CLKSRC, 12, 2), + MUX(0, "mux_cam", camclk_p, CLKSRC, 11, 1), + MUX(0, "mux_usb", usbclk_p, CLKSRC, 10, 1), + MUX(0, "mux_i2s", i2sclk_p, CLKSRC, 9, 1), + MUX(0, "mux_uart", uartclk_p, CLKSRC, 8, 1), + MUX(USYSCLK, "usysclk", usysclk_p, CLKSRC, 5, 1), + MUX(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1), + MUX(MDIVCLK, "mdivclk", mdivclk_p, CLKSRC, 3, 1), + MUX(ARMCLK, "armclk", armclk_p, CLKDIVN, 4, 1), +}; + +static struct samsung_pll_clock s3c2412_plls[] __initdata = { + [mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti", + LOCKTIME, MPLLCON, NULL), + [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk", + LOCKTIME, UPLLCON, NULL), +}; + +struct samsung_gate_clock s3c2412_gates[] __initdata = { + GATE(PCLK_WDT, "wdt", "pclk", CLKCON, 28, 0, 0), + GATE(PCLK_SPI, "spi", "pclk", CLKCON, 27, 0, 0), + GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 26, 0, 0), + GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 25, 0, 0), + GATE(PCLK_ADC, "adc", "pclk", CLKCON, 24, 0, 0), + GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 23, 0, 0), + GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 22, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 21, 0, 0), + GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 20, 0, 0), + GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 19, 0, 0), + GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 18, 0, 0), + GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 17, 0, 0), + GATE(PCLK_USBD, "usb-device", "pclk", CLKCON, 16, 0, 0), + GATE(SCLK_CAM, "sclk_cam", "div_cam", CLKCON, 15, 0, 0), + GATE(SCLK_UART, "sclk_uart", "div_uart", CLKCON, 14, 0, 0), + GATE(SCLK_I2S, "sclk_i2s", "div_i2s", CLKCON, 13, 0, 0), + GATE(SCLK_USBH, "sclk_usbh", "div_usb", CLKCON, 12, 0, 0), + GATE(SCLK_USBD, "sclk_usbd", "div_usb", CLKCON, 11, 0, 0), + GATE(HCLK_HALF, "hclk_half", "div_hclk_half", CLKCON, 10, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_X2, "hclkx2", "ff_hclk", CLKCON, 9, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_SDRAM, "sdram", "hclk", CLKCON, 8, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0), + GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0), + GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0), + GATE(HCLK_DMA3, "dma3", "hclk", CLKCON, 3, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA2, "dma2", "hclk", CLKCON, 2, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA1, "dma1", "hclk", CLKCON, 1, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA0, "dma0", "hclk", CLKCON, 0, CLK_IGNORE_UNUSED, 0), +}; + +struct samsung_clock_alias s3c2412_aliases[] __initdata = { + ALIAS(PCLK_UART0, "s3c2412-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2412-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2412-uart.2", "uart"), + ALIAS(PCLK_UART0, "s3c2412-uart.0", "clk_uart_baud2"), + ALIAS(PCLK_UART1, "s3c2412-uart.1", "clk_uart_baud2"), + ALIAS(PCLK_UART2, "s3c2412-uart.2", "clk_uart_baud2"), + ALIAS(SCLK_UART, NULL, "clk_uart_baud3"), + ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"), + ALIAS(PCLK_ADC, NULL, "adc"), + ALIAS(PCLK_RTC, NULL, "rtc"), + ALIAS(PCLK_PWM, NULL, "timers"), + ALIAS(HCLK_LCD, NULL, "lcd"), + ALIAS(PCLK_USBD, NULL, "usb-device"), + ALIAS(SCLK_USBD, NULL, "usb-bus-gadget"), + ALIAS(HCLK_USBH, NULL, "usb-host"), + ALIAS(SCLK_USBH, NULL, "usb-bus-host"), + ALIAS(ARMCLK, NULL, "armclk"), + ALIAS(HCLK, NULL, "hclk"), + ALIAS(MPLL, NULL, "mpll"), + ALIAS(MSYSCLK, NULL, "fclk"), +}; + +/* + * fixed rate clocks generated outside the soc + * Only necessary until the devicetree-move is complete + */ +#define XTI 1 +struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = { + FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext", NULL, CLK_IS_ROOT, 0), +}; + +static void __init s3c2412_common_clk_register_fixed_ext(unsigned long xti_f, + unsigned long ext_f) +{ + /* xtal alias is necessary for the current cpufreq driver */ + struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal"); + + s3c2412_common_frate_clks[0].fixed_rate = xti_f; + s3c2412_common_frate_clks[1].fixed_rate = ext_f; + samsung_clk_register_fixed_rate(s3c2412_common_frate_clks, + ARRAY_SIZE(s3c2412_common_frate_clks)); + + samsung_clk_register_alias(&xti_alias, 1); +} + +void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, + unsigned long ext_f, void __iomem *base) +{ + reg_base = base; + + if (np) { + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + } + + samsung_clk_init(np, reg_base, NR_CLKS); + + /* Register external clocks only in non-dt cases */ + if (!np) + s3c2412_common_clk_register_fixed_ext(xti_f, ext_f); + + /* Register PLLs. */ + samsung_clk_register_pll(s3c2412_plls, ARRAY_SIZE(s3c2412_plls), + reg_base); + + /* Register common internal clocks. */ + samsung_clk_register_mux(s3c2412_muxes, ARRAY_SIZE(s3c2412_muxes)); + samsung_clk_register_div(s3c2412_dividers, + ARRAY_SIZE(s3c2412_dividers)); + samsung_clk_register_gate(s3c2412_gates, ARRAY_SIZE(s3c2412_gates)); + samsung_clk_register_fixed_factor(s3c2412_ffactor, + ARRAY_SIZE(s3c2412_ffactor)); + samsung_clk_register_alias(s3c2412_aliases, + ARRAY_SIZE(s3c2412_aliases)); + + s3c2412_clk_sleep_init(); +} + +static void __init s3c2412_clk_init(struct device_node *np) +{ + s3c2412_common_clk_init(np, 0, 0, 0); +} +CLK_OF_DECLARE(s3c2412_clk, "samsung,s3c2412-clock", s3c2412_clk_init); diff --git a/include/dt-bindings/clock/s3c2412.h b/include/dt-bindings/clock/s3c2412.h new file mode 100644 index 000000000000..aac1dcfda81c --- /dev/null +++ b/include/dt-bindings/clock/s3c2412.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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 clock controllers of Samsung S3C2412. + */ + +#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_CLOCK_H +#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_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. */ + +/* id 1 is reserved */ +#define MPLL 2 +#define UPLL 3 +#define MDIVCLK 4 +#define MSYSCLK 5 +#define USYSCLK 6 +#define HCLK 7 +#define PCLK 8 +#define ARMDIV 9 +#define ARMCLK 10 + + +/* Special clocks */ +#define SCLK_CAM 16 +#define SCLK_UART 17 +#define SCLK_I2S 18 +#define SCLK_USBD 19 +#define SCLK_USBH 20 + +/* pclk-gates */ +#define PCLK_WDT 32 +#define PCLK_SPI 33 +#define PCLK_I2S 34 +#define PCLK_I2C 35 +#define PCLK_ADC 36 +#define PCLK_RTC 37 +#define PCLK_GPIO 38 +#define PCLK_UART2 39 +#define PCLK_UART1 40 +#define PCLK_UART0 41 +#define PCLK_SDI 42 +#define PCLK_PWM 43 +#define PCLK_USBD 44 + +/* hclk-gates */ +#define HCLK_HALF 48 +#define HCLK_X2 49 +#define HCLK_SDRAM 50 +#define HCLK_USBH 51 +#define HCLK_LCD 52 +#define HCLK_NAND 53 +#define HCLK_DMA3 54 +#define HCLK_DMA2 55 +#define HCLK_DMA1 56 +#define HCLK_DMA0 57 + +/* Total number of clocks. */ +#define NR_CLKS (HCLK_DMA0 + 1) + +#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_CLOCK_H */ From 3c27f314c676ee31eafd423ce2c640ed129cd5e0 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 25 Feb 2014 09:50:44 +0900 Subject: [PATCH 12/23] ARM: S3C24XX: convert s3c2412 to common clock framework Convert all machines using these cpus to use the ccf clock driver instead of the legacy Samsung clock implementation. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 8 +- arch/arm/mach-s3c24xx/Makefile | 2 +- arch/arm/mach-s3c24xx/clock-s3c2412.c | 760 -------------------------- arch/arm/mach-s3c24xx/common.c | 9 +- arch/arm/mach-s3c24xx/common.h | 4 + arch/arm/mach-s3c24xx/mach-jive.c | 9 +- arch/arm/mach-s3c24xx/mach-smdk2413.c | 9 +- arch/arm/mach-s3c24xx/mach-vstms.c | 9 +- arch/arm/mach-s3c24xx/s3c2412.c | 43 -- 9 files changed, 40 insertions(+), 813 deletions(-) delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2412.c diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 52f1c40ccf07..fbafb9a1975b 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -39,9 +39,10 @@ config CPU_S3C2410 config CPU_S3C2412 bool "SAMSUNG S3C2412" - depends on SAMSUNG_CLOCK + select COMMON_CLK select CPU_ARM926T select CPU_LLSERIAL_S3C2440 + select S3C2412_COMMON_CLK select S3C2412_DMA if S3C24XX_DMA select S3C2412_PM if PM help @@ -363,6 +364,11 @@ config S3C2412_PM_SLEEP if CPU_S3C2412 +config S3C2412_COMMON_CLK + bool + help + Build the s3c2412 clock driver based on the common clock framework. + config CPU_S3C2412_ONLY bool depends on !CPU_S3C2410 && !CPU_S3C2416 && !CPU_S3C2440 && \ diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index ba0e5475a807..f25479721dc9 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile @@ -21,7 +21,7 @@ obj-$(CONFIG_S3C2410_DMA) += dma-s3c2410.o obj-$(CONFIG_S3C2410_PLL) += pll-s3c2410.o obj-$(CONFIG_S3C2410_PM) += pm-s3c2410.o sleep-s3c2410.o -obj-$(CONFIG_CPU_S3C2412) += s3c2412.o clock-s3c2412.o +obj-$(CONFIG_CPU_S3C2412) += s3c2412.o obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o diff --git a/arch/arm/mach-s3c24xx/clock-s3c2412.c b/arch/arm/mach-s3c24xx/clock-s3c2412.c deleted file mode 100644 index 192a5b2550b0..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c2412.c +++ /dev/null @@ -1,760 +0,0 @@ -/* linux/arch/arm/mach-s3c2412/clock.c - * - * Copyright (c) 2006 Simtec Electronics - * Ben Dooks - * - * S3C2412,S3C2413 Clock control support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include - -/* We currently have to assume that the system is running - * from the XTPll input, and that all ***REFCLKs are being - * fed from it, as we cannot read the state of OM[4] from - * software. - * - * It would be possible for each board initialisation to - * set the correct muxing at initialisation -*/ - -static int s3c2412_clkcon_enable(struct clk *clk, int enable) -{ - unsigned int clocks = clk->ctrlbit; - unsigned long clkcon; - - clkcon = __raw_readl(S3C2410_CLKCON); - - if (enable) - clkcon |= clocks; - else - clkcon &= ~clocks; - - __raw_writel(clkcon, S3C2410_CLKCON); - - return 0; -} - -static int s3c2412_upll_enable(struct clk *clk, int enable) -{ - unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); - unsigned long orig = upllcon; - - if (!enable) - upllcon |= S3C2412_PLLCON_OFF; - else - upllcon &= ~S3C2412_PLLCON_OFF; - - __raw_writel(upllcon, S3C2410_UPLLCON); - - /* allow ~150uS for the PLL to settle and lock */ - - if (enable && (orig & S3C2412_PLLCON_OFF)) - udelay(150); - - return 0; -} - -/* clock selections */ - -static struct clk clk_erefclk = { - .name = "erefclk", -}; - -static struct clk clk_urefclk = { - .name = "urefclk", -}; - -static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_urefclk) - clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL; - else if (parent == &clk_upll) - clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} - -static struct clk clk_usysclk = { - .name = "usysclk", - .parent = &clk_xtal, - .ops = &(struct clk_ops) { - .set_parent = s3c2412_setparent_usysclk, - }, -}; - -static struct clk clk_mrefclk = { - .name = "mrefclk", - .parent = &clk_xtal, -}; - -static struct clk clk_mdivclk = { - .name = "mdivclk", - .parent = &clk_xtal, -}; - -static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_usysclk) - clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK; - else if (parent == &clk_h) - clksrc |= S3C2412_CLKSRC_USBCLK_HCLK; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} - -static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk, - unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - int div; - - if (rate > parent_rate) - return parent_rate; - - div = parent_rate / rate; - if (div > 2) - div = 2; - - return parent_rate / div; -} - -static unsigned long s3c2412_getrate_usbsrc(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long div = __raw_readl(S3C2410_CLKDIVN); - - return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1); -} - -static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); - - rate = s3c2412_roundrate_usbsrc(clk, rate); - - if ((parent_rate / rate) == 2) - clkdivn |= S3C2412_CLKDIVN_USB48DIV; - else - clkdivn &= ~S3C2412_CLKDIVN_USB48DIV; - - __raw_writel(clkdivn, S3C2410_CLKDIVN); - return 0; -} - -static struct clk clk_usbsrc = { - .name = "usbsrc", - .ops = &(struct clk_ops) { - .get_rate = s3c2412_getrate_usbsrc, - .set_rate = s3c2412_setrate_usbsrc, - .round_rate = s3c2412_roundrate_usbsrc, - .set_parent = s3c2412_setparent_usbsrc, - }, -}; - -static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_mdivclk) - clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL; - else if (parent == &clk_mpll) - clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} - -static struct clk clk_msysclk = { - .name = "msysclk", - .ops = &(struct clk_ops) { - .set_parent = s3c2412_setparent_msysclk, - }, -}; - -static int s3c2412_setparent_armclk(struct clk *clk, struct clk *parent) -{ - unsigned long flags; - unsigned long clkdiv; - unsigned long dvs; - - /* Note, we current equate fclk andf msysclk for S3C2412 */ - - if (parent == &clk_msysclk || parent == &clk_f) - dvs = 0; - else if (parent == &clk_h) - dvs = S3C2412_CLKDIVN_DVSEN; - else - return -EINVAL; - - clk->parent = parent; - - /* update this under irq lockdown, clkdivn is not protected - * by the clock system. */ - - local_irq_save(flags); - - clkdiv = __raw_readl(S3C2410_CLKDIVN); - clkdiv &= ~S3C2412_CLKDIVN_DVSEN; - clkdiv |= dvs; - __raw_writel(clkdiv, S3C2410_CLKDIVN); - - local_irq_restore(flags); - - return 0; -} - -static struct clk clk_armclk = { - .name = "armclk", - .parent = &clk_msysclk, - .ops = &(struct clk_ops) { - .set_parent = s3c2412_setparent_armclk, - }, -}; - -/* these next clocks have an divider immediately after them, - * so we can register them with their divider and leave out the - * intermediate clock stage -*/ -static unsigned long s3c2412_roundrate_clksrc(struct clk *clk, - unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - int div; - - if (rate > parent_rate) - return parent_rate; - - /* note, we remove the +/- 1 calculations as they cancel out */ - - div = (rate / parent_rate); - - if (div < 1) - div = 1; - else if (div > 16) - div = 16; - - return parent_rate / div; -} - -static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_erefclk) - clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL; - else if (parent == &clk_mpll) - clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} - -static unsigned long s3c2412_getrate_uart(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long div = __raw_readl(S3C2410_CLKDIVN); - - div &= S3C2412_CLKDIVN_UARTDIV_MASK; - div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT; - - return parent_rate / (div + 1); -} - -static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); - - rate = s3c2412_roundrate_clksrc(clk, rate); - - clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK; - clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT; - - __raw_writel(clkdivn, S3C2410_CLKDIVN); - return 0; -} - -static struct clk clk_uart = { - .name = "uartclk", - .ops = &(struct clk_ops) { - .get_rate = s3c2412_getrate_uart, - .set_rate = s3c2412_setrate_uart, - .set_parent = s3c2412_setparent_uart, - .round_rate = s3c2412_roundrate_clksrc, - }, -}; - -static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_erefclk) - clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL; - else if (parent == &clk_mpll) - clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} - -static unsigned long s3c2412_getrate_i2s(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long div = __raw_readl(S3C2410_CLKDIVN); - - div &= S3C2412_CLKDIVN_I2SDIV_MASK; - div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT; - - return parent_rate / (div + 1); -} - -static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); - - rate = s3c2412_roundrate_clksrc(clk, rate); - - clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK; - clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT; - - __raw_writel(clkdivn, S3C2410_CLKDIVN); - return 0; -} - -static struct clk clk_i2s = { - .name = "i2sclk", - .ops = &(struct clk_ops) { - .get_rate = s3c2412_getrate_i2s, - .set_rate = s3c2412_setrate_i2s, - .set_parent = s3c2412_setparent_i2s, - .round_rate = s3c2412_roundrate_clksrc, - }, -}; - -static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_usysclk) - clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK; - else if (parent == &clk_h) - clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} -static unsigned long s3c2412_getrate_cam(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long div = __raw_readl(S3C2410_CLKDIVN); - - div &= S3C2412_CLKDIVN_CAMDIV_MASK; - div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT; - - return parent_rate / (div + 1); -} - -static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); - - rate = s3c2412_roundrate_clksrc(clk, rate); - - clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK; - clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT; - - __raw_writel(clkdivn, S3C2410_CLKDIVN); - return 0; -} - -static struct clk clk_cam = { - .name = "camif-upll", /* same as 2440 name */ - .ops = &(struct clk_ops) { - .get_rate = s3c2412_getrate_cam, - .set_rate = s3c2412_setrate_cam, - .set_parent = s3c2412_setparent_cam, - .round_rate = s3c2412_roundrate_clksrc, - }, -}; - -/* standard clock definitions */ - -static struct clk init_clocks_disable[] = { - { - .name = "nand", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_NAND, - }, { - .name = "sdi", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_SDI, - }, { - .name = "adc", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_ADC, - }, { - .name = "i2c", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_IIC, - }, { - .name = "iis", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_IIS, - }, { - .name = "spi", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_SPI, - } -}; - -static struct clk init_clocks[] = { - { - .name = "dma.0", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_DMA0, - }, { - .name = "dma.1", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_DMA1, - }, { - .name = "dma.2", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_DMA2, - }, { - .name = "dma.3", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_DMA3, - }, { - .name = "lcd", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_LCDC, - }, { - .name = "gpio", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_GPIO, - }, { - .name = "usb-host", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_USBH, - }, { - .name = "usb-device", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_USBD, - }, { - .name = "timers", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_PWMT, - }, { - .name = "uart", - .devname = "s3c2412-uart.0", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_UART0, - }, { - .name = "uart", - .devname = "s3c2412-uart.1", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_UART1, - }, { - .name = "uart", - .devname = "s3c2412-uart.2", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_UART2, - }, { - .name = "rtc", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_RTC, - }, { - .name = "watchdog", - .parent = &clk_p, - .ctrlbit = 0, - }, { - .name = "usb-bus-gadget", - .parent = &clk_usb_bus, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_USB_DEV48, - }, { - .name = "usb-bus-host", - .parent = &clk_usb_bus, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_USB_HOST48, - } -}; - -/* clocks to add where we need to check their parentage */ - -struct clk_init { - struct clk *clk; - unsigned int bit; - struct clk *src_0; - struct clk *src_1; -}; - -static struct clk_init clks_src[] __initdata = { - { - .clk = &clk_usysclk, - .bit = S3C2412_CLKSRC_USBCLK_HCLK, - .src_0 = &clk_urefclk, - .src_1 = &clk_upll, - }, { - .clk = &clk_i2s, - .bit = S3C2412_CLKSRC_I2SCLK_MPLL, - .src_0 = &clk_erefclk, - .src_1 = &clk_mpll, - }, { - .clk = &clk_cam, - .bit = S3C2412_CLKSRC_CAMCLK_HCLK, - .src_0 = &clk_usysclk, - .src_1 = &clk_h, - }, { - .clk = &clk_msysclk, - .bit = S3C2412_CLKSRC_MSYSCLK_MPLL, - .src_0 = &clk_mdivclk, - .src_1 = &clk_mpll, - }, { - .clk = &clk_uart, - .bit = S3C2412_CLKSRC_UARTCLK_MPLL, - .src_0 = &clk_erefclk, - .src_1 = &clk_mpll, - }, { - .clk = &clk_usbsrc, - .bit = S3C2412_CLKSRC_USBCLK_HCLK, - .src_0 = &clk_usysclk, - .src_1 = &clk_h, - /* here we assume OM[4] select xtal */ - }, { - .clk = &clk_erefclk, - .bit = S3C2412_CLKSRC_EREFCLK_EXTCLK, - .src_0 = &clk_xtal, - .src_1 = &clk_ext, - }, { - .clk = &clk_urefclk, - .bit = S3C2412_CLKSRC_UREFCLK_EXTCLK, - .src_0 = &clk_xtal, - .src_1 = &clk_ext, - }, -}; - -/* s3c2412_clk_initparents - * - * Initialise the parents for the clocks that we get at start-time -*/ - -static void __init s3c2412_clk_initparents(void) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - struct clk_init *cip = clks_src; - struct clk *src; - int ptr; - int ret; - - for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) { - ret = s3c24xx_register_clock(cip->clk); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - cip->clk->name, ret); - } - - src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0; - - printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name); - clk_set_parent(cip->clk, src); - } -} - -/* clocks to add straight away */ - -static struct clk *clks[] __initdata = { - &clk_ext, - &clk_usb_bus, - &clk_mrefclk, - &clk_armclk, -}; - -static struct clk_lookup s3c2412_clk_lookup[] = { - CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), - CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p), - CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_usysclk), -}; - -int __init s3c2412_baseclk_add(void) -{ - unsigned long clkcon = __raw_readl(S3C2410_CLKCON); - unsigned int dvs; - struct clk *clkp; - int ret; - int ptr; - - clk_upll.enable = s3c2412_upll_enable; - clk_usb_bus.parent = &clk_usbsrc; - clk_usb_bus.rate = 0x0; - - clk_f.parent = &clk_msysclk; - - s3c2412_clk_initparents(); - - for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { - clkp = clks[ptr]; - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - } - - /* set the dvs state according to what we got at boot time */ - - dvs = __raw_readl(S3C2410_CLKDIVN) & S3C2412_CLKDIVN_DVSEN; - - if (dvs) - clk_armclk.parent = &clk_h; - - printk(KERN_INFO "S3C2412: DVS is %s\n", dvs ? "on" : "off"); - - /* ensure usb bus clock is within correct rate of 48MHz */ - - if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) { - printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n"); - - /* for the moment, let's use the UPLL, and see if we can - * get 48MHz */ - - clk_set_parent(&clk_usysclk, &clk_upll); - clk_set_parent(&clk_usbsrc, &clk_usysclk); - clk_set_rate(&clk_usbsrc, 48*1000*1000); - } - - printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", - (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on", - print_mhz(clk_get_rate(&clk_upll)), - print_mhz(clk_get_rate(&clk_usb_bus))); - - /* register clocks from clock array */ - - clkp = init_clocks; - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { - /* ensure that we note the clock state */ - - clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0; - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - } - - /* We must be careful disabling the clocks we are not intending to - * be using at boot time, as subsystems such as the LCD which do - * their own DMA requests to the bus can cause the system to lockup - * if they where in the middle of requesting bus access. - * - * Disabling the LCD clock if the LCD is active is very dangerous, - * and therefore the bootloader should be careful to not enable - * the LCD clock if it is not needed. - */ - - /* install (and disable) the clocks we do not need immediately */ - - clkp = init_clocks_disable; - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - - s3c2412_clkcon_enable(clkp, 0); - } - - clkdev_add_table(s3c2412_clk_lookup, ARRAY_SIZE(s3c2412_clk_lookup)); - return 0; -} diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 412ca006fcce..ad5b76bf4d51 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -127,7 +127,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32412001, .idmask = 0xffffffff, .map_io = s3c2412_map_io, - .init_clocks = s3c2412_init_clocks, .init_uarts = s3c2412_init_uarts, .init = s3c2412_init, .name = name_s3c2412, @@ -136,7 +135,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32412003, .idmask = 0xffffffff, .map_io = s3c2412_map_io, - .init_clocks = s3c2412_init_clocks, .init_uarts = s3c2412_init_uarts, .init = s3c2412_init, .name = name_s3c2412, @@ -535,6 +533,13 @@ struct platform_device s3c2443_device_dma = { }; #endif +#ifdef CONFIG_CPU_S3C2412 +void __init s3c2412_init_clocks(int xtal) +{ + s3c2412_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR); +} +#endif + #ifdef CONFIG_CPU_S3C2416 void __init s3c2416_init_clocks(int xtal) { diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index d7323f16427f..3fade6d796f9 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h @@ -114,6 +114,10 @@ extern struct platform_device s3c2412_device_dma; extern struct platform_device s3c2440_device_dma; extern struct platform_device s3c2443_device_dma; +#ifdef CONFIG_S3C2412_COMMON_CLK +void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, + unsigned long ext_f, void __iomem *reg_base); +#endif #ifdef CONFIG_S3C2443_COMMON_CLK void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, int current_soc, diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c index 5faa7239e7d6..e81ea82c55f9 100644 --- a/arch/arm/mach-s3c24xx/mach-jive.c +++ b/arch/arm/mach-s3c24xx/mach-jive.c @@ -507,11 +507,16 @@ static struct syscore_ops jive_pm_syscore_ops = { static void __init jive_map_io(void) { s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(jive_uartcfgs, ARRAY_SIZE(jive_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init jive_init_time(void) +{ + s3c2412_init_clocks(12000000); + samsung_timer_init(); +} + static void jive_power_off(void) { printk(KERN_INFO "powering system down...\n"); @@ -665,6 +670,6 @@ MACHINE_START(JIVE, "JIVE") .init_irq = s3c2412_init_irq, .map_io = jive_map_io, .init_machine = jive_machine_init, - .init_time = samsung_timer_init, + .init_time = jive_init_time, .restart = s3c2412_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2413.c b/arch/arm/mach-s3c24xx/mach-smdk2413.c index 233fe52d2015..a38f8a049e22 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2413.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2413.c @@ -106,11 +106,16 @@ static void __init smdk2413_fixup(struct tag *tags, char **cmdline, static void __init smdk2413_map_io(void) { s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init smdk2413_init_time(void) +{ + s3c2412_init_clocks(12000000); + samsung_timer_init(); +} + static void __init smdk2413_machine_init(void) { /* Turn off suspend on both USB ports, and switch the * selectable USB port to USB device mode. */ @@ -159,6 +164,6 @@ MACHINE_START(SMDK2413, "SMDK2413") .init_irq = s3c2412_init_irq, .map_io = smdk2413_map_io, .init_machine = smdk2413_machine_init, - .init_time = samsung_timer_init, + .init_time = smdk2413_init_time, .restart = s3c2412_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c index 40868c0e0a68..6b706c915387 100644 --- a/arch/arm/mach-s3c24xx/mach-vstms.c +++ b/arch/arm/mach-s3c24xx/mach-vstms.c @@ -142,11 +142,16 @@ static void __init vstms_fixup(struct tag *tags, char **cmdline, static void __init vstms_map_io(void) { s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init vstms_init_time(void) +{ + s3c2412_init_clocks(12000000); + samsung_timer_init(); +} + static void __init vstms_init(void) { s3c_i2c0_set_platdata(NULL); @@ -162,6 +167,6 @@ MACHINE_START(VSTMS, "VSTMS") .init_irq = s3c2412_init_irq, .init_machine = vstms_init, .map_io = vstms_map_io, - .init_time = samsung_timer_init, + .init_time = vstms_init_time, .restart = s3c2412_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/s3c2412.c b/arch/arm/mach-s3c24xx/s3c2412.c index 657cbaca80ac..d49f52fbc842 100644 --- a/arch/arm/mach-s3c24xx/s3c2412.c +++ b/arch/arm/mach-s3c24xx/s3c2412.c @@ -173,49 +173,6 @@ void __init s3c2412_map_io(void) void __init_or_cpufreq s3c2412_setup_clocks(void) { - struct clk *xtal_clk; - unsigned long tmp; - unsigned long xtal; - unsigned long fclk; - unsigned long hclk; - unsigned long pclk; - - xtal_clk = clk_get(NULL, "xtal"); - xtal = clk_get_rate(xtal_clk); - clk_put(xtal_clk); - - /* now we've got our machine bits initialised, work out what - * clocks we've got */ - - fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal * 2); - - clk_mpll.rate = fclk; - - tmp = __raw_readl(S3C2410_CLKDIVN); - - /* work out clock scalings */ - - hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1); - hclk /= ((tmp & S3C2412_CLKDIVN_ARMDIVN) ? 2 : 1); - pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1); - - /* print brieft summary of clocks, etc */ - - printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", - print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); - - s3c24xx_setup_clocks(fclk, hclk, pclk); -} - -void __init s3c2412_init_clocks(int xtal) -{ - /* initialise the clocks here, to allow other things like the - * console to use them - */ - - s3c24xx_register_baseclocks(xtal); - s3c2412_setup_clocks(); - s3c2412_baseclk_add(); } /* need to register the subsystem before we actually register the device, and From d8b532578f39fdec159105bc415938910351a699 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:48:44 +0900 Subject: [PATCH 13/23] ARM: S3C24XX: cpufreq-utils: don't write raw values to MPLLCON when using ccf The s3c24xx cpufreq driver needs to change the mpll speed and was doing this by writing raw values from a translation table into the MPLLCON register. Change this to use a regular clk_set_rate call when using the common clock framework and only write the raw value in the samsung_clock case. The s3c cpufreq driver does already aquire the mpll, so simply add a reference to struct s3c_cpufreq_config to let set_fvco access it. While struct clk is opaque the differenciation between samsung clock and common clock is kept, as the samsung-clock mpll clk does not implement a real set_rate. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/cpufreq-utils.c | 8 ++++++++ arch/arm/plat-samsung/include/plat/cpu-freq-core.h | 1 + drivers/cpufreq/s3c24xx-cpufreq.c | 1 + 3 files changed, 10 insertions(+) diff --git a/arch/arm/mach-s3c24xx/cpufreq-utils.c b/arch/arm/mach-s3c24xx/cpufreq-utils.c index 2a0aa5684e72..c1b7508523ad 100644 --- a/arch/arm/mach-s3c24xx/cpufreq-utils.c +++ b/arch/arm/mach-s3c24xx/cpufreq-utils.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -60,5 +61,12 @@ void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg) */ void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg) { +#ifdef CONFIG_SAMSUNG_CLOCK __raw_writel(cfg->pll.driver_data, S3C2410_MPLLCON); +#endif + +#ifdef CONFIG_COMMON_CLK + if (!IS_ERR(cfg->mpll)) + clk_set_rate(cfg->mpll, cfg->pll.frequency); +#endif } diff --git a/arch/arm/plat-samsung/include/plat/cpu-freq-core.h b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h index 7231c8e4975e..72d4178ad23b 100644 --- a/arch/arm/plat-samsung/include/plat/cpu-freq-core.h +++ b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h @@ -119,6 +119,7 @@ struct s3c_plltab { struct s3c_cpufreq_config { struct s3c_freq freq; struct s3c_freq max; + struct clk *mpll; struct cpufreq_frequency_table pll; struct s3c_clkdivs divs; struct s3c_cpufreq_info *info; /* for core, not drivers */ diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index be1b2b5c9753..227ebf7c1eea 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -141,6 +141,7 @@ static int s3c_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) static void s3c_cpufreq_setfvco(struct s3c_cpufreq_config *cfg) { + cfg->mpll = _clk_mpll; (cfg->info->set_fvco)(cfg); } From 5799ea12a41286d9588155a1abd828f43bc63d6b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:48:51 +0900 Subject: [PATCH 14/23] clk: samsung: add clock driver for external clock outputs This adds a driver for controlling the external clock outputs of s3c24xx architectures including the dclk muxes and dividers. The driver at the moment only supports the legacy non-dt boards using these clock outputs. The clock-output control itself is part of the system-controller mainly controlled by the pinctrl drivers. So it should most likely be integrated there for dt platforms. Signed-off-by: Heiko Stuebner Acked-by: Mike Turquette Signed-off-by: Kukjin Kim --- drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-s3c2410-dclk.c | 440 +++++++++++++++++++++++++ 2 files changed, 441 insertions(+) create mode 100644 drivers/clk/samsung/clk-s3c2410-dclk.c diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 77313e27bc39..9892de4978e3 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o +obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c new file mode 100644 index 000000000000..8d8dff005c10 --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2410-dclk.c @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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 s3c24xx external clock output. + */ + +#include +#include +#include "clk.h" + +/* legacy access to misccr, until dt conversion is finished */ +#include +#include + +#define MUX_DCLK0 0 +#define MUX_DCLK1 1 +#define DIV_DCLK0 2 +#define DIV_DCLK1 3 +#define GATE_DCLK0 4 +#define GATE_DCLK1 5 +#define MUX_CLKOUT0 6 +#define MUX_CLKOUT1 7 +#define DCLK_MAX_CLKS (MUX_CLKOUT1 + 1) + +enum supported_socs { + S3C2410, + S3C2412, + S3C2440, + S3C2443, +}; + +struct s3c24xx_dclk_drv_data { + const char **clkout0_parent_names; + int clkout0_num_parents; + const char **clkout1_parent_names; + int clkout1_num_parents; + const char **mux_parent_names; + int mux_num_parents; +}; + +/* + * Clock for output-parent selection in misccr + */ + +struct s3c24xx_clkout { + struct clk_hw hw; + u32 mask; + u8 shift; +}; + +#define to_s3c24xx_clkout(_hw) container_of(_hw, struct s3c24xx_clkout, hw) + +static u8 s3c24xx_clkout_get_parent(struct clk_hw *hw) +{ + struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw); + int num_parents = __clk_get_num_parents(hw->clk); + u32 val; + + val = readl_relaxed(S3C24XX_MISCCR) >> clkout->shift; + val >>= clkout->shift; + val &= clkout->mask; + + if (val >= num_parents) + return -EINVAL; + + return val; +} + +static int s3c24xx_clkout_set_parent(struct clk_hw *hw, u8 index) +{ + struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw); + int ret = 0; + + s3c2410_modify_misccr((clkout->mask << clkout->shift), + (index << clkout->shift)); + + return ret; +} + +const struct clk_ops s3c24xx_clkout_ops = { + .get_parent = s3c24xx_clkout_get_parent, + .set_parent = s3c24xx_clkout_set_parent, + .determine_rate = __clk_mux_determine_rate, +}; + +struct clk *s3c24xx_register_clkout(struct device *dev, const char *name, + const char **parent_names, u8 num_parents, + u8 shift, u32 mask) +{ + struct s3c24xx_clkout *clkout; + struct clk *clk; + struct clk_init_data init; + + /* allocate the clkout */ + clkout = kzalloc(sizeof(*clkout), GFP_KERNEL); + if (!clkout) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &s3c24xx_clkout_ops; + init.flags = CLK_IS_BASIC; + init.parent_names = parent_names; + init.num_parents = num_parents; + + clkout->shift = shift; + clkout->mask = mask; + clkout->hw.init = &init; + + clk = clk_register(dev, &clkout->hw); + + return clk; +} + +/* + * dclk and clkout init + */ + +struct s3c24xx_dclk { + struct device *dev; + void __iomem *base; + struct clk_onecell_data clk_data; + struct notifier_block dclk0_div_change_nb; + struct notifier_block dclk1_div_change_nb; + spinlock_t dclk_lock; + unsigned long reg_save; +}; + +#define to_s3c24xx_dclk0(x) \ + container_of(x, struct s3c24xx_dclk, dclk0_div_change_nb) + +#define to_s3c24xx_dclk1(x) \ + container_of(x, struct s3c24xx_dclk, dclk1_div_change_nb) + +PNAME(dclk_s3c2410_p) = { "pclk", "uclk" }; +PNAME(clkout0_s3c2410_p) = { "mpll", "upll", "fclk", "hclk", "pclk", + "gate_dclk0" }; +PNAME(clkout1_s3c2410_p) = { "mpll", "upll", "fclk", "hclk", "pclk", + "gate_dclk1" }; + +PNAME(clkout0_s3c2412_p) = { "mpll", "upll", "rtc_clkout", + "hclk", "pclk", "gate_dclk0" }; +PNAME(clkout1_s3c2412_p) = { "xti", "upll", "fclk", "hclk", "pclk", + "gate_dclk1" }; + +PNAME(clkout0_s3c2440_p) = { "xti", "upll", "fclk", "hclk", "pclk", + "gate_dclk0" }; +PNAME(clkout1_s3c2440_p) = { "mpll", "upll", "rtc_clkout", + "hclk", "pclk", "gate_dclk1" }; + +PNAME(dclk_s3c2443_p) = { "pclk", "epll" }; +PNAME(clkout0_s3c2443_p) = { "xti", "epll", "armclk", "hclk", "pclk", + "gate_dclk0" }; +PNAME(clkout1_s3c2443_p) = { "dummy", "epll", "rtc_clkout", + "hclk", "pclk", "gate_dclk1" }; + +#define DCLKCON_DCLK_DIV_MASK 0xf +#define DCLKCON_DCLK0_DIV_SHIFT 4 +#define DCLKCON_DCLK0_CMP_SHIFT 8 +#define DCLKCON_DCLK1_DIV_SHIFT 20 +#define DCLKCON_DCLK1_CMP_SHIFT 24 + +static void s3c24xx_dclk_update_cmp(struct s3c24xx_dclk *s3c24xx_dclk, + int div_shift, int cmp_shift) +{ + unsigned long flags = 0; + u32 dclk_con, div, cmp; + + spin_lock_irqsave(&s3c24xx_dclk->dclk_lock, flags); + + dclk_con = readl_relaxed(s3c24xx_dclk->base); + + div = ((dclk_con >> div_shift) & DCLKCON_DCLK_DIV_MASK) + 1; + cmp = ((div + 1) / 2) - 1; + + dclk_con &= ~(DCLKCON_DCLK_DIV_MASK << cmp_shift); + dclk_con |= (cmp << cmp_shift); + + writel_relaxed(dclk_con, s3c24xx_dclk->base); + + spin_unlock_irqrestore(&s3c24xx_dclk->dclk_lock, flags); +} + +static int s3c24xx_dclk0_div_notify(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk0(nb); + + if (event == POST_RATE_CHANGE) { + s3c24xx_dclk_update_cmp(s3c24xx_dclk, + DCLKCON_DCLK0_DIV_SHIFT, DCLKCON_DCLK0_CMP_SHIFT); + } + + return NOTIFY_DONE; +} + +static int s3c24xx_dclk1_div_notify(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk1(nb); + + if (event == POST_RATE_CHANGE) { + s3c24xx_dclk_update_cmp(s3c24xx_dclk, + DCLKCON_DCLK1_DIV_SHIFT, DCLKCON_DCLK1_CMP_SHIFT); + } + + return NOTIFY_DONE; +} + +#ifdef CONFIG_PM_SLEEP +static int s3c24xx_dclk_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev); + + s3c24xx_dclk->reg_save = readl_relaxed(s3c24xx_dclk->base); + return 0; +} + +static int s3c24xx_dclk_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev); + + writel_relaxed(s3c24xx_dclk->reg_save, s3c24xx_dclk->base); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(s3c24xx_dclk_pm_ops, + s3c24xx_dclk_suspend, s3c24xx_dclk_resume); + +static int s3c24xx_dclk_probe(struct platform_device *pdev) +{ + struct s3c24xx_dclk *s3c24xx_dclk; + struct resource *mem; + struct clk **clk_table; + struct s3c24xx_dclk_drv_data *dclk_variant; + int ret, i; + + s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk), + GFP_KERNEL); + if (!s3c24xx_dclk) + return -ENOMEM; + + s3c24xx_dclk->dev = &pdev->dev; + platform_set_drvdata(pdev, s3c24xx_dclk); + spin_lock_init(&s3c24xx_dclk->dclk_lock); + + clk_table = devm_kzalloc(&pdev->dev, + sizeof(struct clk *) * DCLK_MAX_CLKS, + GFP_KERNEL); + if (!clk_table) + return -ENOMEM; + + s3c24xx_dclk->clk_data.clks = clk_table; + s3c24xx_dclk->clk_data.clk_num = DCLK_MAX_CLKS; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + s3c24xx_dclk->base = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(s3c24xx_dclk->base)) + return PTR_ERR(s3c24xx_dclk->base); + + dclk_variant = (struct s3c24xx_dclk_drv_data *) + platform_get_device_id(pdev)->driver_data; + + + clk_table[MUX_DCLK0] = clk_register_mux(&pdev->dev, "mux_dclk0", + dclk_variant->mux_parent_names, + dclk_variant->mux_num_parents, 0, + s3c24xx_dclk->base, 1, 1, 0, + &s3c24xx_dclk->dclk_lock); + clk_table[MUX_DCLK1] = clk_register_mux(&pdev->dev, "mux_dclk1", + dclk_variant->mux_parent_names, + dclk_variant->mux_num_parents, 0, + s3c24xx_dclk->base, 17, 1, 0, + &s3c24xx_dclk->dclk_lock); + + clk_table[DIV_DCLK0] = clk_register_divider(&pdev->dev, "div_dclk0", + "mux_dclk0", 0, s3c24xx_dclk->base, + 4, 4, 0, &s3c24xx_dclk->dclk_lock); + clk_table[DIV_DCLK1] = clk_register_divider(&pdev->dev, "div_dclk1", + "mux_dclk1", 0, s3c24xx_dclk->base, + 20, 4, 0, &s3c24xx_dclk->dclk_lock); + + clk_table[GATE_DCLK0] = clk_register_gate(&pdev->dev, "gate_dclk0", + "div_dclk0", CLK_SET_RATE_PARENT, + s3c24xx_dclk->base, 0, 0, + &s3c24xx_dclk->dclk_lock); + clk_table[GATE_DCLK1] = clk_register_gate(&pdev->dev, "gate_dclk1", + "div_dclk1", CLK_SET_RATE_PARENT, + s3c24xx_dclk->base, 16, 0, + &s3c24xx_dclk->dclk_lock); + + clk_table[MUX_CLKOUT0] = s3c24xx_register_clkout(&pdev->dev, + "clkout0", dclk_variant->clkout0_parent_names, + dclk_variant->clkout0_num_parents, 4, 7); + clk_table[MUX_CLKOUT1] = s3c24xx_register_clkout(&pdev->dev, + "clkout1", dclk_variant->clkout1_parent_names, + dclk_variant->clkout1_num_parents, 8, 7); + + for (i = 0; i < DCLK_MAX_CLKS; i++) + if (IS_ERR(clk_table[i])) { + dev_err(&pdev->dev, "clock %d failed to register\n", i); + ret = PTR_ERR(clk_table[i]); + goto err_clk_register; + } + + ret = clk_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL); + if (!ret) + ret = clk_register_clkdev(clk_table[MUX_DCLK1], "dclk1", NULL); + if (!ret) + ret = clk_register_clkdev(clk_table[MUX_CLKOUT0], + "clkout0", NULL); + if (!ret) + ret = clk_register_clkdev(clk_table[MUX_CLKOUT1], + "clkout1", NULL); + if (ret) { + dev_err(&pdev->dev, "failed to register aliases, %d\n", ret); + goto err_clk_register; + } + + s3c24xx_dclk->dclk0_div_change_nb.notifier_call = + s3c24xx_dclk0_div_notify; + + s3c24xx_dclk->dclk1_div_change_nb.notifier_call = + s3c24xx_dclk1_div_notify; + + ret = clk_notifier_register(clk_table[DIV_DCLK0], + &s3c24xx_dclk->dclk0_div_change_nb); + if (ret) + goto err_clk_register; + + ret = clk_notifier_register(clk_table[DIV_DCLK1], + &s3c24xx_dclk->dclk1_div_change_nb); + if (ret) + goto err_dclk_notify; + + return 0; + +err_dclk_notify: + clk_notifier_unregister(clk_table[DIV_DCLK0], + &s3c24xx_dclk->dclk0_div_change_nb); +err_clk_register: + for (i = 0; i < DCLK_MAX_CLKS; i++) + if (clk_table[i] && !IS_ERR(clk_table[i])) + clk_unregister(clk_table[i]); + + return ret; +} + +static int s3c24xx_dclk_remove(struct platform_device *pdev) +{ + struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev); + struct clk **clk_table = s3c24xx_dclk->clk_data.clks; + int i; + + clk_notifier_unregister(clk_table[DIV_DCLK1], + &s3c24xx_dclk->dclk1_div_change_nb); + clk_notifier_unregister(clk_table[DIV_DCLK0], + &s3c24xx_dclk->dclk0_div_change_nb); + + for (i = 0; i < DCLK_MAX_CLKS; i++) + clk_unregister(clk_table[i]); + + return 0; +} + +static struct s3c24xx_dclk_drv_data dclk_variants[] = { + [S3C2410] = { + .clkout0_parent_names = clkout0_s3c2410_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2410_p), + .clkout1_parent_names = clkout1_s3c2410_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2410_p), + .mux_parent_names = dclk_s3c2410_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p), + }, + [S3C2412] = { + .clkout0_parent_names = clkout0_s3c2412_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2412_p), + .clkout1_parent_names = clkout1_s3c2412_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2412_p), + .mux_parent_names = dclk_s3c2410_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p), + }, + [S3C2440] = { + .clkout0_parent_names = clkout0_s3c2440_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2440_p), + .clkout1_parent_names = clkout1_s3c2440_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2440_p), + .mux_parent_names = dclk_s3c2410_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p), + }, + [S3C2443] = { + .clkout0_parent_names = clkout0_s3c2443_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2443_p), + .clkout1_parent_names = clkout1_s3c2443_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2443_p), + .mux_parent_names = dclk_s3c2443_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2443_p), + }, +}; + +static struct platform_device_id s3c24xx_dclk_driver_ids[] = { + { + .name = "s3c2410-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2410], + }, { + .name = "s3c2412-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2412], + }, { + .name = "s3c2440-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2440], + }, { + .name = "s3c2443-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2443], + }, + { } +}; + +MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids); + +static struct platform_driver s3c24xx_dclk_driver = { + .driver = { + .name = "s3c24xx-dclk", + .owner = THIS_MODULE, + .pm = &s3c24xx_dclk_pm_ops, + }, + .probe = s3c24xx_dclk_probe, + .remove = s3c24xx_dclk_remove, + .id_table = s3c24xx_dclk_driver_ids, +}; +module_platform_driver(s3c24xx_dclk_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Heiko Stuebner "); +MODULE_DESCRIPTION("Driver for the S3C24XX external clock outputs"); From 51cb128987d96538fdea4ce3704e79257afad4a5 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:48:57 +0900 Subject: [PATCH 15/23] ARM: S3C24XX: enable usage of common dclk if common clock framework is enabled Add platform device and select the correct implementation automatically depending on wether the old samsung_clock or the common clock framework is enabled. This is only done for machines already using the old dclk implementation, as everybody else should move to use dt anyway. The machine-specific settings for the external clocks will have to be set by somebody with knowledge about the specific hardware. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa [pebolle@tiscali.nl: pointed out typo and fixed] Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 22 +++++++++++++++++----- arch/arm/mach-s3c24xx/common.c | 14 ++++++++++++++ arch/arm/mach-s3c24xx/common.h | 2 ++ arch/arm/mach-s3c24xx/mach-anubis.c | 5 +++++ arch/arm/mach-s3c24xx/mach-bast.c | 5 +++++ arch/arm/mach-s3c24xx/mach-osiris.c | 5 +++++ arch/arm/mach-s3c24xx/mach-rx1950.c | 5 +++++ arch/arm/mach-s3c24xx/mach-vr1000.c | 5 +++++ arch/arm/mach-s3c24xx/s3c244x.c | 2 ++ 9 files changed, 60 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index fbafb9a1975b..c9378806b9e8 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -18,6 +18,13 @@ config PLAT_S3C24XX help Base platform code for any Samsung S3C24XX device +config S3C2410_COMMON_DCLK + bool + select REGMAP_MMIO + help + Temporary symbol to build the dclk driver based on the common clock + framework. + menu "SAMSUNG S3C24XX SoCs Support" comment "S3C24XX SoCs" @@ -263,8 +270,9 @@ config ARCH_BAST bool "Simtec Electronics BAST (EB2410ITX)" select ISA select MACH_BAST_IDE + select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2410_CPUFREQ - select S3C24XX_DCLK + select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_NOR select S3C24XX_SIMTEC_PM if PM select S3C24XX_SIMTEC_USB @@ -345,7 +353,8 @@ config MACH_TCT_HAMMER config MACH_VR1000 bool "Thorcom VR1000" select MACH_BAST_IDE - select S3C24XX_DCLK + select S3C2410_COMMON_DCLK if COMMON_CLK + select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_NOR select S3C24XX_SIMTEC_PM if PM select S3C24XX_SIMTEC_USB @@ -529,8 +538,9 @@ comment "S3C2440 Boards" config MACH_ANUBIS bool "Simtec Electronics ANUBIS" select HAVE_PATA_PLATFORM + select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2440_XTAL_12000000 - select S3C24XX_DCLK + select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_PM if PM select S3C_DEV_USB_HOST help @@ -568,9 +578,10 @@ config MACH_NEXCODER_2440 config MACH_OSIRIS bool "Simtec IM2440D20 (OSIRIS) module" + select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ select S3C2440_XTAL_12000000 - select S3C24XX_DCLK + select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_PM if PM select S3C_DEV_NAND select S3C_DEV_USB_HOST @@ -639,9 +650,10 @@ config MACH_RX1950 bool "HP iPAQ rx1950" select I2C select PM_H1940 if PM + select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ select S3C2440_XTAL_16934400 - select S3C24XX_DCLK + select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_PWM select S3C_DEV_NAND help diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index ad5b76bf4d51..7cc6d944c820 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -553,3 +553,17 @@ void __init s3c2443_init_clocks(int xtal) s3c2443_common_clk_init(NULL, xtal, 1, S3C24XX_VA_CLKPWR); } #endif + +#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2440) || \ + defined(CONFIG_CPU_S3C2442) +static struct resource s3c2410_dclk_resource[] = { + [0] = DEFINE_RES_MEM(0x56000084, 0x4), +}; + +struct platform_device s3c2410_device_dclk = { + .name = "s3c2410-dclk", + .id = 0, + .num_resources = ARRAY_SIZE(s3c2410_dclk_resource), + .resource = s3c2410_dclk_resource, +}; +#endif diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index 3fade6d796f9..50504c77fa00 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h @@ -114,6 +114,8 @@ extern struct platform_device s3c2412_device_dma; extern struct platform_device s3c2440_device_dma; extern struct platform_device s3c2443_device_dma; +extern struct platform_device s3c2410_device_dclk; + #ifdef CONFIG_S3C2412_COMMON_CLK void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, unsigned long ext_f, void __iomem *reg_base); diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c index 81a270af2336..f81944f3217d 100644 --- a/arch/arm/mach-s3c24xx/mach-anubis.c +++ b/arch/arm/mach-s3c24xx/mach-anubis.c @@ -352,6 +352,7 @@ static struct platform_device anubis_device_sm501 = { /* Standard Anubis devices */ static struct platform_device *anubis_devices[] __initdata = { + &s3c2410_device_dclk, &s3c_device_ohci, &s3c_device_wdt, &s3c_device_adc, @@ -364,6 +365,7 @@ static struct platform_device *anubis_devices[] __initdata = { &anubis_device_sm501, }; +#ifdef CONFIG_SAMSUNG_CLOCK static struct clk *anubis_clocks[] __initdata = { &s3c24xx_dclk0, &s3c24xx_dclk1, @@ -371,6 +373,7 @@ static struct clk *anubis_clocks[] __initdata = { &s3c24xx_clkout1, &s3c24xx_uclk, }; +#endif /* I2C devices. */ @@ -394,6 +397,7 @@ static struct s3c24xx_audio_simtec_pdata __initdata anubis_audio = { static void __init anubis_map_io(void) { +#ifdef CONFIG_SAMSUNG_CLOCK /* initialise the clocks */ s3c24xx_dclk0.parent = &clk_upll; @@ -408,6 +412,7 @@ static void __init anubis_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks)); +#endif s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc)); s3c24xx_init_clocks(0); diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c index e371ff53a408..dcdc4a575690 100644 --- a/arch/arm/mach-s3c24xx/mach-bast.c +++ b/arch/arm/mach-s3c24xx/mach-bast.c @@ -523,6 +523,7 @@ static struct s3c_hwmon_pdata bast_hwmon_info = { // cat /sys/devices/platform/s3c24xx-adc/s3c-hwmon/in_0 static struct platform_device *bast_devices[] __initdata = { + &s3c2410_device_dclk, &s3c_device_ohci, &s3c_device_lcd, &s3c_device_wdt, @@ -537,6 +538,7 @@ static struct platform_device *bast_devices[] __initdata = { &bast_sio, }; +#ifdef CONFIG_SAMSUNG_CLK static struct clk *bast_clocks[] __initdata = { &s3c24xx_dclk0, &s3c24xx_dclk1, @@ -544,6 +546,7 @@ static struct clk *bast_clocks[] __initdata = { &s3c24xx_clkout1, &s3c24xx_uclk, }; +#endif static struct s3c_cpufreq_board __initdata bast_cpufreq = { .refresh = 7800, /* 7.8usec */ @@ -558,6 +561,7 @@ static struct s3c24xx_audio_simtec_pdata __initdata bast_audio = { static void __init bast_map_io(void) { +#ifdef CONFIG_SAMSUNG_CLOCK /* initialise the clocks */ s3c24xx_dclk0.parent = &clk_upll; @@ -572,6 +576,7 @@ static void __init bast_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks)); +#endif s3c_hwmon_set_platdata(&bast_hwmon_info); diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c index a4ae4bb3666d..487be02e4f2c 100644 --- a/arch/arm/mach-s3c24xx/mach-osiris.c +++ b/arch/arm/mach-s3c24xx/mach-osiris.c @@ -344,12 +344,14 @@ static struct i2c_board_info osiris_i2c_devs[] __initdata = { /* Standard Osiris devices */ static struct platform_device *osiris_devices[] __initdata = { + &s3c2410_device_dclk, &s3c_device_i2c0, &s3c_device_wdt, &s3c_device_nand, &osiris_pcmcia, }; +#ifdef CONFIG_SAMSUNG_CLOCK static struct clk *osiris_clocks[] __initdata = { &s3c24xx_dclk0, &s3c24xx_dclk1, @@ -357,6 +359,7 @@ static struct clk *osiris_clocks[] __initdata = { &s3c24xx_clkout1, &s3c24xx_uclk, }; +#endif static struct s3c_cpufreq_board __initdata osiris_cpufreq = { .refresh = 7800, /* refresh period is 7.8usec */ @@ -368,6 +371,7 @@ static void __init osiris_map_io(void) { unsigned long flags; +#ifdef CONFIG_SAMSUNG_CLOCK /* initialise the clocks */ s3c24xx_dclk0.parent = &clk_upll; @@ -382,6 +386,7 @@ static void __init osiris_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; s3c24xx_register_clocks(osiris_clocks, ARRAY_SIZE(osiris_clocks)); +#endif s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc)); s3c24xx_init_clocks(0); diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c index afb784e934c8..219454c93db4 100644 --- a/arch/arm/mach-s3c24xx/mach-rx1950.c +++ b/arch/arm/mach-s3c24xx/mach-rx1950.c @@ -710,6 +710,7 @@ static struct i2c_board_info rx1950_i2c_devices[] = { }; static struct platform_device *rx1950_devices[] __initdata = { + &s3c2410_device_dclk, &s3c_device_lcd, &s3c_device_wdt, &s3c_device_i2c0, @@ -728,17 +729,21 @@ static struct platform_device *rx1950_devices[] __initdata = { &rx1950_leds, }; +#ifdef CONFIG_SAMSUNG_CLOCK static struct clk *rx1950_clocks[] __initdata = { &s3c24xx_clkout0, &s3c24xx_clkout1, }; +#endif static void __init rx1950_map_io(void) { +#ifdef CONFIG_SAMSUNG_CLOCK s3c24xx_clkout0.parent = &clk_h; s3c24xx_clkout1.parent = &clk_f; s3c24xx_register_clocks(rx1950_clocks, ARRAY_SIZE(rx1950_clocks)); +#endif s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc)); s3c24xx_init_clocks(16934000); diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c index 1cc5b1bd51cd..bedaeefdc9f0 100644 --- a/arch/arm/mach-s3c24xx/mach-vr1000.c +++ b/arch/arm/mach-s3c24xx/mach-vr1000.c @@ -286,6 +286,7 @@ static struct i2c_board_info vr1000_i2c_devs[] __initdata = { /* devices for this board */ static struct platform_device *vr1000_devices[] __initdata = { + &s3c2410_device_dclk, &s3c_device_ohci, &s3c_device_lcd, &s3c_device_wdt, @@ -299,6 +300,7 @@ static struct platform_device *vr1000_devices[] __initdata = { &vr1000_led3, }; +#ifdef CONFIG_SAMSUNG_CLOCK static struct clk *vr1000_clocks[] __initdata = { &s3c24xx_dclk0, &s3c24xx_dclk1, @@ -306,6 +308,7 @@ static struct clk *vr1000_clocks[] __initdata = { &s3c24xx_clkout1, &s3c24xx_uclk, }; +#endif static void vr1000_power_off(void) { @@ -314,6 +317,7 @@ static void vr1000_power_off(void) static void __init vr1000_map_io(void) { +#if CONFIG_SAMSUNG_CLOCK /* initialise clock sources */ s3c24xx_dclk0.parent = &clk_upll; @@ -328,6 +332,7 @@ static void __init vr1000_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; s3c24xx_register_clocks(vr1000_clocks, ARRAY_SIZE(vr1000_clocks)); +#endif pm_power_off = vr1000_power_off; diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c index fe30ebb234d2..76b691bf724e 100644 --- a/arch/arm/mach-s3c24xx/s3c244x.c +++ b/arch/arm/mach-s3c24xx/s3c244x.c @@ -46,6 +46,7 @@ #include #include +#include "common.h" #include "regs-dsc.h" static struct map_desc s3c244x_iodesc[] __initdata = { @@ -74,6 +75,7 @@ void __init s3c244x_map_io(void) s3c_nand_setname("s3c2440-nand"); s3c_device_ts.name = "s3c2440-ts"; s3c_device_usbgadget.name = "s3c2440-usbgadget"; + s3c2410_device_dclk.name = "s3c2440-dclk"; } void __init_or_cpufreq s3c244x_setup_clocks(void) From f11cadd58280e3aed7f16eb648d50a8faf4ebb1a Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:05 +0900 Subject: [PATCH 16/23] dt-bindings: add documentation for s3c2410 clock controller Describe the clock controller of s3c2410, s3c2440 and s3c2442. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Signed-off-by: Kukjin Kim --- .../bindings/clock/samsung,s3c2410-clock.txt | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c2410-clock.txt diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c2410-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c2410-clock.txt new file mode 100644 index 000000000000..0b64ad8dadf6 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/samsung,s3c2410-clock.txt @@ -0,0 +1,50 @@ +* Samsung S3C2410 Clock Controller + +The S3C2410 clock controller generates and supplies clock to various controllers +within the SoC. The clock binding described here is applicable to the s3c2410, +s3c2440 and s3c2442 SoCs in the s3c24x family. + +Required Properties: + +- compatible: should be one of the following. + - "samsung,s3c2410-clock" - controller compatible with S3C2410 SoC. + - "samsung,s3c2440-clock" - controller compatible with S3C2440 SoC. + - "samsung,s3c2442-clock" - controller compatible with S3C2442 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 SoC. + +All available clocks are defined as preprocessor macros in +dt-bindings/clock/samsung,s3c2410-clock.h header and can be used in device +tree sources. + +External clocks: + +The xti clock used as input for the plls is generated outside the SoC. It is +expected that is are defined using standard clock bindings with a +clock-output-names value of "xti". + +Example: Clock controller node: + + clocks: clock-controller@4c000000 { + compatible = "samsung,s3c2410-clock"; + reg = <0x4c000000 0x20>; + #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): + + serial@50004000 { + compatible = "samsung,s3c2440-uart"; + reg = <0x50004000 0x4000>; + interrupts = <1 23 3 4>, <1 23 4 4>; + clock-names = "uart", "clk_uart_baud2"; + clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>; + status = "disabled"; + }; From 3f7c01ade226e7006d76e42f8c9b99ada7085312 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:10 +0900 Subject: [PATCH 17/23] clk: samsung: add clock controller driver for s3c2410, s3c2440 and s3c2442 This driver can handle the clock controllers of the socs mentioned above, as they share a common clock tree with only small differences. The clock structure is built according to the manuals of the included SoCs and might include changes in comparison to the previous clock structure. As pll-rate-tables only the 12mhz variants are currently included. The original code was wrongly checking for 169mhz xti values [a 0 to much at the end], so the original 16mhz pll table would have never been included and its values are so obscure that I have no possibility to at least check their sane-ness. When using the formula from the manual the resulting frequency is near the table value but still slightly off. Signed-off-by: Heiko Stuebner Acked-by: Mike Turquette Signed-off-by: Kukjin Kim --- drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-s3c2410.c | 477 ++++++++++++++++++++++++++++ include/dt-bindings/clock/s3c2410.h | 62 ++++ 3 files changed, 540 insertions(+) create mode 100644 drivers/clk/samsung/clk-s3c2410.c create mode 100644 include/dt-bindings/clock/s3c2410.h diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 9892de4978e3..2cb62f87e068 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o +obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c new file mode 100644 index 000000000000..7b4182186a30 --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2410.c @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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 S3C2410 and following SoCs. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "clk-pll.h" + +#define LOCKTIME 0x00 +#define MPLLCON 0x04 +#define UPLLCON 0x08 +#define CLKCON 0x0c +#define CLKSLOW 0x10 +#define CLKDIVN 0x14 +#define CAMDIVN 0x18 + +/* the soc types */ +enum supported_socs { + S3C2410, + S3C2440, + S3C2442, +}; + +/* list of PLLs to be registered */ +enum s3c2410_plls { + mpll, upll, +}; + +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *s3c2410_save; + +/* + * list of controller registers to be saved and restored during a + * suspend/resume cycle. + */ +static unsigned long s3c2410_clk_regs[] __initdata = { + LOCKTIME, + MPLLCON, + UPLLCON, + CLKCON, + CLKSLOW, + CLKDIVN, + CAMDIVN, +}; + +static int s3c2410_clk_suspend(void) +{ + samsung_clk_save(reg_base, s3c2410_save, + ARRAY_SIZE(s3c2410_clk_regs)); + + return 0; +} + +static void s3c2410_clk_resume(void) +{ + samsung_clk_restore(reg_base, s3c2410_save, + ARRAY_SIZE(s3c2410_clk_regs)); +} + +static struct syscore_ops s3c2410_clk_syscore_ops = { + .suspend = s3c2410_clk_suspend, + .resume = s3c2410_clk_resume, +}; + +static void s3c2410_clk_sleep_init(void) +{ + s3c2410_save = samsung_clk_alloc_reg_dump(s3c2410_clk_regs, + ARRAY_SIZE(s3c2410_clk_regs)); + if (!s3c2410_save) { + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; + } + + register_syscore_ops(&s3c2410_clk_syscore_ops); + return; +} +#else +static void s3c2410_clk_sleep_init(void) {} +#endif + +PNAME(fclk_p) = { "mpll", "div_slow" }; + +struct samsung_mux_clock s3c2410_common_muxes[] __initdata = { + MUX(FCLK, "fclk", fclk_p, CLKSLOW, 4, 1), +}; + +static struct clk_div_table divslow_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 6 }, + { .val = 4, .div = 8 }, + { .val = 5, .div = 10 }, + { .val = 6, .div = 12 }, + { .val = 7, .div = 14 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2410_common_dividers[] __initdata = { + DIV_T(0, "div_slow", "xti", CLKSLOW, 0, 3, divslow_d), + DIV(PCLK, "pclk", "hclk", CLKDIVN, 0, 1), +}; + +struct samsung_gate_clock s3c2410_common_gates[] __initdata = { + GATE(PCLK_SPI, "spi", "pclk", CLKCON, 18, 0, 0), + GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 17, 0, 0), + GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 16, 0, 0), + GATE(PCLK_ADC, "adc", "pclk", CLKCON, 15, 0, 0), + GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 14, 0, 0), + GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 13, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 12, 0, 0), + GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 11, 0, 0), + GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 10, 0, 0), + GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 9, 0, 0), + GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 8, 0, 0), + GATE(HCLK_USBD, "usb-device", "hclk", CLKCON, 7, 0, 0), + GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0), + GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0), + GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0), +}; + +/* should be added _after_ the soc-specific clocks are created */ +struct samsung_clock_alias s3c2410_common_aliases[] __initdata = { + ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"), + ALIAS(PCLK_ADC, NULL, "adc"), + ALIAS(PCLK_RTC, NULL, "rtc"), + ALIAS(PCLK_PWM, NULL, "timers"), + ALIAS(HCLK_LCD, NULL, "lcd"), + ALIAS(HCLK_USBD, NULL, "usb-device"), + ALIAS(HCLK_USBH, NULL, "usb-host"), + ALIAS(UCLK, NULL, "usb-bus-host"), + ALIAS(UCLK, NULL, "usb-bus-gadget"), + ALIAS(ARMCLK, NULL, "armclk"), + ALIAS(UCLK, NULL, "uclk"), + ALIAS(HCLK, NULL, "hclk"), + ALIAS(MPLL, NULL, "mpll"), + ALIAS(FCLK, NULL, "fclk"), +}; + +/* S3C2410 specific clocks */ + +static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = { + /* sorted in descending order */ + /* 2410A extras */ + PLL_35XX_RATE(270000000, 127, 1, 1), + PLL_35XX_RATE(268000000, 126, 1, 1), + PLL_35XX_RATE(266000000, 125, 1, 1), + PLL_35XX_RATE(226000000, 105, 1, 1), + PLL_35XX_RATE(210000000, 132, 2, 1), + /* 2410 common */ + PLL_35XX_RATE(203000000, 161, 3, 1), + PLL_35XX_RATE(192000000, 88, 1, 1), + PLL_35XX_RATE(186000000, 85, 1, 1), + PLL_35XX_RATE(180000000, 82, 1, 1), + PLL_35XX_RATE(170000000, 77, 1, 1), + PLL_35XX_RATE(158000000, 71, 1, 1), + PLL_35XX_RATE(152000000, 68, 1, 1), + PLL_35XX_RATE(147000000, 90, 2, 1), + PLL_35XX_RATE(135000000, 82, 2, 1), + PLL_35XX_RATE(124000000, 116, 1, 2), + PLL_35XX_RATE(118000000, 150, 2, 2), + PLL_35XX_RATE(113000000, 105, 1, 2), + PLL_35XX_RATE(101000000, 127, 2, 2), + PLL_35XX_RATE(90000000, 112, 2, 2), + PLL_35XX_RATE(85000000, 105, 2, 2), + PLL_35XX_RATE(79000000, 71, 1, 2), + PLL_35XX_RATE(68000000, 82, 2, 2), + PLL_35XX_RATE(56000000, 142, 2, 3), + PLL_35XX_RATE(48000000, 120, 2, 3), + PLL_35XX_RATE(51000000, 161, 3, 3), + PLL_35XX_RATE(45000000, 82, 1, 3), + PLL_35XX_RATE(34000000, 82, 2, 3), + { /* sentinel */ }, +}; + +static struct samsung_pll_clock s3c2410_plls[] __initdata = { + [mpll] = PLL(pll_s3c2410_mpll, MPLL, "mpll", "xti", + LOCKTIME, MPLLCON, NULL), + [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti", + LOCKTIME, UPLLCON, NULL), +}; + +struct samsung_div_clock s3c2410_dividers[] __initdata = { + DIV(HCLK, "hclk", "mpll", CLKDIVN, 1, 1), +}; + +struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = { + /* + * armclk is directly supplied by the fclk, without + * switching possibility like on the s3c244x below. + */ + FFACTOR(ARMCLK, "armclk", "fclk", 1, 1, 0), + + /* uclk is fed from the unmodified upll */ + FFACTOR(UCLK, "uclk", "upll", 1, 1, 0), +}; + +struct samsung_clock_alias s3c2410_aliases[] __initdata = { + ALIAS(PCLK_UART0, "s3c2410-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2410-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2410-uart.2", "uart"), + ALIAS(PCLK_UART0, "s3c2410-uart.0", "clk_uart_baud0"), + ALIAS(PCLK_UART1, "s3c2410-uart.1", "clk_uart_baud0"), + ALIAS(PCLK_UART2, "s3c2410-uart.2", "clk_uart_baud0"), + ALIAS(UCLK, NULL, "clk_uart_baud1"), +}; + +/* S3C244x specific clocks */ + +static struct samsung_pll_rate_table pll_s3c244x_12mhz_tbl[] __initdata = { + /* sorted in descending order */ + PLL_35XX_RATE(400000000, 0x5c, 1, 1), + PLL_35XX_RATE(390000000, 0x7a, 2, 1), + PLL_35XX_RATE(380000000, 0x57, 1, 1), + PLL_35XX_RATE(370000000, 0xb1, 4, 1), + PLL_35XX_RATE(360000000, 0x70, 2, 1), + PLL_35XX_RATE(350000000, 0xa7, 4, 1), + PLL_35XX_RATE(340000000, 0x4d, 1, 1), + PLL_35XX_RATE(330000000, 0x66, 2, 1), + PLL_35XX_RATE(320000000, 0x98, 4, 1), + PLL_35XX_RATE(310000000, 0x93, 4, 1), + PLL_35XX_RATE(300000000, 0x75, 3, 1), + PLL_35XX_RATE(240000000, 0x70, 1, 2), + PLL_35XX_RATE(230000000, 0x6b, 1, 2), + PLL_35XX_RATE(220000000, 0x66, 1, 2), + PLL_35XX_RATE(210000000, 0x84, 2, 2), + PLL_35XX_RATE(200000000, 0x5c, 1, 2), + PLL_35XX_RATE(190000000, 0x57, 1, 2), + PLL_35XX_RATE(180000000, 0x70, 2, 2), + PLL_35XX_RATE(170000000, 0x4d, 1, 2), + PLL_35XX_RATE(160000000, 0x98, 4, 2), + PLL_35XX_RATE(150000000, 0x75, 3, 2), + PLL_35XX_RATE(120000000, 0x70, 1, 3), + PLL_35XX_RATE(110000000, 0x66, 1, 3), + PLL_35XX_RATE(100000000, 0x5c, 1, 3), + PLL_35XX_RATE(90000000, 0x70, 2, 3), + PLL_35XX_RATE(80000000, 0x98, 4, 3), + PLL_35XX_RATE(75000000, 0x75, 3, 3), + { /* sentinel */ }, +}; + +static struct samsung_pll_clock s3c244x_common_plls[] __initdata = { + [mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti", + LOCKTIME, MPLLCON, NULL), + [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti", + LOCKTIME, UPLLCON, NULL), +}; + +PNAME(hclk_p) = { "fclk", "div_hclk_2", "div_hclk_4", "div_hclk_3" }; +PNAME(armclk_p) = { "fclk", "hclk" }; + +struct samsung_mux_clock s3c244x_common_muxes[] __initdata = { + MUX(HCLK, "hclk", hclk_p, CLKDIVN, 1, 2), + MUX(ARMCLK, "armclk", armclk_p, CAMDIVN, 12, 1), +}; + +struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = { + FFACTOR(0, "div_hclk_2", "fclk", 1, 2, 0), + FFACTOR(0, "ff_cam", "div_cam", 2, 1, CLK_SET_RATE_PARENT), +}; + +static struct clk_div_table div_hclk_4_d[] = { + { .val = 0, .div = 4 }, + { .val = 1, .div = 8 }, + { /* sentinel */ }, +}; + +static struct clk_div_table div_hclk_3_d[] = { + { .val = 0, .div = 3 }, + { .val = 1, .div = 6 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c244x_common_dividers[] __initdata = { + DIV(UCLK, "uclk", "upll", CLKDIVN, 3, 1), + DIV(0, "div_hclk", "fclk", CLKDIVN, 1, 1), + DIV_T(0, "div_hclk_4", "fclk", CAMDIVN, 9, 1, div_hclk_4_d), + DIV_T(0, "div_hclk_3", "fclk", CAMDIVN, 8, 1, div_hclk_3_d), + DIV(0, "div_cam", "upll", CAMDIVN, 0, 3), +}; + +struct samsung_gate_clock s3c244x_common_gates[] __initdata = { + GATE(HCLK_CAM, "cam", "hclk", CLKCON, 19, 0, 0), +}; + +struct samsung_clock_alias s3c244x_common_aliases[] __initdata = { + ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"), + ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"), + ALIAS(HCLK_CAM, NULL, "camif"), + ALIAS(CAMIF, NULL, "camif-upll"), +}; + +/* S3C2440 specific clocks */ + +PNAME(s3c2440_camif_p) = { "upll", "ff_cam" }; + +struct samsung_mux_clock s3c2440_muxes[] __initdata = { + MUX(CAMIF, "camif", s3c2440_camif_p, CAMDIVN, 4, 1), +}; + +struct samsung_gate_clock s3c2440_gates[] __initdata = { + GATE(PCLK_AC97, "ac97", "pclk", CLKCON, 20, 0, 0), +}; + +/* S3C2442 specific clocks */ + +struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = { + FFACTOR(0, "upll_3", "upll", 1, 3, 0), +}; + +PNAME(s3c2442_camif_p) = { "upll", "ff_cam", "upll", "upll_3" }; + +struct samsung_mux_clock s3c2442_muxes[] __initdata = { + MUX(CAMIF, "camif", s3c2442_camif_p, CAMDIVN, 4, 2), +}; + +/* + * fixed rate clocks generated outside the soc + * Only necessary until the devicetree-move is complete + */ +#define XTI 1 +struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = { + FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0), +}; + +static void __init s3c2410_common_clk_register_fixed_ext(unsigned long xti_f) +{ + struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal"); + + s3c2410_common_frate_clks[0].fixed_rate = xti_f; + samsung_clk_register_fixed_rate(s3c2410_common_frate_clks, + ARRAY_SIZE(s3c2410_common_frate_clks)); + + samsung_clk_register_alias(&xti_alias, 1); +} + +void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, + int current_soc, + void __iomem *base) +{ + reg_base = base; + + if (np) { + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + } + + samsung_clk_init(np, reg_base, NR_CLKS); + + /* Register external clocks only in non-dt cases */ + if (!np) + s3c2410_common_clk_register_fixed_ext(xti_f); + + if (current_soc == 2410) { + if (_get_rate("xti") == 12 * MHZ) { + s3c2410_plls[mpll].rate_table = pll_s3c2410_12mhz_tbl; + s3c2410_plls[upll].rate_table = pll_s3c2410_12mhz_tbl; + } + + /* Register PLLs. */ + samsung_clk_register_pll(s3c2410_plls, + ARRAY_SIZE(s3c2410_plls), reg_base); + + } else { /* S3C2440, S3C2442 */ + if (_get_rate("xti") == 12 * MHZ) { + /* + * plls follow different calculation schemes, with the + * upll following the same scheme as the s3c2410 plls + */ + s3c244x_common_plls[mpll].rate_table = + pll_s3c244x_12mhz_tbl; + s3c244x_common_plls[upll].rate_table = + pll_s3c2410_12mhz_tbl; + } + + /* Register PLLs. */ + samsung_clk_register_pll(s3c244x_common_plls, + ARRAY_SIZE(s3c244x_common_plls), reg_base); + } + + /* Register common internal clocks. */ + samsung_clk_register_mux(s3c2410_common_muxes, + ARRAY_SIZE(s3c2410_common_muxes)); + samsung_clk_register_div(s3c2410_common_dividers, + ARRAY_SIZE(s3c2410_common_dividers)); + samsung_clk_register_gate(s3c2410_common_gates, + ARRAY_SIZE(s3c2410_common_gates)); + + if (current_soc == S3C2440 || current_soc == S3C2442) { + samsung_clk_register_div(s3c244x_common_dividers, + ARRAY_SIZE(s3c244x_common_dividers)); + samsung_clk_register_gate(s3c244x_common_gates, + ARRAY_SIZE(s3c244x_common_gates)); + samsung_clk_register_mux(s3c244x_common_muxes, + ARRAY_SIZE(s3c244x_common_muxes)); + samsung_clk_register_fixed_factor(s3c244x_common_ffactor, + ARRAY_SIZE(s3c244x_common_ffactor)); + } + + /* Register SoC-specific clocks. */ + switch (current_soc) { + case S3C2410: + samsung_clk_register_div(s3c2410_dividers, + ARRAY_SIZE(s3c2410_dividers)); + samsung_clk_register_fixed_factor(s3c2410_ffactor, + ARRAY_SIZE(s3c2410_ffactor)); + samsung_clk_register_alias(s3c2410_aliases, + ARRAY_SIZE(s3c2410_common_aliases)); + break; + case S3C2440: + samsung_clk_register_mux(s3c2440_muxes, + ARRAY_SIZE(s3c2440_muxes)); + samsung_clk_register_gate(s3c2440_gates, + ARRAY_SIZE(s3c2440_gates)); + break; + case S3C2442: + samsung_clk_register_mux(s3c2442_muxes, + ARRAY_SIZE(s3c2442_muxes)); + samsung_clk_register_fixed_factor(s3c2442_ffactor, + ARRAY_SIZE(s3c2442_ffactor)); + break; + } + + /* + * Register common aliases at the end, as some of the aliased clocks + * are SoC specific. + */ + samsung_clk_register_alias(s3c2410_common_aliases, + ARRAY_SIZE(s3c2410_common_aliases)); + + if (current_soc == S3C2440 || current_soc == S3C2442) { + samsung_clk_register_alias(s3c244x_common_aliases, + ARRAY_SIZE(s3c244x_common_aliases)); + } + + s3c2410_clk_sleep_init(); +} + +static void __init s3c2410_clk_init(struct device_node *np) +{ + s3c2410_common_clk_init(np, 0, S3C2410, 0); +} +CLK_OF_DECLARE(s3c2410_clk, "samsung,s3c2410-clock", s3c2410_clk_init); + +static void __init s3c2440_clk_init(struct device_node *np) +{ + s3c2410_common_clk_init(np, 0, S3C2440, 0); +} +CLK_OF_DECLARE(s3c2440_clk, "samsung,s3c2440-clock", s3c2440_clk_init); + +static void __init s3c2442_clk_init(struct device_node *np) +{ + s3c2410_common_clk_init(np, 0, S3C2442, 0); +} +CLK_OF_DECLARE(s3c2442_clk, "samsung,s3c2442-clock", s3c2442_clk_init); diff --git a/include/dt-bindings/clock/s3c2410.h b/include/dt-bindings/clock/s3c2410.h new file mode 100644 index 000000000000..352a7673fc69 --- /dev/null +++ b/include/dt-bindings/clock/s3c2410.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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 clock controllers of Samsung S3C2410 and later. + */ + +#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C2410_CLOCK_H +#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C2410_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. */ + +/* id 1 is reserved */ +#define MPLL 2 +#define UPLL 3 +#define FCLK 4 +#define HCLK 5 +#define PCLK 6 +#define UCLK 7 +#define ARMCLK 8 + +/* pclk-gates */ +#define PCLK_UART0 16 +#define PCLK_UART1 17 +#define PCLK_UART2 18 +#define PCLK_I2C 19 +#define PCLK_SDI 20 +#define PCLK_SPI 21 +#define PCLK_ADC 22 +#define PCLK_AC97 23 +#define PCLK_I2S 24 +#define PCLK_PWM 25 +#define PCLK_RTC 26 +#define PCLK_GPIO 27 + + +/* hclk-gates */ +#define HCLK_LCD 32 +#define HCLK_USBH 33 +#define HCLK_USBD 34 +#define HCLK_NAND 35 +#define HCLK_CAM 36 + + +#define CAMIF 40 + + +/* Total number of clocks. */ +#define NR_CLKS (CAMIF + 1) + +#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H */ From 4659c534834c33c698c9400e0aedd1e1aa48e9b6 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:14 +0900 Subject: [PATCH 18/23] ARM: S3C24XX: add platform code for conversion to the common clock framework This adds the necessary init functions to init the clocks from the common clock framework and necessary CONFIG_SAMSUNG_CLOCK ifdefs around the legacy clock code. This also includes empty stubs for the *_setup_clocks functions that are called from the cpufreq driver on resume. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 5 +++++ arch/arm/mach-s3c24xx/common.c | 25 +++++++++++++++++++++++++ arch/arm/mach-s3c24xx/common.h | 7 +++++++ arch/arm/mach-s3c24xx/s3c2410.c | 6 ++++++ arch/arm/mach-s3c24xx/s3c2442.c | 3 ++- arch/arm/mach-s3c24xx/s3c244x.c | 6 ++++++ 6 files changed, 51 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index c9378806b9e8..6a0fcb1c3303 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -18,6 +18,11 @@ config PLAT_S3C24XX help Base platform code for any Samsung S3C24XX device +config S3C2410_COMMON_CLK + bool + help + Build the s3c2410 clock driver based on the common clock framework. + config S3C2410_COMMON_DCLK bool select REGMAP_MMIO diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 7cc6d944c820..35cf88e1fa83 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "common.h" @@ -533,6 +534,14 @@ struct platform_device s3c2443_device_dma = { }; #endif +#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2410) +void __init s3c2410_init_clocks(int xtal) +{ + s3c2410_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR); + samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); +} +#endif + #ifdef CONFIG_CPU_S3C2412 void __init s3c2412_init_clocks(int xtal) { @@ -547,6 +556,22 @@ void __init s3c2416_init_clocks(int xtal) } #endif +#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2440) +void __init s3c2440_init_clocks(int xtal) +{ + s3c2410_common_clk_init(NULL, xtal, 1, S3C24XX_VA_CLKPWR); + samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); +} +#endif + +#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2442) +void __init s3c2442_init_clocks(int xtal) +{ + s3c2410_common_clk_init(NULL, xtal, 2, S3C24XX_VA_CLKPWR); + samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); +} +#endif + #ifdef CONFIG_CPU_S3C2443 void __init s3c2443_init_clocks(int xtal) { diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index 50504c77fa00..2d6554140161 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h @@ -77,6 +77,7 @@ extern void s3c244x_restart(enum reboot_mode mode, const char *cmd); #ifdef CONFIG_CPU_S3C2440 extern int s3c2440_init(void); extern void s3c2440_map_io(void); +extern void s3c2440_init_clocks(int xtal); extern void s3c2440_init_irq(void); #else #define s3c2440_init NULL @@ -86,6 +87,7 @@ extern void s3c2440_init_irq(void); #ifdef CONFIG_CPU_S3C2442 extern int s3c2442_init(void); extern void s3c2442_map_io(void); +extern void s3c2442_init_clocks(int xtal); extern void s3c2442_init_irq(void); #else #define s3c2442_init NULL @@ -116,6 +118,11 @@ extern struct platform_device s3c2443_device_dma; extern struct platform_device s3c2410_device_dclk; +#ifdef CONFIG_S3C2410_COMMON_CLK +void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, + int current_soc, + void __iomem *reg_base); +#endif #ifdef CONFIG_S3C2412_COMMON_CLK void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, unsigned long ext_f, void __iomem *reg_base); diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c index 04b58cb49888..52801730ab24 100644 --- a/arch/arm/mach-s3c24xx/s3c2410.c +++ b/arch/arm/mach-s3c24xx/s3c2410.c @@ -83,6 +83,7 @@ void __init s3c2410_map_io(void) iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); } +#ifdef CONFIG_SAMSUNG_CLOCK void __init_or_cpufreq s3c2410_setup_clocks(void) { struct clk *xtal_clk; @@ -142,6 +143,11 @@ void __init s3c2410_init_clocks(int xtal) clkdev_add_table(s3c2410_clk_lookup, ARRAY_SIZE(s3c2410_clk_lookup)); samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); } +#else +void __init_or_cpufreq s3c2410_setup_clocks(void) +{ +} +#endif struct bus_type s3c2410_subsys = { .name = "s3c2410-core", diff --git a/arch/arm/mach-s3c24xx/s3c2442.c b/arch/arm/mach-s3c24xx/s3c2442.c index 2c8adc028538..564c65037ff2 100644 --- a/arch/arm/mach-s3c24xx/s3c2442.c +++ b/arch/arm/mach-s3c24xx/s3c2442.c @@ -53,6 +53,7 @@ #include "common.h" +#ifdef CONFIG_SAMSUNG_CLOCK /* S3C2442 extended clock support */ static unsigned long s3c2442_camif_upll_round(struct clk *clk, @@ -162,7 +163,7 @@ static __init int s3c2442_clk_init(void) } arch_initcall(s3c2442_clk_init); - +#endif static struct device s3c2442_dev = { .bus = &s3c2442_subsys, diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c index 76b691bf724e..1d665d50b034 100644 --- a/arch/arm/mach-s3c24xx/s3c244x.c +++ b/arch/arm/mach-s3c24xx/s3c244x.c @@ -78,6 +78,7 @@ void __init s3c244x_map_io(void) s3c2410_device_dclk.name = "s3c2440-dclk"; } +#ifdef CONFIG_SAMSUNG_CLOCK void __init_or_cpufreq s3c244x_setup_clocks(void) { struct clk *xtal_clk; @@ -138,6 +139,11 @@ void __init s3c244x_init_clocks(int xtal) s3c2410_baseclk_add(); samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); } +#else +void __init_or_cpufreq s3c244x_setup_clocks(void) +{ +} +#endif /* Since the S3C2442 and S3C2440 share items, put both subsystems here */ From a28d618e2e424483afd47de6373665cd78352b25 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:19 +0900 Subject: [PATCH 19/23] ARM: S3C24XX: convert s3c2440 and s3c2442 to common clock framework Convert all machines using these cpus to use the ccf clock driver instead of the legacy Samsung clock implementation. Some of the more esotheric machines will probably need a fixup, as they do strange things to the clkout outputs, that I did not really understand nor have the hardware to check. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 8 ++++---- arch/arm/mach-s3c24xx/Makefile | 4 ++-- arch/arm/mach-s3c24xx/common.c | 4 ---- arch/arm/mach-s3c24xx/mach-anubis.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-at2440evb.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-gta02.c | 8 ++++++-- arch/arm/mach-s3c24xx/mach-mini2440.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-nexcoder.c | 15 ++++++++++++--- arch/arm/mach-s3c24xx/mach-osiris.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-rx1950.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-rx3715.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-smdk2440.c | 10 +++++++--- 12 files changed, 73 insertions(+), 36 deletions(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 6a0fcb1c3303..56ce1c6a283c 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -73,10 +73,10 @@ config CPU_S3C2416 config CPU_S3C2440 bool "SAMSUNG S3C2440" - depends on SAMSUNG_CLOCK + select COMMON_CLK select CPU_ARM920T select CPU_LLSERIAL_S3C2440 - select S3C2410_CLOCK + select S3C2410_COMMON_CLK select S3C2410_PM if PM select S3C2440_DMA if S3C24XX_DMA help @@ -84,10 +84,10 @@ config CPU_S3C2440 config CPU_S3C2442 bool "SAMSUNG S3C2442" - depends on SAMSUNG_CLOCK + select COMMON_CLK select CPU_ARM920T select CPU_LLSERIAL_S3C2440 - select S3C2410_CLOCK + select S3C2410_COMMON_CLK select S3C2410_DMA if S3C24XX_DMA select S3C2410_PM if PM help diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index f25479721dc9..9010ebaafff6 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile @@ -29,9 +29,9 @@ obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o obj-$(CONFIG_CPU_S3C2416) += s3c2416.o obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o -obj-$(CONFIG_CPU_S3C2440) += s3c2440.o clock-s3c2440.o +obj-$(CONFIG_CPU_S3C2440) += s3c2440.o obj-$(CONFIG_CPU_S3C2442) += s3c2442.o -obj-$(CONFIG_CPU_S3C244X) += s3c244x.o clock-s3c244x.o +obj-$(CONFIG_CPU_S3C244X) += s3c244x.o obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 35cf88e1fa83..bda9dd4abae3 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -92,7 +92,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32440000, .idmask = 0xffffffff, .map_io = s3c2440_map_io, - .init_clocks = s3c244x_init_clocks, .init_uarts = s3c244x_init_uarts, .init = s3c2440_init, .name = name_s3c2440 @@ -101,7 +100,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32440001, .idmask = 0xffffffff, .map_io = s3c2440_map_io, - .init_clocks = s3c244x_init_clocks, .init_uarts = s3c244x_init_uarts, .init = s3c2440_init, .name = name_s3c2440a @@ -110,7 +108,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32440aaa, .idmask = 0xffffffff, .map_io = s3c2442_map_io, - .init_clocks = s3c244x_init_clocks, .init_uarts = s3c244x_init_uarts, .init = s3c2442_init, .name = name_s3c2442 @@ -119,7 +116,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32440aab, .idmask = 0xffffffff, .map_io = s3c2442_map_io, - .init_clocks = s3c244x_init_clocks, .init_uarts = s3c244x_init_uarts, .init = s3c2442_init, .name = name_s3c2442b diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c index f81944f3217d..7a0d83b2f93a 100644 --- a/arch/arm/mach-s3c24xx/mach-anubis.c +++ b/arch/arm/mach-s3c24xx/mach-anubis.c @@ -46,7 +46,6 @@ #include -#include #include #include #include @@ -415,7 +414,6 @@ static void __init anubis_map_io(void) #endif s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); @@ -433,6 +431,12 @@ static void __init anubis_map_io(void) } } +static void __init anubis_init_time(void) +{ + s3c2440_init_clocks(12000000); + samsung_timer_init(); +} + static void __init anubis_init(void) { s3c_i2c0_set_platdata(NULL); @@ -452,6 +456,6 @@ MACHINE_START(ANUBIS, "Simtec-Anubis") .map_io = anubis_map_io, .init_machine = anubis_init, .init_irq = s3c2440_init_irq, - .init_time = samsung_timer_init, + .init_time = anubis_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c index d8f6bb1096cb..9db768f448a5 100644 --- a/arch/arm/mach-s3c24xx/mach-at2440evb.c +++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c @@ -45,7 +45,6 @@ #include #include -#include #include #include #include @@ -192,11 +191,16 @@ static struct platform_device *at2440evb_devices[] __initdata = { static void __init at2440evb_map_io(void) { s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc)); - s3c24xx_init_clocks(16934400); s3c24xx_init_uarts(at2440evb_uartcfgs, ARRAY_SIZE(at2440evb_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init at2440evb_init_time(void) +{ + s3c2440_init_clocks(16934400); + samsung_timer_init(); +} + static void __init at2440evb_init(void) { s3c24xx_fb_set_platdata(&at2440evb_fb_info); @@ -213,6 +217,6 @@ MACHINE_START(AT2440EVB, "AT2440EVB") .map_io = at2440evb_map_io, .init_machine = at2440evb_init, .init_irq = s3c2440_init_irq, - .init_time = samsung_timer_init, + .init_time = at2440evb_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c index dc4db849f0fd..fc3a08d0cb3f 100644 --- a/arch/arm/mach-s3c24xx/mach-gta02.c +++ b/arch/arm/mach-s3c24xx/mach-gta02.c @@ -501,7 +501,6 @@ static struct platform_device gta02_buttons_device = { static void __init gta02_map_io(void) { s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } @@ -585,6 +584,11 @@ static void __init gta02_machine_init(void) regulator_has_full_constraints(); } +static void __init gta02_init_time(void) +{ + s3c2442_init_clocks(12000000); + samsung_timer_init(); +} MACHINE_START(NEO1973_GTA02, "GTA02") /* Maintainer: Nelson Castillo */ @@ -592,6 +596,6 @@ MACHINE_START(NEO1973_GTA02, "GTA02") .map_io = gta02_map_io, .init_irq = s3c2442_init_irq, .init_machine = gta02_machine_init, - .init_time = samsung_timer_init, + .init_time = gta02_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c index 9e57fd9f4f3b..5cc40ec1d254 100644 --- a/arch/arm/mach-s3c24xx/mach-mini2440.c +++ b/arch/arm/mach-s3c24xx/mach-mini2440.c @@ -54,7 +54,6 @@ #include #include -#include #include #include #include @@ -525,11 +524,16 @@ static struct platform_device *mini2440_devices[] __initdata = { static void __init mini2440_map_io(void) { s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init mini2440_init_time(void) +{ + s3c2440_init_clocks(12000000); + samsung_timer_init(); +} + /* * mini2440_features string * @@ -690,6 +694,6 @@ MACHINE_START(MINI2440, "MINI2440") .map_io = mini2440_map_io, .init_machine = mini2440_init, .init_irq = s3c2440_init_irq, - .init_time = samsung_timer_init, + .init_time = mini2440_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-nexcoder.c b/arch/arm/mach-s3c24xx/mach-nexcoder.c index 3066851f584d..05627c2b5116 100644 --- a/arch/arm/mach-s3c24xx/mach-nexcoder.c +++ b/arch/arm/mach-s3c24xx/mach-nexcoder.c @@ -42,7 +42,6 @@ #include #include -#include #include #include #include @@ -135,13 +134,23 @@ static void __init nexcoder_sensorboard_init(void) static void __init nexcoder_map_io(void) { s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(nexcoder_uartcfgs, ARRAY_SIZE(nexcoder_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); nexcoder_sensorboard_init(); } +static void __init nexcoder_init_time(void) +{ + /* + * for whatever reason the nexcoder called s3c24xx_init_clocks(0) + * meaning a xti value of 0Hz, so this machine will most likely + * not work out of the box and needs a fixup. + */ + s3c2440_init_clocks(0); + samsung_timer_init(); +} + static void __init nexcoder_init(void) { s3c_i2c0_set_platdata(NULL); @@ -154,6 +163,6 @@ MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440") .map_io = nexcoder_map_io, .init_machine = nexcoder_init, .init_irq = s3c2440_init_irq, - .init_time = samsung_timer_init, + .init_time = nexcoder_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c index 487be02e4f2c..3bc2c9bad8b3 100644 --- a/arch/arm/mach-s3c24xx/mach-osiris.c +++ b/arch/arm/mach-s3c24xx/mach-osiris.c @@ -40,7 +40,6 @@ #include #include -#include #include #include #include @@ -389,7 +388,6 @@ static void __init osiris_map_io(void) #endif s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); @@ -413,6 +411,12 @@ static void __init osiris_map_io(void) local_irq_restore(flags); } +static void __init osiris_init_time(void) +{ + s3c2440_init_clocks(12000000); + samsung_timer_init(); +} + static void __init osiris_init(void) { register_syscore_ops(&osiris_pm_syscore_ops); @@ -434,6 +438,6 @@ MACHINE_START(OSIRIS, "Simtec-OSIRIS") .map_io = osiris_map_io, .init_irq = s3c2440_init_irq, .init_machine = osiris_init, - .init_time = samsung_timer_init, + .init_time = osiris_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c index 219454c93db4..5f37f5262e65 100644 --- a/arch/arm/mach-s3c24xx/mach-rx1950.c +++ b/arch/arm/mach-s3c24xx/mach-rx1950.c @@ -54,7 +54,6 @@ #include #include -#include #include #include #include @@ -746,7 +745,6 @@ static void __init rx1950_map_io(void) #endif s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc)); - s3c24xx_init_clocks(16934000); s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); @@ -759,6 +757,12 @@ static void __init rx1950_map_io(void) s3c_pm_init(); } +static void __init rx1950_init_time(void) +{ + s3c2442_init_clocks(16934000); + samsung_timer_init(); +} + static void __init rx1950_init_machine(void) { int i; @@ -821,6 +825,6 @@ MACHINE_START(RX1950, "HP iPAQ RX1950") .reserve = rx1950_reserve, .init_irq = s3c2442_init_irq, .init_machine = rx1950_init_machine, - .init_time = samsung_timer_init, + .init_time = rx1950_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c index e6535ce1bc5c..6e749ec3a2ea 100644 --- a/arch/arm/mach-s3c24xx/mach-rx3715.c +++ b/arch/arm/mach-s3c24xx/mach-rx3715.c @@ -46,7 +46,6 @@ #include #include -#include #include #include #include @@ -179,11 +178,16 @@ static struct platform_device *rx3715_devices[] __initdata = { static void __init rx3715_map_io(void) { s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc)); - s3c24xx_init_clocks(16934000); s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init rx3715_init_time(void) +{ + s3c2440_init_clocks(16934000); + samsung_timer_init(); +} + /* H1940 and RX3715 need to reserve this for suspend */ static void __init rx3715_reserve(void) { @@ -210,6 +214,6 @@ MACHINE_START(RX3715, "IPAQ-RX3715") .reserve = rx3715_reserve, .init_irq = s3c2440_init_irq, .init_machine = rx3715_init_machine, - .init_time = samsung_timer_init, + .init_time = rx3715_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2440.c b/arch/arm/mach-s3c24xx/mach-smdk2440.c index d071dcfea548..5fb89c0ae17a 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2440.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2440.c @@ -38,7 +38,6 @@ #include #include -#include #include #include #include @@ -159,11 +158,16 @@ static struct platform_device *smdk2440_devices[] __initdata = { static void __init smdk2440_map_io(void) { s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc)); - s3c24xx_init_clocks(16934400); s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init smdk2440_init_time(void) +{ + s3c2440_init_clocks(16934400); + samsung_timer_init(); +} + static void __init smdk2440_machine_init(void) { s3c24xx_fb_set_platdata(&smdk2440_fb_info); @@ -180,6 +184,6 @@ MACHINE_START(S3C2440, "SMDK2440") .init_irq = s3c2440_init_irq, .map_io = smdk2440_map_io, .init_machine = smdk2440_machine_init, - .init_time = samsung_timer_init, + .init_time = smdk2440_init_time, .restart = s3c244x_restart, MACHINE_END From 07ee5e7c3ec00b30996160e9a378471872ea779e Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:29 +0900 Subject: [PATCH 20/23] ARM: S3C24XX: convert s3c2410 to common clock framework Convert the machines using the s3c2410 to use the new driver based on the common clock framework instead of the legacy Samsung clock driver. As with the s3c244x, machines using the clkout output will need a fixup from someone with the hardware. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 4 ++-- arch/arm/mach-s3c24xx/common.c | 2 -- arch/arm/mach-s3c24xx/mach-amlm5900.c | 9 +++++++-- arch/arm/mach-s3c24xx/mach-bast.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-h1940.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-n30.c | 12 ++++++++---- arch/arm/mach-s3c24xx/mach-nexcoder.c | 7 +------ arch/arm/mach-s3c24xx/mach-otom.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-qt2410.c | 9 +++++++-- arch/arm/mach-s3c24xx/mach-smdk2410.c | 9 +++++++-- arch/arm/mach-s3c24xx/mach-tct_hammer.c | 9 +++++++-- arch/arm/mach-s3c24xx/mach-vr1000.c | 10 +++++++--- 12 files changed, 67 insertions(+), 34 deletions(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 56ce1c6a283c..23968c661415 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -37,10 +37,10 @@ comment "S3C24XX SoCs" config CPU_S3C2410 bool "SAMSUNG S3C2410" default y - depends on SAMSUNG_CLOCK + select COMMON_CLK select CPU_ARM920T select CPU_LLSERIAL_S3C2410 - select S3C2410_CLOCK + select S3C2410_COMMON_CLK select S3C2410_DMA if S3C24XX_DMA select ARM_S3C2410_CPUFREQ if ARM_S3C24XX_CPUFREQ select S3C2410_PM if PM diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index bda9dd4abae3..600a1be5696b 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -74,7 +74,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32410000, .idmask = 0xffffffff, .map_io = s3c2410_map_io, - .init_clocks = s3c2410_init_clocks, .init_uarts = s3c2410_init_uarts, .init = s3c2410_init, .name = name_s3c2410 @@ -83,7 +82,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32410002, .idmask = 0xffffffff, .map_io = s3c2410_map_io, - .init_clocks = s3c2410_init_clocks, .init_uarts = s3c2410_init_uarts, .init = s3c2410a_init, .name = name_s3c2410a diff --git a/arch/arm/mach-s3c24xx/mach-amlm5900.c b/arch/arm/mach-s3c24xx/mach-amlm5900.c index 8ac9554aa996..5157e250dd13 100644 --- a/arch/arm/mach-s3c24xx/mach-amlm5900.c +++ b/arch/arm/mach-s3c24xx/mach-amlm5900.c @@ -161,11 +161,16 @@ static struct platform_device *amlm5900_devices[] __initdata = { static void __init amlm5900_map_io(void) { s3c24xx_init_io(amlm5900_iodesc, ARRAY_SIZE(amlm5900_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(amlm5900_uartcfgs, ARRAY_SIZE(amlm5900_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init amlm5900_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + #ifdef CONFIG_FB_S3C2410 static struct s3c2410fb_display __initdata amlm5900_lcd_info = { .width = 160, @@ -241,6 +246,6 @@ MACHINE_START(AML_M5900, "AML_M5900") .map_io = amlm5900_map_io, .init_irq = s3c2410_init_irq, .init_machine = amlm5900_init, - .init_time = samsung_timer_init, + .init_time = amlm5900_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c index dcdc4a575690..ea762f20099b 100644 --- a/arch/arm/mach-s3c24xx/mach-bast.c +++ b/arch/arm/mach-s3c24xx/mach-bast.c @@ -51,7 +51,6 @@ #include #include -#include #include #include #include @@ -581,11 +580,16 @@ static void __init bast_map_io(void) s3c_hwmon_set_platdata(&bast_hwmon_info); s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init bast_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init bast_init(void) { register_syscore_ops(&bast_pm_syscore_ops); @@ -613,6 +617,6 @@ MACHINE_START(BAST, "Simtec-BAST") .map_io = bast_map_io, .init_irq = s3c2410_init_irq, .init_machine = bast_init, - .init_time = samsung_timer_init, + .init_time = bast_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c index e453acd92cbf..fbf5487ae5d1 100644 --- a/arch/arm/mach-s3c24xx/mach-h1940.c +++ b/arch/arm/mach-s3c24xx/mach-h1940.c @@ -57,7 +57,6 @@ #include #include -#include #include #include #include @@ -646,7 +645,6 @@ static struct platform_device *h1940_devices[] __initdata = { static void __init h1940_map_io(void) { s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); @@ -662,6 +660,12 @@ static void __init h1940_map_io(void) WARN_ON(gpiochip_add(&h1940_latch_gpiochip)); } +static void __init h1940_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + /* H1940 and RX3715 need to reserve this for suspend */ static void __init h1940_reserve(void) { @@ -739,6 +743,6 @@ MACHINE_START(H1940, "IPAQ-H1940") .reserve = h1940_reserve, .init_irq = s3c2410_init_irq, .init_machine = h1940_init, - .init_time = samsung_timer_init, + .init_time = h1940_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-n30.c b/arch/arm/mach-s3c24xx/mach-n30.c index 4cccaad34847..3ac2a54348d6 100644 --- a/arch/arm/mach-s3c24xx/mach-n30.c +++ b/arch/arm/mach-s3c24xx/mach-n30.c @@ -45,7 +45,6 @@ #include -#include #include #include #include @@ -535,11 +534,16 @@ static void __init n30_map_io(void) { s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc)); n30_hwinit(); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init n30_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + /* GPB3 is the line that controls the pull-up for the USB D+ line */ static void __init n30_init(void) @@ -591,7 +595,7 @@ MACHINE_START(N30, "Acer-N30") Ben Dooks */ .atag_offset = 0x100, - .init_time = samsung_timer_init, + .init_time = n30_init_time, .init_machine = n30_init, .init_irq = s3c2410_init_irq, .map_io = n30_map_io, @@ -602,7 +606,7 @@ MACHINE_START(N35, "Acer-N35") /* Maintainer: Christer Weinigel */ .atag_offset = 0x100, - .init_time = samsung_timer_init, + .init_time = n30_init_time, .init_machine = n30_init, .init_irq = s3c2410_init_irq, .map_io = n30_map_io, diff --git a/arch/arm/mach-s3c24xx/mach-nexcoder.c b/arch/arm/mach-s3c24xx/mach-nexcoder.c index 05627c2b5116..c82c281ce351 100644 --- a/arch/arm/mach-s3c24xx/mach-nexcoder.c +++ b/arch/arm/mach-s3c24xx/mach-nexcoder.c @@ -142,12 +142,7 @@ static void __init nexcoder_map_io(void) static void __init nexcoder_init_time(void) { - /* - * for whatever reason the nexcoder called s3c24xx_init_clocks(0) - * meaning a xti value of 0Hz, so this machine will most likely - * not work out of the box and needs a fixup. - */ - s3c2440_init_clocks(0); + s3c2440_init_clocks(12000000); samsung_timer_init(); } diff --git a/arch/arm/mach-s3c24xx/mach-otom.c b/arch/arm/mach-s3c24xx/mach-otom.c index bdb3faac2d9b..45833001186d 100644 --- a/arch/arm/mach-s3c24xx/mach-otom.c +++ b/arch/arm/mach-s3c24xx/mach-otom.c @@ -30,7 +30,6 @@ #include #include -#include #include #include #include @@ -100,11 +99,16 @@ static struct platform_device *otom11_devices[] __initdata = { static void __init otom11_map_io(void) { s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(otom11_uartcfgs, ARRAY_SIZE(otom11_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init otom11_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init otom11_init(void) { s3c_i2c0_set_platdata(NULL); @@ -117,6 +121,6 @@ MACHINE_START(OTOM, "Nex Vision - Otom 1.1") .map_io = otom11_map_io, .init_machine = otom11_init, .init_irq = s3c2410_init_irq, - .init_time = samsung_timer_init, + .init_time = otom11_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c index 8c12787a8fd3..228c9094519d 100644 --- a/arch/arm/mach-s3c24xx/mach-qt2410.c +++ b/arch/arm/mach-s3c24xx/mach-qt2410.c @@ -304,11 +304,16 @@ __setup("tft=", qt2410_tft_setup); static void __init qt2410_map_io(void) { s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc)); - s3c24xx_init_clocks(12*1000*1000); s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init qt2410_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init qt2410_machine_init(void) { s3c_nand_set_platdata(&qt2410_nand_info); @@ -346,6 +351,6 @@ MACHINE_START(QT2410, "QT2410") .map_io = qt2410_map_io, .init_irq = s3c2410_init_irq, .init_machine = qt2410_machine_init, - .init_time = samsung_timer_init, + .init_time = qt2410_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2410.c b/arch/arm/mach-s3c24xx/mach-smdk2410.c index f32924ee0e9f..419fadd6e446 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2410.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2410.c @@ -99,11 +99,16 @@ static struct platform_device *smdk2410_devices[] __initdata = { static void __init smdk2410_map_io(void) { s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init smdk2410_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init smdk2410_init(void) { s3c_i2c0_set_platdata(NULL); @@ -118,6 +123,6 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc .map_io = smdk2410_map_io, .init_irq = s3c2410_init_irq, .init_machine = smdk2410_init, - .init_time = samsung_timer_init, + .init_time = smdk2410_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-tct_hammer.c b/arch/arm/mach-s3c24xx/mach-tct_hammer.c index 4108b2f0cede..c616ca2d409e 100644 --- a/arch/arm/mach-s3c24xx/mach-tct_hammer.c +++ b/arch/arm/mach-s3c24xx/mach-tct_hammer.c @@ -135,11 +135,16 @@ static struct platform_device *tct_hammer_devices[] __initdata = { static void __init tct_hammer_map_io(void) { s3c24xx_init_io(tct_hammer_iodesc, ARRAY_SIZE(tct_hammer_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(tct_hammer_uartcfgs, ARRAY_SIZE(tct_hammer_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init tct_hammer_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init tct_hammer_init(void) { s3c_i2c0_set_platdata(NULL); @@ -151,6 +156,6 @@ MACHINE_START(TCT_HAMMER, "TCT_HAMMER") .map_io = tct_hammer_map_io, .init_irq = s3c2410_init_irq, .init_machine = tct_hammer_init, - .init_time = samsung_timer_init, + .init_time = tct_hammer_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c index bedaeefdc9f0..5f588bf20f43 100644 --- a/arch/arm/mach-s3c24xx/mach-vr1000.c +++ b/arch/arm/mach-s3c24xx/mach-vr1000.c @@ -43,7 +43,6 @@ #include #include -#include #include #include #include @@ -337,11 +336,16 @@ static void __init vr1000_map_io(void) pm_power_off = vr1000_power_off; s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init vr1000_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init vr1000_init(void) { s3c_i2c0_set_platdata(NULL); @@ -362,6 +366,6 @@ MACHINE_START(VR1000, "Thorcom-VR1000") .map_io = vr1000_map_io, .init_machine = vr1000_init, .init_irq = s3c2410_init_irq, - .init_time = samsung_timer_init, + .init_time = vr1000_init_time, .restart = s3c2410_restart, MACHINE_END From defd9da51d1a472ffa7a92ba71ffa07839bdc1a3 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:36 +0900 Subject: [PATCH 21/23] ARM: S3C24XX: remove legacy clock code With the move to the common clock framework completed for s3c2410, s3c2440 and s3c2442, the legacy clock code for these machines can go away too. This also includes the legacy dclk code, as all legacy users are converted. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 11 - arch/arm/mach-s3c24xx/Makefile | 2 - arch/arm/mach-s3c24xx/clock-dclk.c | 195 ------------ arch/arm/mach-s3c24xx/clock-s3c2410.c | 284 ------------------ arch/arm/mach-s3c24xx/clock-s3c2440.c | 217 ------------- arch/arm/mach-s3c24xx/clock-s3c244x.c | 141 --------- arch/arm/mach-s3c24xx/common.h | 2 - .../mach-s3c24xx/include/mach/regs-clock.h | 18 -- .../arm/mach-s3c24xx/include/mach/regs-gpio.h | 3 - arch/arm/mach-s3c24xx/pm.c | 12 - arch/arm/mach-s3c24xx/s3c2410.c | 62 ---- arch/arm/mach-s3c24xx/s3c2442.c | 112 ------- arch/arm/mach-s3c24xx/s3c244x.c | 63 ---- 13 files changed, 1122 deletions(-) delete mode 100644 arch/arm/mach-s3c24xx/clock-dclk.c delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2410.c delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2440.c delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c244x.c diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 23968c661415..f9bb1ea14fe4 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -110,17 +110,6 @@ config CPU_S3C2443 # common code -config S3C2410_CLOCK - bool - help - Clock code for the S3C2410, and similar processors which - is currently includes the S3C2410, S3C2440, S3C2442. - -config S3C24XX_DCLK - bool - help - Clock code for supporting DCLK/CLKOUT on S3C24XX architectures - config S3C24XX_SMDK bool help diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index 9010ebaafff6..2235d0d3b38d 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile @@ -44,10 +44,8 @@ obj-$(CONFIG_PM) += pm.o irq-pm.o sleep.o # common code -obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o obj-$(CONFIG_S3C24XX_DMA) += dma.o -obj-$(CONFIG_S3C2410_CLOCK) += clock-s3c2410.o obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o obj-$(CONFIG_S3C2410_IOTIMING) += iotiming-s3c2410.o diff --git a/arch/arm/mach-s3c24xx/clock-dclk.c b/arch/arm/mach-s3c24xx/clock-dclk.c deleted file mode 100644 index 1edd9b2369c5..000000000000 --- a/arch/arm/mach-s3c24xx/clock-dclk.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2004-2008 Simtec Electronics - * Ben Dooks - * http://armlinux.simtec.co.uk/ - * - * 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. - * - * S3C24XX - definitions for DCLK and CLKOUT registers - */ - -#include -#include -#include -#include - -#include -#include - -#include -#include - -/* clocks that could be registered by external code */ - -static int s3c24xx_dclk_enable(struct clk *clk, int enable) -{ - unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON); - - if (enable) - dclkcon |= clk->ctrlbit; - else - dclkcon &= ~clk->ctrlbit; - - __raw_writel(dclkcon, S3C24XX_DCLKCON); - - return 0; -} - -static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent) -{ - unsigned long dclkcon; - unsigned int uclk; - - if (parent == &clk_upll) - uclk = 1; - else if (parent == &clk_p) - uclk = 0; - else - return -EINVAL; - - clk->parent = parent; - - dclkcon = __raw_readl(S3C24XX_DCLKCON); - - if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) { - if (uclk) - dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK; - else - dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK; - } else { - if (uclk) - dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK; - else - dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK; - } - - __raw_writel(dclkcon, S3C24XX_DCLKCON); - - return 0; -} -static unsigned long s3c24xx_calc_div(struct clk *clk, unsigned long rate) -{ - unsigned long div; - - if ((rate == 0) || !clk->parent) - return 0; - - div = clk_get_rate(clk->parent) / rate; - if (div < 2) - div = 2; - else if (div > 16) - div = 16; - - return div; -} - -static unsigned long s3c24xx_round_dclk_rate(struct clk *clk, - unsigned long rate) -{ - unsigned long div = s3c24xx_calc_div(clk, rate); - - if (div == 0) - return 0; - - return clk_get_rate(clk->parent) / div; -} - -static int s3c24xx_set_dclk_rate(struct clk *clk, unsigned long rate) -{ - unsigned long mask, data, div = s3c24xx_calc_div(clk, rate); - - if (div == 0) - return -EINVAL; - - if (clk == &s3c24xx_dclk0) { - mask = S3C2410_DCLKCON_DCLK0_DIV_MASK | - S3C2410_DCLKCON_DCLK0_CMP_MASK; - data = S3C2410_DCLKCON_DCLK0_DIV(div) | - S3C2410_DCLKCON_DCLK0_CMP((div + 1) / 2); - } else if (clk == &s3c24xx_dclk1) { - mask = S3C2410_DCLKCON_DCLK1_DIV_MASK | - S3C2410_DCLKCON_DCLK1_CMP_MASK; - data = S3C2410_DCLKCON_DCLK1_DIV(div) | - S3C2410_DCLKCON_DCLK1_CMP((div + 1) / 2); - } else - return -EINVAL; - - clk->rate = clk_get_rate(clk->parent) / div; - __raw_writel(((__raw_readl(S3C24XX_DCLKCON) & ~mask) | data), - S3C24XX_DCLKCON); - return clk->rate; -} -static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) -{ - unsigned long mask; - unsigned long source; - - /* calculate the MISCCR setting for the clock */ - - if (parent == &clk_mpll) - source = S3C2410_MISCCR_CLK0_MPLL; - else if (parent == &clk_upll) - source = S3C2410_MISCCR_CLK0_UPLL; - else if (parent == &clk_f) - source = S3C2410_MISCCR_CLK0_FCLK; - else if (parent == &clk_h) - source = S3C2410_MISCCR_CLK0_HCLK; - else if (parent == &clk_p) - source = S3C2410_MISCCR_CLK0_PCLK; - else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0) - source = S3C2410_MISCCR_CLK0_DCLK0; - else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1) - source = S3C2410_MISCCR_CLK0_DCLK0; - else - return -EINVAL; - - clk->parent = parent; - - if (clk == &s3c24xx_clkout0) - mask = S3C2410_MISCCR_CLK0_MASK; - else { - source <<= 4; - mask = S3C2410_MISCCR_CLK1_MASK; - } - - s3c2410_modify_misccr(mask, source); - return 0; -} - -/* external clock definitions */ - -static struct clk_ops dclk_ops = { - .set_parent = s3c24xx_dclk_setparent, - .set_rate = s3c24xx_set_dclk_rate, - .round_rate = s3c24xx_round_dclk_rate, -}; - -struct clk s3c24xx_dclk0 = { - .name = "dclk0", - .ctrlbit = S3C2410_DCLKCON_DCLK0EN, - .enable = s3c24xx_dclk_enable, - .ops = &dclk_ops, -}; - -struct clk s3c24xx_dclk1 = { - .name = "dclk1", - .ctrlbit = S3C2410_DCLKCON_DCLK1EN, - .enable = s3c24xx_dclk_enable, - .ops = &dclk_ops, -}; - -static struct clk_ops clkout_ops = { - .set_parent = s3c24xx_clkout_setparent, -}; - -struct clk s3c24xx_clkout0 = { - .name = "clkout0", - .ops = &clkout_ops, -}; - -struct clk s3c24xx_clkout1 = { - .name = "clkout1", - .ops = &clkout_ops, -}; diff --git a/arch/arm/mach-s3c24xx/clock-s3c2410.c b/arch/arm/mach-s3c24xx/clock-s3c2410.c deleted file mode 100644 index d1afcf9252d1..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c2410.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2006 Simtec Electronics - * Ben Dooks - * - * S3C2410,S3C2440,S3C2442 Clock control support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include - -int s3c2410_clkcon_enable(struct clk *clk, int enable) -{ - unsigned int clocks = clk->ctrlbit; - unsigned long clkcon; - - clkcon = __raw_readl(S3C2410_CLKCON); - - if (enable) - clkcon |= clocks; - else - clkcon &= ~clocks; - - /* ensure none of the special function bits set */ - clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER); - - __raw_writel(clkcon, S3C2410_CLKCON); - - return 0; -} - -static int s3c2410_upll_enable(struct clk *clk, int enable) -{ - unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); - unsigned long orig = clkslow; - - if (enable) - clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF; - else - clkslow |= S3C2410_CLKSLOW_UCLK_OFF; - - __raw_writel(clkslow, S3C2410_CLKSLOW); - - /* if we started the UPLL, then allow to settle */ - - if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF)) - udelay(200); - - return 0; -} - -/* standard clock definitions */ - -static struct clk init_clocks_off[] = { - { - .name = "nand", - .parent = &clk_h, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_NAND, - }, { - .name = "sdi", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_SDI, - }, { - .name = "adc", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_ADC, - }, { - .name = "i2c", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_IIC, - }, { - .name = "iis", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_IIS, - }, { - .name = "spi", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_SPI, - } -}; - -static struct clk clk_lcd = { - .name = "lcd", - .parent = &clk_h, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_LCDC, -}; - -static struct clk clk_gpio = { - .name = "gpio", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_GPIO, -}; - -static struct clk clk_usb_host = { - .name = "usb-host", - .parent = &clk_h, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_USBH, -}; - -static struct clk clk_usb_device = { - .name = "usb-device", - .parent = &clk_h, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_USBD, -}; - -static struct clk clk_timers = { - .name = "timers", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_PWMT, -}; - -struct clk s3c24xx_clk_uart0 = { - .name = "uart", - .devname = "s3c2410-uart.0", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART0, -}; - -struct clk s3c24xx_clk_uart1 = { - .name = "uart", - .devname = "s3c2410-uart.1", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART1, -}; - -struct clk s3c24xx_clk_uart2 = { - .name = "uart", - .devname = "s3c2410-uart.2", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART2, -}; - -static struct clk clk_rtc = { - .name = "rtc", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_RTC, -}; - -static struct clk clk_watchdog = { - .name = "watchdog", - .parent = &clk_p, - .ctrlbit = 0, -}; - -static struct clk clk_usb_bus_host = { - .name = "usb-bus-host", - .parent = &clk_usb_bus, -}; - -static struct clk clk_usb_bus_gadget = { - .name = "usb-bus-gadget", - .parent = &clk_usb_bus, -}; - -static struct clk *init_clocks[] = { - &clk_lcd, - &clk_gpio, - &clk_usb_host, - &clk_usb_device, - &clk_timers, - &s3c24xx_clk_uart0, - &s3c24xx_clk_uart1, - &s3c24xx_clk_uart2, - &clk_rtc, - &clk_watchdog, - &clk_usb_bus_host, - &clk_usb_bus_gadget, -}; - -/* s3c2410_baseclk_add() - * - * Add all the clocks used by the s3c2410 or compatible CPUs - * such as the S3C2440 and S3C2442. - * - * We cannot use a system device as we are needed before any - * of the init-calls that initialise the devices are actually - * done. -*/ - -int __init s3c2410_baseclk_add(void) -{ - unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); - unsigned long clkcon = __raw_readl(S3C2410_CLKCON); - struct clk *xtal; - int ret; - int ptr; - - clk_upll.enable = s3c2410_upll_enable; - - if (s3c24xx_register_clock(&clk_usb_bus) < 0) - printk(KERN_ERR "failed to register usb bus clock\n"); - - /* register clocks from clock array */ - - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++) { - struct clk *clkp = init_clocks[ptr]; - - /* ensure that we note the clock state */ - - clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0; - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - } - - /* We must be careful disabling the clocks we are not intending to - * be using at boot time, as subsystems such as the LCD which do - * their own DMA requests to the bus can cause the system to lockup - * if they where in the middle of requesting bus access. - * - * Disabling the LCD clock if the LCD is active is very dangerous, - * and therefore the bootloader should be careful to not enable - * the LCD clock if it is not needed. - */ - - /* install (and disable) the clocks we do not need immediately */ - - s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - - /* show the clock-slow value */ - - xtal = clk_get(NULL, "xtal"); - - printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n", - print_mhz(clk_get_rate(xtal) / - ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))), - (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast", - (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", - (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); - - return 0; -} diff --git a/arch/arm/mach-s3c24xx/clock-s3c2440.c b/arch/arm/mach-s3c24xx/clock-s3c2440.c deleted file mode 100644 index 5527226fd61f..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c2440.c +++ /dev/null @@ -1,217 +0,0 @@ -/* linux/arch/arm/mach-s3c2440/clock.c - * - * Copyright (c) 2004-2005 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks - * - * S3C2440 Clock support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -/* S3C2440 extended clock support */ - -static unsigned long s3c2440_camif_upll_round(struct clk *clk, - unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - int div; - - if (rate > parent_rate) - return parent_rate; - - /* note, we remove the +/- 1 calculations for the divisor */ - - div = (parent_rate / rate) / 2; - - if (div < 1) - div = 1; - else if (div > 16) - div = 16; - - return parent_rate / (div * 2); -} - -static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); - - rate = s3c2440_camif_upll_round(clk, rate); - - camdivn &= ~(S3C2440_CAMDIVN_CAMCLK_SEL | S3C2440_CAMDIVN_CAMCLK_MASK); - - if (rate != parent_rate) { - camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL; - camdivn |= (((parent_rate / rate) / 2) - 1); - } - - __raw_writel(camdivn, S3C2440_CAMDIVN); - - return 0; -} - -static unsigned long s3c2440_camif_upll_getrate(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); - - if (!(camdivn & S3C2440_CAMDIVN_CAMCLK_SEL)) - return parent_rate; - - camdivn &= S3C2440_CAMDIVN_CAMCLK_MASK; - - return parent_rate / (camdivn + 1) / 2; -} - -/* Extra S3C2440 clocks */ - -static struct clk s3c2440_clk_cam = { - .name = "camif", - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2440_CLKCON_CAMERA, -}; - -static struct clk s3c2440_clk_cam_upll = { - .name = "camif-upll", - .ops = &(struct clk_ops) { - .set_rate = s3c2440_camif_upll_setrate, - .get_rate = s3c2440_camif_upll_getrate, - .round_rate = s3c2440_camif_upll_round, - }, -}; - -static struct clk s3c2440_clk_ac97 = { - .name = "ac97", - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2440_CLKCON_AC97, -}; - -#define S3C24XX_VA_UART0 (S3C_VA_UART) -#define S3C24XX_VA_UART1 (S3C_VA_UART + 0x4000 ) -#define S3C24XX_VA_UART2 (S3C_VA_UART + 0x8000 ) -#define S3C24XX_VA_UART3 (S3C_VA_UART + 0xC000 ) - -static unsigned long s3c2440_fclk_n_getrate(struct clk *clk) -{ - unsigned long ucon0, ucon1, ucon2, divisor; - - /* the fun of calculating the uart divisors on the s3c2440 */ - ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON); - ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON); - ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON); - - ucon0 &= S3C2440_UCON0_DIVMASK; - ucon1 &= S3C2440_UCON1_DIVMASK; - ucon2 &= S3C2440_UCON2_DIVMASK; - - if (ucon0 != 0) - divisor = (ucon0 >> S3C2440_UCON_DIVSHIFT) + 6; - else if (ucon1 != 0) - divisor = (ucon1 >> S3C2440_UCON_DIVSHIFT) + 21; - else if (ucon2 != 0) - divisor = (ucon2 >> S3C2440_UCON_DIVSHIFT) + 36; - else - /* manual calims 44, seems to be 9 */ - divisor = 9; - - return clk_get_rate(clk->parent) / divisor; -} - -static struct clk s3c2440_clk_fclk_n = { - .name = "fclk_n", - .parent = &clk_f, - .ops = &(struct clk_ops) { - .get_rate = s3c2440_fclk_n_getrate, - }, -}; - -static struct clk_lookup s3c2440_clk_lookup[] = { - CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), - CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p), - CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n), - CLKDEV_INIT("s3c2440-uart.0", "uart", &s3c24xx_clk_uart0), - CLKDEV_INIT("s3c2440-uart.1", "uart", &s3c24xx_clk_uart1), - CLKDEV_INIT("s3c2440-uart.2", "uart", &s3c24xx_clk_uart2), - CLKDEV_INIT("s3c2440-camif", "camera", &s3c2440_clk_cam_upll), -}; - -static int __init_refok s3c2440_clk_add(struct device *dev, struct subsys_interface *sif) -{ - struct clk *clock_upll; - struct clk *clock_h; - struct clk *clock_p; - - clock_p = clk_get(NULL, "pclk"); - clock_h = clk_get(NULL, "hclk"); - clock_upll = clk_get(NULL, "upll"); - - if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) { - printk(KERN_ERR "S3C2440: Failed to get parent clocks\n"); - return -EINVAL; - } - - s3c2440_clk_cam.parent = clock_h; - s3c2440_clk_ac97.parent = clock_p; - s3c2440_clk_cam_upll.parent = clock_upll; - s3c24xx_register_clock(&s3c2440_clk_fclk_n); - - s3c24xx_register_clock(&s3c2440_clk_ac97); - s3c24xx_register_clock(&s3c2440_clk_cam); - s3c24xx_register_clock(&s3c2440_clk_cam_upll); - clkdev_add_table(s3c2440_clk_lookup, ARRAY_SIZE(s3c2440_clk_lookup)); - - clk_disable(&s3c2440_clk_ac97); - clk_disable(&s3c2440_clk_cam); - - return 0; -} - -static struct subsys_interface s3c2440_clk_interface = { - .name = "s3c2440_clk", - .subsys = &s3c2440_subsys, - .add_dev = s3c2440_clk_add, -}; - -static __init int s3c24xx_clk_init(void) -{ - return subsys_interface_register(&s3c2440_clk_interface); -} - -arch_initcall(s3c24xx_clk_init); diff --git a/arch/arm/mach-s3c24xx/clock-s3c244x.c b/arch/arm/mach-s3c24xx/clock-s3c244x.c deleted file mode 100644 index 6d9b688c442b..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c244x.c +++ /dev/null @@ -1,141 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/s3c24xx-clock.c - * - * Copyright (c) 2004-2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks - * - * S3C2440/S3C2442 Common clock support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -static int s3c2440_setparent_armclk(struct clk *clk, struct clk *parent) -{ - unsigned long camdivn; - unsigned long dvs; - - if (parent == &clk_f) - dvs = 0; - else if (parent == &clk_h) - dvs = S3C2440_CAMDIVN_DVSEN; - else - return -EINVAL; - - clk->parent = parent; - - camdivn = __raw_readl(S3C2440_CAMDIVN); - camdivn &= ~S3C2440_CAMDIVN_DVSEN; - camdivn |= dvs; - __raw_writel(camdivn, S3C2440_CAMDIVN); - - return 0; -} - -static struct clk clk_arm = { - .name = "armclk", - .id = -1, - .ops = &(struct clk_ops) { - .set_parent = s3c2440_setparent_armclk, - }, -}; - -static int s3c244x_clk_add(struct device *dev, struct subsys_interface *sif) -{ - unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); - unsigned long clkdivn; - struct clk *clock_upll; - int ret; - - printk("S3C244X: Clock Support, DVS %s\n", - (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off"); - - clk_arm.parent = (camdivn & S3C2440_CAMDIVN_DVSEN) ? &clk_h : &clk_f; - - ret = s3c24xx_register_clock(&clk_arm); - if (ret < 0) { - printk(KERN_ERR "S3C24XX: Failed to add armclk (%d)\n", ret); - return ret; - } - - clock_upll = clk_get(NULL, "upll"); - if (IS_ERR(clock_upll)) { - printk(KERN_ERR "S3C244X: Failed to get upll clock\n"); - return -ENOENT; - } - - /* check rate of UPLL, and if it is near 96MHz, then change - * to using half the UPLL rate for the system */ - - if (clk_get_rate(clock_upll) > (94 * MHZ)) { - clk_usb_bus.rate = clk_get_rate(clock_upll) / 2; - - spin_lock(&clocks_lock); - - clkdivn = __raw_readl(S3C2410_CLKDIVN); - clkdivn |= S3C2440_CLKDIVN_UCLK; - __raw_writel(clkdivn, S3C2410_CLKDIVN); - - spin_unlock(&clocks_lock); - } - - return 0; -} - -static struct subsys_interface s3c2440_clk_interface = { - .name = "s3c2440_clk", - .subsys = &s3c2440_subsys, - .add_dev = s3c244x_clk_add, -}; - -static int s3c2440_clk_init(void) -{ - return subsys_interface_register(&s3c2440_clk_interface); -} - -arch_initcall(s3c2440_clk_init); - -static struct subsys_interface s3c2442_clk_interface = { - .name = "s3c2442_clk", - .subsys = &s3c2442_subsys, - .add_dev = s3c244x_clk_add, -}; - -static int s3c2442_clk_init(void) -{ - return subsys_interface_register(&s3c2442_clk_interface); -} - -arch_initcall(s3c2442_clk_init); diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index 2d6554140161..ac3ff12a0601 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h @@ -67,10 +67,8 @@ extern struct syscore_ops s3c2416_irq_syscore_ops; #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) extern void s3c244x_map_io(void); extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no); -extern void s3c244x_init_clocks(int xtal); extern void s3c244x_restart(enum reboot_mode mode, const char *cmd); #else -#define s3c244x_init_clocks NULL #define s3c244x_init_uarts NULL #endif diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-clock.h b/arch/arm/mach-s3c24xx/include/mach/regs-clock.h index 3415b60082d7..3db6c10de023 100644 --- a/arch/arm/mach-s3c24xx/include/mach/regs-clock.h +++ b/arch/arm/mach-s3c24xx/include/mach/regs-clock.h @@ -42,24 +42,6 @@ #define S3C2410_CLKCON_IIS (1<<17) #define S3C2410_CLKCON_SPI (1<<18) -/* DCLKCON register addresses in gpio.h */ - -#define S3C2410_DCLKCON_DCLK0EN (1<<0) -#define S3C2410_DCLKCON_DCLK0_PCLK (0<<1) -#define S3C2410_DCLKCON_DCLK0_UCLK (1<<1) -#define S3C2410_DCLKCON_DCLK0_DIV(x) (((x) - 1 )<<4) -#define S3C2410_DCLKCON_DCLK0_CMP(x) (((x) - 1 )<<8) -#define S3C2410_DCLKCON_DCLK0_DIV_MASK ((0xf)<<4) -#define S3C2410_DCLKCON_DCLK0_CMP_MASK ((0xf)<<8) - -#define S3C2410_DCLKCON_DCLK1EN (1<<16) -#define S3C2410_DCLKCON_DCLK1_PCLK (0<<17) -#define S3C2410_DCLKCON_DCLK1_UCLK (1<<17) -#define S3C2410_DCLKCON_DCLK1_DIV(x) (((x) - 1) <<20) -#define S3C2410_DCLKCON_DCLK1_CMP(x) (((x) - 1) <<24) -#define S3C2410_DCLKCON_DCLK1_DIV_MASK ((0xf) <<20) -#define S3C2410_DCLKCON_DCLK1_CMP_MASK ((0xf) <<24) - #define S3C2410_CLKDIVN_PDIVN (1<<0) #define S3C2410_CLKDIVN_HDIVN (1<<1) diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h index c2ef016032ab..c6583cfa5835 100644 --- a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h +++ b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h @@ -457,9 +457,6 @@ /* miscellaneous control */ #define S3C2410_MISCCR S3C2410_GPIOREG(0x80) -#define S3C2410_DCLKCON S3C2410_GPIOREG(0x84) - -#define S3C24XX_DCLKCON S3C24XX_GPIOREG2(0x84) /* see clock.h for dclk definitions */ diff --git a/arch/arm/mach-s3c24xx/pm.c b/arch/arm/mach-s3c24xx/pm.c index 16281bdc750a..3d8cf3054e7f 100644 --- a/arch/arm/mach-s3c24xx/pm.c +++ b/arch/arm/mach-s3c24xx/pm.c @@ -80,12 +80,6 @@ static struct sleep_save core_save[] = { #endif /* CONFIG_SAMSUNG_CLOCK */ }; -#ifdef CONFIG_SAMSUNG_CLOCK -static struct sleep_save misc_save[] = { - SAVE_ITEM(S3C2410_DCLKCON), -}; -#endif - /* s3c_pm_check_resume_pin * * check to see if the pin is configured correctly for sleep mode, and @@ -143,16 +137,10 @@ void s3c_pm_configure_extint(void) void s3c_pm_restore_core(void) { s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); -#ifdef CONFIG_SAMSUNG_CLOCK - s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save)); -#endif } void s3c_pm_save_core(void) { -#ifdef CONFIG_SAMSUNG_CLOCK - s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save)); -#endif s3c_pm_do_save(core_save, ARRAY_SIZE(core_save)); } diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c index 52801730ab24..7eab88829883 100644 --- a/arch/arm/mach-s3c24xx/s3c2410.c +++ b/arch/arm/mach-s3c24xx/s3c2410.c @@ -83,71 +83,9 @@ void __init s3c2410_map_io(void) iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); } -#ifdef CONFIG_SAMSUNG_CLOCK -void __init_or_cpufreq s3c2410_setup_clocks(void) -{ - struct clk *xtal_clk; - unsigned long tmp; - unsigned long xtal; - unsigned long fclk; - unsigned long hclk; - unsigned long pclk; - - xtal_clk = clk_get(NULL, "xtal"); - xtal = clk_get_rate(xtal_clk); - clk_put(xtal_clk); - - /* now we've got our machine bits initialised, work out what - * clocks we've got */ - - fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal); - - tmp = __raw_readl(S3C2410_CLKDIVN); - - /* work out clock scalings */ - - hclk = fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1); - pclk = hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1); - - /* print brieft summary of clocks, etc */ - - printk("S3C2410: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", - print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); - - /* initialise the clocks here, to allow other things like the - * console to use them - */ - - s3c24xx_setup_clocks(fclk, hclk, pclk); -} - -/* fake ARMCLK for use with cpufreq, etc. */ - -static struct clk s3c2410_armclk = { - .name = "armclk", - .parent = &clk_f, - .id = -1, -}; - -static struct clk_lookup s3c2410_clk_lookup[] = { - CLKDEV_INIT(NULL, "clk_uart_baud0", &clk_p), - CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), -}; - -void __init s3c2410_init_clocks(int xtal) -{ - s3c24xx_register_baseclocks(xtal); - s3c2410_setup_clocks(); - s3c2410_baseclk_add(); - s3c24xx_register_clock(&s3c2410_armclk); - clkdev_add_table(s3c2410_clk_lookup, ARRAY_SIZE(s3c2410_clk_lookup)); - samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); -} -#else void __init_or_cpufreq s3c2410_setup_clocks(void) { } -#endif struct bus_type s3c2410_subsys = { .name = "s3c2410-core", diff --git a/arch/arm/mach-s3c24xx/s3c2442.c b/arch/arm/mach-s3c24xx/s3c2442.c index 564c65037ff2..fb9da2b603a2 100644 --- a/arch/arm/mach-s3c24xx/s3c2442.c +++ b/arch/arm/mach-s3c24xx/s3c2442.c @@ -53,118 +53,6 @@ #include "common.h" -#ifdef CONFIG_SAMSUNG_CLOCK -/* S3C2442 extended clock support */ - -static unsigned long s3c2442_camif_upll_round(struct clk *clk, - unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - int div; - - if (rate > parent_rate) - return parent_rate; - - div = parent_rate / rate; - - if (div == 3) - return parent_rate / 3; - - /* note, we remove the +/- 1 calculations for the divisor */ - - div /= 2; - - if (div < 1) - div = 1; - else if (div > 16) - div = 16; - - return parent_rate / (div * 2); -} - -static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); - - rate = s3c2442_camif_upll_round(clk, rate); - - camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3; - - if (rate == parent_rate) { - camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL; - } else if ((parent_rate / rate) == 3) { - camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL; - camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3; - } else { - camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK; - camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL; - camdivn |= (((parent_rate / rate) / 2) - 1); - } - - __raw_writel(camdivn, S3C2440_CAMDIVN); - - return 0; -} - -/* Extra S3C2442 clocks */ - -static struct clk s3c2442_clk_cam = { - .name = "camif", - .id = -1, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2440_CLKCON_CAMERA, -}; - -static struct clk s3c2442_clk_cam_upll = { - .name = "camif-upll", - .id = -1, - .ops = &(struct clk_ops) { - .set_rate = s3c2442_camif_upll_setrate, - .round_rate = s3c2442_camif_upll_round, - }, -}; - -static int s3c2442_clk_add(struct device *dev, struct subsys_interface *sif) -{ - struct clk *clock_upll; - struct clk *clock_h; - struct clk *clock_p; - - clock_p = clk_get(NULL, "pclk"); - clock_h = clk_get(NULL, "hclk"); - clock_upll = clk_get(NULL, "upll"); - - if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) { - printk(KERN_ERR "S3C2442: Failed to get parent clocks\n"); - return -EINVAL; - } - - s3c2442_clk_cam.parent = clock_h; - s3c2442_clk_cam_upll.parent = clock_upll; - - s3c24xx_register_clock(&s3c2442_clk_cam); - s3c24xx_register_clock(&s3c2442_clk_cam_upll); - - clk_disable(&s3c2442_clk_cam); - - return 0; -} - -static struct subsys_interface s3c2442_clk_interface = { - .name = "s3c2442_clk", - .subsys = &s3c2442_subsys, - .add_dev = s3c2442_clk_add, -}; - -static __init int s3c2442_clk_init(void) -{ - return subsys_interface_register(&s3c2442_clk_interface); -} - -arch_initcall(s3c2442_clk_init); -#endif - static struct device s3c2442_dev = { .bus = &s3c2442_subsys, }; diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c index 1d665d50b034..4a64bcc9eb51 100644 --- a/arch/arm/mach-s3c24xx/s3c244x.c +++ b/arch/arm/mach-s3c24xx/s3c244x.c @@ -78,72 +78,9 @@ void __init s3c244x_map_io(void) s3c2410_device_dclk.name = "s3c2440-dclk"; } -#ifdef CONFIG_SAMSUNG_CLOCK -void __init_or_cpufreq s3c244x_setup_clocks(void) -{ - struct clk *xtal_clk; - unsigned long clkdiv; - unsigned long camdiv; - unsigned long xtal; - unsigned long hclk, fclk, pclk; - int hdiv = 1; - - xtal_clk = clk_get(NULL, "xtal"); - xtal = clk_get_rate(xtal_clk); - clk_put(xtal_clk); - - fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2; - - clkdiv = __raw_readl(S3C2410_CLKDIVN); - camdiv = __raw_readl(S3C2440_CAMDIVN); - - /* work out clock scalings */ - - switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) { - case S3C2440_CLKDIVN_HDIVN_1: - hdiv = 1; - break; - - case S3C2440_CLKDIVN_HDIVN_2: - hdiv = 2; - break; - - case S3C2440_CLKDIVN_HDIVN_4_8: - hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4; - break; - - case S3C2440_CLKDIVN_HDIVN_3_6: - hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3; - break; - } - - hclk = fclk / hdiv; - pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2 : 1); - - /* print brief summary of clocks, etc */ - - printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", - print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); - - s3c24xx_setup_clocks(fclk, hclk, pclk); -} - -void __init s3c244x_init_clocks(int xtal) -{ - /* initialise the clocks here, to allow other things like the - * console to use them, and to add new ones after the initialisation - */ - - s3c24xx_register_baseclocks(xtal); - s3c244x_setup_clocks(); - s3c2410_baseclk_add(); - samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); -} -#else void __init_or_cpufreq s3c244x_setup_clocks(void) { } -#endif /* Since the S3C2442 and S3C2440 share items, put both subsystems here */ From 2916f9a2c6d9200b4c840a613cd1fa1dad04240f Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:51:43 +0900 Subject: [PATCH 22/23] ARM: S3C24XX: remove SAMSUNG_CLOCK remnants after ccf conversion This finally removes all remaining SAMSUNG_CLOCK conditional code from s3c24xx architectures. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 3 --- arch/arm/mach-s3c24xx/common.c | 17 ----------------- arch/arm/mach-s3c24xx/cpufreq-utils.c | 6 ------ arch/arm/mach-s3c24xx/mach-anubis.c | 27 --------------------------- arch/arm/mach-s3c24xx/mach-bast.c | 27 --------------------------- arch/arm/mach-s3c24xx/mach-osiris.c | 27 --------------------------- arch/arm/mach-s3c24xx/mach-rx1950.c | 14 -------------- arch/arm/mach-s3c24xx/mach-vr1000.c | 27 --------------------------- arch/arm/mach-s3c24xx/pm.c | 12 ------------ 9 files changed, 160 deletions(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index f9bb1ea14fe4..1331e784c713 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -266,7 +266,6 @@ config ARCH_BAST select MACH_BAST_IDE select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2410_CPUFREQ - select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_NOR select S3C24XX_SIMTEC_PM if PM select S3C24XX_SIMTEC_USB @@ -534,7 +533,6 @@ config MACH_ANUBIS select HAVE_PATA_PLATFORM select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2440_XTAL_12000000 - select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_PM if PM select S3C_DEV_USB_HOST help @@ -575,7 +573,6 @@ config MACH_OSIRIS select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ select S3C2440_XTAL_12000000 - select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_PM if PM select S3C_DEV_NAND select S3C_DEV_USB_HOST diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 600a1be5696b..c0763b837745 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -307,23 +307,6 @@ struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = { }, }; -/* initialise all the clocks */ - -#ifdef CONFIG_SAMSUNG_CLOCK -void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk, - unsigned long hclk, - unsigned long pclk) -{ - clk_upll.rate = s3c24xx_get_pll(__raw_readl(S3C2410_UPLLCON), - clk_xtal.rate); - - clk_mpll.rate = fclk; - clk_h.rate = hclk; - clk_p.rate = pclk; - clk_f.rate = fclk; -} -#endif - #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \ defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) static struct resource s3c2410_dma_resource[] = { diff --git a/arch/arm/mach-s3c24xx/cpufreq-utils.c b/arch/arm/mach-s3c24xx/cpufreq-utils.c index c1b7508523ad..d4d9514335f4 100644 --- a/arch/arm/mach-s3c24xx/cpufreq-utils.c +++ b/arch/arm/mach-s3c24xx/cpufreq-utils.c @@ -61,12 +61,6 @@ void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg) */ void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg) { -#ifdef CONFIG_SAMSUNG_CLOCK - __raw_writel(cfg->pll.driver_data, S3C2410_MPLLCON); -#endif - -#ifdef CONFIG_COMMON_CLK if (!IS_ERR(cfg->mpll)) clk_set_rate(cfg->mpll, cfg->pll.frequency); -#endif } diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c index 7a0d83b2f93a..e053581cab0b 100644 --- a/arch/arm/mach-s3c24xx/mach-anubis.c +++ b/arch/arm/mach-s3c24xx/mach-anubis.c @@ -364,16 +364,6 @@ static struct platform_device *anubis_devices[] __initdata = { &anubis_device_sm501, }; -#ifdef CONFIG_SAMSUNG_CLOCK -static struct clk *anubis_clocks[] __initdata = { - &s3c24xx_dclk0, - &s3c24xx_dclk1, - &s3c24xx_clkout0, - &s3c24xx_clkout1, - &s3c24xx_uclk, -}; -#endif - /* I2C devices. */ static struct i2c_board_info anubis_i2c_devs[] __initdata = { @@ -396,23 +386,6 @@ static struct s3c24xx_audio_simtec_pdata __initdata anubis_audio = { static void __init anubis_map_io(void) { -#ifdef CONFIG_SAMSUNG_CLOCK - /* initialise the clocks */ - - s3c24xx_dclk0.parent = &clk_upll; - s3c24xx_dclk0.rate = 12*1000*1000; - - s3c24xx_dclk1.parent = &clk_upll; - s3c24xx_dclk1.rate = 24*1000*1000; - - s3c24xx_clkout0.parent = &s3c24xx_dclk0; - s3c24xx_clkout1.parent = &s3c24xx_dclk1; - - s3c24xx_uclk.parent = &s3c24xx_clkout1; - - s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks)); -#endif - s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc)); s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c index ea762f20099b..f9112b801a33 100644 --- a/arch/arm/mach-s3c24xx/mach-bast.c +++ b/arch/arm/mach-s3c24xx/mach-bast.c @@ -537,16 +537,6 @@ static struct platform_device *bast_devices[] __initdata = { &bast_sio, }; -#ifdef CONFIG_SAMSUNG_CLK -static struct clk *bast_clocks[] __initdata = { - &s3c24xx_dclk0, - &s3c24xx_dclk1, - &s3c24xx_clkout0, - &s3c24xx_clkout1, - &s3c24xx_uclk, -}; -#endif - static struct s3c_cpufreq_board __initdata bast_cpufreq = { .refresh = 7800, /* 7.8usec */ .auto_io = 1, @@ -560,23 +550,6 @@ static struct s3c24xx_audio_simtec_pdata __initdata bast_audio = { static void __init bast_map_io(void) { -#ifdef CONFIG_SAMSUNG_CLOCK - /* initialise the clocks */ - - s3c24xx_dclk0.parent = &clk_upll; - s3c24xx_dclk0.rate = 12*1000*1000; - - s3c24xx_dclk1.parent = &clk_upll; - s3c24xx_dclk1.rate = 24*1000*1000; - - s3c24xx_clkout0.parent = &s3c24xx_dclk0; - s3c24xx_clkout1.parent = &s3c24xx_dclk1; - - s3c24xx_uclk.parent = &s3c24xx_clkout1; - - s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks)); -#endif - s3c_hwmon_set_platdata(&bast_hwmon_info); s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c index 3bc2c9bad8b3..189147b80eca 100644 --- a/arch/arm/mach-s3c24xx/mach-osiris.c +++ b/arch/arm/mach-s3c24xx/mach-osiris.c @@ -350,16 +350,6 @@ static struct platform_device *osiris_devices[] __initdata = { &osiris_pcmcia, }; -#ifdef CONFIG_SAMSUNG_CLOCK -static struct clk *osiris_clocks[] __initdata = { - &s3c24xx_dclk0, - &s3c24xx_dclk1, - &s3c24xx_clkout0, - &s3c24xx_clkout1, - &s3c24xx_uclk, -}; -#endif - static struct s3c_cpufreq_board __initdata osiris_cpufreq = { .refresh = 7800, /* refresh period is 7.8usec */ .auto_io = 1, @@ -370,23 +360,6 @@ static void __init osiris_map_io(void) { unsigned long flags; -#ifdef CONFIG_SAMSUNG_CLOCK - /* initialise the clocks */ - - s3c24xx_dclk0.parent = &clk_upll; - s3c24xx_dclk0.rate = 12*1000*1000; - - s3c24xx_dclk1.parent = &clk_upll; - s3c24xx_dclk1.rate = 24*1000*1000; - - s3c24xx_clkout0.parent = &s3c24xx_dclk0; - s3c24xx_clkout1.parent = &s3c24xx_dclk1; - - s3c24xx_uclk.parent = &s3c24xx_clkout1; - - s3c24xx_register_clocks(osiris_clocks, ARRAY_SIZE(osiris_clocks)); -#endif - s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc)); s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c index 5f37f5262e65..e2c6541909c1 100644 --- a/arch/arm/mach-s3c24xx/mach-rx1950.c +++ b/arch/arm/mach-s3c24xx/mach-rx1950.c @@ -728,22 +728,8 @@ static struct platform_device *rx1950_devices[] __initdata = { &rx1950_leds, }; -#ifdef CONFIG_SAMSUNG_CLOCK -static struct clk *rx1950_clocks[] __initdata = { - &s3c24xx_clkout0, - &s3c24xx_clkout1, -}; -#endif - static void __init rx1950_map_io(void) { -#ifdef CONFIG_SAMSUNG_CLOCK - s3c24xx_clkout0.parent = &clk_h; - s3c24xx_clkout1.parent = &clk_f; - - s3c24xx_register_clocks(rx1950_clocks, ARRAY_SIZE(rx1950_clocks)); -#endif - s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc)); s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c index 5f588bf20f43..f88c584c3001 100644 --- a/arch/arm/mach-s3c24xx/mach-vr1000.c +++ b/arch/arm/mach-s3c24xx/mach-vr1000.c @@ -299,16 +299,6 @@ static struct platform_device *vr1000_devices[] __initdata = { &vr1000_led3, }; -#ifdef CONFIG_SAMSUNG_CLOCK -static struct clk *vr1000_clocks[] __initdata = { - &s3c24xx_dclk0, - &s3c24xx_dclk1, - &s3c24xx_clkout0, - &s3c24xx_clkout1, - &s3c24xx_uclk, -}; -#endif - static void vr1000_power_off(void) { gpio_direction_output(S3C2410_GPB(9), 1); @@ -316,23 +306,6 @@ static void vr1000_power_off(void) static void __init vr1000_map_io(void) { -#if CONFIG_SAMSUNG_CLOCK - /* initialise clock sources */ - - s3c24xx_dclk0.parent = &clk_upll; - s3c24xx_dclk0.rate = 12*1000*1000; - - s3c24xx_dclk1.parent = NULL; - s3c24xx_dclk1.rate = 3692307; - - s3c24xx_clkout0.parent = &s3c24xx_dclk0; - s3c24xx_clkout1.parent = &s3c24xx_dclk1; - - s3c24xx_uclk.parent = &s3c24xx_clkout1; - - s3c24xx_register_clocks(vr1000_clocks, ARRAY_SIZE(vr1000_clocks)); -#endif - pm_power_off = vr1000_power_off; s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc)); diff --git a/arch/arm/mach-s3c24xx/pm.c b/arch/arm/mach-s3c24xx/pm.c index 3d8cf3054e7f..b19256ec8d40 100644 --- a/arch/arm/mach-s3c24xx/pm.c +++ b/arch/arm/mach-s3c24xx/pm.c @@ -66,18 +66,6 @@ static struct sleep_save core_save[] = { SAVE_ITEM(S3C2410_BANKCON3), SAVE_ITEM(S3C2410_BANKCON4), SAVE_ITEM(S3C2410_BANKCON5), - -#ifdef CONFIG_SAMSUNG_CLOCK - SAVE_ITEM(S3C2410_LOCKTIME), - SAVE_ITEM(S3C2410_CLKCON), -#ifndef CONFIG_CPU_FREQ - SAVE_ITEM(S3C2410_CLKDIVN), - SAVE_ITEM(S3C2410_MPLLCON), - SAVE_ITEM(S3C2410_REFRESH), -#endif - SAVE_ITEM(S3C2410_UPLLCON), - SAVE_ITEM(S3C2410_CLKSLOW), -#endif /* CONFIG_SAMSUNG_CLOCK */ }; /* s3c_pm_check_resume_pin From 34c453ce16633539a94a2e876faeb731ac1be899 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Fri, 9 May 2014 05:51:43 +0900 Subject: [PATCH 23/23] ARM: S3C24XX: fix merge conflict Missed some changes during re-sorting this branch. So fixed it. Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 1331e784c713..22d149bcfcc6 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -347,7 +347,6 @@ config MACH_VR1000 bool "Thorcom VR1000" select MACH_BAST_IDE select S3C2410_COMMON_DCLK if COMMON_CLK - select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_NOR select S3C24XX_SIMTEC_PM if PM select S3C24XX_SIMTEC_USB @@ -644,7 +643,6 @@ config MACH_RX1950 select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ select S3C2440_XTAL_16934400 - select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_PWM select S3C_DEV_NAND help