Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0048f0b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ Optional properties:
    "bus-width = <1>" property.
  - sdhci,auto-cmd12: specifies that a controller can only handle auto
    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:

@@ -29,4 +32,5 @@ sdhci@2e000 {
	interrupt-parent = <&ipic>;
	/* Filled in by U-Boot */
	clock-frequency = <0>;
	voltage-ranges = <3300 3300>;
};
+5 −52
Original line number Diff line number Diff line
@@ -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_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 = {
	.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,
	.powerup_msecs	= 100,
	.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)
+8 −81
Original line number Diff line number Diff line
@@ -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 = {
	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
	.set_pwr	= sdhi0_set_pwr,
	.tmio_caps      = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
			  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[] = {
@@ -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)
/* SDHI1 */
static int sdhi1_get_cd(struct platform_device *pdev)
{
	return !gpio_get_value(GPIO_PTW7);
}

static struct sh_mobile_sdhi_info sdhi1_info = {
	.dma_slave_tx	= SHDMA_SLAVE_SDHI1_TX,
	.dma_slave_rx	= SHDMA_SLAVE_SDHI1_RX,
	.tmio_caps      = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
			  MMC_CAP_NEEDS_POLL,
	.set_pwr	= cn12_set_pwr,
	.get_cd		= sdhi1_get_cd,
	.tmio_flags	= TMIO_MMC_USE_GPIO_CD,
	.cd_gpio	= GPIO_PTW7,
};

static struct resource sdhi1_resources[] = {
@@ -718,27 +670,19 @@ static struct platform_device sdhi1_device = {
#else

/* 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)
{
	gpio_set_value(GPIO_PTB6, maskval ? 1 : 0);
}

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,
	.caps2 = MMC_CAP2_RO_ACTIVE_HIGH,
	.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, /* 3.3V only */
	.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[] = {
@@ -998,11 +942,6 @@ static struct platform_device vou_device = {

#if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE)
/* SH_MMCIF */
static void mmcif_down_pwr(struct platform_device *pdev)
{
	cn12_set_pwr(pdev, 0);
}

static struct resource sh_mmcif_resources[] = {
	[0] = {
		.name	= "SH_MMCIF",
@@ -1023,8 +962,6 @@ static struct resource sh_mmcif_resources[] = {
};

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 */
	.caps		= MMC_CAP_4_BIT_DATA |
			  MMC_CAP_8_BIT_DATA |
@@ -1341,10 +1278,6 @@ static int __init arch_setup(void)
	gpio_direction_input(GPIO_PTR6);

	/* 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)
	/* enable SDHI0 on CN11 (needs DS2.4 set to ON) */
	gpio_request(GPIO_FN_SDHI0WP,  NULL);
@@ -1363,8 +1296,6 @@ static int __init arch_setup(void)
	gpio_direction_output(GPIO_PTM4, 1); /* active low CS */
	gpio_request(GPIO_PTB6, NULL); /* 3.3V power control */
	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));
#endif
@@ -1394,10 +1325,6 @@ static int __init arch_setup(void)
	gpio_request(GPIO_FN_SDHI1D1,  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;
#endif

+43 −4
Original line number Diff line number Diff line
@@ -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.
 */
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;
	u32 status, stop_status = 0;
@@ -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))
		*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
	 * 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,
			return ERR_ABORT;
		if (stop_status & R1_CARD_ECC_FAILED)
			*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 */
@@ -1097,7 +1114,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
						    mmc_active);
	struct mmc_blk_request *brq = &mq_mrq->brq;
	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
@@ -1111,7 +1128,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
	 */
	if (brq->sbc.error || brq->cmd.error || brq->stop.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:
			return MMC_BLK_RETRY;
		case ERR_ABORT:
@@ -1143,6 +1160,14 @@ static int mmc_blk_err_check(struct mmc_card *card,
		u32 status;
		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);
		do {
			int err = get_card_status(card, &status, 5);
@@ -1152,6 +1177,13 @@ static int mmc_blk_err_check(struct mmc_card *card,
				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
			 * and never leaves the program state.
			 */
@@ -1171,6 +1203,13 @@ static int mmc_blk_err_check(struct mmc_card *card,
			 (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) {
		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,
@@ -2191,10 +2230,10 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
		 * is freeing the queue that stops new requests
		 * from being accepted.
		 */
		card = md->queue.card;
		mmc_cleanup_queue(&md->queue);
		if (md->flags & MMC_BLK_PACKED_CMD)
			mmc_packed_clean(&md->queue);
		card = md->queue.card;
		if (md->disk->flags & GENHD_FL_UP) {
			device_remove_file(disk_to_dev(md->disk), &md->force_ro);
			if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
+4 −10
Original line number Diff line number Diff line
@@ -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 mmc_card *card = (struct mmc_card *)sf->private;
	struct mmc_test_card *test;
	char lbuf[12];
	long testcase;
	int ret;

	if (count >= sizeof(lbuf))
		return -EINVAL;

	if (copy_from_user(lbuf, buf, count))
		return -EFAULT;
	lbuf[count] = '\0';

	if (strict_strtol(lbuf, 10, &testcase))
		return -EINVAL;
	ret = kstrtol_from_user(buf, count, 10, &testcase);
	if (ret)
		return ret;

	test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
	if (!test)
Loading