Commit 240a19fd authored by David Brownell's avatar David Brownell Committed by Kevin Hilman

mmc symbol cleanup

Get rid of some needless symbol duplication:

 - Use MMCST0_* symbols for both MMCST0 (irq status) and
   MMCIM (irq mask) registers.

 - Use MMCST0_* symbols instead of MMCSD_EVENT_* enums; the
   enum names obfuscated code with respect to chip specs.

 - Use mmc_resp_type() directly; RSP_TYPE() isn't needed.

Also:

 - Switch the MMCST0_* symbols to the more compact BIT() syntax,
   and add matching "what does this do?" comments.

 - Use the already-defined MMCCMD_* symbols, not magic numbers.

 - Remove obsolete lament about protocol layer not providing
   something which it now provides.

Minor functional changes that shouldn't affect behavior, and
were suggested by the above changes:

 - Don't enable read IRQs when writing data, and vice versa.

 - Shrink the PIO loop in the IRQ handler.

Overall, this code should now be easier to cross-check against
specs and thus more clear in several ways.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent 212e119d
...@@ -92,37 +92,23 @@ ...@@ -92,37 +92,23 @@
#define MMCCLK_CLKEN (1 << 8) #define MMCCLK_CLKEN (1 << 8)
#define MMCCLK_CLKRT_MASK (0xFF << 0) #define MMCCLK_CLKRT_MASK (0xFF << 0)
/* DAVINCI_MMCST0 definitions */ /* IRQ bit definitions, for DAVINCI_MMCST0 and DAVINCI_MMCIM */
#define MMCST0_DATDNE (1 << 0) #define MMCST0_DATDNE BIT(0) /* data done */
#define MMCST0_BSYDNE (1 << 1) #define MMCST0_BSYDNE BIT(1) /* busy done */
#define MMCST0_RSPDNE (1 << 2) #define MMCST0_RSPDNE BIT(2) /* command done */
#define MMCST0_TOUTRD (1 << 3) #define MMCST0_TOUTRD BIT(3) /* data read timeout */
#define MMCST0_TOUTRS (1 << 4) #define MMCST0_TOUTRS BIT(4) /* command response timeout */
#define MMCST0_CRCWR (1 << 5) #define MMCST0_CRCWR BIT(5) /* data write CRC error */
#define MMCST0_CRCRD (1 << 6) #define MMCST0_CRCRD BIT(6) /* data read CRC error */
#define MMCST0_CRCRS (1 << 7) #define MMCST0_CRCRS BIT(7) /* command response CRC error */
#define MMCST0_DXRDY (1 << 9) #define MMCST0_DXRDY BIT(9) /* data transmit ready (fifo empty) */
#define MMCST0_DRRDY (1 << 10) #define MMCST0_DRRDY BIT(10) /* data receive ready (data in fifo)*/
#define MMCST0_DATED (1 << 11) #define MMCST0_DATED BIT(11) /* DAT3 edge detect */
#define MMCST0_TRNDNE (1 << 12) #define MMCST0_TRNDNE BIT(12) /* transfer done */
/* DAVINCI_MMCST1 definitions */ /* DAVINCI_MMCST1 definitions */
#define MMCST1_BUSY (1 << 0) #define MMCST1_BUSY (1 << 0)
/* DAVINCI_MMCIM definitions */
#define MMCIM_EDATDNE (1 << 0)
#define MMCIM_EBSYDNE (1 << 1)
#define MMCIM_ERSPDNE (1 << 2)
#define MMCIM_ETOUTRD (1 << 3)
#define MMCIM_ETOUTRS (1 << 4)
#define MMCIM_ECRCWR (1 << 5)
#define MMCIM_ECRCRD (1 << 6)
#define MMCIM_ECRCRS (1 << 7)
#define MMCIM_EDXRDY (1 << 9)
#define MMCIM_EDRRDY (1 << 10)
#define MMCIM_EDATED (1 << 11)
#define MMCIM_ETRNDNE (1 << 12)
/* DAVINCI_MMCCMD definitions */ /* DAVINCI_MMCCMD definitions */
#define MMCCMD_CMD_MASK (0x3F << 0) #define MMCCMD_CMD_MASK (0x3F << 0)
#define MMCCMD_PPLEN (1 << 7) #define MMCCMD_PPLEN (1 << 7)
...@@ -149,13 +135,6 @@ ...@@ -149,13 +135,6 @@
#define MMCFIFOCTL_ACCWD_2 (2 << 3) /* access width of 2 bytes */ #define MMCFIFOCTL_ACCWD_2 (2 << 3) /* access width of 2 bytes */
#define MMCFIFOCTL_ACCWD_1 (3 << 3) /* access width of 1 byte */ #define MMCFIFOCTL_ACCWD_1 (3 << 3) /* access width of 1 byte */
/*
* Command types
*/
#define DAVINCI_MMC_CMDTYPE_BC 0
#define DAVINCI_MMC_CMDTYPE_BCR 1
#define DAVINCI_MMC_CMDTYPE_AC 2
#define DAVINCI_MMC_CMDTYPE_ADTC 3
/* MMCSD Init clock in Hz in opendain mode */ /* MMCSD Init clock in Hz in opendain mode */
#define MMCSD_INIT_CLOCK 200000 #define MMCSD_INIT_CLOCK 200000
...@@ -227,20 +206,6 @@ struct mmc_davinci_host { ...@@ -227,20 +206,6 @@ struct mmc_davinci_host {
unsigned int option_write; unsigned int option_write;
}; };
enum mmcsdevent {
MMCSD_EVENT_EOFCMD = (1 << 2),
MMCSD_EVENT_READ = (1 << 10),
MMCSD_EVENT_WRITE = (1 << 9),
MMCSD_EVENT_ERROR_CMDCRC = (1 << 7),
MMCSD_EVENT_ERROR_DATACRC = ((1 << 6) | (1 << 5)),
MMCSD_EVENT_ERROR_CMDTIMEOUT = (1 << 4),
MMCSD_EVENT_ERROR_DATATIMEOUT = (1 << 3),
MMCSD_EVENT_CARD_EXITBUSY = (1 << 1),
MMCSD_EVENT_BLOCK_XFERRED = (1 << 0)
};
#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
#define DAVINCI_MMCSD_READ_FIFO(pDst, pRegs, cnt) asm( \ #define DAVINCI_MMCSD_READ_FIFO(pDst, pRegs, cnt) asm( \
" cmp %3,#16\n" \ " cmp %3,#16\n" \
...@@ -336,142 +301,104 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host, ...@@ -336,142 +301,104 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host,
struct mmc_command *cmd) struct mmc_command *cmd)
{ {
u32 cmd_reg = 0; u32 cmd_reg = 0;
u32 resp_type = 0;
u32 cmd_type = 0;
u32 im_val; u32 im_val;
dev_dbg(mmc_dev(host->mmc), "CMD%d, arg 0x%08x%s\n", dev_dbg(mmc_dev(host->mmc), "CMD%d, arg 0x%08x%s\n",
cmd->opcode, cmd->arg, cmd->opcode, cmd->arg,
({ char *s; ({ char *s;
switch (RSP_TYPE(mmc_resp_type(cmd))) { switch (mmc_resp_type(cmd)) {
case RSP_TYPE(MMC_RSP_R1): case MMC_RSP_R1:
s = ", R1/R1b response"; s = ", R1/R5/R6/R7 response";
break; break;
case RSP_TYPE(MMC_RSP_R2): case MMC_RSP_R1B:
s = ", R1b response";
break;
case MMC_RSP_R2:
s = ", R2 response"; s = ", R2 response";
break; break;
case RSP_TYPE(MMC_RSP_R3): case MMC_RSP_R3:
s = ", R3 response"; s = ", R3/R4 response";
break; break;
default: default:
s = ""; s = ", (R? response)";
break; break;
}; s; })); }; s; }));
host->cmd = cmd; host->cmd = cmd;
/* Protocol layer does not provide response type, switch (mmc_resp_type(cmd)) {
* but our hardware needs to know exact type, not just size! case MMC_RSP_R1B:
/* There's some spec confusion about when R1B is
* allowed, but if the card doesn't issue a BUSY
* then it's harmless for us to allow it.
*/ */
switch (RSP_TYPE(mmc_resp_type(cmd))) { cmd_reg |= MMCCMD_BSYEXP;
case MMC_RSP_NONE: /* FALLTHROUGH */
/* resp 0 */ case MMC_RSP_R1: /* 48 bits, CRC */
break; cmd_reg |= MMCCMD_RSPFMT_R1456;
case RSP_TYPE(MMC_RSP_R1):
resp_type = 1;
break; break;
case RSP_TYPE(MMC_RSP_R2): case MMC_RSP_R2: /* 136 bits, CRC */
resp_type = 2; cmd_reg |= MMCCMD_RSPFMT_R2;
break; break;
case RSP_TYPE(MMC_RSP_R3): case MMC_RSP_R3: /* 48 bits, no CRC */
resp_type = 3; cmd_reg |= MMCCMD_RSPFMT_R3;
break; break;
default: default:
cmd_reg |= MMCCMD_RSPFMT_NONE;
dev_dbg(mmc_dev(host->mmc), "unknown resp_type %04x\n",
mmc_resp_type(cmd));
break; break;
} }
/* Protocol layer does not provide command type, but our hardware
* needs it!
* any data transfer means adtc type (but that information is not
* in command structure, so we flagged it into host struct.)
* However, telling bc, bcr and ac apart based on response is
* not foolproof:
* CMD0 = bc = resp0 CMD15 = ac = resp0
* CMD2 = bcr = resp2 CMD10 = ac = resp2
*
* Resolve to best guess with some exception testing:
* resp0 -> bc, except CMD15 = ac
* rest are ac, except if opendrain
*/
if (mmc_cmd_type(cmd) == MMC_CMD_ADTC)
cmd_type = DAVINCI_MMC_CMDTYPE_ADTC;
else if (mmc_cmd_type(cmd) == MMC_CMD_BC)
cmd_type = DAVINCI_MMC_CMDTYPE_BC;
else if (mmc_cmd_type(cmd) == MMC_CMD_BCR)
cmd_type = DAVINCI_MMC_CMDTYPE_BCR;
else
cmd_type = DAVINCI_MMC_CMDTYPE_AC;
/* Set command Busy or not */
if (cmd->flags & MMC_RSP_BUSY) {
/*
* Linux core sending BUSY which is not defined for cmd 24
* as per mmc standard
*/
if (cmd->opcode != 24)
cmd_reg = cmd_reg | (1 << 8);
}
/* Set command index */ /* Set command index */
cmd_reg |= cmd->opcode; cmd_reg |= cmd->opcode;
/* Setting initialize clock */ /* Setting initialize clock */
if (cmd->opcode == 0) if (cmd->opcode == 0)
cmd_reg = cmd_reg | (1 << 14); cmd_reg |= MMCCMD_INITCK;
/* Set for generating DMA Xfer event */ /* Set for generating DMA Xfer event */
if ((host->do_dma == 1) && (host->data != NULL) if ((host->do_dma == 1) && (host->data != NULL)
&& ((cmd->opcode == 18) || (cmd->opcode == 25) && ((cmd->opcode == 18) || (cmd->opcode == 25)
|| (cmd->opcode == 24) || (cmd->opcode == 17))) || (cmd->opcode == 24) || (cmd->opcode == 17)))
cmd_reg = cmd_reg | (1 << 16); cmd_reg |= MMCCMD_DMATRIG;
/* Setting whether command involves data transfer or not */ /* Setting whether command involves data transfer or not */
if (cmd_type == DAVINCI_MMC_CMDTYPE_ADTC) if (cmd->data)
cmd_reg = cmd_reg | (1 << 13); cmd_reg |= MMCCMD_WDATX;
/* Setting whether stream or block transfer */ /* Setting whether stream or block transfer */
if (cmd->flags & MMC_DATA_STREAM) if (cmd->flags & MMC_DATA_STREAM)
cmd_reg = cmd_reg | (1 << 12); cmd_reg |= MMCCMD_STRMTP;
/* Setting whether data read or write */ /* Setting whether data read or write */
if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE)
cmd_reg = cmd_reg | (1 << 11); cmd_reg |= MMCCMD_DTRW;
/* Setting response type */
cmd_reg = cmd_reg | (resp_type << 9);
if (host->bus_mode == MMC_BUSMODE_PUSHPULL) if (host->bus_mode == MMC_BUSMODE_PUSHPULL)
cmd_reg = cmd_reg | (1 << 7); cmd_reg |= MMCCMD_PPLEN;
/* set Command timeout */ /* set Command timeout */
writel(0xFFFF, host->base + DAVINCI_MMCTOR); writel(0xFFFF, host->base + DAVINCI_MMCTOR);
/* Enable interrupt (calculate here, defer until FIFO is stuffed). */ /* Enable interrupt (calculate here, defer until FIFO is stuffed). */
im_val = MMCSD_EVENT_EOFCMD im_val = MMCST0_RSPDNE | MMCST0_CRCRS | MMCST0_TOUTRS;
| MMCSD_EVENT_ERROR_CMDCRC
| MMCSD_EVENT_ERROR_DATACRC
| MMCSD_EVENT_ERROR_CMDTIMEOUT
| MMCSD_EVENT_ERROR_DATATIMEOUT;
if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
im_val |= MMCSD_EVENT_BLOCK_XFERRED; im_val |= MMCST0_DATDNE | MMCST0_CRCWR;
if (!host->do_dma) if (!host->do_dma)
im_val |= MMCSD_EVENT_WRITE; im_val |= MMCST0_DXRDY;
} else if (host->data_dir == DAVINCI_MMC_DATADIR_READ) { } else if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
im_val |= MMCSD_EVENT_BLOCK_XFERRED; im_val |= MMCST0_DATDNE | MMCST0_CRCRD | MMCST0_TOUTRD;
if (!host->do_dma) if (!host->do_dma)
im_val |= MMCSD_EVENT_READ; im_val |= MMCST0_DRRDY;
} }
/* /*
* It is required by controoler b4 WRITE command that * Before non-DMA WRITE commands the controller needs priming:
* FIFO should be populated with 32 bytes * FIFO should be populated with 32 bytes
*/ */
if ((host->data_dir == DAVINCI_MMC_DATADIR_WRITE) if (!host->do_dma && (host->data_dir == DAVINCI_MMC_DATADIR_WRITE))
&& (cmd_type == DAVINCI_MMC_CMDTYPE_ADTC)
&& (host->do_dma != 1))
/* Fill the FIFO for Tx */
davinci_fifo_data_trans(host, 32); davinci_fifo_data_trans(host, 32);
writel(cmd->arg, host->base + DAVINCI_MMCARGHL); writel(cmd->arg, host->base + DAVINCI_MMCARGHL);
...@@ -967,8 +894,7 @@ static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -967,8 +894,7 @@ static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
/* Send clock cycles, poll completion */ /* Send clock cycles, poll completion */
writel(0, host->base + DAVINCI_MMCARGHL); writel(0, host->base + DAVINCI_MMCARGHL);
writel(MMCCMD_INITCK, host->base + DAVINCI_MMCCMD); writel(MMCCMD_INITCK, host->base + DAVINCI_MMCCMD);
while (!(readl(host->base + DAVINCI_MMCST0) & while (!(readl(host->base + DAVINCI_MMCST0) & MMCST0_RSPDNE))
MMCSD_EVENT_EOFCMD))
cpu_relax(); cpu_relax();
} }
...@@ -1040,35 +966,18 @@ static inline int handle_core_command( ...@@ -1040,35 +966,18 @@ static inline int handle_core_command(
{ {
int end_command = 0; int end_command = 0;
int end_transfer = 0; int end_transfer = 0;
unsigned int qstatus; unsigned int qstatus = status;
qstatus = status;
while (1) {
if ((status & MMCSD_EVENT_WRITE) &&
(host->data_dir == DAVINCI_MMC_DATADIR_WRITE)
&& (host->bytes_left > 0)) {
/* Buffer almost empty */
davinci_fifo_data_trans(host, rw_threshold);
}
if ((status & MMCSD_EVENT_READ) && /* handle FIFO first when using PIO for data */
(host->data_dir == DAVINCI_MMC_DATADIR_READ) while (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) {
&& (host->bytes_left > 0)) {
/* Buffer almost empty */
davinci_fifo_data_trans(host, rw_threshold); davinci_fifo_data_trans(host, rw_threshold);
}
status = readl(host->base + DAVINCI_MMCST0); status = readl(host->base + DAVINCI_MMCST0);
if (!status) if (!status)
break; break;
qstatus |= status; qstatus |= status;
if (host->data == NULL) {
dev_dbg(mmc_dev(host->mmc), "Status is %x at end of "
"ISR when host->data is NULL", status);
break;
}
} }
if (qstatus & MMCSD_EVENT_BLOCK_XFERRED) { if (qstatus & MMCST0_DATDNE) {
/* Block sent/received */ /* Block sent/received */
if (host->data != NULL) { if (host->data != NULL) {
if ((host->do_dma == 0) && (host->bytes_left > 0)) { if ((host->do_dma == 0) && (host->bytes_left > 0)) {
...@@ -1084,7 +993,7 @@ static inline int handle_core_command( ...@@ -1084,7 +993,7 @@ static inline int handle_core_command(
} }
} }
if (qstatus & MMCSD_EVENT_ERROR_DATATIMEOUT) { if (qstatus & MMCST0_TOUTRD) {
/* Data timeout */ /* Data timeout */
if (host->data) { if (host->data) {
host->data->error = -ETIMEDOUT; host->data->error = -ETIMEDOUT;
...@@ -1098,7 +1007,7 @@ static inline int handle_core_command( ...@@ -1098,7 +1007,7 @@ static inline int handle_core_command(
} }
} }
if (qstatus & MMCSD_EVENT_ERROR_DATACRC) { if (qstatus & (MMCST0_CRCWR | MMCST0_CRCRD)) {
u32 temp; u32 temp;
/* DAT line portion is disabled and in reset state */ /* DAT line portion is disabled and in reset state */
temp = readl(host->base + DAVINCI_MMCCTL); temp = readl(host->base + DAVINCI_MMCCTL);
...@@ -1122,7 +1031,7 @@ static inline int handle_core_command( ...@@ -1122,7 +1031,7 @@ static inline int handle_core_command(
} }
} }
if (qstatus & MMCSD_EVENT_ERROR_CMDTIMEOUT) { if (qstatus & MMCST0_TOUTRS) {
if (host->do_dma) if (host->do_dma)
davinci_abort_dma(host); davinci_abort_dma(host);
...@@ -1136,7 +1045,7 @@ static inline int handle_core_command( ...@@ -1136,7 +1045,7 @@ static inline int handle_core_command(
} }
} }
if (qstatus & MMCSD_EVENT_ERROR_CMDCRC) { if (qstatus & MMCST0_CRCRS) {
/* Command CRC error */ /* Command CRC error */
dev_dbg(mmc_dev(host->mmc), "Command CRC error\n"); dev_dbg(mmc_dev(host->mmc), "Command CRC error\n");
if (host->cmd) { if (host->cmd) {
...@@ -1147,7 +1056,7 @@ static inline int handle_core_command( ...@@ -1147,7 +1056,7 @@ static inline int handle_core_command(
} }
} }
if (qstatus & MMCSD_EVENT_EOFCMD) { if (qstatus & MMCST0_RSPDNE) {
/* End of command phase */ /* End of command phase */
end_command = 1; end_command = 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment