Commit 32726d2d authored by Tomasz Figa's avatar Tomasz Figa Committed by Kukjin Kim

ARM: SAMSUNG: Remove legacy clock code

Since S5PV210 now has a complete clock driver using Common Clock
Framework, there is no reason to keep the old code. Remove it together
with the whole legacy Samsung-specific clock framework which no longer
has any users.
Signed-off-by: default avatarTomasz Figa <t.figa@samsung.com>
Signed-off-by: default avatarKukjin Kim <kgene.kim@samsung.com>
parent f73d4cb6
......@@ -765,6 +765,7 @@ config ARCH_S5PV210
select ATAGS
select CLKDEV_LOOKUP
select CLKSRC_SAMSUNG_PWM
select COMMON_CLK_SAMSUNG
select CPU_V7
select GENERIC_CLOCKEVENTS
select GPIO_SAMSUNG
......
......@@ -28,7 +28,6 @@
#include <asm/suspend.h>
#include <plat/pm-common.h>
#include <plat/pll.h>
#include <plat/regs-srom.h>
#include <mach/map.h>
......
......@@ -49,9 +49,7 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/clock.h>
#include <plat/cpu-freq.h>
#include <plat/pll.h>
#include <plat/pwm-core.h>
#include <plat/watchdog-reset.h>
......
......@@ -29,7 +29,6 @@
#include <plat/cpu.h>
#include <plat/cpu-freq-core.h>
#include <plat/clock.h>
#include <mach/s3c2412.h>
......
......@@ -60,7 +60,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/gpio-cfg.h>
#include <plat/pll.h>
#include <plat/pm.h>
#include <plat/samsung-time.h>
......@@ -73,6 +72,10 @@
#define H1940_LATCH_BIT(x) (1 << ((x) + 16 - S3C_GPIO_END))
#define S3C24XX_PLL_MDIV_SHIFT (12)
#define S3C24XX_PLL_PDIV_SHIFT (4)
#define S3C24XX_PLL_SDIV_SHIFT (0)
static struct map_desc h1940_iodesc[] __initdata = {
[0] = {
.virtual = (unsigned long)H1940_LATCH,
......
......@@ -48,7 +48,6 @@
#include <linux/mtd/partitions.h>
#include <plat/gpio-cfg.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/pm.h>
......
......@@ -43,7 +43,6 @@
#include <mach/gpio-samsung.h>
#include <mach/fb.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/samsung-time.h>
......
......@@ -44,7 +44,6 @@
#include <linux/platform_data/i2c-s3c2410.h>
#include <plat/gpio-cfg.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <linux/platform_data/mtd-nand-s3c2410.h>
......
......@@ -38,7 +38,6 @@
#include <mach/fb.h>
#include <linux/platform_data/i2c-s3c2410.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/samsung-time.h>
......
......@@ -42,7 +42,6 @@
#include <linux/platform_data/i2c-s3c2410.h>
#include <linux/platform_data/mtd-nand-s3c2410.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/samsung-time.h>
......
......@@ -41,8 +41,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/clock.h>
#include <plat/pll.h>
#include <plat/pm.h>
#include <plat/watchdog-reset.h>
......@@ -83,10 +81,6 @@ void __init s3c2410_map_io(void)
iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
}
void __init_or_cpufreq s3c2410_setup_clocks(void)
{
}
struct bus_type s3c2410_subsys = {
.name = "s3c2410-core",
.dev_name = "s3c2410-core",
......
......@@ -37,12 +37,10 @@
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>
#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/cpu-freq.h>
#include <plat/devs.h>
#include <plat/nand-core.h>
#include <plat/pll.h>
#include <plat/pm.h>
#include <plat/regs-spi.h>
......@@ -171,10 +169,6 @@ void __init s3c2412_map_io(void)
iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
}
void __init_or_cpufreq s3c2412_setup_clocks(void)
{
}
/* need to register the subsystem before we actually register the device, and
* we also need to ensure that it has been initialised before any of the
* drivers even try to use it (even if not on an s3c2412 based system)
......
......@@ -43,7 +43,6 @@
#include <mach/regs-clock.h>
#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/pm.h>
......
......@@ -38,11 +38,9 @@
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/pm.h>
#include <plat/pll.h>
#include <plat/nand-core.h>
#include <plat/watchdog-reset.h>
......@@ -78,10 +76,6 @@ void __init s3c244x_map_io(void)
s3c2410_device_dclk.name = "s3c2440-dclk";
}
void __init_or_cpufreq s3c244x_setup_clocks(void)
{
}
/* Since the S3C2442 and S3C2440 share items, put both subsystems here */
struct bus_type s3c2440_subsys = {
......
......@@ -45,7 +45,6 @@
#include <linux/platform_data/i2c-s3c2410.h>
#include <plat/fb.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <mach/regs-gpio.h>
......
......@@ -58,7 +58,6 @@
#include <linux/platform_data/spi-s3c64xx.h>
#include <plat/keypad.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/adc.h>
......
......@@ -39,7 +39,6 @@
#include <plat/fb.h>
#include <linux/platform_data/mtd-nand-s3c2410.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/samsung-time.h>
......
......@@ -40,7 +40,6 @@
#include <linux/platform_data/i2c-s3c2410.h>
#include <plat/fb.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/samsung-time.h>
......
......@@ -28,7 +28,6 @@
#include <mach/regs-gpio.h>
#include <mach/gpio-samsung.h>
#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/devs.h>
#include <linux/platform_data/i2c-s3c2410.h>
......
......@@ -30,7 +30,6 @@
#include <mach/hardware.h>
#include <mach/map.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <linux/platform_data/i2c-s3c2410.h>
......
......@@ -63,7 +63,6 @@
#include <plat/fb.h>
#include <plat/gpio-cfg.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/adc.h>
......
......@@ -39,7 +39,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/clock.h>
#include <plat/sdhci.h>
#include <plat/iic-core.h>
#include <plat/onenand-core.h>
......
......@@ -40,7 +40,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/clock.h>
#include <plat/sdhci.h>
#include <plat/ata-core.h>
#include <plat/adc-core.h>
......
......@@ -13,7 +13,6 @@ config CPU_S5PV210
bool
select ARM_AMBA
select PL330_DMA if DMADEVICES
select S5P_CLOCK if !COMMON_CLK
select S5P_EXT_INT
select S5P_PM if PM
select S5P_SLEEP if PM
......@@ -71,14 +70,6 @@ config S5PV210_SETUP_USB_PHY
help
Common setup code for USB PHY controller
config COMMON_CLK_S5PV210
bool "Common Clock Framework support"
default y
select COMMON_CLK_SAMSUNG
help
Enable this option to use new clock driver
based on Common Clock Framework.
menu "S5PC110 Machines"
config MACH_AQUILA
......
......@@ -13,7 +13,6 @@ obj- :=
# Core
obj-y += common.o
obj-$(CONFIG_S5P_CLOCK) += clock.o
obj-$(CONFIG_PM) += pm.o
obj-y += dma.o
......
This diff is collapsed.
......@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/device.h>
#include <clocksource/samsung_pwm.h>
......@@ -37,12 +38,6 @@
#include <plat/cpu.h>
#ifdef CONFIG_S5P_CLOCK
#include <plat/clock.h>
#else
#include <linux/clk-provider.h>
#endif
#include <plat/devs.h>
#include <plat/sdhci.h>
#include <plat/adc-core.h>
......@@ -239,16 +234,7 @@ void __init s5pv210_map_io(void)
void __init s5pv210_init_clocks(int xtal)
{
#ifdef CONFIG_S5P_CLOCK
printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
s3c24xx_register_baseclocks(xtal);
s5p_register_clocks(xtal);
s5pv210_register_clocks();
s5pv210_setup_clocks();
#else
xusbxti_f = xtal;
#endif
}
void __init s5pv210_init_irq(void)
......
......@@ -14,14 +14,8 @@
#include <linux/reboot.h>
#ifdef CONFIG_COMMON_CLK_S5PV210
void s5pv210_clk_init(unsigned long xxti_f, unsigned long xusbxti_f,
void __iomem *reg_base);
#else
static inline void s5pv210_clk_init(unsigned long xxti_f,
unsigned long xusbxti_f,
void __iomem *reg_base) {}
#endif
void s5pv210_init_io(struct map_desc *mach_desc, int size);
void s5pv210_init_irq(void);
......
......@@ -46,7 +46,6 @@
#include <linux/platform_data/i2c-s3c2410.h>
#include <plat/keypad.h>
#include <plat/sdhci.h>
#include <plat/clock.h>
#include <plat/samsung-time.h>
#include <plat/mfc.h>
......
......@@ -47,7 +47,6 @@
#include <plat/samsung-time.h>
#include <plat/backlight.h>
#include <plat/mfc.h>
#include <plat/clock.h>
#include "common.h"
......
......@@ -26,55 +26,7 @@
#include <mach/regs-clock.h>
static struct sleep_save s5pv210_core_save[] = {
/* Clock source */
SAVE_ITEM(S5P_CLK_SRC0),
SAVE_ITEM(S5P_CLK_SRC1),
SAVE_ITEM(S5P_CLK_SRC2),
SAVE_ITEM(S5P_CLK_SRC3),
SAVE_ITEM(S5P_CLK_SRC4),
SAVE_ITEM(S5P_CLK_SRC5),
SAVE_ITEM(S5P_CLK_SRC6),
/* Clock source Mask */
SAVE_ITEM(S5P_CLK_SRC_MASK0),
SAVE_ITEM(S5P_CLK_SRC_MASK1),
/* Clock Divider */
SAVE_ITEM(S5P_CLK_DIV0),
SAVE_ITEM(S5P_CLK_DIV1),
SAVE_ITEM(S5P_CLK_DIV2),
SAVE_ITEM(S5P_CLK_DIV3),
SAVE_ITEM(S5P_CLK_DIV4),
SAVE_ITEM(S5P_CLK_DIV5),
SAVE_ITEM(S5P_CLK_DIV6),
SAVE_ITEM(S5P_CLK_DIV7),
/* Clock Main Gate */
SAVE_ITEM(S5P_CLKGATE_MAIN0),
SAVE_ITEM(S5P_CLKGATE_MAIN1),
SAVE_ITEM(S5P_CLKGATE_MAIN2),
/* Clock source Peri Gate */
SAVE_ITEM(S5P_CLKGATE_PERI0),
SAVE_ITEM(S5P_CLKGATE_PERI1),
/* Clock source SCLK Gate */
SAVE_ITEM(S5P_CLKGATE_SCLK0),
SAVE_ITEM(S5P_CLKGATE_SCLK1),
/* Clock IP Clock gate */
SAVE_ITEM(S5P_CLKGATE_IP0),
SAVE_ITEM(S5P_CLKGATE_IP1),
SAVE_ITEM(S5P_CLKGATE_IP2),
SAVE_ITEM(S5P_CLKGATE_IP3),
SAVE_ITEM(S5P_CLKGATE_IP4),
/* Clock Blcok and Bus gate */
SAVE_ITEM(S5P_CLKGATE_BLOCK),
SAVE_ITEM(S5P_CLKGATE_BUS0),
/* Clock ETC */
SAVE_ITEM(S5P_CLK_OUT),
SAVE_ITEM(S5P_MDNIE_SEL),
};
......
......@@ -23,7 +23,6 @@ config PLAT_S5P
select PLAT_SAMSUNG
select S3C_GPIO_TRACK
select S5P_GPIO_DRVSTR
select SAMSUNG_CLKSRC if !COMMON_CLK
help
Base platform code for Samsung's S5P series SoC.
......@@ -65,23 +64,6 @@ config SAMSUNG_ATAGS
if SAMSUNG_ATAGS
# clock options
config SAMSUNG_CLOCK
bool
default y if !COMMON_CLK
config SAMSUNG_CLKSRC
bool
help
Select the clock code for the clksrc implementation
used by newer systems such as the S3C64XX.
config S5P_CLOCK
bool
help
Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
# options for IRQ support
config S5P_IRQ
......
......@@ -16,11 +16,6 @@ obj- :=
obj-y += init.o cpu.o
obj-$(CONFIG_SAMSUNG_CLOCK) += clock.o
obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o
obj-$(CONFIG_S5P_CLOCK) += s5p-clock.o
obj-$(CONFIG_S5P_IRQ) += s5p-irq.o
obj-$(CONFIG_S5P_EXT_INT) += s5p-irq-eint.o
obj-$(CONFIG_S5P_GPIO_INT) += s5p-irq-gpioint.o
......
/* linux/arch/arm/plat-samsung/clock-clksrc.c
*
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* 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/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
#include <plat/clock.h>
#include <plat/clock-clksrc.h>
#include <plat/cpu-freq.h>
static inline struct clksrc_clk *to_clksrc(struct clk *clk)
{
return container_of(clk, struct clksrc_clk, clk);
}
static inline u32 bit_mask(u32 shift, u32 nr_bits)
{
u32 mask = 0xffffffff >> (32 - nr_bits);
return mask << shift;
}
static unsigned long s3c_getrate_clksrc(struct clk *clk)
{
struct clksrc_clk *sclk = to_clksrc(clk);
unsigned long rate = clk_get_rate(clk->parent);
u32 clkdiv = __raw_readl(sclk->reg_div.reg);
u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size);
clkdiv &= mask;
clkdiv >>= sclk->reg_div.shift;
clkdiv++;
rate /= clkdiv;
return rate;
}
static int s3c_setrate_clksrc(struct clk *clk, unsigned long rate)
{
struct clksrc_clk *sclk = to_clksrc(clk);
void __iomem *reg = sclk->reg_div.reg;
unsigned int div;
u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size);
u32 val;
rate = clk_round_rate(clk, rate);
div = clk_get_rate(clk->parent) / rate;
if (div > (1 << sclk->reg_div.size))
return -EINVAL;
val = __raw_readl(reg);
val &= ~mask;
val |= (div - 1) << sclk->reg_div.shift;
__raw_writel(val, reg);
return 0;
}
static int s3c_setparent_clksrc(struct clk *clk, struct clk *parent)
{
struct clksrc_clk *sclk = to_clksrc(clk);
struct clksrc_sources *srcs = sclk->sources;
u32 clksrc = __raw_readl(sclk->reg_src.reg);
u32 mask = bit_mask(sclk->reg_src.shift, sclk->reg_src.size);
int src_nr = -1;
int ptr;
for (ptr = 0; ptr < srcs->nr_sources; ptr++)
if (srcs->sources[ptr] == parent) {
src_nr = ptr;
break;
}
if (src_nr >= 0) {
clk->parent = parent;
clksrc &= ~mask;
clksrc |= src_nr << sclk->reg_src.shift;
__raw_writel(clksrc, sclk->reg_src.reg);
return 0;
}
return -EINVAL;
}
static unsigned long s3c_roundrate_clksrc(struct clk *clk,
unsigned long rate)
{
struct clksrc_clk *sclk = to_clksrc(clk);
unsigned long parent_rate = clk_get_rate(clk->parent);
int max_div = 1 << sclk->reg_div.size;
int div;
if (rate >= parent_rate)
rate = parent_rate;
else {
div = parent_rate / rate;
if (parent_rate % rate)
div++;
if (div == 0)
div = 1;
if (div > max_div)
div = max_div;
rate = parent_rate / div;
}
return rate;
}
/* Clock initialisation code */
void __init_or_cpufreq s3c_set_clksrc(struct clksrc_clk *clk, bool announce)
{
struct clksrc_sources *srcs = clk->sources;
u32 mask = bit_mask(clk->reg_src.shift, clk->reg_src.size);
u32 clksrc;
if (!clk->reg_src.reg) {
if (!clk->clk.parent)
printk(KERN_ERR "%s: no parent clock specified\n",
clk->clk.name);
return;
}
clksrc = __raw_readl(clk->reg_src.reg);
clksrc &= mask;
clksrc >>= clk->reg_src.shift;
if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
printk(KERN_ERR "%s: bad source %d\n",
clk->clk.name, clksrc);
return;
}
clk->clk.parent = srcs->sources[clksrc];
if (announce)
printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n",
clk->clk.name, clk->clk.parent->name, clksrc,
clk_get_rate(&clk->clk));
}
static struct clk_ops clksrc_ops = {
.set_parent = s3c_setparent_clksrc,
.get_rate = s3c_getrate_clksrc,
.set_rate = s3c_setrate_clksrc,
.round_rate = s3c_roundrate_clksrc,
};
static struct clk_ops clksrc_ops_nodiv = {
.set_parent = s3c_setparent_clksrc,
};
static struct clk_ops clksrc_ops_nosrc = {
.get_rate = s3c_getrate_clksrc,
.set_rate = s3c_setrate_clksrc,
.round_rate = s3c_roundrate_clksrc,
};
void __init s3c_register_clksrc(struct clksrc_clk *clksrc, int size)
{
int ret;
for (; size > 0; size--, clksrc++) {
if (!clksrc->reg_div.reg && !clksrc->reg_src.reg)
printk(KERN_ERR "%s: clock %s has no registers set\n",
__func__, clksrc->clk.name);
/* fill in the default functions */
if (!clksrc->clk.ops) {
if (!clksrc->reg_div.reg)
clksrc->clk.ops = &clksrc_ops_nodiv;
else if (!clksrc->reg_src.reg)
clksrc->clk.ops = &clksrc_ops_nosrc;
else
clksrc->clk.ops = &clksrc_ops;
}
/* setup the clocksource, but do not announce it
* as it may be re-set by the setup routines
* called after the rest of the clocks have been
* registered
*/
s3c_set_clksrc(clksrc, false);
ret = s3c24xx_register_clock(&clksrc->clk);
if (ret < 0) {
printk(KERN_ERR "%s: failed to register %s (%d)\n",
__func__, clksrc->clk.name, ret);
}
}
}
This diff is collapsed.
/* linux/arch/arm/plat-samsung/include/plat/clock-clksrc.h
*
* Parts taken from arch/arm/plat-s3c64xx/clock.c
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* Copyright 2009 Ben Dooks <ben-linux@fluff.org>
* Copyright 2009 Harald Welte
*
* 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.
*/
/**
* struct clksrc_sources - list of sources for a given clock
* @sources: array of pointers to clocks
* @nr_sources: The size of @sources
*/
struct clksrc_sources {
unsigned int nr_sources;
struct clk **sources;
};
/**
* struct clksrc_reg - register definition for clock control bits
* @reg: pointer to the register in virtual memory.
* @shift: the shift in bits to where the bitfield is.
* @size: the size in bits of the bitfield.
*
* This specifies the size and position of the bits we are interested
* in within the register specified by @reg.
*/
struct clksrc_reg {
void __iomem *reg;
unsigned short shift;
unsigned short size;
};
/**
* struct clksrc_clk - class of clock for newer style samsung devices.
* @clk: the standard clock representation
* @sources: the sources for this clock
* @reg_src: the register definition for selecting the clock's source
* @reg_div: the register definition for the clock's output divisor
*
* This clock implements the features required by the newer SoCs where
* the standard clock block provides an input mux and a post-mux divisor
* to provide the periperhal's clock.
*
* The array of @sources provides the mapping of mux position to the
* clock, and @reg_src shows the code where to modify to change the mux
* position. The @reg_div defines how to change the divider settings on
* the output.
*/
struct clksrc_clk {
struct clk clk;
struct clksrc_sources *sources;
struct clksrc_reg reg_src;
struct clksrc_reg reg_div;
};
/**
* s3c_set_clksrc() - setup the clock from the register settings
* @clk: The clock to setup.
* @announce: true to announce the setting to printk().
*
* Setup the clock from the current register settings, for when the
* kernel boots or if it is resuming from a possibly unknown state.
*/
extern void s3c_set_clksrc(struct clksrc_clk *clk, bool announce);
/**
* s3c_register_clksrc() register clocks from an array of clksrc clocks
* @srcs: The array of clocks to register
* @size: The size of the @srcs array.
*
* Initialise and register the array of clocks described by @srcs.
*/
extern void s3c_register_clksrc(struct clksrc_clk *srcs, int size);
/* linux/arch/arm/plat-s3c/include/plat/clock.h
*
* Copyright (c) 2004-2005 Simtec Electronics
* http://www.simtec.co.uk/products/SWLINUX/
* Written by Ben Dooks, <ben@simtec.co.uk>
*
* 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.
*/
#ifndef __ASM_PLAT_CLOCK_H
#define __ASM_PLAT_CLOCK_H __FILE__
#include <linux/spinlock.h>
#include <linux/clkdev.h>
struct clk;
/**
* struct clk_ops - standard clock operations
* @set_rate: set the clock rate, see clk_set_rate().
* @get_rate: get the clock rate, see clk_get_rate().
* @round_rate: round a given clock rate, see clk_round_rate().
* @set_parent: set the clock's parent, see clk_set_parent().
*
* Group the common clock implementations together so that we
* don't have to keep setting the same fields again. We leave
* enable in struct clk.
*
* Adding an extra layer of indirection into the process should
* not be a problem as it is unlikely these operations are going
* to need to be called quickly.
*/
struct clk_ops {
int (*set_rate)(struct clk *c, unsigned long rate);
unsigned long (*get_rate)(struct clk *c);
unsigned long (*round_rate)(struct clk *c, unsigned long rate);
int (*set_parent)(struct clk *c, struct clk *parent);
};
struct clk {
struct list_head list;
struct module *owner;
struct clk *parent;
const char *name;
const char *devname;
int id;
int usage;
unsigned long rate;
unsigned long ctrlbit;
struct clk_ops *ops;
int (*enable)(struct clk *, int enable);
struct clk_lookup lookup;
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
struct dentry *dent; /* For visible tree hierarchy */
#endif
};
/* other clocks which may be registered by board support */
extern struct clk s3c24xx_dclk0;
extern struct clk s3c24xx_dclk1;
extern struct clk s3c24xx_clkout0;
extern struct clk s3c24xx_clkout1;
extern struct clk s3c24xx_uclk;
extern struct clk clk_usb_bus;
/* core clock support */
extern struct clk clk_f;
extern struct clk clk_h;
extern struct clk clk_p;
extern struct clk clk_mpll;
extern struct clk clk_upll;
extern struct clk clk_epll;
extern struct clk clk_xtal;
extern struct clk clk_ext;
/* S3C2443/S3C2416 specific clocks */
extern struct clksrc_clk clk_epllref;
extern struct clksrc_clk clk_esysclk;
/* S3C24XX UART clocks */
extern struct clk s3c24xx_clk_uart0;
extern struct clk s3c24xx_clk_uart1;
extern struct clk s3c24xx_clk_uart2;
/* S3C64XX specific clocks */
extern struct clk clk_h2;
extern struct clk clk_27m;
extern struct clk clk_48m;
extern struct clk clk_xusbxti;
extern int clk_default_setrate(struct clk *clk, unsigned long rate);
extern struct clk_ops clk_ops_def_setrate;
/* exports for arch/arm/mach-s3c2410
*
* Please DO NOT use these outside of arch/arm/mach-s3c2410
*/
extern spinlock_t clocks_lock;
extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
extern int s3c24xx_register_clock(struct clk *clk);
extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks);
extern void s3c_register_clocks(struct clk *clk, int nr_clks);
extern void s3c_disable_clocks(struct clk *clkp, int nr_clks);
extern int s3c24xx_register_baseclocks(unsigned long xtal);
extern void s5p_register_clocks(unsigned long xtal_freq);
extern void s3c24xx_setup_clocks(unsigned long fclk,
unsigned long hclk,
unsigned long pclk);
extern void s3c2410_setup_clocks(void);
extern void s3c2412_setup_clocks(void);
extern void s3c244x_setup_clocks(void);
/* S3C2410 specific clock functions */
extern int s3c2410_baseclk_add(void);
/* S3C2443/S3C2416 specific clock functions */
typedef unsigned int (*pll_fn)(unsigned int reg, unsigned int base);
extern void s3c2443_common_setup_clocks(pll_fn get_mpll);
extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
unsigned int *divs, int nr_divs,
int divmask);
extern int s3c2443_clkcon_enable_h(struct clk *clk, int enable);
extern int s3c2443_clkcon_enable_p(struct clk *clk, int enable);
extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable);
/* S3C64XX specific functions and clocks */
extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable);
/* Global watchdog clock used by arch_wtd_reset() callback */
extern struct clk *s3c2410_wdtclk;
#endif /* __ASM_PLAT_CLOCK_H */
......@@ -140,7 +140,6 @@ struct s3c_cpufreq_config {
* any frequency changes. This is really only need by devices like the
* S3C2410 where there is no or limited divider between the PLL and the
* ARMCLK.
* @resume_clocks: Update the clocks on resume.
* @get_iotiming: Get the current IO timing data, mainly for use at start.
* @set_iotiming: Update the IO timings from the cached copies calculated
* from the @calc_iotiming entry when changing the frequency.
......@@ -169,8 +168,6 @@ struct s3c_cpufreq_info {
/* driver routines */
void (*resume_clocks)(void);
int (*get_iotiming)(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *timings);
......
/* linux/arch/arm/plat-samsung/include/plat/pll.h
*
* Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* Samsung PLL codes
*
* 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 <asm/div64.h>
#define S3C24XX_PLL_MDIV_MASK (0xFF)
#define S3C24XX_PLL_PDIV_MASK (0x1F)
#define S3C24XX_PLL_SDIV_MASK (0x3)
#define S3C24XX_PLL_MDIV_SHIFT (12)
#define S3C24XX_PLL_PDIV_SHIFT (4)
#define S3C24XX_PLL_SDIV_SHIFT (0)
static inline unsigned int s3c24xx_get_pll(unsigned int pllval,
unsigned int baseclk)
{
unsigned int mdiv, pdiv, sdiv;
uint64_t fvco;
mdiv = (pllval >> S3C24XX_PLL_MDIV_SHIFT) & S3C24XX_PLL_MDIV_MASK;
pdiv = (pllval >> S3C24XX_PLL_PDIV_SHIFT) & S3C24XX_PLL_PDIV_MASK;
sdiv = (pllval >> S3C24XX_PLL_SDIV_SHIFT) & S3C24XX_PLL_SDIV_MASK;
fvco = (uint64_t)baseclk * (mdiv + 8);
do_div(fvco, (pdiv + 2) << sdiv);
return (unsigned int)fvco;
}
#define S3C2416_PLL_MDIV_MASK (0x3FF)
#define S3C2416_PLL_PDIV_MASK (0x3F)
#define S3C2416_PLL_SDIV_MASK (0x7)
#define S3C2416_PLL_MDIV_SHIFT (14)
#define S3C2416_PLL_PDIV_SHIFT (5)
#define S3C2416_PLL_SDIV_SHIFT (0)
static inline unsigned int s3c2416_get_pll(unsigned int pllval,
unsigned int baseclk)
{
unsigned int mdiv, pdiv, sdiv;
uint64_t fvco;
mdiv = (pllval >> S3C2416_PLL_MDIV_SHIFT) & S3C2416_PLL_MDIV_MASK;
pdiv = (pllval >> S3C2416_PLL_PDIV_SHIFT) & S3C2416_PLL_PDIV_MASK;
sdiv = (pllval >> S3C2416_PLL_SDIV_SHIFT) & S3C2416_PLL_SDIV_MASK;
fvco = (uint64_t)baseclk * mdiv;
do_div(fvco, (pdiv << sdiv));
return (unsigned int)fvco;
}
#define S3C6400_PLL_MDIV_MASK (0x3FF)
#define S3C6400_PLL_PDIV_MASK (0x3F)
#define S3C6400_PLL_SDIV_MASK (0x7)
#define S3C6400_PLL_MDIV_SHIFT (16)
#define S3C6400_PLL_PDIV_SHIFT (8)
#define S3C6400_PLL_SDIV_SHIFT (0)
static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
u32 pllcon)
{
u32 mdiv, pdiv, sdiv;
u64 fvco = baseclk;
mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
fvco *= mdiv;
do_div(fvco, (pdiv << sdiv));
return (unsigned long)fvco;
}
#define PLL6553X_MDIV_MASK (0x7F)
#define PLL6553X_PDIV_MASK (0x1F)
#define PLL6553X_SDIV_MASK (0x3)
#define PLL6553X_KDIV_MASK (0xFFFF)
#define PLL6553X_MDIV_SHIFT (16)
#define PLL6553X_PDIV_SHIFT (8)
#define PLL6553X_SDIV_SHIFT (0)
static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
u32 pll_con0, u32 pll_con1)
{
unsigned long result;
u32 mdiv, pdiv, sdiv, kdiv;
u64 tmp;
mdiv = (pll_con0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
pdiv = (pll_con0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
sdiv = (pll_con0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
kdiv = pll_con1 & PLL6553X_KDIV_MASK;
/*
* We need to multiple baseclk by mdiv (the integer part) and kdiv
* which is in 2^16ths, so shift mdiv up (does not overflow) and
* add kdiv before multiplying. The use of tmp is to avoid any
* overflows before shifting bac down into result when multipling
* by the mdiv and kdiv pair.
*/
tmp = baseclk;
tmp *= (mdiv << 16) + kdiv;
do_div(tmp, (pdiv << sdiv));
result = tmp >> 16;
return result;
}
#define PLL35XX_MDIV_MASK (0x3FF)
#define PLL35XX_PDIV_MASK (0x3F)
#define PLL35XX_SDIV_MASK (0x7)
#define PLL35XX_MDIV_SHIFT (16)
#define PLL35XX_PDIV_SHIFT (8)
#define PLL35XX_SDIV_SHIFT (0)
static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
{
u32 mdiv, pdiv, sdiv;
u64 fvco = baseclk;
mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
fvco *= mdiv;
do_div(fvco, (pdiv << sdiv));
return (unsigned long)fvco;
}
#define PLL36XX_KDIV_MASK (0xFFFF)
#define PLL36XX_MDIV_MASK (0x1FF)
#define PLL36XX_PDIV_MASK (0x3F)
#define PLL36XX_SDIV_MASK (0x7)
#define PLL36XX_MDIV_SHIFT (16)
#define PLL36XX_PDIV_SHIFT (8)
#define PLL36XX_SDIV_SHIFT (0)
static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
u32 pll_con0, u32 pll_con1)
{
unsigned long result;
u32 mdiv, pdiv, sdiv, kdiv;
u64 tmp;
mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
kdiv = pll_con1 & PLL36XX_KDIV_MASK;
tmp = baseclk;
tmp *= (mdiv << 16) + kdiv;
do_div(tmp, (pdiv << sdiv));
result = tmp >> 16;
return result;
}
#define PLL45XX_MDIV_MASK (0x3FF)
#define PLL45XX_PDIV_MASK (0x3F)
#define PLL45XX_SDIV_MASK (0x7)
#define PLL45XX_MDIV_SHIFT (16)
#define PLL45XX_PDIV_SHIFT (8)
#define PLL45XX_SDIV_SHIFT (0)
enum pll45xx_type_t {
pll_4500,
pll_4502,
pll_4508
};
static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
enum pll45xx_type_t pll_type)
{
u32 mdiv, pdiv, sdiv;
u64 fvco = baseclk;
mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
if (pll_type == pll_4508)
sdiv = sdiv - 1;
fvco *= mdiv;
do_div(fvco, (pdiv << sdiv));
return (unsigned long)fvco;
}
/* CON0 bit-fields */
#define PLL46XX_MDIV_MASK (0x1FF)
#define PLL46XX_PDIV_MASK (0x3F)
#define PLL46XX_SDIV_MASK (0x7)
#define PLL46XX_LOCKED_SHIFT (29)
#define PLL46XX_MDIV_SHIFT (16)
#define PLL46XX_PDIV_SHIFT (8)
#define PLL46XX_SDIV_SHIFT (0)
/* CON1 bit-fields */
#define PLL46XX_MRR_MASK (0x1F)
#define PLL46XX_MFR_MASK (0x3F)
#define PLL46XX_KDIV_MASK (0xFFFF)
#define PLL4650C_KDIV_MASK (0xFFF)
#define PLL46XX_MRR_SHIFT (24)
#define PLL46XX_MFR_SHIFT (16)
#define PLL46XX_KDIV_SHIFT (0)
enum pll46xx_type_t {
pll_4600,
pll_4650,
pll_4650c,
};
static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
u32 pll_con0, u32 pll_con1,
enum pll46xx_type_t pll_type)
{
unsigned long result;
u32 mdiv, pdiv, sdiv, kdiv;
u64 tmp;
mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
kdiv = pll_con1 & PLL46XX_KDIV_MASK;
if (pll_type == pll_4650c)
kdiv = pll_con1 & PLL4650C_KDIV_MASK;
else
kdiv = pll_con1 & PLL46XX_KDIV_MASK;
tmp = baseclk;
if (pll_type == pll_4600) {
tmp *= (mdiv << 16) + kdiv;
do_div(tmp, (pdiv << sdiv));
result = tmp >> 16;
} else {
tmp *= (mdiv << 10) + kdiv;
do_div(tmp, (pdiv << sdiv));
result = tmp >> 10;
}
return result;
}
#define PLL90XX_MDIV_MASK (0xFF)
#define PLL90XX_PDIV_MASK (0x3F)
#define PLL90XX_SDIV_MASK (0x7)
#define PLL90XX_KDIV_MASK (0xffff)
#define PLL90XX_LOCKED_SHIFT (29)
#define PLL90XX_MDIV_SHIFT (16)
#define PLL90XX_PDIV_SHIFT (8)
#define PLL90XX_SDIV_SHIFT (0)
#define PLL90XX_KDIV_SHIFT (0)
static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
u32 pll_con, u32 pll_conk)
{
unsigned long result;
u32 mdiv, pdiv, sdiv, kdiv;
u64 tmp;
mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
kdiv = pll_conk & PLL90XX_KDIV_MASK;
/*
* We need to multiple baseclk by mdiv (the integer part) and kdiv
* which is in 2^16ths, so shift mdiv up (does not overflow) and
* add kdiv before multiplying. The use of tmp is to avoid any
* overflows before shifting bac down into result when multipling
* by the mdiv and kdiv pair.
*/
tmp = baseclk;
tmp *= (mdiv << 16) + kdiv;
do_div(tmp, (pdiv << sdiv));
result = tmp >> 16;
return result;
}
#define PLL65XX_MDIV_MASK (0x3FF)
#define PLL65XX_PDIV_MASK (0x3F)
#define PLL65XX_SDIV_MASK (0x7)
#define PLL65XX_MDIV_SHIFT (16)
#define PLL65XX_PDIV_SHIFT (8)
#define PLL65XX_SDIV_SHIFT (0)
static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
{
u32 mdiv, pdiv, sdiv;
u64 fvco = baseclk;
mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
fvco *= mdiv;
do_div(fvco, (pdiv << sdiv));
return (unsigned long)fvco;
}
/* linux/arch/arm/plat-samsung/include/plat/s5p-clock.h
*
* Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Header file for s5p clock support
*
* 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.
*/
#ifndef __ASM_PLAT_S5P_CLOCK_H
#define __ASM_PLAT_S5P_CLOCK_H __FILE__
#include <linux/clk.h>
#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
#define clk_fin_apll clk_ext_xtal_mux
#define clk_fin_bpll clk_ext_xtal_mux
#define clk_fin_cpll clk_ext_xtal_mux
#define clk_fin_mpll clk_ext_xtal_mux
#define clk_fin_epll clk_ext_xtal_mux
#define clk_fin_dpll clk_ext_xtal_mux
#define clk_fin_vpll clk_ext_xtal_mux
#define clk_fin_hpll clk_ext_xtal_mux
extern struct clk clk_ext_xtal_mux;
extern struct clk clk_xusbxti;
extern struct clk clk_48m;
extern struct clk s5p_clk_27m;
extern struct clk clk_fout_apll;
extern struct clk clk_fout_bpll;
extern struct clk clk_fout_bpll_div2;
extern struct clk clk_fout_cpll;
extern struct clk clk_fout_mpll;
extern struct clk clk_fout_mpll_div2;
extern struct clk clk_fout_epll;
extern struct clk clk_fout_dpll;
extern struct clk clk_fout_vpll;
extern struct clk clk_arm;
extern struct clk clk_vpll;
extern struct clksrc_sources clk_src_apll;
extern struct clksrc_sources clk_src_bpll;
extern struct clksrc_sources clk_src_bpll_fout;
extern struct clksrc_sources clk_src_cpll;
extern struct clksrc_sources clk_src_mpll;
extern struct clksrc_sources clk_src_mpll_fout;
extern struct clksrc_sources clk_src_epll;
extern struct clksrc_sources clk_src_dpll;
extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
/* Common EPLL operations for S5P platform */
extern int s5p_epll_enable(struct clk *clk, int enable);
extern unsigned long s5p_epll_get_rate(struct clk *clk);
/* SPDIF clk operations common for S5PV210/C110 and Exynos4 */
extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate);
extern unsigned long s5p_spdif_get_rate(struct clk *clk);
extern struct clk_ops s5p_sclk_spdif_ops;
#endif /* __ASM_PLAT_S5P_CLOCK_H */
......@@ -30,7 +30,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/clock.h>
static struct cpu_table *cpu;
......
/*
* Copyright 2009 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S5P - 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 version 2 as
* published by the Free Software Foundation.
*/
#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/clk.h>
#include <linux/device.h>
#include <linux/io.h>
#include <asm/div64.h>
#include <mach/regs-clock.h>
#include <plat/clock.h>
#include <plat/clock-clksrc.h>
#include <plat/s5p-clock.h>
/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
* clk_ext_xtal_mux.
*/
struct clk clk_ext_xtal_mux = {
.name = "ext_xtal",
.id = -1,
};
struct clk clk_xusbxti = {
.name = "xusbxti",
.id = -1,
.rate = 24000000,
};
struct clk s5p_clk_27m = {
.name = "clk_27m",
.id = -1,
.rate = 27000000,
};
/* 48MHz USB Phy clock output */
struct clk clk_48m = {
.name = "clk_48m",
.id = -1,
.rate = 48000000,
};
/* APLL clock output
* No need .ctrlbit, this is always on
*/
struct clk clk_fout_apll = {
.name = "fout_apll",
.id = -1,
};
/* BPLL clock output */
struct clk clk_fout_bpll = {
.name = "fout_bpll",
.id = -1,
};
struct clk clk_fout_bpll_div2 = {
.name = "fout_bpll_div2",
.id = -1,
};
/* CPLL clock output */
struct clk clk_fout_cpll = {
.name = "fout_cpll",
.id = -1,
};
/* MPLL clock output
* No need .ctrlbit, this is always on
*/
struct clk clk_fout_mpll = {
.name = "fout_mpll",
.id = -1,
};
struct clk clk_fout_mpll_div2 = {
.name = "fout_mpll_div2",
.id = -1,
};
/* EPLL clock output */
struct clk clk_fout_epll = {
.name = "fout_epll",
.id = -1,
.ctrlbit = (1 << 31),
};
/* DPLL clock output */
struct clk clk_fout_dpll = {
.name = "fout_dpll",
.id = -1,
.ctrlbit = (1 << 31),
};
/* VPLL clock output */
struct clk clk_fout_vpll = {
.name = "fout_vpll",
.id = -1,
.ctrlbit = (1 << 31),
};
/* Possible clock sources for APLL Mux */
static struct clk *clk_src_apll_list[] = {
[0] = &clk_fin_apll,
[1] = &clk_fout_apll,
};
struct clksrc_sources clk_src_apll = {
.sources = clk_src_apll_list,
.nr_sources = ARRAY_SIZE(clk_src_apll_list),
};
/* Possible clock sources for BPLL Mux */
static struct clk *clk_src_bpll_list[] = {
[0] = &clk_fin_bpll,
[1] = &clk_fout_bpll,
};
struct clksrc_sources clk_src_bpll = {
.sources = clk_src_bpll_list,
.nr_sources = ARRAY_SIZE(clk_src_bpll_list),
};
static struct clk *clk_src_bpll_fout_list[] = {
[0] = &clk_fout_bpll_div2,
[1] = &clk_fout_bpll,
};
struct clksrc_sources clk_src_bpll_fout = {
.sources = clk_src_bpll_fout_list,
.nr_sources = ARRAY_SIZE(clk_src_bpll_fout_list),
};
/* Possible clock sources for CPLL Mux */
static struct clk *clk_src_cpll_list[] = {
[0] = &clk_fin_cpll,
[1] = &clk_fout_cpll,
};
struct clksrc_sources clk_src_cpll = {
.sources = clk_src_cpll_list,
.nr_sources = ARRAY_SIZE(clk_src_cpll_list),
};
/* Possible clock sources for MPLL Mux */
static struct clk *clk_src_mpll_list[] = {
[0] = &clk_fin_mpll,
[1] = &clk_fout_mpll,
};
struct clksrc_sources clk_src_mpll = {
.sources = clk_src_mpll_list,
.nr_sources = ARRAY_SIZE(clk_src_mpll_list),
};
static struct clk *clk_src_mpll_fout_list[] = {
[0] = &clk_fout_mpll_div2,
[1] = &clk_fout_mpll,
};
struct clksrc_sources clk_src_mpll_fout = {
.sources = clk_src_mpll_fout_list,
.nr_sources = ARRAY_SIZE(clk_src_mpll_fout_list),
};
/* Possible clock sources for EPLL Mux */
static struct clk *clk_src_epll_list[] = {
[0] = &clk_fin_epll,
[1] = &clk_fout_epll,
};
struct clksrc_sources clk_src_epll = {
.sources = clk_src_epll_list,
.nr_sources = ARRAY_SIZE(clk_src_epll_list),
};
/* Possible clock sources for DPLL Mux */
static struct clk *clk_src_dpll_list[] = {
[0] = &clk_fin_dpll,
[1] = &clk_fout_dpll,
};
struct clksrc_sources clk_src_dpll = {
.sources = clk_src_dpll_list,
.nr_sources = ARRAY_SIZE(clk_src_dpll_list),
};
struct clk clk_vpll = {
.name = "vpll",
.id = -1,
};
int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable)
{
unsigned int ctrlbit = clk->ctrlbit;
u32 con;
con = __raw_readl(reg);
con = enable ? (con | ctrlbit) : (con & ~ctrlbit);
__raw_writel(con, reg);
return 0;
}
int s5p_epll_enable(struct clk *clk, int enable)
{
unsigned int ctrlbit = clk->ctrlbit;
unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
if (enable)
__raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
else
__raw_writel(epll_con, S5P_EPLL_CON);
return 0;
}
unsigned long s5p_epll_get_rate(struct clk *clk)
{
return clk->rate;
}
int s5p_spdif_set_rate(struct clk *clk, unsigned long rate)
{
struct clk *pclk;
int ret;
pclk = clk_get_parent(clk);
if (IS_ERR(pclk))
return -EINVAL;
ret = pclk->ops->set_rate(pclk, rate);
clk_put(pclk);
return ret;
}
unsigned long s5p_spdif_get_rate(struct clk *clk)
{
struct clk *pclk;
int rate;
pclk = clk_get_parent(clk);
if (IS_ERR(pclk))
return -EINVAL;
rate = pclk->ops->get_rate(pclk);
clk_put(pclk);
return rate;
}
struct clk_ops s5p_sclk_spdif_ops = {
.set_rate = s5p_spdif_set_rate,
.get_rate = s5p_spdif_get_rate,
};
static struct clk *s5p_clks[] __initdata = {
&clk_ext_xtal_mux,
&clk_48m,
&s5p_clk_27m,
&clk_fout_apll,
&clk_fout_mpll,
&clk_fout_epll,
&clk_fout_dpll,
&clk_fout_vpll,
&clk_vpll,
&clk_xusbxti,
};
void __init s5p_register_clocks(unsigned long xtal_freq)
{
int ret;
clk_ext_xtal_mux.rate = xtal_freq;
ret = s3c24xx_register_clocks(s5p_clks, ARRAY_SIZE(s5p_clks));
if (ret > 0)
printk(KERN_ERR "Failed to register s5p clocks\n");
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment