mmc: sh_mmcif: revision-specific Command Completion Signal handling

Some earlier MMCIF IP revisions contained Command Completion Signal
support, which has been dropped again in modern versions. Sopport for
this feature is added in a way to preserve the current behaviour by
default, i.e. when it is not enabled in platform data. Patch is based
on work by Nobuyuki HIRAI.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski+renesas@gmail.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
Guennadi Liakhovetski 2013-07-10 21:21:12 +02:00 committed by Chris Ball
parent acd6d772a0
commit 967bcb7717
2 changed files with 22 additions and 6 deletions

View File

@ -134,6 +134,8 @@
INT_BUFWEN | INT_CMD12DRE | INT_BUFRE | \ INT_BUFWEN | INT_CMD12DRE | INT_BUFRE | \
INT_DTRANE | INT_CMD12RBE | INT_CMD12CRE) INT_DTRANE | INT_CMD12RBE | INT_CMD12CRE)
#define INT_CCS (INT_CCSTO | INT_CCSRCV | INT_CCSDE)
/* CE_INT_MASK */ /* CE_INT_MASK */
#define MASK_ALL 0x00000000 #define MASK_ALL 0x00000000
#define MASK_MCCSDE (1 << 29) #define MASK_MCCSDE (1 << 29)
@ -162,7 +164,7 @@
#define MASK_START_CMD (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \ #define MASK_START_CMD (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \
MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \ MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \
MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \ MASK_MCRCSTO | MASK_MWDATTO | \
MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO) MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO)
#define MASK_CLEAN (INT_ERR_STS | MASK_MRBSYE | MASK_MCRSPE | \ #define MASK_CLEAN (INT_ERR_STS | MASK_MRBSYE | MASK_MCRSPE | \
@ -244,6 +246,7 @@ struct sh_mmcif_host {
int sg_blkidx; int sg_blkidx;
bool power; bool power;
bool card_present; bool card_present;
bool ccs_enable; /* Command Completion Signal support */
struct mutex thread_lock; struct mutex thread_lock;
/* DMA support */ /* DMA support */
@ -492,8 +495,10 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_ON); sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_ON);
sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_OFF); sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_OFF);
if (host->ccs_enable)
tmp |= SCCSTO_29;
sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp |
SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29); SRSPTO_256 | SRBSYTO_29 | SRWDTO_29);
/* byte swap on */ /* byte swap on */
sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP); sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP);
} }
@ -873,6 +878,9 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
break; break;
} }
if (host->ccs_enable)
mask |= MASK_MCCSTO;
if (mrq->data) { if (mrq->data) {
sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0); sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0);
sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET,
@ -880,7 +888,10 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
} }
opc = sh_mmcif_set_cmd(host, mrq); opc = sh_mmcif_set_cmd(host, mrq);
sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0); if (host->ccs_enable)
sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
else
sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0 | INT_CCS);
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask); sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
/* set arg */ /* set arg */
sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg); sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
@ -1245,11 +1256,14 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
{ {
struct sh_mmcif_host *host = dev_id; struct sh_mmcif_host *host = dev_id;
u32 state; u32 state, mask;
state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
sh_mmcif_writel(host->addr, MMCIF_CE_INT, mask = sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK);
~(state & sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK))); if (host->ccs_enable)
sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~(state & mask));
else
sh_mmcif_writel(host->addr, MMCIF_CE_INT, INT_CCS | ~(state & mask));
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN); sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN);
if (state & ~MASK_CLEAN) if (state & ~MASK_CLEAN)
@ -1383,6 +1397,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
host->mmc = mmc; host->mmc = mmc;
host->addr = reg; host->addr = reg;
host->timeout = msecs_to_jiffies(1000); host->timeout = msecs_to_jiffies(1000);
host->ccs_enable = !pd || !pd->ccs_unsupported;
host->pd = pdev; host->pd = pdev;

View File

@ -36,6 +36,7 @@ struct sh_mmcif_plat_data {
unsigned int slave_id_tx; /* embedded slave_id_[tr]x */ unsigned int slave_id_tx; /* embedded slave_id_[tr]x */
unsigned int slave_id_rx; unsigned int slave_id_rx;
bool use_cd_gpio : 1; bool use_cd_gpio : 1;
bool ccs_unsupported : 1;
unsigned int cd_gpio; unsigned int cd_gpio;
u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */ u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */
unsigned long caps; unsigned long caps;