123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- /* Copyright (c) 2011-2012, 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 <linux/init.h>
- #include <linux/ioport.h>
- #include <linux/platform_device.h>
- #include <linux/bootmem.h>
- #include <linux/gpio.h>
- #include <asm/mach-types.h>
- #include <asm/mach/mmc.h>
- #include <mach/board.h>
- #include <mach/gpiomux.h>
- #include "devices.h"
- #include "board-8960.h"
- #include "board-storage-common-a.h"
- /* MSM8960 has 5 SDCC controllers */
- enum sdcc_controllers {
- SDCC1,
- SDCC2,
- SDCC3,
- SDCC4,
- SDCC5,
- MAX_SDCC_CONTROLLER
- };
- /* All SDCC controllers require VDD/VCC voltage */
- static struct msm_mmc_reg_data mmc_vdd_reg_data[MAX_SDCC_CONTROLLER] = {
- /* SDCC1 : eMMC card connected */
- [SDCC1] = {
- .name = "sdc_vdd",
- .high_vol_level = 2950000,
- .low_vol_level = 2950000,
- .always_on = 1,
- .lpm_sup = 1,
- .lpm_uA = 9000,
- .hpm_uA = 200000, /* 200mA */
- },
- /* SDCC2 : SDIO slot connected */
- [SDCC2] = {
- .name = "sdc_vdd",
- .high_vol_level = 1800000,
- .low_vol_level = 1800000,
- .always_on = 1,
- .lpm_sup = 1,
- .lpm_uA = 9000,
- .hpm_uA = 200000, /* 200mA */
- },
- /* SDCC3 : External card slot connected */
- [SDCC3] = {
- .name = "sdc_vdd",
- .high_vol_level = 2950000,
- .low_vol_level = 2950000,
- .hpm_uA = 600000, /* 600mA */
- }
- };
- /* SDCC controllers may require voting for IO operating voltage */
- static struct msm_mmc_reg_data mmc_vdd_io_reg_data[MAX_SDCC_CONTROLLER] = {
- /* SDCC1 : eMMC card connected */
- [SDCC1] = {
- .name = "sdc_vdd_io",
- .always_on = 1,
- .high_vol_level = 1800000,
- .low_vol_level = 1800000,
- .hpm_uA = 200000, /* 200mA */
- },
- /* SDCC3 : External card slot connected */
- [SDCC3] = {
- .name = "sdc_vdd_io",
- .high_vol_level = 2950000,
- .low_vol_level = 1850000,
- .always_on = 1,
- .lpm_sup = 1,
- /* Max. Active current required is 16 mA */
- .hpm_uA = 16000,
- /*
- * Sleep current required is ~300 uA. But min. vote can be
- * in terms of mA (min. 1 mA). So let's vote for 2 mA
- * during sleep.
- */
- .lpm_uA = 2000,
- },
- /* SDCC4 : SDIO slot connected */
- [SDCC4] = {
- .name = "sdc_vdd_io",
- .high_vol_level = 1800000,
- .low_vol_level = 1800000,
- .always_on = 1,
- .lpm_sup = 1,
- .hpm_uA = 200000, /* 200mA */
- .lpm_uA = 2000,
- },
- };
- static struct msm_mmc_slot_reg_data mmc_slot_vreg_data[MAX_SDCC_CONTROLLER] = {
- /* SDCC1 : eMMC card connected */
- [SDCC1] = {
- .vdd_data = &mmc_vdd_reg_data[SDCC1],
- .vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
- },
- /* SDCC2 : SDIO card slot connected */
- [SDCC2] = {
- .vdd_data = &mmc_vdd_reg_data[SDCC2],
- },
- /* SDCC3 : External card slot connected */
- [SDCC3] = {
- .vdd_data = &mmc_vdd_reg_data[SDCC3],
- .vdd_io_data = &mmc_vdd_io_reg_data[SDCC3],
- },
- /* SDCC4 : SDIO card slot connected */
- [SDCC4] = {
- .vdd_io_data = &mmc_vdd_io_reg_data[SDCC4],
- },
- };
- /* SDC1 pad data */
- static struct msm_mmc_pad_drv sdc1_pad_drv_on_cfg[] = {
- {TLMM_HDRV_SDC1_CLK, GPIO_CFG_16MA},
- {TLMM_HDRV_SDC1_CMD, GPIO_CFG_10MA},
- {TLMM_HDRV_SDC1_DATA, GPIO_CFG_10MA}
- };
- static struct msm_mmc_pad_drv sdc1_pad_drv_off_cfg[] = {
- {TLMM_HDRV_SDC1_CLK, GPIO_CFG_2MA},
- {TLMM_HDRV_SDC1_CMD, GPIO_CFG_2MA},
- {TLMM_HDRV_SDC1_DATA, GPIO_CFG_2MA}
- };
- static struct msm_mmc_pad_pull sdc1_pad_pull_on_cfg[] = {
- {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
- {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
- };
- static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
- {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
- {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
- };
- /* SDC3 pad data */
- static struct msm_mmc_pad_drv sdc3_pad_drv_on_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_mmc_pad_drv sdc3_pad_drv_off_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_mmc_pad_pull sdc3_pad_pull_on_cfg[] = {
- {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
- {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
- };
- static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
- {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
- /*
- * SDC3 CMD line should be PULLed UP otherwise fluid platform will
- * see transitions (1 -> 0 and 0 -> 1) on card detection line,
- * which would result in false card detection interrupts.
- */
- {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
- /*
- * Keeping DATA lines status to PULL UP will make sure that
- * there is no current leak during sleep if external pull up
- * is connected to DATA lines.
- */
- {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
- };
- static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .on = sdc1_pad_pull_on_cfg,
- .off = sdc1_pad_pull_off_cfg,
- .size = ARRAY_SIZE(sdc1_pad_pull_on_cfg)
- },
- [SDCC3] = {
- .on = sdc3_pad_pull_on_cfg,
- .off = sdc3_pad_pull_off_cfg,
- .size = ARRAY_SIZE(sdc3_pad_pull_on_cfg)
- },
- };
- static struct msm_mmc_pad_drv_data mmc_pad_drv_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .on = sdc1_pad_drv_on_cfg,
- .off = sdc1_pad_drv_off_cfg,
- .size = ARRAY_SIZE(sdc1_pad_drv_on_cfg)
- },
- [SDCC3] = {
- .on = sdc3_pad_drv_on_cfg,
- .off = sdc3_pad_drv_off_cfg,
- .size = ARRAY_SIZE(sdc3_pad_drv_on_cfg)
- },
- };
- struct msm_mmc_gpio sdc2_gpio[] = {
- {92, "sdc2_dat_3"},
- {91, "sdc2_dat_2"},
- {90, "sdc2_dat_1"},
- {89, "sdc2_dat_0"},
- {97, "sdc2_cmd"},
- {98, "sdc2_clk"}
- };
- struct msm_mmc_gpio sdc4_gpio[] = {
- {83, "sdc4_dat_3"},
- {84, "sdc4_dat_2"},
- {85, "sdc4_dat_1"},
- {86, "sdc4_dat_0"},
- {87, "sdc4_cmd"},
- {88, "sdc4_clk"}
- };
- struct msm_mmc_gpio_data mmc_gpio_data[MAX_SDCC_CONTROLLER] = {
- [SDCC2] = {
- .gpio = sdc2_gpio,
- .size = ARRAY_SIZE(sdc2_gpio),
- },
- [SDCC4] = {
- .gpio = sdc4_gpio,
- .size = ARRAY_SIZE(sdc4_gpio),
- },
- };
- static struct msm_mmc_pad_data mmc_pad_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .pull = &mmc_pad_pull_data[SDCC1],
- .drv = &mmc_pad_drv_data[SDCC1]
- },
- [SDCC3] = {
- .pull = &mmc_pad_pull_data[SDCC3],
- .drv = &mmc_pad_drv_data[SDCC3]
- },
- };
- static struct msm_mmc_pin_data mmc_slot_pin_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .pad_data = &mmc_pad_data[SDCC1],
- },
- [SDCC2] = {
- .is_gpio = 1,
- .gpio_data = &mmc_gpio_data[SDCC2],
- },
- [SDCC3] = {
- .pad_data = &mmc_pad_data[SDCC3],
- },
- [SDCC4] = {
- .is_gpio = 1,
- .gpio_data = &mmc_gpio_data[SDCC4],
- },
- };
- #define MSM_MPM_PIN_SDC1_DAT1 17
- #define MSM_MPM_PIN_SDC3_DAT1 21
- static unsigned int sdc1_sup_clk_rates[] = {
- 400000, 24000000, 48000000, 96000000
- };
- #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
- static unsigned int sdc3_sup_clk_rates[] = {
- 400000, 24000000, 48000000, 96000000, 192000000
- };
- #endif
- #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
- static struct mmc_platform_data msm8960_sdc1_data = {
- .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
- #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
- .sup_clk_table = sdc1_sup_clk_rates,
- .sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
- .nonremovable = 1,
- .vreg_data = &mmc_slot_vreg_data[SDCC1],
- .pin_data = &mmc_slot_pin_data[SDCC1],
- .mpm_sdiowakeup_int = MSM_MPM_PIN_SDC1_DAT1,
- .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
- .uhs_caps2 = MMC_CAP2_HS200_1_8V_SDR,
- };
- #endif
- #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
- static unsigned int sdc2_sup_clk_rates[] = {
- 400000, 24000000, 48000000
- };
- static struct mmc_platform_data msm8960_sdc2_data = {
- .ocr_mask = MMC_VDD_165_195,
- .mmc_bus_width = MMC_CAP_4_BIT_DATA,
- .sup_clk_table = sdc2_sup_clk_rates,
- .sup_clk_cnt = ARRAY_SIZE(sdc2_sup_clk_rates),
- .vreg_data = &mmc_slot_vreg_data[SDCC2],
- .pin_data = &mmc_slot_pin_data[SDCC2],
- .sdiowakeup_irq = MSM_GPIO_TO_INT(90),
- .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
- };
- #endif
- #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
- static struct mmc_platform_data msm8960_sdc3_data = {
- .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
- .mmc_bus_width = MMC_CAP_4_BIT_DATA,
- .sup_clk_table = sdc3_sup_clk_rates,
- .sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
- #ifdef CONFIG_MMC_MSM_SDC3_WP_SUPPORT
- .wpswitch_gpio = PM8921_GPIO_PM_TO_SYS(16),
- #endif
- .vreg_data = &mmc_slot_vreg_data[SDCC3],
- .pin_data = &mmc_slot_pin_data[SDCC3],
- #ifndef CONFIG_MMC_MSM_SDC3_POLLING
- .status_gpio = PM8921_GPIO_PM_TO_SYS(26),
- .status_irq = PM8921_GPIO_IRQ(PM8921_IRQ_BASE, 26),
- .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- #endif
- .is_status_gpio_active_low = true,
- .xpc_cap = 1,
- .uhs_caps = (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
- MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
- MMC_CAP_UHS_SDR104 | MMC_CAP_MAX_CURRENT_600),
- .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 unsigned int sdc4_sup_clk_rates[] = {
- 400000, 24000000, 48000000
- };
- static struct mmc_platform_data msm8960_sdc4_data = {
- .ocr_mask = MMC_VDD_165_195,
- .mmc_bus_width = MMC_CAP_4_BIT_DATA,
- .sup_clk_table = sdc4_sup_clk_rates,
- .sup_clk_cnt = ARRAY_SIZE(sdc4_sup_clk_rates),
- .vreg_data = &mmc_slot_vreg_data[SDCC4],
- .pin_data = &mmc_slot_pin_data[SDCC4],
- .sdiowakeup_irq = MSM_GPIO_TO_INT(85),
- .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
- };
- #endif
- void __init msm8960_init_mmc(void)
- {
- #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
- /*
- * When eMMC runs in DDR mode on CDP platform, we have
- * seen instability due to DATA CRC errors. These errors are
- * attributed to long physical path between MSM and eMMC on CDP.
- * So let's not enable the DDR mode on CDP platform but let other
- * platforms take advantage of eMMC DDR mode.
- */
- if (!machine_is_msm8960_cdp())
- msm8960_sdc1_data.uhs_caps |= (MMC_CAP_1_8V_DDR |
- MMC_CAP_UHS_DDR50);
- /* SDC1 : eMMC card connected */
- msm_add_sdcc(1, &msm8960_sdc1_data);
- #endif
- #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
- /* SDC2: SDIO slot for WLAN*/
- msm_add_sdcc(2, &msm8960_sdc2_data);
- #endif
- #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
- /* SDC3: External card slot */
- msm_add_sdcc(3, &msm8960_sdc3_data);
- #endif
- #ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
- /* SDC4: SDIO slot for WLAN */
- msm_add_sdcc(4, &msm8960_sdc4_data);
- #endif
- }
|