From cd9d23c6ec1027aa53290fcb1a8e5494e0497a7c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 28 Nov 2008 10:16:40 +0000 Subject: [PATCH] qi-fix-s3c24xx-mci.patch Some work on s3c24xx MCI (which might be useful for GTA01 port eventually too) Signed-off-by: Andy Green --- qiboot/gta03-qi.ocd | 1 + qiboot/include/qi.h | 2 + qiboot/{src/drivers => include}/s3c24xx-mci.h | 14 +- qiboot/include/s3c24xx-regs-sdi.h | 110 +++++ qiboot/src/drivers/s3c24xx-mci.c | 415 ++++++++++-------- qiboot/src/gta03/gta03.c | 35 ++ qiboot/src/start.S | 2 +- 7 files changed, 378 insertions(+), 201 deletions(-) rename qiboot/{src/drivers => include}/s3c24xx-mci.h (77%) create mode 100644 qiboot/include/s3c24xx-regs-sdi.h diff --git a/qiboot/gta03-qi.ocd b/qiboot/gta03-qi.ocd index 16cf0bd..7513767 100755 --- a/qiboot/gta03-qi.ocd +++ b/qiboot/gta03-qi.ocd @@ -3,6 +3,7 @@ reset halt wait_halt +sleep 2000 # bring the steppingstone part of qi image into steppingstone # diff --git a/qiboot/include/qi.h b/qiboot/include/qi.h index 652bb23..7b03687 100644 --- a/qiboot/include/qi.h +++ b/qiboot/include/qi.h @@ -98,6 +98,8 @@ void print8(unsigned char u); void print32(unsigned int u); void printdec(int n); void hexdump(unsigned char *start, int len); +void udelay(int n); + unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len); diff --git a/qiboot/src/drivers/s3c24xx-mci.h b/qiboot/include/s3c24xx-mci.h similarity index 77% rename from qiboot/src/drivers/s3c24xx-mci.h rename to qiboot/include/s3c24xx-mci.h index a271695..7abeb1f 100644 --- a/qiboot/src/drivers/s3c24xx-mci.h +++ b/qiboot/include/s3c24xx-mci.h @@ -21,13 +21,13 @@ * MA 02111-1307 USA */ -#ifndef _MMC_H_ -#define _MMC_H_ -#include +#ifndef _S3C24XX_MMC_H_ +#define _S3C24XX_MMC_H_ +#include -int mmc_init(int verbose); -int mmc_read(ulong src, uchar *dst, int size); -int mmc_write(uchar *src, ulong dst, int size); -int mmc2info(ulong addr); +int s3c24xx_mmc_init(int verbose); +u32 s3c24xx_mmc_bread(int dev_num, u32 blknr, u32 blkcnt, void *dst); +int s3c24xx_mmc_read(u32 src, u8 *dst, int size); +int s3c24xx_mmc_write(u8 *src, u32 dst, int size); #endif /* _MMC_H_ */ diff --git a/qiboot/include/s3c24xx-regs-sdi.h b/qiboot/include/s3c24xx-regs-sdi.h new file mode 100644 index 0000000..9597542 --- /dev/null +++ b/qiboot/include/s3c24xx-regs-sdi.h @@ -0,0 +1,110 @@ +/* linux/include/asm/arch-s3c2410/regs-sdi.h + * + * Copyright (c) 2004 Simtec Electronics + * 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 */ diff --git a/qiboot/src/drivers/s3c24xx-mci.c b/qiboot/src/drivers/s3c24xx-mci.c index b982657..42eecb9 100644 --- a/qiboot/src/drivers/s3c24xx-mci.c +++ b/qiboot/src/drivers/s3c24xx-mci.c @@ -1,5 +1,8 @@ -#if 0 /* + * qi s3c24xx SD card driver + * Author: Andy Green + * based on ----> + * * u-boot S3C2410 MMC/SD card driver * (C) Copyright 2006 by OpenMoko, Inc. * Author: Harald Welte @@ -23,32 +26,51 @@ * MA 02111-1307 USA */ -#include -#include +#include #include -#include -#include -#include -#include +#include +#include -#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 - -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); -} +#define MMC_BLOCK_SIZE 512 /* * FIXME needs to read cid and csd info to determine block size * and other parameters */ -static uchar mmc_buf[MMC_BLOCK_SIZE]; +static u8 mmc_buf[MMC_BLOCK_SIZE]; static mmc_csd_t mmc_csd; static int mmc_ready = 0; static int wide = 0; @@ -57,22 +79,22 @@ static int wide = 0; #define CMD_F_RESP 0x01 #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; - u_int32_t csta_rdy_bit = S3C2410_SDICMDSTAT_CMDSENT; + u32 ccon, csta; + u32 csta_rdy_bit = S3C2410_SDICMDSTAT_CMDSENT; 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; - sdi->SDIDSTA = 0xffffffff; - sdi->SDIFSTA = 0xffffffff; + SDICSTA = 0xffffffff; + SDIDSTA = 0xffffffff; + SDIFSTA = 0xffffffff; - sdi->SDICARG = arg; + SDICARG = arg; ccon = cmd & S3C2410_SDICMDCON_INDEX; 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) ccon |= S3C2410_SDICMDCON_LONGRSP; - sdi->SDICCON = ccon; + SDICCON = ccon; while (1) { - csta = sdi->SDICSTA; + csta = SDICSTA; if (csta & csta_rdy_bit) break; if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) { - printf("===============> MMC CMD Timeout\n"); - sdi->SDICSTA |= S3C2410_SDICMDSTAT_CMDTIMEOUT; + puts("===============> MMC CMD Timeout\n"); + SDICSTA |= S3C2410_SDICMDSTAT_CMDTIMEOUT; 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) { - resp[0] = sdi->SDIRSP0; - resp[1] = sdi->SDIRSP1; - resp[2] = sdi->SDIRSP2; - resp[3] = sdi->SDIRSP3; + resp[0] = SDIRSP0; + resp[1] = SDIRSP1; + resp[2] = SDIRSP2; + resp[3] = SDIRSP3; } 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; - u_int32_t *dst_u32 = (u_int32_t *)dst; - u_int32_t *resp; + u32 dcon, fifo; + u32 *dst_u32 = (u32 *)dst; + u32 *resp; if (len == 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 */ resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, len, CMD_F_RESP); - sdi->SDIBSIZE = len; + SDIBSIZE = len; - //sdi->SDIPRE = 0xff; + //SDIPRE = 0xff; /* setup data */ dcon = (len >> 9) & S3C2410_SDIDCON_BLKNUM; @@ -137,66 +159,82 @@ static int mmc_block_read(uchar *dst, ulong src, ulong len) dcon |= S3C2410_SDIDCON_RXAFTERCMD|S3C2410_SDIDCON_XFER_RXSTART; if (wide) dcon |= S3C2410_SDIDCON_WIDEBUS; -#if defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) - dcon |= S3C2440_SDIDCON_DS_WORD | S3C2440_SDIDCON_DATSTART; -#endif - sdi->SDIDCON = dcon; + + if (!am_i_s3c2410()) + dcon |= S3C2440_SDIDCON_DS_WORD | S3C2440_SDIDCON_DATSTART; + + SDIDCON = dcon; /* send read command */ resp = mmc_cmd(MMC_CMD_READ_BLOCK, src, CMD_F_RESP); while (len > 0) { - u_int32_t sdidsta = sdi->SDIDSTA; - fifo = FIFO_FILL(sdi); + u32 sdidsta = SDIDSTA; + fifo = FIFO_FILL(); if (sdidsta & (S3C2410_SDIDSTA_FIFOFAIL| S3C2410_SDIDSTA_CRCFAIL| S3C2410_SDIDSTA_RXCRCFAIL| S3C2410_SDIDSTA_DATATIMEOUT)) { - printf("mmc_block_read: err SDIDSTA=0x%08x\n", sdidsta); - return -EIO; + puts("mmc_block_read: err SDIDSTA=0x"); + print32(sdidsta); + puts("\n"); + return -1; } - while (fifo--) { - //debug("dst_u32 = 0x%08x\n", dst_u32); - *(dst_u32++) = sdi->SDIDAT; - if (len >= 4) - len -= 4; - else { - len = 0; - break; + if (am_i_s3c2410()) { + while (fifo--) { + //debug("dst_u32 = 0x%08x\n", dst_u32); + *(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) + len -= 4; + else { + len = 0; + break; + } } } } - debug("waiting for SDIDSTA (currently 0x%08x\n", sdi->SDIDSTA); - while (!(sdi->SDIDSTA & (1 << 4))) {} - debug("done waiting for SDIDSTA (currently 0x%08x\n", sdi->SDIDSTA); +// debug("waiting for SDIDSTA (currently 0x%08x\n", SDIDSTA); + while (!(SDIDSTA & (1 << 4))) {} +// debug("done waiting for SDIDSTA (currently 0x%08x\n", SDIDSTA); - sdi->SDIDCON = 0; + SDIDCON = 0; - if (!(sdi->SDIDSTA & S3C2410_SDIDSTA_XFERFINISH)) - debug("mmc_block_read; transfer not finished!\n"); + if (!(SDIDSTA & S3C2410_SDIDSTA_XFERFINISH)) + puts("mmc_block_read; transfer not finished!\n"); 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; } -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; - ulong mmc_block_size, mmc_block_address; + u32 end, part_start, part_end, part_len, aligned_start, aligned_end; + u32 mmc_block_size, mmc_block_address; if (size == 0) return 0; if (!mmc_ready) { - printf("Please initialize the MMC first\n"); + puts("Please initialize the MMC first\n"); return -1; } @@ -211,12 +249,12 @@ int mmc_read(ulong src, uchar *dst, int size) aligned_end = mmc_block_address & end; /* 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); +// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end); 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); +// debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) return -1; @@ -224,19 +262,19 @@ int mmc_read(ulong src, uchar *dst, int size) dst += part_len; src += part_len; } - 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); +// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end); 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) +// debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end); + if ((mmc_block_read((u8 *)(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); +// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_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); +// debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) return -1; @@ -245,16 +283,16 @@ int mmc_read(ulong src, uchar *dst, int size) 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; - ulong mmc_block_size, mmc_block_address; + u32 end, part_start, part_end, part_len, aligned_start, aligned_end; + u32 mmc_block_size, mmc_block_address; if (size == 0) return 0; if (!mmc_ready) { - printf("Please initialize the MMC first\n"); + puts("Please initialize the MMC first\n"); return -1; } @@ -269,12 +307,12 @@ int mmc_write(uchar *src, ulong dst, int size) aligned_end = mmc_block_address & end; /* 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); +// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end); 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); +// debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// (u32)src, dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) return -1; @@ -285,20 +323,20 @@ int mmc_write(uchar *src, ulong dst, int size) dst += part_len; src += part_len; } - 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); +// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end); 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) +// debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end); + if ((mmc_block_write(dst, (u8 *)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); +// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_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); +// debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", +// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) return -1; @@ -310,12 +348,12 @@ int mmc_write(uchar *src, ulong dst, int size) 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; - 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; } @@ -323,9 +361,10 @@ ulong mmc_bread(int dev_num, ulong blknr, ulong blkcnt, void *dst) that expects it to be shifted. */ 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; 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; } +#endif struct sd_cid { char pnm_0; /* product name */ @@ -355,71 +395,92 @@ struct sd_cid { static void print_mmc_cid(mmc_cid_t *cid) { - printf("MMC found. Card desciption is:\n"); - printf("Manufacturer ID = %02x%02x%02x\n", - cid->id[0], cid->id[1], cid->id[2]); - printf("HW/FW Revision = %x %x\n",cid->hwrev, cid->fwrev); + puts("MMC found. Card desciption is:\n"); + puts("Manufacturer ID = "); + print8(cid->id[0]); + 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 */ - printf("Product Name = %s\n",cid->name); - printf("Serial Number = %02x%02x%02x\n", - cid->sn[0], cid->sn[1], cid->sn[2]); - printf("Month = %d\n",cid->month); - printf("Year = %d\n",1997 + cid->year); + puts("Product Name = "); + puts((char *)cid->name); + puts("\nSerial Number = "); + print8(cid->sn[0]); + 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) { - printf("Manufacturer: 0x%02x, OEM \"%c%c\"\n", - cid->mid, cid->oid_0, cid->oid_1); - printf("Product name: \"%c%c%c%c%c\", revision %d.%d\n", - cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3, cid->pnm_4, - cid->prv >> 4, cid->prv & 15); - printf("Serial number: %u\n", - cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 | + puts("Manufacturer: 0x"); + print8(cid->mid); + puts("OEM \""); + this_board->putc(cid->oid_0); + this_board->putc(cid->oid_1); + puts("\"\nProduct name: \""); + 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); - printf("Manufacturing date: %d/%d\n", - cid->mdt_1 & 15, - 2000+((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4)); - printf("CRC: 0x%02x, b0 = %d\n", - cid->crc >> 1, cid->crc & 1); + puts("\nManufacturing date: "); + printdec(cid->mdt_1 & 15); + puts("/"); + printdec(2000+((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4)); + 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; - u_int32_t *resp; - S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); + u32 *resp; - sdi = S3C2410_GetBase_SDI(); + SDICON = S3C2410_SDICON_FIFORESET | S3C2410_SDICON_CLOCKTYPE; + SDIBSIZE = 512; + if (am_i_s3c2410()) { + /* S3C2410 has some bug that prevents reliable operation at higher speed */ + //SDIPRE = 0x3e; /* SDCLK = PCLK/2 / (SDIPRE+1) = 396kHz */ + SDIPRE = 0x02; /* 2410: SDCLK = PCLK/2 / (SDIPRE+1) = 11MHz */ + SDIDTIMER = 0xffff; + SDIIMSK2410 = 0x0; + } else { + SDIPRE = 0x05; /* 2410: SDCLK = PCLK / (SDIPRE+1) = 11MHz */ + SDIDTIMER = 0x7fffff; + SDIIMSK = 0x0; + } - debug("mmc_init(PCLK=%u)\n", get_PCLK()); - - clk_power->CLKCON |= (1 << 9); - - sdi->SDIBSIZE = 512; -#if defined(CONFIG_S3C2410) - /* S3C2410 has some bug that prevents reliable operation at higher speed */ - //sdi->SDIPRE = 0x3e; /* SDCLK = PCLK/2 / (SDIPRE+1) = 396kHz */ - sdi->SDIPRE = 0x02; /* 2410: SDCLK = PCLK/2 / (SDIPRE+1) = 11MHz */ - sdi->SDIDTIMER = 0xffff; -#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) - sdi->SDIPRE = 0x05; /* 2410: SDCLK = PCLK / (SDIPRE+1) = 11MHz */ - sdi->SDIDTIMER = 0x7fffff; -#endif - sdi->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; + puts("Sending reset...\n"); + /* reset */ retries = 10; resp = mmc_cmd(MMC_CMD_RESET, 0, 0); - printf("trying to detect SD Card...\n"); + puts("trying to detect SD Card...\n"); while (retries--) { - udelay(100000); + udelay(1000000); resp = mmc_cmd(55, 0x00000000, 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) { - retries = 10; - 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); - } - } + if (retries < 0 && !is_sd) + return -3; /* try to get card id */ 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) print_mmc_cid(cid); +#if 0 sprintf((char *) mmc_dev.vendor, "Man %02x%02x%02x Snr %02x%02x%02x", 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.revision,"%x %x", cid->hwrev, cid->fwrev); +#endif } else { struct sd_cid *cid = (struct sd_cid *) resp; if (verbose) print_sd_cid(cid); +#if 0 sprintf((char *) mmc_dev.vendor, "Man %02 OEM %c%c \"%c%c%c%c%c\"", cid->mid, cid->oid_0, cid->oid_1, @@ -473,19 +529,9 @@ int mmc_init(int verbose) cid->psn_2 << 8 | cid->psn_3); sprintf((char *) mmc_dev.revision, "%d.%d", 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 */ 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)); rc = 0; mmc_ready = 1; +#if 0 /* FIXME add verbose printout for csd */ printf("READ_BL_LEN=%u, C_SIZE_MULT=%u, C_SIZE=%u\n", csd->read_bl_len, csd->c_size_mult1, csd->c_size); printf("size = %u\n", mmc_size(csd)); +#endif } } @@ -515,26 +563,7 @@ int mmc_init(int verbose) } #endif - fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */ - 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 diff --git a/qiboot/src/gta03/gta03.c b/qiboot/src/gta03/gta03.c index 4c58ee3..73fa268 100644 --- a/qiboot/src/gta03/gta03.c +++ b/qiboot/src/gta03/gta03.c @@ -4,6 +4,7 @@ #include #include #include +#include #define GTA03_DEBUG_UART 2 @@ -215,6 +216,18 @@ static void putc_gta03(char 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 @@ -232,6 +245,28 @@ const struct board_api board_api_gta03 = { /* these are the ways we could boot GTA03 in order to try */ .kernel_source = { [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", .block_read = nand_read_ll, .offset_blocks512_if_no_partition = 0x80000 / 512, diff --git a/qiboot/src/start.S b/qiboot/src/start.S index a16e9a5..bbc8186 100644 --- a/qiboot/src/start.S +++ b/qiboot/src/start.S @@ -166,7 +166,7 @@ startup_2442: /* enable only CPU peripheral block clocks we actually use */ 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] /* gpio UART2 init, H port */