blob: e1b603ca0170e2aa5daf4ef75fb408e3c147135d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Common Flash Interface support:
3 * Intel Extended Vendor Command Set (ID 0x0001)
4 *
5 * (C) 2000 Red Hat. GPL'd
6 *
Thomas Gleixner1f948b42005-11-07 11:15:37 +00007 *
Nicolas Pitre2f82af02009-09-14 03:25:28 -04008 * 10/10/2000 Nicolas Pitre <nico@fluxnic.net>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * - completely revamped method functions so they are aware and
10 * independent of the flash geometry (buswidth, interleave, etc.)
11 * - scalability vs code size is completely set at compile-time
12 * (see include/linux/mtd/cfi.h for selection)
13 * - optimized write buffer method
14 * 02/05/2002 Christopher Hoover <ch@hpl.hp.com>/<ch@murgatroid.com>
15 * - reworked lock/unlock/erase support for var size flash
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -080016 * 21/03/2007 Rodolfo Giometti <giometti@linux.it>
17 * - auto unlock sectors on resume for auto locking flash on power up
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 */
19
20#include <linux/module.h>
21#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <asm/io.h>
25#include <asm/byteorder.h>
26
27#include <linux/errno.h>
28#include <linux/slab.h>
29#include <linux/delay.h>
30#include <linux/interrupt.h>
Nicolas Pitre963a6fb2005-04-01 02:59:56 +010031#include <linux/reboot.h>
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -080032#include <linux/bitmap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/mtd/xip.h>
34#include <linux/mtd/map.h>
35#include <linux/mtd/mtd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/mtd/cfi.h>
37
38/* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */
39/* #define CMDSET0001_DISABLE_WRITE_SUSPEND */
40
41// debugging, turns off buffer write mode if set to 1
42#define FORCE_WORD_WRITE 0
43
Hans-Christian Egtvedtb2ef1a22009-11-05 15:53:43 +010044/* Intel chips */
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#define I82802AB 0x00ad
46#define I82802AC 0x00ac
Daniel Ribeiroec2d0d82009-05-17 08:02:17 -030047#define PF38F4476 0x881c
Joakim Tjernlund0d8f3792018-03-01 14:39:40 +010048#define M28F00AP30 0x8963
Hans-Christian Egtvedtb2ef1a22009-11-05 15:53:43 +010049/* STMicroelectronics chips */
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#define M50LPW080 0x002F
Nate Casedeb1a5f2008-05-13 14:45:29 -050051#define M50FLW080A 0x0080
52#define M50FLW080B 0x0081
Hans-Christian Egtvedt8dbaea42009-11-05 15:53:37 +010053/* Atmel chips */
Hans-Christian Egtvedtd10a39d2007-10-30 16:33:07 +010054#define AT49BV640D 0x02de
Hans-Christian Egtvedt8dbaea42009-11-05 15:53:37 +010055#define AT49BV640DT 0x02db
Andrea Adami812c5fa2014-06-02 23:38:35 +020056/* Sharp chips */
57#define LH28F640BFHE_PTTL90 0x00b0
58#define LH28F640BFHE_PBTL90 0x00b1
59#define LH28F640BFHE_PTTL70A 0x00b2
60#define LH28F640BFHE_PBTL70A 0x00b3
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
62static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070063static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
64static int cfi_intelext_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
Nicolas Pitree102d542005-08-06 05:46:59 +010065static int cfi_intelext_writev(struct mtd_info *, const struct kvec *, unsigned long, loff_t, size_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070066static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *);
67static void cfi_intelext_sync (struct mtd_info *);
Adrian Hunter69423d92008-12-10 13:37:21 +000068static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
69static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
Richard Cochran99384242010-06-14 18:10:33 +020070static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs,
71 uint64_t len);
Todd Poynor8048d2f2005-03-31 00:57:33 +010072#ifdef CONFIG_MTD_OTP
Nicolas Pitref77814d2005-02-08 17:11:19 +000073static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
74static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
75static int cfi_intelext_write_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
76static int cfi_intelext_lock_user_prot_reg (struct mtd_info *, loff_t, size_t);
Christian Riesch4b78fc42014-01-28 09:29:44 +010077static int cfi_intelext_get_fact_prot_info(struct mtd_info *, size_t,
78 size_t *, struct otp_info *);
79static int cfi_intelext_get_user_prot_info(struct mtd_info *, size_t,
80 size_t *, struct otp_info *);
Todd Poynor8048d2f2005-03-31 00:57:33 +010081#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070082static int cfi_intelext_suspend (struct mtd_info *);
83static void cfi_intelext_resume (struct mtd_info *);
Nicolas Pitre963a6fb2005-04-01 02:59:56 +010084static int cfi_intelext_reboot (struct notifier_block *, unsigned long, void *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86static void cfi_intelext_destroy(struct mtd_info *);
87
88struct mtd_info *cfi_cmdset_0001(struct map_info *, int);
89
90static struct mtd_info *cfi_intelext_setup (struct mtd_info *);
91static int cfi_intelext_partition_fixup(struct mtd_info *, struct cfi_private **);
92
93static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len,
Jared Hulberta98889f2008-04-29 23:26:49 -070094 size_t *retlen, void **virt, resource_size_t *phys);
Artem Bityutskiy5e4e6e32012-02-03 13:20:43 +020095static int cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Alexey Korolev5a37cf12007-10-22 17:55:20 +010097static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -070098static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
99static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
100#include "fwh_lock.h"
101
102
103
104/*
105 * *********** SETUP AND PROBE BITS ***********
106 */
107
108static struct mtd_chip_driver cfi_intelext_chipdrv = {
109 .probe = NULL, /* Not usable directly */
110 .destroy = cfi_intelext_destroy,
111 .name = "cfi_cmdset_0001",
112 .module = THIS_MODULE
113};
114
115/* #define DEBUG_LOCK_BITS */
116/* #define DEBUG_CFI_FEATURES */
117
118#ifdef DEBUG_CFI_FEATURES
119static void cfi_tell_features(struct cfi_pri_intelext *extp)
120{
121 int i;
Nicolas Pitre638d9832005-08-06 05:40:46 +0100122 printk(" Extended Query version %c.%c\n", extp->MajorVersion, extp->MinorVersion);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport);
124 printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported");
125 printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported");
126 printk(" - Suspend Program: %s\n", extp->FeatureSupport&4?"supported":"unsupported");
127 printk(" - Legacy Lock/Unlock: %s\n", extp->FeatureSupport&8?"supported":"unsupported");
128 printk(" - Queued Erase: %s\n", extp->FeatureSupport&16?"supported":"unsupported");
129 printk(" - Instant block lock: %s\n", extp->FeatureSupport&32?"supported":"unsupported");
130 printk(" - Protection Bits: %s\n", extp->FeatureSupport&64?"supported":"unsupported");
131 printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported");
132 printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported");
133 printk(" - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported");
Nicolas Pitre638d9832005-08-06 05:40:46 +0100134 printk(" - Extended Flash Array: %s\n", extp->FeatureSupport&1024?"supported":"unsupported");
135 for (i=11; i<32; i++) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000136 if (extp->FeatureSupport & (1<<i))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 printk(" - Unknown Bit %X: supported\n", i);
138 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000139
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 printk(" Supported functions after Suspend: %2.2X\n", extp->SuspendCmdSupport);
141 printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported");
142 for (i=1; i<8; i++) {
143 if (extp->SuspendCmdSupport & (1<<i))
144 printk(" - Unknown Bit %X: supported\n", i);
145 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000146
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 printk(" Block Status Register Mask: %4.4X\n", extp->BlkStatusRegMask);
148 printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no");
Nicolas Pitre638d9832005-08-06 05:40:46 +0100149 printk(" - Lock-Down Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no");
150 for (i=2; i<3; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 if (extp->BlkStatusRegMask & (1<<i))
152 printk(" - Unknown Bit %X Active: yes\n",i);
153 }
Nicolas Pitre638d9832005-08-06 05:40:46 +0100154 printk(" - EFA Lock Bit: %s\n", extp->BlkStatusRegMask&16?"yes":"no");
155 printk(" - EFA Lock-Down Bit: %s\n", extp->BlkStatusRegMask&32?"yes":"no");
156 for (i=6; i<16; i++) {
157 if (extp->BlkStatusRegMask & (1<<i))
158 printk(" - Unknown Bit %X Active: yes\n",i);
159 }
160
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000161 printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 extp->VccOptimal >> 4, extp->VccOptimal & 0xf);
163 if (extp->VppOptimal)
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000164 printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 extp->VppOptimal >> 4, extp->VppOptimal & 0xf);
166}
167#endif
168
Hans-Christian Egtvedtd10a39d2007-10-30 16:33:07 +0100169/* Atmel chips don't use the same PRI format as Intel chips */
Guillaume LECERFcc318222010-11-17 12:35:50 +0100170static void fixup_convert_atmel_pri(struct mtd_info *mtd)
Hans-Christian Egtvedtd10a39d2007-10-30 16:33:07 +0100171{
172 struct map_info *map = mtd->priv;
173 struct cfi_private *cfi = map->fldrv_priv;
174 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
175 struct cfi_pri_atmel atmel_pri;
176 uint32_t features = 0;
177
178 /* Reverse byteswapping */
179 extp->FeatureSupport = cpu_to_le32(extp->FeatureSupport);
180 extp->BlkStatusRegMask = cpu_to_le16(extp->BlkStatusRegMask);
181 extp->ProtRegAddr = cpu_to_le16(extp->ProtRegAddr);
182
183 memcpy(&atmel_pri, extp, sizeof(atmel_pri));
184 memset((char *)extp + 5, 0, sizeof(*extp) - 5);
185
186 printk(KERN_ERR "atmel Features: %02x\n", atmel_pri.Features);
187
188 if (atmel_pri.Features & 0x01) /* chip erase supported */
189 features |= (1<<0);
190 if (atmel_pri.Features & 0x02) /* erase suspend supported */
191 features |= (1<<1);
192 if (atmel_pri.Features & 0x04) /* program suspend supported */
193 features |= (1<<2);
194 if (atmel_pri.Features & 0x08) /* simultaneous operations supported */
195 features |= (1<<9);
196 if (atmel_pri.Features & 0x20) /* page mode read supported */
197 features |= (1<<7);
198 if (atmel_pri.Features & 0x40) /* queued erase supported */
199 features |= (1<<4);
200 if (atmel_pri.Features & 0x80) /* Protection bits supported */
201 features |= (1<<6);
202
203 extp->FeatureSupport = features;
204
205 /* burst write mode not supported */
206 cfi->cfiq->BufWriteTimeoutTyp = 0;
207 cfi->cfiq->BufWriteTimeoutMax = 0;
208}
209
Guillaume LECERFcc318222010-11-17 12:35:50 +0100210static void fixup_at49bv640dx_lock(struct mtd_info *mtd)
Hans-Christian Egtvedt8dbaea42009-11-05 15:53:37 +0100211{
212 struct map_info *map = mtd->priv;
213 struct cfi_private *cfi = map->fldrv_priv;
214 struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
215
216 cfip->FeatureSupport |= (1 << 5);
217 mtd->flags |= MTD_POWERUP_LOCK;
218}
219
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000221/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
Guillaume LECERFcc318222010-11-17 12:35:50 +0100222static void fixup_intel_strataflash(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223{
224 struct map_info *map = mtd->priv;
225 struct cfi_private *cfi = map->fldrv_priv;
Alexander Belyakov91949d62008-05-04 14:32:58 +0400226 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
228 printk(KERN_WARNING "cfi_cmdset_0001: Suspend "
229 "erase on write disabled.\n");
230 extp->SuspendCmdSupport &= ~1;
231}
232#endif
233
234#ifdef CMDSET0001_DISABLE_WRITE_SUSPEND
Guillaume LECERFcc318222010-11-17 12:35:50 +0100235static void fixup_no_write_suspend(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236{
237 struct map_info *map = mtd->priv;
238 struct cfi_private *cfi = map->fldrv_priv;
239 struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
240
241 if (cfip && (cfip->FeatureSupport&4)) {
242 cfip->FeatureSupport &= ~4;
243 printk(KERN_WARNING "cfi_cmdset_0001: write suspend disabled\n");
244 }
245}
246#endif
247
Guillaume LECERFcc318222010-11-17 12:35:50 +0100248static void fixup_st_m28w320ct(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249{
250 struct map_info *map = mtd->priv;
251 struct cfi_private *cfi = map->fldrv_priv;
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000252
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 cfi->cfiq->BufWriteTimeoutTyp = 0; /* Not supported */
254 cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */
255}
256
Guillaume LECERFcc318222010-11-17 12:35:50 +0100257static void fixup_st_m28w320cb(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258{
259 struct map_info *map = mtd->priv;
260 struct cfi_private *cfi = map->fldrv_priv;
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000261
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 /* Note this is done after the region info is endian swapped */
263 cfi->cfiq->EraseRegionInfo[1] =
264 (cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e;
265};
266
Andrea Adami812c5fa2014-06-02 23:38:35 +0200267static int is_LH28F640BF(struct cfi_private *cfi)
268{
269 /* Sharp LH28F640BF Family */
270 if (cfi->mfr == CFI_MFR_SHARP && (
271 cfi->id == LH28F640BFHE_PTTL90 || cfi->id == LH28F640BFHE_PBTL90 ||
272 cfi->id == LH28F640BFHE_PTTL70A || cfi->id == LH28F640BFHE_PBTL70A))
273 return 1;
274 return 0;
275}
276
277static void fixup_LH28F640BF(struct mtd_info *mtd)
278{
279 struct map_info *map = mtd->priv;
280 struct cfi_private *cfi = map->fldrv_priv;
281 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
282
283 /* Reset the Partition Configuration Register on LH28F640BF
284 * to a single partition (PCR = 0x000): PCR is embedded into A0-A15. */
285 if (is_LH28F640BF(cfi)) {
286 printk(KERN_INFO "Reset Partition Config. Register: 1 Partition of 4 planes\n");
287 map_write(map, CMD(0x60), 0);
288 map_write(map, CMD(0x04), 0);
289
290 /* We have set one single partition thus
291 * Simultaneous Operations are not allowed */
292 printk(KERN_INFO "cfi_cmdset_0001: Simultaneous Operations disabled\n");
293 extp->FeatureSupport &= ~512;
294 }
295}
296
Guillaume LECERFcc318222010-11-17 12:35:50 +0100297static void fixup_use_point(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298{
299 struct map_info *map = mtd->priv;
Artem Bityutskiy3c3c10b2012-01-30 14:58:32 +0200300 if (!mtd->_point && map_is_linear(map)) {
301 mtd->_point = cfi_intelext_point;
302 mtd->_unpoint = cfi_intelext_unpoint;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 }
304}
305
Guillaume LECERFcc318222010-11-17 12:35:50 +0100306static void fixup_use_write_buffers(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307{
308 struct map_info *map = mtd->priv;
309 struct cfi_private *cfi = map->fldrv_priv;
310 if (cfi->cfiq->BufWriteTimeoutTyp) {
311 printk(KERN_INFO "Using buffer write method\n" );
Artem Bityutskiy3c3c10b2012-01-30 14:58:32 +0200312 mtd->_write = cfi_intelext_write_buffers;
313 mtd->_writev = cfi_intelext_writev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 }
315}
316
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -0800317/*
318 * Some chips power-up with all sectors locked by default.
319 */
Guillaume LECERFcc318222010-11-17 12:35:50 +0100320static void fixup_unlock_powerup_lock(struct mtd_info *mtd)
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -0800321{
Justin Treone619a752008-01-30 10:25:49 -0800322 struct map_info *map = mtd->priv;
323 struct cfi_private *cfi = map->fldrv_priv;
324 struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
325
326 if (cfip->FeatureSupport&32) {
327 printk(KERN_INFO "Using auto-unlock on power-up/resume\n" );
328 mtd->flags |= MTD_POWERUP_LOCK;
329 }
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -0800330}
331
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332static struct cfi_fixup cfi_fixup_table[] = {
Guillaume LECERFcc318222010-11-17 12:35:50 +0100333 { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri },
334 { CFI_MFR_ATMEL, AT49BV640D, fixup_at49bv640dx_lock },
335 { CFI_MFR_ATMEL, AT49BV640DT, fixup_at49bv640dx_lock },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
Guillaume LECERFcc318222010-11-17 12:35:50 +0100337 { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338#endif
339#ifdef CMDSET0001_DISABLE_WRITE_SUSPEND
Guillaume LECERFcc318222010-11-17 12:35:50 +0100340 { CFI_MFR_ANY, CFI_ID_ANY, fixup_no_write_suspend },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341#endif
342#if !FORCE_WORD_WRITE
Guillaume LECERFcc318222010-11-17 12:35:50 +0100343 { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344#endif
Guillaume LECERFcc318222010-11-17 12:35:50 +0100345 { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct },
346 { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb },
347 { CFI_MFR_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock },
Andrea Adami812c5fa2014-06-02 23:38:35 +0200348 { CFI_MFR_SHARP, CFI_ID_ANY, fixup_unlock_powerup_lock },
349 { CFI_MFR_SHARP, CFI_ID_ANY, fixup_LH28F640BF },
Guillaume LECERFcc318222010-11-17 12:35:50 +0100350 { 0, 0, NULL }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351};
352
353static struct cfi_fixup jedec_fixup_table[] = {
Guillaume LECERFcc318222010-11-17 12:35:50 +0100354 { CFI_MFR_INTEL, I82802AB, fixup_use_fwh_lock },
355 { CFI_MFR_INTEL, I82802AC, fixup_use_fwh_lock },
356 { CFI_MFR_ST, M50LPW080, fixup_use_fwh_lock },
357 { CFI_MFR_ST, M50FLW080A, fixup_use_fwh_lock },
358 { CFI_MFR_ST, M50FLW080B, fixup_use_fwh_lock },
359 { 0, 0, NULL }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360};
361static struct cfi_fixup fixup_table[] = {
362 /* The CFI vendor ids and the JEDEC vendor IDs appear
363 * to be common. It is like the devices id's are as
364 * well. This table is to pick all cases where
365 * we know that is the case.
366 */
Guillaume LECERFcc318222010-11-17 12:35:50 +0100367 { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point },
368 { 0, 0, NULL }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369};
370
Daniel Ribeiroec2d0d82009-05-17 08:02:17 -0300371static void cfi_fixup_major_minor(struct cfi_private *cfi,
372 struct cfi_pri_intelext *extp)
373{
Hans-Christian Egtvedtb2ef1a22009-11-05 15:53:43 +0100374 if (cfi->mfr == CFI_MFR_INTEL &&
Daniel Ribeiroec2d0d82009-05-17 08:02:17 -0300375 cfi->id == PF38F4476 && extp->MinorVersion == '3')
376 extp->MinorVersion = '1';
377}
378
Joakim Tjernlund0d8f3792018-03-01 14:39:40 +0100379static int cfi_is_micron_28F00AP30(struct cfi_private *cfi, struct flchip *chip)
380{
381 /*
382 * Micron(was Numonyx) 1Gbit bottom boot are buggy w.r.t
383 * Erase Supend for their small Erase Blocks(0x8000)
384 */
385 if (cfi->mfr == CFI_MFR_INTEL && cfi->id == M28F00AP30)
386 return 1;
387 return 0;
388}
389
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390static inline struct cfi_pri_intelext *
391read_pri_intelext(struct map_info *map, __u16 adr)
392{
Daniel Ribeiroec2d0d82009-05-17 08:02:17 -0300393 struct cfi_private *cfi = map->fldrv_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 struct cfi_pri_intelext *extp;
Daniel Ribeiroe1b158a2009-05-17 08:02:08 -0300395 unsigned int extra_size = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 unsigned int extp_size = sizeof(*extp);
397
398 again:
399 extp = (struct cfi_pri_intelext *)cfi_read_pri(map, adr, extp_size, "Intel/Sharp");
400 if (!extp)
401 return NULL;
402
Daniel Ribeiroec2d0d82009-05-17 08:02:17 -0300403 cfi_fixup_major_minor(cfi, extp);
404
Todd Poynord88f9772005-07-20 22:01:17 +0100405 if (extp->MajorVersion != '1' ||
Alexey Korolevb1c9c9b2007-11-23 09:31:56 +0000406 (extp->MinorVersion < '0' || extp->MinorVersion > '5')) {
Todd Poynord88f9772005-07-20 22:01:17 +0100407 printk(KERN_ERR " Unknown Intel/Sharp Extended Query "
408 "version %c.%c.\n", extp->MajorVersion,
409 extp->MinorVersion);
410 kfree(extp);
411 return NULL;
412 }
413
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 /* Do some byteswapping if necessary */
415 extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport);
416 extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask);
417 extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr);
418
Daniel Ribeiroe1b158a2009-05-17 08:02:08 -0300419 if (extp->MinorVersion >= '0') {
420 extra_size = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
422 /* Protection Register info */
Nicolas Pitre72b56a22005-02-05 02:06:19 +0000423 extra_size += (extp->NumProtectionFields - 1) *
424 sizeof(struct cfi_intelext_otpinfo);
Daniel Ribeiroe1b158a2009-05-17 08:02:08 -0300425 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
Daniel Ribeiroe1b158a2009-05-17 08:02:08 -0300427 if (extp->MinorVersion >= '1') {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 /* Burst Read info */
Nicolas Pitre6f6ed052005-10-25 21:28:43 +0100429 extra_size += 2;
430 if (extp_size < sizeof(*extp) + extra_size)
431 goto need_more;
Daniel Ribeiroe1b158a2009-05-17 08:02:08 -0300432 extra_size += extp->extra[extra_size - 1];
433 }
434
435 if (extp->MinorVersion >= '3') {
436 int nb_parts, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
438 /* Number of hardware-partitions */
439 extra_size += 1;
440 if (extp_size < sizeof(*extp) + extra_size)
441 goto need_more;
442 nb_parts = extp->extra[extra_size - 1];
443
Nicolas Pitre638d9832005-08-06 05:40:46 +0100444 /* skip the sizeof(partregion) field in CFI 1.4 */
445 if (extp->MinorVersion >= '4')
446 extra_size += 2;
447
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 for (i = 0; i < nb_parts; i++) {
449 struct cfi_intelext_regioninfo *rinfo;
450 rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size];
451 extra_size += sizeof(*rinfo);
452 if (extp_size < sizeof(*extp) + extra_size)
453 goto need_more;
454 rinfo->NumIdentPartitions=le16_to_cpu(rinfo->NumIdentPartitions);
455 extra_size += (rinfo->NumBlockTypes - 1)
456 * sizeof(struct cfi_intelext_blockinfo);
457 }
458
Nicolas Pitre638d9832005-08-06 05:40:46 +0100459 if (extp->MinorVersion >= '4')
460 extra_size += sizeof(struct cfi_intelext_programming_regioninfo);
461
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 if (extp_size < sizeof(*extp) + extra_size) {
463 need_more:
464 extp_size = sizeof(*extp) + extra_size;
465 kfree(extp);
466 if (extp_size > 4096) {
467 printk(KERN_ERR
468 "%s: cfi_pri_intelext is too fat\n",
Harvey Harrisoncb53b3b2008-04-18 13:44:19 -0700469 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 return NULL;
471 }
472 goto again;
473 }
474 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 return extp;
477}
478
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
480{
481 struct cfi_private *cfi = map->fldrv_priv;
482 struct mtd_info *mtd;
483 int i;
484
Burman Yan95b93a02006-11-15 21:10:29 +0200485 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
Jingoo Han5c8b1fb2014-02-06 15:19:35 +0900486 if (!mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 mtd->priv = map;
489 mtd->type = MTD_NORFLASH;
490
491 /* Fill in the default mtd operations */
Artem Bityutskiy3c3c10b2012-01-30 14:58:32 +0200492 mtd->_erase = cfi_intelext_erase_varsize;
493 mtd->_read = cfi_intelext_read;
494 mtd->_write = cfi_intelext_write_words;
495 mtd->_sync = cfi_intelext_sync;
496 mtd->_lock = cfi_intelext_lock;
497 mtd->_unlock = cfi_intelext_unlock;
498 mtd->_is_locked = cfi_intelext_is_locked;
499 mtd->_suspend = cfi_intelext_suspend;
500 mtd->_resume = cfi_intelext_resume;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 mtd->flags = MTD_CAP_NORFLASH;
502 mtd->name = map->name;
Artem B. Bityutskiy17ffc7b2006-06-22 18:15:48 +0400503 mtd->writesize = 1;
Anatolij Gustschin13ce77f2011-02-10 16:01:46 +0100504 mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
Nicolas Pitre963a6fb2005-04-01 02:59:56 +0100505
506 mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
507
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 if (cfi->cfi_mode == CFI_MODE_CFI) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000509 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 * It's a real CFI chip, not one for which the probe
511 * routine faked a CFI structure. So we read the feature
512 * table from it.
513 */
514 __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
515 struct cfi_pri_intelext *extp;
516
517 extp = read_pri_intelext(map, adr);
518 if (!extp) {
519 kfree(mtd);
520 return NULL;
521 }
522
523 /* Install our own private info structure */
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000524 cfi->cmdset_priv = extp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
526 cfi_fixup(mtd, cfi_fixup_table);
527
528#ifdef DEBUG_CFI_FEATURES
529 /* Tell the user about it in lots of lovely detail */
530 cfi_tell_features(extp);
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000531#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
533 if(extp->SuspendCmdSupport & 1) {
534 printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n");
535 }
536 }
537 else if (cfi->cfi_mode == CFI_MODE_JEDEC) {
538 /* Apply jedec specific fixups */
539 cfi_fixup(mtd, jedec_fixup_table);
540 }
541 /* Apply generic fixups */
542 cfi_fixup(mtd, fixup_table);
543
544 for (i=0; i< cfi->numchips; i++) {
David Woodhouse2a5bd592007-02-09 14:39:10 +0000545 if (cfi->cfiq->WordWriteTimeoutTyp)
546 cfi->chips[i].word_write_time =
547 1<<cfi->cfiq->WordWriteTimeoutTyp;
548 else
549 cfi->chips[i].word_write_time = 50000;
550
551 if (cfi->cfiq->BufWriteTimeoutTyp)
552 cfi->chips[i].buffer_write_time =
553 1<<cfi->cfiq->BufWriteTimeoutTyp;
554 /* No default; if it isn't specified, we won't use it */
555
556 if (cfi->cfiq->BlockEraseTimeoutTyp)
557 cfi->chips[i].erase_time =
558 1000<<cfi->cfiq->BlockEraseTimeoutTyp;
559 else
560 cfi->chips[i].erase_time = 2000000;
561
Anders Grafströme93cafe2008-08-05 18:37:41 +0200562 if (cfi->cfiq->WordWriteTimeoutTyp &&
563 cfi->cfiq->WordWriteTimeoutMax)
564 cfi->chips[i].word_write_time_max =
565 1<<(cfi->cfiq->WordWriteTimeoutTyp +
566 cfi->cfiq->WordWriteTimeoutMax);
567 else
568 cfi->chips[i].word_write_time_max = 50000 * 8;
569
570 if (cfi->cfiq->BufWriteTimeoutTyp &&
571 cfi->cfiq->BufWriteTimeoutMax)
572 cfi->chips[i].buffer_write_time_max =
573 1<<(cfi->cfiq->BufWriteTimeoutTyp +
574 cfi->cfiq->BufWriteTimeoutMax);
575
576 if (cfi->cfiq->BlockEraseTimeoutTyp &&
577 cfi->cfiq->BlockEraseTimeoutMax)
578 cfi->chips[i].erase_time_max =
579 1000<<(cfi->cfiq->BlockEraseTimeoutTyp +
580 cfi->cfiq->BlockEraseTimeoutMax);
581 else
582 cfi->chips[i].erase_time_max = 2000000 * 8;
583
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 cfi->chips[i].ref_point_counter = 0;
Simon Voglc314b6f2006-02-24 13:04:09 -0800585 init_waitqueue_head(&(cfi->chips[i].wq));
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
588 map->fldrv = &cfi_intelext_chipdrv;
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000589
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 return cfi_intelext_setup(mtd);
591}
David Woodhousea15bdee2006-05-08 22:35:05 +0100592struct mtd_info *cfi_cmdset_0003(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0001")));
593struct mtd_info *cfi_cmdset_0200(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0001")));
594EXPORT_SYMBOL_GPL(cfi_cmdset_0001);
595EXPORT_SYMBOL_GPL(cfi_cmdset_0003);
596EXPORT_SYMBOL_GPL(cfi_cmdset_0200);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597
598static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
599{
600 struct map_info *map = mtd->priv;
601 struct cfi_private *cfi = map->fldrv_priv;
602 unsigned long offset = 0;
603 int i,j;
604 unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
605
606 //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
607
608 mtd->size = devsize * cfi->numchips;
609
610 mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
Insu Yun33853eb2015-12-29 13:45:09 -0500611 mtd->eraseregions = kzalloc(sizeof(struct mtd_erase_region_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 * mtd->numeraseregions, GFP_KERNEL);
Jingoo Han5c8b1fb2014-02-06 15:19:35 +0900613 if (!mtd->eraseregions)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 goto setup_err;
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000615
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
617 unsigned long ernum, ersize;
618 ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
619 ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
620
621 if (mtd->erasesize < ersize) {
622 mtd->erasesize = ersize;
623 }
624 for (j=0; j<cfi->numchips; j++) {
625 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
626 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
627 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -0800628 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap = kmalloc(ernum / 8 + 1, GFP_KERNEL);
Insu Yun33853eb2015-12-29 13:45:09 -0500629 if (!mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap)
630 goto setup_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 }
632 offset += (ersize * ernum);
633 }
634
635 if (offset != devsize) {
636 /* Argh */
637 printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
638 goto setup_err;
639 }
640
641 for (i=0; i<mtd->numeraseregions;i++){
Adrian Hunter69423d92008-12-10 13:37:21 +0000642 printk(KERN_DEBUG "erase region %d: offset=0x%llx,size=0x%x,blocks=%d\n",
643 i,(unsigned long long)mtd->eraseregions[i].offset,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 mtd->eraseregions[i].erasesize,
645 mtd->eraseregions[i].numblocks);
646 }
647
Nicolas Pitref77814d2005-02-08 17:11:19 +0000648#ifdef CONFIG_MTD_OTP
Artem Bityutskiy3c3c10b2012-01-30 14:58:32 +0200649 mtd->_read_fact_prot_reg = cfi_intelext_read_fact_prot_reg;
650 mtd->_read_user_prot_reg = cfi_intelext_read_user_prot_reg;
651 mtd->_write_user_prot_reg = cfi_intelext_write_user_prot_reg;
652 mtd->_lock_user_prot_reg = cfi_intelext_lock_user_prot_reg;
653 mtd->_get_fact_prot_info = cfi_intelext_get_fact_prot_info;
654 mtd->_get_user_prot_info = cfi_intelext_get_user_prot_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655#endif
656
657 /* This function has the potential to distort the reality
658 a bit and therefore should be called last. */
659 if (cfi_intelext_partition_fixup(mtd, &cfi) != 0)
660 goto setup_err;
661
662 __module_get(THIS_MODULE);
Nicolas Pitre963a6fb2005-04-01 02:59:56 +0100663 register_reboot_notifier(&mtd->reboot_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 return mtd;
665
666 setup_err:
Insu Yun33853eb2015-12-29 13:45:09 -0500667 if (mtd->eraseregions)
668 for (i=0; i<cfi->cfiq->NumEraseRegions; i++)
669 for (j=0; j<cfi->numchips; j++)
670 kfree(mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap);
Jiri Slaby17fabf12010-01-10 10:01:19 +0100671 kfree(mtd->eraseregions);
672 kfree(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 kfree(cfi->cmdset_priv);
674 return NULL;
675}
676
677static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
678 struct cfi_private **pcfi)
679{
680 struct map_info *map = mtd->priv;
681 struct cfi_private *cfi = *pcfi;
682 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
683
684 /*
Jesper Juhl8f1a8662007-07-05 02:18:34 +0200685 * Probing of multi-partition flash chips.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 *
687 * To support multiple partitions when available, we simply arrange
688 * for each of them to have their own flchip structure even if they
689 * are on the same physical chip. This means completely recreating
690 * a new cfi_private structure right here which is a blatent code
691 * layering violation, but this is still the least intrusive
692 * arrangement at this point. This can be rearranged in the future
693 * if someone feels motivated enough. --nico
694 */
Nicolas Pitre638d9832005-08-06 05:40:46 +0100695 if (extp && extp->MajorVersion == '1' && extp->MinorVersion >= '3'
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 && extp->FeatureSupport & (1 << 9)) {
697 struct cfi_private *newcfi;
698 struct flchip *chip;
699 struct flchip_shared *shared;
700 int offs, numregions, numparts, partshift, numvirtchips, i, j;
701
702 /* Protection Register info */
Nicolas Pitre72b56a22005-02-05 02:06:19 +0000703 offs = (extp->NumProtectionFields - 1) *
704 sizeof(struct cfi_intelext_otpinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
706 /* Burst Read info */
Nicolas Pitre6f6ed052005-10-25 21:28:43 +0100707 offs += extp->extra[offs+1]+2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709 /* Number of partition regions */
710 numregions = extp->extra[offs];
711 offs += 1;
712
Nicolas Pitre638d9832005-08-06 05:40:46 +0100713 /* skip the sizeof(partregion) field in CFI 1.4 */
714 if (extp->MinorVersion >= '4')
715 offs += 2;
716
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 /* Number of hardware partitions */
718 numparts = 0;
719 for (i = 0; i < numregions; i++) {
720 struct cfi_intelext_regioninfo *rinfo;
721 rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[offs];
722 numparts += rinfo->NumIdentPartitions;
723 offs += sizeof(*rinfo)
724 + (rinfo->NumBlockTypes - 1) *
725 sizeof(struct cfi_intelext_blockinfo);
726 }
727
Thomas Kunzefe224662008-04-23 01:40:52 +0200728 if (!numparts)
729 numparts = 1;
730
Nicolas Pitre638d9832005-08-06 05:40:46 +0100731 /* Programming Region info */
732 if (extp->MinorVersion >= '4') {
733 struct cfi_intelext_programming_regioninfo *prinfo;
734 prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs];
Joern Engel28318772006-05-22 23:18:05 +0200735 mtd->writesize = cfi->interleave << prinfo->ProgRegShift;
Joern Engel5fa43392006-05-22 23:18:29 +0200736 mtd->flags &= ~MTD_BIT_WRITEABLE;
Nicolas Pitre638d9832005-08-06 05:40:46 +0100737 printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n",
Joern Engel28318772006-05-22 23:18:05 +0200738 map->name, mtd->writesize,
Artem Bityutskiyd4160852007-01-30 10:45:55 +0200739 cfi->interleave * prinfo->ControlValid,
740 cfi->interleave * prinfo->ControlInvalid);
Nicolas Pitre638d9832005-08-06 05:40:46 +0100741 }
742
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 /*
744 * All functions below currently rely on all chips having
745 * the same geometry so we'll just assume that all hardware
746 * partitions are of the same size too.
747 */
748 partshift = cfi->chipshift - __ffs(numparts);
749
750 if ((1 << partshift) < mtd->erasesize) {
751 printk( KERN_ERR
752 "%s: bad number of hw partitions (%d)\n",
Harvey Harrisoncb53b3b2008-04-18 13:44:19 -0700753 __func__, numparts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 return -EINVAL;
755 }
756
757 numvirtchips = cfi->numchips * numparts;
758 newcfi = kmalloc(sizeof(struct cfi_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL);
759 if (!newcfi)
760 return -ENOMEM;
761 shared = kmalloc(sizeof(struct flchip_shared) * cfi->numchips, GFP_KERNEL);
762 if (!shared) {
763 kfree(newcfi);
764 return -ENOMEM;
765 }
766 memcpy(newcfi, cfi, sizeof(struct cfi_private));
767 newcfi->numchips = numvirtchips;
768 newcfi->chipshift = partshift;
769
770 chip = &newcfi->chips[0];
771 for (i = 0; i < cfi->numchips; i++) {
772 shared[i].writing = shared[i].erasing = NULL;
Stefani Seibold8ae66412010-08-05 09:19:26 +0200773 mutex_init(&shared[i].lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 for (j = 0; j < numparts; j++) {
775 *chip = cfi->chips[i];
776 chip->start += j << partshift;
777 chip->priv = &shared[i];
778 /* those should be reset too since
779 they create memory references. */
780 init_waitqueue_head(&chip->wq);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200781 mutex_init(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 chip++;
783 }
784 }
785
786 printk(KERN_DEBUG "%s: %d set(s) of %d interleaved chips "
787 "--> %d partitions of %d KiB\n",
788 map->name, cfi->numchips, cfi->interleave,
789 newcfi->numchips, 1<<(newcfi->chipshift-10));
790
791 map->fldrv_priv = newcfi;
792 *pcfi = newcfi;
793 kfree(cfi);
794 }
795
796 return 0;
797}
798
799/*
800 * *********** CHIP ACCESS FUNCTIONS ***********
801 */
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100802static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803{
804 DECLARE_WAITQUEUE(wait, current);
805 struct cfi_private *cfi = map->fldrv_priv;
806 map_word status, status_OK = CMD(0x80), status_PWS = CMD(0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100808 unsigned long timeo = jiffies + HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809
Alexander Belyakov3afe7eb2008-09-25 17:53:24 +0400810 /* Prevent setting state FL_SYNCING for chip in suspended state. */
811 if (mode == FL_SYNCING && chip->oldstate != FL_READY)
812 goto sleep;
813
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 switch (chip->state) {
815
816 case FL_STATUS:
817 for (;;) {
818 status = map_read(map, adr);
819 if (map_word_andequal(map, status, status_OK, status_OK))
820 break;
821
822 /* At this point we're fine with write operations
823 in other partitions as they don't conflict. */
824 if (chip->priv && map_word_andequal(map, status, status_PWS, status_PWS))
825 break;
826
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200827 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 cfi_udelay(1);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200829 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 /* Someone else might have been playing with it. */
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100831 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 }
Alexey Korolevfb6d0802008-04-04 14:30:01 -0700833 /* Fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 case FL_READY:
835 case FL_CFI_QUERY:
836 case FL_JEDEC_QUERY:
837 return 0;
838
839 case FL_ERASING:
840 if (!cfip ||
841 !(cfip->FeatureSupport & 2) ||
842 !(mode == FL_READY || mode == FL_POINT ||
843 (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1))))
844 goto sleep;
845
Joakim Tjernlund54a21fe2018-03-01 14:39:39 +0100846 /* Do not allow suspend iff read/write to EB address */
847 if ((adr & chip->in_progress_block_mask) ==
848 chip->in_progress_block_addr)
849 goto sleep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850
Joakim Tjernlund0d8f3792018-03-01 14:39:40 +0100851 /* do not suspend small EBs, buggy Micron Chips */
852 if (cfi_is_micron_28F00AP30(cfi, chip) &&
853 (chip->in_progress_block_mask == ~(0x8000-1)))
854 goto sleep;
855
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 /* Erase suspend */
Joakim Tjernlund54a21fe2018-03-01 14:39:39 +0100857 map_write(map, CMD(0xB0), chip->in_progress_block_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858
859 /* If the flash has finished erasing, then 'erase suspend'
860 * appears to make some (28F320) flash devices switch to
861 * 'read' mode. Make sure that we switch to 'read status'
862 * mode so we get the right data. --rmk
863 */
Joakim Tjernlund54a21fe2018-03-01 14:39:39 +0100864 map_write(map, CMD(0x70), chip->in_progress_block_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 chip->oldstate = FL_ERASING;
866 chip->state = FL_ERASE_SUSPENDING;
867 chip->erase_suspended = 1;
868 for (;;) {
Joakim Tjernlund54a21fe2018-03-01 14:39:39 +0100869 status = map_read(map, chip->in_progress_block_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 if (map_word_andequal(map, status, status_OK, status_OK))
871 break;
872
873 if (time_after(jiffies, timeo)) {
Tadashi Abe100f2342011-05-19 15:58:15 +0900874 /* Urgh. Resume and pretend we weren't here.
875 * Make sure we're in 'read status' mode if it had finished */
876 put_chip(map, chip, adr);
Nicolas Pitre48436532005-08-06 05:16:52 +0100877 printk(KERN_ERR "%s: Chip not ready after erase "
878 "suspended: status = 0x%lx\n", map->name, status.x[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 return -EIO;
880 }
881
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200882 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 cfi_udelay(1);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200884 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 /* Nobody will touch it while it's in state FL_ERASE_SUSPENDING.
886 So we can just loop here. */
887 }
888 chip->state = FL_STATUS;
889 return 0;
890
891 case FL_XIP_WHILE_ERASING:
892 if (mode != FL_READY && mode != FL_POINT &&
893 (mode != FL_WRITING || !cfip || !(cfip->SuspendCmdSupport&1)))
894 goto sleep;
895 chip->oldstate = chip->state;
896 chip->state = FL_READY;
897 return 0;
898
Alexey Korolevfb6d0802008-04-04 14:30:01 -0700899 case FL_SHUTDOWN:
900 /* The machine is rebooting now,so no one can get chip anymore */
901 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 case FL_POINT:
903 /* Only if there's no operation suspended... */
904 if (mode == FL_READY && chip->oldstate == FL_READY)
905 return 0;
Alexey Korolevfb6d0802008-04-04 14:30:01 -0700906 /* Fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 default:
908 sleep:
909 set_current_state(TASK_UNINTERRUPTIBLE);
910 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200911 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 schedule();
913 remove_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200914 mutex_lock(&chip->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100915 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 }
917}
918
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100919static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
920{
921 int ret;
Alexander Belyakov6c24e412007-11-07 11:58:07 +0300922 DECLARE_WAITQUEUE(wait, current);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100923
924 retry:
Alexander Belyakov3afe7eb2008-09-25 17:53:24 +0400925 if (chip->priv &&
926 (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE
927 || mode == FL_SHUTDOWN) && chip->state != FL_SYNCING) {
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100928 /*
929 * OK. We have possibility for contention on the write/erase
930 * operations which are global to the real chip and not per
931 * partition. So let's fight it over in the partition which
932 * currently has authority on the operation.
933 *
934 * The rules are as follows:
935 *
936 * - any write operation must own shared->writing.
937 *
938 * - any erase operation must own _both_ shared->writing and
939 * shared->erasing.
940 *
941 * - contention arbitration is handled in the owner's context.
942 *
943 * The 'shared' struct can be read and/or written only when
944 * its lock is taken.
945 */
946 struct flchip_shared *shared = chip->priv;
947 struct flchip *contender;
Stefani Seibold8ae66412010-08-05 09:19:26 +0200948 mutex_lock(&shared->lock);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100949 contender = shared->writing;
950 if (contender && contender != chip) {
951 /*
952 * The engine to perform desired operation on this
953 * partition is already in use by someone else.
954 * Let's fight over it in the context of the chip
955 * currently using it. If it is possible to suspend,
956 * that other partition will do just that, otherwise
957 * it'll happily send us to sleep. In any case, when
958 * get_chip returns success we're clear to go ahead.
959 */
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200960 ret = mutex_trylock(&contender->mutex);
Stefani Seibold8ae66412010-08-05 09:19:26 +0200961 mutex_unlock(&shared->lock);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100962 if (!ret)
963 goto retry;
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200964 mutex_unlock(&chip->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100965 ret = chip_ready(map, contender, contender->start, mode);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200966 mutex_lock(&chip->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100967
968 if (ret == -EAGAIN) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200969 mutex_unlock(&contender->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100970 goto retry;
971 }
972 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200973 mutex_unlock(&contender->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100974 return ret;
975 }
Stefani Seibold8ae66412010-08-05 09:19:26 +0200976 mutex_lock(&shared->lock);
Alexander Belyakov3afe7eb2008-09-25 17:53:24 +0400977
978 /* We should not own chip if it is already
979 * in FL_SYNCING state. Put contender and retry. */
980 if (chip->state == FL_SYNCING) {
981 put_chip(map, contender, contender->start);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200982 mutex_unlock(&contender->mutex);
Alexander Belyakov3afe7eb2008-09-25 17:53:24 +0400983 goto retry;
984 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200985 mutex_unlock(&contender->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100986 }
987
Alexander Belyakov6c24e412007-11-07 11:58:07 +0300988 /* Check if we already have suspended erase
989 * on this chip. Sleep. */
990 if (mode == FL_ERASING && shared->erasing
991 && shared->erasing->oldstate == FL_ERASING) {
Stefani Seibold8ae66412010-08-05 09:19:26 +0200992 mutex_unlock(&shared->lock);
Alexander Belyakov6c24e412007-11-07 11:58:07 +0300993 set_current_state(TASK_UNINTERRUPTIBLE);
994 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200995 mutex_unlock(&chip->mutex);
Alexander Belyakov6c24e412007-11-07 11:58:07 +0300996 schedule();
997 remove_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200998 mutex_lock(&chip->mutex);
Alexander Belyakov6c24e412007-11-07 11:58:07 +0300999 goto retry;
1000 }
1001
Alexey Korolev5a37cf12007-10-22 17:55:20 +01001002 /* We now own it */
1003 shared->writing = chip;
1004 if (mode == FL_ERASING)
1005 shared->erasing = chip;
Stefani Seibold8ae66412010-08-05 09:19:26 +02001006 mutex_unlock(&shared->lock);
Alexey Korolev5a37cf12007-10-22 17:55:20 +01001007 }
1008 ret = chip_ready(map, chip, adr, mode);
1009 if (ret == -EAGAIN)
1010 goto retry;
1011
1012 return ret;
1013}
1014
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr)
1016{
1017 struct cfi_private *cfi = map->fldrv_priv;
1018
1019 if (chip->priv) {
1020 struct flchip_shared *shared = chip->priv;
Stefani Seibold8ae66412010-08-05 09:19:26 +02001021 mutex_lock(&shared->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 if (shared->writing == chip && chip->oldstate == FL_READY) {
1023 /* We own the ability to write, but we're done */
1024 shared->writing = shared->erasing;
1025 if (shared->writing && shared->writing != chip) {
1026 /* give back ownership to who we loaned it from */
1027 struct flchip *loaner = shared->writing;
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001028 mutex_lock(&loaner->mutex);
Stefani Seibold8ae66412010-08-05 09:19:26 +02001029 mutex_unlock(&shared->lock);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001030 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 put_chip(map, loaner, loaner->start);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001032 mutex_lock(&chip->mutex);
1033 mutex_unlock(&loaner->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 wake_up(&chip->wq);
1035 return;
1036 }
1037 shared->erasing = NULL;
1038 shared->writing = NULL;
1039 } else if (shared->erasing == chip && shared->writing != chip) {
1040 /*
1041 * We own the ability to erase without the ability
1042 * to write, which means the erase was suspended
1043 * and some other partition is currently writing.
1044 * Don't let the switch below mess things up since
1045 * we don't have ownership to resume anything.
1046 */
Stefani Seibold8ae66412010-08-05 09:19:26 +02001047 mutex_unlock(&shared->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 wake_up(&chip->wq);
1049 return;
1050 }
Stefani Seibold8ae66412010-08-05 09:19:26 +02001051 mutex_unlock(&shared->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 }
1053
1054 switch(chip->oldstate) {
1055 case FL_ERASING:
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001056 /* What if one interleaved chip has finished and the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 other hasn't? The old code would leave the finished
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001058 one in READY mode. That's bad, and caused -EROFS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 errors to be returned from do_erase_oneblock because
1060 that's the only bit it checked for at the time.
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001061 As the state machine appears to explicitly allow
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 sending the 0x70 (Read Status) command to an erasing
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001063 chip and expecting it to be ignored, that's what we
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 do. */
Joakim Tjernlund54a21fe2018-03-01 14:39:39 +01001065 map_write(map, CMD(0xd0), chip->in_progress_block_addr);
1066 map_write(map, CMD(0x70), chip->in_progress_block_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 chip->oldstate = FL_READY;
1068 chip->state = FL_ERASING;
1069 break;
1070
1071 case FL_XIP_WHILE_ERASING:
1072 chip->state = chip->oldstate;
1073 chip->oldstate = FL_READY;
1074 break;
1075
1076 case FL_READY:
1077 case FL_STATUS:
1078 case FL_JEDEC_QUERY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 break;
1080 default:
Nicolas Pitre48436532005-08-06 05:16:52 +01001081 printk(KERN_ERR "%s: put_chip() called with oldstate %d!!\n", map->name, chip->oldstate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 }
1083 wake_up(&chip->wq);
1084}
1085
1086#ifdef CONFIG_MTD_XIP
1087
1088/*
1089 * No interrupt what so ever can be serviced while the flash isn't in array
1090 * mode. This is ensured by the xip_disable() and xip_enable() functions
1091 * enclosing any code path where the flash is known not to be in array mode.
1092 * And within a XIP disabled code path, only functions marked with __xipram
1093 * may be called and nothing else (it's a good thing to inspect generated
1094 * assembly to make sure inline functions were actually inlined and that gcc
1095 * didn't emit calls to its own support functions). Also configuring MTD CFI
1096 * support to a single buswidth and a single interleave is also recommended.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 */
1098
1099static void xip_disable(struct map_info *map, struct flchip *chip,
1100 unsigned long adr)
1101{
1102 /* TODO: chips with no XIP use should ignore and return */
1103 (void) map_read(map, adr); /* ensure mmu mapping is up to date */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 local_irq_disable();
1105}
1106
1107static void __xipram xip_enable(struct map_info *map, struct flchip *chip,
1108 unsigned long adr)
1109{
1110 struct cfi_private *cfi = map->fldrv_priv;
1111 if (chip->state != FL_POINT && chip->state != FL_READY) {
1112 map_write(map, CMD(0xff), adr);
1113 chip->state = FL_READY;
1114 }
1115 (void) map_read(map, adr);
Thomas Gleixner97f927a2005-07-07 16:50:16 +02001116 xip_iprefetch();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 local_irq_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118}
1119
1120/*
1121 * When a delay is required for the flash operation to complete, the
Nicolas Pitrec1724712006-03-30 15:52:41 +01001122 * xip_wait_for_operation() function is polling for both the given timeout
1123 * and pending (but still masked) hardware interrupts. Whenever there is an
1124 * interrupt pending then the flash erase or write operation is suspended,
1125 * array mode restored and interrupts unmasked. Task scheduling might also
1126 * happen at that point. The CPU eventually returns from the interrupt or
1127 * the call to schedule() and the suspended flash operation is resumed for
1128 * the remaining of the delay period.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 *
1130 * Warning: this function _will_ fool interrupt latency tracing tools.
1131 */
1132
Nicolas Pitrec1724712006-03-30 15:52:41 +01001133static int __xipram xip_wait_for_operation(
1134 struct map_info *map, struct flchip *chip,
Anders Grafströme93cafe2008-08-05 18:37:41 +02001135 unsigned long adr, unsigned int chip_op_time_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136{
1137 struct cfi_private *cfi = map->fldrv_priv;
1138 struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
1139 map_word status, OK = CMD(0x80);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001140 unsigned long usec, suspended, start, done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 flstate_t oldstate, newstate;
1142
Nicolas Pitrec1724712006-03-30 15:52:41 +01001143 start = xip_currtime();
Anders Grafströme93cafe2008-08-05 18:37:41 +02001144 usec = chip_op_time_max;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001145 if (usec == 0)
1146 usec = 500000;
1147 done = 0;
1148
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 do {
1150 cpu_relax();
1151 if (xip_irqpending() && cfip &&
1152 ((chip->state == FL_ERASING && (cfip->FeatureSupport&2)) ||
1153 (chip->state == FL_WRITING && (cfip->FeatureSupport&4))) &&
1154 (cfi_interleave_is_1(cfi) || chip->oldstate == FL_READY)) {
1155 /*
1156 * Let's suspend the erase or write operation when
1157 * supported. Note that we currently don't try to
1158 * suspend interleaved chips if there is already
1159 * another operation suspended (imagine what happens
1160 * when one chip was already done with the current
1161 * operation while another chip suspended it, then
1162 * we resume the whole thing at once). Yes, it
1163 * can happen!
1164 */
Nicolas Pitrec1724712006-03-30 15:52:41 +01001165 usec -= done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 map_write(map, CMD(0xb0), adr);
1167 map_write(map, CMD(0x70), adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 suspended = xip_currtime();
1169 do {
1170 if (xip_elapsed_since(suspended) > 100000) {
1171 /*
1172 * The chip doesn't want to suspend
1173 * after waiting for 100 msecs.
1174 * This is a critical error but there
1175 * is not much we can do here.
1176 */
Nicolas Pitrec1724712006-03-30 15:52:41 +01001177 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 }
1179 status = map_read(map, adr);
1180 } while (!map_word_andequal(map, status, OK, OK));
1181
1182 /* Suspend succeeded */
1183 oldstate = chip->state;
1184 if (oldstate == FL_ERASING) {
1185 if (!map_word_bitsset(map, status, CMD(0x40)))
1186 break;
1187 newstate = FL_XIP_WHILE_ERASING;
1188 chip->erase_suspended = 1;
1189 } else {
1190 if (!map_word_bitsset(map, status, CMD(0x04)))
1191 break;
1192 newstate = FL_XIP_WHILE_WRITING;
1193 chip->write_suspended = 1;
1194 }
1195 chip->state = newstate;
1196 map_write(map, CMD(0xff), adr);
1197 (void) map_read(map, adr);
Paulius Zaleckasca5c23c2008-02-27 01:42:39 +02001198 xip_iprefetch();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 local_irq_enable();
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001200 mutex_unlock(&chip->mutex);
Paulius Zaleckasca5c23c2008-02-27 01:42:39 +02001201 xip_iprefetch();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 cond_resched();
1203
1204 /*
1205 * We're back. However someone else might have
1206 * decided to go write to the chip if we are in
1207 * a suspended erase state. If so let's wait
1208 * until it's done.
1209 */
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001210 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 while (chip->state != newstate) {
1212 DECLARE_WAITQUEUE(wait, current);
1213 set_current_state(TASK_UNINTERRUPTIBLE);
1214 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001215 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 schedule();
1217 remove_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001218 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 }
1220 /* Disallow XIP again */
1221 local_irq_disable();
1222
1223 /* Resume the write or erase operation */
1224 map_write(map, CMD(0xd0), adr);
1225 map_write(map, CMD(0x70), adr);
1226 chip->state = oldstate;
1227 start = xip_currtime();
1228 } else if (usec >= 1000000/HZ) {
1229 /*
1230 * Try to save on CPU power when waiting delay
1231 * is at least a system timer tick period.
1232 * No need to be extremely accurate here.
1233 */
1234 xip_cpu_idle();
1235 }
1236 status = map_read(map, adr);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001237 done = xip_elapsed_since(start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 } while (!map_word_andequal(map, status, OK, OK)
Nicolas Pitrec1724712006-03-30 15:52:41 +01001239 && done < usec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
Nicolas Pitrec1724712006-03-30 15:52:41 +01001241 return (done >= usec) ? -ETIME : 0;
1242}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243
1244/*
1245 * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while
1246 * the flash is actively programming or erasing since we have to poll for
1247 * the operation to complete anyway. We can't do that in a generic way with
Nicolas Pitre6da70122005-05-19 18:05:47 +01001248 * a XIP setup so do it before the actual flash operation in this case
Nicolas Pitrec1724712006-03-30 15:52:41 +01001249 * and stub it out from INVAL_CACHE_AND_WAIT.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 */
Nicolas Pitre6da70122005-05-19 18:05:47 +01001251#define XIP_INVAL_CACHED_RANGE(map, from, size) \
1252 INVALIDATE_CACHED_RANGE(map, from, size)
1253
Anders Grafströme93cafe2008-08-05 18:37:41 +02001254#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec, usec_max) \
1255 xip_wait_for_operation(map, chip, cmd_adr, usec_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
1257#else
1258
1259#define xip_disable(map, chip, adr)
1260#define xip_enable(map, chip, adr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261#define XIP_INVAL_CACHED_RANGE(x...)
Nicolas Pitrec1724712006-03-30 15:52:41 +01001262#define INVAL_CACHE_AND_WAIT inval_cache_and_wait_for_operation
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
Nicolas Pitrec1724712006-03-30 15:52:41 +01001264static int inval_cache_and_wait_for_operation(
1265 struct map_info *map, struct flchip *chip,
1266 unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
Anders Grafströme93cafe2008-08-05 18:37:41 +02001267 unsigned int chip_op_time, unsigned int chip_op_time_max)
Nicolas Pitrec1724712006-03-30 15:52:41 +01001268{
1269 struct cfi_private *cfi = map->fldrv_priv;
1270 map_word status, status_OK = CMD(0x80);
Alexey Korolev46a16522006-06-28 19:22:07 +01001271 int chip_state = chip->state;
Alexey Korolev998453f2008-07-16 15:28:56 +01001272 unsigned int timeo, sleep_time, reset_timeo;
Nicolas Pitre6da70122005-05-19 18:05:47 +01001273
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001274 mutex_unlock(&chip->mutex);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001275 if (inval_len)
1276 INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001277 mutex_lock(&chip->mutex);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001278
Anders Grafströme93cafe2008-08-05 18:37:41 +02001279 timeo = chip_op_time_max;
Alexey Korolev46a16522006-06-28 19:22:07 +01001280 if (!timeo)
1281 timeo = 500000;
Alexey Korolev998453f2008-07-16 15:28:56 +01001282 reset_timeo = timeo;
Alexey Korolev46a16522006-06-28 19:22:07 +01001283 sleep_time = chip_op_time / 2;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001284
Nicolas Pitrec1724712006-03-30 15:52:41 +01001285 for (;;) {
Joakim Tjernlundecf3fde2011-02-07 17:07:11 +01001286 if (chip->state != chip_state) {
1287 /* Someone's suspended the operation: sleep */
1288 DECLARE_WAITQUEUE(wait, current);
1289 set_current_state(TASK_UNINTERRUPTIBLE);
1290 add_wait_queue(&chip->wq, &wait);
1291 mutex_unlock(&chip->mutex);
1292 schedule();
1293 remove_wait_queue(&chip->wq, &wait);
1294 mutex_lock(&chip->mutex);
1295 continue;
1296 }
1297
Nicolas Pitrec1724712006-03-30 15:52:41 +01001298 status = map_read(map, cmd_adr);
1299 if (map_word_andequal(map, status, status_OK, status_OK))
1300 break;
1301
Joakim Tjernlundecf3fde2011-02-07 17:07:11 +01001302 if (chip->erase_suspended && chip_state == FL_ERASING) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001303 /* Erase suspend occurred while sleep: reset timeout */
Joakim Tjernlundecf3fde2011-02-07 17:07:11 +01001304 timeo = reset_timeo;
1305 chip->erase_suspended = 0;
1306 }
1307 if (chip->write_suspended && chip_state == FL_WRITING) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001308 /* Write suspend occurred while sleep: reset timeout */
Joakim Tjernlundecf3fde2011-02-07 17:07:11 +01001309 timeo = reset_timeo;
1310 chip->write_suspended = 0;
1311 }
Alexey Korolev46a16522006-06-28 19:22:07 +01001312 if (!timeo) {
Nicolas Pitrec1724712006-03-30 15:52:41 +01001313 map_write(map, CMD(0x70), cmd_adr);
1314 chip->state = FL_STATUS;
1315 return -ETIME;
1316 }
1317
Alexey Korolev46a16522006-06-28 19:22:07 +01001318 /* OK Still waiting. Drop the lock, wait a while and retry. */
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001319 mutex_unlock(&chip->mutex);
Alexey Korolev46a16522006-06-28 19:22:07 +01001320 if (sleep_time >= 1000000/HZ) {
1321 /*
1322 * Half of the normal delay still remaining
1323 * can be performed with a sleeping delay instead
1324 * of busy waiting.
1325 */
1326 msleep(sleep_time/1000);
1327 timeo -= sleep_time;
1328 sleep_time = 1000000/HZ;
1329 } else {
1330 udelay(1);
1331 cond_resched();
1332 timeo--;
1333 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001334 mutex_lock(&chip->mutex);
Alexey Korolev46a16522006-06-28 19:22:07 +01001335 }
Nicolas Pitrec1724712006-03-30 15:52:41 +01001336
1337 /* Done and happy. */
1338 chip->state = FL_STATUS;
1339 return 0;
1340}
Nicolas Pitre6da70122005-05-19 18:05:47 +01001341
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342#endif
1343
Anders Grafströme93cafe2008-08-05 18:37:41 +02001344#define WAIT_TIMEOUT(map, chip, adr, udelay, udelay_max) \
1345 INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay, udelay_max);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001346
1347
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
1349{
1350 unsigned long cmd_addr;
1351 struct cfi_private *cfi = map->fldrv_priv;
1352 int ret = 0;
1353
1354 adr += chip->start;
1355
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001356 /* Ensure cmd read/writes are aligned. */
1357 cmd_addr = adr & ~(map_bankwidth(map)-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001359 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
1361 ret = get_chip(map, chip, cmd_addr, FL_POINT);
1362
1363 if (!ret) {
1364 if (chip->state != FL_POINT && chip->state != FL_READY)
1365 map_write(map, CMD(0xff), cmd_addr);
1366
1367 chip->state = FL_POINT;
1368 chip->ref_point_counter++;
1369 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001370 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
1372 return ret;
1373}
1374
Jared Hulberta98889f2008-04-29 23:26:49 -07001375static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len,
1376 size_t *retlen, void **virt, resource_size_t *phys)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377{
1378 struct map_info *map = mtd->priv;
1379 struct cfi_private *cfi = map->fldrv_priv;
Andy Lowe097f2572007-01-12 18:05:10 -05001380 unsigned long ofs, last_end = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 int chipnum;
1382 int ret = 0;
1383
Artem Bityutskiy5def4892012-02-03 16:23:52 +02001384 if (!map->virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 return -EINVAL;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001386
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 /* Now lock the chip(s) to POINT state */
1388
1389 /* ofs: offset within the first chip that the first read should start */
1390 chipnum = (from >> cfi->chipshift);
1391 ofs = from - (chipnum << cfi->chipshift);
1392
Jared Hulberta98889f2008-04-29 23:26:49 -07001393 *virt = map->virt + cfi->chips[chipnum].start + ofs;
Jared Hulberta98889f2008-04-29 23:26:49 -07001394 if (phys)
1395 *phys = map->phys + cfi->chips[chipnum].start + ofs;
Andy Lowe097f2572007-01-12 18:05:10 -05001396
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 while (len) {
1398 unsigned long thislen;
1399
1400 if (chipnum >= cfi->numchips)
1401 break;
1402
Andy Lowe097f2572007-01-12 18:05:10 -05001403 /* We cannot point across chips that are virtually disjoint */
1404 if (!last_end)
1405 last_end = cfi->chips[chipnum].start;
1406 else if (cfi->chips[chipnum].start != last_end)
1407 break;
1408
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 if ((len + ofs -1) >> cfi->chipshift)
1410 thislen = (1<<cfi->chipshift) - ofs;
1411 else
1412 thislen = len;
1413
1414 ret = do_point_onechip(map, &cfi->chips[chipnum], ofs, thislen);
1415 if (ret)
1416 break;
1417
1418 *retlen += thislen;
1419 len -= thislen;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001420
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 ofs = 0;
Andy Lowe097f2572007-01-12 18:05:10 -05001422 last_end += 1 << cfi->chipshift;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 chipnum++;
1424 }
1425 return 0;
1426}
1427
Artem Bityutskiy5e4e6e32012-02-03 13:20:43 +02001428static int cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429{
1430 struct map_info *map = mtd->priv;
1431 struct cfi_private *cfi = map->fldrv_priv;
1432 unsigned long ofs;
Artem Bityutskiy5e4e6e32012-02-03 13:20:43 +02001433 int chipnum, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
1435 /* Now unlock the chip(s) POINT state */
1436
1437 /* ofs: offset within the first chip that the first read should start */
1438 chipnum = (from >> cfi->chipshift);
1439 ofs = from - (chipnum << cfi->chipshift);
1440
Artem Bityutskiy5e4e6e32012-02-03 13:20:43 +02001441 while (len && !err) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 unsigned long thislen;
1443 struct flchip *chip;
1444
1445 chip = &cfi->chips[chipnum];
1446 if (chipnum >= cfi->numchips)
1447 break;
1448
1449 if ((len + ofs -1) >> cfi->chipshift)
1450 thislen = (1<<cfi->chipshift) - ofs;
1451 else
1452 thislen = len;
1453
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001454 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 if (chip->state == FL_POINT) {
1456 chip->ref_point_counter--;
1457 if(chip->ref_point_counter == 0)
1458 chip->state = FL_READY;
Artem Bityutskiy5e4e6e32012-02-03 13:20:43 +02001459 } else {
1460 printk(KERN_ERR "%s: Error: unpoint called on non pointed region\n", map->name);
1461 err = -EINVAL;
1462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
1464 put_chip(map, chip, chip->start);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001465 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 len -= thislen;
1468 ofs = 0;
1469 chipnum++;
1470 }
Artem Bityutskiy5e4e6e32012-02-03 13:20:43 +02001471
1472 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473}
1474
1475static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
1476{
1477 unsigned long cmd_addr;
1478 struct cfi_private *cfi = map->fldrv_priv;
1479 int ret;
1480
1481 adr += chip->start;
1482
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001483 /* Ensure cmd read/writes are aligned. */
1484 cmd_addr = adr & ~(map_bankwidth(map)-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001486 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 ret = get_chip(map, chip, cmd_addr, FL_READY);
1488 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001489 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 return ret;
1491 }
1492
1493 if (chip->state != FL_POINT && chip->state != FL_READY) {
1494 map_write(map, CMD(0xff), cmd_addr);
1495
1496 chip->state = FL_READY;
1497 }
1498
1499 map_copy_from(map, buf, adr, len);
1500
1501 put_chip(map, chip, cmd_addr);
1502
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001503 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 return 0;
1505}
1506
1507static int cfi_intelext_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
1508{
1509 struct map_info *map = mtd->priv;
1510 struct cfi_private *cfi = map->fldrv_priv;
1511 unsigned long ofs;
1512 int chipnum;
1513 int ret = 0;
1514
1515 /* ofs: offset within the first chip that the first read should start */
1516 chipnum = (from >> cfi->chipshift);
1517 ofs = from - (chipnum << cfi->chipshift);
1518
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 while (len) {
1520 unsigned long thislen;
1521
1522 if (chipnum >= cfi->numchips)
1523 break;
1524
1525 if ((len + ofs -1) >> cfi->chipshift)
1526 thislen = (1<<cfi->chipshift) - ofs;
1527 else
1528 thislen = len;
1529
1530 ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
1531 if (ret)
1532 break;
1533
1534 *retlen += thislen;
1535 len -= thislen;
1536 buf += thislen;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001537
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 ofs = 0;
1539 chipnum++;
1540 }
1541 return ret;
1542}
1543
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
Nicolas Pitref77814d2005-02-08 17:11:19 +00001545 unsigned long adr, map_word datum, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546{
1547 struct cfi_private *cfi = map->fldrv_priv;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001548 map_word status, write_cmd;
1549 int ret=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
1551 adr += chip->start;
1552
Nicolas Pitref77814d2005-02-08 17:11:19 +00001553 switch (mode) {
Nicolas Pitre638d9832005-08-06 05:40:46 +01001554 case FL_WRITING:
Guillaume LECERFb5d194c2010-10-26 10:55:29 +01001555 write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0x40) : CMD(0x41);
Nicolas Pitre638d9832005-08-06 05:40:46 +01001556 break;
1557 case FL_OTP_WRITE:
1558 write_cmd = CMD(0xc0);
1559 break;
1560 default:
1561 return -EINVAL;
Nicolas Pitref77814d2005-02-08 17:11:19 +00001562 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001564 mutex_lock(&chip->mutex);
Nicolas Pitref77814d2005-02-08 17:11:19 +00001565 ret = get_chip(map, chip, adr, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001567 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 return ret;
1569 }
1570
1571 XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));
1572 ENABLE_VPP(map);
1573 xip_disable(map, chip, adr);
Nicolas Pitref77814d2005-02-08 17:11:19 +00001574 map_write(map, write_cmd, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 map_write(map, datum, adr);
Nicolas Pitref77814d2005-02-08 17:11:19 +00001576 chip->state = mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
Nicolas Pitrec1724712006-03-30 15:52:41 +01001578 ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
1579 adr, map_bankwidth(map),
Anders Grafströme93cafe2008-08-05 18:37:41 +02001580 chip->word_write_time,
1581 chip->word_write_time_max);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001582 if (ret) {
1583 xip_enable(map, chip, adr);
1584 printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
1585 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
Nicolas Pitre48436532005-08-06 05:16:52 +01001588 /* check for errors */
Nicolas Pitrec1724712006-03-30 15:52:41 +01001589 status = map_read(map, adr);
Nicolas Pitre48436532005-08-06 05:16:52 +01001590 if (map_word_bitsset(map, status, CMD(0x1a))) {
1591 unsigned long chipstatus = MERGESTATUS(status);
1592
1593 /* reset status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 map_write(map, CMD(0x50), adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 map_write(map, CMD(0x70), adr);
Nicolas Pitre48436532005-08-06 05:16:52 +01001596 xip_enable(map, chip, adr);
1597
1598 if (chipstatus & 0x02) {
1599 ret = -EROFS;
1600 } else if (chipstatus & 0x08) {
1601 printk(KERN_ERR "%s: word write error (bad VPP)\n", map->name);
1602 ret = -EIO;
1603 } else {
1604 printk(KERN_ERR "%s: word write error (status 0x%lx)\n", map->name, chipstatus);
1605 ret = -EINVAL;
1606 }
1607
1608 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 }
1610
1611 xip_enable(map, chip, adr);
Paul Parsons85e5b2f2012-03-07 14:10:33 +00001612 out: DISABLE_VPP(map);
1613 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001614 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 return ret;
1616}
1617
1618
1619static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
1620{
1621 struct map_info *map = mtd->priv;
1622 struct cfi_private *cfi = map->fldrv_priv;
1623 int ret = 0;
1624 int chipnum;
1625 unsigned long ofs;
1626
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 chipnum = to >> cfi->chipshift;
1628 ofs = to - (chipnum << cfi->chipshift);
1629
1630 /* If it's not bus-aligned, do the first byte write */
1631 if (ofs & (map_bankwidth(map)-1)) {
1632 unsigned long bus_ofs = ofs & ~(map_bankwidth(map)-1);
1633 int gap = ofs - bus_ofs;
1634 int n;
1635 map_word datum;
1636
1637 n = min_t(int, len, map_bankwidth(map)-gap);
1638 datum = map_word_ff(map);
1639 datum = map_word_load_partial(map, datum, buf, gap, n);
1640
1641 ret = do_write_oneword(map, &cfi->chips[chipnum],
Nicolas Pitref77814d2005-02-08 17:11:19 +00001642 bus_ofs, datum, FL_WRITING);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001643 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 return ret;
1645
1646 len -= n;
1647 ofs += n;
1648 buf += n;
1649 (*retlen) += n;
1650
1651 if (ofs >> cfi->chipshift) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001652 chipnum ++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 ofs = 0;
1654 if (chipnum == cfi->numchips)
1655 return 0;
1656 }
1657 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001658
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 while(len >= map_bankwidth(map)) {
1660 map_word datum = map_word_load(map, buf);
1661
1662 ret = do_write_oneword(map, &cfi->chips[chipnum],
Nicolas Pitref77814d2005-02-08 17:11:19 +00001663 ofs, datum, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 if (ret)
1665 return ret;
1666
1667 ofs += map_bankwidth(map);
1668 buf += map_bankwidth(map);
1669 (*retlen) += map_bankwidth(map);
1670 len -= map_bankwidth(map);
1671
1672 if (ofs >> cfi->chipshift) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001673 chipnum ++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 ofs = 0;
1675 if (chipnum == cfi->numchips)
1676 return 0;
1677 }
1678 }
1679
1680 if (len & (map_bankwidth(map)-1)) {
1681 map_word datum;
1682
1683 datum = map_word_ff(map);
1684 datum = map_word_load_partial(map, datum, buf, 0, len);
1685
1686 ret = do_write_oneword(map, &cfi->chips[chipnum],
Nicolas Pitref77814d2005-02-08 17:11:19 +00001687 ofs, datum, FL_WRITING);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001688 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 return ret;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001690
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 (*retlen) += len;
1692 }
1693
1694 return 0;
1695}
1696
1697
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001698static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
Nicolas Pitree102d542005-08-06 05:46:59 +01001699 unsigned long adr, const struct kvec **pvec,
1700 unsigned long *pvec_seek, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701{
1702 struct cfi_private *cfi = map->fldrv_priv;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001703 map_word status, write_cmd, datum;
1704 unsigned long cmd_adr;
1705 int ret, wbufsize, word_gap, words;
Nicolas Pitree102d542005-08-06 05:46:59 +01001706 const struct kvec *vec;
1707 unsigned long vec_seek;
Massimo Cirillo646fd122008-01-11 10:24:11 +00001708 unsigned long initial_adr;
1709 int initial_len = len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710
1711 wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
1712 adr += chip->start;
Massimo Cirillo646fd122008-01-11 10:24:11 +00001713 initial_adr = adr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 cmd_adr = adr & ~(wbufsize-1);
Nicolas Pitre638d9832005-08-06 05:40:46 +01001715
Andrea Adami812c5fa2014-06-02 23:38:35 +02001716 /* Sharp LH28F640BF chips need the first address for the
1717 * Page Buffer Program command. See Table 5 of
1718 * LH28F320BF, LH28F640BF, LH28F128BF Series (Appendix FUM00701) */
1719 if (is_LH28F640BF(cfi))
1720 cmd_adr = adr;
1721
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 /* Let's determine this according to the interleave only once */
Guillaume LECERFb5d194c2010-10-26 10:55:29 +01001723 write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0xe8) : CMD(0xe9);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001725 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 ret = get_chip(map, chip, cmd_adr, FL_WRITING);
1727 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001728 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 return ret;
1730 }
1731
Massimo Cirillo646fd122008-01-11 10:24:11 +00001732 XIP_INVAL_CACHED_RANGE(map, initial_adr, initial_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 ENABLE_VPP(map);
1734 xip_disable(map, chip, cmd_adr);
1735
David Woodhouse151e7652006-05-14 01:51:54 +01001736 /* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001737 [...], the device will not accept any more Write to Buffer commands".
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 So we must check here and reset those bits if they're set. Otherwise
1739 we're just pissing in the wind */
Nicolas Pitre6e7a6802006-03-29 23:31:42 +01001740 if (chip->state != FL_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 map_write(map, CMD(0x70), cmd_adr);
Nicolas Pitre6e7a6802006-03-29 23:31:42 +01001742 chip->state = FL_STATUS;
1743 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 status = map_read(map, cmd_adr);
1745 if (map_word_bitsset(map, status, CMD(0x30))) {
1746 xip_enable(map, chip, cmd_adr);
1747 printk(KERN_WARNING "SR.4 or SR.5 bits set in buffer write (status %lx). Clearing.\n", status.x[0]);
1748 xip_disable(map, chip, cmd_adr);
1749 map_write(map, CMD(0x50), cmd_adr);
1750 map_write(map, CMD(0x70), cmd_adr);
1751 }
1752
1753 chip->state = FL_WRITING_TO_BUFFER;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001754 map_write(map, write_cmd, cmd_adr);
Anders Grafströme93cafe2008-08-05 18:37:41 +02001755 ret = WAIT_TIMEOUT(map, chip, cmd_adr, 0, 0);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001756 if (ret) {
1757 /* Argh. Not ready for write to buffer */
1758 map_word Xstatus = map_read(map, cmd_adr);
1759 map_write(map, CMD(0x70), cmd_adr);
1760 chip->state = FL_STATUS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 status = map_read(map, cmd_adr);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001762 map_write(map, CMD(0x50), cmd_adr);
1763 map_write(map, CMD(0x70), cmd_adr);
1764 xip_enable(map, chip, cmd_adr);
1765 printk(KERN_ERR "%s: Chip not ready for buffer write. Xstatus = %lx, status = %lx\n",
1766 map->name, Xstatus.x[0], status.x[0]);
1767 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 }
1769
Nicolas Pitree102d542005-08-06 05:46:59 +01001770 /* Figure out the number of words to write */
1771 word_gap = (-adr & (map_bankwidth(map)-1));
Julia Lawallc8872b02008-08-02 17:14:21 +02001772 words = DIV_ROUND_UP(len - word_gap, map_bankwidth(map));
Nicolas Pitree102d542005-08-06 05:46:59 +01001773 if (!word_gap) {
1774 words--;
1775 } else {
1776 word_gap = map_bankwidth(map) - word_gap;
1777 adr -= word_gap;
1778 datum = map_word_ff(map);
1779 }
1780
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 /* Write length of data to come */
Nicolas Pitree102d542005-08-06 05:46:59 +01001782 map_write(map, CMD(words), cmd_adr );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
1784 /* Write data */
Nicolas Pitree102d542005-08-06 05:46:59 +01001785 vec = *pvec;
1786 vec_seek = *pvec_seek;
1787 do {
1788 int n = map_bankwidth(map) - word_gap;
1789 if (n > vec->iov_len - vec_seek)
1790 n = vec->iov_len - vec_seek;
1791 if (n > len)
1792 n = len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793
Nicolas Pitree102d542005-08-06 05:46:59 +01001794 if (!word_gap && len < map_bankwidth(map))
1795 datum = map_word_ff(map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796
Nicolas Pitree102d542005-08-06 05:46:59 +01001797 datum = map_word_load_partial(map, datum,
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001798 vec->iov_base + vec_seek,
Nicolas Pitree102d542005-08-06 05:46:59 +01001799 word_gap, n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800
Nicolas Pitree102d542005-08-06 05:46:59 +01001801 len -= n;
1802 word_gap += n;
1803 if (!len || word_gap == map_bankwidth(map)) {
1804 map_write(map, datum, adr);
1805 adr += map_bankwidth(map);
1806 word_gap = 0;
1807 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808
Nicolas Pitree102d542005-08-06 05:46:59 +01001809 vec_seek += n;
1810 if (vec_seek == vec->iov_len) {
1811 vec++;
1812 vec_seek = 0;
1813 }
1814 } while (len);
1815 *pvec = vec;
1816 *pvec_seek = vec_seek;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
1818 /* GO GO GO */
1819 map_write(map, CMD(0xd0), cmd_adr);
1820 chip->state = FL_WRITING;
1821
Nicolas Pitrec1724712006-03-30 15:52:41 +01001822 ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
Massimo Cirillo646fd122008-01-11 10:24:11 +00001823 initial_adr, initial_len,
Anders Grafströme93cafe2008-08-05 18:37:41 +02001824 chip->buffer_write_time,
1825 chip->buffer_write_time_max);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001826 if (ret) {
1827 map_write(map, CMD(0x70), cmd_adr);
1828 chip->state = FL_STATUS;
1829 xip_enable(map, chip, cmd_adr);
1830 printk(KERN_ERR "%s: buffer write error (status timeout)\n", map->name);
1831 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
Nicolas Pitre48436532005-08-06 05:16:52 +01001834 /* check for errors */
Nicolas Pitrec1724712006-03-30 15:52:41 +01001835 status = map_read(map, cmd_adr);
Nicolas Pitre48436532005-08-06 05:16:52 +01001836 if (map_word_bitsset(map, status, CMD(0x1a))) {
1837 unsigned long chipstatus = MERGESTATUS(status);
1838
1839 /* reset status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 map_write(map, CMD(0x50), cmd_adr);
Nicolas Pitre48436532005-08-06 05:16:52 +01001841 map_write(map, CMD(0x70), cmd_adr);
1842 xip_enable(map, chip, cmd_adr);
1843
1844 if (chipstatus & 0x02) {
1845 ret = -EROFS;
1846 } else if (chipstatus & 0x08) {
1847 printk(KERN_ERR "%s: buffer write error (bad VPP)\n", map->name);
1848 ret = -EIO;
1849 } else {
1850 printk(KERN_ERR "%s: buffer write error (status 0x%lx)\n", map->name, chipstatus);
1851 ret = -EINVAL;
1852 }
1853
1854 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 }
1856
1857 xip_enable(map, chip, cmd_adr);
Paul Parsons85e5b2f2012-03-07 14:10:33 +00001858 out: DISABLE_VPP(map);
1859 put_chip(map, chip, cmd_adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001860 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 return ret;
1862}
1863
Nicolas Pitree102d542005-08-06 05:46:59 +01001864static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs,
1865 unsigned long count, loff_t to, size_t *retlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866{
1867 struct map_info *map = mtd->priv;
1868 struct cfi_private *cfi = map->fldrv_priv;
1869 int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
1870 int ret = 0;
1871 int chipnum;
Nicolas Pitree102d542005-08-06 05:46:59 +01001872 unsigned long ofs, vec_seek, i;
1873 size_t len = 0;
1874
1875 for (i = 0; i < count; i++)
1876 len += vecs[i].iov_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 if (!len)
1879 return 0;
1880
1881 chipnum = to >> cfi->chipshift;
Nicolas Pitree102d542005-08-06 05:46:59 +01001882 ofs = to - (chipnum << cfi->chipshift);
1883 vec_seek = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884
Nicolas Pitree102d542005-08-06 05:46:59 +01001885 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 /* We must not cross write block boundaries */
1887 int size = wbufsize - (ofs & (wbufsize-1));
1888
1889 if (size > len)
1890 size = len;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001891 ret = do_write_buffer(map, &cfi->chips[chipnum],
Nicolas Pitree102d542005-08-06 05:46:59 +01001892 ofs, &vecs, &vec_seek, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 if (ret)
1894 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895
1896 ofs += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 (*retlen) += size;
1898 len -= size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
1900 if (ofs >> cfi->chipshift) {
1901 chipnum ++;
1902 ofs = 0;
1903 if (chipnum == cfi->numchips)
1904 return 0;
1905 }
Josh Boyerdf54b52c2005-12-06 17:28:19 +00001906
1907 /* Be nice and reschedule with the chip in a usable state for other
1908 processes. */
1909 cond_resched();
1910
Nicolas Pitree102d542005-08-06 05:46:59 +01001911 } while (len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 return 0;
1914}
1915
Nicolas Pitree102d542005-08-06 05:46:59 +01001916static int cfi_intelext_write_buffers (struct mtd_info *mtd, loff_t to,
1917 size_t len, size_t *retlen, const u_char *buf)
1918{
1919 struct kvec vec;
1920
1921 vec.iov_base = (void *) buf;
1922 vec.iov_len = len;
1923
1924 return cfi_intelext_writev(mtd, &vec, 1, to, retlen);
1925}
1926
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
1928 unsigned long adr, int len, void *thunk)
1929{
1930 struct cfi_private *cfi = map->fldrv_priv;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001931 map_word status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 int retries = 3;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001933 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
1935 adr += chip->start;
1936
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 retry:
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001938 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 ret = get_chip(map, chip, adr, FL_ERASING);
1940 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001941 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 return ret;
1943 }
1944
1945 XIP_INVAL_CACHED_RANGE(map, adr, len);
1946 ENABLE_VPP(map);
1947 xip_disable(map, chip, adr);
1948
1949 /* Clear the status register first */
1950 map_write(map, CMD(0x50), adr);
1951
1952 /* Now erase */
1953 map_write(map, CMD(0x20), adr);
1954 map_write(map, CMD(0xD0), adr);
1955 chip->state = FL_ERASING;
1956 chip->erase_suspended = 0;
Joakim Tjernlund54a21fe2018-03-01 14:39:39 +01001957 chip->in_progress_block_addr = adr;
1958 chip->in_progress_block_mask = ~(len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959
Nicolas Pitrec1724712006-03-30 15:52:41 +01001960 ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
1961 adr, len,
Anders Grafströme93cafe2008-08-05 18:37:41 +02001962 chip->erase_time,
1963 chip->erase_time_max);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001964 if (ret) {
1965 map_write(map, CMD(0x70), adr);
1966 chip->state = FL_STATUS;
1967 xip_enable(map, chip, adr);
1968 printk(KERN_ERR "%s: block erase error: (status timeout)\n", map->name);
1969 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 }
1971
1972 /* We've broken this before. It doesn't hurt to be safe */
1973 map_write(map, CMD(0x70), adr);
1974 chip->state = FL_STATUS;
1975 status = map_read(map, adr);
1976
Nicolas Pitre48436532005-08-06 05:16:52 +01001977 /* check for errors */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 if (map_word_bitsset(map, status, CMD(0x3a))) {
Nicolas Pitre48436532005-08-06 05:16:52 +01001979 unsigned long chipstatus = MERGESTATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980
1981 /* Reset the error bits */
1982 map_write(map, CMD(0x50), adr);
1983 map_write(map, CMD(0x70), adr);
1984 xip_enable(map, chip, adr);
1985
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 if ((chipstatus & 0x30) == 0x30) {
Nicolas Pitre48436532005-08-06 05:16:52 +01001987 printk(KERN_ERR "%s: block erase error: (bad command sequence, status 0x%lx)\n", map->name, chipstatus);
1988 ret = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 } else if (chipstatus & 0x02) {
1990 /* Protection bit set */
1991 ret = -EROFS;
1992 } else if (chipstatus & 0x8) {
1993 /* Voltage */
Nicolas Pitre48436532005-08-06 05:16:52 +01001994 printk(KERN_ERR "%s: block erase error: (bad VPP)\n", map->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 ret = -EIO;
Nicolas Pitre48436532005-08-06 05:16:52 +01001996 } else if (chipstatus & 0x20 && retries--) {
1997 printk(KERN_DEBUG "block erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus);
Paul Parsons85e5b2f2012-03-07 14:10:33 +00001998 DISABLE_VPP(map);
Nicolas Pitre48436532005-08-06 05:16:52 +01001999 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002000 mutex_unlock(&chip->mutex);
Nicolas Pitre48436532005-08-06 05:16:52 +01002001 goto retry;
2002 } else {
2003 printk(KERN_ERR "%s: block erase failed at 0x%08lx (status 0x%lx)\n", map->name, adr, chipstatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 ret = -EIO;
2005 }
Nicolas Pitre48436532005-08-06 05:16:52 +01002006
2007 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 }
2009
Nicolas Pitre48436532005-08-06 05:16:52 +01002010 xip_enable(map, chip, adr);
Paul Parsons85e5b2f2012-03-07 14:10:33 +00002011 out: DISABLE_VPP(map);
2012 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002013 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 return ret;
2015}
2016
Ben Dooks029a9eb2007-05-28 20:11:37 +01002017static int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018{
2019 unsigned long ofs, len;
2020 int ret;
2021
2022 ofs = instr->addr;
2023 len = instr->len;
2024
2025 ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
2026 if (ret)
2027 return ret;
2028
2029 instr->state = MTD_ERASE_DONE;
2030 mtd_erase_callback(instr);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002031
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 return 0;
2033}
2034
2035static void cfi_intelext_sync (struct mtd_info *mtd)
2036{
2037 struct map_info *map = mtd->priv;
2038 struct cfi_private *cfi = map->fldrv_priv;
2039 int i;
2040 struct flchip *chip;
2041 int ret = 0;
2042
2043 for (i=0; !ret && i<cfi->numchips; i++) {
2044 chip = &cfi->chips[i];
2045
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002046 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 ret = get_chip(map, chip, chip->start, FL_SYNCING);
2048
2049 if (!ret) {
2050 chip->oldstate = chip->state;
2051 chip->state = FL_SYNCING;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002052 /* No need to wake_up() on this state change -
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 * as the whole point is that nobody can do anything
2054 * with the chip now anyway.
2055 */
2056 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002057 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 }
2059
2060 /* Unlock the chips again */
2061
2062 for (i--; i >=0; i--) {
2063 chip = &cfi->chips[i];
2064
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002065 mutex_lock(&chip->mutex);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002066
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 if (chip->state == FL_SYNCING) {
2068 chip->state = chip->oldstate;
Nicolas Pitre09c79332005-03-16 22:41:09 +00002069 chip->oldstate = FL_READY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 wake_up(&chip->wq);
2071 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002072 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 }
2074}
2075
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002076static int __xipram do_getlockstatus_oneblock(struct map_info *map,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 struct flchip *chip,
2078 unsigned long adr,
2079 int len, void *thunk)
2080{
2081 struct cfi_private *cfi = map->fldrv_priv;
2082 int status, ofs_factor = cfi->interleave * cfi->device_type;
2083
Todd Poynorc25bb1f2005-04-27 21:01:52 +01002084 adr += chip->start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 xip_disable(map, chip, adr+(2*ofs_factor));
Todd Poynorc25bb1f2005-04-27 21:01:52 +01002086 map_write(map, CMD(0x90), adr+(2*ofs_factor));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 chip->state = FL_JEDEC_QUERY;
2088 status = cfi_read_query(map, adr+(2*ofs_factor));
2089 xip_enable(map, chip, 0);
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002090 return status;
2091}
2092
2093#ifdef DEBUG_LOCK_BITS
2094static int __xipram do_printlockstatus_oneblock(struct map_info *map,
2095 struct flchip *chip,
2096 unsigned long adr,
2097 int len, void *thunk)
2098{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 printk(KERN_DEBUG "block status register for 0x%08lx is %x\n",
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002100 adr, do_getlockstatus_oneblock(map, chip, adr, len, thunk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 return 0;
2102}
2103#endif
2104
2105#define DO_XXLOCK_ONEBLOCK_LOCK ((void *) 1)
2106#define DO_XXLOCK_ONEBLOCK_UNLOCK ((void *) 2)
2107
2108static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip,
2109 unsigned long adr, int len, void *thunk)
2110{
2111 struct cfi_private *cfi = map->fldrv_priv;
Todd Poynor9a6e73e2005-03-29 23:06:40 +01002112 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
Stefan Roese7be1f6b2012-08-28 11:34:13 +02002113 int mdelay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 int ret;
2115
2116 adr += chip->start;
2117
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002118 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 ret = get_chip(map, chip, adr, FL_LOCKING);
2120 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002121 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 return ret;
2123 }
2124
2125 ENABLE_VPP(map);
2126 xip_disable(map, chip, adr);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002127
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 map_write(map, CMD(0x60), adr);
2129 if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) {
2130 map_write(map, CMD(0x01), adr);
2131 chip->state = FL_LOCKING;
2132 } else if (thunk == DO_XXLOCK_ONEBLOCK_UNLOCK) {
2133 map_write(map, CMD(0xD0), adr);
2134 chip->state = FL_UNLOCKING;
2135 } else
2136 BUG();
2137
Todd Poynor9a6e73e2005-03-29 23:06:40 +01002138 /*
2139 * If Instant Individual Block Locking supported then no need
2140 * to delay.
2141 */
Stefan Roese7be1f6b2012-08-28 11:34:13 +02002142 /*
2143 * Unlocking may take up to 1.4 seconds on some Intel flashes. So
2144 * lets use a max of 1.5 seconds (1500ms) as timeout.
2145 *
2146 * See "Clear Block Lock-Bits Time" on page 40 in
2147 * "3 Volt Intel StrataFlash Memory" 28F128J3,28F640J3,28F320J3 manual
2148 * from February 2003
2149 */
2150 mdelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1500 : 0;
Todd Poynor9a6e73e2005-03-29 23:06:40 +01002151
Stefan Roese7be1f6b2012-08-28 11:34:13 +02002152 ret = WAIT_TIMEOUT(map, chip, adr, mdelay, mdelay * 1000);
Nicolas Pitrec1724712006-03-30 15:52:41 +01002153 if (ret) {
2154 map_write(map, CMD(0x70), adr);
2155 chip->state = FL_STATUS;
2156 xip_enable(map, chip, adr);
2157 printk(KERN_ERR "%s: block unlock error: (status timeout)\n", map->name);
2158 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002160
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 xip_enable(map, chip, adr);
Paul Parsons85e5b2f2012-03-07 14:10:33 +00002162 out: DISABLE_VPP(map);
2163 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002164 mutex_unlock(&chip->mutex);
Nicolas Pitrec1724712006-03-30 15:52:41 +01002165 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166}
2167
Adrian Hunter69423d92008-12-10 13:37:21 +00002168static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169{
2170 int ret;
2171
2172#ifdef DEBUG_LOCK_BITS
2173 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
Harvey Harrisoncb53b3b2008-04-18 13:44:19 -07002174 __func__, ofs, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
Randy Dunlap1da1caf2007-06-28 23:00:09 +01002176 ofs, len, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177#endif
2178
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002179 ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 ofs, len, DO_XXLOCK_ONEBLOCK_LOCK);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002181
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182#ifdef DEBUG_LOCK_BITS
2183 printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
Harvey Harrisoncb53b3b2008-04-18 13:44:19 -07002184 __func__, ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
Randy Dunlap1da1caf2007-06-28 23:00:09 +01002186 ofs, len, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187#endif
2188
2189 return ret;
2190}
2191
Adrian Hunter69423d92008-12-10 13:37:21 +00002192static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193{
2194 int ret;
2195
2196#ifdef DEBUG_LOCK_BITS
2197 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
Harvey Harrisoncb53b3b2008-04-18 13:44:19 -07002198 __func__, ofs, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
Randy Dunlap1da1caf2007-06-28 23:00:09 +01002200 ofs, len, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201#endif
2202
2203 ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
2204 ofs, len, DO_XXLOCK_ONEBLOCK_UNLOCK);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002205
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206#ifdef DEBUG_LOCK_BITS
2207 printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
Harvey Harrisoncb53b3b2008-04-18 13:44:19 -07002208 __func__, ret);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002209 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
Randy Dunlap1da1caf2007-06-28 23:00:09 +01002210 ofs, len, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211#endif
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002212
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 return ret;
2214}
2215
Richard Cochran99384242010-06-14 18:10:33 +02002216static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs,
2217 uint64_t len)
2218{
2219 return cfi_varsize_frob(mtd, do_getlockstatus_oneblock,
2220 ofs, len, NULL) ? 1 : 0;
2221}
2222
Nicolas Pitref77814d2005-02-08 17:11:19 +00002223#ifdef CONFIG_MTD_OTP
2224
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002225typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip,
Nicolas Pitref77814d2005-02-08 17:11:19 +00002226 u_long data_offset, u_char *buf, u_int size,
2227 u_long prot_offset, u_int groupno, u_int groupsize);
2228
2229static int __xipram
2230do_otp_read(struct map_info *map, struct flchip *chip, u_long offset,
2231 u_char *buf, u_int size, u_long prot, u_int grpno, u_int grpsz)
2232{
2233 struct cfi_private *cfi = map->fldrv_priv;
2234 int ret;
2235
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002236 mutex_lock(&chip->mutex);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002237 ret = get_chip(map, chip, chip->start, FL_JEDEC_QUERY);
2238 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002239 mutex_unlock(&chip->mutex);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002240 return ret;
2241 }
2242
2243 /* let's ensure we're not reading back cached data from array mode */
Nicolas Pitre6da70122005-05-19 18:05:47 +01002244 INVALIDATE_CACHED_RANGE(map, chip->start + offset, size);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002245
2246 xip_disable(map, chip, chip->start);
2247 if (chip->state != FL_JEDEC_QUERY) {
2248 map_write(map, CMD(0x90), chip->start);
2249 chip->state = FL_JEDEC_QUERY;
2250 }
2251 map_copy_from(map, buf, chip->start + offset, size);
2252 xip_enable(map, chip, chip->start);
2253
2254 /* then ensure we don't keep OTP data in the cache */
Nicolas Pitre6da70122005-05-19 18:05:47 +01002255 INVALIDATE_CACHED_RANGE(map, chip->start + offset, size);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002256
2257 put_chip(map, chip, chip->start);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002258 mutex_unlock(&chip->mutex);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002259 return 0;
2260}
2261
2262static int
2263do_otp_write(struct map_info *map, struct flchip *chip, u_long offset,
2264 u_char *buf, u_int size, u_long prot, u_int grpno, u_int grpsz)
2265{
2266 int ret;
2267
2268 while (size) {
2269 unsigned long bus_ofs = offset & ~(map_bankwidth(map)-1);
2270 int gap = offset - bus_ofs;
2271 int n = min_t(int, size, map_bankwidth(map)-gap);
2272 map_word datum = map_word_ff(map);
2273
2274 datum = map_word_load_partial(map, datum, buf, gap, n);
2275 ret = do_write_oneword(map, chip, bus_ofs, datum, FL_OTP_WRITE);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002276 if (ret)
Nicolas Pitref77814d2005-02-08 17:11:19 +00002277 return ret;
2278
2279 offset += n;
2280 buf += n;
2281 size -= n;
2282 }
2283
2284 return 0;
2285}
2286
2287static int
2288do_otp_lock(struct map_info *map, struct flchip *chip, u_long offset,
2289 u_char *buf, u_int size, u_long prot, u_int grpno, u_int grpsz)
2290{
2291 struct cfi_private *cfi = map->fldrv_priv;
2292 map_word datum;
2293
2294 /* make sure area matches group boundaries */
Nicolas Pitre332d71f2005-02-17 20:35:04 +00002295 if (size != grpsz)
Nicolas Pitref77814d2005-02-08 17:11:19 +00002296 return -EXDEV;
2297
2298 datum = map_word_ff(map);
2299 datum = map_word_clr(map, datum, CMD(1 << grpno));
2300 return do_write_oneword(map, chip, prot, datum, FL_OTP_WRITE);
2301}
2302
2303static int cfi_intelext_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
2304 size_t *retlen, u_char *buf,
2305 otp_op_t action, int user_regs)
2306{
2307 struct map_info *map = mtd->priv;
2308 struct cfi_private *cfi = map->fldrv_priv;
2309 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
2310 struct flchip *chip;
2311 struct cfi_intelext_otpinfo *otp;
2312 u_long devsize, reg_prot_offset, data_offset;
2313 u_int chip_num, chip_step, field, reg_fact_size, reg_user_size;
2314 u_int groups, groupno, groupsize, reg_fact_groups, reg_user_groups;
2315 int ret;
2316
2317 *retlen = 0;
2318
2319 /* Check that we actually have some OTP registers */
2320 if (!extp || !(extp->FeatureSupport & 64) || !extp->NumProtectionFields)
2321 return -ENODATA;
2322
2323 /* we need real chips here not virtual ones */
2324 devsize = (1 << cfi->cfiq->DevSize) * cfi->interleave;
2325 chip_step = devsize >> cfi->chipshift;
Nicolas Pitredce2b4d2005-04-01 17:36:29 +01002326 chip_num = 0;
Nicolas Pitref77814d2005-02-08 17:11:19 +00002327
Nicolas Pitredce2b4d2005-04-01 17:36:29 +01002328 /* Some chips have OTP located in the _top_ partition only.
2329 For example: Intel 28F256L18T (T means top-parameter device) */
Hans-Christian Egtvedtb2ef1a22009-11-05 15:53:43 +01002330 if (cfi->mfr == CFI_MFR_INTEL) {
Nicolas Pitredce2b4d2005-04-01 17:36:29 +01002331 switch (cfi->id) {
2332 case 0x880b:
2333 case 0x880c:
2334 case 0x880d:
2335 chip_num = chip_step - 1;
2336 }
2337 }
2338
2339 for ( ; chip_num < cfi->numchips; chip_num += chip_step) {
Nicolas Pitref77814d2005-02-08 17:11:19 +00002340 chip = &cfi->chips[chip_num];
2341 otp = (struct cfi_intelext_otpinfo *)&extp->extra[0];
2342
2343 /* first OTP region */
2344 field = 0;
2345 reg_prot_offset = extp->ProtRegAddr;
2346 reg_fact_groups = 1;
2347 reg_fact_size = 1 << extp->FactProtRegSize;
2348 reg_user_groups = 1;
2349 reg_user_size = 1 << extp->UserProtRegSize;
2350
2351 while (len > 0) {
2352 /* flash geometry fixup */
2353 data_offset = reg_prot_offset + 1;
2354 data_offset *= cfi->interleave * cfi->device_type;
2355 reg_prot_offset *= cfi->interleave * cfi->device_type;
2356 reg_fact_size *= cfi->interleave;
2357 reg_user_size *= cfi->interleave;
2358
2359 if (user_regs) {
2360 groups = reg_user_groups;
2361 groupsize = reg_user_size;
2362 /* skip over factory reg area */
2363 groupno = reg_fact_groups;
2364 data_offset += reg_fact_groups * reg_fact_size;
2365 } else {
2366 groups = reg_fact_groups;
2367 groupsize = reg_fact_size;
2368 groupno = 0;
2369 }
2370
Nicolas Pitre332d71f2005-02-17 20:35:04 +00002371 while (len > 0 && groups > 0) {
Nicolas Pitref77814d2005-02-08 17:11:19 +00002372 if (!action) {
2373 /*
2374 * Special case: if action is NULL
2375 * we fill buf with otp_info records.
2376 */
2377 struct otp_info *otpinfo;
2378 map_word lockword;
2379 len -= sizeof(struct otp_info);
2380 if (len <= 0)
2381 return -ENOSPC;
2382 ret = do_otp_read(map, chip,
2383 reg_prot_offset,
2384 (u_char *)&lockword,
2385 map_bankwidth(map),
2386 0, 0, 0);
2387 if (ret)
2388 return ret;
2389 otpinfo = (struct otp_info *)buf;
2390 otpinfo->start = from;
2391 otpinfo->length = groupsize;
2392 otpinfo->locked =
2393 !map_word_bitsset(map, lockword,
2394 CMD(1 << groupno));
2395 from += groupsize;
2396 buf += sizeof(*otpinfo);
2397 *retlen += sizeof(*otpinfo);
2398 } else if (from >= groupsize) {
2399 from -= groupsize;
Nicolas Pitre332d71f2005-02-17 20:35:04 +00002400 data_offset += groupsize;
Nicolas Pitref77814d2005-02-08 17:11:19 +00002401 } else {
2402 int size = groupsize;
2403 data_offset += from;
2404 size -= from;
2405 from = 0;
2406 if (size > len)
2407 size = len;
2408 ret = action(map, chip, data_offset,
2409 buf, size, reg_prot_offset,
2410 groupno, groupsize);
2411 if (ret < 0)
2412 return ret;
2413 buf += size;
2414 len -= size;
2415 *retlen += size;
Nicolas Pitre332d71f2005-02-17 20:35:04 +00002416 data_offset += size;
Nicolas Pitref77814d2005-02-08 17:11:19 +00002417 }
2418 groupno++;
2419 groups--;
2420 }
2421
2422 /* next OTP region */
2423 if (++field == extp->NumProtectionFields)
2424 break;
2425 reg_prot_offset = otp->ProtRegAddr;
2426 reg_fact_groups = otp->FactGroups;
2427 reg_fact_size = 1 << otp->FactProtRegSize;
2428 reg_user_groups = otp->UserGroups;
2429 reg_user_size = 1 << otp->UserProtRegSize;
2430 otp++;
2431 }
2432 }
2433
2434 return 0;
2435}
2436
2437static int cfi_intelext_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
2438 size_t len, size_t *retlen,
2439 u_char *buf)
2440{
2441 return cfi_intelext_otp_walk(mtd, from, len, retlen,
2442 buf, do_otp_read, 0);
2443}
2444
2445static int cfi_intelext_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
2446 size_t len, size_t *retlen,
2447 u_char *buf)
2448{
2449 return cfi_intelext_otp_walk(mtd, from, len, retlen,
2450 buf, do_otp_read, 1);
2451}
2452
2453static int cfi_intelext_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
2454 size_t len, size_t *retlen,
2455 u_char *buf)
2456{
2457 return cfi_intelext_otp_walk(mtd, from, len, retlen,
2458 buf, do_otp_write, 1);
2459}
2460
2461static int cfi_intelext_lock_user_prot_reg(struct mtd_info *mtd,
2462 loff_t from, size_t len)
2463{
2464 size_t retlen;
2465 return cfi_intelext_otp_walk(mtd, from, len, &retlen,
2466 NULL, do_otp_lock, 1);
2467}
2468
Christian Riesch4b78fc42014-01-28 09:29:44 +01002469static int cfi_intelext_get_fact_prot_info(struct mtd_info *mtd, size_t len,
2470 size_t *retlen, struct otp_info *buf)
Nicolas Pitref77814d2005-02-08 17:11:19 +00002471
Christian Riesch4b78fc42014-01-28 09:29:44 +01002472{
2473 return cfi_intelext_otp_walk(mtd, 0, len, retlen, (u_char *)buf,
2474 NULL, 0);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002475}
2476
Christian Riesch4b78fc42014-01-28 09:29:44 +01002477static int cfi_intelext_get_user_prot_info(struct mtd_info *mtd, size_t len,
2478 size_t *retlen, struct otp_info *buf)
Nicolas Pitref77814d2005-02-08 17:11:19 +00002479{
Christian Riesch4b78fc42014-01-28 09:29:44 +01002480 return cfi_intelext_otp_walk(mtd, 0, len, retlen, (u_char *)buf,
2481 NULL, 1);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002482}
2483
2484#endif
2485
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002486static void cfi_intelext_save_locks(struct mtd_info *mtd)
2487{
2488 struct mtd_erase_region_info *region;
2489 int block, status, i;
2490 unsigned long adr;
2491 size_t len;
2492
2493 for (i = 0; i < mtd->numeraseregions; i++) {
2494 region = &mtd->eraseregions[i];
2495 if (!region->lockmap)
2496 continue;
2497
2498 for (block = 0; block < region->numblocks; block++){
2499 len = region->erasesize;
2500 adr = region->offset + block * len;
2501
2502 status = cfi_varsize_frob(mtd,
Ben Dooks029a9eb2007-05-28 20:11:37 +01002503 do_getlockstatus_oneblock, adr, len, NULL);
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002504 if (status)
2505 set_bit(block, region->lockmap);
2506 else
2507 clear_bit(block, region->lockmap);
2508 }
2509 }
2510}
2511
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512static int cfi_intelext_suspend(struct mtd_info *mtd)
2513{
2514 struct map_info *map = mtd->priv;
2515 struct cfi_private *cfi = map->fldrv_priv;
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002516 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 int i;
2518 struct flchip *chip;
2519 int ret = 0;
2520
Justin Treone619a752008-01-30 10:25:49 -08002521 if ((mtd->flags & MTD_POWERUP_LOCK)
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002522 && extp && (extp->FeatureSupport & (1 << 5)))
2523 cfi_intelext_save_locks(mtd);
2524
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 for (i=0; !ret && i<cfi->numchips; i++) {
2526 chip = &cfi->chips[i];
2527
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002528 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529
2530 switch (chip->state) {
2531 case FL_READY:
2532 case FL_STATUS:
2533 case FL_CFI_QUERY:
2534 case FL_JEDEC_QUERY:
2535 if (chip->oldstate == FL_READY) {
David Andersa86aaa62006-10-19 19:33:19 +03002536 /* place the chip in a known state before suspend */
2537 map_write(map, CMD(0xFF), cfi->chips[i].start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 chip->oldstate = chip->state;
2539 chip->state = FL_PM_SUSPENDED;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002540 /* No need to wake_up() on this state change -
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 * as the whole point is that nobody can do anything
2542 * with the chip now anyway.
2543 */
2544 } else {
2545 /* There seems to be an operation pending. We must wait for it. */
2546 printk(KERN_NOTICE "Flash device refused suspend due to pending operation (oldstate %d)\n", chip->oldstate);
2547 ret = -EAGAIN;
2548 }
2549 break;
2550 default:
2551 /* Should we actually wait? Once upon a time these routines weren't
2552 allowed to. Or should we return -EAGAIN, because the upper layers
2553 ought to have already shut down anything which was using the device
2554 anyway? The latter for now. */
Russell King342d3a92012-02-15 11:48:34 +00002555 printk(KERN_NOTICE "Flash device refused suspend due to active operation (state %d)\n", chip->state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556 ret = -EAGAIN;
2557 case FL_PM_SUSPENDED:
2558 break;
2559 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002560 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 }
2562
2563 /* Unlock the chips again */
2564
2565 if (ret) {
2566 for (i--; i >=0; i--) {
2567 chip = &cfi->chips[i];
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002568
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002569 mutex_lock(&chip->mutex);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002570
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 if (chip->state == FL_PM_SUSPENDED) {
2572 /* No need to force it into a known state here,
2573 because we're returning failure, and it didn't
2574 get power cycled */
2575 chip->state = chip->oldstate;
2576 chip->oldstate = FL_READY;
2577 wake_up(&chip->wq);
2578 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002579 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002581 }
2582
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 return ret;
2584}
2585
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002586static void cfi_intelext_restore_locks(struct mtd_info *mtd)
2587{
2588 struct mtd_erase_region_info *region;
2589 int block, i;
2590 unsigned long adr;
2591 size_t len;
2592
2593 for (i = 0; i < mtd->numeraseregions; i++) {
2594 region = &mtd->eraseregions[i];
2595 if (!region->lockmap)
2596 continue;
2597
Akinobu Mitac527b412012-03-23 15:02:05 -07002598 for_each_clear_bit(block, region->lockmap, region->numblocks) {
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002599 len = region->erasesize;
2600 adr = region->offset + block * len;
Akinobu Mitac527b412012-03-23 15:02:05 -07002601 cfi_intelext_unlock(mtd, adr, len);
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002602 }
2603 }
2604}
2605
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606static void cfi_intelext_resume(struct mtd_info *mtd)
2607{
2608 struct map_info *map = mtd->priv;
2609 struct cfi_private *cfi = map->fldrv_priv;
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002610 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 int i;
2612 struct flchip *chip;
2613
2614 for (i=0; i<cfi->numchips; i++) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002615
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 chip = &cfi->chips[i];
2617
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002618 mutex_lock(&chip->mutex);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002619
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 /* Go to known state. Chip may have been power cycled */
2621 if (chip->state == FL_PM_SUSPENDED) {
Dmitry Eremin-Solenikov89cf38d2014-10-23 01:23:01 +02002622 /* Refresh LH28F640BF Partition Config. Register */
2623 fixup_LH28F640BF(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 map_write(map, CMD(0xFF), cfi->chips[i].start);
2625 chip->oldstate = chip->state = FL_READY;
2626 wake_up(&chip->wq);
2627 }
2628
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002629 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 }
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002631
Justin Treone619a752008-01-30 10:25:49 -08002632 if ((mtd->flags & MTD_POWERUP_LOCK)
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002633 && extp && (extp->FeatureSupport & (1 << 5)))
2634 cfi_intelext_restore_locks(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635}
2636
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002637static int cfi_intelext_reset(struct mtd_info *mtd)
2638{
2639 struct map_info *map = mtd->priv;
2640 struct cfi_private *cfi = map->fldrv_priv;
2641 int i, ret;
2642
2643 for (i=0; i < cfi->numchips; i++) {
2644 struct flchip *chip = &cfi->chips[i];
2645
2646 /* force the completion of any ongoing operation
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002647 and switch to array mode so any bootloader in
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002648 flash is accessible for soft reboot. */
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002649 mutex_lock(&chip->mutex);
Kevin Haoc4a9f882007-10-02 13:56:04 -07002650 ret = get_chip(map, chip, chip->start, FL_SHUTDOWN);
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002651 if (!ret) {
2652 map_write(map, CMD(0xff), chip->start);
Kevin Haoc4a9f882007-10-02 13:56:04 -07002653 chip->state = FL_SHUTDOWN;
Nicolas Pitrec9f7ec32009-10-23 16:02:42 -04002654 put_chip(map, chip, chip->start);
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002655 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002656 mutex_unlock(&chip->mutex);
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002657 }
2658
2659 return 0;
2660}
2661
2662static int cfi_intelext_reboot(struct notifier_block *nb, unsigned long val,
2663 void *v)
2664{
2665 struct mtd_info *mtd;
2666
2667 mtd = container_of(nb, struct mtd_info, reboot_notifier);
2668 cfi_intelext_reset(mtd);
2669 return NOTIFY_DONE;
2670}
2671
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672static void cfi_intelext_destroy(struct mtd_info *mtd)
2673{
2674 struct map_info *map = mtd->priv;
2675 struct cfi_private *cfi = map->fldrv_priv;
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002676 struct mtd_erase_region_info *region;
2677 int i;
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002678 cfi_intelext_reset(mtd);
2679 unregister_reboot_notifier(&mtd->reboot_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 kfree(cfi->cmdset_priv);
2681 kfree(cfi->cfiq);
2682 kfree(cfi->chips[0].priv);
2683 kfree(cfi);
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002684 for (i = 0; i < mtd->numeraseregions; i++) {
2685 region = &mtd->eraseregions[i];
Markus Elfring05a221b2014-11-20 13:50:43 +01002686 kfree(region->lockmap);
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002687 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688 kfree(mtd->eraseregions);
2689}
2690
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691MODULE_LICENSE("GPL");
2692MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
2693MODULE_DESCRIPTION("MTD chip driver for Intel/Sharp flash chips");
David Woodhousea15bdee2006-05-08 22:35:05 +01002694MODULE_ALIAS("cfi_cmdset_0003");
2695MODULE_ALIAS("cfi_cmdset_0200");