summaryrefslogtreecommitdiff
path: root/cpu/pxa/mmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/pxa/mmc.c')
-rw-r--r--cpu/pxa/mmc.c141
1 files changed, 62 insertions, 79 deletions
diff --git a/cpu/pxa/mmc.c b/cpu/pxa/mmc.c
index 4495962..f7020ee 100644
--- a/cpu/pxa/mmc.c
+++ b/cpu/pxa/mmc.c
@@ -72,13 +72,11 @@ mmc_cmd(ushort cmd, ushort argh, ushort argl, ushort cmdat)
status = MMC_STAT;
debug("MMC status %x\n", status);
- if (status & MMC_STAT_TIME_OUT_RESPONSE)
- {
+ if (status & MMC_STAT_TIME_OUT_RESPONSE) {
return 0;
}
- switch (cmdat & 0x3)
- {
+ switch (cmdat & 0x3) {
case MMC_CMDAT_R1:
case MMC_CMDAT_R3:
words = 3;
@@ -91,8 +89,7 @@ mmc_cmd(ushort cmd, ushort argh, ushort argl, ushort cmdat)
default:
return 0;
}
- for (i = words-1; i >= 0; i--)
- {
+ for (i = words-1; i >= 0; i--) {
ulong res_fifo = MMC_RES;
int offset = i << 1;
@@ -100,8 +97,7 @@ mmc_cmd(ushort cmd, ushort argh, ushort argl, ushort cmdat)
resp[offset+1] = ((uchar *)&res_fifo)[1];
}
#ifdef MMC_DEBUG
- for (i=0; i<words*2; i += 2)
- {
+ for (i=0; i<words*2; i += 2) {
printf("MMC resp[%d] = %02x\n", i, resp[i]);
printf("MMC resp[%d] = %02x\n", i+1, resp[i+1]);
}
@@ -118,8 +114,7 @@ mmc_block_read(uchar *dst, ulong src, ulong len)
ushort argh, argl;
ulong status;
- if (len == 0)
- {
+ if (len == 0) {
return 0;
}
@@ -143,16 +138,21 @@ mmc_block_read(uchar *dst, ulong src, ulong len)
MMC_I_MASK = ~MMC_I_MASK_RXFIFO_RD_REQ;
- while (len)
- {
- if (MMC_I_REG & MMC_I_REG_RXFIFO_RD_REQ)
- {
+ while (len) {
+ if (MMC_I_REG & MMC_I_REG_RXFIFO_RD_REQ) {
+#ifdef CONFIG_PXA27X
+ int i;
+ for (i=min(len,32); i; i--) {
+ *dst++ = * ((volatile uchar *) &MMC_RXFIFO);
+ len--;
+ }
+#else
*dst++ = MMC_RXFIFO;
len--;
+#endif
}
status = MMC_STAT;
- if (status & MMC_STAT_ERRORS)
- {
+ if (status & MMC_STAT_ERRORS) {
printf("MMC_STAT error %lx\n", status);
return -1;
}
@@ -160,8 +160,7 @@ mmc_block_read(uchar *dst, ulong src, ulong len)
MMC_I_MASK = ~MMC_I_MASK_DATA_TRAN_DONE;
while (!(MMC_I_REG & MMC_I_REG_DATA_TRAN_DONE));
status = MMC_STAT;
- if (status & MMC_STAT_ERRORS)
- {
+ if (status & MMC_STAT_ERRORS) {
printf("MMC_STAT error %lx\n", status);
return -1;
}
@@ -177,8 +176,7 @@ mmc_block_write(ulong dst, uchar *src, int len)
ushort argh, argl;
ulong status;
- if (len == 0)
- {
+ if (len == 0) {
return 0;
}
@@ -200,25 +198,20 @@ mmc_block_write(ulong dst, uchar *src, int len)
MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN);
MMC_I_MASK = ~MMC_I_MASK_TXFIFO_WR_REQ;
- while (len)
- {
- if (MMC_I_REG & MMC_I_REG_TXFIFO_WR_REQ)
- {
+ while (len) {
+ if (MMC_I_REG & MMC_I_REG_TXFIFO_WR_REQ) {
int i, bytes = min(32,len);
- for (i=0; i<bytes; i++)
- {
+ for (i=0; i<bytes; i++) {
MMC_TXFIFO = *src++;
}
- if (bytes < 32)
- {
+ if (bytes < 32) {
MMC_PRTBUF = MMC_PRTBUF_BUF_PART_FULL;
}
len -= bytes;
}
status = MMC_STAT;
- if (status & MMC_STAT_ERRORS)
- {
+ if (status & MMC_STAT_ERRORS) {
printf("MMC_STAT error %lx\n", status);
return -1;
}
@@ -228,8 +221,7 @@ mmc_block_write(ulong dst, uchar *src, int len)
MMC_I_MASK = ~MMC_I_MASK_PRG_DONE;
while (!(MMC_I_REG & MMC_I_REG_PRG_DONE));
status = MMC_STAT;
- if (status & MMC_STAT_ERRORS)
- {
+ if (status & MMC_STAT_ERRORS) {
printf("MMC_STAT error %lx\n", status);
return -1;
}
@@ -245,13 +237,11 @@ mmc_read(ulong src, uchar *dst, int size)
ulong end, part_start, part_end, part_len, aligned_start, aligned_end;
ulong mmc_block_size, mmc_block_address;
- if (size == 0)
- {
+ if (size == 0) {
return 0;
}
- if (!mmc_ready)
- {
+ if (!mmc_ready) {
printf("Please initial the MMC first\n");
return -1;
}
@@ -269,13 +259,11 @@ mmc_read(ulong src, uchar *dst, int size)
/* all block aligned accesses */
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
- if (part_start)
- {
+ if (part_start) {
part_len = mmc_block_size - part_start;
debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
- if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0)
- {
+ if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) {
return -1;
}
memcpy(dst, mmc_buf+part_start, part_len);
@@ -284,23 +272,19 @@ mmc_read(ulong src, uchar *dst, int size)
}
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
- for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size)
- {
+ for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
- if ((mmc_block_read((uchar *)(dst), src, mmc_block_size)) < 0)
- {
+ if ((mmc_block_read((uchar *)(dst), src, mmc_block_size)) < 0) {
return -1;
}
}
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
- if (part_end && src < end)
- {
+ if (part_end && src < end) {
debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
- if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0)
- {
+ if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) {
return -1;
}
memcpy(dst, mmc_buf, part_end);
@@ -316,13 +300,11 @@ mmc_write(uchar *src, ulong dst, int size)
ulong end, part_start, part_end, part_len, aligned_start, aligned_end;
ulong mmc_block_size, mmc_block_address;
- if (size == 0)
- {
+ if (size == 0) {
return 0;
}
- if (!mmc_ready)
- {
+ if (!mmc_ready) {
printf("Please initial the MMC first\n");
return -1;
}
@@ -340,18 +322,15 @@ mmc_write(uchar *src, ulong dst, int size)
/* all block aligned accesses */
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
- if (part_start)
- {
+ if (part_start) {
part_len = mmc_block_size - part_start;
debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
(ulong)src, dst, end, part_start, part_end, aligned_start, aligned_end);
- if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0)
- {
+ if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) {
return -1;
}
memcpy(mmc_buf+part_start, src, part_len);
- if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) < 0)
- {
+ if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) < 0) {
return -1;
}
dst += part_len;
@@ -359,28 +338,23 @@ mmc_write(uchar *src, ulong dst, int size)
}
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
- for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size)
- {
+ for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
- if ((mmc_block_write(dst, (uchar *)src, mmc_block_size)) < 0)
- {
+ if ((mmc_block_write(dst, (uchar *)src, mmc_block_size)) < 0) {
return -1;
}
}
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
- if (part_end && dst < end)
- {
+ if (part_end && dst < end) {
debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
- if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0)
- {
+ if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) {
return -1;
}
memcpy(mmc_buf, src, part_end);
- if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0)
- {
+ if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0) {
return -1;
}
}
@@ -412,6 +386,11 @@ mmc_init(int verbose)
set_GPIO_mode( GPIO8_MMCCS0_MD );
#endif
CKEN |= CKEN12_MMC; /* enable MMC unit clock */
+#if defined(CONFIG_ADSVIX)
+ /* turn on the power */
+ GPCR(114) = GPIO_bit(114);
+ udelay(1000);
+#endif
mmc_csd.c_size = 0;
@@ -423,21 +402,22 @@ mmc_init(int verbose)
retries = 10;
resp = mmc_cmd(0, 0, 0, 0);
resp = mmc_cmd(1, 0x00ff, 0xc000, MMC_CMDAT_INIT|MMC_CMDAT_BUSY|MMC_CMDAT_R3);
- while (retries-- && resp && !(resp[4] & 0x80))
- {
+ while (retries-- && resp && !(resp[4] & 0x80)) {
debug("resp %x %x\n", resp[0], resp[1]);
+#ifdef CONFIG_PXA27X
+ udelay(10000);
+#else
udelay(50);
+#endif
resp = mmc_cmd(1, 0x00ff, 0xff00, MMC_CMDAT_BUSY|MMC_CMDAT_R3);
}
/* try to get card id */
resp = mmc_cmd(2, 0, 0, MMC_CMDAT_R2);
- if (resp)
- {
+ if (resp) {
/* TODO configure mmc driver depending on card attributes */
mmc_cid_t *cid = (mmc_cid_t *)resp;
- if (verbose)
- {
+ if (verbose) {
printf("MMC found. Card desciption is:\n");
printf("Manufacturer ID = %02x%02x%02x\n",
cid->id[0], cid->id[1], cid->id[2]);
@@ -451,6 +431,7 @@ mmc_init(int verbose)
}
/* fill in device description */
mmc_dev.if_type = IF_TYPE_MMC;
+ mmc_dev.part_type = PART_TYPE_DOS;
mmc_dev.dev = 0;
mmc_dev.lun = 0;
mmc_dev.type = 0;
@@ -468,8 +449,7 @@ mmc_init(int verbose)
/* MMC exists, get CSD too */
resp = mmc_cmd(MMC_CMD_SET_RCA, MMC_DEFAULT_RCA, 0, MMC_CMDAT_R1);
resp = mmc_cmd(MMC_CMD_SEND_CSD, MMC_DEFAULT_RCA, 0, MMC_CMDAT_R2);
- if (resp)
- {
+ if (resp) {
mmc_csd_t *csd = (mmc_csd_t *)resp;
memcpy(&mmc_csd, csd, sizeof(csd));
rc = 0;
@@ -478,7 +458,11 @@ mmc_init(int verbose)
}
}
+#ifdef CONFIG_PXA27X
+ MMC_CLKRT = 1; /* 10 MHz - see Intel errata */
+#else
MMC_CLKRT = 0; /* 20 MHz */
+#endif
resp = mmc_cmd(7, MMC_DEFAULT_RCA, 0, MMC_CMDAT_R1);
fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */
@@ -496,11 +480,10 @@ int
mmc2info(ulong addr)
{
/* FIXME hard codes to 32 MB device */
- if (addr >= CFG_MMC_BASE && addr < CFG_MMC_BASE + 0x02000000)
- {
+ if (addr >= CFG_MMC_BASE && addr < CFG_MMC_BASE + 0x02000000) {
return 1;
}
return 0;
}
-#endif
+#endif /* CONFIG_MMC */