2010-09-01 15:35:30 +09:00
/* linux/arch/arm/mach-s5p64x0/clock-s5p6450.c
*
* Copyright ( c ) 2010 Samsung Electronics Co . , Ltd .
* http : //www.samsung.com
*
* S5P6450 - 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>
2011-12-21 16:26:03 -08:00
# include <linux/device.h>
2010-09-01 15:35:30 +09:00
# include <linux/io.h>
# include <mach/hardware.h>
# include <mach/map.h>
# include <mach/regs-clock.h>
# include <mach/s5p64x0-clock.h>
# include <plat/cpu-freq.h>
# include <plat/clock.h>
# include <plat/cpu.h>
# include <plat/pll.h>
# include <plat/s5p-clock.h>
# include <plat/clock-clksrc.h>
2011-12-22 23:28:28 +01:00
# include "common.h"
2010-09-01 15:35:30 +09:00
static struct clksrc_clk clk_mout_dpll = {
. clk = {
. name = " mout_dpll " ,
} ,
. sources = & clk_src_dpll ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 5 , . size = 1 } ,
} ;
static u32 epll_div [ ] [ 5 ] = {
{ 133000000 , 27307 , 55 , 2 , 2 } ,
{ 100000000 , 43691 , 41 , 2 , 2 } ,
{ 480000000 , 0 , 80 , 2 , 0 } ,
} ;
static int s5p6450_epll_set_rate ( struct clk * clk , unsigned long rate )
{
unsigned int epll_con , epll_con_k ;
unsigned int i ;
if ( clk - > rate = = rate ) /* Return if nothing changed */
return 0 ;
epll_con = __raw_readl ( S5P64X0_EPLL_CON ) ;
epll_con_k = __raw_readl ( S5P64X0_EPLL_CON_K ) ;
epll_con_k & = ~ ( PLL90XX_KDIV_MASK ) ;
epll_con & = ~ ( PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK ) ;
for ( i = 0 ; i < ARRAY_SIZE ( epll_div ) ; i + + ) {
if ( epll_div [ i ] [ 0 ] = = rate ) {
epll_con_k | = ( epll_div [ i ] [ 1 ] < < PLL90XX_KDIV_SHIFT ) ;
epll_con | = ( epll_div [ i ] [ 2 ] < < PLL90XX_MDIV_SHIFT ) |
( epll_div [ i ] [ 3 ] < < PLL90XX_PDIV_SHIFT ) |
( epll_div [ i ] [ 4 ] < < PLL90XX_SDIV_SHIFT ) ;
break ;
}
}
if ( i = = ARRAY_SIZE ( epll_div ) ) {
printk ( KERN_ERR " %s: Invalid Clock EPLL Frequency \n " , __func__ ) ;
return - EINVAL ;
}
__raw_writel ( epll_con , S5P64X0_EPLL_CON ) ;
__raw_writel ( epll_con_k , S5P64X0_EPLL_CON_K ) ;
2010-10-14 10:39:33 +09:00
printk ( KERN_WARNING " EPLL Rate changes from %lu to %lu \n " ,
clk - > rate , rate ) ;
2010-09-01 15:35:30 +09:00
clk - > rate = rate ;
return 0 ;
}
static struct clk_ops s5p6450_epll_ops = {
2010-10-14 10:39:08 +09:00
. get_rate = s5p_epll_get_rate ,
2010-09-01 15:35:30 +09:00
. set_rate = s5p6450_epll_set_rate ,
} ;
static struct clksrc_clk clk_dout_epll = {
. clk = {
. name = " dout_epll " ,
. parent = & clk_mout_epll . clk ,
} ,
. reg_div = { . reg = S5P64X0_CLK_DIV1 , . shift = 24 , . size = 4 } ,
} ;
static struct clksrc_clk clk_mout_hclk_sel = {
. clk = {
. name = " mout_hclk_sel " ,
} ,
. sources = & clkset_hclk_low ,
. reg_src = { . reg = S5P64X0_OTHERS , . shift = 15 , . size = 1 } ,
} ;
static struct clk * clkset_hclk_list [ ] = {
& clk_mout_hclk_sel . clk ,
& clk_armclk . clk ,
} ;
static struct clksrc_sources clkset_hclk = {
. sources = clkset_hclk_list ,
. nr_sources = ARRAY_SIZE ( clkset_hclk_list ) ,
} ;
static struct clksrc_clk clk_hclk = {
. clk = {
. name = " clk_hclk " ,
} ,
. sources = & clkset_hclk ,
. reg_src = { . reg = S5P64X0_OTHERS , . shift = 14 , . size = 1 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV0 , . shift = 8 , . size = 4 } ,
} ;
static struct clksrc_clk clk_pclk = {
. clk = {
. name = " clk_pclk " ,
. parent = & clk_hclk . clk ,
} ,
. reg_div = { . reg = S5P64X0_CLK_DIV0 , . shift = 12 , . size = 4 } ,
} ;
static struct clksrc_clk clk_dout_pwm_ratio0 = {
. clk = {
. name = " clk_dout_pwm_ratio0 " ,
. parent = & clk_mout_hclk_sel . clk ,
} ,
. reg_div = { . reg = S5P64X0_CLK_DIV3 , . shift = 16 , . size = 4 } ,
} ;
static struct clksrc_clk clk_pclk_to_wdt_pwm = {
. clk = {
. name = " clk_pclk_to_wdt_pwm " ,
. parent = & clk_dout_pwm_ratio0 . clk ,
} ,
. reg_div = { . reg = S5P64X0_CLK_DIV3 , . shift = 20 , . size = 4 } ,
} ;
static struct clksrc_clk clk_hclk_low = {
. clk = {
. name = " clk_hclk_low " ,
} ,
. sources = & clkset_hclk_low ,
. reg_src = { . reg = S5P64X0_OTHERS , . shift = 6 , . size = 1 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV3 , . shift = 8 , . size = 4 } ,
} ;
static struct clksrc_clk clk_pclk_low = {
. clk = {
. name = " clk_pclk_low " ,
. parent = & clk_hclk_low . clk ,
} ,
. reg_div = { . reg = S5P64X0_CLK_DIV3 , . shift = 12 , . size = 4 } ,
} ;
/*
* The following clocks will be disabled during clock initialization . It is
* recommended to keep the following clocks disabled until the driver requests
* for enabling the clock .
*/
2011-01-04 18:14:00 +09:00
static struct clk init_clocks_off [ ] = {
2010-09-01 15:35:30 +09:00
{
. name = " usbhost " ,
. parent = & clk_hclk_low . clk ,
. enable = s5p64x0_hclk0_ctrl ,
. ctrlbit = ( 1 < < 3 ) ,
2010-10-19 18:13:11 +09:00
} , {
2011-09-02 09:44:39 +09:00
. name = " dma " ,
2011-08-18 19:24:55 +09:00
. devname = " dma-pl330 " ,
2010-10-19 18:13:11 +09:00
. parent = & clk_hclk_low . clk ,
. enable = s5p64x0_hclk0_ctrl ,
. ctrlbit = ( 1 < < 12 ) ,
2010-09-01 15:35:30 +09:00
} , {
. name = " hsmmc " ,
2011-06-14 19:12:27 +09:00
. devname = " s3c-sdhci.0 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_hclk_low . clk ,
. enable = s5p64x0_hclk0_ctrl ,
. ctrlbit = ( 1 < < 17 ) ,
} , {
. name = " hsmmc " ,
2011-06-14 19:12:27 +09:00
. devname = " s3c-sdhci.1 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_hclk_low . clk ,
. enable = s5p64x0_hclk0_ctrl ,
. ctrlbit = ( 1 < < 18 ) ,
} , {
. name = " hsmmc " ,
2011-06-14 19:12:27 +09:00
. devname = " s3c-sdhci.2 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_hclk_low . clk ,
. enable = s5p64x0_hclk0_ctrl ,
. ctrlbit = ( 1 < < 19 ) ,
} , {
. name = " usbotg " ,
. parent = & clk_hclk_low . clk ,
. enable = s5p64x0_hclk0_ctrl ,
. ctrlbit = ( 1 < < 20 ) ,
} , {
. name = " lcd " ,
. parent = & clk_h ,
. enable = s5p64x0_hclk1_ctrl ,
. ctrlbit = ( 1 < < 1 ) ,
} , {
. name = " watchdog " ,
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 5 ) ,
2010-12-02 13:36:12 +09:00
} , {
. name = " rtc " ,
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 6 ) ,
2010-09-01 15:35:30 +09:00
} , {
. name = " adc " ,
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 12 ) ,
} , {
. name = " i2c " ,
2011-06-14 19:12:27 +09:00
. devname = " s3c2440-i2c.0 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 17 ) ,
} , {
. name = " spi " ,
2012-07-13 07:15:14 +09:00
. devname = " s5p64x0-spi.0 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 21 ) ,
} , {
. name = " spi " ,
2012-07-13 07:15:14 +09:00
. devname = " s5p64x0-spi.1 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 22 ) ,
} , {
. name = " iis " ,
2011-06-14 19:12:27 +09:00
. devname = " samsung-i2s.0 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 26 ) ,
2010-12-21 09:44:36 +09:00
} , {
. name = " iis " ,
2011-06-14 19:12:27 +09:00
. devname = " samsung-i2s.1 " ,
2010-12-21 09:44:36 +09:00
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 15 ) ,
} , {
. name = " iis " ,
2011-06-14 19:12:27 +09:00
. devname = " samsung-i2s.2 " ,
2010-12-21 09:44:36 +09:00
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 16 ) ,
2010-09-01 15:35:30 +09:00
} , {
. name = " i2c " ,
2011-06-14 19:12:27 +09:00
. devname = " s3c2440-i2c.1 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 27 ) ,
} , {
. name = " dmc0 " ,
. parent = & clk_pclk . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 30 ) ,
}
} ;
/*
* The following clocks will be enabled during clock initialization .
*/
static struct clk init_clocks [ ] = {
{
. name = " intc " ,
. parent = & clk_hclk . clk ,
. enable = s5p64x0_hclk0_ctrl ,
. ctrlbit = ( 1 < < 1 ) ,
} , {
. name = " mem " ,
. parent = & clk_hclk . clk ,
. enable = s5p64x0_hclk0_ctrl ,
. ctrlbit = ( 1 < < 21 ) ,
} , {
. name = " uart " ,
2011-06-14 19:12:27 +09:00
. devname = " s3c6400-uart.0 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 1 ) ,
} , {
. name = " uart " ,
2011-06-14 19:12:27 +09:00
. devname = " s3c6400-uart.1 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 2 ) ,
} , {
. name = " uart " ,
2011-06-14 19:12:27 +09:00
. devname = " s3c6400-uart.2 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 3 ) ,
} , {
. name = " uart " ,
2011-06-14 19:12:27 +09:00
. devname = " s3c6400-uart.3 " ,
2010-09-01 15:35:30 +09:00
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 4 ) ,
} , {
. name = " timers " ,
. parent = & clk_pclk_to_wdt_pwm . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 7 ) ,
} , {
. name = " gpio " ,
. parent = & clk_pclk_low . clk ,
. enable = s5p64x0_pclk_ctrl ,
. ctrlbit = ( 1 < < 18 ) ,
} ,
} ;
static struct clk * clkset_uart_list [ ] = {
& clk_dout_epll . clk ,
& clk_dout_mpll . clk ,
} ;
static struct clksrc_sources clkset_uart = {
. sources = clkset_uart_list ,
. nr_sources = ARRAY_SIZE ( clkset_uart_list ) ,
} ;
static struct clk * clkset_mali_list [ ] = {
& clk_mout_epll . clk ,
& clk_mout_apll . clk ,
& clk_mout_mpll . clk ,
} ;
static struct clksrc_sources clkset_mali = {
. sources = clkset_mali_list ,
. nr_sources = ARRAY_SIZE ( clkset_mali_list ) ,
} ;
static struct clk * clkset_group2_list [ ] = {
& clk_dout_epll . clk ,
& clk_dout_mpll . clk ,
& clk_ext_xtal_mux ,
} ;
static struct clksrc_sources clkset_group2 = {
. sources = clkset_group2_list ,
. nr_sources = ARRAY_SIZE ( clkset_group2_list ) ,
} ;
static struct clk * clkset_dispcon_list [ ] = {
& clk_dout_epll . clk ,
& clk_dout_mpll . clk ,
& clk_ext_xtal_mux ,
& clk_mout_dpll . clk ,
} ;
static struct clksrc_sources clkset_dispcon = {
. sources = clkset_dispcon_list ,
. nr_sources = ARRAY_SIZE ( clkset_dispcon_list ) ,
} ;
static struct clk * clkset_hsmmc44_list [ ] = {
& clk_dout_epll . clk ,
& clk_dout_mpll . clk ,
& clk_ext_xtal_mux ,
& s5p_clk_27m ,
& clk_48m ,
} ;
static struct clksrc_sources clkset_hsmmc44 = {
. sources = clkset_hsmmc44_list ,
. nr_sources = ARRAY_SIZE ( clkset_hsmmc44_list ) ,
} ;
static struct clk * clkset_sclk_audio0_list [ ] = {
[ 0 ] = & clk_dout_epll . clk ,
[ 1 ] = & clk_dout_mpll . clk ,
[ 2 ] = & clk_ext_xtal_mux ,
[ 3 ] = NULL ,
[ 4 ] = NULL ,
} ;
static struct clksrc_sources clkset_sclk_audio0 = {
. sources = clkset_sclk_audio0_list ,
. nr_sources = ARRAY_SIZE ( clkset_sclk_audio0_list ) ,
} ;
static struct clksrc_clk clk_sclk_audio0 = {
. clk = {
. name = " audio-bus " ,
. enable = s5p64x0_sclk_ctrl ,
. ctrlbit = ( 1 < < 8 ) ,
. parent = & clk_dout_epll . clk ,
} ,
. sources = & clkset_sclk_audio0 ,
. reg_src = { . reg = S5P64X0_CLK_SRC1 , . shift = 10 , . size = 3 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV2 , . shift = 8 , . size = 4 } ,
} ;
static struct clksrc_clk clksrcs [ ] = {
{
. clk = {
. name = " sclk_fimc " ,
. ctrlbit = ( 1 < < 10 ) ,
. enable = s5p64x0_sclk_ctrl ,
} ,
. sources = & clkset_group2 ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 26 , . size = 2 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV1 , . shift = 12 , . size = 4 } ,
} , {
. clk = {
. name = " aclk_mali " ,
. ctrlbit = ( 1 < < 2 ) ,
. enable = s5p64x0_sclk1_ctrl ,
} ,
. sources = & clkset_mali ,
. reg_src = { . reg = S5P64X0_CLK_SRC1 , . shift = 8 , . size = 2 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV3 , . shift = 4 , . size = 4 } ,
} , {
. clk = {
. name = " sclk_2d " ,
. ctrlbit = ( 1 < < 12 ) ,
. enable = s5p64x0_sclk_ctrl ,
} ,
. sources = & clkset_mali ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 30 , . size = 2 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV2 , . shift = 20 , . size = 4 } ,
} , {
. clk = {
. name = " sclk_usi " ,
. ctrlbit = ( 1 < < 7 ) ,
. enable = s5p64x0_sclk_ctrl ,
} ,
. sources = & clkset_group2 ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 10 , . size = 2 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV1 , . shift = 16 , . size = 4 } ,
} , {
. clk = {
. name = " sclk_camif " ,
. ctrlbit = ( 1 < < 6 ) ,
. enable = s5p64x0_sclk_ctrl ,
} ,
. sources = & clkset_group2 ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 28 , . size = 2 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV1 , . shift = 20 , . size = 4 } ,
} , {
. clk = {
. name = " sclk_dispcon " ,
. ctrlbit = ( 1 < < 1 ) ,
. enable = s5p64x0_sclk1_ctrl ,
} ,
. sources = & clkset_dispcon ,
. reg_src = { . reg = S5P64X0_CLK_SRC1 , . shift = 4 , . size = 2 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV3 , . shift = 0 , . size = 4 } ,
} , {
. clk = {
. name = " sclk_hsmmc44 " ,
. ctrlbit = ( 1 < < 30 ) ,
. enable = s5p64x0_sclk_ctrl ,
} ,
. sources = & clkset_hsmmc44 ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 6 , . size = 3 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV1 , . shift = 28 , . size = 4 } ,
} ,
} ;
2011-12-26 16:31:02 +09:00
static struct clksrc_clk clk_sclk_mmc0 = {
. clk = {
. name = " sclk_mmc " ,
. devname = " s3c-sdhci.0 " ,
. ctrlbit = ( 1 < < 24 ) ,
. enable = s5p64x0_sclk_ctrl ,
} ,
. sources = & clkset_group2 ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 18 , . size = 2 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV1 , . shift = 0 , . size = 4 } ,
} ;
static struct clksrc_clk clk_sclk_mmc1 = {
. clk = {
. name = " sclk_mmc " ,
. devname = " s3c-sdhci.1 " ,
. ctrlbit = ( 1 < < 25 ) ,
. enable = s5p64x0_sclk_ctrl ,
} ,
. sources = & clkset_group2 ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 20 , . size = 2 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV1 , . shift = 4 , . size = 4 } ,
} ;
static struct clksrc_clk clk_sclk_mmc2 = {
. clk = {
. name = " sclk_mmc " ,
. devname = " s3c-sdhci.2 " ,
. ctrlbit = ( 1 < < 26 ) ,
. enable = s5p64x0_sclk_ctrl ,
} ,
. sources = & clkset_group2 ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 22 , . size = 2 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV1 , . shift = 8 , . size = 4 } ,
} ;
2011-10-24 12:08:42 +02:00
static struct clksrc_clk clk_sclk_uclk = {
. clk = {
. name = " uclk1 " ,
. ctrlbit = ( 1 < < 5 ) ,
. enable = s5p64x0_sclk_ctrl ,
} ,
. sources = & clkset_uart ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 13 , . size = 1 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV2 , . shift = 16 , . size = 4 } ,
} ;
2011-11-02 20:04:08 +09:00
static struct clksrc_clk clk_sclk_spi0 = {
. clk = {
. name = " sclk_spi " ,
2012-07-13 07:15:14 +09:00
. devname = " s5p64x0-spi.0 " ,
2011-11-02 20:04:08 +09:00
. ctrlbit = ( 1 < < 20 ) ,
. enable = s5p64x0_sclk_ctrl ,
} ,
. sources = & clkset_group2 ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 14 , . size = 2 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV2 , . shift = 0 , . size = 4 } ,
} ;
static struct clksrc_clk clk_sclk_spi1 = {
. clk = {
. name = " sclk_spi " ,
2012-07-13 07:15:14 +09:00
. devname = " s5p64x0-spi.1 " ,
2011-11-02 20:04:08 +09:00
. ctrlbit = ( 1 < < 21 ) ,
. enable = s5p64x0_sclk_ctrl ,
} ,
. sources = & clkset_group2 ,
. reg_src = { . reg = S5P64X0_CLK_SRC0 , . shift = 16 , . size = 2 } ,
. reg_div = { . reg = S5P64X0_CLK_DIV2 , . shift = 4 , . size = 4 } ,
} ;
2011-10-24 12:08:42 +02:00
static struct clksrc_clk * clksrc_cdev [ ] = {
& clk_sclk_uclk ,
2011-11-02 20:04:08 +09:00
& clk_sclk_spi0 ,
& clk_sclk_spi1 ,
2011-12-26 16:31:02 +09:00
& clk_sclk_mmc0 ,
& clk_sclk_mmc1 ,
& clk_sclk_mmc2 ,
2011-10-24 12:08:42 +02:00
} ;
static struct clk_lookup s5p6450_clk_lookup [ ] = {
CLKDEV_INIT ( NULL , " clk_uart_baud2 " , & clk_pclk_low . clk ) ,
CLKDEV_INIT ( NULL , " clk_uart_baud3 " , & clk_sclk_uclk . clk ) ,
2011-11-02 20:04:08 +09:00
CLKDEV_INIT ( NULL , " spi_busclk0 " , & clk_p ) ,
2012-07-13 07:15:14 +09:00
CLKDEV_INIT ( " s5p64x0-spi.0 " , " spi_busclk1 " , & clk_sclk_spi0 . clk ) ,
CLKDEV_INIT ( " s5p64x0-spi.1 " , " spi_busclk1 " , & clk_sclk_spi1 . clk ) ,
2011-12-26 16:31:02 +09:00
CLKDEV_INIT ( " s3c-sdhci.0 " , " mmc_busclk.2 " , & clk_sclk_mmc0 . clk ) ,
CLKDEV_INIT ( " s3c-sdhci.1 " , " mmc_busclk.2 " , & clk_sclk_mmc1 . clk ) ,
CLKDEV_INIT ( " s3c-sdhci.2 " , " mmc_busclk.2 " , & clk_sclk_mmc2 . clk ) ,
2011-10-24 12:08:42 +02:00
} ;
2010-09-01 15:35:30 +09:00
/* Clock initialization code */
static struct clksrc_clk * sysclks [ ] = {
& clk_mout_apll ,
& clk_mout_epll ,
& clk_dout_epll ,
& clk_mout_mpll ,
& clk_dout_mpll ,
& clk_armclk ,
& clk_mout_hclk_sel ,
& clk_dout_pwm_ratio0 ,
& clk_pclk_to_wdt_pwm ,
& clk_hclk ,
& clk_pclk ,
& clk_hclk_low ,
& clk_pclk_low ,
& clk_sclk_audio0 ,
} ;
2011-09-02 09:44:39 +09:00
static struct clk dummy_apb_pclk = {
. name = " apb_pclk " ,
. id = - 1 ,
} ;
2010-09-01 15:35:30 +09:00
void __init_or_cpufreq s5p6450_setup_clocks ( void )
{
struct clk * xtal_clk ;
unsigned long xtal ;
unsigned long fclk ;
unsigned long hclk ;
unsigned long hclk_low ;
unsigned long pclk ;
unsigned long pclk_low ;
unsigned long apll ;
unsigned long mpll ;
unsigned long epll ;
unsigned long dpll ;
unsigned int ptr ;
/* Set S5P6450 functions for clk_fout_epll */
2010-10-14 10:39:08 +09:00
clk_fout_epll . enable = s5p_epll_enable ;
2010-09-01 15:35:30 +09:00
clk_fout_epll . ops = & s5p6450_epll_ops ;
clk_48m . enable = s5p64x0_clk48m_ctrl ;
xtal_clk = clk_get ( NULL , " ext_xtal " ) ;
BUG_ON ( IS_ERR ( xtal_clk ) ) ;
xtal = clk_get_rate ( xtal_clk ) ;
clk_put ( xtal_clk ) ;
apll = s5p_get_pll45xx ( xtal , __raw_readl ( S5P64X0_APLL_CON ) , pll_4502 ) ;
mpll = s5p_get_pll45xx ( xtal , __raw_readl ( S5P64X0_MPLL_CON ) , pll_4502 ) ;
epll = s5p_get_pll90xx ( xtal , __raw_readl ( S5P64X0_EPLL_CON ) ,
__raw_readl ( S5P64X0_EPLL_CON_K ) ) ;
dpll = s5p_get_pll46xx ( xtal , __raw_readl ( S5P6450_DPLL_CON ) ,
__raw_readl ( S5P6450_DPLL_CON_K ) , pll_4650c ) ;
clk_fout_apll . rate = apll ;
clk_fout_mpll . rate = mpll ;
clk_fout_epll . rate = epll ;
clk_fout_dpll . rate = dpll ;
printk ( KERN_INFO " S5P6450: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz, " \
" E=%ld.%ldMHz, D=%ld.%ldMHz \n " ,
print_mhz ( apll ) , print_mhz ( mpll ) , print_mhz ( epll ) ,
print_mhz ( dpll ) ) ;
fclk = clk_get_rate ( & clk_armclk . clk ) ;
hclk = clk_get_rate ( & clk_hclk . clk ) ;
pclk = clk_get_rate ( & clk_pclk . clk ) ;
hclk_low = clk_get_rate ( & clk_hclk_low . clk ) ;
pclk_low = clk_get_rate ( & clk_pclk_low . clk ) ;
printk ( KERN_INFO " S5P6450: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz, " \
" PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz \n " ,
print_mhz ( hclk ) , print_mhz ( hclk_low ) ,
print_mhz ( pclk ) , print_mhz ( pclk_low ) ) ;
clk_f . rate = fclk ;
clk_h . rate = hclk ;
clk_p . rate = pclk ;
for ( ptr = 0 ; ptr < ARRAY_SIZE ( clksrcs ) ; ptr + + )
s3c_set_clksrc ( & clksrcs [ ptr ] , true ) ;
}
void __init s5p6450_register_clocks ( void )
{
int ptr ;
for ( ptr = 0 ; ptr < ARRAY_SIZE ( sysclks ) ; ptr + + )
s3c_register_clksrc ( sysclks [ ptr ] , 1 ) ;
s3c_register_clksrc ( clksrcs , ARRAY_SIZE ( clksrcs ) ) ;
s3c_register_clocks ( init_clocks , ARRAY_SIZE ( init_clocks ) ) ;
2011-10-24 12:08:42 +02:00
for ( ptr = 0 ; ptr < ARRAY_SIZE ( clksrc_cdev ) ; ptr + + )
s3c_register_clksrc ( clksrc_cdev [ ptr ] , 1 ) ;
2010-09-01 15:35:30 +09:00
2011-01-04 18:14:00 +09:00
s3c_register_clocks ( init_clocks_off , ARRAY_SIZE ( init_clocks_off ) ) ;
s3c_disable_clocks ( init_clocks_off , ARRAY_SIZE ( init_clocks_off ) ) ;
2011-10-24 12:08:42 +02:00
clkdev_add_table ( s5p6450_clk_lookup , ARRAY_SIZE ( s5p6450_clk_lookup ) ) ;
2010-09-01 15:35:30 +09:00
2011-09-02 09:44:39 +09:00
s3c24xx_register_clock ( & dummy_apb_pclk ) ;
2010-09-01 15:35:30 +09:00
s3c_pwmclk_init ( ) ;
}