ARM: tegra12: set CPU rate to 2.2GHz for sku 0x87
[linux-3.10.git] / arch / arm / mach-tegra / powergate-ops-txx.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/delay.h>
16 #include <linux/tegra-powergate.h>
17
18 #include "powergate-priv.h"
19
20 int tegraxx_powergate_partition(int id,
21         struct powergate_partition_info *pg_info)
22 {
23         int ret;
24
25         /* If first clk_ptr is null, fill clk info for the partition */
26         if (pg_info->clk_info[0].clk_ptr)
27                 get_clk_info(pg_info);
28
29         powergate_partition_assert_reset(pg_info);
30
31         /* Powergating is done only if refcnt of all clks is 0 */
32         ret = is_partition_clk_disabled(pg_info);
33         if (ret)
34                 goto err_clk_off;
35
36         ret = powergate_module(id);
37         if (ret)
38                 goto err_power_off;
39
40         return 0;
41
42 err_power_off:
43         WARN(1, "Could not Powergate Partition %d", id);
44 err_clk_off:
45         WARN(1, "Could not Powergate Partition %d, all clks not disabled", id);
46         return ret;
47 }
48
49 int tegraxx_unpowergate_partition(int id,
50         struct powergate_partition_info *pg_info)
51 {
52         int ret;
53
54         /* If first clk_ptr is null, fill clk info for the partition */
55         if (!pg_info->clk_info[0].clk_ptr)
56                 get_clk_info(pg_info);
57
58         if (tegra_powergate_is_powered(id))
59                 return tegra_powergate_reset_module(pg_info);
60
61         ret = unpowergate_module(id);
62         if (ret)
63                 goto err_power;
64
65         powergate_partition_assert_reset(pg_info);
66
67         /* Un-Powergating fails if all clks are not enabled */
68         ret = partition_clk_enable(pg_info);
69         if (ret)
70                 goto err_clk_on;
71
72         udelay(10);
73
74         ret = tegra_powergate_remove_clamping(id);
75         if (ret)
76                 goto err_clamp;
77
78         udelay(10);
79
80         powergate_partition_deassert_reset(pg_info);
81
82         tegra_powergate_mc_flush_done(id);
83
84         /* Disable all clks enabled earlier. Drivers should enable clks */
85         partition_clk_disable(pg_info);
86
87         return 0;
88
89 err_clamp:
90         partition_clk_disable(pg_info);
91 err_clk_on:
92         powergate_module(id);
93 err_power:
94         WARN(1, "Could not Un-Powergate %d", id);
95
96         return ret;
97 }
98
99 int tegraxx_powergate_partition_with_clk_off(int id,
100         struct powergate_partition_info *pg_info)
101 {
102         int ret = 0;
103
104         /* Disable clks for the partition */
105         partition_clk_disable(pg_info);
106
107         ret = is_partition_clk_disabled(pg_info);
108         if (ret)
109                 goto err_powergate_clk;
110
111         ret = tegra_powergate_partition(id);
112         if (ret)
113                 goto err_powergating;
114
115         return ret;
116
117 err_powergate_clk:
118         WARN(1, "Could not Powergate Partition %d, all clks not disabled", id);
119 err_powergating:
120         ret = partition_clk_enable(pg_info);
121         if (ret)
122                 return ret;
123         WARN(1, "Could not Powergate Partition %d", id);
124         return ret;
125 }
126
127 int tegraxx_unpowergate_partition_with_clk_on(int id,
128         struct powergate_partition_info *pg_info)
129 {
130         int ret = 0;
131
132         ret = tegra_unpowergate_partition(id);
133         if (ret)
134                 goto err_unpowergating;
135
136         /* Enable clks for the partition */
137         ret = partition_clk_enable(pg_info);
138         if (ret)
139                 goto err_unpowergate_clk;
140
141         return ret;
142
143 err_unpowergate_clk:
144         tegra_powergate_partition(id);
145         WARN(1, "Could not Un-Powergate %d, err in enabling clk", id);
146 err_unpowergating:
147         WARN(1, "Could not Un-Powergate %d", id);
148
149         return ret;
150 }