blob: 95a008e8b7353a0525bd0cc313080f4bd6da3930 [file] [log] [blame]
Paul Mundt6d01f512007-11-26 18:17:21 +09001/*
2 * arch/sh/kernel/cpu/sh2a/clock-sh7203.c
3 *
4 * SH7203 support for the clock framework
5 *
6 * Copyright (C) 2007 Kieran Bingham (MPC-Data Ltd)
7 *
8 * Based on clock-sh7263.c
9 * Copyright (C) 2006 Yoshinori Sato
10 *
11 * Based on clock-sh4.c
12 * Copyright (C) 2005 Paul Mundt
13 *
14 * This file is subject to the terms and conditions of the GNU General Public
15 * License. See the file "COPYING" in the main directory of this archive
16 * for more details.
17 */
18#include <linux/init.h>
19#include <linux/kernel.h>
20#include <asm/clock.h>
21#include <asm/freq.h>
22#include <asm/io.h>
23
Tobias Klauser4377e602008-02-17 15:38:35 +010024static const int pll1rate[]={8,12,16,0};
25static const int pfc_divisors[]={1,2,3,4,6,8,12};
Paul Mundt6d01f512007-11-26 18:17:21 +090026#define ifc_divisors pfc_divisors
27
Paul Mundt16b25922010-11-01 12:18:48 -040028static unsigned int pll2_mult;
Paul Mundt6d01f512007-11-26 18:17:21 +090029
30static void master_clk_init(struct clk *clk)
31{
Paul Mundt16b25922010-11-01 12:18:48 -040032 clk->rate *= pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0003] * pll2_mult;
Paul Mundt6d01f512007-11-26 18:17:21 +090033}
34
35static struct clk_ops sh7203_master_clk_ops = {
36 .init = master_clk_init,
37};
38
Paul Mundtb68d82012009-05-12 03:45:08 +090039static unsigned long module_clk_recalc(struct clk *clk)
Paul Mundt6d01f512007-11-26 18:17:21 +090040{
Paul Mundt9d56dd32010-01-26 12:58:40 +090041 int idx = (__raw_readw(FREQCR) & 0x0007);
Paul Mundtb68d82012009-05-12 03:45:08 +090042 return clk->parent->rate / pfc_divisors[idx];
Paul Mundt6d01f512007-11-26 18:17:21 +090043}
44
45static struct clk_ops sh7203_module_clk_ops = {
46 .recalc = module_clk_recalc,
47};
48
Paul Mundtb68d82012009-05-12 03:45:08 +090049static unsigned long bus_clk_recalc(struct clk *clk)
Paul Mundt6d01f512007-11-26 18:17:21 +090050{
Paul Mundt9d56dd32010-01-26 12:58:40 +090051 int idx = (__raw_readw(FREQCR) & 0x0007);
Paul Mundtb68d82012009-05-12 03:45:08 +090052 return clk->parent->rate / pfc_divisors[idx-2];
Paul Mundt6d01f512007-11-26 18:17:21 +090053}
54
55static struct clk_ops sh7203_bus_clk_ops = {
56 .recalc = bus_clk_recalc,
57};
58
Paul Mundt6d01f512007-11-26 18:17:21 +090059static struct clk_ops sh7203_cpu_clk_ops = {
Paul Mundta02cb232009-05-12 03:50:44 +090060 .recalc = followparent_recalc,
Paul Mundt6d01f512007-11-26 18:17:21 +090061};
62
63static struct clk_ops *sh7203_clk_ops[] = {
64 &sh7203_master_clk_ops,
65 &sh7203_module_clk_ops,
66 &sh7203_bus_clk_ops,
67 &sh7203_cpu_clk_ops,
68};
69
70void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
71{
Paul Mundt16b25922010-11-01 12:18:48 -040072 if (test_mode_pin(MODE_PIN1))
73 pll2_mult = 4;
74 else if (test_mode_pin(MODE_PIN0))
75 pll2_mult = 2;
76 else
77 pll2_mult = 1;
78
Paul Mundt6d01f512007-11-26 18:17:21 +090079 if (idx < ARRAY_SIZE(sh7203_clk_ops))
80 *ops = sh7203_clk_ops[idx];
81}