More cleaning ...
[linux-2.6/linux-mips.git] / include / linux / mtd / cfi.h
blobfa32bf254d959296afd76ce4563e683ae573afb3
2 /* Common Flash Interface structures
3 * See http://support.intel.com/design/flash/technote/index.htm
4 * $Id: cfi.h,v 1.35 2003/05/28 15:37:32 dwmw2 Exp $
5 */
7 #ifndef __MTD_CFI_H__
8 #define __MTD_CFI_H__
10 #include <linux/config.h>
11 #include <linux/version.h>
12 #include <linux/delay.h>
13 #include <linux/types.h>
14 #include <linux/interrupt.h>
15 #include <linux/mtd/flashchip.h>
16 #include <linux/mtd/cfi_endian.h>
19 * You can optimize the code size and performance by defining only
20 * the geometry(ies) available on your hardware.
21 * CFIDEV_INTERLEAVE_n, where represents the interleave (number of chips to fill the bus width)
22 * CFIDEV_BUSWIDTH_n, where n is the bus width in bytes (1, 2, 4 or 8 bytes)
24 * By default, all (known) geometries are supported.
27 #ifndef CONFIG_MTD_CFI_GEOMETRY
29 /* The default case - support all but 64-bit, which has
30 a performance penalty */
32 #define CFIDEV_INTERLEAVE_1 (1)
33 #define CFIDEV_INTERLEAVE_2 (2)
34 #define CFIDEV_INTERLEAVE_4 (4)
36 #define CFIDEV_BUSWIDTH_1 (1)
37 #define CFIDEV_BUSWIDTH_2 (2)
38 #define CFIDEV_BUSWIDTH_4 (4)
40 typedef __u32 cfi_word;
42 #else
44 /* Explicitly configured buswidth/interleave support */
46 #ifdef CONFIG_MTD_CFI_I1
47 #define CFIDEV_INTERLEAVE_1 (1)
48 #endif
49 #ifdef CONFIG_MTD_CFI_I2
50 #define CFIDEV_INTERLEAVE_2 (2)
51 #endif
52 #ifdef CONFIG_MTD_CFI_I4
53 #define CFIDEV_INTERLEAVE_4 (4)
54 #endif
55 #ifdef CONFIG_MTD_CFI_I8
56 #define CFIDEV_INTERLEAVE_8 (8)
57 #endif
59 #ifdef CONFIG_MTD_CFI_B1
60 #define CFIDEV_BUSWIDTH_1 (1)
61 #endif
62 #ifdef CONFIG_MTD_CFI_B2
63 #define CFIDEV_BUSWIDTH_2 (2)
64 #endif
65 #ifdef CONFIG_MTD_CFI_B4
66 #define CFIDEV_BUSWIDTH_4 (4)
67 #endif
68 #ifdef CONFIG_MTD_CFI_B8
69 #define CFIDEV_BUSWIDTH_8 (8)
70 #endif
72 /* pick the largest necessary */
73 #ifdef CONFIG_MTD_CFI_B8
74 typedef __u64 cfi_word;
76 /* This only works if asm/io.h is included first */
77 #ifndef __raw_readll
78 #define __raw_readll(addr) (*(volatile __u64 *)(addr))
79 #endif
80 #ifndef __raw_writell
81 #define __raw_writell(v, addr) (*(volatile __u64 *)(addr) = (v))
82 #endif
83 #define CFI_WORD_64
84 #else /* CONFIG_MTD_CFI_B8 */
85 /* All others can use 32-bits. It's probably more efficient than
86 the smaller types anyway */
87 typedef __u32 cfi_word;
88 #endif /* CONFIG_MTD_CFI_B8 */
90 #endif
93 * The following macros are used to select the code to execute:
94 * cfi_buswidth_is_*()
95 * cfi_interleave_is_*()
96 * [where * is either 1, 2, 4, or 8]
97 * Those macros should be used with 'if' statements. If only one of few
98 * geometry arrangements are selected, they expand to constants thus allowing
99 * the compiler (most of them being 0) to optimize away all the unneeded code,
100 * while still validating the syntax (which is not possible with embedded
101 * #if ... #endif constructs).
102 * The exception to this is the 64-bit versions, which need an extension
103 * to the cfi_word type, and cause compiler warnings about shifts being
104 * out of range.
107 #ifdef CFIDEV_INTERLEAVE_1
108 # ifdef CFIDEV_INTERLEAVE
109 # undef CFIDEV_INTERLEAVE
110 # define CFIDEV_INTERLEAVE (cfi->interleave)
111 # else
112 # define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_1
113 # endif
114 # define cfi_interleave_is_1() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_1)
115 #else
116 # define cfi_interleave_is_1() (0)
117 #endif
119 #ifdef CFIDEV_INTERLEAVE_2
120 # ifdef CFIDEV_INTERLEAVE
121 # undef CFIDEV_INTERLEAVE
122 # define CFIDEV_INTERLEAVE (cfi->interleave)
123 # else
124 # define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_2
125 # endif
126 # define cfi_interleave_is_2() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_2)
127 #else
128 # define cfi_interleave_is_2() (0)
129 #endif
131 #ifdef CFIDEV_INTERLEAVE_4
132 # ifdef CFIDEV_INTERLEAVE
133 # undef CFIDEV_INTERLEAVE
134 # define CFIDEV_INTERLEAVE (cfi->interleave)
135 # else
136 # define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_4
137 # endif
138 # define cfi_interleave_is_4() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_4)
139 #else
140 # define cfi_interleave_is_4() (0)
141 #endif
143 #ifdef CFIDEV_INTERLEAVE_8
144 # ifdef CFIDEV_INTERLEAVE
145 # undef CFIDEV_INTERLEAVE
146 # define CFIDEV_INTERLEAVE (cfi->interleave)
147 # else
148 # define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_8
149 # endif
150 # define cfi_interleave_is_8() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_8)
151 #else
152 # define cfi_interleave_is_8() (0)
153 #endif
155 #ifndef CFIDEV_INTERLEAVE
156 #error You must define at least one interleave to support!
157 #endif
159 #ifdef CFIDEV_BUSWIDTH_1
160 # ifdef CFIDEV_BUSWIDTH
161 # undef CFIDEV_BUSWIDTH
162 # define CFIDEV_BUSWIDTH (map->buswidth)
163 # else
164 # define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_1
165 # endif
166 # define cfi_buswidth_is_1() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_1)
167 #else
168 # define cfi_buswidth_is_1() (0)
169 #endif
171 #ifdef CFIDEV_BUSWIDTH_2
172 # ifdef CFIDEV_BUSWIDTH
173 # undef CFIDEV_BUSWIDTH
174 # define CFIDEV_BUSWIDTH (map->buswidth)
175 # else
176 # define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_2
177 # endif
178 # define cfi_buswidth_is_2() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_2)
179 #else
180 # define cfi_buswidth_is_2() (0)
181 #endif
183 #ifdef CFIDEV_BUSWIDTH_4
184 # ifdef CFIDEV_BUSWIDTH
185 # undef CFIDEV_BUSWIDTH
186 # define CFIDEV_BUSWIDTH (map->buswidth)
187 # else
188 # define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_4
189 # endif
190 # define cfi_buswidth_is_4() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_4)
191 #else
192 # define cfi_buswidth_is_4() (0)
193 #endif
195 #ifdef CFIDEV_BUSWIDTH_8
196 # ifdef CFIDEV_BUSWIDTH
197 # undef CFIDEV_BUSWIDTH
198 # define CFIDEV_BUSWIDTH (map->buswidth)
199 # else
200 # define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_8
201 # endif
202 # define cfi_buswidth_is_8() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_8)
203 #else
204 # define cfi_buswidth_is_8() (0)
205 #endif
207 #ifndef CFIDEV_BUSWIDTH
208 #error You must define at least one bus width to support!
209 #endif
211 /* NB: these values must represents the number of bytes needed to meet the
212 * device type (x8, x16, x32). Eg. a 32 bit device is 4 x 8 bytes.
213 * These numbers are used in calculations.
215 #define CFI_DEVICETYPE_X8 (8 / 8)
216 #define CFI_DEVICETYPE_X16 (16 / 8)
217 #define CFI_DEVICETYPE_X32 (32 / 8)
218 #define CFI_DEVICETYPE_X64 (64 / 8)
220 /* NB: We keep these structures in memory in HOST byteorder, except
221 * where individually noted.
224 /* Basic Query Structure */
225 struct cfi_ident {
226 __u8 qry[3];
227 __u16 P_ID;
228 __u16 P_ADR;
229 __u16 A_ID;
230 __u16 A_ADR;
231 __u8 VccMin;
232 __u8 VccMax;
233 __u8 VppMin;
234 __u8 VppMax;
235 __u8 WordWriteTimeoutTyp;
236 __u8 BufWriteTimeoutTyp;
237 __u8 BlockEraseTimeoutTyp;
238 __u8 ChipEraseTimeoutTyp;
239 __u8 WordWriteTimeoutMax;
240 __u8 BufWriteTimeoutMax;
241 __u8 BlockEraseTimeoutMax;
242 __u8 ChipEraseTimeoutMax;
243 __u8 DevSize;
244 __u16 InterfaceDesc;
245 __u16 MaxBufWriteSize;
246 __u8 NumEraseRegions;
247 __u32 EraseRegionInfo[0]; /* Not host ordered */
248 } __attribute__((packed));
250 /* Extended Query Structure for both PRI and ALT */
252 struct cfi_extquery {
253 __u8 pri[3];
254 __u8 MajorVersion;
255 __u8 MinorVersion;
256 } __attribute__((packed));
258 /* Vendor-Specific PRI for Intel/Sharp Extended Command Set (0x0001) */
260 struct cfi_pri_intelext {
261 __u8 pri[3];
262 __u8 MajorVersion;
263 __u8 MinorVersion;
264 __u32 FeatureSupport;
265 __u8 SuspendCmdSupport;
266 __u16 BlkStatusRegMask;
267 __u8 VccOptimal;
268 __u8 VppOptimal;
269 __u8 NumProtectionFields;
270 __u16 ProtRegAddr;
271 __u8 FactProtRegSize;
272 __u8 UserProtRegSize;
273 } __attribute__((packed));
275 struct cfi_pri_query {
276 __u8 NumFields;
277 __u32 ProtField[1]; /* Not host ordered */
278 } __attribute__((packed));
280 struct cfi_bri_query {
281 __u8 PageModeReadCap;
282 __u8 NumFields;
283 __u32 ConfField[1]; /* Not host ordered */
284 } __attribute__((packed));
286 #define P_ID_NONE 0
287 #define P_ID_INTEL_EXT 1
288 #define P_ID_AMD_STD 2
289 #define P_ID_INTEL_STD 3
290 #define P_ID_AMD_EXT 4
291 #define P_ID_MITSUBISHI_STD 256
292 #define P_ID_MITSUBISHI_EXT 257
293 #define P_ID_RESERVED 65535
296 #define CFI_MODE_CFI 1
297 #define CFI_MODE_JEDEC 0
299 struct cfi_private {
300 __u16 cmdset;
301 void *cmdset_priv;
302 int interleave;
303 int device_type;
304 int cfi_mode; /* Are we a JEDEC device pretending to be CFI? */
305 int addr_unlock1;
306 int addr_unlock2;
307 int fast_prog;
308 struct mtd_info *(*cmdset_setup)(struct map_info *);
309 struct cfi_ident *cfiq; /* For now only one. We insist that all devs
310 must be of the same type. */
311 int mfr, id;
312 int numchips;
313 unsigned long chipshift; /* Because they're of the same type */
314 const char *im_name; /* inter_module name for cmdset_setup */
315 struct flchip chips[0]; /* per-chip data structure for each chip */
318 #define MAX_CFI_CHIPS 8 /* Entirely arbitrary to avoid realloc() */
321 * Returns the command address according to the given geometry.
323 static inline __u32 cfi_build_cmd_addr(__u32 cmd_ofs, int interleave, int type)
325 return (cmd_ofs * type) * interleave;
329 * Transforms the CFI command for the given geometry (bus width & interleave.
331 static inline cfi_word cfi_build_cmd(u_char cmd, struct map_info *map, struct cfi_private *cfi)
333 cfi_word val = 0;
335 if (cfi_buswidth_is_1()) {
336 /* 1 x8 device */
337 val = cmd;
338 } else if (cfi_buswidth_is_2()) {
339 if (cfi_interleave_is_1()) {
340 /* 1 x16 device in x16 mode */
341 val = cpu_to_cfi16(cmd);
342 } else if (cfi_interleave_is_2()) {
343 /* 2 (x8, x16 or x32) devices in x8 mode */
344 val = cpu_to_cfi16((cmd << 8) | cmd);
346 } else if (cfi_buswidth_is_4()) {
347 if (cfi_interleave_is_1()) {
348 /* 1 x32 device in x32 mode */
349 val = cpu_to_cfi32(cmd);
350 } else if (cfi_interleave_is_2()) {
351 /* 2 x16 device in x16 mode */
352 val = cpu_to_cfi32((cmd << 16) | cmd);
353 } else if (cfi_interleave_is_4()) {
354 /* 4 (x8, x16 or x32) devices in x8 mode */
355 val = (cmd << 16) | cmd;
356 val = cpu_to_cfi32((val << 8) | val);
358 #ifdef CFI_WORD_64
359 } else if (cfi_buswidth_is_8()) {
360 if (cfi_interleave_is_1()) {
361 /* 1 x64 device in x64 mode */
362 val = cpu_to_cfi64(cmd);
363 } else if (cfi_interleave_is_2()) {
364 /* 2 x32 device in x32 mode */
365 val = cmd;
366 val = cpu_to_cfi64((val << 32) | val);
367 } else if (cfi_interleave_is_4()) {
368 /* 4 (x16, x32 or x64) devices in x16 mode */
369 val = (cmd << 16) | cmd;
370 val = cpu_to_cfi64((val << 32) | val);
371 } else if (cfi_interleave_is_8()) {
372 /* 8 (x8, x16 or x32) devices in x8 mode */
373 val = (cmd << 8) | cmd;
374 val = (val << 16) | val;
375 val = (val << 32) | val;
376 val = cpu_to_cfi64(val);
378 #endif /* CFI_WORD_64 */
380 return val;
382 #define CMD(x) cfi_build_cmd((x), map, cfi)
385 * Read a value according to the bus width.
388 static inline cfi_word cfi_read(struct map_info *map, __u32 addr)
390 if (cfi_buswidth_is_1()) {
391 return map_read8(map, addr);
392 } else if (cfi_buswidth_is_2()) {
393 return map_read16(map, addr);
394 } else if (cfi_buswidth_is_4()) {
395 return map_read32(map, addr);
396 } else if (cfi_buswidth_is_8()) {
397 return map_read64(map, addr);
398 } else {
399 return 0;
404 * Write a value according to the bus width.
407 static inline void cfi_write(struct map_info *map, cfi_word val, __u32 addr)
409 if (cfi_buswidth_is_1()) {
410 map_write8(map, val, addr);
411 } else if (cfi_buswidth_is_2()) {
412 map_write16(map, val, addr);
413 } else if (cfi_buswidth_is_4()) {
414 map_write32(map, val, addr);
415 } else if (cfi_buswidth_is_8()) {
416 map_write64(map, val, addr);
421 * Sends a CFI command to a bank of flash for the given geometry.
423 * Returns the offset in flash where the command was written.
424 * If prev_val is non-null, it will be set to the value at the command address,
425 * before the command was written.
427 static inline __u32 cfi_send_gen_cmd(u_char cmd, __u32 cmd_addr, __u32 base,
428 struct map_info *map, struct cfi_private *cfi,
429 int type, cfi_word *prev_val)
431 cfi_word val;
432 __u32 addr = base + cfi_build_cmd_addr(cmd_addr, CFIDEV_INTERLEAVE, type);
434 val = cfi_build_cmd(cmd, map, cfi);
436 if (prev_val)
437 *prev_val = cfi_read(map, addr);
439 cfi_write(map, val, addr);
441 return addr - base;
444 static inline __u8 cfi_read_query(struct map_info *map, __u32 addr)
446 if (cfi_buswidth_is_1()) {
447 return map_read8(map, addr);
448 } else if (cfi_buswidth_is_2()) {
449 return cfi16_to_cpu(map_read16(map, addr));
450 } else if (cfi_buswidth_is_4()) {
451 return cfi32_to_cpu(map_read32(map, addr));
452 } else if (cfi_buswidth_is_8()) {
453 return cfi64_to_cpu(map_read64(map, addr));
454 } else {
455 return 0;
459 static inline void cfi_udelay(int us)
461 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
462 unsigned long t = us * HZ / 1000000;
463 if (t) {
464 set_current_state(TASK_UNINTERRUPTIBLE);
465 schedule_timeout(t);
466 return;
468 #endif
469 udelay(us);
470 cond_resched();
473 static inline void cfi_spin_lock(spinlock_t *mutex)
475 spin_lock_bh(mutex);
478 static inline void cfi_spin_unlock(spinlock_t *mutex)
480 spin_unlock_bh(mutex);
483 #endif /* __MTD_CFI_H__ */