/* * arch/arm/mach-tegra/board-roth-sensors.c * * Copyright (c) 2012-2013 NVIDIA CORPORATION, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of NVIDIA CORPORATION nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include "gpio-names.h" #include "board.h" #include "board-common.h" #include "board-roth.h" #include "cpu-tegra.h" #include "devices.h" #include "tegra-board-id.h" #include "dvfs.h" static struct board_info board_info; static struct throttle_table tj_throttle_table[] = { /* CPU_THROT_LOW cannot be used by other than CPU */ /* NO_CAP cannot be used by CPU */ /* CPU, C2BUS, C3BUS, SCLK, EMC */ { { 1530000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1428000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1326000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1224000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1122000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1020000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 918000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 816000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 714000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 612000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 612000, 564000, 564000, NO_CAP, NO_CAP } }, { { 612000, 528000, 528000, NO_CAP, NO_CAP } }, { { 612000, 492000, 492000, NO_CAP, NO_CAP } }, { { 612000, 420000, 420000, NO_CAP, NO_CAP } }, { { 612000, 408000, 408000, NO_CAP, NO_CAP } }, { { 612000, 360000, 360000, NO_CAP, NO_CAP } }, { { 612000, 360000, 360000, 312000, NO_CAP } }, { { 510000, 360000, 360000, 312000, 480000 } }, { { 468000, 360000, 360000, 312000, 480000 } }, { { 468000, 276000, 276000, 208000, 480000 } }, { { 372000, 276000, 276000, 208000, 204000 } }, { { 288000, 276000, 276000, 208000, 204000 } }, { { 252000, 276000, 228000, 208000, 102000 } }, { { 204000, 276000, 228000, 208000, 102000 } }, { { 102000, 276000, 228000, 208000, 102000 } }, { { CPU_THROT_LOW, 276000, 228000, 208000, 102000 } }, }; static struct balanced_throttle tj_throttle = { .throt_tab_size = ARRAY_SIZE(tj_throttle_table), .throt_tab = tj_throttle_table, }; static struct throttle_table tj_heavy_throttle_table[] = { { { 204000, 420000, 360000, 208000, 204000 } }, }; static struct balanced_throttle tj_heavy_throttle = { .throt_tab_size = ARRAY_SIZE(tj_heavy_throttle_table), .throt_tab = tj_heavy_throttle_table, }; static int __init roth_throttle_init(void) { if (machine_is_roth()) { balanced_throttle_register(&tj_throttle, "tegra-balanced"); balanced_throttle_register(&tj_heavy_throttle, "tegra-heavy"); } return 0; } module_init(roth_throttle_init); static struct thermal_zone_params roth_nct1008_tzp = { .governor_name = "step_wise", }; static struct nct1008_platform_data roth_nct1008_pdata = { .supported_hwrev = true, .ext_range = true, .conv_rate = 0x08, .offset = 0, .shutdown_ext_limit = 91, /* C */ .shutdown_local_limit = 120, /* C */ .loc_name = "soc", .passive_delay = 2000, .num_trips = 2, .trips = { /* Thermal Throttling */ [0] = { .cdev_type = "tegra-balanced", .trip_temp = 80000, .trip_type = THERMAL_TRIP_PASSIVE, .upper = THERMAL_NO_LIMIT, .lower = THERMAL_NO_LIMIT, .hysteresis = 0, }, [1] = { .cdev_type = "tegra-heavy", .trip_temp = 86000, /* shutdown_ext_limit - 2C */ .trip_type = THERMAL_TRIP_PASSIVE, .upper = 1, .lower = 1, .hysteresis = 6000, }, }, .tzp = &roth_nct1008_tzp, }; static struct i2c_board_info roth_i2c4_nct1008_board_info[] = { { I2C_BOARD_INFO("nct1008", 0x4C), .platform_data = &roth_nct1008_pdata, .irq = -1, } }; #define VI_PINMUX(_pingroup, _mux, _pupd, _tri, _io, _lock, _ioreset) \ { \ .pingroup = TEGRA_PINGROUP_##_pingroup, \ .func = TEGRA_MUX_##_mux, \ .pupd = TEGRA_PUPD_##_pupd, \ .tristate = TEGRA_TRI_##_tri, \ .io = TEGRA_PIN_##_io, \ .lock = TEGRA_PIN_LOCK_##_lock, \ .od = TEGRA_PIN_OD_DEFAULT, \ .ioreset = TEGRA_PIN_IO_RESET_##_ioreset \ } /* MPU board file definition */ static struct mpu_platform_data mpu6050_gyro_data = { .int_config = 0x10, .level_shifter = 0, /* Located in board_[platformname].h */ .orientation = MPU_GYRO_ORIENTATION, .sec_slave_type = SECONDARY_SLAVE_TYPE_NONE, .key = {0x4E, 0xCC, 0x7E, 0xEB, 0xF6, 0x1E, 0x35, 0x22, 0x00, 0x34, 0x0D, 0x65, 0x32, 0xE9, 0x94, 0x89}, }; static struct i2c_board_info __initdata inv_mpu6050_i2c2_board_info[] = { { I2C_BOARD_INFO(MPU_GYRO_NAME, MPU_GYRO_ADDR), .platform_data = &mpu6050_gyro_data, }, }; static void mpuirq_init(void) { int ret = 0; unsigned gyro_irq_gpio = MPU_GYRO_IRQ_GPIO; unsigned gyro_bus_num = MPU_GYRO_BUS_NUM; char *gyro_name = MPU_GYRO_NAME; pr_info("*** MPU START *** mpuirq_init...\n"); ret = gpio_request(gyro_irq_gpio, gyro_name); if (ret < 0) { pr_err("%s: gpio_request failed %d\n", __func__, ret); return; } ret = gpio_direction_input(gyro_irq_gpio); if (ret < 0) { pr_err("%s: gpio_direction_input failed %d\n", __func__, ret); gpio_free(gyro_irq_gpio); return; } pr_info("*** MPU END *** mpuirq_init...\n"); inv_mpu6050_i2c2_board_info[0].irq = gpio_to_irq(MPU_GYRO_IRQ_GPIO); i2c_register_board_info(gyro_bus_num, inv_mpu6050_i2c2_board_info, ARRAY_SIZE(inv_mpu6050_i2c2_board_info)); } static int roth_nct1008_init(void) { int nct1008_port = TEGRA_GPIO_PX6; int ret = 0; tegra_platform_edp_init(roth_nct1008_pdata.trips, &roth_nct1008_pdata.num_trips, 0); /* edp temperature margin */ tegra_add_cdev_trips(roth_nct1008_pdata.trips, &roth_nct1008_pdata.num_trips); tegra_add_tj_trips(roth_nct1008_pdata.trips, &roth_nct1008_pdata.num_trips); roth_i2c4_nct1008_board_info[0].irq = gpio_to_irq(nct1008_port); pr_info("%s: roth nct1008 irq %d", __func__, \ roth_i2c4_nct1008_board_info[0].irq); ret = gpio_request(nct1008_port, "temp_alert"); if (ret < 0) return ret; ret = gpio_direction_input(nct1008_port); if (ret < 0) { pr_info("%s: calling gpio_free(nct1008_port)", __func__); gpio_free(nct1008_port); } /* roth has thermal sensor on GEN1-I2C i.e. instance 0 */ i2c_register_board_info(0, roth_i2c4_nct1008_board_info, ARRAY_SIZE(roth_i2c4_nct1008_board_info)); return ret; } #ifdef CONFIG_TEGRA_SKIN_THROTTLE static int tegra_skin_match(struct thermal_zone_device *thz, void *data) { return strcmp((char *)data, thz->type) == 0; } static int tegra_skin_get_temp(void *data, long *temp) { struct thermal_zone_device *thz; thz = thermal_zone_device_find(data, tegra_skin_match); if (!thz || thz->ops->get_temp(thz, temp)) *temp = 25000; return 0; } static struct therm_est_data skin_data = { .cdev_type = "skin-balanced", .toffset = 9793, .polling_period = 1100, .ndevs = 2, .tc1 = 10, .tc2 = 1, .devs = { { .dev_data = "nct_ext", .get_temp = tegra_skin_get_temp, .coeffs = { 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, -1, -7 }, }, { .dev_data = "nct_int", .get_temp = tegra_skin_get_temp, .coeffs = { -11, -7, -5, -3, -3, -2, -1, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 6, 11, 18 }, }, }, .trip_temp = 45000, .passive_delay = 15000, }; static struct throttle_table skin_throttle_table[] = { /* CPU_THROT_LOW cannot be used by other than CPU */ /* NO_CAP cannot be used by CPU */ /* CPU, C2BUS, C3BUS, SCLK, EMC */ { { 1530000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1530000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1326000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1326000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1326000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1326000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1326000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1122000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1122000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1122000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1122000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1122000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1122000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1020000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1020000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1020000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1020000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1020000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 1020000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 918000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 918000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 918000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 918000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 918000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 918000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 816000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 816000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 816000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 816000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 816000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 816000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 714000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 714000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 714000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 714000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 714000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 714000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 612000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 612000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 612000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 612000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 612000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 612000, NO_CAP, NO_CAP, NO_CAP, NO_CAP } }, { { 612000, 564000, 564000, NO_CAP, NO_CAP } }, { { 612000, 564000, 564000, NO_CAP, NO_CAP } }, { { 612000, 528000, 528000, NO_CAP, NO_CAP } }, { { 612000, 528000, 528000, NO_CAP, NO_CAP } }, { { 612000, 492000, 492000, NO_CAP, NO_CAP } }, { { 612000, 492000, 492000, NO_CAP, NO_CAP } }, { { 612000, 420000, 420000, NO_CAP, NO_CAP } }, { { 612000, 420000, 420000, NO_CAP, NO_CAP } }, { { 612000, 408000, 408000, NO_CAP, NO_CAP } }, { { 612000, 408000, 408000, NO_CAP, NO_CAP } }, { { 612000, 360000, 360000, NO_CAP, NO_CAP } }, { { 612000, 360000, 360000, NO_CAP, NO_CAP } }, { { 510000, 360000, 360000, 312000, NO_CAP } }, { { 510000, 360000, 360000, 312000, NO_CAP } }, { { 510000, 360000, 360000, 312000, 480000 } }, { { 510000, 360000, 360000, 312000, 480000 } }, { { 510000, 360000, 360000, 312000, 480000 } }, { { 510000, 360000, 360000, 312000, 480000 } }, { { 510000, 360000, 360000, 312000, 480000 } }, { { 510000, 360000, 360000, 312000, 480000 } }, { { 468000, 360000, 360000, 312000, 480000 } }, { { 468000, 360000, 360000, 312000, 480000 } }, { { 468000, 276000, 276000, 208000, 480000 } }, { { 468000, 276000, 276000, 208000, 480000 } }, { { 372000, 276000, 276000, 208000, 204000 } }, { { 372000, 276000, 276000, 208000, 204000 } }, { { 288000, 276000, 276000, 208000, 204000 } }, { { 288000, 276000, 276000, 208000, 204000 } }, { { 252000, 276000, 228000, 208000, 102000 } }, { { 252000, 276000, 228000, 208000, 102000 } }, { { 204000, 276000, 228000, 208000, 102000 } }, { { 204000, 276000, 228000, 208000, 102000 } }, { { 102000, 276000, 228000, 208000, 102000 } }, { { CPU_THROT_LOW, 276000, 228000, 208000, 102000 } }, }; static struct balanced_throttle skin_throttle = { .throt_tab_size = ARRAY_SIZE(skin_throttle_table), .throt_tab = skin_throttle_table, }; static int __init roth_skin_init(void) { if (machine_is_roth()) { balanced_throttle_register(&skin_throttle, "skin-balanced"); tegra_skin_therm_est_device.dev.platform_data = &skin_data; platform_device_register(&tegra_skin_therm_est_device); } return 0; } late_initcall(roth_skin_init); #endif static int roth_fan_est_match(struct thermal_zone_device *thz, void *data) { return (strcmp((char *)data, thz->type) == 0); } static int roth_fan_est_get_temp(void *data, long *temp) { struct thermal_zone_device *thz; thz = thermal_zone_device_find(data, roth_fan_est_match); if (!thz || thz->ops->get_temp(thz, temp)) *temp = 25000; return 0; } /*Fan thermal estimator init data for P2454*/ static struct therm_fan_est_data fan_est_data_p2454 = { .toffset = 0, .polling_period = 1100, .ndevs = 2, .devs = { { .dev_data = "nct_ext_soc", .get_temp = roth_fan_est_get_temp, .coeffs = { 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }, { .dev_data = "nct_int_soc", .get_temp = roth_fan_est_get_temp, .coeffs = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }, }, .cdev_type = "pwm-fan", .active_trip_temps = {0, 70000, 82000, 120000, 130000, 140000, 150000, 160000, 170000, 180000}, .active_hysteresis = {0, 10000, 7000, 0, 0, 0, 0, 0, 0, 0}, }; static struct platform_device roth_fan_therm_est_device_p2454 = { .name = "therm-fan-est", .id = -1, .num_resources = 0, .dev = { .platform_data = &fan_est_data_p2454, }, }; /*Fan thermal estimator data for P2560*/ static struct therm_fan_est_data fan_est_data_p2560 = { .toffset = 0, .polling_period = 1100, .ndevs = 2, .devs = { { .dev_data = "nct_ext_soc", .get_temp = roth_fan_est_get_temp, .coeffs = { 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }, { .dev_data = "nct_int_soc", .get_temp = roth_fan_est_get_temp, .coeffs = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }, }, .cdev_type = "pwm-fan", .active_trip_temps = {0, 47000, 55000, 67000, 103000, 140000, 150000, 160000, 170000, 180000}, .active_hysteresis = {0, 12000, 7000, 10000, 0, 0, 0, 0, 0, 0}, }; static struct platform_device roth_fan_therm_est_device_p2560 = { .name = "therm-fan-est", .id = -1, .num_resources = 0, .dev = { .platform_data = &fan_est_data_p2560, }, }; static int __init roth_fan_est_init(void) { struct board_info board_info; tegra_get_board_info(&board_info); if (board_info.board_id == BOARD_P2560) platform_device_register(&roth_fan_therm_est_device_p2560); else platform_device_register(&roth_fan_therm_est_device_p2454); return 0; } int __init roth_sensors_init(void) { int err; tegra_get_board_info(&board_info); err = roth_nct1008_init(); if (err) return err; mpuirq_init(); roth_fan_est_init(); return 0; }