1 /* 2 * arch/sh/kernel/cpu/sh4a/clock-sh7343.c 3 * 4 * SH7343/SH7722 support for the clock framework 5 * 6 * Copyright (C) 2006 Paul Mundt 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file "COPYING" in the main directory of this archive 10 * for more details. 11 */ 12 #include <linux/init.h> 13 #include <linux/kernel.h> 14 #include <linux/io.h> 15 #include <asm/clock.h> 16 #include <asm/freq.h> 17 18 /* 19 * SH7343/SH7722 uses a common set of multipliers and divisors, so this 20 * is quite simple.. 21 */ 22 static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 23 static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; 24 25 #define pll_calc() (((ctrl_inl(FRQCR) >> 24) & 0x1f) + 1) 26 27 static void master_clk_init(struct clk *clk) 28 { 29 clk->parent = clk_get(NULL, "cpu_clk"); 30 } 31 32 static void master_clk_recalc(struct clk *clk) 33 { 34 int idx = (ctrl_inl(FRQCR) & 0x000f); 35 clk->rate *= clk->parent->rate * multipliers[idx] / divisors[idx]; 36 } 37 38 static struct clk_ops sh7343_master_clk_ops = { 39 .init = master_clk_init, 40 .recalc = master_clk_recalc, 41 }; 42 43 static void module_clk_init(struct clk *clk) 44 { 45 clk->parent = NULL; 46 clk->rate = CONFIG_SH_PCLK_FREQ; 47 } 48 49 static struct clk_ops sh7343_module_clk_ops = { 50 .init = module_clk_init, 51 }; 52 53 static void bus_clk_init(struct clk *clk) 54 { 55 clk->parent = clk_get(NULL, "cpu_clk"); 56 } 57 58 static void bus_clk_recalc(struct clk *clk) 59 { 60 int idx = (ctrl_inl(FRQCR) >> 8) & 0x000f; 61 clk->rate = clk->parent->rate * multipliers[idx] / divisors[idx]; 62 } 63 64 static struct clk_ops sh7343_bus_clk_ops = { 65 .init = bus_clk_init, 66 .recalc = bus_clk_recalc, 67 }; 68 69 static void cpu_clk_init(struct clk *clk) 70 { 71 clk->parent = clk_get(NULL, "module_clk"); 72 clk->flags |= CLK_RATE_PROPAGATES; 73 clk_set_rate(clk, clk_get_rate(clk)); 74 } 75 76 static void cpu_clk_recalc(struct clk *clk) 77 { 78 int idx = (ctrl_inl(FRQCR) >> 20) & 0x000f; 79 clk->rate = clk->parent->rate * pll_calc() * 80 multipliers[idx] / divisors[idx]; 81 } 82 83 static struct clk_ops sh7343_cpu_clk_ops = { 84 .init = cpu_clk_init, 85 .recalc = cpu_clk_recalc, 86 }; 87 88 static struct clk_ops *sh7343_clk_ops[] = { 89 &sh7343_master_clk_ops, 90 &sh7343_module_clk_ops, 91 &sh7343_bus_clk_ops, 92 &sh7343_cpu_clk_ops, 93 }; 94 95 void __init arch_init_clk_ops(struct clk_ops **ops, int idx) 96 { 97 if (idx < ARRAY_SIZE(sh7343_clk_ops)) 98 *ops = sh7343_clk_ops[idx]; 99 } 100