1*234a0538SKuninori 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