summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-samsung/clocks-s3c64xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-samsung/clocks-s3c64xx.c')
-rw-r--r--arch/arm/mach-samsung/clocks-s3c64xx.c338
1 files changed, 0 insertions, 338 deletions
diff --git a/arch/arm/mach-samsung/clocks-s3c64xx.c b/arch/arm/mach-samsung/clocks-s3c64xx.c
deleted file mode 100644
index 2229ed0529..0000000000
--- a/arch/arm/mach-samsung/clocks-s3c64xx.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (C) 2012 Juergen Beisert
- *
- * 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 <config.h>
-#include <common.h>
-#include <init.h>
-#include <clock.h>
-#include <io.h>
-#include <linux/math64.h>
-#include <mach/s3c-iomap.h>
-#include <mach/s3c-generic.h>
-#include <mach/s3c-clocks.h>
-
-/*
- * The main clock tree:
- *
- * ref_in
- * |
- * v
- * o-----------\
- * | MUX -o------------\
- * | / ^ | MUX --- DIV_APLL ------- ARMCLK -> CPU core
- * o--- APLL -- | | / |
- * | | o--/2 ------- |
- * | APLL_SEL | |<-MISC_CON_SYN667
- * | \ |
- * o-----------\ MUX-o-------\ |
- * | MUX--/ ^ | MUX --- DIV -o--------- HCLKx2 -> SDRAM (max. 266 MHz)
- * | / ^ | | / |
- * o---- MPLL-- | | o--/5 -- o-- DIV -- HCLK -> AXI / AHB (max. 133 MHz)
- * | | | |
- * | MPLL_SEL OTHERS_CLK_SELECT o-- DIV -- PCLK -> APB (max. 66 MHz)
- * |
- * o-----------\
- * | MUX---- to various hardware
- * | / ^
- * o---- EPLL-- EPLL_SEL
- *
- */
-
-static unsigned s3c_get_apllclk(void)
-{
- uint32_t m, p, s, reg_val;
-
- if (!(readl(S3C_CLK_SRC) & S3C_CLK_SRC_FOUTAPLL))
- return S3C64XX_CLOCK_REFERENCE;
-
- reg_val = readl(S3C_APLLCON);
- if (!(reg_val & S3C_APLLCON_ENABLE))
- return 0;
- m = S3C_APLLCON_GET_MDIV(reg_val);
- p = S3C_APLLCON_GET_PDIV(reg_val);
- s = S3C_APLLCON_GET_SDIV(reg_val);
-
- return (S3C64XX_CLOCK_REFERENCE * m) / (p << s);
-}
-
-uint32_t s3c_get_mpllclk(void)
-{
- uint32_t m, p, s, reg_val;
-
- if (!(readl(S3C_CLK_SRC) & S3C_CLK_SRC_FOUTMPLL))
- return S3C64XX_CLOCK_REFERENCE;
-
- reg_val = readl(S3C_MPLLCON);
- if (!(reg_val & S3C_MPLLCON_ENABLE))
- return 0;
-
- m = S3C_MPLLCON_GET_MDIV(reg_val);
- p = S3C_MPLLCON_GET_PDIV(reg_val);
- s = S3C_MPLLCON_GET_SDIV(reg_val);
-
- return (S3C64XX_CLOCK_REFERENCE * m) / (p << s);
-}
-
-unsigned s3c_get_epllclk(void)
-{
- u32 m, p, s, k, reg0_val, reg1_val;
- u64 tmp;
-
- if (!(readl(S3C_CLK_SRC) & S3C_CLK_SRC_FOUTEPLL))
- return S3C64XX_CLOCK_REFERENCE;
-
- reg0_val = readl(S3C_EPLLCON0);
- if (!(reg0_val & S3C_EPLLCON0_ENABLE))
- return 0; /* PLL is disabled */
-
- reg1_val = readl(S3C_EPLLCON1);
- m = S3C_EPLLCON0_GET_MDIV(reg0_val);
- p = S3C_EPLLCON0_GET_PDIV(reg0_val);
- s = S3C_EPLLCON0_GET_SDIV(reg0_val);
- k = S3C_EPLLCON1_GET_KDIV(reg1_val);
-
- tmp = S3C64XX_CLOCK_REFERENCE;
- tmp *= (m << 16) + k;
- do_div(tmp, (p << s));
-
- return (unsigned)(tmp >> 16);
-}
-
-unsigned s3c_set_epllclk(unsigned m, unsigned p, unsigned s, unsigned k)
-{
- u32 con0, con1, src = readl(S3C_CLK_SRC) & ~S3C_CLK_SRC_FOUTEPLL;
-
- /* do not use the EPLL clock when it is in transit to the new frequency */
- writel(src, S3C_CLK_SRC);
-
- con0 = S3C_EPLLCON0_SET_MDIV(m) | S3C_EPLLCON0_SET_PDIV(p) |
- S3C_EPLLCON0_SET_SDIV(s) | S3C_EPLLCON0_ENABLE;
- con1 = S3C_EPLLCON1_SET_KDIV(k);
-
- /*
- * After changing the multiplication value 'm' the PLL output will
- * be masked for the time set in the EPLL_LOCK register until it
- * settles to the new frequency. EPLL_LOCK contains a value for a
- * simple counter which counts the external reference clock.
- */
- writel(con0, S3C_EPLLCON0);
- writel(con1, S3C_EPLLCON1);
-
- udelay((1000000000 / S3C64XX_CLOCK_REFERENCE)
- * (S3C_EPLL_LOCK_PLL_LOCKTIME(readl(S3C_EPLL_LOCK)) + 1) / 1000);
-
- /* enable the EPLL's clock output to the system */
- writel(src | S3C_CLK_SRC_FOUTEPLL, S3C_CLK_SRC);
-
- return s3c_get_epllclk();
-}
-
-uint32_t s3c_get_fclk(void)
-{
- unsigned clk;
-
- clk = s3c_get_apllclk();
- if (readl(S3C_MISC_CON) & S3C_MISC_CON_SYN667)
- clk /= 2;
-
- return clk / (S3C_CLK_DIV0_GET_ADIV(readl(S3C_CLK_DIV0)) + 1);
-}
-
-static unsigned s3c_get_hclk_in(void)
-{
- unsigned clk;
-
- if (readl(S3C_OTHERS) & S3C_OTHERS_CLK_SELECT)
- clk = s3c_get_apllclk();
- else
- clk = s3c_get_mpllclk();
-
- if (readl(S3C_MISC_CON) & S3C_MISC_CON_SYN667)
- clk /= 5;
-
- return clk;
-}
-
-static unsigned s3c_get_hclkx2(void)
-{
- return s3c_get_hclk_in() /
- (S3C_CLK_DIV0_GET_HCLK2(readl(S3C_CLK_DIV0)) + 1);
-}
-
-uint32_t s3c_get_hclk(void)
-{
- return s3c_get_hclkx2() /
- (S3C_CLK_DIV0_GET_HCLK(readl(S3C_CLK_DIV0)) + 1);
-}
-
-uint32_t s3c_get_pclk(void)
-{
- return s3c_get_hclkx2() /
- (S3C_CLK_DIV0_GET_PCLK(readl(S3C_CLK_DIV0)) + 1);
-}
-
-static void s3c_init_mpll_dout(void)
-{
- unsigned reg;
-
- /* keep it at the same frequency as HCLKx2 */
- reg = readl(S3C_CLK_DIV0) | S3C_CLK_DIV0_SET_MPLL_DIV(1); /* e.g. / 2 */
- writel(reg, S3C_CLK_DIV0);
-}
-
-/* configure and enable UCLK1 */
-static int s3c_init_uart_clock(void)
-{
- unsigned reg;
-
- s3c_init_mpll_dout(); /* to have a reliable clock source */
-
- /* source the UART clock from the MPLL, currently *not* from EPLL */
- reg = readl(S3C_CLK_SRC) | S3C_CLK_SRC_UARTMPLL;
- writel(reg, S3C_CLK_SRC);
-
- /* keep UART clock at the same frequency than the PCLK */
- reg = readl(S3C_CLK_DIV2) & ~S3C_CLK_DIV2_UART_MASK;
- reg |= S3C_CLK_DIV2_SET_UART(0x3); /* / 4 */
- writel(reg, S3C_CLK_DIV2);
-
- /* ensure this very special clock is running */
- reg = readl(S3C_SCLK_GATE) | S3C_SCLK_GATE_UART;
- writel(reg, S3C_SCLK_GATE);
-
- return 0;
-}
-core_initcall(s3c_init_uart_clock);
-
-/* UART source selection
- * The UART related clock path: |
- * v
- * PCLK --------------------------------------o-----0-\
- * ???? -------------------------------UCLK0--|-----1--\MUX----- UART
- * MPLL -----DIV0------\ +-----2--/
- * MUX---DIV2------UCLK1--------3-/
- * EPLL ---------------/
- * ^SRC_UARTMPLL
- */
-unsigned s3c_get_uart_clk(unsigned source)
-{
- u32 reg;
- unsigned clk, pdiv, uartpdiv;
-
- switch (source) {
- default: /* PCLK */
- clk = s3c_get_pclk();
- pdiv = uartpdiv = 1;
- break;
- case 1: /* UCLK0 */
- clk = 0;
- pdiv = uartpdiv = 1; /* TODO */
- break;
- case 3: /* UCLK1 */
- reg = readl(S3C_CLK_SRC);
- if (reg & S3C_CLK_SRC_UARTMPLL) {
- clk = s3c_get_mpllclk();
- pdiv = S3C_CLK_DIV0_GET_MPLL_DIV(readl(S3C_CLK_DIV0)) + 1;
- } else {
- clk = s3c_get_epllclk();
- pdiv = 1;
- }
- uartpdiv = S3C_CLK_DIV2_GET_UART(readl(S3C_CLK_DIV2)) + 1;
- break;
- }
-
- return clk / pdiv / uartpdiv;
-}
-
-/*
- * The MMC related clock path:
- *
- * MMCx_SEL
- * |
- * v
- * EPLLout --------0-\
- * MPLLout --DIV0--1--\-------SCLK_MMCx----DIV_MMCx------>HSMMCx
- * EPLLin --------2--/ on/off / 1..16
- * 27 MHz --------3-/
- *
- * The datasheet is not very precise here, so the schematic shown above was
- * made by checking various bits in the SYSCON.
- */
-unsigned s3c_get_hsmmc_clk(int id)
-{
- u32 sel, div, sclk = readl(S3C_SCLK_GATE);
- unsigned bclk;
-
- if (!(sclk & S3C_SCLK_GATE_MMC(id)))
- return 0; /* disabled */
-
- sel = S3C_CLK_SRC_GET_MMC_SEL(id, readl(S3C_CLK_SRC));
- switch (sel) {
- case 0:
- bclk = s3c_get_epllclk();
- break;
- case 1:
- bclk = s3c_get_mpllclk();
- bclk >>= S3C_CLK_DIV0_GET_MPLL_DIV(readl(S3C_CLK_DIV0));
- break;
- case 2:
- bclk = S3C64XX_CLOCK_REFERENCE;
- break;
- case 3:
- bclk = 27000000;
- break;
- }
-
- div = S3C_CLK_DIV0_GET_MMC(id, readl(S3C_CLK_DIV0)) + 1;
-
- return bclk / div;
-}
-
-void s3c_set_hsmmc_clk(int id, int src, unsigned div)
-{
- u32 reg;
-
- if (!div)
- div = 1;
-
- writel(readl(S3C_SCLK_GATE) & ~S3C_SCLK_GATE_MMC(id), S3C_SCLK_GATE);
-
- /* select the new clock source */
- reg = readl(S3C_CLK_SRC) & ~S3C_CLK_SRC_SET_MMC_SEL(id, ~0);
- reg |= S3C_CLK_SRC_SET_MMC_SEL(id, src);
- writel(reg, S3C_CLK_SRC);
-
- /* select the new pre-divider */
- reg = readl(S3C_CLK_DIV0) & ~ S3C_CLK_DIV0_SET_MMC(id, ~0);
- reg |= S3C_CLK_DIV0_SET_MMC(id, div - 1);
- writel(reg, S3C_CLK_DIV0);
-
- /* calling this function implies enabling of the clock */
- writel(readl(S3C_SCLK_GATE) | S3C_SCLK_GATE_MMC(id), S3C_SCLK_GATE);
-}
-
-static int s3c64xx_dump_clocks(void)
-{
- printf("refclk: %7d kHz\n", S3C64XX_CLOCK_REFERENCE / 1000);
- printf("apll: %7d kHz\n", s3c_get_apllclk() / 1000);
- printf("mpll: %7d kHz\n", s3c_get_mpllclk() / 1000);
- printf("epll: %7d kHz\n", s3c_get_epllclk() / 1000);
- printf("CPU: %7d kHz\n", s3c_get_fclk() / 1000);
- printf("hclkx2: %7d kHz\n", s3c_get_hclkx2() / 1000);
- printf("hclk: %7d kHz\n", s3c_get_hclk() / 1000);
- printf("pclk: %7d kHz\n", s3c_get_pclk() / 1000);
- return 0;
-}
-
-late_initcall(s3c64xx_dump_clocks);