Ver Fonte

Merge tag 'mmc-v4.3-rc3' of git://git.linaro.org/people/ulf.hansson/mmc

Pull MMC fixes from Ulf Hansson:
 "Here are some mmc fixes intended for v4.3 rc4:

  MMC core:
   - Allow users of mmc_of_parse() to succeed when CONFIG_GPIOLIB is
     unset
   - Prevent infinite loop of re-tuning for CRC-errors for CMD19 and
     CMD21

   MMC host:
   - pxamci: Fix issues with card detect
   - sunxi: Fix clk-delay settings"

* tag 'mmc-v4.3-rc3' of git://git.linaro.org/people/ulf.hansson/mmc:
  mmc: core: fix dead loop of mmc_retune
  mmc: pxamci: fix card detect with slot-gpio API
  mmc: sunxi: Fix clk-delay settings
  mmc: core: Don't return an error for CD/WP GPIOs when GPIOLIB is unset
Linus Torvalds há 10 anos atrás
pai
commit
36f8dafe52
4 ficheiros alterados com 67 adições e 62 exclusões
  1. 4 2
      drivers/mmc/core/core.c
  2. 2 2
      drivers/mmc/core/host.c
  3. 22 44
      drivers/mmc/host/pxamci.c
  4. 39 14
      drivers/mmc/host/sunxi-mmc.c

+ 4 - 2
drivers/mmc/core/core.c

@@ -134,9 +134,11 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
 	int err = cmd->error;
 
 	/* Flag re-tuning needed on CRC errors */
-	if (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) ||
+	if ((cmd->opcode != MMC_SEND_TUNING_BLOCK &&
+	    cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) &&
+	    (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) ||
 	    (mrq->data && mrq->data->error == -EILSEQ) ||
-	    (mrq->stop && mrq->stop->error == -EILSEQ))
+	    (mrq->stop && mrq->stop->error == -EILSEQ)))
 		mmc_retune_needed(host);
 
 	if (err && cmd->retries && mmc_host_is_spi(host)) {

+ 2 - 2
drivers/mmc/core/host.c

@@ -457,7 +457,7 @@ int mmc_of_parse(struct mmc_host *host)
 					   0, &cd_gpio_invert);
 		if (!ret)
 			dev_info(host->parent, "Got CD GPIO\n");
-		else if (ret != -ENOENT)
+		else if (ret != -ENOENT && ret != -ENOSYS)
 			return ret;
 
 		/*
@@ -481,7 +481,7 @@ int mmc_of_parse(struct mmc_host *host)
 	ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert);
 	if (!ret)
 		dev_info(host->parent, "Got WP GPIO\n");
-	else if (ret != -ENOENT)
+	else if (ret != -ENOENT && ret != -ENOSYS)
 		return ret;
 
 	if (of_property_read_bool(np, "disable-wp"))

+ 22 - 44
drivers/mmc/host/pxamci.c

@@ -28,6 +28,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/slot-gpio.h>
 #include <linux/io.h>
 #include <linux/regulator/consumer.h>
 #include <linux/gpio.h>
@@ -454,12 +455,8 @@ static int pxamci_get_ro(struct mmc_host *mmc)
 {
 	struct pxamci_host *host = mmc_priv(mmc);
 
-	if (host->pdata && gpio_is_valid(host->pdata->gpio_card_ro)) {
-		if (host->pdata->gpio_card_ro_invert)
-			return !gpio_get_value(host->pdata->gpio_card_ro);
-		else
-			return gpio_get_value(host->pdata->gpio_card_ro);
-	}
+	if (host->pdata && gpio_is_valid(host->pdata->gpio_card_ro))
+		return mmc_gpio_get_ro(mmc);
 	if (host->pdata && host->pdata->get_ro)
 		return !!host->pdata->get_ro(mmc_dev(mmc));
 	/*
@@ -551,6 +548,7 @@ static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable)
 
 static const struct mmc_host_ops pxamci_ops = {
 	.request		= pxamci_request,
+	.get_cd			= mmc_gpio_get_cd,
 	.get_ro			= pxamci_get_ro,
 	.set_ios		= pxamci_set_ios,
 	.enable_sdio_irq	= pxamci_enable_sdio_irq,
@@ -790,37 +788,31 @@ static int pxamci_probe(struct platform_device *pdev)
 		gpio_power = host->pdata->gpio_power;
 	}
 	if (gpio_is_valid(gpio_power)) {
-		ret = gpio_request(gpio_power, "mmc card power");
+		ret = devm_gpio_request(&pdev->dev, gpio_power,
+					"mmc card power");
 		if (ret) {
-			dev_err(&pdev->dev, "Failed requesting gpio_power %d\n", gpio_power);
+			dev_err(&pdev->dev, "Failed requesting gpio_power %d\n",
+				gpio_power);
 			goto out;
 		}
 		gpio_direction_output(gpio_power,
 				      host->pdata->gpio_power_invert);
 	}
-	if (gpio_is_valid(gpio_ro)) {
-		ret = gpio_request(gpio_ro, "mmc card read only");
-		if (ret) {
-			dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_ro);
-			goto err_gpio_ro;
-		}
-		gpio_direction_input(gpio_ro);
+	if (gpio_is_valid(gpio_ro))
+		ret = mmc_gpio_request_ro(mmc, gpio_ro);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_ro);
+		goto out;
+	} else {
+		mmc->caps |= host->pdata->gpio_card_ro_invert ?
+			MMC_CAP2_RO_ACTIVE_HIGH : 0;
 	}
-	if (gpio_is_valid(gpio_cd)) {
-		ret = gpio_request(gpio_cd, "mmc card detect");
-		if (ret) {
-			dev_err(&pdev->dev, "Failed requesting gpio_cd %d\n", gpio_cd);
-			goto err_gpio_cd;
-		}
-		gpio_direction_input(gpio_cd);
 
-		ret = request_irq(gpio_to_irq(gpio_cd), pxamci_detect_irq,
-				  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-				  "mmc card detect", mmc);
-		if (ret) {
-			dev_err(&pdev->dev, "failed to request card detect IRQ\n");
-			goto err_request_irq;
-		}
+	if (gpio_is_valid(gpio_cd))
+		ret = mmc_gpio_request_cd(mmc, gpio_cd, 0);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed requesting gpio_cd %d\n", gpio_cd);
+		goto out;
 	}
 
 	if (host->pdata && host->pdata->init)
@@ -835,13 +827,7 @@ static int pxamci_probe(struct platform_device *pdev)
 
 	return 0;
 
-err_request_irq:
-	gpio_free(gpio_cd);
-err_gpio_cd:
-	gpio_free(gpio_ro);
-err_gpio_ro:
-	gpio_free(gpio_power);
- out:
+out:
 	if (host) {
 		if (host->dma_chan_rx)
 			dma_release_channel(host->dma_chan_rx);
@@ -873,14 +859,6 @@ static int pxamci_remove(struct platform_device *pdev)
 			gpio_ro = host->pdata->gpio_card_ro;
 			gpio_power = host->pdata->gpio_power;
 		}
-		if (gpio_is_valid(gpio_cd)) {
-			free_irq(gpio_to_irq(gpio_cd), mmc);
-			gpio_free(gpio_cd);
-		}
-		if (gpio_is_valid(gpio_ro))
-			gpio_free(gpio_ro);
-		if (gpio_is_valid(gpio_power))
-			gpio_free(gpio_power);
 		if (host->vcc)
 			regulator_put(host->vcc);
 

+ 39 - 14
drivers/mmc/host/sunxi-mmc.c

@@ -210,6 +210,16 @@
 #define SDXC_IDMAC_DES0_CES	BIT(30) /* card error summary */
 #define SDXC_IDMAC_DES0_OWN	BIT(31) /* 1-idma owns it, 0-host owns it */
 
+#define SDXC_CLK_400K		0
+#define SDXC_CLK_25M		1
+#define SDXC_CLK_50M		2
+#define SDXC_CLK_50M_DDR	3
+
+struct sunxi_mmc_clk_delay {
+	u32 output;
+	u32 sample;
+};
+
 struct sunxi_idma_des {
 	u32	config;
 	u32	buf_size;
@@ -229,6 +239,7 @@ struct sunxi_mmc_host {
 	struct clk	*clk_mmc;
 	struct clk	*clk_sample;
 	struct clk	*clk_output;
+	const struct sunxi_mmc_clk_delay *clk_delays;
 
 	/* irq */
 	spinlock_t	lock;
@@ -654,25 +665,19 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
 
 	/* determine delays */
 	if (rate <= 400000) {
-		oclk_dly = 180;
-		sclk_dly = 42;
+		oclk_dly = host->clk_delays[SDXC_CLK_400K].output;
+		sclk_dly = host->clk_delays[SDXC_CLK_400K].sample;
 	} else if (rate <= 25000000) {
-		oclk_dly = 180;
-		sclk_dly = 75;
+		oclk_dly = host->clk_delays[SDXC_CLK_25M].output;
+		sclk_dly = host->clk_delays[SDXC_CLK_25M].sample;
 	} else if (rate <= 50000000) {
 		if (ios->timing == MMC_TIMING_UHS_DDR50) {
-			oclk_dly = 60;
-			sclk_dly = 120;
+			oclk_dly = host->clk_delays[SDXC_CLK_50M_DDR].output;
+			sclk_dly = host->clk_delays[SDXC_CLK_50M_DDR].sample;
 		} else {
-			oclk_dly = 90;
-			sclk_dly = 150;
+			oclk_dly = host->clk_delays[SDXC_CLK_50M].output;
+			sclk_dly = host->clk_delays[SDXC_CLK_50M].sample;
 		}
-	} else if (rate <= 100000000) {
-		oclk_dly = 6;
-		sclk_dly = 24;
-	} else if (rate <= 200000000) {
-		oclk_dly = 3;
-		sclk_dly = 12;
 	} else {
 		return -EINVAL;
 	}
@@ -871,6 +876,7 @@ static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 static const struct of_device_id sunxi_mmc_of_match[] = {
 	{ .compatible = "allwinner,sun4i-a10-mmc", },
 	{ .compatible = "allwinner,sun5i-a13-mmc", },
+	{ .compatible = "allwinner,sun9i-a80-mmc", },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
@@ -884,6 +890,20 @@ static struct mmc_host_ops sunxi_mmc_ops = {
 	.hw_reset	 = sunxi_mmc_hw_reset,
 };
 
+static const struct sunxi_mmc_clk_delay sunxi_mmc_clk_delays[] = {
+	[SDXC_CLK_400K]		= { .output = 180, .sample = 180 },
+	[SDXC_CLK_25M]		= { .output = 180, .sample =  75 },
+	[SDXC_CLK_50M]		= { .output =  90, .sample = 120 },
+	[SDXC_CLK_50M_DDR]	= { .output =  60, .sample = 120 },
+};
+
+static const struct sunxi_mmc_clk_delay sun9i_mmc_clk_delays[] = {
+	[SDXC_CLK_400K]		= { .output = 180, .sample = 180 },
+	[SDXC_CLK_25M]		= { .output = 180, .sample =  75 },
+	[SDXC_CLK_50M]		= { .output = 150, .sample = 120 },
+	[SDXC_CLK_50M_DDR]	= { .output =  90, .sample = 120 },
+};
+
 static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
 				      struct platform_device *pdev)
 {
@@ -895,6 +915,11 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
 	else
 		host->idma_des_size_bits = 16;
 
+	if (of_device_is_compatible(np, "allwinner,sun9i-a80-mmc"))
+		host->clk_delays = sun9i_mmc_clk_delays;
+	else
+		host->clk_delays = sunxi_mmc_clk_delays;
+
 	ret = mmc_regulator_get_supply(host->mmc);
 	if (ret) {
 		if (ret != -EPROBE_DEFER)