aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-05-13 04:55:00 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-05-13 04:55:00 -0400
commita77b5ac0ea8e47c77008d3a9a9976dcfbc01c42a (patch)
tree981fb1cf5b98a5e98a0c02e9dd2f950dc2759231 /arch/sh/kernel
parent253b0887b3736160feac9ccdcf146a2073e41463 (diff)
sh: clkfwk: Update SH7785 for refactored clock framework.
This updates the SH7785 CPU code as well as the SH7785LCR board support code for making use of the newly refactored clock framework. Support for the legacy CPG clocks is dropped at this point, with the extal frequency fed in from the board code. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7785.c203
1 files changed, 102 insertions, 101 deletions
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
index bf5a0dacf8e5..87584dc81926 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * SH7785 support for the clock framework 4 * SH7785 support for the clock framework
5 * 5 *
6 * Copyright (C) 2007 Paul Mundt 6 * Copyright (C) 2007 - 2009 Paul Mundt
7 * 7 *
8 * This file is subject to the terms and conditions of the GNU General Public 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 9 * License. See the file "COPYING" in the main directory of this archive
@@ -11,145 +11,146 @@
11 */ 11 */
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/clk.h>
15#include <linux/io.h>
14#include <asm/clock.h> 16#include <asm/clock.h>
15#include <asm/freq.h> 17#include <asm/freq.h>
16#include <asm/io.h>
17
18static int ifc_divisors[] = { 1, 2, 4, 6 };
19static int ufc_divisors[] = { 1, 1, 4, 6 };
20static int sfc_divisors[] = { 1, 1, 4, 6 };
21static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18,
22 24, 32, 36, 48, 1, 1, 1, 1 };
23static int mfc_divisors[] = { 1, 1, 4, 6 };
24static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18,
25 24, 32, 36, 48, 1, 1, 1, 1 };
26
27static void master_clk_init(struct clk *clk)
28{
29 clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f];
30}
31 18
32static struct clk_ops sh7785_master_clk_ops = { 19static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
33 .init = master_clk_init, 20 24, 32, 36, 48 };
21struct clk_priv {
22 unsigned int shift;
34}; 23};
35 24
36static unsigned long module_clk_recalc(struct clk *clk) 25#define FRQMR_CLK_DATA(_name, _shift) \
37{ 26static struct clk_priv _name##_data = { .shift = _shift, }
38 int idx = (ctrl_inl(FRQMR1) & 0x000f);
39 return clk->parent->rate / pfc_divisors[idx];
40}
41 27
42static struct clk_ops sh7785_module_clk_ops = { 28FRQMR_CLK_DATA(pfc, 0);
43 .recalc = module_clk_recalc, 29FRQMR_CLK_DATA(s3fc, 4);
44}; 30FRQMR_CLK_DATA(s2fc, 8);
31FRQMR_CLK_DATA(mfc, 12);
32FRQMR_CLK_DATA(bfc, 16);
33FRQMR_CLK_DATA(sfc, 20);
34FRQMR_CLK_DATA(ufc, 24);
35FRQMR_CLK_DATA(ifc, 28);
45 36
46static unsigned long bus_clk_recalc(struct clk *clk) 37static unsigned long frqmr_clk_recalc(struct clk *clk)
47{ 38{
48 int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f); 39 struct clk_priv *data = clk->priv;
49 return clk->parent->rate / bfc_divisors[idx]; 40 unsigned int idx;
50}
51 41
52static struct clk_ops sh7785_bus_clk_ops = { 42 idx = (__raw_readl(FRQMR1) >> data->shift) & 0x000f;
53 .recalc = bus_clk_recalc,
54};
55 43
56static unsigned long cpu_clk_recalc(struct clk *clk) 44 /*
57{ 45 * XXX: PLL1 multiplier is locked for the default clock mode,
58 int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003); 46 * when mode pin detection and configuration support is added,
59 return clk->parent->rate / ifc_divisors[idx]; 47 * select the multiplier dynamically.
48 */
49 return clk->parent->rate * 36 / div2[idx];
60} 50}
61 51
62static struct clk_ops sh7785_cpu_clk_ops = { 52static struct clk_ops frqmr_clk_ops = {
63 .recalc = cpu_clk_recalc, 53 .recalc = frqmr_clk_recalc,
64}; 54};
65 55
66static struct clk_ops *sh7785_clk_ops[] = { 56/*
67 &sh7785_master_clk_ops, 57 * Default rate for the root input clock, reset this with clk_set_rate()
68 &sh7785_module_clk_ops, 58 * from the platform code.
69 &sh7785_bus_clk_ops, 59 */
70 &sh7785_cpu_clk_ops, 60static struct clk extal_clk = {
61 .name = "extal",
62 .id = -1,
63 .rate = 33333333,
71}; 64};
72 65
73void __init arch_init_clk_ops(struct clk_ops **ops, int idx) 66static struct clk cpu_clk = {
74{ 67 .name = "cpu_clk", /* Ick */
75 if (idx < ARRAY_SIZE(sh7785_clk_ops)) 68 .id = -1,
76 *ops = sh7785_clk_ops[idx]; 69 .ops = &frqmr_clk_ops,
77} 70 .parent = &extal_clk,
78 71 .flags = CLK_ENABLE_ON_INIT,
79static unsigned long shyway_clk_recalc(struct clk *clk) 72 .priv = &ifc_data,
80{
81 int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003);
82 return clk->parent->rate / sfc_divisors[idx];
83}
84
85static struct clk_ops sh7785_shyway_clk_ops = {
86 .recalc = shyway_clk_recalc,
87}; 73};
88 74
89static struct clk sh7785_shyway_clk = { 75static struct clk shyway_clk = {
90 .name = "shyway_clk", 76 .name = "shyway_clk", /* SHck */
77 .id = -1,
78 .ops = &frqmr_clk_ops,
79 .parent = &extal_clk,
91 .flags = CLK_ENABLE_ON_INIT, 80 .flags = CLK_ENABLE_ON_INIT,
92 .ops = &sh7785_shyway_clk_ops, 81 .priv = &sfc_data,
93}; 82};
94 83
95static unsigned long ddr_clk_recalc(struct clk *clk) 84static struct clk peripheral_clk = {
96{ 85 .name = "peripheral_clk", /* Pck */
97 int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003); 86 .id = -1,
98 return clk->parent->rate / mfc_divisors[idx]; 87 .ops = &frqmr_clk_ops,
99} 88 .parent = &extal_clk,
89 .flags = CLK_ENABLE_ON_INIT,
90 .priv = &pfc_data,
91};
100 92
101static struct clk_ops sh7785_ddr_clk_ops = { 93static struct clk ddr_clk = {
102 .recalc = ddr_clk_recalc, 94 .name = "ddr_clk", /* DDRck */
95 .id = -1,
96 .ops = &frqmr_clk_ops,
97 .parent = &extal_clk,
98 .flags = CLK_ENABLE_ON_INIT,
99 .priv = &mfc_data,
103}; 100};
104 101
105static struct clk sh7785_ddr_clk = { 102static struct clk bus_clk = {
106 .name = "ddr_clk", 103 .name = "bus_clk", /* Bck */
104 .id = -1,
105 .ops = &frqmr_clk_ops,
106 .parent = &extal_clk,
107 .flags = CLK_ENABLE_ON_INIT, 107 .flags = CLK_ENABLE_ON_INIT,
108 .ops = &sh7785_ddr_clk_ops, 108 .priv = &bfc_data,
109}; 109};
110 110
111static unsigned long ram_clk_recalc(struct clk *clk) 111static struct clk ga_clk = {
112{ 112 .name = "ga_clk", /* GAck */
113 int idx = ((ctrl_inl(FRQMR1) >> 24) & 0x0003); 113 .id = -1,
114 return clk->parent->rate / ufc_divisors[idx]; 114 .ops = &frqmr_clk_ops,
115} 115 .parent = &extal_clk,
116 .priv = &s2fc_data,
117};
116 118
117static struct clk_ops sh7785_ram_clk_ops = { 119static struct clk du_clk = {
118 .recalc = ram_clk_recalc, 120 .name = "du_clk", /* DUck */
121 .id = -1,
122 .ops = &frqmr_clk_ops,
123 .parent = &extal_clk,
124 .priv = &s3fc_data,
119}; 125};
120 126
121static struct clk sh7785_ram_clk = { 127static struct clk umem_clk = {
122 .name = "ram_clk", 128 .name = "umem_clk", /* uck */
129 .id = -1,
130 .ops = &frqmr_clk_ops,
131 .parent = &extal_clk,
123 .flags = CLK_ENABLE_ON_INIT, 132 .flags = CLK_ENABLE_ON_INIT,
124 .ops = &sh7785_ram_clk_ops, 133 .priv = &ufc_data,
125}; 134};
126 135
127/* 136static struct clk *clks[] = {
128 * Additional SH7785-specific on-chip clocks that aren't already part of the 137 &extal_clk,
129 * clock framework 138 &cpu_clk,
130 */ 139 &shyway_clk,
131static struct clk *sh7785_onchip_clocks[] = { 140 &peripheral_clk,
132 &sh7785_shyway_clk, 141 &ddr_clk,
133 &sh7785_ddr_clk, 142 &bus_clk,
134 &sh7785_ram_clk, 143 &ga_clk,
144 &du_clk,
145 &umem_clk,
135}; 146};
136 147
137int __init arch_clk_init(void) 148int __init arch_clk_init(void)
138{ 149{
139 struct clk *clk;
140 int i, ret = 0; 150 int i, ret = 0;
141 151
142 cpg_clk_init(); 152 for (i = 0; i < ARRAY_SIZE(clks); i++)
143 153 ret |= clk_register(clks[i]);
144 clk = clk_get(NULL, "master_clk");
145 for (i = 0; i < ARRAY_SIZE(sh7785_onchip_clocks); i++) {
146 struct clk *clkp = sh7785_onchip_clocks[i];
147
148 clkp->parent = clk;
149 ret |= clk_register(clkp);
150 }
151
152 clk_put(clk);
153 154
154 return ret; 155 return ret;
155} 156}