Commit d0048f0b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-updates-for-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc

Pull MMC updates from Chris Ball:
 "MMC highlights for 3.12:

  Core:
   - Support Allocation Units 8MB-64MB in SD3.0, previous max was 4MB.
   - The slot-gpio helper can now handle GPIO debouncing card-detect.
   - Read supported voltages from DT "voltage-ranges" property.

  Drivers:
   - dw_mmc: Add support for ARC architecture, and support exynos5420.
   - mmc_spi: Support CD/RO GPIOs.
   - sh_mobile_sdhi: Add compatibility for more Renesas SoCs.
   - sh_mmcif: Add DT support for DMA channels"

* tag 'mmc-updates-for-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (50 commits)
  Revert "mmc: tmio-mmc: Remove .set_pwr() callback from platform data"
  mmc: dw_mmc: Add support for ARC
  mmc: sdhci-s3c: initialize host->quirks2 for using quirks2
  mmc: sdhci-s3c: fix the wrong register value, when clock is disabled
  mmc: esdhc: add support to get voltage from device-tree
  mmc: sdhci: get voltage from sdhc host
  mmc: core: parse voltage from device-tree
  mmc: omap_hsmmc: use the generic config for omap2plus devices
  mmc: omap_hsmmc: clear status flags before starting a new command
  mmc: dw_mmc: exynos: Add a new compatible string for exynos5420
  mmc: sh_mmcif: revision-specific CLK_CTRL2 handling
  mmc: sh_mmcif: revision-specific Command Completion Signal handling
  mmc: sh_mmcif: add support for Device Tree DMA bindings
  mmc: sh_mmcif: move header include from header into .c
  mmc: SDHI: add DT compatibility strings for further SoCs
  mmc: dw_mmc-pci: enable bus-mastering mode
  mmc: dw_mmc-pci: get resources from a proper BAR
  mmc: tmio-mmc: Remove .set_pwr() callback from platform data
  mmc: tmio-mmc: Remove .get_cd() callback from platform data
  mmc: sh_mobile_sdhi: Remove .set_pwr() callback from platform data
  ...
parents 7426d628 9d731e75
...@@ -19,6 +19,9 @@ Optional properties: ...@@ -19,6 +19,9 @@ Optional properties:
"bus-width = <1>" property. "bus-width = <1>" property.
- sdhci,auto-cmd12: specifies that a controller can only handle auto - sdhci,auto-cmd12: specifies that a controller can only handle auto
CMD12. CMD12.
- voltage-ranges : two cells are required, first cell specifies minimum
slot voltage (mV), second cell specifies maximum slot voltage (mV).
Several ranges could be specified.
Example: Example:
...@@ -29,4 +32,5 @@ sdhci@2e000 { ...@@ -29,4 +32,5 @@ sdhci@2e000 {
interrupt-parent = <&ipic>; interrupt-parent = <&ipic>;
/* Filled in by U-Boot */ /* Filled in by U-Boot */
clock-frequency = <0>; clock-frequency = <0>;
voltage-ranges = <3300 3300>;
}; };
...@@ -224,62 +224,15 @@ static struct ep93xx_spi_chip_ops vision_spi_flash_hw = { ...@@ -224,62 +224,15 @@ static struct ep93xx_spi_chip_ops vision_spi_flash_hw = {
#define VISION_SPI_MMC_WP EP93XX_GPIO_LINE_F(0) #define VISION_SPI_MMC_WP EP93XX_GPIO_LINE_F(0)
#define VISION_SPI_MMC_CD EP93XX_GPIO_LINE_EGPIO15 #define VISION_SPI_MMC_CD EP93XX_GPIO_LINE_EGPIO15
static struct gpio vision_spi_mmc_gpios[] = {
{ VISION_SPI_MMC_WP, GPIOF_DIR_IN, "mmc_spi:wp" },
{ VISION_SPI_MMC_CD, GPIOF_DIR_IN, "mmc_spi:cd" },
};
static int vision_spi_mmc_init(struct device *pdev,
irqreturn_t (*func)(int, void *), void *pdata)
{
int err;
err = gpio_request_array(vision_spi_mmc_gpios,
ARRAY_SIZE(vision_spi_mmc_gpios));
if (err)
return err;
err = gpio_set_debounce(VISION_SPI_MMC_CD, 1);
if (err)
goto exit_err;
err = request_irq(gpio_to_irq(VISION_SPI_MMC_CD), func,
IRQ_TYPE_EDGE_BOTH, "mmc_spi:cd", pdata);
if (err)
goto exit_err;
return 0;
exit_err:
gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
return err;
}
static void vision_spi_mmc_exit(struct device *pdev, void *pdata)
{
free_irq(gpio_to_irq(VISION_SPI_MMC_CD), pdata);
gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
}
static int vision_spi_mmc_get_ro(struct device *pdev)
{
return !!gpio_get_value(VISION_SPI_MMC_WP);
}
static int vision_spi_mmc_get_cd(struct device *pdev)
{
return !gpio_get_value(VISION_SPI_MMC_CD);
}
static struct mmc_spi_platform_data vision_spi_mmc_data = { static struct mmc_spi_platform_data vision_spi_mmc_data = {
.init = vision_spi_mmc_init,
.exit = vision_spi_mmc_exit,
.get_ro = vision_spi_mmc_get_ro,
.get_cd = vision_spi_mmc_get_cd,
.detect_delay = 100, .detect_delay = 100,
.powerup_msecs = 100, .powerup_msecs = 100,
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
.flags = MMC_SPI_USE_CD_GPIO | MMC_SPI_USE_RO_GPIO,
.cd_gpio = VISION_SPI_MMC_CD,
.cd_debounce = 1,
.ro_gpio = VISION_SPI_MMC_WP,
.caps2 = MMC_CAP2_RO_ACTIVE_HIGH,
}; };
static int vision_spi_mmc_hw_setup(struct spi_device *spi) static int vision_spi_mmc_hw_setup(struct spi_device *spi)
......
...@@ -600,37 +600,13 @@ static struct platform_device sdhi0_power = { ...@@ -600,37 +600,13 @@ static struct platform_device sdhi0_power = {
}, },
}; };
static void sdhi0_set_pwr(struct platform_device *pdev, int state)
{
static int power_gpio = -EINVAL;
if (power_gpio < 0) {
int ret = gpio_request(GPIO_PTB6, NULL);
if (!ret) {
power_gpio = GPIO_PTB6;
gpio_direction_output(power_gpio, 0);
}
}
/*
* Toggle the GPIO regardless, whether we managed to grab it above or
* the fixed regulator driver did.
*/
gpio_set_value(GPIO_PTB6, state);
}
static int sdhi0_get_cd(struct platform_device *pdev)
{
return !gpio_get_value(GPIO_PTY7);
}
static struct sh_mobile_sdhi_info sdhi0_info = { static struct sh_mobile_sdhi_info sdhi0_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, .dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
.set_pwr = sdhi0_set_pwr,
.tmio_caps = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD | .tmio_caps = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
MMC_CAP_NEEDS_POLL, MMC_CAP_NEEDS_POLL,
.get_cd = sdhi0_get_cd, .tmio_flags = TMIO_MMC_USE_GPIO_CD,
.cd_gpio = GPIO_PTY7,
}; };
static struct resource sdhi0_resources[] = { static struct resource sdhi0_resources[] = {
...@@ -656,39 +632,15 @@ static struct platform_device sdhi0_device = { ...@@ -656,39 +632,15 @@ static struct platform_device sdhi0_device = {
}, },
}; };
static void cn12_set_pwr(struct platform_device *pdev, int state)
{
static int power_gpio = -EINVAL;
if (power_gpio < 0) {
int ret = gpio_request(GPIO_PTB7, NULL);
if (!ret) {
power_gpio = GPIO_PTB7;
gpio_direction_output(power_gpio, 0);
}
}
/*
* Toggle the GPIO regardless, whether we managed to grab it above or
* the fixed regulator driver did.
*/
gpio_set_value(GPIO_PTB7, state);
}
#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
/* SDHI1 */ /* SDHI1 */
static int sdhi1_get_cd(struct platform_device *pdev)
{
return !gpio_get_value(GPIO_PTW7);
}
static struct sh_mobile_sdhi_info sdhi1_info = { static struct sh_mobile_sdhi_info sdhi1_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX,
.tmio_caps = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD | .tmio_caps = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
MMC_CAP_NEEDS_POLL, MMC_CAP_NEEDS_POLL,
.set_pwr = cn12_set_pwr, .tmio_flags = TMIO_MMC_USE_GPIO_CD,
.get_cd = sdhi1_get_cd, .cd_gpio = GPIO_PTW7,
}; };
static struct resource sdhi1_resources[] = { static struct resource sdhi1_resources[] = {
...@@ -718,27 +670,19 @@ static struct platform_device sdhi1_device = { ...@@ -718,27 +670,19 @@ static struct platform_device sdhi1_device = {
#else #else
/* MMC SPI */ /* MMC SPI */
static int mmc_spi_get_ro(struct device *dev)
{
return gpio_get_value(GPIO_PTY6);
}
static int mmc_spi_get_cd(struct device *dev)
{
return !gpio_get_value(GPIO_PTY7);
}
static void mmc_spi_setpower(struct device *dev, unsigned int maskval) static void mmc_spi_setpower(struct device *dev, unsigned int maskval)
{ {
gpio_set_value(GPIO_PTB6, maskval ? 1 : 0); gpio_set_value(GPIO_PTB6, maskval ? 1 : 0);
} }
static struct mmc_spi_platform_data mmc_spi_info = { static struct mmc_spi_platform_data mmc_spi_info = {
.get_ro = mmc_spi_get_ro,
.get_cd = mmc_spi_get_cd,
.caps = MMC_CAP_NEEDS_POLL, .caps = MMC_CAP_NEEDS_POLL,
.caps2 = MMC_CAP2_RO_ACTIVE_HIGH,
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, /* 3.3V only */ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, /* 3.3V only */
.setpower = mmc_spi_setpower, .setpower = mmc_spi_setpower,
.flags = MMC_SPI_USE_CD_GPIO | MMC_SPI_USE_RO_GPIO,
.cd_gpio = GPIO_PTY7,
.ro_gpio = GPIO_PTY6,
}; };
static struct spi_board_info spi_bus[] = { static struct spi_board_info spi_bus[] = {
...@@ -998,11 +942,6 @@ static struct platform_device vou_device = { ...@@ -998,11 +942,6 @@ static struct platform_device vou_device = {
#if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE) #if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE)
/* SH_MMCIF */ /* SH_MMCIF */
static void mmcif_down_pwr(struct platform_device *pdev)
{
cn12_set_pwr(pdev, 0);
}
static struct resource sh_mmcif_resources[] = { static struct resource sh_mmcif_resources[] = {
[0] = { [0] = {
.name = "SH_MMCIF", .name = "SH_MMCIF",
...@@ -1023,8 +962,6 @@ static struct resource sh_mmcif_resources[] = { ...@@ -1023,8 +962,6 @@ static struct resource sh_mmcif_resources[] = {
}; };
static struct sh_mmcif_plat_data sh_mmcif_plat = { static struct sh_mmcif_plat_data sh_mmcif_plat = {
.set_pwr = cn12_set_pwr,
.down_pwr = mmcif_down_pwr,
.sup_pclk = 0, /* SH7724: Max Pclk/2 */ .sup_pclk = 0, /* SH7724: Max Pclk/2 */
.caps = MMC_CAP_4_BIT_DATA | .caps = MMC_CAP_4_BIT_DATA |
MMC_CAP_8_BIT_DATA | MMC_CAP_8_BIT_DATA |
...@@ -1341,10 +1278,6 @@ static int __init arch_setup(void) ...@@ -1341,10 +1278,6 @@ static int __init arch_setup(void)
gpio_direction_input(GPIO_PTR6); gpio_direction_input(GPIO_PTR6);
/* SD-card slot CN11 */ /* SD-card slot CN11 */
/* Card-detect, used on CN11, either with SDHI0 or with SPI */
gpio_request(GPIO_PTY7, NULL);
gpio_direction_input(GPIO_PTY7);
#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE) #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
/* enable SDHI0 on CN11 (needs DS2.4 set to ON) */ /* enable SDHI0 on CN11 (needs DS2.4 set to ON) */
gpio_request(GPIO_FN_SDHI0WP, NULL); gpio_request(GPIO_FN_SDHI0WP, NULL);
...@@ -1363,8 +1296,6 @@ static int __init arch_setup(void) ...@@ -1363,8 +1296,6 @@ static int __init arch_setup(void)
gpio_direction_output(GPIO_PTM4, 1); /* active low CS */ gpio_direction_output(GPIO_PTM4, 1); /* active low CS */
gpio_request(GPIO_PTB6, NULL); /* 3.3V power control */ gpio_request(GPIO_PTB6, NULL); /* 3.3V power control */
gpio_direction_output(GPIO_PTB6, 0); /* disable power by default */ gpio_direction_output(GPIO_PTB6, 0); /* disable power by default */
gpio_request(GPIO_PTY6, NULL); /* write protect */
gpio_direction_input(GPIO_PTY6);
spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus)); spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus));
#endif #endif
...@@ -1394,10 +1325,6 @@ static int __init arch_setup(void) ...@@ -1394,10 +1325,6 @@ static int __init arch_setup(void)
gpio_request(GPIO_FN_SDHI1D1, NULL); gpio_request(GPIO_FN_SDHI1D1, NULL);
gpio_request(GPIO_FN_SDHI1D0, NULL); gpio_request(GPIO_FN_SDHI1D0, NULL);
/* Card-detect, used on CN12 with SDHI1 */
gpio_request(GPIO_PTW7, NULL);
gpio_direction_input(GPIO_PTW7);
cn12_enabled = true; cn12_enabled = true;
#endif #endif
......
...@@ -812,7 +812,7 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error, ...@@ -812,7 +812,7 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
* Otherwise we don't understand what happened, so abort. * Otherwise we don't understand what happened, so abort.
*/ */
static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
struct mmc_blk_request *brq, int *ecc_err) struct mmc_blk_request *brq, int *ecc_err, int *gen_err)
{ {
bool prev_cmd_status_valid = true; bool prev_cmd_status_valid = true;
u32 status, stop_status = 0; u32 status, stop_status = 0;
...@@ -850,6 +850,16 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, ...@@ -850,6 +850,16 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
(brq->cmd.resp[0] & R1_CARD_ECC_FAILED)) (brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
*ecc_err = 1; *ecc_err = 1;
/* Flag General errors */
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
if ((status & R1_ERROR) ||
(brq->stop.resp[0] & R1_ERROR)) {
pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n",
req->rq_disk->disk_name, __func__,
brq->stop.resp[0], status);
*gen_err = 1;
}
/* /*
* Check the current card state. If it is in some data transfer * Check the current card state. If it is in some data transfer
* mode, tell it to stop (and hopefully transition back to TRAN.) * mode, tell it to stop (and hopefully transition back to TRAN.)
...@@ -869,6 +879,13 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, ...@@ -869,6 +879,13 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
return ERR_ABORT; return ERR_ABORT;
if (stop_status & R1_CARD_ECC_FAILED) if (stop_status & R1_CARD_ECC_FAILED)
*ecc_err = 1; *ecc_err = 1;
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
if (stop_status & R1_ERROR) {
pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
req->rq_disk->disk_name, __func__,
stop_status);
*gen_err = 1;
}
} }
/* Check for set block count errors */ /* Check for set block count errors */
...@@ -1097,7 +1114,7 @@ static int mmc_blk_err_check(struct mmc_card *card, ...@@ -1097,7 +1114,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
mmc_active); mmc_active);
struct mmc_blk_request *brq = &mq_mrq->brq; struct mmc_blk_request *brq = &mq_mrq->brq;
struct request *req = mq_mrq->req; struct request *req = mq_mrq->req;
int ecc_err = 0; int ecc_err = 0, gen_err = 0;
/* /*
* sbc.error indicates a problem with the set block count * sbc.error indicates a problem with the set block count
...@@ -1111,7 +1128,7 @@ static int mmc_blk_err_check(struct mmc_card *card, ...@@ -1111,7 +1128,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
*/ */
if (brq->sbc.error || brq->cmd.error || brq->stop.error || if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
brq->data.error) { brq->data.error) {
switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) { switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) {
case ERR_RETRY: case ERR_RETRY:
return MMC_BLK_RETRY; return MMC_BLK_RETRY;
case ERR_ABORT: case ERR_ABORT:
...@@ -1143,6 +1160,14 @@ static int mmc_blk_err_check(struct mmc_card *card, ...@@ -1143,6 +1160,14 @@ static int mmc_blk_err_check(struct mmc_card *card,
u32 status; u32 status;
unsigned long timeout; unsigned long timeout;
/* Check stop command response */
if (brq->stop.resp[0] & R1_ERROR) {
pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
req->rq_disk->disk_name, __func__,
brq->stop.resp[0]);
gen_err = 1;
}
timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS); timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
do { do {
int err = get_card_status(card, &status, 5); int err = get_card_status(card, &status, 5);
...@@ -1152,6 +1177,13 @@ static int mmc_blk_err_check(struct mmc_card *card, ...@@ -1152,6 +1177,13 @@ static int mmc_blk_err_check(struct mmc_card *card,
return MMC_BLK_CMD_ERR; return MMC_BLK_CMD_ERR;
} }
if (status & R1_ERROR) {
pr_err("%s: %s: general error sending status command, card status %#x\n",
req->rq_disk->disk_name, __func__,
status);
gen_err = 1;
}
/* Timeout if the device never becomes ready for data /* Timeout if the device never becomes ready for data
* and never leaves the program state. * and never leaves the program state.
*/ */
...@@ -1171,6 +1203,13 @@ static int mmc_blk_err_check(struct mmc_card *card, ...@@ -1171,6 +1203,13 @@ static int mmc_blk_err_check(struct mmc_card *card,
(R1_CURRENT_STATE(status) == R1_STATE_PRG)); (R1_CURRENT_STATE(status) == R1_STATE_PRG));
} }
/* if general error occurs, retry the write operation. */
if (gen_err) {
pr_warn("%s: retrying write for general error\n",
req->rq_disk->disk_name);
return MMC_BLK_RETRY;
}
if (brq->data.error) { if (brq->data.error) {
pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n", pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
req->rq_disk->disk_name, brq->data.error, req->rq_disk->disk_name, brq->data.error,
...@@ -2191,10 +2230,10 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md) ...@@ -2191,10 +2230,10 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
* is freeing the queue that stops new requests * is freeing the queue that stops new requests
* from being accepted. * from being accepted.
*/ */
card = md->queue.card;
mmc_cleanup_queue(&md->queue); mmc_cleanup_queue(&md->queue);
if (md->flags & MMC_BLK_PACKED_CMD) if (md->flags & MMC_BLK_PACKED_CMD)
mmc_packed_clean(&md->queue); mmc_packed_clean(&md->queue);
card = md->queue.card;
if (md->disk->flags & GENHD_FL_UP) { if (md->disk->flags & GENHD_FL_UP) {
device_remove_file(disk_to_dev(md->disk), &md->force_ro); device_remove_file(disk_to_dev(md->disk), &md->force_ro);
if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) && if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
......
...@@ -2849,18 +2849,12 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf, ...@@ -2849,18 +2849,12 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,
struct seq_file *sf = (struct seq_file *)file->private_data; struct seq_file *sf = (struct seq_file *)file->private_data;
struct mmc_card *card = (struct mmc_card *)sf->private; struct mmc_card *card = (struct mmc_card *)sf->private;
struct mmc_test_card *test; struct mmc_test_card *test;
char lbuf[12];
long testcase; long testcase;
int ret;
if (count >= sizeof(lbuf)) ret = kstrtol_from_user(buf, count, 10, &testcase);
return -EINVAL; if (ret)
return ret;
if (copy_from_user(lbuf, buf, count))
return -EFAULT;
lbuf[count] = '\0';
if (strict_strtol(lbuf, 10, &testcase))
return -EINVAL;
test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL); test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
if (!test) if (!test)
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/fault-inject.h> #include <linux/fault-inject.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of.h>
#include <linux/mmc/card.h> #include <linux/mmc/card.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
...@@ -1196,6 +1197,49 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max) ...@@ -1196,6 +1197,49 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
} }
EXPORT_SYMBOL(mmc_vddrange_to_ocrmask); EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
#ifdef CONFIG_OF
/**
* mmc_of_parse_voltage - return mask of supported voltages
* @np: The device node need to be parsed.
* @mask: mask of voltages available for MMC/SD/SDIO
*
* 1. Return zero on success.
* 2. Return negative errno: voltage-range is invalid.
*/
int mmc_of_parse_voltage(struct device_node *np, u32 *mask)
{
const u32 *voltage_ranges;
int num_ranges, i;
voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
if (!voltage_ranges || !num_ranges) {
pr_info("%s: voltage-ranges unspecified\n", np->full_name);
return -EINVAL;
}
for (i = 0; i < num_ranges; i++) {
const int j = i * 2;
u32 ocr_mask;
ocr_mask = mmc_vddrange_to_ocrmask(
be32_to_cpu(voltage_ranges[j]),
be32_to_cpu(voltage_ranges[j + 1]));
if (!ocr_mask) {
pr_err("%s: voltage-range #%d is invalid\n",
np->full_name, i);
return -EINVAL;
}
*mask |= ocr_mask;
}
return 0;
}
EXPORT_SYMBOL(mmc_of_parse_voltage);
#endif /* CONFIG_OF */
#ifdef CONFIG_REGULATOR #ifdef CONFIG_REGULATOR
/** /**
......
...@@ -374,7 +374,7 @@ int mmc_of_parse(struct mmc_host *host) ...@@ -374,7 +374,7 @@ int mmc_of_parse(struct mmc_host *host)
if (!(flags & OF_GPIO_ACTIVE_LOW)) if (!(flags & OF_GPIO_ACTIVE_LOW))
gpio_inv_cd = true; gpio_inv_cd = true;
ret = mmc_gpio_request_cd(host, gpio); ret = mmc_gpio_request_cd(host, gpio, 0);
if (ret < 0) { if (ret < 0) {
dev_err(host->parent, dev_err(host->parent,
"Failed to request CD GPIO #%d: %d!\n", "Failed to request CD GPIO #%d: %d!\n",
......
...@@ -531,6 +531,7 @@ mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, ...@@ -531,6 +531,7 @@ mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
data.sg = &sg; data.sg = &sg;
data.sg_len = 1; data.sg_len = 1;
mmc_set_data_timeout(&data, card);
sg_init_one(&sg, data_buf, len); sg_init_one(&sg, data_buf, len);
mmc_wait_for_req(host, &mrq); mmc_wait_for_req(host, &mrq);
err = 0; err = 0;
......
...@@ -215,7 +215,7 @@ static int mmc_decode_scr(struct mmc_card *card) ...@@ -215,7 +215,7 @@ static int mmc_decode_scr(struct mmc_card *card)
static int mmc_read_ssr(struct mmc_card *card) static int mmc_read_ssr(struct mmc_card *card)
{ {
unsigned int au, es, et, eo; unsigned int au, es, et, eo;
int err, i; int err, i, max_au;
u32 *ssr; u32 *ssr;
if (!(card->csd.cmdclass & CCC_APP_SPEC)) { if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
...@@ -239,12 +239,15 @@ static int mmc_read_ssr(struct mmc_card *card) ...@@ -239,12 +239,15 @@ static int mmc_read_ssr(struct mmc_card *card)
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
ssr[i] = be32_to_cpu(ssr[i]); ssr[i] = be32_to_cpu(ssr[i]);
/* SD3.0 increases max AU size to 64MB (0xF) from 4MB (0x9) */
max_au = card->scr.sda_spec3 ? 0xF : 0x9;
/* /*
* UNSTUFF_BITS only works with four u32s so we have to offset the * UNSTUFF_BITS only works with four u32s so we have to offset the
* bitfield positions accordingly. * bitfield positions accordingly.
*/ */
au = UNSTUFF_BITS(ssr, 428 - 384, 4); au = UNSTUFF_BITS(ssr, 428 - 384, 4);
if (au > 0 && au <= 9) { if (au > 0 && au <= max_au) {
card->ssr.au = 1 << (au + 4); card->ssr.au = 1 << (au + 4);
es = UNSTUFF_BITS(ssr, 408 - 384, 16); es = UNSTUFF_BITS(ssr, 408 - 384, 16);
et = UNSTUFF_BITS(ssr, 402 - 384, 6); et = UNSTUFF_BITS(ssr, 402 - 384, 6);
...@@ -942,13 +945,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, ...@@ -942,13 +945,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
if (!mmc_host_is_spi(host)) { if (!mmc_host_is_spi(host)) {
err = mmc_send_relative_addr(host, &card->rca); err = mmc_send_relative_addr(host, &card->rca);
if (err) if (err)
return err; goto free_card;
} }
if (!oldcard) { if (!oldcard) {
err = mmc_sd_get_csd(host, card); err = mmc_sd_get_csd(host, card);
if (err) if (err)
return err; goto free_card;
mmc_decode_cid(card); mmc_decode_cid(card);
} }
...@@ -959,7 +962,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, ...@@ -959,7 +962,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
if (!mmc_host_is_spi(host)) { if (!mmc_host_is_spi(host)) {
err = mmc_select_card(card); err = mmc_select_card(card);
if (err) if (err)
return err; goto free_card;
} }
err = mmc_sd_setup_card(host, card, oldcard != NULL); err = mmc_sd_setup_card(host, card, oldcard != NULL);
......
...@@ -135,6 +135,7 @@ EXPORT_SYMBOL(mmc_gpio_request_ro); ...@@ -135,6 +135,7 @@ EXPORT_SYMBOL(mmc_gpio_request_ro);
* mmc_gpio_request_cd - request a gpio for card-detection * mmc_gpio_request_cd - request a gpio for card-detection
* @host: mmc host * @host: mmc host
* @gpio: gpio number requested * @gpio: gpio number requested
* @debounce: debounce time in microseconds
* *
* As devm_* managed functions are used in mmc_gpio_request_cd(), client * As devm_* managed functions are used in mmc_gpio_request_cd(), client
* drivers do not need to explicitly call mmc_gpio_free_cd() for freeing up, * drivers do not need to explicitly call mmc_gpio_free_cd() for freeing up,
...@@ -143,9 +144,14 @@ EXPORT_SYMBOL(mmc_gpio_request_ro); ...@@ -143,9 +144,14 @@ EXPORT_SYMBOL(mmc_gpio_request_ro);
* switching for card-detection, they are responsible for calling * switching for card-detection, they are responsible for calling
* mmc_gpio_request_cd() and mmc_gpio_free_cd() as a pair on their own. * mmc_gpio_request_cd() and mmc_gpio_free_cd() as a pair on their own.
* *
* If GPIO debouncing is desired, set the debounce parameter to a non-zero
* value. The caller is responsible for ensuring that the GPIO driver associated
* with the GPIO supports debouncing, otherwise an error will be returned.
*
* Returns zero on success, else an error. * Returns zero on success, else an error.
*/ */
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
unsigned int debounce)
{ {
struct mmc_gpio *ctx; struct mmc_gpio *ctx;
int irq = gpio_to_irq(gpio); int irq = gpio_to_irq(gpio);
...@@ -167,6 +173,12 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) ...@@ -167,6 +173,12 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
*/ */
return ret; return ret;
if (debounce) {
ret = gpio_set_debounce(gpio, debounce);
if (ret < 0)
return ret;
}
/* /*
* Even if gpio_to_irq() returns a valid IRQ number, the platform might * Even if gpio_to_irq() returns a valid IRQ number, the platform might
* still prefer to poll, e.g., because that IRQ number is already used * still prefer to poll, e.g., because that IRQ number is already used
......
...@@ -284,11 +284,11 @@ config MMC_OMAP ...@@ -284,11 +284,11 @@ config MMC_OMAP
config MMC_OMAP_HS config MMC_OMAP_HS
tristate "TI OMAP High Speed Multimedia Card Interface support" tristate "TI OMAP High Speed Multimedia Card Interface support"
depends on SOC_OMAP2430 || ARCH_OMAP3 || ARCH_OMAP4 depends on ARCH_OMAP2PLUS || COMPILE_TEST
help help
This selects the TI OMAP High Speed Multimedia card Interface. This selects the TI OMAP High Speed Multimedia card Interface.
If you have an OMAP2430 or OMAP3 board or OMAP4 board with a If you have an omap2plus board with a Multimedia Card slot,
Multimedia Card slot, say Y or M here. say Y or M here.
If unsure, say N. If unsure, say N.
...@@ -530,7 +530,7 @@ config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND ...@@ -530,7 +530,7 @@ config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
config MMC_DW config MMC_DW
tristate "Synopsys DesignWare Memory Card Interface" tristate "Synopsys DesignWare Memory Card Interface"
depends on ARM depends on ARC || ARM
help help
This selects support for the Synopsys DesignWare Mobile Storage IP This selects support for the Synopsys DesignWare Mobile Storage IP
block, this provides host support for SD and MMC interfaces, in both block, this provides host support for SD and MMC interfaces, in both
...@@ -569,7 +569,7 @@ config MMC_DW_EXYNOS ...@@ -569,7 +569,7 @@ config MMC_DW_EXYNOS
config MMC_DW_SOCFPGA config MMC_DW_SOCFPGA
tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface" tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface"
depends on MMC_DW depends on MMC_DW && MFD_SYSCON
select MMC_DW_PLTFM select MMC_DW_PLTFM
help help
This selects support for Altera SoCFPGA specific extensions to the This selects support for Altera SoCFPGA specific extensions to the
......
...@@ -52,8 +52,6 @@ obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o ...@@ -52,8 +52,6 @@ obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o
obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
......
...@@ -378,6 +378,8 @@ static int atmci_regs_show(struct seq_file *s, void *v) ...@@ -378,6 +378,8 @@ static int atmci_regs_show(struct seq_file *s, void *v)
{ {
struct atmel_mci *host = s->private; struct atmel_mci *host = s->private;
u32 *buf; u32 *buf;
int ret = 0;
buf = kmalloc(ATMCI_REGS_SIZE, GFP_KERNEL); buf = kmalloc(ATMCI_REGS_SIZE, GFP_KERNEL);
if (!buf) if (!buf)
...@@ -388,12 +390,16 @@ static int atmci_regs_show(struct seq_file *s, void *v) ...@@ -388,12 +390,16 @@ static int atmci_regs_show(struct seq_file *s, void *v)
* not disabling interrupts, so IMR and SR may not be * not disabling interrupts, so IMR and SR may not be
* consistent. * consistent.
*/ */
ret = clk_prepare_enable(host->mck);
if (ret)
goto out;
spin_lock_bh(&host->lock); spin_lock_bh(&host->lock);
clk_enable(host->mck);
memcpy_fromio(buf, host->regs, ATMCI_REGS_SIZE); memcpy_fromio(buf, host->regs, ATMCI_REGS_SIZE);
clk_disable(host->mck);
spin_unlock_bh(&host->lock); spin_unlock_bh(&host->lock);
clk_disable_unprepare(host->mck);
seq_printf(s, "MR:\t0x%08x%s%s ", seq_printf(s, "MR:\t0x%08x%s%s ",
buf[ATMCI_MR / 4], buf[ATMCI_MR / 4],
buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "", buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "",
...@@ -442,9 +448,10 @@ static int atmci_regs_show(struct seq_file *s, void *v) ...@@ -442,9 +448,10 @@ static int atmci_regs_show(struct seq_file *s, void *v)
val & ATMCI_CFG_LSYNC ? " LSYNC" : ""); val & ATMCI_CFG_LSYNC ? " LSYNC" : "");
} }
out:
kfree(buf); kfree(buf);
return 0; return ret;
} }
static int atmci_regs_open(struct inode *inode, struct file *file) static int atmci_regs_open(struct inode *inode, struct file *file)
...@@ -1262,6 +1269,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -1262,6 +1269,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct atmel_mci_slot *slot = mmc_priv(mmc); struct atmel_mci_slot *slot = mmc_priv(mmc);
struct atmel_mci *host = slot->host; struct atmel_mci *host = slot->host;
unsigned int i; unsigned int i;
bool unprepare_clk;
slot->sdc_reg &= ~ATMCI_SDCBUS_MASK; slot->sdc_reg &= ~ATMCI_SDCBUS_MASK;
switch (ios->bus_width) { switch (ios->bus_width) {
...@@ -1277,9 +1285,13 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -1277,9 +1285,13 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
unsigned int clock_min = ~0U; unsigned int clock_min = ~0U;
u32 clkdiv; u32 clkdiv;
clk_prepare(host->mck);
unprepare_clk = true;
spin_lock_bh(&host->lock); spin_lock_bh(&host->lock);
if (!host->mode_reg) { if (!host->mode_reg) {
clk_enable(host->mck); clk_enable(host->mck);
unprepare_clk = false;
atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
if (host->caps.has_cfg_reg) if (host->caps.has_cfg_reg)
...@@ -1347,6 +1359,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -1347,6 +1359,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
} else { } else {
bool any_slot_active = false; bool any_slot_active = false;
unprepare_clk = false;
spin_lock_bh(&host->lock); spin_lock_bh(&host->lock);
slot->clock = 0; slot->clock = 0;
for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
...@@ -1360,12 +1374,16 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -1360,12 +1374,16 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (host->mode_reg) { if (host->mode_reg) {
atmci_readl(host, ATMCI_MR); atmci_readl(host, ATMCI_MR);
clk_disable(host->mck); clk_disable(host->mck);
unprepare_clk = true;
} }
host->mode_reg = 0; host->mode_reg = 0;
} }
spin_unlock_bh(&host->lock); spin_unlock_bh(&host->lock);
} }
if (unprepare_clk)
clk_unprepare(host->mck);
switch (ios->power_mode) { switch (ios->power_mode) {
case MMC_POWER_UP: case MMC_POWER_UP:
set_bit(ATMCI_CARD_NEED_INIT, &slot->flags); set_bit(ATMCI_CARD_NEED_INIT, &slot->flags);
...@@ -2376,10 +2394,12 @@ static int __init atmci_probe(struct platform_device *pdev) ...@@ -2376,10 +2394,12 @@ static int __init atmci_probe(struct platform_device *pdev)
if (!host->regs) if (!host->regs)
goto err_ioremap; goto err_ioremap;
clk_enable(host->mck); ret = clk_prepare_enable(host->mck);
if (ret)
goto err_request_irq;
atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
host->bus_hz = clk_get_rate(host->mck); host->bus_hz = clk_get_rate(host->mck);
clk_disable(host->mck); clk_disable_unprepare(host->mck);
host->mapbase = regs->start; host->mapbase = regs->start;
...@@ -2482,11 +2502,11 @@ static int __exit atmci_remove(struct platform_device *pdev) ...@@ -2482,11 +2502,11 @@ static int __exit atmci_remove(struct platform_device *pdev)
atmci_cleanup_slot(host->slot[i], i); atmci_cleanup_slot(host->slot[i], i);
} }
clk_enable(host->mck); clk_prepare_enable(host->mck);
atmci_writel(host, ATMCI_IDR, ~0UL); atmci_writel(host, ATMCI_IDR, ~0UL);
atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS); atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
atmci_readl(host, ATMCI_SR); atmci_readl(host, ATMCI_SR);
clk_disable(host->mck); clk_disable_unprepare(host->mck);
if (host->dma.chan) if (host->dma.chan)
dma_release_channel(host->dma.chan); dma_release_channel(host->dma.chan);
......
...@@ -39,6 +39,7 @@ enum dw_mci_exynos_type { ...@@ -39,6 +39,7 @@ enum dw_mci_exynos_type {
DW_MCI_TYPE_EXYNOS4210, DW_MCI_TYPE_EXYNOS4210,
DW_MCI_TYPE_EXYNOS4412, DW_MCI_TYPE_EXYNOS4412,
DW_MCI_TYPE_EXYNOS5250, DW_MCI_TYPE_EXYNOS5250,
DW_MCI_TYPE_EXYNOS5420,
}; };
/* Exynos implementation specific driver private data */ /* Exynos implementation specific driver private data */
...@@ -62,6 +63,9 @@ static struct dw_mci_exynos_compatible { ...@@ -62,6 +63,9 @@ static struct dw_mci_exynos_compatible {
}, { }, {
.compatible = "samsung,exynos5250-dw-mshc", .compatible = "samsung,exynos5250-dw-mshc",
.ctrl_type = DW_MCI_TYPE_EXYNOS5250, .ctrl_type = DW_MCI_TYPE_EXYNOS5250,
}, {
.compatible = "samsung,exynos5420-dw-mshc",
.ctrl_type = DW_MCI_TYPE_EXYNOS5420,
}, },
}; };
...@@ -90,7 +94,8 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host) ...@@ -90,7 +94,8 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host)
{ {
struct dw_mci_exynos_priv_data *priv = host->priv; struct dw_mci_exynos_priv_data *priv = host->priv;
if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250) if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250 ||
priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420)
host->bus_hz /= (priv->ciu_div + 1); host->bus_hz /= (priv->ciu_div + 1);
else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412) else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
host->bus_hz /= EXYNOS4412_FIXED_CIU_CLK_DIV; host->bus_hz /= EXYNOS4412_FIXED_CIU_CLK_DIV;
...@@ -173,6 +178,8 @@ static const struct of_device_id dw_mci_exynos_match[] = { ...@@ -173,6 +178,8 @@ static const struct of_device_id dw_mci_exynos_match[] = {
.data = &exynos_drv_data, }, .data = &exynos_drv_data, },
{ .compatible = "samsung,exynos5250-dw-mshc", { .compatible = "samsung,exynos5250-dw-mshc",
.data = &exynos_drv_data, }, .data = &exynos_drv_data, },
{ .compatible = "samsung,exynos5420-dw-mshc",
.data = &exynos_drv_data, },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, dw_mci_exynos_match); MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
......
...@@ -59,7 +59,9 @@ static int dw_mci_pci_probe(struct pci_dev *pdev, ...@@ -59,7 +59,9 @@ static int dw_mci_pci_probe(struct pci_dev *pdev,
if (ret) if (ret)
return ret; return ret;
host->regs = pcim_iomap_table(pdev)[0]; host->regs = pcim_iomap_table(pdev)[PCI_BAR_NO];
pci_set_master(pdev);
ret = dw_mci_probe(host); ret = dw_mci_probe(host);
if (ret) if (ret)
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/of.h> #include <linux/of.h>
#include "dw_mmc.h" #include "dw_mmc.h"
#include "dw_mmc-pltfm.h"
static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr) static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
{ {
......
...@@ -1601,8 +1601,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) ...@@ -1601,8 +1601,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
pending = mci_readl(host, MINTSTS); /* read-only mask reg */ pending = mci_readl(host, MINTSTS); /* read-only mask reg */
if (pending) {
/* /*
* DTO fix - version 2.10a and below, and only if internal DMA * DTO fix - version 2.10a and below, and only if internal DMA
* is configured. * is configured.
...@@ -1613,6 +1611,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) ...@@ -1613,6 +1611,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
pending |= SDMMC_INT_DATA_OVER; pending |= SDMMC_INT_DATA_OVER;
} }
if (pending) {
if (pending & DW_MCI_CMD_ERROR_FLAGS) { if (pending & DW_MCI_CMD_ERROR_FLAGS) {
mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
host->cmd_status = pending; host->cmd_status = pending;
......
...@@ -713,7 +713,7 @@ static int jz4740_mmc_request_gpios(struct mmc_host *mmc, ...@@ -713,7 +713,7 @@ static int jz4740_mmc_request_gpios(struct mmc_host *mmc,
mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
if (gpio_is_valid(pdata->gpio_card_detect)) { if (gpio_is_valid(pdata->gpio_card_detect)) {
ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect); ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect, 0);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -783,9 +783,8 @@ static int jz4740_mmc_probe(struct platform_device* pdev) ...@@ -783,9 +783,8 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
host->base = devm_ioremap_resource(&pdev->dev, res); host->base = devm_ioremap_resource(&pdev->dev, res);
if (!host->base) { if (IS_ERR(host->base)) {
ret = -EBUSY; ret = PTR_ERR(host->base);
dev_err(&pdev->dev, "Failed to ioremap base memory\n");
goto err_free_host; goto err_free_host;
} }
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/mmc.h> /* for R1_SPI_* bit values */ #include <linux/mmc/mmc.h> /* for R1_SPI_* bit values */
#include <linux/mmc/slot-gpio.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/mmc_spi.h> #include <linux/spi/mmc_spi.h>
...@@ -1272,33 +1273,11 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -1272,33 +1273,11 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
} }
} }
static int mmc_spi_get_ro(struct mmc_host *mmc)
{
struct mmc_spi_host *host = mmc_priv(mmc);
if (host->pdata && host->pdata->get_ro)
return !!host->pdata->get_ro(mmc->parent);
/*
* Board doesn't support read only detection; let the mmc core
* decide what to do.
*/
return -ENOSYS;
}
static int mmc_spi_get_cd(struct mmc_host *mmc)
{
struct mmc_spi_host *host = mmc_priv(mmc);
if (host->pdata && host->pdata->get_cd)
return !!host->pdata->get_cd(mmc->parent);
return -ENOSYS;
}
static const struct mmc_host_ops mmc_spi_ops = { static const struct mmc_host_ops mmc_spi_ops = {
.request = mmc_spi_request, .request = mmc_spi_request,
.set_ios = mmc_spi_set_ios, .set_ios = mmc_spi_set_ios,
.get_ro = mmc_spi_get_ro, .get_ro = mmc_gpio_get_ro,
.get_cd = mmc_spi_get_cd, .get_cd = mmc_gpio_get_cd,
}; };
...@@ -1324,6 +1303,7 @@ static int mmc_spi_probe(struct spi_device *spi) ...@@ -1324,6 +1303,7 @@ static int mmc_spi_probe(struct spi_device *spi)
struct mmc_host *mmc; struct mmc_host *mmc;
struct mmc_spi_host *host; struct mmc_spi_host *host;
int status; int status;
bool has_ro = false;
/* We rely on full duplex transfers, mostly to reduce /* We rely on full duplex transfers, mostly to reduce
* per-transfer overheads (by making fewer transfers). * per-transfer overheads (by making fewer transfers).
...@@ -1448,18 +1428,33 @@ static int mmc_spi_probe(struct spi_device *spi) ...@@ -1448,18 +1428,33 @@ static int mmc_spi_probe(struct spi_device *spi)
} }
/* pass platform capabilities, if any */ /* pass platform capabilities, if any */
if (host->pdata) if (host->pdata) {
mmc->caps |= host->pdata->caps; mmc->caps |= host->pdata->caps;
mmc->caps2 |= host->pdata->caps2;
}
status = mmc_add_host(mmc); status = mmc_add_host(mmc);
if (status != 0) if (status != 0)
goto fail_add_host; goto fail_add_host;
if (host->pdata && host->pdata->flags & MMC_SPI_USE_CD_GPIO) {
status = mmc_gpio_request_cd(mmc, host->pdata->cd_gpio,
host->pdata->cd_debounce);
if (status != 0)
goto fail_add_host;
}
if (host->pdata && host->pdata->flags & MMC_SPI_USE_RO_GPIO) {
has_ro = true;
status = mmc_gpio_request_ro(mmc, host->pdata->ro_gpio);
if (status != 0)
goto fail_add_host;
}
dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n", dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n",
dev_name(&mmc->class_dev), dev_name(&mmc->class_dev),
host->dma_dev ? "" : ", no DMA", host->dma_dev ? "" : ", no DMA",
(host->pdata && host->pdata->get_ro) has_ro ? "" : ", no WP",
? "" : ", no WP",
(host->pdata && host->pdata->setpower) (host->pdata && host->pdata->setpower)
? "" : ", no poweroff", ? "" : ", no poweroff",
(mmc->caps & MMC_CAP_NEEDS_POLL) (mmc->caps & MMC_CAP_NEEDS_POLL)
......
...@@ -757,7 +757,8 @@ static int __init mvsd_probe(struct platform_device *pdev) ...@@ -757,7 +757,8 @@ static int __init mvsd_probe(struct platform_device *pdev)
if (mvsd_data->gpio_card_detect && if (mvsd_data->gpio_card_detect &&
gpio_is_valid(mvsd_data->gpio_card_detect)) { gpio_is_valid(mvsd_data->gpio_card_detect)) {
ret = mmc_gpio_request_cd(mmc, ret = mmc_gpio_request_cd(mmc,
mvsd_data->gpio_card_detect); mvsd_data->gpio_card_detect,
0);
if (ret) if (ret)
goto out; goto out;
} else { } else {
......
...@@ -102,12 +102,15 @@ static int mxs_mmc_get_cd(struct mmc_host *mmc) ...@@ -102,12 +102,15 @@ static int mxs_mmc_get_cd(struct mmc_host *mmc)
BM_SSP_STATUS_CARD_DETECT) ^ host->cd_inverted; BM_SSP_STATUS_CARD_DETECT) ^ host->cd_inverted;
} }
static void mxs_mmc_reset(struct mxs_mmc_host *host) static int mxs_mmc_reset(struct mxs_mmc_host *host)
{ {
struct mxs_ssp *ssp = &host->ssp; struct mxs_ssp *ssp = &host->ssp;
u32 ctrl0, ctrl1; u32 ctrl0, ctrl1;
int ret;
stmp_reset_block(ssp->base); ret = stmp_reset_block(ssp->base);
if (ret)
return ret;
ctrl0 = BM_SSP_CTRL0_IGNORE_CRC; ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) | ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) |
...@@ -132,6 +135,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host) ...@@ -132,6 +135,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host)
writel(ctrl0, ssp->base + HW_SSP_CTRL0); writel(ctrl0, ssp->base + HW_SSP_CTRL0);
writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp)); writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp));
return 0;
} }
static void mxs_mmc_start_cmd(struct mxs_mmc_host *host, static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
...@@ -618,21 +622,25 @@ static int mxs_mmc_probe(struct platform_device *pdev) ...@@ -618,21 +622,25 @@ static int mxs_mmc_probe(struct platform_device *pdev)
} }
} }
ssp->clk = clk_get(&pdev->dev, NULL); ssp->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(ssp->clk)) { if (IS_ERR(ssp->clk)) {
ret = PTR_ERR(ssp->clk); ret = PTR_ERR(ssp->clk);
goto out_mmc_free; goto out_mmc_free;
} }
clk_prepare_enable(ssp->clk); clk_prepare_enable(ssp->clk);
mxs_mmc_reset(host); ret = mxs_mmc_reset(host);
if (ret) {
dev_err(&pdev->dev, "Failed to reset mmc: %d\n", ret);
goto out_clk_disable;
}
ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx"); ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx");
if (!ssp->dmach) { if (!ssp->dmach) {
dev_err(mmc_dev(host->mmc), dev_err(mmc_dev(host->mmc),
"%s: failed to request dma\n", __func__); "%s: failed to request dma\n", __func__);
ret = -ENODEV; ret = -ENODEV;
goto out_clk_put; goto out_clk_disable;
} }
/* set mmc core parameters */ /* set mmc core parameters */
...@@ -685,9 +693,8 @@ static int mxs_mmc_probe(struct platform_device *pdev) ...@@ -685,9 +693,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)
out_free_dma: out_free_dma:
if (ssp->dmach) if (ssp->dmach)
dma_release_channel(ssp->dmach); dma_release_channel(ssp->dmach);
out_clk_put: out_clk_disable:
clk_disable_unprepare(ssp->clk); clk_disable_unprepare(ssp->clk);
clk_put(ssp->clk);
out_mmc_free: out_mmc_free:
mmc_free_host(mmc); mmc_free_host(mmc);
return ret; return ret;
...@@ -705,7 +712,6 @@ static int mxs_mmc_remove(struct platform_device *pdev) ...@@ -705,7 +712,6 @@ static int mxs_mmc_remove(struct platform_device *pdev)
dma_release_channel(ssp->dmach); dma_release_channel(ssp->dmach);
clk_disable_unprepare(ssp->clk); clk_disable_unprepare(ssp->clk);
clk_put(ssp->clk);
mmc_free_host(mmc); mmc_free_host(mmc);
......
...@@ -50,25 +50,6 @@ static struct of_mmc_spi *to_of_mmc_spi(struct device *dev) ...@@ -50,25 +50,6 @@ static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
return container_of(dev->platform_data, struct of_mmc_spi, pdata); return container_of(dev->platform_data, struct of_mmc_spi, pdata);
} }
static int of_mmc_spi_read_gpio(struct device *dev, int gpio_num)
{
struct of_mmc_spi *oms = to_of_mmc_spi(dev);
bool active_low = oms->alow_gpios[gpio_num];
bool value = gpio_get_value(oms->gpios[gpio_num]);
return active_low ^ value;
}
static int of_mmc_spi_get_cd(struct device *dev)
{
return of_mmc_spi_read_gpio(dev, CD_GPIO);
}
static int of_mmc_spi_get_ro(struct device *dev)
{
return of_mmc_spi_read_gpio(dev, WP_GPIO);
}
static int of_mmc_spi_init(struct device *dev, static int of_mmc_spi_init(struct device *dev,
irqreturn_t (*irqhandler)(int, void *), void *mmc) irqreturn_t (*irqhandler)(int, void *), void *mmc)
{ {
...@@ -130,20 +111,22 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) ...@@ -130,20 +111,22 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
if (!gpio_is_valid(oms->gpios[i])) if (!gpio_is_valid(oms->gpios[i]))
continue; continue;
ret = gpio_request(oms->gpios[i], dev_name(dev));
if (ret < 0) {
oms->gpios[i] = -EINVAL;
continue;
}
if (gpio_flags & OF_GPIO_ACTIVE_LOW) if (gpio_flags & OF_GPIO_ACTIVE_LOW)
oms->alow_gpios[i] = true; oms->alow_gpios[i] = true;
} }
if (gpio_is_valid(oms->gpios[CD_GPIO])) if (gpio_is_valid(oms->gpios[CD_GPIO])) {
oms->pdata.get_cd = of_mmc_spi_get_cd; oms->pdata.cd_gpio = oms->gpios[CD_GPIO];
if (gpio_is_valid(oms->gpios[WP_GPIO])) oms->pdata.flags |= MMC_SPI_USE_CD_GPIO;
oms->pdata.get_ro = of_mmc_spi_get_ro; if (!oms->alow_gpios[CD_GPIO])
oms->pdata.caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
}
if (gpio_is_valid(oms->gpios[WP_GPIO])) {
oms->pdata.ro_gpio = oms->gpios[WP_GPIO];
oms->pdata.flags |= MMC_SPI_USE_RO_GPIO;
if (!oms->alow_gpios[WP_GPIO])
oms->pdata.caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
}
oms->detect_irq = irq_of_parse_and_map(np, 0); oms->detect_irq = irq_of_parse_and_map(np, 0);
if (oms->detect_irq != 0) { if (oms->detect_irq != 0) {
...@@ -166,15 +149,10 @@ void mmc_spi_put_pdata(struct spi_device *spi) ...@@ -166,15 +149,10 @@ void mmc_spi_put_pdata(struct spi_device *spi)
struct device *dev = &spi->dev; struct device *dev = &spi->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct of_mmc_spi *oms = to_of_mmc_spi(dev); struct of_mmc_spi *oms = to_of_mmc_spi(dev);
int i;
if (!dev->platform_data || !np) if (!dev->platform_data || !np)
return; return;
for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) {
if (gpio_is_valid(oms->gpios[i]))
gpio_free(oms->gpios[i]);
}
kfree(oms); kfree(oms);
dev->platform_data = NULL; dev->platform_data = NULL;
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/sizes.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -1041,6 +1042,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) ...@@ -1041,6 +1042,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
} }
} }
OMAP_HSMMC_WRITE(host->base, STAT, status);
if (end_cmd || ((status & CC_EN) && host->cmd)) if (end_cmd || ((status & CC_EN) && host->cmd))
omap_hsmmc_cmd_done(host, host->cmd); omap_hsmmc_cmd_done(host, host->cmd);
if ((end_trans || (status & TC_EN)) && host->mrq) if ((end_trans || (status & TC_EN)) && host->mrq)
...@@ -1060,7 +1062,6 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) ...@@ -1060,7 +1062,6 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
omap_hsmmc_do_irq(host, status); omap_hsmmc_do_irq(host, status);
/* Flush posted write */ /* Flush posted write */
OMAP_HSMMC_WRITE(host->base, STAT, status);
status = OMAP_HSMMC_READ(host->base, STAT); status = OMAP_HSMMC_READ(host->base, STAT);
} }
......
...@@ -119,7 +119,7 @@ static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg) ...@@ -119,7 +119,7 @@ static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg)
return byte; return byte;
} }
unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host) static unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
{ {
return MIN_FREQ; return MIN_FREQ;
} }
......
...@@ -616,7 +616,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) ...@@ -616,7 +616,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
/* card_detect */ /* card_detect */
switch (boarddata->cd_type) { switch (boarddata->cd_type) {
case ESDHC_CD_GPIO: case ESDHC_CD_GPIO:
err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio); err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0);
if (err) { if (err) {
dev_err(mmc_dev(host->mmc), dev_err(mmc_dev(host->mmc),
"failed to request card-detect gpio!\n"); "failed to request card-detect gpio!\n");
......
...@@ -316,6 +316,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) ...@@ -316,6 +316,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
/* call to generic mmc_of_parse to support additional capabilities */ /* call to generic mmc_of_parse to support additional capabilities */
mmc_of_parse(host->mmc); mmc_of_parse(host->mmc);
mmc_of_parse_voltage(np, &host->ocr_mask);
ret = sdhci_add_host(host); ret = sdhci_add_host(host);
if (ret) if (ret)
......
...@@ -278,7 +278,8 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) ...@@ -278,7 +278,8 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
host->mmc->pm_caps |= pdata->pm_caps; host->mmc->pm_caps |= pdata->pm_caps;
if (gpio_is_valid(pdata->ext_cd_gpio)) { if (gpio_is_valid(pdata->ext_cd_gpio)) {
ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio); ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio,
0);
if (ret) { if (ret) {
dev_err(mmc_dev(host->mmc), dev_err(mmc_dev(host->mmc),
"failed to allocate card detect gpio\n"); "failed to allocate card detect gpio\n");
......
...@@ -296,9 +296,12 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) ...@@ -296,9 +296,12 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
unsigned long timeout; unsigned long timeout;
u16 clk = 0; u16 clk = 0;
/* don't bother if the clock is going off */ /* If the clock is going off, set to 0 at clock control register */
if (clock == 0) if (clock == 0) {
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
host->clock = clock;
return; return;
}
sdhci_s3c_set_clock(host, clock); sdhci_s3c_set_clock(host, clock);
...@@ -608,6 +611,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev) ...@@ -608,6 +611,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
host->hw_name = "samsung-hsmmc"; host->hw_name = "samsung-hsmmc";
host->ops = &sdhci_s3c_ops; host->ops = &sdhci_s3c_ops;
host->quirks = 0; host->quirks = 0;
host->quirks2 = 0;
host->irq = irq; host->irq = irq;
/* Setup quirks for the controller */ /* Setup quirks for the controller */
......
...@@ -84,7 +84,7 @@ static int sdhci_sirf_probe(struct platform_device *pdev) ...@@ -84,7 +84,7 @@ static int sdhci_sirf_probe(struct platform_device *pdev)
* gets setup in sdhci_add_host() and we oops. * gets setup in sdhci_add_host() and we oops.
*/ */
if (gpio_is_valid(priv->gpio_cd)) { if (gpio_is_valid(priv->gpio_cd)) {
ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd); ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd, 0);
if (ret) { if (ret) {
dev_err(&pdev->dev, "card detect irq request failed: %d\n", dev_err(&pdev->dev, "card detect irq request failed: %d\n",
ret); ret);
......
...@@ -3119,6 +3119,9 @@ int sdhci_add_host(struct sdhci_host *host) ...@@ -3119,6 +3119,9 @@ int sdhci_add_host(struct sdhci_host *host)
SDHCI_MAX_CURRENT_MULTIPLIER; SDHCI_MAX_CURRENT_MULTIPLIER;
} }
if (host->ocr_mask)
ocr_avail = host->ocr_mask;
mmc->ocr_avail = ocr_avail; mmc->ocr_avail = ocr_avail;
mmc->ocr_avail_sdio = ocr_avail; mmc->ocr_avail_sdio = ocr_avail;
if (host->ocr_avail_sdio) if (host->ocr_avail_sdio)
...@@ -3213,6 +3216,8 @@ int sdhci_add_host(struct sdhci_host *host) ...@@ -3213,6 +3216,8 @@ int sdhci_add_host(struct sdhci_host *host)
host->tuning_timer.function = sdhci_tuning_timer; host->tuning_timer.function = sdhci_tuning_timer;
} }
sdhci_init(host, 0);
ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
mmc_hostname(mmc), host); mmc_hostname(mmc), host);
if (ret) { if (ret) {
...@@ -3221,8 +3226,6 @@ int sdhci_add_host(struct sdhci_host *host) ...@@ -3221,8 +3226,6 @@ int sdhci_add_host(struct sdhci_host *host)
goto untasklet; goto untasklet;
} }
sdhci_init(host, 0);
#ifdef CONFIG_MMC_DEBUG #ifdef CONFIG_MMC_DEBUG
sdhci_dumpregs(host); sdhci_dumpregs(host);
#endif #endif
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_qos.h> #include <linux/pm_qos.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/sh_dma.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -133,6 +134,8 @@ ...@@ -133,6 +134,8 @@
INT_BUFWEN | INT_CMD12DRE | INT_BUFRE | \ INT_BUFWEN | INT_CMD12DRE | INT_BUFRE | \
INT_DTRANE | INT_CMD12RBE | INT_CMD12CRE) INT_DTRANE | INT_CMD12RBE | INT_CMD12CRE)
#define INT_CCS (INT_CCSTO | INT_CCSRCV | INT_CCSDE)
/* CE_INT_MASK */ /* CE_INT_MASK */
#define MASK_ALL 0x00000000 #define MASK_ALL 0x00000000
#define MASK_MCCSDE (1 << 29) #define MASK_MCCSDE (1 << 29)
...@@ -161,7 +164,7 @@ ...@@ -161,7 +164,7 @@
#define MASK_START_CMD (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \ #define MASK_START_CMD (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \
MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \ MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \
MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \ MASK_MCRCSTO | MASK_MWDATTO | \
MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO) MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO)
#define MASK_CLEAN (INT_ERR_STS | MASK_MRBSYE | MASK_MCRSPE | \ #define MASK_CLEAN (INT_ERR_STS | MASK_MRBSYE | MASK_MCRSPE | \
...@@ -243,6 +246,8 @@ struct sh_mmcif_host { ...@@ -243,6 +246,8 @@ struct sh_mmcif_host {
int sg_blkidx; int sg_blkidx;
bool power; bool power;
bool card_present; bool card_present;
bool ccs_enable; /* Command Completion Signal support */
bool clk_ctrl2_enable;
struct mutex thread_lock; struct mutex thread_lock;
/* DMA support */ /* DMA support */
...@@ -386,24 +391,28 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host, ...@@ -386,24 +391,28 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
host->dma_active = false; host->dma_active = false;
if (!pdata) if (pdata) {
return;
if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
return; return;
} else if (!host->pd->dev.of_node) {
return;
}
/* We can only either use DMA for both Tx and Rx or not use it at all */ /* We can only either use DMA for both Tx and Rx or not use it at all */
dma_cap_zero(mask); dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
host->chan_tx = dma_request_channel(mask, shdma_chan_filter, host->chan_tx = dma_request_slave_channel_compat(mask, shdma_chan_filter,
(void *)pdata->slave_id_tx); pdata ? (void *)pdata->slave_id_tx : NULL,
&host->pd->dev, "tx");
dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__, dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
host->chan_tx); host->chan_tx);
if (!host->chan_tx) if (!host->chan_tx)
return; return;
/* In the OF case the driver will get the slave ID from the DT */
if (pdata)
cfg.slave_id = pdata->slave_id_tx; cfg.slave_id = pdata->slave_id_tx;
cfg.direction = DMA_MEM_TO_DEV; cfg.direction = DMA_MEM_TO_DEV;
cfg.dst_addr = res->start + MMCIF_CE_DATA; cfg.dst_addr = res->start + MMCIF_CE_DATA;
...@@ -412,14 +421,16 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host, ...@@ -412,14 +421,16 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
if (ret < 0) if (ret < 0)
goto ecfgtx; goto ecfgtx;
host->chan_rx = dma_request_channel(mask, shdma_chan_filter, host->chan_rx = dma_request_slave_channel_compat(mask, shdma_chan_filter,
(void *)pdata->slave_id_rx); pdata ? (void *)pdata->slave_id_rx : NULL,
&host->pd->dev, "rx");
dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__, dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
host->chan_rx); host->chan_rx);
if (!host->chan_rx) if (!host->chan_rx)
goto erqrx; goto erqrx;
if (pdata)
cfg.slave_id = pdata->slave_id_rx; cfg.slave_id = pdata->slave_id_rx;
cfg.direction = DMA_DEV_TO_MEM; cfg.direction = DMA_DEV_TO_MEM;
cfg.dst_addr = 0; cfg.dst_addr = 0;
...@@ -485,8 +496,12 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host) ...@@ -485,8 +496,12 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_ON); sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_ON);
sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_OFF); sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_OFF);
if (host->ccs_enable)
tmp |= SCCSTO_29;
if (host->clk_ctrl2_enable)
sh_mmcif_writel(host->addr, MMCIF_CE_CLK_CTRL2, 0x0F0F0000);
sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp |
SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29); SRSPTO_256 | SRBSYTO_29 | SRWDTO_29);
/* byte swap on */ /* byte swap on */
sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP); sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP);
} }
...@@ -866,6 +881,9 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, ...@@ -866,6 +881,9 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
break; break;
} }
if (host->ccs_enable)
mask |= MASK_MCCSTO;
if (mrq->data) { if (mrq->data) {
sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0); sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0);
sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET,
...@@ -873,7 +891,10 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, ...@@ -873,7 +891,10 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
} }
opc = sh_mmcif_set_cmd(host, mrq); opc = sh_mmcif_set_cmd(host, mrq);
if (host->ccs_enable)
sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0); sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
else
sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0 | INT_CCS);
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask); sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
/* set arg */ /* set arg */
sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg); sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
...@@ -956,11 +977,8 @@ static int sh_mmcif_clk_update(struct sh_mmcif_host *host) ...@@ -956,11 +977,8 @@ static int sh_mmcif_clk_update(struct sh_mmcif_host *host)
static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios) static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios)
{ {
struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
struct mmc_host *mmc = host->mmc; struct mmc_host *mmc = host->mmc;
if (pd && pd->set_pwr)
pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF);
if (!IS_ERR(mmc->supply.vmmc)) if (!IS_ERR(mmc->supply.vmmc))
/* Errors ignored... */ /* Errors ignored... */
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
...@@ -1241,11 +1259,14 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) ...@@ -1241,11 +1259,14 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
{ {
struct sh_mmcif_host *host = dev_id; struct sh_mmcif_host *host = dev_id;
u32 state; u32 state, mask;
state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
sh_mmcif_writel(host->addr, MMCIF_CE_INT, mask = sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK);
~(state & sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK))); if (host->ccs_enable)
sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~(state & mask));
else
sh_mmcif_writel(host->addr, MMCIF_CE_INT, INT_CCS | ~(state & mask));
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN); sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN);
if (state & ~MASK_CLEAN) if (state & ~MASK_CLEAN)
...@@ -1379,6 +1400,8 @@ static int sh_mmcif_probe(struct platform_device *pdev) ...@@ -1379,6 +1400,8 @@ static int sh_mmcif_probe(struct platform_device *pdev)
host->mmc = mmc; host->mmc = mmc;
host->addr = reg; host->addr = reg;
host->timeout = msecs_to_jiffies(1000); host->timeout = msecs_to_jiffies(1000);
host->ccs_enable = !pd || !pd->ccs_unsupported;
host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present;
host->pd = pdev; host->pd = pdev;
...@@ -1436,7 +1459,7 @@ static int sh_mmcif_probe(struct platform_device *pdev) ...@@ -1436,7 +1459,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
} }
if (pd && pd->use_cd_gpio) { if (pd && pd->use_cd_gpio) {
ret = mmc_gpio_request_cd(mmc, pd->cd_gpio); ret = mmc_gpio_request_cd(mmc, pd->cd_gpio, 0);
if (ret < 0) if (ret < 0)
goto erqcd; goto erqcd;
} }
......
...@@ -70,20 +70,6 @@ static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev) ...@@ -70,20 +70,6 @@ static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev)
clk_disable(priv->clk); clk_disable(priv->clk);
} }
static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
{
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
p->set_pwr(pdev, state);
}
static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
{
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
return p->get_cd(pdev);
}
static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
{ {
int timeout = 1000; int timeout = 1000;
...@@ -129,7 +115,12 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = { ...@@ -129,7 +115,12 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = {
static const struct of_device_id sh_mobile_sdhi_of_match[] = { static const struct of_device_id sh_mobile_sdhi_of_match[] = {
{ .compatible = "renesas,shmobile-sdhi" }, { .compatible = "renesas,shmobile-sdhi" },
{ .compatible = "renesas,sh7372-sdhi" }, { .compatible = "renesas,sh7372-sdhi" },
{ .compatible = "renesas,sh73a0-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
{ .compatible = "renesas,r8a73a4-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
{ .compatible = "renesas,r8a7740-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], }, { .compatible = "renesas,r8a7740-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
{ .compatible = "renesas,r8a7778-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
{ .compatible = "renesas,r8a7779-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
{ .compatible = "renesas,r8a7790-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
...@@ -180,10 +171,6 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) ...@@ -180,10 +171,6 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
mmc_data->capabilities |= p->tmio_caps; mmc_data->capabilities |= p->tmio_caps;
mmc_data->capabilities2 |= p->tmio_caps2; mmc_data->capabilities2 |= p->tmio_caps2;
mmc_data->cd_gpio = p->cd_gpio; mmc_data->cd_gpio = p->cd_gpio;
if (p->set_pwr)
mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
if (p->get_cd)
mmc_data->get_cd = sh_mobile_sdhi_get_cd;
if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) { if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
/* /*
......
...@@ -104,6 +104,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) ...@@ -104,6 +104,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
pio: pio:
if (!desc) { if (!desc) {
/* DMA failed, fall back to PIO */ /* DMA failed, fall back to PIO */
tmio_mmc_enable_dma(host, false);
if (ret >= 0) if (ret >= 0)
ret = -EIO; ret = -EIO;
host->chan_rx = NULL; host->chan_rx = NULL;
...@@ -116,7 +117,6 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) ...@@ -116,7 +117,6 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
} }
dev_warn(&host->pdev->dev, dev_warn(&host->pdev->dev,
"DMA failed: %d, falling back to PIO\n", ret); "DMA failed: %d, falling back to PIO\n", ret);
tmio_mmc_enable_dma(host, false);
} }
dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__, dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
...@@ -185,6 +185,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) ...@@ -185,6 +185,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
pio: pio:
if (!desc) { if (!desc) {
/* DMA failed, fall back to PIO */ /* DMA failed, fall back to PIO */
tmio_mmc_enable_dma(host, false);
if (ret >= 0) if (ret >= 0)
ret = -EIO; ret = -EIO;
host->chan_tx = NULL; host->chan_tx = NULL;
...@@ -197,7 +198,6 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) ...@@ -197,7 +198,6 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
} }
dev_warn(&host->pdev->dev, dev_warn(&host->pdev->dev,
"DMA failed: %d, falling back to PIO\n", ret); "DMA failed: %d, falling back to PIO\n", ret);
tmio_mmc_enable_dma(host, false);
} }
dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__, dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__,
......
...@@ -795,9 +795,13 @@ static void tmio_mmc_power_on(struct tmio_mmc_host *host, unsigned short vdd) ...@@ -795,9 +795,13 @@ static void tmio_mmc_power_on(struct tmio_mmc_host *host, unsigned short vdd)
* omap_hsmmc.c driver does. * omap_hsmmc.c driver does.
*/ */
if (!IS_ERR(mmc->supply.vqmmc) && !ret) { if (!IS_ERR(mmc->supply.vqmmc) && !ret) {
regulator_enable(mmc->supply.vqmmc); ret = regulator_enable(mmc->supply.vqmmc);
udelay(200); udelay(200);
} }
if (ret < 0)
dev_dbg(&host->pdev->dev, "Regulators failed to power up: %d\n",
ret);
} }
static void tmio_mmc_power_off(struct tmio_mmc_host *host) static void tmio_mmc_power_off(struct tmio_mmc_host *host)
...@@ -932,25 +936,11 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc) ...@@ -932,25 +936,11 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)); (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
} }
static int tmio_mmc_get_cd(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
struct tmio_mmc_data *pdata = host->pdata;
int ret = mmc_gpio_get_cd(mmc);
if (ret >= 0)
return ret;
if (!pdata->get_cd)
return -ENOSYS;
else
return pdata->get_cd(host->pdev);
}
static const struct mmc_host_ops tmio_mmc_ops = { static const struct mmc_host_ops tmio_mmc_ops = {
.request = tmio_mmc_request, .request = tmio_mmc_request,
.set_ios = tmio_mmc_set_ios, .set_ios = tmio_mmc_set_ios,
.get_ro = tmio_mmc_get_ro, .get_ro = tmio_mmc_get_ro,
.get_cd = tmio_mmc_get_cd, .get_cd = mmc_gpio_get_cd,
.enable_sdio_irq = tmio_mmc_enable_sdio_irq, .enable_sdio_irq = tmio_mmc_enable_sdio_irq,
}; };
...@@ -1106,7 +1096,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, ...@@ -1106,7 +1096,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host,
dev_pm_qos_expose_latency_limit(&pdev->dev, 100); dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
if (pdata->flags & TMIO_MMC_USE_GPIO_CD) { if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio); ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio, 0);
if (ret < 0) { if (ret < 0) {
tmio_mmc_host_remove(_host); tmio_mmc_host_remove(_host);
return ret; return ret;
......
...@@ -2079,7 +2079,7 @@ static void vub300_enable_sdio_irq(struct mmc_host *mmc, int enable) ...@@ -2079,7 +2079,7 @@ static void vub300_enable_sdio_irq(struct mmc_host *mmc, int enable)
kref_put(&vub300->kref, vub300_delete); kref_put(&vub300->kref, vub300_delete);
} }
void vub300_init_card(struct mmc_host *mmc, struct mmc_card *card) static void vub300_init_card(struct mmc_host *mmc, struct mmc_card *card)
{ /* NOT irq */ { /* NOT irq */
struct vub300_mmc_host *vub300 = mmc_priv(mmc); struct vub300_mmc_host *vub300 = mmc_priv(mmc);
dev_info(&vub300->udev->dev, "NO host QUIRKS for this card\n"); dev_info(&vub300->udev->dev, "NO host QUIRKS for this card\n");
......
...@@ -108,7 +108,6 @@ struct tmio_mmc_data { ...@@ -108,7 +108,6 @@ struct tmio_mmc_data {
unsigned int cd_gpio; unsigned int cd_gpio;
void (*set_pwr)(struct platform_device *host, int state); void (*set_pwr)(struct platform_device *host, int state);
void (*set_clk_div)(struct platform_device *host, int state); void (*set_clk_div)(struct platform_device *host, int state);
int (*get_cd)(struct platform_device *host);
int (*write16_hook)(struct tmio_mmc_host *host, int addr); int (*write16_hook)(struct tmio_mmc_host *host, int addr);
/* clock management callbacks */ /* clock management callbacks */
int (*clk_enable)(struct platform_device *pdev, unsigned int *f); int (*clk_enable)(struct platform_device *pdev, unsigned int *f);
......
...@@ -208,6 +208,8 @@ static inline void mmc_claim_host(struct mmc_host *host) ...@@ -208,6 +208,8 @@ static inline void mmc_claim_host(struct mmc_host *host)
__mmc_claim_host(host, NULL); __mmc_claim_host(host, NULL);
} }
struct device_node;
extern u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max); extern u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
extern int mmc_of_parse_voltage(struct device_node *np, u32 *mask);
#endif /* LINUX_MMC_CORE_H */ #endif /* LINUX_MMC_CORE_H */
...@@ -171,6 +171,7 @@ struct sdhci_host { ...@@ -171,6 +171,7 @@ struct sdhci_host {
unsigned int ocr_avail_sdio; /* OCR bit masks */ unsigned int ocr_avail_sdio; /* OCR bit masks */
unsigned int ocr_avail_sd; unsigned int ocr_avail_sd;
unsigned int ocr_avail_mmc; unsigned int ocr_avail_mmc;
u32 ocr_mask; /* available voltages */
wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */ wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */
unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */ unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/sh_dma.h>
/* /*
* MMCIF : CE_CLK_CTRL [19:16] * MMCIF : CE_CLK_CTRL [19:16]
...@@ -33,12 +32,12 @@ ...@@ -33,12 +32,12 @@
*/ */
struct sh_mmcif_plat_data { struct sh_mmcif_plat_data {
void (*set_pwr)(struct platform_device *pdev, int state);
void (*down_pwr)(struct platform_device *pdev);
int (*get_cd)(struct platform_device *pdef); int (*get_cd)(struct platform_device *pdef);
unsigned int slave_id_tx; /* embedded slave_id_[tr]x */ unsigned int slave_id_tx; /* embedded slave_id_[tr]x */
unsigned int slave_id_rx; unsigned int slave_id_rx;
bool use_cd_gpio : 1; bool use_cd_gpio : 1;
bool ccs_unsupported : 1;
bool clk_ctrl2_present : 1;
unsigned int cd_gpio; unsigned int cd_gpio;
u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */ u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */
unsigned long caps; unsigned long caps;
...@@ -62,6 +61,7 @@ struct sh_mmcif_plat_data { ...@@ -62,6 +61,7 @@ struct sh_mmcif_plat_data {
#define MMCIF_CE_INT_MASK 0x00000044 #define MMCIF_CE_INT_MASK 0x00000044
#define MMCIF_CE_HOST_STS1 0x00000048 #define MMCIF_CE_HOST_STS1 0x00000048
#define MMCIF_CE_HOST_STS2 0x0000004C #define MMCIF_CE_HOST_STS2 0x0000004C
#define MMCIF_CE_CLK_CTRL2 0x00000070
#define MMCIF_CE_VERSION 0x0000007C #define MMCIF_CE_VERSION 0x0000007C
/* CE_BUF_ACC */ /* CE_BUF_ACC */
......
...@@ -25,8 +25,6 @@ struct sh_mobile_sdhi_info { ...@@ -25,8 +25,6 @@ struct sh_mobile_sdhi_info {
unsigned long tmio_caps2; unsigned long tmio_caps2;
u32 tmio_ocr_mask; /* available MMC voltages */ u32 tmio_ocr_mask; /* available MMC voltages */
unsigned int cd_gpio; unsigned int cd_gpio;
void (*set_pwr)(struct platform_device *pdev, int state);
int (*get_cd)(struct platform_device *pdev);
/* callbacks for board specific setup code */ /* callbacks for board specific setup code */
int (*init)(struct platform_device *pdev, int (*init)(struct platform_device *pdev,
......
...@@ -18,7 +18,8 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio); ...@@ -18,7 +18,8 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio);
void mmc_gpio_free_ro(struct mmc_host *host); void mmc_gpio_free_ro(struct mmc_host *host);
int mmc_gpio_get_cd(struct mmc_host *host); int mmc_gpio_get_cd(struct mmc_host *host);
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio); int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
unsigned int debounce);
void mmc_gpio_free_cd(struct mmc_host *host); void mmc_gpio_free_cd(struct mmc_host *host);
#endif #endif
...@@ -7,6 +7,11 @@ ...@@ -7,6 +7,11 @@
struct device; struct device;
struct mmc_host; struct mmc_host;
#define MMC_SPI_USE_CD_GPIO (1 << 0)
#define MMC_SPI_USE_RO_GPIO (1 << 1)
#define MMC_SPI_CD_GPIO_ACTIVE_LOW (1 << 2)
#define MMC_SPI_RO_GPIO_ACTIVE_LOW (1 << 3)
/* Put this in platform_data of a device being used to manage an MMC/SD /* Put this in platform_data of a device being used to manage an MMC/SD
* card slot. (Modeled after PXA mmc glue; see that for usage examples.) * card slot. (Modeled after PXA mmc glue; see that for usage examples.)
* *
...@@ -21,17 +26,19 @@ struct mmc_spi_platform_data { ...@@ -21,17 +26,19 @@ struct mmc_spi_platform_data {
void *); void *);
void (*exit)(struct device *, void *); void (*exit)(struct device *, void *);
/* sense switch on sd cards */
int (*get_ro)(struct device *);
/* /*
* If board does not use CD interrupts, driver can optimize polling * Card Detect and Read Only GPIOs. To enable debouncing on the card
* using this function. * detect GPIO, set the cd_debounce to the debounce time in
* microseconds.
*/ */
int (*get_cd)(struct device *); unsigned int flags;
unsigned int cd_gpio;
unsigned int cd_debounce;
unsigned int ro_gpio;
/* Capabilities to pass into mmc core (e.g. MMC_CAP_NEEDS_POLL). */ /* Capabilities to pass into mmc core (e.g. MMC_CAP_NEEDS_POLL). */
unsigned long caps; unsigned long caps;
unsigned long caps2;
/* how long to debounce card detect, in msecs */ /* how long to debounce card detect, in msecs */
u16 detect_delay; u16 detect_delay;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment