diff --git a/arch/arm/include/asm/arch-mtk/gpio.h b/arch/arm/include/asm/arch-mtk/gpio.h new file mode 100644 index 000000000..c7d98ebf3 --- /dev/null +++ b/arch/arm/include/asm/arch-mtk/gpio.h @@ -0,0 +1,146 @@ +/* + * (C) 2010 by Tieto + * Krzysztof Antonowicz + * + * All Rights Reserved + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef __MTK_GPIO_H_ +#define __MTK_GPIO_H_ + +/* GPIOs register definitions */ +#define MTK_GPIO_DIR1 (MTK_GPIO_BASE + 0x0000) +#define MTK_GPIO_DIR2 (MTK_GPIO_BASE + 0x0040) +#define MTK_GPIO_DIR3 (MTK_GPIO_BASE + 0x0080) +#define MTK_GPIO_DIR4 (MTK_GPIO_BASE + 0x00C0) +#define MTK_GPIO_DIR5 (MTK_GPIO_BASE + 0x0100) + +#define MTK_GPIO_PULLEN1 (MTK_GPIO_BASE + 0x0200) +#define MTK_GPIO_PULLEN2 (MTK_GPIO_BASE + 0x0240) +#define MTK_GPIO_PULLEN3 (MTK_GPIO_BASE + 0x0280) +#define MTK_GPIO_PULLEN4 (MTK_GPIO_BASE + 0x02C0) +#define MTK_GPIO_PULLEN5 (MTK_GPIO_BASE + 0x0300) + +#define MTK_GPIO_PULLSELL1 (MTK_GPIO_BASE + 0x0400) +#define MTK_GPIO_PULLSELL2 (MTK_GPIO_BASE + 0x0440) +#define MTK_GPIO_PULLSELL3 (MTK_GPIO_BASE + 0x0480) +#define MTK_GPIO_PULLSELL4 (MTK_GPIO_BASE + 0x04C0) +#define MTK_GPIO_PULLSELL5 (MTK_GPIO_BASE + 0x0500) + +#define MTK_GPIO_DINV1 (MTK_GPIO_BASE + 0x0600) +#define MTK_GPIO_DINV2 (MTK_GPIO_BASE + 0x0640) +#define MTK_GPIO_DINV3 (MTK_GPIO_BASE + 0x0680) +#define MTK_GPIO_DINV4 (MTK_GPIO_BASE + 0x06C0) +#define MTK_GPIO_DINV5 (MTK_GPIO_BASE + 0x0700) + +#define MTK_GPIO_DOUT1 (MTK_GPIO_BASE + 0x0800) +#define MTK_GPIO_DOUT2 (MTK_GPIO_BASE + 0x0840) +#define MTK_GPIO_DOUT3 (MTK_GPIO_BASE + 0x0880) +#define MTK_GPIO_DOUT4 (MTK_GPIO_BASE + 0x08C0) +#define MTK_GPIO_DOUT5 (MTK_GPIO_BASE + 0x0900) + +#define MTK_GPIO_DIN1 (MTK_GPIO_BASE + 0x0A00) +#define MTK_GPIO_DIN2 (MTK_GPIO_BASE + 0x0A40) +#define MTK_GPIO_DIN3 (MTK_GPIO_BASE + 0x0A80) +#define MTK_GPIO_DIN4 (MTK_GPIO_BASE + 0x0AC0) +#define MTK_GPIO_DIN5 (MTK_GPIO_BASE + 0x0B00) + +#define MTK_GPIO_MODE1 (MTK_GPIO_BASE + 0x1000) +#define MTK_GPIO_MODE2 (MTK_GPIO_BASE + 0x1100) +#define MTK_GPIO_MODE3 (MTK_GPIO_BASE + 0x1200) +#define MTK_GPIO_MODE4 (MTK_GPIO_BASE + 0x1300) +#define MTK_GPIO_MODE5 (MTK_GPIO_BASE + 0x1400) +#define MTK_GPIO_MODE6 (MTK_GPIO_BASE + 0x1500) +#define MTK_GPIO_MODE7 (MTK_GPIO_BASE + 0x1600) +#define MTK_GPIO_MODE8 (MTK_GPIO_BASE + 0x1700) +#define MTK_GPIO_MODE9 (MTK_GPIO_BASE + 0x1800) +#define MTK_GPIO_MODEA (MTK_GPIO_BASE + 0x1900) + +#define MTK_GPIO_CLK_OUT1 (MTK_GPIO_BASE + 0x3000) +#define MTK_GPIO_CLK_OUT2 (MTK_GPIO_BASE + 0x3100) +#define MTK_GPIO_CLK_OUT3 (MTK_GPIO_BASE + 0x3200) +#define MTK_GPIO_CLK_OUT4 (MTK_GPIO_BASE + 0x3300) +#define MTK_GPIO_CLK_OUT5 (MTK_GPIO_BASE + 0x3400) +#define MTK_GPIO_CLK_OUT6 (MTK_GPIO_BASE + 0x3500) +#define MTK_GPIO_CLK_OUT7 (MTK_GPIO_BASE + 0x3600) +#define MTK_GPIO_CLK_OUT8 (MTK_GPIO_BASE + 0x3700) +#define MTK_GPIO_CLK_OUT9 (MTK_GPIO_BASE + 0x3800) +#define MTK_GPIO_CLK_OUT10 (MTK_GPIO_BASE + 0x3900) + +/* MTK_GPIO_MODE_9 bit field definitions */ +#define MTK_GPIO_MODE9_GPIO64 0 +#define MTK_GPIO_MODE9_GPIO64_ALT1 1 +#define MTK_GPIO_MODE9_GPIO64_ALT2 2 +#define MTK_GPIO_MODE9_GPIO64_ALT3 3 + +#define MTK_GPIO_MODE9_GPIO65 (0 << 2) +#define MTK_GPIO_MODE9_GPIO65_ALT1 (1 << 2) +#define MTK_GPIO_MODE9_GPIO65_ALT2 (2 << 2) +#define MTK_GPIO_MODE9_GPIO65_ALT3 (3 << 2) + +#define MTK_GPIO_MODE9_GPIO66 (0 << 4) +#define MTK_GPIO_MODE9_GPIO66_ALT1 (1 << 4) +#define MTK_GPIO_MODE9_GPIO66_ALT2 (2 << 4) +#define MTK_GPIO_MODE9_GPIO66_ALT3 (3 << 4) + +#define MTK_GPIO_MODE9_GPIO67 (0 << 6) +#define MTK_GPIO_MODE9_GPIO67_ALT1 (1 << 6) +#define MTK_GPIO_MODE9_GPIO67_ALT2 (2 << 6) +#define MTK_GPIO_MODE9_GPIO67_ALT3 (3 << 6) + +#define MTK_GPIO_MODE9_GPIO68 (0 << 8) +#define MTK_GPIO_MODE9_GPIO68_ALT1 (1 << 8) +#define MTK_GPIO_MODE9_GPIO68_ALT2 (2 << 8) +#define MTK_GPIO_MODE9_GPIO68_ALT3 (3 << 8) + +#define MTK_GPIO_MODE9_GPIO69 (0 << 10) +#define MTK_GPIO_MODE9_GPIO69_ALT1 (1 << 10) +#define MTK_GPIO_MODE9_GPIO69_ALT2 (2 << 10) +#define MTK_GPIO_MODE9_GPIO69_ALT3 (3 << 10) + +#define MTK_GPIO_MODE9_GPIO70 (0 << 12) +#define MTK_GPIO_MODE9_GPIO70_ALT1 (1 << 12) +#define MTK_GPIO_MODE9_GPIO70_ALT2 (2 << 12) +#define MTK_GPIO_MODE9_GPIO70_ALT3 (3 << 12) + +#define MTK_GPIO_MODE9_GPIO71 (0 << 14) +#define MTK_GPIO_MODE9_GPIO71_ALT1 (1 << 14) +#define MTK_GPIO_MODE9_GPIO71_ALT2 (2 << 14) +#define MTK_GPIO_MODE9_GPIO71_ALT3 (3 << 14) + +#define MTK_GPIO_MODEA_GPIO72 0 +#define MTK_GPIO_MODEA_GPIO72_ALT1 1 +#define MTK_GPIO_MODEA_GPIO72_ALT2 2 +#define MTK_GPIO_MODEA_GPIO72_ALT3 3 + +#define MTK_GPIO_MODEA_GPIO73 (0 << 2) +#define MTK_GPIO_MODEA_GPIO73_ALT1 (1 << 2) +#define MTK_GPIO_MODEA_GPIO73_ALT2 (2 << 2) +#define MTK_GPIO_MODEA_GPIO73_ALT3 (3 << 2) + +#define MTK_GPIO_MODEA_GPIO74 (0 << 4) +#define MTK_GPIO_MODEA_GPIO74_ALT1 (1 << 4) +#define MTK_GPIO_MODEA_GPIO74_ALT2 (2 << 4) +#define MTK_GPIO_MODEA_GPIO74_ALT3 (3 << 4) + +#define MTK_GPIO_MODEA_GPIO75 (0 << 6) +#define MTK_GPIO_MODEA_GPIO75_ALT1 (1 << 6) +#define MTK_GPIO_MODEA_GPIO75_ALT2 (2 << 6) +#define MTK_GPIO_MODEA_GPIO75_ALT3 (3 << 6) + +#endif diff --git a/arch/arm/include/asm/arch-mtk/mmc.h b/arch/arm/include/asm/arch-mtk/mmc.h new file mode 100644 index 000000000..fa520f278 --- /dev/null +++ b/arch/arm/include/asm/arch-mtk/mmc.h @@ -0,0 +1,28 @@ +/* + * (C) 2010 by Tieto + * Krzysztof Antonowicz + * + * All Rights Reserved + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef __ASM_ARCH_MMC_H +#define __ASM_ARCH_MMC_H + +int mtk_mmc_init(void *regs); + +#endif /* __ASM_ARCH_MMC_H */ diff --git a/arch/arm/include/asm/arch-mtk/mtk_msdc.h b/arch/arm/include/asm/arch-mtk/mtk_msdc.h new file mode 100644 index 000000000..d588088c1 --- /dev/null +++ b/arch/arm/include/asm/arch-mtk/mtk_msdc.h @@ -0,0 +1,205 @@ +/* + * (C) 2010 by Tieto + * Krzysztof Antonowicz + * + * All Rights Reserved + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef MTK_MSDC_H +#define MTK_MSDC_H + +/* + * Register definitions + */ + +/* MS/SD Memory Card Controller Configuration Register */ +#define MTK_MSDC_CFG (MTK_MSDC_BASE + 0x0000) + +/* MS/SD Memory Card Controller Status Register MSDC_STA */ +#define MTK_MSDC_STA (MTK_MSDC_BASE + 0x0004) + +/* MS/SD Memory Card Controller Interrupt Register MSDC_INT */ +#define MTK_MSDC_INT (MTK_MSDC_BASE + 0x0008) + +/* MS/SD Memory Card Controller Data Register MSDC_DAT */ +#define MTK_MSDC_DAT (MTK_MSDC_BASE + 0x000C) + +/* MS/SD Memory Card Pin Status Register MSDC_PS */ +#define MTK_MSDC_PS (MTK_MSDC_BASE + 0x0010) + +/* MS/SD Memory Card Controller IO Control Register MSDC_IOCON */ +#define MTK_MSDC_IOCON (MTK_MSDC_BASE + 0x0014) + +/* SD Memory Card Controller Configuration Register SDC_CFG */ +#define MTK_MSDC_SDC_CFG (MTK_MSDC_BASE + 0x0020) + +/* SD Memory Card Controller Command Register SDC_CMD */ +#define MTK_MSDC_SDC_CMD (MTK_MSDC_BASE + 0x0024) + +/* SD Memory Card Controller Argument Register SDC_ARG */ +#define MTK_MSDC_SDC_ARG (MTK_MSDC_BASE + 0x0028) + +/* SD Memory Card Controller Status Register SDC_STA */ +#define MTK_MSDC_SDC_STA (MTK_MSDC_BASE + 0x002C) + +/* SD Memory Card Controller Response Register 0 SDC_RESP0 */ +#define MTK_MSDC_SDC_RESP0 (MTK_MSDC_BASE + 0x0030) + +/* SD Memory Card Controller Response Register 1 SDC_RESP1 */ +#define MTK_MSDC_SDC_RESP1 (MTK_MSDC_BASE + 0x0034) + +/* SD Memory Card Controller Response Register 2 SDC_RESP2 */ +#define MTK_MSDC_SDC_RESP2 (MTK_MSDC_BASE + 0x0038) + +/* SD Memory Card Controller Response Register 3 SDC_RESP3 */ +#define MTK_MSDC_SDC_RESP3 (MTK_MSDC_BASE + 0x003C) + +/* SD Memory Card Controller Command Status Register SDC_CMDSTA */ +#define MTK_MSDC_SDC_CMDSTA (MTK_MSDC_BASE + 0x0040) + +/* SD Memory Card Controller Data Status Register SDC_DATSTA */ +#define MTK_MSDC_SDC_DATSTA (MTK_MSDC_BASE + 0x0044) + +/* SD Memory Card Status Register SDC_CSTA */ +#define MTK_MSDC_SDC_CSTA (MTK_MSDC_BASE + 0x0048) + +/* SD Memory Card IRQ Mask Register 0 SDC_IRQMASK0 */ +#define MTK_MSDC_SDC_IRQMASK0 (MTK_MSDC_BASE + 0x004C) + +/* SD Memory Card IRQ Mask Register 1 SDC_IRQMASK1 */ +#define MTK_MSDC_SDC_IRQMASK1 (MTK_MSDC_BASE + 0x0050) + +/* SDIO Configuration Register SDIO_CFG */ +#define MTK_MSDC_SDIO_CFG (MTK_MSDC_BASE + 0x0054) + +/* SDIO Status Register SDIO_STA */ +#define MTK_MSDC_SDIO_STA (MTK_MSDC_BASE + 0x0058) + +/* Memory Stick Controller Configuration Register MSC_CFG */ +#define MTK_MSDC_MSC_CFG (MTK_MSDC_BASE + 0x0060) + +/* Memory Stick Controller Command Register MSC_CMD */ +#define MTK_MSDC_MSC_CMD (MTK_MSDC_BASE + 0x0064) + +/* Memory Stick Controller Auto Command Register MSC_ACMD */ +#define MTK_MSDC_MSC_ACMD (MTK_MSDC_BASE + 0x0068) + +/* Memory Stick Controller Status Register MSC_STA */ +#define MTK_MSDC_MSC_STA (MTK_MSDC_BASE + 0x006C) + + +/* MSDC_CFG bit field definitions */ +#define MTK_MSDC_CFG_MSDC (1 << 0) +#define MTK_MSDC_CFG_NOCRC (1 << 2) +#define MTK_MSDC_CFG_RST (1 << 3) +#define MTK_MSDC_CFG_CLKSRC (1 << 4) +#define MTK_MSDC_CFG_STDBY (1 << 5) +#define MTK_MSDC_CFG_RED (1 << 6) +#define MTK_MSDC_CFG_SCLKON (1 << 7) +#define MTK_MSDC_CFG_SCLKF 8 +#define MTK_MSDC_CFG_SCLKF_MASK (0xFF << MTK_MSDC_CFG_SCLKF) +#define MTK_MSDC_CFG_INTEN (1 << 16) +#define MTK_MSDC_CFG_DMAEN (1 << 17) +#define MTK_MSDC_CFG_PINEN (1 << 18) +#define MTK_MSDC_CFG_DIRQEN (1 << 19) +#define MTK_MSDC_CFG_RCDEN (1 << 20) +#define MTK_MSDC_CFG_VDDP (1 << 21) + +/* MSDC_SDC_CFG bit field definitions */ +#define MTK_MSDC_SDC_CFG_SIEN (1 << 16) +#define MTK_MSDC_SDC_CFG_MDLEN (1 << 17) +#define MTK_MSDC_SDC_CFG_MDLW8 (1 << 18) +#define MTK_MSDC_SDC_CFG_SDIO (1 << 19) +#define MTK_MSDC_SDC_CFG_BSYDLY 12 + +#define MTK_MSDC_SDC_CFG_BLKLEN_MASK 0x00000FFF + +/* MSDC_SDC_CMD bit field definitions */ +#define MTK_MSDC_SDC_CMD_BREAK (1 << 6) +#define MTK_MSDC_SDC_CMD_RSPTYP 7 +#define MTK_MSDC_SDC_CMD_RSPTYP_MASK (7 << MTK_MSDC_SDC_CMD_RSPTYP) +#define MTK_MSDC_SDC_CMD_IDRT (1 << 10) + +#define MTK_MSDC_SDC_CMD_DTYPE 11 +#define MTK_MSDC_SDC_CMD_DTYPE_MASK (3 << MTK_MSDC_SDC_CMD_DTYPE) +#define MTK_MSDC_SDC_CMD_RW (1 << 13) +#define MTK_MSDC_SDC_CMD_STOP (1 << 14) +#define MTK_MSDC_SDC_CMD_INTC (1 << 15) +#define MTK_MSDC_SDC_CMD_CMDFAIL (1 << 16) + +#define MTK_MSDC_SDC_CMD_CMD_MASK 0x0000003F + +#define MTK_MSDC_SDC_CMD_DTYPE_NO_DATA 0 +#define MTK_MSDC_SDC_CMD_DTYPE_SINGLE_BLOCK 1 +#define MTK_MSDC_SDC_CMD_DTYPE_MULTI_BLOCK 2 +#define MTK_MSDC_SDC_CMD_DTYPE_MULTI_STREAM 3 + +#define MTK_MSDC_SDC_CMD_RSPTYP_NONE 0 +#define MTK_MSDC_SDC_CMD_RSPTYP_R1 1 +#define MTK_MSDC_SDC_CMD_RSPTYP_R2 2 +#define MTK_MSDC_SDC_CMD_RSPTYP_R3 3 +#define MTK_MSDC_SDC_CMD_RSPTYP_R4 4 +#define MTK_MSDC_SDC_CMD_RSPTYP_R5 5 +#define MTK_MSDC_SDC_CMD_RSPTYP_R6 6 +#define MTK_MSDC_SDC_CMD_RSPTYP_R1B 7 + + +/* Possible values of PRCFG0 field - MTK_MSDC_CFG register. */ +#define MTK_MSDC_CFG_PRCFG0_PU_DS_PD_DS (0 << 22) +#define MTK_MSDC_CFG_PRCFG0_PU_DS_PD_EN (1 << 22) +#define MTK_MSDC_CFG_PRCFG0_PU_EN_PD_DS (2 << 22) +#define MTK_MSDC_CFG_PRCFG0_KEEPER (3 << 22) + +/* MSDC_PS bit field definitions */ +#define MTK_MSDC_PS_CDEN (1 << 0) +#define MTK_MSDC_PS_PIEN0 (1 << 1) +#define MTK_MSDC_PS_POEN0 (1 << 2) +#define MTK_MSDC_PS_PIN0 (1 << 3) +#define MTK_MSDC_PS_PINCHG (1 << 4) +#define MTK_MSDC_PS_CMD (1 << 24) + +/* MSDC_STA bit field definitions */ +#define MTK_MSDC_STA_BF (1 << 0) +#define MTK_MSDC_STA_BE (1 << 1) +#define MTK_MSDC_STA_DRQ (1 << 2) +#define MTK_MSDC_STA_INT (1 << 3) +#define MTK_MSDC_STA_FIFOCLR (1 << 14) +#define MTK_MSDC_STA_BUSY (1 << 15) +#define MTK_MSDC_STA_FIFOCNT 4 +#define MTK_MSDC_STA_FIFOCNT_MASK 0x00F0 + +/* MSDC_SDC_CMDSTA bit field definitions */ +#define MTK_MSDC_SDC_CMDSTA_CMDRDY (1 << 0) +#define MTK_MSDC_SDC_CMDSTA_CMDTO (1 << 1) +#define MTK_MSDC_SDC_CMDSTA_RSPCRCERR (1 << 2) +#define MTK_MSDC_SDC_CMDSTA_MMCIRQ (1 << 3) + +/* MSDC_SDC_DATSTA bit field definitions */ +#define MTK_MSDC_SDC_DATSTA_BLKDONE (1 << 0) +#define MTK_MSDC_SDC_DATSTA_DATTO (1 << 1) +#define MTK_MSDC_SDC_DATSTA_DATCRCERR (1 << 2) + +/* MSDC_SDC_STA bit field definitions */ +#define MTK_MSDC_SDC_STA_SDCBUSY (1 << 0) +#define MTK_MSDC_SDC_STA_CMDBUSY (1 << 1) +#define MTK_MSDC_SDC_STA_DATBUSY (1 << 2) +#define MTK_MSDC_SDC_STA_RSV (1 << 3) +#define MTK_MSDC_SDC_STA_R1BS (1 << 4) +#define MTK_MSDC_SDC_STA_WP (1 << 15) + +#endif /* MTK_MSDC_H */ diff --git a/board/mtk/sciphone_g2/sciphone_g2.c b/board/mtk/sciphone_g2/sciphone_g2.c index eccbed43a..c4917b3f6 100644 --- a/board/mtk/sciphone_g2/sciphone_g2.c +++ b/board/mtk/sciphone_g2/sciphone_g2.c @@ -24,6 +24,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -117,3 +118,15 @@ int dram_init(void) #endif return 0; } + +#ifdef CONFIG_GENERIC_MMC + +int board_mmc_init(bd_t *bis) +{ + +#ifdef CONFIG_MTK_MMC + return mtk_mmc_init(0); +#endif + +} +#endif diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 3496f0aa0..1de1f50e5 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -36,6 +36,7 @@ COBJS-$(CONFIG_OMAP3_MMC) += omap3_mmc.o COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o COBJS-$(CONFIG_S5P_MMC) += s5p_mmc.o +COBJS-$(CONFIG_MTK_MMC) += mtk_msdc_mmc.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/mmc/mtk_msdc_mmc.c b/drivers/mmc/mtk_msdc_mmc.c new file mode 100644 index 000000000..8f6b621b7 --- /dev/null +++ b/drivers/mmc/mtk_msdc_mmc.c @@ -0,0 +1,833 @@ +/* + * (C) 2010 by Tieto + * Krzysztof Antonowicz + * + * All Rights Reserved + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MIN_SCLK_VALUE 0 +#define MAX_SCLK_VALUE 255 +/* According to documentation MCU is 104 MHz or 52 MHz. */ +#define MCU_CLK_FREQ_HZ 104000000 +#define MAX_SLAVE_FREQ_HZ 26000000 +#define MAX_BLOCK_SIZE 2048 +#define COMMAND_STATUS_READ_DELAY_US 10 +#define POLL_TRANSFER_COND_TIMEOUT_US 500 +#define POLL_CMD_STATUS_TIMEOUT_US 100 +#define DATA_READ_TIMEOUT_US 500 + +#define DEBUG_LINE() do { \ + debug("mtk_msdc_mmc[%s]: called.\n", __func__); \ + } while (0) + +#define DEBUG_MSG(fmt, arg...) do { \ + debug("mtk_msdc_mmc[%s]: " fmt "\n", __func__, ##arg); \ + } while (0) + +#define ERROR(fmt, arg...) do { \ + printf("mtk_msdc_mmc[%s] ERROR: " fmt "\n", __func__, ##arg); \ + } while (0) + +struct mmc_host { + struct mmc *mmc; + u32 clock; + u32 msdc_sdc_cmd; + struct mmc_cmd *cmd; + struct mmc_data *data; +}; + +static struct mmc_host mmc_host; + +#ifdef MTK_MMC_CARD_DETECTION_SUPPORTED + +/* Card detection mechanism is not supported by Sci-phone G2 hardware: + * 1. missing RCDEN resistor on PCB, + * 2. grounded MCINS(GPIO75) pin. + * + * Checks if memory card is present according to the algorithm: + * 1. Pull up CD/DAT3 (INS) pin. + * 2. Enable card detection and input pin at the same time. + * 3. Turn on power for memory card. + * 4. Detect insertion of memory card. + */ +static int check_card_presence(struct mmc_host *mmc_host) +{ + int retval = -ENODEV; + + DEBUG_LINE(); + + writel(readl(MTK_MSDC_CFG) | MTK_MSDC_CFG_PRCFG0_PU_EN_PD_DS, + MTK_MSDC_CFG); + + writel(readl(MTK_MSDC_PS) | MTK_MSDC_PS_CDEN | MTK_MSDC_PS_PIEN0, + MTK_MSDC_PS); + + /* Turn on the power for memory card. */ + writel(readl(MTK_MSDC_CFG) | MTK_MSDC_CFG_VDDP, MTK_MSDC_CFG); + + /* Check if a card is inserted. */ + + if (readl(MTK_MSDC_PS) & MTK_MSDC_PS_PINCHG) + retval = 0; + + return retval; +} + +#endif /* MTK_MMC_CARD_DETECTION_SUPPORTED */ + +/* + * Power up MSDC controller. + */ +static void mtk_power_up(void) +{ + DEBUG_LINE(); + /* Disable power down control for MSDC module. */ + writew(PDN_CON1_MSDC, MTK_CONFG_PDN_CLR1); +} + +/* + * Performs software and synchronous reset of MSDC controller. + */ +static void mtk_software_reset(void) +{ + DEBUG_LINE(); + + writel(MTK_MSDC_CFG_RST, MTK_MSDC_CFG); +} + +/* + * Configures GPIOs for MSDC controller. + */ +static void mtk_configure_gpios(void) +{ + DEBUG_LINE(); + + u16 mode_9_clear_mask = + MTK_GPIO_MODE9_GPIO67_ALT3 | + MTK_GPIO_MODE9_GPIO68_ALT3 | + MTK_GPIO_MODE9_GPIO69_ALT3 | + MTK_GPIO_MODE9_GPIO70_ALT3 | + MTK_GPIO_MODE9_GPIO71_ALT3; + + u16 mode_9_set_mask = + MTK_GPIO_MODE9_GPIO67_ALT1 | + MTK_GPIO_MODE9_GPIO68_ALT1 | + MTK_GPIO_MODE9_GPIO69_ALT1 | + MTK_GPIO_MODE9_GPIO70_ALT1 | + MTK_GPIO_MODE9_GPIO71_ALT1; + + u16 mode_a_clear_mask = + MTK_GPIO_MODEA_GPIO72_ALT3 | + /* GPIO73 skipped (used by USB as regular GPIO) */ + MTK_GPIO_MODEA_GPIO74_ALT3 | + MTK_GPIO_MODEA_GPIO75_ALT3; + + u16 mode_a_set_mask = + MTK_GPIO_MODEA_GPIO72_ALT1 | + /* GPIO73 skipped (used by USB as regular GPIO) */ + MTK_GPIO_MODEA_GPIO74_ALT1 | + MTK_GPIO_MODEA_GPIO75_ALT1; + + writew((readw(MTK_GPIO_MODE9) & (~mode_9_clear_mask)) | + mode_9_set_mask, MTK_GPIO_MODE9); + + writew((readw(MTK_GPIO_MODEA) & (~mode_a_clear_mask)) | + mode_a_set_mask, MTK_GPIO_MODEA); +} + +/* + * Initialization of MMC/SD controller. + */ +static int mtk_init(struct mmc *mmc) +{ + DEBUG_LINE(); + + (void)mmc; + + mtk_configure_gpios(); + mtk_power_up(); + mtk_software_reset(); + + /* Configure the controller as the host of SD/MMC cards. */ + writel(readl(MTK_MSDC_CFG) | MTK_MSDC_CFG_MSDC, MTK_MSDC_CFG); + + /* Use MCU clock as source clock of memory card. */ + writel(readl(MTK_MSDC_CFG) & (~MTK_MSDC_CFG_CLKSRC), MTK_MSDC_CFG); + + /* Clear FIFO. */ + writew(readl(MTK_MSDC_STA) | MTK_MSDC_STA_FIFOCLR, MTK_MSDC_STA); + + return 0; +} + +/* + * Calculates slave frequency for the given sclk value. + */ +static u32 mtk_calculate_f_slave(const u8 sclk) +{ + u32 f_slave = 0; + + if (!sclk) + f_slave = MCU_CLK_FREQ_HZ / 2; + else + f_slave = MCU_CLK_FREQ_HZ / (4 * sclk); + + return f_slave; +} + +/* + * Calculates max. slave frequency. + */ +static u32 mtk_calculate_f_slave_max(void) +{ + u32 f_slave_max = 0; + + f_slave_max = mtk_calculate_f_slave(MIN_SCLK_VALUE); + + return f_slave_max; +} + +/* + * Calculates min. slave frequency. + */ +static u32 mtk_calculate_f_slave_min(void) +{ + u32 f_slave_min = 0; + + f_slave_min = mtk_calculate_f_slave(MAX_SCLK_VALUE); + + return f_slave_min; +} + +/* + * Configures clock for MSDC. + */ +static void mtk_set_clk_rate(struct mmc_host *mmc_host, const u32 f_slave) +{ + u32 f_host; + u8 sclk; + u32 calc_f_slave; + u32 min_f_slave; + u32 max_f_slave; + + DEBUG_LINE(); + DEBUG_MSG("Requested new slave frequency: %dHz.", f_slave); + + f_host = MCU_CLK_FREQ_HZ; + + max_f_slave = mtk_calculate_f_slave_max(); + min_f_slave = mtk_calculate_f_slave_min(); + + if (max_f_slave < f_slave) { + + DEBUG_MSG("Requested slave frequency is too high: %dHz! " + "The max. available is: %dHz", f_slave, max_f_slave); + + sclk = MIN_SCLK_VALUE; + + } else if (min_f_slave > f_slave) { + + DEBUG_MSG("Requested slave frequency is too low: %dHz! " + "The min. available is: %dHz", f_slave, min_f_slave); + + sclk = MAX_SCLK_VALUE; + + } else if (((f_host / 2) == f_slave) || (f_host < (f_slave * 4))) { + + sclk = MIN_SCLK_VALUE; + } else + sclk = f_host / (4 * f_slave); + + calc_f_slave = mtk_calculate_f_slave(sclk); + + /* If the calculated frequency is still too high, + it should be decreased. */ + while (calc_f_slave > f_slave) { + + sclk++; + DEBUG_MSG("Requested frequency out of range, it will " + "be decreased!"); + calc_f_slave = mtk_calculate_f_slave(sclk); + } + + DEBUG_MSG("f_host: %dHz, calc_f_slave: %dHz(f_slave: %dHz), " + "SCLK: %d.", f_host, calc_f_slave, f_slave, sclk); + + writel((readl(MTK_MSDC_CFG) & (~MTK_MSDC_CFG_SCLKF_MASK)) | sclk << 8, + MTK_MSDC_CFG); +} + +/* + * Perform configuration related settings for MMC host. + */ +static void mtk_set_ios(struct mmc *mmc) +{ + struct mmc_host *mmc_host = mmc->priv; + + DEBUG_LINE(); + + /* 4 -bit data line enable/disable. */ + if (4 == mmc->bus_width) + writel(readl(MTK_MSDC_SDC_CFG) | MTK_MSDC_SDC_CFG_MDLEN, + MTK_MSDC_SDC_CFG); + else + writel(readl(MTK_MSDC_SDC_CFG) & (~MTK_MSDC_SDC_CFG_MDLEN), + MTK_MSDC_SDC_CFG); + + if (mmc->clock && (mmc_host->clock != mmc->clock)) { + + /* Before changing the frequency of serial clock on the bus, + it is necessary to disable serial interface + of the controller. */ + writel(readl(MTK_MSDC_SDC_CFG) & (~MTK_MSDC_SDC_CFG_SIEN), + MTK_MSDC_SDC_CFG); + + mtk_set_clk_rate(mmc_host, mmc->clock); + + writel(readl(MTK_MSDC_SDC_CFG) | MTK_MSDC_SDC_CFG_SIEN, + MTK_MSDC_SDC_CFG); + + DEBUG_MSG("Serial clock rate changed. The clock is enabled."); + + mmc_host->clock = mmc->clock; + } +} + +/* + * Configures controller for the given data type. + */ +static int mtk_setup_data(struct mmc_host *mmc_host, u32 *msdc_sdc_cmd) +{ + u32 no_of_blocks = mmc_host->data->blocks; + u32 block_size = mmc_host->data->blocksize; + + DEBUG_LINE(); + + /* Read/write command selection. */ + if (mmc_host->data->flags & MMC_DATA_WRITE) + *msdc_sdc_cmd |= MTK_MSDC_SDC_CMD_RW; + else + *msdc_sdc_cmd &= ~MTK_MSDC_SDC_CMD_RW; + + if (MAX_BLOCK_SIZE < block_size) + DEBUG_MSG("Block size excceeds max. block length!"); + else { + /* Write length of block. */ + writel((readl(MTK_MSDC_SDC_CFG) & + (~MTK_MSDC_SDC_CFG_BLKLEN_MASK)) | block_size, + MTK_MSDC_SDC_CFG); + + DEBUG_MSG("Block size is: %d.", block_size); + } + + DEBUG_MSG("Number of blocks: %d", no_of_blocks); + + if (1 == no_of_blocks) { + *msdc_sdc_cmd |= (MTK_MSDC_SDC_CMD_DTYPE_SINGLE_BLOCK << + MTK_MSDC_SDC_CMD_DTYPE); + } else if (1 < no_of_blocks) { + *msdc_sdc_cmd |= (MTK_MSDC_SDC_CMD_DTYPE_MULTI_BLOCK << + MTK_MSDC_SDC_CMD_DTYPE); + } else { + DEBUG_MSG("Data supplied but block count is 0!"); + return -EINVAL; + } + + /* Clear FIFO. */ + writew(readl(MTK_MSDC_STA) | MTK_MSDC_STA_FIFOCLR, MTK_MSDC_STA); + + return 0; +} + +/* + * Configures controller for the given command type. + */ +static int mtk_setup_cmd(struct mmc_host *mmc_host, + struct mmc_cmd *cmd, u32 *msdc_sdc_cmd) +{ + u32 response_type; + + DEBUG_LINE(); + DEBUG_MSG("CMD ID: %d, CMD ARG: 0x%.8x, CMD RESP TYPE: %d", + cmd->cmdidx, cmd->cmdarg, cmd->resp_type); + + /* Choose response type. */ + switch (cmd->resp_type) { + + case MMC_RSP_R1: + /* R1 response token is 48-bit. */ + response_type = MTK_MSDC_SDC_CMD_RSPTYP_R1; + break; + case MMC_RSP_R1b: + response_type = MTK_MSDC_SDC_CMD_RSPTYP_R1B; + break; + case MMC_RSP_R2: + /* R2 response token is 136-bit. */ + response_type = MTK_MSDC_SDC_CMD_RSPTYP_R2; + break; + case MMC_RSP_R3: + /* R3 response token is 48-bit, no CRC */ + response_type = MTK_MSDC_SDC_CMD_RSPTYP_R3; + break; +#if 0 + case MMC_RSP_R4: + /* R4 response token is 48-bit. (Only for MMC) */ + response_type = MTK_MSDC_SDC_CMD_RSPTYP_R4; + break; + case MMC_RSP_R5: + /* R5 response token is 48-bit. (Only for MMC) */ + response_type = MTK_MSDC_SDC_CMD_RSPTYP_R5; + break; + case MMC_RSP_R6: + /* R6 response token is 48-bit.*/ + response_type = MTK_MSDC_SDC_CMD_RSPTYP_R6; + break; +#endif + case MMC_RSP_NONE: + response_type = MTK_MSDC_SDC_CMD_RSPTYP_NONE; + break; + default: + ERROR("Unexpected response type!"); + return -EINVAL; + } + + *msdc_sdc_cmd |= response_type << MTK_MSDC_SDC_CMD_RSPTYP; + + /* Store the command argument first! */ + writel(cmd->cmdarg, MTK_MSDC_SDC_ARG); + /* ..then the command id. */ + *msdc_sdc_cmd |= cmd->cmdidx; + + if (MMC_CMD_STOP_TRANSMISSION == cmd->cmdidx) { + *msdc_sdc_cmd |= MTK_MSDC_SDC_CMD_STOP; + writel(readl(MTK_MSDC_SDC_CFG) | 16 << MTK_MSDC_SDC_CFG_BSYDLY, + MTK_MSDC_SDC_CFG); + } else + *msdc_sdc_cmd &= ~MTK_MSDC_SDC_CMD_STOP; + + return 0; +} + +/* + * Read SD/MMC Memory Card bus response. + */ +static void mtk_read_response(struct mmc_host *mmc_host) +{ + u32 resp0; + u32 resp1; + u32 resp2; + u32 resp3; + + DEBUG_LINE(); + + if (!mmc_host->cmd) + return; + + /* Check if a response is expected and read it. + For response of type R2 only bit 127 to 0 of response token is stored + in the register field SDC_RESP0, SDC_RESP1, SDC_RESP2 and SDC_RESP3. + For response of other types, only bit 39 to 8 of response token + is stored in the register field SDC_RESP0. */ + + if (mmc_host->cmd->resp_type & MMC_RSP_PRESENT) { + + resp0 = readl(MTK_MSDC_SDC_RESP0); + + if (mmc_host->cmd->resp_type & MMC_RSP_136) { + + resp1 = readl(MTK_MSDC_SDC_RESP1); + resp2 = readl(MTK_MSDC_SDC_RESP2); + resp3 = readl(MTK_MSDC_SDC_RESP3); + + mmc_host->cmd->response[0] = resp3; + mmc_host->cmd->response[1] = resp2; + mmc_host->cmd->response[2] = resp1; + mmc_host->cmd->response[3] = resp0; + + DEBUG_MSG("Response[0]: 0x%.8x", + mmc_host->cmd->response[0]); + DEBUG_MSG("Response[1]: 0x%.8x", + mmc_host->cmd->response[1]); + DEBUG_MSG("Response[2]: 0x%.8x", + mmc_host->cmd->response[2]); + DEBUG_MSG("Response[3]: 0x%.8x", + mmc_host->cmd->response[3]); + } else { + mmc_host->cmd->response[0] = resp0; + + DEBUG_MSG("Response[0]: 0x%.8x", + mmc_host->cmd->response[0]); + } + } +} + +/* + * Checks if reading FIFO is possible. + */ +static int mtk_poll_data_transfer_conditions(const u16 transfer_condition) +{ + int retval = 0; + u16 msdc_sdc_datsta; + u32 timeout_counter = 0; + + DEBUG_LINE(); + + do { + /* First of all check data status. */ + msdc_sdc_datsta = readw(MTK_MSDC_SDC_DATSTA); + + if (msdc_sdc_datsta & MTK_MSDC_SDC_DATSTA_BLKDONE) + DEBUG_MSG("A data block was successfully transferred."); + + if (msdc_sdc_datsta & MTK_MSDC_SDC_DATSTA_DATTO) { + ERROR("MS/SD controller detected a timeout " + "condition while waiting for data token on " + "the DAT line."); + + retval = -1; + } + + if (msdc_sdc_datsta & MTK_MSDC_SDC_DATSTA_DATCRCERR) { + ERROR("MS/SD controller detected a CRC error!"); + + retval = -1; + } + + /* Check FIFO. */ + if ((!(readw(MTK_MSDC_STA) & transfer_condition)) || retval) + break; + else + DEBUG_MSG("FIFO is empty!"); + + udelay(1); + + } while (++timeout_counter != POLL_TRANSFER_COND_TIMEOUT_US); + + if (timeout_counter == POLL_TRANSFER_COND_TIMEOUT_US) { + ERROR("Timeout occurred during polling " + "data transfer conditions."); + retval = TIMEOUT; + } + + return retval; +} + +/* + * Reads data received from memory card. + */ +static int mtk_read_data(void *dest, u32 length) +{ + int retval = 0; + u32 *destl = dest; + u32 timeout_counter = 0; + + DEBUG_LINE(); + + /* Wait for data transfer request. */ + while (!(readw(MTK_MSDC_STA) & MTK_MSDC_STA_DRQ)) { + + udelay(1); + + if (++timeout_counter == DATA_READ_TIMEOUT_US) { + ERROR("Data read timeout occured!"); + break; + } + } + + DEBUG_MSG("Block size is: %d", readl(MTK_MSDC_SDC_CFG) & + MTK_MSDC_SDC_CFG_BLKLEN_MASK); + + while (length) { + + DEBUG_MSG("Bytes left to read: %d.", length); + + /* Read data if there is any in the FIFO. */ + retval = mtk_poll_data_transfer_conditions(MTK_MSDC_STA_BE); + + if (retval) + goto finish_read; + + if (3 < length) { + + *destl++ = readl(MTK_MSDC_DAT); + length -= 4; + + DEBUG_MSG("DATA[R]: 0x%.8x", *(destl - 1)); + + } else { + u8 *dest8 = (u8 *)destl; + u32 msdc_dat = readl(MTK_MSDC_DAT); + memcpy(dest8, &msdc_dat, length); + + length = 0; + + DEBUG_MSG("DATA[R]: 0x%.8x", msdc_dat); + } + } + + if (!readw(MTK_MSDC_STA) & MTK_MSDC_STA_BE) + ERROR("There is still some data left in FIFO!"); + +finish_read: + return retval; +} + +/* + * Writes data to be sent to memory card. + */ +static int mtk_write_data(const void *src, int length) +{ + int retval = 0; + const u32 *srcl = src; + u32 timeout_counter = 0; + + DEBUG_LINE(); + + /* Wait for data transfer request. */ + while (!(readw(MTK_MSDC_STA) & MTK_MSDC_STA_DRQ)) { + + udelay(1); + + if (++timeout_counter == DATA_READ_TIMEOUT_US) { + ERROR("Data write timeout occured!"); + break; + } + } + + while (length) { + + DEBUG_MSG("Length of the data to write: %d.", length); + + /* Write data if there is enough space in the FIFO. */ + retval = mtk_poll_data_transfer_conditions(MTK_MSDC_STA_BF); + + if (retval) + goto finish_write; + + if (3 < length) { + writel(*srcl++, MTK_MSDC_DAT); + length -= 4; + + DEBUG_MSG("DATA[W]: 0x%.8x", *(srcl - 1)); + } else { + + u8 *src8 = (u8 *)srcl; + u32 temp_val; + + memcpy(&temp_val, src8, length); + writel(temp_val, MTK_MSDC_DAT); + + length = 0; + + DEBUG_MSG("DATA[W]: 0x%.8x", temp_val); + } + } + +finish_write: + return retval; +} + +/* + * Performs data transfer between host and memory card. + */ +static int mtk_transfer_data(struct mmc_host *mmc_host) +{ + int retval = 0; + struct mmc_data *data = mmc_host->data; + u32 length = data->blocks * data->blocksize; + + DEBUG_LINE(); + + if (data->flags & MMC_DATA_READ) { + DEBUG_MSG("Reading data..."); + retval = mtk_read_data(data->dest, length); + } else { + DEBUG_MSG("Writing data..."); + retval = mtk_write_data(data->src, length); + } + + return retval; +} + +/* + * Sends a command out on the MMC/SD bus. + */ +static int mtk_send_cmd(struct mmc *mmc, + struct mmc_cmd *cmd, struct mmc_data *data) +{ + int retval; + u16 cmd_status; + u16 controller_status; + struct mmc_host *mmc_host = mmc->priv; + u32 msdc_sdc_cmd = mmc_host->msdc_sdc_cmd; + u32 timeout_counter; + + DEBUG_LINE(); + + mmc_host->cmd = cmd; + mmc_host->data = data; + +#ifdef MTK_MMC_CARD_DETECTION_SUPPORTED + + if (!check_card_presence(mmc_host)) { + DEBUG_MSG("Memory card inserted!"); + } else { + DEBUG_MSG("Memory card not inserted"); + retval = -1; + goto finish; + } + +#endif /* MTK_MMC_CARD_DETECTION_SUPPORTED */ + + /* Check data supplied. */ + if (mmc_host->data) { + retval = mtk_setup_data(mmc_host, &msdc_sdc_cmd); + + if (retval) + goto finish; + } else + msdc_sdc_cmd |= (MTK_MSDC_SDC_CMD_DTYPE_NO_DATA << + MTK_MSDC_SDC_CMD_DTYPE); + + /* Prepared command to send. */ + retval = mtk_setup_cmd(mmc_host, cmd, &msdc_sdc_cmd); + + if (retval) + goto finish; + + /* Clear command status register. */ + (void)readl(MTK_MSDC_SDC_CMDSTA); + + /* Send the command... */ + writel(msdc_sdc_cmd, MTK_MSDC_SDC_CMD); + + timeout_counter = 0; + + /* Wait until the command is sent. */ + do { + controller_status = readl(MTK_MSDC_SDC_STA); + DEBUG_MSG("Controller status: 0x%.4x", controller_status); + udelay(1); + } while ((controller_status & MTK_MSDC_SDC_STA_CMDBUSY) && + (++timeout_counter != POLL_CMD_STATUS_TIMEOUT_US)); + + if (POLL_CMD_STATUS_TIMEOUT_US == timeout_counter) { + ERROR("Waiting for controller status timeout occured " + "(controller status: %d)!", controller_status); + retval = TIMEOUT; + goto finish; + } + + /* Wait for command status. */ + do { + cmd_status = readl(MTK_MSDC_SDC_CMDSTA); + + DEBUG_MSG("Command status: 0x%.4x", cmd_status); + + if (cmd_status & MTK_MSDC_SDC_CMDSTA_CMDRDY) + DEBUG_MSG("Command ready!"); + + if (cmd_status & MTK_MSDC_SDC_CMDSTA_CMDTO) { + ERROR("MS/SD controller detected a timeout " + "condition while waiting for a response on the " + "CMD line."); + retval = TIMEOUT; + goto finish; + } + + if (cmd_status & MTK_MSDC_SDC_CMDSTA_RSPCRCERR) { + ERROR("MS/SD controller detected a CRC error after " + "reading a response from the CMD line."); + retval = -1; + goto finish; + } + + if (cmd_status & MTK_MSDC_SDC_CMDSTA_MMCIRQ) { + ERROR("MMC supporting command class 9 issued an " + "interrupt request."); + retval = -1; + goto finish; + } + + udelay(COMMAND_STATUS_READ_DELAY_US); + + } while (!cmd_status); + + /* Read command response. */ + mtk_read_response(mmc_host); + + /* Read/write data if supplied. */ + if (mmc_host->data) { + + retval = mtk_transfer_data(mmc_host); + + if (retval) + goto finish; + } + + /* Read memory card status register. */ + DEBUG_MSG("=> Memory card status register: 0x%.8x.<=", + readl(MTK_MSDC_SDC_CSTA)); +finish: + mmc_host->cmd = NULL; + mmc_host->data = NULL; + + return retval; +} + +/* + * Initialization of mmc. + */ +int mtk_mmc_init(bd_t *bis) +{ + struct mmc *mmc = malloc(sizeof(struct mmc)); + + DEBUG_LINE(); + + if (!mmc) + return -1; + + strcpy(mmc->name, "msdc_mmc"); + + mmc->send_cmd = mtk_send_cmd; + mmc->set_ios = mtk_set_ios; + mmc->init = mtk_init; + + mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + mmc->host_caps = MMC_MODE_4BIT; + + mmc->priv = &mmc_host; + mmc_host.mmc = mmc; + + /* Min and max frequencies are determined by + max and min values of clock divider (SCLKF in MSDC_CFG). */ + mmc->f_min = mtk_calculate_f_slave_min(); + mmc->f_max = MAX_SLAVE_FREQ_HZ; + + mmc_register(mmc); + + return 0; +} diff --git a/include/configs/sciphone_g2.h b/include/configs/sciphone_g2.h index 76a2eb67a..b81a9601e 100644 --- a/include/configs/sciphone_g2.h +++ b/include/configs/sciphone_g2.h @@ -104,4 +104,32 @@ #define CONFIG_SYS_MAX_FLASH_SECT 512 #define CONFIG_SYS_MAX_FLASH_BANKS 1 +/* Enable support for mmc. */ +#define CONFIG_MMC 1 + +#ifndef DEBUG +/* #define DEBUG */ #endif + +#ifdef CONFIG_MMC + +/* + * The MMC/SD support for is done through the Generic MMC framework + * of u-boot. Following options shall be enabled in the default configuration + * to include MMC/SD support. + */ +#define CONFIG_GENERIC_MMC +#define CONFIG_CMD_MMC +#define CONFIG_MTK_MMC + +/* + * To include File system support for MMC, following configuration options + * shall be enabled + */ +#define CONFIG_DOS_PARTITION +#define CONFIG_CMD_EXT2 +#define CONFIG_CMD_FAT + +#endif /* CONFIG_MMC */ + +#endif /* __CONFIG_H */