[uClinux-dev] AMD - Am29LV160B

Geoffrey Espin espin at idiom.com
Tue Mar 4 16:57:03 EST 2003


Amit.Lubovsky at infineon.com wrote:

> >  x x    (BIG_ENDIAN_BYTE) Flash cmd/query data swapping                  x
> Maybe you need to try other variants, as well, i.e. little
> endian: you never know from which side they are looking
> at it :-)

You're sure its just the "B" part?  Not B3?

I had to write my own driver for the Intel 28F160B3.  It is NOT CFI
compliant.  This code also is verified for the 28F320B3 part.  Only
tested on a Conexant ARM plaform.

Geoff
--
Geoffrey Espin
espin at idiom.com
-------------- next part --------------
diff -b -Naur linux-2.4.20/drivers/mtd/devices/Config.in working/linux/drivers/mtd/devices/Config.in
--- linux-2.4.20/drivers/mtd/devices/Config.in	Thu Nov 28 15:53:13 2002
+++ working/linux/drivers/mtd/devices/Config.in	Sun Dec 22 06:03:15 2002
@@ -10,6 +10,12 @@
    bool '    PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX
    bool '    PMC551 Debugging' CONFIG_MTD_PMC551_DEBUG
 fi
+## XXX
+if [ "$CONFIG_ARCH_CX821XX" = "y" ]; then
+  dep_tristate '  Conexant 28F160/28F320 B3 flash driver' CONFIG_MTD_CONEXANT_FLASH
+$CONFIG_MTD
+fi
+
 if [ "$CONFIG_DECSTATION" = "y" ]; then
    dep_tristate '  DEC MS02-NV NVRAM module support' CONFIG_MTD_MS02NV $CONFIG_MTD $CONFIG_DECSTATION
 fi
diff -b -Naur linux-2.4.20/drivers/mtd/devices/Makefile working/linux/drivers/mtd/devices/Makefile
--- linux-2.4.20/drivers/mtd/devices/Makefile	Thu Nov 28 15:53:13 2002
+++ working/linux/drivers/mtd/devices/Makefile	Sun Dec 22 06:04:10 2002
@@ -22,5 +22,7 @@
 obj-$(CONFIG_MTD_MTDRAM)	+= mtdram.o
 obj-$(CONFIG_MTD_LART)		+= lart.o
 obj-$(CONFIG_MTD_BLKMTD)	+= blkmtd.o
+obj-$(CONFIG_MTD_CONEXANT_FLASH)+= conexant-flash.o
+
 
 include $(TOPDIR)/Rules.make
diff -b -Naur linux-2.4.20/drivers/mtd/devices/conexant-flash.c working/linux/drivers/mtd/devices/conexant-flash.c
--- linux-2.4.20/drivers/mtd/devices/conexant-flash.c	Wed Dec 31 16:00:00 1969
+++ working/linux/drivers/mtd/devices/conexant-flash.c	Sun Dec 22 06:01:37 2002
@@ -0,0 +1,697 @@
+/*
+ * MTD driver for the 28F160B3 Flash Memory (non-CFI) on Conexant.
+ *
+ * Author: Geoffrey Espin based on work by...
+ *         Abraham vd Merwe <abraham at 2d3d.co.za>
+ *
+ * Copyright (c) 2001, 2d3D, Inc.
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * References:
+ *
+ *    [1] 3 Volt Fast Boot Block Flash Memory" Intel Datasheet
+ *           - Order Number: 290644-005
+ *           - January 2000
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#ifndef CONFIG_CHIP_CX82100
+#error This is for CONEXANT architecture only
+#endif
+
+static char module_name[] = "conexant-flash";
+
+#define xCONEXANT_DEBUG 1 /* debugging */
+
+// XXX ESPIN FIX/CHECK! for 28F320 PART
+//
+/*
+ * These values is specific to 28Fxxxx3 flash memory.
+ * See section 2.3.1 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
+ */
+#define FLASH_BLOCKSIZE_PARAM		(8 * 1024)	// 8K
+#define FLASH_NUMBLOCKS_PARAM		8		// same for 16m & 32m
+
+/*
+ * These values is specific to 28Fxxxx3 flash memory.
+ * See section 2.3.2 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
+ */
+#define FLASH_BLOCKSIZE_MAIN		(64 * 1024)	// 64K
+#define FLASH_NUMBLOCKS_16m_MAIN	31
+#define FLASH_NUMBLOCKS_32m_MAIN	(31+32)
+
+#define FLASH_TOTAL_16m_SIZE		((FLASH_NUMBLOCKS_16m_MAIN * 64 * 1024) + (8 * 8 * 1024))
+#define FLASH_TOTAL_32m_SIZE		((FLASH_NUMBLOCKS_32m_MAIN * 64 * 1024) + (8 * 8 * 1024))
+
+#define _WIDTH		u16		/* code could break if changed */
+#define BUSWIDTH	2		/* code could break if changed */
+#define FLASH_OFFSET	0x00400000	/* base of flash */
+#define	READBW	read16			/* read8/read32 */
+#define	WRITEBW	write16			/* write8/write32 */
+
+/*
+ * See section 4.0 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
+ */
+#define READ_ARRAY		(_WIDTH)0x00FF00FF	/* Read Array/Reset */
+#define READ_ID_CODES		(_WIDTH)0x00900090	/* Read Identifier Codes */
+#define ERASE_SETUP		(_WIDTH)0x00200020	/* Block Erase */
+#define ERASE_CONFIRM		(_WIDTH)0x00D000D0	/* Block Erase and Program Resume */
+#define PGM_SETUP		(_WIDTH)0x00400040	/* Program */
+#define STATUS_READ		(_WIDTH)0x00700070	/* Read Status Register */
+#define STATUS_CLEAR		(_WIDTH)0x00500050	/* Clear Status Register */
+#define STATUS_BUSY		(_WIDTH)0x00800080	/* Write State Machine Status (WSMS) */
+#define STATUS_ERASE_ERR	(_WIDTH)0x00200020	/* Erase Status (ES) */
+#define STATUS_PGM_ERR		(_WIDTH)0x00100010	/* Program Status (PS) */
+
+/*
+ * See section 4.2 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
+ */
+#define FLASH_MANUFACTURER		(_WIDTH)0x00890089
+#define xFLASH_DEVICE_16mbit_TOP	(_WIDTH)0x88f388f3	// F3
+#define xFLASH_DEVICE_16mbit_BOTTOM	(_WIDTH)0x88f488f4	// F3
+
+								// 28F160
+#define FLASH_DEVICE_16mbit_TOP		(_WIDTH)0x88908890	// B3 untested?
+#define FLASH_DEVICE_16mbit_BOTTOM	(_WIDTH)0x88918891	// B3 BA90
+								// 28F320
+#define FLASH_DEVICE_32mbit_TOP		(_WIDTH)0x88968896	// B3 untested?
+#define FLASH_DEVICE_32mbit_BOTTOM	(_WIDTH)0x88978897	// B3 BC90
+
+static int conexant_size_bottom = -1;
+
+/******************************************************************************/
+
+
+static __u8
+read8(__u32 offset)
+{
+	__u8 data = *(volatile __u8 *) (FLASH_OFFSET + offset);
+#ifdef CONEXANT_DEBUG
+#if CONEXANT_DEBUG > 1
+	printk("%s(): 0x%.8x -> 0x%.2x\n", __FUNCTION__, FLASH_OFFSET + offset, data);
+#endif
+#endif
+	return (data);
+}
+
+static __u16
+read16(__u32 offset)
+{
+	__u16 data = *(volatile __u16 *) (FLASH_OFFSET + offset);
+#ifdef CONEXANT_DEBUG
+#if CONEXANT_DEBUG > 1
+	printk("%s(): 0x%.8x -> 0x%.8x\n", __FUNCTION__, FLASH_OFFSET + offset, data);
+#endif
+#endif
+	return (data);
+}
+
+static void
+write16(__u16 x, __u32 offset)
+{
+	*(__u16 *) (FLASH_OFFSET + offset) = x;
+#ifdef CONEXANT_DEBUG
+#if CONEXANT_DEBUG > 1
+	printk("%s(): 0x%.8x <- 0x%.8x\n", __FUNCTION__, FLASH_OFFSET + offset, x);
+#endif
+#endif
+}
+
+/*****************************************************************************/
+
+/*
+ * Probe for 16mbit flash memory without doing too much damage.
+ *
+ * Returns 1 if we found 16mbit flash memory, 0 otherwise.
+ */
+static int
+flash_probe(void)
+{
+	_WIDTH manufacturer, devtype;
+
+	/* setup "Read Identifier Codes" mode */
+	WRITEBW(READ_ID_CODES, 0x0 * BUSWIDTH);
+
+	/* probe U2. U2/U3 returns the same data since the first 3 */
+	/* address lines is mangled in the same way */
+
+	manufacturer = READBW (0x0 * BUSWIDTH);
+	devtype = READBW (0x1 * BUSWIDTH);
+
+	/* put the flash back into command mode */
+	WRITEBW(READ_ARRAY, 0x0 * BUSWIDTH);
+
+	if (manufacturer == FLASH_MANUFACTURER) {
+		if (devtype == FLASH_DEVICE_16mbit_TOP)
+			conexant_size_bottom = 0x0;
+		else if (devtype == FLASH_DEVICE_16mbit_BOTTOM)
+			conexant_size_bottom = 0x1;
+		else if (devtype == FLASH_DEVICE_32mbit_TOP)
+			conexant_size_bottom = 0x2;
+		else if (devtype == FLASH_DEVICE_32mbit_BOTTOM)
+			conexant_size_bottom = 0x3;
+	}
+	printk("MFR %#x (%#x) DEV %#x (%#x,%#x,%#x,%#x) %s-boot %s\n", manufacturer,
+		FLASH_MANUFACTURER, devtype,
+		FLASH_DEVICE_16mbit_TOP, FLASH_DEVICE_16mbit_BOTTOM,
+		FLASH_DEVICE_32mbit_TOP, FLASH_DEVICE_32mbit_BOTTOM,
+		(conexant_size_bottom & 0x1) ? "bottom" : "top",
+		(conexant_size_bottom & 0x2) ? "4M" : "2M"
+		);
+
+	if (conexant_size_bottom == -1)
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Erase one block of flash memory at offset ``offset'' which is any
+ * address within the block which should be erased.
+ *
+ * Returns 1 if successful, 0 otherwise.
+ */
+static inline int
+erase_block(__u32 offset)
+{
+	int status;
+
+#ifdef CONEXANT_DEBUG
+	printk("%s(): 0x%.8x\n", __FUNCTION__, offset);
+#endif
+
+	/* erase and confirm */
+	WRITEBW(ERASE_SETUP, offset);
+	WRITEBW(ERASE_CONFIRM, offset);
+
+	/* wait for block erase to finish */
+	do {
+		WRITEBW(STATUS_READ, offset);
+		status = READBW(offset);
+	}
+	while ((~status & STATUS_BUSY) != 0);
+
+	/* put the flash back into command mode */
+	WRITEBW(READ_ARRAY, offset);
+
+	/* was the erase successfull? */
+	if ((status & STATUS_ERASE_ERR)) {
+		printk(KERN_WARNING "%s: erase error at address 0x%.8x.\n",
+		       module_name, offset);
+		return (0);
+	}
+
+	return (1);
+}
+
+static int
+flash_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	__u32 addr, len;
+	int i, first;
+
+#ifdef CONEXANT_DEBUG
+	printk("%s(addr = 0x%.8x, len = %d)\n", __FUNCTION__, instr->addr,
+	       instr->len);
+#endif
+
+	/* sanity checks */
+	if (instr->addr + instr->len > mtd->size)
+		return (-EINVAL);
+
+	/*
+	   * check that both start and end of the requested erase are
+	   * aligned with the erasesize at the appropriate addresses.
+	   *
+	   * skip all erase regions which are ended before the start of
+	   * the requested erase. Actually, to save on the calculations,
+	   * we skip to the first erase region which starts after the
+	   * start of the requested erase, and then go back one.
+	 */
+	for (i = 0;
+	     i < mtd->numeraseregions
+	     && instr->addr >= mtd->eraseregions[i].offset; 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 & (mtd->eraseregions[i].erasesize - 1))
+		return (-EINVAL);
+
+	/* Remember the erase region we start on */
+	first = i;
+
+	/*
+	   * next, check that the end of the requested erase is aligned
+	   * with the erase region at that address.
+	   *
+	   * as before, drop back one to point at the region in which
+	   * the address actually falls
+	 */
+	for (;
+	     i < mtd->numeraseregions
+	     && instr->addr + instr->len >= mtd->eraseregions[i].offset; i++) ;
+	i--;
+
+	/* is the end aligned on a block boundary? */
+	if ((instr->addr + instr->len) & (mtd->eraseregions[i].erasesize - 1))
+		return (-EINVAL);
+
+	addr = instr->addr;
+	len = instr->len;
+
+	i = first;
+
+	/* now erase those blocks */
+	while (len) {
+		if (!erase_block(addr)) {
+			instr->state = MTD_ERASE_FAILED;
+			return (-EIO);
+		}
+
+		addr += mtd->eraseregions[i].erasesize;
+		len -= mtd->eraseregions[i].erasesize;
+
+		if (addr ==
+		    mtd->eraseregions[i].offset +
+		    (mtd->eraseregions[i].erasesize *
+		     mtd->eraseregions[i].numblocks))
+			i++;
+	}
+
+	instr->state = MTD_ERASE_DONE;
+	if (instr->callback)
+		instr->callback(instr);
+
+	return (0);
+}
+
+static int
+flash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen,
+	   u_char * buf)
+{
+#ifdef CONEXANT_DEBUG
+	printk("%s(from = 0x%.8x, len = %d)\n", __FUNCTION__, (__u32) from,
+	       len);
+#endif
+
+	/* sanity checks */
+	if (!len)
+		return (0);
+	if (from + len > mtd->size)
+		return (-EINVAL);
+
+	/* we always read len bytes */
+	*retlen = len;
+
+	/* first, we read bytes until we reach a dword boundary */
+	if (from & (BUSWIDTH - 1)) {
+		int gap = BUSWIDTH - (from & (BUSWIDTH - 1));
+
+		while (len && gap--)
+			*buf++ = read8(from++), len--;
+	}
+
+	/* now we read dwords until we reach a non-dword boundary */
+	while (len >= BUSWIDTH) {
+		*((_WIDTH *) buf) = READBW(from);
+
+		buf += BUSWIDTH;
+		from += BUSWIDTH;
+		len -= BUSWIDTH;
+	}
+
+	/* top up the last unaligned bytes */
+	if (len & (BUSWIDTH - 1))
+		while (len--)
+			*buf++ = read8(from++);
+
+	return (0);
+}
+
+/*
+ * Write one dword ``x'' to flash memory at offset ``offset''. ``offset''
+ * must be 32 bits, i.e. it must be on a dword boundary.
+ *
+ * Returns 1 if successful, 0 otherwise.
+ */
+static inline int
+write_dword(__u32 offset, _WIDTH x)
+{
+	_WIDTH status;
+
+#ifdef CONEXANT_DEBUG
+#if CONEXANT_DEBUG > 1
+	printk("%s(): 0x%.8x <- 0x%.8x\n", __FUNCTION__, offset, x);
+#endif
+#endif
+
+	/* setup writing */
+	WRITEBW(PGM_SETUP, offset);
+
+	/* write the data */
+	WRITEBW(x, offset);
+
+	/* wait for the write to finish */
+	do {
+		WRITEBW(STATUS_READ, offset);
+		status = READBW(offset);
+	}
+	while ((~status & STATUS_BUSY) != 0);
+
+	/* put the flash back into command mode */
+	WRITEBW(READ_ARRAY, offset);
+
+	/* was the write successfull? */
+	if ((status & STATUS_PGM_ERR) || READBW(offset) != x) {
+		printk(KERN_WARNING "%s: write error at address 0x%.8x.\n",
+		       module_name, offset);
+		return (0);
+	}
+
+	return (1);
+}
+
+static int
+flash_write(struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen,
+	    const u_char * buf)
+{
+	__u8 tmp[4];
+	int i, n;
+
+#ifdef CONEXANT_DEBUG
+	printk("%s(to = 0x%.8x, len = %d)\n", __FUNCTION__, (__u32) to, len);
+#endif
+
+	*retlen = 0;
+
+	/* sanity checks */
+	if (!len)
+		return (0);
+	if (to + len > mtd->size)
+		return (-EINVAL);
+
+	/* first, we write a 0xFF.... padded byte until we reach a dword boundary */
+	if (to & (BUSWIDTH - 1)) {
+		__u32 aligned = to & ~(BUSWIDTH - 1);
+		int gap = to - aligned;
+
+		i = n = 0;
+
+		while (gap--)
+			tmp[i++] = 0xFF;
+		while (len && i < BUSWIDTH)
+			tmp[i++] = buf[n++], len--;
+		while (i < BUSWIDTH)
+			tmp[i++] = 0xFF;
+
+		if (!write_dword(aligned, *((_WIDTH *) tmp)))
+			return (-EIO);
+
+		to += n;
+		buf += n;
+		*retlen += n;
+	}
+
+	/* now we write dwords until we reach a non-dword boundary */
+	while (len >= BUSWIDTH) {
+		if (!write_dword(to, *((_WIDTH *) buf)))
+			return (-EIO);
+
+		to += BUSWIDTH;
+		buf += BUSWIDTH;
+		*retlen += BUSWIDTH;
+		len -= BUSWIDTH;
+	}
+
+	/* top up the last unaligned bytes, padded with 0xFF.... */
+	if (len & (BUSWIDTH - 1)) {
+		i = n = 0;
+
+		while (len--)
+			tmp[i++] = buf[n++];
+		while (i < BUSWIDTH)
+			tmp[i++] = 0xFF;
+
+		if (!write_dword(to, *((_WIDTH *) tmp)))
+			return (-EIO);
+
+		*retlen += n;
+	}
+
+	return (0);
+}
+
+static void flash_sync(struct mtd_info *mtd)
+{
+	        /* Nothing to see here */
+}
+
+/******************************************************************************/
+
+#define NB_OF(x) (sizeof (x) / sizeof ((x)[0]))
+
+static struct mtd_info conexant_mtd;
+
+// XXX ESPIN FIX/CHECK!
+static struct mtd_erase_region_info erase_regions_32tb[] = {
+	/* main blocks */
+	{
+		offset:		0x00000000,
+		erasesize:	64 * 1024,
+		numblocks:	31
+	},
+	/* parameter blocks */
+	{
+		offset:		0x00000000 + 31 * (64 * 1024),
+		erasesize:	8 * 1024,
+		numblocks:	8
+	}
+};
+
+static struct mtd_erase_region_info erase_regions_16bb[] = {
+	/* parameter blocks */
+	{
+		offset:		0x00000000,
+		erasesize:	8 * 1024,
+		numblocks:	8
+	},
+	/* main blocks */
+	{
+		offset:		0x00000000 + 8 * (8 * 1024),
+		erasesize:	64 * 1024,
+		numblocks:	31
+	}
+};
+
+static struct mtd_erase_region_info erase_regions_16tb[] = {
+	/* main blocks */
+	{
+		offset:		0x00000000,
+		erasesize:	64 * 1024,
+		numblocks:	31
+	},
+	/* parameter blocks */
+	{
+		offset:		0x00000000 + 31 * (64 * 1024),
+		erasesize:	8 * 1024,
+		numblocks:	8
+	}
+};
+
+static struct mtd_erase_region_info erase_regions_32bb[] = {
+	/* parameter blocks */
+	{
+		offset:		0x00000000,
+		erasesize:	8 * 1024,
+		numblocks:	8
+	},
+	/* main blocks */
+	{
+		offset:		0x00000000 + 8 * (8 * 1024),
+		erasesize:	64 * 1024,
+		numblocks:	31
+	}
+};
+
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition conexant_partitions[] = {
+	{
+		name:       "bootloader+kernel",
+		size:       0x00100000,	/* 1MB */
+		offset:     0,
+		mask_flags: 0		// set MTD_WRITEABLE if want readonly
+	},
+#if 0
+	{
+		name:	    "params",
+		size:	    0x00100000,	/* ? */
+		offset:	    MTDPART_OFS_APPEND,
+		mask_flags: MTD_WRITEABLE
+	},
+#endif
+	{
+		name:	   "romfs",
+		//size:	    MTDPART_SIZ_FULL,	/* 1MB */
+		//offset:	    MTDPART_OFS_APPEND,
+		size:       0x00100000,	/* 1MB */
+		offset:	    0x00100000,	/* 1MB */
+		mask_flags: 0		// set MTD_WRITEABLE if want readonly
+	}
+};
+#endif
+
+int __init
+conexant_flash_init(void)
+{
+	int result;
+
+	memset(&conexant_mtd, 0, sizeof (conexant_mtd));
+
+	printk("%s: probing for Conexant 28F160/320B3 flash.\n", module_name);
+
+	if (!flash_probe()) {
+		printk(KERN_WARNING "%s: Found no flash device.\n",
+		       module_name);
+		return (-ENXIO);
+	}
+
+	// map->fldrv = &mapram_chipdrv;
+	// mtd->priv = map;
+
+	conexant_mtd.name = module_name;
+	conexant_mtd.type = MTD_NORFLASH;
+	conexant_mtd.flags = MTD_CAP_NORFLASH;
+	conexant_mtd.size = ((conexant_size_bottom & 0x2) == 0) ?
+				FLASH_TOTAL_16m_SIZE : FLASH_TOTAL_32m_SIZE;
+	conexant_mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
+
+	if (conexant_size_bottom == 0x0) {
+		conexant_mtd.numeraseregions = NB_OF(erase_regions_16tb);
+		conexant_mtd.eraseregions = erase_regions_16tb;
+	} else if (conexant_size_bottom == 0x01) {
+		conexant_mtd.numeraseregions = NB_OF(erase_regions_16bb);
+		conexant_mtd.eraseregions = erase_regions_16bb;
+	} else if (conexant_size_bottom == 0x02) {
+		conexant_mtd.numeraseregions = NB_OF(erase_regions_32tb);
+		conexant_mtd.eraseregions = erase_regions_32tb;
+	} else if (conexant_size_bottom == 0x03) {
+		conexant_mtd.numeraseregions = NB_OF(erase_regions_32bb);
+		conexant_mtd.eraseregions = erase_regions_32bb;
+	} else {
+		printk (__FUNCTION__ ": conexant chip unknown!\n");
+		return (-ENXIO);
+	}
+
+	conexant_mtd.module = THIS_MODULE;
+	conexant_mtd.erase = flash_erase;
+	conexant_mtd.read = flash_read;
+	conexant_mtd.write = flash_write;
+	conexant_mtd.sync = flash_sync;
+
+#ifdef CONEXANT_DEBUG
+	printk("mtd.name = %s\n"
+	       "mtd.size = 0x%.8x (%uM)\n"
+	       "mtd.erasesize = 0x%.8x (%uK)\n"
+	       "mtd.numeraseregions = %d\n",
+	       conexant_mtd.name,
+	       conexant_mtd.size, conexant_mtd.size / (1024 * 1024),
+	       conexant_mtd.erasesize, conexant_mtd.erasesize / 1024, conexant_mtd.numeraseregions);
+
+	if (conexant_mtd.numeraseregions)
+		{
+		int ix;
+		for (ix = 0; ix < conexant_mtd.numeraseregions; ix++)
+			printk("\n\n"
+			       "mtd.eraseregions[%d].offset = 0x%.8x\n"
+			       "mtd.eraseregions[%d].erasesize = 0x%.8x (%uK)\n"
+			       "mtd.eraseregions[%d].numblocks = %d\n",
+			       ix, conexant_mtd.eraseregions[ix].offset,
+			       ix, conexant_mtd.eraseregions[ix].erasesize,
+			       conexant_mtd.eraseregions[ix].erasesize / 1024,
+			       ix, conexant_mtd.eraseregions[ix].numblocks);
+		}
+#endif
+
+#ifdef CONFIG_MTD_PARTITIONS
+	result = add_mtd_partitions(&conexant_mtd, conexant_partitions,
+			       NB_OF(conexant_partitions));
+#else
+	result = add_mtd_device(&conexant_mtd);
+#endif
+
+#ifdef CONEXANT_DEBUG
+	printk("mtd.name = %s\n"
+	       "mtd.size = 0x%.8x (%uM)\n"
+	       "mtd.erasesize = 0x%.8x (%uK)\n"
+	       "mtd.numeraseregions = %d\n",
+	       conexant_mtd.name,
+	       conexant_mtd.size, conexant_mtd.size / (1024 * 1024),
+	       conexant_mtd.erasesize, conexant_mtd.erasesize / 1024, conexant_mtd.numeraseregions);
+
+	if (conexant_mtd.numeraseregions)
+		{
+		int ix;
+		for (ix = 0; ix < conexant_mtd.numeraseregions; ix++)
+			printk("\n\n"
+			       "mtd.eraseregions[%d].offset = 0x%.8x\n"
+			       "mtd.eraseregions[%d].erasesize = 0x%.8x (%uK)\n"
+			       "mtd.eraseregions[%d].numblocks = %d\n",
+			       ix, conexant_mtd.eraseregions[ix].offset,
+			       ix, conexant_mtd.eraseregions[ix].erasesize,
+			       conexant_mtd.eraseregions[ix].erasesize / 1024,
+			       ix, conexant_mtd.eraseregions[ix].numblocks);
+		}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	{
+	int ix;
+	printk("\npartitions = %d\n", NB_OF(conexant_partitions));
+
+	for (ix = 0; ix < NB_OF(conexant_partitions); ix++)
+		printk("\n\n"
+		       "conexant_partitions[%d].name = %s\n"
+		       "conexant_partitions[%d].offset = 0x%.8x\n"
+		       "conexant_partitions[%d].size = 0x%.8x (%uK)\n",
+		       ix, conexant_partitions[ix].name,
+		       ix, conexant_partitions[ix].offset,
+		       ix, conexant_partitions[ix].size,
+		       conexant_partitions[ix].size / 1024);
+	}
+#endif // CONFIG_MTD_PARTITIONS
+#endif // CONEXANT_DEBUG
+
+	return (result);
+}
+
+void __exit
+conexant_flash_exit(void)
+{
+#ifdef CONFIG_MTD_PARTITIONS
+	del_mtd_partitions(&conexant_mtd);
+#endif
+//	del_mtd_device(&conexant_mtd);
+}
+
+module_init(conexant_flash_init);
+module_exit(conexant_flash_exit);
+
+//MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Geoffrey Espin <espin at idiom.com>");
+MODULE_DESCRIPTION
+    ("MTD driver for Intel 28F160B3 on Conexant board (derived from LART)");
+


More information about the uClinux-dev mailing list