Commit | Line | Data |
---|---|---|
8f8f484b PG |
1 | /* |
2 | * Copyright (c) 2012, 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/clk.h> | |
18 | #include <linux/clk-provider.h> | |
61fd290d PG |
19 | #include <linux/of.h> |
20 | #include <linux/clk/tegra.h> | |
8f8f484b PG |
21 | |
22 | #include "clk.h" | |
23 | ||
d5ff89a8 PDS |
24 | #define CLK_OUT_ENB_L 0x010 |
25 | #define CLK_OUT_ENB_H 0x014 | |
26 | #define CLK_OUT_ENB_U 0x018 | |
27 | #define CLK_OUT_ENB_V 0x360 | |
28 | #define CLK_OUT_ENB_W 0x364 | |
29 | #define CLK_OUT_ENB_X 0x280 | |
30 | #define CLK_OUT_ENB_SET_L 0x320 | |
31 | #define CLK_OUT_ENB_CLR_L 0x324 | |
32 | #define CLK_OUT_ENB_SET_H 0x328 | |
33 | #define CLK_OUT_ENB_CLR_H 0x32c | |
34 | #define CLK_OUT_ENB_SET_U 0x330 | |
35 | #define CLK_OUT_ENB_CLR_U 0x334 | |
36 | #define CLK_OUT_ENB_SET_V 0x440 | |
37 | #define CLK_OUT_ENB_CLR_V 0x444 | |
38 | #define CLK_OUT_ENB_SET_W 0x448 | |
39 | #define CLK_OUT_ENB_CLR_W 0x44c | |
40 | #define CLK_OUT_ENB_SET_X 0x284 | |
41 | #define CLK_OUT_ENB_CLR_X 0x288 | |
42 | ||
43 | #define RST_DEVICES_L 0x004 | |
44 | #define RST_DEVICES_H 0x008 | |
45 | #define RST_DEVICES_U 0x00C | |
46 | #define RST_DFLL_DVCO 0x2F4 | |
47 | #define RST_DEVICES_V 0x358 | |
48 | #define RST_DEVICES_W 0x35C | |
49 | #define RST_DEVICES_X 0x28C | |
50 | #define RST_DEVICES_SET_L 0x300 | |
51 | #define RST_DEVICES_CLR_L 0x304 | |
52 | #define RST_DEVICES_SET_H 0x308 | |
53 | #define RST_DEVICES_CLR_H 0x30c | |
54 | #define RST_DEVICES_SET_U 0x310 | |
55 | #define RST_DEVICES_CLR_U 0x314 | |
56 | #define RST_DEVICES_SET_V 0x430 | |
57 | #define RST_DEVICES_CLR_V 0x434 | |
58 | #define RST_DEVICES_SET_W 0x438 | |
59 | #define RST_DEVICES_CLR_W 0x43c | |
60 | ||
61fd290d | 61 | /* Global data of Tegra CPU CAR ops */ |
6a676fa0 PDS |
62 | static struct tegra_cpu_car_ops dummy_car_ops; |
63 | struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops; | |
61fd290d | 64 | |
d5ff89a8 PDS |
65 | static int periph_banks; |
66 | ||
67 | static struct tegra_clk_periph_regs periph_regs[] = { | |
68 | [0] = { | |
69 | .enb_reg = CLK_OUT_ENB_L, | |
70 | .enb_set_reg = CLK_OUT_ENB_SET_L, | |
71 | .enb_clr_reg = CLK_OUT_ENB_CLR_L, | |
72 | .rst_reg = RST_DEVICES_L, | |
73 | .rst_set_reg = RST_DEVICES_SET_L, | |
74 | .rst_clr_reg = RST_DEVICES_CLR_L, | |
75 | }, | |
76 | [1] = { | |
77 | .enb_reg = CLK_OUT_ENB_H, | |
78 | .enb_set_reg = CLK_OUT_ENB_SET_H, | |
79 | .enb_clr_reg = CLK_OUT_ENB_CLR_H, | |
80 | .rst_reg = RST_DEVICES_H, | |
81 | .rst_set_reg = RST_DEVICES_SET_H, | |
82 | .rst_clr_reg = RST_DEVICES_CLR_H, | |
83 | }, | |
84 | [2] = { | |
85 | .enb_reg = CLK_OUT_ENB_U, | |
86 | .enb_set_reg = CLK_OUT_ENB_SET_U, | |
87 | .enb_clr_reg = CLK_OUT_ENB_CLR_U, | |
88 | .rst_reg = RST_DEVICES_U, | |
89 | .rst_set_reg = RST_DEVICES_SET_U, | |
90 | .rst_clr_reg = RST_DEVICES_CLR_U, | |
91 | }, | |
92 | [3] = { | |
93 | .enb_reg = CLK_OUT_ENB_V, | |
94 | .enb_set_reg = CLK_OUT_ENB_SET_V, | |
95 | .enb_clr_reg = CLK_OUT_ENB_CLR_V, | |
96 | .rst_reg = RST_DEVICES_V, | |
97 | .rst_set_reg = RST_DEVICES_SET_V, | |
98 | .rst_clr_reg = RST_DEVICES_CLR_V, | |
99 | }, | |
100 | [4] = { | |
101 | .enb_reg = CLK_OUT_ENB_W, | |
102 | .enb_set_reg = CLK_OUT_ENB_SET_W, | |
103 | .enb_clr_reg = CLK_OUT_ENB_CLR_W, | |
104 | .rst_reg = RST_DEVICES_W, | |
105 | .rst_set_reg = RST_DEVICES_SET_W, | |
106 | .rst_clr_reg = RST_DEVICES_CLR_W, | |
107 | }, | |
108 | }; | |
109 | ||
110 | struct tegra_clk_periph_regs *get_reg_bank(int clkid) | |
111 | { | |
112 | int reg_bank = clkid / 32; | |
113 | ||
114 | if (reg_bank < periph_banks) | |
115 | return &periph_regs[reg_bank]; | |
116 | else { | |
117 | WARN_ON(1); | |
118 | return NULL; | |
119 | } | |
120 | } | |
121 | ||
122 | int __init tegra_clk_set_periph_banks(int num) | |
123 | { | |
124 | if (num > ARRAY_SIZE(periph_regs)) | |
125 | return -EINVAL; | |
126 | ||
127 | periph_banks = num; | |
128 | ||
129 | return 0; | |
130 | } | |
131 | ||
8f8f484b PG |
132 | void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, |
133 | struct clk *clks[], int clk_max) | |
134 | { | |
135 | struct clk *clk; | |
136 | ||
137 | for (; dup_list->clk_id < clk_max; dup_list++) { | |
138 | clk = clks[dup_list->clk_id]; | |
139 | dup_list->lookup.clk = clk; | |
140 | clkdev_add(&dup_list->lookup); | |
141 | } | |
142 | } | |
143 | ||
144 | void __init tegra_init_from_table(struct tegra_clk_init_table *tbl, | |
145 | struct clk *clks[], int clk_max) | |
146 | { | |
147 | struct clk *clk; | |
148 | ||
149 | for (; tbl->clk_id < clk_max; tbl++) { | |
150 | clk = clks[tbl->clk_id]; | |
151 | if (IS_ERR_OR_NULL(clk)) | |
152 | return; | |
153 | ||
154 | if (tbl->parent_id < clk_max) { | |
155 | struct clk *parent = clks[tbl->parent_id]; | |
156 | if (clk_set_parent(clk, parent)) { | |
157 | pr_err("%s: Failed to set parent %s of %s\n", | |
158 | __func__, __clk_get_name(parent), | |
159 | __clk_get_name(clk)); | |
160 | WARN_ON(1); | |
161 | } | |
162 | } | |
163 | ||
164 | if (tbl->rate) | |
165 | if (clk_set_rate(clk, tbl->rate)) { | |
166 | pr_err("%s: Failed to set rate %lu of %s\n", | |
167 | __func__, tbl->rate, | |
168 | __clk_get_name(clk)); | |
169 | WARN_ON(1); | |
170 | } | |
171 | ||
172 | if (tbl->state) | |
173 | if (clk_prepare_enable(clk)) { | |
174 | pr_err("%s: Failed to enable %s\n", __func__, | |
175 | __clk_get_name(clk)); | |
176 | WARN_ON(1); | |
177 | } | |
178 | } | |
179 | } | |
61fd290d | 180 | |
441f199a SW |
181 | tegra_clk_apply_init_table_func tegra_clk_apply_init_table; |
182 | ||
183 | void __init tegra_clocks_apply_init_table(void) | |
184 | { | |
185 | if (!tegra_clk_apply_init_table) | |
186 | return; | |
187 | ||
188 | tegra_clk_apply_init_table(); | |
189 | } |