2013-05-11 05:08:05 +04:00
/*
* Marvell Armada 370 SoC clocks
*
* Copyright ( C ) 2012 Marvell
*
* Gregory CLEMENT < gregory . clement @ free - electrons . com >
* Sebastian Hesselbarth < sebastian . hesselbarth @ gmail . com >
* Andrew Lunn < andrew @ lunn . ch >
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*/
# include <linux/kernel.h>
# include <linux/clk-provider.h>
# include <linux/io.h>
# include <linux/of.h>
# include "common.h"
/*
* Core Clocks
*/
# define SARL 0 /* Low part [0:31] */
2014-09-02 12:15:17 +04:00
# define SARL_A370_SSCG_ENABLE BIT(10)
2013-05-11 05:08:05 +04:00
# define SARL_A370_PCLK_FREQ_OPT 11
# define SARL_A370_PCLK_FREQ_OPT_MASK 0xF
# define SARL_A370_FAB_FREQ_OPT 15
# define SARL_A370_FAB_FREQ_OPT_MASK 0x1F
# define SARL_A370_TCLK_FREQ_OPT 20
# define SARL_A370_TCLK_FREQ_OPT_MASK 0x1
enum { A370_CPU_TO_NBCLK , A370_CPU_TO_HCLK , A370_CPU_TO_DRAMCLK } ;
2013-08-12 13:14:02 +04:00
static const struct coreclk_ratio a370_coreclk_ratios [ ] __initconst = {
2013-05-11 05:08:05 +04:00
{ . id = A370_CPU_TO_NBCLK , . name = " nbclk " } ,
{ . id = A370_CPU_TO_HCLK , . name = " hclk " } ,
{ . id = A370_CPU_TO_DRAMCLK , . name = " dramclk " } ,
} ;
2013-08-12 13:14:02 +04:00
static const u32 a370_tclk_freqs [ ] __initconst = {
2013-10-03 14:05:02 +04:00
166000000 ,
200000000 ,
2013-05-11 05:08:05 +04:00
} ;
static u32 __init a370_get_tclk_freq ( void __iomem * sar )
{
u8 tclk_freq_select = 0 ;
tclk_freq_select = ( ( readl ( sar ) > > SARL_A370_TCLK_FREQ_OPT ) &
SARL_A370_TCLK_FREQ_OPT_MASK ) ;
return a370_tclk_freqs [ tclk_freq_select ] ;
}
2013-08-12 13:14:02 +04:00
static const u32 a370_cpu_freqs [ ] __initconst = {
2013-05-11 05:08:05 +04:00
400000000 ,
533000000 ,
667000000 ,
800000000 ,
1000000000 ,
1067000000 ,
1200000000 ,
} ;
static u32 __init a370_get_cpu_freq ( void __iomem * sar )
{
u32 cpu_freq ;
u8 cpu_freq_select = 0 ;
cpu_freq_select = ( ( readl ( sar ) > > SARL_A370_PCLK_FREQ_OPT ) &
SARL_A370_PCLK_FREQ_OPT_MASK ) ;
if ( cpu_freq_select > = ARRAY_SIZE ( a370_cpu_freqs ) ) {
pr_err ( " CPU freq select unsupported %d \n " , cpu_freq_select ) ;
cpu_freq = 0 ;
} else
cpu_freq = a370_cpu_freqs [ cpu_freq_select ] ;
return cpu_freq ;
}
2013-08-12 13:14:02 +04:00
static const int a370_nbclk_ratios [ 32 ] [ 2 ] __initconst = {
2013-05-11 05:08:05 +04:00
{ 0 , 1 } , { 1 , 2 } , { 2 , 2 } , { 2 , 2 } ,
{ 1 , 2 } , { 1 , 2 } , { 1 , 1 } , { 2 , 3 } ,
{ 0 , 1 } , { 1 , 2 } , { 2 , 4 } , { 0 , 1 } ,
{ 1 , 2 } , { 0 , 1 } , { 0 , 1 } , { 2 , 2 } ,
{ 0 , 1 } , { 0 , 1 } , { 0 , 1 } , { 1 , 1 } ,
{ 2 , 3 } , { 0 , 1 } , { 0 , 1 } , { 0 , 1 } ,
{ 0 , 1 } , { 0 , 1 } , { 0 , 1 } , { 1 , 1 } ,
{ 0 , 1 } , { 0 , 1 } , { 0 , 1 } , { 0 , 1 } ,
} ;
2013-08-12 13:14:02 +04:00
static const int a370_hclk_ratios [ 32 ] [ 2 ] __initconst = {
2013-05-11 05:08:05 +04:00
{ 0 , 1 } , { 1 , 2 } , { 2 , 6 } , { 2 , 3 } ,
{ 1 , 3 } , { 1 , 4 } , { 1 , 2 } , { 2 , 6 } ,
{ 0 , 1 } , { 1 , 6 } , { 2 , 10 } , { 0 , 1 } ,
{ 1 , 4 } , { 0 , 1 } , { 0 , 1 } , { 2 , 5 } ,
{ 0 , 1 } , { 0 , 1 } , { 0 , 1 } , { 1 , 2 } ,
{ 2 , 6 } , { 0 , 1 } , { 0 , 1 } , { 0 , 1 } ,
{ 0 , 1 } , { 0 , 1 } , { 0 , 1 } , { 1 , 1 } ,
{ 0 , 1 } , { 0 , 1 } , { 0 , 1 } , { 0 , 1 } ,
} ;
2013-08-12 13:14:02 +04:00
static const int a370_dramclk_ratios [ 32 ] [ 2 ] __initconst = {
2013-05-11 05:08:05 +04:00
{ 0 , 1 } , { 1 , 2 } , { 2 , 3 } , { 2 , 3 } ,
{ 1 , 3 } , { 1 , 2 } , { 1 , 2 } , { 2 , 6 } ,
{ 0 , 1 } , { 1 , 3 } , { 2 , 5 } , { 0 , 1 } ,
{ 1 , 4 } , { 0 , 1 } , { 0 , 1 } , { 2 , 5 } ,
{ 0 , 1 } , { 0 , 1 } , { 0 , 1 } , { 1 , 1 } ,
{ 2 , 3 } , { 0 , 1 } , { 0 , 1 } , { 0 , 1 } ,
{ 0 , 1 } , { 0 , 1 } , { 0 , 1 } , { 1 , 1 } ,
{ 0 , 1 } , { 0 , 1 } , { 0 , 1 } , { 0 , 1 } ,
} ;
static void __init a370_get_clk_ratio (
void __iomem * sar , int id , int * mult , int * div )
{
u32 opt = ( ( readl ( sar ) > > SARL_A370_FAB_FREQ_OPT ) &
SARL_A370_FAB_FREQ_OPT_MASK ) ;
switch ( id ) {
case A370_CPU_TO_NBCLK :
* mult = a370_nbclk_ratios [ opt ] [ 0 ] ;
* div = a370_nbclk_ratios [ opt ] [ 1 ] ;
break ;
case A370_CPU_TO_HCLK :
* mult = a370_hclk_ratios [ opt ] [ 0 ] ;
* div = a370_hclk_ratios [ opt ] [ 1 ] ;
break ;
case A370_CPU_TO_DRAMCLK :
* mult = a370_dramclk_ratios [ opt ] [ 0 ] ;
* div = a370_dramclk_ratios [ opt ] [ 1 ] ;
break ;
}
}
2014-09-02 12:15:17 +04:00
static bool a370_is_sscg_enabled ( void __iomem * sar )
{
return ! ( readl ( sar ) & SARL_A370_SSCG_ENABLE ) ;
}
2013-05-11 05:08:05 +04:00
static const struct coreclk_soc_desc a370_coreclks = {
. get_tclk_freq = a370_get_tclk_freq ,
. get_cpu_freq = a370_get_cpu_freq ,
. get_clk_ratio = a370_get_clk_ratio ,
2014-09-02 12:15:17 +04:00
. is_sscg_enabled = a370_is_sscg_enabled ,
. fix_sscg_deviation = kirkwood_fix_sscg_deviation ,
2013-05-11 05:08:05 +04:00
. ratios = a370_coreclk_ratios ,
. num_ratios = ARRAY_SIZE ( a370_coreclk_ratios ) ,
} ;
/*
* Clock Gating Control
*/
2013-08-12 13:14:02 +04:00
static const struct clk_gating_soc_desc a370_gating_desc [ ] __initconst = {
2013-05-11 05:08:05 +04:00
{ " audio " , NULL , 0 , 0 } ,
{ " pex0_en " , NULL , 1 , 0 } ,
{ " pex1_en " , NULL , 2 , 0 } ,
{ " ge1 " , NULL , 3 , 0 } ,
{ " ge0 " , NULL , 4 , 0 } ,
{ " pex0 " , " pex0_en " , 5 , 0 } ,
{ " pex1 " , " pex1_en " , 9 , 0 } ,
{ " sata0 " , NULL , 15 , 0 } ,
{ " sdio " , NULL , 17 , 0 } ,
2015-06-16 18:56:19 +03:00
{ " crypto " , NULL , 23 , CLK_IGNORE_UNUSED } ,
2013-05-11 05:08:05 +04:00
{ " tdm " , NULL , 25 , 0 } ,
{ " ddr " , NULL , 28 , CLK_IGNORE_UNUSED } ,
{ " sata1 " , NULL , 30 , 0 } ,
{ }
} ;
2014-01-25 22:19:07 +04:00
static void __init a370_clk_init ( struct device_node * np )
2013-05-11 05:08:05 +04:00
{
2014-01-25 22:19:07 +04:00
struct device_node * cgnp =
of_find_compatible_node ( NULL , NULL , " marvell,armada-370-gating-clock " ) ;
mvebu_coreclk_setup ( np , & a370_coreclks ) ;
if ( cgnp )
mvebu_clk_gating_setup ( cgnp , a370_gating_desc ) ;
2013-05-11 05:08:05 +04:00
}
2014-01-25 22:19:07 +04:00
CLK_OF_DECLARE ( a370_clk , " marvell,armada-370-core-clock " , a370_clk_init ) ;