diff options
author | Olof Johansson <olof@lixom.net> | 2012-03-08 08:53:14 -0800 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2012-03-08 08:53:14 -0800 |
commit | d60d506e6baaf423148c458df3ece0c1d440dce4 (patch) | |
tree | c25c44e70ebaaddcbe39559df5c5cd260e956be4 /arch/arm/mach-s3c24xx/clock-s3c244x.c | |
parent | 62f383435932ea3d271bee6b957de048452c1b16 (diff) | |
parent | 2e5ac9436645bb9fd2097868e228321f303c9c75 (diff) |
Merge branch 'next/cleanup-s3c24xx' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/cleanup
* 'next/cleanup-s3c24xx' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: (24 commits)
ARM: S3C24XX: remove call to s3c24xx_setup_clocks
ARM: S3C24XX: add get_rate for clk_p on S3C2416/2443
ARM: S3C24XX: add get_rate for clk_h on S3C2416/2443
ARM: S3C24XX: remove XXX_setup_clocks method from S3C2443
ARM: S3C24XX: remove obsolete S3C2416_DMA option
ARM: S3C24XX: Reuse S3C2443 dma for S3C2416
ARM: S3C24XX: Fix indentation of dma-s3c2443
ARM: S3C24XX: Move device setup files to mach directory
ARM: S3C24XX: Consolidate Simtec extensions
ARM: S3C24XX: move simtec-specific code to mach directory
ARM: S3C24XX: Move common-smdk code to mach directory
ARM: S3C24XX: Move s3c2443-clock.c to mach-s3c24xx
ARM: s3c2410_defconfig: update s3c2410_defconfig
ARM: S3C2443: move mach-s3c2443/* into mach-s3c24xx/
ARM: S3C2440: move mach-s3c2440/* into mach-s3c24xx/
ARM: S3C2416: move mach-s3c2416/* into mach-s3c24xx/
ARM: S3C2412: move mach-s3c2412/* into mach-s3c24xx/
ARM: S3C2410: move mach-s3c2410/* into mach-s3c24xx/
ARM: S3C24XX: change the ARCH_S3C2410 to ARCH_S3C24XX
ARM: S3C2410: move s3c2410_baseclk_add to clock.h
...
Diffstat (limited to 'arch/arm/mach-s3c24xx/clock-s3c244x.c')
-rw-r--r-- | arch/arm/mach-s3c24xx/clock-s3c244x.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/arch/arm/mach-s3c24xx/clock-s3c244x.c b/arch/arm/mach-s3c24xx/clock-s3c244x.c new file mode 100644 index 00000000000..6d9b688c442 --- /dev/null +++ b/arch/arm/mach-s3c24xx/clock-s3c244x.c @@ -0,0 +1,141 @@ +/* linux/arch/arm/plat-s3c24xx/s3c24xx-clock.c + * + * Copyright (c) 2004-2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2440/S3C2442 Common clock support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/clk.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <linux/atomic.h> +#include <asm/irq.h> + +#include <mach/regs-clock.h> + +#include <plat/clock.h> +#include <plat/cpu.h> + +static int s3c2440_setparent_armclk(struct clk *clk, struct clk *parent) +{ + unsigned long camdivn; + unsigned long dvs; + + if (parent == &clk_f) + dvs = 0; + else if (parent == &clk_h) + dvs = S3C2440_CAMDIVN_DVSEN; + else + return -EINVAL; + + clk->parent = parent; + + camdivn = __raw_readl(S3C2440_CAMDIVN); + camdivn &= ~S3C2440_CAMDIVN_DVSEN; + camdivn |= dvs; + __raw_writel(camdivn, S3C2440_CAMDIVN); + + return 0; +} + +static struct clk clk_arm = { + .name = "armclk", + .id = -1, + .ops = &(struct clk_ops) { + .set_parent = s3c2440_setparent_armclk, + }, +}; + +static int s3c244x_clk_add(struct device *dev, struct subsys_interface *sif) +{ + unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); + unsigned long clkdivn; + struct clk *clock_upll; + int ret; + + printk("S3C244X: Clock Support, DVS %s\n", + (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off"); + + clk_arm.parent = (camdivn & S3C2440_CAMDIVN_DVSEN) ? &clk_h : &clk_f; + + ret = s3c24xx_register_clock(&clk_arm); + if (ret < 0) { + printk(KERN_ERR "S3C24XX: Failed to add armclk (%d)\n", ret); + return ret; + } + + clock_upll = clk_get(NULL, "upll"); + if (IS_ERR(clock_upll)) { + printk(KERN_ERR "S3C244X: Failed to get upll clock\n"); + return -ENOENT; + } + + /* check rate of UPLL, and if it is near 96MHz, then change + * to using half the UPLL rate for the system */ + + if (clk_get_rate(clock_upll) > (94 * MHZ)) { + clk_usb_bus.rate = clk_get_rate(clock_upll) / 2; + + spin_lock(&clocks_lock); + + clkdivn = __raw_readl(S3C2410_CLKDIVN); + clkdivn |= S3C2440_CLKDIVN_UCLK; + __raw_writel(clkdivn, S3C2410_CLKDIVN); + + spin_unlock(&clocks_lock); + } + + return 0; +} + +static struct subsys_interface s3c2440_clk_interface = { + .name = "s3c2440_clk", + .subsys = &s3c2440_subsys, + .add_dev = s3c244x_clk_add, +}; + +static int s3c2440_clk_init(void) +{ + return subsys_interface_register(&s3c2440_clk_interface); +} + +arch_initcall(s3c2440_clk_init); + +static struct subsys_interface s3c2442_clk_interface = { + .name = "s3c2442_clk", + .subsys = &s3c2442_subsys, + .add_dev = s3c244x_clk_add, +}; + +static int s3c2442_clk_init(void) +{ + return subsys_interface_register(&s3c2442_clk_interface); +} + +arch_initcall(s3c2442_clk_init); |