1234a0538SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
22825999eSPeter Griffin /*
32825999eSPeter Griffin  * arch/sh/kernel/cpu/sh2a/clock-sh7201.c
42825999eSPeter Griffin  *
52825999eSPeter Griffin  * SH7201 support for the clock framework
62825999eSPeter Griffin  *
72825999eSPeter Griffin  *  Copyright (C) 2008 Peter Griffin  <pgriffin@mpc-data.co.uk>
82825999eSPeter Griffin  *
92825999eSPeter Griffin  * Based on clock-sh4.c
102825999eSPeter Griffin  *  Copyright (C) 2005  Paul Mundt
112825999eSPeter Griffin  */
122825999eSPeter Griffin #include <linux/init.h>
132825999eSPeter Griffin #include <linux/kernel.h>
142825999eSPeter Griffin #include <asm/clock.h>
152825999eSPeter Griffin #include <asm/freq.h>
162825999eSPeter Griffin #include <asm/io.h>
172825999eSPeter Griffin 
18270c5609STobias Klauser static const int pll1rate[]={1,2,3,4,6,8};
19270c5609STobias Klauser static const int pfc_divisors[]={1,2,3,4,6,8,12};
202825999eSPeter Griffin #define ifc_divisors pfc_divisors
212825999eSPeter Griffin 
2216b25920SPaul Mundt static unsigned int pll2_mult;
232825999eSPeter Griffin 
master_clk_init(struct clk * clk)242825999eSPeter Griffin static void master_clk_init(struct clk *clk)
252825999eSPeter Griffin {
2616b25920SPaul Mundt 	clk->rate = 10000000 * pll2_mult *
2716b25920SPaul Mundt 	       pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
282825999eSPeter Griffin }
292825999eSPeter Griffin 
304ad2c061SMagnus Damm static struct sh_clk_ops sh7201_master_clk_ops = {
312825999eSPeter Griffin 	.init		= master_clk_init,
322825999eSPeter Griffin };
332825999eSPeter Griffin 
module_clk_recalc(struct clk * clk)34b68d8201SPaul Mundt static unsigned long module_clk_recalc(struct clk *clk)
352825999eSPeter Griffin {
369d56dd3bSPaul Mundt 	int idx = (__raw_readw(FREQCR) & 0x0007);
37b68d8201SPaul Mundt 	return clk->parent->rate / pfc_divisors[idx];
382825999eSPeter Griffin }
392825999eSPeter Griffin 
404ad2c061SMagnus Damm static struct sh_clk_ops sh7201_module_clk_ops = {
412825999eSPeter Griffin 	.recalc		= module_clk_recalc,
422825999eSPeter Griffin };
432825999eSPeter Griffin 
bus_clk_recalc(struct clk * clk)44b68d8201SPaul Mundt static unsigned long bus_clk_recalc(struct clk *clk)
452825999eSPeter Griffin {
469d56dd3bSPaul Mundt 	int idx = (__raw_readw(FREQCR) & 0x0007);
47b68d8201SPaul Mundt 	return clk->parent->rate / pfc_divisors[idx];
482825999eSPeter Griffin }
492825999eSPeter Griffin 
504ad2c061SMagnus Damm static struct sh_clk_ops sh7201_bus_clk_ops = {
512825999eSPeter Griffin 	.recalc		= bus_clk_recalc,
522825999eSPeter Griffin };
532825999eSPeter Griffin 
cpu_clk_recalc(struct clk * clk)54b68d8201SPaul Mundt static unsigned long cpu_clk_recalc(struct clk *clk)
552825999eSPeter Griffin {
569d56dd3bSPaul Mundt 	int idx = ((__raw_readw(FREQCR) >> 4) & 0x0007);
57b68d8201SPaul Mundt 	return clk->parent->rate / ifc_divisors[idx];
582825999eSPeter Griffin }
592825999eSPeter Griffin 
604ad2c061SMagnus Damm static struct sh_clk_ops sh7201_cpu_clk_ops = {
612825999eSPeter Griffin 	.recalc		= cpu_clk_recalc,
622825999eSPeter Griffin };
632825999eSPeter Griffin 
644ad2c061SMagnus Damm static struct sh_clk_ops *sh7201_clk_ops[] = {
652825999eSPeter Griffin 	&sh7201_master_clk_ops,
662825999eSPeter Griffin 	&sh7201_module_clk_ops,
672825999eSPeter Griffin 	&sh7201_bus_clk_ops,
682825999eSPeter Griffin 	&sh7201_cpu_clk_ops,
692825999eSPeter Griffin };
702825999eSPeter Griffin 
arch_init_clk_ops(struct sh_clk_ops ** ops,int idx)714ad2c061SMagnus Damm void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
722825999eSPeter Griffin {
7316b25920SPaul Mundt 	if (test_mode_pin(MODE_PIN1 | MODE_PIN0))
7416b25920SPaul Mundt 		pll2_mult = 1;
7516b25920SPaul Mundt 	else if (test_mode_pin(MODE_PIN1))
7616b25920SPaul Mundt 		pll2_mult = 2;
7716b25920SPaul Mundt 	else
7816b25920SPaul Mundt 		pll2_mult = 4;
7916b25920SPaul Mundt 
802825999eSPeter Griffin 	if (idx < ARRAY_SIZE(sh7201_clk_ops))
812825999eSPeter Griffin 		*ops = sh7201_clk_ops[idx];
822825999eSPeter Griffin }
83