xref: /linux/arch/sh/kernel/cpu/sh2a/clock-sh7203.c (revision 4377e605e0b004a8d2049eac6cc89fbe1fdcdbb2)
16d01f510SPaul Mundt /*
26d01f510SPaul Mundt  * arch/sh/kernel/cpu/sh2a/clock-sh7203.c
36d01f510SPaul Mundt  *
46d01f510SPaul Mundt  * SH7203 support for the clock framework
56d01f510SPaul Mundt  *
66d01f510SPaul Mundt  *  Copyright (C) 2007 Kieran Bingham (MPC-Data Ltd)
76d01f510SPaul Mundt  *
86d01f510SPaul Mundt  * Based on clock-sh7263.c
96d01f510SPaul Mundt  *  Copyright (C) 2006  Yoshinori Sato
106d01f510SPaul Mundt  *
116d01f510SPaul Mundt  * Based on clock-sh4.c
126d01f510SPaul Mundt  *  Copyright (C) 2005  Paul Mundt
136d01f510SPaul Mundt  *
146d01f510SPaul Mundt  * This file is subject to the terms and conditions of the GNU General Public
156d01f510SPaul Mundt  * License.  See the file "COPYING" in the main directory of this archive
166d01f510SPaul Mundt  * for more details.
176d01f510SPaul Mundt  */
186d01f510SPaul Mundt #include <linux/init.h>
196d01f510SPaul Mundt #include <linux/kernel.h>
206d01f510SPaul Mundt #include <asm/clock.h>
216d01f510SPaul Mundt #include <asm/freq.h>
226d01f510SPaul Mundt #include <asm/io.h>
236d01f510SPaul Mundt 
24*4377e605STobias Klauser static const int pll1rate[]={8,12,16,0};
25*4377e605STobias Klauser static const int pfc_divisors[]={1,2,3,4,6,8,12};
266d01f510SPaul Mundt #define ifc_divisors pfc_divisors
276d01f510SPaul Mundt 
286d01f510SPaul Mundt #if (CONFIG_SH_CLK_MD == 0)
296d01f510SPaul Mundt #define PLL2 (1)
306d01f510SPaul Mundt #elif (CONFIG_SH_CLK_MD == 1)
316d01f510SPaul Mundt #define PLL2 (2)
326d01f510SPaul Mundt #elif (CONFIG_SH_CLK_MD == 2)
336d01f510SPaul Mundt #define PLL2 (4)
346d01f510SPaul Mundt #elif (CONFIG_SH_CLK_MD == 3)
356d01f510SPaul Mundt #define PLL2 (4)
366d01f510SPaul Mundt #else
376d01f510SPaul Mundt #error "Illegal Clock Mode!"
386d01f510SPaul Mundt #endif
396d01f510SPaul Mundt 
406d01f510SPaul Mundt static void master_clk_init(struct clk *clk)
416d01f510SPaul Mundt {
426d01f510SPaul Mundt 	clk->rate *= pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0003] * PLL2 ;
436d01f510SPaul Mundt }
446d01f510SPaul Mundt 
456d01f510SPaul Mundt static struct clk_ops sh7203_master_clk_ops = {
466d01f510SPaul Mundt 	.init		= master_clk_init,
476d01f510SPaul Mundt };
486d01f510SPaul Mundt 
496d01f510SPaul Mundt static void module_clk_recalc(struct clk *clk)
506d01f510SPaul Mundt {
516d01f510SPaul Mundt 	int idx = (ctrl_inw(FREQCR) & 0x0007);
526d01f510SPaul Mundt 	clk->rate = clk->parent->rate / pfc_divisors[idx];
536d01f510SPaul Mundt }
546d01f510SPaul Mundt 
556d01f510SPaul Mundt static struct clk_ops sh7203_module_clk_ops = {
566d01f510SPaul Mundt 	.recalc		= module_clk_recalc,
576d01f510SPaul Mundt };
586d01f510SPaul Mundt 
596d01f510SPaul Mundt static void bus_clk_recalc(struct clk *clk)
606d01f510SPaul Mundt {
616d01f510SPaul Mundt 	int idx = (ctrl_inw(FREQCR) & 0x0007);
626d01f510SPaul Mundt 	clk->rate = clk->parent->rate / pfc_divisors[idx-2];
636d01f510SPaul Mundt }
646d01f510SPaul Mundt 
656d01f510SPaul Mundt static struct clk_ops sh7203_bus_clk_ops = {
666d01f510SPaul Mundt 	.recalc		= bus_clk_recalc,
676d01f510SPaul Mundt };
686d01f510SPaul Mundt 
696d01f510SPaul Mundt static void cpu_clk_recalc(struct clk *clk)
706d01f510SPaul Mundt {
716d01f510SPaul Mundt 	clk->rate = clk->parent->rate;
726d01f510SPaul Mundt }
736d01f510SPaul Mundt 
746d01f510SPaul Mundt static struct clk_ops sh7203_cpu_clk_ops = {
756d01f510SPaul Mundt 	.recalc		= cpu_clk_recalc,
766d01f510SPaul Mundt };
776d01f510SPaul Mundt 
786d01f510SPaul Mundt static struct clk_ops *sh7203_clk_ops[] = {
796d01f510SPaul Mundt 	&sh7203_master_clk_ops,
806d01f510SPaul Mundt 	&sh7203_module_clk_ops,
816d01f510SPaul Mundt 	&sh7203_bus_clk_ops,
826d01f510SPaul Mundt 	&sh7203_cpu_clk_ops,
836d01f510SPaul Mundt };
846d01f510SPaul Mundt 
856d01f510SPaul Mundt void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
866d01f510SPaul Mundt {
876d01f510SPaul Mundt 	if (idx < ARRAY_SIZE(sh7203_clk_ops))
886d01f510SPaul Mundt 		*ops = sh7203_clk_ops[idx];
896d01f510SPaul Mundt }
90