mmc: tmio: Add tuning support
Add tuning support for use with SDR104 mode Signed-off-by: Ai Kyuse <ai.kyuse.uw@renesas.com> Signed-off-by: Simon Horman <horms+renesas@verge.net.au> Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
parent
e8f36b5d3b
commit
4f11997773
|
@ -153,6 +153,7 @@ struct tmio_mmc_host {
|
||||||
struct mutex ios_lock; /* protect set_ios() context */
|
struct mutex ios_lock; /* protect set_ios() context */
|
||||||
bool native_hotplug;
|
bool native_hotplug;
|
||||||
bool sdio_irq_enabled;
|
bool sdio_irq_enabled;
|
||||||
|
u32 scc_tappos;
|
||||||
|
|
||||||
/* Mandatory callback */
|
/* Mandatory callback */
|
||||||
int (*clk_enable)(struct tmio_mmc_host *host);
|
int (*clk_enable)(struct tmio_mmc_host *host);
|
||||||
|
@ -168,6 +169,19 @@ struct tmio_mmc_host {
|
||||||
struct mmc_ios *ios);
|
struct mmc_ios *ios);
|
||||||
int (*write16_hook)(struct tmio_mmc_host *host, int addr);
|
int (*write16_hook)(struct tmio_mmc_host *host, int addr);
|
||||||
void (*hw_reset)(struct tmio_mmc_host *host);
|
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);
|
struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev);
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/mfd/tmio.h>
|
#include <linux/mfd/tmio.h>
|
||||||
|
#include <linux/mmc/card.h>
|
||||||
#include <linux/mmc/host.h>
|
#include <linux/mmc/host.h>
|
||||||
#include <linux/mmc/mmc.h>
|
#include <linux/mmc/mmc.h>
|
||||||
#include <linux/mmc/slot-gpio.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))
|
if (mrq->cmd->error || (mrq->data && mrq->data->error))
|
||||||
tmio_mmc_abort_dma(host);
|
tmio_mmc_abort_dma(host);
|
||||||
|
|
||||||
|
if (host->check_scc_error)
|
||||||
|
host->check_scc_error(host);
|
||||||
|
|
||||||
mmc_request_done(host->mmc, mrq);
|
mmc_request_done(host->mmc, mrq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,6 +801,55 @@ static void tmio_mmc_hw_reset(struct mmc_host *mmc)
|
||||||
host->hw_reset(host);
|
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 */
|
/* Process requests from the MMC layer */
|
||||||
static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||||
{
|
{
|
||||||
|
@ -1014,6 +1067,7 @@ static struct mmc_host_ops tmio_mmc_ops = {
|
||||||
.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
|
.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
|
||||||
.multi_io_quirk = tmio_multi_io_quirk,
|
.multi_io_quirk = tmio_multi_io_quirk,
|
||||||
.hw_reset = tmio_mmc_hw_reset,
|
.hw_reset = tmio_mmc_hw_reset,
|
||||||
|
.execute_tuning = tmio_mmc_execute_tuning,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int tmio_mmc_init_ocr(struct tmio_mmc_host *host)
|
static int tmio_mmc_init_ocr(struct tmio_mmc_host *host)
|
||||||
|
@ -1260,6 +1314,11 @@ int tmio_mmc_host_runtime_suspend(struct device *dev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tmio_mmc_host_runtime_suspend);
|
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)
|
int tmio_mmc_host_runtime_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct mmc_host *mmc = dev_get_drvdata(dev);
|
struct mmc_host *mmc = dev_get_drvdata(dev);
|
||||||
|
@ -1273,6 +1332,9 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
|
||||||
|
|
||||||
tmio_mmc_enable_dma(host, true);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
|
EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
|
||||||
|
|
Loading…
Reference in New Issue