aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos/setup-mshci-gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-exynos/setup-mshci-gpio.c')
-rw-r--r--arch/arm/mach-exynos/setup-mshci-gpio.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos/setup-mshci-gpio.c b/arch/arm/mach-exynos/setup-mshci-gpio.c
new file mode 100644
index 0000000..4c73310
--- /dev/null
+++ b/arch/arm/mach-exynos/setup-mshci-gpio.c
@@ -0,0 +1,220 @@
+/* linux/arch/arm/mach-exynos/setup-mshci-gpio.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS4 - Helper functions for setting up MSHCI device(s) GPIO (HSMMC)
+ *
+ * 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 <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/delay.h>
+
+#include <mach/gpio.h>
+#include <mach/map.h>
+#include <plat/gpio-cfg.h>
+#include <plat/mshci.h>
+#include <plat/cpu.h>
+
+#define GPK0DRV (S5P_VA_GPIO2 + 0x4C)
+#define GPK1DRV (S5P_VA_GPIO2 + 0x6C)
+#define GPK2DRV (S5P_VA_GPIO2 + 0x8C)
+#define GPK3DRV (S5P_VA_GPIO2 + 0xAC)
+
+#define DIV_FSYS3 (S5P_VA_CMU + 0x0C54C)
+
+#if defined(CONFIG_MACH_M0) && defined(CONFIG_TARGET_LOCALE_EUR)
+#define EPLL_CON0_F (S5P_VA_CMU + 0x0C110)
+
+void print_epll_con0(void)
+{
+ pr_info("EPLL_CON0 : 0x%x\n",__raw_readl(EPLL_CON0_F));
+}
+#endif
+
+void exynos4_setup_mshci_cfg_gpio(struct platform_device *dev, int width)
+{
+ unsigned int gpio;
+ struct s3c_mshci_platdata *pdata = dev->dev.platform_data;
+
+ /* early_printk("exynos4_setup_mshci_cfg_gpio\n"); */
+
+ /* Set all the necessary GPG0/GPG1 pins to special-function 2 */
+ for (gpio = EXYNOS4_GPK0(0); gpio < EXYNOS4_GPK0(2); gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ }
+
+ /* if CDn pin is used as eMMC_EN pin, it might make a problem
+ So, a built-in type eMMC is embedded, it dose not set CDn pin */
+ if (pdata->cd_type != S3C_MSHCI_CD_PERMANENT) {
+ s3c_gpio_cfgpin(EXYNOS4_GPK0(2), S3C_GPIO_SFN(3));
+ s3c_gpio_setpull(EXYNOS4_GPK0(2), S3C_GPIO_PULL_NONE);
+ }
+
+ switch (width) {
+ case 8:
+ for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6); gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ }
+ __raw_writel(0x2AAA, GPK1DRV);
+ case 4:
+ /* GPK[3:6] special-funtion 2 */
+ for (gpio = EXYNOS4_GPK0(3); gpio <= EXYNOS4_GPK0(6); gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ }
+ __raw_writel(0x2AAA, GPK0DRV);
+ break;
+ case 1:
+ /* GPK[3] special-funtion 2 */
+ for (gpio = EXYNOS4_GPK0(3); gpio < EXYNOS4_GPK0(4); gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ }
+ __raw_writel(0xAA, GPK0DRV);
+ default:
+ break;
+ }
+}
+
+void exynos4_setup_mshci_cfg_ddr(struct platform_device *dev, int ddr)
+{
+ if (ddr) {
+#ifdef CONFIG_EXYNOS4_MSHC_EPLL_45MHZ
+ __raw_writel(0x00, DIV_FSYS3);
+#elif defined(CONFIG_EXYNOS4_MSHC_VPLL_46MHZ)
+ __raw_writel(0x01, DIV_FSYS3);
+#else
+ if ((soc_is_exynos4412() || soc_is_exynos4212()) &&
+ samsung_rev() >= EXYNOS4412_REV_1_0) {
+ __raw_writel(0x1, DIV_FSYS3);
+ } else
+ __raw_writel(0x05, DIV_FSYS3);
+#endif
+ } else {
+#ifdef CONFIG_EXYNOS4_MSHC_EPLL_45MHZ
+ __raw_writel(0x01, DIV_FSYS3);
+#elif defined(CONFIG_EXYNOS4_MSHC_VPLL_46MHZ)
+ __raw_writel(0x03, DIV_FSYS3);
+#else
+ if ((soc_is_exynos4412() || soc_is_exynos4212()) &&
+ samsung_rev() >= EXYNOS4412_REV_1_0)
+ __raw_writel(0x3, DIV_FSYS3);
+ else
+ __raw_writel(0xb, DIV_FSYS3);
+#endif
+ }
+}
+
+void exynos4_setup_mshci_init_card(struct platform_device *dev)
+{
+ /*
+ * Reset moviNAND for re-init.
+ * output/low for eMMC_EN and input/pull-none for others
+ * and then wait 10ms.
+ */
+ __raw_writel(0x100, S5P_VA_GPIO2 + 0x40);
+ __raw_writel(0, S5P_VA_GPIO2 + 0x44);
+ __raw_writel(0, S5P_VA_GPIO2 + 0x48);
+ __raw_writel(0, S5P_VA_GPIO2 + 0x60);
+ __raw_writel(0, S5P_VA_GPIO2 + 0x64);
+ __raw_writel(0, S5P_VA_GPIO2 + 0x68);
+ mdelay(100);
+
+ /* set data buswidth 8 */
+ exynos4_setup_mshci_cfg_gpio(dev, 8);
+
+ /* power to moviNAND on */
+ gpio_set_value(EXYNOS4_GPK0(2), 1);
+
+ /* to wait a pull-up resistance ready */
+ mdelay(10);
+}
+
+void exynos4_setup_mshci_set_power(struct platform_device *dev, int en)
+{
+ struct s3c_mshci_platdata *pdata = dev->dev.platform_data;
+ unsigned int gpio = 0;
+
+ if (pdata->int_power_gpio) {
+ if (en) {
+#ifdef CONFIG_MACH_Q1_BD
+ mdelay(20);
+#endif
+ /*CMD/CLK*/
+ for (gpio = EXYNOS4_GPK0(0); gpio < EXYNOS4_GPK0(2);
+ gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ }
+ /*DAT[0]~[3]*/
+ for (gpio = EXYNOS4_GPK0(3); gpio <= EXYNOS4_GPK0(6);
+ gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ }
+ /*DAT[4]~[7]*/
+ for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6);
+ gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ }
+
+ gpio_set_value(pdata->int_power_gpio, 1);
+ pr_info("%s : internal MMC Card ON samsung-mshc.\n",
+ __func__);
+ } else {
+#if defined(CONFIG_MACH_M0_CTC)
+ s3c_gpio_cfgpin(pdata->int_power_gpio, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(pdata->int_power_gpio,
+ S3C_GPIO_PULL_NONE);
+#endif
+ gpio_set_value(pdata->int_power_gpio, 0);
+
+ /*CMD/CLK*/
+ for (gpio = EXYNOS4_GPK0(0); gpio < EXYNOS4_GPK0(2);
+ gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_DOWN);
+ }
+ /*DAT[0]~[3]*/
+ for (gpio = EXYNOS4_GPK0(3); gpio <= EXYNOS4_GPK0(6);
+ gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_DOWN);
+ }
+ /*DAT[4]~[7]*/
+ for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6);
+ gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_DOWN);
+ }
+ pr_info("%s : internal MMC Card OFF samsung-mshc.\n",
+ __func__);
+ mdelay(50);
+ }
+ }
+}
+
+void exynos4_setup_mshci_shutdown()
+{
+ /* to reset eMMC card, VDD of eMMC should be off over 1ms */
+ __raw_writel(0x100, S5P_VA_GPIO2 + 0x40);
+ __raw_writel(0, S5P_VA_GPIO2 + 0x44);
+ __raw_writel(0, S5P_VA_GPIO2 + 0x48);
+ __raw_writel(0, S5P_VA_GPIO2 + 0x60);
+ __raw_writel(0, S5P_VA_GPIO2 + 0x64);
+ __raw_writel(0, S5P_VA_GPIO2 + 0x68);
+ mdelay(10);
+}