Skip to contentSkip to conversation

SST25L (non JEDEC) SPI Flash driver

PATCH In review Ryan Mallon 4 participants 5 messages Jun 24, 2009 – Jul 3, 2009

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 SST25L (non JEDEC) SPI Flash driver

Hi Andrew,

It was suggested I send the following patch via you as David Woodhouse is currently busy.

Thanks,
~Ryan

----
Add support for the non JEDEC SST25L SPI Flash devices.

----

drivers/mtd/devices/Kconfig +10 -0
index 325fab9..c222514 100644
@@ -104,6 +104,16 @@ config M25PXX_USE_FAST_READ
 	help
 	  This option enables FAST_READ access supported by ST M25Pxx.
 
+config MTD_SST25L
+	tristate "Support SST25L (non JEDEC) SPI Flash chips"
+	depends on SPI_MASTER
+	help
+	  This enables access to the non JEDEC SST25L SPI flash chips, used
+	  for program and data storage.
+
+	  Set up your spi devices with the right board-specific platform data,
+	  if you want to specify device partitioning.
+
 config MTD_SLRAM
 	tristate "Uncached system RAM"
 	help
drivers/mtd/devices/Makefile +1 -0
index 0993d5c..ab5c9b9 100644
@@ -16,3 +16,4 @@ obj-$(CONFIG_MTD_LART)		+= lart.o
 obj-$(CONFIG_MTD_BLOCK2MTD)	+= block2mtd.o
 obj-$(CONFIG_MTD_DATAFLASH)	+= mtd_dataflash.o
 obj-$(CONFIG_MTD_M25P80)	+= m25p80.o
+obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
drivers/mtd/devices/sst25l.c new file +503 -0

503 lines not on this page · raw message

#1 lore raw

2009/6/25 Ryan Mallon <[email protected]>:

Quoted 2 lines

It was suggested I send the following patch via you as David Woodhouse is currently busy.

Actually it was David Brownell (the SPI maintainer) I was thinking of that was sort of busy lately, perhaps Woodhouse (the MTD maintainer) is less busy ... let's see.

Linus Walleij

#3 lore raw
In reply to Ryan Mallon
Quoted 5 lines · On Thu, 25 Jun 2009 11:59:47 +1200 Ryan Mallon <[email protected]> wrote:

Add support for the non JEDEC SST25L SPI Flash devices.

It looks OK to my inexperienced eye.

drivers/mtd/devices/sst25l.c line 301

Quoted 3 lines

...

drivers/mtd/devices/sst25l.c new file +1 -0
+		bytes = min(mtd->writesize, (u32)(len - i));

The conventional way of suppressing the warning is min_t().

Quoted 86 lines
drivers/mtd/devices/sst25l.c new file +86 -0
+static int __init sst25l_probe(struct spi_device *spi)
+{
+	struct flash_info *flash_info;
+	struct sst25l_flash *flash;
+	struct flash_platform_data *data;
+	int i;
+
+	flash_info = sst25l_match_device(spi);
+	if (!flash_info)
+		return -ENODEV;
+
+	flash = kzalloc(sizeof(struct sst25l_flash), GFP_KERNEL);
+	if (!flash)
+		return -ENOMEM;
+
+	flash->spi = spi;
+	mutex_init(&flash->lock);
+	dev_set_drvdata(&spi->dev, flash);
+
+	data = spi->dev.platform_data;
+	if (data && data->name)
+		flash->mtd.name = data->name;
+	else
+		flash->mtd.name = dev_name(&spi->dev);
+
+	flash->mtd.type		= MTD_NORFLASH;
+	flash->mtd.flags	= MTD_CAP_NORFLASH;
+	flash->mtd.erasesize	= flash_info->erase_size;
+	flash->mtd.writesize	= flash_info->page_size;
+	flash->mtd.size		= flash_info->page_size * flash_info->nr_pages;
+	flash->mtd.erase	= sst25l_erase;
+	flash->mtd.read		= sst25l_read;
+	flash->mtd.write 	= sst25l_write;
+
+	dev_info(&spi->dev, "%s (%lld Kbytes)\n", flash_info->name,
+		 (long long)flash->mtd.size >> 10);
+
+	DEBUG(MTD_DEBUG_LEVEL2,
+	      "mtd .name = %s, .size = 0x%llx (%lldMiB) "
+	      ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
+	      flash->mtd.name,
+	      (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
+	      flash->mtd.erasesize, flash->mtd.erasesize / 1024,
+	      flash->mtd.numeraseregions);
+
+	if (flash->mtd.numeraseregions)
+		for (i = 0; i < flash->mtd.numeraseregions; i++)
+			DEBUG(MTD_DEBUG_LEVEL2,
+			      "mtd.eraseregions[%d] = { .offset = 0x%llx, "
+			      ".erasesize = 0x%.8x (%uKiB), "
+			      ".numblocks = %d }\n",
+			      i, (long long)flash->mtd.eraseregions[i].offset,
+			      flash->mtd.eraseregions[i].erasesize,
+			      flash->mtd.eraseregions[i].erasesize / 1024,
+			      flash->mtd.eraseregions[i].numblocks);
+
+	if (mtd_has_partitions()) {
+		struct mtd_partition *parts = NULL;
+		int nr_parts = 0;
+
+		if (mtd_has_cmdlinepart()) {
+			static const char *part_probes[] =
+				{"cmdlinepart", NULL};
+
+			nr_parts = parse_mtd_partitions(&flash->mtd,
+							part_probes,
+							&parts, 0);
+		}
+
+		if (nr_parts <= 0 && data && data->parts) {
+			parts = data->parts;
+			nr_parts = data->nr_parts;
+		}
+
+		if (nr_parts > 0) {
+			for (i = 0; i < nr_parts; i++) {
+				DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
+				      "{.name = %s, .offset = 0x%llx, "
+				      ".size = 0x%llx (%lldKiB) }\n",
+				      i, parts[i].name,
+				      (long long)parts[i].offset,
+				      (long long)parts[i].size,
+				      (long long)(parts[i].size >> 10));
+			}
+
+			flash->partitioned = 1;

drivers/mtd/devices/sst25l.c line 460

Quoted 10 lines
drivers/mtd/devices/sst25l.c new file +10 -0
+			return add_mtd_partitions(&flash->mtd,
+						  parts, nr_parts);
+		}
+
+	} else if (data->nr_parts) {
+		dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
+			 data->nr_parts, data->name);
+	}
+
+	return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;

If this returns -ENODEV, did we leak the memory at *flash?

Quoted 2 lines
(quoted diff) +2 -0
+}
+
#4 lore raw
Quoted 13 lines · Andrew Morton
Quoted 6 lines · On Thu, 25 Jun 2009 11:59:47 +1200 Ryan Mallon <[email protected]> wrote:

Add support for the non JEDEC SST25L SPI Flash devices.

It looks OK to my inexperienced eye.

Cool, thanks for picking this up. The patch below fixes the two issues you pointed out. It will apply on top of mtd-sst25l-non-jedec-spi-flash-driver-update.patch

----
Fix two issues in the SSTL25 driver:
- Replace min() plus u32 cast with min_t
- Fix memory leak on failed add_mtd_device

----

drivers/mtd/devices/sst25l.c +10 -3
index 777fadf..d235067 100644
@@ -298,7 +298,7 @@ static int sst25l_write(struct mtd_info *mtd, loff_t to, size_t len,
 		 * Write the remaining bytes using auto address
 		 * increment mode
 		 */
-		bytes = min(mtd->writesize, (u32)(len - i));
+		bytes = min_t(u32, mtd->writesize, len - i);
 		for (j = 1; j < bytes; j++, copied++) {
 			ret = sst25l_wait_till_ready(flash);
 			if (ret)
@@ -367,7 +367,7 @@ static int __init sst25l_probe(struct spi_device *spi)
 	struct flash_info *flash_info;
 	struct sst25l_flash *flash;
 	struct flash_platform_data *data;
-	int i;
+	int ret, i;
 
 	flash_info = sst25l_match_device(spi);
 	if (!flash_info)
@@ -457,7 +457,14 @@ static int __init sst25l_probe(struct spi_device *spi)
 			 data->nr_parts, data->name);
 	}
 
-	return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;
+	ret = add_mtd_device(&flash->mtd);
+	if (ret == 1) {
+		kfree(flash);
+		dev_set_drvdata(&spi->dev, NULL);
+		return -ENODEV;
+	}
+	
+	return 0;
 }
 
 static int __exit sst25l_remove(struct spi_device *spi)
#2 lore raw
In reply to Linus Walleij
Quoted 6 lines · Linus Walleij
Quoted 2 lines

It was suggested I send the following patch via you as David Woodhouse is currently busy.

Actually it was David Brownell (the SPI maintainer) I was thinking of that was sort of busy lately, perhaps Woodhouse (the MTD maintainer) is less busy ... let's see.

It's an MTD patch so I'd expect it to go through the MTD tree... :)