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: Tomasz Figa <t.figa@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
This commit is contained in:
Родитель
f73d4cb681
Коммит
32726d2d55
|
@ -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
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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
|
||||
|
|
|
@ -1,212 +0,0 @@
|
|||
/* 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,539 +0,0 @@
|
|||
/* linux/arch/arm/plat-s3c24xx/clock.c
|
||||
*
|
||||
* Copyright 2004-2005 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* S3C24XX Core clock control support
|
||||
*
|
||||
* Based on, and code from linux/arch/arm/mach-versatile/clock.c
|
||||
**
|
||||
** Copyright (C) 2004 ARM Limited.
|
||||
** Written by Deep Blue Solutions Limited.
|
||||
*
|
||||
*
|
||||
* 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/platform_device.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/io.h>
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
#include <linux/debugfs.h>
|
||||
#endif
|
||||
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <plat/cpu-freq.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_s3c.h> /* for s3c24xx_uart_devs */
|
||||
|
||||
/* clock information */
|
||||
|
||||
static LIST_HEAD(clocks);
|
||||
|
||||
/* We originally used an mutex here, but some contexts (see resume)
|
||||
* are calling functions such as clk_set_parent() with IRQs disabled
|
||||
* causing an BUG to be triggered.
|
||||
*/
|
||||
DEFINE_SPINLOCK(clocks_lock);
|
||||
|
||||
/* Global watchdog clock used by arch_wtd_reset() callback */
|
||||
struct clk *s3c2410_wdtclk;
|
||||
static int __init s3c_wdt_reset_init(void)
|
||||
{
|
||||
s3c2410_wdtclk = clk_get(NULL, "watchdog");
|
||||
if (IS_ERR(s3c2410_wdtclk))
|
||||
printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(s3c_wdt_reset_init);
|
||||
|
||||
/* enable and disable calls for use with the clk struct */
|
||||
|
||||
static int clk_null_enable(struct clk *clk, int enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (IS_ERR(clk) || clk == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
clk_enable(clk->parent);
|
||||
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
|
||||
if ((clk->usage++) == 0)
|
||||
(clk->enable)(clk, 1);
|
||||
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (IS_ERR(clk) || clk == NULL)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
|
||||
if ((--clk->usage) == 0)
|
||||
(clk->enable)(clk, 0);
|
||||
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
clk_disable(clk->parent);
|
||||
}
|
||||
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(clk))
|
||||
return 0;
|
||||
|
||||
if (clk->rate != 0)
|
||||
return clk->rate;
|
||||
|
||||
if (clk->ops != NULL && clk->ops->get_rate != NULL)
|
||||
return (clk->ops->get_rate)(clk);
|
||||
|
||||
if (clk->parent != NULL)
|
||||
return clk_get_rate(clk->parent);
|
||||
|
||||
return clk->rate;
|
||||
}
|
||||
|
||||
long clk_round_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
if (!IS_ERR_OR_NULL(clk) && clk->ops && clk->ops->round_rate)
|
||||
return (clk->ops->round_rate)(clk, rate);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (IS_ERR_OR_NULL(clk))
|
||||
return -EINVAL;
|
||||
|
||||
/* We do not default just do a clk->rate = rate as
|
||||
* the clock may have been made this way by choice.
|
||||
*/
|
||||
|
||||
WARN_ON(clk->ops == NULL);
|
||||
WARN_ON(clk->ops && clk->ops->set_rate == NULL);
|
||||
|
||||
if (clk->ops == NULL || clk->ops->set_rate == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
ret = (clk->ops->set_rate)(clk, rate);
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct clk *clk_get_parent(struct clk *clk)
|
||||
{
|
||||
return clk->parent;
|
||||
}
|
||||
|
||||
int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (IS_ERR_OR_NULL(clk) || IS_ERR_OR_NULL(parent))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
|
||||
if (clk->ops && clk->ops->set_parent)
|
||||
ret = (clk->ops->set_parent)(clk, parent);
|
||||
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(clk_enable);
|
||||
EXPORT_SYMBOL(clk_disable);
|
||||
EXPORT_SYMBOL(clk_get_rate);
|
||||
EXPORT_SYMBOL(clk_round_rate);
|
||||
EXPORT_SYMBOL(clk_set_rate);
|
||||
EXPORT_SYMBOL(clk_get_parent);
|
||||
EXPORT_SYMBOL(clk_set_parent);
|
||||
|
||||
/* base clocks */
|
||||
|
||||
int clk_default_setrate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
clk->rate = rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct clk_ops clk_ops_def_setrate = {
|
||||
.set_rate = clk_default_setrate,
|
||||
};
|
||||
|
||||
struct clk clk_xtal = {
|
||||
.name = "xtal",
|
||||
.rate = 0,
|
||||
.parent = NULL,
|
||||
.ctrlbit = 0,
|
||||
};
|
||||
|
||||
struct clk clk_ext = {
|
||||
.name = "ext",
|
||||
};
|
||||
|
||||
struct clk clk_epll = {
|
||||
.name = "epll",
|
||||
};
|
||||
|
||||
struct clk clk_mpll = {
|
||||
.name = "mpll",
|
||||
.ops = &clk_ops_def_setrate,
|
||||
};
|
||||
|
||||
struct clk clk_upll = {
|
||||
.name = "upll",
|
||||
.parent = NULL,
|
||||
.ctrlbit = 0,
|
||||
};
|
||||
|
||||
struct clk clk_f = {
|
||||
.name = "fclk",
|
||||
.rate = 0,
|
||||
.parent = &clk_mpll,
|
||||
.ctrlbit = 0,
|
||||
};
|
||||
|
||||
struct clk clk_h = {
|
||||
.name = "hclk",
|
||||
.rate = 0,
|
||||
.parent = NULL,
|
||||
.ctrlbit = 0,
|
||||
.ops = &clk_ops_def_setrate,
|
||||
};
|
||||
|
||||
struct clk clk_p = {
|
||||
.name = "pclk",
|
||||
.rate = 0,
|
||||
.parent = NULL,
|
||||
.ctrlbit = 0,
|
||||
.ops = &clk_ops_def_setrate,
|
||||
};
|
||||
|
||||
struct clk clk_usb_bus = {
|
||||
.name = "usb-bus",
|
||||
.rate = 0,
|
||||
.parent = &clk_upll,
|
||||
};
|
||||
|
||||
|
||||
struct clk s3c24xx_uclk = {
|
||||
.name = "uclk",
|
||||
};
|
||||
|
||||
/* initialise the clock system */
|
||||
|
||||
/**
|
||||
* s3c24xx_register_clock() - register a clock
|
||||
* @clk: The clock to register
|
||||
*
|
||||
* Add the specified clock to the list of clocks known by the system.
|
||||
*/
|
||||
int s3c24xx_register_clock(struct clk *clk)
|
||||
{
|
||||
if (clk->enable == NULL)
|
||||
clk->enable = clk_null_enable;
|
||||
|
||||
/* fill up the clk_lookup structure and register it*/
|
||||
clk->lookup.dev_id = clk->devname;
|
||||
clk->lookup.con_id = clk->name;
|
||||
clk->lookup.clk = clk;
|
||||
clkdev_add(&clk->lookup);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* s3c24xx_register_clocks() - register an array of clock pointers
|
||||
* @clks: Pointer to an array of struct clk pointers
|
||||
* @nr_clks: The number of clocks in the @clks array.
|
||||
*
|
||||
* Call s3c24xx_register_clock() for all the clock pointers contained
|
||||
* in the @clks list. Returns the number of failures.
|
||||
*/
|
||||
int s3c24xx_register_clocks(struct clk **clks, int nr_clks)
|
||||
{
|
||||
int fails = 0;
|
||||
|
||||
for (; nr_clks > 0; nr_clks--, clks++) {
|
||||
if (s3c24xx_register_clock(*clks) < 0) {
|
||||
struct clk *clk = *clks;
|
||||
printk(KERN_ERR "%s: failed to register %p: %s\n",
|
||||
__func__, clk, clk->name);
|
||||
fails++;
|
||||
}
|
||||
}
|
||||
|
||||
return fails;
|
||||
}
|
||||
|
||||
/**
|
||||
* s3c_register_clocks() - register an array of clocks
|
||||
* @clkp: Pointer to the first clock in the array.
|
||||
* @nr_clks: Number of clocks to register.
|
||||
*
|
||||
* Call s3c24xx_register_clock() on the @clkp array given, printing an
|
||||
* error if it fails to register the clock (unlikely).
|
||||
*/
|
||||
void __init s3c_register_clocks(struct clk *clkp, int nr_clks)
|
||||
{
|
||||
int ret;
|
||||
|
||||
for (; nr_clks > 0; nr_clks--, clkp++) {
|
||||
ret = s3c24xx_register_clock(clkp);
|
||||
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "Failed to register clock %s (%d)\n",
|
||||
clkp->name, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* s3c_disable_clocks() - disable an array of clocks
|
||||
* @clkp: Pointer to the first clock in the array.
|
||||
* @nr_clks: Number of clocks to register.
|
||||
*
|
||||
* for internal use only at initialisation time. disable the clocks in the
|
||||
* @clkp array.
|
||||
*/
|
||||
|
||||
void __init s3c_disable_clocks(struct clk *clkp, int nr_clks)
|
||||
{
|
||||
for (; nr_clks > 0; nr_clks--, clkp++)
|
||||
(clkp->enable)(clkp, 0);
|
||||
}
|
||||
|
||||
/* initialise all the clocks */
|
||||
|
||||
int __init s3c24xx_register_baseclocks(unsigned long xtal)
|
||||
{
|
||||
printk(KERN_INFO "S3C24XX Clocks, Copyright 2004 Simtec Electronics\n");
|
||||
|
||||
clk_xtal.rate = xtal;
|
||||
|
||||
/* register our clocks */
|
||||
|
||||
if (s3c24xx_register_clock(&clk_xtal) < 0)
|
||||
printk(KERN_ERR "failed to register master xtal\n");
|
||||
|
||||
if (s3c24xx_register_clock(&clk_mpll) < 0)
|
||||
printk(KERN_ERR "failed to register mpll clock\n");
|
||||
|
||||
if (s3c24xx_register_clock(&clk_upll) < 0)
|
||||
printk(KERN_ERR "failed to register upll clock\n");
|
||||
|
||||
if (s3c24xx_register_clock(&clk_f) < 0)
|
||||
printk(KERN_ERR "failed to register cpu fclk\n");
|
||||
|
||||
if (s3c24xx_register_clock(&clk_h) < 0)
|
||||
printk(KERN_ERR "failed to register cpu hclk\n");
|
||||
|
||||
if (s3c24xx_register_clock(&clk_p) < 0)
|
||||
printk(KERN_ERR "failed to register cpu pclk\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
|
||||
/* debugfs support to trace clock tree hierarchy and attributes */
|
||||
|
||||
static struct dentry *clk_debugfs_root;
|
||||
|
||||
static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
|
||||
{
|
||||
struct clk *child;
|
||||
const char *state;
|
||||
char buf[255] = { 0 };
|
||||
int n = 0;
|
||||
|
||||
if (c->name)
|
||||
n = snprintf(buf, sizeof(buf) - 1, "%s", c->name);
|
||||
|
||||
if (c->devname)
|
||||
n += snprintf(buf + n, sizeof(buf) - 1 - n, ":%s", c->devname);
|
||||
|
||||
state = (c->usage > 0) ? "on" : "off";
|
||||
|
||||
seq_printf(s, "%*s%-*s %-6s %-3d %-10lu\n",
|
||||
level * 3 + 1, "",
|
||||
50 - level * 3, buf,
|
||||
state, c->usage, clk_get_rate(c));
|
||||
|
||||
list_for_each_entry(child, &clocks, list) {
|
||||
if (child->parent != c)
|
||||
continue;
|
||||
|
||||
clock_tree_show_one(s, child, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int clock_tree_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct clk *c;
|
||||
unsigned long flags;
|
||||
|
||||
seq_printf(s, " clock state ref rate\n");
|
||||
seq_printf(s, "----------------------------------------------------\n");
|
||||
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
|
||||
list_for_each_entry(c, &clocks, list)
|
||||
if (c->parent == NULL)
|
||||
clock_tree_show_one(s, c, 0);
|
||||
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clock_tree_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, clock_tree_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations clock_tree_fops = {
|
||||
.open = clock_tree_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int clock_rate_show(void *data, u64 *val)
|
||||
{
|
||||
struct clk *c = data;
|
||||
*val = clk_get_rate(c);
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_rate_show, NULL, "%llu\n");
|
||||
|
||||
static int clk_debugfs_register_one(struct clk *c)
|
||||
{
|
||||
int err;
|
||||
struct dentry *d;
|
||||
struct clk *pa = c->parent;
|
||||
char s[255];
|
||||
char *p = s;
|
||||
|
||||
p += sprintf(p, "%s", c->devname);
|
||||
|
||||
d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
c->dent = d;
|
||||
|
||||
d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usage);
|
||||
if (!d) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
d = debugfs_create_file("rate", S_IRUGO, c->dent, c, &clock_rate_fops);
|
||||
if (!d) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
debugfs_remove_recursive(c->dent);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int clk_debugfs_register(struct clk *c)
|
||||
{
|
||||
int err;
|
||||
struct clk *pa = c->parent;
|
||||
|
||||
if (pa && !pa->dent) {
|
||||
err = clk_debugfs_register(pa);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!c->dent) {
|
||||
err = clk_debugfs_register_one(c);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init clk_debugfs_init(void)
|
||||
{
|
||||
struct clk *c;
|
||||
struct dentry *d;
|
||||
int err = -ENOMEM;
|
||||
|
||||
d = debugfs_create_dir("clock", NULL);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
clk_debugfs_root = d;
|
||||
|
||||
d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
|
||||
&clock_tree_fops);
|
||||
if (!d)
|
||||
goto err_out;
|
||||
|
||||
list_for_each_entry(c, &clocks, list) {
|
||||
err = clk_debugfs_register(c);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
debugfs_remove_recursive(clk_debugfs_root);
|
||||
return err;
|
||||
}
|
||||
late_initcall(clk_debugfs_init);
|
||||
|
||||
#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
|
|
@ -1,83 +0,0 @@
|
|||
/* 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);
|
|
@ -1,152 +0,0 @@
|
|||
/* 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);
|
||||
|
||||
|
|
|
@ -1,323 +0,0 @@
|
|||
/* 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;
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/* 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;
|
||||
|
||||
|
|
|
@ -1,294 +0,0 @@
|
|||
/*
|
||||
* 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");
|
||||
}
|
Загрузка…
Ссылка в новой задаче