diff options
author | Giridhar Maruthy <giridhar.maruthy@linaro.org> | 2011-12-22 15:37:53 +0530 |
---|---|---|
committer | Tushar Behera <tushar.behera@linaro.org> | 2013-03-14 10:46:21 +0530 |
commit | 956364a8ac29d8ed0c51a6326983f1368d0b0b54 (patch) | |
tree | 7d5ec2094dd552ff32d57608023d5bbbd105660e /arch | |
parent | b619155883c9af668bf9ef0c7ad4e04bfa4dafa1 (diff) |
ARM: EXYNOS: Add audio subsystem clocks
When the I2S bus acts as master, it needs to configure the source
clocks. Added bus_clk as the source clock for I2S controller.
Since bus_clk uses fout_epll, also added configuration settings
for fout_epll.
Signed-off-by: Giridhar Maruthy <giridhar.maruthy@linaro.org>
Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-exynos/clock-exynos4.c | 102 | ||||
-rw-r--r-- | arch/arm/mach-exynos/common.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-exynos/include/mach/map.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-exynos/include/mach/regs-audss.h | 11 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/map-s5p.h | 2 |
5 files changed, 120 insertions, 2 deletions
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c index bbcb3dea0d40..e4ed9918a5f1 100644 --- a/arch/arm/mach-exynos/clock-exynos4.c +++ b/arch/arm/mach-exynos/clock-exynos4.c @@ -23,6 +23,7 @@ #include <plat/pm.h> #include <mach/map.h> +#include <mach/regs-audss.h> #include <mach/regs-clock.h> #include <mach/sysmmu.h> @@ -31,6 +32,7 @@ #ifdef CONFIG_PM_SLEEP static struct sleep_save exynos4_clock_save[] = { + SAVE_ITEM(EXYNOS4_CLKSRC_AUDSS), SAVE_ITEM(EXYNOS4_CLKDIV_LEFTBUS), SAVE_ITEM(EXYNOS4_CLKGATE_IP_LEFTBUS), SAVE_ITEM(EXYNOS4_CLKDIV_RIGHTBUS), @@ -118,6 +120,10 @@ static struct clk dummy_apb_pclk = { .id = -1, }; +static struct clk exynos4_clk_xxti = { + .name = "xxti", +}; + static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TOP, clk, enable); @@ -823,6 +829,24 @@ static struct clk exynos4_clk_fimd0 = { .ctrlbit = (1 << 0), }; +static struct clk *exynos4_clkset_mout_audss_list[] = { + &exynos4_clk_xxti, + &clk_fout_epll, +}; + +static struct clksrc_sources exynos4_clkset_mout_audss = { + .sources = exynos4_clkset_mout_audss_list, + .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_audss_list), +}; + +static struct clksrc_clk exynos4_clk_mout_audss = { + .clk = { + .name = "busclk", + }, + .sources = &exynos4_clkset_mout_audss, + .reg_src = { .reg = EXYNOS4_CLKSRC_AUDSS, .shift = 0, .size = 1 }, +}; + struct clk *exynos4_clkset_group_list[] = { [0] = &clk_ext_xtal_mux, [1] = &clk_xusbxti, @@ -1323,6 +1347,7 @@ static struct clksrc_clk *exynos4_sysclks[] = { &exynos4_clk_aclk_100, &exynos4_clk_aclk_160, &exynos4_clk_aclk_133, + &exynos4_clk_mout_audss, &exynos4_clk_dout_mmc0, &exynos4_clk_dout_mmc1, &exynos4_clk_dout_mmc2, @@ -1372,6 +1397,7 @@ static struct clk_lookup exynos4_clk_lookup[] = { CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk), CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk), CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk), + CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &exynos4_clk_mout_audss.clk), }; static int xtal_rate; @@ -1387,6 +1413,78 @@ static unsigned long exynos4_fout_apll_get_rate(struct clk *clk) return 0; } +static u32 exynos4_epll_div[][6] = { + { 48000000, 0, 48, 3, 3, 0 }, + { 96000000, 0, 48, 3, 2, 0 }, + { 144000000, 1, 72, 3, 2, 0 }, + { 192000000, 0, 48, 3, 1, 0 }, + { 288000000, 1, 72, 3, 1, 0 }, + { 84000000, 0, 42, 3, 2, 0 }, + { 50000000, 0, 50, 3, 3, 0 }, + { 80000000, 1, 80, 3, 3, 0 }, + { 32750000, 1, 65, 3, 4, 35127 }, + { 32768000, 1, 65, 3, 4, 35127 }, + { 49152000, 0, 49, 3, 3, 9961 }, + { 67737600, 1, 67, 3, 3, 48366 }, + { 73728000, 1, 73, 3, 3, 47710 }, + { 45158400, 0, 45, 3, 3, 10381 }, + { 45000000, 0, 45, 3, 3, 10355 }, + { 45158000, 0, 45, 3, 3, 10355 }, + { 49125000, 0, 49, 3, 3, 9961 }, + { 67738000, 1, 67, 3, 3, 48366 }, + { 73800000, 1, 73, 3, 3, 47710 }, + { 36000000, 1, 32, 3, 4, 0 }, + { 60000000, 1, 60, 3, 3, 0 }, + { 72000000, 1, 72, 3, 3, 0 }, + { 191923200, 0, 47, 3, 1, 64278 }, + { 180633600, 0, 45, 3, 1, 10381 }, +}; + +static int exynos4_epll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int epll_con, epll_con_k; + unsigned int i; + + /* Return if nothing changed */ + if (clk->rate == rate) + return 0; + + epll_con = __raw_readl(EXYNOS4_EPLL_CON0); + epll_con &= ~(0x1 << 27 | \ + PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \ + PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \ + PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT); + + for (i = 0; i < ARRAY_SIZE(exynos4_epll_div); i++) { + if (exynos4_epll_div[i][0] == rate) { + epll_con_k = exynos4_epll_div[i][5] << 0; + epll_con |= exynos4_epll_div[i][1] << 27; + epll_con |= exynos4_epll_div[i][2] << PLL46XX_MDIV_SHIFT; + epll_con |= exynos4_epll_div[i][3] << PLL46XX_PDIV_SHIFT; + epll_con |= exynos4_epll_div[i][4] << PLL46XX_SDIV_SHIFT; + break; + } + } + + if (i == ARRAY_SIZE(exynos4_epll_div)) { + printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", + __func__); + return -EINVAL; + } + + __raw_writel(epll_con, EXYNOS4_EPLL_CON0); + __raw_writel(epll_con_k, EXYNOS4_EPLL_CON1); + + clk->rate = rate; + + return 0; +} + +static struct clk_ops exynos4_epll_ops = { + .get_rate = s5p_epll_get_rate, + .set_rate = exynos4_epll_set_rate, +}; + static struct clk_ops exynos4_fout_apll_ops = { .get_rate = exynos4_fout_apll_get_rate, }; @@ -1516,6 +1614,10 @@ void __init_or_cpufreq exynos4_setup_clocks(void) clk_fout_vpll.ops = &exynos4_vpll_ops; clk_fout_vpll.rate = vpll; + clk_fout_epll.enable = s5p_epll_enable; + clk_fout_epll.ops = &exynos4_epll_ops; + clk_set_parent(&exynos4_clk_mout_audss.clk, &clk_fout_epll); + printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld", apll, mpll, epll, vpll); diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 0f7006d899a0..41d843aeb028 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -210,6 +210,11 @@ static struct map_desc exynos4_iodesc[] __initdata = { .length = SZ_64K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S5P_VA_AUDSS, + .pfn = __phys_to_pfn(EXYNOS4_PA_AUDSS), + .length = SZ_4K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)S3C_VA_USB_HSPHY, .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY), .length = SZ_4K, diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index e474a1ce0d9b..deb86440bf16 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -221,6 +221,8 @@ #define EXYNOS4_PA_ADC 0x13910000 #define EXYNOS4_PA_ADC1 0x13911000 +#define EXYNOS4_PA_AUDSS 0x03810000 + #define EXYNOS4_PA_AC97 0x139A0000 #define EXYNOS4_PA_SPDIF 0x139B0000 diff --git a/arch/arm/mach-exynos/include/mach/regs-audss.h b/arch/arm/mach-exynos/include/mach/regs-audss.h index ca5a8b64218a..71ceb08ae63b 100644 --- a/arch/arm/mach-exynos/include/mach/regs-audss.h +++ b/arch/arm/mach-exynos/include/mach/regs-audss.h @@ -1,5 +1,4 @@ -/* arch/arm/mach-exynos4/include/mach/regs-audss.h - * +/* * Copyright (c) 2011 Samsung Electronics * http://www.samsung.com * @@ -15,4 +14,12 @@ #define EXYNOS4_AUDSS_INT_MEM (0x03000000) +#define EXYNOS_AUDSSREG(x) (S5P_VA_AUDSS + (x)) + +#define EXYNOS4_CLKSRC_AUDSS EXYNOS_AUDSSREG(0x0) +#define EXYNOS4_CLKDIV_AUDSS EXYNOS_AUDSSREG(0x4) +#define EXYNOS4_CLKGATE_AUDSS EXYNOS_AUDSSREG(0x8) + +#define EXYNOS4_AUDSS_CLKGATE_I2SBUS (1<<2) + #endif /* _PLAT_REGS_AUDSS_H */ diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h index c18678610bc0..1bfe16ed5093 100644 --- a/arch/arm/plat-samsung/include/plat/map-s5p.h +++ b/arch/arm/plat-samsung/include/plat/map-s5p.h @@ -41,6 +41,8 @@ #define S5P_VA_GIC_CPU S3C_ADDR(0x02810000) #define S5P_VA_GIC_DIST S3C_ADDR(0x02820000) +#define S5P_VA_AUDSS S3C_ADDR(0X02A00000) + #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) #define VA_VIC0 VA_VIC(0) #define VA_VIC1 VA_VIC(1) |