29d1bea2e8a76d9d917446bb6cae4dffd03359fd
[linux-2.6.git] / arch / arm / mach-tegra / board-kai-sensors.c
1
2 /*
3  * arch/arm/mach-tegra/board-kai-sensors.c
4  *
5  * Copyright (c) 2012, NVIDIA Corporation.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 #include <linux/delay.h>
22 #include <linux/err.h>
23 #include <linux/i2c.h>
24 #include <linux/nct1008.h>
25 #include <linux/cm3217.h>
26 #include <linux/mpu.h>
27 #include <linux/regulator/consumer.h>
28 #include <linux/slab.h>
29 #include <asm/mach-types.h>
30 #include <mach/gpio.h>
31 #include <mach/thermal.h>
32 #include <media/ov2710.h>
33 #include "board.h"
34 #include "board-kai.h"
35 #include "cpu-tegra.h"
36
37 static struct regulator *kai_1v8_cam3;
38 static struct regulator *kai_vdd_cam3;
39
40 #ifndef CONFIG_TEGRA_INTERNAL_TSENSOR_EDP_SUPPORT
41 static int nct_get_temp(void *_data, long *temp)
42 {
43         struct nct1008_data *data = _data;
44         return nct1008_thermal_get_temp(data, temp);
45 }
46
47 static int nct_get_temp_low(void *_data, long *temp)
48 {
49         struct nct1008_data *data = _data;
50         return nct1008_thermal_get_temp_low(data, temp);
51 }
52
53 static int nct_set_limits(void *_data,
54                         long lo_limit_milli,
55                         long hi_limit_milli)
56 {
57         struct nct1008_data *data = _data;
58         return nct1008_thermal_set_limits(data,
59                                         lo_limit_milli,
60                                         hi_limit_milli);
61 }
62
63 static int nct_set_alert(void *_data,
64                                 void (*alert_func)(void *),
65                                 void *alert_data)
66 {
67         struct nct1008_data *data = _data;
68         return nct1008_thermal_set_alert(data, alert_func, alert_data);
69 }
70
71 static int nct_set_shutdown_temp(void *_data, long shutdown_temp)
72 {
73         struct nct1008_data *data = _data;
74         return nct1008_thermal_set_shutdown_temp(data, shutdown_temp);
75 }
76
77 static void nct1008_probe_callback(struct nct1008_data *data)
78 {
79         struct tegra_thermal_device *thermal_device;
80
81         thermal_device = kzalloc(sizeof(struct tegra_thermal_device),
82                                         GFP_KERNEL);
83         if (!thermal_device) {
84                 pr_err("unable to allocate thermal device\n");
85                 return;
86         }
87
88         thermal_device->name = "nct72";
89         thermal_device->data = data;
90         thermal_device->id = THERMAL_DEVICE_ID_NCT_EXT;
91         thermal_device->offset = TDIODE_OFFSET;
92         thermal_device->get_temp = nct_get_temp;
93         thermal_device->get_temp_low = nct_get_temp_low;
94         thermal_device->set_limits = nct_set_limits;
95         thermal_device->set_alert = nct_set_alert;
96         thermal_device->set_shutdown_temp = nct_set_shutdown_temp;
97
98         tegra_thermal_device_register(thermal_device);
99 }
100 #endif
101
102 static struct nct1008_platform_data kai_nct1008_pdata = {
103         .supported_hwrev = true,
104         .ext_range = true,
105         .conv_rate = 0x09, /* 0x09 corresponds to 32Hz conversion rate */
106         .offset = 8, /* 4 * 2C. 1C for device accuracies */
107 #ifndef CONFIG_TEGRA_INTERNAL_TSENSOR_EDP_SUPPORT
108         .probe_callback = nct1008_probe_callback,
109 #endif
110 };
111
112 static struct i2c_board_info kai_i2c4_nct1008_board_info[] = {
113         {
114                 I2C_BOARD_INFO("nct72", 0x4C),
115                 .platform_data = &kai_nct1008_pdata,
116                 .irq = -1,
117         }
118 };
119
120 static int kai_nct1008_init(void)
121 {
122         int ret = 0;
123
124         /* FIXME: enable irq when throttling is supported */
125         kai_i2c4_nct1008_board_info[0].irq =
126                 TEGRA_GPIO_TO_IRQ(KAI_TEMP_ALERT_GPIO);
127
128         ret = gpio_request(KAI_TEMP_ALERT_GPIO, "temp_alert");
129         if (ret < 0) {
130                 pr_err("%s: gpio_request failed\n", __func__);
131                 return ret;
132         }
133
134         ret = gpio_direction_input(KAI_TEMP_ALERT_GPIO);
135         if (ret < 0) {
136                 pr_err("%s: set gpio to input failed\n", __func__);
137                 gpio_free(KAI_TEMP_ALERT_GPIO);
138         }
139         return ret;
140 }
141
142 static struct cm3217_platform_data kai_cm3217_pdata = {
143         .levels = {10, 160, 225, 320, 640, 1280, 2600, 5800, 8000, 10240},
144         .golden_adc = 0,
145         .power = 0,
146 };
147
148 static struct i2c_board_info kai_i2c0_cm3217_board_info[] = {
149         {
150                 I2C_BOARD_INFO("cm3217", 0x10),
151                 .platform_data = &kai_cm3217_pdata,
152         },
153 };
154
155 static int kai_camera_init(void)
156 {
157         int ret;
158
159         ret = gpio_request(CAM2_POWER_DWN_GPIO, "cam2_power_en");
160         if (ret < 0) {
161                 pr_err("%s: gpio_request failed for gpio %s\n",
162                         __func__, "CAM2_POWER_DWN_GPIO");
163         }
164
165         gpio_direction_output(CAM2_POWER_DWN_GPIO, 1);
166         mdelay(10);
167
168         ret = gpio_request(CAM2_RST_GPIO, "cam2_reset");
169         if (ret < 0) {
170                 pr_err("%s: gpio_request failed for gpio %s\n",
171                         __func__, "CAM2_RST_GPIO");
172         }
173
174         gpio_direction_output(CAM2_RST_GPIO, 0);
175         mdelay(5);
176
177         return 0;
178 }
179
180 static int kai_ov2710_power_on(void)
181 {
182         gpio_direction_output(CAM2_POWER_DWN_GPIO, 0);
183         mdelay(10);
184
185         if (kai_vdd_cam3 == NULL) {
186                 kai_vdd_cam3 = regulator_get(NULL, "vdd_cam3");
187                 if (WARN_ON(IS_ERR(kai_vdd_cam3))) {
188                         pr_err("%s: couldn't get regulator vdd_cam3: %d\n",
189                                 __func__, (int)PTR_ERR(kai_vdd_cam3));
190                         goto reg_get_vdd_cam3_fail;
191                 }
192         }
193         regulator_enable(kai_vdd_cam3);
194
195         if (kai_1v8_cam3 == NULL) {
196                 kai_1v8_cam3 = regulator_get(NULL, "vdd_1v8_cam3");
197                 if (WARN_ON(IS_ERR(kai_1v8_cam3))) {
198                         pr_err("%s: couldn't get regulator vdd_1v8_cam3: %d\n",
199                                 __func__, (int)PTR_ERR(kai_1v8_cam3));
200                         goto reg_get_vdd_1v8_cam3_fail;
201                 }
202         }
203         regulator_enable(kai_1v8_cam3);
204         mdelay(5);
205
206         gpio_direction_output(CAM2_RST_GPIO, 1);
207         mdelay(10);
208
209         return 0;
210
211 reg_get_vdd_1v8_cam3_fail:
212         kai_1v8_cam3 = NULL;
213         regulator_put(kai_vdd_cam3);
214
215 reg_get_vdd_cam3_fail:
216         kai_vdd_cam3 = NULL;
217
218         return -ENODEV;
219 }
220
221 static int kai_ov2710_power_off(void)
222 {
223         gpio_direction_output(CAM2_POWER_DWN_GPIO, 1);
224
225         gpio_direction_output(CAM2_RST_GPIO, 0);
226
227         if (kai_1v8_cam3)
228                 regulator_disable(kai_1v8_cam3);
229         if (kai_vdd_cam3)
230                 regulator_disable(kai_vdd_cam3);
231
232         return 0;
233 }
234
235 struct ov2710_platform_data kai_ov2710_data = {
236         .power_on = kai_ov2710_power_on,
237         .power_off = kai_ov2710_power_off,
238 };
239
240 static struct i2c_board_info kai_i2c2_board_info[] = {
241         {
242                 I2C_BOARD_INFO("ov2710", 0x36),
243                 .platform_data = &kai_ov2710_data,
244         },
245 };
246
247 /* MPU board file definition */
248
249 #if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
250 #define MPU_GYRO_NAME           "mpu3050"
251 #endif
252 #if (MPU_GYRO_TYPE == MPU_TYPE_MPU6050)
253 #define MPU_GYRO_NAME           "mpu6050"
254 #endif
255
256 static struct mpu_platform_data mpu_gyro_data = {
257         .int_config     = 0x10,
258         .level_shifter  = 0,
259         .orientation    = MPU_GYRO_ORIENTATION,
260 };
261
262 #if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
263 static struct ext_slave_platform_data mpu_accel_data = {
264         .address        = MPU_ACCEL_ADDR,
265         .irq            = 0,
266         .adapt_num      = MPU_ACCEL_BUS_NUM,
267         .bus            = EXT_SLAVE_BUS_SECONDARY,
268         .orientation    = MPU_ACCEL_ORIENTATION,
269 };
270 #endif
271
272 static struct ext_slave_platform_data mpu_compass_data = {
273         .address        = MPU_COMPASS_ADDR,
274         .irq            = 0,
275         .adapt_num      = MPU_COMPASS_BUS_NUM,
276         .bus            = EXT_SLAVE_BUS_PRIMARY,
277         .orientation    = MPU_COMPASS_ORIENTATION,
278 };
279
280 static struct i2c_board_info __initdata inv_mpu_i2c0_board_info[] = {
281         {
282                 I2C_BOARD_INFO(MPU_GYRO_NAME, MPU_GYRO_ADDR),
283                 .irq = TEGRA_GPIO_TO_IRQ(MPU_GYRO_IRQ_GPIO),
284                 .platform_data = &mpu_gyro_data,
285         },
286 #if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
287         {
288                 I2C_BOARD_INFO(MPU_ACCEL_NAME, MPU_ACCEL_ADDR),
289 #if MPU_ACCEL_IRQ_GPIO
290                 .irq = TEGRA_GPIO_TO_IRQ(MPU_ACCEL_IRQ_GPIO),
291 #endif
292                 .platform_data = &mpu_accel_data,
293         },
294 #endif
295         {
296                 I2C_BOARD_INFO(MPU_COMPASS_NAME, MPU_COMPASS_ADDR),
297 #if MPU_COMPASS_IRQ_GPIO
298                 .irq = TEGRA_GPIO_TO_IRQ(MPU_COMPASS_IRQ_GPIO),
299 #endif
300                 .platform_data = &mpu_compass_data,
301         },
302 };
303
304 static void mpuirq_init(void)
305 {
306         int ret = 0;
307
308         pr_info("*** MPU START *** mpuirq_init...\n");
309
310 #if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
311 #if MPU_ACCEL_IRQ_GPIO
312         /* ACCEL-IRQ assignment */
313         ret = gpio_request(MPU_ACCEL_IRQ_GPIO, MPU_ACCEL_NAME);
314         if (ret < 0) {
315                 pr_err("%s: gpio_request failed %d\n", __func__, ret);
316                 return;
317         }
318
319         ret = gpio_direction_input(MPU_ACCEL_IRQ_GPIO);
320         if (ret < 0) {
321                 pr_err("%s: gpio_direction_input failed %d\n", __func__, ret);
322                 gpio_free(MPU_ACCEL_IRQ_GPIO);
323                 return;
324         }
325 #endif
326 #endif
327
328         /* MPU-IRQ assignment */
329         ret = gpio_request(MPU_GYRO_IRQ_GPIO, MPU_GYRO_NAME);
330         if (ret < 0) {
331                 pr_err("%s: gpio_request failed %d\n", __func__, ret);
332                 return;
333         }
334
335         ret = gpio_direction_input(MPU_GYRO_IRQ_GPIO);
336         if (ret < 0) {
337                 pr_err("%s: gpio_direction_input failed %d\n", __func__, ret);
338                 gpio_free(MPU_GYRO_IRQ_GPIO);
339                 return;
340         }
341         pr_info("*** MPU END *** mpuirq_init...\n");
342
343         i2c_register_board_info(MPU_GYRO_BUS_NUM, inv_mpu_i2c0_board_info,
344                 ARRAY_SIZE(inv_mpu_i2c0_board_info));
345 }
346
347 int __init kai_sensors_init(void)
348 {
349         int err;
350
351         err = kai_nct1008_init();
352         if (err)
353                 pr_err("%s: nct1008 init failed\n", __func__);
354         else
355                 i2c_register_board_info(4, kai_i2c4_nct1008_board_info,
356                         ARRAY_SIZE(kai_i2c4_nct1008_board_info));
357
358         kai_camera_init();
359
360         i2c_register_board_info(2, kai_i2c2_board_info,
361                 ARRAY_SIZE(kai_i2c2_board_info));
362
363         i2c_register_board_info(0, kai_i2c0_cm3217_board_info,
364                 ARRAY_SIZE(kai_i2c0_cm3217_board_info));
365
366         mpuirq_init();
367
368         return 0;
369 }