mmc: mediatek: Add MMC_CAP_SDIO_IRQ support
This patch enables support SDIO IRQs. It enables MMC_CAP_SDIO_IRQ & MMC_CAP2_SDIO_IRQ_NOTHREAD and implement the ->ack_sdio_irq callback. Signed-off-by: Jjian Zhou <jjian.zhou@mediatek.com> Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> Signed-off-by: Yong Mao <yong.mao@mediatek.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
parent
ca804a5615
commit
5215b2e952
|
@ -1114,6 +1114,7 @@ static void msdc_start_command(struct msdc_host *host,
|
||||||
struct mmc_request *mrq, struct mmc_command *cmd)
|
struct mmc_request *mrq, struct mmc_command *cmd)
|
||||||
{
|
{
|
||||||
u32 rawcmd;
|
u32 rawcmd;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
WARN_ON(host->cmd);
|
WARN_ON(host->cmd);
|
||||||
host->cmd = cmd;
|
host->cmd = cmd;
|
||||||
|
@ -1131,7 +1132,10 @@ static void msdc_start_command(struct msdc_host *host,
|
||||||
cmd->error = 0;
|
cmd->error = 0;
|
||||||
rawcmd = msdc_cmd_prepare_raw_cmd(host, mrq, cmd);
|
rawcmd = msdc_cmd_prepare_raw_cmd(host, mrq, cmd);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&host->lock, flags);
|
||||||
sdr_set_bits(host->base + MSDC_INTEN, cmd_ints_mask);
|
sdr_set_bits(host->base + MSDC_INTEN, cmd_ints_mask);
|
||||||
|
spin_unlock_irqrestore(&host->lock, flags);
|
||||||
|
|
||||||
writel(cmd->arg, host->base + SDC_ARG);
|
writel(cmd->arg, host->base + SDC_ARG);
|
||||||
writel(rawcmd, host->base + SDC_CMD);
|
writel(rawcmd, host->base + SDC_CMD);
|
||||||
}
|
}
|
||||||
|
@ -1351,6 +1355,31 @@ static void msdc_request_timeout(struct work_struct *work)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __msdc_enable_sdio_irq(struct mmc_host *mmc, int enb)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
struct msdc_host *host = mmc_priv(mmc);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&host->lock, flags);
|
||||||
|
if (enb)
|
||||||
|
sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_SDIOIRQ);
|
||||||
|
else
|
||||||
|
sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_SDIOIRQ);
|
||||||
|
spin_unlock_irqrestore(&host->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void msdc_enable_sdio_irq(struct mmc_host *mmc, int enb)
|
||||||
|
{
|
||||||
|
struct msdc_host *host = mmc_priv(mmc);
|
||||||
|
|
||||||
|
__msdc_enable_sdio_irq(mmc, enb);
|
||||||
|
|
||||||
|
if (enb)
|
||||||
|
pm_runtime_get_noresume(host->dev);
|
||||||
|
else
|
||||||
|
pm_runtime_put_noidle(host->dev);
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t msdc_irq(int irq, void *dev_id)
|
static irqreturn_t msdc_irq(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct msdc_host *host = (struct msdc_host *) dev_id;
|
struct msdc_host *host = (struct msdc_host *) dev_id;
|
||||||
|
@ -1373,7 +1402,12 @@ static irqreturn_t msdc_irq(int irq, void *dev_id)
|
||||||
data = host->data;
|
data = host->data;
|
||||||
spin_unlock_irqrestore(&host->lock, flags);
|
spin_unlock_irqrestore(&host->lock, flags);
|
||||||
|
|
||||||
if (!(events & event_mask))
|
if ((events & event_mask) & MSDC_INT_SDIOIRQ) {
|
||||||
|
__msdc_enable_sdio_irq(host->mmc, 0);
|
||||||
|
sdio_signal_irq(host->mmc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(events & (event_mask & ~MSDC_INT_SDIOIRQ)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!mrq) {
|
if (!mrq) {
|
||||||
|
@ -1493,8 +1527,11 @@ static void msdc_init_hw(struct msdc_host *host)
|
||||||
*/
|
*/
|
||||||
sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO);
|
sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO);
|
||||||
|
|
||||||
/* disable detect SDIO device interrupt function */
|
/* Config SDIO device detect interrupt function */
|
||||||
sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
|
if (host->mmc->caps & MMC_CAP_SDIO_IRQ)
|
||||||
|
sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
|
||||||
|
else
|
||||||
|
sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
|
||||||
|
|
||||||
/* Configure to default data timeout */
|
/* Configure to default data timeout */
|
||||||
sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3);
|
sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3);
|
||||||
|
@ -2013,6 +2050,11 @@ static void msdc_hw_reset(struct mmc_host *mmc)
|
||||||
sdr_clr_bits(host->base + EMMC_IOCON, 1);
|
sdr_clr_bits(host->base + EMMC_IOCON, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void msdc_ack_sdio_irq(struct mmc_host *mmc)
|
||||||
|
{
|
||||||
|
__msdc_enable_sdio_irq(mmc, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct mmc_host_ops mt_msdc_ops = {
|
static const struct mmc_host_ops mt_msdc_ops = {
|
||||||
.post_req = msdc_post_req,
|
.post_req = msdc_post_req,
|
||||||
.pre_req = msdc_pre_req,
|
.pre_req = msdc_pre_req,
|
||||||
|
@ -2020,6 +2062,8 @@ static const struct mmc_host_ops mt_msdc_ops = {
|
||||||
.set_ios = msdc_ops_set_ios,
|
.set_ios = msdc_ops_set_ios,
|
||||||
.get_ro = mmc_gpio_get_ro,
|
.get_ro = mmc_gpio_get_ro,
|
||||||
.get_cd = mmc_gpio_get_cd,
|
.get_cd = mmc_gpio_get_cd,
|
||||||
|
.enable_sdio_irq = msdc_enable_sdio_irq,
|
||||||
|
.ack_sdio_irq = msdc_ack_sdio_irq,
|
||||||
.start_signal_voltage_switch = msdc_ops_switch_volt,
|
.start_signal_voltage_switch = msdc_ops_switch_volt,
|
||||||
.card_busy = msdc_card_busy,
|
.card_busy = msdc_card_busy,
|
||||||
.execute_tuning = msdc_execute_tuning,
|
.execute_tuning = msdc_execute_tuning,
|
||||||
|
@ -2147,6 +2191,9 @@ static int msdc_drv_probe(struct platform_device *pdev)
|
||||||
else
|
else
|
||||||
mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 4095);
|
mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 4095);
|
||||||
|
|
||||||
|
if (mmc->caps & MMC_CAP_SDIO_IRQ)
|
||||||
|
mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
|
||||||
|
|
||||||
mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
|
mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
|
||||||
/* MMC core transfer sizes tunable parameters */
|
/* MMC core transfer sizes tunable parameters */
|
||||||
mmc->max_segs = MAX_BD_NUM;
|
mmc->max_segs = MAX_BD_NUM;
|
||||||
|
|
Loading…
Reference in New Issue