]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
Xilinx: ARM: Add initial SecureDigital support.
authorBrian Hill <brian.hill@xilinx.com>
Thu, 9 Dec 2010 16:29:25 +0000 (09:29 -0700)
committerGIT Repo <git@linrock7.(none)>
Fri, 4 Mar 2011 01:00:50 +0000 (18:00 -0700)
Usage:
pele-boot> mmc rescan 0
pele-boot> fatls mmc 0
  3025088   vmlinux.bin
  1048576   ramdisk1m.image
  3145728   ramdisk3m.image
  7340032   ramdisk7m.test.image

4 file(s), 0 dir(s)

pele-boot> fatload mmc 0 0x8000 vmlinux.bin
pele-boot> fatload mmc 0 0x800000 ramdisk3m.image
pele-boot> go 0x8000

board/xilinx/dfe/Makefile
board/xilinx/dfe/mmc.c [new file with mode: 0755]
board/xilinx/dfe/sd_hardware.h [new file with mode: 0644]
drivers/mmc/mmc.c
include/configs/xpele.h

index 60685221bd720a569e4b678a40d7420bf307ab19..fd435d58a3b4c69373a3ed092a73c670cae828d9 100644 (file)
@@ -34,6 +34,7 @@ COBJS := board.o \
           xilinx_nandpss.o \
           xilinx_qspipss.o \
           pele_qspi.o \
+          mmc.o \
           ../common/xbasic_types.o
 
 SOBJS  := lowlevel_init.o
diff --git a/board/xilinx/dfe/mmc.c b/board/xilinx/dfe/mmc.c
new file mode 100755 (executable)
index 0000000..64259b3
--- /dev/null
@@ -0,0 +1,321 @@
+#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;
+}
+
diff --git a/board/xilinx/dfe/sd_hardware.h b/board/xilinx/dfe/sd_hardware.h
new file mode 100644 (file)
index 0000000..53f0622
--- /dev/null
@@ -0,0 +1,90 @@
+
+#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
index 80cd9bff9bb8e23ed2fd08976d71cea56fb357fc..82c131f22c1138b8f2eec1e3e233751714dc2254 100644 (file)
@@ -922,7 +922,10 @@ static int __def_mmc_init(bd_t *bis)
 }
 
 int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
+/* The Xilinx toolchain doesn't properly override the weak symbol */
+#ifndef CONFIG_PELE
 int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
+#endif
 
 void print_mmc_devices(char separator)
 {
index 3c7879fcc49d9810338d39d72b6e7d982ff913df..6f5b3ae7e25a1f4140b60c46a866f5f7e504c07f 100644 (file)
 #endif
 #endif
 
+/* Secure Digital */
+#define CONFIG_MMC     1
+
+#ifdef CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_FAT
+#define CONFIG_DOS_PARTITION
+#endif
+
 #endif /* __CONFIG_H */