Date   

[PATCH 4.4.y-cip 54/83] mmc: tmio: Remove redundant check of mmc->slot.cd_irq

Biju Das <biju.das@...>
 

From: Ulf Hansson <ulf.hansson@...>

commit efd7be7bfc8eb8942ba3dc319f323cfd0eda99e2 upstream.

To validate whether native hotplug needs to be used, the tmio driver checks
whether the mmc->slot.cd_irq has been successfully assigned.

This check is redundant at its current place in tmio_mmc_host_probe(), as
the mmc core assigns mmc->slot.cd_irq a valid value first when
mmc_gpiod_request_cd_irq() is called. Therefore, let's just remove the
check for now, as that also removes a layering violation of the tmio driver
accessing core specific data via ->slot.cd_irq.

Signed-off-by: Ulf Hansson <ulf.hansson@...>
Reviewed-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/tmio_mmc_pio.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 4e38fcc..0f766f4 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -1178,8 +1178,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,

_host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD ||
mmc->caps & MMC_CAP_NEEDS_POLL ||
- mmc->caps & MMC_CAP_NONREMOVABLE ||
- mmc->slot.cd_irq >= 0);
+ !mmc_card_is_removable(mmc));

/*
* On Gen2+, eMMC with NONREMOVABLE currently fails because native
--
2.7.4


[PATCH 4.4.y-cip 53/83] mmc: host: tmio: drop superfluous exit path

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit ad7014b3949b6c2b6ce46a546d6d204b5643e621 upstream.

The probe exit path on error does nothing since commit 94b110aff8679b
("mmc: tmio: add tmio_mmc_host_alloc/free()"), so we can bail out
immediately.

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Reviewed-by: Simon Horman <horms+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/tmio_mmc_pio.c | 20 ++++++--------------
1 file changed, 6 insertions(+), 14 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 87f7aa7..4e38fcc 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -1146,7 +1146,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,

ret = mmc_of_parse(mmc);
if (ret < 0)
- goto host_free;
+ return ret;

_host->pdata = pdata;
platform_set_drvdata(pdev, mmc);
@@ -1156,14 +1156,12 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,

ret = tmio_mmc_init_ocr(_host);
if (ret < 0)
- goto host_free;
+ return ret;

_host->ctl = devm_ioremap(&pdev->dev,
res_ctl->start, resource_size(res_ctl));
- if (!_host->ctl) {
- ret = -ENOMEM;
- goto host_free;
- }
+ if (!_host->ctl)
+ return -ENOMEM;

tmio_mmc_ops.card_busy = _host->card_busy;
tmio_mmc_ops.start_signal_voltage_switch = _host->start_signal_voltage_switch;
@@ -1201,10 +1199,8 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,
* Check the sanity of mmc->f_min to prevent tmio_mmc_set_clock() from
* looping forever...
*/
- if (mmc->f_min == 0) {
- ret = -EINVAL;
- goto host_free;
- }
+ if (mmc->f_min == 0)
+ return -EINVAL;

/*
* While using internal tmio hardware logic for card detection, we need
@@ -1269,10 +1265,6 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,
}

return 0;
-
-host_free:
-
- return ret;
}
EXPORT_SYMBOL(tmio_mmc_host_probe);

--
2.7.4


[PATCH 4.4.y-cip 52/83] mmc: sh_mobile_sdhi: enable HS200

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit b1c95170f97ef19ff63a6da1eb2c70899186aecc upstream.

Setup tuning when the board is HS200 enabled.

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/sh_mobile_sdhi.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index d851535..8e90670 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -650,7 +650,9 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
goto efree;

/* Enable tuning iff we have an SCC and a supported mode */
- if (of_data && of_data->scc_offset && host->mmc->caps & MMC_CAP_UHS_SDR104) {
+ if (of_data && of_data->scc_offset &&
+ (host->mmc->caps & MMC_CAP_UHS_SDR104 ||
+ host->mmc->caps2 & MMC_CAP2_HS200_1_8V_SDR)) {
const struct sh_mobile_sdhi_scc *taps = of_data->taps;
bool hit = false;

--
2.7.4


[PATCH 4.4.y-cip 51/83] mmc: sh_mobile_sdhi: remove superfluous check in init_tuning

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit 7f9096f1c89ea698c22fde91285de2ef3eabd614 upstream.

The function will only be available if SDR104 was detected in probe,
so no need to check in the function itself again.

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/sh_mobile_sdhi.c | 3 ---
1 file changed, 3 deletions(-)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 59cc513..d851535 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -335,9 +335,6 @@ static unsigned int sh_mobile_sdhi_init_tuning(struct tmio_mmc_host *host)
{
struct sh_mobile_sdhi *priv;

- if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
- return 0;
-
priv = host_to_priv(host);

/* set sampling clock selection range */
--
2.7.4


[PATCH 4.4.y-cip 50/83] mmc: sh_mobile_sdhi: remove superfluous check in SCC error check

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit 03c5b0d90300fc725fc1fb644872b522483a2d7e upstream.

The function will only be available if SDR104 was detected in probe,
so no need to check in the function itself again.

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/sh_mobile_sdhi.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 30956c7..59cc513 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -444,12 +444,7 @@ static int sh_mobile_sdhi_select_tuning(struct tmio_mmc_host *host)

static bool sh_mobile_sdhi_check_scc_error(struct tmio_mmc_host *host)
{
- struct sh_mobile_sdhi *priv;
-
- if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
- return 0;
-
- priv = host_to_priv(host);
+ struct sh_mobile_sdhi *priv = host_to_priv(host);

/* Check SCC error */
if (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL) &
--
2.7.4


[PATCH 4.4.y-cip 49/83] mmc: sh_mobile_sdhi: improve prerequisites for tuning

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit e831ead3b3ddc4227cef10dc63d919fd7242d7b8 upstream.

Prerequisites for tuning are the same as for hw_reset. We need an SCC
and a supported mode. Populate the tuning related functions only when
those conditions are met. This also removes a tiny race window.
Previously, the functions were populated when the SCC offset was not
initialized which could have led to an OOPS.

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/sh_mobile_sdhi.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index d3d1db0..30956c7 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -617,11 +617,6 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
host->card_busy = sh_mobile_sdhi_card_busy;
host->start_signal_voltage_switch =
sh_mobile_sdhi_start_signal_voltage_switch;
- host->init_tuning = sh_mobile_sdhi_init_tuning;
- host->prepare_tuning = sh_mobile_sdhi_prepare_tuning;
- host->select_tuning = sh_mobile_sdhi_select_tuning;
- host->check_scc_error = sh_mobile_sdhi_check_scc_error;
- host->hw_reset = sh_mobile_sdhi_hw_reset;
}

/* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */
@@ -662,6 +657,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
if (ret < 0)
goto efree;

+ /* Enable tuning iff we have an SCC and a supported mode */
if (of_data && of_data->scc_offset && host->mmc->caps & MMC_CAP_UHS_SDR104) {
const struct sh_mobile_sdhi_scc *taps = of_data->taps;
bool hit = false;
@@ -681,6 +677,11 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n");

priv->scc_ctl = host->ctl + of_data->scc_offset;
+ host->init_tuning = sh_mobile_sdhi_init_tuning;
+ host->prepare_tuning = sh_mobile_sdhi_prepare_tuning;
+ host->select_tuning = sh_mobile_sdhi_select_tuning;
+ host->check_scc_error = sh_mobile_sdhi_check_scc_error;
+ host->hw_reset = sh_mobile_sdhi_hw_reset;
}

i = 0;
--
2.7.4


[PATCH 4.4.y-cip 48/83] mmc: sh_mobile_sdhi: remove superfluous check in hw_reset

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit 97c64b2cd57608f7064810780056d17944f49128 upstream.

The capability for HW_RESET is only activated if SDR104 is present, so
no need to check for SDR104 in the function itself again.

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/sh_mobile_sdhi.c | 3 ---
1 file changed, 3 deletions(-)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 9bf1f5e..d3d1db0 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -468,9 +468,6 @@ static void sh_mobile_sdhi_hw_reset(struct tmio_mmc_host *host)
{
struct sh_mobile_sdhi *priv;

- if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
- return;
-
priv = host_to_priv(host);

/* Reset SCC */
--
2.7.4


[PATCH 4.4.y-cip 47/83] mmc: sh_mobile_sdhi: improve prerequisite for hw_reset

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit 6ade9a2c2da855ff38e74c4298976400feca968e upstream.

We need a SCC unit for hw_reset. Those units can only be described in
of_data. So, of_data and a valid SCC offset are prerequisites for
enabling the hw_reset capability. Merge the two 'if' conditions into one
and add a check for an scc offset.

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Reviewed-by: Geert Uytterhoeven <geert+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/sh_mobile_sdhi.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 9af62dd..9bf1f5e 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -665,27 +665,25 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
if (ret < 0)
goto efree;

- if (host->mmc->caps & MMC_CAP_UHS_SDR104) {
+ if (of_data && of_data->scc_offset && host->mmc->caps & MMC_CAP_UHS_SDR104) {
+ const struct sh_mobile_sdhi_scc *taps = of_data->taps;
+ bool hit = false;
+
host->mmc->caps |= MMC_CAP_HW_RESET;

- if (of_data) {
- const struct sh_mobile_sdhi_scc *taps = of_data->taps;
- bool hit = false;
-
- for (i = 0; i < of_data->taps_num; i++) {
- if (taps[i].clk_rate == 0 ||
- taps[i].clk_rate == host->mmc->f_max) {
- host->scc_tappos = taps->tap;
- hit = true;
- break;
- }
+ for (i = 0; i < of_data->taps_num; i++) {
+ if (taps[i].clk_rate == 0 ||
+ taps[i].clk_rate == host->mmc->f_max) {
+ host->scc_tappos = taps->tap;
+ hit = true;
+ break;
}
+ }

- if (!hit)
- dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n");
+ if (!hit)
+ dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n");

- priv->scc_ctl = host->ctl + of_data->scc_offset;
- }
+ priv->scc_ctl = host->ctl + of_data->scc_offset;
}

i = 0;
--
2.7.4


[PATCH 4.4.y-cip 46/83] mmc: sh_mobile_sdhi: simplify accessing DT data

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit dc9f1a8d790ee766c47eca163261225680691e64 upstream.

By using the helper of_device_get_match_data(), we can skip some
checking and make the code simpler.

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Reviewed-by: Geert Uytterhoeven <geert+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/sh_mobile_sdhi.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index d1ec75c..9af62dd 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -555,8 +555,7 @@ static void sh_mobile_sdhi_enable_dma(struct tmio_mmc_host *host, bool enable)

static int sh_mobile_sdhi_probe(struct platform_device *pdev)
{
- const struct of_device_id *of_id =
- of_match_device(sh_mobile_sdhi_of_match, &pdev->dev);
+ const struct sh_mobile_sdhi_of_data *of_data = of_device_get_match_data(&pdev->dev);
struct sh_mobile_sdhi *priv;
struct tmio_mmc_data *mmc_data;
struct tmio_mmc_data *mmd = pdev->dev.platform_data;
@@ -597,9 +596,8 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
goto eprobe;
}

- if (of_id && of_id->data) {
- const struct sh_mobile_sdhi_of_data *of_data = of_id->data;

+ if (of_data) {
mmc_data->flags |= of_data->tmio_flags;
mmc_data->ocr_mask = of_data->tmio_ocr_mask;
mmc_data->capabilities |= of_data->capabilities;
@@ -670,14 +668,10 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
if (host->mmc->caps & MMC_CAP_UHS_SDR104) {
host->mmc->caps |= MMC_CAP_HW_RESET;

- if (of_id && of_id->data) {
- const struct sh_mobile_sdhi_of_data *of_data;
- const struct sh_mobile_sdhi_scc *taps;
+ if (of_data) {
+ const struct sh_mobile_sdhi_scc *taps = of_data->taps;
bool hit = false;

- of_data = of_id->data;
- taps = of_data->taps;
-
for (i = 0; i < of_data->taps_num; i++) {
if (taps[i].clk_rate == 0 ||
taps[i].clk_rate == host->mmc->f_max) {
--
2.7.4


[PATCH 4.4.y-cip 45/83] mmc: tmio: use SDIO master interrupt bit only when allowed

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit c51ff6c6180e76a1ba96aef799a9c41aa80fcc95 upstream.

The master bit to enable SDIO interrupts can only be accessed if
SCLKDIVEN bit allows that. However, the core uses the SDIO enable
callback at times when SCLKDIVEN forbids the change. This leads to
"timeout waiting for SD bus idle" messages.

We now activate the master bit in probe once if SDIO is supported. IRQ
en-/disabling will be done now by the individual IRQ enablement bits
only.

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Reviewed-by: Yasushi SHOJI <yashi@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/tmio_mmc_pio.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index fee72a9..87f7aa7 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -140,12 +140,10 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)

host->sdio_irq_mask = TMIO_SDIO_MASK_ALL &
~TMIO_SDIO_STAT_IOIRQ;
- sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask);
} else if (!enable && host->sdio_irq_enabled) {
host->sdio_irq_mask = TMIO_SDIO_MASK_ALL;
sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask);
- sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);

host->sdio_irq_enabled = false;
pm_runtime_mark_last_busy(mmc_dev(mmc));
@@ -1235,7 +1233,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,
if (pdata->flags & TMIO_MMC_SDIO_IRQ) {
_host->sdio_irq_mask = TMIO_SDIO_MASK_ALL;
sd_ctrl_write16(_host, CTL_SDIO_IRQ_MASK, _host->sdio_irq_mask);
- sd_ctrl_write16(_host, CTL_TRANSACTION_CTL, 0x0000);
+ sd_ctrl_write16(_host, CTL_TRANSACTION_CTL, 0x0001);
}

spin_lock_init(&_host->lock);
@@ -1283,6 +1281,9 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
struct platform_device *pdev = host->pdev;
struct mmc_host *mmc = host->mmc;

+ if (host->pdata->flags & TMIO_MMC_SDIO_IRQ)
+ sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
+
if (!host->native_hotplug)
pm_runtime_get_sync(&pdev->dev);

--
2.7.4


[PATCH 4.4.y-cip 44/83] mmc: tmio: remove SDIO from TODO list

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit e726e8c959fc735473f248e142de4d4f77ed342b upstream.

We surely have SDIO support by now :)

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Reviewed-by: Simon Horman <horms+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/tmio_mmc_pio.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 3a69ff5..fee72a9 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -22,7 +22,6 @@
* TODO:
* Investigate using a workqueue for PIO transfers
* Eliminate FIXMEs
- * SDIO support
* Better Power management
* Handle MMC errors better
* double buffer support
--
2.7.4


[PATCH 4.4.y-cip 43/83] mmc: tmio: fix wrong bitmask for SDIO irqs

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit 0c4bf5beff79fd32c5a3b2b511ed6527861ada18 upstream.

Commit 7729c7a232a953 ("mmc: tmio: Provide separate interrupt handlers")
refactored the sdio irq handler and wrongly used the mask for SD irqs,
not for SDIO irqs. This doesn't really matter in practice because both
values keep the only interrupt we are interested in. But still, this is
wrong and wants to be fixed.

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Reviewed-by: Simon Horman <horms+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/tmio_mmc_pio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 37703bf..3a69ff5 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -724,7 +724,7 @@ static bool tmio_mmc_sdio_irq(int irq, void *devid)
return false;

status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
- ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdcard_irq_mask;
+ ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdio_irq_mask;

sdio_status = status & ~TMIO_SDIO_MASK_ALL;
if (pdata->flags & TMIO_MMC_SDIO_STATUS_QUIRK)
--
2.7.4


[PATCH 4.4.y-cip 42/83] mmc: sh_mobile_sdhi: Add tuning support

Biju Das <biju.das@...>
 

From: Simon Horman <horms+renesas@...>

commit 06f438dd389a699d27585f2a4d3685fd1ce05a75 upstream.

Add tuning support for use with SDR104 mode
This includes adding support for the sampling clock controller (SCC).

Based on work by Ai Kyuse.

Cc: Ai Kyuse <ai.kyuse.uw@...>
Signed-off-by: Simon Horman <horms+renesas@...>
Acked-by: Wolfram Sang <wsa+renesas@...>
Tested-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/sh_mobile_sdhi.c | 265 +++++++++++++++++++++++++++++++++++++-
1 file changed, 264 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 9124246..d1ec75c 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -47,6 +47,11 @@

#define host_to_priv(host) container_of((host)->pdata, struct sh_mobile_sdhi, mmc_data)

+struct sh_mobile_sdhi_scc {
+ unsigned long clk_rate; /* clock rate for SDR104 */
+ u32 tap; /* sampling clock position for SDR104 */
+};
+
struct sh_mobile_sdhi_of_data {
unsigned long tmio_flags;
u32 tmio_ocr_mask;
@@ -55,6 +60,9 @@ struct sh_mobile_sdhi_of_data {
enum dma_slave_buswidth dma_buswidth;
dma_addr_t dma_rx_offset;
unsigned bus_shift;
+ int scc_offset;
+ struct sh_mobile_sdhi_scc *taps;
+ int taps_num;
};

static const struct sh_mobile_sdhi_of_data sh_mobile_sdhi_of_cfg[] = {
@@ -69,12 +77,35 @@ static const struct sh_mobile_sdhi_of_data of_rcar_gen1_compatible = {
.capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
};

+/* Definitions for sampling clocks */
+static struct sh_mobile_sdhi_scc rcar_gen2_scc_taps[] = {
+ {
+ .clk_rate = 156000000,
+ .tap = 0x00000703,
+ },
+ {
+ .clk_rate = 0,
+ .tap = 0x00000300,
+ },
+};
+
static const struct sh_mobile_sdhi_of_data of_rcar_gen2_compatible = {
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE |
TMIO_MMC_CLK_ACTUAL | TMIO_MMC_MIN_RCAR2,
.capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
.dma_buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES,
.dma_rx_offset = 0x2000,
+ .scc_offset = 0x0300,
+ .taps = rcar_gen2_scc_taps,
+ .taps_num = ARRAY_SIZE(rcar_gen2_scc_taps),
+};
+
+/* Definitions for sampling clocks */
+static struct sh_mobile_sdhi_scc rcar_gen3_scc_taps[] = {
+ {
+ .clk_rate = 0,
+ .tap = 0x00000300,
+ },
};

static const struct sh_mobile_sdhi_of_data of_rcar_gen3_compatible = {
@@ -82,6 +113,9 @@ static const struct sh_mobile_sdhi_of_data of_rcar_gen3_compatible = {
TMIO_MMC_CLK_ACTUAL | TMIO_MMC_MIN_RCAR2,
.capabilities = MMC_CAP_SD_HIGHSPEED,
.bus_shift = 2,
+ .scc_offset = 0x1000,
+ .taps = rcar_gen3_scc_taps,
+ .taps_num = ARRAY_SIZE(rcar_gen3_scc_taps),
};

static const struct of_device_id sh_mobile_sdhi_of_match[] = {
@@ -109,6 +143,7 @@ struct sh_mobile_sdhi {
struct tmio_mmc_dma dma_priv;
struct pinctrl *pinctrl;
struct pinctrl_state *pins_default, *pins_uhs;
+ void __iomem *scc_ctl;
};

static void sh_mobile_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width)
@@ -263,6 +298,201 @@ static int sh_mobile_sdhi_start_signal_voltage_switch(struct mmc_host *mmc,
return 0;
}

+/* SCC registers */
+#define SH_MOBILE_SDHI_SCC_DTCNTL 0x000
+#define SH_MOBILE_SDHI_SCC_TAPSET 0x002
+#define SH_MOBILE_SDHI_SCC_DT2FF 0x004
+#define SH_MOBILE_SDHI_SCC_CKSEL 0x006
+#define SH_MOBILE_SDHI_SCC_RVSCNTL 0x008
+#define SH_MOBILE_SDHI_SCC_RVSREQ 0x00A
+
+/* Definitions for values the SH_MOBILE_SDHI_SCC_DTCNTL register */
+#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN BIT(0)
+#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT 16
+#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_MASK 0xff
+
+/* Definitions for values the SH_MOBILE_SDHI_SCC_CKSEL register */
+#define SH_MOBILE_SDHI_SCC_CKSEL_DTSEL BIT(0)
+/* Definitions for values the SH_MOBILE_SDHI_SCC_RVSCNTL register */
+#define SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN BIT(0)
+/* Definitions for values the SH_MOBILE_SDHI_SCC_RVSREQ register */
+#define SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR BIT(2)
+
+static inline u32 sd_scc_read32(struct tmio_mmc_host *host,
+ struct sh_mobile_sdhi *priv, int addr)
+{
+ return readl(priv->scc_ctl + (addr << host->bus_shift));
+}
+
+static inline void sd_scc_write32(struct tmio_mmc_host *host,
+ struct sh_mobile_sdhi *priv,
+ int addr, u32 val)
+{
+ writel(val, priv->scc_ctl + (addr << host->bus_shift));
+}
+
+static unsigned int sh_mobile_sdhi_init_tuning(struct tmio_mmc_host *host)
+{
+ struct sh_mobile_sdhi *priv;
+
+ if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
+ return 0;
+
+ priv = host_to_priv(host);
+
+ /* set sampling clock selection range */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
+ 0x8 << SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT);
+
+ /* Initialize SCC */
+ sd_ctrl_write32_as_16_and_16(host, CTL_STATUS, 0x0);
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
+ SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN |
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL));
+
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
+ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL,
+ SH_MOBILE_SDHI_SCC_CKSEL_DTSEL |
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL));
+
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
+ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+ ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, host->scc_tappos);
+
+ /* Read TAPNUM */
+ return (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL) >>
+ SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) &
+ SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_MASK;
+}
+
+static void sh_mobile_sdhi_prepare_tuning(struct tmio_mmc_host *host,
+ unsigned long tap)
+{
+ struct sh_mobile_sdhi *priv = host_to_priv(host);
+
+ /* Set sampling clock position */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, tap);
+}
+
+#define SH_MOBILE_SDHI_MAX_TAP 3
+
+static int sh_mobile_sdhi_select_tuning(struct tmio_mmc_host *host)
+{
+ struct sh_mobile_sdhi *priv = host_to_priv(host);
+ unsigned long tap_cnt; /* counter of tuning success */
+ unsigned long tap_set; /* tap position */
+ unsigned long tap_start;/* start position of tuning success */
+ unsigned long tap_end; /* end position of tuning success */
+ unsigned long ntap; /* temporary counter of tuning success */
+ unsigned long i;
+
+ /* Clear SCC_RVSREQ */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0);
+
+ /*
+ * Find the longest consecutive run of successful probes. If that
+ * is more than SH_MOBILE_SDHI_MAX_TAP probes long then use the
+ * center index as the tap.
+ */
+ tap_cnt = 0;
+ ntap = 0;
+ tap_start = 0;
+ tap_end = 0;
+ for (i = 0; i < host->tap_num * 2; i++) {
+ if (test_bit(i, host->taps))
+ ntap++;
+ else {
+ if (ntap > tap_cnt) {
+ tap_start = i - ntap;
+ tap_end = i - 1;
+ tap_cnt = ntap;
+ }
+ ntap = 0;
+ }
+ }
+
+ if (ntap > tap_cnt) {
+ tap_start = i - ntap;
+ tap_end = i - 1;
+ tap_cnt = ntap;
+ }
+
+ if (tap_cnt >= SH_MOBILE_SDHI_MAX_TAP)
+ tap_set = (tap_start + tap_end) / 2 % host->tap_num;
+ else
+ return -EIO;
+
+ /* Set SCC */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, tap_set);
+
+ /* Enable auto re-tuning */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+ SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN |
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+
+ return 0;
+}
+
+
+static bool sh_mobile_sdhi_check_scc_error(struct tmio_mmc_host *host)
+{
+ struct sh_mobile_sdhi *priv;
+
+ if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
+ return 0;
+
+ priv = host_to_priv(host);
+
+ /* Check SCC error */
+ if (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL) &
+ SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &&
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ) &
+ SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR) {
+ /* Clear SCC error */
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0);
+ return true;
+ }
+
+ return false;
+}
+
+static void sh_mobile_sdhi_hw_reset(struct tmio_mmc_host *host)
+{
+ struct sh_mobile_sdhi *priv;
+
+ if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
+ return;
+
+ priv = host_to_priv(host);
+
+ /* Reset SCC */
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
+ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL,
+ ~SH_MOBILE_SDHI_SCC_CKSEL_DTSEL &
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL));
+
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
+ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+ ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+
+ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+ ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &
+ sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+}
+
static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
{
int timeout = 1000;
@@ -332,7 +562,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
struct tmio_mmc_data *mmd = pdev->dev.platform_data;
struct tmio_mmc_host *host;
struct resource *res;
- int irq, ret, i = 0;
+ int irq, ret, i;
struct tmio_mmc_dma *dma_priv;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -392,6 +622,11 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
host->card_busy = sh_mobile_sdhi_card_busy;
host->start_signal_voltage_switch =
sh_mobile_sdhi_start_signal_voltage_switch;
+ host->init_tuning = sh_mobile_sdhi_init_tuning;
+ host->prepare_tuning = sh_mobile_sdhi_prepare_tuning;
+ host->select_tuning = sh_mobile_sdhi_select_tuning;
+ host->check_scc_error = sh_mobile_sdhi_check_scc_error;
+ host->hw_reset = sh_mobile_sdhi_hw_reset;
}

/* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */
@@ -432,6 +667,34 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
if (ret < 0)
goto efree;

+ if (host->mmc->caps & MMC_CAP_UHS_SDR104) {
+ host->mmc->caps |= MMC_CAP_HW_RESET;
+
+ if (of_id && of_id->data) {
+ const struct sh_mobile_sdhi_of_data *of_data;
+ const struct sh_mobile_sdhi_scc *taps;
+ bool hit = false;
+
+ of_data = of_id->data;
+ taps = of_data->taps;
+
+ for (i = 0; i < of_data->taps_num; i++) {
+ if (taps[i].clk_rate == 0 ||
+ taps[i].clk_rate == host->mmc->f_max) {
+ host->scc_tappos = taps->tap;
+ hit = true;
+ break;
+ }
+ }
+
+ if (!hit)
+ dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n");
+
+ priv->scc_ctl = host->ctl + of_data->scc_offset;
+ }
+ }
+
+ i = 0;
while (1) {
irq = platform_get_irq(pdev, i);
if (irq < 0)
--
2.7.4


[PATCH 4.4.y-cip 41/83] mmc: tmio: Add tuning support

Biju Das <biju.das@...>
 

From: Ai Kyuse <ai.kyuse.uw@...>

commit 4f11997773b6b452b5a0d620c5ac5050e75c227e upstream.

Add tuning support for use with SDR104 mode

Signed-off-by: Ai Kyuse <ai.kyuse.uw@...>
Signed-off-by: Simon Horman <horms+renesas@...>
Acked-by: Wolfram Sang <wsa+renesas@...>
Tested-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/tmio_mmc.h | 14 ++++++++++
drivers/mmc/host/tmio_mmc_pio.c | 62 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 76 insertions(+)

diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 8b4869e..ba2838c 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -153,6 +153,7 @@ struct tmio_mmc_host {
struct mutex ios_lock; /* protect set_ios() context */
bool native_hotplug;
bool sdio_irq_enabled;
+ u32 scc_tappos;

/* Mandatory callback */
int (*clk_enable)(struct tmio_mmc_host *host);
@@ -168,6 +169,19 @@ struct tmio_mmc_host {
struct mmc_ios *ios);
int (*write16_hook)(struct tmio_mmc_host *host, int addr);
void (*hw_reset)(struct tmio_mmc_host *host);
+ void (*prepare_tuning)(struct tmio_mmc_host *host, unsigned long tap);
+ bool (*check_scc_error)(struct tmio_mmc_host *host);
+
+ /*
+ * Mandatory callback for tuning to occur which is optional for SDR50
+ * and mandatory for SDR104.
+ */
+ unsigned int (*init_tuning)(struct tmio_mmc_host *host);
+ int (*select_tuning)(struct tmio_mmc_host *host);
+
+ /* Tuning values: 1 for success, 0 for failure */
+ DECLARE_BITMAP(taps, BITS_PER_BYTE * sizeof(long));
+ unsigned int tap_num;
};

struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev);
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 4bb0553..37703bf 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -36,6 +36,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/mfd/tmio.h>
+#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/slot-gpio.h>
@@ -298,6 +299,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
if (mrq->cmd->error || (mrq->data && mrq->data->error))
tmio_mmc_abort_dma(host);

+ if (host->check_scc_error)
+ host->check_scc_error(host);
+
mmc_request_done(host->mmc, mrq);
}

@@ -800,6 +804,55 @@ static void tmio_mmc_hw_reset(struct mmc_host *mmc)
host->hw_reset(host);
}

+static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct tmio_mmc_host *host = mmc_priv(mmc);
+ int i, ret = 0;
+
+ if (!host->tap_num) {
+ if (!host->init_tuning || !host->select_tuning)
+ /* Tuning is not supported */
+ goto out;
+
+ host->tap_num = host->init_tuning(host);
+ if (!host->tap_num)
+ /* Tuning is not supported */
+ goto out;
+ }
+
+ if (host->tap_num * 2 >= sizeof(host->taps) * BITS_PER_BYTE) {
+ dev_warn_once(&host->pdev->dev,
+ "Too many taps, skipping tuning. Please consider updating size of taps field of tmio_mmc_host\n");
+ goto out;
+ }
+
+ bitmap_zero(host->taps, host->tap_num * 2);
+
+ /* Issue CMD19 twice for each tap */
+ for (i = 0; i < 2 * host->tap_num; i++) {
+ if (host->prepare_tuning)
+ host->prepare_tuning(host, i % host->tap_num);
+
+ ret = mmc_send_tuning(mmc, opcode, NULL);
+ if (ret && ret != -EILSEQ)
+ goto out;
+ if (ret == 0)
+ set_bit(i, host->taps);
+
+ mdelay(1);
+ }
+
+ ret = host->select_tuning(host);
+
+out:
+ if (ret < 0) {
+ dev_warn(&host->pdev->dev, "Tuning procedure failed\n");
+ tmio_mmc_hw_reset(mmc);
+ }
+
+ return ret;
+}
+
/* Process requests from the MMC layer */
static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
@@ -1017,6 +1070,7 @@ static struct mmc_host_ops tmio_mmc_ops = {
.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
.multi_io_quirk = tmio_multi_io_quirk,
.hw_reset = tmio_mmc_hw_reset,
+ .execute_tuning = tmio_mmc_execute_tuning,
};

static int tmio_mmc_init_ocr(struct tmio_mmc_host *host)
@@ -1263,6 +1317,11 @@ int tmio_mmc_host_runtime_suspend(struct device *dev)
}
EXPORT_SYMBOL(tmio_mmc_host_runtime_suspend);

+static bool tmio_mmc_can_retune(struct tmio_mmc_host *host)
+{
+ return host->tap_num && mmc_can_retune(host->mmc);
+}
+
int tmio_mmc_host_runtime_resume(struct device *dev)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
@@ -1276,6 +1335,9 @@ int tmio_mmc_host_runtime_resume(struct device *dev)

tmio_mmc_enable_dma(host, true);

+ if (tmio_mmc_can_retune(host) && host->select_tuning(host))
+ dev_warn(&host->pdev->dev, "Tuning selection failed\n");
+
return 0;
}
EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
--
2.7.4


[PATCH 4.4.y-cip 40/83] mmc: core: Add helper to see if a host can be retuned

Biju Das <biju.das@...>
 

From: Simon Horman <horms+renesas@...>

commit c820af5f18ec248b3cb61a9a9ce47ef0f2e9ec63 upstream.

This is in preparation for restoring saved tuning parameters
when resuming the TMIO driver.

Signed-off-by: Simon Horman <horms+renesas@...>
Acked-by: Wolfram Sang <wsa+renesas@...>
Tested-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
include/linux/mmc/host.h | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 8673ffe..1c483d9 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -515,4 +515,9 @@ static inline void mmc_retune_recheck(struct mmc_host *host)
host->retune_now = 1;
}

+static inline bool mmc_can_retune(struct mmc_host *host)
+{
+ return host->can_retune == 1;
+}
+
#endif /* LINUX_MMC_HOST_H */
--
2.7.4


[PATCH 4.4.y-cip 39/83] mmc: tmio: Add hw reset support

Biju Das <biju.das@...>
 

From: Ai Kyuse <ai.kyuse.uw@...>

commit e8f36b5d3b54a49df02c950050659a5082e2c880 upstream.

Add hw reset support.

Signed-off-by: Ai Kyuse <ai.kyuse.uw@...>
Signed-off-by: Simon Horman <horms+renesas@...>
Acked-by: Wolfram Sang <wsa+renesas@...>
Tested-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/tmio_mmc.h | 1 +
drivers/mmc/host/tmio_mmc_pio.c | 9 +++++++++
2 files changed, 10 insertions(+)

diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index d3d24e1..8b4869e 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -167,6 +167,7 @@ struct tmio_mmc_host {
int (*start_signal_voltage_switch)(struct mmc_host *mmc,
struct mmc_ios *ios);
int (*write16_hook)(struct tmio_mmc_host *host, int addr);
+ void (*hw_reset)(struct tmio_mmc_host *host);
};

struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev);
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index c255af8..4bb0553 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -792,6 +792,14 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host,
return 0;
}

+static void tmio_mmc_hw_reset(struct mmc_host *mmc)
+{
+ struct tmio_mmc_host *host = mmc_priv(mmc);
+
+ if (host->hw_reset)
+ host->hw_reset(host);
+}
+
/* Process requests from the MMC layer */
static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
@@ -1008,6 +1016,7 @@ static struct mmc_host_ops tmio_mmc_ops = {
.get_cd = mmc_gpio_get_cd,
.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
.multi_io_quirk = tmio_multi_io_quirk,
+ .hw_reset = tmio_mmc_hw_reset,
};

static int tmio_mmc_init_ocr(struct tmio_mmc_host *host)
--
2.7.4


[PATCH 4.4.y-cip 38/83] mmc: tmio: document mandatory and optional callbacks

Biju Das <biju.das@...>
 

From: Simon Horman <horms+renesas@...>

commit 2f87365f832bbc26e32f23588aaeb40abe15ff0d upstream.

Signed-off-by: Simon Horman <horms+renesas@...>
Acked-by: Wolfram Sang <wsa+renesas@...>
Tested-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/tmio_mmc.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index c4131d9..d3d24e1 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -154,8 +154,10 @@ struct tmio_mmc_host {
bool native_hotplug;
bool sdio_irq_enabled;

- int (*write16_hook)(struct tmio_mmc_host *host, int addr);
+ /* Mandatory callback */
int (*clk_enable)(struct tmio_mmc_host *host);
+
+ /* Optional callbacks */
unsigned int (*clk_update)(struct tmio_mmc_host *host,
unsigned int new_clock);
void (*clk_disable)(struct tmio_mmc_host *host);
@@ -164,6 +166,7 @@ struct tmio_mmc_host {
int (*card_busy)(struct mmc_host *mmc);
int (*start_signal_voltage_switch)(struct mmc_host *mmc,
struct mmc_ios *ios);
+ int (*write16_hook)(struct tmio_mmc_host *host, int addr);
};

struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev);
--
2.7.4


[PATCH 4.4.y-cip 37/83] mmc: tmio: enhance illegal sequence handling

Biju Das <biju.das@...>
 

From: Ai Kyuse <ai.kyuse.uw@...>

commit 96e0b2ba00ee5dacb12bed6585145ce784ec9153 upstream.

An illegal sequence command error may occur if there is a stopbit or
cmd_index error as well as a CRC error. The correct course of action
is to re-enable IRQs

An illegal sequence data error may occur if there is a CRC or stopbit
error, or underrun. In this case set data->error correctly.

This is in preparation for enabling tuning support which relies on
differentiating between illegal sequence and other errors.

Signed-off-by: Ai Kyuse <ai.kyuse.uw@...>
[simon: broken out of a larger patch]
Signed-off-by: Simon Horman <horms+renesas@...>
Acked-by: Wolfram Sang <wsa+renesas@...>
Tested-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>

Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/tmio_mmc_pio.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 4d9e17a..c255af8 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -552,7 +552,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
schedule_work(&host->done);
}

-static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
+static void tmio_mmc_data_irq(struct tmio_mmc_host *host, unsigned int stat)
{
struct mmc_data *data;
spin_lock(&host->lock);
@@ -561,6 +561,9 @@ static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
if (!data)
goto out;

+ if (stat & TMIO_STAT_CRCFAIL || stat & TMIO_STAT_STOPBIT_ERR ||
+ stat & TMIO_STAT_TXUNDERRUN)
+ data->error = -EILSEQ;
if (host->chan_tx && (data->flags & MMC_DATA_WRITE) && !host->force_pio) {
u32 status = sd_ctrl_read16_and_16_as_32(host, CTL_STATUS);
bool done = false;
@@ -609,8 +612,6 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
goto out;
}

- host->cmd = NULL;
-
/* This controller is sicker than the PXA one. Not only do we need to
* drop the top 8 bits of the first response word, we also need to
* modify the order of the response for short response command types.
@@ -630,14 +631,16 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,

if (stat & TMIO_STAT_CMDTIMEOUT)
cmd->error = -ETIMEDOUT;
- else if (stat & TMIO_STAT_CRCFAIL && cmd->flags & MMC_RSP_CRC)
+ else if ((stat & TMIO_STAT_CRCFAIL && cmd->flags & MMC_RSP_CRC) ||
+ stat & TMIO_STAT_STOPBIT_ERR ||
+ stat & TMIO_STAT_CMD_IDX_ERR)
cmd->error = -EILSEQ;

/* If there is data to handle we enable data IRQs here, and
* we will ultimatley finish the request in the data_end handler.
* If theres no data or we encountered an error, finish now.
*/
- if (host->data && !cmd->error) {
+ if (host->data && (!cmd->error || cmd->error == -EILSEQ)) {
if (host->data->flags & MMC_DATA_READ) {
if (host->force_pio || !host->chan_rx)
tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_READOP);
@@ -698,7 +701,7 @@ static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host,
/* Data transfer completion */
if (ireg & TMIO_STAT_DATAEND) {
tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
- tmio_mmc_data_irq(host);
+ tmio_mmc_data_irq(host, status);
return true;
}

--
2.7.4


[PATCH 4.4.y-cip 36/83] mmc: sh_mobile_sdhi: add ocr_mask option

Biju Das <biju.das@...>
 

From: Chris Brandt <chris.brandt@...>

commit f19417f38264f9a2f7b4627aa4060133c237b211 upstream.

In moving platforms from board files to DT, there still needs to be a way
to set the ocr_mask setting for the tmio driver during probe. Without this
setting, the probe will fail because the supported voltages are not known.

This patch will also traditional platform registration platforms to
migrate to DT.

Signed-off-by: Chris Brandt <chris.brandt@...>
Reviewed-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
drivers/mmc/host/sh_mobile_sdhi.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 3d186cc..9124246 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -49,6 +49,7 @@

struct sh_mobile_sdhi_of_data {
unsigned long tmio_flags;
+ u32 tmio_ocr_mask;
unsigned long capabilities;
unsigned long capabilities2;
enum dma_slave_buswidth dma_buswidth;
@@ -370,6 +371,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
const struct sh_mobile_sdhi_of_data *of_data = of_id->data;

mmc_data->flags |= of_data->tmio_flags;
+ mmc_data->ocr_mask = of_data->tmio_ocr_mask;
mmc_data->capabilities |= of_data->capabilities;
mmc_data->capabilities2 |= of_data->capabilities2;
mmc_data->dma_rx_offset = of_data->dma_rx_offset;
--
2.7.4


[PATCH 4.4.y-cip 35/83] mmc: add define for R1 response without CRC

Biju Das <biju.das@...>
 

From: Wolfram Sang <wsa+renesas@...>

commit 51b50c961676428cd356d6fa494a2e9f53dc77bf upstream.

The core uses it for polling. Give drivers a proper define handle this
case like for other response types.

Signed-off-by: Wolfram Sang <wsa+renesas@...>
Signed-off-by: Ulf Hansson <ulf.hansson@...>
Signed-off-by: Biju Das <biju.das@...>
---
include/linux/mmc/core.h | 3 +++
1 file changed, 3 insertions(+)

diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 37967b6..6c2e285 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -55,6 +55,9 @@ struct mmc_command {
#define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
#define MMC_RSP_R7 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)

+/* Can be used by core to poll after switch to MMC HS mode */
+#define MMC_RSP_R1_NO_CRC (MMC_RSP_PRESENT|MMC_RSP_OPCODE)
+
#define mmc_resp_type(cmd) ((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))

/*
--
2.7.4

6521 - 6540 of 10158