mtd/drivers/mtd/chips cfi_cmdset_0002.c,1.58,1.59

cdavies at infradead.org cdavies at infradead.org
Tue Oct 15 09:45:06 EDT 2002


Update of /home/cvs/mtd/drivers/mtd/chips
In directory phoenix.infradead.org:/tmp/cvs-serv25114

Modified Files:
	cfi_cmdset_0002.c 
Log Message:
Added support for reading the Secure silicon (secsi) area which is present 
in some AMD flash devices.


Index: cfi_cmdset_0002.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0002.c,v
retrieving revision 1.58
retrieving revision 1.59
diff -u -r1.58 -r1.59
--- cfi_cmdset_0002.c	13 Sep 2002 14:37:35 -0000	1.58
+++ cfi_cmdset_0002.c	15 Oct 2002 13:45:03 -0000	1.59
@@ -36,6 +36,8 @@
 static void cfi_amdstd_sync (struct mtd_info *);
 static int cfi_amdstd_suspend (struct mtd_info *);
 static void cfi_amdstd_resume (struct mtd_info *);
+static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
+static int cfi_amdstd_secsi_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 
 static void cfi_amdstd_destroy(struct mtd_info *);
 
@@ -75,7 +77,7 @@
 		cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
 		cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
 		cfi->mfr = cfi_read_query(map, base);
-		cfi->id = cfi_read_query(map, base + ofs_factor);
+		cfi->id = cfi_read_query(map, base + ofs_factor);    
 
 		/* Wheee. Bring me the head of someone at AMD. */
 #ifdef AMD_BOOTLOC_BUG
@@ -246,6 +248,8 @@
 		cfi->fast_prog = 0;
 	}
 		
+	mtd->read_user_prot_reg = cfi_amdstd_secsi_read;
+	mtd->read_fact_prot_reg = cfi_amdstd_secsi_read;
 	mtd->sync = cfi_amdstd_sync;
 	mtd->suspend = cfi_amdstd_suspend;
 	mtd->resume = cfi_amdstd_resume;
@@ -324,6 +328,117 @@
 			thislen = len;
 
 		ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
+		if (ret)
+			break;
+
+		*retlen += thislen;
+		len -= thislen;
+		buf += thislen;
+
+		ofs = 0;
+		chipnum++;
+	}
+	return ret;
+}
+
+static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long timeo = jiffies + HZ;
+	struct cfi_private *cfi = map->fldrv_priv;
+
+ retry:
+	cfi_spin_lock(chip->mutex);
+
+	if (chip->state != FL_READY){
+#if 0
+	        printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state);
+#endif
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		add_wait_queue(&chip->wq, &wait);
+                
+		cfi_spin_unlock(chip->mutex);
+
+		schedule();
+		remove_wait_queue(&chip->wq, &wait);
+#if 0
+		if(signal_pending(current))
+			return -EINTR;
+#endif
+		timeo = jiffies + HZ;
+
+		goto retry;
+	}	
+
+	adr += chip->start;
+
+	chip->state = FL_READY;
+	
+	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+	
+	map->copy_from(map, buf, adr, len);
+
+	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+	
+	wake_up(&chip->wq);
+	cfi_spin_unlock(chip->mutex);
+
+	return 0;
+}
+
+static int cfi_amdstd_secsi_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+	unsigned long ofs;
+	int chipnum;
+	int ret = 0;
+
+        /* does this chip even have a secsi area? */
+	if(cfi->mfr!=1)
+		return -EINVAL;
+	switch(cfi->id){
+	case 0x50:
+	case 0x53:
+	case 0x55:
+	case 0x56:
+	case 0x5C:
+	case 0x5F:
+		break;
+	default:
+		return -EINVAL;
+	}
+	
+        /* yes, it does... */
+
+
+
+	/* ofs: offset within the first chip that the first read should start */
+
+	/* 8 secsi bytes per chip */
+	chipnum=from>>3;
+	ofs=from & 7;
+
+
+	*retlen = 0;
+
+	while (len) {
+		unsigned long thislen;
+
+		if (chipnum >= cfi->numchips)
+			break;
+
+		if ((len + ofs -1) >> 3)
+			thislen = (1<<3) - ofs;
+		else
+			thislen = len;
+
+		ret = do_read_secsi_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
 		if (ret)
 			break;
 





More information about the linux-mtd-cvs mailing list