Commit 0ebd6ce0 authored by Russell King's avatar Russell King

[MTD] Update 2.5 MTD code from MTD CVS and ARM tree

This cset updates the 2.5 MTD code from the MTD CVS.  David Woodhouse
is happy with me sending this.

Summary of changes:
- Add MTD device concatenation support module.
- Bootldr MTD partition parsing is obsolete, replaced by command-line
  based partition information.
- Add support for ARM map drivers:
   AUTCPU12, Ceiva, Camelot, Fortunet, edb7312, Impa7, PCI
- Add support for PCMCIA memory cards
- Update help texts for:
   Ocelot, ITE QED-4N-S01B, Flaga

Please note that this does not completely synchronise the 2.5 kernel
tree with MTD CVS.
parent 71660e15
......@@ -21,11 +21,18 @@ CONFIG_MTD_PARTITIONS
devices. Partitioning on NFTL 'devices' is a different - that's the
'normal' form of partitioning used on a block device.
CONFIG_MTD_CONCAT
Support for concatenating several MTD devices into a single
(virtual) one. This allows you to have -for example- a JFFS(2)
file system spanning multiple physical flash chips. If unsure,
say 'Y'.
CONFIG_MTD_REDBOOT_PARTS
RedBoot is a ROM monitor and bootloader which deals with multiple
'images' in flash devices by putting a table in the last erase block
of the device, similar to a partition table, which gives the
offsets, lengths and names of all the images stored in the flash.
'images' in flash devices by putting a table in the last erase
block of the device, similar to a partition table, which gives
the offsets, lengths and names of all the images stored in the
flash.
If you need code which can detect and parse this table, and register
MTD 'partitions' corresponding to each image in the table, enable
......@@ -36,21 +43,40 @@ CONFIG_MTD_REDBOOT_PARTS
SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
example.
CONFIG_MTD_BOOTLDR_PARTS
The Compaq bootldr deals with multiple 'images' in flash devices
by putting a table in one of the first erase blocks of the device,
similar to a partition table, which gives the offsets, lengths and
names of all the images stored in the flash.
If you need code which can detect and parse this table, and register
MTD 'partitions' corresponding to each image in the table, enable
this option.
CONFIG_MTD_CMDLINE_PARTS
Allow generic configuration of the MTD paritition tables via the kernel
command line. Multiple flash resources are supported for hardware where
different kinds of flash memory are available.
You will still need the parsing functions to be called by the driver
for your particular device. It won't happen automatically. The
SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
example.
The format for the command line is as follows:
mtdparts=<mtddef>[;<mtddef]
<mtddef> := <mtd-id>:<partdef>[,<partdef>]
<partdef> := <size>[@offset][<name>][ro]
<mtd-id> := unique id used in mapping driver/device
<size> := standard linux memsize OR "-" to denote all
remaining space
<name> := (NAME)
Due to the way Linux handles the command line, no spaces are
allowed in the partition definition, including mtd id's and partition
names.
Examples:
1 flash resource (mtd-id "sa1100"), with 1 single writable partition:
mtdparts=sa1100:-
Same flash, but 2 named partitions, the first one being read-only:
mtdparts=sa1100:256k(ARMboot)ro,-(root)
If unsure, say 'N'.
CONFIG_MTD_AFS_PARTS
The ARM Firmware Suite allows the user to divide flash devices into
multiple 'images'. Each such image has a header containing its name
......
# $Id: Config.in,v 1.71 2001/10/03 11:38:38 dwmw2 Exp $
# $Id: Config.in,v 1.74 2002/04/23 13:52:14 mag Exp $
mainmenu_option next_comment
comment 'Memory Technology Devices (MTD)'
......@@ -12,9 +12,10 @@ if [ "$CONFIG_MTD" = "y" -o "$CONFIG_MTD" = "m" ]; then
int ' Debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_MTD_DEBUG_VERBOSE 0
fi
dep_tristate ' MTD partitioning support' CONFIG_MTD_PARTITIONS $CONFIG_MTD
dep_tristate ' MTD concatenating support' CONFIG_MTD_CONCAT $CONFIG_MTD
dep_tristate ' RedBoot partition table parsing' CONFIG_MTD_REDBOOT_PARTS $CONFIG_MTD_PARTITIONS
dep_tristate ' Command line partition table parsing' CONFIG_MTD_CMDLINE_PARTS $CONFIG_MTD_PARTITIONS
if [ "$CONFIG_ARM" = "y" ]; then
dep_tristate ' Compaq bootldr partition table parsing' CONFIG_MTD_BOOTLDR_PARTS $CONFIG_MTD_PARTITIONS
dep_tristate ' ARM Firmware Suite partition parsing' CONFIG_MTD_AFS_PARTS $CONFIG_MTD_PARTITIONS
fi
......
#
# Makefile for the memory technology device drivers.
#
#
# $Id: Makefile,v 1.63 2001/06/13 09:43:07 dwmw2 Exp $
# Based on:
# $Id: Makefile,v 1.66 2002/04/23 13:52:14 mag Exp $
export-objs := mtdcore.o mtdpart.o redboot.o bootldr.o afs.o
export-objs := mtdcore.o mtdpart.o redboot.o cmdline.o afs.o mtdconcat.o
obj-y += chips/ maps/ devices/ nand/
......@@ -26,9 +26,10 @@ obj-y += chips/ maps/ devices/ nand/
# Core functionality.
obj-$(CONFIG_MTD) += mtdcore.o
obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
obj-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
obj-$(CONFIG_MTD_BOOTLDR_PARTS) += bootldr.o
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdline.o
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
# 'Users' - code which presents functionality to userspace.
......
/*
* Read flash partition table from Compaq Bootloader
*
* Copyright 2001 Compaq Computer Corporation.
*
* $Id: bootldr.c,v 1.6 2001/10/02 15:05:11 dwmw2 Exp $
*
* Use consistent with the GNU GPL is permitted,
* provided that this copyright notice is
* preserved in its entirety in all copies and derived works.
*
* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
*/
/*
* Maintainer: Jamey Hicks (jamey.hicks@compaq.com)
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <asm/setup.h>
#include <linux/bootmem.h>
#define FLASH_PARTITION_NAMELEN 32
enum LFR_FLAGS {
LFR_SIZE_PREFIX = 1, /* prefix data with 4-byte size */
LFR_PATCH_BOOTLDR = 2, /* patch bootloader's 0th instruction */
LFR_KERNEL = 4, /* add BOOTIMG_MAGIC, imgsize and VKERNEL_BASE to head of programmed region (see bootldr.c) */
LFR_EXPAND = 8 /* expand partition size to fit rest of flash */
};
// the tags are parsed too early to malloc or alloc_bootmem so we'll fix it
// for now
#define MAX_NUM_PARTITIONS 8
typedef struct FlashRegion {
char name[FLASH_PARTITION_NAMELEN];
unsigned long base;
unsigned long size;
enum LFR_FLAGS flags;
} FlashRegion;
typedef struct BootldrFlashPartitionTable {
int magic; /* should be filled with 0x646c7470 (btlp) BOOTLDR_PARTITION_MAGIC */
int npartitions;
struct FlashRegion partition[8];
} BootldrFlashPartitionTable;
#define BOOTLDR_MAGIC 0x646c7462 /* btld: marks a valid bootldr image */
#define BOOTLDR_PARTITION_MAGIC 0x646c7470 /* btlp: marks a valid bootldr partition table in params sector */
#define BOOTLDR_MAGIC_OFFSET 0x20 /* offset 0x20 into the bootldr */
#define BOOTCAP_OFFSET 0X30 /* offset 0x30 into the bootldr */
#define BOOTCAP_WAKEUP (1<<0)
#define BOOTCAP_PARTITIONS (1<<1) /* partition table stored in params sector */
#define BOOTCAP_PARAMS_AFTER_BOOTLDR (1<<2) /* params sector right after bootldr sector(s), else in last sector */
static struct BootldrFlashPartitionTable Table;
static struct BootldrFlashPartitionTable *partition_table = NULL;
int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts)
{
struct mtd_partition *parts;
int ret, retlen, i;
int npartitions = 0;
long partition_table_offset;
long bootmagic = 0;
long bootcap = 0;
int namelen = 0;
char *names;
#if 0
/* verify bootldr magic */
ret = master->read(master, BOOTLDR_MAGIC_OFFSET, sizeof(long), &retlen, (void *)&bootmagic);
if (ret)
goto out;
if (bootmagic != BOOTLDR_MAGIC)
goto out;
/* see if bootldr supports partition tables and where to find the partition table */
ret = master->read(master, BOOTCAP_OFFSET, sizeof(long), &retlen, (void *)&bootcap);
if (ret)
goto out;
if (!(bootcap & BOOTCAP_PARTITIONS))
goto out;
if (bootcap & BOOTCAP_PARAMS_AFTER_BOOTLDR)
partition_table_offset = master->erasesize;
else
partition_table_offset = master->size - master->erasesize;
printk(__FUNCTION__ ": partition_table_offset=%#lx\n", partition_table_offset);
printk(__FUNCTION__ ": ptable_addr=%#lx\n", ptable_addr);
/* Read the partition table */
partition_table = (struct BootldrFlashPartitionTable *)kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!partition_table)
return -ENOMEM;
ret = master->read(master, partition_table_offset,
PAGE_SIZE, &retlen, (void *)partition_table);
if (ret)
goto out;
#endif
if (!partition_table)
return -ENOMEM;
printk(__FUNCTION__ ": magic=%#x\n", partition_table->magic);
printk(__FUNCTION__ ": numPartitions=%#x\n", partition_table->npartitions);
/* check for partition table magic number */
if (partition_table->magic != BOOTLDR_PARTITION_MAGIC)
goto out;
npartitions = (partition_table->npartitions > MAX_NUM_PARTITIONS)?
MAX_NUM_PARTITIONS:partition_table->npartitions;
printk(__FUNCTION__ ": npartitions=%#x\n", npartitions);
for (i = 0; i < npartitions; i++) {
namelen += strlen(partition_table->partition[i].name) + 1;
}
parts = kmalloc(sizeof(*parts)*npartitions + namelen, GFP_KERNEL);
if (!parts) {
ret = -ENOMEM;
goto out;
}
names = (char *)&parts[npartitions];
memset(parts, 0, sizeof(*parts)*npartitions + namelen);
// from here we use the partition table
for (i = 0; i < npartitions; i++) {
struct FlashRegion *partition = &partition_table->partition[i];
const char *name = partition->name;
parts[i].name = names;
names += strlen(name) + 1;
strcpy(parts[i].name, name);
if (partition->flags & LFR_EXPAND)
parts[i].size = MTDPART_SIZ_FULL;
else
parts[i].size = partition->size;
parts[i].offset = partition->base;
parts[i].mask_flags = 0;
printk(" partition %s o=%x s=%x\n",
parts[i].name, parts[i].offset, parts[i].size);
}
ret = npartitions;
*pparts = parts;
out:
#if 0
if (partition_table)
kfree(partition_table);
#endif
return ret;
}
static int __init parse_tag_ptable(const struct tag *tag)
{
char buf[128];
int i;
int j;
partition_table = &Table;
#ifdef CONFIG_DEBUG_LL
sprintf(buf,"ptable: magic = = 0x%lx npartitions= %d \n",
tag->u.ptable.magic,tag->u.ptable.npartitions);
printascii(buf);
for (i=0; i<tag->u.ptable.npartitions; i++){
sprintf(buf,"ptable: partition name = %s base= 0x%lx size= 0x%lx flags= 0x%lx\n",
(char *) (&tag->u.ptable.partition[i].name[0]),
tag->u.ptable.partition[i].base,
tag->u.ptable.partition[i].size,
tag->u.ptable.partition[i].flags);
printascii(buf);
}
#endif
memcpy((void *)partition_table,(void *) (&(tag->u.ptable)),sizeof(partition_table) +
sizeof(struct FlashRegion)*tag->u.ptable.npartitions);
return 0;
}
__tagtable(ATAG_PTABLE, parse_tag_ptable);
EXPORT_SYMBOL(parse_bootldr_partitions);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Compaq Computer Corporation");
MODULE_DESCRIPTION("Parsing code for Compaq bootldr partitions");
/*
* $Id: cmdline.c,v 1.4 2002/09/13 01:18:38 jamey Exp $
*
* Read flash partition table from command line
*
* Copyright 2002 SYSGO Real-Time Solutions GmbH
*
* The format for the command line is as follows:
*
* mtdparts=<mtddef>[;<mtddef]
* <mtddef> := <mtd-id>:<partdef>[,<partdef>]
* <partdef> := <size>[@offset][<name>][ro]
* <mtd-id> := unique id used in mapping driver/device
* <size> := standard linux memsize OR "-" to denote all remaining space
* <name> := '(' NAME ')'
*
* Examples:
*
* 1 NOR Flash, with 1 single writable partition:
* edb7312-nor:-
*
* 1 NOR Flash with 2 partitions, 1 NAND with one
* edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <asm/setup.h>
#include <linux/bootmem.h>
/* error message prefix */
#define ERRP "mtd: "
/* debug macro */
#if 0
#define dbg(x) do { printk("DEBUG-CMDLINE-PART: "); printk x; } while(0)
#else
#define dbg(x)
#endif
/* special size referring to all the remaining space in a partition */
#define SIZE_REMAINING 0xffffffff
struct cmdline_mtd_partition {
struct cmdline_mtd_partition *next;
char *mtd_id;
int num_parts;
struct mtd_partition *parts;
};
/* mtdpart_setup() parses into here */
static struct cmdline_mtd_partition *partitions;
/* the command line passed to mtdpart_setupd() */
static char *cmdline;
static int cmdline_parsed = 0;
/*
* Parse one partition definition for an MTD. Since there can be many
* comma separated partition definitions, this function calls itself
* recursively until no more partition definitions are found. Nice side
* effect: the memory to keep the mtd_partition structs and the names
* is allocated upon the last definition being found. At that point the
* syntax has been verified ok.
*/
static struct mtd_partition * newpart(char *s,
char **retptr,
int *num_parts,
int this_part,
unsigned char **extra_mem_ptr,
int extra_mem_size)
{
struct mtd_partition *parts;
unsigned long size;
unsigned long offset = 0;
char *name;
int name_len;
unsigned char *extra_mem;
char delim;
unsigned int mask_flags;
/* fetch the partition size */
if (*s == '-')
{ /* assign all remaining space to this partition */
size = SIZE_REMAINING;
s++;
}
else
{
size = memparse(s, &s);
if (size < PAGE_SIZE)
{
printk(KERN_ERR ERRP "partition size too small (%lx)\n", size);
return 0;
}
}
/* fetch partition name and flags */
mask_flags = 0; /* this is going to be a regular partition */
delim = 0;
/* check for offset */
if (*s == '@')
{
s++;
offset = memparse(s, &s);
}
/* now look for name */
if (*s == '(')
{
delim = ')';
}
if (delim)
{
char *p;
name = ++s;
if ((p = strchr(name, delim)) == 0)
{
printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
return 0;
}
name_len = p - name;
s = p + 1;
}
else
{
name = NULL;
name_len = 13; /* Partition_000 */
}
/* record name length for memory allocation later */
extra_mem_size += name_len + 1;
/* test for options */
if (strncmp(s, "ro", 2) == 0)
{
mask_flags |= MTD_WRITEABLE;
s += 2;
}
/* test if more partitions are following */
if (*s == ',')
{
if (size == SIZE_REMAINING)
{
printk(KERN_ERR ERRP "no partitions allowed after a fill-up partition\n");
return 0;
}
/* more partitions follow, parse them */
if ((parts = newpart(s + 1, &s, num_parts,
this_part + 1, &extra_mem, extra_mem_size)) == 0)
return 0;
}
else
{ /* this is the last partition: allocate space for all */
int alloc_size;
*num_parts = this_part + 1;
alloc_size = *num_parts * sizeof(struct mtd_partition) +
extra_mem_size;
parts = kmalloc(alloc_size, GFP_KERNEL);
if (!parts)
{
printk(KERN_ERR ERRP "out of memory\n");
return 0;
}
memset(parts, 0, alloc_size);
extra_mem = (unsigned char *)(parts + *num_parts);
}
/* enter this partition (offset will be calculated later if it is zero at this point) */
parts[this_part].size = size;
parts[this_part].offset = offset;
parts[this_part].mask_flags = mask_flags;
if (name)
{
strncpy(extra_mem, name, name_len);
extra_mem[name_len] = 0;
}
else
{
sprintf(extra_mem, "Partition_%03d", this_part);
}
parts[this_part].name = extra_mem;
extra_mem += name_len + 1;
dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %x\n",
this_part,
parts[this_part].name,
parts[this_part].offset,
parts[this_part].size,
parts[this_part].mask_flags));
/* return (updated) pointer to extra_mem memory */
if (extra_mem_ptr)
*extra_mem_ptr = extra_mem;
/* return (updated) pointer command line string */
*retptr = s;
/* return partition table */
return parts;
}
/*
* Parse the command line.
*/
static int mtdpart_setup_real(char *s)
{
cmdline_parsed = 1;
for( ; s != NULL; )
{
struct cmdline_mtd_partition *this_mtd;
struct mtd_partition *parts;
int mtd_id_len;
int num_parts;
char *p, *mtd_id;
mtd_id = s;
/* fetch <mtd-id> */
if (!(p = strchr(s, ':')))
{
printk(KERN_ERR ERRP "no mtd-id\n");
return 0;
}
mtd_id_len = p - mtd_id;
dbg(("parsing <%s>\n", p+1));
/*
* parse one mtd. have it reserve memory for the
* struct cmdline_mtd_partition and the mtd-id string.
*/
parts = newpart(p + 1, /* cmdline */
&s, /* out: updated cmdline ptr */
&num_parts, /* out: number of parts */
0, /* first partition */
(unsigned char**)&this_mtd, /* out: extra mem */
mtd_id_len + 1 + sizeof(*this_mtd));
/* enter results */
this_mtd->parts = parts;
this_mtd->num_parts = num_parts;
this_mtd->mtd_id = (char*)(this_mtd + 1);
strncpy(this_mtd->mtd_id, mtd_id, mtd_id_len);
this_mtd->mtd_id[mtd_id_len] = 0;
/* link into chain */
this_mtd->next = partitions;
partitions = this_mtd;
dbg(("mtdid=<%s> num_parts=<%d>\n",
this_mtd->mtd_id, this_mtd->num_parts));
/* EOS - we're done */
if (*s == 0)
break;
/* does another spec follow? */
if (*s != ';')
{
printk(KERN_ERR ERRP "bad character after partition (%c)\n", *s);
return 0;
}
s++;
}
return 1;
}
/*
* Main function to be called from the MTD mapping driver/device to
* obtain the partitioning information. At this point the command line
* arguments will actually be parsed and turned to struct mtd_partition
* information.
*/
int parse_cmdline_partitions(struct mtd_info *master,
struct mtd_partition **pparts,
const char *mtd_id)
{
unsigned long offset;
int i;
struct cmdline_mtd_partition *part;
if (!cmdline)
return -EINVAL;
/* parse command line */
if (!cmdline_parsed)
mtdpart_setup_real(cmdline);
for(part = partitions; part; part = part->next)
{
if (!strcmp(part->mtd_id, mtd_id))
{
for(i = 0, offset = 0; i < part->num_parts; i++)
{
if (!part->parts[i].offset)
part->parts[i].offset = offset;
else
offset = part->parts[i].offset;
if (part->parts[i].size == SIZE_REMAINING)
part->parts[i].size = master->size - offset;
if (offset + part->parts[i].size > master->size)
{
printk(KERN_WARNING ERRP
"%s: partitioning exceeds flash size, truncating\n",
mtd_id);
part->parts[i].size = master->size - offset;
part->num_parts = i;
}
offset += part->parts[i].size;
}
*pparts = part->parts;
return part->num_parts;
}
}
return -EINVAL;
}
/*
* This is the handler for our kernel parameter, called from
* main.c::checksetup(). Note that we can not yet kmalloc() anything,
* so we only save the commandline for later processing.
*/
static int __init mtdpart_setup(char *s)
{
cmdline = s;
return 1;
}
__setup("mtdparts=", mtdpart_setup);
EXPORT_SYMBOL(parse_cmdline_partitions);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
MODULE_DESCRIPTION("Command line configuration of MTD partitions");
CONFIG_MTD_CDB89712
This enables access to the flash or ROM chips on the CDB89712 board.
If you have such a board, say 'Y'.
CONFIG_MTD_CEIVA
This enables access to the flash chips on the Ceiva/Polaroid
PhotoMax Digital Picture Frame.
If you have such a device, say 'Y'.
CONFIG_MTD_FORTUNET
This enables access to the Flash on the FortuNet board. If you
have such a board, say 'Y'.
CONFIG_MTD_AUTCPU12
This enables access to the NV-RAM on autronix autcpu12 board.
If you have such a board, say 'Y'.
CONFIG_MTD_EDB7312
This enables access to the CFI Flash on the Cogent EDB7312 board.
If you have such a board, say 'Y' here.
CONFIG_MTD_NAND_EDB7312
This enables access to the NAND Flash on the Cogent EDB7312 board.
If you have such a board, say 'Y' here.
CONFIG_MTD_IMPA7
This enables access to the NOR Flash on the impA7 board of
implementa GmbH. If you have such a board, say 'Y' here.
CONFIG_MTD_SA1100
This enables access to the flash chips on most platforms based on
the SA1100 and SA1110, including the Assabet and the Compaq iPAQ.
......@@ -39,6 +68,12 @@ CONFIG_MTD_SUN_UFLASH
CONFIG_MTD_NORA
If you had to ask, you don't have one. Say 'N'.
CONFIG_MTD_L440GX
Support for treating the BIOS flash chip on Intel L440GX motherboards
as an MTD device - with this you can reprogram your BIOS.
BE VERY CAREFUL.
CONFIG_MTD_PNC2000
PNC-2000 is the name of Network Camera product from PHOTRON
Ltd. in Japan. It uses CFI-compliant flash.
......@@ -50,6 +85,13 @@ CONFIG_MTD_RPXLITE
to communicate with the chips on the RPXLite board. More at
<http://www.embeddedplanet.com/rpx_lite_specification_sheet.htm>.
CONFIG_MTD_TQM8XXL
The TQM8xxL PowerPC board has up to two banks of CFI-compliant
chips, currently uses AMD one. This 'mapping' driver supports
that arrangement, allowing the CFI probe and command set driver
code to communicate with the chips on the TQM8xxL board. More at
<http://www.denx.de/embedded-ppc-en.html>.
CONFIG_MTD_SC520CDP
The SC520 CDP board has two banks of CFI-compliant chips and one
Dual-in-line JEDEC chip. This 'mapping' driver supports that
......@@ -78,6 +120,11 @@ CONFIG_MTD_NETSC520
demonstration board. If you have one of these boards and would like
to use the flash chips on it, say 'Y'.
CONFIG_MTD_OCELOT
This enables access routines for the boot flash device and for the
NVRAM on the Momenco Ocelot board. If you have one of these boards
and would like access to either of these, say 'Y'.
CONFIG_MTD_ELAN_104NC
This provides a driver for the on-board flash of the Arcom Control
System's ELAN-104NC development board. By default the flash
......@@ -91,17 +138,17 @@ CONFIG_MTD_DC21285
<http://developer.intel.com/design/bridge/quicklist/dsc-21285.htm>.
CONFIG_MTD_CSTM_MIPS_IXX
This provides a mapping driver for the Integrated Tecnology Express,
Inc (ITE) QED-4N-S01B eval board and the Globespan IVR Reference
Board. It provides the necessary addressing, length, buswidth, vpp
code and addition setup of the flash device for these boards. In
addition, this mapping driver can be used for other boards via
setting of the CONFIG_MTD_CSTM_MIPS_IXX_START/LEN/BUSWIDTH
parameters. This mapping will provide one mtd device using one
partition. The start address can be offset from the beginning of
flash and the len can be less than the total flash device size to
allow a window into the flash. Both CFI and JEDEC probes are
called.
This provides a mapping driver for the Integrated Tecnology
Express, Inc (ITE) QED-4N-S01B eval board and the Globespan IVR
Reference Board. It provides the necessary addressing, length,
buswidth, vpp code and addition setup of the flash device for
these boards. In addition, this mapping driver can be used for
other boards via setting of the CONFIG_MTD_CSTM_MIPS_IXX_START/
LEN/BUSWIDTH parameters. This mapping will provide one mtd device
using one partition. The start address can be offset from the
beginning of flash and the len can be less than the total flash
device size to allow a window into the flash. Both CFI and JEDEC
probes are called.
CONFIG_MTD_CSTM_MIPS_IXX_START
This is the physical memory location that the MTD driver will
......@@ -141,6 +188,11 @@ CONFIG_MTD_OCTAGON
Computer. More information on the board is available at
<http://www.octagonsystems.com/Products/5066/5066.html>.
CONFIG_MTD_PCMCIA
Map driver for accessing PCMCIA linear flash memory cards. These
cards are usually around 4-16MiB in size. This does not include
Compact Flash cards which are treated as IDE devices.
CONFIG_MTD_VMAX
This provides a 'mapping' driver which supports the way in which
the flash chips are connected in the Tempustech VMAX SBC301 Single
......@@ -151,29 +203,18 @@ CONFIG_MTD_CFI_FLAGADM
Mapping for the Flaga digital module. If you don´t have one, ignore
this setting.
CONFIG_MTD_OCELOT
This enables access routines for the boot flash device and for the
NVRAM on the Momenco Ocelot board. If you have one of these boards
and would like access to either of these, say 'Y'.
CONFIG_MTD_CDB89712
This enables access to the flash or ROM chips on the CDB89712 board.
If you have such a board, say 'Y'.
CONFIG_MTD_L440GX
Support for treating the BIOS flash chip on Intel L440GX motherboards
as an MTD device - with this you can reprogram your BIOS.
BE VERY CAREFUL.
CONFIG_MTD_SOLUTIONENGINE
This enables access to the flash chips on the Hitachi SolutionEngine and
similar boards. Say 'Y' if you are building a kernel for such a board.
CONFIG_MTD_TQM8XXL
The TQM8xxL PowerPC board has up to two banks of CFI-compliant
chips, currently uses AMD one. This 'mapping' driver supports
that arrangement, allowing the CFI probe and command set driver
code to communicate with the chips on the TQM8xxL board. More at
<http://www.denx.de/embedded-ppc-en.html>.
CONFIG_MTD_EPXA10DB
This enables support for the flash devices on the Altera
Excalibur XA10 Development Board. If you are building a kernel
for on of these boards then you should say 'Y' otherwise say 'N'.
CONFIG_MTD_PCI
Mapping for accessing flash devices on add-in cards like the Intel XScale
IQ80310 card, and the Intel EBSA285 card in blank ROM programming mode
(please see the manual for the link settings).
If you are not sure, say N.
......@@ -56,8 +56,18 @@ if [ "$CONFIG_ARM" = "y" ]; then
dep_tristate ' CFI Flash device mapped on ARM Integrator/P720T' CONFIG_MTD_ARM_INTEGRATOR $CONFIG_MTD_CFI
dep_tristate ' Cirrus CDB89712 evaluation board mappings' CONFIG_MTD_CDB89712 $CONFIG_MTD_CFI $CONFIG_ARCH_CDB89712
dep_tristate ' CFI Flash device mapped on StrongARM SA11x0' CONFIG_MTD_SA1100 $CONFIG_MTD_CFI $CONFIG_ARCH_SA1100 $CONFIG_MTD_PARTITIONS
dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE $CONFIG_MTD_PARTITIONS
dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE
dep_tristate ' CFI Flash device mapped on the XScale IQ80310 board' CONFIG_MTD_IQ80310 $CONFIG_MTD_CFI $CONFIG_ARCH_IQ80310
dep_tristate ' CFI Flash device mapped on Epxa10db' CONFIG_MTD_EPXA10DB $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT
dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_SA1100_FORTUNET
dep_tristate ' NV-RAM mapping AUTCPU12 board' CONFIG_MTD_AUTCPU12 $CONFIG_ARCH_AUTCPU12
dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_MTD_CFI
dep_tristate ' JEDEC Flash device mapped on impA7' CONFIG_MTD_IMPA7 $CONFIG_MTD_JEDECPROBE
dep_tristate ' JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame' CONFIG_MTD_CEIVA $CONFIG_MTD_JEDECPROBE $CONFIG_ARCH_CEIVA
fi
# This needs CFI or JEDEC, depending on the cards found.
dep_tristate ' PCI MTD driver' CONFIG_MTD_PCI $CONFIG_MTD $CONFIG_PCI
dep_tristate ' PCMCIA MTD driver' CONFIG_MTD_PCMCIA $CONFIG_MTD $CONFIG_PCMCIA
endmenu
......@@ -10,12 +10,15 @@ obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o
obj-$(CONFIG_MTD_DC21285) += dc21285.o
obj-$(CONFIG_MTD_ELAN_104NC) += elan-104nc.o
obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o
obj-$(CONFIG_MTD_IQ80310) += iq80310.o
obj-$(CONFIG_MTD_L440GX) += l440gx.o
obj-$(CONFIG_MTD_NORA) += nora.o
obj-$(CONFIG_MTD_CEIVA) += ceiva.o
obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
......@@ -28,5 +31,10 @@ obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o
obj-$(CONFIG_MTD_DBOX2) += dbox2-flash.o
obj-$(CONFIG_MTD_OCELOT) += ocelot.o
obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
obj-$(CONFIG_MTD_PCI) += pci.o
obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
obj-$(CONFIG_MTD_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_IMPA7) += impa7.o
obj-$(CONFIG_MTD_FORTUNET) += fortunet.o
include $(TOPDIR)/Rules.make
/*
* NV-RAM memory access on autcpu12
* (C) 2002 Thomas Gleixner (gleixner@autronix.de)
*
* $Id: autcpu12-nvram.c,v 1.1 2002/02/22 09:30:24 gleixner Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/sizes.h>
#include <asm/hardware.h>
#include <asm/arch/autcpu12.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
__u8 autcpu12_read8(struct map_info *map, unsigned long ofs)
{
return __raw_readb(map->map_priv_1 + ofs);
}
__u16 autcpu12_read16(struct map_info *map, unsigned long ofs)
{
return __raw_readw(map->map_priv_1 + ofs);
}
__u32 autcpu12_read32(struct map_info *map, unsigned long ofs)
{
return __raw_readl(map->map_priv_1 + ofs);
}
void autcpu12_write8(struct map_info *map, __u8 d, unsigned long adr)
{
__raw_writeb(d, map->map_priv_1 + adr);
mb();
}
void autcpu12_write16(struct map_info *map, __u16 d, unsigned long adr)
{
__raw_writew(d, map->map_priv_1 + adr);
mb();
}
void autcpu12_write32(struct map_info *map, __u32 d, unsigned long adr)
{
__raw_writel(d, map->map_priv_1 + adr);
mb();
}
void autcpu12_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
memcpy_fromio(to, map->map_priv_1 + from, len);
}
void autcpu12_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
while(len) {
__raw_writeb(*(unsigned char *) from, map->map_priv_1 + to);
from++;
to++;
len--;
}
}
static struct mtd_info *sram_mtd;
struct map_info autcpu12_sram_map = {
name: "SRAM",
size: 32768,
buswidth: 8,
read8: autcpu12_read8,
read16: autcpu12_read16,
read32: autcpu12_read32,
copy_from: autcpu12_copy_from,
write8: autcpu12_write8,
write16: autcpu12_write16,
write32: autcpu12_write32,
copy_to: autcpu12_copy_to
};
static int __init init_autcpu12_sram (void)
{
int err, save0, save1;
autcpu12_sram_map.map_priv_1 = (unsigned long)ioremap(0x12000000, SZ_128K);
if (!autcpu12_sram_map.map_priv_1) {
printk("Failed to ioremap autcpu12 NV-RAM space\n");
err = -EIO;
goto out;
}
/*
* Check for 32K/128K
* read ofs 0
* read ofs 0x10000
* Write complement to ofs 0x100000
* Read and check result on ofs 0x0
* Restore contents
*/
save0 = autcpu12_read32(&autcpu12_sram_map,0);
save1 = autcpu12_read32(&autcpu12_sram_map,0x10000);
autcpu12_write32(&autcpu12_sram_map,~save0,0x10000);
/* if we find this pattern on 0x0, we have 32K size
* restore contents and exit
*/
if ( autcpu12_read32(&autcpu12_sram_map,0) != save0) {
autcpu12_write32(&autcpu12_sram_map,save0,0x0);
goto map;
}
/* We have a 128K found, restore 0x10000 and set size
* to 128K
*/
autcpu12_write32(&autcpu12_sram_map,save1,0x10000);
autcpu12_sram_map.size = SZ_128K;
map:
sram_mtd = do_map_probe("map_ram", &autcpu12_sram_map);
if (!sram_mtd) {
printk("NV-RAM probe failed\n");
err = -ENXIO;
goto out_ioremap;
}
sram_mtd->module = THIS_MODULE;
sram_mtd->erasesize = 16;
if (add_mtd_device(sram_mtd)) {
printk("NV-RAM device addition failed\n");
err = -ENOMEM;
goto out_probe;
}
printk("NV-RAM device size %ldK registered on AUTCPU12\n",autcpu12_sram_map.size/SZ_1K);
return 0;
out_probe:
map_destroy(sram_mtd);
sram_mtd = 0;
out_ioremap:
iounmap((void *)autcpu12_sram_map.map_priv_1);
out:
return err;
}
static void __exit cleanup_autcpu12_maps(void)
{
if (sram_mtd) {
del_mtd_device(sram_mtd);
map_destroy(sram_mtd);
iounmap((void *)autcpu12_sram_map.map_priv_1);
}
}
module_init(init_autcpu12_sram);
module_exit(cleanup_autcpu12_maps);
MODULE_AUTHOR("Thomas Gleixner");
MODULE_DESCRIPTION("autcpu12 NV-RAM map driver");
MODULE_LICENSE("GPL");
/*
* Ceiva flash memory driver.
* Copyright (C) 2002 Rob Scott <rscott@mtrob.fdns.net>
*
* Note: this driver supports jedec compatible devices. Modification
* for CFI compatible devices should be straight forward: change
* jedec_probe to cfi_probe.
*
* Based on: sa1100-flash.c, which has the following copyright:
* Flash memory access on SA11x0 based devices
*
* (C) 2000 Nicolas Pitre <nico@cam.org>
*
* $Id: ceiva.c,v 1.2 2002/10/14 12:50:22 rmk Exp $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/concat.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/io.h>
#include <asm/sizes.h>
/*
* This isnt complete yet, so...
*/
#define CONFIG_MTD_CEIVA_STATICMAP
static __u8 clps_read8(struct map_info *map, unsigned long ofs)
{
return readb(map->map_priv_1 + ofs);
}
static __u16 clps_read16(struct map_info *map, unsigned long ofs)
{
return readw(map->map_priv_1 + ofs);
}
static __u32 clps_read32(struct map_info *map, unsigned long ofs)
{
return readl(map->map_priv_1 + ofs);
}
static void clps_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
memcpy(to, (void *)(map->map_priv_1 + from), len);
}
static void clps_write8(struct map_info *map, __u8 d, unsigned long adr)
{
writeb(d, map->map_priv_1 + adr);
}
static void clps_write16(struct map_info *map, __u16 d, unsigned long adr)
{
writew(d, map->map_priv_1 + adr);
}
static void clps_write32(struct map_info *map, __u32 d, unsigned long adr)
{
writel(d, map->map_priv_1 + adr);
}
static void clps_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
memcpy((void *)(map->map_priv_1 + to), from, len);
}
static struct map_info clps_map __initdata = {
name: "clps flash",
read8: clps_read8,
read16: clps_read16,
read32: clps_read32,
copy_from: clps_copy_from,
write8: clps_write8,
write16: clps_write16,
write32: clps_write32,
copy_to: clps_copy_to,
};
#ifdef CONFIG_MTD_CEIVA_STATICMAP
/*
* See include/linux/mtd/partitions.h for definition of the mtd_partition
* structure.
*
* Please note:
* 1. The flash size given should be the largest flash size that can
* be accomodated.
*
* 2. The bus width must defined in clps_setup_flash.
*
* The MTD layer will detect flash chip aliasing and reduce the size of
* the map accordingly.
*
*/
#ifdef CONFIG_ARCH_CEIVA
/* Flash / Partition sizing */
/* For the 28F8003, we use the block mapping to calcuate the sizes */
#define MAX_SIZE_KiB (16 + 8 + 8 + 96 + (7*128))
#define BOOT_PARTITION_SIZE_KiB (16)
#define PARAMS_PARTITION_SIZE_KiB (8)
#define KERNEL_PARTITION_SIZE_KiB (4*128)
/* Use both remaing portion of first flash, and all of second flash */
#define ROOT_PARTITION_SIZE_KiB (3*128) + (8*128)
static struct mtd_partition ceiva_partitions[] = {
{
name: "Ceiva BOOT partition",
size: BOOT_PARTITION_SIZE_KiB*1024,
offset: 0,
},{
name: "Ceiva parameters partition",
size: PARAMS_PARTITION_SIZE_KiB*1024,
offset: (16 + 8) * 1024,
},{
name: "Ceiva kernel partition",
size: (KERNEL_PARTITION_SIZE_KiB)*1024,
offset: 0x20000,
},{
name: "Ceiva root filesystem partition",
offset: MTDPART_OFS_APPEND,
size: (ROOT_PARTITION_SIZE_KiB)*1024,
}
};
#endif
static int __init clps_static_partitions(struct mtd_partition **parts)
{
int nb_parts = 0;
#ifdef CONFIG_ARCH_CEIVA
if (machine_is_ceiva()) {
*parts = ceiva_partitions;
nb_parts = ARRAY_SIZE(ceiva_partitions);
}
#endif
return nb_parts;
}
#endif
struct clps_info {
unsigned long base;
unsigned long size;
int width;
void *vbase;
struct map_info *map;
struct mtd_info *mtd;
struct resource *res;
};
#define NR_SUBMTD 4
static struct clps_info info[NR_SUBMTD];
static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info **rmtd)
{
struct mtd_info *subdev[nr];
struct map_info *maps;
int i, found = 0, ret = 0;
/*
* Allocate the map_info structs in one go.
*/
maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
if (!maps)
return -ENOMEM;
/*
* Claim and then map the memory regions.
*/
for (i = 0; i < nr; i++) {
if (clps[i].base == (unsigned long)-1)
break;
clps[i].res = request_mem_region(clps[i].base, clps[i].size, "clps flash");
if (!clps[i].res) {
ret = -EBUSY;
break;
}
clps[i].map = maps + i;
memcpy(clps[i].map, &clps_map, sizeof(struct map_info));
clps[i].vbase = ioremap(clps[i].base, clps[i].size);
if (!clps[i].vbase) {
ret = -ENOMEM;
break;
}
clps[i].map->map_priv_1 = (unsigned long)clps[i].vbase;
clps[i].map->buswidth = clps[i].width;
clps[i].map->size = clps[i].size;
clps[i].mtd = do_map_probe("jedec_probe", clps[i].map);
if (clps[i].mtd == NULL) {
ret = -ENXIO;
break;
}
clps[i].mtd->module = THIS_MODULE;
subdev[i] = clps[i].mtd;
printk(KERN_INFO "clps flash: JEDEC device at 0x%08lx, %dMiB, "
"%d-bit\n", clps[i].base, clps[i].mtd->size >> 20,
clps[i].width * 8);
found += 1;
}
/*
* ENXIO is special. It means we didn't find a chip when
* we probed. We need to tear down the mapping, free the
* resource and mark it as such.
*/
if (ret == -ENXIO) {
iounmap(clps[i].vbase);
clps[i].vbase = NULL;
release_resource(clps[i].res);
clps[i].res = NULL;
}
/*
* If we found one device, don't bother with concat support.
* If we found multiple devices, use concat if we have it
* available, otherwise fail.
*/
if (ret == 0 || ret == -ENXIO) {
if (found == 1) {
*rmtd = subdev[0];
ret = 0;
} else if (found > 1) {
/*
* We detected multiple devices. Concatenate
* them together.
*/
#ifdef CONFIG_MTD_CONCAT
*rmtd = mtd_concat_create(subdev, found,
"clps flash");
if (*rmtd == NULL)
ret = -ENXIO;
#else
printk(KERN_ERR "clps flash: multiple devices "
"found but MTD concat support disabled.\n");
ret = -ENXIO;
#endif
}
}
/*
* If we failed, clean up.
*/
if (ret) {
do {
if (clps[i].mtd)
map_destroy(clps[i].mtd);
if (clps[i].vbase)
iounmap(clps[i].vbase);
if (clps[i].res)
release_resource(clps[i].res);
} while (i--);
kfree(maps);
}
return ret;
}
static void __exit clps_destroy_mtd(struct clps_info *clps, struct mtd_info *mtd)
{
int i;
del_mtd_partitions(mtd);
if (mtd != clps[0].mtd)
mtd_concat_destroy(mtd);
for (i = NR_SUBMTD; i >= 0; i--) {
if (clps[i].mtd)
map_destroy(clps[i].mtd);
if (clps[i].vbase)
iounmap(clps[i].vbase);
if (clps[i].res)
release_resource(clps[i].res);
}
kfree(clps[0].map);
}
/*
* We define the memory space, size, and width for the flash memory
* space here.
*/
static int __init clps_setup_flash(void)
{
int nr;
#ifdef CONFIG_ARCH_CEIVA
if (machine_is_ceiva()) {
info[0].base = CS0_PHYS_BASE;
info[0].size = SZ_32M;
info[0].width = CEIVA_FLASH_WIDTH;
info[1].base = CS1_PHYS_BASE;
info[1].size = SZ_32M;
info[1].width = CEIVA_FLASH_WIDTH;
nr = 2;
}
#endif
return nr;
}
extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *);
static struct mtd_partition *parsed_parts;
static void __init clps_locate_partitions(struct mtd_info *mtd)
{
const char *part_type = NULL;
int nr_parts = 0;
do {
/*
* Partition selection stuff.
*/
#ifdef CONFIG_MTD_CMDLINE_PARTS
nr_parts = parse_cmdline_partitions(mtd, &parsed_parts, "clps");
if (nr_parts > 0) {
part_type = "command line";
break;
}
#endif
#ifdef CONFIG_MTD_REDBOOT_PARTS
nr_parts = parse_redboot_partitions(mtd, &parsed_parts);
if (nr_parts > 0) {
part_type = "RedBoot";
break;
}
#endif
#ifdef CONFIG_MTD_CEIVA_STATICMAP
nr_parts = clps_static_partitions(&parsed_parts);
if (nr_parts > 0) {
part_type = "static";
break;
}
printk("found: %d partitions\n", nr_parts);
#endif
} while (0);
if (nr_parts == 0) {
printk(KERN_NOTICE "clps flash: no partition info "
"available, registering whole flash\n");
add_mtd_device(mtd);
} else {
printk(KERN_NOTICE "clps flash: using %s partition "
"definition\n", part_type);
add_mtd_partitions(mtd, parsed_parts, nr_parts);
}
/* Always succeeds. */
}
static void __exit clps_destroy_partitions(void)
{
if (parsed_parts)
kfree(parsed_parts);
}
static struct mtd_info *mymtd;
static int __init clps_mtd_init(void)
{
int ret;
int nr;
nr = clps_setup_flash();
if (nr < 0)
return nr;
ret = clps_setup_mtd(info, nr, &mymtd);
if (ret)
return ret;
clps_locate_partitions(mymtd);
return 0;
}
static void __exit clps_mtd_cleanup(void)
{
clps_destroy_mtd(info, mymtd);
clps_destroy_partitions();
}
module_init(clps_mtd_init);
module_exit(clps_mtd_cleanup);
MODULE_AUTHOR("Rob Scott");
MODULE_DESCRIPTION("Cirrus Logic JEDEC map driver");
MODULE_LICENSE("GPL");
......@@ -5,9 +5,9 @@
*
* This code is GPL
*
* $Id: dc21285.c,v 1.6 2001/10/02 15:05:14 dwmw2 Exp $
* $Id: dc21285.c,v 1.9 2002/10/14 12:22:10 rmk Exp $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
......@@ -44,15 +44,15 @@ void dc21285_copy_from(struct map_info *map, void *to, unsigned long from, ssize
void dc21285_write8(struct map_info *map, __u8 d, unsigned long adr)
{
*CSR_ROMWRITEREG = adr;
*CSR_ROMWRITEREG = adr & 3;
adr &= ~3;
*(__u8*)(map->map_priv_1 + adr) = d;
}
void dc21285_write16(struct map_info *map, __u16 d, unsigned long adr)
{
*CSR_ROMWRITEREG = adr;
adr &= ~1;
*CSR_ROMWRITEREG = adr & 3;
adr &= ~3;
*(__u16*)(map->map_priv_1 + adr) = d;
}
......@@ -131,7 +131,7 @@ int __init init_dc21285(void)
dc21285_map.buswidth*8);
/* Let's map the flash area */
dc21285_map.map_priv_1 = (unsigned long)__ioremap(DC21285_FLASH, 16*1024*1024, 0);
dc21285_map.map_priv_1 = (unsigned long)ioremap(DC21285_FLASH, 16*1024*1024);
if (!dc21285_map.map_priv_1) {
printk("Failed to ioremap\n");
return -EIO;
......@@ -139,21 +139,22 @@ int __init init_dc21285(void)
mymtd = do_map_probe("cfi_probe", &dc21285_map);
if (mymtd) {
int nrparts;
int nrparts = 0;
mymtd->module = THIS_MODULE;
/* partition fixup */
#ifdef CONFIG_MTD_REDBOOT_PARTS
nrparts = parse_redboot_partitions(mymtd, &dc21285_parts);
if (nrparts <=0) {
#endif
if (nrparts > 0) {
add_mtd_partitions(mymtd, dc21285_parts, nrparts);
} else if (nrparts == 0) {
printk(KERN_NOTICE "RedBoot partition table failed\n");
iounmap((void *)dc21285_map.map_priv_1);
return -ENXIO;
add_mtd_device(mymtd);
}
add_mtd_partitions(mymtd, dc21285_parts, nrparts);
/*
* Flash timing is determined with bits 19-16 of the
* CSR_SA110_CNTL. The value is the number of wait cycles, or
......
/*
* $Id: edb7312.c,v 1.2 2002/09/05 05:11:24 acurtis Exp $
*
* Handle mapping of the NOR flash on Cogent EDB7312 boards
*
* Copyright 2002 SYSGO Real-Time Solutions GmbH
*
* This program 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.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/config.h>
#ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h>
#endif
#define WINDOW_ADDR 0x00000000 /* physical properties of flash */
#define WINDOW_SIZE 0x01000000
#define BUSWIDTH 2
#define FLASH_BLOCKSIZE_MAIN 0x20000
#define FLASH_NUMBLOCKS_MAIN 128
/* can be "cfi_probe", "jedec_probe", "map_rom", 0 }; */
#define PROBETYPES { "cfi_probe", 0 }
#define MSG_PREFIX "EDB7312-NOR:" /* prefix for our printk()'s */
#define MTDID "edb7312-nor" /* for mtdparts= partitioning */
static struct mtd_info *mymtd;
__u8 edb7312nor_read8(struct map_info *map, unsigned long ofs)
{
return __raw_readb(map->map_priv_1 + ofs);
}
__u16 edb7312nor_read16(struct map_info *map, unsigned long ofs)
{
return __raw_readw(map->map_priv_1 + ofs);
}
__u32 edb7312nor_read32(struct map_info *map, unsigned long ofs)
{
return __raw_readl(map->map_priv_1 + ofs);
}
void edb7312nor_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
memcpy_fromio(to, map->map_priv_1 + from, len);
}
void edb7312nor_write8(struct map_info *map, __u8 d, unsigned long adr)
{
__raw_writeb(d, map->map_priv_1 + adr);
mb();
}
void edb7312nor_write16(struct map_info *map, __u16 d, unsigned long adr)
{
__raw_writew(d, map->map_priv_1 + adr);
mb();
}
void edb7312nor_write32(struct map_info *map, __u32 d, unsigned long adr)
{
__raw_writel(d, map->map_priv_1 + adr);
mb();
}
void edb7312nor_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
memcpy_toio(map->map_priv_1 + to, from, len);
}
struct map_info edb7312nor_map = {
name: "NOR flash on EDB7312",
size: WINDOW_SIZE,
buswidth: BUSWIDTH,
read8: edb7312nor_read8,
read16: edb7312nor_read16,
read32: edb7312nor_read32,
copy_from: edb7312nor_copy_from,
write8: edb7312nor_write8,
write16: edb7312nor_write16,
write32: edb7312nor_write32,
copy_to: edb7312nor_copy_to
};
#ifdef CONFIG_MTD_PARTITIONS
/*
* MTD partitioning stuff
*/
static struct mtd_partition static_partitions[3] =
{
{
name: "ARMboot",
size: 0x40000,
offset: 0
},
{
name: "Kernel",
size: 0x200000,
offset: 0x40000
},
{
name: "RootFS",
size: 0xDC0000,
offset: 0x240000
},
};
#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
#ifdef CONFIG_MTD_CMDLINE_PARTS
int parse_cmdline_partitions(struct mtd_info *master,
struct mtd_partition **pparts,
const char *mtd_id);
#endif
#endif
static int mtd_parts_nb = 0;
static struct mtd_partition *mtd_parts = 0;
int __init init_edb7312nor(void)
{
static const char *rom_probe_types[] = PROBETYPES;
const char **type;
const char *part_type = 0;
printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n",
WINDOW_SIZE, WINDOW_ADDR);
edb7312nor_map.map_priv_1 = (unsigned long)
ioremap(WINDOW_ADDR, WINDOW_SIZE);
if (!edb7312nor_map.map_priv_1) {
printk(MSG_PREFIX "failed to ioremap\n");
return -EIO;
}
mymtd = 0;
type = rom_probe_types;
for(; !mymtd && *type; type++) {
mymtd = do_map_probe(*type, &edb7312nor_map);
}
if (mymtd) {
mymtd->module = THIS_MODULE;
#ifdef CONFIG_MTD_PARTITIONS
#ifdef CONFIG_MTD_CMDLINE_PARTS
mtd_parts_nb = parse_cmdline_partitions(mymtd, &mtd_parts, MTDID);
if (mtd_parts_nb > 0)
part_type = "command line";
#endif
if (mtd_parts_nb == 0)
{
mtd_parts = static_partitions;
mtd_parts_nb = NB_OF(static_partitions);
part_type = "static";
}
#endif
add_mtd_device(mymtd);
if (mtd_parts_nb == 0)
printk(KERN_NOTICE MSG_PREFIX "no partition info available\n");
else
{
printk(KERN_NOTICE MSG_PREFIX
"using %s partition definition\n", part_type);
add_mtd_partitions(mymtd, mtd_parts, mtd_parts_nb);
}
return 0;
}
iounmap((void *)edb7312nor_map.map_priv_1);
return -ENXIO;
}
static void __exit cleanup_edb7312nor(void)
{
if (mymtd) {
del_mtd_device(mymtd);
map_destroy(mymtd);
}
if (edb7312nor_map.map_priv_1) {
iounmap((void *)edb7312nor_map.map_priv_1);
edb7312nor_map.map_priv_1 = 0;
}
}
module_init(init_edb7312nor);
module_exit(cleanup_edb7312nor);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
MODULE_DESCRIPTION("Generic configurable MTD map driver");
/*
* Flash memory access on EPXA based devices
*
* (C) 2000 Nicolas Pitre <nico@cam.org>
* Copyright (C) 2001 Altera Corporation
* Copyright (C) 2001 Red Hat, Inc.
*
* $Id: epxa10db-flash.c,v 1.4 2002/08/22 10:46:19 cdavies Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/hardware.h>
#ifdef CONFIG_EPXA10DB
#define BOARD_NAME "EPXA10DB"
#else
#define BOARD_NAME "EPXA1DB"
#endif
static int nr_parts = 0;
static struct mtd_partition *parts;
static struct mtd_info *mymtd;
extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **);
static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
static __u8 epxa_read8(struct map_info *map, unsigned long ofs)
{
return __raw_readb(map->map_priv_1 + ofs);
}
static __u16 epxa_read16(struct map_info *map, unsigned long ofs)
{
return __raw_readw(map->map_priv_1 + ofs);
}
static __u32 epxa_read32(struct map_info *map, unsigned long ofs)
{
return __raw_readl(map->map_priv_1 + ofs);
}
static void epxa_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
memcpy_fromio(to, (void *)(map->map_priv_1 + from), len);
}
static void epxa_write8(struct map_info *map, __u8 d, unsigned long adr)
{
__raw_writeb(d, map->map_priv_1 + adr);
mb();
}
static void epxa_write16(struct map_info *map, __u16 d, unsigned long adr)
{
__raw_writew(d, map->map_priv_1 + adr);
mb();
}
static void epxa_write32(struct map_info *map, __u32 d, unsigned long adr)
{
__raw_writel(d, map->map_priv_1 + adr);
mb();
}
static void epxa_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
memcpy_toio((void *)(map->map_priv_1 + to), from, len);
}
static struct map_info epxa_map = {
name: "EPXA flash",
size: FLASH_SIZE,
buswidth: 2,
read8: epxa_read8,
read16: epxa_read16,
read32: epxa_read32,
copy_from: epxa_copy_from,
write8: epxa_write8,
write16: epxa_write16,
write32: epxa_write32,
copy_to: epxa_copy_to
};
static int __init epxa_mtd_init(void)
{
int i;
printk(KERN_NOTICE "%s flash device: %x at %x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
epxa_map.map_priv_1 = (unsigned long)ioremap(FLASH_START, FLASH_SIZE);
if (!epxa_map.map_priv_1) {
printk("Failed to ioremap %s flash\n",BOARD_NAME);
return -EIO;
}
mymtd = do_map_probe("cfi_probe", &epxa_map);
if (!mymtd) {
iounmap((void *)epxa_map.map_priv_1);
return -ENXIO;
}
mymtd->module = THIS_MODULE;
/* Unlock the flash device. */
if(mymtd->unlock){
for (i=0; i<mymtd->numeraseregions;i++){
int j;
for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
}
}
}
#ifdef CONFIG_MTD_REDBOOT_PARTS
nr_parts = parse_redboot_partitions(mymtd, &parts);
if (nr_parts > 0) {
add_mtd_partitions(mymtd, parts, nr_parts);
return 0;
}
#endif
#ifdef CONFIG_MTD_AFS_PARTS
nr_parts = parse_afs_partitions(mymtd, &parts);
if (nr_parts > 0) {
add_mtd_partitions(mymtd, parts, nr_parts);
return 0;
}
#endif
/* No recognised partitioning schemes found - use defaults */
nr_parts = epxa_default_partitions(mymtd, &parts);
if (nr_parts > 0) {
add_mtd_partitions(mymtd, parts, nr_parts);
return 0;
}
/* If all else fails... */
add_mtd_device(mymtd);
return 0;
}
static void __exit epxa_mtd_cleanup(void)
{
if (mymtd) {
if (nr_parts)
del_mtd_partitions(mymtd);
else
del_mtd_device(mymtd);
map_destroy(mymtd);
}
if (epxa_map.map_priv_1) {
iounmap((void *)epxa_map.map_priv_1);
epxa_map.map_priv_1 = 0;
}
}
/*
* This will do for now, once we decide which bootldr we're finally
* going to use then we'll remove this function and do it properly
*
* Partions are currently (as offsets from base of flash):
* 0x00000000 - 0x003FFFFF - bootloader (!)
* 0x00400000 - 0x00FFFFFF - Flashdisk
*/
static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
{
struct mtd_partition *parts;
int ret, i;
int npartitions = 0;
char *names;
const char *name = "jffs";
printk("Using default partitions for %s\n",BOARD_NAME);
npartitions=1;
parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL);
memzero(parts,npartitions*sizeof(*parts)+strlen(name));
if (!parts) {
ret = -ENOMEM;
goto out;
}
i=0;
names = (char *)&parts[npartitions];
parts[i].name = names;
names += strlen(name) + 1;
strcpy(parts[i].name, name);
#ifdef CONFIG_EPXA10DB
parts[i].size = FLASH_SIZE-0x00400000;
parts[i].offset = 0x00400000;
#else
parts[i].size = FLASH_SIZE-0x00180000;
parts[i].offset = 0x00180000;
#endif
out:
*pparts = parts;
return npartitions;
}
module_init(epxa_mtd_init);
module_exit(epxa_mtd_cleanup);
MODULE_AUTHOR("Clive Davies");
MODULE_DESCRIPTION("Altera epxa mtd flash map");
MODULE_LICENSE("GPL");
/* fortunet.c memory map
*
* $Id: fortunet.c,v 1.2 2002/10/14 12:50:22 rmk Exp $
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#define MAX_NUM_REGIONS 4
#define MAX_NUM_PARTITIONS 8
#define DEF_WINDOW_ADDR_PHY 0x00000000
#define DEF_WINDOW_SIZE 0x00800000 // 8 Mega Bytes
#define MTD_FORTUNET_PK "MTD FortuNet: "
#define MAX_NAME_SIZE 128
struct map_region
{
int window_addr_phyical;
int altbuswidth;
struct map_info map_info;
struct mtd_info *mymtd;
struct mtd_partition parts[MAX_NUM_PARTITIONS];
char map_name[MAX_NAME_SIZE];
char parts_name[MAX_NUM_PARTITIONS][MAX_NAME_SIZE];
};
static struct map_region map_regions[MAX_NUM_REGIONS];
static int map_regions_set[MAX_NUM_REGIONS] = {0,0,0,0};
static int map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0};
__u8 fortunet_read8(struct map_info *map, unsigned long ofs)
{
return *(__u8 *)(map->map_priv_1 + ofs);
}
__u16 fortunet_read16(struct map_info *map, unsigned long ofs)
{
return *(__u16 *)(map->map_priv_1 + ofs);
}
__u32 fortunet_read32(struct map_info *map, unsigned long ofs)
{
return *(__u32 *)(map->map_priv_1 + ofs);
}
void fortunet_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
memcpy(to, (void *)(map->map_priv_1 + from), len);
}
void fortunet_write8(struct map_info *map, __u8 d, unsigned long adr)
{
*(__u8 *)(map->map_priv_1 + adr) = d;
}
void fortunet_write16(struct map_info *map, __u16 d, unsigned long adr)
{
*(__u16 *)(map->map_priv_1 + adr) = d;
}
void fortunet_write32(struct map_info *map, __u32 d, unsigned long adr)
{
*(__u32 *)(map->map_priv_1 + adr) = d;
}
void fortunet_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
memcpy((void *)(map->map_priv_1 + to), from, len);
}
struct map_info default_map = {
size: DEF_WINDOW_SIZE,
buswidth: 4,
read8: fortunet_read8,
read16: fortunet_read16,
read32: fortunet_read32,
copy_from: fortunet_copy_from,
write8: fortunet_write8,
write16: fortunet_write16,
write32: fortunet_write32,
copy_to: fortunet_copy_to
};
static char * __init get_string_option(char *dest,int dest_size,char *sor)
{
if(!dest_size)
return sor;
dest_size--;
while(*sor)
{
if(*sor==',')
{
sor++;
break;
}
else if(*sor=='\"')
{
sor++;
while(*sor)
{
if(*sor=='\"')
{
sor++;
break;
}
*dest = *sor;
dest++;
sor++;
dest_size--;
if(!dest_size)
{
*dest = 0;
return sor;
}
}
}
else
{
*dest = *sor;
dest++;
sor++;
dest_size--;
if(!dest_size)
{
*dest = 0;
return sor;
}
}
}
*dest = 0;
return sor;
}
static int __init MTD_New_Region(char *line)
{
char string[MAX_NAME_SIZE];
int params[6];
get_options (get_string_option(string,sizeof(string),line),6,params);
if(params[0]<1)
{
printk(MTD_FORTUNET_PK "Bad paramters for MTD Region "
" name,region-number[,base,size,buswidth,altbuswidth]\n");
return 1;
}
if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
{
printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
params[1],MAX_NUM_REGIONS-1);
return 1;
}
memset(&map_regions[params[1]],0,sizeof(map_regions[params[1]]));
memcpy(&map_regions[params[1]].map_info,
&default_map,sizeof(map_regions[params[1]].map_info));
map_regions_set[params[1]] = 1;
map_regions[params[1]].window_addr_phyical = DEF_WINDOW_ADDR_PHY;
map_regions[params[1]].altbuswidth = 2;
map_regions[params[1]].mymtd = NULL;
map_regions[params[1]].map_info.name = map_regions[params[1]].map_name;
strcpy(map_regions[params[1]].map_info.name,string);
if(params[0]>1)
{
map_regions[params[1]].window_addr_phyical = params[2];
}
if(params[0]>2)
{
map_regions[params[1]].map_info.size = params[3];
}
if(params[0]>3)
{
map_regions[params[1]].map_info.buswidth = params[4];
}
if(params[0]>4)
{
map_regions[params[1]].altbuswidth = params[5];
}
return 1;
}
static int __init MTD_New_Partion(char *line)
{
char string[MAX_NAME_SIZE];
int params[4];
get_options (get_string_option(string,sizeof(string),line),4,params);
if(params[0]<3)
{
printk(MTD_FORTUNET_PK "Bad paramters for MTD Partion "
" name,region-number,size,offset\n");
return 1;
}
if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
{
printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
params[1],MAX_NUM_REGIONS-1);
return 1;
}
if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS)
{
printk(MTD_FORTUNET_PK "Out of space for partion in this region\n");
return 1;
}
map_regions[params[1]].parts[map_regions_parts[params[1]]].name =
map_regions[params[1]]. parts_name[map_regions_parts[params[1]]];
strcpy(map_regions[params[1]].parts[map_regions_parts[params[1]]].name,string);
map_regions[params[1]].parts[map_regions_parts[params[1]]].size =
params[2];
map_regions[params[1]].parts[map_regions_parts[params[1]]].offset =
params[3];
map_regions[params[1]].parts[map_regions_parts[params[1]]].mask_flags = 0;
map_regions_parts[params[1]]++;
return 1;
}
__setup("MTD_Region=", MTD_New_Region);
__setup("MTD_Partion=", MTD_New_Partion);
int __init init_fortunet(void)
{
int ix,iy;
for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++)
{
if(map_regions_parts[ix]&&(!map_regions_set[ix]))
{
printk(MTD_FORTUNET_PK "Region %d is not setup (Seting to default)\n",
ix);
memset(&map_regions[ix],0,sizeof(map_regions[ix]));
memcpy(&map_regions[ix].map_info,&default_map,
sizeof(map_regions[ix].map_info));
map_regions_set[ix] = 1;
map_regions[ix].window_addr_phyical = DEF_WINDOW_ADDR_PHY;
map_regions[ix].altbuswidth = 2;
map_regions[ix].mymtd = NULL;
map_regions[ix].map_info.name = map_regions[ix].map_name;
strcpy(map_regions[ix].map_info.name,"FORTUNET");
}
if(map_regions_set[ix])
{
iy++;
printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at phyicaly "
" address %x size %x\n",
map_regions[ix].map_info.name,
map_regions[ix].window_addr_phyical,
map_regions[ix].map_info.size);
map_regions[ix].map_info.map_priv_1 =
(int)ioremap_nocache(
map_regions[ix].window_addr_phyical,
map_regions[ix].map_info.size);
if(!map_regions[ix].map_info.map_priv_1)
{
printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n",
map_regions[ix].map_info.name);
return -ENXIO;
}
printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is veritualy at: %x\n",
map_regions[ix].map_info.name,
map_regions[ix].map_info.map_priv_1);
map_regions[ix].mymtd = do_map_probe("cfi_probe",
&map_regions[ix].map_info);
if((!map_regions[ix].mymtd)&&(
map_regions[ix].altbuswidth!=map_regions[ix].map_info.buswidth))
{
printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternet buswidth "
"for %s flash.\n",
map_regions[ix].map_info.name);
map_regions[ix].map_info.buswidth =
map_regions[ix].altbuswidth;
map_regions[ix].mymtd = do_map_probe("cfi_probe",
&map_regions[ix].map_info);
}
map_regions[ix].mymtd->module = THIS_MODULE;
add_mtd_partitions(map_regions[ix].mymtd,
map_regions[ix].parts,map_regions_parts[ix]);
}
}
if(iy)
return 0;
return -ENXIO;
}
static void __exit cleanup_fortunet(void)
{
int ix;
for(ix=0;ix<MAX_NUM_REGIONS;ix++)
{
if(map_regions_set[ix])
{
if( map_regions[ix].mymtd )
{
del_mtd_partitions( map_regions[ix].mymtd );
map_destroy( map_regions[ix].mymtd );
}
iounmap((void *)map_regions[ix].map_info.map_priv_1);
}
}
}
module_init(init_fortunet);
module_exit(cleanup_fortunet);
MODULE_AUTHOR("FortuNet, Inc.");
MODULE_DESCRIPTION("MTD map driver for FortuNet boards");
/*
* $Id: impa7.c,v 1.2 2002/09/05 05:11:24 acurtis Exp $
*
* Handle mapping of the NOR flash on implementa A7 boards
*
* Copyright 2002 SYSGO Real-Time Solutions GmbH
*
* This program 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.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/config.h>
#ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h>
#endif
#define WINDOW_ADDR0 0x00000000 /* physical properties of flash */
#define WINDOW_SIZE0 0x00800000
#define WINDOW_ADDR1 0x10000000 /* physical properties of flash */
#define WINDOW_SIZE1 0x00800000
#define NUM_FLASHBANKS 2
#define BUSWIDTH 4
/* can be { "cfi_probe", "jedec_probe", "map_rom", 0 }; */
#define PROBETYPES { "jedec_probe", 0 }
#define MSG_PREFIX "impA7:" /* prefix for our printk()'s */
#define MTDID "impa7-%d" /* for mtdparts= partitioning */
static struct mtd_info *impa7_mtd[NUM_FLASHBANKS] = { 0 };
__u8 impa7_read8(struct map_info *map, unsigned long ofs)
{
return __raw_readb(map->map_priv_1 + ofs);
}
__u16 impa7_read16(struct map_info *map, unsigned long ofs)
{
return __raw_readw(map->map_priv_1 + ofs);
}
__u32 impa7_read32(struct map_info *map, unsigned long ofs)
{
return __raw_readl(map->map_priv_1 + ofs);
}
void impa7_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
memcpy_fromio(to, map->map_priv_1 + from, len);
}
void impa7_write8(struct map_info *map, __u8 d, unsigned long adr)
{
__raw_writeb(d, map->map_priv_1 + adr);
mb();
}
void impa7_write16(struct map_info *map, __u16 d, unsigned long adr)
{
__raw_writew(d, map->map_priv_1 + adr);
mb();
}
void impa7_write32(struct map_info *map, __u32 d, unsigned long adr)
{
__raw_writel(d, map->map_priv_1 + adr);
mb();
}
void impa7_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
memcpy_toio(map->map_priv_1 + to, from, len);
}
static struct map_info impa7_map[NUM_FLASHBANKS] = {
{
name: "impA7 NOR Flash Bank #0",
size: WINDOW_SIZE0,
buswidth: BUSWIDTH,
read8: impa7_read8,
read16: impa7_read16,
read32: impa7_read32,
copy_from: impa7_copy_from,
write8: impa7_write8,
write16: impa7_write16,
write32: impa7_write32,
copy_to: impa7_copy_to
},
{
name: "impA7 NOR Flash Bank #1",
size: WINDOW_SIZE1,
buswidth: BUSWIDTH,
read8: impa7_read8,
read16: impa7_read16,
read32: impa7_read32,
copy_from: impa7_copy_from,
write8: impa7_write8,
write16: impa7_write16,
write32: impa7_write32,
copy_to: impa7_copy_to
},
};
#ifdef CONFIG_MTD_PARTITIONS
/*
* MTD partitioning stuff
*/
static struct mtd_partition static_partitions[] =
{
{
name: "FileSystem",
size: 0x800000,
offset: 0x00000000
},
};
#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
#ifdef CONFIG_MTD_CMDLINE_PARTS
int parse_cmdline_partitions(struct mtd_info *master,
struct mtd_partition **pparts,
const char *mtd_id);
#endif
#endif
static int mtd_parts_nb = 0;
static struct mtd_partition *mtd_parts = 0;
int __init init_impa7(void)
{
static const char *rom_probe_types[] = PROBETYPES;
const char **type;
const char *part_type = 0;
int i;
static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
{ WINDOW_ADDR0, WINDOW_SIZE0 },
{ WINDOW_ADDR1, WINDOW_SIZE1 },
};
char mtdid[10];
int devicesfound = 0;
for(i=0; i<NUM_FLASHBANKS; i++)
{
printk(KERN_NOTICE MSG_PREFIX "probing 0x%08lx at 0x%08lx\n",
pt[i].size, pt[i].addr);
impa7_map[i].map_priv_1 = (unsigned long)
ioremap(pt[i].addr, pt[i].size);
if (!impa7_map[i].map_priv_1) {
printk(MSG_PREFIX "failed to ioremap\n");
return -EIO;
}
impa7_mtd[i] = 0;
type = rom_probe_types;
for(; !impa7_mtd[i] && *type; type++) {
impa7_mtd[i] = do_map_probe(*type, &impa7_map[i]);
}
if (impa7_mtd[i])
{
impa7_mtd[i]->module = THIS_MODULE;
add_mtd_device(impa7_mtd[i]);
devicesfound++;
#ifdef CONFIG_MTD_PARTITIONS
#ifdef CONFIG_MTD_CMDLINE_PARTS
sprintf(mtdid, MTDID, i);
mtd_parts_nb = parse_cmdline_partitions(impa7_mtd[i],
&mtd_parts,
mtdid);
if (mtd_parts_nb > 0)
part_type = "command line";
#endif
if (mtd_parts_nb <= 0)
{
mtd_parts = static_partitions;
mtd_parts_nb = NB_OF(static_partitions);
part_type = "static";
}
if (mtd_parts_nb <= 0)
{
printk(KERN_NOTICE MSG_PREFIX
"no partition info available\n");
}
else
{
printk(KERN_NOTICE MSG_PREFIX
"using %s partition definition\n",
part_type);
add_mtd_partitions(impa7_mtd[i],
mtd_parts, mtd_parts_nb);
}
#endif
}
else
iounmap((void *)impa7_map[i].map_priv_1);
}
return devicesfound == 0 ? -ENXIO : 0;
}
static void __exit cleanup_impa7(void)
{
int i;
for (i=0; i<NUM_FLASHBANKS; i++)
{
if (impa7_mtd[i])
{
del_mtd_device(impa7_mtd[i]);
map_destroy(impa7_mtd[i]);
}
if (impa7_map[i].map_priv_1)
{
iounmap((void *)impa7_map[i].map_priv_1);
impa7_map[i].map_priv_1 = 0;
}
}
}
module_init(init_impa7);
module_exit(cleanup_impa7);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pavel Bartusek <pba@sysgo.de>");
MODULE_DESCRIPTION("MTD map driver for implementa impA7");
/*
* $Id: iq80310.c,v 1.8 2001/10/02 15:05:14 dwmw2 Exp $
* $Id: iq80310.c,v 1.9 2002/01/01 22:45:02 rmk Exp $
*
* Mapping for the Intel XScale IQ80310 evaluation board
*
......@@ -116,7 +116,7 @@ static int __init init_iq80310(void)
int parsed_nr_parts = 0;
char *part_type = "static";
iq80310_map.map_priv_1 = (unsigned long)__ioremap(WINDOW_ADDR, WINDOW_SIZE, 0);
iq80310_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
if (!iq80310_map.map_priv_1) {
printk("Failed to ioremap\n");
return -EIO;
......@@ -161,7 +161,6 @@ static void __exit cleanup_iq80310(void)
}
if (iq80310_map.map_priv_1)
iounmap((void *)iq80310_map.map_priv_1);
return 0;
}
module_init(init_iq80310);
......
/*
* linux/drivers/mtd/maps/pci.c
*
* Copyright (C) 2001 Russell King, All rights reserved.
*
* This program 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.
*
* $Id: pci.c,v 1.1 2001/09/27 20:28:45 rmk Exp $
*
* Generic PCI memory map driver. We support the following boards:
* - Intel IQ80310 ATU.
* - Intel EBSA285 (blank rom programming mode). Tested working 27/09/2001
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
struct map_pci_info;
struct mtd_pci_info {
int (*init)(struct pci_dev *dev, struct map_pci_info *map);
void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
const char *map_name;
};
struct map_pci_info {
struct map_info map;
void *base;
void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
struct pci_dev *dev;
};
/*
* Intel IOP80310 Flash driver
*/
static int
intel_iq80310_init(struct pci_dev *dev, struct map_pci_info *map)
{
u32 win_base;
map->map.buswidth = 1;
map->map.size = 0x00800000;
map->base = ioremap_nocache(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
if (!map->base)
return -ENOMEM;
/*
* We want to base the memory window at Xscale
* bus address 0, not 0x1000.
*/
pci_read_config_dword(dev, 0x44, &win_base);
pci_write_config_dword(dev, 0x44, 0);
map->map.map_priv_2 = win_base;
return 0;
}
static void
intel_iq80310_exit(struct pci_dev *dev, struct map_pci_info *map)
{
if (map->base)
iounmap((void *)map->base);
pci_write_config_dword(dev, 0x44, map->map.map_priv_2);
}
static unsigned long
intel_iq80310_translate(struct map_pci_info *map, unsigned long ofs)
{
unsigned long page_addr = ofs & 0x00400000;
/*
* This mundges the flash location so we avoid
* the first 80 bytes (they appear to read nonsense).
*/
if (page_addr) {
writel(0x00000008, map->base + 0x1558);
writel(0x00000000, map->base + 0x1550);
} else {
writel(0x00000007, map->base + 0x1558);
writel(0x00800000, map->base + 0x1550);
ofs += 0x00800000;
}
return ofs;
}
static struct mtd_pci_info intel_iq80310_info = {
init: intel_iq80310_init,
exit: intel_iq80310_exit,
translate: intel_iq80310_translate,
map_name: "cfi_probe",
};
/*
* Intel DC21285 driver
*/
static int
intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
{
unsigned long base, len;
base = pci_resource_start(dev, PCI_ROM_RESOURCE);
len = pci_resource_len(dev, PCI_ROM_RESOURCE);
if (!len || !base) {
/*
* No ROM resource
*/
base = pci_resource_start(dev, 2);
len = pci_resource_len(dev, 2);
/*
* We need to re-allocate PCI BAR2 address range to the
* PCI ROM BAR, and disable PCI BAR2.
*/
} else {
/*
* Hmm, if an address was allocated to the ROM resource, but
* not enabled, should we be allocating a new resource for it
* or simply enabling it?
*/
if (!(pci_resource_flags(dev, PCI_ROM_RESOURCE) &
PCI_ROM_ADDRESS_ENABLE)) {
u32 val;
pci_resource_flags(dev, PCI_ROM_RESOURCE) |= PCI_ROM_ADDRESS_ENABLE;
pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
val |= PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
printk("%s: enabling expansion ROM\n", dev->slot_name);
}
}
if (!len || !base)
return -ENXIO;
map->map.buswidth = 4;
map->map.size = len;
map->base = ioremap_nocache(base, len);
if (!map->base)
return -ENOMEM;
return 0;
}
static void
intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map)
{
u32 val;
if (map->base)
iounmap((void *)map->base);
/*
* We need to undo the PCI BAR2/PCI ROM BAR address alteration.
*/
pci_resource_flags(dev, PCI_ROM_RESOURCE) &= ~PCI_ROM_ADDRESS_ENABLE;
pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
val &= ~PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
}
static unsigned long
intel_dc21285_translate(struct map_pci_info *map, unsigned long ofs)
{
return ofs & 0x00ffffc0 ? ofs : (ofs ^ (1 << 5));
}
static struct mtd_pci_info intel_dc21285_info = {
init: intel_dc21285_init,
exit: intel_dc21285_exit,
translate: intel_dc21285_translate,
map_name: "jedec_probe",
};
/*
* PCI device ID table
*/
static struct pci_device_id mtd_pci_ids[] __devinitdata = {
{
vendor: PCI_VENDOR_ID_INTEL,
device: 0x530d,
subvendor: PCI_ANY_ID,
subdevice: PCI_ANY_ID,
class: PCI_CLASS_MEMORY_OTHER << 8,
class_mask: 0xffff00,
driver_data: (unsigned long)&intel_iq80310_info,
},
{
vendor: PCI_VENDOR_ID_DEC,
device: PCI_DEVICE_ID_DEC_21285,
subvendor: 0, /* DC21285 defaults to 0 on reset */
subdevice: 0, /* DC21285 defaults to 0 on reset */
class: 0,
class_mask: 0,
driver_data: (unsigned long)&intel_dc21285_info,
},
{ 0, }
};
/*
* Generic code follows.
*/
static u8 mtd_pci_read8(struct map_info *_map, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
u8 val = readb(map->base + map->translate(map, ofs));
// printk("read8 : %08lx => %02x\n", ofs, val);
return val;
}
static u16 mtd_pci_read16(struct map_info *_map, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
u16 val = readw(map->base + map->translate(map, ofs));
// printk("read16: %08lx => %04x\n", ofs, val);
return val;
}
static u32 mtd_pci_read32(struct map_info *_map, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
u32 val = readl(map->base + map->translate(map, ofs));
// printk("read32: %08lx => %08x\n", ofs, val);
return val;
}
static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
memcpy_fromio(to, map->base + map->translate(map, from), len);
}
static void mtd_pci_write8(struct map_info *_map, u8 val, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
// printk("write8 : %08lx <= %02x\n", ofs, val);
writeb(val, map->base + map->translate(map, ofs));
}
static void mtd_pci_write16(struct map_info *_map, u16 val, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
// printk("write16: %08lx <= %04x\n", ofs, val);
writew(val, map->base + map->translate(map, ofs));
}
static void mtd_pci_write32(struct map_info *_map, u32 val, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
// printk("write32: %08lx <= %08x\n", ofs, val);
writel(val, map->base + map->translate(map, ofs));
}
static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
memcpy_toio(map->base + map->translate(map, to), from, len);
}
static struct map_info mtd_pci_map = {
read8: mtd_pci_read8,
read16: mtd_pci_read16,
read32: mtd_pci_read32,
copy_from: mtd_pci_copyfrom,
write8: mtd_pci_write8,
write16: mtd_pci_write16,
write32: mtd_pci_write32,
copy_to: mtd_pci_copyto,
};
static int __devinit
mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data;
struct map_pci_info *map = NULL;
struct mtd_info *mtd = NULL;
int err;
err = pci_enable_device(dev);
if (err)
goto out;
err = pci_request_regions(dev, "pci mtd");
if (err)
goto out;
map = kmalloc(sizeof(*map), GFP_KERNEL);
err = -ENOMEM;
if (!map)
goto release;
map->map = mtd_pci_map;
map->map.name = dev->slot_name;
map->dev = dev;
map->exit = info->exit;
map->translate = info->translate;
err = info->init(dev, map);
if (err)
goto release;
/* tsk - do_map_probe should take const char * */
mtd = do_map_probe((char *)info->map_name, &map->map);
err = -ENODEV;
if (!mtd)
goto release;
mtd->module = THIS_MODULE;
add_mtd_device(mtd);
pci_set_drvdata(dev, mtd);
return 0;
release:
if (mtd)
map_destroy(mtd);
if (map) {
map->exit(dev, map);
kfree(map);
}
pci_release_regions(dev);
out:
return err;
}
static void __devexit
mtd_pci_remove(struct pci_dev *dev)
{
struct mtd_info *mtd = pci_get_drvdata(dev);
struct map_pci_info *map = mtd->priv;
del_mtd_device(mtd);
map_destroy(mtd);
map->exit(dev, map);
kfree(map);
pci_set_drvdata(dev, NULL);
pci_release_regions(dev);
}
static struct pci_driver mtd_pci_driver = {
name: "MTD PCI",
probe: mtd_pci_probe,
remove: mtd_pci_remove,
id_table: mtd_pci_ids,
};
static int __init mtd_pci_maps_init(void)
{
return pci_module_init(&mtd_pci_driver);
}
static void __exit mtd_pci_maps_exit(void)
{
pci_unregister_driver(&mtd_pci_driver);
}
module_init(mtd_pci_maps_init);
module_exit(mtd_pci_maps_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_DESCRIPTION("Generic PCI map driver");
MODULE_DEVICE_TABLE(pci, mtd_pci_ids);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* MTD device concatenation layer definitions
*
* (C) 2002 Robert Kaiser <rkaiser@sysgo.de>
*
* This code is GPL
*
* $Id: concat.h,v 1.1 2002/03/08 16:34:36 rkaiser Exp $
*/
#ifndef MTD_CONCAT_H
#define MTD_CONCAT_H
struct mtd_info *mtd_concat_create(
struct mtd_info *subdev[], /* subdevices to concatenate */
int num_devs, /* number of subdevices */
char *name); /* name for the new device */
void mtd_concat_destroy(struct mtd_info *mtd);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment