summaryrefslogtreecommitdiffstats
path: root/drivers/clk/mmp/clk-pxa910.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 12:09:04 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 12:09:04 -0700
commit2c0c86d5b67ee04e8b71a2ea2a3af6d224611cfc (patch)
tree84cb3b96e68be80b3e8b6876b27fc9ff6ba0370f /drivers/clk/mmp/clk-pxa910.c
parentfdb2f9c2ebd4f07d7b11a3bc86d8c669eb841697 (diff)
parent494bfec99922d54054d2d0873f1017680cfc3f13 (diff)
Merge tag 'clk-for-linus' of git://git.linaro.org/people/mturquette/linux
Pull clk framework update from Michael Turquette: "The common clk framework changes for 3.7 are dominated by ARM platform ports to the framework along with one MIPS port, one MFD port, one minor framework enhancement and one helper function for platforms expressing their clock data through device tree." * tag 'clk-for-linus' of git://git.linaro.org/people/mturquette/linux: clk: add of_clk_src_onecell_get() support clk: ux500: Define smp_twd clock for u8500 mfd: dbx500: Provide a more accurate smp_twd clock clk: ux500: Support for prmcu_rate clock clk: Provide option for clk_get_rate to issue hw for new rate clock: max77686: Add driver for Maxim 77686 32Khz crystal oscillator. ARM: ux500: Switch to use common clock framework clk: ux500: Clock definitions for u8500 clk: ux500: First version of clock definitions for ux500 clk: ux500: Adapt PRCMU and PRCC clocks for common clk clk: versatile: make config option boolean clk: add Loongson1B clock support arm: mmp: make all SOCs use common clock by default clk: mmp: add clock definition for mmp2 clk: mmp: add clock definition for pxa910 clk: mmp: add clock definition for pxa168 clk: mmp: add mmp specific clocks clk: convert ARM RealView to common clk clk: prima2: move from arch/arm/mach to drivers/clk ARM: PRIMA2: convert to common clk and finish full clk tree
Diffstat (limited to 'drivers/clk/mmp/clk-pxa910.c')
-rw-r--r--drivers/clk/mmp/clk-pxa910.c320
1 files changed, 320 insertions, 0 deletions
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
new file mode 100644
index 00000000000..7048c31d6e7
--- /dev/null
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -0,0 +1,320 @@
+/*
+ * pxa910 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/addr-map.h>
+
+#include "clk.h"
+
+#define APBC_RTC 0x28
+#define APBC_TWSI0 0x2c
+#define APBC_KPC 0x18
+#define APBC_UART0 0x0
+#define APBC_UART1 0x4
+#define APBC_GPIO 0x8
+#define APBC_PWM0 0xc
+#define APBC_PWM1 0x10
+#define APBC_PWM2 0x14
+#define APBC_PWM3 0x18
+#define APBC_SSP0 0x1c
+#define APBC_SSP1 0x20
+#define APBC_SSP2 0x4c
+#define APBCP_TWSI1 0x28
+#define APBCP_UART2 0x1c
+#define APMU_SDH0 0x54
+#define APMU_SDH1 0x58
+#define APMU_USB 0x5c
+#define APMU_DISP0 0x4c
+#define APMU_CCIC0 0x50
+#define APMU_DFC 0x60
+#define MPMU_UART_PLL 0x14
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static struct clk_factor_masks uart_factor_masks = {
+ .factor = 2,
+ .num_mask = 0x1fff,
+ .den_mask = 0x1fff,
+ .num_shift = 16,
+ .den_shift = 0,
+};
+
+static struct clk_factor_tbl uart_factor_tbl[] = {
+ {.num = 8125, .den = 1536}, /*14.745MHZ */
+};
+
+static const char *uart_parent[] = {"pll1_3_16", "uart_pll"};
+static const char *ssp_parent[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
+static const char *sdh_parent[] = {"pll1_12", "pll1_13"};
+static const char *disp_parent[] = {"pll1_2", "pll1_12"};
+static const char *ccic_parent[] = {"pll1_2", "pll1_12"};
+static const char *ccic_phy_parent[] = {"pll1_6", "pll1_12"};
+
+void __init pxa910_clk_init(void)
+{
+ struct clk *clk;
+ struct clk *uart_pll;
+ void __iomem *mpmu_base;
+ void __iomem *apmu_base;
+ void __iomem *apbcp_base;
+ void __iomem *apbc_base;
+
+ mpmu_base = ioremap(APB_PHYS_BASE + 0x50000, SZ_4K);
+ if (mpmu_base == NULL) {
+ pr_err("error to ioremap MPMU base\n");
+ return;
+ }
+
+ apmu_base = ioremap(AXI_PHYS_BASE + 0x82800, SZ_4K);
+ if (apmu_base == NULL) {
+ pr_err("error to ioremap APMU base\n");
+ return;
+ }
+
+ apbcp_base = ioremap(APB_PHYS_BASE + 0x3b000, SZ_4K);
+ if (apbcp_base == NULL) {
+ pr_err("error to ioremap APBC extension base\n");
+ return;
+ }
+
+ apbc_base = ioremap(APB_PHYS_BASE + 0x15000, SZ_4K);
+ if (apbc_base == NULL) {
+ pr_err("error to ioremap APBC base\n");
+ return;
+ }
+
+ clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200);
+ clk_register_clkdev(clk, "clk32", NULL);
+
+ clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT,
+ 26000000);
+ clk_register_clkdev(clk, "vctcxo", NULL);
+
+ clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT,
+ 624000000);
+ clk_register_clkdev(clk, "pll1", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_2", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_4", "pll1_2",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_4", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_8", "pll1_4",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_8", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_16", "pll1_8",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_16", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_6", "pll1_2",
+ CLK_SET_RATE_PARENT, 1, 3);
+ clk_register_clkdev(clk, "pll1_6", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_12", "pll1_6",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_12", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_24", "pll1_12",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_24", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_48", "pll1_24",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_48", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_96", "pll1_48",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_96", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_13", "pll1",
+ CLK_SET_RATE_PARENT, 1, 13);
+ clk_register_clkdev(clk, "pll1_13", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_13_1_5", "pll1",
+ CLK_SET_RATE_PARENT, 2, 3);
+ clk_register_clkdev(clk, "pll1_13_1_5", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_2_1_5", "pll1",
+ CLK_SET_RATE_PARENT, 2, 3);
+ clk_register_clkdev(clk, "pll1_2_1_5", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_3_16", "pll1",
+ CLK_SET_RATE_PARENT, 3, 16);
+ clk_register_clkdev(clk, "pll1_3_16", NULL);
+
+ uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
+ mpmu_base + MPMU_UART_PLL,
+ &uart_factor_masks, uart_factor_tbl,
+ ARRAY_SIZE(uart_factor_tbl));
+ clk_set_rate(uart_pll, 14745600);
+ clk_register_clkdev(uart_pll, "uart_pll", NULL);
+
+ clk = mmp_clk_register_apbc("twsi0", "pll1_13_1_5",
+ apbc_base + APBC_TWSI0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.0");
+
+ clk = mmp_clk_register_apbc("twsi1", "pll1_13_1_5",
+ apbcp_base + APBCP_TWSI1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.1");
+
+ clk = mmp_clk_register_apbc("gpio", "vctcxo",
+ apbc_base + APBC_GPIO, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa-gpio");
+
+ clk = mmp_clk_register_apbc("kpc", "clk32",
+ apbc_base + APBC_KPC, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa27x-keypad");
+
+ clk = mmp_clk_register_apbc("rtc", "clk32",
+ apbc_base + APBC_RTC, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sa1100-rtc");
+
+ clk = mmp_clk_register_apbc("pwm0", "pll1_48",
+ apbc_base + APBC_PWM0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa910-pwm.0");
+
+ clk = mmp_clk_register_apbc("pwm1", "pll1_48",
+ apbc_base + APBC_PWM1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa910-pwm.1");
+
+ clk = mmp_clk_register_apbc("pwm2", "pll1_48",
+ apbc_base + APBC_PWM2, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa910-pwm.2");
+
+ clk = mmp_clk_register_apbc("pwm3", "pll1_48",
+ apbc_base + APBC_PWM3, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa910-pwm.3");
+
+ clk = clk_register_mux(NULL, "uart0_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_UART0, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, uart_pll);
+ clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+ clk = mmp_clk_register_apbc("uart0", "uart0_mux",
+ apbc_base + APBC_UART0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.0");
+
+ clk = clk_register_mux(NULL, "uart1_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_UART1, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, uart_pll);
+ clk_register_clkdev(clk, "uart_mux.1", NULL);
+
+ clk = mmp_clk_register_apbc("uart1", "uart1_mux",
+ apbc_base + APBC_UART1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.1");
+
+ clk = clk_register_mux(NULL, "uart2_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbcp_base + APBCP_UART2, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, uart_pll);
+ clk_register_clkdev(clk, "uart_mux.2", NULL);
+
+ clk = mmp_clk_register_apbc("uart2", "uart2_mux",
+ apbcp_base + APBCP_UART2, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.2");
+
+ clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+ clk = mmp_clk_register_apbc("ssp0", "ssp0_mux",
+ apbc_base + APBC_SSP0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.0");
+
+ clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "ssp_mux.1", NULL);
+
+ clk = mmp_clk_register_apbc("ssp1", "ssp1_mux",
+ apbc_base + APBC_SSP1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.1");
+
+ clk = mmp_clk_register_apmu("dfc", "pll1_4",
+ apmu_base + APMU_DFC, 0x19b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa3xx-nand.0");
+
+ clk = clk_register_mux(NULL, "sdh0_mux", sdh_parent,
+ ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_SDH0, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "sdh0_mux", NULL);
+
+ clk = mmp_clk_register_apmu("sdh0", "sdh_mux",
+ apmu_base + APMU_SDH0, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sdhci-pxa.0");
+
+ clk = clk_register_mux(NULL, "sdh1_mux", sdh_parent,
+ ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_SDH1, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "sdh1_mux", NULL);
+
+ clk = mmp_clk_register_apmu("sdh1", "sdh1_mux",
+ apmu_base + APMU_SDH1, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sdhci-pxa.1");
+
+ clk = mmp_clk_register_apmu("usb", "usb_pll",
+ apmu_base + APMU_USB, 0x9, &clk_lock);
+ clk_register_clkdev(clk, "usb_clk", NULL);
+
+ clk = mmp_clk_register_apmu("sph", "usb_pll",
+ apmu_base + APMU_USB, 0x12, &clk_lock);
+ clk_register_clkdev(clk, "sph_clk", NULL);
+
+ clk = clk_register_mux(NULL, "disp0_mux", disp_parent,
+ ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_DISP0, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "disp_mux.0", NULL);
+
+ clk = mmp_clk_register_apmu("disp0", "disp0_mux",
+ apmu_base + APMU_DISP0, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-disp.0");
+
+ clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent,
+ ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_CCIC0, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "ccic_mux.0", NULL);
+
+ clk = mmp_clk_register_apmu("ccic0", "ccic0_mux",
+ apmu_base + APMU_CCIC0, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, "fnclk", "mmp-ccic.0");
+
+ clk = clk_register_mux(NULL, "ccic0_phy_mux", ccic_phy_parent,
+ ARRAY_SIZE(ccic_phy_parent),
+ CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+ 7, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "ccic_phy_mux.0", NULL);
+
+ clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_phy_mux",
+ apmu_base + APMU_CCIC0, 0x24, &clk_lock);
+ clk_register_clkdev(clk, "phyclk", "mmp-ccic.0");
+
+ clk = clk_register_divider(NULL, "ccic0_sphy_div", "ccic0_mux",
+ CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+ 10, 5, 0, &clk_lock);
+ clk_register_clkdev(clk, "sphyclk_div", NULL);
+
+ clk = mmp_clk_register_apmu("ccic0_sphy", "ccic0_sphy_div",
+ apmu_base + APMU_CCIC0, 0x300, &clk_lock);
+ clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0");
+}