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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWDkvnAAoJEP4mhCVzWIwpfg4P/A2KXUrFNw4e0FbFGY49pgvs aqIYWy0g9DFWnki/yl1R/W9NmrpXeRFKRoilC1BGUGqWvWnjBRNObl66ZQ2gWOkb Xg7lZvhINs1ovqOAm6mCp8xr1sSShucoQ4TjKF2nV99BmuV0r5iHtCPFkpU7gAx7 9J+07Ksss/FoBiM6g+2ImVUKCp0HBe13lnXIL9GFv3QVXFNDzVyEoSqaP0GorjCj CD53BlNd8dE7IVme02q/xPuXJ7VuRrp8+tCORForfxvvLc2cy4eoIT43efQp10Fd FPnkWkDg+kmZaGg2clkN9igJja7WZzgMS1r7bZpgx9xc37BXfyv/D3zdWawM/zqJ FhKFGSreAY9mGQNR0kdHNfq4Gk4UV0c2T5BUYgk+OR6bqpXWitRkGYddLmk6q2mD YnNJ6qV9U9y1PlMajrkHNfkYRFitFQYmQfKY/VxqJrVZYSS4jt4k6BBEcfS0YQpu aRRLnx+G4uqYri1l7DyVfaq9GtO5EWyllgy1m8QNgrFJeV09oQXBcWQxjP3HQxqh NIVXVuSNG/5Imj1HX40i1Pa/NRvgd4HRE/QviM3Ukby9Nr2atXFdYWjn5jtMyqk9 KFwI6+dqSKKaxzVB30Mb3booEy6IdueWNc2Sg2pFj1Q5U3O2AofZwjoOHozvDoY1 lf+NQifwnJFloCCXMXLY =bo65 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
36f8dafe52
|
@ -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)) {
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue