106f6463aSDavid du Colombier typedef struct Flash Flash; 206f6463aSDavid du Colombier typedef struct Flashchip Flashchip; 306f6463aSDavid du Colombier typedef struct Flashpart Flashpart; 406f6463aSDavid du Colombier typedef struct Flashregion Flashregion; 506f6463aSDavid du Colombier 606f6463aSDavid du Colombier /* 706f6463aSDavid du Colombier * logical partitions 806f6463aSDavid du Colombier */ 906f6463aSDavid du Colombier enum { 1006f6463aSDavid du Colombier Maxflashpart = 8 1106f6463aSDavid du Colombier }; 1206f6463aSDavid du Colombier 1306f6463aSDavid du Colombier struct Flashpart { 1406f6463aSDavid du Colombier char* name; 1506f6463aSDavid du Colombier ulong start; 1606f6463aSDavid du Colombier ulong end; 1706f6463aSDavid du Colombier }; 1806f6463aSDavid du Colombier 1906f6463aSDavid du Colombier enum { 2006f6463aSDavid du Colombier Maxflashregion = 4 2106f6463aSDavid du Colombier }; 2206f6463aSDavid du Colombier 2306f6463aSDavid du Colombier /* 2406f6463aSDavid du Colombier * physical erase block regions 2506f6463aSDavid du Colombier */ 2606f6463aSDavid du Colombier struct Flashregion { 2706f6463aSDavid du Colombier int n; /* number of blocks in region */ 2806f6463aSDavid du Colombier ulong start; /* physical base address (allowing for banks) */ 2906f6463aSDavid du Colombier ulong end; 3006f6463aSDavid du Colombier ulong erasesize; 31*047f1f95SDavid du Colombier ulong eraseshift; /* log2(erasesize) */ 3206f6463aSDavid du Colombier ulong pagesize; /* if non-0, size of pages within erase block */ 33*047f1f95SDavid du Colombier ulong pageshift; /* log2(pagesize) */ 3406f6463aSDavid du Colombier ulong spares; /* spare bytes per page, for ecc, etc. */ 3506f6463aSDavid du Colombier }; 3606f6463aSDavid du Colombier 3706f6463aSDavid du Colombier /* 3806f6463aSDavid du Colombier * one of a set of chips in a given region 3906f6463aSDavid du Colombier */ 4006f6463aSDavid du Colombier struct Flashchip { 4106f6463aSDavid du Colombier int nr; 4206f6463aSDavid du Colombier Flashregion regions[Maxflashregion]; 4306f6463aSDavid du Colombier 4406f6463aSDavid du Colombier uchar id; /* flash manufacturer ID */ 4506f6463aSDavid du Colombier ushort devid; /* flash device ID */ 4606f6463aSDavid du Colombier int width; /* bytes per flash line */ 4706f6463aSDavid du Colombier int maxwb; /* max write buffer size */ 4806f6463aSDavid du Colombier ulong devsize; /* physical device size */ 4906f6463aSDavid du Colombier int alg; /* programming algorithm (if CFI) */ 5006f6463aSDavid du Colombier int protect; /* software protection */ 5106f6463aSDavid du Colombier }; 5206f6463aSDavid du Colombier 5306f6463aSDavid du Colombier /* 5406f6463aSDavid du Colombier * structure defining a contiguous region of flash memory 5506f6463aSDavid du Colombier */ 5606f6463aSDavid du Colombier struct Flash { 5706f6463aSDavid du Colombier QLock; /* interlock on flash operations */ 5806f6463aSDavid du Colombier Flash* next; 5906f6463aSDavid du Colombier 6006f6463aSDavid du Colombier /* following are filled in before calling Flash.reset */ 6106f6463aSDavid du Colombier char* type; 6206f6463aSDavid du Colombier void* addr; 6306f6463aSDavid du Colombier ulong size; 6406f6463aSDavid du Colombier int xip; /* executing in place: don't query */ 6506f6463aSDavid du Colombier int (*reset)(Flash*); 6606f6463aSDavid du Colombier 6706f6463aSDavid du Colombier /* following are filled in by the reset routine */ 6806f6463aSDavid du Colombier int (*eraseall)(Flash*); 6906f6463aSDavid du Colombier int (*erasezone)(Flash*, Flashregion*, ulong); 7006f6463aSDavid du Colombier /* (optional) reads of correct width and alignment */ 7106f6463aSDavid du Colombier int (*read)(Flash*, ulong, void*, long); 7206f6463aSDavid du Colombier /* writes of correct width and alignment */ 7306f6463aSDavid du Colombier int (*write)(Flash*, ulong, void*, long); 7406f6463aSDavid du Colombier int (*suspend)(Flash*); 7506f6463aSDavid du Colombier int (*resume)(Flash*); 7606f6463aSDavid du Colombier int (*attach)(Flash*); 7706f6463aSDavid du Colombier 7806f6463aSDavid du Colombier /* following might be filled in by either archflashreset or reset routine */ 7906f6463aSDavid du Colombier int nr; 8006f6463aSDavid du Colombier Flashregion regions[Maxflashregion]; 8106f6463aSDavid du Colombier 8206f6463aSDavid du Colombier uchar id; /* flash manufacturer ID */ 8306f6463aSDavid du Colombier ushort devid; /* flash device ID */ 8406f6463aSDavid du Colombier int width; /* bytes per flash line */ 8506f6463aSDavid du Colombier int interleave; /* addresses are interleaved across set of chips */ 8606f6463aSDavid du Colombier int bshift; /* byte addresses are shifted */ 8706f6463aSDavid du Colombier ulong cmask; /* command mask for interleaving */ 8806f6463aSDavid du Colombier int maxwb; /* max write buffer size */ 8906f6463aSDavid du Colombier ulong devsize; /* physical device size */ 9006f6463aSDavid du Colombier int alg; /* programming algorithm (if CFI) */ 9106f6463aSDavid du Colombier void* data; /* flash type routines' private storage, or nil */ 9206f6463aSDavid du Colombier Flashpart part[Maxflashpart]; /* logical partitions */ 9306f6463aSDavid du Colombier int protect; /* software protection */ 9406f6463aSDavid du Colombier char* sort; /* "nand", "nor", "serial", nil (unspecified) */ 9506f6463aSDavid du Colombier }; 9606f6463aSDavid du Colombier 9706f6463aSDavid du Colombier /* 9806f6463aSDavid du Colombier * called by link routine of driver for specific flash type: arguments are 9906f6463aSDavid du Colombier * conventional name for card type/model, and card driver's reset routine. 10006f6463aSDavid du Colombier */ 10106f6463aSDavid du Colombier void addflashcard(char*, int (*)(Flash*)); 10206f6463aSDavid du Colombier 10306f6463aSDavid du Colombier /* 10406f6463aSDavid du Colombier * called by devflash.c:/^flashreset; if flash exists, 10506f6463aSDavid du Colombier * sets type, address, and size in bytes of flash 10606f6463aSDavid du Colombier * and returns 0; returns -1 if flash doesn't exist 10706f6463aSDavid du Colombier */ 10806f6463aSDavid du Colombier int archflashreset(int, Flash*); 10906f6463aSDavid du Colombier 11006f6463aSDavid du Colombier /* 11106f6463aSDavid du Colombier * enable/disable write protect 11206f6463aSDavid du Colombier */ 11306f6463aSDavid du Colombier void archflashwp(Flash*, int); 11406f6463aSDavid du Colombier 11506f6463aSDavid du Colombier /* 11606f6463aSDavid du Colombier * flash access taking width and interleave into account 11706f6463aSDavid du Colombier */ 11806f6463aSDavid du Colombier int flashget(Flash*, ulong); 11906f6463aSDavid du Colombier void flashput(Flash*, ulong, int); 12006f6463aSDavid du Colombier 12106f6463aSDavid du Colombier /* 12206f6463aSDavid du Colombier * Architecture specific routines for managing nand devices 12306f6463aSDavid du Colombier */ 12406f6463aSDavid du Colombier 12506f6463aSDavid du Colombier /* 12606f6463aSDavid du Colombier * do any device spcific initialisation 12706f6463aSDavid du Colombier */ 12806f6463aSDavid du Colombier void archnand_init(Flash*); 12906f6463aSDavid du Colombier 13006f6463aSDavid du Colombier /* 13106f6463aSDavid du Colombier * if claim is 1, claim device exclusively, and enable it (power it up) 13206f6463aSDavid du Colombier * if claim is 0, release, and disable it (power it down) 13306f6463aSDavid du Colombier * claiming may be as simple as a qlock per device 13406f6463aSDavid du Colombier */ 13506f6463aSDavid du Colombier void archnand_claim(Flash*, int claim); 13606f6463aSDavid du Colombier 13706f6463aSDavid du Colombier /* 13806f6463aSDavid du Colombier * set command latch enable (CLE) and address latch enable (ALE) 13906f6463aSDavid du Colombier * appropriately 14006f6463aSDavid du Colombier */ 14106f6463aSDavid du Colombier void archnand_setCLEandALE(Flash*, int cle, int ale); 14206f6463aSDavid du Colombier 14306f6463aSDavid du Colombier /* 14406f6463aSDavid du Colombier * write a sequence of bytes to the device 14506f6463aSDavid du Colombier */ 14606f6463aSDavid du Colombier void archnand_write(Flash*, void *buf, int len); 14706f6463aSDavid du Colombier 14806f6463aSDavid du Colombier /* 14906f6463aSDavid du Colombier * read a sequence of bytes from the device 15006f6463aSDavid du Colombier * if buf is 0, throw away the data 15106f6463aSDavid du Colombier */ 15206f6463aSDavid du Colombier void archnand_read(Flash*, void *buf, int len); 153