6b5bc77c9b
Stefan thinks they don't add value. Command used: sed -i -e '/file is part of /d' $(git grep "file is part of " |egrep ":( */\*.*\*/\$|#|;#|-- | *\* )" | cut -d: -f1 |grep -v crossgcc |grep -v gcov | grep -v /elf.h |grep -v nvramtool) The exceptions are for: - crossgcc (patch file) - gcov (imported from gcc) - elf.h (imported from GNU's libc) - nvramtool (more complicated header) The removed lines are: - fmt.Fprintln(f, "/* This file is part of the coreboot project. */") -# This file is part of a set of unofficial pre-commit hooks available -/* This file is part of coreboot */ -# This file is part of msrtool. -/* This file is part of msrtool. */ - * This file is part of ncurses, designed to be appended after curses.h.in -/* This file is part of pgtblgen. */ - * This file is part of the coreboot project. - /* This file is part of the coreboot project. */ -# This file is part of the coreboot project. -# This file is part of the coreboot project. -## This file is part of the coreboot project. --- This file is part of the coreboot project. -/* This file is part of the coreboot project */ -/* This file is part of the coreboot project. */ -;## This file is part of the coreboot project. -# This file is part of the coreboot project. It originated in the - * This file is part of the coreinfo project. -## This file is part of the coreinfo project. - * This file is part of the depthcharge project. -/* This file is part of the depthcharge project. */ -/* This file is part of the ectool project. */ - * This file is part of the GNU C Library. - * This file is part of the libpayload project. -## This file is part of the libpayload project. -/* This file is part of the Linux kernel. */ -## This file is part of the superiotool project. -/* This file is part of the superiotool project */ -/* This file is part of uio_usbdebug */ Change-Id: I82d872b3b337388c93d5f5bf704e9ee9e53ab3a9 Signed-off-by: Patrick Georgi <pgeorgi@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/41194 Reviewed-by: HAOUAS Elyes <ehaouas@noos.fr> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
254 lines
5.6 KiB
C
254 lines
5.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* MultiMediaCard (MMC), eMMC and Secure Digital (SD) common initialization
|
|
* code which brings the card into the standby state. This code is controller
|
|
* independent.
|
|
*/
|
|
|
|
#include <commonlib/storage.h>
|
|
#include <delay.h>
|
|
#include <endian.h>
|
|
#include <string.h>
|
|
|
|
#include "mmc.h"
|
|
#include "sd_mmc.h"
|
|
#include "storage.h"
|
|
|
|
uint64_t sd_mmc_extract_uint32_bits(const uint32_t *array, int start, int count)
|
|
{
|
|
int i;
|
|
uint64_t value = 0;
|
|
|
|
for (i = 0; i < count; i++, start++) {
|
|
value <<= 1;
|
|
value |= (array[start / 32] >> (31 - (start % 32))) & 0x1;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
static uint32_t sd_mmc_calculate_transfer_speed(uint32_t csd0)
|
|
{
|
|
uint32_t mult, freq;
|
|
|
|
/* frequency bases, divided by 10 to be nice to platforms without
|
|
* floating point */
|
|
static const int fbase[] = {
|
|
10000,
|
|
100000,
|
|
1000000,
|
|
10000000,
|
|
};
|
|
/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
|
|
* to platforms without floating point. */
|
|
static const int multipliers[] = {
|
|
0, // reserved
|
|
10,
|
|
12,
|
|
13,
|
|
15,
|
|
20,
|
|
25,
|
|
30,
|
|
35,
|
|
40,
|
|
45,
|
|
50,
|
|
55,
|
|
60,
|
|
70,
|
|
80,
|
|
};
|
|
|
|
/* divide frequency by 10, since the mults are 10x bigger */
|
|
freq = fbase[csd0 & 0x7];
|
|
mult = multipliers[(csd0 >> 3) & 0xf];
|
|
return freq * mult;
|
|
}
|
|
|
|
int sd_mmc_go_idle(struct storage_media *media)
|
|
{
|
|
struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
|
|
|
|
// Some cards can't accept idle commands without delay.
|
|
if (ctrlr->mdelay_before_cmd0)
|
|
mdelay(ctrlr->mdelay_before_cmd0);
|
|
|
|
struct mmc_command cmd;
|
|
cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
|
|
cmd.cmdarg = 0;
|
|
cmd.resp_type = CARD_RSP_NONE;
|
|
cmd.flags = 0;
|
|
|
|
int err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
|
|
if (err)
|
|
return err;
|
|
|
|
// Some cards need more than half second to respond to next command (ex,
|
|
// SEND_OP_COND).
|
|
if (ctrlr->mdelay_after_cmd0)
|
|
mdelay(ctrlr->mdelay_after_cmd0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sd_mmc_send_status(struct storage_media *media, ssize_t tries)
|
|
{
|
|
struct mmc_command cmd;
|
|
struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
|
|
|
|
cmd.cmdidx = MMC_CMD_SEND_STATUS;
|
|
cmd.resp_type = CARD_RSP_R1;
|
|
cmd.cmdarg = media->rca << 16;
|
|
cmd.flags = 0;
|
|
|
|
while (tries--) {
|
|
int err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
|
|
if (err)
|
|
return err;
|
|
else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA)
|
|
break;
|
|
else if (cmd.response[0] & MMC_STATUS_MASK) {
|
|
sd_mmc_error("Status Error: %#8.8x\n", cmd.response[0]);
|
|
return CARD_COMM_ERR;
|
|
}
|
|
|
|
udelay(100);
|
|
}
|
|
|
|
sd_mmc_trace("CURR STATE:%d\n",
|
|
(cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9);
|
|
|
|
if (tries < 0) {
|
|
sd_mmc_error("Timeout waiting card ready\n");
|
|
return CARD_TIMEOUT;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int sd_mmc_set_blocklen(struct sd_mmc_ctrlr *ctrlr, int len)
|
|
{
|
|
struct mmc_command cmd;
|
|
cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
|
|
cmd.resp_type = CARD_RSP_R1;
|
|
cmd.cmdarg = len;
|
|
cmd.flags = 0;
|
|
|
|
return ctrlr->send_cmd(ctrlr, &cmd, NULL);
|
|
}
|
|
|
|
int sd_mmc_enter_standby(struct storage_media *media)
|
|
{
|
|
struct mmc_command cmd;
|
|
struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
|
|
int err;
|
|
|
|
SET_BUS_WIDTH(ctrlr, 1);
|
|
SET_CLOCK(ctrlr, 1);
|
|
|
|
/* Reset the Card */
|
|
err = sd_mmc_go_idle(media);
|
|
if (err)
|
|
return err;
|
|
|
|
/* Test for SD version 2 */
|
|
err = CARD_TIMEOUT;
|
|
if (CONFIG(COMMONLIB_STORAGE_SD)) {
|
|
err = sd_send_if_cond(media);
|
|
|
|
/* Get SD card operating condition */
|
|
if (!err)
|
|
err = sd_send_op_cond(media);
|
|
}
|
|
|
|
/* If the command timed out, we check for an MMC card */
|
|
if (CONFIG(COMMONLIB_STORAGE_MMC) && (err == CARD_TIMEOUT)) {
|
|
/* Some cards seem to need this */
|
|
sd_mmc_go_idle(media);
|
|
|
|
err = mmc_send_op_cond(media);
|
|
if (err == CARD_IN_PROGRESS)
|
|
err = mmc_complete_op_cond(media);
|
|
}
|
|
|
|
if (err) {
|
|
sd_mmc_error(
|
|
"Card did not respond to voltage select!\n");
|
|
return CARD_UNUSABLE_ERR;
|
|
}
|
|
|
|
/* Put the Card in Identify Mode */
|
|
cmd.cmdidx = MMC_CMD_ALL_SEND_CID;
|
|
cmd.resp_type = CARD_RSP_R2;
|
|
cmd.cmdarg = 0;
|
|
cmd.flags = 0;
|
|
err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
|
|
if (err)
|
|
return err;
|
|
memcpy(media->cid, cmd.response, sizeof(media->cid));
|
|
|
|
/*
|
|
* For MMC cards, set the Relative Address.
|
|
* For SD cards, get the Relative Address.
|
|
* This also puts the cards into Standby State
|
|
*/
|
|
cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
|
|
cmd.cmdarg = media->rca << 16;
|
|
cmd.resp_type = CARD_RSP_R6;
|
|
cmd.flags = 0;
|
|
err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
|
|
if (err)
|
|
return err;
|
|
if (IS_SD(media))
|
|
media->rca = (cmd.response[0] >> 16) & 0xffff;
|
|
|
|
/* Get the Card-Specific Data */
|
|
cmd.cmdidx = MMC_CMD_SEND_CSD;
|
|
cmd.resp_type = CARD_RSP_R2;
|
|
cmd.cmdarg = media->rca << 16;
|
|
cmd.flags = 0;
|
|
err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
|
|
|
|
/* Waiting for the ready status */
|
|
sd_mmc_send_status(media, SD_MMC_IO_RETRIES);
|
|
if (err)
|
|
return err;
|
|
|
|
memcpy(media->csd, cmd.response, sizeof(media->csd));
|
|
if (media->version == MMC_VERSION_UNKNOWN) {
|
|
int version = sd_mmc_extract_uint32_bits(media->csd, 2, 4);
|
|
switch (version) {
|
|
case 0:
|
|
media->version = MMC_VERSION_1_2;
|
|
break;
|
|
case 1:
|
|
media->version = MMC_VERSION_1_4;
|
|
break;
|
|
case 2:
|
|
media->version = MMC_VERSION_2_2;
|
|
break;
|
|
case 3:
|
|
media->version = MMC_VERSION_3;
|
|
break;
|
|
case 4:
|
|
media->version = MMC_VERSION_4;
|
|
break;
|
|
default:
|
|
media->version = MMC_VERSION_1_2;
|
|
break;
|
|
}
|
|
}
|
|
media->tran_speed = sd_mmc_calculate_transfer_speed(media->csd[0]);
|
|
|
|
/* Determine the read and write block lengths */
|
|
media->read_bl_len = 1 << sd_mmc_extract_uint32_bits(media->csd, 44, 4);
|
|
if (IS_SD(media))
|
|
media->write_bl_len = media->read_bl_len;
|
|
else
|
|
media->write_bl_len =
|
|
1 << sd_mmc_extract_uint32_bits(media->csd, 102, 4);
|
|
|
|
sd_mmc_debug("mmc media info: version=%#x, tran_speed=%d\n",
|
|
media->version, (int)media->tran_speed);
|
|
|
|
return 0;
|
|
}
|