mmc: jz4740: Introduce devicetree probe

Add support to probe the device via devicetree, which
will be used to support other SoCs such as the JZ4780.

Based on commits from the CI20 repo, by Paul Cercueil
and Alex Smith. Binding document based on work by
Zubair Lutfullah Kakakhel.

Tested-by: Mathieu Malaterre <malat@debian.org>
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.co.uk>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
Ezequiel Garcia 2018-03-28 18:00:48 -03:00 committed by Ulf Hansson
parent 436a3cfddc
commit 61e11eba23
1 changed files with 41 additions and 10 deletions

View File

@ -26,6 +26,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/scatterlist.h>
@ -107,6 +108,10 @@
#define JZ_MMC_CLK_RATE 24000000
enum jz4740_mmc_version {
JZ_MMC_JZ4740,
};
enum jz4740_mmc_state {
JZ4740_MMC_STATE_READ_RESPONSE,
JZ4740_MMC_STATE_TRANSFER_DATA,
@ -125,6 +130,8 @@ struct jz4740_mmc_host {
struct jz4740_mmc_platform_data *pdata;
struct clk *clk;
enum jz4740_mmc_version version;
int irq;
int card_detect_irq;
@ -857,7 +864,7 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
switch (ios->power_mode) {
case MMC_POWER_UP:
jz4740_mmc_reset(host);
if (gpio_is_valid(host->pdata->gpio_power))
if (host->pdata && gpio_is_valid(host->pdata->gpio_power))
gpio_set_value(host->pdata->gpio_power,
!host->pdata->power_active_low);
host->cmdat |= JZ_MMC_CMDAT_INIT;
@ -866,7 +873,7 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_POWER_ON:
break;
default:
if (gpio_is_valid(host->pdata->gpio_power))
if (host->pdata && gpio_is_valid(host->pdata->gpio_power))
gpio_set_value(host->pdata->gpio_power,
host->pdata->power_active_low);
clk_disable_unprepare(host->clk);
@ -964,11 +971,18 @@ static void jz4740_mmc_free_gpios(struct platform_device *pdev)
gpio_free(pdata->gpio_power);
}
static const struct of_device_id jz4740_mmc_of_match[] = {
{ .compatible = "ingenic,jz4740-mmc", .data = (void *) JZ_MMC_JZ4740 },
{},
};
MODULE_DEVICE_TABLE(of, jz4740_mmc_of_match);
static int jz4740_mmc_probe(struct platform_device* pdev)
{
int ret;
struct mmc_host *mmc;
struct jz4740_mmc_host *host;
const struct of_device_id *match;
struct jz4740_mmc_platform_data *pdata;
pdata = dev_get_platdata(&pdev->dev);
@ -982,6 +996,27 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
host = mmc_priv(mmc);
host->pdata = pdata;
match = of_match_device(jz4740_mmc_of_match, &pdev->dev);
if (match) {
host->version = (enum jz4740_mmc_version)match->data;
ret = mmc_of_parse(mmc);
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"could not parse of data: %d\n", ret);
goto err_free_host;
}
} else {
/* JZ4740 should be the only one using legacy probe */
host->version = JZ_MMC_JZ4740;
mmc->caps |= MMC_CAP_SDIO_IRQ;
if (!(pdata && pdata->data_1bit))
mmc->caps |= MMC_CAP_4_BIT_DATA;
ret = jz4740_mmc_request_gpios(mmc, pdev);
if (ret)
goto err_free_host;
}
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
ret = host->irq;
@ -1004,16 +1039,11 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
goto err_free_host;
}
ret = jz4740_mmc_request_gpios(mmc, pdev);
if (ret)
goto err_free_host;
mmc->ops = &jz4740_mmc_ops;
mmc->f_min = JZ_MMC_CLK_RATE / 128;
mmc->f_max = JZ_MMC_CLK_RATE;
if (!mmc->f_max)
mmc->f_max = JZ_MMC_CLK_RATE;
mmc->f_min = mmc->f_max / 128;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
mmc->caps = (pdata && pdata->data_1bit) ? 0 : MMC_CAP_4_BIT_DATA;
mmc->caps |= MMC_CAP_SDIO_IRQ;
mmc->max_blk_size = (1 << 10) - 1;
mmc->max_blk_count = (1 << 15) - 1;
@ -1118,6 +1148,7 @@ static struct platform_driver jz4740_mmc_driver = {
.remove = jz4740_mmc_remove,
.driver = {
.name = "jz4740-mmc",
.of_match_table = of_match_ptr(jz4740_mmc_of_match),
.pm = JZ4740_MMC_PM_OPS,
},
};