iwlwifi: mvm: fix an overflow in iwl_mvm_get_signal_strength
[sfrench/cifs-2.6.git] / arch / arm / mach-tegra / powergate.c
1 /*
2  * drivers/powergate/tegra-powergate.c
3  *
4  * Copyright (c) 2010 Google, Inc
5  *
6  * Author:
7  *      Colin Cross <ccross@google.com>
8  *
9  * This software is licensed under the terms of the GNU General Public
10  * License version 2, as published by the Free Software Foundation, and
11  * may be copied, distributed, and modified under those terms.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  */
19
20 #include <linux/kernel.h>
21 #include <linux/clk.h>
22 #include <linux/debugfs.h>
23 #include <linux/delay.h>
24 #include <linux/err.h>
25 #include <linux/export.h>
26 #include <linux/init.h>
27 #include <linux/io.h>
28 #include <linux/reset.h>
29 #include <linux/seq_file.h>
30 #include <linux/spinlock.h>
31 #include <linux/clk/tegra.h>
32 #include <linux/tegra-powergate.h>
33
34 #include "fuse.h"
35 #include "iomap.h"
36
37 #define DPD_SAMPLE              0x020
38 #define  DPD_SAMPLE_ENABLE      (1 << 0)
39 #define  DPD_SAMPLE_DISABLE     (0 << 0)
40
41 #define PWRGATE_TOGGLE          0x30
42 #define  PWRGATE_TOGGLE_START   (1 << 8)
43
44 #define REMOVE_CLAMPING         0x34
45
46 #define PWRGATE_STATUS          0x38
47
48 #define IO_DPD_REQ              0x1b8
49 #define  IO_DPD_REQ_CODE_IDLE   (0 << 30)
50 #define  IO_DPD_REQ_CODE_OFF    (1 << 30)
51 #define  IO_DPD_REQ_CODE_ON     (2 << 30)
52 #define  IO_DPD_REQ_CODE_MASK   (3 << 30)
53
54 #define IO_DPD_STATUS           0x1bc
55 #define IO_DPD2_REQ             0x1c0
56 #define IO_DPD2_STATUS          0x1c4
57 #define SEL_DPD_TIM             0x1c8
58
59 #define GPU_RG_CNTRL            0x2d4
60
61 static int tegra_num_powerdomains;
62 static int tegra_num_cpu_domains;
63 static const u8 *tegra_cpu_domains;
64
65 static const u8 tegra30_cpu_domains[] = {
66         TEGRA_POWERGATE_CPU,
67         TEGRA_POWERGATE_CPU1,
68         TEGRA_POWERGATE_CPU2,
69         TEGRA_POWERGATE_CPU3,
70 };
71
72 static const u8 tegra114_cpu_domains[] = {
73         TEGRA_POWERGATE_CPU0,
74         TEGRA_POWERGATE_CPU1,
75         TEGRA_POWERGATE_CPU2,
76         TEGRA_POWERGATE_CPU3,
77 };
78
79 static const u8 tegra124_cpu_domains[] = {
80         TEGRA_POWERGATE_CPU0,
81         TEGRA_POWERGATE_CPU1,
82         TEGRA_POWERGATE_CPU2,
83         TEGRA_POWERGATE_CPU3,
84 };
85
86 static DEFINE_SPINLOCK(tegra_powergate_lock);
87
88 static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
89
90 static u32 pmc_read(unsigned long reg)
91 {
92         return readl(pmc + reg);
93 }
94
95 static void pmc_write(u32 val, unsigned long reg)
96 {
97         writel(val, pmc + reg);
98 }
99
100 static int tegra_powergate_set(int id, bool new_state)
101 {
102         bool status;
103         unsigned long flags;
104
105         spin_lock_irqsave(&tegra_powergate_lock, flags);
106
107         status = pmc_read(PWRGATE_STATUS) & (1 << id);
108
109         if (status == new_state) {
110                 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
111                 return 0;
112         }
113
114         pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
115
116         spin_unlock_irqrestore(&tegra_powergate_lock, flags);
117
118         return 0;
119 }
120
121 int tegra_powergate_power_on(int id)
122 {
123         if (id < 0 || id >= tegra_num_powerdomains)
124                 return -EINVAL;
125
126         return tegra_powergate_set(id, true);
127 }
128
129 int tegra_powergate_power_off(int id)
130 {
131         if (id < 0 || id >= tegra_num_powerdomains)
132                 return -EINVAL;
133
134         return tegra_powergate_set(id, false);
135 }
136 EXPORT_SYMBOL(tegra_powergate_power_off);
137
138 int tegra_powergate_is_powered(int id)
139 {
140         u32 status;
141
142         if (id < 0 || id >= tegra_num_powerdomains)
143                 return -EINVAL;
144
145         status = pmc_read(PWRGATE_STATUS) & (1 << id);
146         return !!status;
147 }
148
149 int tegra_powergate_remove_clamping(int id)
150 {
151         u32 mask;
152
153         if (id < 0 || id >= tegra_num_powerdomains)
154                 return -EINVAL;
155
156         /*
157          * The Tegra124 GPU has a separate register (with different semantics)
158          * to remove clamps.
159          */
160         if (tegra_chip_id == TEGRA124) {
161                 if (id == TEGRA_POWERGATE_3D) {
162                         pmc_write(0, GPU_RG_CNTRL);
163                         return 0;
164                 }
165         }
166
167         /*
168          * Tegra 2 has a bug where PCIE and VDE clamping masks are
169          * swapped relatively to the partition ids
170          */
171         if (id == TEGRA_POWERGATE_VDEC)
172                 mask = (1 << TEGRA_POWERGATE_PCIE);
173         else if (id == TEGRA_POWERGATE_PCIE)
174                 mask = (1 << TEGRA_POWERGATE_VDEC);
175         else
176                 mask = (1 << id);
177
178         pmc_write(mask, REMOVE_CLAMPING);
179
180         return 0;
181 }
182 EXPORT_SYMBOL(tegra_powergate_remove_clamping);
183
184 /* Must be called with clk disabled, and returns with clk enabled */
185 int tegra_powergate_sequence_power_up(int id, struct clk *clk,
186                                         struct reset_control *rst)
187 {
188         int ret;
189
190         reset_control_assert(rst);
191
192         ret = tegra_powergate_power_on(id);
193         if (ret)
194                 goto err_power;
195
196         ret = clk_prepare_enable(clk);
197         if (ret)
198                 goto err_clk;
199
200         udelay(10);
201
202         ret = tegra_powergate_remove_clamping(id);
203         if (ret)
204                 goto err_clamp;
205
206         udelay(10);
207         reset_control_deassert(rst);
208
209         return 0;
210
211 err_clamp:
212         clk_disable_unprepare(clk);
213 err_clk:
214         tegra_powergate_power_off(id);
215 err_power:
216         return ret;
217 }
218 EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
219
220 int tegra_cpu_powergate_id(int cpuid)
221 {
222         if (cpuid > 0 && cpuid < tegra_num_cpu_domains)
223                 return tegra_cpu_domains[cpuid];
224
225         return -EINVAL;
226 }
227
228 int __init tegra_powergate_init(void)
229 {
230         switch (tegra_chip_id) {
231         case TEGRA20:
232                 tegra_num_powerdomains = 7;
233                 break;
234         case TEGRA30:
235                 tegra_num_powerdomains = 14;
236                 tegra_num_cpu_domains = 4;
237                 tegra_cpu_domains = tegra30_cpu_domains;
238                 break;
239         case TEGRA114:
240                 tegra_num_powerdomains = 23;
241                 tegra_num_cpu_domains = 4;
242                 tegra_cpu_domains = tegra114_cpu_domains;
243                 break;
244         case TEGRA124:
245                 tegra_num_powerdomains = 25;
246                 tegra_num_cpu_domains = 4;
247                 tegra_cpu_domains = tegra124_cpu_domains;
248                 break;
249         default:
250                 /* Unknown Tegra variant. Disable powergating */
251                 tegra_num_powerdomains = 0;
252                 break;
253         }
254
255         return 0;
256 }
257
258 #ifdef CONFIG_DEBUG_FS
259
260 static const char * const *powergate_name;
261
262 static const char * const powergate_name_t20[] = {
263         [TEGRA_POWERGATE_CPU]   = "cpu",
264         [TEGRA_POWERGATE_3D]    = "3d",
265         [TEGRA_POWERGATE_VENC]  = "venc",
266         [TEGRA_POWERGATE_VDEC]  = "vdec",
267         [TEGRA_POWERGATE_PCIE]  = "pcie",
268         [TEGRA_POWERGATE_L2]    = "l2",
269         [TEGRA_POWERGATE_MPE]   = "mpe",
270 };
271
272 static const char * const powergate_name_t30[] = {
273         [TEGRA_POWERGATE_CPU]   = "cpu0",
274         [TEGRA_POWERGATE_3D]    = "3d0",
275         [TEGRA_POWERGATE_VENC]  = "venc",
276         [TEGRA_POWERGATE_VDEC]  = "vdec",
277         [TEGRA_POWERGATE_PCIE]  = "pcie",
278         [TEGRA_POWERGATE_L2]    = "l2",
279         [TEGRA_POWERGATE_MPE]   = "mpe",
280         [TEGRA_POWERGATE_HEG]   = "heg",
281         [TEGRA_POWERGATE_SATA]  = "sata",
282         [TEGRA_POWERGATE_CPU1]  = "cpu1",
283         [TEGRA_POWERGATE_CPU2]  = "cpu2",
284         [TEGRA_POWERGATE_CPU3]  = "cpu3",
285         [TEGRA_POWERGATE_CELP]  = "celp",
286         [TEGRA_POWERGATE_3D1]   = "3d1",
287 };
288
289 static const char * const powergate_name_t114[] = {
290         [TEGRA_POWERGATE_CPU]   = "crail",
291         [TEGRA_POWERGATE_3D]    = "3d",
292         [TEGRA_POWERGATE_VENC]  = "venc",
293         [TEGRA_POWERGATE_VDEC]  = "vdec",
294         [TEGRA_POWERGATE_MPE]   = "mpe",
295         [TEGRA_POWERGATE_HEG]   = "heg",
296         [TEGRA_POWERGATE_CPU1]  = "cpu1",
297         [TEGRA_POWERGATE_CPU2]  = "cpu2",
298         [TEGRA_POWERGATE_CPU3]  = "cpu3",
299         [TEGRA_POWERGATE_CELP]  = "celp",
300         [TEGRA_POWERGATE_CPU0]  = "cpu0",
301         [TEGRA_POWERGATE_C0NC]  = "c0nc",
302         [TEGRA_POWERGATE_C1NC]  = "c1nc",
303         [TEGRA_POWERGATE_DIS]   = "dis",
304         [TEGRA_POWERGATE_DISB]  = "disb",
305         [TEGRA_POWERGATE_XUSBA] = "xusba",
306         [TEGRA_POWERGATE_XUSBB] = "xusbb",
307         [TEGRA_POWERGATE_XUSBC] = "xusbc",
308 };
309
310 static const char * const powergate_name_t124[] = {
311         [TEGRA_POWERGATE_CPU]   = "crail",
312         [TEGRA_POWERGATE_3D]    = "3d",
313         [TEGRA_POWERGATE_VENC]  = "venc",
314         [TEGRA_POWERGATE_PCIE]  = "pcie",
315         [TEGRA_POWERGATE_VDEC]  = "vdec",
316         [TEGRA_POWERGATE_L2]    = "l2",
317         [TEGRA_POWERGATE_MPE]   = "mpe",
318         [TEGRA_POWERGATE_HEG]   = "heg",
319         [TEGRA_POWERGATE_SATA]  = "sata",
320         [TEGRA_POWERGATE_CPU1]  = "cpu1",
321         [TEGRA_POWERGATE_CPU2]  = "cpu2",
322         [TEGRA_POWERGATE_CPU3]  = "cpu3",
323         [TEGRA_POWERGATE_CELP]  = "celp",
324         [TEGRA_POWERGATE_CPU0]  = "cpu0",
325         [TEGRA_POWERGATE_C0NC]  = "c0nc",
326         [TEGRA_POWERGATE_C1NC]  = "c1nc",
327         [TEGRA_POWERGATE_SOR]   = "sor",
328         [TEGRA_POWERGATE_DIS]   = "dis",
329         [TEGRA_POWERGATE_DISB]  = "disb",
330         [TEGRA_POWERGATE_XUSBA] = "xusba",
331         [TEGRA_POWERGATE_XUSBB] = "xusbb",
332         [TEGRA_POWERGATE_XUSBC] = "xusbc",
333         [TEGRA_POWERGATE_VIC]   = "vic",
334         [TEGRA_POWERGATE_IRAM]  = "iram",
335 };
336
337 static int powergate_show(struct seq_file *s, void *data)
338 {
339         int i;
340
341         seq_printf(s, " powergate powered\n");
342         seq_printf(s, "------------------\n");
343
344         for (i = 0; i < tegra_num_powerdomains; i++) {
345                 if (!powergate_name[i])
346                         continue;
347
348                 seq_printf(s, " %9s %7s\n", powergate_name[i],
349                         tegra_powergate_is_powered(i) ? "yes" : "no");
350         }
351
352         return 0;
353 }
354
355 static int powergate_open(struct inode *inode, struct file *file)
356 {
357         return single_open(file, powergate_show, inode->i_private);
358 }
359
360 static const struct file_operations powergate_fops = {
361         .open           = powergate_open,
362         .read           = seq_read,
363         .llseek         = seq_lseek,
364         .release        = single_release,
365 };
366
367 int __init tegra_powergate_debugfs_init(void)
368 {
369         struct dentry *d;
370
371         switch (tegra_chip_id) {
372         case TEGRA20:
373                 powergate_name = powergate_name_t20;
374                 break;
375         case TEGRA30:
376                 powergate_name = powergate_name_t30;
377                 break;
378         case TEGRA114:
379                 powergate_name = powergate_name_t114;
380                 break;
381         case TEGRA124:
382                 powergate_name = powergate_name_t124;
383                 break;
384         }
385
386         if (powergate_name) {
387                 d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
388                         &powergate_fops);
389                 if (!d)
390                         return -ENOMEM;
391         }
392
393         return 0;
394 }
395
396 #endif
397
398 static int tegra_io_rail_prepare(int id, unsigned long *request,
399                                  unsigned long *status, unsigned int *bit)
400 {
401         unsigned long rate, value;
402         struct clk *clk;
403
404         *bit = id % 32;
405
406         /*
407          * There are two sets of 30 bits to select IO rails, but bits 30 and
408          * 31 are control bits rather than IO rail selection bits.
409          */
410         if (id > 63 || *bit == 30 || *bit == 31)
411                 return -EINVAL;
412
413         if (id < 32) {
414                 *status = IO_DPD_STATUS;
415                 *request = IO_DPD_REQ;
416         } else {
417                 *status = IO_DPD2_STATUS;
418                 *request = IO_DPD2_REQ;
419         }
420
421         clk = clk_get_sys(NULL, "pclk");
422         if (IS_ERR(clk))
423                 return PTR_ERR(clk);
424
425         rate = clk_get_rate(clk);
426         clk_put(clk);
427
428         pmc_write(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
429
430         /* must be at least 200 ns, in APB (PCLK) clock cycles */
431         value = DIV_ROUND_UP(1000000000, rate);
432         value = DIV_ROUND_UP(200, value);
433         pmc_write(value, SEL_DPD_TIM);
434
435         return 0;
436 }
437
438 static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
439                               unsigned long val, unsigned long timeout)
440 {
441         unsigned long value;
442
443         timeout = jiffies + msecs_to_jiffies(timeout);
444
445         while (time_after(timeout, jiffies)) {
446                 value = pmc_read(offset);
447                 if ((value & mask) == val)
448                         return 0;
449
450                 usleep_range(250, 1000);
451         }
452
453         return -ETIMEDOUT;
454 }
455
456 static void tegra_io_rail_unprepare(void)
457 {
458         pmc_write(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
459 }
460
461 int tegra_io_rail_power_on(int id)
462 {
463         unsigned long request, status, value;
464         unsigned int bit, mask;
465         int err;
466
467         err = tegra_io_rail_prepare(id, &request, &status, &bit);
468         if (err < 0)
469                 return err;
470
471         mask = 1 << bit;
472
473         value = pmc_read(request);
474         value |= mask;
475         value &= ~IO_DPD_REQ_CODE_MASK;
476         value |= IO_DPD_REQ_CODE_OFF;
477         pmc_write(value, request);
478
479         err = tegra_io_rail_poll(status, mask, 0, 250);
480         if (err < 0)
481                 return err;
482
483         tegra_io_rail_unprepare();
484
485         return 0;
486 }
487 EXPORT_SYMBOL(tegra_io_rail_power_on);
488
489 int tegra_io_rail_power_off(int id)
490 {
491         unsigned long request, status, value;
492         unsigned int bit, mask;
493         int err;
494
495         err = tegra_io_rail_prepare(id, &request, &status, &bit);
496         if (err < 0)
497                 return err;
498
499         mask = 1 << bit;
500
501         value = pmc_read(request);
502         value |= mask;
503         value &= ~IO_DPD_REQ_CODE_MASK;
504         value |= IO_DPD_REQ_CODE_ON;
505         pmc_write(value, request);
506
507         err = tegra_io_rail_poll(status, mask, mask, 250);
508         if (err < 0)
509                 return err;
510
511         tegra_io_rail_unprepare();
512
513         return 0;
514 }
515 EXPORT_SYMBOL(tegra_io_rail_power_off);