[U-Boot] Subject: [PATCH 2/3] mmc: use sdhci.c instead of s5p_mmc.c
Jaehoon Chung
jh80.chung at samsung.com
Thu Mar 29 10:25:24 CEST 2012
In driver mmc, generic sdhci code is implemented.
s5p_mmc file is dupulicated.
we are good that use the generic sdhci.
This patch supported the sdhci for Samsung-SoC.
Signed-off-by: Jaehoon Chung <jh80.chung at samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
arch/arm/include/asm/arch-exynos/mmc.h | 93 +++++++++++++++--------------
arch/arm/include/asm/arch-s5pc1xx/mmc.h | 93 +++++++++++++++--------------
drivers/mmc/Makefile | 2 +-
drivers/mmc/s5p_sdhci.c | 98 +++++++++++++++++++++++++++++++
drivers/mmc/sdhci.c | 12 ++++
include/sdhci.h | 6 ++
6 files changed, 211 insertions(+), 93 deletions(-)
create mode 100644 drivers/mmc/s5p_sdhci.c
diff --git a/arch/arm/include/asm/arch-exynos/mmc.h b/arch/arm/include/asm/arch-exynos/mmc.h
index 30f82b8..0f701c9 100644
--- a/arch/arm/include/asm/arch-exynos/mmc.h
+++ b/arch/arm/include/asm/arch-exynos/mmc.h
@@ -21,53 +21,54 @@
#ifndef __ASM_ARCH_MMC_H_
#define __ASM_ARCH_MMC_H_
-#ifndef __ASSEMBLY__
-struct s5p_mmc {
- unsigned int sysad;
- unsigned short blksize;
- unsigned short blkcnt;
- unsigned int argument;
- unsigned short trnmod;
- unsigned short cmdreg;
- unsigned int rspreg0;
- unsigned int rspreg1;
- unsigned int rspreg2;
- unsigned int rspreg3;
- unsigned int bdata;
- unsigned int prnsts;
- unsigned char hostctl;
- unsigned char pwrcon;
- unsigned char blkgap;
- unsigned char wakcon;
- unsigned short clkcon;
- unsigned char timeoutcon;
- unsigned char swrst;
- unsigned int norintsts; /* errintsts */
- unsigned int norintstsen; /* errintstsen */
- unsigned int norintsigen; /* errintsigen */
- unsigned short acmd12errsts;
- unsigned char res1[2];
- unsigned int capareg;
- unsigned char res2[4];
- unsigned int maxcurr;
- unsigned char res3[0x34];
- unsigned int control2;
- unsigned int control3;
- unsigned char res4[4];
- unsigned int control4;
- unsigned char res5[0x6e];
- unsigned short hcver;
- unsigned char res6[0xFF00];
-};
+#define SDHCI_CONTROL2 0x80
+#define SDHCI_CONTROL3 0x84
+#define SDHCI_CONTROL4 0x8C
-struct mmc_host {
- struct s5p_mmc *reg;
- unsigned int version; /* SDHCI spec. version */
- unsigned int clock; /* Current clock (MHz) */
- int dev_index;
-};
+#define SDHCI_CTRL2_ENSTAASYNCCLR (1 << 31)
+#define SDHCI_CTRL2_ENCMDCNFMSK (1 << 30)
+#define SDHCI_CTRL2_CDINVRXD3 (1 << 29)
+#define SDHCI_CTRL2_SLCARDOUT (1 << 28)
-int s5p_mmc_init(int dev_index, int bus_width);
+#define SDHCI_CTRL2_FLTCLKSEL_MASK (0xf << 24)
+#define SDHCI_CTRL2_FLTCLKSEL_SHIFT (24)
+#define SDHCI_CTRL2_FLTCLKSEL(_x) ((_x) << 24)
-#endif /* __ASSEMBLY__ */
+#define SDHCI_CTRL2_LVLDAT_MASK (0xff << 16)
+#define SDHCI_CTRL2_LVLDAT_SHIFT (16)
+#define SDHCI_CTRL2_LVLDAT(_x) ((_x) << 16)
+
+#define SDHCI_CTRL2_ENFBCLKTX (1 << 15)
+#define SDHCI_CTRL2_ENFBCLKRX (1 << 14)
+#define SDHCI_CTRL2_SDCDSEL (1 << 13)
+#define SDHCI_CTRL2_SDSIGPC (1 << 12)
+#define SDHCI_CTRL2_ENBUSYCHKTXSTART (1 << 11)
+
+#define SDHCI_CTRL2_DFCNT_MASK(_x) ((_x) << 9)
+#define SDHCI_CTRL2_DFCNT_SHIFT (9)
+
+#define SDHCI_CTRL2_ENCLKOUTHOLD (1 << 8)
+#define SDHCI_CTRL2_RWAITMODE (1 << 7)
+#define SDHCI_CTRL2_DISBUFRD (1 << 6)
+#define SDHCI_CTRL2_SELBASECLK_MASK(_x) ((_x) << 4)
+#define SDHCI_CTRL2_SELBASECLK_SHIFT (4)
+#define SDHCI_CTRL2_PWRSYNC (1 << 3)
+#define SDHCI_CTRL2_ENCLKOUTMSKCON (1 << 1)
+#define SDHCI_CTRL2_HWINITFIN (1 << 0)
+
+#define SDHCI_CTRL3_FCSEL3 (1 << 31)
+#define SDHCI_CTRL3_FCSEL2 (1 << 23)
+#define SDHCI_CTRL3_FCSEL1 (1 << 15)
+#define SDHCI_CTRL3_FCSEL0 (1 << 7)
+
+#define SDHCI_CTRL4_DRIVE_MASK(_x) ((_x) << 16)
+#define SDHCI_CTRL4_DRIVE_SHIFT (16)
+
+int s5p_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks);
+
+static inline unsigned int s5p_mmc_init(int index, int bus_width)
+{
+ unsigned int base = samsung_get_base_mmc() + (0x10000 * index);
+ return s5p_sdhci_init(base, 52000000, 400000, index);
+}
#endif
diff --git a/arch/arm/include/asm/arch-s5pc1xx/mmc.h b/arch/arm/include/asm/arch-s5pc1xx/mmc.h
index adef4ee..0f701c9 100644
--- a/arch/arm/include/asm/arch-s5pc1xx/mmc.h
+++ b/arch/arm/include/asm/arch-s5pc1xx/mmc.h
@@ -21,53 +21,54 @@
#ifndef __ASM_ARCH_MMC_H_
#define __ASM_ARCH_MMC_H_
-#ifndef __ASSEMBLY__
-struct s5p_mmc {
- unsigned int sysad;
- unsigned short blksize;
- unsigned short blkcnt;
- unsigned int argument;
- unsigned short trnmod;
- unsigned short cmdreg;
- unsigned int rspreg0;
- unsigned int rspreg1;
- unsigned int rspreg2;
- unsigned int rspreg3;
- unsigned int bdata;
- unsigned int prnsts;
- unsigned char hostctl;
- unsigned char pwrcon;
- unsigned char blkgap;
- unsigned char wakcon;
- unsigned short clkcon;
- unsigned char timeoutcon;
- unsigned char swrst;
- unsigned int norintsts; /* errintsts */
- unsigned int norintstsen; /* errintstsen */
- unsigned int norintsigen; /* errintsigen */
- unsigned short acmd12errsts;
- unsigned char res1[2];
- unsigned int capareg;
- unsigned char res2[4];
- unsigned int maxcurr;
- unsigned char res3[0x34];
- unsigned int control2;
- unsigned int control3;
- unsigned char res4[4];
- unsigned int control4;
- unsigned char res5[0x6e];
- unsigned short hcver;
- unsigned char res6[0xFFF00];
-};
+#define SDHCI_CONTROL2 0x80
+#define SDHCI_CONTROL3 0x84
+#define SDHCI_CONTROL4 0x8C
-struct mmc_host {
- struct s5p_mmc *reg;
- unsigned int version; /* SDHCI spec. version */
- unsigned int clock; /* Current clock (MHz) */
- int dev_index;
-};
+#define SDHCI_CTRL2_ENSTAASYNCCLR (1 << 31)
+#define SDHCI_CTRL2_ENCMDCNFMSK (1 << 30)
+#define SDHCI_CTRL2_CDINVRXD3 (1 << 29)
+#define SDHCI_CTRL2_SLCARDOUT (1 << 28)
-int s5p_mmc_init(int dev_index, int bus_width);
+#define SDHCI_CTRL2_FLTCLKSEL_MASK (0xf << 24)
+#define SDHCI_CTRL2_FLTCLKSEL_SHIFT (24)
+#define SDHCI_CTRL2_FLTCLKSEL(_x) ((_x) << 24)
-#endif /* __ASSEMBLY__ */
+#define SDHCI_CTRL2_LVLDAT_MASK (0xff << 16)
+#define SDHCI_CTRL2_LVLDAT_SHIFT (16)
+#define SDHCI_CTRL2_LVLDAT(_x) ((_x) << 16)
+
+#define SDHCI_CTRL2_ENFBCLKTX (1 << 15)
+#define SDHCI_CTRL2_ENFBCLKRX (1 << 14)
+#define SDHCI_CTRL2_SDCDSEL (1 << 13)
+#define SDHCI_CTRL2_SDSIGPC (1 << 12)
+#define SDHCI_CTRL2_ENBUSYCHKTXSTART (1 << 11)
+
+#define SDHCI_CTRL2_DFCNT_MASK(_x) ((_x) << 9)
+#define SDHCI_CTRL2_DFCNT_SHIFT (9)
+
+#define SDHCI_CTRL2_ENCLKOUTHOLD (1 << 8)
+#define SDHCI_CTRL2_RWAITMODE (1 << 7)
+#define SDHCI_CTRL2_DISBUFRD (1 << 6)
+#define SDHCI_CTRL2_SELBASECLK_MASK(_x) ((_x) << 4)
+#define SDHCI_CTRL2_SELBASECLK_SHIFT (4)
+#define SDHCI_CTRL2_PWRSYNC (1 << 3)
+#define SDHCI_CTRL2_ENCLKOUTMSKCON (1 << 1)
+#define SDHCI_CTRL2_HWINITFIN (1 << 0)
+
+#define SDHCI_CTRL3_FCSEL3 (1 << 31)
+#define SDHCI_CTRL3_FCSEL2 (1 << 23)
+#define SDHCI_CTRL3_FCSEL1 (1 << 15)
+#define SDHCI_CTRL3_FCSEL0 (1 << 7)
+
+#define SDHCI_CTRL4_DRIVE_MASK(_x) ((_x) << 16)
+#define SDHCI_CTRL4_DRIVE_SHIFT (16)
+
+int s5p_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks);
+
+static inline unsigned int s5p_mmc_init(int index, int bus_width)
+{
+ unsigned int base = samsung_get_base_mmc() + (0x10000 * index);
+ return s5p_sdhci_init(base, 52000000, 400000, index);
+}
#endif
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index c245352..a8e681c 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -39,8 +39,8 @@ COBJS-$(CONFIG_MXS_MMC) += mxsmmc.o
COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o
COBJS-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
-COBJS-$(CONFIG_S5P_MMC) += s5p_mmc.o
COBJS-$(CONFIG_SDHCI) += sdhci.o
+COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o
COBJS-$(CONFIG_TEGRA2_MMC) += tegra2_mmc.o
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
new file mode 100644
index 0000000..1d4481b
--- /dev/null
+++ b/drivers/mmc/s5p_sdhci.c
@@ -0,0 +1,98 @@
+/*
+ * (C) Copyright 2012 SAMSUNG Electronics
+ * Jaehoon Chung <jh80.chung at samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <sdhci.h>
+#include <asm/arch/mmc.h>
+
+static char *S5P_NAME = "SAMSUNG SDHCI";
+static void s5p_sdhci_set_control_reg(struct sdhci_host *host)
+{
+ unsigned long val, ctrl;
+ /*
+ * SELCLKPADDS[17:16]
+ * 00 = 2mA
+ * 01 = 4mA
+ * 10 = 7mA
+ * 11 = 9mA
+ */
+ sdhci_writel(host, SDHCI_CTRL4_DRIVE_MASK(0x3), SDHCI_CONTROL4);
+
+ val = sdhci_readl(host, SDHCI_CONTROL2);
+ val &= SDHCI_CTRL2_SELBASECLK_SHIFT;
+
+ val |= SDHCI_CTRL2_ENSTAASYNCCLR |
+ SDHCI_CTRL2_ENCMDCNFMSK |
+ SDHCI_CTRL2_ENFBCLKRX |
+ SDHCI_CTRL2_ENCLKOUTHOLD;
+
+ sdhci_writel(host, val, SDHCI_CONTROL2);
+
+ /*
+ * FCSEL3[31] FCSEL2[23] FCSEL1[15] FCSEL0[7]
+ * FCSel[1:0] : Rx Feedback Clock Delay Control
+ * Inverter delay means10ns delay if SDCLK 50MHz setting
+ * 01 = Delay1 (basic delay)
+ * 11 = Delay2 (basic delay + 2ns)
+ * 00 = Delay3 (inverter delay)
+ * 10 = Delay4 (inverter delay + 2ns)
+ */
+ val = SDHCI_CTRL3_FCSEL3 | SDHCI_CTRL3_FCSEL1;
+ sdhci_writel(host, val, SDHCI_CONTROL3);
+
+ /*
+ * SELBASECLK[5:4]
+ * 00/01 = HCLK
+ * 10 = EPLL
+ * 11 = XTI or XEXTCLK
+ */
+ ctrl = sdhci_readl(host, SDHCI_CONTROL2);
+ ctrl &= ~SDHCI_CTRL2_SELBASECLK_MASK(0x3);
+ ctrl |= SDHCI_CTRL2_SELBASECLK_MASK(0x2);
+ sdhci_writel(host, ctrl, SDHCI_CONTROL2);
+}
+
+int s5p_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks)
+{
+ struct sdhci_host *host = NULL;
+ host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
+ if (!host) {
+ printf("sdhci__host malloc fail!\n");
+ return 1;
+ }
+
+ host->name = S5P_NAME;
+ host->ioaddr = (void *)regbase;
+ host->quirks = quirks;
+
+ host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE;
+ host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+ if (quirks & SDHCI_QUIRK_REG32_RW)
+ host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
+ else
+ host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
+
+ host->set_control_reg = &s5p_sdhci_set_control_reg;
+
+ host->host_caps = MMC_MODE_HC;
+
+ add_sdhci(host, max_clk, min_clk);
+ return 0;
+}
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 0dd08b9..962633b 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -338,6 +338,9 @@ void sdhci_set_ios(struct mmc *mmc)
u32 ctrl;
struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
+ if (host->set_control_reg)
+ host->set_control_reg(host);
+
if (mmc->clock != host->clock)
sdhci_set_clock(mmc, mmc->clock);
@@ -361,6 +364,9 @@ void sdhci_set_ios(struct mmc *mmc)
else
ctrl &= ~SDHCI_CTRL_HISPD;
+ if (host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)
+ ctrl &= ~SDHCI_CTRL_HISPD;
+
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
}
@@ -444,9 +450,15 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
if (caps & SDHCI_CAN_VDD_180)
mmc->voltages |= MMC_VDD_165_195;
+
+ if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
+ mmc->voltages |= host->voltages;
+
mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
if (caps & SDHCI_CAN_DO_8BIT)
mmc->host_caps |= MMC_MODE_8BIT;
+ if (host->host_caps)
+ mmc->host_caps |= host->host_caps;
sdhci_reset(host, SDHCI_RESET_ALL);
mmc_register(mmc);
diff --git a/include/sdhci.h b/include/sdhci.h
index 800f9d9..435f945 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -216,6 +216,8 @@
*/
#define SDHCI_QUIRK_32BIT_DMA_ADDR (1 << 0)
#define SDHCI_QUIRK_REG32_RW (1 << 1)
+#define SDHCI_QUIRK_NO_HISPD_BIT (1 << 2)
+#define SDHCI_QUIRK_BROKEN_VOLTAGE (1 << 3)
/* to make gcc happy */
struct sdhci_host;
@@ -240,10 +242,14 @@ struct sdhci_host {
char *name;
void *ioaddr;
unsigned int quirks;
+ unsigned int host_caps;
unsigned int version;
unsigned int clock;
struct mmc *mmc;
const struct sdhci_ops *ops;
+
+ void (*set_control_reg)(struct sdhci_host *host);
+ uint voltages;
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
More information about the U-Boot
mailing list