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_ARCH_* options for those other chip families; that will be done in a future patch, 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.) This second version of the patch fixes some minor errors where the AM35xx files were renamed, but the #includes weren't. Signed-off-by: Paul Walmsley <paul@xxxxxxxxx> Cc: Benoît Cousson <b-cousson@xxxxxx> Cc: Rajendra Nayak <rnayak@xxxxxx> Cc: Ranjith Lohithakshan <ranjithl@xxxxxx> --- arch/arm/mach-omap2/Makefile | 36 ++-- arch/arm/mach-omap2/clkt34xx_dpll3m2.c | 1 + arch/arm/mach-omap2/clock.c | 12 + arch/arm/mach-omap2/clock.h | 2 + arch/arm/mach-omap2/clock34xx.c | 260 +------------------- arch/arm/mach-omap2/clock34xx.h | 27 +-- arch/arm/mach-omap2/clock3517.c | 124 ++++++++++ arch/arm/mach-omap2/clock3517.h | 14 + arch/arm/mach-omap2/clock36xx.c | 72 ++++++ arch/arm/mach-omap2/clock36xx.h | 13 + arch/arm/mach-omap2/clock3xxx.c | 145 +++++++++++ arch/arm/mach-omap2/clock3xxx.h | 21 ++ .../{clock34xx_data.c => clock3xxx_data.c} | 16 +- arch/arm/mach-omap2/clock44xx.c | 19 -- arch/arm/mach-omap2/clock44xx.h | 6 +- arch/arm/mach-omap2/clock44xx_data.c | 12 +- arch/arm/mach-omap2/io.c | 2 +- 17 files changed, 450 insertions(+), 332 deletions(-) create mode 100644 arch/arm/mach-omap2/clock3517.c create mode 100644 arch/arm/mach-omap2/clock3517.h create mode 100644 arch/arm/mach-omap2/clock36xx.c create mode 100644 arch/arm/mach-omap2/clock36xx.h create mode 100644 arch/arm/mach-omap2/clock3xxx.c create mode 100644 arch/arm/mach-omap2/clock3xxx.h rename arch/arm/mach-omap2/{clock34xx_data.c => clock3xxx_data.c} (99%) delete mode 100644 arch/arm/mach-omap2/clock44xx.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 10e6c6e..03058ad 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) += $(omap-3-4-common) $(prcm-common) obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o @@ -56,14 +48,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 @@ -118,7 +120,7 @@ obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o \ mmc-twl4030.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 8716a01..b2b1e37 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 9df5937..82b17ef 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 f7e7100..8b724bb 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -115,4 +115,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 c8b4e56..6febd5f 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 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 b9c65f5..628e8de 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 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 0000000..b496a93 --- /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 0000000..ca5e5a6 --- /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 0000000..0c5e25e --- /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 0000000..a7dee5b --- /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 0000000..d142457 --- /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 0000000..8bbeeaf --- /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 similarity index 99% rename from arch/arm/mach-omap2/clock34xx_data.c rename to arch/arm/mach-omap2/clock3xxx_data.c index 950d6fc..f237902 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 = &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 = &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 = &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 c238717..0000000 --- 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@xxxxxx) - * - * 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 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 ed3b741..6be1095 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 clkops_noncore_dpll_ops; - #endif diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 70b314c..022f1a7 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 = &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 = &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 = &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 = &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 = &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 = &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 01ef2ae..ad782e4 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> -- 1.6.6.GIT