/* linux/arch/arm/mach-exynos/board-smdk5250-mmc.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. * http://www.samsung.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include #include #include #include #include #include #include #include #include #include #include "board-smdk5250.h" #ifdef CONFIG_EXYNOS4_DEV_DWMCI static void exynos_dwmci_cfg_gpio(int width) { unsigned int gpio; for (gpio = EXYNOS5_GPC0(0); gpio < EXYNOS5_GPC0(2); gpio++) { s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV2); } switch (width) { case MMC_BUS_WIDTH_8: for (gpio = EXYNOS5_GPC1(3); gpio <= EXYNOS5_GPC1(6); gpio++) { s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV2); } case MMC_BUS_WIDTH_4: for (gpio = EXYNOS5_GPC0(3); gpio <= EXYNOS5_GPC0(6); gpio++) { s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV2); } break; case MMC_BUS_WIDTH_1: gpio = EXYNOS5_GPC0(3); s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV2); default: break; } } static struct dw_mci_board exynos_dwmci_pdata __initdata = { .num_slots = 1, .quirks = DW_MCI_QUIRK_BROKEN_CARD_DETECTION | DW_MCI_QUIRK_HIGHSPEED, .bus_hz = 66 * 1000 * 1000, .caps = MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, .fifo_depth = 0x80, .detect_delay_ms = 200, .hclk_name = "dwmci", .cclk_name = "sclk_dwmci", .cfg_gpio = exynos_dwmci_cfg_gpio, }; #endif static void exynos_dwmci0_cfg_gpio(int width) { unsigned int gpio; for (gpio = EXYNOS5_GPC0(0); gpio < EXYNOS5_GPC0(2); gpio++) { s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); } switch (width) { case MMC_BUS_WIDTH_8: for (gpio = EXYNOS5_GPC1(0); gpio <= EXYNOS5_GPC1(3); gpio++) { s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); } case MMC_BUS_WIDTH_4: for (gpio = EXYNOS5_GPC0(3); gpio <= EXYNOS5_GPC0(6); gpio++) { s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); } break; case MMC_BUS_WIDTH_1: gpio = EXYNOS5_GPC0(3); s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); default: break; } } static struct dw_mci_board smdk5250_dwmci0_pdata __initdata = { .num_slots = 1, .quirks = DW_MCI_QUIRK_BROKEN_CARD_DETECTION | DW_MCI_QUIRK_HIGHSPEED, .bus_hz = 100 * 1000 * 1000, .caps = MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, .fifo_depth = 0x80, .detect_delay_ms = 200, .hclk_name = "dwmci", .cclk_name = "sclk_dwmci", .cfg_gpio = exynos_dwmci0_cfg_gpio, }; static int smdk5250_dwmci_get_ro(u32 slot_id) { /* smdk5250 rev1.0 did not support SD/MMC card write pritect. */ return 0; } static void exynos_dwmci2_cfg_gpio(int width) { unsigned int gpio; for (gpio = EXYNOS5_GPC3(0); gpio < EXYNOS5_GPC3(2); gpio++) { s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV2); } switch (width) { case MMC_BUS_WIDTH_4: for (gpio = EXYNOS5_GPC3(3); gpio <= EXYNOS5_GPC3(6); gpio++) { s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV2); } break; case MMC_BUS_WIDTH_1: gpio = EXYNOS5_GPC3(3); s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV2); default: break; } gpio = EXYNOS5_GPC3(2); s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV2); } static struct dw_mci_board smdk5250_dwmci2_pdata __initdata = { .num_slots = 1, .quirks = DW_MCI_QUIRK_HIGHSPEED, .bus_hz = 100 * 1000 * 1000, .caps = MMC_CAP_CMD23, .fifo_depth = 0x80, .detect_delay_ms = 200, .hclk_name = "dwmci", .cclk_name = "sclk_dwmci", .cfg_gpio = exynos_dwmci2_cfg_gpio, .get_ro = smdk5250_dwmci_get_ro, }; #ifdef CONFIG_S3C_DEV_HSMMC static struct s3c_sdhci_platdata smdk5250_hsmmc0_pdata __initdata = { .cd_type = S3C_SDHCI_CD_INTERNAL, .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, #ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT .max_width = 8, .host_caps = MMC_CAP_8_BIT_DATA, #endif }; #endif #ifdef CONFIG_S3C_DEV_HSMMC1 static struct s3c_sdhci_platdata smdk5250_hsmmc1_pdata __initdata = { .cd_type = S3C_SDHCI_CD_INTERNAL, .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, }; #endif #ifdef CONFIG_S3C_DEV_HSMMC2 static struct s3c_sdhci_platdata smdk5250_hsmmc2_pdata __initdata = { .cd_type = S3C_SDHCI_CD_INTERNAL, .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, #ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT .max_width = 8, .host_caps = MMC_CAP_8_BIT_DATA, #endif }; #endif #ifdef CONFIG_S3C_DEV_HSMMC3 static struct s3c_sdhci_platdata smdk5250_hsmmc3_pdata __initdata = { .cd_type = S3C_SDHCI_CD_INTERNAL, .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, }; #endif static struct platform_device *smdk5250_mmc_devices[] __initdata = { #ifdef CONFIG_S3C_DEV_HSMMC &s3c_device_hsmmc0, #endif #ifdef CONFIG_S3C_DEV_HSMMC1 &s3c_device_hsmmc1, #endif #ifdef CONFIG_S3C_DEV_HSMMC2 &s3c_device_hsmmc2, #endif #ifdef CONFIG_S3C_DEV_HSMMC3 &s3c_device_hsmmc3, #endif #ifdef CONFIG_EXYNOS4_DEV_DWMCI &exynos_device_dwmci, &exynos_device_dwmci0, &exynos_device_dwmci2, #endif }; void __init exynos5_smdk5250_mmc_init(void) { #ifdef CONFIG_EXYNOS4_DEV_DWMCI if (samsung_rev() >= EXYNOS5250_REV_1_0) { exynos_dwmci_set_platdata(&smdk5250_dwmci0_pdata, 0); dev_set_name(&exynos_device_dwmci0.dev, "s3c-sdhci.0"); clk_add_alias("dwmci", "dw_mmc.0", "hsmmc", &exynos_device_dwmci0.dev); clk_add_alias("sclk_dwmci", "dw_mmc.0", "sclk_mmc", &exynos_device_dwmci0.dev); exynos_dwmci_set_platdata(&smdk5250_dwmci2_pdata, 2); dev_set_name(&exynos_device_dwmci2.dev, "s3c-sdhci.2"); clk_add_alias("dwmci", "dw_mmc.2", "hsmmc", &exynos_device_dwmci2.dev); clk_add_alias("sclk_dwmci", "dw_mmc.2", "sclk_mmc", &exynos_device_dwmci2.dev); } else #endif { #ifdef CONFIG_EXYNOS4_DEV_DWMCI exynos_dwmci_set_platdata(&exynos_dwmci_pdata, 0); #endif #ifdef CONFIG_S3C_DEV_HSMMC s3c_sdhci0_set_platdata(&smdk5250_hsmmc0_pdata); #endif #ifdef CONFIG_S3C_DEV_HSMMC1 s3c_sdhci1_set_platdata(&smdk5250_hsmmc1_pdata); #endif #ifdef CONFIG_S3C_DEV_HSMMC2 s3c_sdhci2_set_platdata(&smdk5250_hsmmc2_pdata); #endif #ifdef CONFIG_S3C_DEV_HSMMC3 s3c_sdhci3_set_platdata(&smdk5250_hsmmc3_pdata); #endif } platform_add_devices(smdk5250_mmc_devices, ARRAY_SIZE(smdk5250_mmc_devices)); }