blob: b7d821d6183639ea86a21e6be2af30a0274da835 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Common Flash Interface support:
3 * AMD & Fujitsu Standard Vendor Command Set (ID 0x0002)
4 *
5 * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
6 * Copyright (C) 2004 Arcom Control Systems Ltd <linux@arcom.com>
Todd Poynor02b15e32005-06-07 00:04:39 +01007 * Copyright (C) 2005 MontaVista Software Inc. <source@mvista.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 * 2_by_8 routines added by Simon Munton
10 *
11 * 4_by_16 work by Carolyn J. Smith
12 *
Thomas Gleixner1f948b42005-11-07 11:15:37 +000013 * XIP support hooks by Vitaly Wool (based on code for Intel flash
Todd Poynor02b15e32005-06-07 00:04:39 +010014 * by Nicolas Pitre)
Thomas Gleixner1f948b42005-11-07 11:15:37 +000015 *
Christopher Moore87e92c02008-10-17 05:32:22 +020016 * 25/09/2008 Christopher Moore: TopBottom fixup for many Macronix with CFI V1.0
17 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
19 *
20 * This code is GPL
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 */
22
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include <linux/module.h>
24#include <linux/types.h>
25#include <linux/kernel.h>
26#include <linux/sched.h>
27#include <linux/init.h>
28#include <asm/io.h>
29#include <asm/byteorder.h>
30
31#include <linux/errno.h>
32#include <linux/slab.h>
33#include <linux/delay.h>
34#include <linux/interrupt.h>
Kevin Cernekeeeafe1312010-04-29 10:26:56 -070035#include <linux/reboot.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/mtd/compatmac.h>
37#include <linux/mtd/map.h>
38#include <linux/mtd/mtd.h>
39#include <linux/mtd/cfi.h>
Todd Poynor02b15e32005-06-07 00:04:39 +010040#include <linux/mtd/xip.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42#define AMD_BOOTLOC_BUG
43#define FORCE_WORD_WRITE 0
44
45#define MAX_WORD_RETRIES 3
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#define SST49LF004B 0x0060
Ryan Jackson89072ef2006-10-20 14:41:03 -070048#define SST49LF040B 0x0050
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +010049#define SST49LF008A 0x005a
Haavard Skinnemoen01655082006-08-09 11:06:07 +020050#define AT49BV6416 0x00d6
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
53static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
54static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
55static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *);
56static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *);
57static void cfi_amdstd_sync (struct mtd_info *);
58static int cfi_amdstd_suspend (struct mtd_info *);
59static void cfi_amdstd_resume (struct mtd_info *);
Kevin Cernekeeeafe1312010-04-29 10:26:56 -070060static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
62
63static void cfi_amdstd_destroy(struct mtd_info *);
64
65struct mtd_info *cfi_cmdset_0002(struct map_info *, int);
66static struct mtd_info *cfi_amdstd_setup (struct mtd_info *);
67
68static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
69static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
70#include "fwh_lock.h"
71
Adrian Hunter69423d92008-12-10 13:37:21 +000072static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
73static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
Haavard Skinnemoen01655082006-08-09 11:06:07 +020074
Linus Torvalds1da177e2005-04-16 15:20:36 -070075static struct mtd_chip_driver cfi_amdstd_chipdrv = {
76 .probe = NULL, /* Not usable directly */
77 .destroy = cfi_amdstd_destroy,
78 .name = "cfi_cmdset_0002",
79 .module = THIS_MODULE
80};
81
82
83/* #define DEBUG_CFI_FEATURES */
84
85
86#ifdef DEBUG_CFI_FEATURES
87static void cfi_tell_features(struct cfi_pri_amdstd *extp)
88{
89 const char* erase_suspend[3] = {
90 "Not supported", "Read only", "Read/write"
91 };
92 const char* top_bottom[6] = {
93 "No WP", "8x8KiB sectors at top & bottom, no WP",
94 "Bottom boot", "Top boot",
95 "Uniform, Bottom WP", "Uniform, Top WP"
96 };
97
98 printk(" Silicon revision: %d\n", extp->SiliconRevision >> 1);
Thomas Gleixner1f948b42005-11-07 11:15:37 +000099 printk(" Address sensitive unlock: %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 (extp->SiliconRevision & 1) ? "Not required" : "Required");
101
102 if (extp->EraseSuspend < ARRAY_SIZE(erase_suspend))
103 printk(" Erase Suspend: %s\n", erase_suspend[extp->EraseSuspend]);
104 else
105 printk(" Erase Suspend: Unknown value %d\n", extp->EraseSuspend);
106
107 if (extp->BlkProt == 0)
108 printk(" Block protection: Not supported\n");
109 else
110 printk(" Block protection: %d sectors per group\n", extp->BlkProt);
111
112
113 printk(" Temporary block unprotect: %s\n",
114 extp->TmpBlkUnprotect ? "Supported" : "Not supported");
115 printk(" Block protect/unprotect scheme: %d\n", extp->BlkProtUnprot);
116 printk(" Number of simultaneous operations: %d\n", extp->SimultaneousOps);
117 printk(" Burst mode: %s\n",
118 extp->BurstMode ? "Supported" : "Not supported");
119 if (extp->PageMode == 0)
120 printk(" Page mode: Not supported\n");
121 else
122 printk(" Page mode: %d word page\n", extp->PageMode << 2);
123
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000124 printk(" Vpp Supply Minimum Program/Erase Voltage: %d.%d V\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 extp->VppMin >> 4, extp->VppMin & 0xf);
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000126 printk(" Vpp Supply Maximum Program/Erase Voltage: %d.%d V\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 extp->VppMax >> 4, extp->VppMax & 0xf);
128
129 if (extp->TopBottom < ARRAY_SIZE(top_bottom))
130 printk(" Top/Bottom Boot Block: %s\n", top_bottom[extp->TopBottom]);
131 else
132 printk(" Top/Bottom Boot Block: Unknown value %d\n", extp->TopBottom);
133}
134#endif
135
136#ifdef AMD_BOOTLOC_BUG
137/* Wheee. Bring me the head of someone at AMD. */
138static void fixup_amd_bootblock(struct mtd_info *mtd, void* param)
139{
140 struct map_info *map = mtd->priv;
141 struct cfi_private *cfi = map->fldrv_priv;
142 struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
143 __u8 major = extp->MajorVersion;
144 __u8 minor = extp->MinorVersion;
145
146 if (((major << 8) | minor) < 0x3131) {
147 /* CFI version 1.0 => don't trust bootloc */
Christopher Moore87e92c02008-10-17 05:32:22 +0200148
149 DEBUG(MTD_DEBUG_LEVEL1,
150 "%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n",
151 map->name, cfi->mfr, cfi->id);
152
153 /* AFAICS all 29LV400 with a bottom boot block have a device ID
154 * of 0x22BA in 16-bit mode and 0xBA in 8-bit mode.
155 * These were badly detected as they have the 0x80 bit set
156 * so treat them as a special case.
157 */
158 if (((cfi->id == 0xBA) || (cfi->id == 0x22BA)) &&
159
160 /* Macronix added CFI to their 2nd generation
161 * MX29LV400C B/T but AFAICS no other 29LV400 (AMD,
162 * Fujitsu, Spansion, EON, ESI and older Macronix)
163 * has CFI.
164 *
165 * Therefore also check the manufacturer.
166 * This reduces the risk of false detection due to
167 * the 8-bit device ID.
168 */
Guillaume LECERFf3e69c62009-12-15 23:01:06 +0100169 (cfi->mfr == CFI_MFR_MACRONIX)) {
Christopher Moore87e92c02008-10-17 05:32:22 +0200170 DEBUG(MTD_DEBUG_LEVEL1,
171 "%s: Macronix MX29LV400C with bottom boot block"
172 " detected\n", map->name);
173 extp->TopBottom = 2; /* bottom boot */
174 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 if (cfi->id & 0x80) {
176 printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id);
177 extp->TopBottom = 3; /* top boot */
178 } else {
179 extp->TopBottom = 2; /* bottom boot */
180 }
Christopher Moore87e92c02008-10-17 05:32:22 +0200181
182 DEBUG(MTD_DEBUG_LEVEL1,
183 "%s: AMD CFI PRI V%c.%c has no boot block field;"
184 " deduced %s from Device ID\n", map->name, major, minor,
185 extp->TopBottom == 2 ? "bottom" : "top");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 }
187}
188#endif
189
190static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
191{
192 struct map_info *map = mtd->priv;
193 struct cfi_private *cfi = map->fldrv_priv;
194 if (cfi->cfiq->BufWriteTimeoutTyp) {
195 DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" );
196 mtd->write = cfi_amdstd_write_buffers;
197 }
198}
199
Haavard Skinnemoen5b0c5c22006-08-09 10:54:44 +0200200/* Atmel chips don't use the same PRI format as AMD chips */
201static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
202{
203 struct map_info *map = mtd->priv;
204 struct cfi_private *cfi = map->fldrv_priv;
205 struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
206 struct cfi_pri_atmel atmel_pri;
207
208 memcpy(&atmel_pri, extp, sizeof(atmel_pri));
HÃ¥vard Skinnemoende591da2006-09-15 17:19:31 +0200209 memset((char *)extp + 5, 0, sizeof(*extp) - 5);
Haavard Skinnemoen5b0c5c22006-08-09 10:54:44 +0200210
211 if (atmel_pri.Features & 0x02)
212 extp->EraseSuspend = 2;
213
Haavard Skinnemoenbe8f78b2008-09-30 13:55:33 +0200214 /* Some chips got it backwards... */
215 if (cfi->id == AT49BV6416) {
216 if (atmel_pri.BottomBoot)
217 extp->TopBottom = 3;
218 else
219 extp->TopBottom = 2;
220 } else {
221 if (atmel_pri.BottomBoot)
222 extp->TopBottom = 2;
223 else
224 extp->TopBottom = 3;
225 }
Hans-Christian Egtvedtd10a39d2007-10-30 16:33:07 +0100226
227 /* burst write mode not supported */
228 cfi->cfiq->BufWriteTimeoutTyp = 0;
229 cfi->cfiq->BufWriteTimeoutMax = 0;
Haavard Skinnemoen5b0c5c22006-08-09 10:54:44 +0200230}
231
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232static void fixup_use_secsi(struct mtd_info *mtd, void *param)
233{
234 /* Setup for chips with a secsi area */
235 mtd->read_user_prot_reg = cfi_amdstd_secsi_read;
236 mtd->read_fact_prot_reg = cfi_amdstd_secsi_read;
237}
238
239static void fixup_use_erase_chip(struct mtd_info *mtd, void *param)
240{
241 struct map_info *map = mtd->priv;
242 struct cfi_private *cfi = map->fldrv_priv;
243 if ((cfi->cfiq->NumEraseRegions == 1) &&
244 ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0)) {
245 mtd->erase = cfi_amdstd_erase_chip;
246 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000247
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248}
249
Haavard Skinnemoen01655082006-08-09 11:06:07 +0200250/*
251 * Some Atmel chips (e.g. the AT49BV6416) power-up with all sectors
252 * locked by default.
253 */
254static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param)
255{
256 mtd->lock = cfi_atmel_lock;
257 mtd->unlock = cfi_atmel_unlock;
Justin Treone619a752008-01-30 10:25:49 -0800258 mtd->flags |= MTD_POWERUP_LOCK;
Haavard Skinnemoen01655082006-08-09 11:06:07 +0200259}
260
Guillaume LECERF83dcd3b2010-04-24 17:58:22 +0200261static void fixup_old_sst_eraseregion(struct mtd_info *mtd)
262{
263 struct map_info *map = mtd->priv;
264 struct cfi_private *cfi = map->fldrv_priv;
265
266 /*
267 * These flashes report two seperate eraseblock regions based on the
268 * sector_erase-size and block_erase-size, although they both operate on the
269 * same memory. This is not allowed according to CFI, so we just pick the
270 * sector_erase-size.
271 */
272 cfi->cfiq->NumEraseRegions = 1;
273}
274
275static void fixup_sst39vf(struct mtd_info *mtd, void *param)
276{
277 struct map_info *map = mtd->priv;
278 struct cfi_private *cfi = map->fldrv_priv;
279
280 fixup_old_sst_eraseregion(mtd);
281
282 cfi->addr_unlock1 = 0x5555;
283 cfi->addr_unlock2 = 0x2AAA;
284}
285
Trent Piepho70b07252008-03-30 21:19:30 -0700286static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
287{
288 struct map_info *map = mtd->priv;
289 struct cfi_private *cfi = map->fldrv_priv;
290
291 if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) {
292 cfi->cfiq->EraseRegionInfo[0] |= 0x0040;
293 pr_warning("%s: Bad S29GL064N CFI data, adjust from 64 to 128 sectors\n", mtd->name);
294 }
295}
296
297static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param)
298{
299 struct map_info *map = mtd->priv;
300 struct cfi_private *cfi = map->fldrv_priv;
301
302 if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) {
303 cfi->cfiq->EraseRegionInfo[1] &= ~0x0040;
304 pr_warning("%s: Bad S29GL032N CFI data, adjust from 127 to 63 sectors\n", mtd->name);
305 }
306}
307
Guillaume LECERF83dcd3b2010-04-24 17:58:22 +0200308/* Used to fix CFI-Tables of chips without Extended Query Tables */
309static struct cfi_fixup cfi_nopri_fixup_table[] = {
310 { CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, // SST39VF1602
311 { CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, // SST39VF1601
312 { CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, // SST39VF3202
313 { CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, // SST39VF3201
314 { 0, 0, NULL, NULL }
315};
316
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317static struct cfi_fixup cfi_fixup_table[] = {
Hans-Christian Egtvedtd10a39d2007-10-30 16:33:07 +0100318 { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319#ifdef AMD_BOOTLOC_BUG
320 { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
Guillaume LECERFf3e69c62009-12-15 23:01:06 +0100321 { CFI_MFR_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock, NULL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322#endif
323 { CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, },
324 { CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, },
325 { CFI_MFR_AMD, 0x0055, fixup_use_secsi, NULL, },
326 { CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, },
327 { CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, },
328 { CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, },
Trent Piepho70b07252008-03-30 21:19:30 -0700329 { CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors, NULL, },
330 { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
331 { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
332 { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333#if !FORCE_WORD_WRITE
334 { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
335#endif
336 { 0, 0, NULL, NULL }
337};
338static struct cfi_fixup jedec_fixup_table[] = {
Guillaume LECERFf3e69c62009-12-15 23:01:06 +0100339 { CFI_MFR_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },
340 { CFI_MFR_SST, SST49LF040B, fixup_use_fwh_lock, NULL, },
341 { CFI_MFR_SST, SST49LF008A, fixup_use_fwh_lock, NULL, },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 { 0, 0, NULL, NULL }
343};
344
345static struct cfi_fixup fixup_table[] = {
346 /* The CFI vendor ids and the JEDEC vendor IDs appear
347 * to be common. It is like the devices id's are as
348 * well. This table is to pick all cases where
349 * we know that is the case.
350 */
351 { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL },
Haavard Skinnemoen01655082006-08-09 11:06:07 +0200352 { CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 { 0, 0, NULL, NULL }
354};
355
356
Wolfgang Grandeggerfefae482009-01-08 19:21:27 +0100357static void cfi_fixup_major_minor(struct cfi_private *cfi,
358 struct cfi_pri_amdstd *extp)
359{
360 if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e &&
361 extp->MajorVersion == '0')
362 extp->MajorVersion = '1';
363}
364
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
366{
367 struct cfi_private *cfi = map->fldrv_priv;
368 struct mtd_info *mtd;
369 int i;
370
Burman Yan95b93a02006-11-15 21:10:29 +0200371 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 if (!mtd) {
373 printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
374 return NULL;
375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 mtd->priv = map;
377 mtd->type = MTD_NORFLASH;
378
379 /* Fill in the default mtd operations */
380 mtd->erase = cfi_amdstd_erase_varsize;
381 mtd->write = cfi_amdstd_write_words;
382 mtd->read = cfi_amdstd_read;
383 mtd->sync = cfi_amdstd_sync;
384 mtd->suspend = cfi_amdstd_suspend;
385 mtd->resume = cfi_amdstd_resume;
386 mtd->flags = MTD_CAP_NORFLASH;
387 mtd->name = map->name;
Artem B. Bityutskiy783ed812006-06-14 19:53:44 +0400388 mtd->writesize = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
Kevin Cernekeeeafe1312010-04-29 10:26:56 -0700390 mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot;
391
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 if (cfi->cfi_mode==CFI_MODE_CFI){
393 unsigned char bootloc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
395 struct cfi_pri_amdstd *extp;
396
397 extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu");
Guillaume LECERF564b8492010-04-24 17:58:17 +0200398 if (extp) {
399 /*
400 * It's a real CFI chip, not one for which the probe
401 * routine faked a CFI structure.
402 */
403 cfi_fixup_major_minor(cfi, extp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
Guillaume LECERF564b8492010-04-24 17:58:17 +0200405 if (extp->MajorVersion != '1' ||
406 (extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
407 printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
408 "version %c.%c.\n", extp->MajorVersion,
409 extp->MinorVersion);
410 kfree(extp);
411 kfree(mtd);
412 return NULL;
413 }
Wolfgang Grandeggerfefae482009-01-08 19:21:27 +0100414
Guillaume LECERF564b8492010-04-24 17:58:17 +0200415 /* Install our own private info structure */
416 cfi->cmdset_priv = extp;
Todd Poynord88f9772005-07-20 22:01:17 +0100417
Guillaume LECERF564b8492010-04-24 17:58:17 +0200418 /* Apply cfi device specific fixups */
419 cfi_fixup(mtd, cfi_fixup_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
421#ifdef DEBUG_CFI_FEATURES
Guillaume LECERF564b8492010-04-24 17:58:17 +0200422 /* Tell the user about it in lots of lovely detail */
423 cfi_tell_features(extp);
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000424#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
Guillaume LECERF564b8492010-04-24 17:58:17 +0200426 bootloc = extp->TopBottom;
David Woodhouse412da2f2010-05-14 01:35:54 +0100427 if ((bootloc < 2) || (bootloc > 5)) {
428 printk(KERN_WARNING "%s: CFI contains unrecognised boot "
429 "bank location (%d). Assuming bottom.\n",
430 bootloc, map->name);
Guillaume LECERF564b8492010-04-24 17:58:17 +0200431 bootloc = 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 }
Guillaume LECERF564b8492010-04-24 17:58:17 +0200433
434 if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) {
David Woodhouse412da2f2010-05-14 01:35:54 +0100435 printk(KERN_WARNING "%s: Swapping erase regions for top-boot CFI table.\n", map->name);
Guillaume LECERF564b8492010-04-24 17:58:17 +0200436
437 for (i=0; i<cfi->cfiq->NumEraseRegions / 2; i++) {
438 int j = (cfi->cfiq->NumEraseRegions-1)-i;
439 __u32 swap;
440
441 swap = cfi->cfiq->EraseRegionInfo[i];
442 cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j];
443 cfi->cfiq->EraseRegionInfo[j] = swap;
444 }
445 }
446 /* Set the default CFI lock/unlock addresses */
447 cfi->addr_unlock1 = 0x555;
448 cfi->addr_unlock2 = 0x2aa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 }
Guillaume LECERF83dcd3b2010-04-24 17:58:22 +0200450 cfi_fixup(mtd, cfi_nopri_fixup_table);
Guillaume LECERF564b8492010-04-24 17:58:17 +0200451
452 if (!cfi->addr_unlock1 || !cfi->addr_unlock2) {
453 kfree(mtd);
454 return NULL;
455 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
457 } /* CFI mode */
458 else if (cfi->cfi_mode == CFI_MODE_JEDEC) {
459 /* Apply jedec specific fixups */
460 cfi_fixup(mtd, jedec_fixup_table);
461 }
462 /* Apply generic fixups */
463 cfi_fixup(mtd, fixup_table);
464
465 for (i=0; i< cfi->numchips; i++) {
466 cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
467 cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
468 cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
Vijay Sampath83d48092007-03-06 02:39:44 -0800469 cfi->chips[i].ref_point_counter = 0;
470 init_waitqueue_head(&(cfi->chips[i].wq));
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000471 }
472
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 map->fldrv = &cfi_amdstd_chipdrv;
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000474
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 return cfi_amdstd_setup(mtd);
476}
David Woodhouse83ea4ef2006-05-08 22:58:25 +0100477EXPORT_SYMBOL_GPL(cfi_cmdset_0002);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
479static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
480{
481 struct map_info *map = mtd->priv;
482 struct cfi_private *cfi = map->fldrv_priv;
483 unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
484 unsigned long offset = 0;
485 int i,j;
486
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000487 printk(KERN_NOTICE "number of %s chips: %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 (cfi->cfi_mode == CFI_MODE_CFI)?"CFI":"JEDEC",cfi->numchips);
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000489 /* Select the correct geometry setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 mtd->size = devsize * cfi->numchips;
491
492 mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
493 mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
494 * mtd->numeraseregions, GFP_KERNEL);
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000495 if (!mtd->eraseregions) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n");
497 goto setup_err;
498 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
501 unsigned long ernum, ersize;
502 ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
503 ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000504
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 if (mtd->erasesize < ersize) {
506 mtd->erasesize = ersize;
507 }
508 for (j=0; j<cfi->numchips; j++) {
509 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
510 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
511 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
512 }
513 offset += (ersize * ernum);
514 }
515 if (offset != devsize) {
516 /* Argh */
517 printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
518 goto setup_err;
519 }
520#if 0
521 // debug
522 for (i=0; i<mtd->numeraseregions;i++){
523 printk("%d: offset=0x%x,size=0x%x,blocks=%d\n",
524 i,mtd->eraseregions[i].offset,
525 mtd->eraseregions[i].erasesize,
526 mtd->eraseregions[i].numblocks);
527 }
528#endif
529
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 __module_get(THIS_MODULE);
Kevin Cernekeeeafe1312010-04-29 10:26:56 -0700531 register_reboot_notifier(&mtd->reboot_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 return mtd;
533
534 setup_err:
Jiri Slaby17fabf12010-01-10 10:01:19 +0100535 kfree(mtd->eraseregions);
536 kfree(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 kfree(cfi->cmdset_priv);
538 kfree(cfi->cfiq);
539 return NULL;
540}
541
542/*
543 * Return true if the chip is ready.
544 *
545 * Ready is one of: read mode, query mode, erase-suspend-read mode (in any
546 * non-suspended sector) and is indicated by no toggle bits toggling.
547 *
548 * Note that anything more complicated than checking if no bits are toggling
549 * (including checking DQ5 for an error status) is tricky to get working
550 * correctly and is therefore not done (particulary with interleaved chips
551 * as each chip must be checked independantly of the others).
552 */
Todd Poynor02b15e32005-06-07 00:04:39 +0100553static int __xipram chip_ready(struct map_info *map, unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554{
555 map_word d, t;
556
557 d = map_read(map, addr);
558 t = map_read(map, addr);
559
560 return map_word_equal(map, d, t);
561}
562
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +0100563/*
564 * Return true if the chip is ready and has the correct value.
565 *
566 * Ready is one of: read mode, query mode, erase-suspend-read mode (in any
567 * non-suspended sector) and it is indicated by no bits toggling.
568 *
569 * Error are indicated by toggling bits or bits held with the wrong value,
570 * or with bits toggling.
571 *
572 * Note that anything more complicated than checking if no bits are toggling
573 * (including checking DQ5 for an error status) is tricky to get working
574 * correctly and is therefore not done (particulary with interleaved chips
575 * as each chip must be checked independantly of the others).
576 *
577 */
Todd Poynor02b15e32005-06-07 00:04:39 +0100578static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected)
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +0100579{
580 map_word oldd, curd;
581
582 oldd = map_read(map, addr);
583 curd = map_read(map, addr);
584
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000585 return map_word_equal(map, oldd, curd) &&
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +0100586 map_word_equal(map, curd, expected);
587}
588
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
590{
591 DECLARE_WAITQUEUE(wait, current);
592 struct cfi_private *cfi = map->fldrv_priv;
593 unsigned long timeo;
594 struct cfi_pri_amdstd *cfip = (struct cfi_pri_amdstd *)cfi->cmdset_priv;
595
596 resettime:
597 timeo = jiffies + HZ;
598 retry:
599 switch (chip->state) {
600
601 case FL_STATUS:
602 for (;;) {
603 if (chip_ready(map, adr))
604 break;
605
606 if (time_after(jiffies, timeo)) {
607 printk(KERN_ERR "Waiting for chip to be ready timed out.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 return -EIO;
609 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200610 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 cfi_udelay(1);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200612 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 /* Someone else might have been playing with it. */
614 goto retry;
615 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000616
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 case FL_READY:
618 case FL_CFI_QUERY:
619 case FL_JEDEC_QUERY:
620 return 0;
621
622 case FL_ERASING:
Joakim Tjernlund2695eab2009-11-19 12:01:58 +0100623 if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) ||
624 !(mode == FL_READY || mode == FL_POINT ||
625 (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 goto sleep;
627
628 /* We could check to see if we're trying to access the sector
629 * that is currently being erased. However, no user will try
630 * anything like that so we just wait for the timeout. */
631
632 /* Erase suspend */
633 /* It's harmless to issue the Erase-Suspend and Erase-Resume
634 * commands when the erase algorithm isn't in progress. */
635 map_write(map, CMD(0xB0), chip->in_progress_block_addr);
636 chip->oldstate = FL_ERASING;
637 chip->state = FL_ERASE_SUSPENDING;
638 chip->erase_suspended = 1;
639 for (;;) {
640 if (chip_ready(map, adr))
641 break;
642
643 if (time_after(jiffies, timeo)) {
644 /* Should have suspended the erase by now.
645 * Send an Erase-Resume command as either
646 * there was an error (so leave the erase
647 * routine to recover from it) or we trying to
648 * use the erase-in-progress sector. */
649 map_write(map, CMD(0x30), chip->in_progress_block_addr);
650 chip->state = FL_ERASING;
651 chip->oldstate = FL_READY;
652 printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
653 return -EIO;
654 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000655
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200656 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 cfi_udelay(1);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200658 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 /* Nobody will touch it while it's in state FL_ERASE_SUSPENDING.
660 So we can just loop here. */
661 }
662 chip->state = FL_READY;
663 return 0;
664
Todd Poynor02b15e32005-06-07 00:04:39 +0100665 case FL_XIP_WHILE_ERASING:
666 if (mode != FL_READY && mode != FL_POINT &&
667 (!cfip || !(cfip->EraseSuspend&2)))
668 goto sleep;
669 chip->oldstate = chip->state;
670 chip->state = FL_READY;
671 return 0;
672
Kevin Cernekeeeafe1312010-04-29 10:26:56 -0700673 case FL_SHUTDOWN:
674 /* The machine is rebooting */
675 return -EIO;
676
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 case FL_POINT:
678 /* Only if there's no operation suspended... */
679 if (mode == FL_READY && chip->oldstate == FL_READY)
680 return 0;
681
682 default:
683 sleep:
684 set_current_state(TASK_UNINTERRUPTIBLE);
685 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200686 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 schedule();
688 remove_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200689 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 goto resettime;
691 }
692}
693
694
695static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr)
696{
697 struct cfi_private *cfi = map->fldrv_priv;
698
699 switch(chip->oldstate) {
700 case FL_ERASING:
701 chip->state = chip->oldstate;
702 map_write(map, CMD(0x30), chip->in_progress_block_addr);
703 chip->oldstate = FL_READY;
704 chip->state = FL_ERASING;
705 break;
706
Todd Poynor02b15e32005-06-07 00:04:39 +0100707 case FL_XIP_WHILE_ERASING:
708 chip->state = chip->oldstate;
709 chip->oldstate = FL_READY;
710 break;
711
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 case FL_READY:
713 case FL_STATUS:
714 /* We should really make set_vpp() count, rather than doing this */
715 DISABLE_VPP(map);
716 break;
717 default:
718 printk(KERN_ERR "MTD: put_chip() called with oldstate %d!!\n", chip->oldstate);
719 }
720 wake_up(&chip->wq);
721}
722
Todd Poynor02b15e32005-06-07 00:04:39 +0100723#ifdef CONFIG_MTD_XIP
724
725/*
726 * No interrupt what so ever can be serviced while the flash isn't in array
727 * mode. This is ensured by the xip_disable() and xip_enable() functions
728 * enclosing any code path where the flash is known not to be in array mode.
729 * And within a XIP disabled code path, only functions marked with __xipram
730 * may be called and nothing else (it's a good thing to inspect generated
731 * assembly to make sure inline functions were actually inlined and that gcc
732 * didn't emit calls to its own support functions). Also configuring MTD CFI
733 * support to a single buswidth and a single interleave is also recommended.
734 */
Thomas Gleixnerf8eb3212005-07-05 01:03:06 +0200735
Todd Poynor02b15e32005-06-07 00:04:39 +0100736static void xip_disable(struct map_info *map, struct flchip *chip,
737 unsigned long adr)
738{
739 /* TODO: chips with no XIP use should ignore and return */
740 (void) map_read(map, adr); /* ensure mmu mapping is up to date */
741 local_irq_disable();
742}
743
744static void __xipram xip_enable(struct map_info *map, struct flchip *chip,
745 unsigned long adr)
746{
747 struct cfi_private *cfi = map->fldrv_priv;
748
749 if (chip->state != FL_POINT && chip->state != FL_READY) {
750 map_write(map, CMD(0xf0), adr);
751 chip->state = FL_READY;
752 }
753 (void) map_read(map, adr);
Thomas Gleixner97f927a2005-07-07 16:50:16 +0200754 xip_iprefetch();
Todd Poynor02b15e32005-06-07 00:04:39 +0100755 local_irq_enable();
756}
757
758/*
759 * When a delay is required for the flash operation to complete, the
760 * xip_udelay() function is polling for both the given timeout and pending
761 * (but still masked) hardware interrupts. Whenever there is an interrupt
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000762 * pending then the flash erase operation is suspended, array mode restored
Todd Poynor02b15e32005-06-07 00:04:39 +0100763 * and interrupts unmasked. Task scheduling might also happen at that
764 * point. The CPU eventually returns from the interrupt or the call to
765 * schedule() and the suspended flash operation is resumed for the remaining
766 * of the delay period.
767 *
768 * Warning: this function _will_ fool interrupt latency tracing tools.
769 */
770
771static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
772 unsigned long adr, int usec)
773{
774 struct cfi_private *cfi = map->fldrv_priv;
775 struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
776 map_word status, OK = CMD(0x80);
777 unsigned long suspended, start = xip_currtime();
778 flstate_t oldstate;
779
780 do {
781 cpu_relax();
782 if (xip_irqpending() && extp &&
783 ((chip->state == FL_ERASING && (extp->EraseSuspend & 2))) &&
784 (cfi_interleave_is_1(cfi) || chip->oldstate == FL_READY)) {
785 /*
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000786 * Let's suspend the erase operation when supported.
787 * Note that we currently don't try to suspend
788 * interleaved chips if there is already another
Todd Poynor02b15e32005-06-07 00:04:39 +0100789 * operation suspended (imagine what happens
790 * when one chip was already done with the current
791 * operation while another chip suspended it, then
792 * we resume the whole thing at once). Yes, it
793 * can happen!
794 */
795 map_write(map, CMD(0xb0), adr);
796 usec -= xip_elapsed_since(start);
797 suspended = xip_currtime();
798 do {
799 if (xip_elapsed_since(suspended) > 100000) {
800 /*
801 * The chip doesn't want to suspend
802 * after waiting for 100 msecs.
803 * This is a critical error but there
804 * is not much we can do here.
805 */
806 return;
807 }
808 status = map_read(map, adr);
809 } while (!map_word_andequal(map, status, OK, OK));
810
811 /* Suspend succeeded */
812 oldstate = chip->state;
813 if (!map_word_bitsset(map, status, CMD(0x40)))
814 break;
815 chip->state = FL_XIP_WHILE_ERASING;
816 chip->erase_suspended = 1;
817 map_write(map, CMD(0xf0), adr);
818 (void) map_read(map, adr);
Paulius Zaleckasca5c23c2008-02-27 01:42:39 +0200819 xip_iprefetch();
Todd Poynor02b15e32005-06-07 00:04:39 +0100820 local_irq_enable();
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200821 mutex_unlock(&chip->mutex);
Paulius Zaleckasca5c23c2008-02-27 01:42:39 +0200822 xip_iprefetch();
Todd Poynor02b15e32005-06-07 00:04:39 +0100823 cond_resched();
824
825 /*
826 * We're back. However someone else might have
827 * decided to go write to the chip if we are in
828 * a suspended erase state. If so let's wait
829 * until it's done.
830 */
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200831 mutex_lock(&chip->mutex);
Todd Poynor02b15e32005-06-07 00:04:39 +0100832 while (chip->state != FL_XIP_WHILE_ERASING) {
833 DECLARE_WAITQUEUE(wait, current);
834 set_current_state(TASK_UNINTERRUPTIBLE);
835 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200836 mutex_unlock(&chip->mutex);
Todd Poynor02b15e32005-06-07 00:04:39 +0100837 schedule();
838 remove_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200839 mutex_lock(&chip->mutex);
Todd Poynor02b15e32005-06-07 00:04:39 +0100840 }
841 /* Disallow XIP again */
842 local_irq_disable();
843
844 /* Resume the write or erase operation */
845 map_write(map, CMD(0x30), adr);
846 chip->state = oldstate;
847 start = xip_currtime();
848 } else if (usec >= 1000000/HZ) {
849 /*
850 * Try to save on CPU power when waiting delay
851 * is at least a system timer tick period.
852 * No need to be extremely accurate here.
853 */
854 xip_cpu_idle();
855 }
856 status = map_read(map, adr);
857 } while (!map_word_andequal(map, status, OK, OK)
858 && xip_elapsed_since(start) < usec);
859}
860
861#define UDELAY(map, chip, adr, usec) xip_udelay(map, chip, adr, usec)
862
863/*
864 * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while
865 * the flash is actively programming or erasing since we have to poll for
866 * the operation to complete anyway. We can't do that in a generic way with
867 * a XIP setup so do it before the actual flash operation in this case
868 * and stub it out from INVALIDATE_CACHE_UDELAY.
869 */
870#define XIP_INVAL_CACHED_RANGE(map, from, size) \
871 INVALIDATE_CACHED_RANGE(map, from, size)
872
873#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \
874 UDELAY(map, chip, adr, usec)
875
876/*
877 * Extra notes:
878 *
879 * Activating this XIP support changes the way the code works a bit. For
880 * example the code to suspend the current process when concurrent access
881 * happens is never executed because xip_udelay() will always return with the
882 * same chip state as it was entered with. This is why there is no care for
883 * the presence of add_wait_queue() or schedule() calls from within a couple
884 * xip_disable()'d areas of code, like in do_erase_oneblock for example.
885 * The queueing and scheduling are always happening within xip_udelay().
886 *
887 * Similarly, get_chip() and put_chip() just happen to always be executed
888 * with chip->state set to FL_READY (or FL_XIP_WHILE_*) where flash state
889 * is in array mode, therefore never executing many cases therein and not
890 * causing any problem with XIP.
891 */
892
893#else
894
895#define xip_disable(map, chip, adr)
896#define xip_enable(map, chip, adr)
897#define XIP_INVAL_CACHED_RANGE(x...)
898
899#define UDELAY(map, chip, adr, usec) \
900do { \
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200901 mutex_unlock(&chip->mutex); \
Todd Poynor02b15e32005-06-07 00:04:39 +0100902 cfi_udelay(usec); \
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200903 mutex_lock(&chip->mutex); \
Todd Poynor02b15e32005-06-07 00:04:39 +0100904} while (0)
905
906#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \
907do { \
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200908 mutex_unlock(&chip->mutex); \
Todd Poynor02b15e32005-06-07 00:04:39 +0100909 INVALIDATE_CACHED_RANGE(map, adr, len); \
910 cfi_udelay(usec); \
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200911 mutex_lock(&chip->mutex); \
Todd Poynor02b15e32005-06-07 00:04:39 +0100912} while (0)
913
914#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915
916static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
917{
918 unsigned long cmd_addr;
919 struct cfi_private *cfi = map->fldrv_priv;
920 int ret;
921
922 adr += chip->start;
923
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000924 /* Ensure cmd read/writes are aligned. */
925 cmd_addr = adr & ~(map_bankwidth(map)-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200927 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 ret = get_chip(map, chip, cmd_addr, FL_READY);
929 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200930 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 return ret;
932 }
933
934 if (chip->state != FL_POINT && chip->state != FL_READY) {
935 map_write(map, CMD(0xf0), cmd_addr);
936 chip->state = FL_READY;
937 }
938
939 map_copy_from(map, buf, adr, len);
940
941 put_chip(map, chip, cmd_addr);
942
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200943 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 return 0;
945}
946
947
948static int cfi_amdstd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
949{
950 struct map_info *map = mtd->priv;
951 struct cfi_private *cfi = map->fldrv_priv;
952 unsigned long ofs;
953 int chipnum;
954 int ret = 0;
955
956 /* ofs: offset within the first chip that the first read should start */
957
958 chipnum = (from >> cfi->chipshift);
959 ofs = from - (chipnum << cfi->chipshift);
960
961
962 *retlen = 0;
963
964 while (len) {
965 unsigned long thislen;
966
967 if (chipnum >= cfi->numchips)
968 break;
969
970 if ((len + ofs -1) >> cfi->chipshift)
971 thislen = (1<<cfi->chipshift) - ofs;
972 else
973 thislen = len;
974
975 ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
976 if (ret)
977 break;
978
979 *retlen += thislen;
980 len -= thislen;
981 buf += thislen;
982
983 ofs = 0;
984 chipnum++;
985 }
986 return ret;
987}
988
989
990static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
991{
992 DECLARE_WAITQUEUE(wait, current);
993 unsigned long timeo = jiffies + HZ;
994 struct cfi_private *cfi = map->fldrv_priv;
995
996 retry:
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200997 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998
999 if (chip->state != FL_READY){
1000#if 0
1001 printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state);
1002#endif
1003 set_current_state(TASK_UNINTERRUPTIBLE);
1004 add_wait_queue(&chip->wq, &wait);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001005
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001006 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007
1008 schedule();
1009 remove_wait_queue(&chip->wq, &wait);
1010#if 0
1011 if(signal_pending(current))
1012 return -EINTR;
1013#endif
1014 timeo = jiffies + HZ;
1015
1016 goto retry;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001017 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
1019 adr += chip->start;
1020
1021 chip->state = FL_READY;
1022
1023 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1024 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
1025 cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001026
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 map_copy_from(map, buf, adr, len);
1028
1029 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1030 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
1031 cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1032 cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 wake_up(&chip->wq);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001035 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
1037 return 0;
1038}
1039
1040static int cfi_amdstd_secsi_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
1041{
1042 struct map_info *map = mtd->priv;
1043 struct cfi_private *cfi = map->fldrv_priv;
1044 unsigned long ofs;
1045 int chipnum;
1046 int ret = 0;
1047
1048
1049 /* ofs: offset within the first chip that the first read should start */
1050
1051 /* 8 secsi bytes per chip */
1052 chipnum=from>>3;
1053 ofs=from & 7;
1054
1055
1056 *retlen = 0;
1057
1058 while (len) {
1059 unsigned long thislen;
1060
1061 if (chipnum >= cfi->numchips)
1062 break;
1063
1064 if ((len + ofs -1) >> 3)
1065 thislen = (1<<3) - ofs;
1066 else
1067 thislen = len;
1068
1069 ret = do_read_secsi_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
1070 if (ret)
1071 break;
1072
1073 *retlen += thislen;
1074 len -= thislen;
1075 buf += thislen;
1076
1077 ofs = 0;
1078 chipnum++;
1079 }
1080 return ret;
1081}
1082
1083
Todd Poynor02b15e32005-06-07 00:04:39 +01001084static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085{
1086 struct cfi_private *cfi = map->fldrv_priv;
1087 unsigned long timeo = jiffies + HZ;
1088 /*
1089 * We use a 1ms + 1 jiffies generic timeout for writes (most devices
1090 * have a max write time of a few hundreds usec). However, we should
1091 * use the maximum timeout value given by the chip at probe time
1092 * instead. Unfortunately, struct flchip does have a field for
1093 * maximum timeout, only for typical which can be far too short
1094 * depending of the conditions. The ' + 1' is to avoid having a
1095 * timeout of 0 jiffies if HZ is smaller than 1000.
1096 */
1097 unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
1098 int ret = 0;
1099 map_word oldd;
1100 int retry_cnt = 0;
1101
1102 adr += chip->start;
1103
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001104 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 ret = get_chip(map, chip, adr, FL_WRITING);
1106 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001107 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 return ret;
1109 }
1110
1111 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
1112 __func__, adr, datum.x[0] );
1113
1114 /*
1115 * Check for a NOP for the case when the datum to write is already
1116 * present - it saves time and works around buggy chips that corrupt
1117 * data at other locations when 0xff is written to a location that
1118 * already contains 0xff.
1119 */
1120 oldd = map_read(map, adr);
1121 if (map_word_equal(map, oldd, datum)) {
1122 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n",
1123 __func__);
1124 goto op_done;
1125 }
1126
Todd Poynor02b15e32005-06-07 00:04:39 +01001127 XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 ENABLE_VPP(map);
Todd Poynor02b15e32005-06-07 00:04:39 +01001129 xip_disable(map, chip, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 retry:
1131 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1132 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
1133 cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1134 map_write(map, datum, adr);
1135 chip->state = FL_WRITING;
1136
Todd Poynor02b15e32005-06-07 00:04:39 +01001137 INVALIDATE_CACHE_UDELAY(map, chip,
1138 adr, map_bankwidth(map),
1139 chip->word_write_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
1141 /* See comment above for timeout value. */
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001142 timeo = jiffies + uWriteTimeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 for (;;) {
1144 if (chip->state != FL_WRITING) {
1145 /* Someone's suspended the write. Sleep */
1146 DECLARE_WAITQUEUE(wait, current);
1147
1148 set_current_state(TASK_UNINTERRUPTIBLE);
1149 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001150 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 schedule();
1152 remove_wait_queue(&chip->wq, &wait);
1153 timeo = jiffies + (HZ / 2); /* FIXME */
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001154 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 continue;
1156 }
1157
Konstantin Baidarovb95f9602005-11-07 09:00:05 +00001158 if (time_after(jiffies, timeo) && !chip_ready(map, adr)){
Todd Poynor02b15e32005-06-07 00:04:39 +01001159 xip_enable(map, chip, adr);
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001160 printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);
Todd Poynor02b15e32005-06-07 00:04:39 +01001161 xip_disable(map, chip, adr);
Konstantin Baidarovb95f9602005-11-07 09:00:05 +00001162 break;
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
Konstantin Baidarovb95f9602005-11-07 09:00:05 +00001165 if (chip_ready(map, adr))
1166 break;
1167
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 /* Latency issues. Drop the lock, wait a while and retry */
Todd Poynor02b15e32005-06-07 00:04:39 +01001169 UDELAY(map, chip, adr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 }
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001171 /* Did we succeed? */
1172 if (!chip_good(map, adr, datum)) {
1173 /* reset on all failures. */
1174 map_write( map, CMD(0xF0), chip->start );
1175 /* FIXME - should have reset delay before continuing */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001177 if (++retry_cnt <= MAX_WORD_RETRIES)
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001178 goto retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001180 ret = -EIO;
1181 }
Todd Poynor02b15e32005-06-07 00:04:39 +01001182 xip_enable(map, chip, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 op_done:
1184 chip->state = FL_READY;
1185 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001186 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187
1188 return ret;
1189}
1190
1191
1192static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
1193 size_t *retlen, const u_char *buf)
1194{
1195 struct map_info *map = mtd->priv;
1196 struct cfi_private *cfi = map->fldrv_priv;
1197 int ret = 0;
1198 int chipnum;
1199 unsigned long ofs, chipstart;
1200 DECLARE_WAITQUEUE(wait, current);
1201
1202 *retlen = 0;
1203 if (!len)
1204 return 0;
1205
1206 chipnum = to >> cfi->chipshift;
1207 ofs = to - (chipnum << cfi->chipshift);
1208 chipstart = cfi->chips[chipnum].start;
1209
1210 /* If it's not bus-aligned, do the first byte write */
1211 if (ofs & (map_bankwidth(map)-1)) {
1212 unsigned long bus_ofs = ofs & ~(map_bankwidth(map)-1);
1213 int i = ofs - bus_ofs;
1214 int n = 0;
1215 map_word tmp_buf;
1216
1217 retry:
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001218 mutex_lock(&cfi->chips[chipnum].mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
1220 if (cfi->chips[chipnum].state != FL_READY) {
1221#if 0
1222 printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);
1223#endif
1224 set_current_state(TASK_UNINTERRUPTIBLE);
1225 add_wait_queue(&cfi->chips[chipnum].wq, &wait);
1226
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001227 mutex_unlock(&cfi->chips[chipnum].mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 schedule();
1230 remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
1231#if 0
1232 if(signal_pending(current))
1233 return -EINTR;
1234#endif
1235 goto retry;
1236 }
1237
1238 /* Load 'tmp_buf' with old contents of flash */
1239 tmp_buf = map_read(map, bus_ofs+chipstart);
1240
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001241 mutex_unlock(&cfi->chips[chipnum].mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
1243 /* Number of bytes to copy from buffer */
1244 n = min_t(int, len, map_bankwidth(map)-i);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001245
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n);
1247
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001248 ret = do_write_oneword(map, &cfi->chips[chipnum],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 bus_ofs, tmp_buf);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001250 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 return ret;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001252
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 ofs += n;
1254 buf += n;
1255 (*retlen) += n;
1256 len -= n;
1257
1258 if (ofs >> cfi->chipshift) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001259 chipnum ++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 ofs = 0;
1261 if (chipnum == cfi->numchips)
1262 return 0;
1263 }
1264 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001265
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 /* We are now aligned, write as much as possible */
1267 while(len >= map_bankwidth(map)) {
1268 map_word datum;
1269
1270 datum = map_word_load(map, buf);
1271
1272 ret = do_write_oneword(map, &cfi->chips[chipnum],
1273 ofs, datum);
1274 if (ret)
1275 return ret;
1276
1277 ofs += map_bankwidth(map);
1278 buf += map_bankwidth(map);
1279 (*retlen) += map_bankwidth(map);
1280 len -= map_bankwidth(map);
1281
1282 if (ofs >> cfi->chipshift) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001283 chipnum ++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 ofs = 0;
1285 if (chipnum == cfi->numchips)
1286 return 0;
1287 chipstart = cfi->chips[chipnum].start;
1288 }
1289 }
1290
1291 /* Write the trailing bytes if any */
1292 if (len & (map_bankwidth(map)-1)) {
1293 map_word tmp_buf;
1294
1295 retry1:
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001296 mutex_lock(&cfi->chips[chipnum].mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297
1298 if (cfi->chips[chipnum].state != FL_READY) {
1299#if 0
1300 printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);
1301#endif
1302 set_current_state(TASK_UNINTERRUPTIBLE);
1303 add_wait_queue(&cfi->chips[chipnum].wq, &wait);
1304
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001305 mutex_unlock(&cfi->chips[chipnum].mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
1307 schedule();
1308 remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
1309#if 0
1310 if(signal_pending(current))
1311 return -EINTR;
1312#endif
1313 goto retry1;
1314 }
1315
1316 tmp_buf = map_read(map, ofs + chipstart);
1317
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001318 mutex_unlock(&cfi->chips[chipnum].mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
1320 tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001321
1322 ret = do_write_oneword(map, &cfi->chips[chipnum],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 ofs, tmp_buf);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001324 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 return ret;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001326
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 (*retlen) += len;
1328 }
1329
1330 return 0;
1331}
1332
1333
1334/*
1335 * FIXME: interleaved mode not tested, and probably not supported!
1336 */
Todd Poynor02b15e32005-06-07 00:04:39 +01001337static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001338 unsigned long adr, const u_char *buf,
Todd Poynor02b15e32005-06-07 00:04:39 +01001339 int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340{
1341 struct cfi_private *cfi = map->fldrv_priv;
1342 unsigned long timeo = jiffies + HZ;
1343 /* see comments in do_write_oneword() regarding uWriteTimeo. */
1344 unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
1345 int ret = -EIO;
1346 unsigned long cmd_adr;
1347 int z, words;
1348 map_word datum;
1349
1350 adr += chip->start;
1351 cmd_adr = adr;
1352
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001353 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 ret = get_chip(map, chip, adr, FL_WRITING);
1355 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001356 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 return ret;
1358 }
1359
1360 datum = map_word_load(map, buf);
1361
1362 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
1363 __func__, adr, datum.x[0] );
1364
Todd Poynor02b15e32005-06-07 00:04:39 +01001365 XIP_INVAL_CACHED_RANGE(map, adr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 ENABLE_VPP(map);
Todd Poynor02b15e32005-06-07 00:04:39 +01001367 xip_disable(map, chip, cmd_adr);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001368
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1370 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
1371 //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1372
1373 /* Write Buffer Load */
1374 map_write(map, CMD(0x25), cmd_adr);
1375
1376 chip->state = FL_WRITING_TO_BUFFER;
1377
1378 /* Write length of data to come */
1379 words = len / map_bankwidth(map);
1380 map_write(map, CMD(words - 1), cmd_adr);
1381 /* Write data */
1382 z = 0;
1383 while(z < words * map_bankwidth(map)) {
1384 datum = map_word_load(map, buf);
1385 map_write(map, datum, adr + z);
1386
1387 z += map_bankwidth(map);
1388 buf += map_bankwidth(map);
1389 }
1390 z -= map_bankwidth(map);
1391
1392 adr += z;
1393
1394 /* Write Buffer Program Confirm: GO GO GO */
1395 map_write(map, CMD(0x29), cmd_adr);
1396 chip->state = FL_WRITING;
1397
Todd Poynor02b15e32005-06-07 00:04:39 +01001398 INVALIDATE_CACHE_UDELAY(map, chip,
1399 adr, map_bankwidth(map),
1400 chip->word_write_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001402 timeo = jiffies + uWriteTimeout;
1403
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 for (;;) {
1405 if (chip->state != FL_WRITING) {
1406 /* Someone's suspended the write. Sleep */
1407 DECLARE_WAITQUEUE(wait, current);
1408
1409 set_current_state(TASK_UNINTERRUPTIBLE);
1410 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001411 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 schedule();
1413 remove_wait_queue(&chip->wq, &wait);
1414 timeo = jiffies + (HZ / 2); /* FIXME */
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001415 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 continue;
1417 }
1418
Konstantin Baidarovb95f9602005-11-07 09:00:05 +00001419 if (time_after(jiffies, timeo) && !chip_ready(map, adr))
1420 break;
1421
Todd Poynor02b15e32005-06-07 00:04:39 +01001422 if (chip_ready(map, adr)) {
1423 xip_enable(map, chip, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 goto op_done;
Todd Poynor02b15e32005-06-07 00:04:39 +01001425 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
1427 /* Latency issues. Drop the lock, wait a while and retry */
Todd Poynor02b15e32005-06-07 00:04:39 +01001428 UDELAY(map, chip, adr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 }
1430
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 /* reset on all failures. */
1432 map_write( map, CMD(0xF0), chip->start );
Todd Poynor02b15e32005-06-07 00:04:39 +01001433 xip_enable(map, chip, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 /* FIXME - should have reset delay before continuing */
1435
Todd Poynor02b15e32005-06-07 00:04:39 +01001436 printk(KERN_WARNING "MTD %s(): software timeout\n",
1437 __func__ );
1438
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 ret = -EIO;
1440 op_done:
1441 chip->state = FL_READY;
1442 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001443 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 return ret;
1446}
1447
1448
1449static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
1450 size_t *retlen, const u_char *buf)
1451{
1452 struct map_info *map = mtd->priv;
1453 struct cfi_private *cfi = map->fldrv_priv;
1454 int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
1455 int ret = 0;
1456 int chipnum;
1457 unsigned long ofs;
1458
1459 *retlen = 0;
1460 if (!len)
1461 return 0;
1462
1463 chipnum = to >> cfi->chipshift;
1464 ofs = to - (chipnum << cfi->chipshift);
1465
1466 /* If it's not bus-aligned, do the first word write */
1467 if (ofs & (map_bankwidth(map)-1)) {
1468 size_t local_len = (-ofs)&(map_bankwidth(map)-1);
1469 if (local_len > len)
1470 local_len = len;
1471 ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<<cfi->chipshift),
1472 local_len, retlen, buf);
1473 if (ret)
1474 return ret;
1475 ofs += local_len;
1476 buf += local_len;
1477 len -= local_len;
1478
1479 if (ofs >> cfi->chipshift) {
1480 chipnum ++;
1481 ofs = 0;
1482 if (chipnum == cfi->numchips)
1483 return 0;
1484 }
1485 }
1486
1487 /* Write buffer is worth it only if more than one word to write... */
1488 while (len >= map_bankwidth(map) * 2) {
1489 /* We must not cross write block boundaries */
1490 int size = wbufsize - (ofs & (wbufsize-1));
1491
1492 if (size > len)
1493 size = len;
1494 if (size % map_bankwidth(map))
1495 size -= size % map_bankwidth(map);
1496
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001497 ret = do_write_buffer(map, &cfi->chips[chipnum],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 ofs, buf, size);
1499 if (ret)
1500 return ret;
1501
1502 ofs += size;
1503 buf += size;
1504 (*retlen) += size;
1505 len -= size;
1506
1507 if (ofs >> cfi->chipshift) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001508 chipnum ++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 ofs = 0;
1510 if (chipnum == cfi->numchips)
1511 return 0;
1512 }
1513 }
1514
1515 if (len) {
1516 size_t retlen_dregs = 0;
1517
1518 ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<<cfi->chipshift),
1519 len, &retlen_dregs, buf);
1520
1521 *retlen += retlen_dregs;
1522 return ret;
1523 }
1524
1525 return 0;
1526}
1527
1528
1529/*
1530 * Handle devices with one erase region, that only implement
1531 * the chip erase command.
1532 */
Todd Poynor02b15e32005-06-07 00:04:39 +01001533static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534{
1535 struct cfi_private *cfi = map->fldrv_priv;
1536 unsigned long timeo = jiffies + HZ;
1537 unsigned long int adr;
1538 DECLARE_WAITQUEUE(wait, current);
1539 int ret = 0;
1540
1541 adr = cfi->addr_unlock1;
1542
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001543 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 ret = get_chip(map, chip, adr, FL_WRITING);
1545 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001546 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 return ret;
1548 }
1549
1550 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
1551 __func__, chip->start );
1552
Todd Poynor02b15e32005-06-07 00:04:39 +01001553 XIP_INVAL_CACHED_RANGE(map, adr, map->size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 ENABLE_VPP(map);
Todd Poynor02b15e32005-06-07 00:04:39 +01001555 xip_disable(map, chip, adr);
1556
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1558 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
1559 cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1560 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1561 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
1562 cfi_send_gen_cmd(0x10, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1563
1564 chip->state = FL_ERASING;
1565 chip->erase_suspended = 0;
1566 chip->in_progress_block_addr = adr;
1567
Todd Poynor02b15e32005-06-07 00:04:39 +01001568 INVALIDATE_CACHE_UDELAY(map, chip,
1569 adr, map->size,
1570 chip->erase_time*500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
1572 timeo = jiffies + (HZ*20);
1573
1574 for (;;) {
1575 if (chip->state != FL_ERASING) {
1576 /* Someone's suspended the erase. Sleep */
1577 set_current_state(TASK_UNINTERRUPTIBLE);
1578 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001579 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 schedule();
1581 remove_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001582 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 continue;
1584 }
1585 if (chip->erase_suspended) {
1586 /* This erase was suspended and resumed.
1587 Adjust the timeout */
1588 timeo = jiffies + (HZ*20); /* FIXME */
1589 chip->erase_suspended = 0;
1590 }
1591
1592 if (chip_ready(map, adr))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 break;
1594
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001595 if (time_after(jiffies, timeo)) {
1596 printk(KERN_WARNING "MTD %s(): software timeout\n",
1597 __func__ );
1598 break;
1599 }
1600
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 /* Latency issues. Drop the lock, wait a while and retry */
Todd Poynor02b15e32005-06-07 00:04:39 +01001602 UDELAY(map, chip, adr, 1000000/HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 }
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001604 /* Did we succeed? */
1605 if (!chip_good(map, adr, map_word_ff(map))) {
1606 /* reset on all failures. */
1607 map_write( map, CMD(0xF0), chip->start );
1608 /* FIXME - should have reset delay before continuing */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001610 ret = -EIO;
1611 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 chip->state = FL_READY;
Todd Poynor02b15e32005-06-07 00:04:39 +01001614 xip_enable(map, chip, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001616 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617
1618 return ret;
1619}
1620
1621
Todd Poynor02b15e32005-06-07 00:04:39 +01001622static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623{
1624 struct cfi_private *cfi = map->fldrv_priv;
1625 unsigned long timeo = jiffies + HZ;
1626 DECLARE_WAITQUEUE(wait, current);
1627 int ret = 0;
1628
1629 adr += chip->start;
1630
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001631 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 ret = get_chip(map, chip, adr, FL_ERASING);
1633 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001634 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 return ret;
1636 }
1637
1638 DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
1639 __func__, adr );
1640
Todd Poynor02b15e32005-06-07 00:04:39 +01001641 XIP_INVAL_CACHED_RANGE(map, adr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 ENABLE_VPP(map);
Todd Poynor02b15e32005-06-07 00:04:39 +01001643 xip_disable(map, chip, adr);
1644
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1646 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
1647 cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1648 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1649 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
1650 map_write(map, CMD(0x30), adr);
1651
1652 chip->state = FL_ERASING;
1653 chip->erase_suspended = 0;
1654 chip->in_progress_block_addr = adr;
Todd Poynor02b15e32005-06-07 00:04:39 +01001655
1656 INVALIDATE_CACHE_UDELAY(map, chip,
1657 adr, len,
1658 chip->erase_time*500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659
1660 timeo = jiffies + (HZ*20);
1661
1662 for (;;) {
1663 if (chip->state != FL_ERASING) {
1664 /* Someone's suspended the erase. Sleep */
1665 set_current_state(TASK_UNINTERRUPTIBLE);
1666 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001667 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 schedule();
1669 remove_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001670 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 continue;
1672 }
1673 if (chip->erase_suspended) {
1674 /* This erase was suspended and resumed.
1675 Adjust the timeout */
1676 timeo = jiffies + (HZ*20); /* FIXME */
1677 chip->erase_suspended = 0;
1678 }
1679
Todd Poynor02b15e32005-06-07 00:04:39 +01001680 if (chip_ready(map, adr)) {
1681 xip_enable(map, chip, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 break;
Todd Poynor02b15e32005-06-07 00:04:39 +01001683 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001685 if (time_after(jiffies, timeo)) {
Todd Poynor02b15e32005-06-07 00:04:39 +01001686 xip_enable(map, chip, adr);
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001687 printk(KERN_WARNING "MTD %s(): software timeout\n",
1688 __func__ );
1689 break;
1690 }
1691
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 /* Latency issues. Drop the lock, wait a while and retry */
Todd Poynor02b15e32005-06-07 00:04:39 +01001693 UDELAY(map, chip, adr, 1000000/HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 }
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001695 /* Did we succeed? */
Thomas Gleixner22fd9a82005-05-24 15:33:49 +02001696 if (!chip_good(map, adr, map_word_ff(map))) {
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001697 /* reset on all failures. */
1698 map_write( map, CMD(0xF0), chip->start );
1699 /* FIXME - should have reset delay before continuing */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
Eric W. Biedermannfb4a90b2005-05-20 04:28:26 +01001701 ret = -EIO;
1702 }
1703
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 chip->state = FL_READY;
1705 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001706 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 return ret;
1708}
1709
1710
Ben Dooksce0f33a2007-05-28 19:59:00 +01001711static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712{
1713 unsigned long ofs, len;
1714 int ret;
1715
1716 ofs = instr->addr;
1717 len = instr->len;
1718
1719 ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
1720 if (ret)
1721 return ret;
1722
1723 instr->state = MTD_ERASE_DONE;
1724 mtd_erase_callback(instr);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001725
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 return 0;
1727}
1728
1729
1730static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr)
1731{
1732 struct map_info *map = mtd->priv;
1733 struct cfi_private *cfi = map->fldrv_priv;
1734 int ret = 0;
1735
1736 if (instr->addr != 0)
1737 return -EINVAL;
1738
1739 if (instr->len != mtd->size)
1740 return -EINVAL;
1741
1742 ret = do_erase_chip(map, &cfi->chips[0]);
1743 if (ret)
1744 return ret;
1745
1746 instr->state = MTD_ERASE_DONE;
1747 mtd_erase_callback(instr);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001748
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 return 0;
1750}
1751
Haavard Skinnemoen01655082006-08-09 11:06:07 +02001752static int do_atmel_lock(struct map_info *map, struct flchip *chip,
1753 unsigned long adr, int len, void *thunk)
1754{
1755 struct cfi_private *cfi = map->fldrv_priv;
1756 int ret;
1757
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001758 mutex_lock(&chip->mutex);
Haavard Skinnemoen01655082006-08-09 11:06:07 +02001759 ret = get_chip(map, chip, adr + chip->start, FL_LOCKING);
1760 if (ret)
1761 goto out_unlock;
1762 chip->state = FL_LOCKING;
1763
1764 DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
1765 __func__, adr, len);
1766
1767 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
1768 cfi->device_type, NULL);
1769 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
1770 cfi->device_type, NULL);
1771 cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi,
1772 cfi->device_type, NULL);
1773 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
1774 cfi->device_type, NULL);
1775 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
1776 cfi->device_type, NULL);
1777 map_write(map, CMD(0x40), chip->start + adr);
1778
1779 chip->state = FL_READY;
1780 put_chip(map, chip, adr + chip->start);
1781 ret = 0;
1782
1783out_unlock:
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001784 mutex_unlock(&chip->mutex);
Haavard Skinnemoen01655082006-08-09 11:06:07 +02001785 return ret;
1786}
1787
1788static int do_atmel_unlock(struct map_info *map, struct flchip *chip,
1789 unsigned long adr, int len, void *thunk)
1790{
1791 struct cfi_private *cfi = map->fldrv_priv;
1792 int ret;
1793
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001794 mutex_lock(&chip->mutex);
Haavard Skinnemoen01655082006-08-09 11:06:07 +02001795 ret = get_chip(map, chip, adr + chip->start, FL_UNLOCKING);
1796 if (ret)
1797 goto out_unlock;
1798 chip->state = FL_UNLOCKING;
1799
1800 DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
1801 __func__, adr, len);
1802
1803 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
1804 cfi->device_type, NULL);
1805 map_write(map, CMD(0x70), adr);
1806
1807 chip->state = FL_READY;
1808 put_chip(map, chip, adr + chip->start);
1809 ret = 0;
1810
1811out_unlock:
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001812 mutex_unlock(&chip->mutex);
Haavard Skinnemoen01655082006-08-09 11:06:07 +02001813 return ret;
1814}
1815
Adrian Hunter69423d92008-12-10 13:37:21 +00001816static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
Haavard Skinnemoen01655082006-08-09 11:06:07 +02001817{
1818 return cfi_varsize_frob(mtd, do_atmel_lock, ofs, len, NULL);
1819}
1820
Adrian Hunter69423d92008-12-10 13:37:21 +00001821static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
Haavard Skinnemoen01655082006-08-09 11:06:07 +02001822{
1823 return cfi_varsize_frob(mtd, do_atmel_unlock, ofs, len, NULL);
1824}
1825
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
1827static void cfi_amdstd_sync (struct mtd_info *mtd)
1828{
1829 struct map_info *map = mtd->priv;
1830 struct cfi_private *cfi = map->fldrv_priv;
1831 int i;
1832 struct flchip *chip;
1833 int ret = 0;
1834 DECLARE_WAITQUEUE(wait, current);
1835
1836 for (i=0; !ret && i<cfi->numchips; i++) {
1837 chip = &cfi->chips[i];
1838
1839 retry:
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001840 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841
1842 switch(chip->state) {
1843 case FL_READY:
1844 case FL_STATUS:
1845 case FL_CFI_QUERY:
1846 case FL_JEDEC_QUERY:
1847 chip->oldstate = chip->state;
1848 chip->state = FL_SYNCING;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001849 /* No need to wake_up() on this state change -
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 * as the whole point is that nobody can do anything
1851 * with the chip now anyway.
1852 */
1853 case FL_SYNCING:
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001854 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 break;
1856
1857 default:
1858 /* Not an idle state */
Dmitry Adamushkof8e30e42008-04-08 17:41:59 -07001859 set_current_state(TASK_UNINTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 add_wait_queue(&chip->wq, &wait);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001861
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001862 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
1864 schedule();
1865
1866 remove_wait_queue(&chip->wq, &wait);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001867
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 goto retry;
1869 }
1870 }
1871
1872 /* Unlock the chips again */
1873
1874 for (i--; i >=0; i--) {
1875 chip = &cfi->chips[i];
1876
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001877 mutex_lock(&chip->mutex);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001878
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 if (chip->state == FL_SYNCING) {
1880 chip->state = chip->oldstate;
1881 wake_up(&chip->wq);
1882 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001883 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 }
1885}
1886
1887
1888static int cfi_amdstd_suspend(struct mtd_info *mtd)
1889{
1890 struct map_info *map = mtd->priv;
1891 struct cfi_private *cfi = map->fldrv_priv;
1892 int i;
1893 struct flchip *chip;
1894 int ret = 0;
1895
1896 for (i=0; !ret && i<cfi->numchips; i++) {
1897 chip = &cfi->chips[i];
1898
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001899 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900
1901 switch(chip->state) {
1902 case FL_READY:
1903 case FL_STATUS:
1904 case FL_CFI_QUERY:
1905 case FL_JEDEC_QUERY:
1906 chip->oldstate = chip->state;
1907 chip->state = FL_PM_SUSPENDED;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001908 /* No need to wake_up() on this state change -
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 * as the whole point is that nobody can do anything
1910 * with the chip now anyway.
1911 */
1912 case FL_PM_SUSPENDED:
1913 break;
1914
1915 default:
1916 ret = -EAGAIN;
1917 break;
1918 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001919 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 }
1921
1922 /* Unlock the chips again */
1923
1924 if (ret) {
1925 for (i--; i >=0; i--) {
1926 chip = &cfi->chips[i];
1927
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001928 mutex_lock(&chip->mutex);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001929
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 if (chip->state == FL_PM_SUSPENDED) {
1931 chip->state = chip->oldstate;
1932 wake_up(&chip->wq);
1933 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001934 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 }
1936 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001937
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 return ret;
1939}
1940
1941
1942static void cfi_amdstd_resume(struct mtd_info *mtd)
1943{
1944 struct map_info *map = mtd->priv;
1945 struct cfi_private *cfi = map->fldrv_priv;
1946 int i;
1947 struct flchip *chip;
1948
1949 for (i=0; i<cfi->numchips; i++) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001950
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 chip = &cfi->chips[i];
1952
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001953 mutex_lock(&chip->mutex);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001954
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 if (chip->state == FL_PM_SUSPENDED) {
1956 chip->state = FL_READY;
1957 map_write(map, CMD(0xF0), chip->start);
1958 wake_up(&chip->wq);
1959 }
1960 else
1961 printk(KERN_ERR "Argh. Chip not in PM_SUSPENDED state upon resume()\n");
1962
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001963 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 }
1965}
1966
Kevin Cernekeeeafe1312010-04-29 10:26:56 -07001967
1968/*
1969 * Ensure that the flash device is put back into read array mode before
1970 * unloading the driver or rebooting. On some systems, rebooting while
1971 * the flash is in query/program/erase mode will prevent the CPU from
1972 * fetching the bootloader code, requiring a hard reset or power cycle.
1973 */
1974static int cfi_amdstd_reset(struct mtd_info *mtd)
1975{
1976 struct map_info *map = mtd->priv;
1977 struct cfi_private *cfi = map->fldrv_priv;
1978 int i, ret;
1979 struct flchip *chip;
1980
1981 for (i = 0; i < cfi->numchips; i++) {
1982
1983 chip = &cfi->chips[i];
1984
1985 mutex_lock(&chip->mutex);
1986
1987 ret = get_chip(map, chip, chip->start, FL_SHUTDOWN);
1988 if (!ret) {
1989 map_write(map, CMD(0xF0), chip->start);
1990 chip->state = FL_SHUTDOWN;
1991 put_chip(map, chip, chip->start);
1992 }
1993
1994 mutex_unlock(&chip->mutex);
1995 }
1996
1997 return 0;
1998}
1999
2000
2001static int cfi_amdstd_reboot(struct notifier_block *nb, unsigned long val,
2002 void *v)
2003{
2004 struct mtd_info *mtd;
2005
2006 mtd = container_of(nb, struct mtd_info, reboot_notifier);
2007 cfi_amdstd_reset(mtd);
2008 return NOTIFY_DONE;
2009}
2010
2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012static void cfi_amdstd_destroy(struct mtd_info *mtd)
2013{
2014 struct map_info *map = mtd->priv;
2015 struct cfi_private *cfi = map->fldrv_priv;
Jesper Juhlfa671642005-11-07 01:01:27 -08002016
Kevin Cernekeeeafe1312010-04-29 10:26:56 -07002017 cfi_amdstd_reset(mtd);
2018 unregister_reboot_notifier(&mtd->reboot_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 kfree(cfi->cmdset_priv);
2020 kfree(cfi->cfiq);
2021 kfree(cfi);
2022 kfree(mtd->eraseregions);
2023}
2024
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025MODULE_LICENSE("GPL");
2026MODULE_AUTHOR("Crossnet Co. <info@crossnet.co.jp> et al.");
2027MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips");