diff options
author | Paul Walmsley <paul@pwsan.com> | 2010-02-23 08:09:20 +0300 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2010-02-24 22:16:15 +0300 |
commit | 657ebfadc19c5a14f709dee1645082828330d5d4 (patch) | |
tree | 26d615ae6e76437e0852b8d7fc060a070786f369 /arch/arm | |
parent | b92c170d019db7554db95380d2e1dfb3a368e350 (diff) | |
download | linux-657ebfadc19c5a14f709dee1645082828330d5d4.tar.xz |
OMAP3/4 clock: split into per-chip family files
clock34xx_data.c now contains data for the OMAP34xx family, the
OMAP36xx family, and the OMAP3517 family, so rename it to
clock3xxx_data.c. Rename clock34xx.c to clock3xxx.c, and move the
chip family-specific clock functions to clock34xx.c, clock36xx.c, or
clock3517.c, as appropriate. So now "clock3xxx.*" refers to the OMAP3
superset.
The main goal here is to prepare to compile chip family-specific clock
functions only for kernel builds that target that chip family. To get to
that point, we also need to add CONFIG_SOC_* options for those other
chip families; that will be done in future patches, planned for 2.6.35.
OMAP4 is also affected by this. It duplicated the OMAP3 non-CORE DPLL
clkops structure. The OMAP4 variant of this clkops structure has been
removed, and since there was nothing else currently in clock44xx.c, it
too has been removed -- it can always be added back later when there
is some content for it. (The OMAP4 clock autogeneration scripts have been
updated accordingly.)
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Benoît Cousson <b-cousson@ti.com>
Cc: Rajendra Nayak <rnayak@ti.com>
Cc: Ranjith Lohithakshan <ranjithl@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 36 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clkt34xx_dpll3m2.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 12 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock34xx.c | 260 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock34xx.h | 27 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock3517.c | 124 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock3517.h | 14 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock36xx.c | 72 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock36xx.h | 13 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock3xxx.c | 145 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock3xxx.h | 21 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock3xxx_data.c (renamed from arch/arm/mach-omap2/clock34xx_data.c) | 16 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock44xx.c | 19 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock44xx.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock44xx_data.c | 12 | ||||
-rw-r--r-- | arch/arm/mach-omap2/io.c | 2 |
17 files changed, 450 insertions, 332 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 3ebd0b6525df..5f10d32f1184 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -7,22 +7,14 @@ obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o omap-2-3-common = irq.o sdrc.o omap_hwmod.o \ omap_hwmod_common_data.o -omap-3-4-common = dpll3xxx.o prcm-common = prcm.o powerdomain.o clock-common = clock.o clock_common_data.o \ clockdomain.o clkt_dpll.o \ clkt_clksel.o -clock-omap2xxx = clkt2xxx_dpllcore.o \ - clkt2xxx_virt_prcm_set.o \ - clkt2xxx_apll.o clkt2xxx_osc.o \ - clkt2xxx_sys.o -clock-omap3xxx = clkt34xx_dpll3m2.o - -obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) $(clock-common) \ - $(clock-omap2xxx) -obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(clock-common) \ - $(omap-3-4-common) $(clock-omap3xxx) -obj-$(CONFIG_ARCH_OMAP4) += $(omap-3-4-common) $(prcm-common) $(clock-common) + +obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) +obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) +obj-$(CONFIG_ARCH_OMAP4) += $(prcm-common) obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o @@ -64,14 +56,24 @@ obj-$(CONFIG_ARCH_OMAP3) += cm.o obj-$(CONFIG_ARCH_OMAP4) += cm4xxx.o # Clock framework -obj-$(CONFIG_ARCH_OMAP2) += clock2xxx.o clock2xxx_data.o +obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o \ + clock2xxx_data.o clkt2xxx_sys.o \ + clkt2xxx_dpllcore.o \ + clkt2xxx_virt_prcm_set.o \ + clkt2xxx_apll.o clkt2xxx_osc.o +obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o \ + clock34xx.o clkt34xx_dpll3m2.o \ + clock3517.o clock36xx.o \ + dpll3xxx.o clock3xxx_data.o +obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) clock44xx_data.o \ + dpll3xxx.o + +# OMAP2 clock rate set data (old "OPP" data) obj-$(CONFIG_ARCH_OMAP2420) += opp2420_data.o -obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o clock34xx_data.o obj-$(CONFIG_ARCH_OMAP2430) += opp2430_data.o -obj-$(CONFIG_ARCH_OMAP4) += clock44xx.o clock44xx_data.o # EMU peripherals -obj-$(CONFIG_OMAP3_EMU) += emu.o +obj-$(CONFIG_OMAP3_EMU) += emu.o obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o mailbox_mach-objs := mailbox.o @@ -127,7 +129,7 @@ obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o \ hsmmc.o obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o -obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o +obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o # Platform specific device init code obj-y += usb-musb.o diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c index 8716a01d1f5b..b2b1e37bb6bb 100644 --- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c +++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c @@ -26,6 +26,7 @@ #include <plat/sdrc.h> #include "clock.h" +#include "clock3xxx.h" #include "clock34xx.h" #include "sdrc.h" diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 9df5937999cb..82b17ef17dbe 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -336,6 +336,18 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) return omap2_clksel_set_parent(clk, new_parent); } +/* OMAP3/4 non-CORE DPLL clkops */ + +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) + +const struct clkops clkops_omap3_noncore_dpll_ops = { + .enable = omap3_noncore_dpll_enable, + .disable = omap3_noncore_dpll_disable, +}; + +#endif + + /*------------------------------------------------------------------------- * Omap2 clock reset and init functions *-------------------------------------------------------------------------*/ diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 0b0f52083121..f98dd0407e7e 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -141,4 +141,6 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) #define omap2_clk_exit_cpufreq_table 0 #endif +extern const struct clkops clkops_omap3_noncore_dpll_ops; + #endif diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 9039e8cbe487..6febd5f11e85 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -8,7 +8,8 @@ * Jouni Högander * * Parts of this code are based on code written by - * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu + * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu, + * Russell King * * 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 @@ -17,42 +18,16 @@ #undef DEBUG #include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/delay.h> #include <linux/clk.h> #include <linux/io.h> -#include <linux/err.h> -#include <plat/cpu.h> #include <plat/clock.h> #include "clock.h" #include "clock34xx.h" -#include "prm.h" -#include "prm-regbits-34xx.h" #include "cm.h" #include "cm-regbits-34xx.h" -/* - * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks - * that are sourced by DPLL5, and both of these require this clock - * to be at 120 MHz for proper operation. - */ -#define DPLL5_FREQ_FOR_USBHOST 120000000 - -/* - * In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported - * in the same register at a bit offset of 0x8. The EN_ACK for ICK is - * at an offset of 4 from ICK enable bit. - */ -#define AM35XX_IPSS_ICK_MASK 0xF -#define AM35XX_IPSS_ICK_EN_ACK_OFFSET 0x4 -#define AM35XX_IPSS_ICK_FCK_OFFSET 0x8 -#define AM35XX_IPSS_CLK_IDLEST_VAL 0 - -/* needed by omap3_core_dpll_m2_set_rate() */ -struct clk *sdrc_ick_p, *arm_fck_p; - /** * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI * @clk: struct clk * being enabled @@ -149,234 +124,3 @@ const struct clkops clkops_omap3430es2_hsotgusb_wait = { .find_idlest = omap3430es2_clk_hsotgusb_find_idlest, .find_companion = omap2_clk_dflt_find_companion, }; - -/** - * omap36xx_pwrdn_clk_enable_with_hsdiv_restore - enable clocks suffering - * from HSDivider PWRDN problem Implements Errata ID: i556. - * @clk: DPLL output struct clk - * - * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck, - * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset - * valueafter their respective PWRDN bits are set. Any dummy write - * (Any other value different from the Read value) to the - * corresponding CM_CLKSEL register will refresh the dividers. - */ -static int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk *clk) -{ - u32 dummy_v, orig_v, clksel_shift; - int ret; - - /* Clear PWRDN bit of HSDIVIDER */ - ret = omap2_dflt_clk_enable(clk); - - /* Restore the dividers */ - if (!ret) { - clksel_shift = __ffs(clk->parent->clksel_mask); - orig_v = __raw_readl(clk->parent->clksel_reg); - dummy_v = orig_v; - - /* Write any other value different from the Read value */ - dummy_v ^= (1 << clksel_shift); - __raw_writel(dummy_v, clk->parent->clksel_reg); - - /* Write the original divider */ - __raw_writel(orig_v, clk->parent->clksel_reg); - } - - return ret; -} - -const struct clkops clkops_omap36xx_pwrdn_with_hsdiv_wait_restore = { - .enable = omap36xx_pwrdn_clk_enable_with_hsdiv_restore, - .disable = omap2_dflt_clk_disable, - .find_companion = omap2_clk_dflt_find_companion, - .find_idlest = omap2_clk_dflt_find_idlest, -}; - -const struct clkops omap3_clkops_noncore_dpll_ops = { - .enable = omap3_noncore_dpll_enable, - .disable = omap3_noncore_dpll_disable, -}; - -/** - * am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS - * @clk: struct clk * being enabled - * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into - * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into - * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator - * - * The interface clocks on AM35xx IPSS reflects the clock idle status - * in the enable register itsel at a bit offset of 4 from the enable - * bit. A value of 1 indicates that clock is enabled. - */ -static void am35xx_clk_find_idlest(struct clk *clk, - void __iomem **idlest_reg, - u8 *idlest_bit, - u8 *idlest_val) -{ - *idlest_reg = (__force void __iomem *)(clk->enable_reg); - *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET; - *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL; -} - -/** - * am35xx_clk_find_companion - find companion clock to @clk - * @clk: struct clk * to find the companion clock of - * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in - * @other_bit: u8 ** to return the companion clock bit shift in - * - * Some clocks don't have companion clocks. For example, modules with - * only an interface clock (such as HECC) don't have a companion - * clock. Right now, this code relies on the hardware exporting a bit - * in the correct companion register that indicates that the - * nonexistent 'companion clock' is active. Future patches will - * associate this type of code with per-module data structures to - * avoid this issue, and remove the casts. No return value. - */ -static void am35xx_clk_find_companion(struct clk *clk, void __iomem **other_reg, - u8 *other_bit) -{ - *other_reg = (__force void __iomem *)(clk->enable_reg); - if (clk->enable_bit & AM35XX_IPSS_ICK_MASK) - *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET; - else - *other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET; -} - -const struct clkops clkops_am35xx_ipss_module_wait = { - .enable = omap2_dflt_clk_enable, - .disable = omap2_dflt_clk_disable, - .find_idlest = am35xx_clk_find_idlest, - .find_companion = am35xx_clk_find_companion, -}; - -/** - * am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS - * @clk: struct clk * being enabled - * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into - * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into - * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator - * - * The IPSS target CM_IDLEST bit is at a different shift from the - * CM_{I,F}CLKEN bit. Pass back the correct info via @idlest_reg - * and @idlest_bit. No return value. - */ -static void am35xx_clk_ipss_find_idlest(struct clk *clk, - void __iomem **idlest_reg, - u8 *idlest_bit, - u8 *idlest_val) -{ - u32 r; - - r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); - *idlest_reg = (__force void __iomem *)r; - *idlest_bit = AM35XX_ST_IPSS_SHIFT; - *idlest_val = OMAP34XX_CM_IDLEST_VAL; -} - -const struct clkops clkops_am35xx_ipss_wait = { - .enable = omap2_dflt_clk_enable, - .disable = omap2_dflt_clk_disable, - .find_idlest = am35xx_clk_ipss_find_idlest, - .find_companion = omap2_clk_dflt_find_companion, -}; - -int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate) -{ - /* - * According to the 12-5 CDP code from TI, "Limitation 2.5" - * on 3430ES1 prevents us from changing DPLL multipliers or dividers - * on DPLL4. - */ - if (omap_rev() == OMAP3430_REV_ES1_0) { - printk(KERN_ERR "clock: DPLL4 cannot change rate due to " - "silicon 'Limitation 2.5' on 3430ES1.\n"); - return -EINVAL; - } - return omap3_noncore_dpll_set_rate(clk, rate); -} - -void __init omap3_clk_lock_dpll5(void) -{ - struct clk *dpll5_clk; - struct clk *dpll5_m2_clk; - - dpll5_clk = clk_get(NULL, "dpll5_ck"); - clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST); - clk_enable(dpll5_clk); - - /* Enable autoidle to allow it to enter low power bypass */ - omap3_dpll_allow_idle(dpll5_clk); - - /* Program dpll5_m2_clk divider for no division */ - dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck"); - clk_enable(dpll5_m2_clk); - clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST); - - clk_disable(dpll5_m2_clk); - clk_disable(dpll5_clk); - return; -} - -/* Common clock code */ - -/* REVISIT: Move this init stuff out into clock.c */ - -/* - * Switch the MPU rate if specified on cmdline. - * We cannot do this early until cmdline is parsed. - */ -static int __init omap3xxx_clk_arch_init(void) -{ - struct clk *osc_sys_ck, *dpll1_ck, *arm_fck, *core_ck; - unsigned long osc_sys_rate; - bool err = 0; - - if (!cpu_is_omap34xx()) - return 0; - - if (!mpurate) - return -EINVAL; - - /* XXX test these for success */ - dpll1_ck = clk_get(NULL, "dpll1_ck"); - if (WARN(IS_ERR(dpll1_ck), "Failed to get dpll1_ck.\n")) - err = 1; - - arm_fck = clk_get(NULL, "arm_fck"); - if (WARN(IS_ERR(arm_fck), "Failed to get arm_fck.\n")) - err = 1; - - core_ck = clk_get(NULL, "core_ck"); - if (WARN(IS_ERR(core_ck), "Failed to get core_ck.\n")) - err = 1; - - osc_sys_ck = clk_get(NULL, "osc_sys_ck"); - if (WARN(IS_ERR(osc_sys_ck), "Failed to get osc_sys_ck.\n")) - err = 1; - - if (err) - return -ENOENT; - - /* REVISIT: not yet ready for 343x */ - if (clk_set_rate(dpll1_ck, mpurate)) - printk(KERN_ERR "*** Unable to set MPU rate\n"); - - recalculate_root_clocks(); - - osc_sys_rate = clk_get_rate(osc_sys_ck); - - pr_info("Switched to new clocking rate (Crystal/Core/MPU): " - "%ld.%01ld/%ld/%ld MHz\n", - (osc_sys_rate / 1000000), - ((osc_sys_rate / 100000) % 10), - (clk_get_rate(core_ck) / 1000000), - (clk_get_rate(arm_fck) / 1000000)); - - calibrate_delay(); - - return 0; -} -arch_initcall(omap3xxx_clk_arch_init); - - diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 720091ddced1..628e8de57680 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -1,32 +1,15 @@ /* - * OMAP3 clock function prototypes and macros + * OMAP34xx clock function prototypes and macros * - * Copyright (C) 2007-2009 Texas Instruments, Inc. - * Copyright (C) 2007-2009 Nokia Corporation + * Copyright (C) 2007-2010 Texas Instruments, Inc. + * Copyright (C) 2007-2010 Nokia Corporation */ -#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_34XX_H -#define __ARCH_ARM_MACH_OMAP2_CLOCK_34XX_H +#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H +#define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H -int omap3xxx_clk_init(void); -int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate); -int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate); -void omap3_clk_lock_dpll5(void); - -extern struct clk *sdrc_ick_p; -extern struct clk *arm_fck_p; - -/* OMAP34xx-specific clkops */ extern const struct clkops clkops_omap3430es2_ssi_wait; extern const struct clkops clkops_omap3430es2_hsotgusb_wait; extern const struct clkops clkops_omap3430es2_dss_usbhost_wait; -extern const struct clkops omap3_clkops_noncore_dpll_ops; - -/* AM35xx-specific clkops */ -extern const struct clkops clkops_am35xx_ipss_module_wait; -extern const struct clkops clkops_am35xx_ipss_wait; - -/* OMAP36xx-specific clkops */ -extern const struct clkops clkops_omap36xx_pwrdn_with_hsdiv_wait_restore; #endif diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c new file mode 100644 index 000000000000..b496a9305e1c --- /dev/null +++ b/arch/arm/mach-omap2/clock3517.c @@ -0,0 +1,124 @@ +/* + * OMAP3517/3505-specific clock framework functions + * + * Copyright (C) 2010 Texas Instruments, Inc. + * Copyright (C) 2010 Nokia Corporation + * + * Ranjith Lohithakshan + * Paul Walmsley + * + * Parts of this code are based on code written by + * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu, + * Russell King + * + * 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. + */ +#undef DEBUG + +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/io.h> + +#include <plat/clock.h> + +#include "clock.h" +#include "clock3517.h" +#include "cm.h" +#include "cm-regbits-34xx.h" + +/* + * In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported + * in the same register at a bit offset of 0x8. The EN_ACK for ICK is + * at an offset of 4 from ICK enable bit. + */ +#define AM35XX_IPSS_ICK_MASK 0xF +#define AM35XX_IPSS_ICK_EN_ACK_OFFSET 0x4 +#define AM35XX_IPSS_ICK_FCK_OFFSET 0x8 +#define AM35XX_IPSS_CLK_IDLEST_VAL 0 + +/** + * am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS + * @clk: struct clk * being enabled + * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into + * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into + * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator + * + * The interface clocks on AM35xx IPSS reflects the clock idle status + * in the enable register itsel at a bit offset of 4 from the enable + * bit. A value of 1 indicates that clock is enabled. + */ +static void am35xx_clk_find_idlest(struct clk *clk, + void __iomem **idlest_reg, + u8 *idlest_bit, + u8 *idlest_val) +{ + *idlest_reg = (__force void __iomem *)(clk->enable_reg); + *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET; + *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL; +} + +/** + * am35xx_clk_find_companion - find companion clock to @clk + * @clk: struct clk * to find the companion clock of + * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in + * @other_bit: u8 ** to return the companion clock bit shift in + * + * Some clocks don't have companion clocks. For example, modules with + * only an interface clock (such as HECC) don't have a companion + * clock. Right now, this code relies on the hardware exporting a bit + * in the correct companion register that indicates that the + * nonexistent 'companion clock' is active. Future patches will + * associate this type of code with per-module data structures to + * avoid this issue, and remove the casts. No return value. + */ +static void am35xx_clk_find_companion(struct clk *clk, void __iomem **other_reg, + u8 *other_bit) +{ + *other_reg = (__force void __iomem *)(clk->enable_reg); + if (clk->enable_bit & AM35XX_IPSS_ICK_MASK) + *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET; + else + *other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET; +} + +const struct clkops clkops_am35xx_ipss_module_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_idlest = am35xx_clk_find_idlest, + .find_companion = am35xx_clk_find_companion, +}; + +/** + * am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS + * @clk: struct clk * being enabled + * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into + * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into + * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator + * + * The IPSS target CM_IDLEST bit is at a different shift from the + * CM_{I,F}CLKEN bit. Pass back the correct info via @idlest_reg + * and @idlest_bit. No return value. + */ +static void am35xx_clk_ipss_find_idlest(struct clk *clk, + void __iomem **idlest_reg, + u8 *idlest_bit, + u8 *idlest_val) +{ + u32 r; + + r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); + *idlest_reg = (__force void __iomem *)r; + *idlest_bit = AM35XX_ST_IPSS_SHIFT; + *idlest_val = OMAP34XX_CM_IDLEST_VAL; +} + +const struct clkops clkops_am35xx_ipss_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_idlest = am35xx_clk_ipss_find_idlest, + .find_companion = omap2_clk_dflt_find_companion, +}; + + diff --git a/arch/arm/mach-omap2/clock3517.h b/arch/arm/mach-omap2/clock3517.h new file mode 100644 index 000000000000..ca5e5a64c2e2 --- /dev/null +++ b/arch/arm/mach-omap2/clock3517.h @@ -0,0 +1,14 @@ +/* + * OMAP3517/3505 clock function prototypes and macros + * + * Copyright (C) 2010 Texas Instruments, Inc. + * Copyright (C) 2010 Nokia Corporation + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK3517_H +#define __ARCH_ARM_MACH_OMAP2_CLOCK3517_H + +extern const struct clkops clkops_am35xx_ipss_module_wait; +extern const struct clkops clkops_am35xx_ipss_wait; + +#endif diff --git a/arch/arm/mach-omap2/clock36xx.c b/arch/arm/mach-omap2/clock36xx.c new file mode 100644 index 000000000000..0c5e25ed8879 --- /dev/null +++ b/arch/arm/mach-omap2/clock36xx.c @@ -0,0 +1,72 @@ +/* + * OMAP36xx-specific clkops + * + * Copyright (C) 2010 Texas Instruments, Inc. + * Copyright (C) 2010 Nokia Corporation + * + * Mike Turquette + * Vijaykumar GN + * Paul Walmsley + * + * Parts of this code are based on code written by + * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu, + * Russell King + * + * 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. + */ +#undef DEBUG + +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/io.h> + +#include <plat/clock.h> + +#include "clock.h" +#include "clock36xx.h" + + +/** + * omap36xx_pwrdn_clk_enable_with_hsdiv_restore - enable clocks suffering + * from HSDivider PWRDN problem Implements Errata ID: i556. + * @clk: DPLL output struct clk + * + * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck, + * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset + * valueafter their respective PWRDN bits are set. Any dummy write + * (Any other value different from the Read value) to the + * corresponding CM_CLKSEL register will refresh the dividers. + */ +static int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk *clk) +{ + u32 dummy_v, orig_v, clksel_shift; + int ret; + + /* Clear PWRDN bit of HSDIVIDER */ + ret = omap2_dflt_clk_enable(clk); + + /* Restore the dividers */ + if (!ret) { + clksel_shift = __ffs(clk->parent->clksel_mask); + orig_v = __raw_readl(clk->parent->clksel_reg); + dummy_v = orig_v; + + /* Write any other value different from the Read value */ + dummy_v ^= (1 << clksel_shift); + __raw_writel(dummy_v, clk->parent->clksel_reg); + + /* Write the original divider */ + __raw_writel(orig_v, clk->parent->clksel_reg); + } + + return ret; +} + +const struct clkops clkops_omap36xx_pwrdn_with_hsdiv_wait_restore = { + .enable = omap36xx_pwrdn_clk_enable_with_hsdiv_restore, + .disable = omap2_dflt_clk_disable, + .find_companion = omap2_clk_dflt_find_companion, + .find_idlest = omap2_clk_dflt_find_idlest, +}; diff --git a/arch/arm/mach-omap2/clock36xx.h b/arch/arm/mach-omap2/clock36xx.h new file mode 100644 index 000000000000..a7dee5bc6364 --- /dev/null +++ b/arch/arm/mach-omap2/clock36xx.h @@ -0,0 +1,13 @@ +/* + * OMAP36xx clock function prototypes and macros + * + * Copyright (C) 2010 Texas Instruments, Inc. + * Copyright (C) 2010 Nokia Corporation + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H +#define __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H + +extern const struct clkops clkops_omap36xx_pwrdn_with_hsdiv_wait_restore; + +#endif diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c new file mode 100644 index 000000000000..d142457cd041 --- /dev/null +++ b/arch/arm/mach-omap2/clock3xxx.c @@ -0,0 +1,145 @@ +/* + * OMAP3-specific clock framework functions + * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Copyright (C) 2007-2010 Nokia Corporation + * + * Paul Walmsley + * Jouni Högander + * + * Parts of this code are based on code written by + * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu + * + * 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. + */ +#undef DEBUG + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/err.h> + +#include <plat/cpu.h> +#include <plat/clock.h> + +#include "clock.h" +#include "clock3xxx.h" +#include "prm.h" +#include "prm-regbits-34xx.h" +#include "cm.h" +#include "cm-regbits-34xx.h" + +/* + * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks + * that are sourced by DPLL5, and both of these require this clock + * to be at 120 MHz for proper operation. + */ +#define DPLL5_FREQ_FOR_USBHOST 120000000 + +/* needed by omap3_core_dpll_m2_set_rate() */ +struct clk *sdrc_ick_p, *arm_fck_p; + +int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate) +{ + /* + * According to the 12-5 CDP code from TI, "Limitation 2.5" + * on 3430ES1 prevents us from changing DPLL multipliers or dividers + * on DPLL4. + */ + if (omap_rev() == OMAP3430_REV_ES1_0) { + pr_err("clock: DPLL4 cannot change rate due to " + "silicon 'Limitation 2.5' on 3430ES1.\n"); + return -EINVAL; + } + + return omap3_noncore_dpll_set_rate(clk, rate); +} + +void __init omap3_clk_lock_dpll5(void) +{ + struct clk *dpll5_clk; + struct clk *dpll5_m2_clk; + + dpll5_clk = clk_get(NULL, "dpll5_ck"); + clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST); + clk_enable(dpll5_clk); + + /* Enable autoidle to allow it to enter low power bypass */ + omap3_dpll_allow_idle(dpll5_clk); + + /* Program dpll5_m2_clk divider for no division */ + dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck"); + clk_enable(dpll5_m2_clk); + clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST); + + clk_disable(dpll5_m2_clk); + clk_disable(dpll5_clk); + return; +} + +/* Common clock code */ + +/* REVISIT: Move this init stuff out into clock.c */ + +/* + * Switch the MPU rate if specified on cmdline. + * We cannot do this early until cmdline is parsed. + */ +static int __init omap3xxx_clk_arch_init(void) +{ + struct clk *osc_sys_ck, *dpll1_ck, *arm_fck, *core_ck; + unsigned long osc_sys_rate; + bool err = 0; + + if (!cpu_is_omap34xx()) + return 0; + + if (!mpurate) + return -EINVAL; + + /* XXX test these for success */ + dpll1_ck = clk_get(NULL, "dpll1_ck"); + if (WARN(IS_ERR(dpll1_ck), "Failed to get dpll1_ck.\n")) + err = 1; + + arm_fck = clk_get(NULL, "arm_fck"); + if (WARN(IS_ERR(arm_fck), "Failed to get arm_fck.\n")) + err = 1; + + core_ck = clk_get(NULL, "core_ck"); + if (WARN(IS_ERR(core_ck), "Failed to get core_ck.\n")) + err = 1; + + osc_sys_ck = clk_get(NULL, "osc_sys_ck"); + if (WARN(IS_ERR(osc_sys_ck), "Failed to get osc_sys_ck.\n")) + err = 1; + + if (err) + return -ENOENT; + + /* REVISIT: not yet ready for 343x */ + if (clk_set_rate(dpll1_ck, mpurate)) + printk(KERN_ERR "*** Unable to set MPU rate\n"); + + recalculate_root_clocks(); + + osc_sys_rate = clk_get_rate(osc_sys_ck); + + pr_info("Switched to new clocking rate (Crystal/Core/MPU): " + "%ld.%01ld/%ld/%ld MHz\n", + (osc_sys_rate / 1000000), + ((osc_sys_rate / 100000) % 10), + (clk_get_rate(core_ck) / 1000000), + (clk_get_rate(arm_fck) / 1000000)); + + calibrate_delay(); + + return 0; +} +arch_initcall(omap3xxx_clk_arch_init); + + diff --git a/arch/arm/mach-omap2/clock3xxx.h b/arch/arm/mach-omap2/clock3xxx.h new file mode 100644 index 000000000000..8bbeeaf399e2 --- /dev/null +++ b/arch/arm/mach-omap2/clock3xxx.h @@ -0,0 +1,21 @@ +/* + * OMAP3-common clock function prototypes and macros + * + * Copyright (C) 2007-2010 Texas Instruments, Inc. + * Copyright (C) 2007-2010 Nokia Corporation + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK3XXX_H +#define __ARCH_ARM_MACH_OMAP2_CLOCK3XXX_H + +int omap3xxx_clk_init(void); +int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate); +int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate); +void omap3_clk_lock_dpll5(void); + +extern struct clk *sdrc_ick_p; +extern struct clk *arm_fck_p; + +extern const struct clkops clkops_noncore_dpll_ops; + +#endif diff --git a/arch/arm/mach-omap2/clock34xx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 995d5d4c897d..f23790297003 100644 --- a/arch/arm/mach-omap2/clock34xx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -24,7 +24,11 @@ #include <plat/clkdev_omap.h> #include "clock.h" +#include "clock3xxx.h" #include "clock34xx.h" +#include "clock36xx.h" +#include "clock3517.h" + #include "cm.h" #include "cm-regbits-34xx.h" #include "prm.h" @@ -374,7 +378,7 @@ static struct dpll_data dpll2_dd = { static struct clk dpll2_ck = { .name = "dpll2_ck", - .ops = &omap3_clkops_noncore_dpll_ops, + .ops = &clkops_omap3_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll2_dd, .round_rate = &omap2_dpll_round_rate, @@ -615,7 +619,7 @@ static struct dpll_data dpll4_dd_3630 __initdata = { static struct clk dpll4_ck = { .name = "dpll4_ck", - .ops = &omap3_clkops_noncore_dpll_ops, + .ops = &clkops_omap3_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll4_dd, .round_rate = &omap2_dpll_round_rate, @@ -1023,7 +1027,7 @@ static struct dpll_data dpll5_dd = { static struct clk dpll5_ck = { .name = "dpll5_ck", - .ops = &omap3_clkops_noncore_dpll_ops, + .ops = &clkops_omap3_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll5_dd, .round_rate = &omap2_dpll_round_rate, @@ -3567,10 +3571,12 @@ int __init omap3xxx_clk_init(void) clk_init(&omap2_clk_functions); - for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); c++) + for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); + c++) clk_preinit(c->lk.clk); - for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); c++) + for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); + c++) if (c->cpu & cpu_clkflg) { clkdev_add(&c->lk); clk_register(c->lk.clk); diff --git a/arch/arm/mach-omap2/clock44xx.c b/arch/arm/mach-omap2/clock44xx.c deleted file mode 100644 index 84ee6b0c7995..000000000000 --- a/arch/arm/mach-omap2/clock44xx.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * OMAP4-specific clock framework functions - * - * Copyright (C) 2009 Texas Instruments, Inc. - * - * Rajendra Nayak (rnayak@ti.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/errno.h> -#include "clock.h" - -const struct clkops omap4_clkops_noncore_dpll_ops = { - .enable = &omap3_noncore_dpll_enable, - .disable = &omap3_noncore_dpll_disable, -}; diff --git a/arch/arm/mach-omap2/clock44xx.h b/arch/arm/mach-omap2/clock44xx.h index 0c739726703d..6be1095936db 100644 --- a/arch/arm/mach-omap2/clock44xx.h +++ b/arch/arm/mach-omap2/clock44xx.h @@ -5,8 +5,8 @@ * Copyright (C) 2010 Nokia Corporation */ -#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_44XX_H -#define __ARCH_ARM_MACH_OMAP2_CLOCK_44XX_H +#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H +#define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H /* * XXX Missing values for the OMAP4 DPLL_USB @@ -17,6 +17,4 @@ int omap4xxx_clk_init(void); -extern const struct clkops omap4_clkops_noncore_dpll_ops; - #endif diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 8c7ab76bc70c..022f1a75286a 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -277,7 +277,7 @@ static struct clk dpll_abe_ck = { .parent = &abe_dpll_refclk_mux_ck, .dpll_data = &dpll_abe_dd, .init = &omap2_init_dpll_parent, - .ops = &omap4_clkops_noncore_dpll_ops, + .ops = &clkops_omap3_noncore_dpll_ops, .recalc = &omap3_dpll_recalc, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, @@ -644,7 +644,7 @@ static struct clk dpll_iva_ck = { .parent = &dpll_sys_ref_clk, .dpll_data = &dpll_iva_dd, .init = &omap2_init_dpll_parent, - .ops = &omap4_clkops_noncore_dpll_ops, + .ops = &clkops_omap3_noncore_dpll_ops, .recalc = &omap3_dpll_recalc, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, @@ -704,7 +704,7 @@ static struct clk dpll_mpu_ck = { .parent = &dpll_sys_ref_clk, .dpll_data = &dpll_mpu_dd, .init = &omap2_init_dpll_parent, - .ops = &omap4_clkops_noncore_dpll_ops, + .ops = &clkops_omap3_noncore_dpll_ops, .recalc = &omap3_dpll_recalc, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, @@ -776,7 +776,7 @@ static struct clk dpll_per_ck = { .parent = &dpll_sys_ref_clk, .dpll_data = &dpll_per_dd, .init = &omap2_init_dpll_parent, - .ops = &omap4_clkops_noncore_dpll_ops, + .ops = &clkops_omap3_noncore_dpll_ops, .recalc = &omap3_dpll_recalc, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, @@ -891,7 +891,7 @@ static struct clk dpll_unipro_ck = { .parent = &dpll_sys_ref_clk, .dpll_data = &dpll_unipro_dd, .init = &omap2_init_dpll_parent, - .ops = &omap4_clkops_noncore_dpll_ops, + .ops = &clkops_omap3_noncore_dpll_ops, .recalc = &omap3_dpll_recalc, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, @@ -947,7 +947,7 @@ static struct clk dpll_usb_ck = { .parent = &dpll_sys_ref_clk, .dpll_data = &dpll_usb_dd, .init = &omap2_init_dpll_parent, - .ops = &omap4_clkops_noncore_dpll_ops, + .ops = &clkops_omap3_noncore_dpll_ops, .recalc = &omap3_dpll_recalc, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 5a3d6f9107e4..2c5185474972 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -36,7 +36,7 @@ #include <plat/vram.h> #include "clock2xxx.h" -#include "clock34xx.h" +#include "clock3xxx.h" #include "clock44xx.h" #include <plat/omap-pm.h> |