From 33a2e90bf491f13a4546d09a6105582c0ba7f313 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 2 Jul 2010 13:47:39 +0200 Subject: Replace MMC/SD driver to fit new framework. IR265772: MMC driver does not detect SDHC cards. IR254201: Restructure MMC/SD driver for U8500 board according to the block device framework in mainline U-Boot. Changes to mmc framework: - Multi Block Read support in mmc framework. - Wrap Multi Block Write/Read to be able to adopt for large transaction. - Removed incorrect check in EXT CSD for high capacity MMC. - Corrected check for high capacity SD cards. - Set MMC buswidth to 8, prio of using 4. Known limitations/bugs in mmc framework: - High capacity MMC, will likely not get the correct density. - High speed is set, whether or not the host supports it or not. board/st/u8500/mmc_utils: IMPORTANT FOR DEVELOPERS: - Removed unessary U-Boot commands which is already supported in cmd_fat. - mmc_read_cmd_file: Read command.txt into bootcmd env from FAT FS in SD card. - write_partition_block: Writes the MBR if it is not already written. board/st/u8500/mmc_host[c.h]: - Implements the entire MMC/SD host driver for the PL180 block. - There is still room for optimization: Increase CLK-speed. Use high-speed for SD cards. Is GPIO setup correctly for both cards an eMMC. EarlyDrop support not fully tested. Dynamically turn on voltage/clocks to SD, not always. More... Note: - Increased read/write performance for eMMC, to around 5.4 MB/s for sequential read/write. Earlier measurements was 3.5 MB/s for read and 2.6 MB/s for write. ST-Ericsson ID: ER265772, CR267996, ER267993 Change-Id: I921102edbde761407ff5ad476d1bb99f5dc7a2ef Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/2288 Reviewed-by: Michael BRANDT Tested-by: Michael BRANDT Reviewed-by: Martin LUNDHOLM Tested-by: Martin LUNDHOLM Reviewed-by: Mikael LARSSON Tested-by: Mikael LARSSON --- board/st/u8500/Makefile | 2 +- board/st/u8500/common.h | 3 +- board/st/u8500/emmc.c | 391 ------- board/st/u8500/emmc.h | 36 - board/st/u8500/init_mmc.c | 214 ---- board/st/u8500/init_mmc.h | 43 - board/st/u8500/mmc.c | 2594 -------------------------------------------- board/st/u8500/mmc.h | 263 ----- board/st/u8500/mmc_host.c | 636 +++++++++++ board/st/u8500/mmc_host.h | 296 +++++ board/st/u8500/mmc_p.h | 315 ------ board/st/u8500/mmc_utils.c | 974 ++--------------- board/st/u8500/mmc_utils.h | 107 -- board/st/u8500/u8500.c | 8 - 14 files changed, 1050 insertions(+), 4832 deletions(-) delete mode 100644 board/st/u8500/emmc.c delete mode 100755 board/st/u8500/emmc.h delete mode 100644 board/st/u8500/init_mmc.c delete mode 100755 board/st/u8500/init_mmc.h delete mode 100644 board/st/u8500/mmc.c delete mode 100644 board/st/u8500/mmc.h create mode 100644 board/st/u8500/mmc_host.c create mode 100644 board/st/u8500/mmc_host.h delete mode 100755 board/st/u8500/mmc_p.h delete mode 100755 board/st/u8500/mmc_utils.h (limited to 'board') diff --git a/board/st/u8500/Makefile b/board/st/u8500/Makefile index ccaae6aa5..c151f72b5 100644 --- a/board/st/u8500/Makefile +++ b/board/st/u8500/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk CFLAGS += -D__RELEASE -D__STN_8500 LIB = $(obj)lib$(BOARD).a -COBJS := u8500.o flash.o gpio.o u8500_i2c.o mmc.o mmc_utils.o init_mmc.o emmc.o clock.o prcmu.o mcde_display.o mcde_hw.o ab8500vibra.o +COBJS := u8500.o flash.o gpio.o u8500_i2c.o mmc_host.o mmc_utils.o clock.o prcmu.o mcde_display.o mcde_hw.o ab8500vibra.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/st/u8500/common.h b/board/st/u8500/common.h index 07c97bea5..a11b605f5 100644 --- a/board/st/u8500/common.h +++ b/board/st/u8500/common.h @@ -128,7 +128,6 @@ typedef u32 t_logical_address; /*function prototypes*/ void gpio_init(void); -int emmc_init (u8); -extern int u8500_is_earlydrop(void); +int u8500_is_earlydrop(void); #endif /* _COMMON_H_ */ diff --git a/board/st/u8500/emmc.c b/board/st/u8500/emmc.c deleted file mode 100644 index 7336b0334..000000000 --- a/board/st/u8500/emmc.c +++ /dev/null @@ -1,391 +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 -*/ -/* --- includes ----------------------------------------------------------- */ -#include "common.h" /* XXX: Arrgghh! "common.h" includes */ -#include -#include "mmc.h" -#include "emmc.h" -#include "gpio.h" -#include - -#define PIB_EMMC_ADDR 0x00 -/* ======================================================================== -Name: init_emmc -Description: init embedded multimedia card interface - -======================================================================== */ -int emmc_init(u8 card_num) -{ - t_mmc_error mmc_error; - t_mmc_error response; - gpio_error gpioerror; - t_logical_address mmcbase; - int error; - - mmcbase = u8500_is_earlydrop() ? CFG_EMMC_BASE_ED : CFG_EMMC_BASE_V1; - -/* Initialize the base address of eMMC */ - mmc_error = mmc_init(card_num, mmcbase); - - if (MMC_OK != mmc_error) - { - printf("emmc_init() %d \n", mmc_error); - goto end; - } - - /* - * FIXME The following code is not required on v1. Check if it is really - * needed on ED or can be dropped. - */ - if (u8500_is_earlydrop()) { -#ifndef CONFIG_U8500_V1 - /* Initialize the gpio alternate function for eMMC */ - struct gpio_register *p_gpio_register = (void *) IO_ADDRESS(CFG_GPIO_6_BASE); - p_gpio_register -> gpio_dats |= 0x0000FFE0; - p_gpio_register -> gpio_pdis &= ~0x0000FFE0; - - //enable the alternate function of EMMC - gpioerror = gpio_altfuncenable(GPIO_ALT_EMMC, "EMMC"); - if(gpioerror != GPIO_OK) - { - printf("emmc_init() gpio_altfuncenable %d failed\n", gpioerror); - goto end; - } - -#else - //enable the alternate function of PoP EMMC - // gpioerror = gpio_altfuncenable(GPIO_ALT_POP_EMMC, "EMMC"); - gpioerror = gpio_altfuncenable(GPIO_ALT_EMMC, "EMMC"); - if (gpioerror != GPIO_OK) { - printf("emmc_init() gpio_altfuncenable %d failed \n", - gpioerror); - goto end; - } -#endif - } - - //Power-on the controller - response = mmc_poweron(card_num); - if (response != MMC_OK) - { - printf("Error in eMMC power on, response is %d\n",response); - goto end; - } - // Initialise the cards,get CID and CSD on the bus - response = mmc_initializeCards(card_num); - - if (response != MMC_OK) - { - printf(" Error in eMMC initialization\n"); - goto end; - } - - error = emmc_write_pib(); - if(error) - printf("PIB info writing into eMMC failed\n"); - printf("eMMC done\n"); - - return 0; - -end: - mmc_poweroff(card_num); - return 1; -} - -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, 0x00124000, 0x00000800), /* Modem parameters */ - [3] = {0}, -}; - -#undef PART - -int emmc_write_pib(void) -{ - int i; - t_mmc_error mmc_error; - u32 block_offset = PIB_EMMC_ADDR; - u8 card_num = 4; - u8 mbr[512]; - - 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; - -/* HACK required for HREF board as erase block size = 512KB */ -/* - mmc_error = mmc_erase(card_num, 0x0, 0x1FF); - if (mmc_error != MMC_OK) { - printf(" eMMC erase failed in PIB \n"); - return 1; - } -*/ - - mmc_error = - mmc_writeblocks(card_num, block_offset, (u32 *) mbr, - 512, 1); - if (mmc_error != MMC_OK) { - printf(" eMMC PIB write failed \n"); - return 1; - } - return 0; -} - -int emmc_erase(u32 start, u32 end) -{ - t_mmc_error mmc_error; - u8 card_num = 4; - printf("emmc erase start \n"); - mmc_error = mmc_erase(card_num, start, end); - if (mmc_error != MMC_OK) { - printf(" eMMC erase failed \n"); - return 1; - } - printf("emmc erase done \n"); - return 0; -} - -int emmc_read(u32 block_offset, u32 read_buffer, u32 filesize) -{ - t_mmc_error mmc_error; - u32 remaining; - u8 card_num = 4; - u8 *mem_address = (u8 *) read_buffer; - u32 n=filesize,blocks; - - remaining = filesize; - - printf(" eMMC read start filesize=0x%x \n", filesize); - - blocks = (n%512==0)?(n/512):(n/512)+1; - - while(blocks>=8) - { - mmc_error = mmc_readblocks(card_num, block_offset, (u32 *) mem_address, 512, 8); - if (mmc_error != MMC_OK) - { - printf(" eMMC read blocks failed \n"); - return 1; - } - - block_offset += 4096; - mem_address += 4096; - blocks -=8; - remaining -= 4096; - } - if(blocks) - { - mmc_error = mmc_readblocks(card_num, block_offset, (u32 *) mem_address, 512, blocks); - if (mmc_error != MMC_OK) - { - printf(" eMMC read blocks failed \n"); - return 1; - } - } - - printf(" eMMC read done \n"); - return 0; -} - -int emmc_write(u32 block_offset, u32 write_buffer, u32 filesize) -{ - t_mmc_error mmc_error; - u32 remaining; - u8 card_num = 4; - u8 *mem_address = (u8 *) write_buffer; - u32 n=filesize,blocks; - - remaining = filesize; - - printf(" eMMC write start filesize=0x%x \n", filesize); - - blocks = (n%512==0)?(n/512):(n/512)+1; - while(blocks>=8) - { - mmc_error = mmc_writeblocks(card_num, block_offset, (u32 *) mem_address,512, 8); - if (mmc_error != MMC_OK) - { - printf(" eMMC write blocks failed \n"); - return 1; - } - - block_offset += 4096; - mem_address += 4096; - blocks -=8; - remaining -= 4096; - } - if(blocks) - { - - mmc_error = mmc_writeblocks(card_num, block_offset, (u32 *) mem_address,512, blocks); - if (mmc_error != MMC_OK) - { - printf(" eMMC write blocks failed \n"); - return 1; - } - - } - - printf(" eMMC write done \n"); - return 0; -} - -/* - * command line commands - */ -#ifdef CONFIG_CMD_EMMC -int do_emmc_erase(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - u32 start_address; - u32 end_address; - int load_result = 1; - u32 error_name = 0; - - start_address = simple_strtoul(argv[1],0,16); - end_address = simple_strtoul(argv[2],0,16); - - printf("emmc_erase :: start address = %x end_address=0x%x\n",start_address,end_address); - - load_result = emmc_erase(start_address,end_address); - if (load_result != 0) - { - error_name = (unsigned long) (-load_result); - printf("emmc_erase error : failed \n"); - } - return(0); -} - -U_BOOT_CMD( - emmc_erase, 3, 0, do_emmc_erase, - "- erase the eMMC flash \n", - "start_address- start address of the eMMC block\n" - "end_address- end address of the eMMC block\n" -); - -int do_emmc_read(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - u32 ram_address; - u32 block_offset; - u32 filesize; - int load_result = 1; - u32 error_name = 0; - - ram_address = simple_strtoul (argv[1],0,16); - block_offset = simple_strtoul (argv[2],0,16); - filesize = simple_strtoul (argv[3],0,16); - - boottime_tag("load_image"); - printf("emmc_read :: ram address = 0x%x block address=0x%x \n",ram_address,block_offset); - - load_result = emmc_read(block_offset,ram_address,filesize); - if (load_result != 0) - { - boottime_remove_last(); - error_name = (unsigned long) (-load_result); - printf("emmc_read error : in reading data from eMMC block \n"); - } - return(0); -} - -U_BOOT_CMD( - emmc_read, 4, 0, do_emmc_read, - "- read file from emmc flash \n", - "ram_address - read from eMMC and copy into ram address\n" - "block_offset - address to read the file from the eMMC block \n" - "filesize - size of the file \n" -); - -int do_emmc_write(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - u32 ram_address; - u32 block_offset; - u32 filesize; - int load_result = 1; - u32 error_name = 0; - - ram_address = simple_strtoul (argv[1],0,16); - block_offset = simple_strtoul (argv[2],0,16); - filesize = simple_strtoul (argv[3],0,16); - - printf("emmc_write :: ram address = %x block address=0x%x \n",ram_address,block_offset); - - load_result = emmc_write(block_offset,ram_address,filesize); - if (load_result != 0) - { - error_name = (unsigned long) (-load_result); - printf("emmc_read error : in writing data into eMMC block \n"); - } - return(0); -} - -U_BOOT_CMD( - emmc_write, 4, 0, do_emmc_write, - "- write file from emmc flash \n", - "ram_address - write to eMMC by copying from ram address\n" - "block_offset - address to write the file into the eMMC block \n" - "filesize - size of the file \n" -); - -#endif /* CONFIG_CMD_EMMC */ -/* ------------------------------- End of file ---------------------------- */ diff --git a/board/st/u8500/emmc.h b/board/st/u8500/emmc.h deleted file mode 100755 index 62256ae9e..000000000 --- a/board/st/u8500/emmc.h +++ /dev/null @@ -1,36 +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 - */ - -#ifndef _STM_EMMC_H -#define _STM_EMMC_H - - -#include - -extern int emmc_init (u8); -int emmc_erase(u32, u32); -int emmc_read (u32,u32,u32); -int emmc_write(u32,u32,u32); -int emmc_write_pib(void); - - -#endif /* !defined(_STM_EMMC_H) */ diff --git a/board/st/u8500/init_mmc.c b/board/st/u8500/init_mmc.c deleted file mode 100644 index fb6470a23..000000000 --- a/board/st/u8500/init_mmc.c +++ /dev/null @@ -1,214 +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 - */ -/* --- includes ----------------------------------------------------------- */ -#include "common.h" -#include "mmc.h" -#include "init_mmc.h" -#include "gpio.h" -#include "mmc_utils.h" - -#ifdef CONFIG_CMD_FAT -#include -#include -#endif - -#define MMC_CARD_NUM 1 -#define EMMC_CARD_NUM 4 -enum { - DEV_EMMC = 0, - DEV_MMC -}; - -static block_dev_desc_t mmc_dev; -static block_dev_desc_t emmc_dev; -static u32 CSD[4]; - -block_dev_desc_t * mmc_get_dev(int dev) -{ - if (dev == DEV_EMMC) - return (block_dev_desc_t *)(&emmc_dev); - else if (dev == DEV_MMC) - return (block_dev_desc_t *)(&mmc_dev); - - printf("mmc_get_dev: unknown dev %d\n", dev); - return 0; -} - -static unsigned long emmc_block_read(int dev, unsigned long blknr, - lbaint_t blkcnt, void *dest) -{ - unsigned long rc; - - rc = mmc_readblocks(EMMC_CARD_NUM, (u32) (512 * blknr), (u32 *)dest, - 512, blkcnt); - if (rc != 0) { - printf("mmc_block_read: readblocks failed %ld\n", rc); - rc = 0; - } else { - rc = blkcnt; - } - return rc; -} - -unsigned long mmc_block_read(int dev, unsigned long blknr, - lbaint_t blkcnt, void *dest) -{ - unsigned long i; - unsigned long src= blknr; - unsigned long rc = 0; - - for(i = 0; i < blkcnt; i++) - { - /* card#, read offset, buffer, blksize, transfer mode */ - mmc_readblock(MMC_CARD_NUM, (u32) (512 * src), - (u32 *)dest, 512, MMCPOLLING); - rc++; - src++; - dest += 512; - } - return rc; -} - -int mmc_hw_init(void) -{ - t_mmc_error response; - - /* save the GPIO0 AFSELA register*/ - gpio_altfuncenable(GPIO_ALT_SD_CARD0, "MMC"); - /* Power-on the controller*/ - response = mmc_enable (); - - if (response != MMC_OK) - { - response = mmc_enable (); - if (response != MMC_OK) - { - printf ("Error in card power on\n"); - goto end; - } - } - /* Initialise the cards on the bus, if any*/ - response = mmc_initCard (); - if (response != MMC_OK) - { - printf ("Error in card initialization\n"); - goto end; - } - response = mmc_readcsd (CSD); - if (response != MMC_OK) - { - printf ("Error while fetching card info\n"); - goto end; - } - - return 0; - end: - return 1; -} - -/* - * mmc_legacy_init - called from commandline mmc init - * - * Initialise hardware and setup block device structure for fat and ext2 - * commands. - */ -int mmc_legacy_init(int dev) -{ - - if (dev == DEV_EMMC) { - debug("EMMC init\n"); - /* XXX: emmc_init() does write the MBR (called pib)! */ - emmc_init(EMMC_CARD_NUM); - emmc_dev.if_type = IF_TYPE_MMC; - emmc_dev.part_type = PART_TYPE_DOS; - emmc_dev.dev = dev; - emmc_dev.lun = 0; - emmc_dev.type = 0; - emmc_dev.blksz = 512; - emmc_dev.lba = 0x80000; /* XXX: use real size, here 256 MB */ - sprintf((char*)emmc_dev.vendor, "Unknown vendor"); - sprintf((char*)emmc_dev.product, "Unknown product"); - sprintf((char*)emmc_dev.revision, "N/A"); - emmc_dev.removable = 0; - emmc_dev.block_read = emmc_block_read; - return 0; - } else if (dev == DEV_MMC) { - debug("MMC init\n"); - return init_mmc(); - } - - printf("mmc_legacy_init: unsupported device# %d\n", dev); - return -1; -} - -/* ======================================================================== - Name: init_mmc - Description: init multimedia card interface - - ======================================================================== */ -static int init_mmc(void) -{ - t_mmc_error mmc_error; - struct gpio_register * gpio_base_address; - - /* Initialize the base address of MMC-SD */ - mmc_error = mmc_init (0,CFG_MMC_BASE); - - if (MMC_OK != mmc_error) - { - printf("mmc_init():: %d \n", mmc_error); - return 1 ; - } - - if (u8500_is_earlydrop()) { - gpio_base_address = (void *) IO_ADDRESS(CFG_GPIO_0_BASE); - gpio_base_address -> gpio_dats |= 0xFFC0000; - gpio_base_address -> gpio_pdis &= ~0xFFC0000; - } - - if (mmc_hw_init() != 0) { - printf("mmc_init: hw init failed\n"); - return -1; - } - mmc_dev.if_type = IF_TYPE_MMC; - mmc_dev.part_type = PART_TYPE_DOS; - mmc_dev.dev = 0; - mmc_dev.lun = 0; - mmc_dev.type = 0; - mmc_dev.blksz = 512; - mmc_dev.lba = 0x20000; /* XXX: use real size, here 64 MB */ - sprintf((char*)mmc_dev.vendor, "Unknown vendor"); - sprintf((char*)mmc_dev.product, "Unknown product"); - sprintf((char*)mmc_dev.revision, "N/A"); - mmc_dev.removable = 0; - mmc_dev.block_read = mmc_block_read; -#ifdef CONFIG_CMD_FAT - if (fat_register_device(&mmc_dev, 1) != 0) { - printf("mmc_init: could not register as FAT device\n"); - } -#endif /* CONFIG_CMD_FAT */ - - return 0; -} - - -/* ------------------------------- End of file ---------------------------- */ diff --git a/board/st/u8500/init_mmc.h b/board/st/u8500/init_mmc.h deleted file mode 100755 index b66f866f8..000000000 --- a/board/st/u8500/init_mmc.h +++ /dev/null @@ -1,43 +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 - */ - -#ifndef __INIT_MMC_H -#define __INIT_MMC_H -#define PUBLIC /* Extern by default */ - -#include - -typedef void (*t_callback_fct) (u32); -typedef struct -{ - t_callback_fct fct; - u32 param; -} t_callback; - -static int init_mmc(void); -int init_mmc_fat(void); -t_mmc_error mmc_fat_read_file (char *, u32, u32); -int mmc_hw_init (void); -unsigned long mmc_block_read(int dev,unsigned long blknr,lbaint_t blkcnt,void *dest); - - -#endif /* !defined(__INIT_MMC_H) */ diff --git a/board/st/u8500/mmc.c b/board/st/u8500/mmc.c deleted file mode 100644 index 97508af8d..000000000 --- a/board/st/u8500/mmc.c +++ /dev/null @@ -1,2594 +0,0 @@ -/* - * Copyright (C) ST-Ericsson 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 -#include -#include - -#include -#include "common.h" -#include "mmc.h" -#include "mmc_p.h" - -#define MAX_NUM_CARDS 5 -t_mmc_register *t_mmc0; /* Removed so it can be used in mmc_utils.c, by Chris S. */ -t_mmc_register *t_mmc4; -t_mmc_register *t_mmc[MAX_NUM_CARDS]; -u32 t_mmc_rel_addr = 0x00010000; -u32 emmc_rel_addr = 0x00100000; -u8 no_of_cards = 0; -u8 mmc_card = 0, sd_card = 0; -u32 clockfreq; -t_mmc_card_info card_array[30]; -t_mmc_device_mode device_mode = POLLING_MODE; -u32 *source_buffer; -u32 *dest_buffer; -u16 total_no_of_bytes = 0; -u8 selected_card = 0; -t_mmc_error transfer_error = MMC_CMD_CRC_FAIL; -u32 pwddata[8]; -t_mmc_event mmc_event; // For event management -u32 write_freq = 0; - -/* Private Functions*/ -t_mmc_error mmc_cmderror(u8); -t_mmc_error mmc_cmdresp145error(u8, u8); -t_mmc_error mmc_cmdresp2error(u8); -t_mmc_error mmc_cmdresp3error(u8); -t_mmc_error mmc_cmdresp6error(u8, u16 *, u8); -t_mmc_error mmc_cmdresp7error(u8); -t_mmc_error mmc_findblocklen(u16 nobytes, u8 * power); -t_mmc_error mmc_sendstatus(u8, u32 *); -t_mmc_error mmc_iscardprogramming(u8, u8 *); - -/****************************************************************************/ -/* NAME : mmc_init() */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine initializes the MMC registers, checks */ -/* Peripheral and PCell Id and clears all interrupts. */ -/* PARAMETERS : */ -/* IN : t_logical_address MMCBaseAddress:MMC registers base address */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error : MMC error code */ -/****************************************************************************/ - -t_mmc_error mmc_init(u8 card_num, t_logical_address MMCBaseAddress) -{ - t_mmc_error error; - if (card_num == 0) - t_mmc0 = (t_mmc_register *) MMCBaseAddress; - else if (card_num == 4) - t_mmc[card_num] = (t_mmc_register *) MMCBaseAddress; - error = MMC_OK; - - return error; -} - -/****************************************************************************/ -/* NAME : mmc_setpowerstate() */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine sets the power status of the controller. */ -/* */ -/* PARAMETERS : */ -/* IN : t_mmc_Power_state Power state to set */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error : MMC error code */ -/****************************************************************************/ -t_mmc_error mmc_setpowerstate(t_mmc_power_state MMCPowerState) -{ - t_mmc_error error; - - MMC_SET_CTRL(t_mmc0->mmc_Power, MMCPowerState); - error = MMC_OK; - - return error; -} - -/****************************************************************************/ -/* NAME : mmc_getpowerstate() */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine returns the power status of the controller. */ -/* */ -/* PARAMETERS : */ -/* IN : t_mmc_Power_state Power state to set */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error : MMC error code */ -/****************************************************************************/ - -t_mmc_power_state mmc_getpowerstate() -{ - t_mmc_power_state state; - state = MMC_READ_BITS(t_mmc0->mmc_Power, MMC_Power_MASK_CTRL, sbMMC_Power_CTRL); - return (state); -} - -/*****************************************************************************/ -/* NAME : mmc_setoperatingvoltage */ -/*-------------------------------------------------------------------------- */ -/* DESCRIPTION: This routine sets the operating voltage range of . */ -/* the controller */ -/* PARAMETERS : */ -/* IN : u8 The encoded value of the output voltage range to set.*/ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error : MMC error code */ -/*****************************************************************************/ - -t_mmc_error mmc_setoperatingvoltage(u8 value) -{ - t_mmc_error error; - if (value < 16) - { - MMC_SET_VOLT(t_mmc0->mmc_Power, value); - error = MMC_OK; - } - else - error = MMC_INVALID_PARAMETER; - return error; -} - -/****************************************************************************/ -/* NAME : mmc_getoperatingvoltage */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine returns the encoded value of the current */ -/* operating voltage range */ -/* PARAMETERS : */ -/* IN : */ -/* OUT : */ -/* */ -/* RETURN : u8 The encoded value of the output voltage range to set*/ -/****************************************************************************/ - -u8 mmc_getoperatingvoltage() -{ - u8 voltage; - voltage = - MMC_READ_BITS(t_mmc0->mmc_Power, MMC_Power_MASK_VOLT,sbMMC_Power_VOLT); - return (voltage); -} - -/****************************************************************************/ -/* NAME : mmc_configbus */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine configures the bus in open drain or . */ -/* push-pull mode */ -/* PARAMETERS : */ -/* IN : t_mmc_bus_configuration Bus configuration to set */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_configbus(t_mmc_bus_configuration busconfig) -{ - t_mmc_error error; - MMC_SET_OPEND(t_mmc0->mmc_Power, busconfig.mode); - MMC_SET_ROD(t_mmc0->mmc_Power, busconfig.rodctrl); - error = MMC_OK; - return error; -} - -/****************************************************************************/ -/* NAME : mmc_setclock */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine sets the clock state as enabled or disabled. */ -/* */ -/* PARAMETERS : */ -/* IN : t_mmc_state clock state to set. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_setclock(t_mmc_state busstate) -{ - t_mmc_error error; - MMC_SET_CENABLE(t_mmc0->mmc_Clock, busstate); - error = MMC_OK; - return error; -} - -/****************************************************************************/ -/* NAME : mmc_configclockcontrol */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine sets configurations for clock and bus mode. */ -/* */ -/* PARAMETERS : */ -/* IN : t_mmc_Clock_control clock control state to set. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_configclockcontrol(t_mmc_clock_control clockcontrol) -{ - t_mmc_error error; - - MMC_SET_PWRSAVE(t_mmc0->mmc_Clock, clockcontrol.pwrsave); - MMC_SET_BYPASS(t_mmc0->mmc_Clock, clockcontrol.bypass); - MMC_SET_WIDEBUS(t_mmc0->mmc_Clock, clockcontrol.widebus); - error = MMC_OK; - - return error; -} - -/****************************************************************************/ -/* NAME : mmc_setclockfrequency */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine sets clock frequency for MMCI controller. */ -/* */ -/* PARAMETERS : */ -/* IN : u8 Clock divider value for desired frequency. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ -/* COMMENT: Clock frequency is calculated by this formula: */ -/* MCICLK = MCLK/(2 * [Clock_div +1]) */ - -/****************************************************************************/ - -t_mmc_error mmc_setclockfrequency(u8 clockdiv) -{ - t_mmc_error error; - - MMC_SET_CLKDIV(t_mmc0->mmc_Clock, clockdiv); - error = MMC_OK; - - return error; -} - -/****************************************************************************/ -/* NAME : mmc_sendcommand */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine sends command and enable Command path */ -/* state machine. */ -/* PARAMETERS : */ -/* IN : t_mmc_Command_index: Command to send. */ -/* u32: argument to send. */ -/* t_mmc_Command_control: Command control parameters to set. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ - -/****************************************************************************/ - -t_mmc_error mmc_sendcommand(t_mmc_command_index commandindex, u32 argument, - t_mmc_command_control commcontrol) -{ - t_mmc_error error; - u32 reg; - - if (commandindex != MMC_NO_CMD) - { - reg = commandindex; - t_mmc0->mmc_Argument = argument; - reg |= (commcontrol.IsRespExpected << 6); - reg |= (commcontrol.IsLongResp << 7); - reg |= (commcontrol.IsInterruptMode << 8); - reg |= (commcontrol.IsPending << 9); - reg |= (commcontrol.cmdpath << 10); - t_mmc0->mmc_Command = reg; - } - - error = MMC_OK; - return error; -} - -/****************************************************************************/ -/* NAME : mmc_getresponse */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine returns command index of last command for */ -/* which response received. */ -/* PARAMETERS : */ -/* IN : */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_Command_index command index of last command */ - -/****************************************************************************/ - -t_mmc_command_index mmc_getcommandresponse() -{ - t_mmc_command_index respcommand; - respcommand = t_mmc0->mmc_RespCommand; - return respcommand; -} - -/****************************************************************************/ -/* NAME : mmc_getresponse */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine returns response received from the card for */ -/* the last command. */ -/* PARAMETERS : */ -/* IN : t_mmc_response_type Expected response type */ -/* u32 * u32 pointer to store response. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ - -/****************************************************************************/ - -t_mmc_error mmc_getresponse(t_mmc_response_type resptype, u32 * response) -{ - t_mmc_error error; - if (resptype == MMC_SHORT_RESP) - *response = (t_mmc0->mmc_Response0); - else - { - *response = t_mmc0->mmc_Response0; - *(response + 1) = t_mmc0->mmc_Response1; - *(response + 2) = t_mmc0->mmc_Response2; - *(response + 3) = t_mmc0->mmc_Response3; - } - - error = MMC_OK; - return error; - -} - -/****************************************************************************/ -/* NAME : mmc_setdatapath */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine enables/disables the data path for data transfer.*/ -/* */ -/* PARAMETERS : */ -/* IN : t_mmc_state Specifies the state of the */ -/* data path, whether to enabled or disabled. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ - -/****************************************************************************/ - -t_mmc_error mmc_setdatapath(t_mmc_state datapath) -{ - t_mmc_error error; - MMC_SET_DATAPATH(t_mmc0->mmc_DataCtrl, datapath); - error = MMC_OK; - return error; -} - -/****************************************************************************/ -/* NAME : mmc_setdatatimeout */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine sets the data timeout period in card bus */ -/* clock periods */ -/* PARAMETERS : */ -/* IN : u32 Specifies the timeout value of the data path. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ - -/****************************************************************************/ - -t_mmc_error mmc_setdatatimeout(u32 datatimeout) -{ - t_mmc_error error; - t_mmc0->mmc_DataTimer = datatimeout; - error = MMC_OK; - return error; - -} - -/******************************************************************************/ -/* NAME : mmc_setdatalength */ -/*----------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine sets the data length (in bytes) for the data */ -/* transfer. */ -/* PARAMETERS : */ -/* IN : u16 Specifies the number of data bytes to be transferred.*/ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ - -/******************************************************************************/ - -t_mmc_error mmc_setdatalength(u16 datalength) -{ - t_mmc_error error; - - t_mmc0->mmc_DataLength = datalength; - error = MMC_OK; - return error; -} - -/****************************************************************************/ -/* NAME : mmc_setdatablocklength */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine sets the data block size (in an encoded fashion)*/ -/* for block data transfer. */ -/* PARAMETERS : */ -/* IN : u8 Specifies the data block size for block transfer. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ - -/****************************************************************************/ - -t_mmc_error mmc_setdatablocklength(u8 blocksize) -{ - t_mmc_error error; - if (blocksize <= MAXBSIZEPOWER) - { - MMC_SET_BLOCKSIZE(t_mmc0->mmc_DataCtrl, blocksize); - error = MMC_OK; - } - else - error = MMC_INVALID_PARAMETER; - return error; - -} - -/****************************************************************************/ -/* NAME : mmc_settransferdirection */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: routine sets direction for data transfer, whether */ -/* the transfer is a read or write. */ -/* PARAMETERS : */ -/* IN : t_mmc_transfer_direction the direction for data transfer. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ - -/****************************************************************************/ - -t_mmc_error mmc_settransferdirection(t_mmc_transfer_direction transdir) -{ - t_mmc_error error = MMC_OK; - MMC_SET_DATADIR(t_mmc0->mmc_DataCtrl, transdir); - return error; -} - -/******************************************************************************/ -/* NAME : mmc_settransfertype */ -/*----------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine sets whether data transfer is */ -/* in stream mode or block mode. */ -/* PARAMETERS : */ -/* IN : t_mmc_transfer_type Specifies the transfer type for data transfer. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ -/******************************************************************************/ - -t_mmc_error mmc_settransfertype(t_mmc_transfer_type transtype) -{ - t_mmc_error error = MMC_OK; - MMC_SET_MODE(t_mmc0->mmc_DataCtrl, transtype); - return error; -} - -/****************************************************************************/ -/* NAME : mmc_handledma */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine enables or disables data transfer through DMA. */ -/* PARAMETERS : */ -/* IN : t_mmc_state Specifies whether to enable/disable DMA for */ -/* data transfer. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_handledma(t_mmc_state dmastate) -{ - t_mmc_error error = MMC_OK; - MMC_SET_DMA(t_mmc0->mmc_DataCtrl, dmastate); - return error; -} - -/****************************************************************************/ -/* NAME : mmc_getdatacounter */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine returns number of data elements (in bytes) */ -/* yet to be transferred. */ -/* PARAMETERS : */ -/* IN : */ -/* OUT : */ -/* */ -/* RETURN : u16 */ -/****************************************************************************/ - -u16 mmc_getdatacounter() -{ - u16 no_of_elements; - no_of_elements = t_mmc0->mmc_DataCnt; - return no_of_elements; -} - -/****************************************************************************/ -/* NAME : mmc_selectsdcard */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine selects specific SD card. */ -/* PARAMETERS : */ -/* IN : u8 SD card to select. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_selectsdcard(u8 cardno) -{ - t_mmc_error error; - - if (cardno < 16) - { - t_mmc0->mmc_SelectSD = cardno; - error = MMC_OK; - } - else - error = MMC_REQUEST_NOT_APPLICABLE; - - return error; - -} - -/****************************************************************************/ -/* NAME : mmc_Poweron */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine enquires cards about their operating voltage */ -/* and sets optimal value to supply output voltage. Sends out */ -/* of range cards to inactive states. Also configures */ -/* clock controls. */ -/* PARAMETERS : */ -/* IN : */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_poweron(u8 card_num) -{ - t_mmc_error error = MMC_OK; - u32 response, one_msec, count = 0, delay; - t_bool validvoltage, flag = FALSE; - u32 address_mode = Byte_Mode; - - validvoltage = FALSE; - selected_card = 0; - no_of_cards = 5; - - t_mmc[card_num]->mmc_Power = 0x43; //PowerOn | OpenDrain; - - t_mmc[card_num]->mmc_Clock = 0x41FF; //ClkDivInit| ClkEnable | Hwfc_en;//setting clk freq just less than 400KHz - clockfreq = MCLK / (2 * (ClkDivInit + 1)); - t_mmc[card_num]->mmc_Mask0 &= ~AllInterrupts; - one_msec = 52000 / ((t_mmc[card_num]->mmc_Power & 0xFF) + 2); - - t_mmc[card_num]->mmc_Argument = 0; - t_mmc[card_num]->mmc_Command = (GO_IDLE_STATE & ~RespExpected) | CmdPathEnable; - error = mmc_cmderror(card_num); - if (error != MMC_OK) - return error; - - /* send CMD8 to verify SD card interface operating condition */ - t_mmc[card_num]->mmc_Argument = Check_Pattern; - t_mmc[card_num]->mmc_Command = SD_SEND_IF_COND | RespExpected | CmdPathEnable; - - error = mmc_cmdresp7error(card_num); - /* IF ERROR IS COMMAND TIMEOUT IT IS MMC CARD */ - if (error == MMC_OK) - { - address_mode = Sector_Mode; - } - else - { - t_mmc[card_num]->mmc_Argument = 0; - t_mmc[card_num]->mmc_Command = (GO_IDLE_STATE & ~RespExpected) | CmdPathEnable; - error = mmc_cmderror(card_num); - if (error != MMC_OK) - return error; - } - t_mmc[card_num]->mmc_Argument = 0; - t_mmc[card_num]->mmc_Command = APP_CMD | RespExpected | CmdPathEnable; - -#define barrier() asm volatile("" ::: "memory") - for (delay = 0; delay < (one_msec * 27); delay++) - barrier(); - - error = mmc_cmdresp145error(APP_CMD, card_num); - - /* IF ERROR IS COMMAND TIMEOUT IT IS MMC CARD */ - if (MMC_OK == error) - { - /*SD CARD */ - /*Send CMD41 SD_APP_APP_OP_COND WITH ARGUMENT 0x00FFC000 */ - printf(" initcard:: Set the SD voltage \n"); - while ((!validvoltage) && (count < 0xFFFF)) - { - if (flag) - { - /*SEND CMD55 APP_CMD with RCA as 0*/ - t_mmc[card_num]->mmc_Argument = 0; - t_mmc[card_num]->mmc_Command = APP_CMD | RespExpected | CmdPathEnable; - - error = mmc_cmdresp145error(APP_CMD, card_num); - if (error != MMC_OK) - { - return (error); - } - } - - t_mmc[card_num]->mmc_Argument = VoltageWindowSD | address_mode; /* voltage window */ - t_mmc[card_num]->mmc_Command = SD_APP_OP_COND | RespExpected | CmdPathEnable; - - error = mmc_cmdresp3error(card_num); - if (MMC_OK != error) - { - return (error); - } - - response = t_mmc[card_num]->mmc_Response0; - validvoltage = (t_bool) (((response >> 31) == 1) ? 1 : 0); - flag = TRUE; - count++; - } - - if (count >= 0xFFFF) - { - error = MMC_INVALID_VOLTRANGE; - return (error); - } - - if (Sector_Mode == address_mode) - { - printf(" SD high capacity card detected \n"); - } - else - { - printf(" SD card detected \n"); - } - sd_card = 1; - } - else if (MMC_CMD_RSP_TIMEOUT == error) - { - /*Send CMD0 GO_IDLE_STATE*/ - printf(" initcard:: Set the MMC voltage \n"); - t_mmc[card_num]->mmc_Argument = 0; - t_mmc[card_num]->mmc_Command = (GO_IDLE_STATE & ~RespExpected) | CmdPathEnable; - - error = mmc_cmderror(card_num); - if (MMC_OK != error) - { - return (error); - } - address_mode = Byte_Mode; - validvoltage = FALSE; - response = 0; - - /* MMC_CARD */ - while ((!validvoltage) && (count < 0xFFFF)) - { - t_mmc[card_num]->mmc_Argument = 0xc0ff8000; //VoltageWindowMMC | address_mode; - t_mmc[card_num]->mmc_Command = SEND_OP_COND | RespExpected | CmdPathEnable; - - error = mmc_cmdresp3error(card_num); - if (MMC_OK != error) - { - return (error); - } - - for (delay = 0; delay < 1; delay++) ; - - response = t_mmc[card_num]->mmc_Response0; - validvoltage = (t_bool) (((response >> 31) == 1) ? 1 : 0); - count++; - } - - if (count >= 0xFFFF) - { - error = MMC_INVALID_VOLTRANGE; - return (error); - } - - if (response & Sector_Mode) - { - printf(" MMC high capacity card detected \n"); - } - else - { - printf(" EMMC card detected \n"); - } - mmc_card = 1; - error = MMC_OK; - } - return error; -} - -/****************************************************************************/ -/* NAME : mmc_Poweroff */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine turns the supply output voltage off. */ -/* PARAMETERS : */ -/* IN : */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ -t_mmc_error mmc_poweroff(u8 card_num) -{ - t_mmc_error error = MMC_OK; - t_mmc[card_num]->mmc_Power &= ~PowerOn; - return error; -} - -/****************************************************************************/ -/* NAME : mmc_initializeCards */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine initializes all cards. All cards come into */ -/* standby state. */ -/* PARAMETERS : */ -/* IN : */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_initializeCards(u8 card_num) -{ - t_mmc_error error = MMC_OK; - u16 rca = emmc_rel_addr; - t_bool card_initialized = FALSE; - - if ((t_mmc[card_num]->mmc_Power & PowerOn) == 0x00) - { - printf("emmc power failed \n"); - error = MMC_REQUEST_NOT_APPLICABLE; - return error; - } - while (!card_initialized) - { - t_mmc[card_num]->mmc_Argument = 0x00000000; - t_mmc[card_num]->mmc_Command = ALL_SEND_CID | RespExpected | LongResponse | CmdPathEnable; - - error = mmc_cmdresp2error(card_num); - if (MMC_OK != error) - { - return (error); - } - - card_array[card_num].CID[0] = t_mmc[card_num]->mmc_Response3; - card_array[card_num].CID[1] = t_mmc[card_num]->mmc_Response2; - card_array[card_num].CID[2] = t_mmc[card_num]->mmc_Response1; - card_array[card_num].CID[3] = t_mmc[card_num]->mmc_Response0; - if (mmc_card == 1) - { - printf("init the MMC Card\n"); - t_mmc[card_num]->mmc_Argument = rca;//rca << 16; - t_mmc[card_num]->mmc_Command = SET_REL_ADDR | RespExpected | CmdPathEnable; - - error = mmc_cmdresp145error(SET_REL_ADDR, card_num); - if (error != MMC_OK) - { - printf ("emmc card init response for CMD3 error \n"); - return error; - } - } - else if (sd_card == 1) - { - printf("init the SD Card\n"); - t_mmc[card_num]->mmc_Argument = 0; - t_mmc[card_num]->mmc_Command = SET_REL_ADDR | RespExpected | CmdPathEnable; - - error = mmc_cmdresp6error(SET_REL_ADDR, &rca, card_num); - if (error != MMC_OK) - { - printf ("emmc card init response for CMD6 error \n"); - return error; - } - } - card_array[card_num].RCA = rca; - t_mmc[card_num]->mmc_Argument = rca;//(u32) rca << 16; - t_mmc[card_num]->mmc_Command = SEND_CSD | RespExpected | LongResponse | CmdPathEnable; - - error = mmc_cmdresp2error(card_num); - if (error != MMC_OK) - { - printf("emmc card init response for CMD9 error \n"); - return error; - } - card_array[card_num].CSD[0] = t_mmc[card_num]->mmc_Response3; - card_array[card_num].CSD[1] = t_mmc[card_num]->mmc_Response2; - card_array[card_num].CSD[2] = t_mmc[card_num]->mmc_Response1; - card_array[card_num].CSD[3] = t_mmc[card_num]->mmc_Response0; - - //rca++; - error = MMC_OK; //All cards get intialized - card_initialized = TRUE; - - if (card_num != selected_card) - { - t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA; - t_mmc[card_num]->mmc_Command = SEL_DESEL_CARD - | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SEL_DESEL_CARD, card_num); - - if (error != MMC_OK) - { - printf("SEL_DESEL_CARD ::error=0x%x \n", error); - return error; - } - else - selected_card = card_num; - } - - t_mmc[card_num]->mmc_Argument = (u32) (0x03B70201); - t_mmc[card_num]->mmc_Command = - APP_SD_SET_BUSWIDTH | RespExpected | CmdPathEnable; - - error = mmc_cmdresp2error(card_num); - if (error != MMC_OK) - { - printf("emmc card init response for CMD6 error \n"); - return error; - } - } - t_mmc[card_num]->mmc_Power = 0x3; - t_mmc[card_num]->mmc_Clock = 0x7500; - - /* TODO remove this and use EXT_CSD to determine it */ - if (mmc_card == 1 && t_mmc[card_num] == 0x80005000) - card_array[card_num].blockaddressed = 0; - else - card_array[card_num].blockaddressed = 1; - - return error; -} - -/****************************************************************************/ -/* NAME : mmc_setdevicemode */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine sets device mode whether to operate in Polling,*/ -/* Interrupt, dma mode. */ -/* PARAMETERS : */ -/* IN : t_mmc_device_mode mode to for further transmission. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_setdevicemode(t_mmc_device_mode mode) -{ - t_mmc_error error; - - switch (mode) - { - case POLLING_MODE: - device_mode = POLLING_MODE; - break; - case INTERRUPT_MODE: - device_mode = INTERRUPT_MODE; - break; - case DMA_MODE: - device_mode = DMA_MODE; - break; - default: - error = MMC_INVALID_PARAMETER; - return error; - } - - error = MMC_OK; - return error; -} - -/****************************************************************************/ -/* NAME : mmc_readbytes */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine allows to read bytes from specified address */ -/* in a card */ -/* PARAMETERS : */ -/* IN : u8 cardno: card to access */ -/* u32 addr : address from where to start reading */ -/* u16 no_of_bytes: no. of bytes to read */ -/* OUT : u32* readbuff: buffer to store data */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_readbytes(u8 card_num, u32 addr, u32 * readbuff,u16 no_of_bytes) -{ - t_mmc_error error = MMC_OK; - u32 i; - u32 timeout = 0; - u32 *tempbuff = readbuff; - - total_no_of_bytes = 0; - - t_mmc0->mmc_DataCtrl = AllZero; - - if ((card_num > no_of_cards) || (card_num == 0)) - { - error = MMC_INVALID_PARAMETER; - return error; - } - - /* send command for selecting the card */ - if (card_num != selected_card) - { - t_mmc0->mmc_Argument = card_array[card_num].RCA;//card_array[card_num - 1].RCA << 16; - t_mmc0->mmc_Command = SEL_DESEL_CARD | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SET_REL_ADDR, card_num); - if (error != MMC_OK) - return error; - else - selected_card = card_num; - } - - /* now depending on parameter no_of_bytes, send command READ_DAT_UNTIL_STOP */ - - if (no_of_bytes == 0) // this means open-ended stream read,until STOP_TRANSMISSION follows - { - if (device_mode != INTERRUPT_MODE) - return MMC_REQUEST_NOT_APPLICABLE; - - total_no_of_bytes = 65532; - - t_mmc0->mmc_DataLength = 65532; - - t_mmc0->mmc_DataTimer = 0xefffffff; - - t_mmc0->mmc_DataCtrl = ReadDir | StreamMode | DataPathEnable; - - dest_buffer = readbuff; - - t_mmc0->mmc_Clock = (t_mmc0->mmc_Clock & 0xFFFFFF00) | 0x0000000B; - - t_mmc0->mmc_Argument = addr >> 9; - t_mmc0->mmc_Command = READ_DAT_UNTIL_STOP | RespExpected | CmdPathEnable; - - error = mmc_cmdresp145error(READ_DAT_UNTIL_STOP, card_num); - if (error != MMC_OK) - return error; - - t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | RxFifoHalfFull | RxOverrun; - } - else if (no_of_bytes > 0) - { - total_no_of_bytes = no_of_bytes; - - t_mmc0->mmc_DataLength = no_of_bytes; - - t_mmc0->mmc_DataTimer = 0xefffffff; - - t_mmc0->mmc_DataCtrl = ReadDir | StreamMode | DataPathEnable; - - dest_buffer = readbuff; - - t_mmc0->mmc_Clock = (t_mmc0->mmc_Clock & 0xFFFFFF00) | 0x0000000B; - - t_mmc0->mmc_Argument = addr >> 9; - t_mmc0->mmc_Command = READ_DAT_UNTIL_STOP | RespExpected | CmdPathEnable; - - error = mmc_cmdresp145error(READ_DAT_UNTIL_STOP, card_num); - - if (error != MMC_OK) - return error; - - if (device_mode == POLLING_MODE) - { - - timeout = 0xffffffff; - - while ((timeout > 0) && !(t_mmc0->mmc_Status & (DataCrcFail | DataTimeOut | DataEnd))) - { - timeout--; - if (t_mmc0->mmc_Status & RxFifoHalfFull) - { - for (i = 0; i < 8; i++) - *(tempbuff + i) = t_mmc0->mmc_Fifo; - tempbuff += 8; - } - - } - - if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut)) - { - t_mmc0->mmc_Clear |= DataTimeOut; - error = MMC_DATA_TIMEOUT; - transfer_error = MMC_DATA_TIMEOUT; - return error; - } - else if (t_mmc0->mmc_Status & DataCrcFail) - { - t_mmc0->mmc_Clear |= DataCrcFail; - error = MMC_DATA_CRC_FAIL; - transfer_error = MMC_DATA_CRC_FAIL; - return error; - } - - t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags - - while (t_mmc0->mmc_Status & RxDataAvlbl) - { - *tempbuff = t_mmc0->mmc_Fifo; - tempbuff++; - } - - t_mmc0->mmc_Argument = 0x00000000; - t_mmc0->mmc_Command = STOP_TRANSMISSION | RespExpected | CmdPathEnable; - - error = mmc_cmdresp145error(STOP_TRANSMISSION, card_num); - - transfer_error = error; - if (error != MMC_OK) - return error; - - } - - else if (device_mode == INTERRUPT_MODE) - t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxFifoHalfFull | RxOverrun; - - else if (device_mode == DMA_MODE) - { - t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxOverrun; - t_mmc0->mmc_DataCtrl |= DMAEnab; - } - } - return error; -} - -/****************************************************************************/ -/* NAME : mmc_writebytes */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine allows to write bytes starting from a specified*/ -/* address in a card */ -/* PARAMETERS : */ -/* IN : u8 cardno: card to access */ -/* u32 addr : address where to start writing */ -/* u16 no_of_bytes: no. of bytes to write */ -/* OUT : u32* writebuff: source buffer */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_writebytes(u8 card_num, u32 addr, u32 * writebuff, u16 no_of_bytes) -{ - t_mmc_error error; - u32 timeout = 0; - u32 *tempbuff = writebuff; - u32 i, j, bytes_transferred = 0; - u8 cardstate; - - total_no_of_bytes = 0; - - t_mmc0->mmc_DataCtrl = AllZero; - - if ((card_num > no_of_cards) || (card_num == 0)) - { - error = MMC_INVALID_PARAMETER; - return error; - } - /* send command for selecting the card */ - - if (card_num != selected_card) - { - t_mmc0->mmc_Argument = card_array[card_num].RCA;//card_array[card_num - 1].RCA << 16; - t_mmc0->mmc_Command = SEL_DESEL_CARD | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SEL_DESEL_CARD, card_num); - - if (error != MMC_OK) - return error; - else - selected_card = card_num; - } - - /* now depending on parameter no_of_bytes, send command WRITE_DAT_UNTIL_STOP */ - - if (no_of_bytes == 0) // this means open-ended stream read,until STOP_TRANSMISSION follows - { - if (device_mode != INTERRUPT_MODE) - return MMC_REQUEST_NOT_APPLICABLE; - - t_mmc0->mmc_DataTimer = 0xefffffff; - - total_no_of_bytes = 65532; - - t_mmc0->mmc_DataLength = 65532; - - source_buffer = writebuff; - - t_mmc0->mmc_Clock = (t_mmc0->mmc_Clock & 0xFFFFFF00) | 0x00000031; - - t_mmc0->mmc_Argument = addr >> 9; - t_mmc0->mmc_Command = WRITE_DAT_UNTIL_STOP | RespExpected | CmdPathEnable; - - error = mmc_cmdresp145error(WRITE_DAT_UNTIL_STOP, card_num); - - if (error != MMC_OK) - return error; - - t_mmc0->mmc_DataCtrl = (StreamMode & ~ReadDir) | DataPathEnable; - - t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | TxFifoHalfEmpty | TxUnderrun; - - /*Now the card will send data thru DMA to the destination buffer.CRC/TimeOut error will - be handled in the interrupt handler*/ - } - else if (no_of_bytes > 0) - { - total_no_of_bytes = no_of_bytes; - - t_mmc0->mmc_DataLength = no_of_bytes; - - t_mmc0->mmc_DataTimer = 0xefffffff; - - source_buffer = writebuff; - - t_mmc0->mmc_Argument = addr >> 9; - t_mmc0->mmc_Command = WRITE_DAT_UNTIL_STOP | RespExpected | CmdPathEnable; - - error = mmc_cmdresp145error(WRITE_DAT_UNTIL_STOP, card_num); - - if (error != MMC_OK) - return error; - - t_mmc0->mmc_DataCtrl = (StreamMode & ~ReadDir) | DataPathEnable; - - if (device_mode == POLLING_MODE) - { - timeout = 0xefffffff; - - while ((timeout > 0) && !(t_mmc0->mmc_Status & (DataCrcFail | DataTimeOut | DataEnd))) - { - timeout--; - if (t_mmc0->mmc_Status & TxFifoHalfEmpty) - { - if ((total_no_of_bytes - bytes_transferred) < 32) - { - j = ((total_no_of_bytes - bytes_transferred) % 4 == 0) ? - ((total_no_of_bytes - bytes_transferred) / 4) - : ((total_no_of_bytes - bytes_transferred) / 4 +1); - - for (i = 0; i < j; i++, tempbuff++,bytes_transferred += 4) - t_mmc0->mmc_Fifo = *tempbuff; - - } - else - { - for (i = 0; i < 8; i++) - t_mmc0->mmc_Fifo = *(tempbuff + i); - tempbuff += 8; - bytes_transferred += 32; - } - } - } - - if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut)) - { - t_mmc0->mmc_Clear |= DataTimeOut; - transfer_error = error = MMC_DATA_TIMEOUT; - return error; - } - else if (t_mmc0->mmc_Status & DataCrcFail) - { - t_mmc0->mmc_Clear |= DataCrcFail; - transfer_error = error = MMC_DATA_CRC_FAIL; - return error; - } - - t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags - - mmc_iscardprogramming(card_num, &cardstate); - while ((cardstate == 7) || (cardstate == 6)) - mmc_iscardprogramming(card_num, &cardstate); - - t_mmc0->mmc_Argument = 0x00000000; - t_mmc0->mmc_Command = STOP_TRANSMISSION | RespExpected | CmdPathEnable; - - transfer_error = error = mmc_cmdresp145error(STOP_TRANSMISSION, card_num); - - if (error != MMC_OK) - return error; - - } - - else if (device_mode == INTERRUPT_MODE) - - t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | TxFifoHalfEmpty | TxUnderrun; - - else if (device_mode == DMA_MODE) - { - t_mmc0->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | TxUnderrun; - t_mmc0->mmc_DataCtrl |= DMAEnab; - } - - } - error = MMC_OK; - return error; -} - -/****************************************************************************/ -/* NAME : mmc_readblocks */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine allows to read blocks from a specified */ -/* address in a card */ -/* PARAMETERS : */ -/* IN : u8 cardno: card to access */ -/* u32 addr : address from where to start reading */ -/* u16 blocksize : size of block in bytes */ -/* u16 no_of_blocks: no. of blocks to read */ -/* OUT : u32* readbuff: source buffer */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_readblocks(u8 card_num, u32 addr, u32 * readbuff, u16 blocksize, u16 no_of_blocks) -{ - t_mmc_error error = MMC_OK; - u32 i; - u32 timeout = 0; - u8 power; - u32 *tempbuff = readbuff; - - total_no_of_bytes = 0; - - t_mmc[card_num]->mmc_DataCtrl = AllZero; - - /* send command for selecting the card */ - if ((card_num > no_of_cards) || (card_num == 0)) - { - error = MMC_INVALID_PARAMETER; - return error; - } - if (card_num != selected_card) - { - t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA;//0x1 << 16; //card_array[cardno - 1].RCA << 16; - t_mmc[card_num]->mmc_Command = SEL_DESEL_CARD | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SEL_DESEL_CARD, card_num); - - if (error != MMC_OK) - { - printf("SEL_DESEL_CARD ::error=0x%x \n", error); - return error; - } - else - selected_card = card_num; - } - - if (t_mmc[card_num]->mmc_Response0 & 0x02000000) - return MMC_LOCK_UNLOCK_FAILED; - - /* now depending on parameter no_of_blocks, send command READ_DAT_UNTIL_STOP */ - - //set the block size,both on controller and card - - if ((blocksize > 0) && (blocksize <= 2048) && ((blocksize & (blocksize - 1)) == 0)) - { - - power = convert_from_bytes_to_power_of_two(blocksize); - t_mmc[card_num]->mmc_DataCtrl = power << 4; - - t_mmc[card_num]->mmc_Argument = (u32) blocksize; - t_mmc[card_num]->mmc_Command = SET_BLOCKLEN | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SET_BLOCKLEN, card_num); - - if (error != MMC_OK) - { - printf("SET_BLOCKLEN ::error=0x%x \n", error); - return error; - } - } - else - { - printf("SET_BLOCKLEN ::error set proper block len\n"); - error = MMC_INVALID_PARAMETER; - return error; - } - - if (no_of_blocks == 0) // this means open-ended block read,until STOP_TRANSMISSION follows - { - - if (device_mode != INTERRUPT_MODE) - return MMC_REQUEST_NOT_APPLICABLE; - - t_mmc[card_num]->mmc_DataTimer = 0xefffffff; - - t_mmc[card_num]->mmc_DataLength = (65535 / blocksize) * blocksize; - - total_no_of_bytes = (65535 / blocksize) * blocksize; - - t_mmc[card_num]->mmc_Argument = (65535 / blocksize); - t_mmc[card_num]->mmc_Command = SET_BLOCK_COUNT | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SET_BLOCK_COUNT, card_num); - - if (error != MMC_OK) - return error; - - t_mmc[card_num]->mmc_DataCtrl |= (ReadDir & ~StreamMode) | DataPathEnable; - - dest_buffer = readbuff; - - t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; - t_mmc[card_num]->mmc_Command = READ_MULT_BLOCK | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(READ_MULT_BLOCK, card_num); - - if (error != MMC_OK) - return error; - - t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | RxFifoHalfFull | RxOverrun; - - /*Now the card will send data thru DMA to the destination buffer.CRC/TimeOut error will - be handled in the interrupt handler*/ - - } - else if (no_of_blocks == 1) - { - total_no_of_bytes = blocksize; - - t_mmc[card_num]->mmc_DataLength = blocksize; - - t_mmc[card_num]->mmc_DataTimer = 0x0fffffff; - - t_mmc[card_num]->mmc_DataCtrl |= (ReadDir & ~StreamMode) | DataPathEnable; - - dest_buffer = readbuff; - - t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; - t_mmc[card_num]->mmc_Command = READ_SINGLE_BLOCK | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(READ_SINGLE_BLOCK, card_num); - - if (error != MMC_OK) - { - printf("READ_SINGLE_BLOCK ::error=0x%x \n", error); - return error; - } - if (device_mode == POLLING_MODE) - { - - timeout = 0xefffffff; - - while ((timeout > 0) && !(t_mmc[card_num]->mmc_Status & (RxOverrun | DataCrcFail | - DataTimeOut | DataBlockEnd))) - { - timeout--; - if (t_mmc[card_num]->mmc_Status & RxFifoHalfFull) - { - for (i = 0; i < 8; i++) - { - *(tempbuff + i) = t_mmc[card_num]->mmc_Fifo; - } - tempbuff += 8; - } - - } - - if ((timeout == 0)|| (t_mmc[card_num]->mmc_Status & DataTimeOut)) - { - t_mmc[card_num]->mmc_Clear |= DataTimeOut; - transfer_error = error = MMC_DATA_TIMEOUT; - printf("mmc_readblocks::1 MMC_DATA_TIMEOUT \n"); - return error; - } - else if (t_mmc[card_num]->mmc_Status & DataCrcFail) - { - t_mmc[card_num]->mmc_Clear |= DataCrcFail; - transfer_error = error = MMC_DATA_CRC_FAIL; - printf("mmc_readblocks::1 MMC_DATA_CRC_FAIL \n"); - return error; - } - else if (t_mmc[card_num]->mmc_Status & RxOverrun) - { - t_mmc[card_num]->mmc_Clear |= RxOverrun; - transfer_error = error = MMC_RX_OVERRUN; - printf("mmc_readblocks::1 MMC_RX_OVERRUN \n"); - return error; - } - - while (t_mmc[card_num]->mmc_Status & RxDataAvlbl) - { - *tempbuff = t_mmc[card_num]->mmc_Fifo; - tempbuff++; - } - transfer_error = error; - t_mmc[card_num]->mmc_Clear = ClrStaticFlags; //clear all the static status flags - } - - else if (device_mode == INTERRUPT_MODE) - { - t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxFifoHalfFull | RxOverrun; - } - else if (device_mode == DMA_MODE) - { - t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxOverrun; - t_mmc[card_num]->mmc_DataCtrl |= DMAEnab; - } - - } - else if (no_of_blocks > 1) - { - // set the block count,both for the controller and the card - total_no_of_bytes = no_of_blocks * blocksize; - - t_mmc[card_num]->mmc_DataLength = no_of_blocks * blocksize; - - t_mmc[card_num]->mmc_Argument = (u32) no_of_blocks; - t_mmc[card_num]->mmc_Command = SET_BLOCK_COUNT | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SET_BLOCK_COUNT, card_num); - - if (error != MMC_OK) - return error; - - t_mmc[card_num]->mmc_DataTimer = 0xefffffff; - - t_mmc[card_num]->mmc_DataCtrl |= (ReadDir & ~StreamMode) | DataPathEnable; - - dest_buffer = readbuff; - - t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; - t_mmc[card_num]->mmc_Command = READ_MULT_BLOCK | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(READ_MULT_BLOCK, card_num); - if (error != MMC_OK) - return error; - - if (device_mode == POLLING_MODE) - { - timeout = 0xefffffff; - while ((timeout > 0)&& !(t_mmc[card_num]->mmc_Status & (RxOverrun | DataCrcFail |DataTimeOut | DataEnd))) - { - timeout--; - if (t_mmc[card_num]->mmc_Status & RxFifoHalfFull) - { - for (i = 0; i < 8; i++) - { - *(tempbuff + i) = t_mmc[card_num]->mmc_Fifo; - } - tempbuff += 8; - } - } - - if ((timeout == 0) || (t_mmc[card_num]->mmc_Status & DataTimeOut)) - { - t_mmc[card_num]->mmc_Clear |= DataTimeOut; - transfer_error = error = MMC_DATA_TIMEOUT; - return error; - - } - else if (t_mmc[card_num]->mmc_Status & DataCrcFail) - { - t_mmc[card_num]->mmc_Clear |= DataCrcFail; - transfer_error = error = MMC_DATA_CRC_FAIL; - return error; - } - else if (t_mmc[card_num]->mmc_Status & RxOverrun) - { - t_mmc[card_num]->mmc_Clear |= RxOverrun; - transfer_error = error = MMC_RX_OVERRUN; - return error; - } - - while (t_mmc[card_num]->mmc_Status & RxDataAvlbl) - { - *tempbuff = t_mmc[card_num]->mmc_Fifo; - tempbuff++; - } - transfer_error = error; - t_mmc[card_num]->mmc_Clear = ClrStaticFlags; //clear all the static status flags - } - - else if (device_mode == INTERRUPT_MODE) - { - t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxFifoHalfFull | RxOverrun; - } - else if (device_mode == DMA_MODE) - { - t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | RxOverrun; - t_mmc[card_num]->mmc_DataCtrl |= DMAEnab; - } - } - - return error; -} - -/****************************************************************************/ -/* NAME : mmc_writeblocks */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine allows to write blocks starting from a */ -/* specified address in a card */ -/* PARAMETERS : */ -/* IN : u8 cardno: card to access */ -/* u32 addr : address from where to start writing */ -/* u16 blocksize : size of block in bytes */ -/* u16 no_of_blocks: no. of blocks to write */ -/* OUT : u32* writebuff: source buffer */ -/* */ -/* RETURN : t_mmc_error */ -/****************************************************************************/ - -t_mmc_error mmc_writeblocks(u8 card_num, u32 addr, u32 * writebuff, - u16 blocksize, u16 no_of_blocks) -{ - t_mmc_error error = MMC_OK; - u32 count, rest_words; - u8 power, cardstate; - u32 timeout = 0; - u32 *tempbuff = writebuff; - u32 bytes_transferred = 0; - u32 card_status; - - if (NULL == writebuff) - { - error = MMC_INVALID_PARAMETER; - return (error); - } - - total_no_of_bytes = 0; - - t_mmc[card_num]->mmc_DataCtrl = AllZero; - - /* send command for selecting the card */ - if ((card_num > no_of_cards) || (card_num == 0)) - { - error = MMC_INVALID_PARAMETER; - return error; - } - if (card_num != selected_card) - { - t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA; //card_array[cardno - 1].RCA << 16; - t_mmc[card_num]->mmc_Command = SEL_DESEL_CARD | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SEL_DESEL_CARD, card_num); - - if (error != MMC_OK) - return error; - else - selected_card = card_num; - } - - if (t_mmc[card_num]->mmc_Response0 & R1_CARD_IS_LOCKED) - return MMC_LOCK_UNLOCK_FAILED; - - /* now depending on parameter no_of_blocks, send command READ_DAT_UNTIL_STOP */ - - //set the block size,both on controller and card - - if ((blocksize > 0) && (blocksize <= 2048) - && (((blocksize & (blocksize - 1)) == 0))) - { - power = convert_from_bytes_to_power_of_two(blocksize); - t_mmc[card_num]->mmc_DataCtrl = power << 4; - - t_mmc[card_num]->mmc_Argument = (u32) blocksize; - t_mmc[card_num]->mmc_Command = SET_BLOCKLEN | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SET_BLOCKLEN, card_num); - - if (error != MMC_OK) - return error; - - } - else - { - printf(" mmc_writeblocks::bad block size \n"); - error = MMC_INVALID_PARAMETER; - return error; - } - - if (no_of_blocks == 0) // this means open-ended block read,until STOP_TRANSMISSION follows - { - if (device_mode != INTERRUPT_MODE) - return MMC_REQUEST_NOT_APPLICABLE; - - t_mmc[card_num]->mmc_DataTimer = 0xefffffff; - - t_mmc[card_num]->mmc_DataLength = (65535 / blocksize) * blocksize; - - total_no_of_bytes = (65535 / blocksize) * blocksize; - - t_mmc[card_num]->mmc_Argument = (65535 / blocksize); - t_mmc[card_num]->mmc_Command = SET_BLOCK_COUNT | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SET_BLOCK_COUNT, card_num); - - if (error != MMC_OK) - return error; - - source_buffer = writebuff; - - t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; - t_mmc[card_num]->mmc_Command = WRITE_MULT_BLOCK | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(WRITE_MULT_BLOCK, card_num); - - if (error != MMC_OK) - return error; - - t_mmc[card_num]->mmc_DataCtrl |= DataPathEnable & ~(ReadDir | StreamMode); - - t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | TxFifoHalfEmpty | TxUnderrun; - - /*Now the card will send data thru DMA to the destination buffer.CRC/TimeOut error will - be handled in the interrupt handler*/ - - } - else if (no_of_blocks == 1) - { - total_no_of_bytes = blocksize; - - t_mmc[card_num]->mmc_DataLength = blocksize; - - t_mmc[card_num]->mmc_DataTimer = 0xefffffff; - - source_buffer = writebuff; - - /*Wait till card is ready for data Added*/ - t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA; //card_array[cardno - 1].RCA << 16; - t_mmc[card_num]->mmc_Command = SEND_STATUS | RespExpected | CmdPathEnable; - - error = mmc_cmdresp145error(SEND_STATUS, card_num); - - if (error != MMC_OK) - return error; - - card_status = t_mmc[card_num]->mmc_Response0; - timeout = 0xefffffff; - - while ((0 == (card_status & 0x00000100)) && (timeout > 0)) - { - timeout--; - t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA;//0x1 << 16; - t_mmc[card_num]->mmc_Command = SEND_STATUS | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SEND_STATUS, card_num); - - if (error != MMC_OK) - return error; - card_status = t_mmc[card_num]->mmc_Response0; - } - if (timeout == 0) - { - return (MMC_DATA_TIMEOUT); - } - - /*Till here*/ - /*SEND CMD24 WRITE_SINGLE_BLOCK */ - t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; - t_mmc[card_num]->mmc_Command = WRITE_SINGLE_BLOCK | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(WRITE_SINGLE_BLOCK, card_num); - if (error != MMC_OK) - return error; - t_mmc[card_num]->mmc_DataCtrl |= DataPathEnable & ~(ReadDir | StreamMode); - - if (device_mode == POLLING_MODE) - { - - while (!(t_mmc[card_num]->mmc_Status & (DataBlockEnd | TxUnderrun | DataCrcFail | DataTimeOut))) - { - - if (t_mmc[card_num]-> mmc_Status & TxFifoHalfEmpty) - { - if ((total_no_of_bytes - bytes_transferred) < 32) - { - rest_words = ((total_no_of_bytes - bytes_transferred) % 4 == 0) ? - ((total_no_of_bytes - bytes_transferred) / 4) - : ((total_no_of_bytes - bytes_transferred) / 4 +1); - - for (count = 0; count < rest_words; count++, tempbuff++, bytes_transferred += 4) - t_mmc[card_num]-> mmc_Fifo = *tempbuff; - - } - else - { - for (count = 0; count < 8; count++) - { - t_mmc[card_num]->mmc_Fifo = *(tempbuff + count); - } - tempbuff += 8; - bytes_transferred += 32; - } - } - } - - if ((timeout == 0) || (t_mmc[card_num]->mmc_Status & DataTimeOut)) - { - t_mmc[card_num]->mmc_Clear |= DataTimeOut; - transfer_error = error = MMC_DATA_TIMEOUT; - printf(" MMC_DATA_TIMEOUT error \n"); - return error; - } - else if (t_mmc[card_num]->mmc_Status & DataCrcFail) - { - t_mmc[card_num]->mmc_Clear |= DataCrcFail; - transfer_error = error = MMC_DATA_CRC_FAIL; - printf(" MMC_DATA_CRC_FAIL error \n"); - return error; - } - else if (t_mmc[card_num]->mmc_Status & TxUnderrun) - { - t_mmc[card_num]->mmc_Clear |= TxUnderrun; - transfer_error = error = MMC_TX_UNDERRUN; - printf(" MMC_TX_UNDERRUN underrun error \n"); - return error; - } - else if (t_mmc[card_num]->mmc_Status & StartBitError) - { - t_mmc[card_num]->mmc_Clear |= StartBitError; - transfer_error = error = MMC_START_BIT_ERR; - printf(" MMC_START_BIT_ERR start bit error \n"); - return error; - } - //clear all the static status flags - t_mmc[card_num]->mmc_Clear = ClrStaticFlags; - transfer_error = error; - - error = mmc_iscardprogramming(card_num, &cardstate); - while (error == MMC_OK && ((cardstate == 7) || (cardstate == 6))) - error = mmc_iscardprogramming(card_num, &cardstate); - } - - else if (device_mode == INTERRUPT_MODE) - { - t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | TxFifoHalfEmpty | TxUnderrun; - } - else if (device_mode == DMA_MODE) - { - t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | TxUnderrun; - t_mmc[card_num]->mmc_DataCtrl |= DMAEnab; - } - - } - else if (no_of_blocks > 1) - { - // set the block count,both for the controller and the card - if (no_of_blocks * blocksize > 0x01FFFFFF) - { - error = MMC_INVALID_PARAMETER; - return (error); - } - - total_no_of_bytes = no_of_blocks * blocksize; - - t_mmc[card_num]->mmc_DataLength = (u32) (no_of_blocks * blocksize); - - t_mmc[card_num]->mmc_Argument = (u32) no_of_blocks; - t_mmc[card_num]->mmc_Command = SET_BLOCK_COUNT | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SET_BLOCK_COUNT, card_num); - - if (error != MMC_OK) - return error; - - t_mmc[card_num]->mmc_DataTimer = 0xefffffff; - - source_buffer = writebuff; - - /*SEND CMD25 WRITE_MULT_BLOCK with argument data address*/ - t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; - t_mmc[card_num]->mmc_Command = WRITE_MULT_BLOCK | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(WRITE_MULT_BLOCK, card_num); - - if (error != MMC_OK) - return error; - - t_mmc[card_num]->mmc_DataCtrl |= DataPathEnable & ~(ReadDir | StreamMode); - - if (device_mode == POLLING_MODE) - { - timeout = 0xefffffff; - - while ((timeout > 0) && !(t_mmc[card_num]->mmc_Status & (TxUnderrun | DataCrcFail | - DataTimeOut | DataEnd | StartBitError))) - { - timeout--; - if (t_mmc[card_num]-> mmc_Status & TxFifoHalfEmpty) - { - if ((total_no_of_bytes - bytes_transferred) < 32) - { - rest_words = ((total_no_of_bytes - bytes_transferred) % 4 == 0) ? - ((total_no_of_bytes - bytes_transferred) /4) - : ((total_no_of_bytes - bytes_transferred) / 4 +1); - - for (count = 0; count < rest_words; count++, tempbuff++,bytes_transferred += 4) - t_mmc[card_num]-> mmc_Fifo = *tempbuff; - - } - else - { - for (count = 0; count < 8; count++) - { - t_mmc[card_num]-> mmc_Fifo = *(tempbuff + count); - } - tempbuff += 8; - bytes_transferred += 32; - } - } - - } - - if ((timeout == 0) || (t_mmc[card_num]->mmc_Status & DataTimeOut)) - { - t_mmc[card_num]->mmc_Clear |= DataTimeOut; - transfer_error = error = MMC_DATA_TIMEOUT; - printf(" MMC_DATA_TIMEOUT start bit error \n"); - return error; - - } - else if (t_mmc[card_num]->mmc_Status & DataCrcFail) - { - t_mmc[card_num]->mmc_Clear |= DataCrcFail; - transfer_error = error = MMC_DATA_CRC_FAIL; - printf(" MMC_DATA_CRC_FAIL start bit error \n"); - return error; - } - else if (t_mmc[card_num]->mmc_Status & TxUnderrun) - { - t_mmc[card_num]->mmc_Clear |= TxUnderrun; - transfer_error = error = MMC_TX_UNDERRUN; - printf(" MMC_TX_UNDERRUN start bit error \n"); - return error; - } - else if (t_mmc[card_num]->mmc_Status & StartBitError) - { - t_mmc[card_num]->mmc_Clear |= StartBitError; - transfer_error = error = MMC_START_BIT_ERR; - printf(" MMC_START_BIT_ERR start bit error \n"); - return error; - } - - t_mmc[card_num]->mmc_Clear = ClrStaticFlags; //clear all the static status flags - transfer_error = error; - error = mmc_iscardprogramming(card_num, &cardstate); - while ((MMC_OK == error) && ((cardstate == 7) || (cardstate == 6))) - error = mmc_iscardprogramming(card_num, &cardstate); - } - else if (device_mode == INTERRUPT_MODE) - { - t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd |TxFifoHalfEmpty | TxUnderrun; - } - else if (device_mode == DMA_MODE) - { - t_mmc[card_num]->mmc_Mask0 = DataCrcFail | DataTimeOut | DataEnd | TxUnderrun; - t_mmc[card_num]->mmc_DataCtrl |= DMAEnab; - } - - } - - return error; -} - -/****************************************************************************/ -/* NAME : mmc_gettransferstate() */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine */ -/* PARAMETERS : */ -/* */ -/* RETURN : t_mmc_transfer_state */ -/****************************************************************************/ - -t_mmc_transfer_state mmc_gettransferstate() -{ - if (t_mmc0->mmc_Status & (TxActive | RxActive)) - return TRANSFER_IN_PROGRESS; - else - return NO_TRANSFER; -} - -/****************************************************************************/ -/* NAME : mmc_erase */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: This routine allows to erase memory area specified for the */ -/* given card. */ -/* PARAMETERS : */ -/* IN : u8 Cardno. to access */ -/* u32 start address for erase. */ -/* u32 Last address for erase. */ -/* OUT : */ -/* */ -/* RETURN : t_mmc_error */ - -/****************************************************************************/ - -t_mmc_error mmc_erase(u8 card_num, u32 StartAddr, u32 EndAddr) -{ - t_mmc_error error; - u32 response; - u8 cardstate; - u32 delay, max_delay; - - if ((card_num > no_of_cards) || (card_num == 0)) - { - printf("mmc_erase:: card no=%d no_of_cards=%d failed \n",card_num, no_of_cards); - error = MMC_INVALID_PARAMETER; - return error; - } - max_delay = 52000 / ((t_mmc[card_num]->mmc_Clock & 0xFF) + 2); - - /* send command for selecting the card */ - - if (card_num != selected_card) - { - t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA; //card_array[cardno - 1].RCA << 16; - t_mmc[card_num]->mmc_Command = SEL_DESEL_CARD | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(SEL_DESEL_CARD, card_num); - if (error != MMC_OK) - return error; - else - selected_card = card_num; - } - - if (t_mmc[card_num]->mmc_Response0 & R1_CARD_IS_LOCKED) - { - error = MMC_LOCK_UNLOCK_FAILED; - return (error); - } - - t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (StartAddr >> 9) : StartAddr; - t_mmc[card_num]->mmc_Command = ERASE_GRP_START | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(ERASE_GRP_START, card_num); - if (error != MMC_OK) - { - printf("mmc_erase:: erase start CMD35 failed \n"); - return error; - } - response = t_mmc[card_num]->mmc_Response0; - - if (response & (R1_OUT_OF_RANGE | R1_ERASE_PARAM)) - { - printf("mmc_erase:: erase start CMD35 R1_OUT_OF_RANGE \n"); - error = MMC_BAD_ERASE_PARAM; - return error; - } - - if (response & R1_ERASE_SEQ_ERROR) - { - printf("mmc_erase:: erase start CMD35 R1_ERASE_SEQ_ERROR \n"); - error = MMC_ERASE_SEQ_ERR; - return error; - } - - if (response & (R1_CARD_IS_LOCKED | R1_LOCK_UNLOCK_FAILED)) - { - printf("mmc_erase:: erase start CMD35 R1_CARD_IS_LOCKED \n"); - error = MMC_LOCK_UNLOCK_FAILED; - return error; - } - - t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (EndAddr >> 9) : EndAddr; - t_mmc[card_num]->mmc_Command = ERASE_GRP_END | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(ERASE_GRP_END, card_num); - if (error != MMC_OK) - { - printf("mmc_erase:: erase end CMD36 failed \n"); - return error; - } - response = t_mmc[card_num]->mmc_Response0; - - if (response & (R1_OUT_OF_RANGE | R1_ERASE_PARAM)) - { - printf("mmc_erase:: erase end R1_OUT_OF_RANGE \n"); - error = MMC_BAD_ERASE_PARAM; - return error; - } - - if (response & R1_ERASE_SEQ_ERROR) - { - printf("mmc_erase:: erase end R1_ERASE_SEQ_ERROR \n"); - error = MMC_ERASE_SEQ_ERR; - return error; - } - - if (response & (R1_CARD_IS_LOCKED | R1_LOCK_UNLOCK_FAILED)) - { - printf("mmc_erase:: erase end R1_CARD_IS_LOCKED\n"); - error = MMC_LOCK_UNLOCK_FAILED; - return error; - } - - t_mmc[card_num]->mmc_Argument = 0; - t_mmc[card_num]->mmc_Command = ERASE | RespExpected | CmdPathEnable; - error = mmc_cmdresp145error(ERASE, card_num); - if (error != MMC_OK) - { - printf("mmc_erase:: erase CMD38 failed \n"); - return error; - } - response = t_mmc[card_num]->mmc_Response0; - if (response & R1_ERASE_SEQ_ERROR) - { - printf("mmc_erase:: erase R1_ERASE_SEQ_ERROR \n"); - error = MMC_ERASE_SEQ_ERR; - return error; - } - - if (response & (R1_CARD_IS_LOCKED | R1_LOCK_UNLOCK_FAILED)) - { - printf("mmc_erase:: erase R1_CARD_IS_LOCKED \n"); - error = MMC_LOCK_UNLOCK_FAILED; - return error; - } - - if (response & R1_WP_ERASE_SKIP) - { - printf("mmc_erase:: erase R1_WP_ERASE_SKIP \n"); - error = MMC_WRITE_PROT_VIOLATION; - return error; - } - for (delay = 0; delay < (max_delay * 3); delay++) ; - - mmc_iscardprogramming(card_num, &cardstate); - while ((MMC_OK == error) && ((cardstate == 7) || (cardstate == 6))) - mmc_iscardprogramming(card_num, &cardstate); - - error = MMC_OK; - return error; -} - -t_mmc_error mmc_cmderror(u8 card_num) -{ - t_mmc_error error = MMC_OK; - u32 timeout; - - timeout = 100000; - while ((timeout > 0) && !(t_mmc[card_num]->mmc_Status & CmdSent)) - timeout--; - - if (timeout == 0) { - error = MMC_CMD_RSP_TIMEOUT; - return error; - } - - t_mmc[card_num]->mmc_Clear = ClrStaticFlags; //clear all the static flags - - return error; -} - -t_mmc_error mmc_cmdresp145error(u8 cmd, u8 card_num) -{ - t_mmc_error error = MMC_OK; - u32 status, timeout; - - timeout = 100000; - status = t_mmc[card_num]->mmc_Status; - while ((timeout > 0) && !(status & (CmdCrcFail | CmdRespEnd | CmdTimeOut))) - { - timeout--; - status = t_mmc[card_num]->mmc_Status; - } - if ((timeout == 0) || (status & CmdTimeOut)) - { - error = MMC_CMD_RSP_TIMEOUT; - t_mmc[card_num]->mmc_Clear |= CmdTimeOut; - return error; - } - else if (status & CmdCrcFail) - { - error = MMC_CMD_CRC_FAIL; - t_mmc[card_num]->mmc_Clear |= CmdCrcFail; - return error; - } - - t_mmc[card_num]->mmc_Clear = ClrStaticFlags; /*Clear Static flags */ - if (t_mmc[card_num]->mmc_RespCommand != cmd) - { - /* check response received for CMD7*/ - error = MMC_ILLEGAL_CMD; - return error; - } - return error; -} - -t_mmc_error mmc_cmdresp2error(u8 card_num) -{ - t_mmc_error error = MMC_OK; - u32 status, timeout; - - timeout = 100000; - status = t_mmc[card_num]->mmc_Status; - while ((timeout > 0) && !(status & (CmdCrcFail | CmdTimeOut | CmdRespEnd))) - { - timeout--; - status = t_mmc[card_num]->mmc_Status; - } - if ((timeout == 0) || (status & CmdTimeOut)) - { - error = MMC_CMD_RSP_TIMEOUT; - t_mmc[card_num]->mmc_Clear |= CmdTimeOut; - return error; - } - else if (status & CmdCrcFail) - { - error = MMC_CMD_CRC_FAIL; - t_mmc[card_num]->mmc_Clear |= CmdCrcFail; - return error; - } - - t_mmc[card_num]->mmc_Clear = ClrStaticFlags; /*Clear Static flags */ - - return error; -} - -t_mmc_error mmc_cmdresp3error(u8 card_num) -{ - t_mmc_error error = MMC_OK; - u32 status, timeout; - - timeout = 0x100000; - status = t_mmc[card_num]->mmc_Status; - while ((timeout > 0) && !(status & (CmdRespEnd | CmdTimeOut | CmdCrcFail))) - { - timeout--; - status = t_mmc[card_num]->mmc_Status; - } - if ((timeout == 0) || (status & CmdTimeOut)) - { - error = MMC_CMD_RSP_TIMEOUT; - t_mmc[card_num]->mmc_Clear |= CmdTimeOut; - return error; - } - - t_mmc[card_num]->mmc_Clear = ClrStaticFlags; - return error; -} - -t_mmc_error mmc_cmdresp6error(u8 cmd, u16 * p_rca, u8 card_num) -{ - t_mmc_error error = MMC_OK; - u32 status; - u32 response_r1; - - status = t_mmc[card_num]->mmc_Status; - while (!(status & (CmdRespEnd | CmdTimeOut | CmdCrcFail))) - { - status = t_mmc[card_num]->mmc_Status; - } - - if (status & CmdTimeOut) - { - error = MMC_CMD_RSP_TIMEOUT; - t_mmc[card_num]->mmc_Clear |= CmdTimeOut; - return (error); - } - else if (status & CmdCrcFail) - { - error = MMC_CMD_CRC_FAIL; - t_mmc[card_num]->mmc_Clear |= CmdCrcFail; - return (error); - } - - /* CHECK RESPONSE RECEIVED IS OF DESIRED COMMAND */ - if (t_mmc[card_num]->mmc_RespCommand != cmd) - { - error = MMC_ILLEGAL_CMD; - return (error); - } - - /*Clear Static flags*/ - t_mmc[card_num]->mmc_Clear = ClrStaticFlags; - - /* WE HAVE RECEIVED RESPONSE, RETRIEVE IT. */ - response_r1 = t_mmc[card_num]->mmc_Response0; - - if (AllZero == (response_r1 & (R6_GEN_UNKNOWN_ERROR | R6_ILLEGAL_CMD | R6_COM_CRC_FAILED))) - { - *p_rca = (u16) (response_r1 >> 16); - return (error); - } - - if (response_r1 & R6_GEN_UNKNOWN_ERROR) - { - return (MMC_GENERAL_UNKNOWN_ERROR); - } - - if (response_r1 & R6_ILLEGAL_CMD) - { - return (MMC_ILLEGAL_CMD); - } - - if (response_r1 & R6_COM_CRC_FAILED) - { - return (MMC_COM_CRC_FAILED); - } - - return (error); -} - -t_mmc_error mmc_cmdresp7error(u8 card_num) -{ - t_mmc_error error = MMC_OK; - u32 status; - u32 timeout = 10000; - - status = t_mmc[card_num]->mmc_Status; - while (!(status & (CmdCrcFail | CmdRespEnd | CmdTimeOut)) && (timeout > 0)) - { - timeout--; - status = t_mmc[card_num]->mmc_Status; - } - - if ((timeout == 0) || (status & CmdTimeOut)) - { - /* Card is not V2.0 complient or card does not support the set voltage range */ - error = MMC_CMD_RSP_TIMEOUT; - return (error); - } - - if (status & CmdRespEnd) - { - /* Card is V2.0 complient */ - error = MMC_OK; - return (error); - } - - return (error); -} - -t_mmc_error mmc_iscardprogramming(u8 card_num, u8 * status) -{ - t_mmc_error error; - u32 response; - - t_mmc[card_num]->mmc_Argument = card_array[card_num].RCA;//0x1 << 16; //RCA - t_mmc[card_num]->mmc_Command = SEND_STATUS | RespExpected | CmdPathEnable; - - error = mmc_cmdresp145error(SEND_STATUS, card_num); - if (error != MMC_OK) - return error; - - response = t_mmc[card_num]->mmc_Response0; - *status = (response >> 9) & 0x0000000f; - - return error; - -} - -t_mmc_error mmc_sendstatus(u8 cardno, u32 * status) -{ - t_mmc_error error = MMC_OK; - - t_mmc0->mmc_Argument = card_array[cardno].RCA;//card_array[cardno - 1].RCA << 16; //RCA - t_mmc0->mmc_Command = SEND_STATUS | RespExpected | CmdPathEnable; - - error = mmc_cmdresp145error(SEND_STATUS, cardno); - if (error != MMC_OK) - return error; - - *status = t_mmc0->mmc_Response0; - - return error; -} - -t_mmc_error mmc_cmderror_2(void) -{ - t_mmc_error error = MMC_OK; - u32 status, timeout; - - timeout = 0xefffffff; - status = t_mmc0->mmc_Status; - while ((timeout > 0) && !(status & (CmdSent| CmdCrcFail | CmdTimeOut | CmdRespEnd))) - { - timeout--; - status = t_mmc0->mmc_Status; - } - - if (timeout == 0) - { - printf(" cmd1 timeout error\n"); - error = MMC_CMD_RSP_TIMEOUT; - return error; - } - - t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static flags - - return error; -} - -t_mmc_error mmc_cmdresp2error_2(void) -{ - t_mmc_error error = MMC_OK; - u32 status, timeout; - - timeout = 0xefffffff; //(u32)((float)(64/(float)clockfreq )/ ((float)(1/(float)MCLK) + 8*(float)(1/(float)PROCESSOR_CLK))); - status = t_mmc0->mmc_Status; - - while ((timeout > 0) && !(status & (CmdCrcFail | CmdTimeOut | CmdRespEnd))) - { - timeout--; - status = t_mmc0->mmc_Status; - } - if ((timeout == 0) || (status & CmdTimeOut)) - { - error = MMC_CMD_RSP_TIMEOUT; - t_mmc0->mmc_Clear |= CmdTimeOut; - return error; - } - if (status & CmdCrcFail) - { - error = MMC_CMD_CRC_FAIL; - t_mmc0->mmc_Clear |= CmdCrcFail; - return error; - } - - t_mmc0->mmc_Clear = ClrStaticFlags; /*Clear Static flags */ - - return error; -} - -t_mmc_error mmc_cmdresp3error_2(void) -{ - t_mmc_error error = MMC_OK; - u32 status, timeout; - - timeout = 0xefffffff; - status = t_mmc0->mmc_Status; - - while ((timeout > 0) && !(status & (CmdRespEnd | CmdTimeOut | CmdCrcFail))) - { - timeout--; - status = t_mmc0->mmc_Status; - } - if ((timeout == 0) || (status & CmdTimeOut)) - { - error = MMC_CMD_RSP_TIMEOUT; - t_mmc0->mmc_Clear |= CmdTimeOut; - return error; - } - - t_mmc0->mmc_Clear = ClrStaticFlags; - - return error; -} - -t_mmc_error mmc_cmdresp145error_2(u8 cmd) -{ - t_mmc_error error = MMC_OK; - u32 status, timeout; - - timeout = 0xefffffff; - status = t_mmc0->mmc_Status; - - while ((timeout > 0) && !(status & (CmdCrcFail | CmdRespEnd | CmdTimeOut))) - { - timeout--; - status = t_mmc0->mmc_Status; - } - if ((timeout == 0) || (status & CmdTimeOut)) - { - error = MMC_CMD_RSP_TIMEOUT; - t_mmc0->mmc_Clear |= CmdTimeOut; - return error; - } - else if (status & CmdCrcFail) - { - error = MMC_CMD_CRC_FAIL; - t_mmc0->mmc_Clear |= CmdCrcFail; - return error; - } - - t_mmc0->mmc_Clear = ClrStaticFlags; /*Clear Static flags */ - if (t_mmc0->mmc_RespCommand != cmd) - { - /* check response received for CMD7*/ - error = MMC_ILLEGAL_CMD; - return error; - } - - return error; -} - -t_mmc_error mmc_cmdreadresp(u32 * tempbuff) -{ - t_mmc_error error = MMC_OK; - u32 i; - u32 timeout = 0; - - timeout = 0xefffffff; - - while ((timeout > 0) && !(t_mmc0-> mmc_Status & (RxOverrun | DataCrcFail | DataTimeOut |DataBlockEnd))) - { - timeout--; - if (t_mmc0->mmc_Status & RxFifoHalfFull) - { - for (i = 0; i < 8; i++) - { - *(tempbuff + i) = t_mmc0->mmc_Fifo; - } - tempbuff += 8; - } - } - if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut)) - { - t_mmc0->mmc_Clear |= DataTimeOut; - return error; - } - else if (t_mmc0->mmc_Status & DataCrcFail) - { - t_mmc0->mmc_Clear |= DataCrcFail; - error = MMC_DATA_CRC_FAIL; - return error; - } - else if (t_mmc0->mmc_Status & RxOverrun) - { - t_mmc0->mmc_Clear |= RxOverrun; - error = MMC_RX_OVERRUN; - return error; - } - - while (t_mmc0->mmc_Status & RxDataAvlbl) - { - *tempbuff = t_mmc0->mmc_Fifo; - tempbuff++; - } - t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags - - return error; -} - -t_mmc_error mmc_waitcmdreadresp(void) -{ - t_mmc_error error = MMC_OK; - u32 timeout = 0; - - timeout = 0xefffffff; - - while (!(t_mmc0->mmc_Status & (RxOverrun | DataCrcFail | DataTimeOut | DataBlockEnd))) - { - - } - - if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut)) - { - t_mmc0->mmc_Clear |= DataTimeOut; - return error; - } - else if (t_mmc0->mmc_Status & DataCrcFail) - { - t_mmc0->mmc_Clear |= DataCrcFail; - error = MMC_DATA_CRC_FAIL; - return error; - } - else if (t_mmc0->mmc_Status & RxOverrun) - { - t_mmc0->mmc_Clear |= RxOverrun; - error = MMC_RX_OVERRUN; - return error; - } - - t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags - - return error; -} - -t_mmc_error mmc_iscardprogramming_2(u8 * status) -{ - t_mmc_error error; - u32 response; - t_mmc_command_control commcontrol; - - commcontrol.IsRespExpected = TRUE; - commcontrol.IsLongResp = FALSE; - commcontrol.IsInterruptMode = FALSE; - commcontrol.IsPending = FALSE; - commcontrol.cmdpath = MMC_ENABLE; - - error = mmc_sendcommand(MMC_SEND_STATUS, t_mmc_rel_addr, commcontrol); - error = mmc_cmdresp145error_2(MMC_SEND_STATUS); - - if (error != MMC_OK) - return error; - - response = t_mmc0->mmc_Response0; - *status = (response >> 9) & 0x0000000f; - - return error; -} - -t_mmc_error mmc_cmdwriteresp(u8 cardno, u32 * tempbuff, u16 total_num_of_bytes) -{ - u32 timeout = 0; - t_mmc_error error = MMC_OK; - u32 bytes_transferred = 0; - u32 i, j; - u8 cardstate; - - timeout = 0xefffffff; - - while ((timeout > 0) && !(t_mmc0-> mmc_Status & (DataBlockEnd | TxUnderrun | DataCrcFail | DataTimeOut))) - { - timeout--; - if (t_mmc0->mmc_Status & TxFifoHalfEmpty) - { - if ((total_num_of_bytes - bytes_transferred) < 32) - { - j = ((total_num_of_bytes - bytes_transferred) % 4 ==0) ? - ((total_num_of_bytes - bytes_transferred) / 4) : - ((total_num_of_bytes - bytes_transferred) / 4 + 1); - - for (i = 0; i < j; i++, tempbuff++, bytes_transferred += 4) - t_mmc0->mmc_Fifo = *tempbuff; - } - else - { - for (i = 0; i < 8; i++) - t_mmc0->mmc_Fifo = *(tempbuff + i); - tempbuff += 8; - bytes_transferred += 32; - } - } - } - - if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut)) - { - t_mmc0->mmc_Clear |= DataTimeOut; - error = MMC_DATA_TIMEOUT; - printf(" mmc_cmdwriteresp timeout error \n"); - return error; - } - else if (t_mmc0->mmc_Status & DataCrcFail) - { - t_mmc0->mmc_Clear |= DataCrcFail; - error = MMC_DATA_CRC_FAIL; - printf(" mmc_cmdwriteresp CRC error \n"); - return error; - } - else if (t_mmc0->mmc_Status & TxUnderrun) - { - t_mmc0->mmc_Clear |= TxUnderrun; - error = MMC_TX_UNDERRUN; - printf(" mmc_cmdwriteresp underrun error \n"); - return error; - } - - t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags - - error = mmc_iscardprogramming_2(&cardstate); - while (error == MMC_OK && cardstate == 7) - error = mmc_iscardprogramming_2(&cardstate); - - return error; -} - -t_mmc_error mmc_waitcmdwriteresp(u8 cardno, u32 * tempbuff, u16 total_num_of_bytes) -{ - u32 timeout = 0; - t_mmc_error error = MMC_OK; - u8 cardstate; - - timeout = 0xefffffff; - - while ((timeout > 0) && !(t_mmc0-> mmc_Status & (DataBlockEnd | TxUnderrun | DataCrcFail | DataTimeOut))) - { - - } - - if ((timeout == 0) || (t_mmc0->mmc_Status & DataTimeOut)) - { - t_mmc0->mmc_Clear |= DataTimeOut; - error = MMC_DATA_TIMEOUT; - return error; - - } - else if (t_mmc0->mmc_Status & DataCrcFail) - { - t_mmc0->mmc_Clear |= DataCrcFail; - error = MMC_DATA_CRC_FAIL; - return error; - } - else if (t_mmc0->mmc_Status & TxUnderrun) - { - t_mmc0->mmc_Clear |= TxUnderrun; - error = MMC_TX_UNDERRUN; - return error; - } - - t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags - - error = mmc_iscardprogramming_2(&cardstate); - while (error == MMC_OK && cardstate == 7) - error = mmc_iscardprogramming_2(&cardstate); - - return error; -} diff --git a/board/st/u8500/mmc.h b/board/st/u8500/mmc.h deleted file mode 100644 index 069aced00..000000000 --- a/board/st/u8500/mmc.h +++ /dev/null @@ -1,263 +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 - */ -#ifndef _MMC_H_ -#define _MMC_H_ - -#include -#include "asm-arm/arch-stw8500/mmc.h" - -/*--------------------------------------------------------------------------- - * Enums - *---------------------------------------------------------------------------*/ - -extern char *mmc_error_name[]; - -#define t_mmc_irq_src u32 - -typedef enum { - MMC_CMD_CRC_FAIL_INT = 0x00000001, - MMC_DATA_CRC_FAIL_INT = 0x00000002, - MMC_CMD_TIMEOUT_INT = 0x00000004, - MMC_DATA_TIMEOUT_INT = 0x00000008, - MMC_TX_UNDERRUN_INT = 0x00000010, - MMC_RX_OVERRUN_INT = 0x00000020, - MMC_CMD_RESP_OK_INT = 0x00000040, - MMC_CMD_SENT_INT = 0x00000080, - MMC_DATA_END_INT = 0x00000100, - MMC_DATA_BLOCK_OK_INT = 0x00000400, - MMC_CMD_ACTIVE_INT = 0x00000800, - MMC_TX_ACTIVE_INT = 0x00001000, - MMC_RX_ACTIVE_INT = 0x00002000, - MMC_TX_FIFO_HALF_EMPTY_INT = 0x00004000, - MMC_RX_FIFO_HALF_FULL_INT = 0x00008000, - MMC_TX_FIFO_FULL_INT = 0x00010000, - MMC_RX_FIFO_FULL_INT = 0x00020000, - MMC_TX_FIFO_EMPTY_INT = 0x00040000, - MMC_RX_FIFO_EMPTY_INT = 0x00080000, - MMC_TX_DATA_AVLBL_INT = 0x00100000, - MMC_RX_DATA_AVLBL_INT = 0x00200000, - MMC_ALL_STATIC_IT = 0x000005FF, - MMC_ALL_IT = 0x003FFDFF - -} t_mmc_interrupt; - -typedef enum { - MMC_DISABLE = 0, - MMC_ENABLE -} t_mmc_state; - - -typedef enum { - MMC_POWER_OFF = 0x0, - MMC_POWER_UP = 0x2, - MMC_POWER_ON = 0x3 -} t_mmc_power_state; - -typedef enum { - MMC_PUSH_PULL = 0, - MMC_OPEN_DRAIN -} t_mmc_bus_mode; - -typedef enum { - MMC_GO_IDLE_STATE = 0, - MMC_SEND_OP_COND = 1, - MMC_ALL_SEND_CID = 2, - MMC_SET_REL_ADDR = 3, - MMC_SET_DSR = 4, - MMC_SEL_DESEL_CARD = 7, - MMC_SEND_CSD = 9, - MMC_SEND_CID = 10, - MMC_READ_DAT_UNTIL_STOP = 11, - MMC_STOP_TRANSMISSION = 12, - MMC_SEND_STATUS = 13, - MMC_GO_INACTIVE_STATE = 15, - MMC_SET_BLOCKLEN = 16, - MMC_READ_SINGLE_BLOCK = 17, - MMC_READ_MULT_BLOCK = 18, - MMC_WRITE_DAT_UNTIL_STOP = 20, - MMC_SET_BLOCK_COUNT = 23, - MMC_WRITE_SINGLE_BLOCK = 24, - MMC_WRITE_MULT_BLOCK = 25, - MMC_PROG_CID = 26, - MMC_PROG_CSD = 27, - MMC_SET_WRITE_PROT = 28, - MMC_CLR_WRITE_PROT = 29, - MMC_SEND_WRITE_PROT = 30, - MMC_ERASE_GRP_START = 35, - MMC_ERASE_GRP_END = 36, - MMC_ERASE = 38, - MMC_FAST_IO = 39, - MMC_GO_IRQ_STATE = 40, - SD_SEND_OP_COND = 41, - MMC_LOCK_UNLOCK = 42, - MMC_APP_CMD = 55, - MMC_GEN_CMD = 56, - MMC_NO_CMD = 64 -} t_mmc_command_index; - -typedef enum { - MMC_SHORT_RESP = 0, - MMC_LONG_RESP -} t_mmc_response_type; - - -typedef enum { - MMC_WRITE= 0, - MMC_READ -} t_mmc_transfer_direction; - -typedef enum { - MMC_BLOCK = 0, - MMC_STREAM -} t_mmc_transfer_type; - -typedef enum { - POLLING_MODE = 0, - INTERRUPT_MODE, - DMA_MODE -} t_mmc_device_mode; - -/*--------------------------------------------------------------------------- - * Structures - *---------------------------------------------------------------------------*/ - -typedef struct { - t_mmc_bus_mode mode; - t_mmc_state rodctrl; -} t_mmc_bus_configuration; - -typedef struct { - t_mmc_state pwrsave; - t_mmc_state bypass; - t_mmc_state widebus; -} t_mmc_clock_control; - -typedef struct { - t_bool IsRespExpected; - t_bool IsLongResp; - t_bool IsInterruptMode; - t_bool IsPending; - t_mmc_state cmdpath; -} t_mmc_command_control; - - -#define t_mmc_event u32 - -#define t_mmc_filter_mode u32 -#define NO_FILTER_MODE 0 - -typedef enum -{ - MMC_NEW = 0, - MMC_OLD -} t_mmc_irq_status_usage; - -typedef struct -{ - t_mmc_irq_status_usage usage; - u32 IRQStatus; - u32 EventStatus; -} t_mmc_irq_status; - -typedef enum { - - MMC_MULTIMEDIA_CARD, - MMC_SECURE_DIGITAL_CARD, - MMC_SECURE_DIGITAL_IO_CARD, - MMC_HIGH_SPEED_MULTIMEDIA_CARD, - MMC_SECURE_DIGITAL_IO_COMBO_CARD - -} t_mmc_card_type; - -typedef struct { - u32 CID[4]; - u32 CSD[4]; - u16 RCA; - t_mmc_card_type card_type; - u8 padding; - u8 sdio_cccr[4]; /* I/O ready, CCCR/SDIO revision, SD Specification revision, and Card Capability registers */ - int blockaddressed; -} t_mmc_card_info; - -typedef struct { - t_mmc_error error; - u16 transferred_bytes; -} t_mmc_last_transfer_info; - -typedef enum { - NO_TRANSFER = 0, - TRANSFER_IN_PROGRESS -} t_mmc_transfer_state; - -typedef enum { - WRITE_PROT_WHOLE_CARD_TEMP = 0, - WRITE_PROT_WHOLE_CARD_PERM, - WRITE_PROT_SINGLE_GROUP -} t_mmc_write_protect_type; - -/*--------------------------------------------------------------------------- - * Functions Prototype - *---------------------------------------------------------------------------*/ - - -t_mmc_error mmc_init (u8,t_logical_address) ; - -t_mmc_error mmc_setpowerstate(t_mmc_power_state); -t_mmc_power_state mmc_getpowerstate(void); -t_mmc_error mmc_setoperatingvoltage(u8); -u8 mmc_getoperatingvoltage (void); -t_mmc_error mmc_configbus(t_mmc_bus_configuration); - -t_mmc_error mmc_setclock(t_mmc_state); -t_mmc_error mmc_configclockcontrol(t_mmc_clock_control); -t_mmc_error mmc_setclockfrequency(u8); -t_mmc_error mmc_sendcommand(t_mmc_command_index, u32,t_mmc_command_control) ; -t_mmc_command_index mmc_getcommandresponse(void) ; -t_mmc_error mmc_getresponse(t_mmc_response_type, u32*) ; -t_mmc_error mmc_setdatapath(t_mmc_state); -t_mmc_error mmc_setdatatimeout(u32); -t_mmc_error mmc_setdatalength(u16); -t_mmc_error mmc_setdatablocklength(u8); -t_mmc_error mmc_settransferdirection(t_mmc_transfer_direction) ; -t_mmc_error mmc_settransfertype(t_mmc_transfer_type); -t_mmc_error mmc_handledma(t_mmc_state); -u16 mmc_getdatacounter(void); - -t_mmc_error mmc_selectsdcard(u8); -t_mmc_error mmc_poweron(u8) ; -t_mmc_error mmc_poweroff(u8); -t_mmc_error mmc_initializeCards(u8); -t_mmc_error mmc_getcardinfo(u8, t_mmc_card_info *) ; -t_mmc_error mmc_setdevicemode(t_mmc_device_mode); -t_mmc_error mmc_readbytes(u8, u32, u32*, u16) ; -t_mmc_error mmc_readblocks(u8, u32, u32*, u16, u16) ; -t_mmc_error mmc_writebytes(u8, u32, u32* , u16) ; -t_mmc_error mmc_writeblocks(u8, u32, u32*, u16, u16) ; -t_mmc_transfer_state mmc_gettransferstate(void); -t_mmc_error mmc_erase(u8, u32, u32) ; - -u8 convert_from_bytes_to_power_of_two (u16 no_of_bytes); - -/*New Interrupt strategy(M1 functions)*/ -void mmc_acknowledgementevent(t_mmc_event *); - -#endif /* _MMC_H_ */ diff --git a/board/st/u8500/mmc_host.c b/board/st/u8500/mmc_host.c new file mode 100644 index 000000000..479e76391 --- /dev/null +++ b/board/st/u8500/mmc_host.c @@ -0,0 +1,636 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Ulf Hansson + * Author: Martin Lundholm + * + * License terms: GNU General Public License (GPL), version 2. + */ + +/*#define DEBUG*/ + +#include "common.h" +#include +#include "gpio.h" /* two copies of gpio.h exists - why? */ +#include "mmc_host.h" +#include + +struct mmc_host { + struct sdi_registers *base; +}; + +/* + * wait_for_command_end() - waiting for the command completion + * this function will wait till 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); + + debug("SDI_ICR <= 0x%08X\n", statusmask); + writel(statusmask, &host->base->status_clear); + + if (hoststatus & SDI_STA_CTIMEOUT) { + debug("CMD%d time out\n", cmd->cmdidx); + return TIMEOUT; + } else if ((hoststatus & SDI_STA_CCRCFAIL) && + (cmd->flags & MMC_RSP_CRC)) { + debug("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); + debug("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; + + debug("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; + } + + debug("SDI_ARG <= 0x%08X\n", cmd->cmdarg); + writel((u32)cmd->cmdarg, &host->base->argument); + udelay(COMMAND_REG_DELAY); /* DONT REMOVE */ + debug("SDI_CMD <= 0x%08X\n", sdi_cmd); + writel(sdi_cmd, &host->base->command); + + result = wait_for_command_end(dev, cmd); + + /* 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; + debug("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) +{ + u32 *tempbuff = dest; + int i; + u64 xfercount = blkcount * blksize; + struct mmc_host *host = dev->priv; + u32 status; + u32 status_err; + + debug("read_bytes: blkcount=%u blksize=%u\n", blkcount, blksize); + + status = readl(&host->base->status); + status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT); + while (!status_err && + (xfercount >= SDI_FIFO_BURST_SIZE * sizeof(u32))) { + if (status & SDI_STA_RXFIFOBR) { + for (i = 0; i < SDI_FIFO_BURST_SIZE; i++) + *(tempbuff + i) = readl(&host->base->fifo); + tempbuff += SDI_FIFO_BURST_SIZE; + xfercount -= SDI_FIFO_BURST_SIZE * sizeof(u32); + } + status = readl(&host->base->status); + status_err = status & + (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT); + } + + if (status & SDI_STA_DTIMEOUT) { + printf("Reading data timedout, xfercount:%llu," + "status:0x%08X\n", xfercount, status); + return MMC_DATA_TIMEOUT; + } else if (status & SDI_STA_DCRCFAIL) { + printf("Reading data CRC error\n"); + return MMC_DATA_CRC_FAIL; + } + + while ((!status_err) && (xfercount >= sizeof(u32))) { + if (status & SDI_STA_RXDAVL) { + *(tempbuff) = readl(&host->base->fifo); + tempbuff++; + xfercount -= sizeof(u32); + } + status = readl(&host->base->status); + status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT); + } + + /* Wait for DBCKEND */ + status_err = status & + (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND); + while (!status_err) { + status = readl(&host->base->status); + status_err = status & + (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND); + } + + if (status & SDI_STA_DTIMEOUT) { + printf("Reading data timedout, xfercount:%llu," + "status:0x%08X\n", xfercount, status); + return MMC_DATA_TIMEOUT; + } else if (status & SDI_STA_DCRCFAIL) { + printf("Reading data CRC error\n"); + return MMC_DATA_CRC_FAIL; + } + + debug("SDI_ICR <= 0x%08X\n", SDI_ICR_MASK); + writel(SDI_ICR_MASK, &host->base->status_clear); + debug("Reading loop ended\n"); + + if (xfercount) { + printf("Reading data error, xfercount:%llu", + (unsigned long long) xfercount); + return MMC_GENERAL_UNKNOWN_ERROR; + } + + 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) +{ + u32 *tempbuff = src; + int i; + u64 xfercount = blkcount * blksize; + struct mmc_host *host = dev->priv; + u32 status; + u32 status_err; + + debug("write_bytes: blkcount=%u blksize=%u\n", blkcount, blksize); + + status = readl(&host->base->status); + status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT); + while (!status_err && xfercount) { + if (status & SDI_STA_TXFIFOBW) { + if (xfercount >= SDI_FIFO_BURST_SIZE * sizeof(u32)) { + for (i = 0; i < SDI_FIFO_BURST_SIZE; i++) + writel(*(tempbuff + i), + &host->base->fifo); + tempbuff += SDI_FIFO_BURST_SIZE; + xfercount -= SDI_FIFO_BURST_SIZE * sizeof(u32); + } else { + while (xfercount >= sizeof(u32)) { + writel(*(tempbuff), &host->base->fifo); + tempbuff++; + xfercount -= sizeof(u32); + } + } + } + status = readl(&host->base->status); + status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT); + } + + /* Wait for DBCKEND */ + status_err = status & + (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND); + while (!status_err) { + status = readl(&host->base->status); + status_err = status & + (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND); + } + + if (status & SDI_STA_DTIMEOUT) { + printf( + "Writing data timedout, xfercount:%llu,status:0x%08X\n", + xfercount, status); + return MMC_DATA_TIMEOUT; + } else if (status & SDI_STA_DCRCFAIL) { + printf("Writing data CRC error\n"); + return MMC_DATA_CRC_FAIL; + } + + + writel(SDI_ICR_MASK, &host->base->status_clear); + debug("Writing data loop completed status:0x%08X\n", status); + + if (xfercount) { + printf("Writing data error, xfercount:%llu", + (unsigned long long) xfercount); + return MMC_GENERAL_UNKNOWN_ERROR; + } + + 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) +{ + 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); + + debug("Request to do data xfer on %s\n", dev->name); + debug("do_data_transfer(%u) start\n", data->blocks); + + blksz = convert_from_bytes_to_power_of_two(data->blocksize); + data_ctrl |= (blksz << INDEX(SDI_DCTRL_DBLOCKSIZE_MASK)); + data_ctrl |= SDI_DCTRL_DTEN; + + debug("SDI_DTIMER <= 0x%08X\n", SDI_DTIMER_DEFAULT); + writel(SDI_DTIMER_DEFAULT, &host->base->datatimer); + debug("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)) { + debug("It is a read operation\n"); + + data_ctrl |= SDI_DCTRL_DTDIR_IN; + debug("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)) { + debug("It is a write operation\n"); + + error = do_command(dev, cmd); + if (error) + return error; + + debug("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); + } + + debug("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; + + debug("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) +{ + 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; + + debug("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; + } + + debug("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; + + mmc_device->priv = host; + return mmc_device; + err: + free(host); + return NULL; +} + +static int host_poweroff(struct mmc *dev) +{ + struct mmc_host *host = dev->priv; + u32 sdi_pwr = ~SDI_PWR_PWRCTRL_ON; + debug("SDI_PWR <= 0x%08X\n", sdi_pwr); + writel(sdi_pwr, &host->base->power); + return 0; +} + +/* + * 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; + gpio_error gpioerror; + u32 sdi_u32; + + /* TODO: Investigate what is actually needed of the below. */ + + if (u8500_is_earlydrop()) { + debug("configuring EMMC for ED\n"); + /* Initialize the gpio alternate function for eMMC */ + struct gpio_register *p_gpio_register = + (void *)IO_ADDRESS(CFG_GPIO_6_BASE); + p_gpio_register->gpio_dats |= 0x0000FFE0; + p_gpio_register->gpio_pdis &= ~0x0000FFE0; + + gpioerror = gpio_altfuncenable(GPIO_ALT_EMMC, "EMMC"); + if (GPIO_OK != gpioerror) { + printf( + "emmc_host_init() gpio_altfuncenable %d failed\n", + gpioerror); + goto end; + } + + host->base = (struct sdi_registers *)CFG_EMMC_BASE_ED; + } else { + debug("configuring EMMC for V1\n"); + /* enable the alternate function of PoP EMMC */ + gpioerror = gpio_altfuncenable(GPIO_ALT_POP_EMMC, "EMMC"); + if (gpioerror != GPIO_OK) { + printf( + "emmc_host_init() gpio_altfuncenable %d failed \n", + gpioerror); + goto end; + } + host->base = (struct sdi_registers *)CFG_EMMC_BASE_V1; + } + + sdi_u32 = SDI_PWR_OPD | SDI_PWR_PWRCTRL_ON; + debug("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; + debug("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; + debug("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; + dev->voltages = VOLTAGE_WINDOW_MMC; + dev->f_min = dev->clock; + dev->f_max = MCLK / 2; + return 0; + + end: + if (u8500_is_earlydrop()) + gpio_altfuncdisable(GPIO_ALT_EMMC, "EMMC"); + else + gpio_altfuncdisable(GPIO_ALT_POP_EMMC, "EMMC"); + + host_poweroff(dev); + return MMC_UNSUPPORTED_HW; +} + +/* + * 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; + gpio_error gpioerror; + struct gpio_register *gpio_base_address; + u32 sdi_u32; + + gpio_base_address = (void *) IO_ADDRESS(CFG_GPIO_0_BASE); + gpio_base_address->gpio_dats |= 0xFFC0000; + gpio_base_address->gpio_pdis &= ~0xFFC0000; + + /* save the GPIO0 AFSELA register */ + gpioerror = gpio_altfuncenable(GPIO_ALT_SD_CARD0, "MMC"); + if (gpioerror != GPIO_OK) { + printf("mmc_host_init() gpio_altfuncenable %d failed \n", + gpioerror); + goto end; + } + + host->base = (struct sdi_registers *)CFG_MMC_BASE; + sdi_u32 = 0xBF; + debug("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; + debug("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; + debug("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; + return 0; + + end: + gpio_altfuncdisable(GPIO_ALT_SD_CARD0, "MMC"); + host_poweroff(dev); + return MMC_UNSUPPORTED_HW; +} + +/* + * 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; + + debug("mmc_host - board_mmc_init\n"); + + 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); + debug("registered emmc interface number is:%d\n", + dev->block_dev.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); + debug("registered mmc/sd interface number is:%d\n", + dev->block_dev.dev); + + return 0; +} diff --git a/board/st/u8500/mmc_host.h b/board/st/u8500/mmc_host.h new file mode 100644 index 000000000..644f01b37 --- /dev/null +++ b/board/st/u8500/mmc_host.h @@ -0,0 +1,296 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Ulf Hansson + * Author: Martin Lundholm + * + * 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 1000 +#define CLK_CHANGE_DELAY 2000 + +#define MAX_ERROR_VALUE -65 +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, +}; + +#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) + +#define SDI_DTIMER_DEFAULT (0xFFFF0000) + +/* 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_FIFO_BURST_SIZE (8) + +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 diff --git a/board/st/u8500/mmc_p.h b/board/st/u8500/mmc_p.h deleted file mode 100755 index e32701f3e..000000000 --- a/board/st/u8500/mmc_p.h +++ /dev/null @@ -1,315 +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 - */ -#ifndef _MMC_P_H_ -#define _MMC_P_H_ - -#define BIT31 0x80000000 -#define PROCESSOR_CLK 200000000 -#define MAXBSIZEPOWER 11 - -#define MCLK 26000000 - -#define MMC_PERIPHERAL_ID0 0x81 -#define MMC_PERIPHERAL_ID1 0x11 -#define MMC_PERIPHERAL_ID2 0x04 -#define MMC_PERIPHERAL_ID3 0x00 - - -#define MMC_PCELL_ID0 0x0D -#define MMC_PCELL_ID1 0xF0 -#define MMC_PCELL_ID2 0x05 -#define MMC_PCELL_ID3 0xB1 - - -typedef volatile struct { - u32 mmc_Power; // 0x00 - u32 mmc_Clock; // 0x04 - u32 mmc_Argument; // 0x08 - u32 mmc_Command; // 0x0c - u32 mmc_RespCommand; // 0x10 - u32 mmc_Response0; // 0x14 - u32 mmc_Response1; // 0x18 - u32 mmc_Response2; // 0x1c - u32 mmc_Response3; // 0x20 - u32 mmc_DataTimer; // 0x24 - u32 mmc_DataLength; // 0x28 - u32 mmc_DataCtrl; // 0x2c - u32 mmc_DataCnt; // 0x30 - u32 mmc_Status; // 0x34 - u32 mmc_Clear; // 0x38 - u32 mmc_Mask0; // 0x3c - u32 mmc_Mask1; // 0x40 - u32 mmc_SelectSD; // 0x44 - u32 mmc_FifoCnt; // 0x48 - u32 mmc_unused1[(0x80-0x4C)>>2]; - u32 mmc_Fifo; // 0x80 - u32 mmc_unused2[(0xFE0-0x84)>>2]; - u32 mmc_PeriphId0; // 0xFE0 mmc Peripheral Identi.cation Register - u32 mmc_PeriphId1; // 0xFE4 - u32 mmc_PeriphId2; // 0xFE8 - u32 mmc_PeriphId3; // 0xFEC - - u32 mmc_PCellId0; // 0xFF0 mmc PCell Identi.cation Register - u32 mmc_PCellId1; // 0xFF4 - u32 mmc_PCellId2; // 0xFF8 - u32 mmc_PCellId3; // 0xFFc -}t_mmc_register; - - -// Elementary layer -#define BIT_MASK(__bws) ((u32)(((wb ## __bws)==32)?0xFFFFFFFF:\ - ((1U << (wb ## __bws)) - 1)) << (sb ## __bws)) - -#define MMC_WRITE_BITS(reg,val,mask,sb) ((reg) = (((reg) & ~(mask)) | (((val)<<(sb)) & (mask)))) -#define MMC_READ_BITS(reg,mask,sb) ((reg & mask)>>sb) - -#define wbMMC_Power_CTRL 2 -#define sbMMC_Power_CTRL 0 -#define MMC_Power_MASK_CTRL BIT_MASK(MMC_Power_CTRL) - -#define wbMMC_Power_VOLT 4 -#define sbMMC_Power_VOLT 2 -#define MMC_Power_MASK_VOLT BIT_MASK(MMC_Power_VOLT) - -#define wbMMC_Power_OPEND 1 -#define sbMMC_Power_OPEND 6 -#define MMC_Power_MASK_OPEND BIT_MASK(MMC_Power_OPEND) - -#define wbMMC_Power_ROD 1 -#define sbMMC_Power_ROD 7 -#define MMC_Power_MASK_ROD BIT_MASK(MMC_Power_ROD) - -#define wbMMC_Clock_CLKDIV 8 -#define sbMMC_Clock_CLKDIV 0 -#define MMC_Clock_MASK_CLKDIV BIT_MASK(MMC_Clock_CLKDIV) - -#define wbMMC_Clock_ENABLE 1 -#define sbMMC_Clock_ENABLE 8 -#define MMC_Clock_MASK_ENABLE BIT_MASK(MMC_Clock_ENABLE) - -#define wbMMC_Clock_PWRSAVE 1 -#define sbMMC_Clock_PWRSAVE 9 -#define MMC_Clock_MASK_PWRSAVE BIT_MASK(MMC_Clock_PWRSAVE) - -#define wbMMC_Clock_BYPASS 1 -#define sbMMC_Clock_BYPASS 10 -#define MMC_Clock_MASK_BYPASS BIT_MASK(MMC_Clock_BYPASS) - -#define wbMMC_Clock_WIDEBUS 1 -#define sbMMC_Clock_WIDEBUS 11 -#define MMC_Clock_MASK_WIDEBUS BIT_MASK(MMC_Clock_WIDEBUS) -#define MMC_SET_WIDEBUS(reg,a) MMC_WRITE_BITS(reg,a,MMC_Clock_MASK_WIDEBUS,sbMMC_Clock_WIDEBUS) - -#define wbMMC_DataPath_ENABLE 1 -#define sbMMC_DataPath_ENABLE 0 -#define MMC_DataPath_MASK_ENABLE BIT_MASK(MMC_DataPath_ENABLE) - -#define wbMMC_DataPath_BLOCKSIZE 4 -#define sbMMC_DataPath_BLOCKSIZE 4 -#define MMC_DataPath_MASK_BLOCKSIZE BIT_MASK(MMC_DataPath_BLOCKSIZE) - -#define wbMMC_DataPath_DIRECTION 1 -#define sbMMC_DataPath_DIRECTION 1 -#define MMC_DataPath_MASK_DIRECTION BIT_MASK(MMC_DataPath_DIRECTION) - -#define wbMMC_DataPath_MODE 1 -#define sbMMC_DataPath_MODE 2 -#define MMC_DataPath_MASK_MODE BIT_MASK(MMC_DataPath_MODE) - -#define wbMMC_DataPath_DMA 1 -#define sbMMC_DataPath_DMA 3 -#define MMC_DataPath_MASK_DMA BIT_MASK(MMC_DataPath_DMA) - -#define MMC_SET_CTRL(reg,a) MMC_WRITE_BITS(reg,a,MMC_Power_MASK_CTRL,sbMMC_Power_CTRL) -#define MMC_SET_VOLT(reg,a) MMC_WRITE_BITS(reg,a,MMC_Power_MASK_VOLT,sbMMC_Power_VOLT) -#define MMC_SET_OPEND(reg,a) MMC_WRITE_BITS(reg,a,MMC_Power_MASK_OPEND,sbMMC_Power_OPEND) -#define MMC_SET_ROD(reg,a) MMC_WRITE_BITS(reg,a,MMC_Power_MASK_ROD,sbMMC_Power_ROD) -#define MMC_SET_CENABLE(reg,a) MMC_WRITE_BITS(reg,a,MMC_Clock_MASK_ENABLE,sbMMC_Clock_ENABLE) -#define MMC_SET_PWRSAVE(reg,a) MMC_WRITE_BITS(reg,a,MMC_Clock_MASK_PWRSAVE,sbMMC_Clock_PWRSAVE) -#define MMC_SET_BYPASS(reg,a) MMC_WRITE_BITS(reg,a,MMC_Clock_MASK_BYPASS,sbMMC_Clock_BYPASS) - -#define MMC_SET_CLKDIV(reg,a) MMC_WRITE_BITS(reg,a,MMC_Clock_MASK_CLKDIV,sbMMC_Clock_CLKDIV) -#define MMC_SET_DATAPATH(reg,a) MMC_WRITE_BITS(reg,a,MMC_DataPath_MASK_ENABLE,sbMMC_DataPath_ENABLE) -#define MMC_SET_BLOCKSIZE(reg,a) MMC_WRITE_BITS(reg,a,MMC_DataPath_MASK_BLOCKSIZE,sbMMC_DataPath_BLOCKSIZE) -#define MMC_SET_DATADIR(reg,a) MMC_WRITE_BITS(reg,a,MMC_DataPath_MASK_DIRECTION,sbMMC_DataPath_DIRECTION) -#define MMC_SET_MODE(reg,a) MMC_WRITE_BITS(reg,a,MMC_DataPath_MASK_MODE,sbMMC_DataPath_MODE) -#define MMC_SET_DMA(reg,a) MMC_WRITE_BITS(reg,a,MMC_DataPath_MASK_DMA,sbMMC_DataPath_DMA) - - - -// Functional layer -#define R1_OUT_OF_RANGE 0x80000000 -#define R1_ADDRESS_ERROR 0x40000000 -#define R1_BLOCK_LEN_ERROR 0x20000000 -#define R1_ERASE_SEQ_ERROR 0x10000000 -#define R1_ERASE_PARAM 0x08000000 -#define R1_WP_VIOLATION 0x04000000 -#define R1_CARD_IS_LOCKED 0x02000000 -#define R1_LOCK_UNLOCK_FAILED 0x01000000 -#define R1_COM_CRC_ERROR 0x00800000 -#define R1_ILLEGAL_COMMAND 0x00400000 -#define R1_CARD_ECC_FAILED 0x00200000 -#define R1_CC_ERROR 0x00100000 -#define R1_UNKNOWN_ERROR 0x00080000 -#define R1_STREAM_READ_UNDERRUN 0x00040000 -#define R1_STREAM_WRITE_OVERRUN 0x00020000 -#define R1_CID_CSD_OVERWRITE 0x00010000 -#define R1_WP_ERASE_SKIP 0x00008000 -#define R1_CARD_ECC_DISABLED 0x00004000 -#define R1_ERASE_RESET 0x00002000 -#define R1_AKE_SEQ_ERROR 0x00000008 -#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ -#define R1_READY_FOR_DATA 0x000000100 -#define R1_APP_CMD 0x000000020 - -/* DEFINES FOR R6 RESPONSE */ -#define R6_GEN_UNKNOWN_ERROR 0x00002000 -#define R6_ILLEGAL_CMD 0x00004000 -#define R6_COM_CRC_FAILED 0x00008000 - -#define AllOne (0xffffffff) -#define AllZero (0x00000000) - - -//Power Control register - -#define PowerOn (0x00000003) -#define OpenDrain (0x00000040) -#define CmdDatEn (0x0000003C) -#define VoltageWindowMMC (0x80FFC000) -#define VoltageWindowSD (0x80010000) -#define StuffBits0To32 (0xFFFFFFFF) -#define StuffBits0To15 (0xFFFF) -#define Sector_Mode (0x40000000) -#define Byte_Mode (0x00000000) -#define Check_Pattern (0x000001AA) - -//Clock Control register - -#define ClkDivInit (0x00000076) -#define ClkDivTrans (0x00000001) -#define ClkEnable (0x00000100) -#define PwrSave (0x00000200) -#define Enab_Bypass (0x00000400) -#define Widebus_4 (0x00000800) -#define Widebus_8 (0x00001000) -#define Hwfc_en (0x00004000) - -//Command register - -//all commands - -#define GO_IDLE_STATE (0) -#define SEND_OP_COND (1) -#define ALL_SEND_CID (2) -#define SET_REL_ADDR (3) -#define SET_DSR (4) -#define SEL_DESEL_CARD (7) -#define SEND_EXT_CSD (8) -#define SEND_CSD (9) -#define SEND_CID (10) -#define READ_DAT_UNTIL_STOP (11) -#define STOP_TRANSMISSION (12) -#define SEND_STATUS (13) -#define GO_INACTIVE_STATE (15) -#define SET_BLOCKLEN (16) -#define READ_SINGLE_BLOCK (17) -#define READ_MULT_BLOCK (18) -#define WRITE_DAT_UNTIL_STOP (20) -#define SET_BLOCK_COUNT (23) -#define WRITE_SINGLE_BLOCK (24) -#define WRITE_MULT_BLOCK (25) -#define PROG_CID (26) -#define PROG_CSD (27) -#define SET_WRITE_PROT (28) -#define CLR_WRITE_PROT (29) -#define SEND_WRITE_PROT (30) -#define ERASE_GRP_START (35) -#define ERASE_GRP_END (36) -#define ERASE (38) -#define FAST_IO (39) -#define GO_IRQ_STATE (40) -#define LOCK_UNLOCK (42) -#define APP_CMD (55) -#define GEN_CMD (56) - -/*Following commands are SD Card Specific commands. MMC_APP_CMD should be sent before sending these commands.*/ -#define APP_SD_SET_BUSWIDTH (6) -#define SD_APP_STAUS (13) -#define SD_APP_SEND_NUM_WRITE_BLOCKS (22) -#define SD_APP_OP_COND (41) -#define SD_APP_SET_CLR_CARD_DETECT (42) -#define SD_APP_SEND_SCR (51) -#define SD_SEND_IF_COND (8) - -//Command control register - -#define RespExpected (0x00000040) -#define LongResponse (0x00000080) -#define EnabIntrReq (0x00000100) -#define EnabCmdPend (0x00000200) -#define CmdPathEnable (0x00000400) - - -//Data Control register - -#define DataPathEnable (0x00000001) -#define ReadDir (0x00000002) -#define StreamMode (0x00000004) -#define DMAEnab (0x00000008) -#define BlockSize (0x000000F0) - -//Status register - -#define CmdCrcFail (0x00000001) -#define DataCrcFail (0x00000002) -#define CmdTimeOut (0x00000004) -#define DataTimeOut (0x00000008) -#define TxUnderrun (0x00000010) -#define RxOverrun (0x00000020) -#define CmdRespEnd (0x00000040) -#define CmdSent (0x00000080) -#define DataEnd (0x00000100) -#define StartBitError (0x00000200) -#define DataBlockEnd (0x00000400) -#define CmdActive (0x00000800) -#define TxActive (0x00001000) -#define RxActive (0x00002000) -#define TxFifoHalfEmpty (0x00004000) -#define RxFifoHalfFull (0x00008000) -#define TxFifoFull (0x00010000) -#define RxFifoFull (0x00020000) -#define TxFifoEmpty (0x00040000) -#define RxFifoEmpty (0x00080000) -#define TxDataAvlbl (0x00100000) -#define RxDataAvlbl (0x00200000) -#define AllInterrupts (0x003FFDFF) -#define ErrorBits (0xFDFFE008) - -#define ClrStaticFlags (0x00C007FF) - -/* COMMAND CLASS SUPPORTED */ -#define CCCC_LOCK_UNLOCK (0x80) -#define CCCC_WRITE_PROT (0x40) -#define CCCC_ERASE (0x20) - -#endif /*MMCP*/ diff --git a/board/st/u8500/mmc_utils.c b/board/st/u8500/mmc_utils.c index 5ff34425e..d29255937 100644 --- a/board/st/u8500/mmc_utils.c +++ b/board/st/u8500/mmc_utils.c @@ -21,880 +21,138 @@ */ #include -#include +#include "common.h" #include +#include #include -#include "gpio.h" -#include "mmc.h" // MMC api -#include "mmc_utils.h" // to access MMC -#include "mmc_p.h" // t_mmc_register definition -u32 MMCBuffer[1024] ; -static int IS_SD_CARD; - -/* --- exported from other modules ---------------------------------------- */ -static u8 selected_card = 0; -extern t_mmc_error mmc_cmderror_2 (void); -extern t_mmc_error mmc_cmdresp2error_2 (void); -extern t_mmc_error mmc_cmdresp3error_2 (void); -extern t_mmc_error mmc_cmdresp145error_2 (u8 cmd); -extern t_mmc_error mmc_cmdreadresp (u32 * tempbuff); -extern t_mmc_error mmc_waitcmdreadresp (void); -extern t_mmc_error mmc_cmdwriteresp (u8 cardno, u32 * tempbuff, u16 total_num_of_bytes); -extern t_mmc_error mmc_waitcmdwriteresp (u8 cardno, u32 * tempbuff, u16 total_num_of_bytes); - -extern t_mmc_register *t_mmc0; -extern u32 t_mmc_rel_addr; - -t_mmc_boot_record mmc_boot_record; - -void mmc_copyByteH (u8 * sourceAddr, u8 * destAddress, int size) -{ - int i; - for (i = 0; i < size; i++) - { - *(destAddress + i) = *(sourceAddr + i); - } -} - -void mmc_shift_memH (int num_of_words, u32 * start_address, u32 * dest_address, u32 shift) -{ - u32 *address; - int word = 0; - u32 high; - int i, word_offset, bit_offset; - - word_offset = (int) (shift / 32); - bit_offset = (int) (shift % 32); - for (i = 0; i < num_of_words; i++) - { - *(dest_address + i) = 0; - } - for (i = word_offset; i < num_of_words; i++) - { - *(dest_address + i - word_offset) = *(start_address + i); - } - address = dest_address; - for (word = 0; word < num_of_words - 1; word++) - { - *address = (*address) >> bit_offset; - address++; - high = (*address << (32 - bit_offset)); - *(address - 1) |= high; - } - *address = (*address) >> bit_offset; -} - -u8 convert_from_bytes_to_power_of_two (u16 no_of_bytes) -{ - u8 count = 0; - while (no_of_bytes != 1) - { - no_of_bytes >>= 1; - count++; - } - return count; -} - -t_mmc_error mmc_enable () -{ - t_mmc_error error = MMC_OK; - t_mmc_command_control commcontrol; - t_bool validvoltage = FALSE; - u32 arg, response; - int i; - - IS_SD_CARD = 0; - - selected_card = 0; - - t_mmc0->mmc_Power = 0x1BF; - t_mmc0->mmc_Clock = 0x41FF; - - commcontrol.IsRespExpected = FALSE; - commcontrol.IsLongResp = FALSE; - commcontrol.IsInterruptMode = FALSE; - commcontrol.IsPending = FALSE; - commcontrol.cmdpath = MMC_ENABLE; - - error = mmc_sendcommand (MMC_GO_IDLE_STATE, 0x00000000, commcontrol); - - error = mmc_cmderror_2 (); - - //// Added by Chris Sebastian for SD Card support: - //// Send ACMD41. If we do not get a response, it is not an SD card. - //// If we do get a response, loop until card is not busy. - - commcontrol.IsRespExpected = TRUE; - commcontrol.IsLongResp = FALSE; - commcontrol.IsInterruptMode = FALSE; - commcontrol.IsPending = FALSE; - commcontrol.cmdpath = MMC_ENABLE; - - for(i = 200; i; i--) { - error = mmc_sendcommand (MMC_APP_CMD, 0x00000000, commcontrol); // Let the card know that the next command is an app-cmd. - error = mmc_cmdresp145error_2(MMC_APP_CMD); - error = mmc_sendcommand (SD_SEND_OP_COND, 0x00060000, commcontrol); // I got the 0x00060000 from Linux kernel source. - error = mmc_cmdresp3error_2 (); - t_mmc0->mmc_Clear = ClrStaticFlags; //clear all the static status flags. CmdResp3Error_2 leaves some bits set. - if (t_mmc0->mmc_Response0 & 0x80000000) { - printf("SD card detected \n"); - IS_SD_CARD = 1; - return MMC_OK; // SD CARD DETECTED. Do not continue with MMC init logic. Quick escape! - } - } - - commcontrol.IsRespExpected = FALSE; - commcontrol.IsLongResp = FALSE; - commcontrol.IsInterruptMode = FALSE; - commcontrol.IsPending = FALSE; - commcontrol.cmdpath = MMC_ENABLE; - - error = mmc_sendcommand (MMC_GO_IDLE_STATE, 0x00000000, commcontrol); - error = mmc_cmderror_2 (); - - arg = 0x00060000; // High Voltage MMC, byte mode. Was 0x00FFC000, but that writes to reserved bits... - while (!validvoltage) - { - // send CMD1 (SEND_OP_COND) - commcontrol.IsRespExpected = TRUE; - error = mmc_sendcommand (MMC_SEND_OP_COND, arg, commcontrol); - - error = mmc_cmdresp3error_2 (); - - if (error != MMC_OK) - { - goto end; - } - mmc_getresponse (MMC_SHORT_RESP, &response); - - arg = response; - validvoltage = (t_bool) (((response >> 31) == 1) ? 1 : 0); - - } -end: - return error; -} - -t_mmc_error mmc_disable () -{ - t_mmc_error error = MMC_OK; - t_mmc_power_state powerstate = MMC_POWER_OFF; - - error = mmc_setpowerstate (powerstate); - return error; -} - -t_mmc_error mmc_initCard () -{ - t_mmc_error error = MMC_OK; - t_mmc_command_control commcontrol; - t_mmc_bus_configuration busconfig; - t_mmc_clock_control clockcontrol; - - // send CMD2 (ALL_SEND_CID) - commcontrol.IsRespExpected = TRUE; - commcontrol.IsLongResp = TRUE; - commcontrol.IsInterruptMode = FALSE; - commcontrol.IsPending = FALSE; - commcontrol.cmdpath = MMC_ENABLE; - - error = mmc_sendcommand (MMC_ALL_SEND_CID, 0x00000000, commcontrol); - error = mmc_cmdresp2error_2 (); - // error is MMC_CMD_CRC_FAIL on COB board ?! - // if( error != MMC_OK) - // goto end; - - // send CMD3 (SET_RELATIVE_ADDR) - - commcontrol.IsLongResp = FALSE; - error = mmc_sendcommand (MMC_SET_REL_ADDR, t_mmc_rel_addr, commcontrol); - error = mmc_cmdresp145error_2 (MMC_SET_REL_ADDR); - if(IS_SD_CARD) { - t_mmc_rel_addr = t_mmc0->mmc_Response0 & 0xFFFF0000; - } - - if (error != MMC_OK) - { - goto end; - } - busconfig.mode = MMC_PUSH_PULL; - busconfig.rodctrl = MMC_DISABLE; - error = mmc_configbus (busconfig); - clockcontrol.pwrsave= MMC_DISABLE; - clockcontrol.bypass = MMC_DISABLE; - clockcontrol.widebus= MMC_DISABLE; - error = mmc_setclockfrequency(0x00); /* 26 MHz */ - if (error != MMC_OK) - { - goto end; - } - error = mmc_configclockcontrol (clockcontrol); - if (error != MMC_OK) - { - goto end; - } -end: - return error; -} - -t_mmc_error mmc_readblock (u8 cardno, u32 addr, u32 * readbuff, u16 blocksize, t_mmc_transfer_mode mmc_transfer_mode) -{ - t_mmc_error error = MMC_OK; - u8 power; - t_mmc_command_control commcontrol; - u32 response; - - commcontrol.IsRespExpected = TRUE ; - commcontrol.IsLongResp = FALSE ; - commcontrol.IsInterruptMode = FALSE ; - commcontrol.IsPending = FALSE ; - commcontrol.cmdpath = MMC_ENABLE ; - error = mmc_setdatapath (MMC_DISABLE); - error = mmc_handledma (MMC_DISABLE); - if (error != MMC_OK) - { - goto end; - } - // send command for selecting the card - if (cardno != selected_card) - { - error = mmc_sendcommand (MMC_SEL_DESEL_CARD, t_mmc_rel_addr, commcontrol); - error = mmc_cmdresp145error_2 (MMC_SEL_DESEL_CARD); - if (error != MMC_OK) - { - goto end; - } - else - { - selected_card = cardno; - } - } - error = mmc_getresponse (MMC_SHORT_RESP, &response); - if (response & 0x02000000) - { - return MMC_LOCK_UNLOCK_FAILED; - } - // set the block size,both on controller and card - if ((blocksize > 0) && (blocksize <= 2048) && ((blocksize & (blocksize - 1)) == 0)) - { - power = convert_from_bytes_to_power_of_two (blocksize); - error = mmc_setdatablocklength (power); - error = mmc_sendcommand (MMC_SET_BLOCKLEN, (u32) blocksize, commcontrol); - error = mmc_cmdresp145error_2 (MMC_SET_BLOCKLEN); - if (error != MMC_OK) - { - return error; - } - } - else - { - error = MMC_INVALID_PARAMETER; - goto end; - } - error = mmc_setdatalength (blocksize ); - error = mmc_setdatatimeout (0xefffffff ); - error = mmc_settransferdirection (MMC_READ ); - error = mmc_settransfertype (MMC_BLOCK ); - error = mmc_setdatapath (MMC_ENABLE); - //t_mmc0->mmc_DataCtrl |= (ReadDir & ~StreamMode) | DataPathEnable; - error = mmc_sendcommand (MMC_READ_SINGLE_BLOCK, addr, commcontrol); - error = mmc_cmdresp145error_2 (MMC_READ_SINGLE_BLOCK); - if (error != MMC_OK) - { - goto end; - } - if (mmc_transfer_mode == MMCDMA) - { - error = mmc_waitcmdreadresp (); - } - else - { - error = mmc_cmdreadresp (readbuff); - } - if (error != MMC_OK) - { - goto end; - } -end: - return error; -} - -t_mmc_error mmc_writeblock (u8 cardno, u32 addr, u32 * writebuff, u16 blocksize, t_mmc_transfer_mode mmc_transfer_mode) -{ - t_mmc_error error = MMC_OK; - u8 power; - t_mmc_command_control commcontrol; - u32 response; - - commcontrol.IsRespExpected = TRUE; - commcontrol.IsLongResp = FALSE; - commcontrol.IsInterruptMode = FALSE; - commcontrol.IsPending = FALSE; - commcontrol.cmdpath = MMC_ENABLE; - - error = mmc_setdatapath (MMC_DISABLE); - error = mmc_handledma (MMC_DISABLE); - error = mmc_settransferdirection(MMC_WRITE); - error = mmc_settransfertype (MMC_BLOCK); - - if (cardno != selected_card) - { - error = mmc_sendcommand (MMC_SEL_DESEL_CARD, t_mmc_rel_addr, commcontrol); - error = mmc_cmdresp145error_2 (MMC_SEL_DESEL_CARD); - if (error != MMC_OK) - { - goto end; - } - else - { - selected_card = cardno; - } - } - - mmc_getresponse (MMC_SHORT_RESP, &response); - if (response & 0x02000000) - { - return MMC_LOCK_UNLOCK_FAILED; - } - // set the block size,both on controller and card - if ((blocksize > 0) && (blocksize <= 2048) && (((blocksize & (blocksize - 1)) == 0))) - { - power = convert_from_bytes_to_power_of_two (blocksize); - error = mmc_setdatablocklength (power); - error = mmc_sendcommand (MMC_SET_BLOCKLEN, (u32) blocksize, commcontrol); - error = mmc_cmdresp145error_2 (MMC_SET_BLOCKLEN); - if (error != MMC_OK) - { - goto end; - } - } - else - { - error = MMC_INVALID_PARAMETER; - goto end; - } - - error = mmc_setdatalength (blocksize); - error = mmc_setdatatimeout (0xefffffff); - error = mmc_settransferdirection (MMC_WRITE); - error = mmc_settransfertype (MMC_BLOCK); - error = mmc_setdatapath (MMC_ENABLE); - error = mmc_sendcommand (MMC_WRITE_SINGLE_BLOCK, addr, commcontrol); - error = mmc_cmdresp145error_2 (MMC_WRITE_SINGLE_BLOCK); - if (error != MMC_OK) - { - goto end; - } - if (mmc_transfer_mode == MMCDMA) - { - error = mmc_waitcmdwriteresp (cardno, writebuff, blocksize); - } - else - { - error = mmc_cmdwriteresp (cardno, writebuff, blocksize); - } - if (error != MMC_OK) - { - goto end; - } -end: - return error; -} - -t_mmc_error mmc_readcsd (u32 * CSD) -{ - t_mmc_error error = MMC_OK; - t_mmc_command_control commcontrol; - u32 buf[4]; - - // send CMD9 (SEND CSD) - commcontrol.IsRespExpected = TRUE; - commcontrol.IsLongResp = TRUE; - commcontrol.IsInterruptMode = FALSE; - commcontrol.IsPending = FALSE; - commcontrol.cmdpath = MMC_ENABLE; - - error = mmc_sendcommand (MMC_SEND_CSD, t_mmc_rel_addr, commcontrol); - error = mmc_cmdresp2error_2 (); - if (error != MMC_OK) - { - goto end; - } - error = mmc_getresponse (MMC_LONG_RESP, buf); - CSD[0] = buf[3]; - CSD[1] = buf[2]; - CSD[2] = buf[1]; - CSD[3] = buf[0]; -end: - return error; -} - -t_mmc_error mmc_select_n_switch(void) +#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, 0x00124000, 0x00000800), /* Modem parameters */ + [3] = {0}, +}; + +#undef PART + +int write_partition_block(void) { - t_mmc_error error = MMC_OK; - t_mmc_command_control commcontrol; - /* t_mmc_clock_control clockcontrol; */ - u32 response; - u8 cardno = 1; - - commcontrol.IsRespExpected = TRUE; - commcontrol.IsLongResp = FALSE; - commcontrol.IsInterruptMode = FALSE; - commcontrol.IsPending = FALSE; - commcontrol.cmdpath = MMC_ENABLE; - - // send command for selecting the card - if (cardno != selected_card) - { - error = mmc_sendcommand(MMC_SEL_DESEL_CARD, t_mmc_rel_addr, commcontrol); - error = mmc_cmdresp145error_2(MMC_SEL_DESEL_CARD); - if (error != MMC_OK) - { - goto end; - } - else - { - selected_card = cardno; - } - } - error = mmc_getresponse(MMC_SHORT_RESP, &response); - if (response & 0x02000000) - { - error = MMC_LOCK_UNLOCK_FAILED; - goto end; - } - /* XXX: what is this, why is it commented out, why is it here at all? */ - /* - error = mmc_sendcommand (MMC_APP_CMD, 0x00000000, commcontrol); - error = mmc_cmdresp145error_2(MMC_APP_CMD); - error = mmc_sendcommand (6, 0x2, commcontrol); - error = mmc_cmdresp145error_2(6); - if (error != MMC_OK) - { - goto end; - } - clockcontrol.pwrsave= MMC_DISABLE; - clockcontrol.bypass = MMC_DISABLE; - clockcontrol.widebus= MMC_ENABLE; - error = mmc_configclockcontrol (clockcontrol); - if (error != MMC_OK) - { - goto end; - } - */ -end: - return error; -} - -t_mmc_error mmc_readcid (u32 * CID) -{ - t_mmc_error error = MMC_OK; - t_mmc_command_control commcontrol; - u32 buf[4]; - - // send CMD9 (SEND CSD) - commcontrol.IsRespExpected = TRUE; - commcontrol.IsLongResp = TRUE; - commcontrol.IsInterruptMode = FALSE; - commcontrol.IsPending = FALSE; - commcontrol.cmdpath = MMC_ENABLE; - - error = mmc_sendcommand (MMC_SEND_CID, t_mmc_rel_addr, commcontrol); - error = mmc_cmdresp2error_2 (); - if (error != MMC_OK) - { - goto end; - } - error = mmc_getresponse (MMC_LONG_RESP, buf); - CID[0] = buf[3]; - CID[1] = buf[2]; - CID[2] = buf[1]; - CID[3] = buf[0]; -end: - return error; + int err; + u32 offset = PIB_EMMC_ADDR; + u8 mbr[512]; + u8 emmc_existing_partition[512]; + struct mmc *boot_dev = NULL; + + 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; } -t_mmc_error mmc_read_file (char *filename, u32 address, u32 * FileSize) -{ - u8 *mem_address = (u8 *) address; - u8 sector[512]; - u16 BytesPerSector; - u32 BRStartSector; - u32 FATStartSector; - u32 DataStartSector; - u32 FileStartSector; - u16 SectorsPerFAT; - u8 SectorsPerCluster; - u8 k; - u16 MaxRDEntries; - u16 ReservedSectors; - u32 RDStartSector, j; - char nomefile[12] = " "; - int filelength; - u16 FileStartCluster = 0; - t_mmc_error response, response2; - int i, goout, found, result = PASS; - u32 CSD[4]; - char mmcfilename[] = " "; - char *dotpos; - - /////////// Attention please: ///////////////////// - // // - // if other Alternate function apart from MMCI // - // are selected, the MMCI I/F has some problems // - // // - //////////////////////////////////////////////////// - - gpio_altfuncenable(GPIO_ALT_SD_CARD0, "MMC"); - // Power-on the controller - response = mmc_enable (); - - if (response != MMC_OK) - { - - response = mmc_enable (); // This actually IS necessary because it takes time for newly-inserted cards initialize. ~Chris S. - if (response != MMC_OK) - { - printf ("Error in card power on\n"); - result = FAIL; - goto end; - } - } - // Initialise the cards on the bus, if any - response = mmc_initCard (); - - if (response != MMC_OK) - { - printf ("Error in card initialization\n"); - result = FAIL; - goto end; - } - // Get card info: CID, CSD, RCA registers - response = mmc_readcsd (CSD); - - if (response != MMC_OK) - { - printf ("Error while fetching card info\n"); - result = FAIL; - goto end; - } - - // Select card and switch to 4-Bit, TODO HS if possible - response = mmc_select_n_switch (); - - if (response != MMC_OK) - { - printf ("Error while select or switching to 4-bit/HS\n"); - goto end; - } - - // Read the MBR - response = mmc_readblock (1, 0, (u32 *) sector, 512, MMCPOLLING); - - if (response != MMC_OK) - { - printf ("Error while reading boot record\n"); - result = FAIL; - goto end; - } - if (sector[446] == 0x00 || sector[446] == 0x80) - { // found a MBR at the beginning of card - BRStartSector = sector[454]; - } - else - { // BR at the beginning of card - BRStartSector = 0x00; - } - // Read the BR - response = mmc_readblock (1, (u32) (512 * BRStartSector), (u32 *) & mmc_boot_record, 512, MMCPOLLING); - - k = 0; - while (response == MMC_DATA_CRC_FAIL && (k < 2)) - { - response = mmc_readblock (1, (u32) (512 * BRStartSector), (u32 *) & mmc_boot_record, 512, MMCPOLLING); - k++; - } - if (response != MMC_OK) - { - printf ("Error while reading boot record\n"); - result = FAIL; - goto end; - } - mmc_copyByteH (mmc_boot_record.BytesPerSector, (u8 *) & BytesPerSector, 2); - mmc_copyByteH (mmc_boot_record.ReservedSectors, (u8 *) & ReservedSectors, 2); - FATStartSector = BRStartSector + ReservedSectors; // the field at offset 15 contains the number of reserved sectors at - // the beginning of the media including the boot sector - mmc_copyByteH (mmc_boot_record.SectorsPerFat, (u8 *) & SectorsPerFAT, 2); - SectorsPerCluster = mmc_boot_record.SectorsPerCluster[0]; - mmc_copyByteH (mmc_boot_record.NumOfRootEntries, (u8 *) & MaxRDEntries, 2); - FATStartSector += SectorsPerFAT; - RDStartSector = FATStartSector + SectorsPerFAT; - DataStartSector = RDStartSector + (u32) ((MaxRDEntries * 32) / 512); - - - - // convert filename into mmc compatible file name (upper case , <= 8+3 char, no dot, no extension) - filelength = strlen (filename); - dotpos = strchr (filename, '.'); - if (dotpos == NULL) - { - // no dot - if (filelength <= 8) - { - for (j = 0; j < filelength; j++) - { - mmcfilename[j] = (char) toupper (filename[j]); - } - } - else - { - for (j = 0; j < 6; j++) - { - mmcfilename[j] = (char) toupper (filename[j]); - } - mmcfilename[7] = '~'; - mmcfilename[8] = '1'; - filelength = 8; - } - } - else - { - // dot - if ((dotpos - filename) <= 8) - { - for (j = 0; j < (dotpos - filename); j++) - { - mmcfilename[j] = (char) toupper (filename[j]); - } - for (; j < 8; j++) - { - mmcfilename[j] = ' '; - } - // copy 3 char after . - mmcfilename[j++] = (char) toupper (dotpos[1]); - mmcfilename[j++] = (char) toupper (dotpos[2]); - mmcfilename[j++] = (char) toupper (dotpos[3]); - - } - else - { - for (j = 0; j < 6; j++) - { - mmcfilename[j] = (char) toupper (filename[j]); - } - mmcfilename[6] = '~'; - mmcfilename[7] = '1'; - // copy 3 char after . - mmcfilename[8] = (char) toupper (dotpos[1]); - mmcfilename[9] = (char) toupper (dotpos[2]); - mmcfilename[10] = (char) toupper (dotpos[3]); - } - filelength = 11; - } - mmcfilename[11] = '\0'; - - - // search Root Directory for entry filename - goout = 0; - found = 0; - for (j = 0; j < (DataStartSector - RDStartSector); j++) - { - if (goout == 1) - break; - response = mmc_readblock (1, (u32) ((RDStartSector + j) * 512), (u32 *) sector, 512, MMCPOLLING); - if (response != MMC_OK) - { - printf ("Error while reading root directory\n"); - result = FAIL; - goto end; - } - - for (i = 0; i < 512; i += 32) - { - strncpy (nomefile, (char *) §or[i], filelength); - if (strcmp (nomefile, mmcfilename) == 0) - { - mmc_copyByteH (§or[i + 26], (u8 *) & FileStartCluster, 2); - mmc_copyByteH (§or[i + 28], (u8 *) FileSize, 4); - FileStartCluster -= 2; - goout = 1; - found = 1; - break; - } - if (nomefile[0] == 0) - { // end of Root Directory - goout = 1; - break; - } - } - } - - // size of file : *FileSize ( 32 bits quantum) - // number of bytes per sector : BytesPerSector - // Beginning of file : FileStartSector - - printf ("Bytes per sector : %d \n", BytesPerSector ); - printf ("Sectors per cluster : %d \n", SectorsPerCluster ); - if (found) - { - u32 remaining = *FileSize ; - u32 count; - u32 burstsize = BytesPerSector ; - - FileStartSector = ( DataStartSector + (u32)(FileStartCluster * SectorsPerCluster)) ; - printf ("Reading file %s from MMC ..., start sector = %d, address 0x%x \n",filename,FileStartSector,address); - count = SectorsPerCluster - (FileStartSector % SectorsPerCluster) ; - FileStartSector = FileStartSector * BytesPerSector; // the first burst might be different to align of clusters - - do - { - if ( remaining >= burstsize ) - { // read straight burst - - k = 0; - do - { - response = mmc_readblock (1, (u32) FileStartSector , (u32 *) mem_address, burstsize , MMCPOLLING); - k++; - - } while ((response==MMC_DATA_CRC_FAIL)&&(k<4)); - if ( k != 1) printf ("!"); - FileStartSector += burstsize; - mem_address += burstsize; - remaining -= burstsize; - } - else - { // read burst +1 and perform memcpy - - burstsize = ((remaining + (BytesPerSector-1))/BytesPerSector) * BytesPerSector ; - k = 0; - do - { - response = mmc_readblock (1, (u32) FileStartSector , (u32 *) MMCBuffer , burstsize , MMCPOLLING); - k++; - } while ((response==MMC_DATA_CRC_FAIL)&&(k<4)); - if ( k != 1) printf ("!"); - memcpy ((char *) mem_address, (char *)MMCBuffer,remaining); - remaining = 0; - } - if (response != MMC_OK) - { - printf ("Error while reading file %s\n", filename); - result = FAIL; - goto end; - } - } while ( remaining ); - - } - else - { - printf ("Unable to find %s on Multi Media Card\n", filename); - response = MMC_INVALID_PARAMETER; - result = FAIL; - goto end; - } - -end: - - return response; -} +U_BOOT_CMD( + write_partition_block, 1, 0, write_partition_block, + "- write partition block on emmc device\n", + NULL +); /* * command line commands */ - -static char mmc_cmdbuffer[1024] ; - -static int copy_file_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ #ifdef CONFIG_CMD_FAT - unsigned long address; - long sz; - - address = simple_strtoul (argv[2], 0, 16); - - printf("copy_file_mmc : filename = %s\n", argv[1]); - printf("copy_file_mmc : address = %lx\n", address); - - sz = file_fat_read(argv[1], (void *)address, 0); - if (sz == -1) - { - printf("copy_file_mmc error : in loading file \n"); - return 1; - } - - return 0; -#else - unsigned long address; - unsigned long filesize; - int load_result = 1; - unsigned long error_name = 0; - char filename[30] ; - { - strcpy(filename , argv[1]); - address = simple_strtoul (argv[2],0,16);//argv[2]; - - printf("copy_file_mmc : filename = %s\n",filename); - printf("copy_file_mmc : address = %lx\n",address); - - load_result = mmc_read_file(filename,address,&filesize); - if (load_result != 0) - { - error_name = (unsigned long) (-load_result); - printf("copy_file_mmc error : in loading file \n"); - } - return(0); - } -#endif -} - -static int mmc_read_cmd_file (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +static int mmc_read_cmd_file(cmd_tbl_t *cmdtp, int flag, int argc, + char *argv[]) { -#ifdef CONFIG_CMD_FAT - long sz; - - sz = file_fat_read("command.txt", &mmc_cmdbuffer, sizeof(mmc_cmdbuffer) - 1); - if (sz == -1) - { - printf("No command.txt found in the Card\n"); - return 1; - } - - mmc_cmdbuffer[sz] = '\0'; - setenv ("bootcmd", mmc_cmdbuffer); - return 0; -#else - unsigned long filesize; - int load_result = 1; - unsigned long error_name = 0; - - load_result = mmc_read_file("command.txt",(unsigned long)&mmc_cmdbuffer,&filesize); - if (load_result != 0) - { - error_name = (unsigned long) (-load_result); - printf("mmc_read_cmd_file error : in loading file \n"); - } - else - { - setenv ("bootcmd", mmc_cmdbuffer); - } - return(0); -#endif + long sz; + char mmc_cmdbuffer[1024]; + + 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( - copy_file_mmc, 3, 0, copy_file_mmc, - "- copy file from mmc card\n", - "filename address\n" - " - load binary file from the MMC/SD card to a memory address\n" -); - - -U_BOOT_CMD( - mmc_read_cmd_file, 1, 0, mmc_read_cmd_file, - "- copy command file from mmc card\n", + mmc_read_cmd_file, 1, 0, mmc_read_cmd_file, + "- setup bootcmd env by reading command.txt file from MMC/SD card\n", NULL ); +#endif /* ------------------------------- End of file ---------------------------- */ diff --git a/board/st/u8500/mmc_utils.h b/board/st/u8500/mmc_utils.h deleted file mode 100755 index c0b997a5e..000000000 --- a/board/st/u8500/mmc_utils.h +++ /dev/null @@ -1,107 +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 - */ -#ifndef __MMC_UTILS_H -#define __MMC_UTILS_H - -#include - -typedef struct -{ - u8 jump [3]; - u8 OEMname [8]; - u8 BytesPerSector [2]; - u8 SectorsPerCluster [1]; - u8 ReservedSectors [2]; - u8 NumOfFAT [1]; - u8 NumOfRootEntries [2]; - u8 NumOfSectors [2]; - u8 MediaDesc [1]; - u8 SectorsPerFat [2]; - u8 SectorsPerTrack [2]; - u8 NumOfHeads [2]; - u8 NumOfHiddenSectors [4]; - u8 NumOfTotSectors [4]; - u8 DriveNumber [1]; - u8 reserved [1]; - u8 ExtBootSig [1]; - u8 VolumeID [4]; - u8 VolumeLabel [11]; - u8 FSType [8]; - u8 LoadProg [448]; - u8 Signature [2]; -} t_mmc_boot_record; - -typedef struct -{ - u8 filename [8]; - u8 extension [3]; - u8 attrib ; - u8 reserved [10]; - u8 hour [2]; - u8 date [2]; - u8 startCluster [2]; - u8 dimension [4]; -} t_mmc_root_entry; - -typedef struct s_root_elem -{ - char name[8]; - char ext[3]; - char nulll[0xf]; - short offset; - unsigned sizee; -} s_root_elem; - -typedef struct s_root -{ - s_root_elem elem[16]; -} s_root; - -typedef struct s_file_elem -{ - char filename [8] ; -} s_file_elem; - -typedef struct s_file_list -{ - s_file_elem elem [30]; -} s_file_list ; - -typedef enum -{ - MMCPOLLING, - MMCDMA -}t_mmc_transfer_mode; - - -t_mmc_error mmc_readblock (u8 cardno, u32 addr, u32* readbuff, u16 blocksize, t_mmc_transfer_mode transfer_mode); -t_mmc_error mmc_writeblock (u8 cardno, u32 addr, u32* writebuff, u16 blocksize, t_mmc_transfer_mode transfer_mode); -t_mmc_error mmc_enable (void); -t_mmc_error mmc_disable (void); -t_mmc_error mmc_initCard (void); -t_mmc_error mmc_readcsd (u32 *response); -t_mmc_error mmc_readcid (u32 *response) ; -t_mmc_error display_file_list(char *extension); - -#endif /* !defined(__MMC_UTILS_H) */ - - diff --git a/board/st/u8500/u8500.c b/board/st/u8500/u8500.c index 7c47ab977..eb6dda5af 100644 --- a/board/st/u8500/u8500.c +++ b/board/st/u8500/u8500.c @@ -420,7 +420,6 @@ static void init_regs(void) } } else { struct prcmu *prcmu = (struct prcmu *) U8500_PRCMU_BASE; - u32 tmp; /* Enable timers */ writel(1 << 17, &prcmu->tcr); @@ -435,13 +434,6 @@ static void init_regs(void) u8500_prcmu_enable(&prcmu->uartclk_mgt); u8500_prcmu_enable(&prcmu->i2cclk_mgt); - if (!u8500_is_earlydrop()) { - /* Switch SDMMCCLK to 52Mhz instead of 104Mhz */ - tmp = readl(&prcmu->sdmmcclk_mgt); - tmp = (tmp & ~0x1f) | 16; - writel(tmp, &prcmu->sdmmcclk_mgt); - } - u8500_prcmu_enable(&prcmu->sdmmcclk_mgt); u8500_clock_enable(1, 9, -1); /* GPIO0 */ -- cgit v1.2.3