2424
2525#include <mach/map.h>
2626#include <mach/regs-clock.h>
27+ #include <mach/regs-audss.h>
2728#include <mach/sysmmu.h>
2829
2930#include "common.h"
@@ -198,6 +199,11 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
198199 return s5p_gatectrl (EXYNOS4_CLKGATE_IP_PERIR , clk , enable );
199200}
200201
202+ static int exynos4_clk_vpll_ctrl (struct clk * clk , int enable )
203+ {
204+ return s5p_gatectrl (EXYNOS4_VPLL_CON0 , clk , enable );
205+ }
206+
201207int exynos4_clk_ip_dmc_ctrl (struct clk * clk , int enable )
202208{
203209 return s5p_gatectrl (EXYNOS4_CLKGATE_IP_DMC , clk , enable );
@@ -213,6 +219,16 @@ static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
213219 return s5p_gatectrl (S5P_DAC_PHY_CONTROL , clk , enable );
214220}
215221
222+ static int exynos4_clksrc_mask_maudio_ctrl (struct clk * clk , int enable )
223+ {
224+ return s5p_gatectrl (EXYNOS4_CLKSRC_MASK_MAUDIO , clk , enable );
225+ }
226+
227+ int exynos4_clk_audss_ctrl (struct clk * clk , int enable )
228+ {
229+ return s5p_gatectrl (S5P_CLKGATE_AUDSS , clk , enable );
230+ }
231+
216232/* Core list of CMU_CPU side */
217233
218234static struct clksrc_clk exynos4_clk_mout_apll = {
@@ -451,6 +467,25 @@ static struct clksrc_sources exynos4_clkset_sclk_vpll = {
451467 .nr_sources = ARRAY_SIZE (exynos4_clkset_sclk_vpll_list ),
452468};
453469
470+ static struct clk * exynos4_clkset_mout_audss_list [] = {
471+ & clk_ext_xtal_mux ,
472+ & clk_fout_epll ,
473+ };
474+
475+ static struct clksrc_sources clkset_mout_audss = {
476+ .sources = exynos4_clkset_mout_audss_list ,
477+ .nr_sources = ARRAY_SIZE (exynos4_clkset_mout_audss_list ),
478+ };
479+
480+ static struct clksrc_clk exynos4_clk_mout_audss = {
481+ .clk = {
482+ .name = "mout_audss" ,
483+ },
484+ .sources = & clkset_mout_audss ,
485+ .reg_src = { .reg = S5P_CLKSRC_AUDSS , .shift = 0 , .size = 1 },
486+ };
487+
488+
454489static struct clksrc_clk exynos4_clk_sclk_vpll = {
455490 .clk = {
456491 .name = "sclk_vpll" ,
@@ -459,6 +494,43 @@ static struct clksrc_clk exynos4_clk_sclk_vpll = {
459494 .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0 , .shift = 8 , .size = 1 },
460495};
461496
497+ static struct clksrc_clk exynos4_clk_dout_audss_srp = {
498+ .clk = {
499+ .name = "dout_srp" ,
500+ .parent = & exynos4_clk_mout_audss .clk ,
501+ },
502+ .reg_div = { .reg = S5P_CLKDIV_AUDSS , .shift = 0 , .size = 4 },
503+ };
504+
505+ static struct clksrc_clk exynos4_clk_sclk_audss_bus = {
506+ .clk = {
507+ .name = "busclk" ,
508+ .parent = & exynos4_clk_dout_audss_srp .clk ,
509+ .enable = exynos4_clk_audss_ctrl ,
510+ .ctrlbit = (1 << 2 ),
511+ },
512+ .reg_div = { .reg = S5P_CLKDIV_AUDSS , .shift = 4 , .size = 4 },
513+ };
514+
515+ static struct clk exynos4_init_audss_clocks [] = {
516+ {
517+ .name = "srpclk" ,
518+ .enable = exynos4_clk_audss_ctrl ,
519+ .parent = & exynos4_clk_dout_audss_srp .clk ,
520+ .ctrlbit = (1 << 0 ),
521+ }, {
522+ .name = "iis" ,
523+ .devname = "samsung-i2s.0" ,
524+ .enable = exynos4_clk_audss_ctrl ,
525+ .ctrlbit = (1 << 3 ) | (1 << 2 ),
526+ }, {
527+ .name = "pcm" ,
528+ .devname = "samsung-pcm.0" ,
529+ .enable = exynos4_clk_audss_ctrl ,
530+ .ctrlbit = (1 << 5 ),
531+ },
532+ };
533+
462534static struct clk exynos4_init_clocks_off [] = {
463535 {
464536 .name = "timers" ,
@@ -599,11 +671,6 @@ static struct clk exynos4_init_clocks_off[] = {
599671 .devname = "exynos4210-spi.2" ,
600672 .enable = exynos4_clk_ip_peril_ctrl ,
601673 .ctrlbit = (1 << 18 ),
602- }, {
603- .name = "iis" ,
604- .devname = "samsung-i2s.0" ,
605- .enable = exynos4_clk_ip_peril_ctrl ,
606- .ctrlbit = (1 << 19 ),
607674 }, {
608675 .name = "iis" ,
609676 .devname = "samsung-i2s.1" ,
@@ -728,7 +795,65 @@ static struct clk exynos4_init_clocks_off[] = {
728795 .devname = SYSMMU_CLOCK_DEVNAME (fimd0 , 10 ),
729796 .enable = exynos4_clk_ip_lcd0_ctrl ,
730797 .ctrlbit = (1 << 4 ),
731- }
798+ },
799+ };
800+
801+ struct clksrc_clk exynos4_clk_audiocdclk0 = {
802+ .clk = {
803+ .name = "audiocdclk" ,
804+ .rate = 16934400 ,
805+ },
806+ };
807+
808+ static struct clk * clkset_sclk_audio0_list [] = {
809+ [0 ] = & exynos4_clk_audiocdclk0 .clk ,
810+ [1 ] = NULL ,
811+ [2 ] = & exynos4_clk_sclk_hdmi27m ,
812+ [3 ] = & exynos4_clk_sclk_usbphy0 ,
813+ [4 ] = & clk_ext_xtal_mux ,
814+ [5 ] = & clk_xusbxti ,
815+ [6 ] = & exynos4_clk_mout_mpll .clk ,
816+ [7 ] = & exynos4_clk_mout_epll .clk ,
817+ [8 ] = & exynos4_clk_sclk_vpll .clk ,
818+ };
819+
820+ static struct clksrc_sources exynos4_clkset_sclk_audio0 = {
821+ .sources = clkset_sclk_audio0_list ,
822+ .nr_sources = ARRAY_SIZE (clkset_sclk_audio0_list ),
823+ };
824+
825+ static struct clksrc_clk exynos4_clk_sclk_audio0 = {
826+ .clk = {
827+ .name = "audio-bus" ,
828+ .enable = exynos4_clksrc_mask_maudio_ctrl ,
829+ .ctrlbit = (1 << 0 ),
830+ },
831+ .sources = & exynos4_clkset_sclk_audio0 ,
832+ .reg_src = { .reg = EXYNOS4_CLKSRC_MAUDIO , .shift = 0 , .size = 4 },
833+ .reg_div = { .reg = EXYNOS4_CLKDIV_MAUDIO , .shift = 0 , .size = 4 },
834+ };
835+
836+ static struct clk * exynos4_clkset_sclk_audss_list [] = {
837+ & exynos4_clk_mout_audss .clk ,
838+ & exynos4_clk_audiocdclk0 .clk ,
839+ & exynos4_clk_sclk_audio0 .clk ,
840+ };
841+
842+ static struct clksrc_sources exynos4_clkset_sclk_audss = {
843+ .sources = exynos4_clkset_sclk_audss_list ,
844+ .nr_sources = ARRAY_SIZE (exynos4_clkset_sclk_audss_list ),
845+ };
846+
847+ static struct clksrc_clk exynos4_clk_sclk_audss_i2s = {
848+ .clk = {
849+ .name = "i2sclk" ,
850+ .parent = & exynos4_clk_mout_audss .clk ,
851+ .enable = exynos4_clk_audss_ctrl ,
852+ .ctrlbit = (1 << 3 ),
853+ },
854+ .sources = & exynos4_clkset_sclk_audss ,
855+ .reg_src = { .reg = S5P_CLKSRC_AUDSS , .shift = 2 , .size = 2 },
856+ .reg_div = { .reg = S5P_CLKDIV_AUDSS , .shift = 8 , .size = 4 },
732857};
733858
734859static struct clk exynos4_init_clocks_on [] = {
@@ -1102,15 +1227,7 @@ static struct clksrc_clk exynos4_clksrcs[] = {
11021227 .sources = & exynos4_clkset_mout_mfc ,
11031228 .reg_src = { .reg = EXYNOS4_CLKSRC_MFC , .shift = 8 , .size = 1 },
11041229 .reg_div = { .reg = EXYNOS4_CLKDIV_MFC , .shift = 0 , .size = 4 },
1105- }, {
1106- .clk = {
1107- .name = "sclk_dwmmc" ,
1108- .parent = & exynos4_clk_dout_mmc4 .clk ,
1109- .enable = exynos4_clksrc_mask_fsys_ctrl ,
1110- .ctrlbit = (1 << 16 ),
1111- },
1112- .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3 , .shift = 8 , .size = 8 },
1113- }
1230+ },
11141231};
11151232
11161233static struct clksrc_clk exynos4_clk_sclk_uart0 = {
@@ -1279,6 +1396,14 @@ static struct clksrc_clk exynos4_clk_sclk_spi2 = {
12791396 .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2 , .shift = 8 , .size = 8 },
12801397};
12811398
1399+ static struct clksrc_clk exynos4_clk_sclk_pcm0 = {
1400+ .clk = {
1401+ .name = "sclk_pcm" ,
1402+ .parent = & exynos4_clk_sclk_audio0 .clk ,
1403+ },
1404+ .reg_div = { .reg = EXYNOS4_CLKDIV_MAUDIO , .shift = 4 , .size = 8 },
1405+ };
1406+
12821407/* Clock initialization code */
12831408static struct clksrc_clk * exynos4_sysclks [] = {
12841409 & exynos4_clk_mout_apll ,
@@ -1311,6 +1436,13 @@ static struct clksrc_clk *exynos4_sysclks[] = {
13111436 & exynos4_clk_dout_mmc4 ,
13121437 & exynos4_clk_mout_mfc0 ,
13131438 & exynos4_clk_mout_mfc1 ,
1439+ & exynos4_clk_audiocdclk0 ,
1440+ & exynos4_clk_mout_audss ,
1441+ & exynos4_clk_sclk_audss_bus ,
1442+ & exynos4_clk_sclk_audss_i2s ,
1443+ & exynos4_clk_dout_audss_srp ,
1444+ & exynos4_clk_sclk_audio0 ,
1445+ & exynos4_clk_sclk_pcm0 ,
13141446};
13151447
13161448static struct clk * exynos4_clk_cdev [] = {
@@ -1438,6 +1570,92 @@ static struct clk_ops exynos4_vpll_ops = {
14381570 .set_rate = exynos4_vpll_set_rate ,
14391571};
14401572
1573+ static unsigned long exynos4_epll_get_rate (struct clk * clk )
1574+ {
1575+ return clk -> rate ;
1576+ }
1577+
1578+ static u32 epll_div [][6 ] = {
1579+ { 192000000 , 0 , 48 , 3 , 1 , 0 },
1580+ { 180000000 , 0 , 45 , 3 , 1 , 0 },
1581+ { 73728000 , 1 , 73 , 3 , 3 , 47710 },
1582+ { 67737600 , 1 , 90 , 4 , 3 , 20762 },
1583+ { 49152000 , 0 , 49 , 3 , 3 , 9961 },
1584+ { 45158400 , 0 , 45 , 3 , 3 , 10381 },
1585+ { 180633600 , 0 , 45 , 3 , 1 , 10381 },
1586+ };
1587+
1588+ static int exynos4_epll_set_rate (struct clk * clk , unsigned long rate )
1589+ {
1590+ unsigned int epll_con , epll_con_k ;
1591+ unsigned int i ;
1592+ unsigned int tmp ;
1593+ unsigned int epll_rate ;
1594+ unsigned int locktime ;
1595+ unsigned int lockcnt ;
1596+
1597+ /* Return if nothing changed */
1598+ if (clk -> rate == rate )
1599+ return 0 ;
1600+
1601+ if (clk -> parent )
1602+ epll_rate = clk_get_rate (clk -> parent );
1603+ else
1604+ epll_rate = clk_ext_xtal_mux .rate ;
1605+
1606+ if (epll_rate != 24000000 ) {
1607+ pr_err ("Invalid Clock : recommended clock is 24MHz.\n" );
1608+ return - EINVAL ;
1609+ }
1610+
1611+
1612+ epll_con = __raw_readl (EXYNOS4_EPLL_CON0 );
1613+ epll_con &= ~(0x1 << 27 | \
1614+ PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \
1615+ PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
1616+ PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT );
1617+
1618+ for (i = 0 ; i < ARRAY_SIZE (epll_div ); i ++ ) {
1619+ if (epll_div [i ][0 ] == rate ) {
1620+ epll_con_k = epll_div [i ][5 ] << 0 ;
1621+ epll_con |= epll_div [i ][1 ] << 27 ;
1622+ epll_con |= epll_div [i ][2 ] << PLL46XX_MDIV_SHIFT ;
1623+ epll_con |= epll_div [i ][3 ] << PLL46XX_PDIV_SHIFT ;
1624+ epll_con |= epll_div [i ][4 ] << PLL46XX_SDIV_SHIFT ;
1625+ break ;
1626+ }
1627+ }
1628+
1629+ if (i == ARRAY_SIZE (epll_div )) {
1630+ pr_err ("%s: Invalid Clock EPLL Frequency\n" , __func__ );
1631+ return - EINVAL ;
1632+ }
1633+
1634+ epll_rate /= 1000000 ;
1635+
1636+ /* 3000 max_cycls : specification data */
1637+ locktime = 3000 / epll_rate * epll_div [i ][3 ];
1638+ lockcnt = locktime * 10000 / (10000 / epll_rate );
1639+
1640+ __raw_writel (lockcnt , EXYNOS4_EPLL_LOCK );
1641+
1642+ __raw_writel (epll_con , EXYNOS4_EPLL_CON0 );
1643+ __raw_writel (epll_con_k , EXYNOS4_EPLL_CON1 );
1644+
1645+ do {
1646+ tmp = __raw_readl (EXYNOS4_EPLL_CON0 );
1647+ } while (!(tmp & 0x1 << EXYNOS4_EPLLCON0_LOCKED_SHIFT ));
1648+
1649+ clk -> rate = rate ;
1650+
1651+ return 0 ;
1652+ }
1653+
1654+ static struct clk_ops exynos4_epll_ops = {
1655+ .get_rate = exynos4_epll_get_rate ,
1656+ .set_rate = exynos4_epll_set_rate ,
1657+ };
1658+
14411659void __init_or_cpufreq exynos4_setup_clocks (void )
14421660{
14431661 struct clk * xtal_clk ;
@@ -1494,6 +1712,7 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
14941712
14951713 clk_fout_apll .ops = & exynos4_fout_apll_ops ;
14961714 clk_fout_mpll .rate = mpll ;
1715+ clk_fout_epll .ops = & exynos4_epll_ops ;
14971716 clk_fout_epll .rate = epll ;
14981717 clk_fout_vpll .ops = & exynos4_vpll_ops ;
14991718 clk_fout_vpll .rate = vpll ;
@@ -1518,6 +1737,16 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
15181737 clk_h .rate = sclk_dmc ;
15191738 clk_p .rate = aclk_100 ;
15201739
1740+ clk_set_parent (& exynos4_clk_mout_audss .clk , & clk_fout_epll );
1741+ clk_set_parent (& exynos4_clk_sclk_audio0 .clk ,
1742+ & exynos4_clk_mout_epll .clk );
1743+ clk_set_parent (& exynos4_clk_mout_epll .clk , & clk_fout_epll );
1744+
1745+ clk_fout_vpll .enable = exynos4_clk_vpll_ctrl ;
1746+ clk_fout_vpll .ops = & exynos4_vpll_ops ;
1747+
1748+ clk_set_rate (& exynos4_clk_sclk_apll .clk , 100000000 );
1749+
15211750 for (ptr = 0 ; ptr < ARRAY_SIZE (exynos4_clksrcs ); ptr ++ )
15221751 s3c_set_clksrc (& exynos4_clksrcs [ptr ], true);
15231752}
@@ -1577,6 +1806,11 @@ void __init exynos4_register_clocks(void)
15771806 s3c_disable_clocks (exynos4_init_clocks_off , ARRAY_SIZE (exynos4_init_clocks_off ));
15781807 clkdev_add_table (exynos4_clk_lookup , ARRAY_SIZE (exynos4_clk_lookup ));
15791808
1809+ s3c_register_clocks (exynos4_init_audss_clocks ,
1810+ ARRAY_SIZE (exynos4_init_audss_clocks ));
1811+ s3c_disable_clocks (exynos4_init_audss_clocks ,
1812+ ARRAY_SIZE (exynos4_init_audss_clocks ));
1813+
15801814 register_syscore_ops (& exynos4_clock_syscore_ops );
15811815 s3c24xx_register_clock (& dummy_apb_pclk );
15821816
0 commit comments