From d1b6aa1480c937e326bef99746299cd004a51f28 Mon Sep 17 00:00:00 2001 From: Alison Wang Date: Thu, 4 Aug 2011 09:59:46 +0800 Subject: [PATCH 28/52] Add SD/MMC/SDIO over SPI support for MCF54451 and MCF54418 Add SD/MMC/SDIO over SPI support for MCF54451 and MCF54418. Signed-off-by: Alison Wang --- drivers/mmc/core/sdio.c | 9 +++++- drivers/mmc/host/Kconfig | 35 +++++++++++++++++++++ drivers/mmc/host/mmc_spi.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletions(-) --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -566,8 +566,15 @@ static void mmc_sdio_detect(struct mmc_h /* * Just check if our card has been removed. */ +#if defined(M54451_SD_HW_DETECT) + { + unsigned char x; + err = mmc_io_rw_direct(host->card, 0, 0, + SDIO_FBR_BASE(0) + SDIO_FBR_CIS + 0, 0, &x); + } +#else err = mmc_select_card(host->card); - +#endif mmc_release_host(host); /* --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -368,6 +368,41 @@ config MMC_SPI If unsure, or if your system has no SPI master driver, say N. +config M54451_SD_HW_DETECT + tristate "use extern IRQ7 to detect SD/MMC card" + depends on MMC_SPI && M54451 + default y + help + MMC/SD interface on 54551evb was over SPI. Enable this option will + use irq7 to dectect the card inserting/removing. + +config M5441X_SD_HW_DETECT + tristate "use extern IRQ to detect SD/MMC card" + depends on MMC_SPI && M5441X + help + MMC/SD interface on 54418evb was over SPI. Enable this option will + use irq7 or irq1 to dectect the card inserting/removing. + +choice + prompt "MMC/SD card detect " + depends on M5441X_SD_HW_DETECT + +config DETECT_USE_EXTERN_IRQ7 + tristate "based extern IRQ7" + depends on M5441X_SD_HW_DETECT + help + MMC/SD cards using spi controller, + we use the extern irq7 to detect card. + +config DETECT_USE_EXTERN_IRQ1 + tristate "based extern IRQ1" + depends on M5441X_SD_HW_DETECT + help + MMC/SD cards using spi controller, + we use the extern irq1 to detect card. + +endchoice + config MMC_S3C tristate "Samsung S3C SD/MMC Card Interface support" depends on ARCH_S3C2410 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -9,6 +9,10 @@ * (C) Copyright 2007, ATRON electronic GmbH, * Jan Nikitenko * + * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Modified for M54451EVB/M54418TWR boards. + * Shrek Wu + * Jingchang Lu * * 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 @@ -32,6 +36,14 @@ #include #include #include +#if defined(CONFIG_M54451_SD_HW_DETECT) +#include +#include +#include +#elif defined(CONFIG_M5441X_SD_HW_DETECT) +#include +#include +#endif #include #include /* for R1_SPI_* bit values */ @@ -268,6 +280,9 @@ static int mmc_spi_response_get(struct m unsigned short rotator; int i; char tag[32]; +#if defined(CONFIG_M54451_SD_HW_DETECT) || defined(CONFIG_M5441X_SD_HW_DETECT) + u8 oldcp_value = 0; +#endif snprintf(tag, sizeof(tag), " ... CMD%d response SPI_%s", cmd->opcode, maptype(cmd)); @@ -278,6 +293,9 @@ static int mmc_spi_response_get(struct m * first byte. After STOP_TRANSMISSION command it may include * two data bits, but otherwise it's all ones. */ +#if defined(CONFIG_M54451_SD_HW_DETECT) || defined(CONFIG_M5441X_SD_HW_DETECT) + oldcp_value = *cp; +#endif cp += 8; while (cp < end && *cp == 0xff) cp++; @@ -310,6 +328,15 @@ static int mmc_spi_response_get(struct m } checkstatus: +#if defined(CONFIG_M54451_SD_HW_DETECT) || defined(CONFIG_M5441X_SD_HW_DETECT) + if ((*cp == 0) && (oldcp_value == 0)) { + dev_dbg(&host->spi->dev, "NO CARD in the SD SOCKET, " + "new status %02x, old status %02x\n", + *cp, oldcp_value); + value = -EBADR; + goto done; + } +#endif bitshift = 0; if (*cp & 0x80) { /* Houston, we have an ugly card with a bit-shifted response */ @@ -1313,7 +1340,53 @@ mmc_spi_detect_irq(int irq, void *mmc) struct mmc_spi_host *host = mmc_priv(mmc); u16 delay_msec = max(host->pdata->detect_delay, (u16)100); +#if defined(CONFIG_M54451_SD_HW_DETECT) + dev_dbg(&host->spi->dev, "mmc_spi_detect_irq " + "MCF_EPORT_EPPAR %x, MCF_EPORT_EPIER %x," + "MCF_INTC0_ICR7 %x, MCF_GPIO_PAR_IRQ %x," + "MCF_EPORT_EPDDR %x, MCF_EPORT_EPFR %x\n", + MCF_EPORT_EPPAR, MCF_EPORT_EPIER, + MCF_INTC0_ICR7, MCF_GPIO_PAR_IRQ, + MCF_EPORT_EPDDR, MCF_EPORT_EPFR); + + MCF_EPORT_EPIER &= (~MCF_EPORT_EPIER_EPIE7); +#elif defined(CONFIG_M5441X_SD_HW_DETECT) +#if defined(CONFIG_DETECT_USE_EXTERN_IRQ1) + MCF_EPORT_EPIER = MCF_EPORT_EPIER & (~MCF_EPORT_EPIER_EPIE1); +#elif defined(CONFIG_DETECT_USE_EXTERN_IRQ7) + MCF_EPORT_EPIER = MCF_EPORT_EPIER & (~MCF_EPORT_EPIER_EPIE7); +#else + MCF_EPORT_EPIER = MCF_EPORT_EPIER & (~MCF_EPORT_EPIER_EPIE7); +#endif +#endif mmc_detect_change(mmc, msecs_to_jiffies(delay_msec)); +#if defined(CONFIG_M54451_SD_HW_DETECT) + MCF_EPORT_EPPAR |= MCF_EPORT_EPPAR_EPPA7_BOTH; + MCF_EPORT_EPIER = MCF_EPORT_EPIER | MCF_EPORT_EPIER_EPIE7; + MCF_EPORT_EPFR |= MCF_EPORT_EPFR_EPF7; + dev_dbg(&host->spi->dev, "mmc_spi_detect_irq " + "MCF_EPORT_EPPAR %x, MCF_EPORT_EPIER %x," + "MCF_INTC0_ICR7 %x, MCF_GPIO_PAR_IRQ %x," + "MCF_EPORT_EPDDR %x, MCF_EPORT_EPFR %x\n", + MCF_EPORT_EPPAR, MCF_EPORT_EPIER, + MCF_INTC0_ICR7, MCF_GPIO_PAR_IRQ, + MCF_EPORT_EPDDR, MCF_EPORT_EPFR); + +#elif defined(CONFIG_M5441X_SD_HW_DETECT) +#if defined(CONFIG_DETECT_USE_EXTERN_IRQ1) + MCF_EPORT_EPPAR = MCF_EPORT_EPPAR | MCF_EPORT_EPPAR_EPPA1_BOTH; + MCF_EPORT_EPIER = MCF_EPORT_EPIER | MCF_EPORT_EPIER_EPIE1; + MCF_EPORT_EPFR = MCF_EPORT_EPFR | MCF_EPORT_EPFR_EPF1; +#elif defined(CONFIG_DETECT_USE_EXTERN_IRQ7) + MCF_EPORT_EPPAR = MCF_EPORT_EPPAR | MCF_EPORT_EPPAR_EPPA7_BOTH; + MCF_EPORT_EPIER = MCF_EPORT_EPIER | MCF_EPORT_EPIER_EPIE7; + MCF_EPORT_EPFR = MCF_EPORT_EPFR | MCF_EPORT_EPFR_EPF7; +#else + MCF_EPORT_EPPAR = MCF_EPORT_EPPAR | MCF_EPORT_EPPAR_EPPA7_BOTH; + MCF_EPORT_EPIER = MCF_EPORT_EPIER | MCF_EPORT_EPIER_EPIE7; + MCF_EPORT_EPFR = MCF_EPORT_EPFR | MCF_EPORT_EPFR_EPF7; +#endif +#endif return IRQ_HANDLED; }