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 
212825999eSPeter Griffin const static int pll1rate[]={1,2,3,4,6,8};
222825999eSPeter Griffin const static int pfc_divisors[]={1,2,3,4,6,8,12};
232825999eSPeter Griffin #define ifc_divisors pfc_divisors
242825999eSPeter Griffin 
252825999eSPeter Griffin #if (CONFIG_SH_CLK_MD == 0)
262825999eSPeter Griffin #define PLL2 (4)
272825999eSPeter Griffin #elif (CONFIG_SH_CLK_MD == 2)
282825999eSPeter Griffin #define PLL2 (2)
292825999eSPeter Griffin #elif (CONFIG_SH_CLK_MD == 3)
302825999eSPeter Griffin #define PLL2 (1)
312825999eSPeter Griffin #else
322825999eSPeter Griffin #error "Illegal Clock Mode!"
332825999eSPeter Griffin #endif
342825999eSPeter Griffin 
352825999eSPeter Griffin static void master_clk_init(struct clk *clk)
362825999eSPeter Griffin {
372825999eSPeter Griffin 	clk->rate = 10000000 * PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
382825999eSPeter Griffin }
392825999eSPeter Griffin 
402825999eSPeter Griffin static struct clk_ops sh7201_master_clk_ops = {
412825999eSPeter Griffin 	.init		= master_clk_init,
422825999eSPeter Griffin };
432825999eSPeter Griffin 
442825999eSPeter Griffin static void module_clk_recalc(struct clk *clk)
452825999eSPeter Griffin {
462825999eSPeter Griffin 	int idx = (ctrl_inw(FREQCR) & 0x0007);
472825999eSPeter Griffin 	clk->rate = clk->parent->rate / pfc_divisors[idx];
482825999eSPeter Griffin }
492825999eSPeter Griffin 
502825999eSPeter Griffin static struct clk_ops sh7201_module_clk_ops = {
512825999eSPeter Griffin 	.recalc		= module_clk_recalc,
522825999eSPeter Griffin };
532825999eSPeter Griffin 
542825999eSPeter Griffin static void bus_clk_recalc(struct clk *clk)
552825999eSPeter Griffin {
562825999eSPeter Griffin 	int idx = (ctrl_inw(FREQCR) & 0x0007);
572825999eSPeter Griffin 	clk->rate = clk->parent->rate / pfc_divisors[idx];
582825999eSPeter Griffin }
592825999eSPeter Griffin 
602825999eSPeter Griffin static struct clk_ops sh7201_bus_clk_ops = {
612825999eSPeter Griffin 	.recalc		= bus_clk_recalc,
622825999eSPeter Griffin };
632825999eSPeter Griffin 
642825999eSPeter Griffin static void cpu_clk_recalc(struct clk *clk)
652825999eSPeter Griffin {
662825999eSPeter Griffin 	int idx = ((ctrl_inw(FREQCR) >> 4) & 0x0007);
672825999eSPeter Griffin 	clk->rate = clk->parent->rate / ifc_divisors[idx];
682825999eSPeter Griffin }
692825999eSPeter Griffin 
702825999eSPeter Griffin static struct clk_ops sh7201_cpu_clk_ops = {
712825999eSPeter Griffin 	.recalc		= cpu_clk_recalc,
722825999eSPeter Griffin };
732825999eSPeter Griffin 
742825999eSPeter Griffin static struct clk_ops *sh7201_clk_ops[] = {
752825999eSPeter Griffin 	&sh7201_master_clk_ops,
762825999eSPeter Griffin 	&sh7201_module_clk_ops,
772825999eSPeter Griffin 	&sh7201_bus_clk_ops,
782825999eSPeter Griffin 	&sh7201_cpu_clk_ops,
792825999eSPeter Griffin };
802825999eSPeter Griffin 
812825999eSPeter Griffin void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
822825999eSPeter Griffin {
832825999eSPeter Griffin 	if (idx < ARRAY_SIZE(sh7201_clk_ops))
842825999eSPeter Griffin 		*ops = sh7201_clk_ops[idx];
852825999eSPeter Griffin }
86