Title: [6694] trunk/drivers/mtd/chips: clean up stm flash driver so that it actually builds and works with 2.6.30
Revision
6694
Author
vapier
Date
2009-06-13 05:42:50 -0500 (Sat, 13 Jun 2009)

Log Message

clean up stm flash driver so that it actually builds and works with 2.6.30

Modified Paths

Diff

Modified: trunk/drivers/mtd/chips/Kconfig (6693 => 6694)


--- trunk/drivers/mtd/chips/Kconfig	2009-06-13 10:41:35 UTC (rev 6693)
+++ trunk/drivers/mtd/chips/Kconfig	2009-06-13 10:42:50 UTC (rev 6694)
@@ -208,9 +208,13 @@
 	  provides support for one of those command sets.
 
 config MTD_PSD4256G
- 	tristate "ST PSD4256G compatible flash chip support"
- 	depends on EZKIT && MTD_GEN_PROBE
+	tristate "ST PSD4256G compatible flash chip support"
+	help
+	  Driver for flashes compatible with ST PSD4256G.  This is a non-CFI
+	  and non-JEDEC compliant flash and you really shouldn't buy this.
 
+	  If unsure, say N here.
+
 config MTD_CFI_UTIL
 	tristate
 

Modified: trunk/drivers/mtd/chips/stm_flash.c (6693 => 6694)


--- trunk/drivers/mtd/chips/stm_flash.c	2009-06-13 10:41:35 UTC (rev 6693)
+++ trunk/drivers/mtd/chips/stm_flash.c	2009-06-13 10:42:50 UTC (rev 6694)
@@ -1,23 +1,24 @@
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
+/*
+ * Driver for ST PSD4256G flash
+ *
+ * Copyright 2004-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#define pr_fmt(fmt) "stm_flash: " fmt
+
 #include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/flashchip.h>
-#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/types.h>
 
-#include <linux/interrupt.h>
-
-#define MAX_SMT_CHIPS 8
-
-#define DEVICE_TYPE_X8  (8 / 8)
-#define DEVICE_TYPE_X16 (16 / 8)
-#define DEVICE_TYPE_X32 (32 / 8)
-
 /* Addresses */
 #define ADDR_MANUFACTURER		0x0000
 #define ADDR_DEVICE_ID			0x0002
@@ -36,332 +37,50 @@
 #define D6_MASK 0x40
 
 struct stm_flash_private {
-	int device_type;
-	int interleave;
-	int numchips;
 	unsigned long chipshift;
-	struct flchip chips[0];
+	struct flchip chip;
 };
 
-struct stm_flash_info {
-	const __u16 mfr_id;
-	const __u16 dev_id;
-	const char *name;
-	const u_long size;
-	const int numeraseregions;
-	const struct mtd_erase_region_info regions[4];
-};
-
-static int stm_flash_read(struct mtd_info *, loff_t, size_t, size_t *, unsigned char *);
-static int stm_flash_write(struct mtd_info *, loff_t, size_t, size_t *, const unsigned char *);
-static void stm_flash_sync(struct mtd_info *);
-static int stm_flash_erase(struct mtd_info *, struct erase_info *);
-static void stm_flash_destroy(struct mtd_info*);
-static struct mtd_info* stm_flash_probe(struct map_info *);
-static int stm_flash_suspend(struct mtd_info *mtd);
-static void stm_flash_resume(struct mtd_info *mtd);
-
-static struct mtd_chip_driver stm_flash_chipdrv = {
-	probe:		stm_flash_probe,
-	destroy:	stm_flash_destroy,
-	name:		"stm_flash",
-	module:		THIS_MODULE
-};
-
-static const char im_name[] = "stm_flash";
-
 static void send_unlock(struct map_info *map, unsigned long base)
 {
 	map_word test;
-	test.x[0]=0x00aa;
-	map->write(map,test, base + ADDR_UNLOCK_1);
-	test.x[0]=0x0055;
-	map->write(map,test, base + ADDR_UNLOCK_2);
+	test.x[0] = 0x00aa;
+	map_write(map, test, base + ADDR_UNLOCK_1);
+	test.x[0] = 0x0055;
+	map_write(map, test, base + ADDR_UNLOCK_2);
 }
 
 static void send_cmd(struct map_info *map, unsigned long base,
 		     unsigned long cmd)
 {
 	map_word test;
-	test.x[0]=cmd;
+	test.x[0] = cmd;
 	send_unlock(map, base);
-	map->write(map, test, base + ADDR_UNLOCK_1);
+	map_write(map, test, base + ADDR_UNLOCK_1);
 }
 
 static void send_cmd_to_addr(struct map_info *map, unsigned long base,
 			     unsigned long cmd, unsigned long addr)
 {
 	map_word test;
-	test.x[0]=cmd;
+	test.x[0] = cmd;
 	send_unlock(map, base);
-	map->write(map, test, addr);
+	map_write(map, test, addr);
 }
 
-static int probe_new_chip(struct mtd_info *mtd, __u32 base,
-			  struct flchip *chips,
-			  struct stm_flash_private *private,
-			  const struct stm_flash_info *table,
-			  int table_size)
-{
-	__u32 mfr_id, dev_id;
-	struct map_info *map = mtd->priv;
-	struct stm_flash_private temp;
-	int i;
-	map_word mfr_id1,dev_id1;
-
-	temp.device_type = DEVICE_TYPE_X16;
-	temp.interleave = 1;
-	map->fldrv_priv = &temp;
-
-	/* Enter autoselect mode. */
-	send_cmd(map, base, CMD_RESET_DATA);
-	send_cmd(map, base, CMD_MANUFACTURER_UNLOCK_DATA);
-
-	mfr_id1=map->read(map, base + ADDR_MANUFACTURER) ;
-	dev_id1=map->read(map, base + ADDR_DEVICE_ID) ;
-
-	mfr_id = mfr_id1.x[0] & 0x00FF;
-	dev_id = dev_id1.x[0] & 0x00FF;
-
-	for (i = 0; i < table_size; i++)
-	{
-		if ((mfr_id == table[i].mfr_id) &&
-		    (dev_id == table[i].dev_id))
-		{
-			if (chips)
-			{
-				int j;
-
-				for (j = 0; j < private->numchips; j++)
-				{
-					mfr_id1=map->read(map, chips[j].start +	ADDR_MANUFACTURER);
-					dev_id1=map->read(map, chips[j].start +
-							 ADDR_DEVICE_ID) ;
-					if ((mfr_id1.x[0] == mfr_id) && ( dev_id1.x[0] == dev_id))
-					{
-						/* Exit autoselect mode */
-						send_cmd(map, base, CMD_RESET_DATA);
-						return -1;
-					}
-				}
-
-				if (private->numchips == MAX_SMT_CHIPS)
-				{
-					printk(KERN_WARNING "%s: Too many "
-						"flash chips detected. "
-						"Increase MAX_SMT_CHIPS "
-						"from %d.\n", map->name,
-						MAX_SMT_CHIPS);
-					return -1;
-				}
-
-				chips[private->numchips].start = base;
-				chips[private->numchips].state = FL_READY;
-				chips[private->numchips].mutex =
-					&chips[private->numchips]._spinlock;
-				private->numchips++;
-			}
-			printk("%s: Found %d x %ldMiB %s at 0x%08x\n",
-				map->name, temp.interleave,
-				(table[i].size)/(1024*1024),
-				table[i].name, base);
-
-			mtd->size += table[i].size * temp.interleave;
-			mtd->numeraseregions += table[i].numeraseregions;
-
-			break;
-		}
-	}
-	printk("Manufacture id 0x%02x, Device id 0x%02x\n", mfr_id, dev_id);
-
-	/* Exit autoselect mode. */
-	send_cmd(map, base, CMD_RESET_DATA);
-
-	if (i == table_size)
-	{
-		printk(KERN_DEBUG "%s: unknown flash device at 0x%08x, "
-			"mfr id 0x%02x, dev_id 0x%02x\n", map->name,
-			base, mfr_id, dev_id);
-		map->fldrv_priv = NULL;
-
-		return -1;
-	}
-
-	private->device_type = temp.device_type;
-	private->interleave = temp.interleave;
-
-	return i;
-}
-
-static struct mtd_info* stm_flash_probe(struct map_info *map)
-{
-	const struct stm_flash_info table[] = {
-	{
-		mfr_id: 0x20,
-		dev_id: 0xe9,
-		name: "ST PSD4256G",
-		size: 0x00100000,
-		numeraseregions: 1,
-		regions: {
-		  { offset: 0x000000, erasesize: 0x10000, numblocks: 16 },
-		}
-	}
-	};
-	struct mtd_info *mtd;
-	struct flchip chips[MAX_SMT_CHIPS];
-	int table_pos[MAX_SMT_CHIPS];
-	struct stm_flash_private temp;
-	struct stm_flash_private *private;
-	unsigned long base;
-	unsigned long size;
-	int i;
-	int offset, reg_idx;
-
-	mtd = (struct mtd_info*)kmalloc(sizeof(*mtd), GFP_KERNEL);
-	if (!mtd)
-	{
-		printk(KERN_WARNING "%s: kmalloc failed for info structure\n",
-			map->name);
-		return NULL;
-	}
-	memset(mtd, 0, sizeof(*mtd));
-	mtd->priv = map;
-
-	memset(&temp, 0, sizeof(temp));
-
-	printk("%s: Probing for SMT PSD4256G compatible flash...\n", map->name);
-
-	if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table,
-					sizeof(table)/sizeof(table[0]))) == -1)
-	{
-		printk(KERN_WARNING
-			"%s: Found no SMT PSD4256G compatible device at "
-			"location zero\n", map->name);
-		kfree(mtd);
-
-		return NULL;
-	}
-
-	chips[0].start = 0;
-	chips[0].state = FL_READY;
-	chips[0].mutex = &chips[0]._spinlock;
-	temp.numchips = 1;
-	for (size = mtd->size; size > 1; size >>= 1)
-		temp.chipshift++;
-
-	/* Find out if there are any more chips in the map. */
-	for (base = (1 << temp.chipshift); base < map->size;
-			base += (1 << temp.chipshift))
-	{
-		int numchips = temp.numchips;
-		table_pos[numchips] =
-			probe_new_chip(mtd, base, chips, &temp,
-				table, sizeof(table)/sizeof(table[0]));
-	}
-
-	mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) *
-					mtd->numeraseregions, GFP_KERNEL);
-
-	if (!mtd->eraseregions)
-	{
-		printk(KERN_WARNING "%s: Failed to allocate memory for "
-			"MTD erase region info\n", map->name);
-		kfree(mtd);
-		map->fldrv_priv = NULL;
-		return NULL;
-	}
-
-	reg_idx = 0;
-	offset = 0;
-	for (i = 0; i < temp.numchips; i++)
-	{
-		int dev_size;
-		int j;
-
-		dev_size = 0;
-		for (j = 0; j < table[table_pos[i]].numeraseregions; j++)
-		{
-			mtd->eraseregions[reg_idx].offset = offset +
-				(table[table_pos[i]].regions[j].offset *
-				 temp.interleave);
-			mtd->eraseregions[reg_idx].erasesize =
-				table[table_pos[i]].regions[j].erasesize *
-				temp.interleave;
-			mtd->eraseregions[reg_idx].numblocks =
-				table[table_pos[i]].regions[j].numblocks;
-			if (mtd->erasesize <
-					mtd->eraseregions[reg_idx].erasesize)
-				mtd->erasesize =
-					mtd->eraseregions[reg_idx].erasesize;
-
-			dev_size += mtd->eraseregions[reg_idx].erasesize *
-				mtd->eraseregions[reg_idx].numblocks;
-			reg_idx++;
-		}
-		offset += dev_size;
-	}
-
-	mtd->type = MTD_NORFLASH;
-	mtd->flags = MTD_CAP_NORFLASH;
-	mtd->name = map->name;
-	mtd->erase = stm_flash_erase;
-	mtd->read = stm_flash_read;
-	mtd->write = stm_flash_write;
-	mtd->sync = stm_flash_sync;
-	mtd->suspend = stm_flash_suspend;
-	mtd->resume = stm_flash_resume;
-
-	private = kmalloc(sizeof(*private) +
-			(sizeof(struct flchip) * temp.numchips), GFP_KERNEL);
-	if (!private) {
-		printk(KERN_WARNING
-		       "%s: kmalloc failed for private structure\n", map->name);
-		kfree(mtd);
-		map->fldrv_priv = NULL;
-		return NULL;
-	}
-	memcpy(private, &temp, sizeof(temp));
-	memcpy(private->chips, chips,
-		sizeof(struct flchip) * private->numchips);
-	for (i = 0; i < private->numchips; i++)
-	{
-		init_waitqueue_head(&private->chips[i].wq);
-		spin_lock_init(&private->chips[i]._spinlock);
-	}
-
-	map->fldrv_priv = private;
-
-	map->fldrv = &stm_flash_chipdrv;
-	MOD_INC_USE_COUNT;
-
-	return mtd;
-}
-
-static void stm_flash_destroy(struct mtd_info *mtd)
-{
-	struct map_info *map = mtd->priv;
-	struct stm_flash_private *private = map->fldrv_priv;
-	kfree(private);
-}
-
 static void stm_flash_sync(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct stm_flash_private *private = map->fldrv_priv;
-	int i;
 	struct flchip *chip;
-	int ret = 0;
 	DECLARE_WAITQUEUE(wait, current);
 
-	for (i = 0; !ret && (i < private->numchips); i++)
-	{
-		chip = &private->chips[i];
+	chip = &private->chip;
 
-	retry:
+ retry:
 		spin_lock_bh(chip->mutex);
 
-		switch (chip->state)
-		{
+		switch (chip->state) {
 		case FL_READY:
 		case FL_STATUS:
 		case FL_CFI_QUERY:
@@ -376,29 +95,21 @@
 			add_wait_queue(&chip->wq, &wait);
 
 			spin_unlock_bh(chip->mutex);
-
 			schedule();
-
 			remove_wait_queue(&chip->wq, &wait);
 
 			goto retry;
 		}
-	}
 
-	/* Unlock the chips again */
-	for (i--; i >= 0; i--)
-	{
-		chip = &private->chips[i];
+	chip = &private->chip;
 
-		spin_lock_bh(chip->mutex);
+	spin_lock_bh(chip->mutex);
 
-		if (chip->state == FL_SYNCING)
-		{
-			chip->state = chip->oldstate;
-			wake_up(&chip->wq);
-		}
-		spin_unlock_bh(chip->mutex);
+	if (chip->state == FL_SYNCING) {
+		chip->state = chip->oldstate;
+		wake_up(&chip->wq);
 	}
+	spin_unlock_bh(chip->mutex);
 }
 
 static int read_one_chip(struct map_info *map, struct flchip *chip,
@@ -407,13 +118,12 @@
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long timeo = jiffies + HZ;
 
-retry:
+ retry:
 	spin_lock_bh(chip->mutex);
 
-	if (chip->state != FL_READY)
-	{
-		printk(KERN_INFO "%s: waiting for chip to read, state = %d\n",
-			map->name, chip->state);
+	if (chip->state != FL_READY) {
+		pr_info("waiting for chip to read, state = %d\n",
+			chip->state);
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		add_wait_queue(&chip->wq, &wait);
 
@@ -434,7 +144,7 @@
 
 	chip->state = FL_READY;
 
-	map->copy_from(map, buf, addr, len);
+	map_copy_from(map, buf, addr, len);
 
 	wake_up(&chip->wq);
 	spin_unlock_bh(chip->mutex);
@@ -448,13 +158,11 @@
 	struct map_info *map = mtd->priv;
 	struct stm_flash_private *private = map->fldrv_priv;
 	unsigned long offset;
-	int chipnum;
-	int ret = 0;
+	int chipnum, ret = 0;
 
-	if ((from + len) > mtd->size)
-	{
-		printk(KERN_WARNING "%s: read request past end of device "
-			"(0x%lx)\n", map->name, (unsigned long)from + len);
+	if ((from + len) > mtd->size) {
+		pr_warning("read request past end of device (0x%lx)\n",
+			   (unsigned long)from + len);
 		return -EINVAL;
 	}
 
@@ -464,19 +172,15 @@
 
 	*retlen = 0;
 
-	while (len)
-	{
+	while (len) {
 		unsigned long this_len;
 
-		if (chipnum >= private->numchips)
-			break;
-
-		if ((len + offset -1) >> private->chipshift)
+		if ((len + offset - 1) >> private->chipshift)
 			this_len = (1 << private->chipshift) - offset;
 		else
 			this_len = len;
 
-		ret = read_one_chip(map, &private->chips[chipnum], offset,
+		ret = read_one_chip(map, &private->chip, offset,
 				this_len, buf);
 
 		if (ret)
@@ -496,10 +200,10 @@
 static int flash_is_busy(struct map_info *map, unsigned long addr)
 {
 	unsigned short toggled;
-	map_word read11,read21;
+	map_word read11, read21;
 
-	read11 = map->read(map,addr);
-	read21 = map->read(map,addr);
+	read11 = map_read(map, addr);
+	read21 = map_read(map, addr);
 
 	toggled = (unsigned short)read11.x[0] ^ (unsigned short)read21.x[0];
 
@@ -511,19 +215,17 @@
 		unsigned long addr, unsigned long datum)
 {
 	unsigned long timeo = jiffies + HZ;
-	struct stm_flash_private *private = map->fldrv_priv;
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
 	int times_left;
 	map_word test;
 
-retry:
+ retry:
 	spin_lock_bh(chip->mutex);
 
-	if (chip->state != FL_READY)
-	{
-		printk("%s: waiting for chip to write, state = %d\n",
-				map->name, chip->state);
+	if (chip->state != FL_READY) {
+		pr_info("%s: waiting for chip to write, state = %d\n",
+			map->name, chip->state);
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		add_wait_queue(&chip->wq, &wait);
 
@@ -531,7 +233,7 @@
 
 		schedule();
 		remove_wait_queue(&chip->wq, &wait);
-		printk(KERN_INFO "%s: woke up to write\n", map->name);
+		pr_info("%s: woke up to write\n", map->name);
 		if (signal_pending(current))
 			return -EINTR;
 
@@ -546,36 +248,31 @@
 
 	send_cmd(map, chip->start, CMD_PROGRAM_UNLOCK_DATA);
 
-	test.x[0]=datum;
-	map->write(map, test, addr);
+	test.x[0] = datum;
+	map_write(map, test, addr);
 
 	times_left = 50000;
-	while (times_left-- && flash_is_busy(map, addr))
-	{
-		if (need_resched())
-		{
+	while (times_left-- && flash_is_busy(map, addr)) {
+		if (need_resched()) {
 			spin_unlock_bh(chip->mutex);
 			schedule();
 			spin_lock_bh(chip->mutex);
 		}
 	}
 
-	if (!times_left)
-	{
-		printk(KERN_WARNING "%s: write to 0x%lx timed out!\n",
-				map->name, addr);
+	if (!times_left) {
+		pr_warning("write to 0x%lx timed out!\n", addr);
 		ret = -EIO;
 	} else {
 		unsigned long verify;
 		map_word test;
 
-		test = map->read(map,addr);
-		verify = test.x[0] ;
-		if(verify != datum)
-		{
-			printk(KERN_WARNING "%s: write to 0x%lx failed. "
-				"datum = %lx, verify = %lx\n", map->name,
-				addr, datum, verify);
+		test = map_read(map, addr);
+		verify = test.x[0];
+		if (verify != datum) {
+			pr_warning("write to 0x%lx failed "
+				   "datum = %lx, verify = %lx\n",
+				   addr, datum, verify);
 			ret = -EIO;
 		}
 	}
@@ -594,7 +291,6 @@
 	int ret = 0;
 	int chipnum;
 	unsigned long offset;
-	unsigned long chipstart;
 
 	*retlen = 0;
 	if (!len)
@@ -602,31 +298,29 @@
 
 	chipnum = to >> private->chipshift;
 	offset = to - (chipnum << private->chipshift);
-	chipstart = private->chips[chipnum].start;
 
 	/* If it's not bus-aligned, do the first byte write. */
-	if (offset & (map->bankwidth -1))
-	{
+	if (offset & (map->bankwidth - 1)) {
 		unsigned long bus_offset = offset & ~(map->bankwidth - 1);
 		int i = offset - bus_offset;
 		int n = 0;
 		unsigned char tmp_buf[4];
 		unsigned long datum;
 
-		map->copy_from(map, tmp_buf,
-			       bus_offset + private->chips[chipnum].start,
+		map_copy_from(map, tmp_buf,
+			       bus_offset + private->chip.start,
 			       map->bankwidth);
 		while (len && i < map->bankwidth)
 			tmp_buf[i++] = buf[n++], len--;
 
 		if (map->bankwidth == 2)
-			datum = *(__u16*)tmp_buf;
+			datum = *(__u16 *)tmp_buf;
 		else if (map->bankwidth == 4)
-			datum = *(__u32*)tmp_buf;
+			datum = *(__u32 *)tmp_buf;
 		else
 			return -EINVAL;
 
-		ret = write_one_word(map, &private->chips[chipnum], bus_offset,
+		ret = write_one_word(map, &private->chip, bus_offset,
 				datum);
 
 		if (ret)
@@ -637,29 +331,23 @@
 		(*retlen) += n;
 
 		if (offset >> private->chipshift)
-		{
-			chipnum++;
-			offset = 0;
-			if (chipnum == private->numchips)
-				return 0;
-		}
+			return 0;
 	}
 
 	/* We are now aligned, write as much as possible. */
-	while (len >= map->bankwidth)
-	{
+	while (len >= map->bankwidth) {
 		unsigned long datum;
 
 		if (map->bankwidth == 1)
-			datum = *(unsigned char*)buf;
+			datum = *(unsigned char *)buf;
 		else if (map->bankwidth == 2)
-			datum = *(unsigned short*)buf;
+			datum = *(unsigned short *)buf;
 		else if (map->bankwidth == 4)
-			datum = *(unsigned long*)buf;
+			datum = *(unsigned long *)buf;
 		else
 			return -EINVAL;
 
-		ret = write_one_word(map, &private->chips[chipnum], offset,
+		ret = write_one_word(map, &private->chip, offset,
 				datum);
 
 		if (ret)
@@ -671,36 +359,29 @@
 		len -= map->bankwidth;
 
 		if (offset >> private->chipshift)
-		{
-			chipnum++;
-			offset = 0;
-			if (chipnum == private->numchips)
-				return 0;
-			chipstart = private->chips[chipnum].start;
-		}
+			return 0;
 	}
 
-	if (len & (map->bankwidth - 1))
-	{
+	if (len & (map->bankwidth - 1)) {
 		int i = 0, n = 0;
 		unsigned char tmp_buf[2];
 		unsigned long datum;
 
-		map->copy_from(map, tmp_buf,
-				offset + private->chips[chipnum].start,
+		map_copy_from(map, tmp_buf,
+				offset + private->chip.start,
 				map->bankwidth);
 
 		while (len--)
 			tmp_buf[i++] = buf[n++];
 
 		if (map->bankwidth == 2)
-			datum = *(unsigned short*)tmp_buf;
+			datum = *(unsigned short *)tmp_buf;
 		else if (map->bankwidth == 4)
-			datum = *(unsigned long*)tmp_buf;
+			datum = *(unsigned long *)tmp_buf;
 		else
 			return -EINVAL;
 
-		ret = write_one_word(map, &private->chips[chipnum], offset,
+		ret = write_one_word(map, &private->chip, offset,
 				datum);
 
 		if (ret)
@@ -716,14 +397,12 @@
 			   unsigned long addr, unsigned long size)
 {
 	unsigned long timeo = jiffies + HZ;
-	/*struct stm_flash_private *private = map->fldrv_priv;*/
 	DECLARE_WAITQUEUE(wait, current);
 
-retry:
+ retry:
 	spin_lock_bh(chip->mutex);
 
-	if (chip->state != FL_READY)
-	{
+	if (chip->state != FL_READY) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		add_wait_queue(&chip->wq, &wait);
 
@@ -753,17 +432,14 @@
 	schedule_timeout(HZ);
 	spin_lock_bh(chip->mutex);
 
-	while (flash_is_busy(map, chip->start))
-	{
-		if (chip->state != FL_ERASING)
-		{
+	while (flash_is_busy(map, chip->start)) {
+		if (chip->state != FL_ERASING) {
 			/* Someone's suspended the erase. Sleep. */
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			add_wait_queue(&chip->wq, &wait);
 
 			spin_unlock_bh(chip->mutex);
-			printk(KERN_INFO "%s: erase suspended. Sleeping.\n",
-				map->name);
+			pr_info("erase suspended, sleeping\n");
 			schedule();
 			remove_wait_queue(&chip->wq, &wait);
 
@@ -776,13 +452,10 @@
 		}
 
 		/* OK Still waiting */
-		if (time_after(jiffies, timeo))
-		{
+		if (time_after(jiffies, timeo)) {
 			chip->state = FL_READY;
 			spin_unlock_bh(chip->mutex);
-			printk(KERN_WARNING "%s: waiting for erase to complete "
-				"timed out.\n", map->name);
-
+			pr_warning("waiting for erase to complete timed out\n");
 			return -EIO;
 		}
 
@@ -804,22 +477,20 @@
 		int verify;
 		map_word test;
 
-		for (address = addr; address < (addr + size); address += 2){
-			test = map_read(map,address);
+		for (address = addr; address < (addr + size); address += 2) {
+			test = map_read(map, address);
 			verify = test.x[0];
-			if(verify != 0xFFFF)
-			{
+			if (verify != 0xFFFF) {
 				error = 1;
 				break;
 			}
 		}
 
-		if (error)
-		{
+		if (error) {
 			chip->state = FL_READY;
 			spin_unlock_bh(chip->mutex);
-			printk(KERN_WARNING "%s: verify error at 0x%x, size "
-				"%ld.\n", map->name, address, size);
+			pr_warning("verify error at 0x%x, size %ld\n",
+				   address, size);
 			return -EIO;
 		}
 	}
@@ -835,7 +506,7 @@
 {
 	struct map_info *map = mtd->priv;
 	struct stm_flash_private *private = map->fldrv_priv;
-	unsigned long addr, len;
+	unsigned long addr, len, shift;
 	int chipnum;
 	int ret = 0;
 	int i, first;
@@ -861,15 +532,15 @@
 	 */
 	while ((i < mtd->numeraseregions) &&
 	       (instr->addr >= regions[i].offset))
-		i++;
-	i--;
+		++i;
+	--i;
 
 	/*
 	 * OK. Now i is pointing at the erase region in which this erase
 	 * request starts. Check the start of the requested erase range
 	 * is aligned with the erase size which is in effect here.
 	 */
-	if (instr->addr & (regions[i].erasesize -1))
+	if (instr->addr & (regions[i].erasesize - 1))
 		return -EINVAL;
 
 	/*
@@ -883,10 +554,10 @@
 	 */
 	while ((i < mtd->numeraseregions) &&
 	       ((instr->addr + instr->len) >= regions[i].offset))
-		i++;
-	i--;
+		++i;
+	--i;
 
-	if ((instr->addr + instr->len) & (regions[i].erasesize-1))
+	if ((instr->addr + instr->len) & (regions[i].erasesize - 1))
 		return -EINVAL;
 
 	chipnum = instr->addr >> private->chipshift;
@@ -894,10 +565,9 @@
 	len = instr->len;
 
 	i = first;
-
-	while (len)
-	{
-		ret = erase_one_block(map, &private->chips[chipnum], addr,
+	shift = (1 << private->chipshift) - 1;
+	while (len) {
+		ret = erase_one_block(map, &private->chip, addr,
 				regions[i].erasesize);
 
 		if (ret)
@@ -906,20 +576,14 @@
 		addr += regions[i].erasesize;
 		len -= regions[i].erasesize;
 
-		if ((addr % (1 << private->chipshift)) ==
-		    ((regions[i].offset + (regions[i].erasesize *
-					   regions[i].numblocks))
-		     % (1 << private->chipshift)))
-			i++;
+		if ((addr & shift) ==
+		    ((regions[i].offset +
+		      (regions[i].erasesize * regions[i].numblocks))
+		     & shift))
+			++i;
 
-		if (addr >> private->chipshift)
-		{
-			addr = 0;
-			chipnum++;
-
-			if (chipnum >= private->numchips)
-				break;
-		}
+		if (addr & ~shift)
+			break;
 	}
 
 	instr->state = MTD_ERASE_DONE;
@@ -929,27 +593,155 @@
 	return 0;
 }
 
-static int stm_flash_suspend(struct mtd_info *mtd)
+static void stm_flash_destroy(struct mtd_info *mtd)
 {
-	printk("stm_flash_suspend(): not implemented!\n");
-	        return -EINVAL;
+	struct map_info *map = mtd->priv;
+	struct stm_flash_private *private = map->fldrv_priv;
+	kfree(private);
 }
 
-static void stm_flash_resume(struct mtd_info *mtd)
+struct stm_flash_info {
+	u8 mfr_id, dev_id;
+	char *name;
+	unsigned long size;
+	int numeraseregions;
+	struct mtd_erase_region_info regions[1];
+};
+
+const struct stm_flash_info stm_data[] = {
+	{
+		.mfr_id = 0x20,
+		.dev_id = 0xe9,
+		.name   = "STM PSD4256G6V",
+		.size   = 0x100000,
+		.numeraseregions = 1,
+		.regions = {
+			{
+				.offset    = 0x000000,
+				.erasesize = 0x10000,
+				.numblocks = 16
+			},
+		},
+	},
+};
+
+static int stm_probe_new_chip(struct mtd_info *mtd)
 {
-	printk("stm_flash_resume(): not implemented!\n");
+	const struct stm_flash_info *std;
+	struct map_info *map = mtd->priv;
+	int i;
+	u8 mfr_id, dev_id;
+	map_word mfr_word, dev_word;
+
+	/* Enter autoselect mode */
+	send_cmd(map, 0, CMD_RESET_DATA);
+	send_cmd(map, 0, CMD_MANUFACTURER_UNLOCK_DATA);
+
+	mfr_word = map_read(map, ADDR_MANUFACTURER);
+	dev_word = map_read(map, ADDR_DEVICE_ID);
+	mfr_id = mfr_word.x[0] & 0xFF;
+	dev_id = dev_word.x[0] & 0xFF;
+
+	/* Exit autoselect mode */
+	send_cmd(map, 0, CMD_RESET_DATA);
+
+	for (i = 0; i < ARRAY_SIZE(stm_data); ++i) {
+		std = &stm_data[i];
+		if (mfr_id == std->mfr_id && dev_id == std->dev_id)
+			break;
+	}
+	if (i == ARRAY_SIZE(stm_data)) {
+		pr_warning("unknown mfr/dev id: 0x%02x 0x%02x\n", mfr_id, dev_id);
+		return 1;
+	}
+
+	mtd->size += std->size;
+	mtd->numeraseregions += std->numeraseregions;
+
+	mtd->eraseregions = kmalloc(sizeof(*mtd->eraseregions) *
+				    mtd->numeraseregions, GFP_KERNEL);
+	if (!mtd->eraseregions) {
+		pr_warning("failed to allocate memory for MTD erase region\n");
+		return 1;
+	}
+
+	for (i = 0; i < std->numeraseregions; ++i) {
+		mtd->eraseregions[i].offset    = std->regions[i].offset;
+		mtd->eraseregions[i].erasesize = std->regions[i].erasesize;
+		mtd->eraseregions[i].numblocks = std->regions[i].numblocks;
+		if (mtd->erasesize < mtd->eraseregions[i].erasesize)
+			mtd->erasesize = mtd->eraseregions[i].erasesize;
+	}
+
+	pr_info("found %s device at %p in %d-bit bank\n",
+	        std->name, map->virt, map->bankwidth * 8);
+
+	return 0;
 }
 
-int __init stm_flash_init(void)
+static struct mtd_info *stm_flash_probe(struct map_info *map);
+
+static struct mtd_chip_driver stm_flash_chipdrv = {
+	.probe   = stm_flash_probe,
+	.destroy = stm_flash_destroy,
+	.name    = "stm_flash",
+	.module  = THIS_MODULE
+};
+
+static struct mtd_info *stm_flash_probe(struct map_info *map)
 {
+	struct mtd_info *mtd;
+	struct flchip *chip;
+	struct stm_flash_private *private;
+	unsigned long size;
+
+	mtd = kzalloc(sizeof(*mtd) + sizeof(*private), GFP_KERNEL);
+	if (!mtd) {
+		pr_warning("kmalloc failed for info structure\n");
+		return NULL;
+	}
+	mtd->priv = map;
+	map->fldrv_priv = private = (void *)&mtd[1];
+	map->fldrv = &stm_flash_chipdrv;
+
+	if (stm_probe_new_chip(mtd)) {
+		kfree(mtd);
+		return NULL;
+	}
+
+	chip = &private->chip;
+	init_waitqueue_head(&chip->wq);
+	spin_lock_init(&chip->_spinlock);
+	chip->start = 0;
+	chip->state = FL_READY;
+	chip->mutex = &chip->_spinlock;
+	for (size = mtd->size; size > 1; size >>= 1)
+		++private->chipshift;
+
+	mtd->type  = MTD_NORFLASH;
+	mtd->flags = MTD_CAP_NORFLASH;
+	mtd->name  = map->name;
+	mtd->erase = stm_flash_erase;
+	mtd->read  = stm_flash_read;
+	mtd->write = stm_flash_write;
+	mtd->sync  = stm_flash_sync;
+	mtd->writesize = 1;
+
+	return mtd;
+}
+
+static int __init stm_flash_init(void)
+{
 	register_mtd_chip_driver(&stm_flash_chipdrv);
 	return 0;
 }
+module_init(stm_flash_init);
 
-void __exit stm_flash_exit(void)
+static void __exit stm_flash_exit(void)
 {
 	unregister_mtd_chip_driver(&stm_flash_chipdrv);
 }
-
-module_init(stm_flash_init);
 module_exit(stm_flash_exit);
+
+MODULE_DESCRIPTION("MTD chip driver for ST PSD4256G flashes");
+MODULE_LICENSE("GPL");
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to