[PATCH 4/9] qi-fix-slow-first-bulk.patch

Andy Green andy at openmoko.com
Fri Sep 26 14:55:32 CEST 2008


This patch performs the equivalent init actions to the SDHC slow
unitl first bulk patch in kernel, it allows us to work with large
SDHC cards which exceed Glamo timeout capability at 16MHz for first
access.

Signed-off-by: Andy Green <andy at openmoko.com>
---

 src/drivers/glamo-mmc.c |   21 ++++++++++++++++++---
 src/fs/ext2.c           |   41 ++++++++++++++++++++++++++++++++---------
 src/phase2.c            |    3 ++-
 3 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/src/drivers/glamo-mmc.c b/src/drivers/glamo-mmc.c
index 16ca21a..39d4199 100644
--- a/src/drivers/glamo-mmc.c
+++ b/src/drivers/glamo-mmc.c
@@ -106,12 +106,16 @@ unsigned long mmc_bread(int dev_num, unsigned long blknr, unsigned long blkcnt,
 								      void *dst)
 {
 	unsigned long src = blknr * MMC_BLOCK_SIZE;
+	int ret;
 
 	if (!blkcnt)
 		return 0;
 
 /*	printf("mmc_bread(%d, %ld, %ld, %p)\n", dev_num, blknr, blkcnt, dst); */
-	mmc_read(src, dst, blkcnt * MMC_BLOCK_SIZE);
+	ret = mmc_read(src, dst, blkcnt * MMC_BLOCK_SIZE);
+	if (ret)
+		return ret;
+
 	return blkcnt;
 }
 
@@ -443,6 +447,8 @@ int mmc_read(unsigned long src, u8 *dst, int size)
 	resp = mmc_cmd(MMC_SET_BLOCKLEN, MMC_BLOCK_SIZE,
 		       MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,
 		       (u16 *)&response[0]);
+	if (resp)
+		return resp;
 
 	while (size) {
 		switch (card_type) {
@@ -460,6 +466,15 @@ int mmc_read(unsigned long src, u8 *dst, int size)
 				(u16 *)&response[0]);
 			break;
 		}
+
+		if (resp)
+			return resp;
+
+		/* final speed 16MHz */
+		glamo_reg_write((glamo_reg_read(GLAMO_REG_CLOCK_GEN8) &
+					     0xff00) | 2, GLAMO_REG_CLOCK_GEN8);
+
+
 		do_pio_read((u16 *)dst, MMC_BLOCK_SIZE >> 1);
 
 		if (size >= MMC_BLOCK_SIZE)
@@ -824,9 +839,9 @@ int mmc_init(int verbose)
 	}
 #endif
 
-	/* crank the clock to the final speed, 16MHz */
+	/* set the clock to slow until first bulk completes (for slow SDHC)  */
 
-	glamo_reg_write((glamo_reg_read(GLAMO_REG_CLOCK_GEN8) & 0xff00) | 2,
+	glamo_reg_write((glamo_reg_read(GLAMO_REG_CLOCK_GEN8) & 0xff00) | 32,
 			 GLAMO_REG_CLOCK_GEN8);
 
 	return rc;
diff --git a/src/fs/ext2.c b/src/fs/ext2.c
index 25616e5..ffbffa0 100644
--- a/src/fs/ext2.c
+++ b/src/fs/ext2.c
@@ -453,9 +453,18 @@ static int ext2fs_iterate_dir(ext2fs_node_t dir, char *name, ext2fs_node_t * fno
 	if (!diro->inode_read) {
 		status = ext2fs_read_inode(diro->data, diro->ino,
 					    &diro->inode);
-		if (status == 0)
+		if (status == 0) {
+			printdec(diro->ino);
+			puts("failed to read inode\n");
 			return(0);
+		}
+	} else {
+		puts("fail\n");
 	}
+	printdec(fpos);
+	puts(" ");
+	printdec(diro->inode.size);
+	puts("\n");
 	/* Search the file.  */
 	while (fpos < __le32_to_cpu(diro->inode.size)) {
 		struct ext2_dirent dirent;
@@ -463,8 +472,10 @@ static int ext2fs_iterate_dir(ext2fs_node_t dir, char *name, ext2fs_node_t * fno
 		status = ext2fs_read_file(diro, fpos,
 					   sizeof(struct ext2_dirent),
 					  (char *) &dirent);
-		if (status < 1)
+		if (status < 1) {
+			puts("ext2fs_read_file ret < 1\n");
 			return 0;
+		}
 
 		if (dirent.namelen != 0) {
 			char filename[256];
@@ -474,12 +485,16 @@ static int ext2fs_iterate_dir(ext2fs_node_t dir, char *name, ext2fs_node_t * fno
 			status = ext2fs_read_file(diro,
 						   fpos + sizeof(struct ext2_dirent),
 						   dirent.namelen, filename);
-			if (status < 1)
+			if (status < 1) {
+				puts("ext2fs_read_file fail 2\n");
 				return(0);
+			}
 
 			fdiro = malloc(sizeof(struct ext2fs_node));
-			if (!fdiro)
+			if (!fdiro) {
+				puts("malloc fail\n");
 				return(0);
+			}
 
 
 			fdiro->data = diro->data;
@@ -505,6 +520,7 @@ static int ext2fs_iterate_dir(ext2fs_node_t dir, char *name, ext2fs_node_t * fno
 							    __le32_to_cpu(dirent.inode),
 							    &fdiro->inode);
 				if (status == 0) {
+					puts("inner ext2fs_read_inode fail\n");
 					free(fdiro);
 					return(0);
 				}
@@ -540,6 +556,7 @@ static int ext2fs_iterate_dir(ext2fs_node_t dir, char *name, ext2fs_node_t * fno
 							    __le32_to_cpu(dirent.inode),
 							    &fdiro->inode);
 					if (status == 0) {
+						puts("ext2fs_read_inode 3 fail\n");
 						free(fdiro);
 						return(0);
 					}
@@ -720,7 +737,7 @@ int ext2fs_find_file
 
 	symlinknest = 0;
 	if (!path)
-		return(0);
+		return 0;
 
 	status = ext2fs_find_file1(path, rootnode, foundnode, &foundtype);
 	if (status == 0)
@@ -760,29 +777,35 @@ int ext2fs_open(const char *filename) {
 	ext2fs_node_t fdiro = NULL;
 	int status;
 	int len;
+	int ret = -1;
 
 	if (ext2fs_root == NULL)
-		return -1;
+		goto fail;
 
 	ext2fs_file = NULL;
 	status = ext2fs_find_file(filename, &ext2fs_root->diropen, &fdiro,
 				   FILETYPE_REG);
-	if (status == 0)
+	if (status == 0) {
+		ret = -2;
 		goto fail;
+	}
 
 	if (!fdiro->inode_read) {
 		status = ext2fs_read_inode(fdiro->data, fdiro->ino,
 					    &fdiro->inode);
-		if (status == 0)
+		if (status == 0) {
+			ret = -3;
 			goto fail;
+		}
 	}
 	len = __le32_to_cpu(fdiro->inode.size);
 	ext2fs_file = fdiro;
+
 	return(len);
 
 fail:
 	ext2fs_free_node(fdiro, &ext2fs_root->diropen);
-	return -1;
+	return ret;
 }
 
 
diff --git a/src/phase2.c b/src/phase2.c
index fe8b0ec..c3f4e44 100644
--- a/src/phase2.c
+++ b/src/phase2.c
@@ -81,7 +81,8 @@ void bootloader_second_phase(void)
 		if (this_kernel->partition_index) {
 			unsigned char *p = kernel_dram;
 
-			if (this_kernel->block_read(kernel_dram, 0, 4) < 0) {
+			if ((int)this_kernel->block_read(kernel_dram, 0, 4)
+									  < 0) {
 				puts("Bad partition read\n");
 				this_kernel = &this_board->
 							kernel_source[kernel++];




More information about the openmoko-kernel mailing list