1
0
mirror of git://projects.qi-hardware.com/xburst-tools.git synced 2024-11-29 16:09:42 +02:00

qi-fix-s3c24xx-mci.patch

Some work on s3c24xx MCI (which might be useful for GTA01 port
eventually too)

Signed-off-by: Andy Green <andy@openmoko.com>
This commit is contained in:
Andy Green 2008-11-28 10:16:40 +00:00 committed by Andy Green
parent 064a13861c
commit cd9d23c6ec
7 changed files with 378 additions and 201 deletions

View File

@ -3,6 +3,7 @@
reset halt reset halt
wait_halt wait_halt
sleep 2000
# bring the steppingstone part of qi image into steppingstone # bring the steppingstone part of qi image into steppingstone
# #

View File

@ -98,6 +98,8 @@ void print8(unsigned char u);
void print32(unsigned int u); void print32(unsigned int u);
void printdec(int n); void printdec(int n);
void hexdump(unsigned char *start, int len); void hexdump(unsigned char *start, int len);
void udelay(int n);
unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned long crc32(unsigned long crc, const unsigned char *buf,
unsigned int len); unsigned int len);

View File

@ -21,13 +21,13 @@
* MA 02111-1307 USA * MA 02111-1307 USA
*/ */
#ifndef _MMC_H_ #ifndef _S3C24XX_MMC_H_
#define _MMC_H_ #define _S3C24XX_MMC_H_
#include <asm/arch/mmc.h> #include <mmc.h>
int mmc_init(int verbose); int s3c24xx_mmc_init(int verbose);
int mmc_read(ulong src, uchar *dst, int size); u32 s3c24xx_mmc_bread(int dev_num, u32 blknr, u32 blkcnt, void *dst);
int mmc_write(uchar *src, ulong dst, int size); int s3c24xx_mmc_read(u32 src, u8 *dst, int size);
int mmc2info(ulong addr); int s3c24xx_mmc_write(u8 *src, u32 dst, int size);
#endif /* _MMC_H_ */ #endif /* _MMC_H_ */

View File

@ -0,0 +1,110 @@
/* linux/include/asm/arch-s3c2410/regs-sdi.h
*
* Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
* http://www.simtec.co.uk/products/SWLINUX/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* S3C2410 MMC/SDIO register definitions
*
* Changelog:
* 18-Aug-2004 Ben Dooks Created initial file
* 29-Nov-2004 Koen Martens Added some missing defines, fixed duplicates
* 29-Nov-2004 Ben Dooks Updated Koen's patch
*/
#ifndef __ASM_ARM_REGS_SDI
#define __ASM_ARM_REGS_SDI "regs-sdi.h"
#define S3C2440_SDICON_SDRESET (1<<8)
#define S3C2440_SDICON_MMCCLOCK (1<<5)
#define S3C2410_SDICON_BYTEORDER (1<<4)
#define S3C2410_SDICON_SDIOIRQ (1<<3)
#define S3C2410_SDICON_RWAITEN (1<<2)
#define S3C2410_SDICON_FIFORESET (1<<1)
#define S3C2410_SDICON_CLOCKTYPE (1<<0)
#define S3C2410_SDICMDCON_ABORT (1<<12)
#define S3C2410_SDICMDCON_WITHDATA (1<<11)
#define S3C2410_SDICMDCON_LONGRSP (1<<10)
#define S3C2410_SDICMDCON_WAITRSP (1<<9)
#define S3C2410_SDICMDCON_CMDSTART (1<<8)
#define S3C2410_SDICMDCON_SENDERHOST (1<<6)
#define S3C2410_SDICMDCON_INDEX (0x3f)
#define S3C2410_SDICMDSTAT_CRCFAIL (1<<12)
#define S3C2410_SDICMDSTAT_CMDSENT (1<<11)
#define S3C2410_SDICMDSTAT_CMDTIMEOUT (1<<10)
#define S3C2410_SDICMDSTAT_RSPFIN (1<<9)
#define S3C2410_SDICMDSTAT_XFERING (1<<8)
#define S3C2410_SDICMDSTAT_INDEX (0xff)
#define S3C2440_SDIDCON_DS_BYTE (0<<22)
#define S3C2440_SDIDCON_DS_HALFWORD (1<<22)
#define S3C2440_SDIDCON_DS_WORD (2<<22)
#define S3C2410_SDIDCON_IRQPERIOD (1<<21)
#define S3C2410_SDIDCON_TXAFTERRESP (1<<20)
#define S3C2410_SDIDCON_RXAFTERCMD (1<<19)
#define S3C2410_SDIDCON_BUSYAFTERCMD (1<<18)
#define S3C2410_SDIDCON_BLOCKMODE (1<<17)
#define S3C2410_SDIDCON_WIDEBUS (1<<16)
#define S3C2410_SDIDCON_DMAEN (1<<15)
#define S3C2410_SDIDCON_STOP (1<<14)
#define S3C2440_SDIDCON_DATSTART (1<<14)
#define S3C2410_SDIDCON_DATMODE (3<<12)
#define S3C2410_SDIDCON_BLKNUM (0x7ff)
/* constants for S3C2410_SDIDCON_DATMODE */
#define S3C2410_SDIDCON_XFER_READY (0<<12)
#define S3C2410_SDIDCON_XFER_CHKSTART (1<<12)
#define S3C2410_SDIDCON_XFER_RXSTART (2<<12)
#define S3C2410_SDIDCON_XFER_TXSTART (3<<12)
#define S3C2410_SDIDCNT_BLKNUM_MASK (0xFFF)
#define S3C2410_SDIDCNT_BLKNUM_SHIFT (12)
#define S3C2410_SDIDSTA_RDYWAITREQ (1<<10)
#define S3C2410_SDIDSTA_SDIOIRQDETECT (1<<9)
#define S3C2410_SDIDSTA_FIFOFAIL (1<<8) /* reserved on 2440 */
#define S3C2410_SDIDSTA_CRCFAIL (1<<7)
#define S3C2410_SDIDSTA_RXCRCFAIL (1<<6)
#define S3C2410_SDIDSTA_DATATIMEOUT (1<<5)
#define S3C2410_SDIDSTA_XFERFINISH (1<<4)
#define S3C2410_SDIDSTA_BUSYFINISH (1<<3)
#define S3C2410_SDIDSTA_SBITERR (1<<2) /* reserved on 2410a/2440 */
#define S3C2410_SDIDSTA_TXDATAON (1<<1)
#define S3C2410_SDIDSTA_RXDATAON (1<<0)
#define S3C2440_SDIFSTA_FIFORESET (1<<16)
#define S3C2440_SDIFSTA_FIFOFAIL (3<<14) /* 3 is correct (2 bits) */
#define S3C2410_SDIFSTA_TFDET (1<<13)
#define S3C2410_SDIFSTA_RFDET (1<<12)
#define S3C2410_SDIFSTA_TFHALF (1<<11)
#define S3C2410_SDIFSTA_TFEMPTY (1<<10)
#define S3C2410_SDIFSTA_RFLAST (1<<9)
#define S3C2410_SDIFSTA_RFFULL (1<<8)
#define S3C2410_SDIFSTA_RFHALF (1<<7)
#define S3C2410_SDIFSTA_COUNTMASK (0x7f)
#define S3C2410_SDIIMSK_RESPONSECRC (1<<17)
#define S3C2410_SDIIMSK_CMDSENT (1<<16)
#define S3C2410_SDIIMSK_CMDTIMEOUT (1<<15)
#define S3C2410_SDIIMSK_RESPONSEND (1<<14)
#define S3C2410_SDIIMSK_READWAIT (1<<13)
#define S3C2410_SDIIMSK_SDIOIRQ (1<<12)
#define S3C2410_SDIIMSK_FIFOFAIL (1<<11)
#define S3C2410_SDIIMSK_CRCSTATUS (1<<10)
#define S3C2410_SDIIMSK_DATACRC (1<<9)
#define S3C2410_SDIIMSK_DATATIMEOUT (1<<8)
#define S3C2410_SDIIMSK_DATAFINISH (1<<7)
#define S3C2410_SDIIMSK_BUSYFINISH (1<<6)
#define S3C2410_SDIIMSK_SBITERR (1<<5) /* reserved 2440/2410a */
#define S3C2410_SDIIMSK_TXFIFOHALF (1<<4)
#define S3C2410_SDIIMSK_TXFIFOEMPTY (1<<3)
#define S3C2410_SDIIMSK_RXFIFOLAST (1<<2)
#define S3C2410_SDIIMSK_RXFIFOFULL (1<<1)
#define S3C2410_SDIIMSK_RXFIFOHALF (1<<0)
#endif /* __ASM_ARM_REGS_SDI */

View File

@ -1,5 +1,8 @@
#if 0
/* /*
* qi s3c24xx SD card driver
* Author: Andy Green <andy@openmoko.com>
* based on ---->
*
* u-boot S3C2410 MMC/SD card driver * u-boot S3C2410 MMC/SD card driver
* (C) Copyright 2006 by OpenMoko, Inc. * (C) Copyright 2006 by OpenMoko, Inc.
* Author: Harald Welte <laforge@openmoko.org> * Author: Harald Welte <laforge@openmoko.org>
@ -23,32 +26,51 @@
* MA 02111-1307 USA * MA 02111-1307 USA
*/ */
#include <config.h> #include <qi.h>
#include <common.h>
#include <mmc.h> #include <mmc.h>
#include <asm/io.h> #include <s3c24xx-regs-sdi.h>
#include <s3c2410.h> #include <string.h>
#include <part.h>
#include <fat.h>
#if defined(CONFIG_MMC) && defined(CONFIG_MMC_S3C) #define SDICON (*(u32 *)0x5a000000)
#define SDIPRE (*(u32 *)0x5a000004)
#define SDICARG (*(u32 *)0x5a000008)
#define SDICCON (*(u32 *)0x5a00000c)
#define SDICSTA (*(u32 *)0x5a000010)
#define SDIRSP0 (*(u32 *)0x5a000014)
#define SDIRSP1 (*(u32 *)0x5a000018)
#define SDIRSP2 (*(u32 *)0x5a00001c)
#define SDIRSP3 (*(u32 *)0x5a000020)
#define SDIDTIMER (*(u32 *)0x5a000024)
#define SDIBSIZE (*(u32 *)0x5a000028)
#define SDIDCON (*(u32 *)0x5a00002c)
#define SDIDCNT (*(u32 *)0x5a000030)
#define SDIDSTA (*(u32 *)0x5a000034)
#define SDIFSTA (*(u32 *)0x5a000038)
/* s3c2410 in GTA01 has these two last ones the other way around!!! */
#define SDIIMSK (*(u32 *)0x5a00003c)
#define SDIDAT (*(u32 *)0x5a000040)
#define SDIDAT2410 (*(u32 *)0x5a00003c)
#define SDIIMSK2410 (*(u32 *)0x5a000040)
#define CFG_MMC_BASE 0xff000000
/* FIXME: anyone who wants to use this on GTA01 / s3c2410 need to
* have this return 1 on that CPU
*/
int am_i_s3c2410(void)
{
return 0;
}
#define CONFIG_MMC_WIDE #define CONFIG_MMC_WIDE
#define MMC_BLOCK_SIZE 512
static S3C2410_SDI *sdi;
static block_dev_desc_t mmc_dev;
block_dev_desc_t * mmc_get_dev(int dev)
{
return ((block_dev_desc_t *)&mmc_dev);
}
/* /*
* FIXME needs to read cid and csd info to determine block size * FIXME needs to read cid and csd info to determine block size
* and other parameters * and other parameters
*/ */
static uchar mmc_buf[MMC_BLOCK_SIZE]; static u8 mmc_buf[MMC_BLOCK_SIZE];
static mmc_csd_t mmc_csd; static mmc_csd_t mmc_csd;
static int mmc_ready = 0; static int mmc_ready = 0;
static int wide = 0; static int wide = 0;
@ -57,22 +79,22 @@ static int wide = 0;
#define CMD_F_RESP 0x01 #define CMD_F_RESP 0x01
#define CMD_F_RESP_LONG 0x02 #define CMD_F_RESP_LONG 0x02
static u_int32_t *mmc_cmd(ushort cmd, ulong arg, ushort flags) static u32 *mmc_cmd(u16 cmd, u32 arg, u16 flags)
{ {
static u_int32_t resp[5]; static u32 resp[5];
u_int32_t ccon, csta; u32 ccon, csta;
u_int32_t csta_rdy_bit = S3C2410_SDICMDSTAT_CMDSENT; u32 csta_rdy_bit = S3C2410_SDICMDSTAT_CMDSENT;
memset(resp, 0, sizeof(resp)); memset(resp, 0, sizeof(resp));
debug("mmc_cmd CMD%d arg=0x%08x flags=%x\n", cmd, arg, flags); // debug("mmc_cmd CMD%d arg=0x%08x flags=%x\n", cmd, arg, flags);
sdi->SDICSTA = 0xffffffff; SDICSTA = 0xffffffff;
sdi->SDIDSTA = 0xffffffff; SDIDSTA = 0xffffffff;
sdi->SDIFSTA = 0xffffffff; SDIFSTA = 0xffffffff;
sdi->SDICARG = arg; SDICARG = arg;
ccon = cmd & S3C2410_SDICMDCON_INDEX; ccon = cmd & S3C2410_SDICMDCON_INDEX;
ccon |= S3C2410_SDICMDCON_SENDERHOST|S3C2410_SDICMDCON_CMDSTART; ccon |= S3C2410_SDICMDCON_SENDERHOST|S3C2410_SDICMDCON_CMDSTART;
@ -85,51 +107,51 @@ static u_int32_t *mmc_cmd(ushort cmd, ulong arg, ushort flags)
if (flags & CMD_F_RESP_LONG) if (flags & CMD_F_RESP_LONG)
ccon |= S3C2410_SDICMDCON_LONGRSP; ccon |= S3C2410_SDICMDCON_LONGRSP;
sdi->SDICCON = ccon; SDICCON = ccon;
while (1) { while (1) {
csta = sdi->SDICSTA; csta = SDICSTA;
if (csta & csta_rdy_bit) if (csta & csta_rdy_bit)
break; break;
if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) { if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
printf("===============> MMC CMD Timeout\n"); puts("===============> MMC CMD Timeout\n");
sdi->SDICSTA |= S3C2410_SDICMDSTAT_CMDTIMEOUT; SDICSTA |= S3C2410_SDICMDSTAT_CMDTIMEOUT;
break; break;
} }
} }
debug("final MMC CMD status 0x%x\n", csta); // debug("final MMC CMD status 0x%x\n", csta);
sdi->SDICSTA |= csta_rdy_bit; SDICSTA |= csta_rdy_bit;
if (flags & CMD_F_RESP) { if (flags & CMD_F_RESP) {
resp[0] = sdi->SDIRSP0; resp[0] = SDIRSP0;
resp[1] = sdi->SDIRSP1; resp[1] = SDIRSP1;
resp[2] = sdi->SDIRSP2; resp[2] = SDIRSP2;
resp[3] = sdi->SDIRSP3; resp[3] = SDIRSP3;
} }
return resp; return resp;
} }
#define FIFO_FILL(host) ((host->SDIFSTA & S3C2410_SDIFSTA_COUNTMASK) >> 2) #define FIFO_FILL() ((SDIFSTA & S3C2410_SDIFSTA_COUNTMASK) >> 2)
static int mmc_block_read(uchar *dst, ulong src, ulong len) static int mmc_block_read(u8 *dst, u32 src, u32 len)
{ {
u_int32_t dcon, fifo; u32 dcon, fifo;
u_int32_t *dst_u32 = (u_int32_t *)dst; u32 *dst_u32 = (u32 *)dst;
u_int32_t *resp; u32 *resp;
if (len == 0) if (len == 0)
return 0; return 0;
debug("mmc_block_rd dst %lx src %lx len %d\n", (ulong)dst, src, len); // debug("mmc_block_rd dst %lx src %lx len %d\n", (u32)dst, src, len);
/* set block len */ /* set block len */
resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, len, CMD_F_RESP); resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, len, CMD_F_RESP);
sdi->SDIBSIZE = len; SDIBSIZE = len;
//sdi->SDIPRE = 0xff; //SDIPRE = 0xff;
/* setup data */ /* setup data */
dcon = (len >> 9) & S3C2410_SDIDCON_BLKNUM; dcon = (len >> 9) & S3C2410_SDIDCON_BLKNUM;
@ -137,28 +159,43 @@ static int mmc_block_read(uchar *dst, ulong src, ulong len)
dcon |= S3C2410_SDIDCON_RXAFTERCMD|S3C2410_SDIDCON_XFER_RXSTART; dcon |= S3C2410_SDIDCON_RXAFTERCMD|S3C2410_SDIDCON_XFER_RXSTART;
if (wide) if (wide)
dcon |= S3C2410_SDIDCON_WIDEBUS; dcon |= S3C2410_SDIDCON_WIDEBUS;
#if defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
if (!am_i_s3c2410())
dcon |= S3C2440_SDIDCON_DS_WORD | S3C2440_SDIDCON_DATSTART; dcon |= S3C2440_SDIDCON_DS_WORD | S3C2440_SDIDCON_DATSTART;
#endif
sdi->SDIDCON = dcon; SDIDCON = dcon;
/* send read command */ /* send read command */
resp = mmc_cmd(MMC_CMD_READ_BLOCK, src, CMD_F_RESP); resp = mmc_cmd(MMC_CMD_READ_BLOCK, src, CMD_F_RESP);
while (len > 0) { while (len > 0) {
u_int32_t sdidsta = sdi->SDIDSTA; u32 sdidsta = SDIDSTA;
fifo = FIFO_FILL(sdi); fifo = FIFO_FILL();
if (sdidsta & (S3C2410_SDIDSTA_FIFOFAIL| if (sdidsta & (S3C2410_SDIDSTA_FIFOFAIL|
S3C2410_SDIDSTA_CRCFAIL| S3C2410_SDIDSTA_CRCFAIL|
S3C2410_SDIDSTA_RXCRCFAIL| S3C2410_SDIDSTA_RXCRCFAIL|
S3C2410_SDIDSTA_DATATIMEOUT)) { S3C2410_SDIDSTA_DATATIMEOUT)) {
printf("mmc_block_read: err SDIDSTA=0x%08x\n", sdidsta); puts("mmc_block_read: err SDIDSTA=0x");
return -EIO; print32(sdidsta);
puts("\n");
return -1;
} }
if (am_i_s3c2410()) {
while (fifo--) { while (fifo--) {
//debug("dst_u32 = 0x%08x\n", dst_u32); //debug("dst_u32 = 0x%08x\n", dst_u32);
*(dst_u32++) = sdi->SDIDAT; *(dst_u32++) = SDIDAT2410;
if (len >= 4)
len -= 4;
else {
len = 0;
break;
}
}
} else {
while (fifo--) {
//debug("dst_u32 = 0x%08x\n", dst_u32);
*(dst_u32++) = SDIDAT;
if (len >= 4) if (len >= 4)
len -= 4; len -= 4;
else { else {
@ -167,36 +204,37 @@ static int mmc_block_read(uchar *dst, ulong src, ulong len)
} }
} }
} }
}
debug("waiting for SDIDSTA (currently 0x%08x\n", sdi->SDIDSTA); // debug("waiting for SDIDSTA (currently 0x%08x\n", SDIDSTA);
while (!(sdi->SDIDSTA & (1 << 4))) {} while (!(SDIDSTA & (1 << 4))) {}
debug("done waiting for SDIDSTA (currently 0x%08x\n", sdi->SDIDSTA); // debug("done waiting for SDIDSTA (currently 0x%08x\n", SDIDSTA);
sdi->SDIDCON = 0; SDIDCON = 0;
if (!(sdi->SDIDSTA & S3C2410_SDIDSTA_XFERFINISH)) if (!(SDIDSTA & S3C2410_SDIDSTA_XFERFINISH))
debug("mmc_block_read; transfer not finished!\n"); puts("mmc_block_read; transfer not finished!\n");
return 0; return 0;
} }
static int mmc_block_write(ulong dst, uchar *src, int len) static int mmc_block_write(u32 dst, u8 *src, int len)
{ {
printf("MMC block write not yet supported on S3C2410!\n"); puts("MMC block write not yet supported on S3C2410!\n");
return -1; return -1;
} }
int mmc_read(ulong src, uchar *dst, int size) int s3c24xx_mmc_read(u32 src, u8 *dst, int size)
{ {
ulong end, part_start, part_end, part_len, aligned_start, aligned_end; u32 end, part_start, part_end, part_len, aligned_start, aligned_end;
ulong mmc_block_size, mmc_block_address; u32 mmc_block_size, mmc_block_address;
if (size == 0) if (size == 0)
return 0; return 0;
if (!mmc_ready) { if (!mmc_ready) {
printf("Please initialize the MMC first\n"); puts("Please initialize the MMC first\n");
return -1; return -1;
} }
@ -211,12 +249,12 @@ int mmc_read(ulong src, uchar *dst, int size)
aligned_end = mmc_block_address & end; aligned_end = mmc_block_address & end;
/* all block aligned accesses */ /* all block aligned accesses */
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", // 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); // src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
if (part_start) { if (part_start) {
part_len = mmc_block_size - 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", // 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); // src, (u32)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; return -1;
@ -224,19 +262,19 @@ int mmc_read(ulong src, uchar *dst, int size)
dst += part_len; dst += part_len;
src += part_len; src += part_len;
} }
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", // 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); // src, (u32)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", // 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); // src, (u32)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((u8 *)(dst), src, mmc_block_size)) < 0)
return -1; return -1;
} }
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", // 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); // src, (u32)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", // 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); // src, (u32)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; return -1;
@ -245,16 +283,16 @@ int mmc_read(ulong src, uchar *dst, int size)
return 0; return 0;
} }
int mmc_write(uchar *src, ulong dst, int size) int s3c24xx_mmc_write(u8 *src, u32 dst, int size)
{ {
ulong end, part_start, part_end, part_len, aligned_start, aligned_end; u32 end, part_start, part_end, part_len, aligned_start, aligned_end;
ulong mmc_block_size, mmc_block_address; u32 mmc_block_size, mmc_block_address;
if (size == 0) if (size == 0)
return 0; return 0;
if (!mmc_ready) { if (!mmc_ready) {
printf("Please initialize the MMC first\n"); puts("Please initialize the MMC first\n");
return -1; return -1;
} }
@ -269,12 +307,12 @@ int mmc_write(uchar *src, ulong dst, int size)
aligned_end = mmc_block_address & end; aligned_end = mmc_block_address & end;
/* all block aligned accesses */ /* all block aligned accesses */
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", // 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); // src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
if (part_start) { if (part_start) {
part_len = mmc_block_size - 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", // 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); // (u32)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; return -1;
@ -285,20 +323,20 @@ int mmc_write(uchar *src, ulong dst, int size)
dst += part_len; dst += part_len;
src += part_len; src += part_len;
} }
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", // 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); // src, (u32)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", // 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); // src, (u32)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, (u8 *)src, mmc_block_size)) < 0)
return -1; return -1;
} }
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", // 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); // src, (u32)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", // 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); // src, (u32)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; return -1;
@ -310,12 +348,12 @@ int mmc_write(uchar *src, ulong dst, int size)
return 0; return 0;
} }
ulong mmc_bread(int dev_num, ulong blknr, ulong blkcnt, void *dst) u32 s3c24xx_mmc_bread(int dev_num, u32 blknr, u32 blkcnt, void *dst)
{ {
int mmc_block_size = MMC_BLOCK_SIZE; int mmc_block_size = MMC_BLOCK_SIZE;
ulong src = blknr * mmc_block_size + CFG_MMC_BASE; u32 src = blknr * mmc_block_size + CFG_MMC_BASE;
mmc_read(src, dst, blkcnt*mmc_block_size); s3c24xx_mmc_read(src, dst, blkcnt*mmc_block_size);
return blkcnt; return blkcnt;
} }
@ -323,9 +361,10 @@ ulong mmc_bread(int dev_num, ulong blknr, ulong blkcnt, void *dst)
that expects it to be shifted. */ that expects it to be shifted. */
static u_int16_t rca = MMC_DEFAULT_RCA >> 16; static u_int16_t rca = MMC_DEFAULT_RCA >> 16;
static u_int32_t mmc_size(const struct mmc_csd *csd) #if 0
static u32 mmc_size(const struct mmc_csd *csd)
{ {
u_int32_t block_len, mult, blocknr; u32 block_len, mult, blocknr;
block_len = csd->read_bl_len << 12; block_len = csd->read_bl_len << 12;
mult = csd->c_size_mult1 << 8; mult = csd->c_size_mult1 << 8;
@ -333,6 +372,7 @@ static u_int32_t mmc_size(const struct mmc_csd *csd)
return blocknr * block_len; return blocknr * block_len;
} }
#endif
struct sd_cid { struct sd_cid {
char pnm_0; /* product name */ char pnm_0; /* product name */
@ -355,71 +395,92 @@ struct sd_cid {
static void print_mmc_cid(mmc_cid_t *cid) static void print_mmc_cid(mmc_cid_t *cid)
{ {
printf("MMC found. Card desciption is:\n"); puts("MMC found. Card desciption is:\n");
printf("Manufacturer ID = %02x%02x%02x\n", puts("Manufacturer ID = ");
cid->id[0], cid->id[1], cid->id[2]); print8(cid->id[0]);
printf("HW/FW Revision = %x %x\n",cid->hwrev, cid->fwrev); print8(cid->id[1]);
print8(cid->id[2]);
puts("\nHW/FW Revision = ");
print8(cid->hwrev);
print8(cid->fwrev);
cid->hwrev = cid->fwrev = 0; /* null terminate string */ cid->hwrev = cid->fwrev = 0; /* null terminate string */
printf("Product Name = %s\n",cid->name); puts("Product Name = ");
printf("Serial Number = %02x%02x%02x\n", puts((char *)cid->name);
cid->sn[0], cid->sn[1], cid->sn[2]); puts("\nSerial Number = ");
printf("Month = %d\n",cid->month); print8(cid->sn[0]);
printf("Year = %d\n",1997 + cid->year); print8(cid->sn[1]);
print8(cid->sn[2]);
puts("\nMonth = ");
printdec(cid->month);
puts("\nYear = ");
printdec(1997 + cid->year);
puts("\n");
} }
static void print_sd_cid(const struct sd_cid *cid) static void print_sd_cid(const struct sd_cid *cid)
{ {
printf("Manufacturer: 0x%02x, OEM \"%c%c\"\n", puts("Manufacturer: 0x");
cid->mid, cid->oid_0, cid->oid_1); print8(cid->mid);
printf("Product name: \"%c%c%c%c%c\", revision %d.%d\n", puts("OEM \"");
cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3, cid->pnm_4, this_board->putc(cid->oid_0);
cid->prv >> 4, cid->prv & 15); this_board->putc(cid->oid_1);
printf("Serial number: %u\n", puts("\"\nProduct name: \"");
cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 | this_board->putc(cid->pnm_0);
this_board->putc(cid->pnm_1);
this_board->putc(cid->pnm_2);
this_board->putc(cid->pnm_3);
this_board->putc(cid->pnm_4);
puts("\", revision ");
printdec(cid->prv >> 4);
puts(".");
printdec(cid->prv & 15);
puts("\nSerial number: ");
printdec(cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 |
cid->psn_3); cid->psn_3);
printf("Manufacturing date: %d/%d\n", puts("\nManufacturing date: ");
cid->mdt_1 & 15, printdec(cid->mdt_1 & 15);
2000+((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4)); puts("/");
printf("CRC: 0x%02x, b0 = %d\n", printdec(2000+((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4));
cid->crc >> 1, cid->crc & 1); puts("\nCRC: 0x");
print8(cid->crc >> 1);
puts(" b0 = ");
print8(cid->crc & 1);
puts("\n");
} }
int mmc_init(int verbose) int s3c24xx_mmc_init(int verbose)
{ {
int retries, rc = -ENODEV; int retries, rc = -2;
int is_sd = 0; int is_sd = 0;
u_int32_t *resp; u32 *resp;
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
sdi = S3C2410_GetBase_SDI(); SDICON = S3C2410_SDICON_FIFORESET | S3C2410_SDICON_CLOCKTYPE;
SDIBSIZE = 512;
debug("mmc_init(PCLK=%u)\n", get_PCLK()); if (am_i_s3c2410()) {
clk_power->CLKCON |= (1 << 9);
sdi->SDIBSIZE = 512;
#if defined(CONFIG_S3C2410)
/* S3C2410 has some bug that prevents reliable operation at higher speed */ /* S3C2410 has some bug that prevents reliable operation at higher speed */
//sdi->SDIPRE = 0x3e; /* SDCLK = PCLK/2 / (SDIPRE+1) = 396kHz */ //SDIPRE = 0x3e; /* SDCLK = PCLK/2 / (SDIPRE+1) = 396kHz */
sdi->SDIPRE = 0x02; /* 2410: SDCLK = PCLK/2 / (SDIPRE+1) = 11MHz */ SDIPRE = 0x02; /* 2410: SDCLK = PCLK/2 / (SDIPRE+1) = 11MHz */
sdi->SDIDTIMER = 0xffff; SDIDTIMER = 0xffff;
#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) SDIIMSK2410 = 0x0;
sdi->SDIPRE = 0x05; /* 2410: SDCLK = PCLK / (SDIPRE+1) = 11MHz */ } else {
sdi->SDIDTIMER = 0x7fffff; SDIPRE = 0x05; /* 2410: SDCLK = PCLK / (SDIPRE+1) = 11MHz */
#endif SDIDTIMER = 0x7fffff;
sdi->SDIIMSK = 0x0; SDIIMSK = 0x0;
sdi->SDICON = S3C2410_SDICON_FIFORESET|S3C2410_SDICON_CLOCKTYPE; }
udelay(125000); /* FIXME: 74 SDCLK cycles */
udelay(1250000); /* FIXME: 74 SDCLK cycles */
mmc_csd.c_size = 0; mmc_csd.c_size = 0;
puts("Sending reset...\n");
/* reset */ /* reset */
retries = 10; retries = 10;
resp = mmc_cmd(MMC_CMD_RESET, 0, 0); resp = mmc_cmd(MMC_CMD_RESET, 0, 0);
printf("trying to detect SD Card...\n"); puts("trying to detect SD Card...\n");
while (retries--) { while (retries--) {
udelay(100000); udelay(1000000);
resp = mmc_cmd(55, 0x00000000, CMD_F_RESP); resp = mmc_cmd(55, 0x00000000, CMD_F_RESP);
resp = mmc_cmd(41, 0x00300000, CMD_F_RESP); resp = mmc_cmd(41, 0x00300000, CMD_F_RESP);
@ -429,16 +490,8 @@ int mmc_init(int verbose)
} }
} }
if (retries == 0 && !is_sd) { if (retries < 0 && !is_sd)
retries = 10; return -3;
printf("failed to detect SD Card, trying MMC\n");
resp = mmc_cmd(MMC_CMD_SEND_OP_COND, 0x00ffc000, CMD_F_RESP);
while (retries-- && resp && !(resp[4] & 0x80)) {
debug("resp %x %x\n", resp[0], resp[1]);
udelay(50);
resp = mmc_cmd(1, 0x00ffff00, CMD_F_RESP);
}
}
/* try to get card id */ /* try to get card id */
resp = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, CMD_F_RESP|CMD_F_RESP_LONG); resp = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, CMD_F_RESP|CMD_F_RESP_LONG);
@ -450,6 +503,7 @@ int mmc_init(int verbose)
if (verbose) if (verbose)
print_mmc_cid(cid); print_mmc_cid(cid);
#if 0
sprintf((char *) mmc_dev.vendor, sprintf((char *) mmc_dev.vendor,
"Man %02x%02x%02x Snr %02x%02x%02x", "Man %02x%02x%02x Snr %02x%02x%02x",
cid->id[0], cid->id[1], cid->id[2], cid->id[0], cid->id[1], cid->id[2],
@ -457,12 +511,14 @@ int mmc_init(int verbose)
sprintf((char *) mmc_dev.product,"%s",cid->name); sprintf((char *) mmc_dev.product,"%s",cid->name);
sprintf((char *) mmc_dev.revision,"%x %x", sprintf((char *) mmc_dev.revision,"%x %x",
cid->hwrev, cid->fwrev); cid->hwrev, cid->fwrev);
#endif
} }
else { else {
struct sd_cid *cid = (struct sd_cid *) resp; struct sd_cid *cid = (struct sd_cid *) resp;
if (verbose) if (verbose)
print_sd_cid(cid); print_sd_cid(cid);
#if 0
sprintf((char *) mmc_dev.vendor, sprintf((char *) mmc_dev.vendor,
"Man %02 OEM %c%c \"%c%c%c%c%c\"", "Man %02 OEM %c%c \"%c%c%c%c%c\"",
cid->mid, cid->oid_0, cid->oid_1, cid->mid, cid->oid_0, cid->oid_1,
@ -473,19 +529,9 @@ int mmc_init(int verbose)
cid->psn_2 << 8 | cid->psn_3); cid->psn_2 << 8 | cid->psn_3);
sprintf((char *) mmc_dev.revision, "%d.%d", sprintf((char *) mmc_dev.revision, "%d.%d",
cid->prv >> 4, cid->prv & 15); cid->prv >> 4, cid->prv & 15);
#endif
} }
/* 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;
/* FIXME fill in the correct size (is set to 32MByte) */
mmc_dev.blksz = 512;
mmc_dev.lba = 0x10000;
mmc_dev.removable = 0;
mmc_dev.block_read = mmc_bread;
/* MMC exists, get CSD too */ /* MMC exists, get CSD too */
resp = mmc_cmd(MMC_CMD_SET_RCA, MMC_DEFAULT_RCA, CMD_F_RESP); resp = mmc_cmd(MMC_CMD_SET_RCA, MMC_DEFAULT_RCA, CMD_F_RESP);
@ -498,10 +544,12 @@ int mmc_init(int verbose)
memcpy(&mmc_csd, csd, sizeof(csd)); memcpy(&mmc_csd, csd, sizeof(csd));
rc = 0; rc = 0;
mmc_ready = 1; mmc_ready = 1;
#if 0
/* FIXME add verbose printout for csd */ /* FIXME add verbose printout for csd */
printf("READ_BL_LEN=%u, C_SIZE_MULT=%u, C_SIZE=%u\n", printf("READ_BL_LEN=%u, C_SIZE_MULT=%u, C_SIZE=%u\n",
csd->read_bl_len, csd->c_size_mult1, csd->c_size); csd->read_bl_len, csd->c_size_mult1, csd->c_size);
printf("size = %u\n", mmc_size(csd)); printf("size = %u\n", mmc_size(csd));
#endif
} }
} }
@ -515,26 +563,7 @@ int mmc_init(int verbose)
} }
#endif #endif
fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */
return rc; return rc;
} }
int
mmc_ident(block_dev_desc_t *dev)
{
return 0;
}
int
mmc2info(ulong addr)
{
/* FIXME hard codes to 32 MB device */
if (addr >= CFG_MMC_BASE && addr < CFG_MMC_BASE + 0x02000000)
return 1;
return 0;
}
#endif /* defined(CONFIG_MMC) && defined(CONFIG_MMC_S3C) */
#endif

View File

@ -4,6 +4,7 @@
#include <ports-s3c24xx.h> #include <ports-s3c24xx.h>
#include <i2c-bitbang-s3c24xx.h> #include <i2c-bitbang-s3c24xx.h>
#include <pcf50633.h> #include <pcf50633.h>
#include <s3c24xx-mci.h>
#define GTA03_DEBUG_UART 2 #define GTA03_DEBUG_UART 2
@ -215,6 +216,18 @@ static void putc_gta03(char c)
serial_putc_s3c24xx(GTA03_DEBUG_UART, c); serial_putc_s3c24xx(GTA03_DEBUG_UART, c);
} }
int sd_card_init_gta03(void)
{
return s3c24xx_mmc_init(1);
}
int sd_card_block_read_gta03(unsigned char * buf, unsigned long start512,
int blocks512)
{
return s3c24xx_mmc_bread(0, start512, blocks512, buf);
}
/* /*
* our API for bootloader on this machine * our API for bootloader on this machine
@ -232,6 +245,28 @@ const struct board_api board_api_gta03 = {
/* these are the ways we could boot GTA03 in order to try */ /* these are the ways we could boot GTA03 in order to try */
.kernel_source = { .kernel_source = {
[0] = { [0] = {
.name = "SD Card EXT2 Kernel",
.block_init = sd_card_init_gta03,
.block_read = sd_card_block_read_gta03,
.partition_index = 1,
.filesystem = FS_EXT2,
.filepath = "boot/uImage.bin",
.commandline = "mtdparts=physmap-flash:-(nor);" \
"neo1973-nand:" \
"0x00040000(qi)," \
"0x00040000(cmdline)," \
"0x00800000(backupkernel)," \
"0x000a0000(extra)," \
"0x00040000(identity)," \
"0x0f6a0000(backuprootfs) " \
"rootfstype=ext2 " \
"root=/dev/mmcblk0p1 " \
"console=ttySAC2,115200 " \
"loglevel=4 " \
"init=/sbin/init "\
"ro"
},
[1] = {
.name = "NAND Kernel", .name = "NAND Kernel",
.block_read = nand_read_ll, .block_read = nand_read_ll,
.offset_blocks512_if_no_partition = 0x80000 / 512, .offset_blocks512_if_no_partition = 0x80000 / 512,

View File

@ -166,7 +166,7 @@ startup_2442:
/* enable only CPU peripheral block clocks we actually use */ /* enable only CPU peripheral block clocks we actually use */
ldr r0, =0x4c00000c /* clkcon */ ldr r0, =0x4c00000c /* clkcon */
ldr r1, =0x3d10 /* uart, pwm, gpio, nand clocks on */ ldr r1, =0x3f10 /* uart, pwm, gpio, nand, sdi clocks on */
str r1, [r0] str r1, [r0]
/* gpio UART2 init, H port */ /* gpio UART2 init, H port */