diff options
-rw-r--r-- | board/st-ericsson/snowball/Makefile | 12 | ||||
-rw-r--r-- | board/st-ericsson/snowball/mmc_fifo.S | 146 | ||||
-rw-r--r-- | board/st-ericsson/snowball/mmc_fifo.h | 45 | ||||
-rw-r--r-- | board/st-ericsson/snowball/mmc_host.c | 589 | ||||
-rw-r--r-- | board/st-ericsson/snowball/mmc_host.h | 302 | ||||
-rw-r--r-- | board/st-ericsson/snowball/mmc_utils.c | 180 | ||||
-rw-r--r-- | board/st-ericsson/snowball/snowball.c | 124 |
7 files changed, 124 insertions, 1274 deletions
diff --git a/board/st-ericsson/snowball/Makefile b/board/st-ericsson/snowball/Makefile index 560ed118c..61382960b 100644 --- a/board/st-ericsson/snowball/Makefile +++ b/board/st-ericsson/snowball/Makefile @@ -25,20 +25,18 @@ include $(TOPDIR)/config.mk CFLAGS += -D__RELEASE -D__STN_8500 LIB = $(obj)lib$(BOARD).o -COBJS := snowball.o mmc_host.o mmc_utils.o -SOBJS := mmc_fifo.o +COBJS := snowball.o #prcmu.o -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +SRCS := $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) -SOBJS := $(addprefix $(obj),$(SOBJS)) -$(LIB): $(obj).depend $(OBJS) $(SOBJS) - $(call cmd_link_o_target, $(OBJS) $(SOBJS)) +$(LIB): $(obj).depend $(OBJS) + $(call cmd_link_o_target, $(OBJS)) clean: - rm -f $(SOBJS) $(OBJS) + rm -f $(OBJS) distclean: clean rm -f $(LIB) core *.bak $(obj).depend diff --git a/board/st-ericsson/snowball/mmc_fifo.S b/board/st-ericsson/snowball/mmc_fifo.S deleted file mode 100644 index 44911a8d5..000000000 --- a/board/st-ericsson/snowball/mmc_fifo.S +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Martin Lundholm <martin.xa.lundholm@stericsson.com> - * - * License terms: GNU General Public License (GPL), version 2. - */ - -#include "mmc_fifo.h" -#include "mmc_host.h" - -/* - * Function: mmc_fifo_read() - * - * int mmc_fifo_read(u32 *fifo, u32 *buf, unsigned int count, u32 *status_reg) - * - * Info: Reads data from an MMC (ARM PL180) FIFO - * - * Parameters: - * fifo - pointer to the first PL180 FIFO register - * buf - pointer to a read buffer (32-bit aligned) - * count - number of bytes to be read (32-bit aligned) - * status_reg - pointer to the PL180 status register - * - * Returns '0' if success and PL180 status on failure. - * - */ - - .globl mmc_fifo_read -mmc_fifo_read: - push {r4-r10,lr} -mmc_fifo_read_loop_32_1: - /* If count is <32B read word-wise */ - cmp r2,#32 - blo mmc_fifo_read_loop_4_1 -mmc_fifo_read_loop_32_2: - /* Load SDI_STA to r4 */ - ldr r4,[r3] - /* Exit if SDI_STA_DCRCFAIL or SDI_STA_DTIMEOUT is set */ - ands r5,r4,#(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT) - bne mmc_fifo_read_fail - /* Wait until SDI_STA_RXFIFOBR is set */ - tst r4,#SDI_STA_RXFIFOBR - beq mmc_fifo_read_loop_32_2 - /* Load and store 8 words */ - ldmia r0,{r4-r10,lr} - stmia r1!,{r4-r10,lr} - subs r2,r2,#32 - b mmc_fifo_read_loop_32_1 -mmc_fifo_read_loop_4_1: - /* Read word wise */ - cmp r2,#4 - blo mmc_fifo_read_ok -mmc_fifo_read_loop_4_2: - /* Load SDI_STA to r4 */ - ldr r4,[r3] - /* Exit if SDI_STA_DCRCFAIL or SDI_STA_DTIMEOUT is set */ - ands r5,r4,#(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT) - bne mmc_fifo_read_fail - /* Wait until SDI_STA_RXDAVL is set */ - tst r4,#SDI_STA_RXDAVL - beq mmc_fifo_read_loop_4_2 - /* Load and store 1 word */ - ldmia r0,{r4} - stmia r1!,{r4} - subs r2,r2,#4 - b mmc_fifo_read_loop_4_1 -mmc_fifo_read_ok: - /* Wait until SDI_STA_DBCKEND and SDI_STA_DATAEND are set */ - ldr r4,[r3] - ands r5,r4,#(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT) - bne mmc_fifo_read_fail - and r5,r4,#(SDI_STA_DBCKEND | SDI_STA_DATAEND) - cmp r5,#(SDI_STA_DBCKEND | SDI_STA_DATAEND) - bne mmc_fifo_read_ok -mmc_fifo_read_fail: - mov r0,r4 - pop {r4-r10,pc} - -/* - * Function: mmc_fifo_write() - * - * int mmc_fifo_write(u32 *buf, u32 *fifo, unsigned int count, u32 *status_reg) - * - * Info: Writes data to an MMC (ARM PL180) FIFO - * - * Parameters: - * buf - pointer to a write buffer (32-bit aligned) - * fifo - pointer to the first PL180 FIFO register - * count - number of bytes to be written (32-bit aligned) - * status_reg - pointer to the PL180 status register - * - * Returns '0' if success and PL180 status on failure. - * - */ - - .globl mmc_fifo_write -mmc_fifo_write: - push {r4-r10,lr} -mmc_fifo_write_loop_32_1: - /* If count is <32B read word-wise */ - cmp r2,#32 - blo mmc_fifo_write_loop_4_1 -mmc_fifo_write_loop_32_2: - /* Load SDI_STA to r4 */ - ldr r4,[r3] - /* Exit if SDI_STA_DCRCFAIL or SDI_STA_DTIMEOUT is set */ - ands r5,r4,#(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT) - bne mmc_fifo_write_fail - /* Wait until SDI_STA_TXFIFOBW is set */ - tst r4,#SDI_STA_TXFIFOBW - beq mmc_fifo_write_loop_32_2 - /* Load and store 8 words */ - ldmia r0!,{r4-r10,lr} - stmia r1,{r4-r10,lr} - subs r2,r2,#32 - b mmc_fifo_write_loop_32_1 -mmc_fifo_write_loop_4_1: - /* Read word wise */ - cmp r2,#4 - blo mmc_fifo_write_ok -mmc_fifo_write_loop_4_2: - /* Load SDI_STA to r4 */ - ldr r4,[r3] - /* Exit if SDI_STA_DCRCFAIL or SDI_STA_DTIMEOUT is set */ - ands r5,r4,#(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT) - bne mmc_fifo_write_fail - /* Wait until SDI_STA_TXFIFOBW is set */ - tst r4,#SDI_STA_TXFIFOBW - beq mmc_fifo_write_loop_4_2 - /* Load and store 1 word */ - ldmia r0!,{r4} - stmia r1,{r4} - subs r2,r2,#4 - b mmc_fifo_write_loop_4_1 -mmc_fifo_write_ok: - /* Wait until SDI_STA_DBCKEND and SDI_STA_DATAEND are set */ - ldr r4,[r3] - ands r5,r4,#(SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT) - bne mmc_fifo_write_fail - and r5,r4,#(SDI_STA_DBCKEND | SDI_STA_DATAEND) - cmp r5,#(SDI_STA_DBCKEND | SDI_STA_DATAEND) - bne mmc_fifo_write_ok -mmc_fifo_write_fail: - mov r0,r4 - pop {r4-r10,pc} diff --git a/board/st-ericsson/snowball/mmc_fifo.h b/board/st-ericsson/snowball/mmc_fifo.h deleted file mode 100644 index e2fb0a53b..000000000 --- a/board/st-ericsson/snowball/mmc_fifo.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Martin Lundholm <martin.xa.lundholm@stericsson.com> - * - * License terms: GNU General Public License (GPL), version 2. - */ - -#include <common.h> - -#ifndef __ASSEMBLY__ - -/* - * Function: mmc_fifo_read() - * - * Info: Reads data from an MMC (ARM PL180) FIFO - * - * Parameters: - * fifo - pointer to the first PL180 FIFO register - * buf - pointer to a read buffer (32-bit aligned) - * count - number of bytes to be read (32-bit aligned) - * status_reg - pointer to the PL180 status register - * - * Returns '0' if success and PL180 status on failure. - * - */ -int mmc_fifo_read(u32 *fifo, u32 *buf, unsigned int count, u32 *status_reg); - -/* - * Function: mmc_fifo_write() - * - * Info: Writes data to an MMC (ARM PL180) FIFO - * - * Parameters: - * buf - pointer to a write buffer (32-bit aligned) - * fifo - pointer to the first PL180 FIFO register - * count - number of bytes to be written (32-bit aligned) - * status_reg - pointer to the PL180 status register - * - * Returns '0' if success and PL180 status on failure. - * - */ -int mmc_fifo_write(u32 *buf, u32 *fifo, unsigned int count, u32 *status_reg); - -#endif /* __ASSEMBLY__ */ diff --git a/board/st-ericsson/snowball/mmc_host.c b/board/st-ericsson/snowball/mmc_host.c deleted file mode 100644 index 4e5c0e39a..000000000 --- a/board/st-ericsson/snowball/mmc_host.c +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Ulf Hansson <ulf.hansson@stericsson.com> - * Author: Martin Lundholm <martin.xa.lundholm@stericsson.com> - * - * License terms: GNU General Public License (GPL), version 2. - */ - -/* - * There are two levels of debug printouts in this file. The macro DEBUG can be - * set to either DBG_LVL_INFO (1) or DBG_LVL_VERBOSE (2). - */ -#define DBG_LVL_INFO (1) -#define DBG_LVL_VERBOSE (2) - -#include <asm/io.h> -#include <asm/arch/common.h> -#include <asm/arch/cpu.h> -#include <mmc.h> -#include "mmc_host.h" -#include <malloc.h> -#include <div64.h> -#include "mmc_fifo.h" - - -struct mmc_host { - struct sdi_registers *base; -}; - -/* - * wait_for_command_end() - waiting for the command completion - * this function will wait until the command completion has happened or - * any error generated by reading the status register - */ -static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd) -{ - u32 hoststatus, statusmask; - struct mmc_host *host = dev->priv; - - statusmask = SDI_STA_CTIMEOUT | SDI_STA_CCRCFAIL; - if ((cmd->resp_type & MMC_RSP_PRESENT)) - statusmask |= SDI_STA_CMDREND; - else - statusmask |= SDI_STA_CMDSENT; - - do - hoststatus = readl(&host->base->status) & statusmask; - while (!hoststatus); - - debugX(DBG_LVL_VERBOSE, "SDI_ICR <= 0x%08X\n", statusmask); - writel(statusmask, &host->base->status_clear); - - if (hoststatus & SDI_STA_CTIMEOUT) { - debugX(DBG_LVL_VERBOSE, "CMD%d time out\n", cmd->cmdidx); - return TIMEOUT; - } else if ((hoststatus & SDI_STA_CCRCFAIL) && - (cmd->flags & MMC_RSP_CRC)) { - debugX(DBG_LVL_VERBOSE, "CMD%d CRC error\n", cmd->cmdidx); - return MMC_CMD_CRC_FAIL; - } - - if (cmd->resp_type & MMC_RSP_PRESENT) { - cmd->response[0] = readl(&host->base->response0); - cmd->response[1] = readl(&host->base->response1); - cmd->response[2] = readl(&host->base->response2); - cmd->response[3] = readl(&host->base->response3); - debugX(DBG_LVL_VERBOSE, - "CMD%d response[0]:0x%08X, response[1]:0x%08X, " - "response[2]:0x%08X, response[3]:0x%08X\n", - cmd->cmdidx, cmd->response[0], cmd->response[1], - cmd->response[2], cmd->response[3]); - } - return MMC_OK; -} - -/* - * do_command - sends command to card, and waits for its result. - */ -static int do_command(struct mmc *dev, struct mmc_cmd *cmd) -{ - int result; - u32 sdi_cmd = 0; - struct mmc_host *host = dev->priv; - u32 lap = 0; - - debugX(DBG_LVL_VERBOSE, "Request to do CMD%d on %s\n", cmd->cmdidx, - dev->name); - - sdi_cmd = (cmd->cmdidx & SDI_CMD_CMDINDEX_MASK) | SDI_CMD_CPSMEN; - - if (cmd->resp_type) { - sdi_cmd |= SDI_CMD_WAITRESP; - if (cmd->resp_type & MMC_RSP_136) - sdi_cmd |= SDI_CMD_LONGRESP; - } - - debugX(DBG_LVL_VERBOSE, "SDI_ARG <= 0x%08X\n", cmd->cmdarg); - writel((u32)cmd->cmdarg, &host->base->argument); - udelay(COMMAND_REG_DELAY); /* DONT REMOVE */ - debugX(DBG_LVL_VERBOSE, "SDI_CMD <= 0x%08X\n", sdi_cmd); - - /* - * It has been noticed that after a write operation some cards does - * not respond to a new command for a few milliseconds. So here we - * retry the command a couple of times if we get a timeout. - */ - do { - writel(sdi_cmd, &host->base->command); - result = wait_for_command_end(dev, cmd); - if ((result != TIMEOUT) || (lap >= 10)) - break; - udelay(1000); - lap++; - } while (1); - - /* After CMD2 set RCA to a none zero value. */ - if ((result == MMC_OK) && (cmd->cmdidx == MMC_CMD_ALL_SEND_CID)) - dev->rca = 10; - - /* After CMD3 open drain is switched off and push pull is used. */ - if ((result == MMC_OK) && (cmd->cmdidx == MMC_CMD_SET_RELATIVE_ADDR)) { - u32 sdi_pwr = readl(&host->base->power) & ~SDI_PWR_OPD; - debugX(DBG_LVL_VERBOSE, "SDI_PWR <= 0x%08X\n", sdi_pwr); - writel(sdi_pwr, &host->base->power); - } - - return result; -} - -static int convert_from_bytes_to_power_of_two(unsigned int x) -{ - int y = 0; - y = (x & 0xAAAA) ? 1 : 0; - y |= ((x & 0xCCCC) ? 1 : 0)<<1; - y |= ((x & 0xF0F0) ? 1 : 0)<<2; - y |= ((x & 0xFF00) ? 1 : 0)<<3; - - return y; -} - -/* - * read_bytes - reads bytes from the card, part of data transfer. - */ -static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize) -{ - u64 xfercount = blkcount * blksize; - struct mmc_host *host = dev->priv; - u32 status; - - debugX(DBG_LVL_VERBOSE, "read_bytes: blkcount=%u blksize=%u\n", - blkcount, blksize); - - status = mmc_fifo_read(&host->base->fifo, dest, xfercount, - &host->base->status); - - if (status & (SDI_STA_DTIMEOUT | SDI_STA_DCRCFAIL)) { - printf("Reading data failed: status:0x%08X\n", status); - if (status & SDI_STA_DTIMEOUT) - return MMC_DATA_TIMEOUT; - else if (status & SDI_STA_DCRCFAIL) - return MMC_DATA_CRC_FAIL; - } - - debugX(DBG_LVL_VERBOSE, "SDI_ICR <= 0x%08X\n", SDI_ICR_MASK); - writel(SDI_ICR_MASK, &host->base->status_clear); - debugX(DBG_LVL_VERBOSE, "Reading data completed status:0x%08X\n", - status); - - return MMC_OK; -} - -/* - * write_bytes - writes byte to the card, part of data transfer. - */ -static int write_bytes(struct mmc *dev, u32 *src, u32 blkcount, u32 blksize) -{ - u64 xfercount = blkcount * blksize; - struct mmc_host *host = dev->priv; - u32 status; - u32 status_busy; - - debugX(DBG_LVL_VERBOSE, "write_bytes: blkcount=%u blksize=%u\n", - blkcount, blksize); - - status = mmc_fifo_write(src, &host->base->fifo, xfercount, - &host->base->status); - - if (status & (SDI_STA_DTIMEOUT | SDI_STA_DCRCFAIL)) { - printf("Writing data failed: status=0x%08X\n", status); - if (status & SDI_STA_DTIMEOUT) - return MMC_DATA_TIMEOUT; - else if (status & SDI_STA_DCRCFAIL) - return MMC_DATA_CRC_FAIL; - } - - /* Wait if busy */ - status_busy = status & SDI_STA_CARDBUSY; - while (status_busy) - status_busy = readl(&host->base->status) & SDI_STA_CARDBUSY; - - writel(SDI_ICR_MASK, &host->base->status_clear); - debugX(DBG_LVL_VERBOSE, "Writing data completed status:0x%08X\n", - status); - - return MMC_OK; -} - -/* - * do_data_transfer - for doing any data transfer operation. - * - * dev: mmc device for doing the operation on. - * cmd: cmd to do. - * data: if cmd warrants any data transfer. - */ -static int do_data_transfer(struct mmc *dev, - struct mmc_cmd *cmd, - struct mmc_data *data) -{ -#if (DEBUG >= DBG_LVL_INFO) - u32 start_time = 0; -#endif - int error = MMC_DATA_TIMEOUT; - struct mmc_host *host = dev->priv; - u32 blksz = 0; - u32 data_ctrl = 0; - u32 data_len = (u32) (data->blocks * data->blocksize); - - debugX(DBG_LVL_VERBOSE, "Request to do data xfer on %s\n", dev->name); - debugX(DBG_LVL_VERBOSE, "do_data_transfer(%u) start\n", data->blocks); - -#if (DEBUG >= DBG_LVL_INFO) - // if (data->blocks > 1) - // start_time = (u32) get_timer_us(); -#endif - - if (cpu_is_u8500v1() || u8500_is_earlydrop()) { - blksz = convert_from_bytes_to_power_of_two(data->blocksize); - data_ctrl |= (blksz << INDEX(SDI_DCTRL_DBLOCKSIZE_MASK)); - } else { - blksz = data->blocksize; - data_ctrl |= (blksz << INDEX(SDI_DCTRL_DBLOCKSIZE_V2_MASK)); - } - data_ctrl |= SDI_DCTRL_DTEN | SDI_DCTRL_BUSYMODE; - if (dev->ddr_en && - ((cmd->cmdidx == MMC_CMD_READ_SINGLE_BLOCK) || - (cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK) || - (cmd->cmdidx == MMC_CMD_WRITE_SINGLE_BLOCK) || - (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK) || - (cmd->cmdidx == MMC_CMD_SEND_EXT_CSD))) - data_ctrl |= SDI_DCTRL_DDR_MODE; - -#if (DEBUG >= DBG_LVL_VERBOSE) - if (data_ctrl & SDI_DCTRL_DDR_MODE) - printf("SDI_DCTRL_DDR_MODE\n"); -#endif - - debugX(DBG_LVL_VERBOSE, "SDI_DTIMER <= 0x%08X\n", dev->data_timeout); - writel(dev->data_timeout, &host->base->datatimer); - debugX(DBG_LVL_VERBOSE, "SDI_DLEN <= 0x%08X\n", data_len); - writel(data_len, &host->base->datalength); - udelay(DATA_REG_DELAY); /* DONT REMOVE */ - - if (data->flags & (MMC_DATA_READ)) { - debugX(DBG_LVL_VERBOSE, "It is a read operation\n"); - - data_ctrl |= SDI_DCTRL_DTDIR_IN; - debugX(DBG_LVL_VERBOSE, "SDI_DCTRL <= 0x%08X\n", data_ctrl); - writel(data_ctrl, &host->base->datactrl); - - error = do_command(dev, cmd); - if (error) - return error; - - error = read_bytes(dev, - (u32 *)data->dest, - (u32)data->blocks, - (u32)data->blocksize); - } else if (data->flags & (MMC_DATA_WRITE)) { - debugX(DBG_LVL_VERBOSE, "It is a write operation\n"); - - error = do_command(dev, cmd); - if (error) - return error; - - debugX(DBG_LVL_VERBOSE, "SDI_DCTRL <= 0x%08X\n", data_ctrl); - writel(data_ctrl, &host->base->datactrl); - - error = write_bytes(dev, - (u32 *)data->src, - (u32)data->blocks, - (u32)data->blocksize); - } - -#if (DEBUG >= DBG_LVL_INFO) -#if 0 - if (data->blocks > 1) { - u32 transfer_time = (u32) get_timer_us() - start_time; - u64 throughput = lldiv((u64) 1000 * 1000 * data->blocks * - data->blocksize, transfer_time); - printf("MMC %s: %u bytes in %u [us] => %llu [B/s] = " - "%llu [kB/s] = %llu.%02u [MB/s] = %llu [Mbits/s]\n", - (data->flags & (MMC_DATA_READ)) ? "read" : "write", - data->blocks * data->blocksize, - transfer_time, - throughput, throughput / 1024, - throughput / (1024 * 1024), - (u32)((100 * throughput) / (1024 * 1024) - - (throughput / (1024 * 1024)) * 100), - throughput * 8 / (1024 * 1024)); - } -#endif -#endif - debugX(DBG_LVL_VERBOSE, "do_data_transfer() end\n"); - - return error; -} - -/* - * host_request - For all operations on cards. - * - * dev: mmc device for doing the operation on. - * cmd: cmd to do. - * data: if cmd warrants any data transfer. - */ -static int host_request(struct mmc *dev, - struct mmc_cmd *cmd, - struct mmc_data *data) -{ - int result; - - if (data) - result = do_data_transfer(dev, cmd, data); - else - result = do_command(dev, cmd); - - return result; -} - -/* - * This is to initialize card specific things just before enumerating - * them. MMC cards uses open drain drivers in enumeration phase. - */ -static int mmc_host_reset(struct mmc *dev) -{ - struct mmc_host *host = dev->priv; - u32 sdi_u32 = SDI_PWR_OPD | SDI_PWR_PWRCTRL_ON; - - debugX(DBG_LVL_VERBOSE, "SDI_PWR <= 0x%08X\n", sdi_u32); - writel(sdi_u32, &host->base->power); - return MMC_OK; -} - -/* - * This is to initialize card specific things just before enumerating - * them. SD cards does not need to be initialized. - */ -static int sd_host_reset(struct mmc *dev) -{ - (void) dev; /* Parameter not used! */ - - return MMC_OK; -} -/* - * host_set_ios:to configure host parameters. - * - * dev: the pointer to the host structure for MMC. - */ -static void host_set_ios(struct mmc *dev) -{ - struct mmc_host *host = dev->priv; - u32 sdi_clkcr; - - /* First read out the contents of clock control register. */ - sdi_clkcr = readl(&host->base->clock); - - /* Set the clock rate and bus width */ - if (dev->clock) { - u32 clkdiv = 0; - u32 tmp_clock; - - debugX(DBG_LVL_VERBOSE, - "setting clock and bus width in the host:"); - if (dev->clock >= dev->f_max) { - clkdiv = 0; - dev->clock = dev->f_max; - } else { - clkdiv = (MCLK / dev->clock) - 2; - } - tmp_clock = MCLK / (clkdiv + 2); - while (tmp_clock > dev->clock) { - clkdiv++; - tmp_clock = MCLK / (clkdiv + 2); - } - if (clkdiv > SDI_CLKCR_CLKDIV_MASK) - clkdiv = SDI_CLKCR_CLKDIV_MASK; - tmp_clock = MCLK / (clkdiv + 2); - dev->clock = tmp_clock; - sdi_clkcr &= ~(SDI_CLKCR_CLKDIV_MASK); - sdi_clkcr |= clkdiv; - } - - if (dev->bus_width) { - u32 buswidth = 0; - - switch (dev->bus_width) { - case 1: - buswidth |= SDI_CLKCR_WIDBUS_1; - break; - case 4: - buswidth |= SDI_CLKCR_WIDBUS_4; - break; - case 8: - buswidth |= SDI_CLKCR_WIDBUS_8; - break; - default: - printf("wrong bus width, so ignoring"); - break; - } - sdi_clkcr &= ~(SDI_CLKCR_WIDBUS_MASK); - sdi_clkcr |= buswidth; - } - - - dev->data_timeout = MMC_DATA_TIMEOUT * dev->clock; - - debugX(DBG_LVL_VERBOSE, "SDI_CLKCR <= 0x%08X\n", sdi_clkcr); - writel(sdi_clkcr, &host->base->clock); - udelay(CLK_CHANGE_DELAY); -} - -struct mmc *alloc_mmc_struct(void) -{ - struct mmc_host *host = NULL; - struct mmc *mmc_device = NULL; - - host = malloc(sizeof(struct mmc_host)); - if (!host) - return NULL; - - mmc_device = malloc(sizeof(struct mmc)); - if (!mmc_device) - goto err; - - memset(mmc_device, 0x00, sizeof(struct mmc)); - - mmc_device->priv = host; - return mmc_device; - err: - free(host); - return NULL; -} - -/* - * emmc_host_init - initialize the emmc controller. - * Configure GPIO settings, set initial clock and power for emmc slot. - * Initialize mmc struct and register with mmc framework. - */ -static int emmc_host_init(struct mmc *dev) -{ - struct mmc_host *host = dev->priv; - u32 sdi_u32; - - /* TODO: Investigate what is actually needed of the below. */ - - if (u8500_is_earlydrop() || u8500_is_snowball()) { - debugX(DBG_LVL_VERBOSE, "configuring EMMC for ED\n"); - host->base = (struct sdi_registers *)CFG_EMMC_BASE_ED; - } else { - debugX(DBG_LVL_VERBOSE, "configuring EMMC for V1\n"); - host->base = (struct sdi_registers *)CFG_EMMC_BASE_V1; - } - - sdi_u32 = SDI_PWR_OPD | SDI_PWR_PWRCTRL_ON; - debugX(DBG_LVL_VERBOSE, "SDI_PWR <= 0x%08X\n", sdi_u32); - writel(sdi_u32, &host->base->power); - /* setting clk freq less than 400KHz */ - sdi_u32 = SDI_CLKCR_CLKDIV_INIT | SDI_CLKCR_CLKEN | SDI_CLKCR_HWFC_EN; - debugX(DBG_LVL_VERBOSE, "SDI_CLKCR <= 0x%08X\n", sdi_u32); - writel(sdi_u32, &host->base->clock); - udelay(CLK_CHANGE_DELAY); - sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK; - debugX(DBG_LVL_VERBOSE, "SDI_MASK0 <= 0x%08X\n", sdi_u32); - writel(sdi_u32, &host->base->mask0); - dev->clock = MCLK / (2 + SDI_CLKCR_CLKDIV_INIT); - sprintf(dev->name, "EMMC"); - dev->send_cmd = host_request; - dev->set_ios = host_set_ios; - dev->init = mmc_host_reset; - dev->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HS | - MMC_MODE_HS_52MHz /* | MMC_MODE_REL_WR | MMC_MODE_DDR */; - dev->voltages = VOLTAGE_WINDOW_MMC; - dev->f_min = dev->clock; - dev->f_max = MCLK / 2; - dev->ddr_en = 0; - return 0; -} - -/* - * mmc_host_init - initialize the external mmc controller. - * Configure GPIO settings, set initial clock and power for mmc slot. - * Initialize mmc struct and register with mmc framework. - */ -static int mmc_host_init(struct mmc *dev) -{ - struct mmc_host *host = dev->priv; - u32 sdi_u32; - - host->base = (struct sdi_registers *)CFG_MMC_BASE; - sdi_u32 = 0xBF; - debugX(DBG_LVL_VERBOSE, "SDI_PWR <= 0x%08X\n", sdi_u32); - writel(sdi_u32, &host->base->power); - /* setting clk freq just less than 400KHz */ - sdi_u32 = SDI_CLKCR_CLKDIV_INIT | SDI_CLKCR_CLKEN | SDI_CLKCR_HWFC_EN; - debugX(DBG_LVL_VERBOSE, "SDI_CLKCR <= 0x%08X\n", sdi_u32); - writel(sdi_u32, &host->base->clock); - udelay(CLK_CHANGE_DELAY); - sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK; - debugX(DBG_LVL_VERBOSE, "SDI_MASK0 <= 0x%08X\n", sdi_u32); - writel(sdi_u32, &host->base->mask0); - dev->clock = MCLK / (2 + SDI_CLKCR_CLKDIV_INIT); - sprintf(dev->name, "MMC"); - dev->send_cmd = host_request; - dev->set_ios = host_set_ios; - dev->init = sd_host_reset; - dev->host_caps = /* MMC_MODE_4BIT */ 0; /* Some SD cards do not work in - 4 bit mode! */ - dev->voltages = VOLTAGE_WINDOW_SD; - dev->f_min = dev->clock; - dev->f_max = MCLK / 2; - dev->ddr_en = 0; - return 0; -} - -/* - * board_mmc_init - initialize all the mmc/sd host controllers. - * Called by generic mmc framework. - */ -int board_mmc_init(bd_t *bis) -{ - int error; - struct mmc *dev; - - debugX(DBG_LVL_VERBOSE, "[%s] mmc_host - board_mmc_init board ed %d, snow %d\n", - __func__,u8500_is_earlydrop(), u8500_is_snowball()); - - (void) bis; /* Parameter not used! */ - - dev = alloc_mmc_struct(); - if (!dev) - return -1; - - error = emmc_host_init(dev); - if (error) { - printf("emmc_host_init() %d \n", error); - return -1; - } - mmc_register(dev); - debugX(DBG_LVL_VERBOSE, "registered emmc interface number is:%d\n", - dev->block_dev.dev); - - - mmc_init(dev); - - /* - * In a perfect world board_early_access shouldn't be here but we want - * some functionality to be loaded as quickly as possible and putting it - * here will get the shortest time to start that functionality. Time - * saved by putting it here compared to later is somewhere between - * 0.3-0.7s. That is enough to be able to justify putting it here. - */ - - board_early_access(&dev->block_dev); - - dev = alloc_mmc_struct(); - if (!dev) - return -1; - - error = mmc_host_init(dev); - if (error) { - printf("mmc_host_init() %d \n", error); - return -1; - } - mmc_register(dev); - debugX(DBG_LVL_VERBOSE, "registered mmc/sd interface number is:%d\n", - dev->block_dev.dev); - - return 0; -} diff --git a/board/st-ericsson/snowball/mmc_host.h b/board/st-ericsson/snowball/mmc_host.h deleted file mode 100644 index 3b5e1c589..000000000 --- a/board/st-ericsson/snowball/mmc_host.h +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Ulf Hansson <ulf.hansson@stericsson.com> - * Author: Martin Lundholm <martin.xa.lundholm@stericsson.com> - * - * License terms: GNU General Public License (GPL), version 2. - */ - -#ifndef __MMC_NOMADIK_H__ -#define __MMC_NOMADIK_H__ - -/* See SDI (SD card host interface) documentation in U8500 sw specification. */ - -#define COMMAND_REG_DELAY 300 -#define DATA_REG_DELAY 10000 -#define CLK_CHANGE_DELAY 2000 - -#define MAX_ERROR_VALUE -65 -#ifndef __ASSEMBLY__ -enum mmc_result { - /* MMC specific error defines */ - MMC_CMD_CRC_FAIL = (MAX_ERROR_VALUE - 1),/* Command response received - (but CRC check failed) */ - MMC_DATA_CRC_FAIL = (MAX_ERROR_VALUE - 2),/* Data bock sent/received - (CRC check Failed) */ - MMC_CMD_RSP_TIMEOUT = (MAX_ERROR_VALUE - 3),/*Command response timeout - */ - MMC_DATA_TIMEOUT = (MAX_ERROR_VALUE - 4),/* Data time out*/ - MMC_TX_UNDERRUN = (MAX_ERROR_VALUE - 5),/* Transmit FIFO under-run */ - MMC_RX_OVERRUN = (MAX_ERROR_VALUE - 6), /* Receive FIFO over-run */ - MMC_START_BIT_ERR = (MAX_ERROR_VALUE - 7),/* Start bit not detected on - all data signals in widE bus mode */ - MMC_CMD_OUT_OF_RANGE = (MAX_ERROR_VALUE - 8),/* CMD's argument was out - of range.*/ - MMC_ADDR_MISALIGNED = (MAX_ERROR_VALUE - 9),/* Misaligned address */ - MMC_BLOCK_LEN_ERR = (MAX_ERROR_VALUE - 10),/* Transferred block length - is not allowed for the card or the number of - transferred bytes does not match the block length*/ - MMC_ERASE_SEQ_ERR = (MAX_ERROR_VALUE - 11),/* An error in the sequence - of erase command occurs.*/ - MMC_BAD_ERASE_PARAM = (MAX_ERROR_VALUE - 12),/* An Invalid selection - for erase groups */ - MMC_WRITE_PROT_VIOLATION = (MAX_ERROR_VALUE - 13),/* Attempt to program - a write protect block */ - MMC_LOCK_UNLOCK_FAILED = (MAX_ERROR_VALUE - 14),/* Sequence or password - error has been detected in unlock command or - if there was an attempt to access a locked card */ - MMC_COM_CRC_FAILED = (MAX_ERROR_VALUE - 15),/* CRC check of the - previous command failed*/ - MMC_ILLEGAL_CMD = (MAX_ERROR_VALUE - 16),/* Command is not legal for - the card state */ - MMC_CARD_ECC_FAILED = (MAX_ERROR_VALUE - 17),/* Card internal ECC was - applied but failed to correct the data */ - MMC_CC_ERROR = (MAX_ERROR_VALUE - 18),/*Internal card controller error - */ - MMC_GENERAL_UNKNOWN_ERROR = (MAX_ERROR_VALUE - 19),/* General or - Unknown error */ - MMC_STREAM_READ_UNDERRUN = (MAX_ERROR_VALUE - 20),/* The card could not - sustain data transfer in stream read - operation. */ - MMC_STREAM_WRITE_OVERRUN = (MAX_ERROR_VALUE - 21),/* The card could not - sustain data programming in stream mode */ - MMC_CID_CSD_OVERWRITE = (MAX_ERROR_VALUE - 22), /* CID/CSD overwrite - error */ - MMC_WP_ERASE_SKIP = (MAX_ERROR_VALUE - 23),/* only partial address - space was erased */ - MMC_CARD_ECC_DISABLED = (MAX_ERROR_VALUE - 24),/* Command has been - executed without using internal ECC */ - MMC_ERASE_RESET = (MAX_ERROR_VALUE - 25),/* Erase sequence was cleared - before executing because an out of erase sequence - command was received */ - MMC_AKE_SEQ_ERROR = (MAX_ERROR_VALUE - 26),/* Error in sequence of - authentication. */ - MMC_INVALID_VOLTRANGE = (MAX_ERROR_VALUE - 27), - MMC_ADDR_OUT_OF_RANGE = (MAX_ERROR_VALUE - 28), - MMC_SWITCH_ERROR = (MAX_ERROR_VALUE - 29), - MMC_SDIO_DISABLED = (MAX_ERROR_VALUE - 30), - MMC_SDIO_FUNCTION_BUSY = (MAX_ERROR_VALUE - 31), - MMC_SDIO_FUNCTION_FAILED = (MAX_ERROR_VALUE - 32), - MMC_SDIO_UNKNOWN_FUNCTION = MAX_ERROR_VALUE, - /* standard error defines */ - MMC_INTERNAL_ERROR = -8, - MMC_NOT_CONFIGURED = -7, - MMC_REQUEST_PENDING = -6, - MMC_REQUEST_NOT_APPLICABLE = -5, - MMC_INVALID_PARAMETER = -4, - MMC_UNSUPPORTED_FEATURE = -3, - MMC_UNSUPPORTED_HW = -2, - MMC_ERROR = -1, - MMC_OK = 0, - MMC_INTERNAL_EVENT = 1, - MMC_REMAINING_PENDING_EVENTS = 2, - MMC_REMAINING_FILTER_PENDING_EVENTS = 3, - MMC_NO_MORE_PENDING_EVENT = 4, - MMC_NO_MORE_FILTER_PENDING_EVENT = 5, - MMC_NO_PENDING_EVENT_ERROR = 7, -}; -#endif - -#define MCLK (100*1000*1000) - -#define INDEX(mask) ( \ - ((mask & 0x00000001) ? 0 : \ - ((mask & 0x00000002) ? 1 : \ - ((mask & 0x00000004) ? 2 : \ - ((mask & 0x00000008) ? 3 : \ - ((mask & 0x00000010) ? 4 : \ - ((mask & 0x00000020) ? 5 : \ - ((mask & 0x00000040) ? 6 : \ - ((mask & 0x00000080) ? 7 : \ - ((mask & 0x00000100) ? 8 : \ - ((mask & 0x00000200) ? 9 : \ - ((mask & 0x00000400) ? 10 : \ - ((mask & 0x00000800) ? 11 : \ - ((mask & 0x00001000) ? 12 : \ - ((mask & 0x00002000) ? 13 : \ - ((mask & 0x00004000) ? 14 : \ - ((mask & 0x00008000) ? 15 : \ - ((mask & 0x00010000) ? 16 : \ - ((mask & 0x00020000) ? 17 : \ - ((mask & 0x00040000) ? 18 : \ - ((mask & 0x00080000) ? 19 : \ - ((mask & 0x00100000) ? 20 : \ - ((mask & 0x00200000) ? 21 : \ - ((mask & 0x00400000) ? 22 : \ - ((mask & 0x00800000) ? 23 : \ - ((mask & 0x01000000) ? 24 : \ - ((mask & 0x02000000) ? 25 : \ - ((mask & 0x04000000) ? 26 : \ - ((mask & 0x08000000) ? 27 : \ - ((mask & 0x10000000) ? 28 : \ - ((mask & 0x20000000) ? 29 : \ - ((mask & 0x40000000) ? 30 : \ - ((mask & 0x80000000) ? 31 : 0) \ - ))))))))))))))))))))))))))))))) \ -) - -#define MMC_PERIPHERAL_ID0 0x81 -#define MMC_PERIPHERAL_ID1 0x11 -#define MMC_PERIPHERAL_ID2 0x04 -#define MMC_PERIPHERAL_ID3 0x00 - -/* SDI Power Control register bits */ - -#define SDI_PWR_PWRCTRL_MASK (0x00000003) -#define SDI_PWR_PWRCTRL_ON (0x00000003) -#define SDI_PWR_PWRCTRL_OFF (0x00000000) -#define SDI_PWR_DAT2DIREN (0x00000004) -#define SDI_PWR_CMDDIREN (0x00000008) -#define SDI_PWR_DAT0DIREN (0x00000010) -#define SDI_PWR_DAT31DIREN (0x00000020) -#define SDI_PWR_OPD (0x00000040) -#define SDI_PWR_FBCLKEN (0x00000080) -#define SDI_PWR_DAT74DIREN (0x00000100) -#define SDI_PWR_RSTEN (0x00000200) - -#define VOLTAGE_WINDOW_MMC (0x00FF8080) -#define VOLTAGE_WINDOW_SD (0x80010000) - -/* SDI clock control register bits */ - -#define SDI_CLKCR_CLKDIV_MASK (0x000000FF) -#define SDI_CLKCR_CLKEN (0x00000100) -#define SDI_CLKCR_PWRSAV (0x00000200) -#define SDI_CLKCR_BYPASS (0x00000400) -#define SDI_CLKCR_WIDBUS_MASK (0x00001800) -#define SDI_CLKCR_WIDBUS_1 (0x00000000) -#define SDI_CLKCR_WIDBUS_4 (0x00000800) -#define SDI_CLKCR_WIDBUS_8 (0x00001000) -#define SDI_CLKCR_NEGEDGE (0x00002000) -#define SDI_CLKCR_HWFC_EN (0x00004000) - -#define SDI_CLKCR_CLKDIV_INIT (0x000000FD) - -/* SDI command register bits */ - -#define SDI_CMD_CMDINDEX_MASK (0x000000FF) -#define SDI_CMD_WAITRESP (0x00000040) -#define SDI_CMD_LONGRESP (0x00000080) -#define SDI_CMD_WAITINT (0x00000100) -#define SDI_CMD_WAITPEND (0x00000200) -#define SDI_CMD_CPSMEN (0x00000400) -#define SDI_CMD_SDIOSUSPEND (0x00000800) -#define SDI_CMD_ENDCMDCOMPL (0x00001000) -#define SDI_CMD_NIEN (0x00002000) -#define SDI_CMD_CE_ATACMD (0x00004000) -#define SDI_CMD_CBOOTMODEEN (0x00008000) - -/* MMC_DATA_TIMEOUT sets the data timeout in seconds */ -#define MMC_DATA_TIMEOUT (30) - -/* SDI Status register bits */ - -#define SDI_STA_CCRCFAIL (0x00000001) /* (1 << 0) */ -#define SDI_STA_DCRCFAIL (0x00000002) /* (1 << 1) */ -#define SDI_STA_CTIMEOUT (0x00000004) /* (1 << 2) */ -#define SDI_STA_DTIMEOUT (0x00000008) /* (1 << 3) */ -#define SDI_STA_TXUNDERR (0x00000010) /* (1 << 4) */ -#define SDI_STA_RXOVERR (0x00000020) /* (1 << 5) */ -#define SDI_STA_CMDREND (0x00000040) /* (1 << 6) */ -#define SDI_STA_CMDSENT (0x00000080) /* (1 << 7) */ -#define SDI_STA_DATAEND (0x00000100) /* (1 << 8) */ -#define SDI_STA_STBITERR (0x00000200) /* (1 << 9) */ -#define SDI_STA_DBCKEND (0x00000400) /* (1 << 10) */ -#define SDI_STA_CMDACT (0x00000800) /* (1 << 11) */ -#define SDI_STA_TXACT (0x00001000) /* (1 << 12) */ -#define SDI_STA_RXACT (0x00002000) /* (1 << 13) */ -#define SDI_STA_TXFIFOBW (0x00004000) /* (1 << 14) */ -#define SDI_STA_RXFIFOBR (0x00008000) /* (1 << 15) */ -#define SDI_STA_TXFIFOF (0x00010000) /* (1 << 16) */ -#define SDI_STA_RXFIFOF (0x00020000) /* (1 << 17) */ -#define SDI_STA_TXFIFOE (0x00040000) /* (1 << 18) */ -#define SDI_STA_RXFIFOE (0x00080000) /* (1 << 19) */ -#define SDI_STA_TXDAVL (0x00100000) /* (1 << 20) */ -#define SDI_STA_RXDAVL (0x00200000) /* (1 << 21) */ -#define SDI_STA_SDIOIT (0x00400000) /* (1 << 22) */ -#define SDI_STA_CEATAEND (0x00800000) /* (1 << 23) */ -#define SDI_STA_CARDBUSY (0x01000000) /* (1 << 24) */ -#define SDI_STA_BOOTMODE (0x02000000) /* (1 << 25) */ -#define SDI_STA_BOOTACKERR (0x04000000) /* (1 << 26) */ -#define SDI_STA_BOOTACKTIMEOUT (0x08000000) /* (1 << 27) */ -#define SDI_STA_RSTNEND (0x10000000) /* (1 << 28) */ - -/* SDI Interrupt Clear register bits */ - -#define SDI_ICR_MASK (0x1DC007FF) -#define SDI_ICR_CCRCFAILC (0x00000001) /* (1 << 0) */ -#define SDI_ICR_DCRCFAILC (0x00000002) /* (1 << 1) */ -#define SDI_ICR_CTIMEOUTC (0x00000004) /* (1 << 2) */ -#define SDI_ICR_DTIMEOUTC (0x00000008) /* (1 << 3) */ -#define SDI_ICR_TXUNDERRC (0x00000010) /* (1 << 4) */ -#define SDI_ICR_RXOVERRC (0x00000020) /* (1 << 5) */ -#define SDI_ICR_CMDRENDC (0x00000040) /* (1 << 6) */ -#define SDI_ICR_CMDSENTC (0x00000080) /* (1 << 7) */ -#define SDI_ICR_DATAENDC (0x00000100) /* (1 << 8) */ -#define SDI_ICR_STBITERRC (0x00000200) /* (1 << 9) */ -#define SDI_ICR_DBCKENDC (0x00000400) /* (1 << 10) */ -#define SDI_ICR_SDIOITC (0x00400000) /* (1 << 22) */ -#define SDI_ICR_CEATAENDC (0x00800000) /* (1 << 23) */ -#define SDI_ICR_BUSYENDC (0x01000000) /* (1 << 24) */ -#define SDI_ICR_BOOTACKERRC (0x04000000) /* (1 << 26) */ -#define SDI_ICR_BOOTACKTIMEOUTC (0x08000000) /* (1 << 27) */ -#define SDI_ICR_RSTNENDC (0x10000000) /* (1 << 28) */ - -#define SDI_MASK0_MASK (0x1FFFFFFF) - -/* SDI Data control register bits */ - -#define SDI_DCTRL_DTEN (0x00000001) /* (1 << 0) */ -#define SDI_DCTRL_DTDIR_IN (0x00000002) /* (1 << 1) */ -#define SDI_DCTRL_DTMODE_STREAM (0x00000004) /* (1 << 2) */ -#define SDI_DCTRL_DMAEN (0x00000008) /* (1 << 3) */ -#define SDI_DCTRL_DBLOCKSIZE_MASK (0x000000F0) -#define SDI_DCTRL_RWSTART (0x00000100) /* (1 << 8) */ -#define SDI_DCTRL_RWSTOP (0x00000200) /* (1 << 9) */ -#define SDI_DCTRL_RWMOD (0x00000200) /* (1 << 10) */ -#define SDI_DCTRL_SDIOEN (0x00000800) /* (1 << 11) */ -#define SDI_DCTRL_DMAREQCTL (0x00001000) /* (1 << 12) */ -#define SDI_DCTRL_DBOOTMODEEN (0x00002000) /* (1 << 13) */ -#define SDI_DCTRL_BUSYMODE (0x00004000) /* (1 << 14) */ -#define SDI_DCTRL_DDR_MODE (0x00008000) /* (1 << 15) */ -#define SDI_DCTRL_DBLOCKSIZE_V2_MASK (0x7fff0000) - -#define SDI_FIFO_BURST_SIZE (8) - -#ifndef __ASSEMBLY__ -struct sdi_registers { - u32 power; /* 0x00*/ - u32 clock; /* 0x04*/ - u32 argument; /* 0x08*/ - u32 command; /* 0x0c*/ - u32 respcommand; /* 0x10*/ - u32 response0; /* 0x14*/ - u32 response1; /* 0x18*/ - u32 response2; /* 0x1c*/ - u32 response3; /* 0x20*/ - u32 datatimer; /* 0x24*/ - u32 datalength; /* 0x28*/ - u32 datactrl; /* 0x2c*/ - u32 datacount; /* 0x30*/ - u32 status; /* 0x34*/ - u32 status_clear; /* 0x38*/ - u32 mask0; /* 0x3c*/ - u32 mask1; /* 0x40*/ - u32 card_select; /* 0x44*/ - u32 fifo_count; /* 0x48*/ - u32 padding1[(0x80-0x4C)>>2]; - u32 fifo; /* 0x80*/ - u32 padding2[(0xFE0-0x84)>>2]; - u32 periph_id0; /* 0xFE0 mmc Peripheral Identi.cation Register*/ - u32 periph_id1; /* 0xFE4*/ - u32 periph_id2; /* 0xFE8*/ - u32 periph_id3; /* 0xFEC*/ - u32 pcell_id0; /* 0xFF0*/ - u32 pcell_id1; /* 0xFF4*/ - u32 pcell_id2; /* 0xFF8*/ - u32 pcell_id3; /* 0xFFC*/ -}; -#endif - -#endif diff --git a/board/st-ericsson/snowball/mmc_utils.c b/board/st-ericsson/snowball/mmc_utils.c deleted file mode 100644 index 6c5a8150d..000000000 --- a/board/st-ericsson/snowball/mmc_utils.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2009 - * - * See file CREDITS for list of people who contributed to this - * project. - * - * 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 <linux/ctype.h> - -#include <asm/arch/common.h> -#include <asm/arch/cpu.h> -#include <command.h> -#include <mmc.h> -#include <fat.h> - -#define PIB_EMMC_ADDR 0x00 - -struct partition { - unsigned char boot_ind; /* 0x80 - active */ - unsigned char head; /* starting head */ - unsigned char sector; /* starting sector */ - unsigned char cyl; /* starting cylinder */ - unsigned char sys_ind; /* What partition type */ - unsigned char end_head; /* end head */ - unsigned char end_sector; /* end sector */ - unsigned char end_cyl; /* end cylinder */ - u32 start_sect; /* starting sector counting from 0 */ - u32 nr_sects; /* nr of sectors in partition */ -} __attribute__((packed)); - -#define PART(type, start, num) \ - { \ - .boot_ind = 0x00, \ - .head = 0x03, \ - .sector = 0xD0, \ - .cyl = 0xff, \ - .sys_ind = type, \ - .end_head = 0x03, \ - .end_sector = 0xd0, \ - .end_cyl = 0xff, \ - .start_sect = start, \ - .nr_sects = num, \ - } - -static struct partition partitions_ed[] = { - [0] = PART(0x83, 0x000A0000, 0x00004000), /* Kernel */ - [1] = PART(0x83, 0x000A4000, 0x00080000), /* Root file system */ - [2] = PART(0x83, 0x00124000, 0x0022c000), - [3] = PART(0x0c, 0x00350000, 0x00b9a000), -}; - -static struct partition partitions_v1[] = { - [0] = PART(0x83, 0x000A0000, 0x00004000), /* Kernel */ - [1] = PART(0x83, 0x000A4000, 0x00080000), /* Root file system */ - [2] = PART(0x83, 0x00000400, 0x00000800), /* Modem parameters */ - [3] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -}; - -#undef PART - -int write_partition_block(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - int err; - u32 offset = PIB_EMMC_ADDR; - u8 mbr[512]; - u8 emmc_existing_partition[512]; - struct mmc *boot_dev = NULL; - - (void) cmdtp; /* Parameter not used! */ - (void) flag; /* Parameter not used! */ - (void) argc; /* Parameter not used! */ - (void) argv; /* Parameter not used! */ - - memset(mbr, 0, 0x1be); - if (u8500_is_earlydrop()) - memcpy(mbr + 0x1be, partitions_ed, sizeof(partitions_ed)); - else - memcpy(mbr + 0x1be, partitions_v1, sizeof(partitions_v1)); - - /* magic */ - mbr[0x1fe] = 0x55; - mbr[0x1ff] = 0xAA; - - printf("Writing partition block (if needed)...\n"); - - boot_dev = find_mmc_device(CONFIG_EMMC_DEV_NUM); - if (!boot_dev) { - printf(" Error: eMMC device not found\n"); - return 1; - } - - err = boot_dev->block_dev.block_read(CONFIG_EMMC_DEV_NUM, - offset, - 1, - (void *) emmc_existing_partition); - if (err != 1) { - printf(" Error: eMMC read failed\n"); - return 1; - } - - if (memcmp((void *)emmc_existing_partition, (void *)mbr, 512)) { - err = boot_dev->block_dev.block_write(CONFIG_EMMC_DEV_NUM, - offset, - 1, - (void *) mbr); - if (err != 1) { - printf(" Error: eMMC write failed\n"); - return 1; - } - } - printf(" eMMC partition block exists now\n"); - return 0; -} - -U_BOOT_CMD( - write_partition_block, 1, 0, write_partition_block, - "- write partition block on emmc device\n", - NULL -); - -/* - * command line commands - */ -#ifdef CONFIG_CMD_FAT -static int mmc_read_cmd_file(cmd_tbl_t *cmdtp, int flag, int argc, - char *argv[]) -{ - long sz; - char mmc_cmdbuffer[1024]; - struct mmc *mmc_dev; - (void) cmdtp; /* Parameter not used! */ - (void) flag; /* Parameter not used! */ - (void) argc; /* Parameter not used! */ - (void) argv; /* Parameter not used! */ - - mmc_dev = find_mmc_device(CONFIG_MMC_DEV_NUM); - if (mmc_dev == NULL) { - printf("mmc_read_cmd_file: find_mmc_device failed\n"); - return 1; - } - - if (fat_register_device(&mmc_dev->block_dev, 1) != 0) { - printf("mmc_read_cmd_file: fat_register_device failed\n"); - return 1; - } - - sz = file_fat_read("/command.txt", &mmc_cmdbuffer, - sizeof(mmc_cmdbuffer) - 1); - if (sz == -1) { - printf("No command.txt found in the MMC/SD card\n"); - return 1; - } - - mmc_cmdbuffer[sz] = '\0'; - setenv("bootcmd", mmc_cmdbuffer); - return 0; -} - -U_BOOT_CMD( - mmc_read_cmd_file, 1, 0, mmc_read_cmd_file, - "setup bootcmd env from command.txt on SD", - NULL -); -#endif - -/* ------------------------------- End of file ---------------------------- */ diff --git a/board/st-ericsson/snowball/snowball.c b/board/st-ericsson/snowball/snowball.c index 4379b2cb9..bcd5cdb95 100644 --- a/board/st-ericsson/snowball/snowball.c +++ b/board/st-ericsson/snowball/snowball.c @@ -18,7 +18,9 @@ #include <config.h> #include <common.h> +#include <malloc.h> #include <i2c.h> +#include <mmc.h> #include <asm/types.h> #include <asm/io.h> #include <asm/errno.h> @@ -31,6 +33,8 @@ #include <asm/arch/prcmu.h> #include <asm/arch/common.h> +#include "../../../drivers/mmc/arm_pl180_mmci.h" + #include <db8500_pincfg.h> #include "db8500_pins.h" @@ -254,7 +258,7 @@ int board_early_access(block_dev_desc_t *block_dev) return 0; } -#ifdef BOARD_LATE_INIT +#ifdef CONFIG_BOARD_LATE_INIT #ifdef CONFIG_MMC #define LDO_VAUX3_ENABLE_MASK 0x3 @@ -424,7 +428,6 @@ out: return ret; } - /* * called after all initialisation were done, but before the generic * mmc_initialize(). @@ -455,8 +458,11 @@ int board_late_init(void) /* setup FSMC for LAN controler */ writel(0x305b, 0x80000000); - /* the default is too slow */ - writel(0x01010110, 0x80000004); + /* + * the default is too slow + * NOTE: below this some boards corrupt data in SRAM transfers + */ + writel(0x01010210, 0x80000004); } /* enable 3V6 for GBF chip */ @@ -477,5 +483,113 @@ int board_late_init(void) return (0); } -#endif /* BOARD_LATE_INIT */ +/* + * emmc_host_init - initialize the emmc controller. + * Configure GPIO settings, set initial clock and power for emmc slot. + * Initialize mmc struct and register with mmc framework. + */ +static int emmc_host_init(void) +{ + struct pl180_mmc_host *host; + u32 sdi_u32; + int rc = 0; + struct mmc *dev; + + host = malloc(sizeof(struct pl180_mmc_host)); + if (!host) + return -ENOMEM; + memset(host, 0, sizeof(*host)); + + host->base = (struct sdi_registers *)CFG_EMMC_BASE; + host->pwr_init = SDI_PWR_OPD | SDI_PWR_PWRCTRL_ON; + host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT | SDI_CLKCR_CLKEN | SDI_CLKCR_HWFC_EN; + strcpy(host->name, "EMMC"); + host->caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz; + host->voltages = VOLTAGE_WINDOW_MMC; + host->clock_min = ARM_MCLK / (2 + SDI_CLKCR_CLKDIV_INIT); + host->clock_max = ARM_MCLK / 2; + host->clock_in = ARM_MCLK; + host->version2 = 1; + + rc = arm_pl180_mmci_init(host); + + if (rc < 0) + return rc; + + dev = find_mmc_device(0); + if (!dev) + return -ENODEV; + + rc = mmc_init(dev); + + return rc; +} + +/* + * mmc_host_init - initialize the external mmc controller. + * Configure GPIO settings, set initial clock and power for mmc slot. + * Initialize mmc struct and register with mmc framework. + */ +static int mmc_host_init(void) +{ + struct pl180_mmc_host *host; + u32 sdi_u32; + int rc = 0; + + host = malloc(sizeof(struct pl180_mmc_host)); + if (!host) + return -ENOMEM; + memset(host, 0, sizeof(*host)); + + host->base = (struct sdi_registers *)CFG_MMC_BASE; + sdi_u32 = 0xBF; + writel(sdi_u32, &host->base->power); + host->pwr_init = 0xBF; + host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT | SDI_CLKCR_CLKEN | SDI_CLKCR_HWFC_EN; + strcpy(host->name, "MMC"); + host->caps = 0; /* Some SD cards do not work in 4 bit mode! */ + host->b_max = 0; + host->voltages = VOLTAGE_WINDOW_SD; + host->clock_min = ARM_MCLK / (2 + SDI_CLKCR_CLKDIV_INIT); + host->clock_max = ARM_MCLK / 2; + host->clock_in = ARM_MCLK; + host->version2 = 1; + rc = arm_pl180_mmci_init(host); + + return rc; +} + +/* + * board_mmc_init - initialize all the mmc/sd host controllers. + * Called by generic mmc framework. + */ +int board_mmc_init(bd_t *bis) +{ + int error; + + (void) bis; + + error = emmc_host_init(); + if (error) { + printf("emmc_host_init() %d \n", error); + return -1; + } + + /* + * In a perfect world board_early_access shouldn't be here but we want + * some functionality to be loaded as quickly as possible and putting it + * here will get the shortest time to start that functionality. Time + * saved by putting it here compared to later is somewhere between + * 0.3-0.7s. That is enough to be able to justify putting it here. + */ + + error = mmc_host_init(); + if (error) { + printf("mmc_host_init() %d \n", error); + return -1; + } + + return 0; +} +#endif /* CONFIG_BOARD_LATE_INIT */ |