From efde98be6744f152889078e0e0775f8fd8d0080b Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Fri, 25 Jan 2013 18:16:36 +0100 Subject: [PATCH] zynq: mmc: Support the sdhci instead of zynq_mmc This patch provides a support to use the generic sdhci interface for zynq soc, hence removed the the existing zynq_mmc. Signed-off-by: Jagannadha Sutradharudu Teki --- arch/arm/include/asm/arch-zynq/mmc.h | 16 +- drivers/mmc/Makefile | 2 +- drivers/mmc/zynq_mmc.c | 473 --------------------------- drivers/mmc/zynq_mmc.h | 111 ------- drivers/mmc/zynq_sdhci.c | 38 +++ include/configs/zynq_common.h | 3 +- 6 files changed, 56 insertions(+), 587 deletions(-) delete mode 100644 drivers/mmc/zynq_mmc.c delete mode 100644 drivers/mmc/zynq_mmc.h create mode 100644 drivers/mmc/zynq_sdhci.c diff --git a/arch/arm/include/asm/arch-zynq/mmc.h b/arch/arm/include/asm/arch-zynq/mmc.h index 8a70ae3af07..18dd036d3c2 100644 --- a/arch/arm/include/asm/arch-zynq/mmc.h +++ b/arch/arm/include/asm/arch-zynq/mmc.h @@ -20,4 +20,18 @@ * MA 02111-1307 USA */ -extern int zynq_mmc_init(bd_t *bd); +#ifndef __ASM_ARCH_MMC_H_ +#define __ASM_ARCH_MMC_H_ + +#include + +int zynq_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk); + +static inline int zynq_mmc_init(bd_t *bd) +{ + u32 regbase = (u32) SD_BASEADDR; + + return zynq_sdhci_init(regbase, 52000000, 52000000 >> 9); +} + +#endif /* __ASM_ARCH_MMC_H_ */ diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 54a492c1345..692a2f79173 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -46,9 +46,9 @@ COBJS-$(CONFIG_SDHCI) += sdhci.o COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o -COBJS-$(CONFIG_ZYNQ_MMC) += zynq_mmc.o COBJS-$(CONFIG_DWMMC) += dw_mmc.o COBJS-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o +COBJS-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/mmc/zynq_mmc.c b/drivers/mmc/zynq_mmc.c deleted file mode 100644 index 22074b3fd5d..00000000000 --- a/drivers/mmc/zynq_mmc.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * (C) Copyright 2012 Xilinx - * - * Zynq SD Host Controller Interface - * - * 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. - * - * 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 - -#include "zynq_mmc.h" - -static u32 *sd_dma_buffer; - -/* Data Memory Barrier */ -#define dmb() __asm__ __volatile__ ("dmb" : : : "memory") -#define SYNCHRONIZE_IO dmb() - -static void sd_out32(u32 OutAddress, u32 Value) -{ - OutAddress += SD_BASEADDR; - *(volatile u32 *) OutAddress = Value; - SYNCHRONIZE_IO; -} -static void sd_out16(u32 OutAddress, u16 Value) -{ - OutAddress += SD_BASEADDR; - *(volatile u16 *) OutAddress = Value; - SYNCHRONIZE_IO; -} -static void sd_out8(u32 OutAddress, u8 Value) -{ - OutAddress += SD_BASEADDR; - *(volatile u8 *) OutAddress = Value; - SYNCHRONIZE_IO; -} - -static u32 sd_in32(u32 InAddress) -{ - SYNCHRONIZE_IO; - InAddress += SD_BASEADDR; - return *(volatile u32 *) InAddress; -} -static u16 sd_in16(u32 InAddress) -{ - SYNCHRONIZE_IO; - InAddress += SD_BASEADDR; - return *(volatile u16 *) InAddress; -} -static u8 sd_in8(u32 InAddress) -{ - SYNCHRONIZE_IO; - InAddress += SD_BASEADDR; - return *(volatile u8 *) InAddress; -} - -static void connect_test_mode(void) -{ - volatile unsigned statusreg; - - /* Fake out the card detect since it is also NAND CS */ - sd_out8(SD_HOST_CTRL_R, SD_CD_TEST | SD_CD_TEST_INS); - - /* Wait for card detected */ - statusreg = sd_in32(SD_PRES_STATE_R); - while ((!(statusreg & SD_CARD_DPL)) - || (!(statusreg & SD_CARD_DB)) - || (!(statusreg & SD_CARD_INS))) - statusreg = sd_in32(SD_PRES_STATE_R); -} - -/* Initialize the SD controller */ -static void init_port(void) -{ - unsigned clk; - - /* Power off the card */ - sd_out8(SD_PWR_CTRL_R, 0); - - /* Disable interrupts */ - sd_out32(SD_SIG_ENA_R, 0); - - /* Perform soft reset */ - sd_out8(SD_SOFT_RST_R, SD_RST_ALL); - /* Wait for reset to comlete */ - while (sd_in8(SD_SOFT_RST_R)) { - ; - } - - /* Power on the card */ - sd_out8(SD_PWR_CTRL_R, SD_POWER_33|SD_POWER_ON); - - connect_test_mode(); - - /* Enable Internal clock and wait for it to stablilize */ - clk = (0x4 << SD_DIV_SHIFT) | SD_CLK_INT_EN; - sd_out16(SD_CLK_CTL_R, clk); - do { - clk = sd_in16(SD_CLK_CTL_R); - } while (!(clk & SD_CLK_INT_STABLE)); - - /* Enable SD clock */ - clk |= SD_CLK_SD_EN; - sd_out16(SD_CLK_CTL_R, clk); - - sd_out32(SD_SIG_ENA_R, 0xFFFFFFFF); - sd_out32(SD_INT_ENA_R, 0xFFFFFFFF); -} - -/* MMC/SD command (SPI mode) */ -#define CMD0 (0) /* GO_IDLE_STATE */ -#define CMD1 (1) /* SEND_OP_COND */ -#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */ -#define CMD2 (2) /* SEND_CID */ -#define CMD3 (3) /* RELATIVE_ADDR */ -#define CMD5 (5) /* SLEEP_WAKE (SDC) */ -#define CMD6 (6) /* APP_SET_BUS_WIDTH */ -#define CMD7 (7) /* SELECT */ -#define CMD8 (8) /* SEND_IF_COND */ -#define CMD9 (9) /* SEND_CSD */ -#define CMD10 (10) /* SEND_CID */ -#define CMD12 (12) /* STOP_TRANSMISSION */ -#define CMD13 (13) /* SEND_STATUS */ -#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */ -#define CMD16 (16) /* SET_BLOCKLEN */ -#define CMD17 (17) /* READ_SINGLE_BLOCK */ -#define CMD18 (18) /* READ_MULTIPLE_BLOCK */ -#define CMD23 (23) /* SET_BLOCK_COUNT */ -#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */ -#define CMD24 (24) /* WRITE_BLOCK */ -#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */ -#define CMD41 (41) /* SEND_OP_COND (ACMD) */ -#define CMD51 (51) /* SEND_SCR (ACMD) */ -#define CMD52 (52) /* */ -#define CMD55 (55) /* APP_CMD */ -#define CMD58 (58) /* READ_OCR */ - -/* make_command: - * Determing the proper value for the command register for the indicated - * command index. - */ -static int make_command(unsigned cmd) -{ - unsigned retval; - - retval = cmd << 8; - -#define RSP_NONE SD_CMD_RESP_NONE -#define RSP_R1 (SD_CMD_INDEX | SD_CMD_RESP_48 | SD_CMD_CRC) -#define RSP_R1b (SD_CMD_INDEX | SD_CMD_RESP_48_BUSY | SD_CMD_CRC) -#define RSP_R2 (SD_CMD_CRC | SD_CMD_RESP_136) -#define RSP_R3 (SD_CMD_RESP_48) -#define RSP_R6 (SD_CMD_INDEX | SD_CMD_RESP_48_BUSY | SD_CMD_CRC) - - switch(cmd) { - case CMD0: - retval |= (SD_CMD_RESP_NONE); - break; - case CMD1: - retval |= RSP_R3; - break; - case CMD2: - retval |= RSP_R2; - break; - case CMD3: - retval |= RSP_R6; - break; - case CMD5: - retval |= RSP_R1b; - break; - case CMD6: - retval |= RSP_R1; - break; - case CMD7: - retval |= RSP_R1; - break; - case CMD8: - retval |= RSP_R1; - break; - case CMD9: - retval |= RSP_R2; - break; - case CMD10: - case CMD12: - case CMD13: - case ACMD13: - case CMD16: - case CMD23: - retval |= RSP_R1; - break; - case CMD17: - case CMD18: - retval |= RSP_R1|SD_CMD_DATA; - break; - case ACMD23: - case CMD24: - case CMD25: - case CMD41: - retval |= RSP_R3; - break; - case CMD51: - retval |= RSP_R1 | SD_CMD_DATA; - break; - case CMD52: - case CMD55: - retval |= RSP_R1; - break; - case CMD58: - break; - default: - printf("Unknown command CMD%d\n", cmd); - break; - } - - return retval; -} - -static int zynq_sdh_request(struct mmc *mmc, struct mmc_cmd *cmd, - struct mmc_data *data) -{ - u32 status; - u16 cmdreg; - u16 modereg; - int result = 0, i; - - debug("zynq_sdh_request: cmdidx: %d arg: 0x%x\n", - cmd->cmdidx, cmd->cmdarg); - - cmd->response[0] = 0; - cmdreg = make_command(cmd->cmdidx); - - /* append the data if the command is SWITCH_FUNC */ - if (data && (data->flags & MMC_DATA_READ) && (cmd->cmdidx == 6)) - cmdreg |= SD_CMD_DATA; - - /* Wait until the device is willing to accept commands */ - do { - status = sd_in32(SD_PRES_STATE_R); - } while (status & (SD_CMD_INHIBIT|SD_DATA_INHIBIT)); - - /* - * Set the DMA address to the DMA buffer. - * This is only relevant for data commands. - * u-boot performs a copy rather than DMA directly into the user - * buffer because the controller can't DMA into the first 512K - * of DDR. - */ - debug("data->dest = %p (%d) (%d * %d)\n", data->dest, - (cmdreg & SD_CMD_DATA) ? data->blocks : 0, data->blocks, - data->blocksize); - -#ifdef CONFIG_ZYNQ_SD_DIRECT_DMA - /* - * Added based on above comment. - * No evidence in the TRM supports this that I could find, though - */ - if (data->dest < 0x80000) { - printf("Cannot DMA to lowest 512k of DDR\n"); - return COMM_ERR; - } - sd_out32(SD_DMA_ADDR_R, (u32)data->dest); -#else - if ((cmdreg & SD_CMD_DATA) && data->blocksize * data->blocks > 512) { - printf("MMC driver buffer too small\n"); - return COMM_ERR; - } - sd_out32(SD_DMA_ADDR_R, (u32)sd_dma_buffer); -#endif - - /* - * 512 bytes - * This is only relevant for data commands. - */ - if (cmdreg & SD_CMD_DATA) { - sd_out16(SD_BLOCK_SZ_R, data->blocksize); - sd_out16(SD_BLOCK_CNT_R, data->blocks); - } - - sd_out8(SD_TIMEOUT_CTL_R, 0xA); - - sd_out32(SD_ARG_R, cmd->cmdarg); - - /* - * Set the transfer mode to read, simple DMA, single block - * (applicable only to data commands) - * This is all that this software supports. - */ - modereg = SD_TRNS_BLK_CNT_EN | SD_TRNS_READ | SD_TRNS_DMA; - if (data->blocks > 1) - modereg |= SD_TRNS_MULTI; - sd_out16(SD_TRNS_MODE_R, modereg); - - /* Clear all pending interrupt status */ - sd_out32(SD_INT_STAT_R, 0xFFFFFFFF); - - /* Initiate the command */ - sd_out16(SD_CMD_R, cmdreg); - - /* Poll until operation complete */ - while (1) { - status = sd_in32(SD_INT_STAT_R); - if (status & SD_INT_ERROR) { -#ifdef DEBUG - printf("send_cmd: Error: (0x%08x) cmd: %d arg: 0x%x\n", - status, cmd->cmdidx, cmd->cmdarg); -#else - if (cmd->cmdidx == CMD17) { - printf("MMC: Error reading sector %d (0x%08x)\n", - cmd->cmdarg, cmd->cmdarg); - } -#endif - sd_out8(SD_SOFT_RST_R, - SD_RST_CMD|SD_RST_DATA); - - if (status & (SD_INT_ERR_CTIMEOUT|SD_INT_ERR_DTIMEOUT)) { - result = TIMEOUT; - goto exit; - } else { - result = COMM_ERR; - goto exit; - } - } - if (status & SD_INT_CMD_CMPL) { - if (cmdreg & SD_CMD_DATA) { - if (status & (SD_INT_DMA | SD_INT_TRNS_CMPL)) { - break; - } - } else { - break; - } - } - } - - if (cmd->resp_type & MMC_RSP_PRESENT) { - if (cmd->resp_type & MMC_RSP_136) { - /* CRC is stripped so we need to do some shifting */ - /* response type 2 */ - for (i = 0; i < 4; i++) { - cmd->response[i] = - sd_in32(SD_RSP_R + (3-i) * 4) << 8; - debug("CMD%d cmd->response[%d] = %d\n", - cmd->cmdidx, i, cmd->response[i]); - if (i != 3) { - cmd->response[i] |= - sd_in8((SD_RSP_R + (3-i)*4)-1); - } - } - } else { - /* response type 1, 1b, 3, 6 */ - cmd->response[0] = sd_in32(SD_RSP_R); - debug("CMD%d cmd->response[0] = %d\n", - cmd->cmdidx, cmd->response[0]); - } - } - -#ifndef CONFIG_ZYNQ_SD_DIRECT_DMA - if (cmdreg & SD_CMD_DATA) { - memcpy(data->dest, sd_dma_buffer, - data->blocks * data->blocksize); - } -#endif - -exit: - /* Clear all pending interrupt status */ - sd_out32(SD_INT_STAT_R, 0xFFFFFFFF); - - return result; -} - -static void zynq_sdh_set_ios(struct mmc *mmc) -{ - u16 clk, sdhci_clkctrl; - - debug("%s: voltages: 0x%x clock: 0x%x bus_width: 0x%x\n", - __func__, mmc->voltages, mmc->clock, mmc->bus_width); - - sdhci_clkctrl = sd_in16(SD_HOST_CTRL_R); - - /* Configure the clock 50MHz system REFF clock*/ - if (mmc->clock) { - u32 div; - - for (div = 1; div < 256; div *= 2) { - if ((SD_REFF_CLK_50M / div) <= mmc->clock) - break; - } - div >>= 1; - - /* Disable SD clock and internal clock */ - clk = sd_in16(SD_CLK_CTL_R); - clk &= ~(SD_CLK_SD_EN|SD_CLK_INT_EN); - sd_out16(SD_CLK_CTL_R, clk); - - /* Enable Internal clock and wait for it to stablilize */ - clk = (div << SD_DIV_SHIFT) | SD_CLK_INT_EN; - sd_out16(SD_CLK_CTL_R, clk); - do { - clk = sd_in16(SD_CLK_CTL_R); - } while (!(clk & SD_CLK_INT_STABLE)); - - /* Enable SD clock */ - clk |= SD_CLK_SD_EN; - sd_out16(SD_CLK_CTL_R, clk); - - if (!div) - /* Enable high speed mode in controller */ - sdhci_clkctrl |= SD_HOST_HS; - else - sdhci_clkctrl &= ~SD_HOST_HS; - } - - /* Configure the bus_width */ - if (mmc->bus_width == 4) - sdhci_clkctrl |= SD_HOST_4BIT; - else if (mmc->bus_width == 1) - sdhci_clkctrl &= ~SD_HOST_4BIT; - else - printf("Invalid bus_width\n"); - - sd_out16(SD_HOST_CTRL_R, sdhci_clkctrl); -} - -static int zynq_sdh_init(struct mmc *mmc) -{ - debug(" zynq_sdh_init called\n"); - init_port(); - return 0; -} - -int zynq_mmc_init(bd_t *bd) -{ - struct mmc *mmc; - - sd_dma_buffer = malloc(512); - if (!sd_dma_buffer) { - return -ENOMEM; - } - - mmc = malloc(sizeof(struct mmc)); - if (!mmc) { - return -ENOMEM; - } - sprintf(mmc->name, "SDHCI"); - mmc->send_cmd = zynq_sdh_request; - mmc->set_ios = zynq_sdh_set_ios; - mmc->init = zynq_sdh_init; - - mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz; - - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - - mmc->f_max = 52000000; - mmc->f_min = mmc->f_max >> 9; - - mmc->block_dev.part_type = PART_TYPE_DOS; - - mmc_register(mmc); - - return 0; -} - diff --git a/drivers/mmc/zynq_mmc.h b/drivers/mmc/zynq_mmc.h deleted file mode 100644 index dd14dcb15b5..00000000000 --- a/drivers/mmc/zynq_mmc.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * (C) Copyright 2012 Xilinx - * - * Zynq SD Host Controller Interface - * Controller register and bit definitions - * - * 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. - * - * 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 __SDHCI_MMC_H_ -#define __SDHCI_MMC_H_ - -#define SD_DMA_ADDR_R 0x00 - -#define SD_BLOCK_SZ_R 0x04 - -#define SD_BLOCK_CNT_R 0x06 - -#define SD_ARG_R 0x08 - -#define SD_TRNS_MODE_R 0x0C -#define SD_TRNS_DMA 0x01 -#define SD_TRNS_BLK_CNT_EN 0x02 -#define SD_TRNS_ACMD12 0x04 -#define SD_TRNS_READ 0x10 -#define SD_TRNS_MULTI 0x20 - -#define SD_CMD_R 0x0E -#define SD_CMD_RESP_NONE 0x00 -#define SD_CMD_RESP_136 0x01 -#define SD_CMD_RESP_48 0x02 -#define SD_CMD_RESP_48_BUSY 0x03 -#define SD_CMD_CRC 0x08 -#define SD_CMD_INDEX 0x10 -#define SD_CMD_DATA 0x20 - -#define SD_RSP_R 0x10 - -#define SD_BUFF_R 0x20 - -#define SD_PRES_STATE_R 0x24 -#define SD_CMD_INHIBIT 0x00000001 -#define SD_DATA_INHIBIT 0x00000002 -#define SD_WRITE_ACTIVE 0x00000100 -#define SD_READ_ACTIVE 0x00000200 -#define SD_CARD_INS 0x00010000 -#define SD_CARD_DB 0x00020000 -#define SD_CARD_DPL 0x00040000 -#define SD_CARD_WP 0x00080000 - -#define SD_HOST_CTRL_R 0x28 -#define SD_HOST_4BIT 0x02 -#define SD_CD_TEST_INS 0x40 -#define SD_CD_TEST 0x80 - -#define SD_PWR_CTRL_R 0x29 -#define SD_POWER_ON 0x01 -#define SD_POWER_18 0x0A -#define SD_POWER_30 0x0C -#define SD_POWER_33 0x0E - -#define SD_BLCK_GAP_CTL_R 0x2A - -#define SD_WAKE_CTL_R 0x2B - -#define SD_CLK_CTL_R 0x2C -#define SD_DIV_SHIFT 8 -#define SD_CLK_SD_EN 0x0004 -#define SD_CLK_INT_STABLE 0x0002 -#define SD_CLK_INT_EN 0x0001 - -#define SD_REFF_CLK_50M 50000000 -#define SD_HOST_HS 0x4 - -#define SD_TIMEOUT_CTL_R 0x2E - -#define SD_SOFT_RST_R 0x2F -#define SD_RST_ALL 0x01 -#define SD_RST_CMD 0x02 -#define SD_RST_DATA 0x04 - -#define SD_INT_STAT_R 0x30 -#define SD_INT_ENA_R 0x34 -#define SD_SIG_ENA_R 0x38 -#define SD_INT_CMD_CMPL 0x00000001 -#define SD_INT_TRNS_CMPL 0x00000002 -#define SD_INT_DMA 0x00000008 -#define SD_INT_ERROR 0x00008000 -#define SD_INT_ERR_CTIMEOUT 0x00010000 -#define SD_INT_ERR_CCRC 0x00020000 -#define SD_INT_ERR_CEB 0x00040000 -#define SD_INT_ERR_IDX 0x00080000 -#define SD_INT_ERR_DTIMEOUT 0x00100000 -#define SD_INT_ERR_DCRC 0x00200000 -#define SD_INT_ERR_DEB 0x00400000 -#define SD_INT_ERR_CLMT 0x00800000 -#define SD_INT_ERR_ACMD12 0x01000000 -#define SD_INT_ERR_ADMA 0x02000000 -#define SD_INT_ERR_TRESP 0x10000000 - -#define SD_CAPABILITIES_R 0x40 - -#endif /* __SDHCI_MMC_H_ */ diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c new file mode 100644 index 00000000000..761a8596e21 --- /dev/null +++ b/drivers/mmc/zynq_sdhci.c @@ -0,0 +1,38 @@ +/* + * (C) Copyright 2013 Inc. + * + * Xilinx Zynq SD Host Controller Interface + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * 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 + +int zynq_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk) +{ + struct sdhci_host *host = NULL; + + host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host)); + if (!host) { + printf("zynq_sdhci_init: sdhci_host malloc fail\n"); + return 1; + } + + host->name = "zynq_sdhci"; + host->ioaddr = (void *) regbase; + host->quirks = SDHCI_QUIRK_NO_CD; + host->version = sdhci_readw(host, SDHCI_HOST_VERSION); + + add_sdhci(host, max_clk, min_clk); + return 0; +} diff --git a/include/configs/zynq_common.h b/include/configs/zynq_common.h index f55e6d7fbac..2a4e014edf6 100644 --- a/include/configs/zynq_common.h +++ b/include/configs/zynq_common.h @@ -130,7 +130,8 @@ /* MMC */ #ifdef CONFIG_MMC # define CONFIG_GENERIC_MMC -# define CONFIG_ZYNQ_MMC +# define CONFIG_SDHCI +# define CONFIG_ZYNQ_SDHCI # define CONFIG_CMD_MMC # define CONFIG_CMD_FAT # define CONFIG_CMD_EXT2 -- 2.47.3