提交 32726d2d 编写于 作者: T Tomasz Figa 提交者: 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: NTomasz Figa <t.figa@samsung.com>
Signed-off-by: NKukjin Kim <kgene.kim@samsung.com>
上级 f73d4cb6
...@@ -765,6 +765,7 @@ config ARCH_S5PV210 ...@@ -765,6 +765,7 @@ config ARCH_S5PV210
select ATAGS select ATAGS
select CLKDEV_LOOKUP select CLKDEV_LOOKUP
select CLKSRC_SAMSUNG_PWM select CLKSRC_SAMSUNG_PWM
select COMMON_CLK_SAMSUNG
select CPU_V7 select CPU_V7
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select GPIO_SAMSUNG select GPIO_SAMSUNG
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include <asm/suspend.h> #include <asm/suspend.h>
#include <plat/pm-common.h> #include <plat/pm-common.h>
#include <plat/pll.h>
#include <plat/regs-srom.h> #include <plat/regs-srom.h>
#include <mach/map.h> #include <mach/map.h>
......
...@@ -49,9 +49,7 @@ ...@@ -49,9 +49,7 @@
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/clock.h>
#include <plat/cpu-freq.h> #include <plat/cpu-freq.h>
#include <plat/pll.h>
#include <plat/pwm-core.h> #include <plat/pwm-core.h>
#include <plat/watchdog-reset.h> #include <plat/watchdog-reset.h>
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/cpu-freq-core.h> #include <plat/cpu-freq-core.h>
#include <plat/clock.h>
#include <mach/s3c2412.h> #include <mach/s3c2412.h>
......
...@@ -60,7 +60,6 @@ ...@@ -60,7 +60,6 @@
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/gpio-cfg.h> #include <plat/gpio-cfg.h>
#include <plat/pll.h>
#include <plat/pm.h> #include <plat/pm.h>
#include <plat/samsung-time.h> #include <plat/samsung-time.h>
...@@ -73,6 +72,10 @@ ...@@ -73,6 +72,10 @@
#define H1940_LATCH_BIT(x) (1 << ((x) + 16 - S3C_GPIO_END)) #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 = { static struct map_desc h1940_iodesc[] __initdata = {
[0] = { [0] = {
.virtual = (unsigned long)H1940_LATCH, .virtual = (unsigned long)H1940_LATCH,
......
...@@ -48,7 +48,6 @@ ...@@ -48,7 +48,6 @@
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <plat/gpio-cfg.h> #include <plat/gpio-cfg.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/pm.h> #include <plat/pm.h>
......
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#include <mach/gpio-samsung.h> #include <mach/gpio-samsung.h>
#include <mach/fb.h> #include <mach/fb.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/samsung-time.h> #include <plat/samsung-time.h>
......
...@@ -44,7 +44,6 @@ ...@@ -44,7 +44,6 @@
#include <linux/platform_data/i2c-s3c2410.h> #include <linux/platform_data/i2c-s3c2410.h>
#include <plat/gpio-cfg.h> #include <plat/gpio-cfg.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <linux/platform_data/mtd-nand-s3c2410.h> #include <linux/platform_data/mtd-nand-s3c2410.h>
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include <mach/fb.h> #include <mach/fb.h>
#include <linux/platform_data/i2c-s3c2410.h> #include <linux/platform_data/i2c-s3c2410.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/samsung-time.h> #include <plat/samsung-time.h>
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#include <linux/platform_data/i2c-s3c2410.h> #include <linux/platform_data/i2c-s3c2410.h>
#include <linux/platform_data/mtd-nand-s3c2410.h> #include <linux/platform_data/mtd-nand-s3c2410.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/samsung-time.h> #include <plat/samsung-time.h>
......
...@@ -41,8 +41,6 @@ ...@@ -41,8 +41,6 @@
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/clock.h>
#include <plat/pll.h>
#include <plat/pm.h> #include <plat/pm.h>
#include <plat/watchdog-reset.h> #include <plat/watchdog-reset.h>
...@@ -83,10 +81,6 @@ void __init s3c2410_map_io(void) ...@@ -83,10 +81,6 @@ void __init s3c2410_map_io(void)
iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
} }
void __init_or_cpufreq s3c2410_setup_clocks(void)
{
}
struct bus_type s3c2410_subsys = { struct bus_type s3c2410_subsys = {
.name = "s3c2410-core", .name = "s3c2410-core",
.dev_name = "s3c2410-core", .dev_name = "s3c2410-core",
......
...@@ -37,12 +37,10 @@ ...@@ -37,12 +37,10 @@
#include <mach/regs-clock.h> #include <mach/regs-clock.h>
#include <mach/regs-gpio.h> #include <mach/regs-gpio.h>
#include <plat/clock.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/cpu-freq.h> #include <plat/cpu-freq.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/nand-core.h> #include <plat/nand-core.h>
#include <plat/pll.h>
#include <plat/pm.h> #include <plat/pm.h>
#include <plat/regs-spi.h> #include <plat/regs-spi.h>
...@@ -171,10 +169,6 @@ void __init s3c2412_map_io(void) ...@@ -171,10 +169,6 @@ void __init s3c2412_map_io(void)
iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc)); 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 /* 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 * 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) * drivers even try to use it (even if not on an s3c2412 based system)
......
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#include <mach/regs-clock.h> #include <mach/regs-clock.h>
#include <plat/clock.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/pm.h> #include <plat/pm.h>
......
...@@ -38,11 +38,9 @@ ...@@ -38,11 +38,9 @@
#include <mach/regs-clock.h> #include <mach/regs-clock.h>
#include <mach/regs-gpio.h> #include <mach/regs-gpio.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/pm.h> #include <plat/pm.h>
#include <plat/pll.h>
#include <plat/nand-core.h> #include <plat/nand-core.h>
#include <plat/watchdog-reset.h> #include <plat/watchdog-reset.h>
...@@ -78,10 +76,6 @@ void __init s3c244x_map_io(void) ...@@ -78,10 +76,6 @@ void __init s3c244x_map_io(void)
s3c2410_device_dclk.name = "s3c2440-dclk"; 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 */ /* Since the S3C2442 and S3C2440 share items, put both subsystems here */
struct bus_type s3c2440_subsys = { struct bus_type s3c2440_subsys = {
......
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
#include <linux/platform_data/i2c-s3c2410.h> #include <linux/platform_data/i2c-s3c2410.h>
#include <plat/fb.h> #include <plat/fb.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <mach/regs-gpio.h> #include <mach/regs-gpio.h>
......
...@@ -58,7 +58,6 @@ ...@@ -58,7 +58,6 @@
#include <linux/platform_data/spi-s3c64xx.h> #include <linux/platform_data/spi-s3c64xx.h>
#include <plat/keypad.h> #include <plat/keypad.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/adc.h> #include <plat/adc.h>
......
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
#include <plat/fb.h> #include <plat/fb.h>
#include <linux/platform_data/mtd-nand-s3c2410.h> #include <linux/platform_data/mtd-nand-s3c2410.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/samsung-time.h> #include <plat/samsung-time.h>
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include <linux/platform_data/i2c-s3c2410.h> #include <linux/platform_data/i2c-s3c2410.h>
#include <plat/fb.h> #include <plat/fb.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/samsung-time.h> #include <plat/samsung-time.h>
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include <mach/regs-gpio.h> #include <mach/regs-gpio.h>
#include <mach/gpio-samsung.h> #include <mach/gpio-samsung.h>
#include <plat/clock.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <linux/platform_data/i2c-s3c2410.h> #include <linux/platform_data/i2c-s3c2410.h>
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/map.h> #include <mach/map.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <linux/platform_data/i2c-s3c2410.h> #include <linux/platform_data/i2c-s3c2410.h>
......
...@@ -63,7 +63,6 @@ ...@@ -63,7 +63,6 @@
#include <plat/fb.h> #include <plat/fb.h>
#include <plat/gpio-cfg.h> #include <plat/gpio-cfg.h>
#include <plat/clock.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/adc.h> #include <plat/adc.h>
......
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/clock.h>
#include <plat/sdhci.h> #include <plat/sdhci.h>
#include <plat/iic-core.h> #include <plat/iic-core.h>
#include <plat/onenand-core.h> #include <plat/onenand-core.h>
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/clock.h>
#include <plat/sdhci.h> #include <plat/sdhci.h>
#include <plat/ata-core.h> #include <plat/ata-core.h>
#include <plat/adc-core.h> #include <plat/adc-core.h>
......
...@@ -13,7 +13,6 @@ config CPU_S5PV210 ...@@ -13,7 +13,6 @@ config CPU_S5PV210
bool bool
select ARM_AMBA select ARM_AMBA
select PL330_DMA if DMADEVICES select PL330_DMA if DMADEVICES
select S5P_CLOCK if !COMMON_CLK
select S5P_EXT_INT select S5P_EXT_INT
select S5P_PM if PM select S5P_PM if PM
select S5P_SLEEP if PM select S5P_SLEEP if PM
...@@ -71,14 +70,6 @@ config S5PV210_SETUP_USB_PHY ...@@ -71,14 +70,6 @@ config S5PV210_SETUP_USB_PHY
help help
Common setup code for USB PHY controller 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" menu "S5PC110 Machines"
config MACH_AQUILA config MACH_AQUILA
......
...@@ -13,7 +13,6 @@ obj- := ...@@ -13,7 +13,6 @@ obj- :=
# Core # Core
obj-y += common.o obj-y += common.o
obj-$(CONFIG_S5P_CLOCK) += clock.o
obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_PM) += pm.o
obj-y += dma.o obj-y += dma.o
......
此差异已折叠。
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/device.h> #include <linux/device.h>
#include <clocksource/samsung_pwm.h> #include <clocksource/samsung_pwm.h>
...@@ -37,12 +38,6 @@ ...@@ -37,12 +38,6 @@
#include <plat/cpu.h> #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/devs.h>
#include <plat/sdhci.h> #include <plat/sdhci.h>
#include <plat/adc-core.h> #include <plat/adc-core.h>
...@@ -239,16 +234,7 @@ void __init s5pv210_map_io(void) ...@@ -239,16 +234,7 @@ void __init s5pv210_map_io(void)
void __init s5pv210_init_clocks(int xtal) 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; xusbxti_f = xtal;
#endif
} }
void __init s5pv210_init_irq(void) void __init s5pv210_init_irq(void)
......
...@@ -14,14 +14,8 @@ ...@@ -14,14 +14,8 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#ifdef CONFIG_COMMON_CLK_S5PV210
void s5pv210_clk_init(unsigned long xxti_f, unsigned long xusbxti_f, void s5pv210_clk_init(unsigned long xxti_f, unsigned long xusbxti_f,
void __iomem *reg_base); 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_io(struct map_desc *mach_desc, int size);
void s5pv210_init_irq(void); void s5pv210_init_irq(void);
......
...@@ -46,7 +46,6 @@ ...@@ -46,7 +46,6 @@
#include <linux/platform_data/i2c-s3c2410.h> #include <linux/platform_data/i2c-s3c2410.h>
#include <plat/keypad.h> #include <plat/keypad.h>
#include <plat/sdhci.h> #include <plat/sdhci.h>
#include <plat/clock.h>
#include <plat/samsung-time.h> #include <plat/samsung-time.h>
#include <plat/mfc.h> #include <plat/mfc.h>
......
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
#include <plat/samsung-time.h> #include <plat/samsung-time.h>
#include <plat/backlight.h> #include <plat/backlight.h>
#include <plat/mfc.h> #include <plat/mfc.h>
#include <plat/clock.h>
#include "common.h" #include "common.h"
......
...@@ -26,55 +26,7 @@ ...@@ -26,55 +26,7 @@
#include <mach/regs-clock.h> #include <mach/regs-clock.h>
static struct sleep_save s5pv210_core_save[] = { 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 */ /* Clock ETC */
SAVE_ITEM(S5P_CLK_OUT),
SAVE_ITEM(S5P_MDNIE_SEL), SAVE_ITEM(S5P_MDNIE_SEL),
}; };
......
...@@ -23,7 +23,6 @@ config PLAT_S5P ...@@ -23,7 +23,6 @@ config PLAT_S5P
select PLAT_SAMSUNG select PLAT_SAMSUNG
select S3C_GPIO_TRACK select S3C_GPIO_TRACK
select S5P_GPIO_DRVSTR select S5P_GPIO_DRVSTR
select SAMSUNG_CLKSRC if !COMMON_CLK
help help
Base platform code for Samsung's S5P series SoC. Base platform code for Samsung's S5P series SoC.
...@@ -65,23 +64,6 @@ config SAMSUNG_ATAGS ...@@ -65,23 +64,6 @@ config SAMSUNG_ATAGS
if 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 # options for IRQ support
config S5P_IRQ config S5P_IRQ
......
...@@ -16,11 +16,6 @@ obj- := ...@@ -16,11 +16,6 @@ obj- :=
obj-y += init.o cpu.o 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_IRQ) += s5p-irq.o
obj-$(CONFIG_S5P_EXT_INT) += s5p-irq-eint.o obj-$(CONFIG_S5P_EXT_INT) += s5p-irq-eint.o
obj-$(CONFIG_S5P_GPIO_INT) += s5p-irq-gpioint.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);
}
}
}
/* 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) */
/* 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 { ...@@ -140,7 +140,6 @@ struct s3c_cpufreq_config {
* any frequency changes. This is really only need by devices like the * 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 * S3C2410 where there is no or limited divider between the PLL and the
* ARMCLK. * ARMCLK.
* @resume_clocks: Update the clocks on resume.
* @get_iotiming: Get the current IO timing data, mainly for use at start. * @get_iotiming: Get the current IO timing data, mainly for use at start.
* @set_iotiming: Update the IO timings from the cached copies calculated * @set_iotiming: Update the IO timings from the cached copies calculated
* from the @calc_iotiming entry when changing the frequency. * from the @calc_iotiming entry when changing the frequency.
...@@ -169,8 +168,6 @@ struct s3c_cpufreq_info { ...@@ -169,8 +168,6 @@ struct s3c_cpufreq_info {
/* driver routines */ /* driver routines */
void (*resume_clocks)(void);
int (*get_iotiming)(struct s3c_cpufreq_config *cfg, int (*get_iotiming)(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *timings); 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 @@ ...@@ -30,7 +30,6 @@
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/devs.h> #include <plat/devs.h>
#include <plat/clock.h>
static struct cpu_table *cpu; 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% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册