/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(CONFIG_SMB137B_CHARGER_MODULE) #include #endif #ifdef CONFIG_SND_SOC_WM8903 #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_USB_G_ANDROID #include #include #endif #include #include #include #include #include #include #include #include #include "devices.h" #include "devices-msm8x60.h" #include #include "pm.h" #include #include "spm.h" #include "rpm_log.h" #include "timer.h" #include "gpiomux-8x60.h" #include "rpm_stats.h" #include "peripheral-loader.h" #include #include "rpm_resources.h" #include "clock.h" #include "pm-boot.h" #include "board-storage-common-a.h" #include #include #include #define MSM_SHARED_RAM_PHYS 0x40000000 #define MDM2AP_SYNC 129 #define GPIO_ETHERNET_RESET_N_DRAGON 30 #define LCDC_SPI_GPIO_CLK 73 #define LCDC_SPI_GPIO_CS 72 #define LCDC_SPI_GPIO_MOSI 70 #define LCDC_AUO_PANEL_NAME "lcdc_auo_wvga" #define LCDC_SAMSUNG_OLED_PANEL_NAME "lcdc_samsung_oled" #define LCDC_SAMSUNG_WSVGA_PANEL_NAME "lcdc_samsung_wsvga" #define LCDC_SAMSUNG_SPI_DEVICE_NAME "lcdc_samsung_ams367pe02" #define LCDC_AUO_SPI_DEVICE_NAME "lcdc_auo_nt35582" #define LCDC_NT35582_PANEL_NAME "lcdc_nt35582_wvga" #define MIPI_CMD_NOVATEK_QHD_PANEL_NAME "mipi_cmd_novatek_qhd" #define MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME "mipi_video_novatek_qhd" #define MIPI_VIDEO_TOSHIBA_WVGA_PANEL_NAME "mipi_video_toshiba_wvga" #define HDMI_PANEL_NAME "hdmi_msm" #define TVOUT_PANEL_NAME "tvout_msm" #define DSPS_PIL_GENERIC_NAME "dsps" #define DSPS_PIL_FLUID_NAME "dsps_fluid" #ifdef CONFIG_ION_MSM static struct platform_device ion_dev; #endif enum { GPIO_EXPANDER_IRQ_BASE = PM8901_IRQ_BASE + NR_PMIC8901_IRQS, GPIO_EXPANDER_GPIO_BASE = PM8901_MPP_BASE + PM8901_MPPS, /* CORE expander */ GPIO_CORE_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE, GPIO_CLASS_D1_EN = GPIO_CORE_EXPANDER_BASE, GPIO_WLAN_DEEP_SLEEP_N, GPIO_LVDS_SHUTDOWN_N, GPIO_DISP_RESX_N = GPIO_LVDS_SHUTDOWN_N, GPIO_MS_SYS_RESET_N, GPIO_CAP_TS_RESOUT_N, GPIO_CAP_GAUGE_BI_TOUT, GPIO_ETHERNET_PME, GPIO_EXT_GPS_LNA_EN, GPIO_MSM_WAKES_BT, GPIO_ETHERNET_RESET_N, GPIO_HEADSET_DET_N, GPIO_USB_UICC_EN, GPIO_BACKLIGHT_EN, GPIO_EXT_CAMIF_PWR_EN, GPIO_BATT_GAUGE_INT_N, GPIO_BATT_GAUGE_EN, /* DOCKING expander */ GPIO_DOCKING_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE + 16, GPIO_MIPI_DSI_RST_N = GPIO_DOCKING_EXPANDER_BASE, GPIO_AUX_JTAG_DET_N, GPIO_DONGLE_DET_N, GPIO_SVIDEO_LOAD_DET, GPIO_SVID_AMP_SHUTDOWN1_N, GPIO_SVID_AMP_SHUTDOWN0_N, GPIO_SDC_WP, GPIO_IRDA_PWDN, GPIO_IRDA_RESET_N, GPIO_DONGLE_GPIO0, GPIO_DONGLE_GPIO1, GPIO_DONGLE_GPIO2, GPIO_DONGLE_GPIO3, GPIO_DONGLE_PWR_EN, GPIO_EMMC_RESET_N, GPIO_TP_EXP2_IO15, /* SURF expander */ GPIO_SURF_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE + (16 * 2), GPIO_SD_CARD_DET_1 = GPIO_SURF_EXPANDER_BASE, GPIO_SD_CARD_DET_2, GPIO_SD_CARD_DET_4, GPIO_SD_CARD_DET_5, GPIO_UIM3_RST, GPIO_SURF_EXPANDER_IO5, GPIO_SURF_EXPANDER_IO6, GPIO_ADC_I2C_EN, GPIO_SURF_EXPANDER_IO8, GPIO_SURF_EXPANDER_IO9, GPIO_SURF_EXPANDER_IO10, GPIO_SURF_EXPANDER_IO11, GPIO_SURF_EXPANDER_IO12, GPIO_SURF_EXPANDER_IO13, GPIO_SURF_EXPANDER_IO14, GPIO_SURF_EXPANDER_IO15, /* LEFT KB IO expander */ GPIO_LEFT_KB_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE + (16 * 3), GPIO_LEFT_LED_1 = GPIO_LEFT_KB_EXPANDER_BASE, GPIO_LEFT_LED_2, GPIO_LEFT_LED_3, GPIO_LEFT_LED_WLAN, GPIO_JOYSTICK_EN, GPIO_CAP_TS_SLEEP, GPIO_LEFT_KB_IO6, GPIO_LEFT_LED_5, /* RIGHT KB IO expander */ GPIO_RIGHT_KB_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE + (16 * 3) + 8, GPIO_RIGHT_LED_1 = GPIO_RIGHT_KB_EXPANDER_BASE, GPIO_RIGHT_LED_2, GPIO_RIGHT_LED_3, GPIO_RIGHT_LED_BT, GPIO_WEB_CAMIF_STANDBY, GPIO_COMPASS_RST_N, GPIO_WEB_CAMIF_RESET_N, GPIO_RIGHT_LED_5, GPIO_R_ALTIMETER_RESET_N, /* FLUID S IO expander */ GPIO_SOUTH_EXPANDER_BASE, GPIO_MIC2_ANCR_SEL = GPIO_SOUTH_EXPANDER_BASE, GPIO_MIC1_ANCL_SEL, GPIO_HS_MIC4_SEL, GPIO_FML_MIC3_SEL, GPIO_FMR_MIC5_SEL, GPIO_TS_SLEEP, GPIO_HAP_SHIFT_LVL_OE, GPIO_HS_SW_DIR, /* FLUID N IO expander */ GPIO_NORTH_EXPANDER_BASE, GPIO_EPM_3_3V_EN = GPIO_NORTH_EXPANDER_BASE, GPIO_EPM_5V_BOOST_EN, GPIO_AUX_CAM_2P7_EN, GPIO_LED_FLASH_EN, GPIO_LED1_GREEN_N, GPIO_LED2_RED_N, GPIO_FRONT_CAM_RESET_N, GPIO_EPM_LVLSFT_EN, GPIO_N_ALTIMETER_RESET_N, /* EPM expander */ GPIO_EPM_EXPANDER_BASE, GPIO_PWR_MON_START = GPIO_EPM_EXPANDER_BASE, GPIO_PWR_MON_RESET_N, GPIO_ADC1_PWDN_N, GPIO_ADC2_PWDN_N, GPIO_EPM_EXPANDER_IO4, GPIO_ADC1_MUX_SPI_INT_N_3_3V, GPIO_ADC2_MUX_SPI_INT_N, GPIO_EPM_EXPANDER_IO7, GPIO_PWR_MON_ENABLE, GPIO_EPM_SPI_ADC1_CS_N, GPIO_EPM_SPI_ADC2_CS_N, GPIO_EPM_EXPANDER_IO11, GPIO_EPM_EXPANDER_IO12, GPIO_EPM_EXPANDER_IO13, GPIO_EPM_EXPANDER_IO14, GPIO_EPM_EXPANDER_IO15, }; struct pm8xxx_mpp_init_info { unsigned mpp; struct pm8xxx_mpp_config_data config; }; #define PM8058_MPP_INIT(_mpp, _type, _level, _control) \ { \ .mpp = PM8058_MPP_PM_TO_SYS(_mpp), \ .config = { \ .type = PM8XXX_MPP_TYPE_##_type, \ .level = _level, \ .control = PM8XXX_MPP_##_control, \ } \ } #define PM8901_MPP_INIT(_mpp, _type, _level, _control) \ { \ .mpp = PM8901_MPP_PM_TO_SYS(_mpp), \ .config = { \ .type = PM8XXX_MPP_TYPE_##_type, \ .level = _level, \ .control = PM8XXX_MPP_##_control, \ } \ } /* * The UI_INTx_N lines are pmic gpio lines which connect i2c * gpio expanders to the pm8058. */ #define UI_INT1_N 25 #define UI_INT2_N 34 #define UI_INT3_N 14 /* FM GPIO is GPIO 18 on PMIC 8058. As the index starts from 0 in the PMIC driver, and hence 17 corresponds to GPIO 18 on PMIC 8058. */ #define FM_GPIO 17 #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT static void (*sdc2_status_notify_cb)(int card_present, void *dev_id); static void *sdc2_status_notify_cb_devid; #endif #ifdef CONFIG_MMC_MSM_SDC5_SUPPORT static void (*sdc5_status_notify_cb)(int card_present, void *dev_id); static void *sdc5_status_notify_cb_devid; #endif static struct msm_spm_platform_data msm_spm_data_v1[] __initdata = { [0] = { .reg_base_addr = MSM_SAW0_BASE, .reg_init_values[MSM_SPM_REG_SAW_CFG] = 0x0F, .reg_init_values[MSM_SPM_REG_SAW_SPM_CTL] = 0x68, .reg_init_values[MSM_SPM_REG_SAW_SPM_SLP_TMR_DLY] = 0xFFFFFFFF, .reg_init_values[MSM_SPM_REG_SAW_SPM_WAKE_TMR_DLY] = 0xFFFFFFFF, .reg_init_values[MSM_SPM_REG_SAW_SLP_CLK_EN] = 0x01, .reg_init_values[MSM_SPM_REG_SAW_SLP_HSFS_PRECLMP_EN] = 0x07, .reg_init_values[MSM_SPM_REG_SAW_SLP_HSFS_POSTCLMP_EN] = 0x00, .reg_init_values[MSM_SPM_REG_SAW_SLP_CLMP_EN] = 0x01, .reg_init_values[MSM_SPM_REG_SAW_SLP_RST_EN] = 0x00, .reg_init_values[MSM_SPM_REG_SAW_SPM_MPM_CFG] = 0x00, .awake_vlevel = 0x94, .retention_vlevel = 0x81, .collapse_vlevel = 0x20, .retention_mid_vlevel = 0x94, .collapse_mid_vlevel = 0x8C, .vctl_timeout_us = 50, }, [1] = { .reg_base_addr = MSM_SAW1_BASE, .reg_init_values[MSM_SPM_REG_SAW_CFG] = 0x0F, .reg_init_values[MSM_SPM_REG_SAW_SPM_CTL] = 0x68, .reg_init_values[MSM_SPM_REG_SAW_SPM_SLP_TMR_DLY] = 0xFFFFFFFF, .reg_init_values[MSM_SPM_REG_SAW_SPM_WAKE_TMR_DLY] = 0xFFFFFFFF, .reg_init_values[MSM_SPM_REG_SAW_SLP_CLK_EN] = 0x13, .reg_init_values[MSM_SPM_REG_SAW_SLP_HSFS_PRECLMP_EN] = 0x07, .reg_init_values[MSM_SPM_REG_SAW_SLP_HSFS_POSTCLMP_EN] = 0x00, .reg_init_values[MSM_SPM_REG_SAW_SLP_CLMP_EN] = 0x01, .reg_init_values[MSM_SPM_REG_SAW_SLP_RST_EN] = 0x00, .reg_init_values[MSM_SPM_REG_SAW_SPM_MPM_CFG] = 0x00, .awake_vlevel = 0x94, .retention_vlevel = 0x81, .collapse_vlevel = 0x20, .retention_mid_vlevel = 0x94, .collapse_mid_vlevel = 0x8C, .vctl_timeout_us = 50, }, }; static struct msm_spm_platform_data msm_spm_data[] __initdata = { [0] = { .reg_base_addr = MSM_SAW0_BASE, .reg_init_values[MSM_SPM_REG_SAW_CFG] = 0x1C, .reg_init_values[MSM_SPM_REG_SAW_SPM_CTL] = 0x68, .reg_init_values[MSM_SPM_REG_SAW_SPM_SLP_TMR_DLY] = 0x0C0CFFFF, .reg_init_values[MSM_SPM_REG_SAW_SPM_WAKE_TMR_DLY] = 0x78780FFF, .reg_init_values[MSM_SPM_REG_SAW_SLP_CLK_EN] = 0x01, .reg_init_values[MSM_SPM_REG_SAW_SLP_HSFS_PRECLMP_EN] = 0x07, .reg_init_values[MSM_SPM_REG_SAW_SLP_HSFS_POSTCLMP_EN] = 0x00, .reg_init_values[MSM_SPM_REG_SAW_SLP_CLMP_EN] = 0x01, .reg_init_values[MSM_SPM_REG_SAW_SLP_RST_EN] = 0x00, .reg_init_values[MSM_SPM_REG_SAW_SPM_MPM_CFG] = 0x00, .awake_vlevel = 0xA0, .retention_vlevel = 0x89, .collapse_vlevel = 0x20, .retention_mid_vlevel = 0x89, .collapse_mid_vlevel = 0x89, .vctl_timeout_us = 50, }, [1] = { .reg_base_addr = MSM_SAW1_BASE, .reg_init_values[MSM_SPM_REG_SAW_CFG] = 0x1C, .reg_init_values[MSM_SPM_REG_SAW_SPM_CTL] = 0x68, .reg_init_values[MSM_SPM_REG_SAW_SPM_SLP_TMR_DLY] = 0x0C0CFFFF, .reg_init_values[MSM_SPM_REG_SAW_SPM_WAKE_TMR_DLY] = 0x78780FFF, .reg_init_values[MSM_SPM_REG_SAW_SLP_CLK_EN] = 0x13, .reg_init_values[MSM_SPM_REG_SAW_SLP_HSFS_PRECLMP_EN] = 0x07, .reg_init_values[MSM_SPM_REG_SAW_SLP_HSFS_POSTCLMP_EN] = 0x00, .reg_init_values[MSM_SPM_REG_SAW_SLP_CLMP_EN] = 0x01, .reg_init_values[MSM_SPM_REG_SAW_SLP_RST_EN] = 0x00, .reg_init_values[MSM_SPM_REG_SAW_SPM_MPM_CFG] = 0x00, .awake_vlevel = 0xA0, .retention_vlevel = 0x89, .collapse_vlevel = 0x20, .retention_mid_vlevel = 0x89, .collapse_mid_vlevel = 0x89, .vctl_timeout_us = 50, }, }; /* * Consumer specific regulator names: * regulator name consumer dev_name */ static struct regulator_consumer_supply vreg_consumers_8901_S0[] = { REGULATOR_SUPPLY("8901_s0", NULL), }; static struct regulator_consumer_supply vreg_consumers_8901_S1[] = { REGULATOR_SUPPLY("8901_s1", NULL), }; static struct regulator_init_data saw_s0_init_data = { .constraints = { .name = "8901_s0", .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, .min_uV = 800000, .max_uV = 1325000, }, .consumer_supplies = vreg_consumers_8901_S0, .num_consumer_supplies = ARRAY_SIZE(vreg_consumers_8901_S0), }; static struct regulator_init_data saw_s1_init_data = { .constraints = { .name = "8901_s1", .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, .min_uV = 800000, .max_uV = 1325000, }, .consumer_supplies = vreg_consumers_8901_S1, .num_consumer_supplies = ARRAY_SIZE(vreg_consumers_8901_S1), }; static struct platform_device msm_device_saw_s0 = { .name = "saw-regulator", .id = 0, .dev = { .platform_data = &saw_s0_init_data, }, }; static struct platform_device msm_device_saw_s1 = { .name = "saw-regulator", .id = 1, .dev = { .platform_data = &saw_s1_init_data, }, }; static struct resource smsc911x_resources[] = { [0] = { .flags = IORESOURCE_MEM, .start = 0x1b800000, .end = 0x1b8000ff }, [1] = { .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, }, }; static struct smsc911x_platform_config smsc911x_config = { .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, .flags = SMSC911X_USE_16BIT, .has_reset_gpio = 1, .reset_gpio = GPIO_ETHERNET_RESET_N }; static struct platform_device smsc911x_device = { .name = "smsc911x", .id = 0, .num_resources = ARRAY_SIZE(smsc911x_resources), .resource = smsc911x_resources, .dev = { .platform_data = &smsc911x_config } }; #if \ defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \ \ defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE) #define QCE_SIZE 0x10000 #define QCE_0_BASE 0x18500000 #define QCE_HW_KEY_SUPPORT 0 #define QCE_SHA_HMAC_SUPPORT 0 #define QCE_SHARE_CE_RESOURCE 2 #define QCE_CE_SHARED 1 static struct resource qcrypto_resources[] = { [0] = { .start = QCE_0_BASE, .end = QCE_0_BASE + QCE_SIZE - 1, .flags = IORESOURCE_MEM, }, [1] = { .name = "crypto_channels", .start = DMOV_CE_IN_CHAN, .end = DMOV_CE_OUT_CHAN, .flags = IORESOURCE_DMA, }, [2] = { .name = "crypto_crci_in", .start = DMOV_CE_IN_CRCI, .end = DMOV_CE_IN_CRCI, .flags = IORESOURCE_DMA, }, [3] = { .name = "crypto_crci_out", .start = DMOV_CE_OUT_CRCI, .end = DMOV_CE_OUT_CRCI, .flags = IORESOURCE_DMA, }, [4] = { .name = "crypto_crci_hash", .start = DMOV_CE_HASH_CRCI, .end = DMOV_CE_HASH_CRCI, .flags = IORESOURCE_DMA, }, }; static struct resource qcedev_resources[] = { [0] = { .start = QCE_0_BASE, .end = QCE_0_BASE + QCE_SIZE - 1, .flags = IORESOURCE_MEM, }, [1] = { .name = "crypto_channels", .start = DMOV_CE_IN_CHAN, .end = DMOV_CE_OUT_CHAN, .flags = IORESOURCE_DMA, }, [2] = { .name = "crypto_crci_in", .start = DMOV_CE_IN_CRCI, .end = DMOV_CE_IN_CRCI, .flags = IORESOURCE_DMA, }, [3] = { .name = "crypto_crci_out", .start = DMOV_CE_OUT_CRCI, .end = DMOV_CE_OUT_CRCI, .flags = IORESOURCE_DMA, }, [4] = { .name = "crypto_crci_hash", .start = DMOV_CE_HASH_CRCI, .end = DMOV_CE_HASH_CRCI, .flags = IORESOURCE_DMA, }, }; #endif #if \ defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) static struct msm_ce_hw_support qcrypto_ce_hw_suppport = { .ce_shared = QCE_CE_SHARED, .shared_ce_resource = QCE_SHARE_CE_RESOURCE, .hw_key_support = QCE_HW_KEY_SUPPORT, .sha_hmac = QCE_SHA_HMAC_SUPPORT, .bus_scale_table = NULL, }; static struct platform_device qcrypto_device = { .name = "qcrypto", .id = 0, .num_resources = ARRAY_SIZE(qcrypto_resources), .resource = qcrypto_resources, .dev = { .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = &qcrypto_ce_hw_suppport, }, }; #endif #if \ defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE) static struct msm_ce_hw_support qcedev_ce_hw_suppport = { .ce_shared = QCE_CE_SHARED, .shared_ce_resource = QCE_SHARE_CE_RESOURCE, .hw_key_support = QCE_HW_KEY_SUPPORT, .sha_hmac = QCE_SHA_HMAC_SUPPORT, .bus_scale_table = NULL, }; static struct platform_device qcedev_device = { .name = "qce", .id = 0, .num_resources = ARRAY_SIZE(qcedev_resources), .resource = qcedev_resources, .dev = { .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = &qcedev_ce_hw_suppport, }, }; #endif #if \ defined(CONFIG_HAPTIC_ISA1200_MODULE) static const char *vregs_isa1200_name[] = { "8058_s3", "8901_l4", }; static const int vregs_isa1200_val[] = { 1800000,/* uV */ 2600000, }; static struct regulator *vregs_isa1200[ARRAY_SIZE(vregs_isa1200_name)]; static struct msm_xo_voter *xo_handle_a1; static int isa1200_power(int vreg_on) { int i, rc = 0; for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++) { rc = vreg_on ? regulator_enable(vregs_isa1200[i]) : regulator_disable(vregs_isa1200[i]); if (rc < 0) { pr_err("%s: vreg %s %s failed (%d)\n", __func__, vregs_isa1200_name[i], vreg_on ? "enable" : "disable", rc); goto vreg_fail; } } rc = vreg_on ? msm_xo_mode_vote(xo_handle_a1, MSM_XO_MODE_ON) : msm_xo_mode_vote(xo_handle_a1, MSM_XO_MODE_OFF); if (rc < 0) { pr_err("%s: failed to %svote for TCXO A1 buffer%d\n", __func__, vreg_on ? "" : "de-", rc); goto vreg_fail; } return 0; vreg_fail: while (i--) !vreg_on ? regulator_enable(vregs_isa1200[i]) : regulator_disable(vregs_isa1200[i]); return rc; } static int isa1200_dev_setup(bool enable) { int i, rc; if (enable == true) { for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++) { vregs_isa1200[i] = regulator_get(NULL, vregs_isa1200_name[i]); if (IS_ERR(vregs_isa1200[i])) { pr_err("%s: regulator get of %s failed (%ld)\n", __func__, vregs_isa1200_name[i], PTR_ERR(vregs_isa1200[i])); rc = PTR_ERR(vregs_isa1200[i]); goto vreg_get_fail; } rc = regulator_set_voltage(vregs_isa1200[i], vregs_isa1200_val[i], vregs_isa1200_val[i]); if (rc) { pr_err("%s: regulator_set_voltage(%s) failed\n", __func__, vregs_isa1200_name[i]); goto vreg_get_fail; } } rc = gpio_request(GPIO_HAP_SHIFT_LVL_OE, "haptics_shft_lvl_oe"); if (rc) { pr_err("%s: unable to request gpio %d (%d)\n", __func__, GPIO_HAP_SHIFT_LVL_OE, rc); goto vreg_get_fail; } rc = gpio_direction_output(GPIO_HAP_SHIFT_LVL_OE, 1); if (rc) { pr_err("%s: Unable to set direction\n", __func__);; goto free_gpio; } xo_handle_a1 = msm_xo_get(MSM_XO_TCXO_A1, "isa1200"); if (IS_ERR(xo_handle_a1)) { rc = PTR_ERR(xo_handle_a1); pr_err("%s: failed to get the handle for A1(%d)\n", __func__, rc); goto gpio_set_dir; } } else { gpio_set_value(GPIO_HAP_SHIFT_LVL_OE, 0); gpio_free(GPIO_HAP_SHIFT_LVL_OE); for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++) regulator_put(vregs_isa1200[i]); msm_xo_put(xo_handle_a1); } return 0; gpio_set_dir: gpio_set_value(GPIO_HAP_SHIFT_LVL_OE, 0); free_gpio: gpio_free(GPIO_HAP_SHIFT_LVL_OE); vreg_get_fail: while (i) regulator_put(vregs_isa1200[--i]); return rc; } #define PMIC_GPIO_HAP_ENABLE 18 /* PMIC GPIO Number 19 */ #define PMIC_GPIO_HAP_LDO_ENABLE 5 /* PMIC GPIO Number 6 */ static struct isa1200_platform_data isa1200_1_pdata = { .name = "vibrator", .power_on = isa1200_power, .dev_setup = isa1200_dev_setup, /*gpio to enable haptic*/ .hap_en_gpio = PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_ENABLE), .hap_len_gpio = PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_LDO_ENABLE), .max_timeout = 15000, .mode_ctrl = PWM_GEN_MODE, .pwm_fd = { .pwm_div = 256, }, .is_erm = false, .smart_en = true, .ext_clk_en = true, .chip_en = 1, }; static struct i2c_board_info msm_isa1200_board_info[] = { { I2C_BOARD_INFO("isa1200_1", 0x90>>1), .platform_data = &isa1200_1_pdata, }, }; #endif #if \ defined(CONFIG_BATTERY_BQ27520_MODULE) static struct bq27520_platform_data bq27520_pdata = { .name = "fuel-gauge", .vreg_name = "8058_s3", .vreg_value = 1800000, .soc_int = GPIO_BATT_GAUGE_INT_N, .bi_tout = GPIO_CAP_GAUGE_BI_TOUT, .chip_en = GPIO_BATT_GAUGE_EN, .enable_dlog = 0, /* if enable coulomb counter logger */ }; static struct i2c_board_info msm_bq27520_board_info[] = { { I2C_BOARD_INFO("bq27520", 0xaa>>1), .platform_data = &bq27520_pdata, }, }; #endif static struct msm_rpmrs_level msm_rpmrs_levels[] __initdata = { { MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT, MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE), true, 1, 8000, 100000, 1, }, { MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE, MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE), true, 1500, 5000, 60100000, 3000, }, { MSM_PM_SLEEP_MODE_POWER_COLLAPSE, MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE), false, 1800, 5000, 60350000, 3500, }, { MSM_PM_SLEEP_MODE_POWER_COLLAPSE, MSM_RPMRS_LIMITS(OFF, ACTIVE, MAX, ACTIVE), false, 3800, 4500, 65350000, 5500, }, { MSM_PM_SLEEP_MODE_POWER_COLLAPSE, MSM_RPMRS_LIMITS(ON, HSFS_OPEN, MAX, ACTIVE), false, 2800, 2500, 66850000, 4800, }, { MSM_PM_SLEEP_MODE_POWER_COLLAPSE, MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, MAX, ACTIVE), false, 4800, 2000, 71850000, 6800, }, { MSM_PM_SLEEP_MODE_POWER_COLLAPSE, MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, ACTIVE, RET_HIGH), false, 6800, 500, 75850000, 8800, }, { MSM_PM_SLEEP_MODE_POWER_COLLAPSE, MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, RET_HIGH, RET_LOW), false, 7800, 0, 76350000, 9800, }, }; static struct msm_rpmrs_platform_data msm_rpmrs_data __initdata = { .levels = &msm_rpmrs_levels[0], .num_levels = ARRAY_SIZE(msm_rpmrs_levels), .vdd_mem_levels = { [MSM_RPMRS_VDD_MEM_RET_LOW] = 500, [MSM_RPMRS_VDD_MEM_RET_HIGH] = 750, [MSM_RPMRS_VDD_MEM_ACTIVE] = 1000, [MSM_RPMRS_VDD_MEM_MAX] = 1325, }, .vdd_dig_levels = { [MSM_RPMRS_VDD_DIG_RET_LOW] = 500, [MSM_RPMRS_VDD_DIG_RET_HIGH] = 750, [MSM_RPMRS_VDD_DIG_ACTIVE] = 1000, [MSM_RPMRS_VDD_DIG_MAX] = 1250, }, .vdd_mask = 0xFFF, .rpmrs_target_id = { [MSM_RPMRS_ID_PXO_CLK] = MSM_RPM_ID_PXO_CLK, [MSM_RPMRS_ID_L2_CACHE_CTL] = MSM_RPM_ID_APPS_L2_CACHE_CTL, [MSM_RPMRS_ID_VDD_DIG_0] = MSM_RPM_ID_SMPS1_0, [MSM_RPMRS_ID_VDD_DIG_1] = MSM_RPM_ID_SMPS1_1, [MSM_RPMRS_ID_VDD_MEM_0] = MSM_RPM_ID_SMPS0_0, [MSM_RPMRS_ID_VDD_MEM_1] = MSM_RPM_ID_SMPS0_1, [MSM_RPMRS_ID_RPM_CTL] = MSM_RPM_ID_TRIGGER_SET_FROM, }, }; static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = { .mode = MSM_PM_BOOT_CONFIG_TZ, }; #if defined(CONFIG_USB_PEHCI_HCD) || defined(CONFIG_USB_PEHCI_HCD_MODULE) #define ISP1763_INT_GPIO 117 #define ISP1763_RST_GPIO 152 static struct resource isp1763_resources[] = { [0] = { .flags = IORESOURCE_MEM, .start = 0x1D000000, .end = 0x1D005FFF, /* 24KB */ }, [1] = { .flags = IORESOURCE_IRQ, }, }; static void __init msm8x60_cfg_isp1763(void) { isp1763_resources[1].start = gpio_to_irq(ISP1763_INT_GPIO); isp1763_resources[1].end = gpio_to_irq(ISP1763_INT_GPIO); } static int isp1763_setup_gpio(int enable) { int status = 0; if (enable) { status = gpio_request(ISP1763_INT_GPIO, "isp1763_usb"); if (status) { pr_err("%s:Failed to request GPIO %d\n", __func__, ISP1763_INT_GPIO); return status; } status = gpio_direction_input(ISP1763_INT_GPIO); if (status) { pr_err("%s:Failed to configure GPIO %d\n", __func__, ISP1763_INT_GPIO); goto gpio_free_int; } status = gpio_request(ISP1763_RST_GPIO, "isp1763_usb"); if (status) { pr_err("%s:Failed to request GPIO %d\n", __func__, ISP1763_RST_GPIO); goto gpio_free_int; } status = gpio_direction_output(ISP1763_RST_GPIO, 1); if (status) { pr_err("%s:Failed to configure GPIO %d\n", __func__, ISP1763_RST_GPIO); goto gpio_free_rst; } pr_debug("\nISP GPIO configuration done\n"); return status; } gpio_free_rst: gpio_free(ISP1763_RST_GPIO); gpio_free_int: gpio_free(ISP1763_INT_GPIO); return status; } static struct isp1763_platform_data isp1763_pdata = { .reset_gpio = ISP1763_RST_GPIO, .setup_gpio = isp1763_setup_gpio }; static struct platform_device isp1763_device = { .name = "isp1763_usb", .num_resources = ARRAY_SIZE(isp1763_resources), .resource = isp1763_resources, .dev = { .platform_data = &isp1763_pdata } }; #endif #if defined(CONFIG_USB_EHCI_MSM_72K) static struct msm_otg_platform_data msm_otg_pdata; static struct regulator *ldo6_3p3; static struct regulator *ldo7_1p8; static struct regulator *vdd_cx; #define PMICID_INT PM8058_GPIO_IRQ(PM8058_IRQ_BASE, 36) #define PMIC_ID_GPIO 36 notify_vbus_state notify_vbus_state_func_ptr; static int usb_phy_susp_dig_vol = 750000; static int pmic_id_notif_supported; #ifdef CONFIG_USB_EHCI_MSM_72K #define USB_PMIC_ID_DET_DELAY msecs_to_jiffies(100) struct delayed_work pmic_id_det; static int __init usb_id_pin_rework_setup(char *support) { if (strncmp(support, "true", 4) == 0) pmic_id_notif_supported = 1; return 1; } __setup("usb_id_pin_rework=", usb_id_pin_rework_setup); static void pmic_id_detect(struct work_struct *w) { int val = gpio_get_value_cansleep(PM8058_GPIO_PM_TO_SYS(36)); pr_debug("%s(): gpio_read_value = %d\n", __func__, val); if (notify_vbus_state_func_ptr) (*notify_vbus_state_func_ptr) (val); } static irqreturn_t pmic_id_on_irq(int irq, void *data) { /* * Spurious interrupts are observed on pmic gpio line * even though there is no state change on USB ID. Schedule the * work to to allow debounce on gpio */ schedule_delayed_work(&pmic_id_det, USB_PMIC_ID_DET_DELAY); return IRQ_HANDLED; } static int msm_hsusb_phy_id_setup_init(int init) { unsigned ret; struct pm8xxx_mpp_config_data hsusb_phy_mpp = { .type = PM8XXX_MPP_TYPE_D_OUTPUT, .level = PM8901_MPP_DIG_LEVEL_L5, }; if (init) { hsusb_phy_mpp.control = PM8XXX_MPP_DOUT_CTRL_HIGH; ret = pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1), &hsusb_phy_mpp); if (ret < 0) pr_err("%s:MPP2 configuration failed\n", __func__); } else { hsusb_phy_mpp.control = PM8XXX_MPP_DOUT_CTRL_LOW; ret = pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1), &hsusb_phy_mpp); if (ret < 0) pr_err("%s:MPP2 un config failed\n", __func__); } return ret; } static int msm_hsusb_pmic_id_notif_init(void (*callback)(int online), int init) { unsigned ret = -ENODEV; struct pm_gpio pmic_id_cfg = { .direction = PM_GPIO_DIR_IN, .pull = PM_GPIO_PULL_UP_1P5, .function = PM_GPIO_FUNC_NORMAL, .vin_sel = 2, .inv_int_pol = 0, }; struct pm_gpio pmic_id_uncfg = { .direction = PM_GPIO_DIR_IN, .pull = PM_GPIO_PULL_NO, .function = PM_GPIO_FUNC_NORMAL, .vin_sel = 2, .inv_int_pol = 0, }; if (!callback) return -EINVAL; if (machine_is_msm8x60_fluid()) return -ENOTSUPP; if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 2) { pr_debug("%s: USB_ID pin is not routed to PMIC" "on V1 surf/ffa\n", __func__); return -ENOTSUPP; } if ((machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa() || machine_is_msm8x60_ffa()) && !pmic_id_notif_supported) { pr_debug("%s: USB_ID is not routed to PMIC" "on V2 ffa\n", __func__); return -ENOTSUPP; } usb_phy_susp_dig_vol = 500000; if (init) { notify_vbus_state_func_ptr = callback; INIT_DELAYED_WORK(&pmic_id_det, pmic_id_detect); ret = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(PMIC_ID_GPIO), &pmic_id_cfg); if (ret) { pr_err("%s:return val of pm8xxx_gpio_config: %d\n", __func__, ret); return ret; } ret = request_threaded_irq(PMICID_INT, NULL, pmic_id_on_irq, (IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING), "msm_otg_id", NULL); if (ret) { pr_err("%s:pmic_usb_id interrupt registration failed", __func__); return ret; } msm_otg_pdata.pmic_id_irq = PMICID_INT; } else { usb_phy_susp_dig_vol = 750000; free_irq(PMICID_INT, 0); ret = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(PMIC_ID_GPIO), &pmic_id_uncfg); if (ret) { pr_err("%s: return val of pm8xxx_gpio_config: %d\n", __func__, ret); return ret; } msm_otg_pdata.pmic_id_irq = 0; cancel_delayed_work_sync(&pmic_id_det); notify_vbus_state_func_ptr = NULL; } return 0; } #endif #define USB_PHY_OPERATIONAL_MIN_VDD_DIG_VOL 1000000 #define USB_PHY_MAX_VDD_DIG_VOL 1320000 static int msm_hsusb_init_vddcx(int init) { int ret = 0; if (init) { vdd_cx = regulator_get(NULL, "8058_s1"); if (IS_ERR(vdd_cx)) { return PTR_ERR(vdd_cx); } ret = regulator_set_voltage(vdd_cx, USB_PHY_OPERATIONAL_MIN_VDD_DIG_VOL, USB_PHY_MAX_VDD_DIG_VOL); if (ret) { pr_err("%s: unable to set the voltage for regulator" "vdd_cx\n", __func__); regulator_put(vdd_cx); return ret; } ret = regulator_enable(vdd_cx); if (ret) { pr_err("%s: unable to enable regulator" "vdd_cx\n", __func__); regulator_put(vdd_cx); } } else { ret = regulator_disable(vdd_cx); if (ret) { pr_err("%s: Unable to disable the regulator:" "vdd_cx\n", __func__); return ret; } regulator_put(vdd_cx); } return ret; } static int msm_hsusb_config_vddcx(int high) { int max_vol = USB_PHY_MAX_VDD_DIG_VOL; int min_vol; int ret; if (high) min_vol = USB_PHY_OPERATIONAL_MIN_VDD_DIG_VOL; else min_vol = usb_phy_susp_dig_vol; ret = regulator_set_voltage(vdd_cx, min_vol, max_vol); if (ret) { pr_err("%s: unable to set the voltage for regulator" "vdd_cx\n", __func__); return ret; } pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol); return ret; } #define USB_PHY_3P3_VOL_MIN 3050000 /* uV */ #define USB_PHY_3P3_VOL_MAX 3050000 /* uV */ #define USB_PHY_3P3_HPM_LOAD 50000 /* uA */ #define USB_PHY_3P3_LPM_LOAD 4000 /* uA */ #define USB_PHY_1P8_VOL_MIN 1800000 /* uV */ #define USB_PHY_1P8_VOL_MAX 1800000 /* uV */ #define USB_PHY_1P8_HPM_LOAD 50000 /* uA */ #define USB_PHY_1P8_LPM_LOAD 4000 /* uA */ static int msm_hsusb_ldo_init(int init) { int rc = 0; if (init) { ldo6_3p3 = regulator_get(NULL, "8058_l6"); if (IS_ERR(ldo6_3p3)) return PTR_ERR(ldo6_3p3); ldo7_1p8 = regulator_get(NULL, "8058_l7"); if (IS_ERR(ldo7_1p8)) { rc = PTR_ERR(ldo7_1p8); goto put_3p3; } rc = regulator_set_voltage(ldo6_3p3, USB_PHY_3P3_VOL_MIN, USB_PHY_3P3_VOL_MAX); if (rc) { pr_err("%s: Unable to set voltage level for" "ldo6_3p3 regulator\n", __func__); goto put_1p8; } rc = regulator_enable(ldo6_3p3); if (rc) { pr_err("%s: Unable to enable the regulator:" "ldo6_3p3\n", __func__); goto put_1p8; } rc = regulator_set_voltage(ldo7_1p8, USB_PHY_1P8_VOL_MIN, USB_PHY_1P8_VOL_MAX); if (rc) { pr_err("%s: Unable to set voltage level for" "ldo7_1p8 regulator\n", __func__); goto disable_3p3; } rc = regulator_enable(ldo7_1p8); if (rc) { pr_err("%s: Unable to enable the regulator:" "ldo7_1p8\n", __func__); goto disable_3p3; } return 0; } regulator_disable(ldo7_1p8); disable_3p3: regulator_disable(ldo6_3p3); put_1p8: regulator_put(ldo7_1p8); put_3p3: regulator_put(ldo6_3p3); return rc; } static int msm_hsusb_ldo_enable(int on) { int ret = 0; if (!ldo7_1p8 || IS_ERR(ldo7_1p8)) { pr_err("%s: ldo7_1p8 is not initialized\n", __func__); return -ENODEV; } if (!ldo6_3p3 || IS_ERR(ldo6_3p3)) { pr_err("%s: ldo6_3p3 is not initialized\n", __func__); return -ENODEV; } if (on) { ret = regulator_set_optimum_mode(ldo7_1p8, USB_PHY_1P8_HPM_LOAD); if (ret < 0) { pr_err("%s: Unable to set HPM of the regulator:" "ldo7_1p8\n", __func__); return ret; } ret = regulator_set_optimum_mode(ldo6_3p3, USB_PHY_3P3_HPM_LOAD); if (ret < 0) { pr_err("%s: Unable to set HPM of the regulator:" "ldo6_3p3\n", __func__); regulator_set_optimum_mode(ldo7_1p8, USB_PHY_1P8_LPM_LOAD); return ret; } } else { ret = regulator_set_optimum_mode(ldo7_1p8, USB_PHY_1P8_LPM_LOAD); if (ret < 0) pr_err("%s: Unable to set LPM of the regulator:" "ldo7_1p8\n", __func__); ret = regulator_set_optimum_mode(ldo6_3p3, USB_PHY_3P3_LPM_LOAD); if (ret < 0) pr_err("%s: Unable to set LPM of the regulator:" "ldo6_3p3\n", __func__); } pr_debug("reg (%s)\n", on ? "HPM" : "LPM"); return ret < 0 ? ret : 0; } #endif #ifdef CONFIG_USB_EHCI_MSM_72K #if defined(CONFIG_SMB137B_CHARGER_MODULE) static void msm_hsusb_smb137b_vbus_power(unsigned phy_info, int on) { static int vbus_is_on; /* If VBUS is already on (or off), do nothing. */ if (on == vbus_is_on) return; smb137b_otg_power(on); vbus_is_on = on; } #endif static void msm_hsusb_vbus_power(unsigned phy_info, int on) { static struct regulator *votg_5v_switch; static struct regulator *ext_5v_reg; static int vbus_is_on; /* If VBUS is already on (or off), do nothing. */ if (on == vbus_is_on) return; if (!votg_5v_switch) { votg_5v_switch = regulator_get(NULL, "8901_usb_otg"); if (IS_ERR(votg_5v_switch)) { pr_err("%s: unable to get votg_5v_switch\n", __func__); return; } } if (!ext_5v_reg) { ext_5v_reg = regulator_get(NULL, "8901_mpp0"); if (IS_ERR(ext_5v_reg)) { pr_err("%s: unable to get ext_5v_reg\n", __func__); return; } } if (on) { if (regulator_enable(ext_5v_reg)) { pr_err("%s: Unable to enable the regulator:" " ext_5v_reg\n", __func__); return; } if (regulator_enable(votg_5v_switch)) { pr_err("%s: Unable to enable the regulator:" " votg_5v_switch\n", __func__); return; } } else { if (regulator_disable(votg_5v_switch)) pr_err("%s: Unable to enable the regulator:" " votg_5v_switch\n", __func__); if (regulator_disable(ext_5v_reg)) pr_err("%s: Unable to enable the regulator:" " ext_5v_reg\n", __func__); } vbus_is_on = on; } static struct msm_usb_host_platform_data msm_usb_host_pdata = { .phy_info = (USB_PHY_INTEGRATED | USB_PHY_MODEL_45NM), .power_budget = 390, }; #endif #if defined(CONFIG_USB_EHCI_MSM_72K) static struct msm_otg_platform_data msm_otg_pdata = { /* if usb link is in sps there is no need for * usb pclk as dayatona fabric clock will be * used instead */ .pemp_level = PRE_EMPHASIS_WITH_20_PERCENT, .cdr_autoreset = CDR_AUTO_RESET_DISABLE, .se1_gating = SE1_GATING_DISABLE, .bam_disable = 1, #ifdef CONFIG_USB_EHCI_MSM_72K .pmic_id_notif_init = msm_hsusb_pmic_id_notif_init, .phy_id_setup_init = msm_hsusb_phy_id_setup_init, #endif #ifdef CONFIG_USB_EHCI_MSM_72K .vbus_power = msm_hsusb_vbus_power, #endif .ldo_init = msm_hsusb_ldo_init, .ldo_enable = msm_hsusb_ldo_enable, .config_vddcx = msm_hsusb_config_vddcx, .init_vddcx = msm_hsusb_init_vddcx, }; #endif #ifdef CONFIG_USB_G_ANDROID #define PID_MAGIC_ID 0x71432909 #define SERIAL_NUM_MAGIC_ID 0x61945374 #define SERIAL_NUMBER_LENGTH 127 #define DLOAD_USB_BASE_ADD 0x2A05F0C8 struct magic_num_struct { uint32_t pid; uint32_t serial_num; }; struct dload_struct { uint32_t reserved1; uint32_t reserved2; uint32_t reserved3; uint16_t reserved4; uint16_t pid; char serial_number[SERIAL_NUMBER_LENGTH]; uint16_t reserved5; struct magic_num_struct magic_struct; }; static int usb_diag_update_pid_and_serial_num(uint32_t pid, const char *snum) { struct dload_struct __iomem *dload = 0; dload = ioremap(DLOAD_USB_BASE_ADD, sizeof(*dload)); if (!dload) { pr_err("%s: cannot remap I/O memory region: %08x\n", __func__, DLOAD_USB_BASE_ADD); return -ENXIO; } pr_debug("%s: dload:%p pid:%x serial_num:%s\n", __func__, dload, pid, snum); /* update pid */ dload->magic_struct.pid = PID_MAGIC_ID; dload->pid = pid; /* update serial number */ dload->magic_struct.serial_num = 0; if (!snum) return 0; dload->magic_struct.serial_num = SERIAL_NUM_MAGIC_ID; strncpy(dload->serial_number, snum, SERIAL_NUMBER_LENGTH); dload->serial_number[SERIAL_NUMBER_LENGTH - 1] = '\0'; iounmap(dload); return 0; } static struct android_usb_platform_data android_usb_pdata = { .update_pid_and_serial_num = usb_diag_update_pid_and_serial_num, }; static struct platform_device android_usb_device = { .name = "android_usb", .id = -1, .dev = { .platform_data = &android_usb_pdata, }, }; #endif #ifdef CONFIG_MSM_BUS_SCALING static struct msm_bus_vectors cam_init_vectors[] = { { .src = MSM_BUS_MASTER_VFE, .dst = MSM_BUS_SLAVE_SMI, .ab = 0, .ib = 0, }, { .src = MSM_BUS_MASTER_VFE, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = 0, }, { .src = MSM_BUS_MASTER_VPE, .dst = MSM_BUS_SLAVE_SMI, .ab = 0, .ib = 0, }, { .src = MSM_BUS_MASTER_VPE, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = 0, }, { .src = MSM_BUS_MASTER_JPEG_ENC, .dst = MSM_BUS_SLAVE_SMI, .ab = 0, .ib = 0, }, { .src = MSM_BUS_MASTER_JPEG_ENC, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = 0, }, }; #if defined(CONFIG_SPI_QUP) || defined(CONFIG_SPI_QUP_MODULE) static struct msm_spi_platform_data msm_gsbi1_qup_spi_pdata = { .max_clock_speed = 24000000, }; static struct msm_spi_platform_data msm_gsbi10_qup_spi_pdata = { .max_clock_speed = 24000000, }; #endif #ifdef CONFIG_FB_MSM_LCDC_DSUB /* VGA = 1440 x 900 x 4(bpp) x 2(pages) prim = 1024 x 600 x 4(bpp) x 2(pages) This is the difference. */ #define MSM_FB_DSUB_PMEM_ADDER (0xA32000-0x4B0000) #else #define MSM_FB_DSUB_PMEM_ADDER (0) #endif /* Sensors DSPS platform data */ #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER #define MSM_FB_PRIM_BUF_SIZE \ (roundup((1024 * 600 * 4), 4096) * 3) /* 4 bpp x 3 pages */ #else #define MSM_FB_PRIM_BUF_SIZE \ (roundup((1024 * 600 * 4), 4096) * 2) /* 4 bpp x 2 pages */ #endif #define MSM_FB_EXT_BUF_SIZE 0 /* Note: must be multiple of 4096 */ #define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE + \ MSM_FB_DSUB_PMEM_ADDER, 4096) #define MSM_PMEM_SF_SIZE 0x4000000 /* 64 Mbytes */ #define MSM_HDMI_PRIM_PMEM_SF_SIZE 0x8000000 /* 128 Mbytes */ #ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY unsigned char hdmi_is_primary = 1; #else unsigned char hdmi_is_primary; #endif #ifdef CONFIG_FB_MSM_OVERLAY0_WRITEBACK #define MSM_FB_OVERLAY0_WRITEBACK_SIZE roundup((1376 * 768 * 3 * 2), 4096) #else #define MSM_FB_OVERLAY0_WRITEBACK_SIZE (0) #endif /* CONFIG_FB_MSM_OVERLAY0_WRITEBACK */ #ifdef CONFIG_FB_MSM_OVERLAY1_WRITEBACK #define MSM_FB_OVERLAY1_WRITEBACK_SIZE roundup((1920 * 1088 * 3 * 2), 4096) #else #define MSM_FB_OVERLAY1_WRITEBACK_SIZE (0) #endif /* CONFIG_FB_MSM_OVERLAY1_WRITEBACK */ #define MSM_PMEM_KERNEL_EBI1_SIZE 0x3BC000 #define MSM_PMEM_ADSP_SIZE 0x4200000 #define MSM_PMEM_AUDIO_SIZE 0x4CF000 #define MSM_SMI_BASE 0x38000000 #define MSM_SMI_SIZE 0x4000000 #define KERNEL_SMI_BASE (MSM_SMI_BASE) #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION) #define KERNEL_SMI_SIZE 0x000000 #else #define KERNEL_SMI_SIZE 0x600000 #endif #define USER_SMI_BASE (KERNEL_SMI_BASE + KERNEL_SMI_SIZE) #define USER_SMI_SIZE (MSM_SMI_SIZE - KERNEL_SMI_SIZE) #define MSM_PMEM_SMIPOOL_SIZE USER_SMI_SIZE #ifdef CONFIG_MSM_CP #define MSM_ION_HOLE_SIZE SZ_128K /* (128KB) */ #else #define MSM_ION_HOLE_SIZE 0 #endif #define MSM_MM_FW_SIZE (0x200000 - MSM_ION_HOLE_SIZE) /*(2MB-128KB)*/ #define MSM_ION_MM_SIZE 0x3800000 /* (56MB) */ #define MSM_ION_MFC_SIZE SZ_8K #define MSM_MM_FW_BASE MSM_SMI_BASE #define MSM_ION_HOLE_BASE (MSM_MM_FW_BASE + MSM_MM_FW_SIZE) #define MSM_ION_MM_BASE (MSM_ION_HOLE_BASE + MSM_ION_HOLE_SIZE) #define MSM_ION_MFC_BASE (MSM_ION_MM_BASE + MSM_ION_MM_SIZE) #ifdef CONFIG_MSM_CP #define SECURE_BASE (MSM_ION_HOLE_BASE) #define SECURE_SIZE (MSM_ION_MM_SIZE + MSM_ION_HOLE_SIZE) #else #define SECURE_BASE (MSM_MM_FW_BASE) #define SECURE_SIZE (MSM_ION_MM_SIZE + MSM_MM_FW_SIZE) #endif #define MSM_ION_SF_SIZE 0x4000000 /* 64MB */ #define MSM_ION_CAMERA_SIZE MSM_PMEM_ADSP_SIZE #ifdef CONFIG_FB_MSM_OVERLAY1_WRITEBACK #define MSM_ION_WB_SIZE 0xC00000 /* 12MB */ #else #define MSM_ION_WB_SIZE 0x600000 /* 6MB */ #endif #define MSM_ION_QSECOM_SIZE 0x600000 /* (6MB) */ #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION #define MSM_ION_AUDIO_SIZE MSM_PMEM_AUDIO_SIZE #define MSM_ION_HEAP_NUM 9 #define MSM_HDMI_PRIM_ION_SF_SIZE MSM_HDMI_PRIM_PMEM_SF_SIZE static unsigned msm_ion_sf_size = MSM_ION_SF_SIZE; #else #define MSM_ION_HEAP_NUM 1 #endif static unsigned fb_size; static int __init fb_size_setup(char *p) { fb_size = memparse(p, NULL); return 0; } early_param("fb_size", fb_size_setup); static unsigned pmem_kernel_ebi1_size = MSM_PMEM_KERNEL_EBI1_SIZE; static int __init pmem_kernel_ebi1_size_setup(char *p) { pmem_kernel_ebi1_size = memparse(p, NULL); return 0; } early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup); static struct resource msm_fb_resources[] = { { .flags = IORESOURCE_DMA, } }; static void set_mdp_clocks_for_wuxga(void); static int msm_fb_detect_panel(const char *name) { if (machine_is_msm8x60_fluid()) { uint32_t soc_platform_version = socinfo_get_platform_version(); if (SOCINFO_VERSION_MAJOR(soc_platform_version) < 3) { } else { /*P3 and up use AUO panel */ } } else { if (!strncmp(name, LCDC_SAMSUNG_WSVGA_PANEL_NAME, strnlen(LCDC_SAMSUNG_WSVGA_PANEL_NAME, PANEL_NAME_MAX_LEN))) return 0; #if !defined(CONFIG_FB_MSM_LCDC_AUTO_DETECT) && \ !defined(CONFIG_FB_MSM_MIPI_PANEL_AUTO_DETECT) && \ !defined(CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT) if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WVGA_PANEL_NAME, strnlen(MIPI_VIDEO_TOSHIBA_WVGA_PANEL_NAME, PANEL_NAME_MAX_LEN))) return 0; if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME, strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME, PANEL_NAME_MAX_LEN))) return 0; if (!strncmp(name, MIPI_CMD_NOVATEK_QHD_PANEL_NAME, strnlen(MIPI_CMD_NOVATEK_QHD_PANEL_NAME, PANEL_NAME_MAX_LEN))) return 0; #endif } if (!strncmp(name, HDMI_PANEL_NAME, strnlen(HDMI_PANEL_NAME, PANEL_NAME_MAX_LEN))) { if (hdmi_is_primary) set_mdp_clocks_for_wuxga(); return 0; } if (!strncmp(name, TVOUT_PANEL_NAME, strnlen(TVOUT_PANEL_NAME, PANEL_NAME_MAX_LEN))) return 0; pr_warning("%s: not supported '%s'", __func__, name); return -ENODEV; } static struct msm_fb_platform_data msm_fb_pdata = { .detect_client = msm_fb_detect_panel, }; static struct platform_device msm_fb_device = { .name = "msm_fb", .id = 0, .num_resources = ARRAY_SIZE(msm_fb_resources), .resource = msm_fb_resources, .dev.platform_data = &msm_fb_pdata, }; #define GPIO_DONGLE_PWR_EN 258 static void setup_display_power(void); static int lcdc_vga_enabled; static int vga_enable_request(int enable) { if (enable) lcdc_vga_enabled = 1; else lcdc_vga_enabled = 0; setup_display_power(); return 0; } #define GPIO_BACKLIGHT_PWM0 0 #define GPIO_BACKLIGHT_PWM1 1 static int pmic_backlight_gpio[2] = { GPIO_BACKLIGHT_PWM0, GPIO_BACKLIGHT_PWM1 }; static struct msm_panel_common_pdata lcdc_samsung_panel_data = { .gpio_num = pmic_backlight_gpio, /* two LPG CHANNELS for backlight */ .vga_switch = vga_enable_request, }; static struct platform_device lcdc_samsung_panel_device = { .name = LCDC_SAMSUNG_WSVGA_PANEL_NAME, .id = 0, .dev = { .platform_data = &lcdc_samsung_panel_data, } }; #if (!defined(CONFIG_SPI_QUP)) && \ (\ defined(CONFIG_FB_MSM_LCDC_AUO_WVGA)) static int lcdc_spi_gpio_array_num[] = { LCDC_SPI_GPIO_CLK, LCDC_SPI_GPIO_CS, LCDC_SPI_GPIO_MOSI, }; static uint32_t lcdc_spi_gpio_config_data[] = { GPIO_CFG(LCDC_SPI_GPIO_CLK, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG(LCDC_SPI_GPIO_CS, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG(LCDC_SPI_GPIO_MOSI, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), }; static void lcdc_config_spi_gpios(int enable) { int n; for (n = 0; n < ARRAY_SIZE(lcdc_spi_gpio_config_data); ++n) gpio_tlmm_config(lcdc_spi_gpio_config_data[n], 0); } #endif #ifdef CONFIG_FB_MSM_MIPI_DSI static struct platform_device mipi_dsi_toshiba_panel_device = { .name = "mipi_toshiba", .id = 0, }; #define FPGA_3D_GPIO_CONFIG_ADDR 0x1D00017A static struct mipi_dsi_panel_platform_data novatek_pdata = { .fpga_3d_config_addr = FPGA_3D_GPIO_CONFIG_ADDR, .fpga_ctrl_mode = FPGA_EBI2_INTF, }; static struct platform_device mipi_dsi_novatek_panel_device = { .name = "mipi_novatek", .id = 0, .dev = { .platform_data = &novatek_pdata, } }; #endif static void __init msm8x60_allocate_memory_regions(void) { void *addr; unsigned long size; if (hdmi_is_primary) size = roundup((1920 * 1088 * 4 * 2), 4096); else size = MSM_FB_SIZE; addr = alloc_bootmem_align(size, 0x1000); msm_fb_resources[0].start = __pa(addr); msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1; pr_info("allocating %lu bytes at %p (%lx physical) for fb\n", size, addr, __pa(addr)); } void __init msm8x60_set_display_params(char *prim_panel, char *ext_panel) { if (strnlen(prim_panel, PANEL_NAME_MAX_LEN)) { strlcpy(msm_fb_pdata.prim_panel_name, prim_panel, PANEL_NAME_MAX_LEN); pr_debug("msm_fb_pdata.prim_panel_name %s\n", msm_fb_pdata.prim_panel_name); if (!strncmp((char *)msm_fb_pdata.prim_panel_name, HDMI_PANEL_NAME, strnlen(HDMI_PANEL_NAME, PANEL_NAME_MAX_LEN))) { pr_debug("HDMI is the primary display by" " boot parameter\n"); hdmi_is_primary = 1; set_mdp_clocks_for_wuxga(); } } if (strnlen(ext_panel, PANEL_NAME_MAX_LEN)) { strlcpy(msm_fb_pdata.ext_panel_name, ext_panel, PANEL_NAME_MAX_LEN); pr_debug("msm_fb_pdata.ext_panel_name %s\n", msm_fb_pdata.ext_panel_name); } } #if \ defined(CONFIG_TOUCHSCREEN_CYTTSP_I2C_QC_MODULE) /*virtual key support */ static ssize_t tma300_vkeys_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":60:900:90:120" ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":180:900:90:120" ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":300:900:90:120" ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":420:900:90:120" "\n"); } static struct kobj_attribute tma300_vkeys_attr = { .attr = { .mode = S_IRUGO, }, .show = &tma300_vkeys_show, }; static struct attribute *tma300_properties_attrs[] = { &tma300_vkeys_attr.attr, NULL }; static struct attribute_group tma300_properties_attr_group = { .attrs = tma300_properties_attrs, }; static struct kobject *properties_kobj; #define CYTTSP_TS_GPIO_IRQ 61 static int cyttsp_platform_init(struct i2c_client *client) { int rc = -EINVAL; struct regulator *pm8058_l5 = NULL, *pm8058_s3; if (machine_is_msm8x60_fluid()) { pm8058_l5 = regulator_get(NULL, "8058_l5"); if (IS_ERR(pm8058_l5)) { pr_err("%s: regulator get of 8058_l5 failed (%ld)\n", __func__, PTR_ERR(pm8058_l5)); rc = PTR_ERR(pm8058_l5); return rc; } rc = regulator_set_voltage(pm8058_l5, 2850000, 2850000); if (rc) { pr_err("%s: regulator_set_voltage of 8058_l5 failed(%d)\n", __func__, rc); goto reg_l5_put; } rc = regulator_enable(pm8058_l5); if (rc) { pr_err("%s: regulator_enable of 8058_l5 failed(%d)\n", __func__, rc); goto reg_l5_put; } } /* vote for s3 to enable i2c communication lines */ pm8058_s3 = regulator_get(NULL, "8058_s3"); if (IS_ERR(pm8058_s3)) { pr_err("%s: regulator get of 8058_s3 failed (%ld)\n", __func__, PTR_ERR(pm8058_s3)); rc = PTR_ERR(pm8058_s3); goto reg_l5_disable; } rc = regulator_set_voltage(pm8058_s3, 1800000, 1800000); if (rc) { pr_err("%s: regulator_set_voltage() = %d\n", __func__, rc); goto reg_s3_put; } rc = regulator_enable(pm8058_s3); if (rc) { pr_err("%s: regulator_enable of 8058_l5 failed(%d)\n", __func__, rc); goto reg_s3_put; } /* wait for vregs to stabilize */ usleep_range(10000, 10000); /* check this device active by reading first byte/register */ rc = i2c_smbus_read_byte_data(client, 0x01); if (rc < 0) { pr_err("%s: i2c sanity check failed\n", __func__); goto reg_s3_disable; } /* virtual keys */ if (machine_is_msm8x60_fluid()) { properties_kobj = kobject_create_and_add("board_properties", NULL); if (properties_kobj); if (!properties_kobj || rc) pr_err("%s: failed to create board_properties\n", __func__); } return CY_OK; reg_s3_disable: regulator_disable(pm8058_s3); reg_s3_put: regulator_put(pm8058_s3); reg_l5_disable: if (machine_is_msm8x60_fluid()) regulator_disable(pm8058_l5); reg_l5_put: if (machine_is_msm8x60_fluid()) regulator_put(pm8058_l5); return rc; } /* TODO: Put the regulator to LPM / HPM in suspend/resume*/ static int cyttsp_platform_suspend(struct i2c_client *client) { msleep(20); return CY_OK; } static int cyttsp_platform_resume(struct i2c_client *client) { /* add any special code to strobe a wakeup pin or chip reset */ msleep(10); return CY_OK; } static struct cyttsp_platform_data cyttsp_fluid_pdata = { .flags = 0x04, .gen = CY_GEN3, /* or */ .use_st = CY_USE_ST, .use_mt = CY_USE_MT, .use_hndshk = CY_SEND_HNDSHK, .use_trk_id = CY_USE_TRACKING_ID, .use_sleep = CY_USE_DEEP_SLEEP_SEL | CY_USE_LOW_POWER_SEL, .use_gestures = CY_USE_GESTURES, /* activate up to 4 groups * and set active distance */ .gest_set = CY_GEST_GRP1 | CY_GEST_GRP2 | CY_GEST_GRP3 | CY_GEST_GRP4 | CY_ACT_DIST, /* change act_intrvl to customize the Active power state * scanning/processing refresh interval for Operating mode */ .act_intrvl = CY_ACT_INTRVL_DFLT, /* change tch_tmout to customize the touch timeout for the * Active power state for Operating mode */ .tch_tmout = CY_TCH_TMOUT_DFLT, /* change lp_intrvl to customize the Low Power power state * scanning/processing refresh interval for Operating mode */ .lp_intrvl = CY_LP_INTRVL_DFLT, .sleep_gpio = -1, .resout_gpio = -1, .irq_gpio = CYTTSP_TS_GPIO_IRQ, .resume = cyttsp_platform_resume, .suspend = cyttsp_platform_suspend, .init = cyttsp_platform_init, }; static struct cyttsp_platform_data cyttsp_tmg240_pdata = { .panel_maxx = 1083, .panel_maxy = 659, .disp_minx = 30, .disp_maxx = 1053, .disp_miny = 30, .disp_maxy = 629, .correct_fw_ver = 8, .fw_fname = "cyttsp_8660_ffa.hex", .flags = 0x00, .gen = CY_GEN2, /* or */ .use_st = CY_USE_ST, .use_mt = CY_USE_MT, .use_hndshk = CY_SEND_HNDSHK, .use_trk_id = CY_USE_TRACKING_ID, .use_sleep = CY_USE_DEEP_SLEEP_SEL | CY_USE_LOW_POWER_SEL, .use_gestures = CY_USE_GESTURES, /* activate up to 4 groups * and set active distance */ .gest_set = CY_GEST_GRP1 | CY_GEST_GRP2 | CY_GEST_GRP3 | CY_GEST_GRP4 | CY_ACT_DIST, /* change act_intrvl to customize the Active power state * scanning/processing refresh interval for Operating mode */ .act_intrvl = CY_ACT_INTRVL_DFLT, /* change tch_tmout to customize the touch timeout for the * Active power state for Operating mode */ .tch_tmout = CY_TCH_TMOUT_DFLT, /* change lp_intrvl to customize the Low Power power state * scanning/processing refresh interval for Operating mode */ .lp_intrvl = CY_LP_INTRVL_DFLT, .sleep_gpio = -1, .resout_gpio = -1, .irq_gpio = CYTTSP_TS_GPIO_IRQ, .resume = cyttsp_platform_resume, .suspend = cyttsp_platform_suspend, .init = cyttsp_platform_init, .disable_ghost_det = true, }; static void cyttsp_set_params(void) { if (SOCINFO_VERSION_MAJOR(socinfo_get_platform_version()) < 3) { cyttsp_fluid_pdata.fw_fname = "cyttsp_8660_fluid_p2.hex"; cyttsp_fluid_pdata.panel_maxx = 539; cyttsp_fluid_pdata.panel_maxy = 994; cyttsp_fluid_pdata.disp_minx = 30; cyttsp_fluid_pdata.disp_maxx = 509; cyttsp_fluid_pdata.disp_miny = 60; cyttsp_fluid_pdata.disp_maxy = 859; cyttsp_fluid_pdata.correct_fw_ver = 4; } else { cyttsp_fluid_pdata.fw_fname = "cyttsp_8660_fluid_p3.hex"; cyttsp_fluid_pdata.panel_maxx = 550; cyttsp_fluid_pdata.panel_maxy = 1013; cyttsp_fluid_pdata.disp_minx = 35; cyttsp_fluid_pdata.disp_maxx = 515; cyttsp_fluid_pdata.disp_miny = 69; cyttsp_fluid_pdata.disp_maxy = 869; cyttsp_fluid_pdata.correct_fw_ver = 5; } } static struct i2c_board_info cyttsp_fluid_info[] __initdata = { { I2C_BOARD_INFO(CY_I2C_NAME, 0x24), .platform_data = &cyttsp_fluid_pdata, #ifndef CY_USE_TIMER .irq = MSM_GPIO_TO_INT(CYTTSP_TS_GPIO_IRQ), #endif /* CY_USE_TIMER */ }, }; static struct i2c_board_info cyttsp_ffa_info[] __initdata = { { I2C_BOARD_INFO(CY_I2C_NAME, 0x3b), .platform_data = &cyttsp_tmg240_pdata, #ifndef CY_USE_TIMER .irq = MSM_GPIO_TO_INT(CYTTSP_TS_GPIO_IRQ), #endif /* CY_USE_TIMER */ }, }; #endif static struct regulator *vreg_tmg200; #define TS_PEN_IRQ_GPIO 61 static int tmg200_power(int vreg_on) { int rc = -EINVAL; if (!vreg_tmg200) { printk(KERN_ERR "%s: regulator 8058_s3 not found (%d)\n", __func__, rc); return rc; } rc = vreg_on ? regulator_enable(vreg_tmg200) : regulator_disable(vreg_tmg200); if (rc < 0) printk(KERN_ERR "%s: vreg 8058_s3 %s failed (%d)\n", __func__, vreg_on ? "enable" : "disable", rc); /* wait for vregs to stabilize */ msleep(20); return rc; } static int tmg200_dev_setup(bool enable) { int rc; if (enable) { vreg_tmg200 = regulator_get(NULL, "8058_s3"); if (IS_ERR(vreg_tmg200)) { pr_err("%s: regulator get of 8058_s3 failed (%ld)\n", __func__, PTR_ERR(vreg_tmg200)); rc = PTR_ERR(vreg_tmg200); return rc; } rc = regulator_set_voltage(vreg_tmg200, 1800000, 1800000); if (rc) { pr_err("%s: regulator_set_voltage() = %d\n", __func__, rc); goto reg_put; } } else { /* put voltage sources */ regulator_put(vreg_tmg200); } return 0; reg_put: regulator_put(vreg_tmg200); return rc; } static struct cy8c_ts_platform_data cy8ctmg200_pdata = { .ts_name = "msm_tmg200_ts", .dis_min_x = 0, .dis_max_x = 1023, .dis_min_y = 0, .dis_max_y = 599, .min_tid = 0, .max_tid = 255, .min_touch = 0, .max_touch = 255, .min_width = 0, .max_width = 255, .power_on = tmg200_power, .dev_setup = tmg200_dev_setup, .nfingers = 2, .irq_gpio = TS_PEN_IRQ_GPIO, .resout_gpio = GPIO_CAP_TS_RESOUT_N, }; static struct i2c_board_info cy8ctmg200_board_info[] = { { I2C_BOARD_INFO("cy8ctmg200", 0x2), .platform_data = &cy8ctmg200_pdata, } }; static struct regulator *vreg_tma340; static int tma340_power(int vreg_on) { int rc = -EINVAL; if (!vreg_tma340) { pr_err("%s: regulator 8901_l2 not found (%d)\n", __func__, rc); return rc; } rc = vreg_on ? regulator_enable(vreg_tma340) : regulator_disable(vreg_tma340); if (rc < 0) pr_err("%s: vreg 8901_l2 %s failed (%d)\n", __func__, vreg_on ? "enable" : "disable", rc); /* wait for vregs to stabilize */ msleep(100); return rc; } static struct kobject *tma340_prop_kobj; static int tma340_dragon_dev_setup(bool enable) { int rc; if (enable) { vreg_tma340 = regulator_get(NULL, "8901_l2"); if (IS_ERR(vreg_tma340)) { pr_err("%s: regulator get of 8901_l2 failed (%ld)\n", __func__, PTR_ERR(vreg_tma340)); rc = PTR_ERR(vreg_tma340); return rc; } rc = regulator_set_voltage(vreg_tma340, 3300000, 3300000); if (rc) { pr_err("%s: regulator_set_voltage() = %d\n", __func__, rc); goto reg_put; } tma340_prop_kobj = kobject_create_and_add("board_properties", NULL); if (tma340_prop_kobj) { ; if (rc) { kobject_put(tma340_prop_kobj); pr_err("%s: failed to create board_properties\n", __func__); goto reg_put; } } } else { /* put voltage sources */ regulator_put(vreg_tma340); /* destroy virtual keys */ if (tma340_prop_kobj) { kobject_put(tma340_prop_kobj); } } return 0; reg_put: regulator_put(vreg_tma340); return rc; } static struct cy8c_ts_platform_data cy8ctma340_dragon_pdata = { .ts_name = "cy8ctma340", .dis_min_x = 0, .dis_max_x = 479, .dis_min_y = 0, .dis_max_y = 799, .min_tid = 0, .max_tid = 255, .min_touch = 0, .max_touch = 255, .min_width = 0, .max_width = 255, .power_on = tma340_power, .dev_setup = tma340_dragon_dev_setup, .nfingers = 2, .irq_gpio = TS_PEN_IRQ_GPIO, .resout_gpio = -1, }; static struct i2c_board_info cy8ctma340_dragon_board_info[] = { { I2C_BOARD_INFO("cy8ctma340", 0x24), .platform_data = &cy8ctma340_dragon_pdata, } }; #ifdef CONFIG_SERIAL_MSM_HS static struct msm_serial_hs_platform_data msm_uart_dm1_pdata = { .inject_rx_on_wakeup = 1, .rx_to_inject = 0xFD, .config_gpio = 4, .uart_tx_gpio = 53, .uart_rx_gpio = 54, .uart_cts_gpio = 55, .uart_rfr_gpio = 56, }; #endif #if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE) static struct gpio_led gpio_exp_leds_config[] = { { .name = "left_led1:green", .gpio = GPIO_LEFT_LED_1, .active_low = 1, .retain_state_suspended = 0, .default_state = LEDS_GPIO_DEFSTATE_OFF, }, { .name = "left_led2:red", .gpio = GPIO_LEFT_LED_2, .active_low = 1, .retain_state_suspended = 0, .default_state = LEDS_GPIO_DEFSTATE_OFF, }, { .name = "left_led3:green", .gpio = GPIO_LEFT_LED_3, .active_low = 1, .retain_state_suspended = 0, .default_state = LEDS_GPIO_DEFSTATE_OFF, }, { .name = "wlan_led:orange", .gpio = GPIO_LEFT_LED_WLAN, .active_low = 1, .retain_state_suspended = 0, .default_state = LEDS_GPIO_DEFSTATE_OFF, }, { .name = "left_led5:green", .gpio = GPIO_LEFT_LED_5, .active_low = 1, .retain_state_suspended = 0, .default_state = LEDS_GPIO_DEFSTATE_OFF, }, { .name = "right_led1:green", .gpio = GPIO_RIGHT_LED_1, .active_low = 1, .retain_state_suspended = 0, .default_state = LEDS_GPIO_DEFSTATE_OFF, }, { .name = "right_led2:red", .gpio = GPIO_RIGHT_LED_2, .active_low = 1, .retain_state_suspended = 0, .default_state = LEDS_GPIO_DEFSTATE_OFF, }, { .name = "right_led3:green", .gpio = GPIO_RIGHT_LED_3, .active_low = 1, .retain_state_suspended = 0, .default_state = LEDS_GPIO_DEFSTATE_OFF, }, { .name = "bt_led:blue", .gpio = GPIO_RIGHT_LED_BT, .active_low = 1, .retain_state_suspended = 0, .default_state = LEDS_GPIO_DEFSTATE_OFF, }, { .name = "right_led5:green", .gpio = GPIO_RIGHT_LED_5, .active_low = 1, .retain_state_suspended = 0, .default_state = LEDS_GPIO_DEFSTATE_OFF, }, }; static struct gpio_led_platform_data gpio_leds_pdata = { .num_leds = ARRAY_SIZE(gpio_exp_leds_config), .leds = gpio_exp_leds_config, }; static struct platform_device gpio_leds = { .name = "leds-gpio", .id = -1, .dev = { .platform_data = &gpio_leds_pdata, }, }; static struct gpio_led fluid_gpio_leds[] = { { .name = "dual_led:green", .gpio = GPIO_LED1_GREEN_N, .default_state = LEDS_GPIO_DEFSTATE_OFF, .active_low = 1, .retain_state_suspended = 0, }, { .name = "dual_led:red", .gpio = GPIO_LED2_RED_N, .default_state = LEDS_GPIO_DEFSTATE_OFF, .active_low = 1, .retain_state_suspended = 0, }, }; static struct gpio_led_platform_data gpio_led_pdata = { .leds = fluid_gpio_leds, .num_leds = ARRAY_SIZE(fluid_gpio_leds), }; static struct platform_device fluid_leds_gpio = { .name = "leds-gpio", .id = -1, .dev = { .platform_data = &gpio_led_pdata, }, }; #endif /* * Consumer specific regulator names: * regulator name consumer dev_name */ static struct regulator_consumer_supply vreg_consumers_PM8058_L0[] = { REGULATOR_SUPPLY("8058_l0", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L1[] = { REGULATOR_SUPPLY("8058_l1", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L2[] = { REGULATOR_SUPPLY("8058_l2", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L3[] = { REGULATOR_SUPPLY("8058_l3", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L4[] = { REGULATOR_SUPPLY("8058_l4", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L5[] = { REGULATOR_SUPPLY("8058_l5", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L6[] = { REGULATOR_SUPPLY("8058_l6", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L7[] = { REGULATOR_SUPPLY("8058_l7", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L8[] = { REGULATOR_SUPPLY("8058_l8", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L9[] = { REGULATOR_SUPPLY("8058_l9", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L10[] = { REGULATOR_SUPPLY("8058_l10", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L11[] = { REGULATOR_SUPPLY("8058_l11", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L12[] = { REGULATOR_SUPPLY("8058_l12", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L13[] = { REGULATOR_SUPPLY("8058_l13", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L14[] = { REGULATOR_SUPPLY("8058_l14", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L15[] = { REGULATOR_SUPPLY("8058_l15", NULL), REGULATOR_SUPPLY("cam_vana", "1-001a"), REGULATOR_SUPPLY("cam_vana", "1-006c"), REGULATOR_SUPPLY("cam_vana", "1-0078"), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L16[] = { REGULATOR_SUPPLY("8058_l16", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L17[] = { REGULATOR_SUPPLY("8058_l17", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L18[] = { REGULATOR_SUPPLY("8058_l18", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L19[] = { REGULATOR_SUPPLY("8058_l19", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L20[] = { REGULATOR_SUPPLY("8058_l20", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L21[] = { REGULATOR_SUPPLY("8058_l21", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L22[] = { REGULATOR_SUPPLY("8058_l22", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L23[] = { REGULATOR_SUPPLY("8058_l23", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L24[] = { REGULATOR_SUPPLY("8058_l24", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L25[] = { REGULATOR_SUPPLY("8058_l25", NULL), REGULATOR_SUPPLY("cam_vdig", "1-001a"), REGULATOR_SUPPLY("cam_vdig", "1-006c"), REGULATOR_SUPPLY("cam_vdig", "1-0078"), }; static struct regulator_consumer_supply vreg_consumers_PM8058_S0[] = { REGULATOR_SUPPLY("8058_s0", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_S1[] = { REGULATOR_SUPPLY("8058_s1", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_S2[] = { REGULATOR_SUPPLY("8058_s2", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_S3[] = { REGULATOR_SUPPLY("8058_s3", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_S4[] = { REGULATOR_SUPPLY("8058_s4", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_LVS0[] = { REGULATOR_SUPPLY("8058_lvs0", NULL), REGULATOR_SUPPLY("cam_vio", "1-001a"), REGULATOR_SUPPLY("cam_vio", "1-006c"), REGULATOR_SUPPLY("cam_vio", "1-0078"), }; static struct regulator_consumer_supply vreg_consumers_PM8058_LVS1[] = { REGULATOR_SUPPLY("8058_lvs1", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_NCP[] = { REGULATOR_SUPPLY("8058_ncp", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_L0[] = { REGULATOR_SUPPLY("8901_l0", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_L1[] = { REGULATOR_SUPPLY("8901_l1", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_L2[] = { REGULATOR_SUPPLY("8901_l2", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_L3[] = { REGULATOR_SUPPLY("8901_l3", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_L4[] = { REGULATOR_SUPPLY("8901_l4", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_L5[] = { REGULATOR_SUPPLY("8901_l5", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_L6[] = { REGULATOR_SUPPLY("8901_l6", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_S2[] = { REGULATOR_SUPPLY("8901_s2", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_S3[] = { REGULATOR_SUPPLY("8901_s3", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_S4[] = { REGULATOR_SUPPLY("8901_s4", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_LVS0[] = { REGULATOR_SUPPLY("8901_lvs0", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_LVS1[] = { REGULATOR_SUPPLY("8901_lvs1", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_LVS2[] = { REGULATOR_SUPPLY("8901_lvs2", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_LVS3[] = { REGULATOR_SUPPLY("8901_lvs3", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_MVS0[] = { REGULATOR_SUPPLY("8901_mvs0", NULL), }; /* Pin control regulators */ static struct regulator_consumer_supply vreg_consumers_PM8058_L8_PC[] = { REGULATOR_SUPPLY("8058_l8_pc", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L20_PC[] = { REGULATOR_SUPPLY("8058_l20_pc", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_L21_PC[] = { REGULATOR_SUPPLY("8058_l21_pc", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8058_S2_PC[] = { REGULATOR_SUPPLY("8058_s2_pc", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_L0_PC[] = { REGULATOR_SUPPLY("8901_l0_pc", NULL), }; static struct regulator_consumer_supply vreg_consumers_PM8901_S4_PC[] = { REGULATOR_SUPPLY("8901_s4_pc", NULL), }; #define RPM_VREG_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, \ _default_uV, _peak_uA, _avg_uA, _pull_down, _pin_ctrl, \ _freq, _pin_fn, _force_mode, _sleep_set_force_mode, \ _state, _sleep_selectable, _always_on) \ { \ .init_data = { \ .constraints = { \ .valid_modes_mask = _modes, \ .valid_ops_mask = _ops, \ .min_uV = _min_uV, \ .max_uV = _max_uV, \ .input_uV = _min_uV, \ .apply_uV = _apply_uV, \ .always_on = _always_on, \ }, \ .consumer_supplies = vreg_consumers_##_id, \ .num_consumer_supplies = \ ARRAY_SIZE(vreg_consumers_##_id), \ }, \ .id = RPM_VREG_ID_##_id, \ .default_uV = _default_uV, \ .peak_uA = _peak_uA, \ .avg_uA = _avg_uA, \ .pull_down_enable = _pull_down, \ .pin_ctrl = _pin_ctrl, \ .freq = RPM_VREG_FREQ_##_freq, \ .pin_fn = _pin_fn, \ .force_mode = _force_mode, \ .sleep_set_force_mode = _sleep_set_force_mode, \ .state = _state, \ .sleep_selectable = _sleep_selectable, \ } /* Pin control initialization */ #define RPM_PC(_id, _always_on, _pin_fn, _pin_ctrl) \ { \ .init_data = { \ .constraints = { \ .valid_ops_mask = REGULATOR_CHANGE_STATUS, \ .always_on = _always_on, \ }, \ .num_consumer_supplies = \ ARRAY_SIZE(vreg_consumers_##_id##_PC), \ .consumer_supplies = vreg_consumers_##_id##_PC, \ }, \ .id = RPM_VREG_ID_##_id##_PC, \ .pin_fn = RPM_VREG_PIN_FN_8660_##_pin_fn, \ .pin_ctrl = _pin_ctrl, \ } /* * The default LPM/HPM state of an RPM controlled regulator can be controlled * via the peak_uA value specified in the table below. If the value is less * than the high power min threshold for the regulator, then the regulator will * be set to LPM. Otherwise, it will be set to HPM. * * This value can be further overridden by specifying an initial mode via * .init_data.constraints.initial_mode. */ #define RPM_LDO(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \ _init_peak_uA) \ RPM_VREG_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_FAST | \ REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE | \ REGULATOR_MODE_STANDBY, REGULATOR_CHANGE_VOLTAGE | \ REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \ REGULATOR_CHANGE_DRMS, 0, _min_uV, _init_peak_uA, \ _init_peak_uA, _pd, RPM_VREG_PIN_CTRL_NONE, NONE, \ RPM_VREG_PIN_FN_8660_ENABLE, \ RPM_VREG_FORCE_MODE_8660_NONE, \ RPM_VREG_FORCE_MODE_8660_NONE, RPM_VREG_STATE_OFF, \ _sleep_selectable, _always_on) #define RPM_SMPS(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \ _init_peak_uA, _freq) \ RPM_VREG_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_FAST | \ REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE | \ REGULATOR_MODE_STANDBY, REGULATOR_CHANGE_VOLTAGE | \ REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \ REGULATOR_CHANGE_DRMS, 0, _min_uV, _init_peak_uA, \ _init_peak_uA, _pd, RPM_VREG_PIN_CTRL_NONE, _freq, \ RPM_VREG_PIN_FN_8660_ENABLE, \ RPM_VREG_FORCE_MODE_8660_NONE, \ RPM_VREG_FORCE_MODE_8660_NONE, RPM_VREG_STATE_OFF, \ _sleep_selectable, _always_on) #define RPM_VS(_id, _always_on, _pd, _sleep_selectable) \ RPM_VREG_INIT(_id, 0, 0, REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE, \ REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE, 0, 0, \ 1000, 1000, _pd, RPM_VREG_PIN_CTRL_NONE, NONE, \ RPM_VREG_PIN_FN_8660_ENABLE, \ RPM_VREG_FORCE_MODE_8660_NONE, \ RPM_VREG_FORCE_MODE_8660_NONE, RPM_VREG_STATE_OFF, \ _sleep_selectable, _always_on) #define RPM_NCP(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV) \ RPM_VREG_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL, \ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, 0, \ _min_uV, 1000, 1000, _pd, RPM_VREG_PIN_CTRL_NONE, NONE, \ RPM_VREG_PIN_FN_8660_ENABLE, \ RPM_VREG_FORCE_MODE_8660_NONE, \ RPM_VREG_FORCE_MODE_8660_NONE, RPM_VREG_STATE_OFF, \ _sleep_selectable, _always_on) #define LDO50HMIN RPM_VREG_8660_LDO_50_HPM_MIN_LOAD #define LDO150HMIN RPM_VREG_8660_LDO_150_HPM_MIN_LOAD #define LDO300HMIN RPM_VREG_8660_LDO_300_HPM_MIN_LOAD #define SMPS_HMIN RPM_VREG_8660_SMPS_HPM_MIN_LOAD #define FTS_HMIN RPM_VREG_8660_FTSMPS_HPM_MIN_LOAD /* RPM early regulator constraints */ static struct rpm_regulator_init_data rpm_regulator_early_init_data[] = { /* ID a_on pd ss min_uV max_uV init_ip freq */ RPM_SMPS(PM8058_S0, 0, 1, 1, 500000, 1325000, SMPS_HMIN, 1p60), RPM_SMPS(PM8058_S1, 0, 1, 1, 500000, 1250000, SMPS_HMIN, 1p60), }; /* RPM regulator constraints */ static struct rpm_regulator_init_data rpm_regulator_init_data[] = { /* ID a_on pd ss min_uV max_uV init_ip */ RPM_LDO(PM8058_L0, 0, 1, 0, 1200000, 1200000, LDO150HMIN), RPM_LDO(PM8058_L1, 0, 1, 0, 1200000, 1200000, LDO300HMIN), RPM_LDO(PM8058_L2, 0, 1, 0, 1800000, 2600000, LDO300HMIN), RPM_LDO(PM8058_L3, 0, 1, 0, 1800000, 1800000, LDO150HMIN), RPM_LDO(PM8058_L4, 0, 1, 0, 2850000, 2850000, LDO50HMIN), RPM_LDO(PM8058_L5, 0, 1, 0, 2850000, 2850000, LDO300HMIN), RPM_LDO(PM8058_L6, 0, 1, 0, 3000000, 3600000, LDO50HMIN), RPM_LDO(PM8058_L7, 0, 1, 0, 1800000, 1800000, LDO50HMIN), RPM_LDO(PM8058_L8, 0, 1, 0, 2900000, 3050000, LDO300HMIN), RPM_LDO(PM8058_L9, 0, 1, 0, 1800000, 1800000, LDO300HMIN), RPM_LDO(PM8058_L10, 0, 1, 0, 2600000, 2600000, LDO300HMIN), RPM_LDO(PM8058_L11, 0, 1, 0, 1500000, 1500000, LDO150HMIN), RPM_LDO(PM8058_L12, 0, 1, 0, 2900000, 2900000, LDO150HMIN), RPM_LDO(PM8058_L13, 0, 1, 0, 2050000, 2050000, LDO300HMIN), RPM_LDO(PM8058_L14, 0, 0, 0, 2850000, 2850000, LDO300HMIN), RPM_LDO(PM8058_L15, 0, 1, 0, 2850000, 2850000, LDO300HMIN), RPM_LDO(PM8058_L16, 1, 1, 0, 1800000, 1800000, LDO300HMIN), RPM_LDO(PM8058_L17, 0, 1, 0, 2600000, 2600000, LDO150HMIN), RPM_LDO(PM8058_L18, 0, 1, 0, 2200000, 2200000, LDO150HMIN), RPM_LDO(PM8058_L19, 0, 1, 0, 2500000, 2500000, LDO150HMIN), RPM_LDO(PM8058_L20, 0, 1, 0, 1800000, 1800000, LDO150HMIN), RPM_LDO(PM8058_L21, 1, 1, 0, 1200000, 1200000, LDO150HMIN), RPM_LDO(PM8058_L22, 0, 1, 0, 1150000, 1150000, LDO300HMIN), RPM_LDO(PM8058_L23, 0, 1, 0, 1200000, 1200000, LDO300HMIN), RPM_LDO(PM8058_L24, 0, 1, 0, 1200000, 1200000, LDO150HMIN), RPM_LDO(PM8058_L25, 0, 1, 0, 1200000, 1200000, LDO150HMIN), /* ID a_on pd ss min_uV max_uV init_ip freq */ RPM_SMPS(PM8058_S2, 0, 1, 1, 1200000, 1400000, SMPS_HMIN, 1p60), RPM_SMPS(PM8058_S3, 1, 1, 0, 1800000, 1800000, SMPS_HMIN, 1p60), RPM_SMPS(PM8058_S4, 1, 1, 0, 2200000, 2200000, SMPS_HMIN, 1p60), /* ID a_on pd ss */ RPM_VS(PM8058_LVS0, 0, 1, 0), RPM_VS(PM8058_LVS1, 0, 1, 0), /* ID a_on pd ss min_uV max_uV */ RPM_NCP(PM8058_NCP, 0, 1, 0, 1800000, 1800000), /* ID a_on pd ss min_uV max_uV init_ip */ RPM_LDO(PM8901_L0, 0, 1, 0, 1200000, 1200000, LDO300HMIN), RPM_LDO(PM8901_L1, 0, 1, 0, 3300000, 3300000, LDO300HMIN), RPM_LDO(PM8901_L2, 0, 1, 0, 2850000, 3300000, LDO300HMIN), RPM_LDO(PM8901_L3, 0, 1, 0, 3300000, 3300000, LDO300HMIN), RPM_LDO(PM8901_L4, 0, 1, 0, 2600000, 2600000, LDO300HMIN), RPM_LDO(PM8901_L5, 0, 1, 0, 2850000, 2850000, LDO300HMIN), RPM_LDO(PM8901_L6, 0, 1, 0, 2200000, 2200000, LDO300HMIN), /* ID a_on pd ss min_uV max_uV init_ip freq */ RPM_SMPS(PM8901_S2, 0, 1, 0, 1300000, 1300000, FTS_HMIN, 1p60), RPM_SMPS(PM8901_S3, 0, 1, 0, 1100000, 1100000, FTS_HMIN, 1p60), RPM_SMPS(PM8901_S4, 0, 1, 0, 1225000, 1225000, FTS_HMIN, 1p60), /* ID a_on pd ss */ RPM_VS(PM8901_LVS0, 1, 1, 0), RPM_VS(PM8901_LVS1, 0, 1, 0), RPM_VS(PM8901_LVS2, 0, 1, 0), RPM_VS(PM8901_LVS3, 0, 1, 0), RPM_VS(PM8901_MVS0, 0, 1, 0), /* ID a_on pin_func pin_ctrl */ RPM_PC(PM8058_L8, 0, SLEEP_B, RPM_VREG_PIN_CTRL_NONE), RPM_PC(PM8058_L20, 0, SLEEP_B, RPM_VREG_PIN_CTRL_NONE), RPM_PC(PM8058_L21, 1, SLEEP_B, RPM_VREG_PIN_CTRL_NONE), RPM_PC(PM8058_S2, 0, ENABLE, RPM_VREG_PIN_CTRL_PM8058_A0), RPM_PC(PM8901_L0, 0, ENABLE, RPM_VREG_PIN_CTRL_PM8901_A0), RPM_PC(PM8901_S4, 0, ENABLE, RPM_VREG_PIN_CTRL_PM8901_A0), }; static struct rpm_regulator_platform_data rpm_regulator_early_pdata = { .init_data = rpm_regulator_early_init_data, .num_regulators = ARRAY_SIZE(rpm_regulator_early_init_data), .version = RPM_VREG_VERSION_8660, .vreg_id_vdd_mem = RPM_VREG_ID_PM8058_S0, .vreg_id_vdd_dig = RPM_VREG_ID_PM8058_S1, }; static struct rpm_regulator_platform_data rpm_regulator_pdata = { .init_data = rpm_regulator_init_data, .num_regulators = ARRAY_SIZE(rpm_regulator_init_data), .version = RPM_VREG_VERSION_8660, }; static struct platform_device rpm_regulator_early_device = { .name = "rpm-regulator", .id = 0, .dev = { .platform_data = &rpm_regulator_early_pdata, }, }; static struct platform_device rpm_regulator_device = { .name = "rpm-regulator", .id = 1, .dev = { .platform_data = &rpm_regulator_pdata, }, }; static struct platform_device *early_regulators[] __initdata = { &msm_device_saw_s0, &msm_device_saw_s1, &rpm_regulator_early_device, }; static struct platform_device *early_devices[] __initdata = { #ifdef CONFIG_MSM_BUS_SCALING &msm_bus_apps_fabric, &msm_bus_sys_fabric, &msm_bus_mm_fabric, &msm_bus_sys_fpb, &msm_bus_cpss_fpb, #endif &msm_device_dmov_adm0, &msm_device_dmov_adm1, }; static struct platform_device msm_tsens_device = { .name = "tsens-tm", .id = -1, }; #if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE) enum { SX150X_CORE, SX150X_DOCKING, SX150X_SURF, SX150X_LEFT_FHA, SX150X_RIGHT_FHA, SX150X_SOUTH, SX150X_NORTH, SX150X_CORE_FLUID, }; static struct sx150x_platform_data sx150x_data[] __initdata = { [SX150X_CORE] = { .gpio_base = GPIO_CORE_EXPANDER_BASE, .oscio_is_gpo = false, .io_pullup_ena = 0x0c08, .io_pulldn_ena = 0x4060, .io_open_drain_ena = 0x000c, .io_polarity = 0, .irq_summary = -1, /* see fixup_i2c_configs() */ .irq_base = GPIO_EXPANDER_IRQ_BASE, }, [SX150X_DOCKING] = { .gpio_base = GPIO_DOCKING_EXPANDER_BASE, .oscio_is_gpo = false, .io_pullup_ena = 0x5e06, .io_pulldn_ena = 0x81b8, .io_open_drain_ena = 0, .io_polarity = 0, .irq_summary = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT2_N), .irq_base = GPIO_EXPANDER_IRQ_BASE + GPIO_DOCKING_EXPANDER_BASE - GPIO_EXPANDER_GPIO_BASE, }, [SX150X_SURF] = { .gpio_base = GPIO_SURF_EXPANDER_BASE, .oscio_is_gpo = false, .io_pullup_ena = 0, .io_pulldn_ena = 0, .io_open_drain_ena = 0, .io_polarity = 0, .irq_summary = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT1_N), .irq_base = GPIO_EXPANDER_IRQ_BASE + GPIO_SURF_EXPANDER_BASE - GPIO_EXPANDER_GPIO_BASE, }, [SX150X_LEFT_FHA] = { .gpio_base = GPIO_LEFT_KB_EXPANDER_BASE, .oscio_is_gpo = false, .io_pullup_ena = 0, .io_pulldn_ena = 0x40, .io_open_drain_ena = 0, .io_polarity = 0, .irq_summary = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT3_N), .irq_base = GPIO_EXPANDER_IRQ_BASE + GPIO_LEFT_KB_EXPANDER_BASE - GPIO_EXPANDER_GPIO_BASE, }, [SX150X_RIGHT_FHA] = { .gpio_base = GPIO_RIGHT_KB_EXPANDER_BASE, .oscio_is_gpo = true, .io_pullup_ena = 0, .io_pulldn_ena = 0, .io_open_drain_ena = 0, .io_polarity = 0, .irq_summary = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT3_N), .irq_base = GPIO_EXPANDER_IRQ_BASE + GPIO_RIGHT_KB_EXPANDER_BASE - GPIO_EXPANDER_GPIO_BASE, }, [SX150X_SOUTH] = { .gpio_base = GPIO_SOUTH_EXPANDER_BASE, .irq_base = GPIO_EXPANDER_IRQ_BASE + GPIO_SOUTH_EXPANDER_BASE - GPIO_EXPANDER_GPIO_BASE, .irq_summary = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT3_N), }, [SX150X_NORTH] = { .gpio_base = GPIO_NORTH_EXPANDER_BASE, .irq_base = GPIO_EXPANDER_IRQ_BASE + GPIO_NORTH_EXPANDER_BASE - GPIO_EXPANDER_GPIO_BASE, .irq_summary = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT3_N), .oscio_is_gpo = true, .io_open_drain_ena = 0x30, }, [SX150X_CORE_FLUID] = { .gpio_base = GPIO_CORE_EXPANDER_BASE, .oscio_is_gpo = false, .io_pullup_ena = 0x0408, .io_pulldn_ena = 0x4060, .io_open_drain_ena = 0x0008, .io_polarity = 0, .irq_summary = -1, /* see fixup_i2c_configs() */ .irq_base = GPIO_EXPANDER_IRQ_BASE, }, }; /* sx150x_low_power_cfg * * This data and init function are used to put unused gpio-expander output * lines into their low-power states at boot. The init * function must be deferred until a later init stage because the i2c * gpio expander drivers do not probe until after they are registered * (see register_i2c_devices) and the work-queues for those registrations * are processed. Because these lines are unused, there is no risk of * competing with a device driver for the gpio. * * gpio lines whose low-power states are input are naturally in their low- * power configurations once probed, see the platform data structures above. */ struct sx150x_low_power_cfg { unsigned gpio; unsigned val; }; static struct sx150x_low_power_cfg common_sx150x_lp_cfgs[] __initdata = { {GPIO_WLAN_DEEP_SLEEP_N, 0}, {GPIO_EXT_GPS_LNA_EN, 0}, {GPIO_MSM_WAKES_BT, 0}, {GPIO_USB_UICC_EN, 0}, {GPIO_BATT_GAUGE_EN, 0}, }; static struct sx150x_low_power_cfg surf_ffa_sx150x_lp_cfgs[] __initdata = { {GPIO_MIPI_DSI_RST_N, 0}, {GPIO_DONGLE_PWR_EN, 0}, {GPIO_CAP_TS_SLEEP, 1}, {GPIO_WEB_CAMIF_RESET_N, 0}, }; static void __init cfg_gpio_low_power(struct sx150x_low_power_cfg *cfgs, unsigned nelems) { unsigned n; int rc; for (n = 0; n < nelems; ++n) { rc = gpio_request(cfgs[n].gpio, NULL); if (!rc) { rc = gpio_direction_output(cfgs[n].gpio, cfgs[n].val); gpio_free(cfgs[n].gpio); } if (rc) { printk(KERN_NOTICE "%s: failed to sleep gpio %d: %d\n", __func__, cfgs[n].gpio, rc); } } } static int __init cfg_sx150xs_low_power(void) { cfg_gpio_low_power(common_sx150x_lp_cfgs, ARRAY_SIZE(common_sx150x_lp_cfgs)); if (!machine_is_msm8x60_fluid()) cfg_gpio_low_power(surf_ffa_sx150x_lp_cfgs, ARRAY_SIZE(surf_ffa_sx150x_lp_cfgs)); return 0; } module_init(cfg_sx150xs_low_power); #ifdef CONFIG_I2C static struct i2c_board_info core_expander_i2c_info[] __initdata = { { I2C_BOARD_INFO("sx1509q", 0x3e), .platform_data = &sx150x_data[SX150X_CORE] }, }; static struct i2c_board_info docking_expander_i2c_info[] __initdata = { { I2C_BOARD_INFO("sx1509q", 0x3f), .platform_data = &sx150x_data[SX150X_DOCKING] }, }; static struct i2c_board_info surf_expanders_i2c_info[] __initdata = { { I2C_BOARD_INFO("sx1509q", 0x70), .platform_data = &sx150x_data[SX150X_SURF] } }; static struct i2c_board_info fha_expanders_i2c_info[] __initdata = { { I2C_BOARD_INFO("sx1508q", 0x21), .platform_data = &sx150x_data[SX150X_LEFT_FHA] }, { I2C_BOARD_INFO("sx1508q", 0x22), .platform_data = &sx150x_data[SX150X_RIGHT_FHA] } }; static struct i2c_board_info fluid_expanders_i2c_info[] __initdata = { { I2C_BOARD_INFO("sx1508q", 0x23), .platform_data = &sx150x_data[SX150X_SOUTH] }, { I2C_BOARD_INFO("sx1508q", 0x20), .platform_data = &sx150x_data[SX150X_NORTH] } }; static struct i2c_board_info fluid_core_expander_i2c_info[] __initdata = { { I2C_BOARD_INFO("sx1509q", 0x3e), .platform_data = &sx150x_data[SX150X_CORE_FLUID] }, }; #endif #endif #define GPIO_VREG_ID_EXT_5V 0 static struct regulator_consumer_supply vreg_consumers_EXT_5V[] = { REGULATOR_SUPPLY("ext_5v", NULL), REGULATOR_SUPPLY("8901_mpp0", NULL), }; #define GPIO_VREG_INIT(_id, _reg_name, _gpio_label, _gpio, _active_low) \ [GPIO_VREG_ID_##_id] = { \ .init_data = { \ .constraints = { \ .valid_ops_mask = REGULATOR_CHANGE_STATUS, \ }, \ .num_consumer_supplies = \ ARRAY_SIZE(vreg_consumers_##_id), \ .consumer_supplies = vreg_consumers_##_id, \ }, \ .regulator_name = _reg_name, \ .active_low = _active_low, \ .gpio_label = _gpio_label, \ .gpio = _gpio, \ } /* GPIO regulator constraints */ static struct gpio_regulator_platform_data msm_gpio_regulator_pdata[] = { GPIO_VREG_INIT(EXT_5V, "ext_5v", "ext_5v_en", PM8901_MPP_PM_TO_SYS(0), 0), }; /* GPIO regulator */ static struct platform_device msm8x60_8901_mpp_vreg = { .name = GPIO_REGULATOR_DEV_NAME, .id = PM8901_MPP_PM_TO_SYS(0), .dev = { .platform_data = &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V], }, }; static void __init pm8901_vreg_mpp0_init(void) { int rc; struct pm8xxx_mpp_init_info pm8901_vreg_mpp0 = { .mpp = PM8901_MPP_PM_TO_SYS(0), .config = { .type = PM8XXX_MPP_TYPE_D_OUTPUT, .level = PM8901_MPP_DIG_LEVEL_VPH, }, }; /* * Set PMIC 8901 MPP0 active_high to 0 for surf and charm_surf. This * implies that the regulator connected to MPP0 is enabled when * MPP0 is low. */ if (machine_is_msm8x60_surf() || machine_is_msm8x60_fusion()) { msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V].active_low = 1; pm8901_vreg_mpp0.config.control = PM8XXX_MPP_DOUT_CTRL_HIGH; } else { msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V].active_low = 0; pm8901_vreg_mpp0.config.control = PM8XXX_MPP_DOUT_CTRL_LOW; } rc = pm8xxx_mpp_config(pm8901_vreg_mpp0.mpp, &pm8901_vreg_mpp0.config); if (rc) pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc); } static struct platform_device *charm_devices[] __initdata = { &msm_charm_modem, }; #ifdef CONFIG_SND_SOC_MSM8660_APQ static struct platform_device *dragon_alsa_devices[] __initdata = { &msm_pcm, &msm_pcm_routing, &msm_cpudai0, &msm_cpudai1, &msm_cpudai_hdmi_rx, &msm_cpudai_bt_rx, &msm_cpudai_bt_tx, &msm_cpudai_fm_rx, &msm_cpudai_fm_tx, &msm_cpu_fe, &msm_stub_codec, &msm_lpa_pcm, }; #endif static struct platform_device *asoc_devices[] __initdata = { &asoc_msm_pcm, &asoc_msm_dai0, &asoc_msm_dai1, }; /* qseecom bus scaling */ static struct msm_bus_vectors qseecom_clks_init_vectors[] = { { .src = MSM_BUS_MASTER_SPS, .dst = MSM_BUS_SLAVE_EBI_CH0, .ib = 0, .ab = 0, }, { .src = MSM_BUS_MASTER_SPDM, .dst = MSM_BUS_SLAVE_SPDM, .ib = 0, .ab = 0, }, }; static struct msm_bus_vectors qseecom_enable_dfab_vectors[] = { { .src = MSM_BUS_MASTER_SPS, .dst = MSM_BUS_SLAVE_EBI_CH0, .ib = (492 * 8) * 1000000UL, .ab = (492 * 8) * 100000UL, }, { .src = MSM_BUS_MASTER_SPDM, .dst = MSM_BUS_SLAVE_SPDM, .ib = 0, .ab = 0, }, }; static struct msm_bus_vectors qseecom_enable_sfpb_vectors[] = { { .src = MSM_BUS_MASTER_SPS, .dst = MSM_BUS_SLAVE_EBI_CH0, .ib = 0, .ab = 0, }, { .src = MSM_BUS_MASTER_SPDM, .dst = MSM_BUS_SLAVE_SPDM, .ib = (64 * 8) * 1000000UL, .ab = (64 * 8) * 100000UL, }, }; static struct msm_bus_paths qseecom_hw_bus_scale_usecases[] = { { ARRAY_SIZE(qseecom_clks_init_vectors), qseecom_clks_init_vectors, }, { ARRAY_SIZE(qseecom_enable_dfab_vectors), qseecom_enable_sfpb_vectors, }, { ARRAY_SIZE(qseecom_enable_sfpb_vectors), qseecom_enable_sfpb_vectors, }, }; static struct msm_bus_scale_pdata qseecom_bus_pdata = { .usecase = qseecom_hw_bus_scale_usecases, .num_usecases = ARRAY_SIZE(qseecom_hw_bus_scale_usecases), .name = "qsee", }; static struct platform_device qseecom_device = { .name = "qseecom", .id = -1, .dev = { .platform_data = &qseecom_bus_pdata, }, }; static struct platform_device *surf_devices[] __initdata = { &msm8x60_device_acpuclk, &msm_device_smd, &msm_device_uart_dm12, &msm_pil_q6v3, &msm_pil_modem, &msm_pil_tzapps, &msm_pil_dsps, &msm_pil_vidc, &qseecom_device, #ifdef CONFIG_SERIAL_MSM_HS &msm_device_uart_dm1, #endif #if defined(CONFIG_USB_PEHCI_HCD) || defined(CONFIG_USB_PEHCI_HCD_MODULE) &isp1763_device, #endif #if defined (CONFIG_MSM_8x60_VOIP) &asoc_msm_mvs, &asoc_mvs_dai0, &asoc_mvs_dai1, #endif #if defined(CONFIG_USB_EHCI_HCD) &msm_device_otg, #endif #ifdef CONFIG_USB_G_ANDROID &android_usb_device, #endif &msm_fb_device, &msm_kgsl_3d0, &msm_kgsl_2d0, &msm_kgsl_2d1, &lcdc_samsung_panel_device, #ifdef CONFIG_FB_MSM_MIPI_DSI &mipi_dsi_toshiba_panel_device, &mipi_dsi_novatek_panel_device, #endif #if defined(CONFIG_MSM_RPM_LOG) || defined(CONFIG_MSM_RPM_LOG_MODULE) &msm8660_rpm_log_device, #endif #if defined(CONFIG_MSM_RPM_STATS_LOG) &msm8660_rpm_stat_device, #endif &msm_device_vidc, &rpm_regulator_device, #if \ defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) &qcrypto_device, #endif #if \ defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE) &qcedev_device, #endif #if defined(CONFIG_TSIF) || defined(CONFIG_TSIF_MODULE) #ifdef CONFIG_MSM_USE_TSIF1 &msm_device_tsif[1], #else &msm_device_tsif[0], #endif /* CONFIG_MSM_USE_TSIF1 */ #endif /* CONFIG_TSIF */ &msm_tsens_device, &msm8660_rpm_device, #ifdef CONFIG_ION_MSM &ion_dev, #endif &msm8660_device_watchdog, &msm_device_tz_log, &msm_rtb_device, &msm8660_iommu_domain_device, }; #ifdef CONFIG_ION_MSM #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION static struct ion_cp_heap_pdata cp_mm_ion_pdata = { .permission_type = IPT_TYPE_MM_CARVEOUT, .align = SZ_64K, .request_region = request_smi_region, .release_region = release_smi_region, .setup_region = setup_smi_region, .secure_base = SECURE_BASE, .secure_size = SECURE_SIZE, .iommu_map_all = 1, .iommu_2x_map_domain = VIDEO_DOMAIN, }; static struct ion_cp_heap_pdata cp_mfc_ion_pdata = { .permission_type = IPT_TYPE_MFC_SHAREDMEM, .align = PAGE_SIZE, .request_region = request_smi_region, .release_region = release_smi_region, .setup_region = setup_smi_region, }; static struct ion_cp_heap_pdata cp_wb_ion_pdata = { .permission_type = IPT_TYPE_MDP_WRITEBACK, .align = PAGE_SIZE, }; static struct ion_co_heap_pdata mm_fw_co_ion_pdata = { .adjacent_mem_id = ION_CP_MM_HEAP_ID, }; static struct ion_co_heap_pdata co_ion_pdata = { .adjacent_mem_id = INVALID_HEAP_ID, .align = PAGE_SIZE, }; #endif /** * These heaps are listed in the order they will be allocated. Due to * video hardware restrictions and content protection the FW heap has to * be allocated adjacent (below) the MM heap and the MFC heap has to be * allocated after the MM heap to ensure MFC heap is not more than 256MB * away from the base address of the FW heap. * However, the order of FW heap and MM heap doesn't matter since these * two heaps are taken care of by separate code to ensure they are adjacent * to each other. * Don't swap the order unless you know what you are doing! */ struct ion_platform_heap msm8x60_heaps [] = { { .id = ION_SYSTEM_HEAP_ID, .type = ION_HEAP_TYPE_SYSTEM, .name = ION_VMALLOC_HEAP_NAME, }, #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION { .id = ION_CP_MM_HEAP_ID, .type = ION_HEAP_TYPE_CP, .name = ION_MM_HEAP_NAME, .base = MSM_ION_MM_BASE, .size = MSM_ION_MM_SIZE, .memory_type = ION_SMI_TYPE, .extra_data = (void *) &cp_mm_ion_pdata, }, { .id = ION_MM_FIRMWARE_HEAP_ID, .type = ION_HEAP_TYPE_CARVEOUT, .name = ION_MM_FIRMWARE_HEAP_NAME, .base = MSM_MM_FW_BASE, .size = MSM_MM_FW_SIZE, .memory_type = ION_SMI_TYPE, .extra_data = (void *) &mm_fw_co_ion_pdata, }, { .id = ION_CP_MFC_HEAP_ID, .type = ION_HEAP_TYPE_CP, .name = ION_MFC_HEAP_NAME, .base = MSM_ION_MFC_BASE, .size = MSM_ION_MFC_SIZE, .memory_type = ION_SMI_TYPE, .extra_data = (void *) &cp_mfc_ion_pdata, }, { .id = ION_SF_HEAP_ID, .type = ION_HEAP_TYPE_CARVEOUT, .name = ION_SF_HEAP_NAME, .size = MSM_ION_SF_SIZE, .memory_type = ION_EBI_TYPE, .extra_data = (void *)&co_ion_pdata, }, { .id = ION_CP_WB_HEAP_ID, .type = ION_HEAP_TYPE_CP, .name = ION_WB_HEAP_NAME, .size = MSM_ION_WB_SIZE, .memory_type = ION_EBI_TYPE, .extra_data = (void *) &cp_wb_ion_pdata, }, { .id = ION_QSECOM_HEAP_ID, .type = ION_HEAP_TYPE_CARVEOUT, .name = ION_QSECOM_HEAP_NAME, .size = MSM_ION_QSECOM_SIZE, .memory_type = ION_EBI_TYPE, .extra_data = (void *) &co_ion_pdata, }, { .id = ION_AUDIO_HEAP_ID, .type = ION_HEAP_TYPE_CARVEOUT, .name = ION_AUDIO_HEAP_NAME, .size = MSM_ION_AUDIO_SIZE, .memory_type = ION_EBI_TYPE, .extra_data = (void *)&co_ion_pdata, }, #endif }; static struct ion_platform_data ion_pdata = { .nr = MSM_ION_HEAP_NUM, .heaps = msm8x60_heaps, }; static struct platform_device ion_dev = { .name = "ion-msm", .id = 1, .dev = { .platform_data = &ion_pdata }, }; #endif static struct memtype_reserve msm8x60_reserve_table[] __initdata = { /* Kernel SMI memory pool for video core, used for firmware */ /* and encoder, decoder scratch buffers */ /* Kernel SMI memory pool should always precede the user space */ /* SMI memory pool, as the video core will use offset address */ /* from the Firmware base */ [MEMTYPE_SMI_KERNEL] = { .start = KERNEL_SMI_BASE, .limit = KERNEL_SMI_SIZE, .size = KERNEL_SMI_SIZE, .flags = MEMTYPE_FLAGS_FIXED, }, [MEMTYPE_SMI] = { }, [MEMTYPE_EBI0] = { .flags = MEMTYPE_FLAGS_1M_ALIGN, }, [MEMTYPE_EBI1] = { .flags = MEMTYPE_FLAGS_1M_ALIGN, }, }; static void __init reserve_ion_memory(void) { #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION) unsigned int i; if (hdmi_is_primary) { msm_ion_sf_size = MSM_HDMI_PRIM_ION_SF_SIZE; for (i = 0; i < ion_pdata.nr; i++) { if (ion_pdata.heaps[i].id == ION_SF_HEAP_ID) { ion_pdata.heaps[i].size = msm_ion_sf_size; pr_debug("msm_ion_sf_size 0x%x\n", msm_ion_sf_size); break; } } } /* Verify size of heap is a multiple of 64K */ for (i = 0; i < ion_pdata.nr; i++) { struct ion_platform_heap *heap = &(ion_pdata.heaps[i]); if (heap->extra_data && heap->type == (enum ion_heap_type) ION_HEAP_TYPE_CP) { int map_all = ((struct ion_cp_heap_pdata *) heap->extra_data)->iommu_map_all; if (map_all && (heap->size & (SZ_64K-1))) { heap->size = ALIGN(heap->size, SZ_64K); pr_err("Heap %s size is not a multiple of 64K. Adjusting size to %x\n", heap->name, heap->size); } } } msm8x60_reserve_table[MEMTYPE_EBI1].size += msm_ion_sf_size; msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_WB_SIZE; msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE; msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_QSECOM_SIZE; #endif } static void __init size_pmem_devices(void) { } static void __init reserve_pmem_memory(void) { } static void __init reserve_mdp_memory(void); static void __init reserve_rtb_memory(void) { #if defined(CONFIG_MSM_RTB) msm8x60_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size; #endif } static void __init msm8x60_calculate_reserve_sizes(void) { size_pmem_devices(); reserve_pmem_memory(); reserve_ion_memory(); reserve_mdp_memory(); reserve_rtb_memory(); } static int msm8x60_paddr_to_memtype(unsigned int paddr) { if (paddr >= 0x40000000 && paddr < 0x60000000) return MEMTYPE_EBI1; if (paddr >= 0x38000000 && paddr < 0x40000000) return MEMTYPE_SMI; return MEMTYPE_NONE; } static struct reserve_info msm8x60_reserve_info __initdata = { .memtype_reserve_table = msm8x60_reserve_table, .calculate_reserve_sizes = msm8x60_calculate_reserve_sizes, .paddr_to_memtype = msm8x60_paddr_to_memtype, }; static char prim_panel_name[PANEL_NAME_MAX_LEN]; static char ext_panel_name[PANEL_NAME_MAX_LEN]; static int __init prim_display_setup(char *param) { if (strnlen(param, PANEL_NAME_MAX_LEN)) strlcpy(prim_panel_name, param, PANEL_NAME_MAX_LEN); return 0; } early_param("prim_display", prim_display_setup); static int __init ext_display_setup(char *param) { if (strnlen(param, PANEL_NAME_MAX_LEN)) strlcpy(ext_panel_name, param, PANEL_NAME_MAX_LEN); return 0; } early_param("ext_display", ext_display_setup); static void __init msm8x60_reserve(void) { msm8x60_set_display_params(prim_panel_name, ext_panel_name); reserve_info = &msm8x60_reserve_info; msm_reserve(); } #define EXT_CHG_VALID_MPP 10 #define EXT_CHG_VALID_MPP_2 11 static struct pm8xxx_mpp_init_info isl_mpp[] = { PM8058_MPP_INIT(EXT_CHG_VALID_MPP, D_INPUT, PM8058_MPP_DIG_LEVEL_S3, DIN_TO_INT), PM8058_MPP_INIT(EXT_CHG_VALID_MPP_2, D_BI_DIR, PM8058_MPP_DIG_LEVEL_S3, BI_PULLUP_10KOHM), }; #if defined(CONFIG_SMB137B_CHARGER_MODULE) static int smb137b_detection_setup(void) { int ret = 0, i; for (i = 0; i < ARRAY_SIZE(isl_mpp); i++) { ret = pm8xxx_mpp_config(isl_mpp[i].mpp, &isl_mpp[i].config); if (ret) { pr_err("%s: Config MPP %d of PM8058 failed\n", __func__, isl_mpp[i].mpp); return ret; } } return ret; } static struct smb137b_platform_data smb137b_data __initdata = { .chg_detection_config = smb137b_detection_setup, .valid_n_gpio = PM8058_MPP_PM_TO_SYS(10), .batt_mah_rating = 950, }; static struct i2c_board_info smb137b_charger_i2c_info[] __initdata = { { I2C_BOARD_INFO("smb137b", 0x08), .irq = PM8058_IRQ_BASE + PM8058_CBLPWR_IRQ, .platform_data = &smb137b_data, }, }; #endif #if \ defined(CONFIG_HAPTIC_ISA1200_MODULE) struct pm_gpio en_hap_gpio_cfg = { .direction = PM_GPIO_DIR_OUT, .pull = PM_GPIO_PULL_NO, .out_strength = PM_GPIO_STRENGTH_HIGH, .function = PM_GPIO_FUNC_NORMAL, .inv_int_pol = 0, .vin_sel = 2, .output_buffer = PM_GPIO_OUT_BUF_CMOS, .output_value = 0, }; #endif #if defined(CONFIG_PMIC8058_OTHC_MODULE) struct pm8058_gpio_cfg line_in_gpio_cfg = { PM8058_GPIO_PM_TO_SYS(18), { .direction = PM_GPIO_DIR_IN, .pull = PM_GPIO_PULL_UP_1P5, .vin_sel = 2, .function = PM_GPIO_FUNC_NORMAL, .inv_int_pol = 0, } }; #endif #if \ defined(CONFIG_HAPTIC_ISA1200_MODULE) if (machine_is_msm8x60_fluid()) { rc = pm8xxx_gpio_config( PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_ENABLE), &en_hap_gpio_cfg); if (rc < 0) { pr_err("%s: pmic haptics gpio config failed\n", __func__); } rc = pm8xxx_gpio_config( PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_LDO_ENABLE), &en_hap_gpio_cfg); if (rc < 0) { pr_err("%s: pmic haptics ldo gpio config failed\n", __func__); } } #endif #if \ defined(CONFIG_TOUCHDISC_VTD518_SHINETSU_MODULE) if (machine_is_msm8x60_ffa() || machine_is_msm8x60_surf() || machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) { rc = pm8xxx_gpio_config( PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_TOUCH_DISC_INTR), &touchdisc_intr_gpio_cfg); if (rc < 0) { pr_err("%s: Touchdisc interrupt gpio config failed\n", __func__); } } #endif #if defined(CONFIG_PMIC8058_OTHC_MODULE) /* Line_in only for 8660 ffa & surf */ if (machine_is_msm8x60_ffa() || machine_is_msm8x60_surf() || machine_is_msm8x60_fusion() || machine_is_msm8x60_dragon() || machine_is_msm8x60_fusn_ffa()) { rc = pm8xxx_gpio_config(line_in_gpio_cfg.gpio, &line_in_gpio_cfg.cfg); if (rc < 0) { pr_err("%s pmic line_in gpio config failed\n", __func__); return rc; } } #endif for (i = 0; i < ARRAY_SIZE(gpio_cfgs); ++i) { rc = pm8xxx_gpio_config(gpio_cfgs[i].gpio, &gpio_cfgs[i].cfg); if (rc < 0) { pr_err("%s pmic gpio config failed\n", __func__); return rc; } } return 0; } static const unsigned int ffa_keymap[] = { KEY(0, 0, KEY_FN_F1), /* LS - PUSH1 */ KEY(0, 1, KEY_UP), /* NAV - UP */ KEY(0, 2, KEY_LEFT), /* NAV - LEFT */ KEY(0, 3, KEY_VOLUMEUP), /* Shuttle SW_UP */ KEY(1, 0, KEY_FN_F2), /* LS - PUSH2 */ KEY(1, 1, KEY_RIGHT), /* NAV - RIGHT */ KEY(1, 2, KEY_DOWN), /* NAV - DOWN */ KEY(1, 3, KEY_VOLUMEDOWN), KEY(2, 3, KEY_ENTER), /* SW_PUSH key */ KEY(4, 0, KEY_CAMERA_FOCUS), /* RS - PUSH1 */ KEY(4, 1, KEY_UP), /* USER_UP */ KEY(4, 2, KEY_LEFT), /* USER_LEFT */ KEY(4, 3, KEY_HOME), /* Right switch: MIC Bd */ KEY(4, 4, KEY_FN_F3), /* Reserved MIC */ KEY(5, 0, KEY_CAMERA), /* RS - PUSH2 */ KEY(5, 1, KEY_RIGHT), /* USER_RIGHT */ KEY(5, 2, KEY_DOWN), /* USER_DOWN */ KEY(5, 3, KEY_BACK), /* Left switch: MIC */ KEY(5, 4, KEY_MENU), /* Center switch: MIC */ }; static const unsigned int dragon_keymap[] = { KEY(0, 0, KEY_MENU), KEY(0, 2, KEY_1), KEY(0, 3, KEY_4), KEY(0, 4, KEY_7), KEY(1, 0, KEY_UP), KEY(1, 1, KEY_LEFT), KEY(1, 2, KEY_DOWN), KEY(1, 3, KEY_5), KEY(1, 4, KEY_8), KEY(2, 0, KEY_HOME), KEY(2, 1, KEY_REPLY), KEY(2, 2, KEY_2), KEY(2, 3, KEY_6), KEY(2, 4, KEY_0), KEY(3, 0, KEY_VOLUMEUP), KEY(3, 1, KEY_RIGHT), KEY(3, 2, KEY_3), KEY(3, 3, KEY_9), KEY(3, 4, KEY_SWITCHVIDEOMODE), KEY(4, 0, KEY_VOLUMEDOWN), KEY(4, 1, KEY_BACK), KEY(4, 2, KEY_CAMERA), KEY(4, 3, KEY_KBDILLUMTOGGLE), }; static struct matrix_keymap_data ffa_keymap_data = { .keymap_size = ARRAY_SIZE(ffa_keymap), .keymap = ffa_keymap, }; static struct pm8xxx_keypad_platform_data ffa_keypad_data = { .input_name = "ffa-keypad", .input_phys_device = "ffa-keypad/input0", .num_rows = 6, .num_cols = 5, .rows_gpio_start = PM8058_GPIO_PM_TO_SYS(8), .cols_gpio_start = PM8058_GPIO_PM_TO_SYS(0), .debounce_ms = 15, .scan_delay_ms = 32, .row_hold_ns = 91500, .wakeup = 1, .keymap_data = &ffa_keymap_data, }; static struct matrix_keymap_data dragon_keymap_data = { .keymap_size = ARRAY_SIZE(dragon_keymap), .keymap = dragon_keymap, }; static struct pm8xxx_keypad_platform_data dragon_keypad_data = { .input_name = "dragon-keypad", .input_phys_device = "dragon-keypad/input0", .num_rows = 6, .num_cols = 5, .rows_gpio_start = PM8058_GPIO_PM_TO_SYS(8), .cols_gpio_start = PM8058_GPIO_PM_TO_SYS(0), .debounce_ms = 15, .scan_delay_ms = 32, .row_hold_ns = 91500, .wakeup = 1, .keymap_data = &dragon_keymap_data, }; static const unsigned int fluid_keymap[] = { KEY(0, 0, KEY_FN_F1), /* LS - PUSH1 */ KEY(0, 1, KEY_UP), /* NAV - UP */ KEY(0, 2, KEY_LEFT), /* NAV - LEFT */ KEY(0, 3, KEY_VOLUMEDOWN), /* Shuttle SW_UP */ KEY(1, 0, KEY_FN_F2), /* LS - PUSH2 */ KEY(1, 1, KEY_RIGHT), /* NAV - RIGHT */ KEY(1, 2, KEY_DOWN), /* NAV - DOWN */ KEY(1, 3, KEY_VOLUMEUP), KEY(2, 3, KEY_ENTER), /* SW_PUSH key */ KEY(4, 0, KEY_CAMERA_FOCUS), /* RS - PUSH1 */ KEY(4, 1, KEY_UP), /* USER_UP */ KEY(4, 2, KEY_LEFT), /* USER_LEFT */ KEY(4, 3, KEY_HOME), /* Right switch: MIC Bd */ KEY(4, 4, KEY_FN_F3), /* Reserved MIC */ KEY(5, 0, KEY_CAMERA), /* RS - PUSH2 */ KEY(5, 1, KEY_RIGHT), /* USER_RIGHT */ KEY(5, 2, KEY_DOWN), /* USER_DOWN */ KEY(5, 3, KEY_BACK), /* Left switch: MIC */ KEY(5, 4, KEY_MENU), /* Center switch: MIC */ }; static struct matrix_keymap_data fluid_keymap_data = { .keymap_size = ARRAY_SIZE(fluid_keymap), .keymap = fluid_keymap, }; static struct pm8xxx_keypad_platform_data fluid_keypad_data = { .input_name = "fluid-keypad", .input_phys_device = "fluid-keypad/input0", .num_rows = 6, .num_cols = 5, .rows_gpio_start = PM8058_GPIO_PM_TO_SYS(8), .cols_gpio_start = PM8058_GPIO_PM_TO_SYS(0), .debounce_ms = 15, .scan_delay_ms = 32, .row_hold_ns = 91500, .wakeup = 1, .keymap_data = &fluid_keymap_data, }; static struct pm8xxx_vibrator_platform_data pm8058_vib_pdata = { .initial_vibrate_ms = 500, .level_mV = 3000, .max_timeout_ms = 15000, }; static struct pm8xxx_rtc_platform_data pm8058_rtc_pdata = { .rtc_write_enable = false, .rtc_alarm_powerup = false, }; static struct pm8xxx_pwrkey_platform_data pm8058_pwrkey_pdata = { .pull_up = 1, .kpd_trigger_delay_us = 15625, .wakeup = 1, }; #define PM8058_LINE_IN_DET_GPIO PM8058_GPIO_PM_TO_SYS(18) static struct othc_accessory_info othc_accessories[] = { { .accessory = OTHC_SVIDEO_OUT, .detect_flags = OTHC_MICBIAS_DETECT | OTHC_SWITCH_DETECT | OTHC_ADC_DETECT, .key_code = SW_VIDEOOUT_INSERT, .enabled = false, .adc_thres = { .min_threshold = 20, .max_threshold = 40, }, }, { .accessory = OTHC_ANC_HEADPHONE, .detect_flags = OTHC_MICBIAS_DETECT | OTHC_GPIO_DETECT | OTHC_SWITCH_DETECT, .gpio = PM8058_LINE_IN_DET_GPIO, .active_low = 1, .key_code = SW_HEADPHONE_INSERT, .enabled = true, }, { .accessory = OTHC_ANC_HEADSET, .detect_flags = OTHC_MICBIAS_DETECT | OTHC_GPIO_DETECT, .gpio = PM8058_LINE_IN_DET_GPIO, .active_low = 1, .key_code = SW_HEADPHONE_INSERT, .enabled = true, }, { .accessory = OTHC_HEADPHONE, .detect_flags = OTHC_MICBIAS_DETECT | OTHC_SWITCH_DETECT, .key_code = SW_HEADPHONE_INSERT, .enabled = true, }, { .accessory = OTHC_MICROPHONE, .detect_flags = OTHC_GPIO_DETECT, .gpio = PM8058_LINE_IN_DET_GPIO, .active_low = 1, .key_code = SW_MICROPHONE_INSERT, .enabled = true, }, { .accessory = OTHC_HEADSET, .detect_flags = OTHC_MICBIAS_DETECT, .key_code = SW_HEADPHONE_INSERT, .enabled = true, }, }; static struct othc_switch_info switch_info[] = { { .min_adc_threshold = 0, .max_adc_threshold = 100, .key_code = KEY_PLAYPAUSE, }, { .min_adc_threshold = 100, .max_adc_threshold = 200, .key_code = KEY_REWIND, }, { .min_adc_threshold = 200, .max_adc_threshold = 500, .key_code = KEY_FASTFORWARD, }, }; static struct othc_n_switch_config switch_config = { .voltage_settling_time_ms = 0, .num_adc_samples = 3, .adc_channel = CHANNEL_ADC_HDSET, .switch_info = switch_info, .num_keys = ARRAY_SIZE(switch_info), .default_sw_en = true, .default_sw_idx = 0, }; static struct hsed_bias_config hsed_bias_config = { /* HSED mic bias config info */ .othc_headset = OTHC_HEADSET_NO, .othc_lowcurr_thresh_uA = 100, .othc_highcurr_thresh_uA = 600, .othc_hyst_prediv_us = 7800, .othc_period_clkdiv_us = 62500, .othc_hyst_clk_us = 121000, .othc_period_clk_us = 312500, .othc_wakeup = 1, }; static struct othc_hsed_config hsed_config_1 = { .hsed_bias_config = &hsed_bias_config, /* * The detection delay and switch reporting delay are * required to encounter a hardware bug (spurious switch * interrupts on slow insertion/removal of the headset). * This will introduce a delay in reporting the accessory * insertion and removal to the userspace. */ .detection_delay_ms = 1500, /* Switch info */ .switch_debounce_ms = 1500, .othc_support_n_switch = false, .switch_config = &switch_config, .ir_gpio = -1, /* Accessory info */ .accessories_support = true, .accessories = othc_accessories, .othc_num_accessories = ARRAY_SIZE(othc_accessories), }; static struct othc_regulator_config othc_reg = { .regulator = "8058_l5", .max_uV = 2850000, .min_uV = 2850000, }; /* MIC_BIAS0 is configured as normal MIC BIAS */ static struct pmic8058_othc_config_pdata othc_config_pdata_0 = { .micbias_select = OTHC_MICBIAS_0, .micbias_capability = OTHC_MICBIAS, .micbias_enable = OTHC_SIGNAL_OFF, .micbias_regulator = &othc_reg, }; /* MIC_BIAS1 is configured as HSED_BIAS for OTHC */ static struct pmic8058_othc_config_pdata othc_config_pdata_1 = { .micbias_select = OTHC_MICBIAS_1, .micbias_capability = OTHC_MICBIAS_HSED, .micbias_enable = OTHC_SIGNAL_PWM_TCXO, .micbias_regulator = &othc_reg, .hsed_config = &hsed_config_1, .hsed_name = "8660_handset", }; /* MIC_BIAS2 is configured as normal MIC BIAS */ static struct pmic8058_othc_config_pdata othc_config_pdata_2 = { .micbias_select = OTHC_MICBIAS_2, .micbias_capability = OTHC_MICBIAS, .micbias_enable = OTHC_SIGNAL_OFF, .micbias_regulator = &othc_reg, }; static void __init msm8x60_init_pm8058_othc(void) { int i; if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2 || machine_is_msm8x60_fluid() || machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) { /* 3-switch headset supported only by V2 FFA and FLUID */ hsed_config_1.accessories_adc_support = true, /* ADC based accessory detection works only on V2 and FLUID */ hsed_config_1.accessories_adc_channel = CHANNEL_ADC_HDSET, hsed_config_1.othc_support_n_switch = true; } /* IR GPIO is absent on FLUID */ if (machine_is_msm8x60_fluid()) hsed_config_1.ir_gpio = -1; for (i = 0; i < ARRAY_SIZE(othc_accessories); i++) { if (machine_is_msm8x60_fluid()) { switch (othc_accessories[i].accessory) { case OTHC_ANC_HEADPHONE: case OTHC_ANC_HEADSET: othc_accessories[i].gpio = GPIO_HEADSET_DET_N; break; case OTHC_MICROPHONE: othc_accessories[i].enabled = false; break; case OTHC_SVIDEO_OUT: othc_accessories[i].enabled = true; hsed_config_1.video_out_gpio = GPIO_HS_SW_DIR; break; } } } } static int pm8058_pwm_config(struct pwm_device *pwm, int ch, int on) { struct pm_gpio pwm_gpio_config = { .direction = PM_GPIO_DIR_OUT, .output_buffer = PM_GPIO_OUT_BUF_CMOS, .output_value = 0, .pull = PM_GPIO_PULL_NO, .vin_sel = PM8058_GPIO_VIN_VPH, .out_strength = PM_GPIO_STRENGTH_HIGH, .function = PM_GPIO_FUNC_2, }; int rc = -EINVAL; int id, mode, max_mA; id = mode = max_mA = 0; switch (ch) { case 0: case 1: case 2: if (on) { id = 24 + ch; rc = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(id - 1), &pwm_gpio_config); if (rc) pr_err("%s: pm8xxx_gpio_config(%d): rc=%d\n", __func__, id, rc); } break; case 6: id = PM_PWM_LED_FLASH; mode = PM_PWM_CONF_PWM1; max_mA = 300; break; case 7: id = PM_PWM_LED_FLASH1; mode = PM_PWM_CONF_PWM1; max_mA = 300; break; default: break; } if (ch >= 6 && ch <= 7) { if (!on) { mode = PM_PWM_CONF_NONE; max_mA = 0; } rc = pm8058_pwm_config_led(pwm, id, mode, max_mA); if (rc) pr_err("%s: pm8058_pwm_config_led(ch=%d): rc=%d\n", __func__, ch, rc); } return rc; } static struct pm8058_pwm_pdata pm8058_pwm_data = { .config = pm8058_pwm_config, }; #define PM8058_GPIO_INT 88 static struct pmic8058_charger_data pmic8058_charger_dragon = { .charger_data_valid = true, .max_source_current = 1800, .charger_type = CHG_TYPE_AC, }; static struct pmic8058_charger_data pmic8058_charger_ffa_surf = { .charger_data_valid = false, }; static struct pm8xxx_misc_platform_data pm8058_misc_pdata = { .priority = 0, }; static struct pm8xxx_irq_platform_data pm8058_irq_pdata = { .irq_base = PM8058_IRQ_BASE, .devirq = MSM_GPIO_TO_INT(PM8058_GPIO_INT), .irq_trigger_flag = IRQF_TRIGGER_LOW, }; static struct pm8xxx_gpio_platform_data pm8058_gpio_pdata = { .gpio_base = PM8058_GPIO_PM_TO_SYS(0), }; static struct pm8xxx_mpp_platform_data pm8058_mpp_pdata = { .mpp_base = PM8058_MPP_PM_TO_SYS(0), }; static struct pm8058_platform_data pm8058_platform_data = { .irq_pdata = &pm8058_irq_pdata, .gpio_pdata = &pm8058_gpio_pdata, .mpp_pdata = &pm8058_mpp_pdata, .rtc_pdata = &pm8058_rtc_pdata, .pwrkey_pdata = &pm8058_pwrkey_pdata, .othc0_pdata = &othc_config_pdata_0, .othc1_pdata = &othc_config_pdata_1, .othc2_pdata = &othc_config_pdata_2, .pwm_pdata = &pm8058_pwm_data, .misc_pdata = &pm8058_misc_pdata, }; #endif /* CONFIG_PMIC8058 */ #if \ defined(CONFIG_TOUCHDISC_VTD518_SHINETSU_MODULE) #define TDISC_I2C_SLAVE_ADDR 0x67 #define PMIC_GPIO_TDISC PM8058_GPIO_PM_TO_SYS(5) #define TDISC_INT PM8058_GPIO_IRQ(PM8058_IRQ_BASE, 5) static const char *vregs_tdisc_name[] = { "8058_l5", "8058_s3", }; static const int vregs_tdisc_val[] = { 2850000,/* uV */ 1800000, }; static struct regulator *vregs_tdisc[ARRAY_SIZE(vregs_tdisc_name)]; static int tdisc_shinetsu_setup(void) { int rc, i; rc = gpio_request(PMIC_GPIO_TDISC, "tdisc_interrupt"); if (rc) { pr_err("%s: gpio_request failed for PMIC_GPIO_TDISC\n", __func__); return rc; } rc = gpio_request(GPIO_JOYSTICK_EN, "tdisc_oe"); if (rc) { pr_err("%s: gpio_request failed for GPIO_JOYSTICK_EN\n", __func__); goto fail_gpio_oe; } rc = gpio_direction_output(GPIO_JOYSTICK_EN, 1); if (rc) { pr_err("%s: gpio_direction_output failed for GPIO_JOYSTICK_EN\n", __func__); gpio_free(GPIO_JOYSTICK_EN); goto fail_gpio_oe; } for (i = 0; i < ARRAY_SIZE(vregs_tdisc_name); i++) { vregs_tdisc[i] = regulator_get(NULL, vregs_tdisc_name[i]); if (IS_ERR(vregs_tdisc[i])) { printk(KERN_ERR "%s: regulator get %s failed (%ld)\n", __func__, vregs_tdisc_name[i], PTR_ERR(vregs_tdisc[i])); rc = PTR_ERR(vregs_tdisc[i]); goto vreg_get_fail; } rc = regulator_set_voltage(vregs_tdisc[i], vregs_tdisc_val[i], vregs_tdisc_val[i]); if (rc) { printk(KERN_ERR "%s: regulator_set_voltage() = %d\n", __func__, rc); goto vreg_set_voltage_fail; } } return rc; vreg_set_voltage_fail: i++; vreg_get_fail: while (i) regulator_put(vregs_tdisc[--i]); fail_gpio_oe: gpio_free(PMIC_GPIO_TDISC); return rc; } static void tdisc_shinetsu_release(void) { int i; for (i = 0; i < ARRAY_SIZE(vregs_tdisc_name); i++) regulator_put(vregs_tdisc[i]); gpio_free(PMIC_GPIO_TDISC); gpio_free(GPIO_JOYSTICK_EN); } static int tdisc_shinetsu_enable(void) { int i, rc = -EINVAL; for (i = 0; i < ARRAY_SIZE(vregs_tdisc_name); i++) { rc = regulator_enable(vregs_tdisc[i]); if (rc < 0) { printk(KERN_ERR "%s: vreg %s enable failed (%d)\n", __func__, vregs_tdisc_name[i], rc); goto vreg_fail; } } /* Enable the OE (output enable) gpio */ gpio_set_value_cansleep(GPIO_JOYSTICK_EN, 1); /* voltage and gpio stabilization delay */ msleep(50); return 0; vreg_fail: while (i) regulator_disable(vregs_tdisc[--i]); return rc; } static int tdisc_shinetsu_disable(void) { int i, rc; for (i = 0; i < ARRAY_SIZE(vregs_tdisc_name); i++) { rc = regulator_disable(vregs_tdisc[i]); if (rc < 0) { printk(KERN_ERR "%s: vreg %s disable failed (%d)\n", __func__, vregs_tdisc_name[i], rc); goto tdisc_reg_fail; } } /* Disable the OE (output enable) gpio */ gpio_set_value_cansleep(GPIO_JOYSTICK_EN, 0); return 0; tdisc_reg_fail: while (i) regulator_enable(vregs_tdisc[--i]); return rc; } static struct tdisc_abs_values tdisc_abs = { .x_max = 32, .y_max = 32, .x_min = -32, .y_min = -32, .pressure_max = 32, .pressure_min = 0, }; static struct tdisc_platform_data tdisc_data = { .tdisc_setup = tdisc_shinetsu_setup, .tdisc_release = tdisc_shinetsu_release, .tdisc_enable = tdisc_shinetsu_enable, .tdisc_disable = tdisc_shinetsu_disable, .tdisc_wakeup = 0, .tdisc_gpio = PMIC_GPIO_TDISC, .tdisc_report_keys = true, .tdisc_report_relative = true, .tdisc_report_absolute = false, .tdisc_report_wheel = false, .tdisc_reverse_x = false, .tdisc_reverse_y = true, .tdisc_abs = &tdisc_abs, }; static struct i2c_board_info msm_i2c_gsbi3_tdisc_info[] = { { I2C_BOARD_INFO("vtd518", TDISC_I2C_SLAVE_ADDR), .irq = TDISC_INT, .platform_data = &tdisc_data, }, }; #endif #define PM_GPIO_CDC_RST_N 20 #define GPIO_CDC_RST_N PM8058_GPIO_PM_TO_SYS(PM_GPIO_CDC_RST_N) static struct regulator *vreg_timpani_1; static struct regulator *vreg_timpani_2; static unsigned int msm_timpani_setup_power(void) { int rc; vreg_timpani_1 = regulator_get(NULL, "8058_l0"); if (IS_ERR(vreg_timpani_1)) { pr_err("%s: Unable to get 8058_l0\n", __func__); return -ENODEV; } vreg_timpani_2 = regulator_get(NULL, "8058_s3"); if (IS_ERR(vreg_timpani_2)) { pr_err("%s: Unable to get 8058_s3\n", __func__); regulator_put(vreg_timpani_1); return -ENODEV; } rc = regulator_set_voltage(vreg_timpani_1, 1200000, 1200000); if (rc) { pr_err("%s: unable to set L0 voltage to 1.2V\n", __func__); goto fail; } rc = regulator_set_voltage(vreg_timpani_2, 1800000, 1800000); if (rc) { pr_err("%s: unable to set S3 voltage to 1.8V\n", __func__); goto fail; } rc = regulator_enable(vreg_timpani_1); if (rc) { pr_err("%s: Enable regulator 8058_l0 failed\n", __func__); goto fail; } /* The settings for LDO0 should be set such that * it doesn't require to reset the timpani. */ rc = regulator_set_optimum_mode(vreg_timpani_1, 5000); if (rc < 0) { pr_err("Timpani regulator optimum mode setting failed\n"); goto fail; } rc = regulator_enable(vreg_timpani_2); if (rc) { pr_err("%s: Enable regulator 8058_s3 failed\n", __func__); regulator_disable(vreg_timpani_1); goto fail; } rc = gpio_request(GPIO_CDC_RST_N, "CDC_RST_N"); if (rc) { pr_err("%s: GPIO Request %d failed\n", __func__, GPIO_CDC_RST_N); regulator_disable(vreg_timpani_1); regulator_disable(vreg_timpani_2); goto fail; } else { gpio_direction_output(GPIO_CDC_RST_N, 1); usleep_range(1000, 1050); gpio_direction_output(GPIO_CDC_RST_N, 0); usleep_range(1000, 1050); gpio_direction_output(GPIO_CDC_RST_N, 1); gpio_free(GPIO_CDC_RST_N); } return rc; fail: regulator_put(vreg_timpani_1); regulator_put(vreg_timpani_2); return rc; } static void msm_timpani_shutdown_power(void) { int rc; rc = regulator_disable(vreg_timpani_1); if (rc) pr_err("%s: Disable regulator 8058_l0 failed\n", __func__); regulator_put(vreg_timpani_1); rc = regulator_disable(vreg_timpani_2); if (rc) pr_err("%s: Disable regulator 8058_s3 failed\n", __func__); regulator_put(vreg_timpani_2); } /* Power analog function of codec */ static struct regulator *vreg_timpani_cdc_apwr; static int msm_timpani_codec_power(int vreg_on) { int rc = 0; if (!vreg_timpani_cdc_apwr) { vreg_timpani_cdc_apwr = regulator_get(NULL, "8058_s4"); if (IS_ERR(vreg_timpani_cdc_apwr)) { pr_err("%s: vreg_get failed (%ld)\n", __func__, PTR_ERR(vreg_timpani_cdc_apwr)); rc = PTR_ERR(vreg_timpani_cdc_apwr); return rc; } } if (vreg_on) { rc = regulator_set_voltage(vreg_timpani_cdc_apwr, 2200000, 2200000); if (rc) { pr_err("%s: unable to set 8058_s4 voltage to 2.2 V\n", __func__); goto vreg_fail; } rc = regulator_enable(vreg_timpani_cdc_apwr); if (rc) { pr_err("%s: vreg_enable failed %d\n", __func__, rc); goto vreg_fail; } } else { rc = regulator_disable(vreg_timpani_cdc_apwr); if (rc) { pr_err("%s: vreg_disable failed %d\n", __func__, rc); goto vreg_fail; } } return 0; vreg_fail: regulator_put(vreg_timpani_cdc_apwr); vreg_timpani_cdc_apwr = NULL; return rc; } static struct marimba_codec_platform_data timpani_codec_pdata = { .marimba_codec_power = msm_timpani_codec_power, }; #define TIMPANI_SLAVE_ID_CDC_ADDR 0X77 #define TIMPANI_SLAVE_ID_QMEMBIST_ADDR 0X66 static struct marimba_platform_data timpani_pdata = { .slave_id[MARIMBA_SLAVE_ID_CDC] = TIMPANI_SLAVE_ID_CDC_ADDR, .slave_id[MARIMBA_SLAVE_ID_QMEMBIST] = TIMPANI_SLAVE_ID_QMEMBIST_ADDR, .marimba_setup = msm_timpani_setup_power, .marimba_shutdown = msm_timpani_shutdown_power, .codec = &timpani_codec_pdata, .tsadc_ssbi_adap = MARIMBA_SSBI_ADAP, }; #define TIMPANI_I2C_SLAVE_ADDR 0xD static struct i2c_board_info msm_i2c_gsbi7_timpani_info[] = { { I2C_BOARD_INFO("timpani", TIMPANI_I2C_SLAVE_ADDR), .platform_data = &timpani_pdata, }, }; #ifdef CONFIG_SND_SOC_WM8903 static struct wm8903_platform_data wm8903_pdata = { .gpio_cfg[2] = 0x3A8, }; #define WM8903_I2C_SLAVE_ADDR 0x34 static struct i2c_board_info wm8903_codec_i2c_info[] = { { I2C_BOARD_INFO("wm8903", WM8903_I2C_SLAVE_ADDR >> 1), .platform_data = &wm8903_pdata, }, }; #endif #ifdef CONFIG_I2C #define I2C_SURF 1 #define I2C_FFA (1 << 1) #define I2C_RUMI (1 << 2) #define I2C_SIM (1 << 3) #define I2C_FLUID (1 << 4) #define I2C_DRAGON (1 << 5) struct i2c_registry { u8 machs; int bus; struct i2c_board_info *info; int len; }; static struct i2c_registry msm8x60_i2c_devices[] __initdata = { #if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE) { I2C_SURF | I2C_FFA | I2C_DRAGON, MSM_GSBI8_QUP_I2C_BUS_ID, core_expander_i2c_info, ARRAY_SIZE(core_expander_i2c_info), }, { I2C_SURF | I2C_FFA | I2C_DRAGON, MSM_GSBI8_QUP_I2C_BUS_ID, docking_expander_i2c_info, ARRAY_SIZE(docking_expander_i2c_info), }, { I2C_SURF, MSM_GSBI8_QUP_I2C_BUS_ID, surf_expanders_i2c_info, ARRAY_SIZE(surf_expanders_i2c_info), }, { I2C_SURF | I2C_FFA | I2C_DRAGON, MSM_GSBI3_QUP_I2C_BUS_ID, fha_expanders_i2c_info, ARRAY_SIZE(fha_expanders_i2c_info), }, { I2C_FLUID, MSM_GSBI3_QUP_I2C_BUS_ID, fluid_expanders_i2c_info, ARRAY_SIZE(fluid_expanders_i2c_info), }, { I2C_FLUID, MSM_GSBI8_QUP_I2C_BUS_ID, fluid_core_expander_i2c_info, ARRAY_SIZE(fluid_core_expander_i2c_info), }, #endif #if \ defined(CONFIG_TOUCHDISC_VTD518_SHINETSU_MODULE) { I2C_SURF | I2C_FFA | I2C_FLUID | I2C_DRAGON, MSM_GSBI3_QUP_I2C_BUS_ID, msm_i2c_gsbi3_tdisc_info, ARRAY_SIZE(msm_i2c_gsbi3_tdisc_info), }, #endif { I2C_SURF | I2C_FFA | I2C_FLUID, MSM_GSBI3_QUP_I2C_BUS_ID, cy8ctmg200_board_info, ARRAY_SIZE(cy8ctmg200_board_info), }, { I2C_DRAGON, MSM_GSBI3_QUP_I2C_BUS_ID, cy8ctma340_dragon_board_info, ARRAY_SIZE(cy8ctma340_dragon_board_info), }, #if \ defined(CONFIG_TOUCHSCREEN_CYTTSP_I2C_QC_MODULE) { I2C_FLUID, MSM_GSBI3_QUP_I2C_BUS_ID, cyttsp_fluid_info, ARRAY_SIZE(cyttsp_fluid_info), }, { I2C_FFA | I2C_SURF, MSM_GSBI3_QUP_I2C_BUS_ID, cyttsp_ffa_info, ARRAY_SIZE(cyttsp_ffa_info), }, #endif { I2C_SURF | I2C_FFA | I2C_FLUID, MSM_GSBI7_QUP_I2C_BUS_ID, msm_i2c_gsbi7_timpani_info, ARRAY_SIZE(msm_i2c_gsbi7_timpani_info), }, #if \ defined(CONFIG_HAPTIC_ISA1200_MODULE) { I2C_FLUID, MSM_GSBI8_QUP_I2C_BUS_ID, msm_isa1200_board_info, ARRAY_SIZE(msm_isa1200_board_info), }, #endif #if defined(CONFIG_SMB137B_CHARGER_MODULE) { I2C_FLUID, MSM_GSBI8_QUP_I2C_BUS_ID, smb137b_charger_i2c_info, ARRAY_SIZE(smb137b_charger_i2c_info), }, #endif #if \ defined(CONFIG_BATTERY_BQ27520_MODULE) { I2C_FLUID, MSM_GSBI8_QUP_I2C_BUS_ID, msm_bq27520_board_info, ARRAY_SIZE(msm_bq27520_board_info), }, #endif #if defined(CONFIG_SND_SOC_WM8903) || defined(CONFIG_SND_SOC_WM8903_MODULE) { I2C_DRAGON, MSM_GSBI8_QUP_I2C_BUS_ID, wm8903_codec_i2c_info, ARRAY_SIZE(wm8903_codec_i2c_info), }, #endif }; #endif /* CONFIG_I2C */ static void __init fixup_i2c_configs(void) { #ifdef CONFIG_I2C #if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE) if (machine_is_msm8x60_surf() || machine_is_msm8x60_fusion()) sx150x_data[SX150X_CORE].irq_summary = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT2_N); else if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa() || machine_is_msm8x60_dragon()) sx150x_data[SX150X_CORE].irq_summary = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT1_N); else if (machine_is_msm8x60_fluid()) sx150x_data[SX150X_CORE_FLUID].irq_summary = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT1_N); #endif #endif } static void __init register_i2c_devices(void) { #ifdef CONFIG_I2C u8 mach_mask = 0; int i; /* Build the matching 'supported_machs' bitmask */ if (machine_is_msm8x60_surf() || machine_is_msm8x60_fusion()) mach_mask = I2C_SURF; else if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa()) mach_mask = I2C_FFA; else if (machine_is_msm8x60_fluid()) mach_mask = I2C_FLUID; else if (machine_is_msm8x60_dragon()) mach_mask = I2C_DRAGON; else pr_err("unmatched machine ID in register_i2c_devices\n"); /* Run the array and install devices as appropriate */ for (i = 0; i < ARRAY_SIZE(msm8x60_i2c_devices); ++i) { if (msm8x60_i2c_devices[i].machs & mach_mask) i2c_register_board_info(msm8x60_i2c_devices[i].bus, msm8x60_i2c_devices[i].info, msm8x60_i2c_devices[i].len); } #endif } static void __init msm8x60_init_uart12dm(void) { #if !defined(CONFIG_USB_PEHCI_HCD) && !defined(CONFIG_USB_PEHCI_HCD_MODULE) /* 0x1D000000 now belongs to EBI2:CS3 i.e. USB ISP Controller */ void *fpga_mem = ioremap_nocache(0x1D000000, SZ_4K); if (!fpga_mem) pr_err("%s(): Error getting memory\n", __func__); /* Advanced mode */ writew(0xFFFF, fpga_mem + 0x15C); /* FPGA_UART_SEL */ writew(0, fpga_mem + 0x172); /* FPGA_GPIO_CONFIG_117 */ writew(1, fpga_mem + 0xEA); /* FPGA_GPIO_CONFIG_118 */ writew(1, fpga_mem + 0xEC); mb(); iounmap(fpga_mem); #endif } #define MSM_GSBI9_PHYS 0x19900000 #define GSBI_DUAL_MODE_CODE 0x60 static void __init msm8x60_init_buses(void) { #if defined(CONFIG_SPI_QUP) || defined(CONFIG_SPI_QUP_MODULE) msm_gsbi1_qup_spi_device.dev.platform_data = &msm_gsbi1_qup_spi_pdata; #endif if (machine_is_msm8x60_fluid()) { #if (defined(CONFIG_USB_EHCI_MSM_72K) && \ (\ defined(CONFIG_SMB137B_CHARGER_MODULE))) msm_otg_pdata.vbus_power = msm_hsusb_smb137b_vbus_power; #endif #if defined(CONFIG_SPI_QUP) || defined(CONFIG_SPI_QUP_MODULE) msm_gsbi10_qup_spi_device.dev.platform_data = &msm_gsbi10_qup_spi_pdata; #endif } #if defined(CONFIG_USB_EHCI_HCD) /* * We can not put USB regulators (8058_l6 and 8058_l7) in LPM * when we depend on USB PHY for VBUS/ID notifications. VBUS * and ID notifications are available only on V2 surf and FFA * with a hardware workaround. */ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2 && (machine_is_msm8x60_surf() || (machine_is_msm8x60_ffa() && pmic_id_notif_supported))) msm_otg_pdata.phy_can_powercollapse = 1; msm_device_otg.dev.platform_data = &msm_otg_pdata; #endif #ifdef CONFIG_SERIAL_MSM_HS msm_uart_dm1_pdata.wakeup_irq = gpio_to_irq(54); /* GSBI6(2) */ msm_device_uart_dm1.dev.platform_data = &msm_uart_dm1_pdata; #endif #ifdef CONFIG_MSM_GSBI9_UART if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) { msm_device_uart_gsbi9 = msm_add_gsbi9_uart(); if (IS_ERR(msm_device_uart_gsbi9)) pr_err("%s(): Failed to create uart gsbi9 device\n", __func__); } #endif #ifdef CONFIG_MSM_BUS_SCALING /* RPM calls are only enabled on V2 */ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) { msm_bus_apps_fabric_pdata.rpm_enabled = 1; msm_bus_sys_fabric_pdata.rpm_enabled = 1; msm_bus_mm_fabric_pdata.rpm_enabled = 1; msm_bus_sys_fpb_pdata.rpm_enabled = 1; msm_bus_cpss_fpb_pdata.rpm_enabled = 1; } msm_bus_apps_fabric.dev.platform_data = &msm_bus_apps_fabric_pdata; msm_bus_sys_fabric.dev.platform_data = &msm_bus_sys_fabric_pdata; msm_bus_mm_fabric.dev.platform_data = &msm_bus_mm_fabric_pdata; msm_bus_sys_fpb.dev.platform_data = &msm_bus_sys_fpb_pdata; msm_bus_cpss_fpb.dev.platform_data = &msm_bus_cpss_fpb_pdata; #endif } static void __init msm8x60_map_io(void) { msm_shared_ram_phys = MSM_SHARED_RAM_PHYS; msm_map_msm8x60_io(); if (socinfo_init() < 0) pr_err("socinfo_init() failed!\n"); } /* * Most segments of the EBI2 bus are disabled by default. */ static void __init msm8x60_init_ebi2(void) { uint32_t ebi2_cfg; void *ebi2_cfg_ptr; struct clk *mem_clk = clk_get_sys("msm_ebi2", "mem_clk"); if (IS_ERR(mem_clk)) { pr_err("%s: clk_get_sys(%s,%s), failed", __func__, "msm_ebi2", "mem_clk"); return; } clk_prepare_enable(mem_clk); clk_put(mem_clk); ebi2_cfg_ptr = ioremap_nocache(0x1a100000, sizeof(uint32_t)); if (ebi2_cfg_ptr != 0) { ebi2_cfg = readl_relaxed(ebi2_cfg_ptr); if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() || machine_is_msm8x60_fluid() || machine_is_msm8x60_dragon()) ebi2_cfg |= (1 << 4) | (1 << 5); /* CS2, CS3 */ writel_relaxed(ebi2_cfg, ebi2_cfg_ptr); iounmap(ebi2_cfg_ptr); } if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() || machine_is_msm8x60_fluid() || machine_is_msm8x60_dragon()) { ebi2_cfg_ptr = ioremap_nocache(0x1a110000, SZ_4K); if (ebi2_cfg_ptr != 0) { /* EBI2_XMEM_CFG:PWRSAVE_MODE off */ writel_relaxed(0UL, ebi2_cfg_ptr); /* CS2: Delay 9 cycles (140ns@64MHz) between SMSC * LAN9221 Ethernet controller reads and writes. * The lowest 4 bits are the read delay, the next * 4 are the write delay. */ writel_relaxed(0x031F1C99, ebi2_cfg_ptr + 0x10); #if defined(CONFIG_USB_PEHCI_HCD) || defined(CONFIG_USB_PEHCI_HCD_MODULE) /* * RECOVERY=5, HOLD_WR=1 * INIT_LATENCY_WR=1, INIT_LATENCY_RD=1 * WAIT_WR=1, WAIT_RD=2 */ writel_relaxed(0x51010112, ebi2_cfg_ptr + 0x14); /* * HOLD_RD=1 * ADV_OE_RECOVERY=0, ADDR_HOLD_ENA=1 */ writel_relaxed(0x01000020, ebi2_cfg_ptr + 0x34); #else /* EBI2 CS3 muxed address/data, * two cyc addr enable */ writel_relaxed(0xA3030020, ebi2_cfg_ptr + 0x34); #endif iounmap(ebi2_cfg_ptr); } } } #if (defined(CONFIG_MMC_MSM_SDC1_SUPPORT)\ || defined(CONFIG_MMC_MSM_SDC2_SUPPORT)\ || defined(CONFIG_MMC_MSM_SDC3_SUPPORT)\ || defined(CONFIG_MMC_MSM_SDC4_SUPPORT)\ || defined(CONFIG_MMC_MSM_SDC5_SUPPORT)) /* 8x60 has 5 SDCC controllers */ #define MAX_SDCC_CONTROLLER 5 struct msm_sdcc_gpio { /* maximum 10 GPIOs per SDCC controller */ s16 no; /* name of this GPIO */ const char *name; bool always_on; bool is_enabled; }; #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT static struct msm_sdcc_gpio sdc1_gpio_cfg[] = { {159, "sdc1_dat_0"}, {160, "sdc1_dat_1"}, {161, "sdc1_dat_2"}, {162, "sdc1_dat_3"}, #ifdef CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT {163, "sdc1_dat_4"}, {164, "sdc1_dat_5"}, {165, "sdc1_dat_6"}, {166, "sdc1_dat_7"}, #endif {167, "sdc1_clk"}, {168, "sdc1_cmd"} }; #endif #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT static struct msm_sdcc_gpio sdc2_gpio_cfg[] = { {143, "sdc2_dat_0"}, {144, "sdc2_dat_1", 1}, {145, "sdc2_dat_2"}, {146, "sdc2_dat_3"}, #ifdef CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT {147, "sdc2_dat_4"}, {148, "sdc2_dat_5"}, {149, "sdc2_dat_6"}, {150, "sdc2_dat_7"}, #endif {151, "sdc2_cmd"}, {152, "sdc2_clk", 1} }; #endif #ifdef CONFIG_MMC_MSM_SDC5_SUPPORT static struct msm_sdcc_gpio sdc5_gpio_cfg[] = { {95, "sdc5_cmd"}, {96, "sdc5_dat_3"}, {97, "sdc5_clk", 1}, {98, "sdc5_dat_2"}, {99, "sdc5_dat_1", 1}, {100, "sdc5_dat_0"} }; #endif struct msm_sdcc_pad_pull_cfg { enum msm_tlmm_pull_tgt pull; u32 pull_val; }; struct msm_sdcc_pad_drv_cfg { enum msm_tlmm_hdrive_tgt drv; u32 drv_val; }; #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT static struct msm_sdcc_pad_drv_cfg sdc3_pad_on_drv_cfg[] = { {TLMM_HDRV_SDC3_CLK, GPIO_CFG_8MA}, {TLMM_HDRV_SDC3_CMD, GPIO_CFG_8MA}, {TLMM_HDRV_SDC3_DATA, GPIO_CFG_8MA} }; static struct msm_sdcc_pad_pull_cfg sdc3_pad_on_pull_cfg[] = { {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP}, {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP} }; static struct msm_sdcc_pad_drv_cfg sdc3_pad_off_drv_cfg[] = { {TLMM_HDRV_SDC3_CLK, GPIO_CFG_2MA}, {TLMM_HDRV_SDC3_CMD, GPIO_CFG_2MA}, {TLMM_HDRV_SDC3_DATA, GPIO_CFG_2MA} }; static struct msm_sdcc_pad_pull_cfg sdc3_pad_off_pull_cfg[] = { {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_DOWN}, {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_DOWN} }; #endif #ifdef CONFIG_MMC_MSM_SDC4_SUPPORT static struct msm_sdcc_pad_drv_cfg sdc4_pad_on_drv_cfg[] = { {TLMM_HDRV_SDC4_CLK, GPIO_CFG_8MA}, {TLMM_HDRV_SDC4_CMD, GPIO_CFG_8MA}, {TLMM_HDRV_SDC4_DATA, GPIO_CFG_8MA} }; static struct msm_sdcc_pad_pull_cfg sdc4_pad_on_pull_cfg[] = { {TLMM_PULL_SDC4_CMD, GPIO_CFG_PULL_UP}, {TLMM_PULL_SDC4_DATA, GPIO_CFG_PULL_UP} }; static struct msm_sdcc_pad_drv_cfg sdc4_pad_off_drv_cfg[] = { {TLMM_HDRV_SDC4_CLK, GPIO_CFG_2MA}, {TLMM_HDRV_SDC4_CMD, GPIO_CFG_2MA}, {TLMM_HDRV_SDC4_DATA, GPIO_CFG_2MA} }; static struct msm_sdcc_pad_pull_cfg sdc4_pad_off_pull_cfg[] = { {TLMM_PULL_SDC4_CMD, GPIO_CFG_PULL_DOWN}, {TLMM_PULL_SDC4_DATA, GPIO_CFG_PULL_DOWN} }; #endif struct msm_sdcc_pin_cfg { /* * = 1 if controller pins are using gpios * = 0 if controller has dedicated MSM pins */ u8 is_gpio; u8 cfg_sts; u8 gpio_data_size; struct msm_sdcc_gpio *gpio_data; struct msm_sdcc_pad_drv_cfg *pad_drv_on_data; struct msm_sdcc_pad_drv_cfg *pad_drv_off_data; struct msm_sdcc_pad_pull_cfg *pad_pull_on_data; struct msm_sdcc_pad_pull_cfg *pad_pull_off_data; u8 pad_drv_data_size; u8 pad_pull_data_size; u8 sdio_lpm_gpio_cfg; }; static struct msm_sdcc_pin_cfg sdcc_pin_cfg_data[MAX_SDCC_CONTROLLER] = { #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT [0] = { .is_gpio = 1, .gpio_data_size = ARRAY_SIZE(sdc1_gpio_cfg), .gpio_data = sdc1_gpio_cfg }, #endif #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT [1] = { .is_gpio = 1, .gpio_data_size = ARRAY_SIZE(sdc2_gpio_cfg), .gpio_data = sdc2_gpio_cfg }, #endif #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT [2] = { .is_gpio = 0, .pad_drv_on_data = sdc3_pad_on_drv_cfg, .pad_drv_off_data = sdc3_pad_off_drv_cfg, .pad_pull_on_data = sdc3_pad_on_pull_cfg, .pad_pull_off_data = sdc3_pad_off_pull_cfg, .pad_drv_data_size = ARRAY_SIZE(sdc3_pad_on_drv_cfg), .pad_pull_data_size = ARRAY_SIZE(sdc3_pad_on_pull_cfg) }, #endif #ifdef CONFIG_MMC_MSM_SDC4_SUPPORT [3] = { .is_gpio = 0, .pad_drv_on_data = sdc4_pad_on_drv_cfg, .pad_drv_off_data = sdc4_pad_off_drv_cfg, .pad_pull_on_data = sdc4_pad_on_pull_cfg, .pad_pull_off_data = sdc4_pad_off_pull_cfg, .pad_drv_data_size = ARRAY_SIZE(sdc4_pad_on_drv_cfg), .pad_pull_data_size = ARRAY_SIZE(sdc4_pad_on_pull_cfg) }, #endif #ifdef CONFIG_MMC_MSM_SDC5_SUPPORT [4] = { .is_gpio = 1, .gpio_data_size = ARRAY_SIZE(sdc5_gpio_cfg), .gpio_data = sdc5_gpio_cfg } #endif }; static int msm_sdcc_setup_gpio(int dev_id, unsigned int enable) { int rc = 0; struct msm_sdcc_pin_cfg *curr; int n; curr = &sdcc_pin_cfg_data[dev_id - 1]; if (!curr->gpio_data) goto out; for (n = 0; n < curr->gpio_data_size; n++) { if (enable) { if (curr->gpio_data[n].always_on && curr->gpio_data[n].is_enabled) continue; pr_debug("%s: enable: %s\n", __func__, curr->gpio_data[n].name); rc = gpio_request(curr->gpio_data[n].no, curr->gpio_data[n].name); if (rc) { pr_err("%s: gpio_request(%d, %s)" "failed", __func__, curr->gpio_data[n].no, curr->gpio_data[n].name); goto free_gpios; } /* set direction as output for all GPIOs */ rc = gpio_direction_output( curr->gpio_data[n].no, 1); if (rc) { pr_err("%s: gpio_direction_output" "(%d, 1) failed\n", __func__, curr->gpio_data[n].no); goto free_gpios; } curr->gpio_data[n].is_enabled = 1; } else { /* * now free this GPIO which will put GPIO * in low power mode and will also put GPIO * in input mode */ if (curr->gpio_data[n].always_on) continue; pr_debug("%s: disable: %s\n", __func__, curr->gpio_data[n].name); gpio_free(curr->gpio_data[n].no); curr->gpio_data[n].is_enabled = 0; } } curr->cfg_sts = enable; goto out; free_gpios: for (; n >= 0; n--) gpio_free(curr->gpio_data[n].no); out: return rc; } static int msm_sdcc_setup_pad(int dev_id, unsigned int enable) { int rc = 0; struct msm_sdcc_pin_cfg *curr; int n; curr = &sdcc_pin_cfg_data[dev_id - 1]; if (!curr->pad_drv_on_data || !curr->pad_pull_on_data) goto out; if (enable) { /* * set up the normal driver strength and * pull config for pads */ for (n = 0; n < curr->pad_drv_data_size; n++) { if (curr->sdio_lpm_gpio_cfg) { if (curr->pad_drv_on_data[n].drv == TLMM_HDRV_SDC4_DATA) continue; } msm_tlmm_set_hdrive(curr->pad_drv_on_data[n].drv, curr->pad_drv_on_data[n].drv_val); } for (n = 0; n < curr->pad_pull_data_size; n++) { if (curr->sdio_lpm_gpio_cfg) { if (curr->pad_pull_on_data[n].pull == TLMM_PULL_SDC4_DATA) continue; } msm_tlmm_set_pull(curr->pad_pull_on_data[n].pull, curr->pad_pull_on_data[n].pull_val); } } else { /* set the low power config for pads */ for (n = 0; n < curr->pad_drv_data_size; n++) { if (curr->sdio_lpm_gpio_cfg) { if (curr->pad_drv_off_data[n].drv == TLMM_HDRV_SDC4_DATA) continue; } msm_tlmm_set_hdrive( curr->pad_drv_off_data[n].drv, curr->pad_drv_off_data[n].drv_val); } for (n = 0; n < curr->pad_pull_data_size; n++) { if (curr->sdio_lpm_gpio_cfg) { if (curr->pad_pull_off_data[n].pull == TLMM_PULL_SDC4_DATA) continue; } msm_tlmm_set_pull( curr->pad_pull_off_data[n].pull, curr->pad_pull_off_data[n].pull_val); } } curr->cfg_sts = enable; out: return rc; } struct sdcc_reg { /* VDD/VCC/VCCQ regulator name on PMIC8058/PMIC8089*/ const char *reg_name; /* * is set voltage supported for this regulator? * 0 = not supported, 1 = supported */ unsigned char set_voltage_sup; /* voltage level to be set */ unsigned int level; /* VDD/VCC/VCCQ voltage regulator handle */ struct regulator *reg; /* is this regulator enabled? */ bool enabled; /* is this regulator needs to be always on? */ bool always_on; /* is operating power mode setting required for this regulator? */ bool op_pwr_mode_sup; /* Load values for low power and high power mode */ unsigned int lpm_uA; unsigned int hpm_uA; }; /* all SDCC controllers require VDD/VCC voltage */ static struct sdcc_reg sdcc_vdd_reg_data[MAX_SDCC_CONTROLLER]; /* only SDCC1 requires VCCQ voltage */ static struct sdcc_reg sdcc_vccq_reg_data[1]; /* all SDCC controllers may require voting for VDD PAD voltage */ static struct sdcc_reg sdcc_vddp_reg_data[MAX_SDCC_CONTROLLER]; struct sdcc_reg_data { struct sdcc_reg *vdd_data; /* keeps VDD/VCC regulator info */ struct sdcc_reg *vccq_data; /* keeps VCCQ regulator info */ struct sdcc_reg *vddp_data; /* keeps VDD Pad regulator info */ unsigned char sts; /* regulator enable/disable status */ }; /* msm8x60 has 5 SDCC controllers */ static struct sdcc_reg_data sdcc_vreg_data[MAX_SDCC_CONTROLLER]; static int msm_sdcc_vreg_init_reg(struct sdcc_reg *vreg) { int rc = 0; /* Get the regulator handle */ vreg->reg = regulator_get(NULL, vreg->reg_name); if (IS_ERR(vreg->reg)) { rc = PTR_ERR(vreg->reg); pr_err("%s: regulator_get(%s) failed. rc=%d\n", __func__, vreg->reg_name, rc); goto out; } /* Set the voltage level if required */ if (vreg->set_voltage_sup) { rc = regulator_set_voltage(vreg->reg, vreg->level, vreg->level); if (rc) { pr_err("%s: regulator_set_voltage(%s) failed rc=%d\n", __func__, vreg->reg_name, rc); goto vreg_put; } } goto out; vreg_put: regulator_put(vreg->reg); out: return rc; } static inline void msm_sdcc_vreg_deinit_reg(struct sdcc_reg *vreg) { regulator_put(vreg->reg); } /* this init function should be called only once for each SDCC */ static int msm_sdcc_vreg_init(int dev_id, unsigned char init) { int rc = 0; struct sdcc_reg *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg; struct sdcc_reg_data *curr; curr = &sdcc_vreg_data[dev_id - 1]; curr_vdd_reg = curr->vdd_data; curr_vccq_reg = curr->vccq_data; curr_vddp_reg = curr->vddp_data; if (init) { /* * get the regulator handle from voltage regulator framework * and then try to set the voltage level for the regulator */ if (curr_vdd_reg) { rc = msm_sdcc_vreg_init_reg(curr_vdd_reg); if (rc) goto out; } if (curr_vccq_reg) { rc = msm_sdcc_vreg_init_reg(curr_vccq_reg); if (rc) goto vdd_reg_deinit; } if (curr_vddp_reg) { rc = msm_sdcc_vreg_init_reg(curr_vddp_reg); if (rc) goto vccq_reg_deinit; } goto out; } else /* deregister with all regulators from regulator framework */ goto vddp_reg_deinit; vddp_reg_deinit: if (curr_vddp_reg) msm_sdcc_vreg_deinit_reg(curr_vddp_reg); vccq_reg_deinit: if (curr_vccq_reg) msm_sdcc_vreg_deinit_reg(curr_vccq_reg); vdd_reg_deinit: if (curr_vdd_reg) msm_sdcc_vreg_deinit_reg(curr_vdd_reg); out: return rc; } static int msm_sdcc_vreg_enable(struct sdcc_reg *vreg) { int rc; if (!vreg->enabled) { rc = regulator_enable(vreg->reg); if (rc) { pr_err("%s: regulator_enable(%s) failed. rc=%d\n", __func__, vreg->reg_name, rc); goto out; } vreg->enabled = 1; } /* Put always_on regulator in HPM (high power mode) */ if (vreg->always_on && vreg->op_pwr_mode_sup) { rc = regulator_set_optimum_mode(vreg->reg, vreg->hpm_uA); if (rc < 0) { pr_err("%s: reg=%s: HPM setting failed" " hpm_uA=%d, rc=%d\n", __func__, vreg->reg_name, vreg->hpm_uA, rc); goto vreg_disable; } rc = 0; } goto out; vreg_disable: regulator_disable(vreg->reg); vreg->enabled = 0; out: return rc; } static int msm_sdcc_vreg_disable(struct sdcc_reg *vreg) { int rc; /* Never disable always_on regulator */ if (!vreg->always_on) { rc = regulator_disable(vreg->reg); if (rc) { pr_err("%s: regulator_disable(%s) failed. rc=%d\n", __func__, vreg->reg_name, rc); goto out; } vreg->enabled = 0; } /* Put always_on regulator in LPM (low power mode) */ if (vreg->always_on && vreg->op_pwr_mode_sup) { rc = regulator_set_optimum_mode(vreg->reg, vreg->lpm_uA); if (rc < 0) { pr_err("%s: reg=%s: LPM setting failed" " lpm_uA=%d, rc=%d\n", __func__, vreg->reg_name, vreg->lpm_uA, rc); goto out; } rc = 0; } out: return rc; } static int msm_sdcc_setup_vreg(int dev_id, unsigned char enable) { int rc = 0; struct sdcc_reg *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg; struct sdcc_reg_data *curr; curr = &sdcc_vreg_data[dev_id - 1]; curr_vdd_reg = curr->vdd_data; curr_vccq_reg = curr->vccq_data; curr_vddp_reg = curr->vddp_data; /* check if regulators are initialized or not? */ if ((curr_vdd_reg && !curr_vdd_reg->reg) || (curr_vccq_reg && !curr_vccq_reg->reg) || (curr_vddp_reg && !curr_vddp_reg->reg)) { /* initialize voltage regulators required for this SDCC */ rc = msm_sdcc_vreg_init(dev_id, 1); if (rc) { pr_err("%s: regulator init failed = %d\n", __func__, rc); goto out; } } if (curr->sts == enable) goto out; if (curr_vdd_reg) { if (enable) rc = msm_sdcc_vreg_enable(curr_vdd_reg); else rc = msm_sdcc_vreg_disable(curr_vdd_reg); if (rc) goto out; } if (curr_vccq_reg) { if (enable) rc = msm_sdcc_vreg_enable(curr_vccq_reg); else rc = msm_sdcc_vreg_disable(curr_vccq_reg); if (rc) goto out; } if (curr_vddp_reg) { if (enable) rc = msm_sdcc_vreg_enable(curr_vddp_reg); else rc = msm_sdcc_vreg_disable(curr_vddp_reg); if (rc) goto out; } curr->sts = enable; out: return rc; } static u32 msm_sdcc_setup_power(struct device *dv, unsigned int vdd) { u32 rc_pin_cfg = 0; u32 rc_vreg_cfg = 0; u32 rc = 0; struct platform_device *pdev; struct msm_sdcc_pin_cfg *curr_pin_cfg; pdev = container_of(dv, struct platform_device, dev); /* setup gpio/pad */ curr_pin_cfg = &sdcc_pin_cfg_data[pdev->id - 1]; if (curr_pin_cfg->cfg_sts == !!vdd) goto setup_vreg; if (curr_pin_cfg->is_gpio) rc_pin_cfg = msm_sdcc_setup_gpio(pdev->id, !!vdd); else rc_pin_cfg = msm_sdcc_setup_pad(pdev->id, !!vdd); setup_vreg: /* setup voltage regulators */ rc_vreg_cfg = msm_sdcc_setup_vreg(pdev->id, !!vdd); if (rc_pin_cfg || rc_vreg_cfg) rc = rc_pin_cfg ? rc_pin_cfg : rc_vreg_cfg; return rc; } static void msm_sdcc_sdio_lpm_gpio(struct device *dv, unsigned int active) { struct msm_sdcc_pin_cfg *curr_pin_cfg; struct platform_device *pdev; pdev = container_of(dv, struct platform_device, dev); /* setup gpio/pad */ curr_pin_cfg = &sdcc_pin_cfg_data[pdev->id - 1]; if (curr_pin_cfg->cfg_sts == active) return; curr_pin_cfg->sdio_lpm_gpio_cfg = 1; if (curr_pin_cfg->is_gpio) msm_sdcc_setup_gpio(pdev->id, active); else msm_sdcc_setup_pad(pdev->id, active); curr_pin_cfg->sdio_lpm_gpio_cfg = 0; } static int msm_sdc3_get_wpswitch(struct device *dev) { struct platform_device *pdev; int status; pdev = container_of(dev, struct platform_device, dev); status = gpio_request(GPIO_SDC_WP, "SD_WP_Switch"); if (status) { pr_err("%s:Failed to request GPIO %d\n", __func__, GPIO_SDC_WP); } else { status = gpio_direction_input(GPIO_SDC_WP); if (!status) { status = gpio_get_value_cansleep(GPIO_SDC_WP); pr_info("%s: WP Status for Slot %d = %d\n", __func__, pdev->id, status); } gpio_free(GPIO_SDC_WP); } return status; } #ifdef CONFIG_MMC_MSM_SDC5_SUPPORT int sdc5_register_status_notify(void (*callback)(int, void *), void *dev_id) { sdc5_status_notify_cb = callback; sdc5_status_notify_cb_devid = dev_id; return 0; } #endif #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT int sdc2_register_status_notify(void (*callback)(int, void *), void *dev_id) { sdc2_status_notify_cb = callback; sdc2_status_notify_cb_devid = dev_id; return 0; } #endif /* Interrupt handler for SDC2 and SDC5 detection * This function uses dual-edge interrputs settings in order * to get SDIO detection when the GPIO is rising and SDIO removal * when the GPIO is falling */ static irqreturn_t msm8x60_multi_sdio_slot_status_irq(int irq, void *dev_id) { int status; if (!machine_is_msm8x60_fusion() && !machine_is_msm8x60_fusn_ffa()) return IRQ_NONE; status = gpio_get_value(MDM2AP_SYNC); pr_info("%s: MDM2AP_SYNC Status = %d\n", __func__, status); #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT if (sdc2_status_notify_cb) { pr_info("%s: calling sdc2_status_notify_cb\n", __func__); sdc2_status_notify_cb(status, sdc2_status_notify_cb_devid); } #endif #ifdef CONFIG_MMC_MSM_SDC5_SUPPORT if (sdc5_status_notify_cb) { pr_info("%s: calling sdc5_status_notify_cb\n", __func__); sdc5_status_notify_cb(status, sdc5_status_notify_cb_devid); } #endif return IRQ_HANDLED; } static int msm8x60_multi_sdio_init(void) { int ret, irq_num; if (!machine_is_msm8x60_fusion() && !machine_is_msm8x60_fusn_ffa()) return 0; ret = msm_gpiomux_get(MDM2AP_SYNC); if (ret) { pr_err("%s:Failed to request GPIO %d, ret=%d\n", __func__, MDM2AP_SYNC, ret); return ret; } irq_num = gpio_to_irq(MDM2AP_SYNC); ret = request_irq(irq_num, msm8x60_multi_sdio_slot_status_irq, IRQ_TYPE_EDGE_BOTH, "sdio_multidetection", NULL); if (ret) { pr_err("%s:Failed to request irq, ret=%d\n", __func__, ret); return ret; } return ret; } #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT static unsigned int msm8x60_sdcc_slot_status(struct device *dev) { int status; status = gpio_request(PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC3_DET - 1) , "SD_HW_Detect"); if (status) { pr_err("%s:Failed to request GPIO %d\n", __func__, PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC3_DET - 1)); } else { status = gpio_direction_input( PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC3_DET - 1)); if (!status) status = !(gpio_get_value_cansleep( PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC3_DET - 1))); gpio_free(PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC3_DET - 1)); } return (unsigned int) status; } #endif #endif #define MSM_MPM_PIN_SDC3_DAT1 21 #define MSM_MPM_PIN_SDC4_DAT1 23 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT static struct mmc_platform_data msm8x60_sdc1_data = { .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29, .translate_vdd = msm_sdcc_setup_power, #ifdef CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT .mmc_bus_width = MMC_CAP_8_BIT_DATA, #else .mmc_bus_width = MMC_CAP_4_BIT_DATA, #endif .msmsdcc_fmin = 400000, .msmsdcc_fmid = 24000000, .msmsdcc_fmax = 48000000, .nonremovable = 1, .msm_bus_voting_data = &sps_to_ddr_bus_voting_data, }; #endif #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT static struct mmc_platform_data msm8x60_sdc2_data = { .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_165_195, .translate_vdd = msm_sdcc_setup_power, .sdio_lpm_gpio_setup = msm_sdcc_sdio_lpm_gpio, .mmc_bus_width = MMC_CAP_8_BIT_DATA, .msmsdcc_fmin = 400000, .msmsdcc_fmid = 24000000, .msmsdcc_fmax = 48000000, .nonremovable = 0, .register_status_notify = sdc2_register_status_notify, .msm_bus_voting_data = &sps_to_ddr_bus_voting_data, }; #endif #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT static struct mmc_platform_data msm8x60_sdc3_data = { .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29, .translate_vdd = msm_sdcc_setup_power, .mmc_bus_width = MMC_CAP_4_BIT_DATA, .wpswitch = msm_sdc3_get_wpswitch, .status = msm8x60_sdcc_slot_status, .status_irq = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, PMIC_GPIO_SDC3_DET - 1), .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, .msmsdcc_fmin = 400000, .msmsdcc_fmid = 24000000, .msmsdcc_fmax = 48000000, .nonremovable = 0, .mpm_sdiowakeup_int = MSM_MPM_PIN_SDC3_DAT1, .msm_bus_voting_data = &sps_to_ddr_bus_voting_data, }; #endif #ifdef CONFIG_MMC_MSM_SDC4_SUPPORT static struct mmc_platform_data msm8x60_sdc4_data = { .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29, .translate_vdd = msm_sdcc_setup_power, .mmc_bus_width = MMC_CAP_4_BIT_DATA, .msmsdcc_fmin = 400000, .msmsdcc_fmid = 24000000, .msmsdcc_fmax = 48000000, .nonremovable = 0, .mpm_sdiowakeup_int = MSM_MPM_PIN_SDC4_DAT1, .msm_bus_voting_data = &sps_to_ddr_bus_voting_data, }; #endif #ifdef CONFIG_MMC_MSM_SDC5_SUPPORT static struct mmc_platform_data msm8x60_sdc5_data = { .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_165_195, .translate_vdd = msm_sdcc_setup_power, .sdio_lpm_gpio_setup = msm_sdcc_sdio_lpm_gpio, .mmc_bus_width = MMC_CAP_4_BIT_DATA, .msmsdcc_fmin = 400000, .msmsdcc_fmid = 24000000, .msmsdcc_fmax = 48000000, .nonremovable = 0, .register_status_notify = sdc5_register_status_notify, .msm_bus_voting_data = &sps_to_ddr_bus_voting_data, }; #endif static void __init msm8x60_init_mmc(void) { #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT /* SDCC1 : eMMC card connected */ sdcc_vreg_data[0].vdd_data = &sdcc_vdd_reg_data[0]; sdcc_vreg_data[0].vdd_data->reg_name = "8901_l5"; sdcc_vreg_data[0].vdd_data->set_voltage_sup = 1; sdcc_vreg_data[0].vdd_data->level = 2850000; sdcc_vreg_data[0].vdd_data->always_on = 1; sdcc_vreg_data[0].vdd_data->op_pwr_mode_sup = 1; sdcc_vreg_data[0].vdd_data->lpm_uA = 9000; sdcc_vreg_data[0].vdd_data->hpm_uA = 200000; sdcc_vreg_data[0].vccq_data = &sdcc_vccq_reg_data[0]; sdcc_vreg_data[0].vccq_data->reg_name = "8901_lvs0"; sdcc_vreg_data[0].vccq_data->set_voltage_sup = 0; sdcc_vreg_data[0].vccq_data->always_on = 1; msm_add_sdcc(1, &msm8x60_sdc1_data); #endif #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT /* * MDM SDIO client is connected to SDC2 on charm SURF/FFA * and no card is connected on 8660 SURF/FFA/FLUID. */ sdcc_vreg_data[1].vdd_data = &sdcc_vdd_reg_data[1]; sdcc_vreg_data[1].vdd_data->reg_name = "8058_s3"; sdcc_vreg_data[1].vdd_data->set_voltage_sup = 1; sdcc_vreg_data[1].vdd_data->level = 1800000; sdcc_vreg_data[1].vccq_data = NULL; if (machine_is_msm8x60_fusion()) msm8x60_sdc2_data.msmsdcc_fmax = 24000000; if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) { msm8x60_sdc2_data.sdiowakeup_irq = gpio_to_irq(144); msm_sdcc_setup_gpio(2, 1); msm_add_sdcc(2, &msm8x60_sdc2_data); } #endif #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT /* SDCC3 : External card slot connected */ sdcc_vreg_data[2].vdd_data = &sdcc_vdd_reg_data[2]; sdcc_vreg_data[2].vdd_data->reg_name = "8058_l14"; sdcc_vreg_data[2].vdd_data->set_voltage_sup = 1; sdcc_vreg_data[2].vdd_data->level = 2850000; sdcc_vreg_data[2].vdd_data->always_on = 1; sdcc_vreg_data[2].vdd_data->op_pwr_mode_sup = 1; sdcc_vreg_data[2].vdd_data->lpm_uA = 9000; sdcc_vreg_data[2].vdd_data->hpm_uA = 200000; sdcc_vreg_data[2].vccq_data = NULL; sdcc_vreg_data[2].vddp_data = &sdcc_vddp_reg_data[2]; sdcc_vreg_data[2].vddp_data->reg_name = "8058_l5"; sdcc_vreg_data[2].vddp_data->set_voltage_sup = 1; sdcc_vreg_data[2].vddp_data->level = 2850000; sdcc_vreg_data[2].vddp_data->always_on = 1; sdcc_vreg_data[2].vddp_data->op_pwr_mode_sup = 1; /* Sleep current required is ~300 uA. But min. RPM * vote can be in terms of mA (min. 1 mA). * So let's vote for 2 mA during sleep. */ sdcc_vreg_data[2].vddp_data->lpm_uA = 2000; /* Max. Active current required is 16 mA */ sdcc_vreg_data[2].vddp_data->hpm_uA = 16000; if (machine_is_msm8x60_fluid()) msm8x60_sdc3_data.wpswitch = NULL; msm_add_sdcc(3, &msm8x60_sdc3_data); #endif #ifdef CONFIG_MMC_MSM_SDC4_SUPPORT /* SDCC4 : WLAN WCN1314 chip is connected */ sdcc_vreg_data[3].vdd_data = &sdcc_vdd_reg_data[3]; sdcc_vreg_data[3].vdd_data->reg_name = "8058_s3"; sdcc_vreg_data[3].vdd_data->set_voltage_sup = 1; sdcc_vreg_data[3].vdd_data->level = 1800000; sdcc_vreg_data[3].vccq_data = NULL; msm_add_sdcc(4, &msm8x60_sdc4_data); #endif #ifdef CONFIG_MMC_MSM_SDC5_SUPPORT /* * MDM SDIO client is connected to SDC5 on charm SURF/FFA * and no card is connected on 8660 SURF/FFA/FLUID. */ sdcc_vreg_data[4].vdd_data = &sdcc_vdd_reg_data[4]; sdcc_vreg_data[4].vdd_data->reg_name = "8058_s3"; sdcc_vreg_data[4].vdd_data->set_voltage_sup = 1; sdcc_vreg_data[4].vdd_data->level = 1800000; sdcc_vreg_data[4].vccq_data = NULL; if (machine_is_msm8x60_fusion()) msm8x60_sdc5_data.msmsdcc_fmax = 24000000; if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) { msm8x60_sdc5_data.sdiowakeup_irq = gpio_to_irq(99); msm_sdcc_setup_gpio(5, 1); msm_add_sdcc(5, &msm8x60_sdc5_data); } #endif } #if !defined(CONFIG_GPIO_SX150X) && !defined(CONFIG_GPIO_SX150X_MODULE) static inline void display_common_power(int on) {} #else #define _GET_REGULATOR(var, name) do { \ if (var == NULL) { \ var = regulator_get(NULL, name); \ if (IS_ERR(var)) { \ pr_err("'%s' regulator not found, rc=%ld\n", \ name, PTR_ERR(var)); \ var = NULL; \ } \ } \ } while (0) static int dsub_regulator(int on) { static struct regulator *dsub_reg; static struct regulator *mpp0_reg; static int dsub_reg_enabled; int rc = 0; _GET_REGULATOR(dsub_reg, "8901_l3"); if (IS_ERR(dsub_reg)) { printk(KERN_ERR "%s: failed to get reg 8901_l3 err=%ld", __func__, PTR_ERR(dsub_reg)); return PTR_ERR(dsub_reg); } _GET_REGULATOR(mpp0_reg, "8901_mpp0"); if (IS_ERR(mpp0_reg)) { printk(KERN_ERR "%s: failed to get reg 8901_mpp0 err=%ld", __func__, PTR_ERR(mpp0_reg)); return PTR_ERR(mpp0_reg); } if (on && !dsub_reg_enabled) { rc = regulator_set_voltage(dsub_reg, 3300000, 3300000); if (rc) { printk(KERN_ERR "%s: failed to set reg 8901_l3 voltage" " err=%d", __func__, rc); goto dsub_regulator_err; } rc = regulator_enable(dsub_reg); if (rc) { printk(KERN_ERR "%s: failed to enable reg 8901_l3" " err=%d", __func__, rc); goto dsub_regulator_err; } rc = regulator_enable(mpp0_reg); if (rc) { printk(KERN_ERR "%s: failed to enable reg 8901_mpp0" " err=%d", __func__, rc); goto dsub_regulator_err; } dsub_reg_enabled = 1; } else if (!on && dsub_reg_enabled) { rc = regulator_disable(dsub_reg); if (rc) printk(KERN_WARNING "%s: failed to disable reg 8901_l3" " err=%d", __func__, rc); rc = regulator_disable(mpp0_reg); if (rc) printk(KERN_WARNING "%s: failed to disable reg " "8901_mpp0 err=%d", __func__, rc); dsub_reg_enabled = 0; } return rc; dsub_regulator_err: regulator_put(mpp0_reg); regulator_put(dsub_reg); return rc; } static int display_power_on; static void setup_display_power(void) { if (display_power_on) if (lcdc_vga_enabled) { dsub_regulator(1); gpio_set_value_cansleep(GPIO_LVDS_SHUTDOWN_N, 0); gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, 0); if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa()) gpio_set_value_cansleep(GPIO_DONGLE_PWR_EN, 1); } else { dsub_regulator(0); gpio_set_value_cansleep(GPIO_LVDS_SHUTDOWN_N, 1); gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, 1); if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa()) gpio_set_value_cansleep(GPIO_DONGLE_PWR_EN, 0); } else { dsub_regulator(0); if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa()) gpio_set_value_cansleep(GPIO_DONGLE_PWR_EN, 0); /* BACKLIGHT */ gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, 0); /* LVDS */ gpio_set_value_cansleep(GPIO_LVDS_SHUTDOWN_N, 0); } } #define _GET_REGULATOR(var, name) do { \ if (var == NULL) { \ var = regulator_get(NULL, name); \ if (IS_ERR(var)) { \ pr_err("'%s' regulator not found, rc=%ld\n", \ name, PTR_ERR(var)); \ var = NULL; \ } \ } \ } while (0) #define GPIO_RESX_N (GPIO_EXPANDER_GPIO_BASE + 2) static void display_common_power(int on) { int rc; static struct regulator *display_reg; if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() || machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) { if (on) { /* LVDS */ _GET_REGULATOR(display_reg, "8901_l2"); if (!display_reg) return; rc = regulator_set_voltage(display_reg, 3300000, 3300000); if (rc) goto out; rc = regulator_enable(display_reg); if (rc) goto out; rc = gpio_request(GPIO_LVDS_SHUTDOWN_N, "LVDS_STDN_OUT_N"); if (rc) { printk(KERN_ERR "%s: LVDS gpio %d request" "failed\n", __func__, GPIO_LVDS_SHUTDOWN_N); goto out2; } /* BACKLIGHT */ rc = gpio_request(GPIO_BACKLIGHT_EN, "BACKLIGHT_EN"); if (rc) { printk(KERN_ERR "%s: BACKLIGHT gpio %d request" "failed\n", __func__, GPIO_BACKLIGHT_EN); goto out3; } if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa()) { rc = gpio_request(GPIO_DONGLE_PWR_EN, "DONGLE_PWR_EN"); if (rc) { printk(KERN_ERR "%s: DONGLE_PWR_EN gpio" " %d request failed\n", __func__, GPIO_DONGLE_PWR_EN); goto out4; } } gpio_direction_output(GPIO_LVDS_SHUTDOWN_N, 0); gpio_direction_output(GPIO_BACKLIGHT_EN, 0); if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa()) gpio_direction_output(GPIO_DONGLE_PWR_EN, 0); mdelay(20); display_power_on = 1; setup_display_power(); } else { if (display_power_on) { display_power_on = 0; setup_display_power(); mdelay(20); if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa()) gpio_free(GPIO_DONGLE_PWR_EN); goto out4; } } } #if \ defined(CONFIG_FB_MSM_LCDC_AUO_WVGA) else if (machine_is_msm8x60_fluid()) { static struct regulator *fluid_reg; static struct regulator *fluid_reg2; if (on) { _GET_REGULATOR(fluid_reg, "8901_l2"); if (!fluid_reg) return; _GET_REGULATOR(fluid_reg2, "8058_s3"); if (!fluid_reg2) { regulator_put(fluid_reg); return; } rc = gpio_request(GPIO_RESX_N, "RESX_N"); if (rc) { regulator_put(fluid_reg2); regulator_put(fluid_reg); return; } regulator_set_voltage(fluid_reg, 2850000, 2850000); regulator_set_voltage(fluid_reg2, 1800000, 1800000); regulator_enable(fluid_reg); regulator_enable(fluid_reg2); msleep(20); gpio_direction_output(GPIO_RESX_N, 0); udelay(10); gpio_set_value_cansleep(GPIO_RESX_N, 1); display_power_on = 1; setup_display_power(); } else { gpio_set_value_cansleep(GPIO_RESX_N, 0); gpio_free(GPIO_RESX_N); msleep(20); regulator_disable(fluid_reg2); regulator_disable(fluid_reg); regulator_put(fluid_reg2); regulator_put(fluid_reg); display_power_on = 0; setup_display_power(); fluid_reg = NULL; fluid_reg2 = NULL; } } #endif return; out4: gpio_free(GPIO_BACKLIGHT_EN); out3: gpio_free(GPIO_LVDS_SHUTDOWN_N); out2: regulator_disable(display_reg); out: regulator_put(display_reg); display_reg = NULL; } #undef _GET_REGULATOR #endif static int mipi_dsi_panel_power(int on); #define LCDC_NUM_GPIO 28 #define LCDC_GPIO_START 0 static void lcdc_samsung_panel_power(int on) { int n, ret = 0; display_common_power(on); for (n = 0; n < LCDC_NUM_GPIO; n++) { if (on) { ret = gpio_request(LCDC_GPIO_START + n, "LCDC_GPIO"); if (unlikely(ret)) { pr_err("%s not able to get gpio\n", __func__); break; } } else gpio_free(LCDC_GPIO_START + n); } if (ret) { for (n--; n >= 0; n--) gpio_free(LCDC_GPIO_START + n); } mipi_dsi_panel_power(0); /* set 8058_ldo0 to LPM */ } static int lcdc_panel_power(int on) { int flag_on = !!on; static int lcdc_power_save_on; if (lcdc_power_save_on == flag_on) return 0; lcdc_power_save_on = flag_on; lcdc_samsung_panel_power(on); return 0; } #ifdef CONFIG_MSM_BUS_SCALING static struct msm_bus_vectors rotator_init_vectors[] = { { .src = MSM_BUS_MASTER_ROTATOR, .dst = MSM_BUS_SLAVE_SMI, .ab = 0, .ib = 0, }, { .src = MSM_BUS_MASTER_ROTATOR, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = 0, }, }; static struct msm_bus_vectors rotator_ui_vectors[] = { { .src = MSM_BUS_MASTER_ROTATOR, .dst = MSM_BUS_SLAVE_SMI, .ab = 0, .ib = 0, }, { .src = MSM_BUS_MASTER_ROTATOR, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = (1024 * 600 * 4 * 2 * 60), .ib = (1024 * 600 * 4 * 2 * 60 * 1.5), }, }; static struct msm_bus_vectors rotator_vga_vectors[] = { { .src = MSM_BUS_MASTER_ROTATOR, .dst = MSM_BUS_SLAVE_SMI, .ab = (640 * 480 * 2 * 2 * 30), .ib = (640 * 480 * 2 * 2 * 30 * 1.5), }, { .src = MSM_BUS_MASTER_ROTATOR, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = (640 * 480 * 2 * 2 * 30), .ib = (640 * 480 * 2 * 2 * 30 * 1.5), }, }; static struct msm_bus_vectors rotator_720p_vectors[] = { { .src = MSM_BUS_MASTER_ROTATOR, .dst = MSM_BUS_SLAVE_SMI, .ab = (1280 * 736 * 2 * 2 * 30), .ib = (1280 * 736 * 2 * 2 * 30 * 1.5), }, { .src = MSM_BUS_MASTER_ROTATOR, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = (1280 * 736 * 2 * 2 * 30), .ib = (1280 * 736 * 2 * 2 * 30 * 1.5), }, }; static struct msm_bus_vectors rotator_1080p_vectors[] = { { .src = MSM_BUS_MASTER_ROTATOR, .dst = MSM_BUS_SLAVE_SMI, .ab = (1920 * 1088 * 2 * 2 * 30), .ib = (1920 * 1088 * 2 * 2 * 30 * 1.5), }, { .src = MSM_BUS_MASTER_ROTATOR, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = (1920 * 1088 * 2 * 2 * 30), .ib = (1920 * 1088 * 2 * 2 * 30 * 1.5), }, }; static struct msm_bus_paths rotator_bus_scale_usecases[] = { { ARRAY_SIZE(rotator_init_vectors), rotator_init_vectors, }, { ARRAY_SIZE(rotator_ui_vectors), rotator_ui_vectors, }, { ARRAY_SIZE(rotator_vga_vectors), rotator_vga_vectors, }, { ARRAY_SIZE(rotator_720p_vectors), rotator_720p_vectors, }, { ARRAY_SIZE(rotator_1080p_vectors), rotator_1080p_vectors, }, }; struct msm_bus_scale_pdata rotator_bus_scale_pdata = { rotator_bus_scale_usecases, ARRAY_SIZE(rotator_bus_scale_usecases), .name = "rotator", }; static struct msm_bus_vectors mdp_init_vectors[] = { /* For now, 0th array entry is reserved. * Please leave 0 as is and don't use it */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 0, .ib = 0, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = 0, }, }; #ifdef CONFIG_FB_MSM_LCDC_DSUB static struct msm_bus_vectors mdp_sd_smi_vectors[] = { /* Default case static display/UI/2d/3d if FB SMI */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 388800000, .ib = 486000000, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = 0, }, }; static struct msm_bus_vectors mdp_sd_ebi_vectors[] = { /* Default case static display/UI/2d/3d if FB SMI */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 0, .ib = 0, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 388800000, .ib = 486000000 * 2, }, }; static struct msm_bus_vectors mdp_vga_vectors[] = { /* VGA and less video */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 458092800, .ib = 572616000, }, { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 458092800, .ib = 572616000 * 2, }, }; static struct msm_bus_vectors mdp_720p_vectors[] = { /* 720p and less video */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 471744000, .ib = 589680000, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 471744000, .ib = 589680000 * 2, }, }; static struct msm_bus_vectors mdp_1080p_vectors[] = { /* 1080p and less video */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 575424000, .ib = 719280000, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 575424000, .ib = 719280000 * 2, }, }; #else static struct msm_bus_vectors mdp_sd_smi_vectors[] = { /* Default case static display/UI/2d/3d if FB SMI */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 175110000, .ib = 218887500, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = 0, }, }; static struct msm_bus_vectors mdp_sd_ebi_vectors[] = { /* Default case static display/UI/2d/3d if FB SMI */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 0, .ib = 0, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 216000000, .ib = 270000000 * 2, }, }; static struct msm_bus_vectors mdp_vga_vectors[] = { /* VGA and less video */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 216000000, .ib = 270000000, }, { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 216000000, .ib = 270000000 * 2, }, }; static struct msm_bus_vectors mdp_720p_vectors[] = { /* 720p and less video */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 230400000, .ib = 288000000, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 230400000, .ib = 288000000 * 2, }, }; static struct msm_bus_vectors mdp_1080p_vectors[] = { /* 1080p and less video */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 334080000, .ib = 417600000, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 334080000, .ib = 550000000 * 2, }, }; #endif static struct msm_bus_paths mdp_bus_scale_usecases[] = { { ARRAY_SIZE(mdp_init_vectors), mdp_init_vectors, }, { ARRAY_SIZE(mdp_sd_smi_vectors), mdp_sd_smi_vectors, }, { ARRAY_SIZE(mdp_sd_ebi_vectors), mdp_sd_ebi_vectors, }, { ARRAY_SIZE(mdp_vga_vectors), mdp_vga_vectors, }, { ARRAY_SIZE(mdp_720p_vectors), mdp_720p_vectors, }, { ARRAY_SIZE(mdp_1080p_vectors), mdp_1080p_vectors, }, }; static struct msm_bus_scale_pdata mdp_bus_scale_pdata = { mdp_bus_scale_usecases, ARRAY_SIZE(mdp_bus_scale_usecases), .name = "mdp", }; #endif #ifdef CONFIG_MSM_BUS_SCALING static struct msm_bus_vectors dtv_bus_init_vectors[] = { /* For now, 0th array entry is reserved. * Please leave 0 as is and don't use it */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 0, .ib = 0, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, .ib = 0, }, }; static struct msm_bus_vectors dtv_bus_def_vectors[] = { /* For now, 0th array entry is reserved. * Please leave 0 as is and don't use it */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 566092800, .ib = 707616000, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 566092800, .ib = 707616000, }, }; static struct msm_bus_vectors dtv_bus_hdmi_prim_vectors[] = { /* For now, 0th array entry is reserved. * Please leave 0 as is and don't use it */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_SMI, .ab = 2000000000, .ib = 2000000000, }, /* Master and slaves can be from different fabrics */ { .src = MSM_BUS_MASTER_MDP_PORT0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 2000000000, .ib = 2000000000, }, }; static struct msm_bus_paths dtv_bus_scale_usecases[] = { { ARRAY_SIZE(dtv_bus_init_vectors), dtv_bus_init_vectors, }, { ARRAY_SIZE(dtv_bus_def_vectors), dtv_bus_def_vectors, }, }; static struct msm_bus_scale_pdata dtv_bus_scale_pdata = { dtv_bus_scale_usecases, ARRAY_SIZE(dtv_bus_scale_usecases), .name = "dtv", }; static struct lcdc_platform_data dtv_pdata = { .bus_scale_table = &dtv_bus_scale_pdata, .lcdc_power_save = hdmi_panel_power, }; static struct msm_bus_paths dtv_hdmi_prim_bus_scale_usecases[] = { { ARRAY_SIZE(dtv_bus_init_vectors), dtv_bus_init_vectors, }, { ARRAY_SIZE(dtv_bus_hdmi_prim_vectors), dtv_bus_hdmi_prim_vectors, }, }; static struct msm_bus_scale_pdata dtv_hdmi_prim_bus_scale_pdata = { dtv_hdmi_prim_bus_scale_usecases, ARRAY_SIZE(dtv_hdmi_prim_bus_scale_usecases), .name = "dtv", }; static struct lcdc_platform_data dtv_hdmi_prim_pdata = { .bus_scale_table = &dtv_hdmi_prim_bus_scale_pdata, }; #endif static struct lcdc_platform_data lcdc_pdata = { .lcdc_power_save = lcdc_panel_power, }; #define MDP_VSYNC_GPIO 28 /* * MIPI_DSI only use 8058_LDO0 which need always on * therefore it need to be put at low power mode if * it was not used instead of turn it off. */ static int mipi_dsi_panel_power(int on) { int flag_on = !!on; static int mipi_dsi_power_save_on; static struct regulator *ldo0; int rc = 0; if (mipi_dsi_power_save_on == flag_on) return 0; mipi_dsi_power_save_on = flag_on; if (ldo0 == NULL) { /* init */ ldo0 = regulator_get(NULL, "8058_l0"); if (IS_ERR(ldo0)) { pr_debug("%s: LDO0 failed\n", __func__); rc = PTR_ERR(ldo0); return rc; } rc = regulator_set_voltage(ldo0, 1200000, 1200000); if (rc) goto out; rc = regulator_enable(ldo0); if (rc) goto out; } if (on) { /* set ldo0 to HPM */ rc = regulator_set_optimum_mode(ldo0, 100000); if (rc < 0) goto out; } else { /* set ldo0 to LPM */ rc = regulator_set_optimum_mode(ldo0, 1000); if (rc < 0) goto out; } return 0; out: regulator_disable(ldo0); regulator_put(ldo0); ldo0 = NULL; return rc; } static struct mipi_dsi_platform_data mipi_dsi_pdata = { .vsync_gpio = MDP_VSYNC_GPIO, .dsi_power_save = mipi_dsi_panel_power, }; static struct msm_panel_common_pdata mdp_pdata = { .gpio = MDP_VSYNC_GPIO, .mdp_max_clk = 200000000, #ifdef CONFIG_MSM_BUS_SCALING .mdp_bus_scale_table = &mdp_bus_scale_pdata, #endif .mdp_rev = MDP_REV_41, #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION .mem_hid = BIT(ION_CP_WB_HEAP_ID), #else .mem_hid = MEMTYPE_EBI1, #endif .mdp_iommu_split_domain = 0, }; static void __init reserve_mdp_memory(void) { mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE; mdp_pdata.ov1_wb_size = MSM_FB_OVERLAY1_WRITEBACK_SIZE; } static void __init msm_fb_add_devices(void) { #ifdef CONFIG_FB_MSM_LCDC_DSUB mdp_pdata.mdp_max_clk = 200000000; #endif msm_fb_register_device("mdp", &mdp_pdata); msm_fb_register_device("lcdc", &lcdc_pdata); msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata); #ifdef CONFIG_MSM_BUS_SCALING if (hdmi_is_primary) msm_fb_register_device("dtv", &dtv_hdmi_prim_pdata); else msm_fb_register_device("dtv", &dtv_pdata); #endif } /** * Set MDP clocks to high frequency to avoid underflow when * using high resolution 1200x1920 WUXGA/HDMI as primary panels */ static void set_mdp_clocks_for_wuxga(void) { mdp_sd_smi_vectors[0].ab = 2000000000; mdp_sd_smi_vectors[0].ib = 2000000000; mdp_sd_smi_vectors[1].ab = 2000000000; mdp_sd_smi_vectors[1].ib = 2000000000; mdp_sd_ebi_vectors[0].ab = 2000000000; mdp_sd_ebi_vectors[0].ib = 2000000000; mdp_sd_ebi_vectors[1].ab = 2000000000; mdp_sd_ebi_vectors[1].ib = 2000000000; mdp_vga_vectors[0].ab = 2000000000; mdp_vga_vectors[0].ib = 2000000000; mdp_vga_vectors[1].ab = 2000000000; mdp_vga_vectors[1].ib = 2000000000; mdp_720p_vectors[0].ab = 2000000000; mdp_720p_vectors[0].ib = 2000000000; mdp_720p_vectors[1].ab = 2000000000; mdp_720p_vectors[1].ib = 2000000000; mdp_1080p_vectors[0].ab = 2000000000; mdp_1080p_vectors[0].ib = 2000000000; mdp_1080p_vectors[1].ab = 2000000000; mdp_1080p_vectors[1].ib = 2000000000; mdp_pdata.mdp_max_clk = 200000000; } static void __init msm8x60_cfg_smsc911x(void) { smsc911x_resources[1].start = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, 6); smsc911x_resources[1].end = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, 6); } void msm_fusion_setup_pinctrl(void) { struct msm_xo_voter *a1; if (socinfo_get_platform_subtype() == 0x3) { /* * Vote for the A1 clock to be in pin control mode before * the external images are loaded. */ a1 = msm_xo_get(MSM_XO_TCXO_A1, "mdm"); BUG_ON(!a1); msm_xo_mode_vote(a1, MSM_XO_MODE_PIN_CTRL); } } struct msm_board_data { struct msm_gpiomux_configs *gpiomux_cfgs; }; static struct msm_board_data msm8x60_surf_board_data __initdata = { .gpiomux_cfgs = msm8x60_surf_ffa_gpiomux_cfgs, }; static struct msm_board_data msm8x60_ffa_board_data __initdata = { .gpiomux_cfgs = msm8x60_surf_ffa_gpiomux_cfgs, }; static struct msm_board_data msm8x60_fluid_board_data __initdata = { .gpiomux_cfgs = msm8x60_fluid_gpiomux_cfgs, }; static struct msm_board_data msm8x60_charm_surf_board_data __initdata = { .gpiomux_cfgs = msm8x60_charm_gpiomux_cfgs, }; static struct msm_board_data msm8x60_charm_ffa_board_data __initdata = { .gpiomux_cfgs = msm8x60_charm_gpiomux_cfgs, }; static struct msm_board_data msm8x60_dragon_board_data __initdata = { .gpiomux_cfgs = msm8x60_dragon_gpiomux_cfgs, }; static void __init msm8x60_init(struct msm_board_data *board_data) { uint32_t soc_platform_version; #ifdef CONFIG_USB_EHCI_MSM_72K struct pm8xxx_mpp_config_data hsusb_phy_mpp = { .type = PM8XXX_MPP_TYPE_D_OUTPUT, .level = PM8901_MPP_DIG_LEVEL_L5, .control = PM8XXX_MPP_DOUT_CTRL_HIGH, }; #endif pmic_reset_irq = PM8058_IRQ_BASE + PM8058_RESOUT_IRQ; platform_device_register(&msm_gpio_device); /* * Initialize RPM first as other drivers and devices may need * it for their initialization. */ BUG_ON(msm_rpm_init(&msm8660_rpm_data)); BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data)); if (msm_xo_init()) pr_err("Failed to initialize XO votes\n"); msm8x60_check_2d_hardware(); /* Change SPM handling of core 1 if PMM 8160 is present. */ soc_platform_version = socinfo_get_platform_version(); if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1 && SOCINFO_VERSION_MINOR(soc_platform_version) >= 2) { struct msm_spm_platform_data *spm_data; spm_data = &msm_spm_data_v1[1]; spm_data->reg_init_values[MSM_SPM_REG_SAW_CFG] &= ~0x0F00UL; spm_data->reg_init_values[MSM_SPM_REG_SAW_CFG] |= 0x0100UL; spm_data = &msm_spm_data[1]; spm_data->reg_init_values[MSM_SPM_REG_SAW_CFG] &= ~0x0F00UL; spm_data->reg_init_values[MSM_SPM_REG_SAW_CFG] |= 0x0100UL; } /* * Initialize SPM before acpuclock as the latter calls into SPM * driver to set ACPU voltages. */ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 1) msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data)); else msm_spm_init(msm_spm_data_v1, ARRAY_SIZE(msm_spm_data_v1)); /* * Set regulators 8901_l4 and 8901_l6 to be always on in HPM for SURF * devices so that the RPM doesn't drop into a low power mode that an * un-reworked SURF cannot resume from. */ if (machine_is_msm8x60_surf()) { int i; for (i = 0; i < ARRAY_SIZE(rpm_regulator_init_data); i++) if (rpm_regulator_init_data[i].id == RPM_VREG_ID_PM8901_L4 || rpm_regulator_init_data[i].id == RPM_VREG_ID_PM8901_L6) rpm_regulator_init_data[i] .init_data.constraints.always_on = 1; } /* * Disable regulator info printing so that regulator registration * messages do not enter the kmsg log. */ regulator_suppress_info_printing(); /* Initialize regulators needed for clock_init. */ platform_add_devices(early_regulators, ARRAY_SIZE(early_regulators)); msm_clock_init(&msm8x60_clock_init_data); /* Buses need to be initialized before early-device registration * to get the platform data for fabrics. */ msm8x60_init_buses(); platform_add_devices(early_devices, ARRAY_SIZE(early_devices)); /* * Enable EBI2 only for boards which make use of it. Leave * it disabled for all others for additional power savings. */ if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() || machine_is_msm8x60_fluid() || machine_is_msm8x60_dragon()) msm8x60_init_ebi2(); msm8x60_init_gpiomux(board_data->gpiomux_cfgs); msm8x60_init_uart12dm(); msm8x60_init_mmc(); #if defined(CONFIG_PMIC8058_OTHC_MODULE) msm8x60_init_pm8058_othc(); #endif if (machine_is_msm8x60_fluid()) pm8058_platform_data.keypad_pdata = &fluid_keypad_data; else if (machine_is_msm8x60_dragon()) pm8058_platform_data.keypad_pdata = &dragon_keypad_data; else pm8058_platform_data.keypad_pdata = &ffa_keypad_data; if (machine_is_msm8x60_dragon()) pm8058_platform_data.charger_pdata = &pmic8058_charger_dragon; if (!machine_is_msm8x60_fluid()) pm8058_platform_data.charger_pdata = &pmic8058_charger_ffa_surf; /* configure pmic leds */ if (machine_is_msm8x60_fluid()) pm8058_platform_data.leds_pdata = &pm8058_fluid_flash_leds_data; else if (machine_is_msm8x60_dragon()) pm8058_platform_data.leds_pdata = &pm8058_dragon_leds_data; else pm8058_platform_data.leds_pdata = &pm8058_flash_leds_data; if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa() || machine_is_msm8x60_dragon()) { pm8058_platform_data.vibrator_pdata = &pm8058_vib_pdata; } if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() || machine_is_msm8x60_fluid() || machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa() || machine_is_msm8x60_dragon()) { msm8x60_cfg_smsc911x(); if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 1) platform_add_devices(msm8660_footswitch, msm8660_num_footswitch); platform_add_devices(surf_devices, ARRAY_SIZE(surf_devices)); pm8901_vreg_mpp0_init(); platform_device_register(&msm8x60_8901_mpp_vreg); #ifdef CONFIG_USB_EHCI_MSM_72K /* * Drive MPP2 pin HIGH for PHY to generate ID interrupts on 8660 * fluid */ if (machine_is_msm8x60_fluid()) pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1), &hsusb_phy_mpp); msm_add_host(0, &msm_usb_host_pdata); #endif #ifdef CONFIG_SND_SOC_MSM8660_APQ if (machine_is_msm8x60_dragon()) platform_add_devices(dragon_alsa_devices, ARRAY_SIZE(dragon_alsa_devices)); else #endif platform_add_devices(asoc_devices, ARRAY_SIZE(asoc_devices)); } #if defined(CONFIG_USB_PEHCI_HCD) || defined(CONFIG_USB_PEHCI_HCD_MODULE) if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() || machine_is_msm8x60_dragon()) msm8x60_cfg_isp1763(); #endif if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) platform_add_devices(charm_devices, ARRAY_SIZE(charm_devices)); #if defined(CONFIG_SPI_QUP) || defined(CONFIG_SPI_QUP_MODULE) if (machine_is_msm8x60_fluid()) platform_device_register(&msm_gsbi10_qup_spi_device); else platform_device_register(&msm_gsbi1_qup_spi_device); #endif #if \ defined(CONFIG_TOUCHSCREEN_CYTTSP_I2C_QC_MODULE) if (machine_is_msm8x60_fluid()) cyttsp_set_params(); #endif msm_fb_add_devices(); fixup_i2c_configs(); register_i2c_devices(); if (machine_is_msm8x60_dragon()) smsc911x_config.reset_gpio = GPIO_ETHERNET_RESET_N_DRAGON; platform_device_register(&smsc911x_device); #if (defined(CONFIG_SPI_QUP)) && \ (\ \ defined(CONFIG_FB_MSM_LCDC_NT35582_WVGA)) if (machine_is_msm8x60_fluid()) { { } } #endif BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata)); pm8058_gpios_init(); #ifdef CONFIG_MSM8X60_AUDIO msm_snddev_init(); #endif #if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE) if (machine_is_msm8x60_fluid()) platform_device_register(&fluid_leds_gpio); else platform_device_register(&gpio_leds); #endif msm8x60_multi_sdio_init(); if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) msm_fusion_setup_pinctrl(); } static void __init msm8x60_surf_init(void) { msm8x60_init(&msm8x60_surf_board_data); } static void __init msm8x60_ffa_init(void) { msm8x60_init(&msm8x60_ffa_board_data); } static void __init msm8x60_fluid_init(void) { msm8x60_init(&msm8x60_fluid_board_data); } static void __init msm8x60_charm_surf_init(void) { msm8x60_init(&msm8x60_charm_surf_board_data); } static void __init msm8x60_charm_ffa_init(void) { msm8x60_init(&msm8x60_charm_ffa_board_data); } static void __init msm8x60_charm_init_early(void) { msm8x60_allocate_memory_regions(); } static void __init msm8x60_dragon_init(void) { msm8x60_init(&msm8x60_dragon_board_data); } MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF") .map_io = msm8x60_map_io, .reserve = msm8x60_reserve, .init_irq = msm8x60_init_irq, .handle_irq = gic_handle_irq, .init_machine = msm8x60_surf_init, .timer = &msm_timer, .init_early = msm8x60_charm_init_early, .restart = msm_restart, MACHINE_END MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA") .map_io = msm8x60_map_io, .reserve = msm8x60_reserve, .init_irq = msm8x60_init_irq, .handle_irq = gic_handle_irq, .init_machine = msm8x60_ffa_init, .timer = &msm_timer, .init_early = msm8x60_charm_init_early, .restart = msm_restart, MACHINE_END MACHINE_START(MSM8X60_FLUID, "QCT MSM8X60 FLUID") .map_io = msm8x60_map_io, .reserve = msm8x60_reserve, .init_irq = msm8x60_init_irq, .handle_irq = gic_handle_irq, .init_machine = msm8x60_fluid_init, .timer = &msm_timer, .init_early = msm8x60_charm_init_early, .restart = msm_restart, MACHINE_END MACHINE_START(MSM8X60_FUSION, "QCT MSM8X60 FUSION SURF") .map_io = msm8x60_map_io, .reserve = msm8x60_reserve, .init_irq = msm8x60_init_irq, .handle_irq = gic_handle_irq, .init_machine = msm8x60_charm_surf_init, .timer = &msm_timer, .init_early = msm8x60_charm_init_early, .restart = msm_restart, MACHINE_END MACHINE_START(MSM8X60_FUSN_FFA, "QCT MSM8X60 FUSION FFA") .map_io = msm8x60_map_io, .reserve = msm8x60_reserve, .init_irq = msm8x60_init_irq, .handle_irq = gic_handle_irq, .init_machine = msm8x60_charm_ffa_init, .timer = &msm_timer, .init_early = msm8x60_charm_init_early, .restart = msm_restart, MACHINE_END MACHINE_START(MSM8X60_DRAGON, "QCT MSM8X60 DRAGON") .map_io = msm8x60_map_io, .reserve = msm8x60_reserve, .init_irq = msm8x60_init_irq, .handle_irq = gic_handle_irq, .init_machine = msm8x60_dragon_init, .timer = &msm_timer, .init_early = msm8x60_charm_init_early, .restart = msm_restart, MACHINE_END