2018-12-28 00:32:00 -08:00
// SPDX-License-Identifier: GPL-2.0
2008-11-28 22:48:20 +09:00
/*
* arch / sh / kernel / cpu / sh2a / clock - sh7201 . c
*
* SH7201 support for the clock framework
*
* Copyright ( C ) 2008 Peter Griffin < pgriffin @ mpc - data . co . uk >
*
* Based on clock - sh4 . c
* Copyright ( C ) 2005 Paul Mundt
*/
# include <linux/init.h>
# include <linux/kernel.h>
# include <asm/clock.h>
# include <asm/freq.h>
# include <asm/io.h>
2009-02-09 20:59:40 +00:00
static const int pll1rate [ ] = { 1 , 2 , 3 , 4 , 6 , 8 } ;
static const int pfc_divisors [ ] = { 1 , 2 , 3 , 4 , 6 , 8 , 12 } ;
2008-11-28 22:48:20 +09:00
# define ifc_divisors pfc_divisors
2010-11-01 12:18:48 -04:00
static unsigned int pll2_mult ;
2008-11-28 22:48:20 +09:00
static void master_clk_init ( struct clk * clk )
{
2010-11-01 12:18:48 -04:00
clk - > rate = 10000000 * pll2_mult *
pll1rate [ ( __raw_readw ( FREQCR ) > > 8 ) & 0x0007 ] ;
2008-11-28 22:48:20 +09:00
}
2012-02-29 22:17:32 +09:00
static struct sh_clk_ops sh7201_master_clk_ops = {
2008-11-28 22:48:20 +09:00
. init = master_clk_init ,
} ;
2009-05-12 03:45:08 +09:00
static unsigned long module_clk_recalc ( struct clk * clk )
2008-11-28 22:48:20 +09:00
{
2010-01-26 12:58:40 +09:00
int idx = ( __raw_readw ( FREQCR ) & 0x0007 ) ;
2009-05-12 03:45:08 +09:00
return clk - > parent - > rate / pfc_divisors [ idx ] ;
2008-11-28 22:48:20 +09:00
}
2012-02-29 22:17:32 +09:00
static struct sh_clk_ops sh7201_module_clk_ops = {
2008-11-28 22:48:20 +09:00
. recalc = module_clk_recalc ,
} ;
2009-05-12 03:45:08 +09:00
static unsigned long bus_clk_recalc ( struct clk * clk )
2008-11-28 22:48:20 +09:00
{
2010-01-26 12:58:40 +09:00
int idx = ( __raw_readw ( FREQCR ) & 0x0007 ) ;
2009-05-12 03:45:08 +09:00
return clk - > parent - > rate / pfc_divisors [ idx ] ;
2008-11-28 22:48:20 +09:00
}
2012-02-29 22:17:32 +09:00
static struct sh_clk_ops sh7201_bus_clk_ops = {
2008-11-28 22:48:20 +09:00
. recalc = bus_clk_recalc ,
} ;
2009-05-12 03:45:08 +09:00
static unsigned long cpu_clk_recalc ( struct clk * clk )
2008-11-28 22:48:20 +09:00
{
2010-01-26 12:58:40 +09:00
int idx = ( ( __raw_readw ( FREQCR ) > > 4 ) & 0x0007 ) ;
2009-05-12 03:45:08 +09:00
return clk - > parent - > rate / ifc_divisors [ idx ] ;
2008-11-28 22:48:20 +09:00
}
2012-02-29 22:17:32 +09:00
static struct sh_clk_ops sh7201_cpu_clk_ops = {
2008-11-28 22:48:20 +09:00
. recalc = cpu_clk_recalc ,
} ;
2012-02-29 22:17:32 +09:00
static struct sh_clk_ops * sh7201_clk_ops [ ] = {
2008-11-28 22:48:20 +09:00
& sh7201_master_clk_ops ,
& sh7201_module_clk_ops ,
& sh7201_bus_clk_ops ,
& sh7201_cpu_clk_ops ,
} ;
2012-02-29 22:17:32 +09:00
void __init arch_init_clk_ops ( struct sh_clk_ops * * ops , int idx )
2008-11-28 22:48:20 +09:00
{
2010-11-01 12:18:48 -04:00
if ( test_mode_pin ( MODE_PIN1 | MODE_PIN0 ) )
pll2_mult = 1 ;
else if ( test_mode_pin ( MODE_PIN1 ) )
pll2_mult = 2 ;
else
pll2_mult = 4 ;
2008-11-28 22:48:20 +09:00
if ( idx < ARRAY_SIZE ( sh7201_clk_ops ) )
* ops = sh7201_clk_ops [ idx ] ;
}