ARM: tegra: powermon: Fix copyrights from GPLv3 to GPLv2
[linux-3.10.git] / arch / arm / mach-tegra / powergate-t30.c
1 /*
2  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  */
14
15 #include <linux/spinlock.h>
16 #include <linux/delay.h>
17
18 #include <mach/powergate.h>
19
20 #include "powergate-priv.h"
21 #include "powergate-ops-txx.h"
22
23 enum mc_client {
24         MC_CLIENT_AFI           = 0,
25         MC_CLIENT_AVPC          = 1,
26         MC_CLIENT_DC            = 2,
27         MC_CLIENT_DCB           = 3,
28         MC_CLIENT_EPP           = 4,
29         MC_CLIENT_G2            = 5,
30         MC_CLIENT_HC            = 6,
31         MC_CLIENT_HDA           = 7,
32         MC_CLIENT_ISP           = 8,
33         MC_CLIENT_MPCORE        = 9,
34         MC_CLIENT_MPCORELP      = 10,
35         MC_CLIENT_MPE           = 11,
36         MC_CLIENT_NV            = 12,
37         MC_CLIENT_NV2           = 13,
38         MC_CLIENT_PPCS          = 14,
39         MC_CLIENT_SATA          = 15,
40         MC_CLIENT_VDE           = 16,
41         MC_CLIENT_VI            = 17,
42         MC_CLIENT_LAST          = -1,
43 };
44
45 struct tegra3_powergate_mc_client_info {
46         enum mc_client hot_reset_clients[MAX_HOTRESET_CLIENT_NUM];
47 };
48
49 static struct tegra3_powergate_mc_client_info tegra3_pg_mc_info[] = {
50         [TEGRA_POWERGATE_CPU] = {
51                 .hot_reset_clients = {
52                         [0] = MC_CLIENT_LAST,
53                 },
54         },
55         [TEGRA_POWERGATE_L2] = {
56                 .hot_reset_clients = {
57                         [0] = MC_CLIENT_LAST,
58                 },
59         },
60         [TEGRA_POWERGATE_3D] = {
61                 .hot_reset_clients = {
62                         [0] = MC_CLIENT_NV,
63                         [1] = MC_CLIENT_LAST,
64                 },
65         },
66 #ifdef CONFIG_ARCH_TEGRA_HAS_PCIE
67         [TEGRA_POWERGATE_PCIE] = {
68                 .hot_reset_clients ={
69                         [0] = MC_CLIENT_AFI,
70                         [1] = MC_CLIENT_LAST,
71                 },
72         },
73 #endif
74         [TEGRA_POWERGATE_VDEC] = {
75                 .hot_reset_clients = {
76                         [0] = MC_CLIENT_VDE,
77                         [1] = MC_CLIENT_LAST,
78                 },
79         },
80         [TEGRA_POWERGATE_MPE] = {
81                 .hot_reset_clients = {
82                         [0] = MC_CLIENT_MPE,
83                         [1] = MC_CLIENT_LAST,
84                 },
85         },
86         [TEGRA_POWERGATE_VENC] = {
87                 .hot_reset_clients = {
88                         [0] = MC_CLIENT_ISP,
89                         [1] = MC_CLIENT_VI,
90                         [2] = MC_CLIENT_LAST,
91                 },
92         },
93         [TEGRA_POWERGATE_CPU1] = {
94                 .hot_reset_clients = {
95                         [0] = MC_CLIENT_LAST,
96                 },
97         },
98         [TEGRA_POWERGATE_CPU2] = {
99                 .hot_reset_clients = {
100                         [0] = MC_CLIENT_LAST,
101                 },
102         },
103         [TEGRA_POWERGATE_CPU3] = {
104                 .hot_reset_clients = {
105                         [0] = MC_CLIENT_LAST,
106                 },
107         },
108         [TEGRA_POWERGATE_CELP] = {
109                 .hot_reset_clients = {
110                         [0] = MC_CLIENT_LAST,
111                 },
112         },
113 #ifdef CONFIG_ARCH_TEGRA_HAS_SATA
114         [TEGRA_POWERGATE_SATA] = {
115                 .hot_reset_clients ={
116                         [0] = MC_CLIENT_SATA,
117                         [1] = MC_CLIENT_LAST
118                 },
119         },
120 #endif
121 #ifdef CONFIG_ARCH_TEGRA_HAS_DUAL_3D
122         [TEGRA_POWERGATE_3D1] = {
123                 .hot_reset_clients = {
124                         [0] = MC_CLIENT_NV2,
125                         [1] = MC_CLIENT_LAST
126                 },
127         },
128 #endif
129         [TEGRA_POWERGATE_HEG] = {
130                 .hot_reset_clients = {
131                         [0] = MC_CLIENT_G2,
132                         [1] = MC_CLIENT_EPP,
133                         [2] = MC_CLIENT_HC,
134                         [3] = MC_CLIENT_LAST
135                 },
136         },
137 };
138
139 static struct powergate_partition_info tegra3_powergate_partition_info[] = {
140         [TEGRA_POWERGATE_CPU] = { .name = "cpu0" },
141         [TEGRA_POWERGATE_L2] = { .name = "l2" },
142         [TEGRA_POWERGATE_3D] = {
143                 .name = "3d0",
144                 .clk_info = {
145                         [0] = { .clk_name = "3d", .clk_type = CLK_AND_RST },
146                 },
147         },
148 #ifdef CONFIG_ARCH_TEGRA_HAS_PCIE
149         [TEGRA_POWERGATE_PCIE] = {
150                 .name = "pcie",
151                 .clk_info = {
152                         [0] = { .clk_name = "afi", .clk_type = CLK_AND_RST },
153                         [1] = { .clk_name = "pcie", .clk_type = CLK_AND_RST },
154                         [2] = { .clk_name = "cml0", .clk_type = CLK_ONLY },
155                         [3] = { .clk_name = "pciex", .clk_type = RST_ONLY },
156                 },
157         },
158 #endif
159         [TEGRA_POWERGATE_VDEC] = {
160                 .name = "vde",
161                 .clk_info = {
162                         [0] = { .clk_name = "vde", .clk_type = CLK_AND_RST },
163                 },
164         },
165         [TEGRA_POWERGATE_MPE] = {
166                 .name = "mpe",
167                 .clk_info = {
168                         [0] = { .clk_name = "mpe.cbus", CLK_AND_RST },
169                 },
170         },
171         [TEGRA_POWERGATE_VENC] = {
172                 .name = "ve",
173                 .clk_info = {
174                         [0] = { .clk_name = "isp", .clk_type = CLK_AND_RST },
175                         [1] = { .clk_name = "vi", .clk_type = CLK_AND_RST },
176                         [2] = { .clk_name = "csi", .clk_type = CLK_AND_RST },
177                 },
178         },
179         [TEGRA_POWERGATE_CPU1] = { .name = "cpu1" },
180         [TEGRA_POWERGATE_CPU2] = { .name = "cpu2" },
181         [TEGRA_POWERGATE_CPU3] = { .name = "cpu3" },
182         [TEGRA_POWERGATE_CELP] = { .name = "celp" },
183 #ifdef CONFIG_ARCH_TEGRA_HAS_SATA
184         [TEGRA_POWERGATE_SATA] = {
185                 .name = "sata",
186                 .clk_info = {
187                         [0] = { .clk_name = "sata", .clk_type = CLK_AND_RST },
188                         [1] = { .clk_name = "sata_oob", .clk_type = CLK_AND_RST },
189                         [2] = { .clk_name = "cml1", .clk_type = CLK_ONLY },
190                         [3] = { .clk_name = "sata_cold", .clk_type = RST_ONLY },
191                 },
192         },
193 #endif
194 #ifdef CONFIG_ARCH_TEGRA_HAS_DUAL_3D
195         [TEGRA_POWERGATE_3D1] = {
196                 .name = "3d1",
197                 .clk_info = {
198                         [0] = { .clk_name = "3d2", .clk_type = CLK_AND_RST },
199                 },
200         },
201 #endif
202         [TEGRA_POWERGATE_HEG] = {
203                 .name = "heg",
204                 .clk_info = {
205                         [0] = { .clk_name = "2d.cbus", .clk_type = CLK_AND_RST },
206                         [1] = { .clk_name = "epp.cbus", .clk_type = CLK_AND_RST },
207                         [2] = { .clk_name = "host1x.cbus", .clk_type = CLK_AND_RST },
208                 },
209         },
210 };
211
212 static u8 tegra3_quad_cpu_domains[] = {
213         TEGRA_POWERGATE_CPU0,
214         TEGRA_POWERGATE_CPU1,
215         TEGRA_POWERGATE_CPU2,
216         TEGRA_POWERGATE_CPU3,
217 };
218
219 #define MC_CLIENT_HOTRESET_CTRL         0x200
220 #define MC_CLIENT_HOTRESET_STAT         0x204
221
222 static DEFINE_SPINLOCK(tegra3_powergate_lock);
223
224 int tegra3_powergate_partition(int id)
225 {
226         return tegraxx_powergate_partition(id,
227                 &tegra3_powergate_partition_info[id]);
228 }
229
230 int tegra3_unpowergate_partition(int id)
231 {
232         return tegraxx_unpowergate_partition(id,
233                 &tegra3_powergate_partition_info[id]);
234 }
235
236 int tegra3_powergate_partition_with_clk_off(int id)
237 {
238         if (id != TEGRA_POWERGATE_PCIE && id != TEGRA_POWERGATE_SATA) {
239                 WARN_ON(1);
240                 return -EINVAL;
241         }
242
243         return tegraxx_powergate_partition_with_clk_off(id,
244                 &tegra3_powergate_partition_info[id]);
245 }
246
247 int tegra3_unpowergate_partition_with_clk_on(int id)
248 {
249         if (id != TEGRA_POWERGATE_SATA && id != TEGRA_POWERGATE_PCIE) {
250                 WARN_ON(1);
251                 return -EINVAL;
252         }
253
254         return tegraxx_unpowergate_partition_with_clk_on(id,
255                 &tegra3_powergate_partition_info[id]);
256 }
257
258 int tegra3_powergate_mc_enable(int id)
259 {
260         return 0;
261 }
262
263 int tegra3_powergate_mc_disable(int id)
264 {
265         return 0;
266 }
267
268 int tegra3_powergate_mc_flush(int id)
269 {
270         u32 idx, rst_ctrl, rst_stat;
271         enum mc_client mcClientBit;
272         unsigned long flags;
273
274         for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
275                 mcClientBit =
276                         tegra3_pg_mc_info[id].hot_reset_clients[idx];
277                 if (mcClientBit == MC_CLIENT_LAST)
278                         break;
279
280                 spin_lock_irqsave(&tegra3_powergate_lock, flags);
281                 rst_ctrl = mc_read(MC_CLIENT_HOTRESET_CTRL);
282                 rst_ctrl |= (1 << mcClientBit);
283                 mc_write(rst_ctrl, MC_CLIENT_HOTRESET_CTRL);
284                 spin_unlock_irqrestore(&tegra3_powergate_lock, flags);
285
286                 do {
287                         udelay(10);
288                         rst_stat = mc_read(MC_CLIENT_HOTRESET_STAT);
289                 } while (!(rst_stat & (1 << mcClientBit)));
290         }
291
292         return 0;
293 }
294
295 int tegra3_powergate_mc_flush_done(int id)
296 {
297         u32 idx, rst_ctrl;
298         enum mc_client mcClientBit;
299         unsigned long flags;
300
301         for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
302                 mcClientBit =
303                         tegra3_pg_mc_info[id].hot_reset_clients[idx];
304                 if (mcClientBit == MC_CLIENT_LAST)
305                         break;
306
307                 spin_lock_irqsave(&tegra3_powergate_lock, flags);
308
309                 rst_ctrl = mc_read(MC_CLIENT_HOTRESET_CTRL);
310                 rst_ctrl &= ~(1 << mcClientBit);
311                 mc_write(rst_ctrl, MC_CLIENT_HOTRESET_CTRL);
312
313                 spin_unlock_irqrestore(&tegra3_powergate_lock, flags);
314         }
315
316         wmb();
317
318         return 0;
319 }
320
321 const char *tegra3_get_powergate_domain_name(int id)
322 {
323         return tegra3_powergate_partition_info[id].name;
324 }
325
326 spinlock_t *tegra3_get_powergate_lock(void)
327 {
328         return &tegra3_powergate_lock;
329 }
330
331 static struct powergate_ops tegra3_powergate_ops = {
332         .soc_name = "tegra3",
333
334         .num_powerdomains = TEGRA_NUM_POWERGATE,
335         .num_cpu_domains = 4,
336         .cpu_domains = tegra3_quad_cpu_domains,
337
338         .get_powergate_lock = tegra3_get_powergate_lock,
339
340         .get_powergate_domain_name = tegra3_get_powergate_domain_name,
341
342         .powergate_partition = tegra3_powergate_partition,
343         .unpowergate_partition = tegra3_unpowergate_partition,
344
345         .powergate_partition_with_clk_off = tegra3_powergate_partition_with_clk_off,
346         .unpowergate_partition_with_clk_on = tegra3_unpowergate_partition_with_clk_on,
347
348         .powergate_mc_enable = tegra3_powergate_mc_enable,
349         .powergate_mc_disable = tegra3_powergate_mc_disable,
350
351         .powergate_mc_flush = tegra3_powergate_mc_flush,
352         .powergate_mc_flush_done = tegra3_powergate_mc_flush_done,
353 };
354
355 struct powergate_ops *tegra3_powergate_init_chip_support(void)
356 {
357         return &tegra3_powergate_ops;
358 }