ARM: tegra: thermal: Utilize hysteresis on nct
[linux-3.10.git] / arch / arm / mach-tegra / board-pluto-sensors.c
1 /*
2  * arch/arm/mach-tegra/board-pluto-sensors.c
3  *
4  * Copyright (c) 2012, 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 #include <linux/err.h>
20 #include <linux/i2c.h>
21 #include <linux/delay.h>
22 #include <linux/regulator/consumer.h>
23 #include <mach/edp.h>
24 #include <linux/gpio.h>
25 #include <linux/mpu.h>
26 #include <media/imx091.h>
27 #include <media/imx132.h>
28 #include <media/ad5816.h>
29
30 #include <linux/nct1008.h>
31 #include "gpio-names.h"
32 #include "board.h"
33 #include "board-pluto.h"
34 #include <mach/gpio.h>
35 #include "cpu-tegra.h"
36 #include "devices.h"
37 #include "tegra-board-id.h"
38
39 static struct board_info board_info;
40
41 /* isl29029 support is provided by isl29028*/
42 static struct i2c_board_info pluto_i2c1_isl_board_info[] = {
43         {
44                 I2C_BOARD_INFO("isl29028", 0x44),
45         }
46 };
47
48 struct pluto_cam_gpio {
49         int gpio;
50         const char *label;
51         int value;
52 };
53
54 static char *pluto_cam_reg_name[] = {
55         "avdd_cam1",            /* Analog VDD 2.7V */
56         "avdd_cam2",            /* Analog VDD 2.7V */
57         "vdd_1v2_cam",          /* Digital VDD 1.2V */
58         "vdd_1v8_cam12",        /* Digital VDDIO 1.8V */
59         "vddio_cam_mb",         /* CAM_I2C PULL-UP VDD 1.8V */
60         "vdd_af_cam1",          /* AF VDD */
61 };
62
63 static struct regulator *pluto_cam_reg[ARRAY_SIZE(pluto_cam_reg_name)];
64
65 static struct balanced_throttle tj_throttle = {
66         .throt_tab_size = 10,
67         .throt_tab = {
68                 {      0, 1000 },
69                 { 640000, 1000 },
70                 { 640000, 1000 },
71                 { 640000, 1000 },
72                 { 640000, 1000 },
73                 { 640000, 1000 },
74                 { 760000, 1000 },
75                 { 760000, 1050 },
76                 {1000000, 1050 },
77                 {1000000, 1100 },
78         },
79 };
80
81 static struct nct1008_platform_data pluto_nct1008_pdata = {
82         .supported_hwrev = true,
83         .ext_range = true,
84         .conv_rate = 0x08,
85         .offset = 80, /* 4 * 20C. Bug 844025 - 1C for device accuracies */
86         .shutdown_ext_limit = 90, /* C */
87         .shutdown_local_limit = 120, /* C */
88
89         /* Thermal Throttling */
90         .passive = {
91                 .create_cdev = (struct thermal_cooling_device *(*)(void *))
92                                 balanced_throttle_register,
93                 .cdev_data = &tj_throttle,
94                 .trip_temp = 80000,
95                 .tc1 = 0,
96                 .tc1 = 1,
97                 .passive_delay = 2000,
98         }
99 };
100
101 static struct i2c_board_info pluto_i2c4_nct1008_board_info[] = {
102         {
103                 I2C_BOARD_INFO("nct1008", 0x4C),
104                 .platform_data = &pluto_nct1008_pdata,
105                 .irq = -1,
106         }
107 };
108
109 static int pluto_imx091_power_on(struct device *dev)
110 {
111         int i;
112
113         for (i = 0; i < ARRAY_SIZE(pluto_cam_reg_name); i++) {
114                 if (!pluto_cam_reg[i]) {
115                         pluto_cam_reg[i] = regulator_get(dev,
116                                         pluto_cam_reg_name[i]);
117                         if (WARN_ON(IS_ERR(pluto_cam_reg[i]))) {
118                                 pr_err("%s: didn't get regulator #%d: %ld\n",
119                                 __func__, i, PTR_ERR(pluto_cam_reg[i]));
120                                 goto reg_alloc_fail;
121                         }
122                 }
123                 regulator_enable(pluto_cam_reg[i]);
124         }
125
126         gpio_direction_output(CAM_RSTN, 0);
127         gpio_direction_output(CAM_GPIO1, 1);
128         gpio_direction_output(CAM_RSTN, 1);
129
130         mdelay(1);
131
132         return 0;
133
134 reg_alloc_fail:
135
136         for (i = ARRAY_SIZE(pluto_cam_reg_name) - 1; i >= 0; i--) {
137                 if (pluto_cam_reg[i]) {
138                         regulator_put(pluto_cam_reg[i]);
139                         pluto_cam_reg[i] = NULL;
140                 }
141         }
142         pr_info("%s fail\n", __func__);
143
144         return -ENODEV;
145 }
146
147 static int pluto_imx091_power_off(struct device *dev)
148 {
149         int i;
150
151         for (i = ARRAY_SIZE(pluto_cam_reg_name) - 1; i >= 0; i--) {
152                 if (pluto_cam_reg[i]) {
153                         regulator_disable(pluto_cam_reg[i]);
154                         regulator_put(pluto_cam_reg[i]);
155                         pluto_cam_reg[i] = NULL;
156                 }
157         }
158
159         return 0;
160 }
161
162 static int pluto_imx132_power_on(struct device *dev)
163 {
164         int i;
165
166         for (i = 0; i < ARRAY_SIZE(pluto_cam_reg_name); i++) {
167                 if (!pluto_cam_reg[i]) {
168                         pluto_cam_reg[i] = regulator_get(dev,
169                                         pluto_cam_reg_name[i]);
170                         if (WARN_ON(IS_ERR(pluto_cam_reg[i]))) {
171                                 pr_err("%s: didn't get regulator #%d: %ld\n",
172                                 __func__, i, PTR_ERR(pluto_cam_reg[i]));
173                                 goto reg_alloc_fail;
174                         }
175                 }
176                 regulator_enable(pluto_cam_reg[i]);
177         }
178
179         gpio_direction_output(CAM_RSTN, 0);
180         gpio_direction_output(CAM_GPIO2, 1);
181         gpio_direction_output(CAM_RSTN, 1);
182
183         mdelay(1);
184
185         return 0;
186
187 reg_alloc_fail:
188         for (i = ARRAY_SIZE(pluto_cam_reg_name) - 1; i >= 0; i--) {
189                 if (pluto_cam_reg[i]) {
190                         regulator_put(pluto_cam_reg[i]);
191                         pluto_cam_reg[i] = NULL;
192                 }
193         }
194
195         return -ENODEV;
196 }
197
198
199 static int pluto_imx132_power_off(struct device *dev)
200 {
201         int i;
202
203         for (i = ARRAY_SIZE(pluto_cam_reg_name) - 1; i >= 0; i--) {
204                 if (pluto_cam_reg[i]) {
205                         regulator_disable(pluto_cam_reg[i]);
206                         regulator_put(pluto_cam_reg[i]);
207                         pluto_cam_reg[i] = NULL;
208                 }
209         }
210
211         return 0;
212 }
213
214 struct imx091_platform_data pluto_imx091_data = {
215         .power_on = pluto_imx091_power_on,
216         .power_off = pluto_imx091_power_off,
217 };
218
219 struct imx132_platform_data pluto_imx132_data = {
220         .power_on = pluto_imx132_power_on,
221         .power_off = pluto_imx132_power_off,
222 };
223
224 static struct ad5816_platform_data pluto_ad5816_pdata = {
225         .cfg            = 0,
226         .num            = 0,
227         .sync           = 0,
228         .dev_name       = "focuser",
229 };
230
231 static struct i2c_board_info pluto_i2c_board_info_e1625[] = {
232         {
233                 I2C_BOARD_INFO("imx091", 0x10),
234                 .platform_data = &pluto_imx091_data,
235         },
236         {
237                 I2C_BOARD_INFO("imx132", 0x36),
238                 .platform_data = &pluto_imx132_data,
239         },
240         {
241                 I2C_BOARD_INFO("ad5816", 0x0E),
242                 .platform_data = &pluto_ad5816_pdata,
243         },
244 };
245
246 #define TEGRA_CAMERA_GPIO(_gpio, _label, _value)                \
247         {                                                       \
248                 .gpio = _gpio,                                  \
249                 .label = _label,                                \
250                 .value = _value,                                \
251         }
252 static struct pluto_cam_gpio pluto_cam_gpio_data[] = {
253         [0] = TEGRA_CAMERA_GPIO(CAM1_POWER_DWN_GPIO, "camera_power_en", 1),
254         [1] = TEGRA_CAMERA_GPIO(CAM2_POWER_DWN_GPIO, "camera2_power_en", 1),
255         [2] = TEGRA_CAMERA_GPIO(CAM_GPIO1, "camera_gpio1", 0),
256         [3] = TEGRA_CAMERA_GPIO(CAM_GPIO2, "camera_gpio2", 0),
257         [4] = TEGRA_CAMERA_GPIO(CAM_RSTN, "camera_rstn", 1),
258         [5] = TEGRA_CAMERA_GPIO(CAM_AF_PWDN, "camera_af_pwdn", 1),
259 };
260
261 static int pluto_camera_init(void)
262 {
263         int ret;
264         int i;
265
266         pr_debug("%s: ++\n", __func__);
267
268         for (i = 0; i < ARRAY_SIZE(pluto_cam_gpio_data); i++) {
269                 ret = gpio_request(pluto_cam_gpio_data[i].gpio,
270                                 pluto_cam_gpio_data[i].label);
271                 if (ret < 0) {
272                         pr_err("%s: gpio_request failed for gpio #%d\n",
273                                 __func__, i);
274                         goto fail_free_gpio;
275                 }
276                 gpio_direction_output(pluto_cam_gpio_data[i].gpio,
277                                         pluto_cam_gpio_data[i].value);
278                 gpio_export(pluto_cam_gpio_data[i].gpio, false);
279         }
280
281         i2c_register_board_info(2, pluto_i2c_board_info_e1625,
282                 ARRAY_SIZE(pluto_i2c_board_info_e1625));
283
284         return 0;
285
286 fail_free_gpio:
287         while (i--)
288                 gpio_free(pluto_cam_gpio_data[i].gpio);
289         return ret;
290 }
291
292 /* MPU board file definition */
293 static struct mpu_platform_data mpu_gyro_data = {
294         .int_config     = 0x10,
295         .level_shifter  = 0,
296         .orientation    = MPU_GYRO_ORIENTATION,
297         .sec_slave_type = SECONDARY_SLAVE_TYPE_NONE,
298         .key            = {0x4E, 0xCC, 0x7E, 0xEB, 0xF6, 0x1E, 0x35, 0x22,
299                            0x00, 0x34, 0x0D, 0x65, 0x32, 0xE9, 0x94, 0x89},
300 };
301
302 static struct mpu_platform_data mpu_compass_data = {
303         .orientation    = MPU_COMPASS_ORIENTATION,
304         .sec_slave_type = SECONDARY_SLAVE_TYPE_NONE,
305 };
306
307 static struct i2c_board_info __initdata inv_mpu_i2c0_board_info[] = {
308         {
309                 I2C_BOARD_INFO(MPU_GYRO_NAME, MPU_GYRO_ADDR),
310                 .platform_data = &mpu_gyro_data,
311         },
312         {
313                 I2C_BOARD_INFO(MPU_COMPASS_NAME, MPU_COMPASS_ADDR),
314                 .platform_data = &mpu_compass_data,
315         },
316 };
317
318 static void mpuirq_init(void)
319 {
320         int ret = 0;
321         int i = 0;
322
323         pr_info("*** MPU START *** mpuirq_init...\n");
324
325         /* MPU-IRQ assignment */
326         ret = gpio_request(MPU_GYRO_IRQ_GPIO, MPU_GYRO_NAME);
327         if (ret < 0) {
328                 pr_err("%s: gpio_request failed %d\n", __func__, ret);
329                 return;
330         }
331
332         ret = gpio_direction_input(MPU_GYRO_IRQ_GPIO);
333         if (ret < 0) {
334                 pr_err("%s: gpio_direction_input failed %d\n", __func__, ret);
335                 gpio_free(MPU_GYRO_IRQ_GPIO);
336                 return;
337         }
338         pr_info("*** MPU END *** mpuirq_init...\n");
339
340         inv_mpu_i2c0_board_info[i++].irq = gpio_to_irq(MPU_GYRO_IRQ_GPIO);
341 #if MPU_COMPASS_IRQ_GPIO
342         inv_mpu_i2c0_board_info[i++].irq = gpio_to_irq(MPU_COMPASS_IRQ_GPIO);
343 #endif
344         i2c_register_board_info(MPU_GYRO_BUS_NUM, inv_mpu_i2c0_board_info,
345                 ARRAY_SIZE(inv_mpu_i2c0_board_info));
346 }
347
348 static int pluto_nct1008_init(void)
349 {
350         int nct1008_port = -1;
351         int ret = 0;
352
353 #if defined(CONFIG_ARCH_TEGRA_11x_SOC)
354         if (board_info.board_id == BOARD_E1580) {
355                 nct1008_port = TEGRA_GPIO_PX6;
356         } else {
357                 nct1008_port = TEGRA_GPIO_PX6;
358                 pr_err("Warning: nct alert port assumed TEGRA_GPIO_PX6 for unknown pluto board id E%d\n",
359                        board_info.board_id);
360         }
361 #else
362         /* pluto + AP30 interposer has SPI2_CS0 gpio */
363         nct1008_port = TEGRA_GPIO_PX3;
364 #endif
365
366         if (nct1008_port >= 0) {
367 #ifdef CONFIG_TEGRA_EDP_LIMITS
368                 const struct tegra_edp_limits *cpu_edp_limits;
369                 int cpu_edp_limits_size;
370                 int i;
371
372                 /* edp capping */
373                 tegra_get_cpu_edp_limits(&cpu_edp_limits, &cpu_edp_limits_size);
374
375                 if (cpu_edp_limits_size > MAX_THROT_TABLE_SIZE)
376                         BUG();
377
378                 for (i = 0; i < cpu_edp_limits_size-1; i++) {
379                         pluto_nct1008_pdata.active[i].create_cdev =
380                                 (struct thermal_cooling_device *(*)(void *))
381                                         edp_cooling_device_create;
382                         pluto_nct1008_pdata.active[i].cdev_data = (void *)i;
383                         pluto_nct1008_pdata.active[i].trip_temp =
384                                 cpu_edp_limits[i].temperature * 1000;
385                         pluto_nct1008_pdata.active[i].hysteresis = 1000;
386                 }
387                 pluto_nct1008_pdata.active[i].create_cdev = NULL;
388 #endif
389
390                 pluto_i2c4_nct1008_board_info[0].irq = gpio_to_irq(nct1008_port);
391                 pr_info("%s: pluto nct1008 irq %d", __func__, pluto_i2c4_nct1008_board_info[0].irq);
392
393                 ret = gpio_request(nct1008_port, "temp_alert");
394                 if (ret < 0)
395                         return ret;
396
397                 ret = gpio_direction_input(nct1008_port);
398                 if (ret < 0) {
399                         pr_info("%s: calling gpio_free(nct1008_port)", __func__);
400                         gpio_free(nct1008_port);
401                 }
402         }
403
404         /* pluto has thermal sensor on GEN1-I2C i.e. instance 0 */
405         i2c_register_board_info(0, pluto_i2c4_nct1008_board_info,
406                 ARRAY_SIZE(pluto_i2c4_nct1008_board_info));
407
408         return ret;
409 }
410
411 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
412 static int tegra_skin_match(struct thermal_zone_device *thz, void *data)
413 {
414         return strcmp((char *)data, thz->type) == 0;
415 }
416
417 static int tegra_skin_get_temp(void *data, long *temp)
418 {
419         struct thermal_zone_device *thz;
420
421         thz = thermal_zone_device_find(data, tegra_skin_match);
422
423         if (!thz || thz->ops->get_temp(thz, temp))
424                 *temp = 25000;
425
426         return 0;
427 }
428
429 static struct therm_est_data skin_data = {
430         .toffset = 9793,
431         .polling_period = 1100,
432         .ndevs = 2,
433         .devs = {
434                         {
435                                 .dev_data = "nct_ext",
436                                 .get_temp = tegra_skin_get_temp,
437                                 .coeffs = {
438                                         2, 1, 1, 1,
439                                         1, 1, 1, 1,
440                                         1, 1, 1, 0,
441                                         1, 1, 0, 0,
442                                         0, 0, -1, -7
443                                 },
444                         },
445                         {
446                                 .dev_data = "nct_int",
447                                 .get_temp = tegra_skin_get_temp,
448                                 .coeffs = {
449                                         -11, -7, -5, -3,
450                                         -3, -2, -1, 0,
451                                         0, 0, 1, 1,
452                                         1, 2, 2, 3,
453                                         4, 6, 11, 18
454                                 },
455                         },
456         },
457         .trip_temp = 43000,
458         .tc1 = 1,
459         .tc2 = 15,
460         .passive_delay = 15000,
461 };
462
463 static struct balanced_throttle skin_throttle = {
464         .throt_tab_size = 6,
465         .throt_tab = {
466                 { 640000, 1200 },
467                 { 640000, 1200 },
468                 { 760000, 1200 },
469                 { 760000, 1200 },
470                 {1000000, 1200 },
471                 {1000000, 1200 },
472         },
473 };
474
475 static int __init pluto_skin_init(void)
476 {
477         struct thermal_cooling_device *skin_cdev;
478
479         skin_cdev = balanced_throttle_register(&skin_throttle);
480
481         skin_data.cdev = skin_cdev;
482         tegra_skin_therm_est_device.dev.platform_data = &skin_data;
483         platform_device_register(&tegra_skin_therm_est_device);
484
485         return 0;
486 }
487 late_initcall(pluto_skin_init);
488 #endif
489
490 int __init pluto_sensors_init(void)
491 {
492         int err;
493
494         tegra_get_board_info(&board_info);
495
496         pr_debug("%s: ++\n", __func__);
497         pluto_camera_init();
498
499         err = pluto_nct1008_init();
500         if (err)
501                 return err;
502
503         i2c_register_board_info(0, pluto_i2c1_isl_board_info,
504                                 ARRAY_SIZE(pluto_i2c1_isl_board_info));
505
506         return 0;
507 }