
NAK for this patch, the mv_sdhci.c with the generic sdhci.c framework is intend to support armada100.
Best regards, Lei
On Fri, Jul 8, 2011 at 2:22 PM, Ajay Bhargav ajay.bhargav@einfochips.com wrote:
This patch provide support for MMC on GuruPlug-Display in uboot.
Signed-off-by: Ajay Bhargav ajay.bhargav@einfochips.com
arch/arm/include/asm/arch-armada100/cpu.h | 4 + arch/arm/include/asm/arch-armada100/mfp.h | 17 + board/Marvell/gplugd/gplugd.c | 26 ++ drivers/mmc/Makefile | 1 + drivers/mmc/pxa_sdh.c | 677 +++++++++++++++++++++++++++++ drivers/mmc/pxa_sdh.h | 241 ++++++++++ include/configs/gplugd.h | 15 + 7 files changed, 981 insertions(+), 0 deletions(-) create mode 100644 drivers/mmc/pxa_sdh.c create mode 100644 drivers/mmc/pxa_sdh.h
diff --git a/arch/arm/include/asm/arch-armada100/cpu.h b/arch/arm/include/asm/arch-armada100/cpu.h index 0518a6a..6ab3bf9 100644 --- a/arch/arm/include/asm/arch-armada100/cpu.h +++ b/arch/arm/include/asm/arch-armada100/cpu.h @@ -50,4 +50,8 @@ struct armd1cpu_registers { u32 armd1_sdram_base(int); u32 armd1_sdram_size(int);
+#ifdef CONFIG_PXASDH +int pxa_sdh_init(bd_t *); +#endif
#endif /* _ARMADA100CPU_H */ diff --git a/arch/arm/include/asm/arch-armada100/mfp.h b/arch/arm/include/asm/arch-armada100/mfp.h index e94be3a..1d897ae 100644 --- a/arch/arm/include/asm/arch-armada100/mfp.h +++ b/arch/arm/include/asm/arch-armada100/mfp.h @@ -89,6 +89,23 @@ #define MFP110_SSP2_CS (MFP_REG(0x1B8) | MFP_AF0 | MFP_DRIVE_MEDIUM) #define MFP111_SSP2_CLK (MFP_REG(0x1BC) | MFP_AF4 | MFP_DRIVE_MEDIUM)
+/* MMC1 */ +#define MFP040_MMC1_D1 (MFP_REG(0x00C) | MFP_AF1 | MFP_DRIVE_MEDIUM) +#define MFP041_MMC1_D0 (MFP_REG(0x010) | MFP_AF1 | MFP_DRIVE_MEDIUM) +#define MFP043_MMC1_CLK (MFP_REG(0x018) | MFP_AF1 | MFP_DRIVE_MEDIUM) +#define MFP049_MMC1_CMD (MFP_REG(0x030) | MFP_AF1 | MFP_DRIVE_MEDIUM) +#define MFP051_MMC1_D3 (MFP_REG(0x038) | MFP_AF1 | MFP_DRIVE_MEDIUM) +#define MFP052_MMC1_D2 (MFP_REG(0x03C) | MFP_AF1 | MFP_DRIVE_MEDIUM) +#define MFP053_MMC1_CD (MFP_REG(0x040) | MFP_AF1 | MFP_DRIVE_MEDIUM)
+/* MMC2 */ +#define MFP028_MMC2_CMD (MFP_REG(0x0BC) | MFP_AF6 | MFP_DRIVE_MEDIUM) +#define MFP029_MMC2_CLK (MFP_REG(0x0C0) | MFP_AF6 | MFP_DRIVE_MEDIUM) +#define MFP030_MMC2_D0 (MFP_REG(0x0C4) | MFP_AF6 | MFP_DRIVE_MEDIUM) +#define MFP031_MMC2_D1 (MFP_REG(0x0C8) | MFP_AF6 | MFP_DRIVE_MEDIUM) +#define MFP032_MMC2_D2 (MFP_REG(0x0CC) | MFP_AF6 | MFP_DRIVE_MEDIUM) +#define MFP033_MMC2_D3 (MFP_REG(0x0D0) | MFP_AF6 | MFP_DRIVE_MEDIUM)
/* More macros can be defined here... */
#define MFP_PIN_MAX 117 diff --git a/board/Marvell/gplugd/gplugd.c b/board/Marvell/gplugd/gplugd.c index 0c7a8fd..7eacd63 100644 --- a/board/Marvell/gplugd/gplugd.c +++ b/board/Marvell/gplugd/gplugd.c @@ -31,6 +31,7 @@ #include <common.h> #include <mvmfp.h> #include <asm/arch/mfp.h> +#include <asm/arch/cpu.h> #include <asm/arch/armada100.h> #include <asm/arch/gpio.h> #include <miiphy.h> @@ -81,11 +82,29 @@ int board_early_init_f(void) MFP101_ETH_MDIO, MFP103_ETH_RXDV,
- /* SPI Flash interface */
MFP107_SSP2_RXD, MFP108_SSP2_TXD, MFP110_SSP2_CS, MFP111_SSP2_CLK,
- /* MMC1 */
- MFP040_MMC1_D1,
- MFP041_MMC1_D0,
- MFP043_MMC1_CLK,
- MFP049_MMC1_CMD,
- MFP051_MMC1_D3,
- MFP052_MMC1_D2,
- MFP053_MMC1_CD,
- /* MMC2 */
- MFP028_MMC2_CMD,
- MFP029_MMC2_CLK,
- MFP030_MMC2_D0,
- MFP031_MMC2_D1,
- MFP032_MMC2_D2,
- MFP033_MMC2_D3,
MFP_EOC /*End of configuration*/ }; /* configure MFP's */ @@ -121,6 +140,13 @@ int board_init(void) return 0; }
+#ifdef CONFIG_PXASDH +int board_mmc_init(bd_t *bd) +{
- return pxa_sdh_init(bd);
+} +#endif
#ifdef CONFIG_PXA_ETH int board_eth_init(bd_t *bis) { diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index a8fe17a..7f88031 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -38,6 +38,7 @@ COBJS-$(CONFIG_OMAP3_MMC) += omap3_mmc.o COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o COBJS-$(CONFIG_S5P_MMC) += s5p_mmc.o +COBJS-$(CONFIG_PXASDH) += pxa_sdh.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/mmc/pxa_sdh.c b/drivers/mmc/pxa_sdh.c new file mode 100644 index 0000000..0198af3 --- /dev/null +++ b/drivers/mmc/pxa_sdh.c @@ -0,0 +1,677 @@ +/**************************************************************************
- Copyright (c) 2009, 2010 Marvell International Ltd.
- This file is part of GNU program.
- GNU 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.
- GNU 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.
- *************************************************************************/
+/*
- Copyright (C) Marvell International Ltd. (kvedere@marvell.com)
- Code heavily based on Linux driver
- /driver/mmc/host/pxa_sdh.c
- Copyright (C) 2008-2009 Marvell International Ltd.
- 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 <common.h> +#include <part.h> +#include <malloc.h> +#include <mmc.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <linux/mtd/compat.h>
+#include "pxa_sdh.h"
+#define CLKRT_OFF (~0) +#define GET_REG(host, reg) readw(host->regbase + reg) +#define SET_REG(host, val, reg) writew(val, host->regbase + reg) +#define DATA_DIRECTION_READ(data) (data->flags & MMC_DATA_READ) +#define SET_REG_BIT(host, bit_mask, reg) \
- SET_REG(host, \
- GET_REG(host, reg) | (bit_mask), reg)
+#define CLEAR_REG_BIT(host, bit_mask, reg) \
- SET_REG(host, \
- GET_REG(host, reg) & ~(bit_mask), reg)
+#define SET_REG_BITS(host, bits_pos, bits_mask, val, reg) \
- {SET_REG(host, \
- GET_REG(host, reg) & ~(bits_mask << bits_pos), reg); \
- SET_REG(host, \
- GET_REG(host, reg) | (val << bits_pos), reg); }
+#define GET_REG_BITS(host, bit_pos, bits_mask, reg) \
- ((GET_REG(host, reg) >> bit_pos) & bits_mask)
+#define mmc_resp_type(cmd) ((cmd)->resp_type & (MMC_RSP_PRESENT|MMC_RSP_136| \
- MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
+#define MMC_BUS_WIDTH_1 1 +#define MMC_BUS_WIDTH_4 4 +#define MMC_BUS_WIDTH_8 8 +#define CONFIG_MMC_SDMA 1
+/* #define CONFIG_MMC_DEBUG 1 */
+#ifdef CONFIG_MMC_DEBUG +#define mmc_dbg printf +#else +#define mmc_dbg(arg...) +#endif
+struct pxa_sdh_host {
- struct mmc_cmd *cmd;
- struct mmc_data *data;
- u32 regbase;
- u32 bytes_xfered;
- u32 clkrate;
- u32 clkrt;
- u32 data_len;
- int error;
- int port_num;
+};
+static int pxa_sdh_cmd_done(struct pxa_sdh_host *host); +static void pxa_sdh_dma_data_done(struct pxa_sdh_host *host); +static void pxa_sdh_data_done(struct pxa_sdh_host *host);
+#ifdef CONFIG_MMC_DEBUG +static void dump_registers(struct pxa_sdh_host *host) +{
- unsigned int val;
- int offset;
- for (offset = 0; offset < 0x60; offset += 4) {
- if (offset == 0x20)
- continue;
- val = readl(host->regbase + offset);
- printf("%08x: %08x\n",
- (unsigned int)host->regbase + offset, val);
- }
- for (offset = 0xE0; offset < 0xF0; offset += 4) {
- val = readl(host->regbase + offset);
- printf("%08x: %08x\n",
- (unsigned int)host->regbase + offset, val);
- }
- val = readl(host->regbase + 0xFC);
- printf("%08x: %08x\n", (unsigned int)host->regbase + 0xFC, val);
+} +#endif
+/*static inline int fls(int x) +{
- int ret;
- asm("clz\t%0, %1" : "=r" (ret) : "r" (x) : "cc");
- ret = 32 - ret;
- return ret;
+}*/
+static int pxa_sdh_wait_reset(struct pxa_sdh_host *host) +{
- u32 timeout = 1000;
- u16 val;
- do {
- val = GET_REG(host, SD_TO_CTRL_SW_RST);
- if (!(val & (SW_RST_DAT | SW_RST_CMD | SW_RST_ALL)))
- break;
- udelay(1);
- } while (timeout--);
- if (timeout)
- return 0;
- printf("%s: Fatal: Wait RESET timeout.\n", __func__);
- return 1;
+}
+static void pxa_sdh_stop_clock(struct pxa_sdh_host *host) +{
- CLEAR_REG_BIT(host, EXT_CLK_EN, SD_CLOCK_CNTL);
+}
+static void pxa_sdh_start_clock(struct pxa_sdh_host *host) +{
- u32 timeout = 1000;
- SET_REG_BIT(host, INT_CLK_EN, SD_CLOCK_CNTL);
- do {
- if (GET_REG(host, SD_CLOCK_CNTL) & INT_CLK_STABLE)
- break;
- udelay(1);
- } while (timeout--);
- if (!timeout)
- printf("%s: unable to start clock\n", __func__);
- SET_REG_BITS(host, SD_FREQ_SEL_OFFSET, SD_FREQ_SEL_MASK,
- host->clkrt, SD_CLOCK_CNTL);
- /* set as maximum value for data line timeout*/
- SET_REG_BITS(host, DAT_TO_VAL_OFFSET, DAT_TO_MASK,
- (DAT_TO_MASK - 1), SD_TO_CTRL_SW_RST);
- SET_REG_BIT(host, EXT_CLK_EN, SD_CLOCK_CNTL);
+}
+static void pxa_sdh_setup_sdma(struct pxa_sdh_host *host) +{
- struct mmc_data *data = host->data;
- if (DATA_DIRECTION_READ(data)) {
- char *dest = data->dest + host->bytes_xfered;
- SET_REG(host, (u32) dest & 0xffff, SD_SYS_ADDR_LOW);
- SET_REG(host, (u32) dest >> 16, SD_SYS_ADDR_HIGH);
- } else {
- char *src = (char *) data->src + host->bytes_xfered;
- SET_REG(host, (u32) src & 0xffff, SD_SYS_ADDR_LOW);
- SET_REG(host, (u32) src >> 16, SD_SYS_ADDR_HIGH);
- }
+}
+static void pxa_sdh_setup_data(struct pxa_sdh_host *host) +{ +#ifdef CONFIG_MMC_SDMA
- pxa_sdh_setup_sdma(host);
- SET_REG_BITS(host, DMA_SEL_OFFSET, DMA_SEL_MASK,
- DMA_SEL_SDMA, SD_HOST_CTRL);
+#endif +}
+static void pxa_sdh_finish_request(struct pxa_sdh_host *host) +{
+#ifdef CONFIG_MMC_DEBUG
- struct mmc_cmd *cmd = host->cmd;
- dump_registers(host);
+#endif
- if (host->data && host->error)
- SET_REG_BIT(host, SW_RST_DAT, SD_TO_CTRL_SW_RST);
- mmc_dbg("%s: Finishing CMD%d(%s)\n", __func__, cmd->cmdidx,
- (host->error ? "failed" : "done"));
- host->data = NULL;
- host->cmd = NULL;
- host->error = 0;
- host->data_len = 0;
- host->bytes_xfered = 0;
+}
+static int pxa_sdh_process_irq(struct pxa_sdh_host *host, u32 intr_type) +{
- ulong hz = 3250000; /* 3.25 MHz Timer Clock */
- ushort done = GET_REG(host, SD_NOR_I_STAT) & intr_type;
- ulong start, curr, diff;
+#ifdef CONFIG_MMC_DEBUG
- struct mmc_cmd *cmd = host->cmd;
+#endif
- start = get_timer(0);
- while (!done) {
- done = GET_REG(host, SD_NOR_I_STAT) & intr_type;
- if (GET_REG(host, SD_NOR_I_STAT) & 0x8000) {
- mmc_dbg("Error! cmd : %d, err : %04x\n",
- cmd->cmdidx, GET_REG(host, SD_ERR_I_STAT));
- host->error = 1;
- pxa_sdh_finish_request(host);
- if (GET_REG(host, SD_ERR_I_STAT) & 0x1)
- return TIMEOUT; /* error happened */
- else
- return COMM_ERR;
- }
- curr = get_timer(0);
- diff = (long) curr - (long) start;
- if (diff > (3*hz)) {
- printf("cmd timeout, status : %04x\n",
- GET_REG(host, SD_NOR_I_STAT));
- printf("xfer mode : %04x\n",
- GET_REG(host, SD_TRANS_MODE));
- host->error = 1;
- pxa_sdh_finish_request(host);
- return -ETIMEDOUT;
- }
- }
- if (intr_type & CMD_COMP)
- pxa_sdh_cmd_done(host);
+#ifdef CONFIG_MMC_SDMA
- if (intr_type & DMA_INT)
- pxa_sdh_dma_data_done(host);
+#else
- if ((cmdtype & TX_RDY) || (cmdtype & RX_RDY))
- pxa_sdh_pio_data_done(host);
+#endif
- if (intr_type & XFER_COMP)
- pxa_sdh_data_done(host);
- /* Clear Status Bits */
- SET_REG(host, intr_type, SD_NOR_I_STAT);
- return 0;
+}
+static int pxa_sdh_start_cmd(struct pxa_sdh_host *host) +{
- u16 resp = 0;
- u16 xfrmd_val = 0;
- u16 cmd_val = 0;
- u16 val, mask;
- struct mmc_data *data = host->data;
- struct mmc_cmd *cmd = host->cmd;
- int ret;
- BUG_ON(!cmd);
- /*Set Response Type*/
- switch (mmc_resp_type(cmd)) {
- case MMC_RSP_NONE:
- break;
- case MMC_RSP_R1: /* r1, r5, r6, r7 */
- resp = CMD_RESP_48BIT;
- cmd_val |= CMD_CRC_CHK_EN | CMD_IDX_CHK_EN;
- break;
- case MMC_RSP_R2: /* r2 */
- resp = CMD_RESP_136BIT;
- cmd_val |= CMD_CRC_CHK_EN;
- break;
- case MMC_RSP_R3: /* r3, r4*/
- resp = CMD_RESP_48BIT;
- break;
- case MMC_RSP_R1b: /* r1b */
- resp = CMD_RESP_48BITB;
- cmd_val |= CMD_CRC_CHK_EN | CMD_IDX_CHK_EN;
- break;
- default:
- break;
- }
- /*Set Transfer mode regarding to data flag*/
- if (data) {
- cmd_val |= DATA_PRESENT;
- xfrmd_val |= BLK_CNT_EN;
- if (data->blocks > 1)
- xfrmd_val |= MULTI_BLK_SEL;
+#ifdef CONFIG_MMC_SDMA
- xfrmd_val |= DMA_EN;
+#else
- xfrmd_val &= ~DMA_EN;
+#endif
- if (DATA_DIRECTION_READ(data))
- xfrmd_val |= TO_HOST_DIR;
- else
- xfrmd_val &= ~TO_HOST_DIR;
- }
- /* if (cmd->opcode == 12)
- cmd_val |= host, CMD_TYPE_OFFSET,
- CMD_TYPE_MASK, CMD_TYPE_ABORT, SD_COMMAND);*/
- SET_REG(host, cmd->cmdarg & 0xffff, SD_ARG_LOW);
- SET_REG(host, cmd->cmdarg >> 16, SD_ARG_HIGH);
- SET_REG(host, xfrmd_val, SD_TRANS_MODE);
- cmd_val |= cmd->cmdidx << CMD_IDX_OFFSET | resp << RESP_TYPE_OFFSET;
- mmc_dbg("%s:Starting CMD%d with ARGUMENT 0x%x\n",
- __func__, cmd->cmdidx, cmd->cmdarg);
- val = GET_REG(host, SD_PRESENT_STAT_2);
- mask = CMD_LINE_LEVEL_MASK | DATA_LINE_LEVEL_MASK;
- if ((val & mask) != mask)
- mmc_dbg("%s:WARN: CMD/DATA pins are not all high, "
- "PRE_STAT=0x%04x\n", __func__,
- GET_REG(host, SD_PRESENT_STAT_2));
- SET_REG(host, cmd_val, SD_COMMAND);
- ret = pxa_sdh_process_irq(host, CMD_COMP);
- if (!ret && data) {
- do {
- ret = pxa_sdh_process_irq(host, (DMA_INT | XFER_COMP));
- /* If error or xfer completed (in which case
- * bytes_xfered is reset to 0) break */
- } while (host->bytes_xfered);
- }
- return ret;
+}
+static int pxa_sdh_cmd_done(struct pxa_sdh_host *host) +{
- struct mmc_cmd *cmd = host->cmd;
- u32 resp[8];
- BUG_ON(!cmd);
- /* get cmd response */
- resp[0] = GET_REG(host, SD_RESP_0);
- resp[1] = GET_REG(host, SD_RESP_1);
- resp[2] = GET_REG(host, SD_RESP_2);
- resp[3] = GET_REG(host, SD_RESP_3);
- resp[4] = GET_REG(host, SD_RESP_4);
- resp[5] = GET_REG(host, SD_RESP_5);
- resp[6] = GET_REG(host, SD_RESP_6);
- resp[7] = readb(host->regbase + SD_RESP_7);
- if (cmd->resp_type & MMC_RSP_136) {
- cmd->response[0] = resp[5] >> 8 | resp[6] << 8 | resp[7] << 24;
- cmd->response[1] = resp[3] >> 8 | resp[4] << 8 | resp[5] << 24;
- cmd->response[2] = resp[1] >> 8 | resp[2] << 8 | resp[3] << 24;
- cmd->response[3] = resp[0] << 8 | resp[1] << 24;
- } else {
- cmd->response[0] = resp[1] << 16 | resp[0];
- cmd->response[1] = resp[3] << 16 | resp[2];
- cmd->response[2] = resp[5] << 16 | resp[4];
- cmd->response[3] = resp[7] << 16 | resp[6];
- }
- mmc_dbg("%s: resp[0]=0x%x resp[1]=0x%x resp[2]=0x%x resp[3]=0x%x\n",
- __func__, cmd->response[0], cmd->response[1],
- cmd->response[2], cmd->response[3]);
- if (host->error || !host->data)
- pxa_sdh_finish_request(host);
- return 1;
+}
+#ifndef CONFIG_MMC_SDMA +static void pxa_sdh_pio_data_done(struct pxa_sdh_host *host) +{
- struct mmc_data *data = host->data;
- u16 blk_size = data->blocksize;
- u16 i = 0;
- if (DATA_DIRECTION_READ(data)) {
- char *dest = data->dest + host->bytes_xfered;
- for (i = 0; i < blk_size; i += sizeof(u32)) {
- *(u32 *)(dest + i) = readl(host->regbase +
- SD_BUF_DPORT_0);
- }
- } else {
- char *src = (char *) data->src + host->bytes_xfered;
- for (i = 0; i < blk_size; i += sizeof(u32))
- writel(*(u32 *)(src + i),
- host->regbase + SD_BUF_DPORT_0);
- }
- if (host->bytes_xfered < host->data_len) {
- host->bytes_xfered = host->bytes_xfered + blk_size;
- pxa_sdh_setup_data(host);
- }
+} +#endif
+static void pxa_sdh_dma_data_done(struct pxa_sdh_host *host) +{
- struct mmc_data *data = host->data;
- int host_dma_bdry_size;
- if (host->bytes_xfered < host->data_len) {
- host_dma_bdry_size = 0x1000 << (((u16) GET_REG(host,
- SD_BLOCK_SIZE)) >> HOST_DMA_BDRY_OFFSET);
- if (host_dma_bdry_size < data->blocksize)
- host->bytes_xfered = host->bytes_xfered +
- host_dma_bdry_size;
- else
- host->bytes_xfered = host->bytes_xfered +
- data->blocksize;
- pxa_sdh_setup_data(host);
- }
+}
+static void pxa_sdh_data_done(struct pxa_sdh_host *host) +{
- pxa_sdh_finish_request(host);
+}
+static int pxa_sdh_request(struct mmc *mmc, struct mmc_cmd *cmd,
- struct mmc_data *data)
+{
- struct pxa_sdh_host *host = mmc->priv;
- u16 val;
- u32 timeout = 1000;
- int ret = 0;
- host->data = data;
- host->cmd = cmd;
- if (pxa_sdh_wait_reset(host)) {
- host->error = 1;
- pxa_sdh_finish_request(host);
- return -ETIMEDOUT;
- }
- do {
- val = GET_REG(host, SD_PRESENT_STAT_1);
- if (!(val & CMD_INHBT_DAT || val & CMD_INHBT_CMD))
- break;
- udelay(1);
- } while (timeout--);
- if (!timeout) {
- printf("%s: In busy, unable to start the request.\n",
- __func__);
- host->error = 1;
- pxa_sdh_finish_request(host);
- return -EBUSY;
- }
- /* Clear Interrupt/Error status */
- SET_REG(host, 0xffff, SD_NOR_I_STAT);
- SET_REG(host, 0xffff, SD_ERR_I_STAT);
- if (data) {
- mmc_dbg("%s: setup data, blk_sz=%d, blk_cnt=0x%x\n", __func__,
- data->blocksize, data->blocks);
- /*
- * Set the Host DMA Boundary Buffer
- * to Maximum allowed (512 KB)
- */
- SET_REG(host, ((u16)((HOST_DMA_BDRY_MASK & 0x7) <<
- HOST_DMA_BDRY_OFFSET) | data->blocksize),
- SD_BLOCK_SIZE);
- SET_REG(host, data->blocks, SD_BLOCK_COUNT);
- pxa_sdh_setup_data(host);
- }
- ret = pxa_sdh_start_cmd(host);
- return ret;
+}
+static void pxa_sdh_set_ios(struct mmc *mmc) +{
- struct pxa_sdh_host *host = mmc->priv;
- if (pxa_sdh_wait_reset(host))
- return;
- if (mmc->clock) {
- unsigned long rate = host->clkrate;
- unsigned int clk = rate / mmc->clock;
- unsigned int shift;
- BUG_ON((mmc->clock > mmc->f_max) || (mmc->clock < mmc->f_min));
- if (mmc->clock >= host->clkrate) {
- host->clkrt = 0x00;
- } else {
- shift = generic_fls(clk);
- if (rate / clk > mmc->clock)
- shift++;
- host->clkrt = 1 << (shift - 2);
- }
- mmc_dbg("%s: set clkrt = %08x\n", __func__, host->clkrt);
- pxa_sdh_stop_clock(host);
- pxa_sdh_start_clock(host);
- if ((host->clkrt == 0 && host->clkrate > 25000000)
- || (host->clkrt && (host->clkrate/(host->clkrt*2))
- > 25000000)) {
- SET_REG_BIT(host, HI_SPEED_EN, SD_HOST_CTRL);
- mmc_dbg("%s: set as HIGH_SPEED.\n", __func__);
- } else
- CLEAR_REG_BIT(host, HI_SPEED_EN, SD_HOST_CTRL);
- } else {
- pxa_sdh_stop_clock(host);
- if (host->clkrt != CLKRT_OFF)
- host->clkrt = CLKRT_OFF;
- }
- SET_REG_BITS(host, SDCLK_SEL_OFFSET, SDCLK_SEL_MASK,
- SDCLK_SEL_INIT_VAL, SD_CLK_BURST_SET);
- SET_REG_BITS(host, SD_BUS_VLT_OFFSET, SD_BUS_VLT_MASK,
- SD_BUS_VLT_18V, SD_HOST_CTRL);
- SET_REG_BIT(host, SD_BUS_POWER, SD_HOST_CTRL);
- if (mmc->bus_width == MMC_BUS_WIDTH_8) {
- SET_REG_BIT(host, MMC_CARD, SD_CE_ATA_2);
- SET_REG_BIT(host, DATA_WIDTH_8BIT, SD_CE_ATA_2);
- mmc_dbg("%s: set as 8_BIT_MODE.\n", __func__);
- } else {
- CLEAR_REG_BIT(host, MMC_CARD, SD_CE_ATA_2);
- CLEAR_REG_BIT(host, DATA_WIDTH_8BIT, SD_CE_ATA_2);
- if (mmc->bus_width == MMC_BUS_WIDTH_4) {
- SET_REG_BIT(host, DATA_WIDTH_4BIT, SD_HOST_CTRL);
- mmc_dbg("%s: set as 4_BIT_MODE.\n", __func__);
- } else {
- CLEAR_REG_BIT(host, DATA_WIDTH_4BIT, SD_HOST_CTRL);
- }
- }
+}
+static int sdh_init(struct mmc *mmc) +{
- struct pxa_sdh_host *host = mmc->priv;
- switch (host->port_num) {
- case 0:
- /* Setup the MMC/SD(1) Host Controller Clock */
- writel(0x19, 0xd4282854);
- udelay(10);
- writel(0x1B, 0xd4282854);
- break;
- case 1:
- /* Setup the MMC/SD(2) Host Controller Clock */
- writel(0x10, 0xd4282858);
- udelay(10);
- writel(0x12, 0xd4282858);
- break;
- case 2:
- /* Setup the MMC/SD(3) Host Controller Clock */
- writel(0x19, 0xd42828e0);
- udelay(10);
- writel(0x1b, 0xd42828e0);
- break;
- case 3:
- /* Setup the MMC/SD(4) Host Controller Clock */
- writel(0x10, 0xd42828e4);
- udelay(10);
- writel(0x12, 0xd42828e4);
- break;
- }
- /* Enable Interrupt status */
- SET_REG(host, 0xffff, SD_NOR_I_STAT_EN);
- SET_REG(host, 0xffff, SD_ERR_I_STAT_EN);
- /* Disable interrupt generation */
- SET_REG(host, 0, SD_NOR_INT_EN);
- SET_REG(host, 0, SD_ERR_INT_EN);
- return 0;
+}
+int pxa_sdh_init(bd_t *bis) +{
- struct mmc *mmc;
- struct pxa_sdh_host *host;
- unsigned int i;
- unsigned int mmc_base[] = {
- CONFIG_SYS_MMC_BASE,
- CONFIG_SYS_MMC1_BASE,
- CONFIG_SYS_MMC2_BASE,
- CONFIG_SYS_MMC3_BASE,
- 0
- };
- /* Initialize the controllers clock for SD1 and SD2 */
- if (mmc_base[0] != 0xFF || mmc_base[1] != 0xFF) {
- writel(0xa, 0xd4282854);
- udelay(10);
- writel(0xb, 0xd4282854);
- }
- /* Initialize the controllers clock for SD3 and SD4 */
- if (mmc_base[2] != 0xFF || mmc_base[3] != 0xFF) {
- writel(0xa, 0xd42828e0);
- udelay(10);
- writel(0xb, 0xd42828e0);
- }
- for (i = 0; mmc_base[i]; i++) {
- if (mmc_base[i] == 0xFF)
- continue;
- mmc = malloc(sizeof(struct mmc));
- if (!mmc) {
- printf("mmc malloc fail!!\n");
- return -1;
- }
- host = malloc(sizeof(struct pxa_sdh_host));
- if (!host) {
- printf("host malloc fail!!!\n");
- return -1;
- }
- host->regbase = mmc_base[i];
- host->clkrate = 48000000;
- host->clkrt = CLKRT_OFF;
- host->port_num = i;
- strncpy(mmc->name, "pxa-sdh", 7);
- mmc->priv = host;
- mmc->send_cmd = pxa_sdh_request;
- mmc->set_ios = pxa_sdh_set_ios;
- mmc->init = sdh_init;
- /*
- * Calculate minimum clock rate, rounding up.
- */
- mmc->f_min = (host->clkrate + SD_FREQ_SEL_MASK) /
- (SD_FREQ_SEL_MASK + 1);
- mmc->f_max = host->clkrate / 2;
- mmc->ocr = 0xffffffff;
- mmc->voltages = MMC_VDD_27_28|MMC_VDD_28_29;
+#ifndef CONFIG_MMC3
- mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_HS;
+#else
- mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HS;
+#endif
- mmc_register(mmc);
- }
- return 0;
+} diff --git a/drivers/mmc/pxa_sdh.h b/drivers/mmc/pxa_sdh.h new file mode 100644 index 0000000..fc48cd2 --- /dev/null +++ b/drivers/mmc/pxa_sdh.h @@ -0,0 +1,241 @@ +/**************************************************************************
- Copyright (c) 2009, 2010 Marvell International Ltd.
- This file is part of GNU program.
- GNU 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.
- GNU 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.
- *************************************************************************/
+/* register definitions of PXA SD Host Controller*/ +#define SD_SYS_ADDR_LOW 0x0000 /* DMA System Address Low */ +#define SD_SYS_ADDR_HIGH 0x0002 /* DMA System Address High */ +#define SD_BLOCK_SIZE 0x0004 /* Block Size*/ +#define SD_BLOCK_COUNT 0x0006 /* Block Count */ +#define SD_ARG_LOW 0x0008 /* Command Argument Low */ +#define SD_ARG_HIGH 0x000a /* Command Argument High */ +#define SD_TRANS_MODE 0x000c /* Transfer Mode */ +#define SD_COMMAND 0x000e /* Command */ +#define SD_RESP_0 0x0010 /* Command Response 0 */ +#define SD_RESP_1 0x0012 /* Command Response 1 */ +#define SD_RESP_2 0x0014 /* Command Response 2 */ +#define SD_RESP_3 0x0016 /* Command Response 3 */ +#define SD_RESP_4 0x0018 /* Command Response 4 */ +#define SD_RESP_5 0x001a /* Command Response 5 */ +#define SD_RESP_6 0x001c /* Command Response 6 */ +#define SD_RESP_7 0x001e /* Command Response 7 */ +#define SD_BUF_DPORT_0 0x0020 /* Buffer Data Port 0 */ +#define SD_BUF_DPORT_1 0x0022 /* Buffer Data Port 1 */ +#define SD_PRESENT_STAT_1 0x0024 /* Present State 1 */ +#define SD_PRESENT_STAT_2 0x0026 /* Present State 2 */ +#define SD_HOST_CTRL 0x0028 /* Host Control */ +#define SD_BLOCK_GAP_CTRL 0x002a /* Block Gap Control */ +#define SD_CLOCK_CNTL 0x002c /* Clock Control */ +#define SD_TO_CTRL_SW_RST 0x002e /* Timeout Control/SW Reset */ +#define SD_NOR_I_STAT 0x0030 /* Normal Interrupt Status */ +#define SD_ERR_I_STAT 0x0032 /* Error Interrupt Status */ +#define SD_NOR_I_STAT_EN 0x0034 /* Normal Interrupt Status Enable */ +#define SD_ERR_I_STAT_EN 0x0036 /* Error Interrupt Status Enable */ +#define SD_NOR_INT_EN 0x0038 /* Normal Interrupt Generation Enable */ +#define SD_ERR_INT_EN 0x003a /* Error Interrupt Generation Enable */ +#define SD_ACMD12_ERR_STAT 0x003c /* Auto CMD12 Error Status */ +#define SD_CAP_1 0x0040 /* Capabilities 1 */ +#define SD_CAP_3 0x0044 /* Capabilities 3 */ +#define SD_CAP_4 0x0046 /* Capabilities 4 */ +#define SD_MAX_CUR_1 0x0048 /* Maximum Current 1 */ +#define SD_MAX_CUR_2 0x004a /* Maximum Current 2 */ +#define SD_MAX_CUR_3 0x004c /* Maximum Current 3 */ +#define SD_MAX_CUR_4 0x004e /* Maximum Current 4 */ +#define SD_FE_ACMD12_ERR 0x0050 /* Force Event for Auto CMD12 Error */ +#define SD_FE_ERR_STAT 0x0052 /* Force Event for Error Status */ +#define SD_ADMA_ERR_STAT 0x0054 /* ADMA Error Status */ +#define SD_ADMA_SADDR_1 0x0058 /* ADMA System Address[15:0] */ +#define SD_ADMA_SADDR_2 0x005a /* ADMA System Address[31:16] */ +#define SD_ADMA_SADDR_3 0x005c /* ADMA System Address[47:32] */ +#define SD_ADMA_SADDR_4 0x005e /* ADMA System Address[64:48] */ +#define SD_FIFO_PARAM 0x00e0 /* FIRO Parameters */ +#define SD_SPI_MODE 0x00e4 /* SPI Mode */ +#define SD_CLK_BURST_SET 0x00e6 /* Clock and Burst Size Setup */ +#define SD_CE_ATA_1 0x00e8 /* CE-ATA 1 */ +#define SD_CE_ATA_2 0x00ea /* CE-ATA 2 */ +#define SD_PAD_IO_SETUP 0x00ec /* Pad I/O Setup */ +#define SD_SLOT_INT_STAT 0x00fc /* Slot Interrupt Status*/ +#define SD_HOST_CTRL_VER 0x00fe /* Host Controller Version */
+/* SD_BLOCK_SIZE */ +#define HOST_DMA_BDRY_OFFSET 12 +#define HOST_DMA_BDRY_MASK ((u16)0x7) +#define BLOCK_SIZE_OFFSET 0 +#define BLOCK_SIZE_MASK ((u16)0x0fff) +#define BLOCK_SIZE_MAX ((u16)0x0800)
+/* SD_TRANS_MODE */ +#define MULTI_BLK_SEL ((u16)1 << 5) +#define TO_HOST_DIR ((u16)1 << 4) +#define AUTO_CMD12_EN ((u16)1 << 2) +#define BLK_CNT_EN ((u16)1 << 1) +#define DMA_EN ((u16)1 << 0)
+/* SD_COMMAND */ +#define CMD_IDX_OFFSET 8 +#define CMD_IDX_MASK ((u16)0x3f) +#define CMD_TYPE_OFFSET 6 +#define CMD_TYPE_MASK ((u16)0x3) +#define CMD_TYPE_NORMAL ((u16)0x0) +#define CMD_TYPE_RESUME ((u16)0x1) +#define CMD_TYPE_SUSPEND ((u16)0x2) +#define CMD_TYPE_ABORT ((u16)0x3) +#define DATA_PRESENT ((u16)1 << 5) +#define CMD_IDX_CHK_EN ((u16)1 << 4) +#define CMD_CRC_CHK_EN ((u16)1 << 3) +#define RESP_TYPE_OFFSET 0 +#define RESP_TYPE_MASK ((u16)0x3) +/* RES_TYPE */ +#define CMD_RESP_NONE ((u16)0x0) +#define CMD_RESP_136BIT ((u16)0x1) +#define CMD_RESP_48BIT ((u16)0x2) +#define CMD_RESP_48BITB ((u16)0x3)
+/* SD_PRESENT_STAT_1 */ +#define CMD_INHBT_DAT ((u16)1 << 1) +#define CMD_INHBT_CMD ((u16)1 << 0)
+/* SD_PRESENT_STAT_2 */ +#define CARD_STABLE ((u16)1 << 1) +#define CARD_DETECTED ((u16)1 << 2) +#define CARD_PROT ((u16)1 << 3) +#define DATA_LINE_LEVEL_MASK ((u16)0xf << 4) +#define CMD_LINE_LEVEL_MASK ((u16)1 << 8)
+/* SD_HOST_CTRL */ +#define SD_BUS_VLT_OFFSET 9 +#define SD_BUS_VLT_MASK ((u16)0x7) +#define SD_BUS_VLT_18V ((u16)0x5) +#define SD_BUS_VLT_30V ((u16)0x6) +#define SD_BUS_VLT_33V ((u16)0x7) +#define SD_BUS_POWER ((u16)1 << 8) +#define DMA_SEL_OFFSET 3 +#define DMA_SEL_MASK ((u16)0x3) +#define DMA_SEL_SDMA ((u16)0) +#define DMA_SEL_ADMA1 ((u16)1) +#define DMA_SEL_ADMA2_32 ((u16)2) +#define DMA_SEL_ADMA2_64 ((u16)3) +#define HI_SPEED_EN ((u16)1 << 2) +#define DATA_WIDTH_4BIT ((u16)1 << 1)
+/* SD_BLOCK_GAP_CTRL */ +#define INT_BLK_GAP ((u16)1 << 3) +#define RD_WT_CNTL ((u16)1 << 2) +#define CONT_REQ ((u16)1 << 1) +#define STOP_AT_BLK_GAP_REQ ((u16)1 << 0)
+/* SD_CLOCK_CNTL */ +#define SD_FREQ_SEL_OFFSET 8 +#define SD_FREQ_SEL_MASK ((u16)0xff) +#define EXT_CLK_EN ((u16)1 << 2) +#define INT_CLK_STABLE ((u16)1 << 1) +#define INT_CLK_EN ((u16)1 << 0)
+/* SD_TO_CTRL_SW_RST */ +#define SW_RST_DAT ((u16)1 << 10) +#define SW_RST_CMD ((u16)1 << 9) +#define SW_RST_ALL ((u16)1 << 8) +#define DAT_TO_VAL_OFFSET 0 +#define DAT_TO_MASK ((u16)0xf)
+/* SD_NOR_I_STAT, SD_NOR_I_STAT_EN, SD_NOR_INT_EN */ +#define ERR_INT ((u16)1 << 15) /* Error Interrupt*/ +#define CARD_INT ((u16)1 << 8) /* Card Interrupt */ +#define CARD_REM ((u16)1 << 7) /* Card Removal Interrupt */ +#define CARD_INS ((u16)1 << 6) /* Card Insertion Interrupt */ +#define RX_RDY ((u16)1 << 5) /* Buffer Read Ready */ +#define TX_RDY ((u16)1 << 4) /* Buffer Write Ready */ +#define DMA_INT ((u16)1 << 3) /* DMA Interrupt */ +#define BLK_GAP_EVNT ((u16)1 << 2) /* Block Gap Event */ +#define XFER_COMP ((u16)1 << 1) /* Transfer Complete */ +#define CMD_COMP ((u16)1 << 0) /* Command Complete */ +#define SD_NOR_I_STAT_RVD_MASK ((u16)0x7e00) /* Mask for SD_NOR_I_STAT
- Reserved Bits[14 :9] */
+#define SD_NOR_INT_EN_RVD_MASK ((u16)0xfe00) /* Mask for SD_NOR_INT_EN/
- SD_NOR_I_STAT_EN Reserved Bits[15 :9] */
+/* SD_ERR_I_STAT, SD_ERR_I_STAT_EN, SD_ERR_INT_EN */ +#define CRC_STATUS_ERR ((u16)1 << 15) /* CRC Status Error Returned
- from Card in Write Transaction */
+#define CPL_TO_ERR ((u16)1 << 14) /* Command Completion Signal
- Timeout Error, for CE-ATA mode only*/
+#define AXI_RESP_ERR ((u16)1 << 13) /* AXI Bus Response Error */ +#define SPI_ERR ((u16)1 << 12) /* SPI Mode Error*/ +#define ADMA_ERR ((u16)1 << 9) /* AMDA Error */ +#define AUTO_CMD12_ERR ((u16)1 << 8) /* Auto CMD12 Error*/ +#define CUR_LIMIT_ERR ((u16)1 << 7) /* Current Limit Error*/ +#define RD_DATA_END_ERR ((u16)1 << 6) /* Read Data End Bit Error*/ +#define RD_DATA_CRC_ERR ((u16)1 << 5) /* Read Data CRC Error*/ +#define DATA_TO_ERR ((u16)1 << 4) /* Data Timeout Error*/ +#define CMD_IDX_ERR ((u16)1 << 3) /* Command Index Error*/ +#define CMD_END_BIT_ERR ((u16)1 << 2) /* Command End Bit Error*/ +#define CMD_CRC_ERR ((u16)1 << 1) /* Command CRC Error*/ +#define CMD_TO_ERR ((u16)1 << 0) /* Command Timeout Error*/
+#define SD_ERR_INT_EN_RVD_MASK ((u16)0x0c00)/* Mask for
- SD_ERR_INT_EN/SD_ERR_I_STAT_EN Reserved Bits[11 :10] */
+#define SD_ERR_INT_DATA_ERR_MASK (DATA_TO_ERR | RD_DATA_CRC_ERR | \
- RD_DATA_END_ERR) /*DATA Line Error*/
+#define SD_ERR_INT_CMD_ERR_MASK (CMD_TO_ERR | CMD_CRC_ERR | \
- CMD_END_BIT_ERR | CMD_IDX_ERR)
- /* CMD Line Error*/
+/* SD_FIFO_PARAM */ +#define DIS_PAD_SD_CLK_GATE ((u16)1 << 10) /* Turn on/off Dynamic
- SD Clock Gating */
+/* SD_CLK_BURST_SET */ +#define SDCLK_DELAY_OFFSET 10 +#define SDCLK_DELAY_MASK ((u16)0xf) +#define SDCLK_DELAY_MAX ((u16)0xf) +#define SDCLK_SEL_OFFSET 8 +#define SDCLK_SEL_MASK ((u16)0x3) +#define SDCLK_SEL_INIT_VAL ((u16)0x3) +#define DMA_BURST_SIZE ((u16)0)
+/* SD_SLOT_INT_STAT */ +#define SLOT_INT1 ((u16)1<<1) +#define SLOT_INT0 ((u16)1<<0) +#define SlOT_INT_MASK (SLOT_INT0 | SLOT_INT1)
+/* SD_CE_ATA_2 */ +#define DATA_WIDTH_8BIT ((u16)1 << 8) +#define MMC_CARD ((u16)1 << 12)
+#ifndef CONFIG_SYS_MMC_BASE +#define CONFIG_SYS_MMC_BASE 0xFF +#endif
+#ifndef CONFIG_SYS_MMC1_BASE +#define CONFIG_SYS_MMC1_BASE 0xFF +#endif
+#ifndef CONFIG_SYS_MMC2_BASE +#define CONFIG_SYS_MMC2_BASE 0xFF +#endif
+#ifndef CONFIG_SYS_MMC3_BASE +#define CONFIG_SYS_MMC3_BASE 0xFF +#endif
diff --git a/include/configs/gplugd.h b/include/configs/gplugd.h index f0fb057..16fd03e 100644 --- a/include/configs/gplugd.h +++ b/include/configs/gplugd.h @@ -109,6 +109,21 @@ #endif /*CONFIG_PXA3XX_SPI*/
/*
- SD/MMC & FAT support
- */
+#define CONFIG_PXASDH
+#ifdef CONFIG_PXASDH +#define CONFIG_CMD_MMC +#define CONFIG_MMC +#define CONFIG_CMD_FAT +#define CONFIG_DOS_PARTITION +#define CONFIG_GENERIC_MMC +#define CONFIG_SYS_MMC_BASE 0xd4280000 +#define CONFIG_SYS_MMC1_BASE 0xd4281000 +#endif /* CONFIG_PXASDH */
+/* * mv-common.h should be defined after CMD configs since it used them * to enable certain macros */ -- 1.7.0.4
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot