/* * arch/arm/mach-tegra/board-vcm30_t124-power.c * * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include "pm.h" #include "board.h" #include "gpio-names.h" #include "board-common.h" #include "board-vcm30_t124.h" #include "tegra_cl_dvfs.h" #include "devices.h" #include "tegra11_soctherm.h" #include #define PMC_CTRL 0x0 #define PMC_CTRL_INTR_LOW (1 << 17) static struct regulator_consumer_supply max77663_ldo5_supply[] = { REGULATOR_SUPPLY("vddio_sdmmc", "sdhci-tegra.2"), REGULATOR_SUPPLY("vddio_sd_slot", "sdhci-tegra.2"), REGULATOR_SUPPLY("pwrdet_sdmmc3", NULL), }; static struct max77663_regulator_fps_cfg max77663_fps_cfgs[] = { { .src = FPS_SRC_0, .en_src = FPS_EN_SRC_EN0, .time_period = FPS_TIME_PERIOD_DEF, }, { .src = FPS_SRC_1, .en_src = FPS_EN_SRC_EN1, .time_period = FPS_TIME_PERIOD_DEF, }, { .src = FPS_SRC_2, .en_src = FPS_EN_SRC_EN0, .time_period = FPS_TIME_PERIOD_DEF, }, }; #define MAX77663_PDATA_INIT(_rid, _id, _min_uV, _max_uV, _supply_reg, \ _always_on, _boot_on, _apply_uV, \ _fps_src, _fps_pu_period, _fps_pd_period, _flags) \ static struct regulator_init_data max77663_regulator_idata_##_id = { \ .supply_regulator = _supply_reg, \ .constraints = { \ .name = max77663_rails(_id), \ .min_uV = _min_uV, \ .max_uV = _max_uV, \ .valid_modes_mask = (REGULATOR_MODE_NORMAL | \ REGULATOR_MODE_STANDBY), \ .valid_ops_mask = (REGULATOR_CHANGE_MODE | \ REGULATOR_CHANGE_STATUS | \ REGULATOR_CHANGE_VOLTAGE), \ .always_on = _always_on, \ .boot_on = _boot_on, \ .apply_uV = _apply_uV, \ }, \ .num_consumer_supplies = \ ARRAY_SIZE(max77663_##_id##_supply), \ .consumer_supplies = max77663_##_id##_supply, \ }; \ static struct max77663_regulator_platform_data \ max77663_regulator_pdata_##_id = \ { \ .reg_init_data = &max77663_regulator_idata_##_id, \ .id = MAX77663_REGULATOR_ID_##_rid, \ .fps_src = _fps_src, \ .fps_pu_period = _fps_pu_period, \ .fps_pd_period = _fps_pd_period, \ .fps_cfgs = max77663_fps_cfgs, \ .flags = _flags, \ } MAX77663_PDATA_INIT(LDO5, ldo5, 800000, 3950000, NULL, 1, 1, 0, FPS_SRC_1, FPS_POWER_PERIOD_7, FPS_POWER_PERIOD_0, 0); #define MAX77663_REG(_id, _data) (&max77663_regulator_pdata_##_data) static struct max77663_regulator_platform_data *max77663_reg_pdata[] = { MAX77663_REG(LDO5, ldo5), }; static struct max77663_gpio_config max77663_gpio_cfgs[] = { { .gpio = MAX77663_GPIO5, .dir = GPIO_DIR_OUT, .dout = GPIO_DOUT_HIGH, .out_drv = GPIO_OUT_DRV_PUSH_PULL, .alternate = GPIO_ALT_DISABLE, }, }; static struct max77663_platform_data max77663_pdata = { .irq_base = MAX77663_IRQ_BASE, .gpio_base = MAX77663_GPIO_BASE, .num_gpio_cfgs = ARRAY_SIZE(max77663_gpio_cfgs), .gpio_cfgs = max77663_gpio_cfgs, .regulator_pdata = max77663_reg_pdata, .num_regulator_pdata = ARRAY_SIZE(max77663_reg_pdata), .rtc_i2c_addr = 0x68, .use_power_off = false, }; static struct i2c_board_info __initdata max77663_regulators[] = { { /* The I2C address was determined by OTP factory setting */ I2C_BOARD_INFO("max77663", 0x3c), .irq = -1, .platform_data = &max77663_pdata, }, }; /* MAX15569 switching regulator for vdd_cpu */ static struct regulator_consumer_supply max15569_vddcpu_supply[] = { REGULATOR_SUPPLY("vdd_cpu", NULL), }; static struct regulator_init_data max15569_vddcpu_init_data = { .constraints = { .min_uV = 500000, .max_uV = 1520000, .valid_modes_mask = (REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY), .valid_ops_mask = (REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_CONTROL | REGULATOR_CHANGE_VOLTAGE), .always_on = 1, .boot_on = 1, .apply_uV = 0, }, .num_consumer_supplies = ARRAY_SIZE(max15569_vddcpu_supply), .consumer_supplies = max15569_vddcpu_supply, }; static struct max15569_regulator_platform_data max15569_vddcpu_pdata = { .reg_init_data = &max15569_vddcpu_init_data, .max_voltage_uV = 1520000, .slew_rate_mv_per_us = 44, }; static struct i2c_board_info __initdata max15569_vddcpu_boardinfo[] = { { I2C_BOARD_INFO("max15569", 0x3a), .platform_data = &max15569_vddcpu_pdata, }, }; #ifdef CONFIG_ARCH_TEGRA_HAS_CL_DVFS /* board parameters for cpu dfll */ static struct tegra_cl_dvfs_cfg_param vcm30_t124_cl_dvfs_param = { .sample_rate = 12500, .force_mode = TEGRA_CL_DVFS_FORCE_FIXED, .cf = 10, .ci = 0, .cg = 2, .droop_cut_value = 0xF, .droop_restore_ramp = 0x0, .scale_out_ramp = 0x0, }; /* MAX15569: fixed 10mV steps from 600mV to 1400mV, with offset 0x0b */ #define PMU_CPU_VDD_MAP_SIZE ((1400000 - 600000) / 10000 + 1) static struct voltage_reg_map pmu_cpu_vdd_map[PMU_CPU_VDD_MAP_SIZE]; static inline void fill_reg_map(void) { int i; for (i = 0; i < PMU_CPU_VDD_MAP_SIZE; i++) { pmu_cpu_vdd_map[i].reg_value = i + 0x0b; pmu_cpu_vdd_map[i].reg_uV = 600000 + 10000 * i; } } static struct tegra_cl_dvfs_platform_data vcm30_t124_cl_dvfs_data = { .dfll_clk_name = "dfll_cpu", .pmu_if = TEGRA_CL_DVFS_PMU_I2C, .u.pmu_i2c = { .fs_rate = 400000, .slave_addr = 0x74, .reg = 0x07, }, .vdd_map = pmu_cpu_vdd_map, .vdd_map_size = PMU_CPU_VDD_MAP_SIZE, .flags = TEGRA_CL_DVFS_DYN_OUTPUT_CFG, .cfg_param = &vcm30_t124_cl_dvfs_param, }; static int __init vcm30_t124_cl_dvfs_init(void) { fill_reg_map(); tegra_cl_dvfs_device.dev.platform_data = &vcm30_t124_cl_dvfs_data; platform_device_register(&tegra_cl_dvfs_device); return 0; } #endif /* MAX15569 switching regulator for vdd_gpu */ static struct regulator_consumer_supply max15569_vddgpu_supply[] = { REGULATOR_SUPPLY("vdd_gpu", NULL), }; static struct regulator_init_data max15569_vddgpu_init_data = { .constraints = { .min_uV = 500000, .max_uV = 1520000, .valid_modes_mask = (REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY), .valid_ops_mask = (REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_CONTROL | REGULATOR_CHANGE_VOLTAGE), .always_on = 0, .boot_on = 0, .apply_uV = 0, }, .num_consumer_supplies = ARRAY_SIZE(max15569_vddgpu_supply), .consumer_supplies = max15569_vddgpu_supply, }; static struct max15569_regulator_platform_data max15569_vddgpu_pdata = { .reg_init_data = &max15569_vddgpu_init_data, .max_voltage_uV = 1400000, .slew_rate_mv_per_us = 44, }; static struct i2c_board_info __initdata max15569_vddgpu_boardinfo[] = { { I2C_BOARD_INFO("max15569", 0x38), .platform_data = &max15569_vddgpu_pdata, }, }; static int __init vcm30_t124_max77663_regulator_init(void) { int sku_rev; sku_rev = tegra_board_get_skurev("61859"); tegra_pmc_pmu_interrupt_polarity(true); #ifdef CONFIG_ARCH_TEGRA_HAS_CL_DVFS vcm30_t124_cl_dvfs_init(); #endif /* C01 boards have tegra gpio for gpu_pwr_req and * boards before C01 have PMU gpio for gpu_pwr_req */ if (sku_rev >= 300) { max15569_vddgpu_pdata.ena_gpio = TEGRA_GPIO_PR2; } else { max77663_pdata.num_gpio_cfgs = ARRAY_SIZE(max77663_gpio_cfgs); max77663_pdata.gpio_cfgs = max77663_gpio_cfgs; } i2c_register_board_info(4, max77663_regulators, ARRAY_SIZE(max77663_regulators)); return 0; } int __init vcm30_t124_regulator_init(void) { vcm30_t124_max77663_regulator_init(); i2c_register_board_info(4, max15569_vddcpu_boardinfo, 1); i2c_register_board_info(4, max15569_vddgpu_boardinfo, 1); return 0; } static struct tegra_suspend_platform_data vcm30_t124_suspend_data = { .cpu_timer = 2000, .cpu_off_timer = 2000, .suspend_mode = TEGRA_SUSPEND_LP0, .core_timer = 0xfefe, .core_off_timer = 2000, .corereq_high = true, .sysclkreq_high = true, .cpu_lp2_min_residency = 1000, }; int __init vcm30_t124_suspend_init(void) { tegra_init_suspend(&vcm30_t124_suspend_data); return 0; } static struct thermal_zone_params soctherm_tzp = { .governor_name = "pid_thermal_gov", }; static struct tegra_thermtrip_pmic_data tpdata_palmas = { .reset_tegra = 1, .pmu_16bit_ops = 0, .controller_type = 0, .pmu_i2c_addr = 0x58, .i2c_controller_id = 4, .poweroff_reg_addr = 0xa0, .poweroff_reg_data = 0x0, }; static struct tegra_thermtrip_pmic_data tpdata_max77663 = { .reset_tegra = 1, .pmu_16bit_ops = 0, .controller_type = 0, .pmu_i2c_addr = 0x3c, .i2c_controller_id = 4, .poweroff_reg_addr = 0x41, .poweroff_reg_data = 0x80, }; static struct soctherm_platform_data vcm30_t124_soctherm_data = { .therm = { [THERM_CPU] = { .zone_enable = true, .passive_delay = 1000, .hotspot_offset = 6000, .num_trips = 3, .trips = { { .cdev_type = "tegra-balanced", .trip_temp = 90000, .trip_type = THERMAL_TRIP_PASSIVE, .upper = THERMAL_NO_LIMIT, .lower = THERMAL_NO_LIMIT, }, { .cdev_type = "tegra-heavy", .trip_temp = 100000, .trip_type = THERMAL_TRIP_HOT, .upper = THERMAL_NO_LIMIT, .lower = THERMAL_NO_LIMIT, }, { .cdev_type = "tegra-shutdown", .trip_temp = 102000, .trip_type = THERMAL_TRIP_CRITICAL, .upper = THERMAL_NO_LIMIT, .lower = THERMAL_NO_LIMIT, }, }, .tzp = &soctherm_tzp, }, [THERM_GPU] = { .zone_enable = true, .passive_delay = 1000, .hotspot_offset = 6000, .num_trips = 3, .trips = { { .cdev_type = "tegra-balanced", .trip_temp = 90000, .trip_type = THERMAL_TRIP_PASSIVE, .upper = THERMAL_NO_LIMIT, .lower = THERMAL_NO_LIMIT, }, { .cdev_type = "tegra-heavy", .trip_temp = 100000, .trip_type = THERMAL_TRIP_HOT, .upper = THERMAL_NO_LIMIT, .lower = THERMAL_NO_LIMIT, }, { .cdev_type = "tegra-shutdown", .trip_temp = 102000, .trip_type = THERMAL_TRIP_CRITICAL, .upper = THERMAL_NO_LIMIT, .lower = THERMAL_NO_LIMIT, }, }, .tzp = &soctherm_tzp, }, [THERM_PLL] = { .zone_enable = true, }, }, .throttle = { [THROTTLE_HEAVY] = { .priority = 100, .devs = { [THROTTLE_DEV_CPU] = { .enable = true, .depth = 80, }, }, }, }, .tshut_pmu_trip_data = &tpdata_palmas, }; /* FIXME: Needed? */ int __init vcm30_t124_soctherm_init(void) { vcm30_t124_soctherm_data.tshut_pmu_trip_data = &tpdata_max77663; tegra_add_cpu_clk_switch_trips( vcm30_t124_soctherm_data.therm[THERM_CPU].trips, &vcm30_t124_soctherm_data.therm[THERM_CPU].num_trips); /*tegra_add_vc_trips(vcm30_t124_soctherm_data.therm[THERM_CPU].trips, &vcm30_t124_soctherm_data.therm[THERM_CPU].num_trips); */ return tegra11_soctherm_init(&vcm30_t124_soctherm_data); } /* * GPIO init table for PCA9539 MISC IO GPIOs * that have to be brought up to a known good state * except for WiFi as it is handled via the * WiFi stack. */ static struct gpio vcm30_t124_system_0_gpios[] = { {MISCIO_BT_RST_GPIO, GPIOF_OUT_INIT_HIGH, "bt_rst"}, #ifdef CONFIG_TEGRA_PREPOWER_WIFI {MISCIO_WF_EN_GPIO, GPIOF_OUT_INIT_HIGH, "wifi_en"}, {MISCIO_WF_RST_GPIO, GPIOF_OUT_INIT_HIGH, "wifi_rst"}, #else {MISCIO_WF_EN_GPIO, GPIOF_OUT_INIT_LOW, "wifi_en"}, {MISCIO_WF_RST_GPIO, GPIOF_OUT_INIT_LOW, "wifi_rst"}, #endif {MISCIO_BT_EN_GPIO, GPIOF_OUT_INIT_HIGH, "bt_en"}, {MISCIO_BT_WAKEUP_GPIO, GPIOF_OUT_INIT_HIGH, "bt_wk"}, {MISCIO_ABB_RST_GPIO, GPIOF_OUT_INIT_HIGH, "ebb_rst"}, {MISCIO_USER_LED2_GPIO, GPIOF_OUT_INIT_LOW, "usr_led2"}, {MISCIO_USER_LED1_GPIO, GPIOF_OUT_INIT_LOW, "usr_led1"}, }; /* * GPIO init table for PCA9539 MISC IO GPIOs * related to DAP_D_SEL and DAP_D_EN. */ static struct gpio vcm30_t124_system_1_gpios[] = { {MISCIO_MUX_DAP_D_SEL, GPIOF_OUT_INIT_LOW, "dap_d_sel"}, {MISCIO_MUX_DAP_D_EN, GPIOF_OUT_INIT_LOW, "dap_d_en"}, }; static int __init vcm30_t124_system_0_gpio_init(void) { int ret, pin_count = 0; struct gpio *gpios_info = NULL; gpios_info = vcm30_t124_system_0_gpios; pin_count = ARRAY_SIZE(vcm30_t124_system_0_gpios); /* Set required system GPIOs to initial bootup values */ ret = gpio_request_array(gpios_info, pin_count); if (ret) pr_err("%s gpio_request_array failed(%d)\r\n", __func__, ret); gpio_free_array(gpios_info, pin_count); return ret; } static int __init vcm30_t124_system_1_gpio_init(void) { int ret, pin_count = 0; struct gpio *gpios_info = NULL; gpios_info = vcm30_t124_system_1_gpios; pin_count = ARRAY_SIZE(vcm30_t124_system_1_gpios); /* Set required system GPIOs to initial bootup values */ ret = gpio_request_array(gpios_info, pin_count); if (ret) pr_err("%s gpio_request_array failed(%d)\r\n", __func__, ret); gpio_free_array(gpios_info, pin_count); return ret; } /* * TODO: Check for the correct pca953x before invoking client * init functions */ static int pca953x_client_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *context) { int ret = 0; int system = (int)context; switch (system) { case 0: ret = vcm30_t124_system_0_gpio_init(); break; case 1: ret = vcm30_t124_system_1_gpio_init(); break; default: ret = -EINVAL; } if (ret < 0) goto fail; return 0; fail: pr_err("%s failed(%d)\r\n", __func__, ret); return ret; } static struct pca953x_platform_data vcm30_t124_miscio_0_pca9539_data = { .gpio_base = PCA953X_MISCIO_0_GPIO_BASE, .setup = pca953x_client_setup, .context = (void *)0, }; static struct pca953x_platform_data vcm30_t124_miscio_1_pca9539_data = { .gpio_base = PCA953X_MISCIO_1_GPIO_BASE, .setup = pca953x_client_setup, .context = (void *)1, }; static struct i2c_board_info vcm30_t124_i2c2_board_info_pca9539_0 = { I2C_BOARD_INFO("pca9539", PCA953X_MISCIO_0_ADDR), .platform_data = &vcm30_t124_miscio_0_pca9539_data, }; static struct i2c_board_info vcm30_t124_i2c2_board_info_pca9539_1 = { I2C_BOARD_INFO("pca9539", PCA953X_MISCIO_1_ADDR), .platform_data = &vcm30_t124_miscio_1_pca9539_data, }; int __init vcm30_t124_pca953x_init(void) { int is_e1860_b00 = 0; is_e1860_b00 = tegra_is_board(NULL, "61860", NULL, "300", NULL); i2c_register_board_info(1, &vcm30_t124_i2c2_board_info_pca9539_0, 1); if (is_e1860_b00) { i2c_register_board_info(1, &vcm30_t124_i2c2_board_info_pca9539_1, 1); } return 0; }