typedef struct Flash Flash; typedef struct Flashchip Flashchip; typedef struct Flashpart Flashpart; typedef struct Flashregion Flashregion; /* * logical partitions */ enum { Maxflashpart = 8 }; struct Flashpart { char* name; ulong start; ulong end; }; enum { Maxflashregion = 4 }; /* * physical erase block regions */ struct Flashregion { int n; /* number of blocks in region */ ulong start; /* physical base address (allowing for banks) */ ulong end; ulong erasesize; ulong eraseshift; /* log2(erasesize) */ ulong pagesize; /* if non-0, size of pages within erase block */ ulong pageshift; /* log2(pagesize) */ ulong spares; /* spare bytes per page, for ecc, etc. */ }; /* * one of a set of chips in a given region */ struct Flashchip { int nr; Flashregion regions[Maxflashregion]; uchar id; /* flash manufacturer ID */ ushort devid; /* flash device ID */ int width; /* bytes per flash line */ int maxwb; /* max write buffer size */ ulong devsize; /* physical device size */ int alg; /* programming algorithm (if CFI) */ int protect; /* software protection */ }; /* * structure defining a contiguous region of flash memory */ struct Flash { QLock; /* interlock on flash operations */ Flash* next; /* following are filled in before calling Flash.reset */ char* type; void* addr; ulong size; int xip; /* executing in place: don't query */ int (*reset)(Flash*); /* following are filled in by the reset routine */ int (*eraseall)(Flash*); int (*erasezone)(Flash*, Flashregion*, ulong); /* (optional) reads of correct width and alignment */ int (*read)(Flash*, ulong, void*, long); /* writes of correct width and alignment */ int (*write)(Flash*, ulong, void*, long); int (*suspend)(Flash*); int (*resume)(Flash*); int (*attach)(Flash*); /* following might be filled in by either archflashreset or reset routine */ int nr; Flashregion regions[Maxflashregion]; uchar id; /* flash manufacturer ID */ ushort devid; /* flash device ID */ int width; /* bytes per flash line */ int interleave; /* addresses are interleaved across set of chips */ int bshift; /* byte addresses are shifted */ ulong cmask; /* command mask for interleaving */ int maxwb; /* max write buffer size */ ulong devsize; /* physical device size */ int alg; /* programming algorithm (if CFI) */ void* data; /* flash type routines' private storage, or nil */ Flashpart part[Maxflashpart]; /* logical partitions */ int protect; /* software protection */ char* sort; /* "nand", "nor", "serial", nil (unspecified) */ }; /* * called by link routine of driver for specific flash type: arguments are * conventional name for card type/model, and card driver's reset routine. */ void addflashcard(char*, int (*)(Flash*)); /* * called by devflash.c:/^flashreset; if flash exists, * sets type, address, and size in bytes of flash * and returns 0; returns -1 if flash doesn't exist */ int archflashreset(int, Flash*); /* * enable/disable write protect */ void archflashwp(Flash*, int); /* * flash access taking width and interleave into account */ int flashget(Flash*, ulong); void flashput(Flash*, ulong, int); /* * Architecture specific routines for managing nand devices */ /* * do any device spcific initialisation */ void archnand_init(Flash*); /* * if claim is 1, claim device exclusively, and enable it (power it up) * if claim is 0, release, and disable it (power it down) * claiming may be as simple as a qlock per device */ void archnand_claim(Flash*, int claim); /* * set command latch enable (CLE) and address latch enable (ALE) * appropriately */ void archnand_setCLEandALE(Flash*, int cle, int ale); /* * write a sequence of bytes to the device */ void archnand_write(Flash*, void *buf, int len); /* * read a sequence of bytes from the device * if buf is 0, throw away the data */ void archnand_read(Flash*, void *buf, int len);