1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
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);
|