diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/Kconfig | 6 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/clock-sh7786.c | 184 |
2 files changed, 91 insertions, 99 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 8d0eabbf7460..352879c1b86b 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -551,8 +551,7 @@ config SH_PCLK_FREQ | |||
551 | CPU_SUBTYPE_SH7203 || \ | 551 | CPU_SUBTYPE_SH7203 || \ |
552 | CPU_SUBTYPE_SH7206 || \ | 552 | CPU_SUBTYPE_SH7206 || \ |
553 | CPU_SUBTYPE_SH7263 || \ | 553 | CPU_SUBTYPE_SH7263 || \ |
554 | CPU_SUBTYPE_MXG || \ | 554 | CPU_SUBTYPE_MXG |
555 | CPU_SUBTYPE_SH7786 | ||
556 | default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R | 555 | default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R |
557 | default "66000000" if CPU_SUBTYPE_SH4_202 | 556 | default "66000000" if CPU_SUBTYPE_SH4_202 |
558 | default "50000000" | 557 | default "50000000" |
@@ -566,7 +565,8 @@ config SH_CLK_CPG | |||
566 | 565 | ||
567 | config SH_CLK_CPG_LEGACY | 566 | config SH_CLK_CPG_LEGACY |
568 | depends on SH_CLK_CPG | 567 | depends on SH_CLK_CPG |
569 | def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE | 568 | def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE && \ |
569 | !CPU_SUBTYPE_SH7786 | ||
570 | 570 | ||
571 | config SH_CLK_MD | 571 | config SH_CLK_MD |
572 | int "CPU Mode Pin Setting" | 572 | int "CPU Mode Pin Setting" |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index a0e8869071ac..494c636012bb 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,123 @@ | |||
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 | |||
30 | static void master_clk_init(struct clk *clk) | ||
31 | { | ||
32 | clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f]; | ||
33 | } | ||
34 | 18 | ||
35 | static struct clk_ops sh7786_master_clk_ops = { | 19 | /* |
36 | .init = master_clk_init, | 20 | * Default rate for the root input clock, reset this with clk_set_rate() |
21 | * from the platform code. | ||
22 | */ | ||
23 | static struct clk extal_clk = { | ||
24 | .name = "extal", | ||
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 | |||
82 | static unsigned long shyway_clk_recalc(struct clk *clk) | ||
83 | { | ||
84 | int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003); | ||
85 | return clk->parent->rate / sfc_divisors[idx]; | ||
86 | } | ||
87 | 61 | ||
88 | static struct clk_ops sh7786_shyway_clk_ops = { | 62 | static struct clk_div_mult_table div4_table = { |
89 | .recalc = shyway_clk_recalc, | 63 | .divisors = div2, |
64 | .nr_divisors = ARRAY_SIZE(div2), | ||
90 | }; | 65 | }; |
91 | 66 | ||
92 | static struct clk sh7786_shyway_clk = { | 67 | enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_DU, DIV4_P, DIV4_NR }; |
93 | .name = "shyway_clk", | ||
94 | .flags = CLK_ENABLE_ON_INIT, | ||
95 | .ops = &sh7786_shyway_clk_ops, | ||
96 | }; | ||
97 | 68 | ||
98 | static unsigned long ddr_clk_recalc(struct clk *clk) | 69 | #define DIV4(_str, _bit, _mask, _flags) \ |
99 | { | 70 | SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags) |
100 | int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003); | ||
101 | return clk->parent->rate / mfc_divisors[idx]; | ||
102 | } | ||
103 | 71 | ||
104 | static struct clk_ops sh7786_ddr_clk_ops = { | 72 | struct clk div4_clks[DIV4_NR] = { |
105 | .recalc = ddr_clk_recalc, | 73 | [DIV4_P] = DIV4("peripheral_clk", 0, 0x0b40, 0), |
74 | [DIV4_DU] = DIV4("du_clk", 4, 0x0010, 0), | ||
75 | [DIV4_DDR] = DIV4("ddr_clk", 12, 0x0002, CLK_ENABLE_ON_INIT), | ||
76 | [DIV4_B] = DIV4("bus_clk", 16, 0x0360, CLK_ENABLE_ON_INIT), | ||
77 | [DIV4_SH] = DIV4("shyway_clk", 20, 0x0002, CLK_ENABLE_ON_INIT), | ||
78 | [DIV4_I] = DIV4("cpu_clk", 28, 0x0006, CLK_ENABLE_ON_INIT), | ||
106 | }; | 79 | }; |
107 | 80 | ||
108 | static struct clk sh7786_ddr_clk = { | 81 | #define MSTPCR0 0xffc40030 |
109 | .name = "ddr_clk", | 82 | #define MSTPCR1 0xffc40034 |
110 | .flags = CLK_ENABLE_ON_INIT, | 83 | |
111 | .ops = &sh7786_ddr_clk_ops, | 84 | static struct clk mstp_clks[] = { |
112 | }; | 85 | /* MSTPCR0 */ |
113 | 86 | SH_CLK_MSTP32("scif_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), | |
114 | /* | 87 | SH_CLK_MSTP32("scif_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), |
115 | * Additional SH7786-specific on-chip clocks that aren't already part of the | 88 | SH_CLK_MSTP32("scif_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), |
116 | * clock framework | 89 | SH_CLK_MSTP32("scif_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), |
117 | */ | 90 | SH_CLK_MSTP32("scif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), |
118 | static struct clk *sh7786_onchip_clocks[] = { | 91 | SH_CLK_MSTP32("scif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), |
119 | &sh7786_shyway_clk, | 92 | SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0), |
120 | &sh7786_ddr_clk, | 93 | SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0), |
94 | SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), | ||
95 | SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), | ||
96 | SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), | ||
97 | SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), | ||
98 | SH_CLK_MSTP32("i2c_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 15, 0), | ||
99 | SH_CLK_MSTP32("i2c_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 14, 0), | ||
100 | SH_CLK_MSTP32("tmu9_11_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 11, 0), | ||
101 | SH_CLK_MSTP32("tmu678_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 10, 0), | ||
102 | SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), | ||
103 | SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), | ||
104 | SH_CLK_MSTP32("sdif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 5, 0), | ||
105 | SH_CLK_MSTP32("sdif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 4, 0), | ||
106 | SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), | ||
107 | |||
108 | /* MSTPCR1 */ | ||
109 | SH_CLK_MSTP32("usb_fck", -1, NULL, MSTPCR1, 12, 0), | ||
110 | SH_CLK_MSTP32("pcie_fck", 2, NULL, MSTPCR1, 10, 0), | ||
111 | SH_CLK_MSTP32("pcie_fck", 1, NULL, MSTPCR1, 9, 0), | ||
112 | SH_CLK_MSTP32("pcie_fck", 0, NULL, MSTPCR1, 8, 0), | ||
113 | SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), | ||
114 | SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), | ||
115 | SH_CLK_MSTP32("du_fck", -1, NULL, MSTPCR1, 3, 0), | ||
116 | SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0), | ||
121 | }; | 117 | }; |
122 | 118 | ||
123 | int __init arch_clk_init(void) | 119 | int __init arch_clk_init(void) |
124 | { | 120 | { |
125 | struct clk *clk; | ||
126 | int i, ret = 0; | 121 | int i, ret = 0; |
127 | 122 | ||
128 | cpg_clk_init(); | 123 | for (i = 0; i < ARRAY_SIZE(clks); i++) |
129 | 124 | 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 | 125 | ||
138 | clk_put(clk); | 126 | if (!ret) |
127 | ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), | ||
128 | &div4_table); | ||
129 | if (!ret) | ||
130 | ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); | ||
139 | 131 | ||
140 | return ret; | 132 | return ret; |
141 | } | 133 | } |