diff options
author | Peter De Schrijver <pdeschrijver@nvidia.com> | 2013-10-15 10:19:13 -0400 |
---|---|---|
committer | Peter De Schrijver <pdeschrijver@nvidia.com> | 2013-11-26 11:46:49 -0500 |
commit | de4f30fd8403cd67449fbb9dc06a3d898fb9f10c (patch) | |
tree | b3de7152b5f04afe69b272c6e45dce33c91fae32 | |
parent | 76ebc134d45d7e6e1dc29fdcef4e539c5bc76eb8 (diff) |
clk: tegra: move PMC, fixed clocks to common files
Introduce new files for fixed and PMC clocks common between several Tegra
SoCs and move Tegra114 to this new infrastructure.
Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
-rw-r--r-- | drivers/clk/tegra/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra-fixed.c | 111 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra-pmc.c | 132 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra114.c | 75 | ||||
-rw-r--r-- | drivers/clk/tegra/clk.h | 7 |
5 files changed, 253 insertions, 74 deletions
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index 304ea5df63eb..a02e9a95a4cb 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile | |||
@@ -8,6 +8,8 @@ obj-y += clk-pll-out.o | |||
8 | obj-y += clk-super.o | 8 | obj-y += clk-super.o |
9 | obj-y += clk-tegra-audio.o | 9 | obj-y += clk-tegra-audio.o |
10 | obj-y += clk-tegra-periph.o | 10 | obj-y += clk-tegra-periph.o |
11 | obj-y += clk-tegra-pmc.o | ||
12 | obj-y += clk-tegra-fixed.o | ||
11 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o | 13 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o |
12 | obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o | 14 | obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o |
13 | obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o | 15 | obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o |
diff --git a/drivers/clk/tegra/clk-tegra-fixed.c b/drivers/clk/tegra/clk-tegra-fixed.c new file mode 100644 index 000000000000..f3b773833429 --- /dev/null +++ b/drivers/clk/tegra/clk-tegra-fixed.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/io.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/clk-provider.h> | ||
20 | #include <linux/of.h> | ||
21 | #include <linux/of_address.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/export.h> | ||
24 | #include <linux/clk/tegra.h> | ||
25 | |||
26 | #include "clk.h" | ||
27 | #include "clk-id.h" | ||
28 | |||
29 | #define OSC_CTRL 0x50 | ||
30 | #define OSC_CTRL_OSC_FREQ_SHIFT 28 | ||
31 | #define OSC_CTRL_PLL_REF_DIV_SHIFT 26 | ||
32 | |||
33 | int __init tegra_osc_clk_init(void __iomem *clk_base, | ||
34 | struct tegra_clk *tegra_clks, | ||
35 | unsigned long *input_freqs, int num, | ||
36 | unsigned long *osc_freq, | ||
37 | unsigned long *pll_ref_freq) | ||
38 | { | ||
39 | struct clk *clk; | ||
40 | struct clk **dt_clk; | ||
41 | u32 val, pll_ref_div; | ||
42 | unsigned osc_idx; | ||
43 | |||
44 | val = readl_relaxed(clk_base + OSC_CTRL); | ||
45 | osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT; | ||
46 | |||
47 | if (osc_idx < num) | ||
48 | *osc_freq = input_freqs[osc_idx]; | ||
49 | else | ||
50 | *osc_freq = 0; | ||
51 | |||
52 | if (!*osc_freq) { | ||
53 | WARN_ON(1); | ||
54 | return -EINVAL; | ||
55 | } | ||
56 | |||
57 | dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, tegra_clks); | ||
58 | if (!dt_clk) | ||
59 | return 0; | ||
60 | |||
61 | clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT, | ||
62 | *osc_freq); | ||
63 | *dt_clk = clk; | ||
64 | |||
65 | /* pll_ref */ | ||
66 | val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3; | ||
67 | pll_ref_div = 1 << val; | ||
68 | dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, tegra_clks); | ||
69 | if (!dt_clk) | ||
70 | return 0; | ||
71 | |||
72 | clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m", | ||
73 | 0, 1, pll_ref_div); | ||
74 | *dt_clk = clk; | ||
75 | |||
76 | if (pll_ref_freq) | ||
77 | *pll_ref_freq = *osc_freq / pll_ref_div; | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks) | ||
83 | { | ||
84 | struct clk *clk; | ||
85 | struct clk **dt_clk; | ||
86 | |||
87 | /* clk_32k */ | ||
88 | dt_clk = tegra_lookup_dt_id(tegra_clk_clk_32k, tegra_clks); | ||
89 | if (dt_clk) { | ||
90 | clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, | ||
91 | CLK_IS_ROOT, 32768); | ||
92 | *dt_clk = clk; | ||
93 | } | ||
94 | |||
95 | /* clk_m_div2 */ | ||
96 | dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div2, tegra_clks); | ||
97 | if (dt_clk) { | ||
98 | clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m", | ||
99 | CLK_SET_RATE_PARENT, 1, 2); | ||
100 | *dt_clk = clk; | ||
101 | } | ||
102 | |||
103 | /* clk_m_div4 */ | ||
104 | dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div4, tegra_clks); | ||
105 | if (dt_clk) { | ||
106 | clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m", | ||
107 | CLK_SET_RATE_PARENT, 1, 4); | ||
108 | *dt_clk = clk; | ||
109 | } | ||
110 | } | ||
111 | |||
diff --git a/drivers/clk/tegra/clk-tegra-pmc.c b/drivers/clk/tegra/clk-tegra-pmc.c new file mode 100644 index 000000000000..08b21c1ee867 --- /dev/null +++ b/drivers/clk/tegra/clk-tegra-pmc.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/io.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/clk-provider.h> | ||
20 | #include <linux/clkdev.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/of_address.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/export.h> | ||
25 | #include <linux/clk/tegra.h> | ||
26 | |||
27 | #include "clk.h" | ||
28 | #include "clk-id.h" | ||
29 | |||
30 | #define PMC_CLK_OUT_CNTRL 0x1a8 | ||
31 | #define PMC_DPD_PADS_ORIDE 0x1c | ||
32 | #define PMC_DPD_PADS_ORIDE_BLINK_ENB 20 | ||
33 | #define PMC_CTRL 0 | ||
34 | #define PMC_CTRL_BLINK_ENB 7 | ||
35 | #define PMC_BLINK_TIMER 0x40 | ||
36 | |||
37 | struct pmc_clk_init_data { | ||
38 | char *mux_name; | ||
39 | char *gate_name; | ||
40 | const char **parents; | ||
41 | int num_parents; | ||
42 | int mux_id; | ||
43 | int gate_id; | ||
44 | char *dev_name; | ||
45 | u8 mux_shift; | ||
46 | u8 gate_shift; | ||
47 | }; | ||
48 | |||
49 | #define PMC_CLK(_num, _mux_shift, _gate_shift)\ | ||
50 | {\ | ||
51 | .mux_name = "clk_out_" #_num "_mux",\ | ||
52 | .gate_name = "clk_out_" #_num,\ | ||
53 | .parents = clk_out ##_num ##_parents,\ | ||
54 | .num_parents = ARRAY_SIZE(clk_out ##_num ##_parents),\ | ||
55 | .mux_id = tegra_clk_clk_out_ ##_num ##_mux,\ | ||
56 | .gate_id = tegra_clk_clk_out_ ##_num,\ | ||
57 | .dev_name = "extern" #_num,\ | ||
58 | .mux_shift = _mux_shift,\ | ||
59 | .gate_shift = _gate_shift,\ | ||
60 | } | ||
61 | |||
62 | static DEFINE_SPINLOCK(clk_out_lock); | ||
63 | |||
64 | static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2", | ||
65 | "clk_m_div4", "extern1", | ||
66 | }; | ||
67 | |||
68 | static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2", | ||
69 | "clk_m_div4", "extern2", | ||
70 | }; | ||
71 | |||
72 | static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2", | ||
73 | "clk_m_div4", "extern3", | ||
74 | }; | ||
75 | |||
76 | static struct pmc_clk_init_data pmc_clks[] = { | ||
77 | PMC_CLK(1, 6, 2), | ||
78 | PMC_CLK(2, 14, 10), | ||
79 | PMC_CLK(3, 22, 18), | ||
80 | }; | ||
81 | |||
82 | void __init tegra_pmc_clk_init(void __iomem *pmc_base, | ||
83 | struct tegra_clk *tegra_clks) | ||
84 | { | ||
85 | struct clk *clk; | ||
86 | struct clk **dt_clk; | ||
87 | int i; | ||
88 | |||
89 | for (i = 0; i < ARRAY_SIZE(pmc_clks); i++) { | ||
90 | struct pmc_clk_init_data *data; | ||
91 | |||
92 | data = pmc_clks + i; | ||
93 | |||
94 | dt_clk = tegra_lookup_dt_id(data->mux_id, tegra_clks); | ||
95 | if (!dt_clk) | ||
96 | continue; | ||
97 | |||
98 | clk = clk_register_mux(NULL, data->mux_name, data->parents, | ||
99 | data->num_parents, CLK_SET_RATE_NO_REPARENT, | ||
100 | pmc_base + PMC_CLK_OUT_CNTRL, data->mux_shift, | ||
101 | 3, 0, &clk_out_lock); | ||
102 | *dt_clk = clk; | ||
103 | |||
104 | |||
105 | dt_clk = tegra_lookup_dt_id(data->gate_id, tegra_clks); | ||
106 | if (!dt_clk) | ||
107 | continue; | ||
108 | |||
109 | clk = clk_register_gate(NULL, data->gate_name, data->mux_name, | ||
110 | 0, pmc_base + PMC_CLK_OUT_CNTRL, | ||
111 | data->gate_shift, 0, &clk_out_lock); | ||
112 | *dt_clk = clk; | ||
113 | clk_register_clkdev(clk, data->dev_name, data->gate_name); | ||
114 | } | ||
115 | |||
116 | /* blink */ | ||
117 | writel_relaxed(0, pmc_base + PMC_BLINK_TIMER); | ||
118 | clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0, | ||
119 | pmc_base + PMC_DPD_PADS_ORIDE, | ||
120 | PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL); | ||
121 | |||
122 | dt_clk = tegra_lookup_dt_id(tegra_clk_blink, tegra_clks); | ||
123 | if (!dt_clk) | ||
124 | return; | ||
125 | |||
126 | clk = clk_register_gate(NULL, "blink", "blink_override", 0, | ||
127 | pmc_base + PMC_CTRL, | ||
128 | PMC_CTRL_BLINK_ENB, 0, NULL); | ||
129 | clk_register_clkdev(clk, "blink", NULL); | ||
130 | *dt_clk = clk; | ||
131 | } | ||
132 | |||
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 07098597db53..046dbed0c2c5 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c | |||
@@ -107,13 +107,6 @@ | |||
107 | #define PLLC_OUT 0x84 | 107 | #define PLLC_OUT 0x84 |
108 | #define PLLM_OUT 0x94 | 108 | #define PLLM_OUT 0x94 |
109 | 109 | ||
110 | #define PMC_CLK_OUT_CNTRL 0x1a8 | ||
111 | #define PMC_DPD_PADS_ORIDE 0x1c | ||
112 | #define PMC_DPD_PADS_ORIDE_BLINK_ENB 20 | ||
113 | #define PMC_CTRL 0 | ||
114 | #define PMC_CTRL_BLINK_ENB 7 | ||
115 | #define PMC_BLINK_TIMER 0x40 | ||
116 | |||
117 | #define OSC_CTRL 0x50 | 110 | #define OSC_CTRL 0x50 |
118 | #define OSC_CTRL_OSC_FREQ_SHIFT 28 | 111 | #define OSC_CTRL_OSC_FREQ_SHIFT 28 |
119 | #define OSC_CTRL_PLL_REF_DIV_SHIFT 26 | 112 | #define OSC_CTRL_PLL_REF_DIV_SHIFT 26 |
@@ -177,7 +170,6 @@ static DEFINE_SPINLOCK(pll_d_lock); | |||
177 | static DEFINE_SPINLOCK(pll_d2_lock); | 170 | static DEFINE_SPINLOCK(pll_d2_lock); |
178 | static DEFINE_SPINLOCK(pll_u_lock); | 171 | static DEFINE_SPINLOCK(pll_u_lock); |
179 | static DEFINE_SPINLOCK(pll_re_lock); | 172 | static DEFINE_SPINLOCK(pll_re_lock); |
180 | static DEFINE_SPINLOCK(clk_out_lock); | ||
181 | static DEFINE_SPINLOCK(sysrate_lock); | 173 | static DEFINE_SPINLOCK(sysrate_lock); |
182 | 174 | ||
183 | static struct div_nmp pllxc_nmp = { | 175 | static struct div_nmp pllxc_nmp = { |
@@ -1199,71 +1191,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, | |||
1199 | clks[TEGRA114_CLK_PLL_E_OUT0] = clk; | 1191 | clks[TEGRA114_CLK_PLL_E_OUT0] = clk; |
1200 | } | 1192 | } |
1201 | 1193 | ||
1202 | static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2", | ||
1203 | "clk_m_div4", "extern1", | ||
1204 | }; | ||
1205 | |||
1206 | static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2", | ||
1207 | "clk_m_div4", "extern2", | ||
1208 | }; | ||
1209 | |||
1210 | static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2", | ||
1211 | "clk_m_div4", "extern3", | ||
1212 | }; | ||
1213 | |||
1214 | static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) | ||
1215 | { | ||
1216 | struct clk *clk; | ||
1217 | |||
1218 | /* clk_out_1 */ | ||
1219 | clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents, | ||
1220 | ARRAY_SIZE(clk_out1_parents), | ||
1221 | CLK_SET_RATE_NO_REPARENT, | ||
1222 | pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0, | ||
1223 | &clk_out_lock); | ||
1224 | clks[TEGRA114_CLK_CLK_OUT_1_MUX] = clk; | ||
1225 | clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0, | ||
1226 | pmc_base + PMC_CLK_OUT_CNTRL, 2, 0, | ||
1227 | &clk_out_lock); | ||
1228 | clks[TEGRA114_CLK_CLK_OUT_1] = clk; | ||
1229 | |||
1230 | /* clk_out_2 */ | ||
1231 | clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents, | ||
1232 | ARRAY_SIZE(clk_out2_parents), | ||
1233 | CLK_SET_RATE_NO_REPARENT, | ||
1234 | pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0, | ||
1235 | &clk_out_lock); | ||
1236 | clks[TEGRA114_CLK_CLK_OUT_2_MUX] = clk; | ||
1237 | clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0, | ||
1238 | pmc_base + PMC_CLK_OUT_CNTRL, 10, 0, | ||
1239 | &clk_out_lock); | ||
1240 | clks[TEGRA114_CLK_CLK_OUT_2] = clk; | ||
1241 | |||
1242 | /* clk_out_3 */ | ||
1243 | clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents, | ||
1244 | ARRAY_SIZE(clk_out3_parents), | ||
1245 | CLK_SET_RATE_NO_REPARENT, | ||
1246 | pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0, | ||
1247 | &clk_out_lock); | ||
1248 | clks[TEGRA114_CLK_CLK_OUT_3_MUX] = clk; | ||
1249 | clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0, | ||
1250 | pmc_base + PMC_CLK_OUT_CNTRL, 18, 0, | ||
1251 | &clk_out_lock); | ||
1252 | clks[TEGRA114_CLK_CLK_OUT_3] = clk; | ||
1253 | |||
1254 | /* blink */ | ||
1255 | /* clear the blink timer register to directly output clk_32k */ | ||
1256 | writel_relaxed(0, pmc_base + PMC_BLINK_TIMER); | ||
1257 | clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0, | ||
1258 | pmc_base + PMC_DPD_PADS_ORIDE, | ||
1259 | PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL); | ||
1260 | clk = clk_register_gate(NULL, "blink", "blink_override", 0, | ||
1261 | pmc_base + PMC_CTRL, | ||
1262 | PMC_CTRL_BLINK_ENB, 0, NULL); | ||
1263 | clks[TEGRA114_CLK_BLINK] = clk; | ||
1264 | |||
1265 | } | ||
1266 | |||
1267 | static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", | 1194 | static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", |
1268 | "pll_p", "pll_p_out2", "unused", | 1195 | "pll_p", "pll_p_out2", "unused", |
1269 | "clk_32k", "pll_m_out1" }; | 1196 | "clk_32k", "pll_m_out1" }; |
@@ -1612,7 +1539,7 @@ static void __init tegra114_clock_init(struct device_node *np) | |||
1612 | tegra114_pll_init(clk_base, pmc_base); | 1539 | tegra114_pll_init(clk_base, pmc_base); |
1613 | tegra114_periph_clk_init(clk_base, pmc_base); | 1540 | tegra114_periph_clk_init(clk_base, pmc_base); |
1614 | tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks, &pll_a_params); | 1541 | tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks, &pll_a_params); |
1615 | tegra114_pmc_clk_init(pmc_base); | 1542 | tegra_pmc_clk_init(pmc_base, tegra114_clks); |
1616 | tegra114_super_clk_init(clk_base); | 1543 | tegra114_super_clk_init(clk_base); |
1617 | 1544 | ||
1618 | tegra_add_of_provider(np); | 1545 | tegra_add_of_provider(np); |
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 9ec6118e9b99..2d4881763902 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
@@ -604,6 +604,13 @@ void tegra_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base, | |||
604 | struct tegra_clk *tegra_clks, | 604 | struct tegra_clk *tegra_clks, |
605 | struct tegra_clk_pll_params *pll_params); | 605 | struct tegra_clk_pll_params *pll_params); |
606 | 606 | ||
607 | void tegra_pmc_clk_init(void __iomem *pmc_base, struct tegra_clk *tegra_clks); | ||
608 | void tegra_fixed_clk_init(struct tegra_clk *tegra_clks); | ||
609 | int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *tegra_clks, | ||
610 | unsigned long *input_freqs, int num, | ||
611 | unsigned long *osc_freq, | ||
612 | unsigned long *pll_ref_freq); | ||
613 | |||
607 | void tegra114_clock_tune_cpu_trimmers_high(void); | 614 | void tegra114_clock_tune_cpu_trimmers_high(void); |
608 | void tegra114_clock_tune_cpu_trimmers_low(void); | 615 | void tegra114_clock_tune_cpu_trimmers_low(void); |
609 | void tegra114_clock_tune_cpu_trimmers_init(void); | 616 | void tegra114_clock_tune_cpu_trimmers_init(void); |