12825999eSPeter Griffin /*
22825999eSPeter Griffin  * arch/sh/kernel/cpu/sh2a/clock-sh7201.c
32825999eSPeter Griffin  *
42825999eSPeter Griffin  * SH7201 support for the clock framework
52825999eSPeter Griffin  *
62825999eSPeter Griffin  *  Copyright (C) 2008 Peter Griffin  <pgriffin@mpc-data.co.uk>
72825999eSPeter Griffin  *
82825999eSPeter Griffin  * Based on clock-sh4.c
92825999eSPeter Griffin  *  Copyright (C) 2005  Paul Mundt
102825999eSPeter Griffin  *
112825999eSPeter Griffin  * This file is subject to the terms and conditions of the GNU General Public
122825999eSPeter Griffin  * License.  See the file "COPYING" in the main directory of this archive
132825999eSPeter Griffin  * for more details.
142825999eSPeter Griffin  */
152825999eSPeter Griffin #include <linux/init.h>
162825999eSPeter Griffin #include <linux/kernel.h>
172825999eSPeter Griffin #include <asm/clock.h>
182825999eSPeter Griffin #include <asm/freq.h>
192825999eSPeter Griffin #include <asm/io.h>
202825999eSPeter Griffin 
21270c5609STobias Klauser static const int pll1rate[]={1,2,3,4,6,8};
22270c5609STobias Klauser static const int pfc_divisors[]={1,2,3,4,6,8,12};
232825999eSPeter Griffin #define ifc_divisors pfc_divisors
242825999eSPeter Griffin 
2516b25920SPaul Mundt static unsigned int pll2_mult;
262825999eSPeter Griffin 
272825999eSPeter Griffin static void master_clk_init(struct clk *clk)
282825999eSPeter Griffin {
2916b25920SPaul Mundt 	clk->rate = 10000000 * pll2_mult *
3016b25920SPaul Mundt 	       pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
312825999eSPeter Griffin }
322825999eSPeter Griffin 
332825999eSPeter Griffin static struct clk_ops sh7201_master_clk_ops = {
342825999eSPeter Griffin 	.init		= master_clk_init,
352825999eSPeter Griffin };
362825999eSPeter Griffin 
37b68d8201SPaul Mundt static unsigned long module_clk_recalc(struct clk *clk)
382825999eSPeter Griffin {
399d56dd3bSPaul Mundt 	int idx = (__raw_readw(FREQCR) & 0x0007);
40b68d8201SPaul Mundt 	return clk->parent->rate / pfc_divisors[idx];
412825999eSPeter Griffin }
422825999eSPeter Griffin 
432825999eSPeter Griffin static struct clk_ops sh7201_module_clk_ops = {
442825999eSPeter Griffin 	.recalc		= module_clk_recalc,
452825999eSPeter Griffin };
462825999eSPeter Griffin 
47b68d8201SPaul Mundt static unsigned long bus_clk_recalc(struct clk *clk)
482825999eSPeter Griffin {
499d56dd3bSPaul Mundt 	int idx = (__raw_readw(FREQCR) & 0x0007);
50b68d8201SPaul Mundt 	return clk->parent->rate / pfc_divisors[idx];
512825999eSPeter Griffin }
522825999eSPeter Griffin 
532825999eSPeter Griffin static struct clk_ops sh7201_bus_clk_ops = {
542825999eSPeter Griffin 	.recalc		= bus_clk_recalc,
552825999eSPeter Griffin };
562825999eSPeter Griffin 
57b68d8201SPaul Mundt static unsigned long cpu_clk_recalc(struct clk *clk)
582825999eSPeter Griffin {
599d56dd3bSPaul Mundt 	int idx = ((__raw_readw(FREQCR) >> 4) & 0x0007);
60b68d8201SPaul Mundt 	return clk->parent->rate / ifc_divisors[idx];
612825999eSPeter Griffin }
622825999eSPeter Griffin 
632825999eSPeter Griffin static struct clk_ops sh7201_cpu_clk_ops = {
642825999eSPeter Griffin 	.recalc		= cpu_clk_recalc,
652825999eSPeter Griffin };
662825999eSPeter Griffin 
672825999eSPeter Griffin static struct clk_ops *sh7201_clk_ops[] = {
682825999eSPeter Griffin 	&sh7201_master_clk_ops,
692825999eSPeter Griffin 	&sh7201_module_clk_ops,
702825999eSPeter Griffin 	&sh7201_bus_clk_ops,
712825999eSPeter Griffin 	&sh7201_cpu_clk_ops,
722825999eSPeter Griffin };
732825999eSPeter Griffin 
742825999eSPeter Griffin void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
752825999eSPeter Griffin {
7616b25920SPaul Mundt 	if (test_mode_pin(MODE_PIN1 | MODE_PIN0))
7716b25920SPaul Mundt 		pll2_mult = 1;
7816b25920SPaul Mundt 	else if (test_mode_pin(MODE_PIN1))
7916b25920SPaul Mundt 		pll2_mult = 2;
8016b25920SPaul Mundt 	else
8116b25920SPaul Mundt 		pll2_mult = 4;
8216b25920SPaul Mundt 
832825999eSPeter Griffin 	if (idx < ARRAY_SIZE(sh7201_clk_ops))
842825999eSPeter Griffin 		*ops = sh7201_clk_ops[idx];
852825999eSPeter Griffin }
86