aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/board-enterprise-sensors.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/board-enterprise-sensors.c')
-rw-r--r--arch/arm/mach-tegra/board-enterprise-sensors.c673
1 files changed, 673 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/board-enterprise-sensors.c b/arch/arm/mach-tegra/board-enterprise-sensors.c
new file mode 100644
index 00000000000..f775c2bd3b3
--- /dev/null
+++ b/arch/arm/mach-tegra/board-enterprise-sensors.c
@@ -0,0 +1,673 @@
1/*
2 * arch/arm/mach-tegra/board-enterprise-sensors.c
3 *
4 * Copyright (c) 2011, NVIDIA CORPORATION, All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * Neither the name of NVIDIA CORPORATION nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <linux/i2c.h>
35#include <linux/delay.h>
36#include <linux/i2c/pca954x.h>
37#include <linux/nct1008.h>
38#include <linux/err.h>
39#include <linux/mpu.h>
40#include <linux/platform_data/ina230.h>
41#include <linux/regulator/consumer.h>
42#include <linux/slab.h>
43#include <mach/gpio.h>
44#include <media/ar0832_main.h>
45#include <media/tps61050.h>
46#include <media/ov9726.h>
47#include <mach/edp.h>
48#include <mach/thermal.h>
49#include "cpu-tegra.h"
50#include "gpio-names.h"
51#include "board-enterprise.h"
52#include "board.h"
53
54static int nct_get_temp(void *_data, long *temp)
55{
56 struct nct1008_data *data = _data;
57 return nct1008_thermal_get_temp(data, temp);
58}
59
60static int nct_get_temp_low(void *_data, long *temp)
61{
62 struct nct1008_data *data = _data;
63 return nct1008_thermal_get_temp_low(data, temp);
64}
65
66static int nct_set_limits(void *_data,
67 long lo_limit_milli,
68 long hi_limit_milli)
69{
70 struct nct1008_data *data = _data;
71 return nct1008_thermal_set_limits(data,
72 lo_limit_milli,
73 hi_limit_milli);
74}
75
76static int nct_set_alert(void *_data,
77 void (*alert_func)(void *),
78 void *alert_data)
79{
80 struct nct1008_data *data = _data;
81 return nct1008_thermal_set_alert(data, alert_func, alert_data);
82}
83
84static int nct_set_shutdown_temp(void *_data, long shutdown_temp)
85{
86 struct nct1008_data *data = _data;
87 return nct1008_thermal_set_shutdown_temp(data,
88 shutdown_temp);
89}
90
91static void nct1008_probe_callback(struct nct1008_data *data)
92{
93 struct tegra_thermal_device *thermal_device;
94
95 thermal_device = kzalloc(sizeof(struct tegra_thermal_device),
96 GFP_KERNEL);
97 if (!thermal_device) {
98 pr_err("unable to allocate thermal device\n");
99 return;
100 }
101
102 thermal_device->name = "nct1008";
103 thermal_device->data = data;
104 thermal_device->offset = TDIODE_OFFSET;
105 thermal_device->get_temp = nct_get_temp;
106 thermal_device->get_temp_low = nct_get_temp_low;
107 thermal_device->set_limits = nct_set_limits;
108 thermal_device->set_alert = nct_set_alert;
109 thermal_device->set_shutdown_temp = nct_set_shutdown_temp;
110
111 tegra_thermal_set_device(thermal_device);
112}
113
114static struct nct1008_platform_data enterprise_nct1008_pdata = {
115 .supported_hwrev = true,
116 .ext_range = true,
117 .conv_rate = 0x08,
118 .offset = 8, /* 4 * 2C. Bug 844025 - 1C for device accuracies */
119 .probe_callback = nct1008_probe_callback,
120};
121
122static struct i2c_board_info enterprise_i2c4_nct1008_board_info[] = {
123 {
124 I2C_BOARD_INFO("nct1008", 0x4C),
125 .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PH7),
126 .platform_data = &enterprise_nct1008_pdata,
127 }
128};
129
130static void enterprise_nct1008_init(void)
131{
132 int ret;
133
134 tegra_gpio_enable(TEGRA_GPIO_PH7);
135 ret = gpio_request(TEGRA_GPIO_PH7, "temp_alert");
136 if (ret < 0) {
137 pr_err("%s: gpio_request failed %d\n", __func__, ret);
138 return;
139 }
140
141 ret = gpio_direction_input(TEGRA_GPIO_PH7);
142 if (ret < 0) {
143 pr_err("%s: gpio_direction_input failed %d\n", __func__, ret);
144 gpio_free(TEGRA_GPIO_PH7);
145 return;
146 }
147
148 i2c_register_board_info(4, enterprise_i2c4_nct1008_board_info,
149 ARRAY_SIZE(enterprise_i2c4_nct1008_board_info));
150}
151
152/* MPU board file definition */
153#if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
154#define MPU_GYRO_NAME "mpu3050"
155#endif
156#if (MPU_GYRO_TYPE == MPU_TYPE_MPU6050)
157#define MPU_GYRO_NAME "mpu6050"
158#endif
159static struct mpu_platform_data mpu_gyro_data = {
160 .int_config = 0x10,
161 .level_shifter = 0,
162 .orientation = MPU_GYRO_ORIENTATION, /* Located in board_[platformname].h */
163};
164
165#if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
166static struct ext_slave_platform_data mpu_accel_data = {
167 .address = MPU_ACCEL_ADDR,
168 .irq = 0,
169 .adapt_num = MPU_ACCEL_BUS_NUM,
170 .bus = EXT_SLAVE_BUS_SECONDARY,
171 .orientation = MPU_ACCEL_ORIENTATION, /* Located in board_[platformname].h */
172};
173#endif
174
175static struct ext_slave_platform_data mpu_compass_data = {
176 .address = MPU_COMPASS_ADDR,
177 .irq = 0,
178 .adapt_num = MPU_COMPASS_BUS_NUM,
179 .bus = EXT_SLAVE_BUS_PRIMARY,
180 .orientation = MPU_COMPASS_ORIENTATION, /* Located in board_[platformname].h */
181};
182
183static struct i2c_board_info __initdata inv_mpu_i2c2_board_info[] = {
184 {
185 I2C_BOARD_INFO(MPU_GYRO_NAME, MPU_GYRO_ADDR),
186 .irq = TEGRA_GPIO_TO_IRQ(MPU_GYRO_IRQ_GPIO),
187 .platform_data = &mpu_gyro_data,
188 },
189#if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
190 {
191 I2C_BOARD_INFO(MPU_ACCEL_NAME, MPU_ACCEL_ADDR),
192#if MPU_ACCEL_IRQ_GPIO
193 .irq = TEGRA_GPIO_TO_IRQ(MPU_ACCEL_IRQ_GPIO),
194#endif
195 .platform_data = &mpu_accel_data,
196 },
197#endif
198 {
199 I2C_BOARD_INFO(MPU_COMPASS_NAME, MPU_COMPASS_ADDR),
200#if MPU_COMPASS_IRQ_GPIO
201 .irq = TEGRA_GPIO_TO_IRQ(MPU_COMPASS_IRQ_GPIO),
202#endif
203 .platform_data = &mpu_compass_data,
204 },
205};
206
207static void mpuirq_init(void)
208{
209 int ret = 0;
210
211 pr_info("*** MPU START *** mpuirq_init...\n");
212
213#if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
214#if MPU_ACCEL_IRQ_GPIO
215 /* ACCEL-IRQ assignment */
216 tegra_gpio_enable(MPU_ACCEL_IRQ_GPIO);
217 ret = gpio_request(MPU_ACCEL_IRQ_GPIO, MPU_ACCEL_NAME);
218 if (ret < 0) {
219 pr_err("%s: gpio_request failed %d\n", __func__, ret);
220 return;
221 }
222
223 ret = gpio_direction_input(MPU_ACCEL_IRQ_GPIO);
224 if (ret < 0) {
225 pr_err("%s: gpio_direction_input failed %d\n", __func__, ret);
226 gpio_free(MPU_ACCEL_IRQ_GPIO);
227 return;
228 }
229#endif
230#endif
231
232 /* MPU-IRQ assignment */
233 tegra_gpio_enable(MPU_GYRO_IRQ_GPIO);
234 ret = gpio_request(MPU_GYRO_IRQ_GPIO, MPU_GYRO_NAME);
235 if (ret < 0) {
236 pr_err("%s: gpio_request failed %d\n", __func__, ret);
237 return;
238 }
239
240 ret = gpio_direction_input(MPU_GYRO_IRQ_GPIO);
241 if (ret < 0) {
242 pr_err("%s: gpio_direction_input failed %d\n", __func__, ret);
243 gpio_free(MPU_GYRO_IRQ_GPIO);
244 return;
245 }
246 pr_info("*** MPU END *** mpuirq_init...\n");
247
248 i2c_register_board_info(MPU_GYRO_BUS_NUM, inv_mpu_i2c2_board_info,
249 ARRAY_SIZE(inv_mpu_i2c2_board_info));
250}
251
252static inline void enterprise_msleep(u32 t)
253{
254 /*
255 If timer value is between ( 10us - 20ms),
256 usleep_range() is recommended.
257 Please read Documentation/timers/timers-howto.txt.
258 */
259 usleep_range(t*1000, t*1000 + 500);
260}
261
262static struct i2c_board_info enterprise_i2c0_isl_board_info[] = {
263 {
264 I2C_BOARD_INFO("isl29028", 0x44),
265 }
266};
267
268static void enterprise_isl_init(void)
269{
270 i2c_register_board_info(0, enterprise_i2c0_isl_board_info,
271 ARRAY_SIZE(enterprise_i2c0_isl_board_info));
272}
273
274enum CAMERA_INDEX {
275 CAM_REAR_LEFT,
276 CAM_REAR_RIGHT,
277 CAM_FRONT,
278 NUM_OF_CAM
279};
280
281struct enterprise_power_rail {
282 struct regulator *cam_reg;
283 struct regulator *csi_reg;
284};
285
286static struct enterprise_power_rail ent_vicsi_pwr[NUM_OF_CAM];
287
288static int enterprise_cam_pwr(enum CAMERA_INDEX cam, bool pwr_on)
289{
290 struct enterprise_power_rail *reg_cam = &ent_vicsi_pwr[cam];
291 int ret = 0;
292
293 /*
294 * SW must turn on 1.8V first then 2.8V
295 * SW must turn off 2.8V first then 1.8V
296 */
297 if (pwr_on) {
298 if (reg_cam->csi_reg == NULL) {
299 reg_cam->csi_reg = regulator_get(NULL,
300 "avdd_dsi_csi");
301 if (IS_ERR_OR_NULL(reg_cam->csi_reg)) {
302 pr_err("%s: csi pwr err\n", __func__);
303 ret = PTR_ERR(reg_cam->csi_reg);
304 goto enterprise_cam_pwr_fail;
305 }
306 }
307
308 ret = regulator_enable(reg_cam->csi_reg);
309 if (ret) {
310 pr_err("%s: enable csi pwr err\n", __func__);
311 goto enterprise_cam_pwr_fail;
312 }
313
314 if (reg_cam->cam_reg == NULL) {
315 reg_cam->cam_reg = regulator_get(NULL,
316 "vddio_cam");
317 if (IS_ERR_OR_NULL(reg_cam->cam_reg)) {
318 pr_err("%s: vddio pwr err\n", __func__);
319 ret = PTR_ERR(reg_cam->cam_reg);
320 regulator_disable(reg_cam->csi_reg);
321 goto enterprise_cam_pwr_fail;
322 }
323 }
324
325 ret = regulator_enable(reg_cam->cam_reg);
326 if (ret) {
327 pr_err("%s: enable vddio pwr err\n", __func__);
328 regulator_disable(reg_cam->csi_reg);
329 goto enterprise_cam_pwr_fail;
330 }
331 } else {
332 if (reg_cam->cam_reg)
333 regulator_disable(reg_cam->cam_reg);
334
335 if (reg_cam->csi_reg)
336 regulator_disable(reg_cam->csi_reg);
337 }
338 return 0;
339
340enterprise_cam_pwr_fail:
341 if (!IS_ERR_OR_NULL(reg_cam->cam_reg))
342 regulator_put(reg_cam->cam_reg);
343 reg_cam->cam_reg = NULL;
344
345 if (!IS_ERR_OR_NULL(reg_cam->csi_reg))
346 regulator_put(reg_cam->csi_reg);
347 reg_cam->csi_reg = NULL;
348
349 return ret;
350}
351
352static int enterprise_ar0832_ri_power_on(int is_stereo)
353{
354 int ret = 0;
355
356 pr_info("%s: ++\n", __func__);
357 ret = enterprise_cam_pwr(CAM_REAR_RIGHT, true);
358
359 /* Release Reset */
360 if (is_stereo) {
361 gpio_set_value(CAM1_RST_L_GPIO, 1);
362 gpio_set_value(CAM2_RST_L_GPIO, 1);
363 } else
364 gpio_set_value(CAM1_RST_L_GPIO, 1);
365 /*
366 It takes 2400 EXTCLK for ar0832 to be ready for I2c.
367 EXTCLK is 10 ~ 24MHz. 1 ms should be enough to cover
368 at least 2400 EXTCLK within frequency range.
369 */
370 enterprise_msleep(1);
371
372 return ret;
373}
374
375static int enterprise_ar0832_le_power_on(int is_stereo)
376{
377 int ret = 0;
378
379 pr_info("%s: ++\n", __func__);
380 ret = enterprise_cam_pwr(CAM_REAR_LEFT, true);
381
382 /* Release Reset */
383 gpio_set_value(CAM2_RST_L_GPIO, 1);
384
385 /*
386 It takes 2400 EXTCLK for ar0832 to be ready for I2c.
387 EXTCLK is 10 ~ 24MHz. 1 ms should be enough to cover
388 at least 2400 EXTCLK within frequency range.
389 */
390 enterprise_msleep(1);
391
392 /* CSI B is shared between Front camera and Rear Left camera */
393 gpio_set_value(CAM_CSI_MUX_SEL_GPIO, 1);
394
395 return ret;
396}
397
398static int enterprise_ar0832_ri_power_off(int is_stereo)
399{
400 int ret;
401
402 pr_info("%s: ++\n", __func__);
403 ret = enterprise_cam_pwr(CAM_REAR_RIGHT, false);
404
405 /* Assert Reset */
406 if (is_stereo) {
407 gpio_set_value(CAM1_RST_L_GPIO, 0);
408 gpio_set_value(CAM2_RST_L_GPIO, 0);
409 } else
410 gpio_set_value(CAM1_RST_L_GPIO, 0);
411
412 return ret;
413}
414
415static int enterprise_ar0832_le_power_off(int is_stereo)
416{
417 int ret;
418
419 pr_info("%s: ++\n", __func__);
420 ret = enterprise_cam_pwr(CAM_REAR_LEFT, false);
421
422 /* Assert Reset */
423 gpio_set_value(CAM2_RST_L_GPIO, 0);
424
425 return ret;
426}
427
428static int enterprise_ov9726_power_on(void)
429{
430 pr_info("ov9726 power on\n");
431
432 /* switch mipi mux to front camera */
433 gpio_set_value(CAM_CSI_MUX_SEL_GPIO, CAM_CSI_MUX_SEL_FRONT);
434 enterprise_cam_pwr(CAM_FRONT, true);
435
436 return 0;
437}
438
439static int enterprise_ov9726_power_off(void)
440{
441 pr_info("ov9726 power off\n");
442
443 enterprise_cam_pwr(CAM_FRONT, false);
444
445 return 0;
446}
447
448struct ov9726_platform_data enterprise_ov9726_data = {
449 .power_on = enterprise_ov9726_power_on,
450 .power_off = enterprise_ov9726_power_off,
451 .gpio_rst = CAM3_RST_L_GPIO,
452 .rst_low_active = true,
453 .gpio_pwdn = CAM3_PWDN_GPIO,
454 .pwdn_low_active = false,
455};
456
457static struct nvc_torch_pin_state enterprise_tps61050_pinstate = {
458 .mask = 0x0008, /*VGP3*/
459 .values = 0x0008,
460};
461
462static struct tps61050_platform_data enterprise_tps61050_pdata = {
463 .dev_name = "torch",
464 .pinstate = &enterprise_tps61050_pinstate,
465};
466
467
468struct enterprise_cam_gpio {
469 int gpio;
470 const char *label;
471 int value;
472};
473
474#define TEGRA_CAMERA_GPIO(_gpio, _label, _value) \
475 { \
476 .gpio = _gpio, \
477 .label = _label, \
478 .value = _value, \
479 }
480
481static struct enterprise_cam_gpio enterprise_cam_gpio_data[] = {
482 [0] = TEGRA_CAMERA_GPIO(CAM_CSI_MUX_SEL_GPIO, "cam_csi_sel", 1),
483 [1] = TEGRA_CAMERA_GPIO(CAM1_RST_L_GPIO, "cam1_rst_lo", 0),
484 [2] = TEGRA_CAMERA_GPIO(CAM2_RST_L_GPIO, "cam2_rst_lo", 0),
485 [3] = TEGRA_CAMERA_GPIO(CAM3_RST_L_GPIO, "cam3_rst_lo", 0),
486 [4] = TEGRA_CAMERA_GPIO(CAM3_PWDN_GPIO, "cam3_pwdn", 1),
487 [5] = TEGRA_CAMERA_GPIO(CAM_FLASH_EN_GPIO, "flash_en", 1),
488 [6] = TEGRA_CAMERA_GPIO(CAM_I2C_MUX_RST_EXP, "cam_i2c_mux_rst", 1),
489};
490
491static struct pca954x_platform_mode enterprise_pca954x_modes[] = {
492 { .adap_id = PCA954x_I2C_BUS0, .deselect_on_exit = true, },
493 { .adap_id = PCA954x_I2C_BUS1, .deselect_on_exit = true, },
494 { .adap_id = PCA954x_I2C_BUS2, .deselect_on_exit = true, },
495 { .adap_id = PCA954x_I2C_BUS3, .deselect_on_exit = true, },
496};
497
498static struct pca954x_platform_data enterprise_pca954x_data = {
499 .modes = enterprise_pca954x_modes,
500 .num_modes = ARRAY_SIZE(enterprise_pca954x_modes),
501};
502
503static struct ar0832_platform_data enterprise_ar0832_ri_data = {
504 .power_on = enterprise_ar0832_ri_power_on,
505 .power_off = enterprise_ar0832_ri_power_off,
506 .id = "right",
507};
508
509static struct ar0832_platform_data enterprise_ar0832_le_data = {
510 .power_on = enterprise_ar0832_le_power_on,
511 .power_off = enterprise_ar0832_le_power_off,
512 .id = "left",
513};
514
515static const struct i2c_board_info enterprise_i2c2_boardinfo[] = {
516 {
517 I2C_BOARD_INFO("pca9546", 0x70),
518 .platform_data = &enterprise_pca954x_data,
519 },
520 {
521 I2C_BOARD_INFO("tps61050", 0x33),
522 .platform_data = &enterprise_tps61050_pdata,
523 },
524 {
525 I2C_BOARD_INFO("ov9726", OV9726_I2C_ADDR >> 1),
526 .platform_data = &enterprise_ov9726_data,
527 },
528};
529
530/*
531 * Since ar0832 driver should support multiple devices, slave
532 * address should be changed after it is open. Default slave
533 * address of ar0832 is 0x36. It will be changed to alternate
534 * address defined below when device is open.
535 */
536static struct i2c_board_info ar0832_i2c2_boardinfo[] = {
537 {
538 /* 0x36: alternative slave address */
539 I2C_BOARD_INFO("ar0832", 0x36),
540 .platform_data = &enterprise_ar0832_ri_data,
541 },
542 {
543 /* 0x32: alternative slave address */
544 I2C_BOARD_INFO("ar0832", 0x32),
545 .platform_data = &enterprise_ar0832_le_data,
546 },
547 {
548 I2C_BOARD_INFO("tps61050", 0x33),
549 .platform_data = &enterprise_tps61050_pdata,
550 },
551 {
552 I2C_BOARD_INFO("ov9726", OV9726_I2C_ADDR >> 1),
553 .platform_data = &enterprise_ov9726_data,
554 },
555};
556
557static struct i2c_board_info enterprise_i2c6_boardinfo[] = {
558 {
559 I2C_BOARD_INFO("ar0832", 0x36),
560 .platform_data = &enterprise_ar0832_le_data,
561 },
562};
563
564static struct i2c_board_info enterprise_i2c7_boardinfo[] = {
565 {
566 I2C_BOARD_INFO("ar0832", 0x36),
567 .platform_data = &enterprise_ar0832_ri_data,
568 },
569};
570
571static int enterprise_cam_init(void)
572{
573 int ret;
574 int i;
575 struct board_info bi;
576 struct board_info cam_bi;
577 bool i2c_mux = false;
578
579 pr_info("%s:++\n", __func__);
580 memset(ent_vicsi_pwr, 0, sizeof(ent_vicsi_pwr));
581 for (i = 0; i < ARRAY_SIZE(enterprise_cam_gpio_data); i++) {
582 ret = gpio_request(enterprise_cam_gpio_data[i].gpio,
583 enterprise_cam_gpio_data[i].label);
584 if (ret < 0) {
585 pr_err("%s: gpio_request failed for gpio #%d\n",
586 __func__, i);
587 goto fail_free_gpio;
588 }
589 gpio_direction_output(enterprise_cam_gpio_data[i].gpio,
590 enterprise_cam_gpio_data[i].value);
591 gpio_export(enterprise_cam_gpio_data[i].gpio, false);
592 tegra_gpio_enable(enterprise_cam_gpio_data[i].gpio);
593 }
594
595 tegra_get_board_info(&bi);
596 tegra_get_camera_board_info(&cam_bi);
597
598 if (bi.board_id == BOARD_E1205) {
599 if (bi.fab == BOARD_FAB_A00 || bi.fab == BOARD_FAB_A01)
600 i2c_mux = false;
601 else if (bi.fab == BOARD_FAB_A02)
602 i2c_mux = true;
603 } else if (bi.board_id == BOARD_E1197) {
604 if (cam_bi.fab == BOARD_FAB_A00)
605 i2c_mux = false;
606 else if (cam_bi.fab == BOARD_FAB_A01)
607 i2c_mux = true;
608 }
609
610 if (!i2c_mux)
611 i2c_register_board_info(2, ar0832_i2c2_boardinfo,
612 ARRAY_SIZE(ar0832_i2c2_boardinfo));
613 else {
614 i2c_register_board_info(2, enterprise_i2c2_boardinfo,
615 ARRAY_SIZE(enterprise_i2c2_boardinfo));
616 /*
617 * Right camera is on PCA954x's I2C BUS1,
618 * Left camera is on BUS0
619 */
620 i2c_register_board_info(PCA954x_I2C_BUS0, enterprise_i2c6_boardinfo,
621 ARRAY_SIZE(enterprise_i2c6_boardinfo));
622 i2c_register_board_info(PCA954x_I2C_BUS1, enterprise_i2c7_boardinfo,
623 ARRAY_SIZE(enterprise_i2c7_boardinfo));
624 }
625 return 0;
626
627fail_free_gpio:
628 pr_err("%s enterprise_cam_init failed!\n", __func__);
629 while (i--)
630 gpio_free(enterprise_cam_gpio_data[i].gpio);
631 return ret;
632}
633
634#define ENTERPRISE_INA230_ENABLED 0
635
636#if ENTERPRISE_INA230_ENABLED
637static struct ina230_platform_data ina230_platform = {
638 .rail_name = "VDD_AC_BAT",
639 .current_threshold = TEGRA_CUR_MON_THRESHOLD,
640 .resistor = TEGRA_CUR_MON_RESISTOR,
641 .min_cores_online = TEGRA_CUR_MON_MIN_CORES,
642};
643
644static struct i2c_board_info enterprise_i2c0_ina230_info[] = {
645 {
646 I2C_BOARD_INFO("ina230", 0x42),
647 .platform_data = &ina230_platform,
648 .irq = -1,
649 },
650};
651
652static int __init enterprise_ina230_init(void)
653{
654 return i2c_register_board_info(0, enterprise_i2c0_ina230_info,
655 ARRAY_SIZE(enterprise_i2c0_ina230_info));
656}
657#endif
658
659int __init enterprise_sensors_init(void)
660{
661 int ret;
662
663 enterprise_isl_init();
664 enterprise_nct1008_init();
665 mpuirq_init();
666#if ENTERPRISE_INA230_ENABLED
667 enterprise_ina230_init();
668#endif
669 ret = enterprise_cam_init();
670
671 return ret;
672}
673