2018-09-12 15:40:17 +02:00
// SPDX-License-Identifier: GPL-2.0
2013-05-11 03:08:03 +02:00
/*
* Marvell Dove SoC clocks
*
* Copyright ( C ) 2012 Marvell
*
* Gregory CLEMENT < gregory . clement @ free - electrons . com >
* Sebastian Hesselbarth < sebastian . hesselbarth @ gmail . com >
* Andrew Lunn < andrew @ lunn . ch >
*
*/
# include <linux/kernel.h>
# include <linux/clk-provider.h>
# include <linux/io.h>
# include <linux/of.h>
# include "common.h"
2015-12-08 10:38:05 +00:00
# include "dove-divider.h"
2013-05-11 03:08:03 +02:00
/*
* Core Clocks
*
* Dove PLL sample - at - reset configuration
*
* SAR0 [ 8 : 5 ] : CPU frequency
* 5 = 1000 MHz
* 6 = 933 MHz
* 7 = 933 MHz
* 8 = 800 MHz
* 9 = 800 MHz
* 10 = 800 MHz
* 11 = 1067 MHz
* 12 = 667 MHz
* 13 = 533 MHz
* 14 = 400 MHz
* 15 = 333 MHz
* others reserved .
*
* SAR0 [ 11 : 9 ] : CPU to L2 Clock divider ratio
* 0 = ( 1 / 1 ) * CPU
* 2 = ( 1 / 2 ) * CPU
* 4 = ( 1 / 3 ) * CPU
* 6 = ( 1 / 4 ) * CPU
* others reserved .
*
* SAR0 [ 15 : 12 ] : CPU to DDR DRAM Clock divider ratio
* 0 = ( 1 / 1 ) * CPU
* 2 = ( 1 / 2 ) * CPU
* 3 = ( 2 / 5 ) * CPU
* 4 = ( 1 / 3 ) * CPU
* 6 = ( 1 / 4 ) * CPU
* 8 = ( 1 / 5 ) * CPU
* 10 = ( 1 / 6 ) * CPU
* 12 = ( 1 / 7 ) * CPU
* 14 = ( 1 / 8 ) * CPU
* 15 = ( 1 / 10 ) * CPU
* others reserved .
*
* SAR0 [ 24 : 23 ] : TCLK frequency
* 0 = 166 MHz
* 1 = 125 MHz
* others reserved .
*/
# define SAR_DOVE_CPU_FREQ 5
# define SAR_DOVE_CPU_FREQ_MASK 0xf
# define SAR_DOVE_L2_RATIO 9
# define SAR_DOVE_L2_RATIO_MASK 0x7
# define SAR_DOVE_DDR_RATIO 12
# define SAR_DOVE_DDR_RATIO_MASK 0xf
# define SAR_DOVE_TCLK_FREQ 23
# define SAR_DOVE_TCLK_FREQ_MASK 0x3
enum { DOVE_CPU_TO_L2 , DOVE_CPU_TO_DDR } ;
2013-08-12 14:44:04 +05:30
static const struct coreclk_ratio dove_coreclk_ratios [ ] __initconst = {
2013-05-11 03:08:03 +02:00
{ . id = DOVE_CPU_TO_L2 , . name = " l2clk " , } ,
{ . id = DOVE_CPU_TO_DDR , . name = " ddrclk " , }
} ;
2013-08-12 14:44:04 +05:30
static const u32 dove_tclk_freqs [ ] __initconst = {
2013-05-11 03:08:03 +02:00
166666667 ,
125000000 ,
0 , 0
} ;
static u32 __init dove_get_tclk_freq ( void __iomem * sar )
{
u32 opt = ( readl ( sar ) > > SAR_DOVE_TCLK_FREQ ) &
SAR_DOVE_TCLK_FREQ_MASK ;
return dove_tclk_freqs [ opt ] ;
}
2013-08-12 14:44:04 +05:30
static const u32 dove_cpu_freqs [ ] __initconst = {
2013-05-11 03:08:03 +02:00
0 , 0 , 0 , 0 , 0 ,
1000000000 ,
933333333 , 933333333 ,
800000000 , 800000000 , 800000000 ,
1066666667 ,
666666667 ,
533333333 ,
400000000 ,
333333333
} ;
static u32 __init dove_get_cpu_freq ( void __iomem * sar )
{
u32 opt = ( readl ( sar ) > > SAR_DOVE_CPU_FREQ ) &
SAR_DOVE_CPU_FREQ_MASK ;
return dove_cpu_freqs [ opt ] ;
}
2013-08-12 14:44:04 +05:30
static const int dove_cpu_l2_ratios [ 8 ] [ 2 ] __initconst = {
2013-05-11 03:08:03 +02:00
{ 1 , 1 } , { 0 , 1 } , { 1 , 2 } , { 0 , 1 } ,
{ 1 , 3 } , { 0 , 1 } , { 1 , 4 } , { 0 , 1 }
} ;
2013-08-12 14:44:04 +05:30
static const int dove_cpu_ddr_ratios [ 16 ] [ 2 ] __initconst = {
2013-05-11 03:08:03 +02:00
{ 1 , 1 } , { 0 , 1 } , { 1 , 2 } , { 2 , 5 } ,
{ 1 , 3 } , { 0 , 1 } , { 1 , 4 } , { 0 , 1 } ,
{ 1 , 5 } , { 0 , 1 } , { 1 , 6 } , { 0 , 1 } ,
{ 1 , 7 } , { 0 , 1 } , { 1 , 8 } , { 1 , 10 }
} ;
static void __init dove_get_clk_ratio (
void __iomem * sar , int id , int * mult , int * div )
{
switch ( id ) {
case DOVE_CPU_TO_L2 :
{
u32 opt = ( readl ( sar ) > > SAR_DOVE_L2_RATIO ) &
SAR_DOVE_L2_RATIO_MASK ;
* mult = dove_cpu_l2_ratios [ opt ] [ 0 ] ;
* div = dove_cpu_l2_ratios [ opt ] [ 1 ] ;
break ;
}
case DOVE_CPU_TO_DDR :
{
u32 opt = ( readl ( sar ) > > SAR_DOVE_DDR_RATIO ) &
SAR_DOVE_DDR_RATIO_MASK ;
* mult = dove_cpu_ddr_ratios [ opt ] [ 0 ] ;
* div = dove_cpu_ddr_ratios [ opt ] [ 1 ] ;
break ;
}
}
}
static const struct coreclk_soc_desc dove_coreclks = {
. get_tclk_freq = dove_get_tclk_freq ,
. get_cpu_freq = dove_get_cpu_freq ,
. get_clk_ratio = dove_get_clk_ratio ,
. ratios = dove_coreclk_ratios ,
. num_ratios = ARRAY_SIZE ( dove_coreclk_ratios ) ,
} ;
/*
* Clock Gating Control
*/
2013-08-12 14:44:04 +05:30
static const struct clk_gating_soc_desc dove_gating_desc [ ] __initconst = {
2013-05-11 03:08:03 +02:00
{ " usb0 " , NULL , 0 , 0 } ,
{ " usb1 " , NULL , 1 , 0 } ,
{ " ge " , " gephy " , 2 , 0 } ,
{ " sata " , NULL , 3 , 0 } ,
{ " pex0 " , NULL , 4 , 0 } ,
{ " pex1 " , NULL , 5 , 0 } ,
{ " sdio0 " , NULL , 8 , 0 } ,
{ " sdio1 " , NULL , 9 , 0 } ,
{ " nand " , NULL , 10 , 0 } ,
{ " camera " , NULL , 11 , 0 } ,
{ " i2s0 " , NULL , 12 , 0 } ,
{ " i2s1 " , NULL , 13 , 0 } ,
{ " crypto " , NULL , 15 , 0 } ,
{ " ac97 " , NULL , 21 , 0 } ,
{ " pdma " , NULL , 22 , 0 } ,
{ " xor0 " , NULL , 23 , 0 } ,
{ " xor1 " , NULL , 24 , 0 } ,
{ " gephy " , NULL , 30 , 0 } ,
{ }
} ;
2014-01-25 19:19:09 +01:00
static void __init dove_clk_init ( struct device_node * np )
2013-05-11 03:08:03 +02:00
{
2014-01-25 19:19:09 +01:00
struct device_node * cgnp =
of_find_compatible_node ( NULL , NULL , " marvell,dove-gating-clock " ) ;
2015-12-08 10:38:05 +00:00
struct device_node * ddnp =
of_find_compatible_node ( NULL , NULL , " marvell,dove-divider-clock " ) ;
2014-01-25 19:19:09 +01:00
mvebu_coreclk_setup ( np , & dove_coreclks ) ;
2018-12-26 08:50:13 -05:00
if ( ddnp ) {
2015-12-08 10:38:05 +00:00
dove_divider_clk_init ( ddnp ) ;
2018-12-26 08:50:13 -05:00
of_node_put ( ddnp ) ;
}
2015-12-08 10:38:05 +00:00
2018-12-26 08:50:13 -05:00
if ( cgnp ) {
2014-01-25 19:19:09 +01:00
mvebu_clk_gating_setup ( cgnp , dove_gating_desc ) ;
2018-12-26 08:50:13 -05:00
of_node_put ( cgnp ) ;
}
2013-05-11 03:08:03 +02:00
}
2014-01-25 19:19:09 +01:00
CLK_OF_DECLARE ( dove_clk , " marvell,dove-core-clock " , dove_clk_init ) ;