--- /dev/null
+#include <common.h>
+#include <asm/errno.h>
+#include <mmc.h>
+
+#include "sd_hardware.h"
+#include "xparameters.h"
+
+#define SD_BASEADDR XPSS_SDIO0_BASEADDR
+
+static u32 *sd_dma_buffer;
+
+/* Data Memory Barrier */
+#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")
+#define SYNCHRONIZE_IO dmb()
+
+static void sd_out32(u32 OutAddress, u32 Value)
+{
+ OutAddress += SD_BASEADDR;
+ *(volatile u32 *) OutAddress = Value;
+ SYNCHRONIZE_IO;
+}
+static void sd_out16(u32 OutAddress, u16 Value)
+{
+ OutAddress += SD_BASEADDR;
+ *(volatile u16 *) OutAddress = Value;
+ SYNCHRONIZE_IO;
+}
+static void sd_out8(u32 OutAddress, u8 Value)
+{
+ OutAddress += SD_BASEADDR;
+ *(volatile u8 *) OutAddress = Value;
+ SYNCHRONIZE_IO;
+}
+
+static u32 sd_in32(u32 InAddress)
+{
+ SYNCHRONIZE_IO;
+ InAddress += SD_BASEADDR;
+ return *(volatile u32 *) InAddress;
+}
+static u16 sd_in16(u32 InAddress)
+{
+ SYNCHRONIZE_IO;
+ InAddress += SD_BASEADDR;
+ return *(volatile u16 *) InAddress;
+}
+static u8 sd_in8(u32 InAddress)
+{
+ SYNCHRONIZE_IO;
+ InAddress += SD_BASEADDR;
+ return *(volatile u8 *) InAddress;
+}
+
+/* Initialize the SD controller */
+static void init_port(void)
+{
+ unsigned clk;
+
+ /* Power off the card */
+ sd_out8(SD_PWR_CTRL_R, 0);
+
+ /* Disable interrupts */
+ sd_out32(SD_SIG_ENA_R, 0);
+
+ /* Perform soft reset */
+ sd_out8(SD_SOFT_RST_R, SD_RST_ALL);
+ /* Wait for reset to comlete */
+ while (sd_in8(SD_SOFT_RST_R)) {
+ ;
+ }
+
+ /* Power on the card */
+ sd_out8(SD_PWR_CTRL_R, SD_POWER_33|SD_POWER_ON);
+
+ /* Enable Internal clock and wait for it to stablilize */
+ clk = (0x40 << SD_DIV_SHIFT) | SD_CLK_INT_EN;
+ sd_out16(SD_CLK_CTL_R, clk);
+ do {
+ clk = sd_in16(SD_CLK_CTL_R);
+ } while (!(clk & SD_CLK_INT_STABLE));
+
+ /* Enable SD clock */
+ clk |= SD_CLK_SD_EN;
+ sd_out16(SD_CLK_CTL_R, clk);
+
+ sd_out32(SD_SIG_ENA_R, 0xFFFFFFFF);
+ sd_out32(SD_INT_ENA_R, 0xFFFFFFFF);
+}
+
+/* MMC/SD command (SPI mode) */
+#define CMD0 (0) /* GO_IDLE_STATE */
+#define CMD1 (1) /* SEND_OP_COND */
+#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */
+#define CMD2 (2) /* SEND_CID */
+#define CMD3 (3) /* RELATIVE_ADDR */
+#define CMD5 (5) /* SLEEP_WAKE (SDC) */
+#define CMD7 (7) /* SELECT */
+#define CMD8 (8) /* SEND_IF_COND */
+#define CMD9 (9) /* SEND_CSD */
+#define CMD10 (10) /* SEND_CID */
+#define CMD12 (12) /* STOP_TRANSMISSION */
+#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */
+#define CMD16 (16) /* SET_BLOCKLEN */
+#define CMD17 (17) /* READ_SINGLE_BLOCK */
+#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
+#define CMD23 (23) /* SET_BLOCK_COUNT */
+#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
+#define CMD24 (24) /* WRITE_BLOCK */
+#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
+#define CMD41 (41) /* SEND_OP_COND (ACMD) */
+#define CMD52 (52) /* */
+#define CMD55 (55) /* APP_CMD */
+#define CMD58 (58) /* READ_OCR */
+
+/* make_command:
+ * Determing the proper value for the command register for the indicated
+ * command index.
+ */
+static int
+make_command (unsigned cmd)
+{
+ unsigned retval;
+
+ retval = cmd << 8;
+
+#define RSP_NONE SD_CMD_RESP_NONE
+#define RSP_R1 (SD_CMD_INDEX|SD_CMD_RESP_48 |SD_CMD_CRC)
+#define RSP_R1b (SD_CMD_INDEX|SD_CMD_RESP_48_BUSY|SD_CMD_CRC)
+#define RSP_R2 (SD_CMD_CRC |SD_CMD_RESP_136)
+#define RSP_R3 (SD_CMD_RESP_48)
+#define RSP_R6 (SD_CMD_INDEX|SD_CMD_RESP_48_BUSY|SD_CMD_CRC)
+
+ switch(cmd) {
+ case CMD0:
+ retval |= (SD_CMD_RESP_NONE);
+ break;
+ case CMD1:
+ retval |= RSP_R3;
+ break;
+ case CMD2:
+ retval |= RSP_R2;
+ break;
+ case CMD3:
+ retval |= RSP_R6;
+ break;
+ case CMD5:
+ retval |= RSP_R1b;
+ break;
+ case CMD7:
+ retval |= RSP_R1;
+ break;
+ case CMD8:
+ retval |= RSP_R1;
+ break;
+ case CMD9:
+ retval |= RSP_R2;
+ break;
+ case CMD10:
+ case CMD12:
+ case ACMD13:
+ case CMD16:
+ retval |= RSP_R1;
+ break;
+ case CMD17:
+ retval |= RSP_R1|SD_CMD_DATA;
+ break;
+ case CMD18:
+ case CMD23:
+ case ACMD23:
+ case CMD24:
+ case CMD25:
+ case CMD41:
+ retval |= RSP_R3;
+ break;
+ case CMD52:
+ case CMD55:
+ retval |= RSP_R1;
+ break;
+ case CMD58:
+ break;
+ }
+
+ return retval;
+}
+
+static int pele_sdh_request(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ u32 status;
+ u16 cmdreg;
+
+#ifdef DEBUG_VERBOSE
+ printf("pele_sdh_request: cmdidx: %d arg: 0x%x\n",
+ cmd->cmdidx, cmd->cmdarg);
+#endif
+
+ cmd->response[0] = 0;
+
+ /* Wait until the device is willing to accept commands */
+ do {
+ status = sd_in32(SD_PRES_STATE_R);
+ } while (status & (SD_CMD_INHIBIT|SD_DATA_INHIBIT));
+
+ /* Set the DMA address to the DMA buffer.
+ * This is only relevant for data commands.
+ * u-boot performs a copy rather than DMA directly into the user
+ * buffer because the controller can't DMA into the first 512K
+ * of DDR.
+ */
+ sd_out32(SD_DMA_ADDR_R, sd_dma_buffer);
+
+ /* 512 bytes
+ * This is only relevant for data commands.
+ */
+ sd_out16(SD_BLOCK_SZ_R, 0x200);
+ sd_out16(SD_BLOCK_CNT_R, 1);
+
+ sd_out8(SD_TIMEOUT_CTL_R, 0xA);
+
+ sd_out32(SD_ARG_R, cmd->cmdarg);
+
+ /* Set the transfer mode to read, simple DMA, single block
+ * (applicable only to data commands)
+ * This is all that this software supports.
+ */
+ sd_out16(SD_TRNS_MODE_R,
+ SD_TRNS_BLK_CNT_EN|SD_TRNS_READ|SD_TRNS_DMA);
+
+ /* Clear all pending interrupt status */
+ sd_out32(SD_INT_STAT_R, 0xFFFFFFFF);
+
+ /* Initiate the command */
+ cmdreg = make_command(cmd->cmdidx);
+ sd_out16(SD_CMD_R, cmdreg);
+
+ /* Poll until operation complete */
+ while (1) {
+ status = sd_in32(SD_INT_STAT_R);
+ if (status & SD_INT_ERROR) {
+#ifdef DEBUG
+ printf("send_cmd: Error: (0x%08x) cmd: %d arg: 0x%x\n",
+ status, cmd->cmdidx, cmd->cmdarg);
+#else
+ if (cmd->cmdidx == CMD17) {
+ printf("MMC: Error reading sector %d (0x%08x)\n",
+ cmd->cmdarg);
+ }
+#endif
+ sd_out8(SD_SOFT_RST_R,
+ SD_RST_CMD|SD_RST_DATA);
+
+ if (status & (SD_INT_ERR_CTIMEOUT|SD_INT_ERR_DTIMEOUT)) {
+ return TIMEOUT;
+ } else {
+ return COMM_ERR;
+ }
+ }
+ if (status & SD_INT_CMD_CMPL) {
+ if (cmdreg & SD_CMD_DATA) {
+ if (status & (SD_INT_DMA | SD_INT_TRNS_CMPL)) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ cmd->response[0] = sd_in32(SD_RSP_R);
+ cmd->response[1] = sd_in32(SD_RSP_R+4);
+ cmd->response[2] = sd_in32(SD_RSP_R+8);
+ cmd->response[3] = sd_in32(SD_RSP_R+12);
+
+ if (cmdreg & SD_CMD_DATA) {
+ memcpy(data->dest, sd_dma_buffer, 512);
+ }
+
+ return 0;
+}
+
+static void pele_sdh_set_ios(struct mmc *mmc)
+{
+}
+static int pele_sdh_init(struct mmc *mmc)
+{
+ init_port();
+ return 0;
+}
+
+int board_mmc_init(bd_t *bd)
+{
+ struct mmc *mmc;
+
+ sd_dma_buffer = malloc(512);
+ if (!sd_dma_buffer) {
+ return -ENOMEM;
+ }
+
+ mmc = malloc(sizeof(struct mmc));
+ if (!mmc) {
+ return -ENOMEM;
+ }
+ sprintf(mmc->name, "SDHCI");
+ mmc->send_cmd = pele_sdh_request;
+ mmc->set_ios = pele_sdh_set_ios;
+ mmc->init = pele_sdh_init;
+
+ mmc->host_caps = MMC_MODE_4BIT;
+
+ mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+#if 0
+ mmc->f_max = get_sclk();
+ mmc->f_min = mmc->f_max >> 9;
+#endif
+ mmc->block_dev.part_type = PART_TYPE_DOS;
+
+ mmc_register(mmc);
+
+ return 0;
+}
+
--- /dev/null
+
+#ifndef __SD_H__
+#define __SD_H__
+
+/*
+ * Controller register and bit definitions
+ */
+
+#define SD_DMA_ADDR_R 0x00
+
+#define SD_BLOCK_SZ_R 0x04
+
+#define SD_BLOCK_CNT_R 0x06
+
+#define SD_ARG_R 0x08
+
+#define SD_TRNS_MODE_R 0x0C
+#define SD_TRNS_DMA 0x01
+#define SD_TRNS_BLK_CNT_EN 0x02
+#define SD_TRNS_ACMD12 0x04
+#define SD_TRNS_READ 0x10
+#define SD_TRNS_MULTI 0x20
+
+#define SD_CMD_R 0x0E
+#define SD_CMD_RESP_NONE 0x00
+#define SD_CMD_RESP_136 0x01
+#define SD_CMD_RESP_48 0x02
+#define SD_CMD_RESP_48_BUSY 0x03
+#define SD_CMD_CRC 0x08
+#define SD_CMD_INDEX 0x10
+#define SD_CMD_DATA 0x20
+
+#define SD_RSP_R 0x10
+
+#define SD_BUFF_R 0x20
+
+#define SD_PRES_STATE_R 0x24
+#define SD_CMD_INHIBIT 0x00000001
+#define SD_DATA_INHIBIT 0x00000002
+#define SD_WRITE_ACTIVE 0x00000100
+#define SD_READ_ACTIVE 0x00000200
+#define SD_CARD_INS 0x00010000
+
+#define SD_HOST_CTRL_R 0x28
+
+#define SD_PWR_CTRL_R 0x29
+#define SD_POWER_ON 0x01
+#define SD_POWER_18 0x0A
+#define SD_POWER_30 0x0C
+#define SD_POWER_33 0x0E
+
+#define SD_BLCK_GAP_CTL_R 0x2A
+
+#define SD_WAKE_CTL_R 0x2B
+
+#define SD_CLK_CTL_R 0x2C
+#define SD_DIV_SHIFT 8
+#define SD_CLK_SD_EN 0x0004
+#define SD_CLK_INT_STABLE 0x0002
+#define SD_CLK_INT_EN 0x0001
+
+#define SD_TIMEOUT_CTL_R 0x2E
+
+#define SD_SOFT_RST_R 0x2F
+#define SD_RST_ALL 0x01
+#define SD_RST_CMD 0x02
+#define SD_RST_DATA 0x04
+
+#define SD_INT_STAT_R 0x30
+#define SD_INT_ENA_R 0x34
+#define SD_SIG_ENA_R 0x38
+#define SD_INT_CMD_CMPL 0x00000001
+#define SD_INT_TRNS_CMPL 0x00000002
+#define SD_INT_DMA 0x00000008
+#define SD_INT_ERROR 0x00008000
+#define SD_INT_ERR_CTIMEOUT 0x00010000
+#define SD_INT_ERR_CCRC 0x00020000
+#define SD_INT_ERR_CEB 0x00040000
+#define SD_INT_ERR_IDX 0x00080000
+#define SD_INT_ERR_DTIMEOUT 0x00100000
+#define SD_INT_ERR_DCRC 0x00200000
+#define SD_INT_ERR_DEB 0x00400000
+#define SD_INT_ERR_CLMT 0x00800000
+#define SD_INT_ERR_ACMD12 0x01000000
+#define SD_INT_ERR_ADMA 0x02000000
+#define SD_INT_ERR_TRESP 0x10000000
+
+#define SD_CAPABILITIES_R 0x40
+
+#endif