diff options
author | Scott Anderson <saa@android.com> | 2012-03-19 10:33:15 -0700 |
---|---|---|
committer | Scott Anderson <saa@android.com> | 2012-03-19 10:33:15 -0700 |
commit | 7ffaa889ac7e5a0ceab4067f64618704cfb4de39 (patch) | |
tree | 65bf821f96800f79ebf1a02a5b41f6c6e514e8dd | |
parent | f2641088c260b554f9f1f38cafc15fe42402106b (diff) | |
parent | 43b06888a686ffb00dc37ec94e757f0a63d9791d (diff) | |
download | uboot-7ffaa889ac7e5a0ceab4067f64618704cfb4de39.tar.gz |
Merge branch 'android-master' into android-omap-tungsten
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/cmd_mmc_samsung.c | 181 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 113 |
3 files changed, 182 insertions, 113 deletions
diff --git a/common/Makefile b/common/Makefile index ceb8d117c..35e2b7ac5 100644 --- a/common/Makefile +++ b/common/Makefile @@ -127,6 +127,7 @@ COBJS-$(CONFIG_CMD_MII) += cmd_mdio.o endif COBJS-$(CONFIG_CMD_MISC) += cmd_misc.o COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o +COBJS-$(CONFIG_CMD_MMC_SAMSUNG) += cmd_mmc_samsung.o COBJS-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o COBJS-$(CONFIG_MP) += cmd_mp.o COBJS-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o diff --git a/common/cmd_mmc_samsung.c b/common/cmd_mmc_samsung.c new file mode 100644 index 000000000..4fe677590 --- /dev/null +++ b/common/cmd_mmc_samsung.c @@ -0,0 +1,181 @@ +/* + * (C) Copyright 2011-2012 Google, Inc. + * + * 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 <config.h> +#include <common.h> +#include <command.h> +#include <mmc.h> +#include <malloc.h> + +static int oem_cmd(struct mmc *mmc, uint mode) +{ + struct mmc_cmd cmd; + int ret; + + cmd.cmdidx = 62; /* Samsung OEM command */ + cmd.cmdarg = 0xEFAC62EC; /* Magic value */ + cmd.resp_type = MMC_RSP_R1b; + cmd.flags = 0; + ret = mmc->send_cmd(mmc, &cmd, NULL); + if (ret) { + printf("%s: Error %d sending magic.\n", __func__, ret); + return 1; + } + cmd.cmdarg = mode; + ret = mmc->send_cmd(mmc, &cmd, NULL); + if (ret) { + printf("%s: Error %d sending mode 0x%08X.\n", + __func__, ret, mode); + return 1; + } + return 0; +} + + +static int read_smart(struct mmc *mmc, uint32_t *dst) +{ + struct mmc_cmd cmd; + struct mmc_data data; + int ret; + + cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1; + cmd.flags = 0; + + data.dest = (char *)dst; + data.blocks = 1; + data.blocksize = mmc->read_bl_len; + data.flags = MMC_DATA_READ; + + ret = mmc->send_cmd(mmc, &cmd, &data); + if (ret) { + printf("%s: Error %d reading.\n", __func__, ret); + return 1; + } + return 0; +} + +static int get_smart(struct mmc *mmc, uint32_t *data) +{ + int ret; + /* Enter Smart Report Mode */ + ret = oem_cmd(mmc, 0x0000CCEE) || read_smart(mmc, data); + + /* Exit Smart Report Mode */ + ret = oem_cmd(mmc, 0x00DECCEE) || ret; + + return ret; +} + +static int print_smart(struct mmc *mmc, uint32_t *data) +{ + int i; + uint32_t val; + + if (get_smart(mmc, data)) + return 1; + + val = le32_to_cpup(data); + switch (val) { + case 0xD2D2D2D2: + printf(" Error Mode: Normal\n"); + break; + case 0x5C5C5C5C: + printf(" Error Mode: RuntimeFatalError\n"); + break; + case 0xE1E1E1E1: + printf(" Error Mode: MetaBrokenError\n"); + break; + case 0x37373737: + printf("The Error Mode is OpenFatalError; no valid data.\n"); + return 1; /* Fatal */ + default: + printf("Error Mode: Unknown (0x%08X)\n", val); + return 1; /* Fatal */ + } + printf(" Super Block Size: %d bytes\n", le32_to_cpup(data + 1)); + printf(" Super Page Size: %d bytes\n", le32_to_cpup(data + 2)); + printf("Optimal Write Size: %d bytes\n", le32_to_cpup(data + 3)); + printf("Read Reclaim Count: %d\n", le32_to_cpup(data + 20)); + printf(" Optimal Trim Size: %d\n", le32_to_cpup(data + 21)); + printf(" Number of Banks: %d\n", le32_to_cpup(data + 4)); + printf("========== Bad Blocks ===========\n"); + printf("Bank Initial Runtime Remaining\n"); + for (i = 0; i < 4; i++) + printf("%4d %7d %7d %9d\n", i, + le32_to_cpup(data + 5 + i * 3), + le32_to_cpup(data + 6 + i * 3), + le32_to_cpup(data + 7 + i * 3)); + printf("========== Erase Count ==========\n"); + printf(" Min Avg Max\n"); + printf(" All %7d %7d %7d\n", le32_to_cpup(data + 18), + le32_to_cpup(data + 19), + le32_to_cpup(data + 17)); + printf(" SLC %7d %7d %7d\n", le32_to_cpup(data + 31), + le32_to_cpup(data + 32), + le32_to_cpup(data + 30)); + printf(" MLC %7d %7d %7d\n", le32_to_cpup(data + 34), + le32_to_cpup(data + 35), + le32_to_cpup(data + 33)); + return 0; +} + +static int do_samsung_smart(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + struct mmc *mmc; + int i, ret; + char *ep; + uint32_t *data = NULL; + + if (argc != 2) + return cmd_usage(cmdtp); + i = simple_strtoul(argv[1], &ep, 10); + if (ep == argv[1] || *ep != '\0') { + printf("'%s' is not a number\n", argv[1]); + return cmd_usage(cmdtp); + } + + mmc = find_mmc_device(i); + if (!mmc) { + printf("no mmc device at slot %x\n", i); + return 1; + } + + /* Allocate space for the report to be read in to. */ + data = malloc(mmc->read_bl_len); + if (!data) { + printf("%s: Error allocating SMART buffer.\n", __func__); + return 1; + } + + ret = print_smart(mmc, data); + + free(data); + + return ret != 0; +} +U_BOOT_CMD(samsung_smart, 2, 1, do_samsung_smart, + "list the Samsung e-MMC Smart Report data", + "" +); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index af6fa9664..946ef6b5d 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1300,116 +1300,3 @@ int mmc_initialize(bd_t *bis) return 0; } - -#if defined(CONFIG_MMC_SAMSUNG_SMART) && !defined(CONFIG_SPL_BUILD) -static int do_samsung_smart(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - struct mmc *mmc; - struct mmc_cmd cmd; - int i, ret, read_ret; - char *ep; - uint32_t val, data[512 / 4]; - - if (argc != 2) - return cmd_usage(cmdtp); - i = simple_strtoul(argv[1], &ep, 10); - if (ep == argv[1] || *ep != '\0') { - printf("'%s' is not a number\n", argv[1]); - return cmd_usage(cmdtp); - } - - mmc = find_mmc_device(i); - if (!mmc) { - printf("no mmc device at slot %x\n", i); - return 1; - } - - cmd.cmdidx = 62; - cmd.resp_type = MMC_RSP_R1b; - cmd.flags = 0; - - /* Enter Smart Report Mode */ - cmd.cmdarg = 0xEFAC62EC; - ret = mmc_send_cmd(mmc, &cmd, NULL); - if (ret) { - printf("Error 1:%d entering Smart Report mode.\n", ret); - return 1; - } - cmd.cmdarg = 0x0000CCEE; - ret = mmc_send_cmd(mmc, &cmd, NULL); - if (ret) { - printf("Error 2:%d entering Smart Report mode.\n", ret); - return 1; - } - - /* Fetch the Smart Report */ - read_ret = mmc_read_blocks(mmc, data, 0, 1); - - /* Exit Smart Report Mode */ - cmd.cmdarg = 0xEFAC62EC; - ret = mmc_send_cmd(mmc, &cmd, NULL); - if (ret) - printf("Error 1:%d exiting Smart Report mode.\n", ret); - else { - cmd.cmdarg = 0x00DECCEE; - ret = mmc_send_cmd(mmc, &cmd, NULL); - if (ret) - printf("Error 2:%d exiting Smart Report mode.\n", ret); - } - - if (read_ret != 1) { - printf("Smart Report could not be read.\n"); - return 1; - } - - val = le32_to_cpup(data); - switch (val) { - case 0xD2D2D2D2: - printf(" Error Mode: Normal\n"); - break; - case 0x5C5C5C5C: - printf(" Error Mode: RuntimeFatalError\n"); - break; - case 0xE1E1E1E1: - printf(" Error Mode: MetaBrokenError\n"); - break; - case 0x37373737: - printf("The Error Mode is OpenFatalError; no valid data.\n"); - return 1; /* Fatal */ - default: - printf("Error Mode: Unknown (0x%08X)\n", val); - return 1; /* Fatal */ - } - printf(" Super Block Size: %d bytes\n", le32_to_cpup(data + 1)); - printf(" Super Page Size: %d bytes\n", le32_to_cpup(data + 2)); - printf("Optimal Write Size: %d bytes\n", le32_to_cpup(data + 3)); - printf("Read Reclaim Count: %d\n", le32_to_cpup(data + 20)); - printf(" Optimal Trim Size: %d\n", le32_to_cpup(data + 21)); - printf(" Number of Banks: %d\n", le32_to_cpup(data + 4)); - printf("========== Bad Blocks ===========\n"); - printf("Bank Initial Runtime Remaining\n"); - for (i = 0; i < 4; i++) - printf("%4d %7d %7d %9d\n", i, - le32_to_cpup(data + 5 + i * 3), - le32_to_cpup(data + 6 + i * 3), - le32_to_cpup(data + 7 + i * 3)); - printf("========== Erase Count ==========\n"); - printf(" Min Avg Max\n"); - printf(" All %7d %7d %7d\n", le32_to_cpup(data + 18), - le32_to_cpup(data + 19), - le32_to_cpup(data + 17)); - printf(" SLC %7d %7d %7d\n", le32_to_cpup(data + 31), - le32_to_cpup(data + 32), - le32_to_cpup(data + 30)); - printf(" MLC %7d %7d %7d\n", le32_to_cpup(data + 34), - le32_to_cpup(data + 35), - le32_to_cpup(data + 33)); - - return ret != 0; -} -U_BOOT_CMD(samsung_smart, 2, 1, do_samsung_smart, - "list the Samsung e-MMC Smart Report data", - "" -); -#endif /* CONFIG_MMC_SAMSUNG_SMART && !CONFIG_SPL_BUILD */ |