diff options
Diffstat (limited to 'drivers/mmc')
| -rw-r--r-- | drivers/mmc/core/core.c | 6 | ||||
| -rw-r--r-- | drivers/mmc/core/host.c | 4 | ||||
| -rw-r--r-- | drivers/mmc/host/pxamci.c | 66 | ||||
| -rw-r--r-- | drivers/mmc/host/sunxi-mmc.c | 53 | 
4 files changed, 67 insertions, 62 deletions
| diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 0520064dc33b..a3eb20bdcd97 100644 --- a/drivers/mmc/core/core.c +++ b/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)) { diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index abd933b7029b..5466f25f0281 100644 --- a/drivers/mmc/core/host.c +++ b/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")) diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 1420f29628c7..8cadd74e8407 100644 --- a/drivers/mmc/host/pxamci.c +++ b/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); diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index a7b7a6771598..b981b8552e43 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/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) |