From: Jaehoon Chung <jh80.chung@samsung.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] Subject: [PATCH 2/3] mmc: use sdhci.c instead of s5p_mmc.c
Date: Thu, 29 Mar 2012 17:25:24 +0900 [thread overview]
Message-ID: <4F741C74.5040204@samsung.com> (raw)
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@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@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@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
reply other threads:[~2012-03-29 8:25 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F741C74.5040204@samsung.com \
--to=jh80.chung@samsung.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.