ARM: tegra: loki: fix build error due to warning
[linux-3.10.git] / arch / arm / mach-tegra / tegra_emc_therm.c
1 /*
2  * arch/arm/mach-tegra/therm-dram.c
3  *
4  * Copyright (C) 2013 NVIDIA Corporation. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/debugfs.h>
23 #include <linux/kthread.h>
24 #include <linux/seq_file.h>
25 #include <linux/thermal.h>
26 #include <linux/timer.h>
27 #include <linux/atomic.h>
28
29 #include "tegra_emc.h"
30
31 #define TEGRA_DRAM_THERM_MAX_STATE     1
32
33 /* In ms - time between taking MR4 samples. */
34 static unsigned long emc_mr4_sample_interval = 1000;
35 static atomic_t do_poll;
36 static int prev_temp = -1;
37
38 static struct timer_list emc_mr4_timer;
39
40 /*
41  * Set to 1 to allow debugfs to control the mr4 read value.
42  */
43 static int test_mode;
44 static int dram_temp_override;
45
46 static void emc_mr4_poll(unsigned long nothing)
47 {
48         int dram_temp;
49
50         if (!test_mode)
51                 dram_temp = tegra_emc_get_dram_temperature();
52         else
53                 dram_temp = dram_temp_override;
54
55         if (prev_temp == dram_temp)
56                 goto reset;
57
58         switch (dram_temp) {
59         case 0:
60         case 1:
61         case 2:
62         case 3:
63                 /*
64                  * Temp is fine - go back to regular refresh.
65                  */
66                 pr_info("[dram-therm] Setting nominal refresh + timings.\n");
67                 tegra_emc_set_over_temp_state(DRAM_OVER_TEMP_NONE);
68                 break;
69         case 4:
70                 pr_info("[dram-therm] Enabling 2x refresh.\n");
71                 tegra_emc_set_over_temp_state(DRAM_OVER_TEMP_REFRESH_X2);
72                 break;
73         case 5:
74                 pr_info("[dram-therm] Enabling 4x refresh.\n");
75                 tegra_emc_set_over_temp_state(DRAM_OVER_TEMP_REFRESH_X4);
76                 break;
77         case 6:
78                 pr_info("[dram-therm] Enabling 4x refresh + derating.\n");
79                 tegra_emc_set_over_temp_state(DRAM_OVER_TEMP_THROTTLE);
80                 break;
81         default:
82                 WARN(1, "%s: Invalid DRAM temp state %d\n",
83                      __func__, dram_temp);
84                 break;
85         }
86         prev_temp = dram_temp;
87
88 reset:
89         if (atomic_read(&do_poll) == 0)
90                 return;
91
92         if (mod_timer(&emc_mr4_timer,
93                       jiffies + msecs_to_jiffies(emc_mr4_sample_interval)))
94                 pr_err("[dram-therm] Failed to restart timer!!!\n");
95 }
96
97 /*
98  * Tell the dram thermal driver to start polling for the DRAM temperature. This
99  * should be invoked when there is reason to believe the DRAM temperature is
100  * high.
101  */
102 static int tegra_dram_temp_start(void)
103 {
104         int err;
105
106         pr_info("[dram-therm] Starting DRAM temperature polling.\n");
107
108         err = mod_timer(&emc_mr4_timer,
109                         jiffies + msecs_to_jiffies(emc_mr4_sample_interval));
110         if (err)
111                 return err;
112
113         atomic_set(&do_poll, 1);
114         return mod_timer(&emc_mr4_timer,
115                          jiffies + msecs_to_jiffies(emc_mr4_sample_interval));
116 }
117
118 /*
119  * Stop the DRAM thermal driver from polling for the DRAM temperature. If there
120  * is no reason to expect the DRAM to be very hot then there is no reason to
121  * poll for the DRAM's temperature.
122  */
123 static void tegra_dram_temp_stop(void)
124 {
125         pr_info("[dram-therm] Stopping DRAM temperature polling.\n");
126         atomic_set(&do_poll, 0);
127 }
128
129 static int tegra_dram_cd_max_state(struct thermal_cooling_device *tcd,
130                                    unsigned long *state)
131 {
132         *state = TEGRA_DRAM_THERM_MAX_STATE;
133         return 0;
134 }
135
136 static int tegra_dram_cd_cur_state(struct thermal_cooling_device *tcd,
137                                    unsigned long *state)
138 {
139         *state = (unsigned long)atomic_read(&do_poll);
140         return 0;
141 }
142
143 static int tegra_dram_cd_set_state(struct thermal_cooling_device *tcd,
144                                    unsigned long state)
145 {
146         if (state == (unsigned long)atomic_read(&do_poll))
147                 return 0;
148
149         if (state)
150                 tegra_dram_temp_start();
151         else
152                 tegra_dram_temp_stop();
153         return 0;
154 }
155
156 /*
157  * Cooling device support.
158  */
159 static struct thermal_cooling_device_ops emc_dram_cd_ops = {
160         .get_max_state = tegra_dram_cd_max_state,
161         .get_cur_state = tegra_dram_cd_cur_state,
162         .set_cur_state = tegra_dram_cd_set_state,
163 };
164
165 #ifdef CONFIG_DEBUG_FS
166 static struct dentry *dram_therm_debugfs;
167
168 static int __get_sample_interval(void *data, u64 *val)
169 {
170         *val = emc_mr4_sample_interval;
171         return 0;
172 }
173 static int __set_sample_interval(void *data, u64 val)
174 {
175         emc_mr4_sample_interval = (unsigned long) val;
176         return 0;
177 }
178 DEFINE_SIMPLE_ATTRIBUTE(sample_interval_fops, __get_sample_interval,
179                         __set_sample_interval, "%llu\n");
180
181 static int __get_test_mode(void *data, u64 *val)
182 {
183         *val = test_mode;
184         return 0;
185 }
186 static int __set_test_mode(void *data, u64 val)
187 {
188         test_mode = !!val;
189         return 0;
190 }
191 DEFINE_SIMPLE_ATTRIBUTE(test_mode_fops, __get_test_mode,
192                         __set_test_mode, "%llu\n");
193
194 static int __get_dram_temp_override(void *data, u64 *val)
195 {
196         *val = dram_temp_override;
197         return 0;
198 }
199 static int __set_dram_temp_override(void *data, u64 val)
200 {
201         dram_temp_override = (unsigned int) val;
202         return 0;
203 }
204 DEFINE_SIMPLE_ATTRIBUTE(dram_temp_override_fops, __get_dram_temp_override,
205                         __set_dram_temp_override, "%llu\n");
206
207 static int __get_do_poll(void *data, u64 *val)
208 {
209         *val = atomic_read(&do_poll);
210
211         return 0;
212 }
213 static int __set_do_poll(void *data, u64 val)
214 {
215         atomic_set(&do_poll, (unsigned int)val);
216
217         /* Explicitly wake up the DRAM monitoring thread. */
218         if (atomic_read(&do_poll))
219                 tegra_dram_temp_start();
220
221         return 0;
222 }
223 DEFINE_SIMPLE_ATTRIBUTE(do_poll_fops, __get_do_poll, __set_do_poll, "%llu\n");
224 #endif
225
226 static int __init tegra_dram_therm_init(void)
227 {
228         void *ret;
229
230         ret = thermal_cooling_device_register("tegra-dram", NULL,
231                                               &emc_dram_cd_ops);
232         if (IS_ERR(ret))
233                 return PTR_ERR(ret);
234         if (ret == NULL)
235                 return -ENODEV;
236
237         setup_timer(&emc_mr4_timer, emc_mr4_poll, 0);
238
239 #ifdef CONFIG_DEBUG_FS
240         dram_therm_debugfs = debugfs_create_dir("dram-therm", NULL);
241         if (!dram_therm_debugfs)
242                 return -ENOMEM;
243
244         if (!debugfs_create_file("sample_interval", S_IRUGO | S_IWUSR,
245                                  dram_therm_debugfs, NULL,
246                                  &sample_interval_fops))
247                 return -ENOMEM;
248         if (!debugfs_create_file("test_mode", S_IRUGO | S_IWUSR,
249                                  dram_therm_debugfs, NULL, &test_mode_fops))
250                 return -ENOMEM;
251         if (!debugfs_create_file("dram_temp_override", S_IRUGO | S_IWUSR,
252                                  dram_therm_debugfs, NULL,
253                                  &dram_temp_override_fops))
254                 return -ENOMEM;
255         if (!debugfs_create_file("do_poll", S_IRUGO | S_IWUSR,
256                                  dram_therm_debugfs, NULL, &do_poll_fops))
257                 return -ENOMEM;
258 #endif
259
260         return 0;
261 }
262 late_initcall(tegra_dram_therm_init);