diff -Naur 2.1.x/drivers/mmcsd/mmcsd_bus.c 2.1.x.1/drivers/mmcsd/mmcsd_bus.c
--- 2.1.x/drivers/mmcsd/mmcsd_bus.c	2007-02-28 15:10:07.000000000 +0200
+++ 2.1.x.1/drivers/mmcsd/mmcsd_bus.c	2007-03-07 23:31:51.000000000 +0200
@@ -121,7 +121,7 @@
  *
  * Description: This function transfer lblock
  *
- * Arguments  : rd(r/w), from(sector positin), buf
+ * Arguments  : rd(r/w), from(512B block number), buf
  *
  * Returns    : none
  *
@@ -131,11 +131,20 @@
 	int ret;
 	struct mmcsd_cmd cmd;
 
+	/* FIXME: it appears invalid 'from' value locks up the kernel */
+
 	ret = down_interruptible(&slot->mutex);
 	if (ret < 0) {
 		return ret;
 	}
 
+	/* Currently only SDHC uses block addressing */
+	if (!slot->sd || !slot->sdhc)
+	{
+		/* switch to byte addressing */
+		from <<= 9;
+	}
+
 	if(slot->cnt < 1)
 	{
 		/* check card-state. if card-state != StandBy, return BUSY */
@@ -207,7 +216,8 @@
 		mdelay(10);
 
 #if 1 /* shkim patch : support 1024 bytes per block */
-		if( (slot->read_len > 512) || (slot->write_len > 512) )
+//		if( (slot->read_len > 512) || (slot->write_len > 512) )
+		if (!slot->sdhc) /* SDHC cards have hardcoded block size and don't need CMD16 */
 		{
 			/* change block length 512 bytes */
 			cmd.cmd = MMCSD_CMD16;
@@ -222,10 +232,6 @@
 				printk("CMD16 failed, ret = %d\n", ret);
 				goto err;
 			}
-
-			/* change block length infomation */
-			slot->read_len = 512;
-			slot->write_len = 512;
 		}
 #endif
 	}
@@ -383,6 +389,7 @@
 int check_sd_ocr(struct mmcsd_slot *slot)
 {
 	struct mmcsd_cmd  cmd;
+	int ret, sd20 = 0;
 
 #if 1 /* shkim patch : 051215 */
 	int retry = MMCSD_RESP_TIME_LONG;  //org int retry = 50;
@@ -391,6 +398,19 @@
 
 
 retry_sd_ocr:
+	/* CMD8, SEND_IF_COND (tell that we support SD2.0) */
+	cmd.cmd = MMCSD_CMD8;
+	cmd.arg = 0x1aa;		/* [11:8] Host Voltage Supply Flags, [7:0] Check Pattern (0xAA) */
+	cmd.res_type = MMCSD_RES_TYPE_R3; /* actually it should be R7 (?), but this should fit too (no status bits) */
+	cmd.res_flag = 0;
+	cmd.t_res = MMCSD_TIME_NCR_MAX;
+	cmd.t_fin = MMCSD_TIME_NRC_MIN;
+	ret = slot->send_cmd(slot, &cmd);
+	if (ret == 0) {
+		/* if a card responds to CMD8, it means it is SD2.0 compliant (but it does not mean it is a SDHC card) */
+		sd20 = 1;
+	}
+
 	/* CMD55, make ACMD */
 	slot->rca = 0;
 	cmd.cmd = MMCSD_CMD55;
@@ -403,7 +423,7 @@
 
 	/* ACMD41, SEND_OP_COND */
 	cmd.cmd = MMCSD_ACMD41;
-	slot->ocr = MMCSD_VDD_27_36;
+	slot->ocr = MMCSD_VDD_27_36 | (sd20<<30);
 	cmd.arg = slot->ocr;
 	cmd.res_type = MMCSD_RES_TYPE_R1;
 	cmd.res_flag = MMCSD_RES_FLAG_NOCRC;
@@ -419,7 +439,7 @@
 		goto retry_sd_ocr;
 		return 0;               // fail
 #else /* shkim patch : 051215 */
-	if(SDIRSP0 == 0x80ff8000) {
+	if(SDIRSP0 & (1 << 31)) {
 		mdelay(10);     // wait card power up status
 		return 1;       //success
 	} else {
@@ -616,7 +636,12 @@
 
 	DPRINTK("sent CMD9\n");
 
-	mmcsd_str2csd( &(slot->csd), cmd.res, slot->sd);
+	ret = mmcsd_str2csd( &(slot->csd), cmd.res, slot->sd);
+	if (ret) return ret;
+	slot->sdhc = (slot->csd.csd == 1);
+	if (slot->sdhc)
+		printk("SDHC card detected\n");
+
 if(slot->sd) /* SD */
 	DPRINTK("csd(%d) spec_vers(%d) taac.man(%d) taac.exp(%d) nsac(%d)\n"
 	       "tran.man(%d) tran.exp(%d) ccc(%03x) read_len(%x)\n"//read_len(%d)\n"
@@ -772,7 +797,7 @@
 			slot->readonly ? "yes":"no",
 			slot->sd ? "SD":"MMC",
 			slot->sd ? slot->cid.pnm_sd : slot->cid.pnm,
-			slot->size/(1024 * 1024));
+			slot->block_cnt / (1024 * 1024 / slot->read_len));
 
 	len = (p - page) - off;
 	if (len < 0) len = 0;
diff -Naur 2.1.x/drivers/mmcsd/mmcsd_cs.c 2.1.x.1/drivers/mmcsd/mmcsd_cs.c
--- 2.1.x/drivers/mmcsd/mmcsd_cs.c	2007-02-28 15:10:07.000000000 +0200
+++ 2.1.x.1/drivers/mmcsd/mmcsd_cs.c	2007-03-07 22:39:19.000000000 +0200
@@ -69,51 +69,95 @@
  * Returns    : none
  *
 *************************************************************************/
-void mmcsd_str2csd( CSD_regs *regs, __u8 *buff, __u8 id)
+int mmcsd_str2csd( CSD_regs *regs, __u8 *buff, __u8 id)
 {
 	regs->csd		= (buff[0] & 0xc0) >> 6;
-	if(!id) /* MMC */
-		regs->spec_vers	= (buff[0] & 0x3c) >> 2;
-	(regs->taac).man	= (buff[1] & 0x78) >> 3;
-	(regs->taac).exp	= (buff[1]) & 0x07;
-	regs->nsac		= buff[2];
-	(regs->tran_speed).man  = (buff[3] & 0x78) >> 3;
-	(regs->tran_speed).exp  = (buff[3]) & 0x07;
-	regs->ccc		= (buff[4] << 4) | ((buff[5] & 0xf0) >> 4);
-	regs->read_len		= (buff[5] & 0x0f);
-	regs->read_part		= (buff[6] & 0x80) ? 1 : 0;
-	regs->write_mis		= (buff[6] & 0x40) ? 1 : 0;
-	regs->read_mis		= (buff[6] & 0x20) ? 1 : 0;
-	regs->dsr		= (buff[6] & 0x10) ? 1 : 0;
-	regs->c_size		= ((buff[6] & 0x03) << 10) | (buff[7] << 2) | ((buff[8] & 0xc0) >> 6);
-	regs->vcc_r_min		= (buff[8] & 0x38) >> 3;
-	regs->vcc_r_max		= (buff[8] & 0x07);
-	regs->vcc_w_min		= (buff[9] & 0xe0) >> 5;
-	regs->vcc_w_max		= (buff[9] & 0x1c) >> 2;
-	regs->c_size_mult 	= ((buff[9] & 0x03) << 1) | ((buff[10] & 0x80) >> 7);
-	if(id) {
-		regs->er_blk_en	= (buff[10] & 0x40) ? 1: 0;
-		regs->er_size	= ((buff[10] & 0x3f) | (buff[11] & 0x80)) >> 7;
-		regs->wp_grp_size= (buff[11] & 0x7f);
-	} /* SD */
-	else {
-		regs->er_size   = (buff[10] & 0x7c) >> 2;
-		regs->er_grp_size= ((buff[10] & 0x03) << 3) |((buff[11] & 0xe0) >> 5);
-		regs->wp_grp_size= (buff[11] & 0x1f);
-	} /* MMC */
-	regs->wp_grp_en		= (buff[12] & 0x80) ? 1 : 0;
-	if(!id)	/* MMC */
-		regs->dflt_ecc	= (buff[12] & 0x60) >> 5;
-	regs->r2w_factor 	= (buff[12] & 0x1c) >> 2;
-	regs->write_len  	= ((buff[12] & 0x03) << 2) | ((buff[13] & 0xc0) >> 6);
-	regs->write_part 	= (buff[13] & 0x20) ? 1 : 0;
-	regs->ffmt_grp   	= (buff[14] & 0x80) ? 1 : 0;
-	regs->copy		= (buff[14] & 0x40) ? 1 : 0;
-	regs->perm_wp		= (buff[14] & 0x20) ? 1 : 0;
-	regs->tmp_wp		= (buff[14] & 0x10) ? 1 : 0;
-	regs->ffmt		= (buff[14] & 0x0c) >> 2;
-	if(!id)	/* MMC */
-		regs->ecc	= (buff[14] & 0x03);
+	if (regs->csd > 2)
+		return -ENODEV;		/* unknown CSD version */
+
+	if (regs->csd == 1)
+	{
+		/* CSD version 2.0; consists mostly of fixed values,
+		 * which host must override and not bother parsing out.
+		 * FIXME: we should parse CSD correctly for HC MMC cards */
+
+		(regs->taac).man	= 1;
+		(regs->taac).exp	= 6;
+		regs->nsac		= 0;
+		(regs->tran_speed).man  = (buff[3] & 0x78) >> 3;
+		(regs->tran_speed).exp  = (buff[3]) & 0x07;
+		regs->ccc		= (buff[4] << 4) | ((buff[5] & 0xf0) >> 4);
+		regs->read_len		= 9;
+		regs->read_part		= 0;
+		regs->write_mis		= 0;
+		regs->read_mis		= 0;
+		regs->dsr		= (buff[6] & 0x10) ? 1 : 0;
+		regs->c_size		= ((buff[7] & 0x3f) << 16) | (buff[8] << 8) | buff[9];
+		regs->vcc_r_min		= 7;
+		regs->vcc_r_max		= 6;
+		regs->vcc_w_min		= 7;
+		regs->vcc_w_max		= 6;
+		regs->c_size_mult 	= 10 - 2;
+		regs->er_blk_en		= 1;
+		regs->er_size		= 0x7f;
+		regs->wp_grp_size	= 0;
+		regs->wp_grp_en		= 0;
+		regs->r2w_factor 	= 2;
+		regs->write_len  	= 9;
+		regs->write_part 	= 0;
+		regs->ffmt_grp   	= 0;
+		regs->copy		= (buff[14] & 0x40) ? 1 : 0;
+		regs->perm_wp		= (buff[14] & 0x20) ? 1 : 0;
+		regs->tmp_wp		= (buff[14] & 0x10) ? 1 : 0;
+		regs->ffmt		= 0;
+	}
+	else
+	{
+		if(!id) /* MMC */
+			regs->spec_vers	= (buff[0] & 0x3c) >> 2;
+		(regs->taac).man	= (buff[1] & 0x78) >> 3;
+		(regs->taac).exp	= (buff[1]) & 0x07;
+		regs->nsac		= buff[2];
+		(regs->tran_speed).man  = (buff[3] & 0x78) >> 3;
+		(regs->tran_speed).exp  = (buff[3]) & 0x07;
+		regs->ccc		= (buff[4] << 4) | ((buff[5] & 0xf0) >> 4);
+		regs->read_len		= (buff[5] & 0x0f);
+		regs->read_part		= (buff[6] & 0x80) ? 1 : 0;
+		regs->write_mis		= (buff[6] & 0x40) ? 1 : 0;
+		regs->read_mis		= (buff[6] & 0x20) ? 1 : 0;
+		regs->dsr		= (buff[6] & 0x10) ? 1 : 0;
+		regs->c_size		= ((buff[6] & 0x03) << 10) | (buff[7] << 2) | ((buff[8] & 0xc0) >> 6);
+		regs->vcc_r_min		= (buff[8] & 0x38) >> 3;
+		regs->vcc_r_max		= (buff[8] & 0x07);
+		regs->vcc_w_min		= (buff[9] & 0xe0) >> 5;
+		regs->vcc_w_max		= (buff[9] & 0x1c) >> 2;
+		regs->c_size_mult 	= ((buff[9] & 0x03) << 1) | ((buff[10] & 0x80) >> 7);
+		if(id) {
+			regs->er_blk_en	= (buff[10] & 0x40) ? 1: 0;
+			regs->er_size	= ((buff[10] & 0x3f) | (buff[11] & 0x80)) >> 7;
+			regs->wp_grp_size= (buff[11] & 0x7f);
+		} /* SD */
+		else {
+			regs->er_size   = (buff[10] & 0x7c) >> 2;
+			regs->er_grp_size= ((buff[10] & 0x03) << 3) |((buff[11] & 0xe0) >> 5);
+			regs->wp_grp_size= (buff[11] & 0x1f);
+		} /* MMC */
+		regs->wp_grp_en		= (buff[12] & 0x80) ? 1 : 0;
+		if(!id)	/* MMC */
+			regs->dflt_ecc	= (buff[12] & 0x60) >> 5;
+		regs->r2w_factor 	= (buff[12] & 0x1c) >> 2;
+		regs->write_len  	= ((buff[12] & 0x03) << 2) | ((buff[13] & 0xc0) >> 6);
+		regs->write_part 	= (buff[13] & 0x20) ? 1 : 0;
+		regs->ffmt_grp   	= (buff[14] & 0x80) ? 1 : 0;
+		regs->copy		= (buff[14] & 0x40) ? 1 : 0;
+		regs->perm_wp		= (buff[14] & 0x20) ? 1 : 0;
+		regs->tmp_wp		= (buff[14] & 0x10) ? 1 : 0;
+		regs->ffmt		= (buff[14] & 0x0c) >> 2;
+		if(!id)	/* MMC */
+			regs->ecc	= (buff[14] & 0x03);
+	}
+
+	return 0;
 }
 
 /*====================================================================*/
@@ -148,7 +192,15 @@
 	if (csd->perm_wp) slot->stat |= MMCSD_PERM_WP;
 	if (csd->tmp_wp) slot->stat |= MMCSD_TMP_WP;
 
-	/* calculate total card size in bytes */
-	slot->size = (1 + csd->c_size) *
-		(0x01 << (csd->c_size_mult + 2)) * slot->read_len;
+	/* calculate total card size in blocks */
+	slot->block_cnt = (1 + csd->c_size) * (0x01 << (csd->c_size_mult + 2));
+
+	/* If card's block size is not 512, force it to 512 and adjust block count.
+	 * Card will be notified about this when mmcsd_do_transfer_Multblock is called the first time */
+	if (slot->read_len > 512)
+	{
+		slot->block_cnt <<= csd->read_len - 9;
+		slot->read_len  = 512;
+		slot->write_len = 512;
+	}
 }
diff -Naur 2.1.x/drivers/mmcsd/mmcsd_disk.c 2.1.x.1/drivers/mmcsd/mmcsd_disk.c
--- 2.1.x/drivers/mmcsd/mmcsd_disk.c	2007-02-28 15:10:07.000000000 +0200
+++ 2.1.x.1/drivers/mmcsd/mmcsd_disk.c	2007-03-07 23:33:57.000000000 +0200
@@ -86,18 +86,16 @@
 {
 	int ret = 0;
 	int dev = DEVICE_NR(req->rq_dev);
-	unsigned int sect_first, sect_last;
-	unsigned long blksize, from;
+	unsigned int sect, sect_last;
 	char *buffer;
 	unsigned int stat;
 	int ncnt;
 
-	/* read_len must be 512 bytes */
-	blksize = SD_SLOT(dev)->read_len;
+	/* read_len and sect must be 512 bytes */
+	// blksize = SD_SLOT(dev)->read_len;
 	buffer = req->buffer;
-	sect_first = req->sector + mmcsd_part[MINOR(req->rq_dev)].start_sect;
-	sect_last = sect_first + req->current_nr_sectors;
-	from = sect_first * blksize;
+	sect = req->sector + mmcsd_part[MINOR(req->rq_dev)].start_sect;
+	sect_last = sect + req->current_nr_sectors;
 
 	if(xflag)
 	{
@@ -121,9 +119,9 @@
 
 	if(rd)
 	{
-		while (sect_first < sect_last)
+		while (sect < sect_last)
 		{
-			ret = SD_SLOT(dev)->transferMultblock(SD_SLOT(dev), rd, from, buffer,1);
+			ret = SD_SLOT(dev)->transferMultblock(SD_SLOT(dev), rd, sect, buffer,1);
 
 			if (ret)
 			{
@@ -134,9 +132,8 @@
 				}else break;
 			}
 
-			sect_first++;
-			from += blksize;
-			buffer += blksize;
+			sect++;
+			buffer += 512;
 		}
 	}
 	else
@@ -170,7 +167,7 @@
 		if(req->current_nr_sectors > 1)
 			xflag=1;
 
-		ret = SD_SLOT(dev)->transferMultblock(SD_SLOT(dev), rd, from, buffer,req->current_nr_sectors);
+		ret = SD_SLOT(dev)->transferMultblock(SD_SLOT(dev), rd, sect, buffer,req->current_nr_sectors);
 
 	}
 
@@ -299,7 +296,7 @@
 			}
 		}
 		grok_partitions(&mmcsd_gendisk, dev, mmcsd_gendisk.max_p,
-				SD_SLOT(dev)->size / SD_SLOT(dev)->read_len);
+				SD_SLOT(dev)->block_cnt);
 		return 0;
 	}
 	case BLKROSET:
@@ -383,7 +380,6 @@
 static void mmcsd_notify_add(struct mmcsd_slot *slot)
 {
 	int i, dev, minor;
-	loff_t		size;
 	unsigned int nsize;
 
 
@@ -408,7 +404,7 @@
 
 	register_disk(&mmcsd_gendisk, MKDEV(MAJOR_NR, minor),
 		       mmcsd_gendisk.max_p, mmcsd_gendisk.fops,
-		      SD_SLOT(dev)->size / SD_SLOT(dev)->read_len);
+		      SD_SLOT(dev)->block_cnt);
 
 	/* Check usb */
 	switch(nsize)
@@ -430,7 +426,8 @@
 			break;
 	}
 
-	printk("Register %s: %ldMsB\n", SD_SLOT(dev)->sd ? "SD": "MMC", SD_SLOT(dev)->size/(1024 * 1024));
+	printk("Register %s: %ldMsB\n", SD_SLOT(dev)->sd ? "SD": "MMC",
+		SD_SLOT(dev)->block_cnt / (1024 * 1024 / SD_SLOT(dev)->read_len));
 
 }
 
diff -Naur 2.1.x/drivers/mmcsd/mmcsd.h 2.1.x.1/drivers/mmcsd/mmcsd.h
--- 2.1.x/drivers/mmcsd/mmcsd.h	2007-02-28 15:10:07.000000000 +0200
+++ 2.1.x.1/drivers/mmcsd/mmcsd.h	2007-03-07 23:17:14.000000000 +0200
@@ -119,6 +119,7 @@
 				/* bcr, , R6, SEBD_RELATIVE_ADDR, SD only */
 #define MMCSD_CMD4	0x44	/* bc, 31:16 RCA, , SET_DSR */
 #define MMCSD_CMD7	0x47	/* ac, 31:16 RCA, R1, SELECT/DESELECT CARD */
+#define MMCSD_CMD8	0x48	/* bcr, 11:0, , SEND_IF_COND */
 #define MMCSD_CMD9	0x49	/* ac, 31:16 RCA, R2, SEND_CSD */
 #define MMCSD_CMD10	0x4a	/* ac, 31:16 RCA, R2, SEND_CID */
 #define MMCSD_CMD11	0x4b	/* adtc, 31:0 dadr, R1, READ_DAT_UNTIL_STOP */
@@ -282,7 +283,7 @@
 	__u8 read_mis;		/* [ 77: 77] read block misalignment */
 	__u8 dsr;		/* [ 76: 76] DSR implemented */
 				/* [ 75: 74] Reserved */
-	__u16 c_size;		/* [ 73: 62] Device size */
+	__u32 c_size;		/* [ 73: 62] Device size (SDHC: [ 69: 48] )*/
 	__u8 vcc_r_min;		/* [ 61: 59] Max. read current at Vcc min */
 	__u8 vcc_r_max;		/* [ 58: 56] Max. read current at Vcc max */
 	__u8 vcc_w_min;		/* [ 55: 53] Max. write current at Vcc min */
@@ -591,12 +592,13 @@
 	__u8 bus_width;	/* bus width for SD card(0x0: 1 bit, 0x2: 4 bits) */
 	__u8 narrow_bus; /* if true, support only narrow bus */
 	__u8 cnt;
+	__u8 sdhc;	/* if true, it's a SDHC card */
 	int card_in;
 
 	/* MMC/SD card information */
 	unsigned int read_len;	/* read block length */
 	unsigned int write_len;	/* write block length */
-	u_long size;	/* total size of card in bytes */
+	u_long block_cnt;	/* total card block count (in 512B blocks) */
 	u_long stat;	/* card status */
 	__u8 readonly;	/* If true, it's readonly */
 
@@ -649,7 +651,7 @@
 	r6->card_status = (buff[2] << 8) | buff[3];
 }
 extern void mmcsd_str2cid( CID_regs *regs, __u8 *buff, __u8 id);
-extern void mmcsd_str2csd( CSD_regs *regs, __u8 *buff, __u8 id);
+extern int  mmcsd_str2csd( CSD_regs *regs, __u8 *buff, __u8 id);
 
 /* Information Collecting functions */
 extern void mmcsd_get_CSD_info(struct mmcsd_slot *slot, CSD_regs *csd);
