diff options
author | David S. Miller <davem@davemloft.net> | 2010-02-28 22:23:06 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-28 22:23:06 -0500 |
commit | 47871889c601d8199c51a4086f77eebd77c29b0b (patch) | |
tree | 40cdcac3bff0ee40cc33dcca61d0577cdf965f77 /arch/sh/kernel/cpu/sh4a/clock-sh7786.c | |
parent | c16cc0b464b8876cfd57ce1c1dbcb6f9a6a0bce3 (diff) | |
parent | 30ff056c42c665b9ea535d8515890857ae382540 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Conflicts:
drivers/firmware/iscsi_ibft.c
Diffstat (limited to 'arch/sh/kernel/cpu/sh4a/clock-sh7786.c')
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/clock-sh7786.c | 184 |
1 files changed, 90 insertions, 94 deletions
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index a0e8869071ac..af69fd468703 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c | |||
@@ -3,11 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SH7786 support for the clock framework | 4 | * SH7786 support for the clock framework |
5 | * | 5 | * |
6 | * Copyright (C) 2008, 2009 Renesas Solutions Corp. | 6 | * Copyright (C) 2010 Paul Mundt |
7 | * Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
8 | * | ||
9 | * Based on SH7785 | ||
10 | * Copyright (C) 2007 Paul Mundt | ||
11 | * | 7 | * |
12 | * 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 |
13 | * 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 |
@@ -15,127 +11,127 @@ | |||
15 | */ | 11 | */ |
16 | #include <linux/init.h> | 12 | #include <linux/init.h> |
17 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/clk.h> | ||
15 | #include <linux/io.h> | ||
18 | #include <asm/clock.h> | 16 | #include <asm/clock.h> |
19 | #include <asm/freq.h> | 17 | #include <asm/freq.h> |
20 | #include <asm/io.h> | ||
21 | |||
22 | static int ifc_divisors[] = { 1, 2, 4, 1 }; | ||
23 | static int sfc_divisors[] = { 1, 1, 4, 1 }; | ||
24 | static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 1, | ||
25 | 24, 32, 1, 1, 1, 1, 1, 1 }; | ||
26 | static int mfc_divisors[] = { 1, 1, 4, 1 }; | ||
27 | static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 16, 1, | ||
28 | 24, 32, 1, 48, 1, 1, 1, 1 }; | ||
29 | 18 | ||
30 | static void master_clk_init(struct clk *clk) | 19 | /* |
31 | { | 20 | * Default rate for the root input clock, reset this with clk_set_rate() |
32 | clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f]; | 21 | * from the platform code. |
33 | } | 22 | */ |
34 | 23 | static struct clk extal_clk = { | |
35 | static struct clk_ops sh7786_master_clk_ops = { | 24 | .name = "extal", |
36 | .init = master_clk_init, | 25 | .id = -1, |
26 | .rate = 33333333, | ||
37 | }; | 27 | }; |
38 | 28 | ||
39 | static unsigned long module_clk_recalc(struct clk *clk) | 29 | static unsigned long pll_recalc(struct clk *clk) |
40 | { | 30 | { |
41 | int idx = (ctrl_inl(FRQMR1) & 0x000f); | 31 | int multiplier; |
42 | return clk->parent->rate / pfc_divisors[idx]; | ||
43 | } | ||
44 | 32 | ||
45 | static struct clk_ops sh7786_module_clk_ops = { | 33 | /* |
46 | .recalc = module_clk_recalc, | 34 | * Clock modes 0, 1, and 2 use an x64 multiplier against PLL1, |
47 | }; | 35 | * while modes 3, 4, and 5 use an x32. |
36 | */ | ||
37 | multiplier = (sh_mv.mv_mode_pins() & 0xf) < 3 ? 64 : 32; | ||
48 | 38 | ||
49 | static unsigned long bus_clk_recalc(struct clk *clk) | 39 | return clk->parent->rate * multiplier; |
50 | { | ||
51 | int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f); | ||
52 | return clk->parent->rate / bfc_divisors[idx]; | ||
53 | } | 40 | } |
54 | 41 | ||
55 | static struct clk_ops sh7786_bus_clk_ops = { | 42 | static struct clk_ops pll_clk_ops = { |
56 | .recalc = bus_clk_recalc, | 43 | .recalc = pll_recalc, |
57 | }; | 44 | }; |
58 | 45 | ||
59 | static unsigned long cpu_clk_recalc(struct clk *clk) | 46 | static struct clk pll_clk = { |
60 | { | 47 | .name = "pll_clk", |
61 | int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003); | 48 | .id = -1, |
62 | return clk->parent->rate / ifc_divisors[idx]; | 49 | .ops = &pll_clk_ops, |
63 | } | 50 | .parent = &extal_clk, |
64 | 51 | .flags = CLK_ENABLE_ON_INIT, | |
65 | static struct clk_ops sh7786_cpu_clk_ops = { | ||
66 | .recalc = cpu_clk_recalc, | ||
67 | }; | 52 | }; |
68 | 53 | ||
69 | static struct clk_ops *sh7786_clk_ops[] = { | 54 | static struct clk *clks[] = { |
70 | &sh7786_master_clk_ops, | 55 | &extal_clk, |
71 | &sh7786_module_clk_ops, | 56 | &pll_clk, |
72 | &sh7786_bus_clk_ops, | ||
73 | &sh7786_cpu_clk_ops, | ||
74 | }; | 57 | }; |
75 | 58 | ||
76 | void __init arch_init_clk_ops(struct clk_ops **ops, int idx) | 59 | static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18, |
77 | { | 60 | 24, 32, 36, 48 }; |
78 | if (idx < ARRAY_SIZE(sh7786_clk_ops)) | ||
79 | *ops = sh7786_clk_ops[idx]; | ||
80 | } | ||
81 | 61 | ||
82 | static unsigned long shyway_clk_recalc(struct clk *clk) | 62 | static struct clk_div_mult_table div4_div_mult_table = { |
83 | { | 63 | .divisors = div2, |
84 | int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003); | 64 | .nr_divisors = ARRAY_SIZE(div2), |
85 | return clk->parent->rate / sfc_divisors[idx]; | ||
86 | } | ||
87 | |||
88 | static struct clk_ops sh7786_shyway_clk_ops = { | ||
89 | .recalc = shyway_clk_recalc, | ||
90 | }; | 65 | }; |
91 | 66 | ||
92 | static struct clk sh7786_shyway_clk = { | 67 | static struct clk_div4_table div4_table = { |
93 | .name = "shyway_clk", | 68 | .div_mult_table = &div4_div_mult_table, |
94 | .flags = CLK_ENABLE_ON_INIT, | ||
95 | .ops = &sh7786_shyway_clk_ops, | ||
96 | }; | 69 | }; |
97 | 70 | ||
98 | static unsigned long ddr_clk_recalc(struct clk *clk) | 71 | enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_DU, DIV4_P, DIV4_NR }; |
99 | { | ||
100 | int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003); | ||
101 | return clk->parent->rate / mfc_divisors[idx]; | ||
102 | } | ||
103 | 72 | ||
104 | static struct clk_ops sh7786_ddr_clk_ops = { | 73 | #define DIV4(_str, _bit, _mask, _flags) \ |
105 | .recalc = ddr_clk_recalc, | 74 | SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags) |
106 | }; | ||
107 | 75 | ||
108 | static struct clk sh7786_ddr_clk = { | 76 | struct clk div4_clks[DIV4_NR] = { |
109 | .name = "ddr_clk", | 77 | [DIV4_P] = DIV4("peripheral_clk", 0, 0x0b40, 0), |
110 | .flags = CLK_ENABLE_ON_INIT, | 78 | [DIV4_DU] = DIV4("du_clk", 4, 0x0010, 0), |
111 | .ops = &sh7786_ddr_clk_ops, | 79 | [DIV4_DDR] = DIV4("ddr_clk", 12, 0x0002, CLK_ENABLE_ON_INIT), |
80 | [DIV4_B] = DIV4("bus_clk", 16, 0x0360, CLK_ENABLE_ON_INIT), | ||
81 | [DIV4_SH] = DIV4("shyway_clk", 20, 0x0002, CLK_ENABLE_ON_INIT), | ||
82 | [DIV4_I] = DIV4("cpu_clk", 28, 0x0006, CLK_ENABLE_ON_INIT), | ||
112 | }; | 83 | }; |
113 | 84 | ||
114 | /* | 85 | #define MSTPCR0 0xffc40030 |
115 | * Additional SH7786-specific on-chip clocks that aren't already part of the | 86 | #define MSTPCR1 0xffc40034 |
116 | * clock framework | 87 | |
117 | */ | 88 | static struct clk mstp_clks[] = { |
118 | static struct clk *sh7786_onchip_clocks[] = { | 89 | /* MSTPCR0 */ |
119 | &sh7786_shyway_clk, | 90 | SH_CLK_MSTP32("scif_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), |
120 | &sh7786_ddr_clk, | 91 | SH_CLK_MSTP32("scif_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), |
92 | SH_CLK_MSTP32("scif_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), | ||
93 | SH_CLK_MSTP32("scif_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), | ||
94 | SH_CLK_MSTP32("scif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), | ||
95 | SH_CLK_MSTP32("scif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), | ||
96 | SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0), | ||
97 | SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0), | ||
98 | SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), | ||
99 | SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), | ||
100 | SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), | ||
101 | SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), | ||
102 | SH_CLK_MSTP32("i2c_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 15, 0), | ||
103 | SH_CLK_MSTP32("i2c_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 14, 0), | ||
104 | SH_CLK_MSTP32("tmu9_11_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 11, 0), | ||
105 | SH_CLK_MSTP32("tmu678_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 10, 0), | ||
106 | SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), | ||
107 | SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), | ||
108 | SH_CLK_MSTP32("sdif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 5, 0), | ||
109 | SH_CLK_MSTP32("sdif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 4, 0), | ||
110 | SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), | ||
111 | |||
112 | /* MSTPCR1 */ | ||
113 | SH_CLK_MSTP32("usb_fck", -1, NULL, MSTPCR1, 12, 0), | ||
114 | SH_CLK_MSTP32("pcie_fck", 2, NULL, MSTPCR1, 10, 0), | ||
115 | SH_CLK_MSTP32("pcie_fck", 1, NULL, MSTPCR1, 9, 0), | ||
116 | SH_CLK_MSTP32("pcie_fck", 0, NULL, MSTPCR1, 8, 0), | ||
117 | SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), | ||
118 | SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), | ||
119 | SH_CLK_MSTP32("du_fck", -1, NULL, MSTPCR1, 3, 0), | ||
120 | SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0), | ||
121 | }; | 121 | }; |
122 | 122 | ||
123 | int __init arch_clk_init(void) | 123 | int __init arch_clk_init(void) |
124 | { | 124 | { |
125 | struct clk *clk; | ||
126 | int i, ret = 0; | 125 | int i, ret = 0; |
127 | 126 | ||
128 | cpg_clk_init(); | 127 | for (i = 0; i < ARRAY_SIZE(clks); i++) |
129 | 128 | ret |= clk_register(clks[i]); | |
130 | clk = clk_get(NULL, "master_clk"); | ||
131 | for (i = 0; i < ARRAY_SIZE(sh7786_onchip_clocks); i++) { | ||
132 | struct clk *clkp = sh7786_onchip_clocks[i]; | ||
133 | |||
134 | clkp->parent = clk; | ||
135 | ret |= clk_register(clkp); | ||
136 | } | ||
137 | 129 | ||
138 | clk_put(clk); | 130 | if (!ret) |
131 | ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), | ||
132 | &div4_table); | ||
133 | if (!ret) | ||
134 | ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); | ||
139 | 135 | ||
140 | return ret; | 136 | return ret; |
141 | } | 137 | } |