Merge branch 'master' of git://git.denx.de/u-boot-mmc

This commit is contained in:
Tom Rini 2013-09-20 14:06:10 -04:00
commit d0b961684e
12 changed files with 336 additions and 195 deletions

View File

@ -9,7 +9,6 @@
#include <common.h>
#include <spl.h>
#include <asm/u-boot.h>
#include <asm/utils.h>
#include <mmc.h>
#include <fat.h>
#include <version.h>
@ -45,8 +44,10 @@ static int mmc_load_image_raw(struct mmc *mmc, unsigned long sector)
(void *)spl_image.load_addr);
end:
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
if (err == 0)
printf("spl: mmc blk read err - %lu\n", err);
#endif
return (err == 0);
}
@ -58,7 +59,9 @@ static int mmc_load_image_raw_os(struct mmc *mmc)
CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS,
(void *)CONFIG_SYS_SPL_ARGS_ADDR)) {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
printf("mmc args blk read error\n");
#endif
return -1;
}
@ -84,9 +87,11 @@ static int mmc_load_image_fat(struct mmc *mmc, const char *filename)
err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0);
end:
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
if (err <= 0)
printf("spl: error reading image %s, err - %d\n",
filename, err);
#endif
return (err <= 0);
}
@ -99,8 +104,10 @@ static int mmc_load_image_fat_os(struct mmc *mmc)
err = file_fat_read(CONFIG_SPL_FAT_LOAD_ARGS_NAME,
(void *)CONFIG_SYS_SPL_ARGS_ADDR, 0);
if (err <= 0) {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
printf("spl: error reading image %s, err - %d\n",
CONFIG_SPL_FAT_LOAD_ARGS_NAME, err);
#endif
return -1;
}
@ -120,13 +127,17 @@ void spl_mmc_load_image(void)
/* We register only one device. So, the dev id is always 0 */
mmc = find_mmc_device(0);
if (!mmc) {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
puts("spl: mmc device not found!!\n");
#endif
hang();
}
err = mmc_init(mmc);
if (err) {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
printf("spl: mmc init failed: err - %d\n", err);
#endif
hang();
}
@ -145,7 +156,9 @@ void spl_mmc_load_image(void)
err = fat_register_device(&mmc->block_dev,
CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION);
if (err) {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
printf("spl: fat register err - %d\n", err);
#endif
hang();
}
@ -155,7 +168,9 @@ void spl_mmc_load_image(void)
err = mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME);
#endif
} else {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
puts("spl: wrong MMC boot mode\n");
#endif
hang();
}

View File

@ -34,6 +34,8 @@ COBJS-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
COBJS-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
ifdef CONFIG_SPL_BUILD
COBJS-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
else
COBJS-$(CONFIG_GENERIC_MMC) += mmc_write.o
endif
COBJS := $(COBJS-y)

View File

@ -41,12 +41,11 @@ static void dwmci_set_idma_desc(struct dwmci_idmac *idmac,
}
static void dwmci_prepare_data(struct dwmci_host *host,
struct mmc_data *data)
struct mmc_data *data, struct dwmci_idmac *cur_idmac)
{
unsigned long ctrl;
unsigned int i = 0, flags, cnt, blk_cnt;
ulong data_start, data_end, start_addr;
ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, data->blocks);
blk_cnt = data->blocks;
@ -73,7 +72,7 @@ static void dwmci_prepare_data(struct dwmci_host *host,
dwmci_set_idma_desc(cur_idmac, flags, cnt,
start_addr + (i * PAGE_SIZE));
if(blk_cnt < 8)
if (blk_cnt <= 8)
break;
blk_cnt -= 8;
cur_idmac++;
@ -111,6 +110,8 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac,
data ? DIV_ROUND_UP(data->blocks, 8) : 0);
int flags = 0, i;
unsigned int timeout = 100000;
u32 retry = 10000;
@ -127,7 +128,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
if (data)
dwmci_prepare_data(host, data);
dwmci_prepare_data(host, data, cur_idmac);
dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);

View File

@ -15,6 +15,7 @@
#include <malloc.h>
#include <linux/list.h>
#include <div64.h>
#include "mmc_private.h"
/* Set block count limit because of 16 bit register limit on some hardware*/
#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
@ -52,14 +53,10 @@ int __board_mmc_getcd(struct mmc *mmc) {
int board_mmc_getcd(struct mmc *mmc)__attribute__((weak,
alias("__board_mmc_getcd")));
static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
struct mmc_data backup;
int ret;
memset(&backup, 0, sizeof(backup));
#ifdef CONFIG_MMC_TRACE
int i;
u8 *ptr;
@ -114,7 +111,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
return ret;
}
static int mmc_send_status(struct mmc *mmc, int timeout)
int mmc_send_status(struct mmc *mmc, int timeout)
{
struct mmc_cmd cmd;
int err, retries = 5;
@ -135,8 +132,10 @@ static int mmc_send_status(struct mmc *mmc, int timeout)
MMC_STATE_PRG)
break;
else if (cmd.response[0] & MMC_STATUS_MASK) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("Status Error: 0x%08X\n",
cmd.response[0]);
#endif
return COMM_ERR;
}
} else if (--retries < 0)
@ -151,14 +150,16 @@ static int mmc_send_status(struct mmc *mmc, int timeout)
printf("CURR STATE:%d\n", status);
#endif
if (timeout <= 0) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("Timeout waiting card ready\n");
#endif
return TIMEOUT;
}
return 0;
}
static int mmc_set_blocklen(struct mmc *mmc, int len)
int mmc_set_blocklen(struct mmc *mmc, int len)
{
struct mmc_cmd cmd;
@ -181,179 +182,13 @@ struct mmc *find_mmc_device(int dev_num)
return m;
}
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("MMC Device %d not found\n", dev_num);
#endif
return NULL;
}
static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
{
struct mmc_cmd cmd;
ulong end;
int err, start_cmd, end_cmd;
if (mmc->high_capacity)
end = start + blkcnt - 1;
else {
end = (start + blkcnt - 1) * mmc->write_bl_len;
start *= mmc->write_bl_len;
}
if (IS_SD(mmc)) {
start_cmd = SD_CMD_ERASE_WR_BLK_START;
end_cmd = SD_CMD_ERASE_WR_BLK_END;
} else {
start_cmd = MMC_CMD_ERASE_GROUP_START;
end_cmd = MMC_CMD_ERASE_GROUP_END;
}
cmd.cmdidx = start_cmd;
cmd.cmdarg = start;
cmd.resp_type = MMC_RSP_R1;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
goto err_out;
cmd.cmdidx = end_cmd;
cmd.cmdarg = end;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
goto err_out;
cmd.cmdidx = MMC_CMD_ERASE;
cmd.cmdarg = SECURE_ERASE;
cmd.resp_type = MMC_RSP_R1b;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
goto err_out;
return 0;
err_out:
puts("mmc erase failed\n");
return err;
}
static unsigned long
mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
{
int err = 0;
struct mmc *mmc = find_mmc_device(dev_num);
lbaint_t blk = 0, blk_r = 0;
int timeout = 1000;
if (!mmc)
return -1;
if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
printf("\n\nCaution! Your devices Erase group is 0x%x\n"
"The erase range would be change to "
"0x" LBAF "~0x" LBAF "\n\n",
mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
((start + blkcnt + mmc->erase_grp_size)
& ~(mmc->erase_grp_size - 1)) - 1);
while (blk < blkcnt) {
blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
mmc->erase_grp_size : (blkcnt - blk);
err = mmc_erase_t(mmc, start + blk, blk_r);
if (err)
break;
blk += blk_r;
/* Waiting for the ready status */
if (mmc_send_status(mmc, timeout))
return 0;
}
return blk;
}
static ulong
mmc_write_blocks(struct mmc *mmc, lbaint_t start, lbaint_t blkcnt, const void*src)
{
struct mmc_cmd cmd;
struct mmc_data data;
int timeout = 1000;
if ((start + blkcnt) > mmc->block_dev.lba) {
printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
start + blkcnt, mmc->block_dev.lba);
return 0;
}
if (blkcnt == 0)
return 0;
else if (blkcnt == 1)
cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
else
cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
if (mmc->high_capacity)
cmd.cmdarg = start;
else
cmd.cmdarg = start * mmc->write_bl_len;
cmd.resp_type = MMC_RSP_R1;
data.src = src;
data.blocks = blkcnt;
data.blocksize = mmc->write_bl_len;
data.flags = MMC_DATA_WRITE;
if (mmc_send_cmd(mmc, &cmd, &data)) {
printf("mmc write failed\n");
return 0;
}
/* SPI multiblock writes terminate using a special
* token, not a STOP_TRANSMISSION request.
*/
if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_R1b;
if (mmc_send_cmd(mmc, &cmd, NULL)) {
printf("mmc fail to send stop cmd\n");
return 0;
}
}
/* Waiting for the ready status */
if (mmc_send_status(mmc, timeout))
return 0;
return blkcnt;
}
static ulong
mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void*src)
{
lbaint_t cur, blocks_todo = blkcnt;
struct mmc *mmc = find_mmc_device(dev_num);
if (!mmc)
return 0;
if (mmc_set_blocklen(mmc, mmc->write_bl_len))
return 0;
do {
cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
if(mmc_write_blocks(mmc, start, cur, src) != cur)
return 0;
blocks_todo -= cur;
start += cur;
src += cur * mmc->write_bl_len;
} while (blocks_todo > 0);
return blkcnt;
}
static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
lbaint_t blkcnt)
{
@ -385,7 +220,9 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_R1b;
if (mmc_send_cmd(mmc, &cmd, NULL)) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("mmc fail to send stop cmd\n");
#endif
return 0;
}
}
@ -405,8 +242,10 @@ static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
return 0;
if ((start + blkcnt) > mmc->block_dev.lba) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
start + blkcnt, mmc->block_dev.lba);
#endif
return 0;
}
@ -1268,6 +1107,7 @@ static int mmc_startup(struct mmc *mmc)
mmc->block_dev.blksz = mmc->read_bl_len;
mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz);
mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x",
mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
(mmc->cid[3] >> 16) & 0xffff);
@ -1277,6 +1117,11 @@ static int mmc_startup(struct mmc *mmc)
(mmc->cid[2] >> 24) & 0xff);
sprintf(mmc->block_dev.revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
(mmc->cid[2] >> 16) & 0xf);
#else
mmc->block_dev.vendor[0] = 0;
mmc->block_dev.product[0] = 0;
mmc->block_dev.revision[0] = 0;
#endif
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
init_part(&mmc->block_dev);
#endif
@ -1343,7 +1188,9 @@ int mmc_start_init(struct mmc *mmc)
if (mmc_getcd(mmc) == 0) {
mmc->has_init = 0;
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("MMC: no card present\n");
#endif
return NO_CARD_ERR;
}
@ -1378,7 +1225,9 @@ int mmc_start_init(struct mmc *mmc)
err = mmc_send_op_cond(mmc);
if (err && err != IN_PROGRESS) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("Card did not respond to voltage select!\n");
#endif
return UNUSABLE_ERR;
}
}
@ -1434,6 +1283,8 @@ static int __def_mmc_init(bd_t *bis)
int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
void print_mmc_devices(char separator)
{
struct mmc *m;
@ -1451,6 +1302,10 @@ void print_mmc_devices(char separator)
printf("\n");
}
#else
void print_mmc_devices(char separator) { }
#endif
int get_mmc_num(void)
{
return cur_dev_num;

45
drivers/mmc/mmc_private.h Normal file
View File

@ -0,0 +1,45 @@
/*
* Copyright 2008,2010 Freescale Semiconductor, Inc
* Andy Fleming
*
* Based (loosely) on the Linux code
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _MMC_PRIVATE_H_
#define _MMC_PRIVATE_H_
#include <mmc.h>
extern int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data);
extern int mmc_send_status(struct mmc *mmc, int timeout);
extern int mmc_set_blocklen(struct mmc *mmc, int len);
#ifndef CONFIG_SPL_BUILD
extern unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt);
extern ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt,
const void *src);
#else /* CONFIG_SPL_BUILD */
/* SPL will never write or erase, declare dummies to reduce code size. */
static inline unsigned long mmc_berase(int dev_num, lbaint_t start,
lbaint_t blkcnt)
{
return 0;
}
static inline ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt,
const void *src)
{
return 0;
}
#endif /* CONFIG_SPL_BUILD */
#endif /* _MMC_PRIVATE_H_ */

179
drivers/mmc/mmc_write.c Normal file
View File

@ -0,0 +1,179 @@
/*
* Copyright 2008, Freescale Semiconductor, Inc
* Andy Fleming
*
* Based vaguely on the Linux code
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <config.h>
#include <common.h>
#include <part.h>
#include "mmc_private.h"
static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
{
struct mmc_cmd cmd;
ulong end;
int err, start_cmd, end_cmd;
if (mmc->high_capacity) {
end = start + blkcnt - 1;
} else {
end = (start + blkcnt - 1) * mmc->write_bl_len;
start *= mmc->write_bl_len;
}
if (IS_SD(mmc)) {
start_cmd = SD_CMD_ERASE_WR_BLK_START;
end_cmd = SD_CMD_ERASE_WR_BLK_END;
} else {
start_cmd = MMC_CMD_ERASE_GROUP_START;
end_cmd = MMC_CMD_ERASE_GROUP_END;
}
cmd.cmdidx = start_cmd;
cmd.cmdarg = start;
cmd.resp_type = MMC_RSP_R1;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
goto err_out;
cmd.cmdidx = end_cmd;
cmd.cmdarg = end;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
goto err_out;
cmd.cmdidx = MMC_CMD_ERASE;
cmd.cmdarg = SECURE_ERASE;
cmd.resp_type = MMC_RSP_R1b;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
goto err_out;
return 0;
err_out:
puts("mmc erase failed\n");
return err;
}
unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
{
int err = 0;
struct mmc *mmc = find_mmc_device(dev_num);
lbaint_t blk = 0, blk_r = 0;
int timeout = 1000;
if (!mmc)
return -1;
if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
printf("\n\nCaution! Your devices Erase group is 0x%x\n"
"The erase range would be change to "
"0x" LBAF "~0x" LBAF "\n\n",
mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
((start + blkcnt + mmc->erase_grp_size)
& ~(mmc->erase_grp_size - 1)) - 1);
while (blk < blkcnt) {
blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
mmc->erase_grp_size : (blkcnt - blk);
err = mmc_erase_t(mmc, start + blk, blk_r);
if (err)
break;
blk += blk_r;
/* Waiting for the ready status */
if (mmc_send_status(mmc, timeout))
return 0;
}
return blk;
}
static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
lbaint_t blkcnt, const void *src)
{
struct mmc_cmd cmd;
struct mmc_data data;
int timeout = 1000;
if ((start + blkcnt) > mmc->block_dev.lba) {
printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
start + blkcnt, mmc->block_dev.lba);
return 0;
}
if (blkcnt == 0)
return 0;
else if (blkcnt == 1)
cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
else
cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
if (mmc->high_capacity)
cmd.cmdarg = start;
else
cmd.cmdarg = start * mmc->write_bl_len;
cmd.resp_type = MMC_RSP_R1;
data.src = src;
data.blocks = blkcnt;
data.blocksize = mmc->write_bl_len;
data.flags = MMC_DATA_WRITE;
if (mmc_send_cmd(mmc, &cmd, &data)) {
printf("mmc write failed\n");
return 0;
}
/* SPI multiblock writes terminate using a special
* token, not a STOP_TRANSMISSION request.
*/
if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_R1b;
if (mmc_send_cmd(mmc, &cmd, NULL)) {
printf("mmc fail to send stop cmd\n");
return 0;
}
}
/* Waiting for the ready status */
if (mmc_send_status(mmc, timeout))
return 0;
return blkcnt;
}
ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void *src)
{
lbaint_t cur, blocks_todo = blkcnt;
struct mmc *mmc = find_mmc_device(dev_num);
if (!mmc)
return 0;
if (mmc_set_blocklen(mmc, mmc->write_bl_len))
return 0;
do {
cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
if (mmc_write_blocks(mmc, start, cur, src) != cur)
return 0;
blocks_todo -= cur;
start += cur;
src += cur * mmc->write_bl_len;
} while (blocks_todo > 0);
return blkcnt;
}

View File

@ -288,6 +288,30 @@ static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit)
mmc_reg_out(&mmc_base->sysctl, bit, bit);
/*
* CMD(DAT) lines reset procedures are slightly different
* for OMAP3 and OMAP4(AM335x,OMAP5,DRA7xx).
* According to OMAP3 TRM:
* Set SRC(SRD) bit in MMCHS_SYSCTL register to 0x1 and wait until it
* returns to 0x0.
* According to OMAP4(AM335x,OMAP5,DRA7xx) TRMs, CMD(DATA) lines reset
* procedure steps must be as follows:
* 1. Initiate CMD(DAT) line reset by writing 0x1 to SRC(SRD) bit in
* MMCHS_SYSCTL register (SD_SYSCTL for AM335x).
* 2. Poll the SRC(SRD) bit until it is set to 0x1.
* 3. Wait until the SRC (SRD) bit returns to 0x0
* (reset procedure is completed).
*/
#if defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \
defined(CONFIG_AM33XX)
if (!(readl(&mmc_base->sysctl) & bit)) {
start = get_timer(0);
while (!(readl(&mmc_base->sysctl) & bit)) {
if (get_timer(0) - start > MAX_RETRY_MS)
return;
}
}
#endif
start = get_timer(0);
while ((readl(&mmc_base->sysctl) & bit) != 0) {
if (get_timer(0) - start > MAX_RETRY_MS) {
@ -376,6 +400,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
}
writel(cmd->cmdarg, &mmc_base->arg);
udelay(20); /* To fix "No status update" error on eMMC */
writel((cmd->cmdidx << 24) | flags, &mmc_base->cmd);
start = get_timer(0);
@ -480,7 +505,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
unsigned int count;
/*
* Start Polled Read
* Start Polled Write
*/
count = (size > MMCSD_SECTOR_SIZE) ? MMCSD_SECTOR_SIZE : size;
count /= 4;
@ -586,6 +611,8 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
{
struct mmc *mmc = &hsmmc_dev[dev_index];
struct omap_hsmmc_data *priv_data = &hsmmc_dev_data[dev_index];
uint host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
MMC_MODE_HC;
sprintf(mmc->name, "OMAP SD/MMC");
mmc->send_cmd = mmc_send_cmd;
@ -600,11 +627,20 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
#ifdef OMAP_HSMMC2_BASE
case 1:
priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE;
#if (defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \
defined(CONFIG_DRA7XX)) && defined(CONFIG_HSMMC2_8BIT)
/* Enable 8-bit interface for eMMC on OMAP4/5 or DRA7XX */
host_caps_val |= MMC_MODE_8BIT;
#endif
break;
#endif
#ifdef OMAP_HSMMC3_BASE
case 2:
priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE;
#if defined(CONFIG_DRA7XX) && defined(CONFIG_HSMMC3_8BIT)
/* Enable 8-bit interface for eMMC on DRA7XX */
host_caps_val |= MMC_MODE_8BIT;
#endif
break;
#endif
default:
@ -620,8 +656,7 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
mmc->getwp = omap_mmc_getwp;
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
mmc->host_caps = (MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
MMC_MODE_HC) & ~host_caps_mask;
mmc->host_caps = host_caps_val & ~host_caps_mask;
mmc->f_min = 400000;

View File

@ -72,7 +72,7 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width)
host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE |
SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR |
SDHCI_QUIRK_WAIT_SEND_CMD;
SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_USE_WIDE8;
host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
@ -81,6 +81,8 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width)
host->index = index;
host->host_caps = MMC_MODE_HC;
if (bus_width == 8)
host->host_caps |= MMC_MODE_8BIT;
return add_sdhci(host, 52000000, 400000);
}

View File

@ -68,10 +68,9 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
unsigned int stat, rdy, mask, timeout, block = 0;
#ifdef CONFIG_MMC_SDMA
unsigned char ctrl;
ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL);
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
ctrl &= ~SDHCI_CTRL_DMA_MASK;
ctrl |= SDHCI_CTRL_SDMA;
sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL);
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
#endif
timeout = 1000000;
@ -254,7 +253,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
if (clock == 0)
return 0;
if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300) {
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
/* Version 3.00 divisors must be a multiple of 2. */
if (mmc->f_max <= clock)
div = 1;
@ -347,10 +346,11 @@ void sdhci_set_ios(struct mmc *mmc)
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
if (mmc->bus_width == 8) {
ctrl &= ~SDHCI_CTRL_4BITBUS;
if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
if ((SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) ||
(host->quirks & SDHCI_QUIRK_USE_WIDE8))
ctrl |= SDHCI_CTRL_8BITBUS;
} else {
if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
ctrl &= ~SDHCI_CTRL_8BITBUS;
if (mmc->bus_width == 4)
ctrl |= SDHCI_CTRL_4BITBUS;
@ -437,7 +437,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
if (max_clk)
mmc->f_max = max_clk;
else {
if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
mmc->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
>> SDHCI_CLOCK_BASE_SHIFT;
else
@ -452,7 +452,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
if (min_clk)
mmc->f_min = min_clk;
else {
if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_300;
else
mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_200;
@ -470,7 +470,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
mmc->voltages |= host->voltages;
mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300) {
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
if (caps & SDHCI_CAN_DO_8BIT)
mmc->host_caps |= MMC_MODE_8BIT;
}

View File

@ -1015,10 +1015,10 @@ static inline phys_addr_t map_to_sysmem(void *ptr)
* of a function scoped static buffer. It can not be used to create a cache
* line aligned global buffer.
*/
#define PAD_COUNT(s, pad) ((s - 1) / pad + 1)
#define PAD_COUNT(s, pad) (((s) - 1) / (pad) + 1)
#define PAD_SIZE(s, pad) (PAD_COUNT(s, pad) * pad)
#define ALLOC_ALIGN_BUFFER_PAD(type, name, size, align, pad) \
char __##name[ROUND(PAD_SIZE(size * sizeof(type), pad), align) \
char __##name[ROUND(PAD_SIZE((size) * sizeof(type), pad), align) \
+ (align - 1)]; \
\
type *name = (type *) ALIGN((uintptr_t)__##name, align)

View File

@ -335,7 +335,11 @@ int mmc_start_init(struct mmc *mmc);
void mmc_set_preinit(struct mmc *mmc, int preinit);
#ifdef CONFIG_GENERIC_MMC
#ifdef CONFIG_MMC_SPI
#define mmc_host_is_spi(mmc) ((mmc)->host_caps & MMC_MODE_SPI)
#else
#define mmc_host_is_spi(mmc) 0
#endif
struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode);
#else
int mmc_legacy_init(int verbose);

View File

@ -192,6 +192,8 @@
#define SDHCI_SPEC_200 1
#define SDHCI_SPEC_300 2
#define SDHCI_GET_VERSION(x) (x->version & SDHCI_SPEC_VER_MASK)
/*
* End of controller registers.
*/
@ -210,6 +212,7 @@
#define SDHCI_QUIRK_NO_CD (1 << 5)
#define SDHCI_QUIRK_WAIT_SEND_CMD (1 << 6)
#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1 << 7)
#define SDHCI_QUIRK_USE_WIDE8 (1 << 8)
/* to make gcc happy */
struct sdhci_host;