blob: 79a53cb8507b69a6102c8ac7e9d7716eb58dc021 [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 Tjernlund46a16a22018-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 Riesch4b78fc42f2014-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 Tjernlund46a16a22018-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 Woodhouse2a5bd5962007-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;
Kees Cook6396bb22018-06-12 14:03:40 -0700611 mtd->eraseregions = kcalloc(mtd->numeraseregions,
612 sizeof(struct mtd_erase_region_info),
613 GFP_KERNEL);
Jingoo Han5c8b1fb2014-02-06 15:19:35 +0900614 if (!mtd->eraseregions)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 goto setup_err;
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000616
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
618 unsigned long ernum, ersize;
619 ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
620 ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
621
622 if (mtd->erasesize < ersize) {
623 mtd->erasesize = ersize;
624 }
625 for (j=0; j<cfi->numchips; j++) {
626 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
627 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
628 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -0800629 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap = kmalloc(ernum / 8 + 1, GFP_KERNEL);
Insu Yun33853eb2015-12-29 13:45:09 -0500630 if (!mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap)
631 goto setup_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 }
633 offset += (ersize * ernum);
634 }
635
636 if (offset != devsize) {
637 /* Argh */
638 printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
639 goto setup_err;
640 }
641
642 for (i=0; i<mtd->numeraseregions;i++){
Adrian Hunter69423d92008-12-10 13:37:21 +0000643 printk(KERN_DEBUG "erase region %d: offset=0x%llx,size=0x%x,blocks=%d\n",
644 i,(unsigned long long)mtd->eraseregions[i].offset,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 mtd->eraseregions[i].erasesize,
646 mtd->eraseregions[i].numblocks);
647 }
648
Nicolas Pitref77814d2005-02-08 17:11:19 +0000649#ifdef CONFIG_MTD_OTP
Artem Bityutskiy3c3c10b2012-01-30 14:58:32 +0200650 mtd->_read_fact_prot_reg = cfi_intelext_read_fact_prot_reg;
651 mtd->_read_user_prot_reg = cfi_intelext_read_user_prot_reg;
652 mtd->_write_user_prot_reg = cfi_intelext_write_user_prot_reg;
653 mtd->_lock_user_prot_reg = cfi_intelext_lock_user_prot_reg;
654 mtd->_get_fact_prot_info = cfi_intelext_get_fact_prot_info;
655 mtd->_get_user_prot_info = cfi_intelext_get_user_prot_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656#endif
657
658 /* This function has the potential to distort the reality
659 a bit and therefore should be called last. */
660 if (cfi_intelext_partition_fixup(mtd, &cfi) != 0)
661 goto setup_err;
662
663 __module_get(THIS_MODULE);
Nicolas Pitre963a6fb2005-04-01 02:59:56 +0100664 register_reboot_notifier(&mtd->reboot_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 return mtd;
666
667 setup_err:
Insu Yun33853eb2015-12-29 13:45:09 -0500668 if (mtd->eraseregions)
669 for (i=0; i<cfi->cfiq->NumEraseRegions; i++)
670 for (j=0; j<cfi->numchips; j++)
671 kfree(mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap);
Jiri Slaby17fabf12010-01-10 10:01:19 +0100672 kfree(mtd->eraseregions);
673 kfree(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 kfree(cfi->cmdset_priv);
675 return NULL;
676}
677
678static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
679 struct cfi_private **pcfi)
680{
681 struct map_info *map = mtd->priv;
682 struct cfi_private *cfi = *pcfi;
683 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
684
685 /*
Jesper Juhl8f1a8662007-07-05 02:18:34 +0200686 * Probing of multi-partition flash chips.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 *
688 * To support multiple partitions when available, we simply arrange
689 * for each of them to have their own flchip structure even if they
690 * are on the same physical chip. This means completely recreating
691 * a new cfi_private structure right here which is a blatent code
692 * layering violation, but this is still the least intrusive
693 * arrangement at this point. This can be rearranged in the future
694 * if someone feels motivated enough. --nico
695 */
Nicolas Pitre638d9832005-08-06 05:40:46 +0100696 if (extp && extp->MajorVersion == '1' && extp->MinorVersion >= '3'
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 && extp->FeatureSupport & (1 << 9)) {
698 struct cfi_private *newcfi;
699 struct flchip *chip;
700 struct flchip_shared *shared;
701 int offs, numregions, numparts, partshift, numvirtchips, i, j;
702
703 /* Protection Register info */
Nicolas Pitre72b56a22005-02-05 02:06:19 +0000704 offs = (extp->NumProtectionFields - 1) *
705 sizeof(struct cfi_intelext_otpinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
707 /* Burst Read info */
Nicolas Pitre6f6ed052005-10-25 21:28:43 +0100708 offs += extp->extra[offs+1]+2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
710 /* Number of partition regions */
711 numregions = extp->extra[offs];
712 offs += 1;
713
Nicolas Pitre638d9832005-08-06 05:40:46 +0100714 /* skip the sizeof(partregion) field in CFI 1.4 */
715 if (extp->MinorVersion >= '4')
716 offs += 2;
717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 /* Number of hardware partitions */
719 numparts = 0;
720 for (i = 0; i < numregions; i++) {
721 struct cfi_intelext_regioninfo *rinfo;
722 rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[offs];
723 numparts += rinfo->NumIdentPartitions;
724 offs += sizeof(*rinfo)
725 + (rinfo->NumBlockTypes - 1) *
726 sizeof(struct cfi_intelext_blockinfo);
727 }
728
Thomas Kunzefe224662008-04-23 01:40:52 +0200729 if (!numparts)
730 numparts = 1;
731
Nicolas Pitre638d9832005-08-06 05:40:46 +0100732 /* Programming Region info */
733 if (extp->MinorVersion >= '4') {
734 struct cfi_intelext_programming_regioninfo *prinfo;
735 prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs];
Joern Engel28318772006-05-22 23:18:05 +0200736 mtd->writesize = cfi->interleave << prinfo->ProgRegShift;
Joern Engel5fa43392006-05-22 23:18:29 +0200737 mtd->flags &= ~MTD_BIT_WRITEABLE;
Nicolas Pitre638d9832005-08-06 05:40:46 +0100738 printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n",
Joern Engel28318772006-05-22 23:18:05 +0200739 map->name, mtd->writesize,
Artem Bityutskiyd4160852007-01-30 10:45:55 +0200740 cfi->interleave * prinfo->ControlValid,
741 cfi->interleave * prinfo->ControlInvalid);
Nicolas Pitre638d9832005-08-06 05:40:46 +0100742 }
743
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 /*
745 * All functions below currently rely on all chips having
746 * the same geometry so we'll just assume that all hardware
747 * partitions are of the same size too.
748 */
749 partshift = cfi->chipshift - __ffs(numparts);
750
751 if ((1 << partshift) < mtd->erasesize) {
752 printk( KERN_ERR
753 "%s: bad number of hw partitions (%d)\n",
Harvey Harrisoncb53b3b2008-04-18 13:44:19 -0700754 __func__, numparts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 return -EINVAL;
756 }
757
758 numvirtchips = cfi->numchips * numparts;
Gustavo A. R. Silva04b4c062019-01-08 09:52:44 -0600759 newcfi = kmalloc(struct_size(newcfi, chips, numvirtchips),
760 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 if (!newcfi)
762 return -ENOMEM;
Kees Cook6da2ec52018-06-12 13:55:00 -0700763 shared = kmalloc_array(cfi->numchips,
764 sizeof(struct flchip_shared),
765 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 if (!shared) {
767 kfree(newcfi);
768 return -ENOMEM;
769 }
770 memcpy(newcfi, cfi, sizeof(struct cfi_private));
771 newcfi->numchips = numvirtchips;
772 newcfi->chipshift = partshift;
773
774 chip = &newcfi->chips[0];
775 for (i = 0; i < cfi->numchips; i++) {
776 shared[i].writing = shared[i].erasing = NULL;
Stefani Seibold8ae66412010-08-05 09:19:26 +0200777 mutex_init(&shared[i].lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 for (j = 0; j < numparts; j++) {
779 *chip = cfi->chips[i];
780 chip->start += j << partshift;
781 chip->priv = &shared[i];
782 /* those should be reset too since
783 they create memory references. */
784 init_waitqueue_head(&chip->wq);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200785 mutex_init(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 chip++;
787 }
788 }
789
790 printk(KERN_DEBUG "%s: %d set(s) of %d interleaved chips "
791 "--> %d partitions of %d KiB\n",
792 map->name, cfi->numchips, cfi->interleave,
793 newcfi->numchips, 1<<(newcfi->chipshift-10));
794
795 map->fldrv_priv = newcfi;
796 *pcfi = newcfi;
797 kfree(cfi);
798 }
799
800 return 0;
801}
802
803/*
804 * *********** CHIP ACCESS FUNCTIONS ***********
805 */
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100806static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807{
808 DECLARE_WAITQUEUE(wait, current);
809 struct cfi_private *cfi = map->fldrv_priv;
810 map_word status, status_OK = CMD(0x80), status_PWS = CMD(0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100812 unsigned long timeo = jiffies + HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
Alexander Belyakov3afe7eb2008-09-25 17:53:24 +0400814 /* Prevent setting state FL_SYNCING for chip in suspended state. */
815 if (mode == FL_SYNCING && chip->oldstate != FL_READY)
816 goto sleep;
817
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 switch (chip->state) {
819
820 case FL_STATUS:
821 for (;;) {
822 status = map_read(map, adr);
823 if (map_word_andequal(map, status, status_OK, status_OK))
824 break;
825
826 /* At this point we're fine with write operations
827 in other partitions as they don't conflict. */
828 if (chip->priv && map_word_andequal(map, status, status_PWS, status_PWS))
829 break;
830
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200831 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 cfi_udelay(1);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200833 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 /* Someone else might have been playing with it. */
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100835 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 }
Alexey Korolevfb6d0802008-04-04 14:30:01 -0700837 /* Fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 case FL_READY:
839 case FL_CFI_QUERY:
840 case FL_JEDEC_QUERY:
841 return 0;
842
843 case FL_ERASING:
844 if (!cfip ||
845 !(cfip->FeatureSupport & 2) ||
846 !(mode == FL_READY || mode == FL_POINT ||
847 (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1))))
848 goto sleep;
849
Joakim Tjernlund6510bbc2018-03-01 14:39:39 +0100850 /* Do not allow suspend iff read/write to EB address */
851 if ((adr & chip->in_progress_block_mask) ==
852 chip->in_progress_block_addr)
853 goto sleep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854
Joakim Tjernlund46a16a22018-03-01 14:39:40 +0100855 /* do not suspend small EBs, buggy Micron Chips */
856 if (cfi_is_micron_28F00AP30(cfi, chip) &&
857 (chip->in_progress_block_mask == ~(0x8000-1)))
858 goto sleep;
859
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 /* Erase suspend */
Joakim Tjernlund6510bbc2018-03-01 14:39:39 +0100861 map_write(map, CMD(0xB0), chip->in_progress_block_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
863 /* If the flash has finished erasing, then 'erase suspend'
864 * appears to make some (28F320) flash devices switch to
865 * 'read' mode. Make sure that we switch to 'read status'
866 * mode so we get the right data. --rmk
867 */
Joakim Tjernlund6510bbc2018-03-01 14:39:39 +0100868 map_write(map, CMD(0x70), chip->in_progress_block_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 chip->oldstate = FL_ERASING;
870 chip->state = FL_ERASE_SUSPENDING;
871 chip->erase_suspended = 1;
872 for (;;) {
Joakim Tjernlund6510bbc2018-03-01 14:39:39 +0100873 status = map_read(map, chip->in_progress_block_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 if (map_word_andequal(map, status, status_OK, status_OK))
875 break;
876
877 if (time_after(jiffies, timeo)) {
Tadashi Abe100f2342011-05-19 15:58:15 +0900878 /* Urgh. Resume and pretend we weren't here.
879 * Make sure we're in 'read status' mode if it had finished */
880 put_chip(map, chip, adr);
Nicolas Pitre48436532005-08-06 05:16:52 +0100881 printk(KERN_ERR "%s: Chip not ready after erase "
882 "suspended: status = 0x%lx\n", map->name, status.x[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 return -EIO;
884 }
885
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200886 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 cfi_udelay(1);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200888 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 /* Nobody will touch it while it's in state FL_ERASE_SUSPENDING.
890 So we can just loop here. */
891 }
892 chip->state = FL_STATUS;
893 return 0;
894
895 case FL_XIP_WHILE_ERASING:
896 if (mode != FL_READY && mode != FL_POINT &&
897 (mode != FL_WRITING || !cfip || !(cfip->SuspendCmdSupport&1)))
898 goto sleep;
899 chip->oldstate = chip->state;
900 chip->state = FL_READY;
901 return 0;
902
Alexey Korolevfb6d0802008-04-04 14:30:01 -0700903 case FL_SHUTDOWN:
904 /* The machine is rebooting now,so no one can get chip anymore */
905 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 case FL_POINT:
907 /* Only if there's no operation suspended... */
908 if (mode == FL_READY && chip->oldstate == FL_READY)
909 return 0;
Alexey Korolevfb6d0802008-04-04 14:30:01 -0700910 /* Fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 default:
912 sleep:
913 set_current_state(TASK_UNINTERRUPTIBLE);
914 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200915 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 schedule();
917 remove_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200918 mutex_lock(&chip->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100919 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 }
921}
922
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100923static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
924{
925 int ret;
Alexander Belyakov6c24e412007-11-07 11:58:07 +0300926 DECLARE_WAITQUEUE(wait, current);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100927
928 retry:
Alexander Belyakov3afe7eb2008-09-25 17:53:24 +0400929 if (chip->priv &&
930 (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE
931 || mode == FL_SHUTDOWN) && chip->state != FL_SYNCING) {
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100932 /*
933 * OK. We have possibility for contention on the write/erase
934 * operations which are global to the real chip and not per
935 * partition. So let's fight it over in the partition which
936 * currently has authority on the operation.
937 *
938 * The rules are as follows:
939 *
940 * - any write operation must own shared->writing.
941 *
942 * - any erase operation must own _both_ shared->writing and
943 * shared->erasing.
944 *
945 * - contention arbitration is handled in the owner's context.
946 *
947 * The 'shared' struct can be read and/or written only when
948 * its lock is taken.
949 */
950 struct flchip_shared *shared = chip->priv;
951 struct flchip *contender;
Stefani Seibold8ae66412010-08-05 09:19:26 +0200952 mutex_lock(&shared->lock);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100953 contender = shared->writing;
954 if (contender && contender != chip) {
955 /*
956 * The engine to perform desired operation on this
957 * partition is already in use by someone else.
958 * Let's fight over it in the context of the chip
959 * currently using it. If it is possible to suspend,
960 * that other partition will do just that, otherwise
961 * it'll happily send us to sleep. In any case, when
962 * get_chip returns success we're clear to go ahead.
963 */
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200964 ret = mutex_trylock(&contender->mutex);
Stefani Seibold8ae66412010-08-05 09:19:26 +0200965 mutex_unlock(&shared->lock);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100966 if (!ret)
967 goto retry;
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200968 mutex_unlock(&chip->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100969 ret = chip_ready(map, contender, contender->start, mode);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200970 mutex_lock(&chip->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100971
972 if (ret == -EAGAIN) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200973 mutex_unlock(&contender->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100974 goto retry;
975 }
976 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200977 mutex_unlock(&contender->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100978 return ret;
979 }
Stefani Seibold8ae66412010-08-05 09:19:26 +0200980 mutex_lock(&shared->lock);
Alexander Belyakov3afe7eb2008-09-25 17:53:24 +0400981
982 /* We should not own chip if it is already
983 * in FL_SYNCING state. Put contender and retry. */
984 if (chip->state == FL_SYNCING) {
985 put_chip(map, contender, contender->start);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200986 mutex_unlock(&contender->mutex);
Alexander Belyakov3afe7eb2008-09-25 17:53:24 +0400987 goto retry;
988 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200989 mutex_unlock(&contender->mutex);
Alexey Korolev5a37cf12007-10-22 17:55:20 +0100990 }
991
Alexander Belyakov6c24e412007-11-07 11:58:07 +0300992 /* Check if we already have suspended erase
993 * on this chip. Sleep. */
994 if (mode == FL_ERASING && shared->erasing
995 && shared->erasing->oldstate == FL_ERASING) {
Stefani Seibold8ae66412010-08-05 09:19:26 +0200996 mutex_unlock(&shared->lock);
Alexander Belyakov6c24e412007-11-07 11:58:07 +0300997 set_current_state(TASK_UNINTERRUPTIBLE);
998 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +0200999 mutex_unlock(&chip->mutex);
Alexander Belyakov6c24e412007-11-07 11:58:07 +03001000 schedule();
1001 remove_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001002 mutex_lock(&chip->mutex);
Alexander Belyakov6c24e412007-11-07 11:58:07 +03001003 goto retry;
1004 }
1005
Alexey Korolev5a37cf12007-10-22 17:55:20 +01001006 /* We now own it */
1007 shared->writing = chip;
1008 if (mode == FL_ERASING)
1009 shared->erasing = chip;
Stefani Seibold8ae66412010-08-05 09:19:26 +02001010 mutex_unlock(&shared->lock);
Alexey Korolev5a37cf12007-10-22 17:55:20 +01001011 }
1012 ret = chip_ready(map, chip, adr, mode);
1013 if (ret == -EAGAIN)
1014 goto retry;
1015
1016 return ret;
1017}
1018
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr)
1020{
1021 struct cfi_private *cfi = map->fldrv_priv;
1022
1023 if (chip->priv) {
1024 struct flchip_shared *shared = chip->priv;
Stefani Seibold8ae66412010-08-05 09:19:26 +02001025 mutex_lock(&shared->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 if (shared->writing == chip && chip->oldstate == FL_READY) {
1027 /* We own the ability to write, but we're done */
1028 shared->writing = shared->erasing;
1029 if (shared->writing && shared->writing != chip) {
1030 /* give back ownership to who we loaned it from */
1031 struct flchip *loaner = shared->writing;
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001032 mutex_lock(&loaner->mutex);
Stefani Seibold8ae66412010-08-05 09:19:26 +02001033 mutex_unlock(&shared->lock);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001034 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 put_chip(map, loaner, loaner->start);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001036 mutex_lock(&chip->mutex);
1037 mutex_unlock(&loaner->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 wake_up(&chip->wq);
1039 return;
1040 }
1041 shared->erasing = NULL;
1042 shared->writing = NULL;
1043 } else if (shared->erasing == chip && shared->writing != chip) {
1044 /*
1045 * We own the ability to erase without the ability
1046 * to write, which means the erase was suspended
1047 * and some other partition is currently writing.
1048 * Don't let the switch below mess things up since
1049 * we don't have ownership to resume anything.
1050 */
Stefani Seibold8ae66412010-08-05 09:19:26 +02001051 mutex_unlock(&shared->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 wake_up(&chip->wq);
1053 return;
1054 }
Stefani Seibold8ae66412010-08-05 09:19:26 +02001055 mutex_unlock(&shared->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 }
1057
1058 switch(chip->oldstate) {
1059 case FL_ERASING:
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001060 /* What if one interleaved chip has finished and the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 other hasn't? The old code would leave the finished
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001062 one in READY mode. That's bad, and caused -EROFS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 errors to be returned from do_erase_oneblock because
1064 that's the only bit it checked for at the time.
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001065 As the state machine appears to explicitly allow
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 sending the 0x70 (Read Status) command to an erasing
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001067 chip and expecting it to be ignored, that's what we
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 do. */
Joakim Tjernlund6510bbc2018-03-01 14:39:39 +01001069 map_write(map, CMD(0xd0), chip->in_progress_block_addr);
1070 map_write(map, CMD(0x70), chip->in_progress_block_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 chip->oldstate = FL_READY;
1072 chip->state = FL_ERASING;
1073 break;
1074
1075 case FL_XIP_WHILE_ERASING:
1076 chip->state = chip->oldstate;
1077 chip->oldstate = FL_READY;
1078 break;
1079
1080 case FL_READY:
1081 case FL_STATUS:
1082 case FL_JEDEC_QUERY:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 break;
1084 default:
Nicolas Pitre48436532005-08-06 05:16:52 +01001085 printk(KERN_ERR "%s: put_chip() called with oldstate %d!!\n", map->name, chip->oldstate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 }
1087 wake_up(&chip->wq);
1088}
1089
1090#ifdef CONFIG_MTD_XIP
1091
1092/*
1093 * No interrupt what so ever can be serviced while the flash isn't in array
1094 * mode. This is ensured by the xip_disable() and xip_enable() functions
1095 * enclosing any code path where the flash is known not to be in array mode.
1096 * And within a XIP disabled code path, only functions marked with __xipram
1097 * may be called and nothing else (it's a good thing to inspect generated
1098 * assembly to make sure inline functions were actually inlined and that gcc
1099 * didn't emit calls to its own support functions). Also configuring MTD CFI
1100 * support to a single buswidth and a single interleave is also recommended.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 */
1102
1103static void xip_disable(struct map_info *map, struct flchip *chip,
1104 unsigned long adr)
1105{
1106 /* TODO: chips with no XIP use should ignore and return */
1107 (void) map_read(map, adr); /* ensure mmu mapping is up to date */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 local_irq_disable();
1109}
1110
1111static void __xipram xip_enable(struct map_info *map, struct flchip *chip,
1112 unsigned long adr)
1113{
1114 struct cfi_private *cfi = map->fldrv_priv;
1115 if (chip->state != FL_POINT && chip->state != FL_READY) {
1116 map_write(map, CMD(0xff), adr);
1117 chip->state = FL_READY;
1118 }
1119 (void) map_read(map, adr);
Thomas Gleixner97f927a2005-07-07 16:50:16 +02001120 xip_iprefetch();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 local_irq_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122}
1123
1124/*
1125 * When a delay is required for the flash operation to complete, the
Nicolas Pitrec1724712006-03-30 15:52:41 +01001126 * xip_wait_for_operation() function is polling for both the given timeout
1127 * and pending (but still masked) hardware interrupts. Whenever there is an
1128 * interrupt pending then the flash erase or write operation is suspended,
1129 * array mode restored and interrupts unmasked. Task scheduling might also
1130 * happen at that point. The CPU eventually returns from the interrupt or
1131 * the call to schedule() and the suspended flash operation is resumed for
1132 * the remaining of the delay period.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 *
1134 * Warning: this function _will_ fool interrupt latency tracing tools.
1135 */
1136
Nicolas Pitrec1724712006-03-30 15:52:41 +01001137static int __xipram xip_wait_for_operation(
1138 struct map_info *map, struct flchip *chip,
Anders Grafströme93cafe2008-08-05 18:37:41 +02001139 unsigned long adr, unsigned int chip_op_time_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140{
1141 struct cfi_private *cfi = map->fldrv_priv;
1142 struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
1143 map_word status, OK = CMD(0x80);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001144 unsigned long usec, suspended, start, done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 flstate_t oldstate, newstate;
1146
Nicolas Pitrec1724712006-03-30 15:52:41 +01001147 start = xip_currtime();
Anders Grafströme93cafe2008-08-05 18:37:41 +02001148 usec = chip_op_time_max;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001149 if (usec == 0)
1150 usec = 500000;
1151 done = 0;
1152
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 do {
1154 cpu_relax();
1155 if (xip_irqpending() && cfip &&
1156 ((chip->state == FL_ERASING && (cfip->FeatureSupport&2)) ||
1157 (chip->state == FL_WRITING && (cfip->FeatureSupport&4))) &&
1158 (cfi_interleave_is_1(cfi) || chip->oldstate == FL_READY)) {
1159 /*
1160 * Let's suspend the erase or write operation when
1161 * supported. Note that we currently don't try to
1162 * suspend interleaved chips if there is already
1163 * another operation suspended (imagine what happens
1164 * when one chip was already done with the current
1165 * operation while another chip suspended it, then
1166 * we resume the whole thing at once). Yes, it
1167 * can happen!
1168 */
Nicolas Pitrec1724712006-03-30 15:52:41 +01001169 usec -= done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 map_write(map, CMD(0xb0), adr);
1171 map_write(map, CMD(0x70), adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 suspended = xip_currtime();
1173 do {
1174 if (xip_elapsed_since(suspended) > 100000) {
1175 /*
1176 * The chip doesn't want to suspend
1177 * after waiting for 100 msecs.
1178 * This is a critical error but there
1179 * is not much we can do here.
1180 */
Nicolas Pitrec1724712006-03-30 15:52:41 +01001181 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 }
1183 status = map_read(map, adr);
1184 } while (!map_word_andequal(map, status, OK, OK));
1185
1186 /* Suspend succeeded */
1187 oldstate = chip->state;
1188 if (oldstate == FL_ERASING) {
1189 if (!map_word_bitsset(map, status, CMD(0x40)))
1190 break;
1191 newstate = FL_XIP_WHILE_ERASING;
1192 chip->erase_suspended = 1;
1193 } else {
1194 if (!map_word_bitsset(map, status, CMD(0x04)))
1195 break;
1196 newstate = FL_XIP_WHILE_WRITING;
1197 chip->write_suspended = 1;
1198 }
1199 chip->state = newstate;
1200 map_write(map, CMD(0xff), adr);
1201 (void) map_read(map, adr);
Paulius Zaleckasca5c23c2008-02-27 01:42:39 +02001202 xip_iprefetch();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 local_irq_enable();
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001204 mutex_unlock(&chip->mutex);
Paulius Zaleckasca5c23c2008-02-27 01:42:39 +02001205 xip_iprefetch();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 cond_resched();
1207
1208 /*
1209 * We're back. However someone else might have
1210 * decided to go write to the chip if we are in
1211 * a suspended erase state. If so let's wait
1212 * until it's done.
1213 */
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001214 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 while (chip->state != newstate) {
1216 DECLARE_WAITQUEUE(wait, current);
1217 set_current_state(TASK_UNINTERRUPTIBLE);
1218 add_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001219 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 schedule();
1221 remove_wait_queue(&chip->wq, &wait);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001222 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 }
1224 /* Disallow XIP again */
1225 local_irq_disable();
1226
1227 /* Resume the write or erase operation */
1228 map_write(map, CMD(0xd0), adr);
1229 map_write(map, CMD(0x70), adr);
1230 chip->state = oldstate;
1231 start = xip_currtime();
1232 } else if (usec >= 1000000/HZ) {
1233 /*
1234 * Try to save on CPU power when waiting delay
1235 * is at least a system timer tick period.
1236 * No need to be extremely accurate here.
1237 */
1238 xip_cpu_idle();
1239 }
1240 status = map_read(map, adr);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001241 done = xip_elapsed_since(start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 } while (!map_word_andequal(map, status, OK, OK)
Nicolas Pitrec1724712006-03-30 15:52:41 +01001243 && done < usec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
Nicolas Pitrec1724712006-03-30 15:52:41 +01001245 return (done >= usec) ? -ETIME : 0;
1246}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247
1248/*
1249 * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while
1250 * the flash is actively programming or erasing since we have to poll for
1251 * the operation to complete anyway. We can't do that in a generic way with
Nicolas Pitre6da70122005-05-19 18:05:47 +01001252 * a XIP setup so do it before the actual flash operation in this case
Nicolas Pitrec1724712006-03-30 15:52:41 +01001253 * and stub it out from INVAL_CACHE_AND_WAIT.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 */
Nicolas Pitre6da70122005-05-19 18:05:47 +01001255#define XIP_INVAL_CACHED_RANGE(map, from, size) \
1256 INVALIDATE_CACHED_RANGE(map, from, size)
1257
Anders Grafströme93cafe2008-08-05 18:37:41 +02001258#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec, usec_max) \
1259 xip_wait_for_operation(map, chip, cmd_adr, usec_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
1261#else
1262
1263#define xip_disable(map, chip, adr)
1264#define xip_enable(map, chip, adr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265#define XIP_INVAL_CACHED_RANGE(x...)
Nicolas Pitrec1724712006-03-30 15:52:41 +01001266#define INVAL_CACHE_AND_WAIT inval_cache_and_wait_for_operation
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
Nicolas Pitrec1724712006-03-30 15:52:41 +01001268static int inval_cache_and_wait_for_operation(
1269 struct map_info *map, struct flchip *chip,
1270 unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
Anders Grafströme93cafe2008-08-05 18:37:41 +02001271 unsigned int chip_op_time, unsigned int chip_op_time_max)
Nicolas Pitrec1724712006-03-30 15:52:41 +01001272{
1273 struct cfi_private *cfi = map->fldrv_priv;
1274 map_word status, status_OK = CMD(0x80);
Alexey Korolev46a16522006-06-28 19:22:07 +01001275 int chip_state = chip->state;
Alexey Korolev998453f2008-07-16 15:28:56 +01001276 unsigned int timeo, sleep_time, reset_timeo;
Nicolas Pitre6da70122005-05-19 18:05:47 +01001277
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001278 mutex_unlock(&chip->mutex);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001279 if (inval_len)
1280 INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001281 mutex_lock(&chip->mutex);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001282
Anders Grafströme93cafe2008-08-05 18:37:41 +02001283 timeo = chip_op_time_max;
Alexey Korolev46a16522006-06-28 19:22:07 +01001284 if (!timeo)
1285 timeo = 500000;
Alexey Korolev998453f2008-07-16 15:28:56 +01001286 reset_timeo = timeo;
Alexey Korolev46a16522006-06-28 19:22:07 +01001287 sleep_time = chip_op_time / 2;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001288
Nicolas Pitrec1724712006-03-30 15:52:41 +01001289 for (;;) {
Joakim Tjernlundecf3fde2011-02-07 17:07:11 +01001290 if (chip->state != chip_state) {
1291 /* Someone's suspended the operation: sleep */
1292 DECLARE_WAITQUEUE(wait, current);
1293 set_current_state(TASK_UNINTERRUPTIBLE);
1294 add_wait_queue(&chip->wq, &wait);
1295 mutex_unlock(&chip->mutex);
1296 schedule();
1297 remove_wait_queue(&chip->wq, &wait);
1298 mutex_lock(&chip->mutex);
1299 continue;
1300 }
1301
Nicolas Pitrec1724712006-03-30 15:52:41 +01001302 status = map_read(map, cmd_adr);
1303 if (map_word_andequal(map, status, status_OK, status_OK))
1304 break;
1305
Joakim Tjernlundecf3fde2011-02-07 17:07:11 +01001306 if (chip->erase_suspended && chip_state == FL_ERASING) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001307 /* Erase suspend occurred while sleep: reset timeout */
Joakim Tjernlundecf3fde2011-02-07 17:07:11 +01001308 timeo = reset_timeo;
1309 chip->erase_suspended = 0;
1310 }
1311 if (chip->write_suspended && chip_state == FL_WRITING) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001312 /* Write suspend occurred while sleep: reset timeout */
Joakim Tjernlundecf3fde2011-02-07 17:07:11 +01001313 timeo = reset_timeo;
1314 chip->write_suspended = 0;
1315 }
Alexey Korolev46a16522006-06-28 19:22:07 +01001316 if (!timeo) {
Nicolas Pitrec1724712006-03-30 15:52:41 +01001317 map_write(map, CMD(0x70), cmd_adr);
1318 chip->state = FL_STATUS;
1319 return -ETIME;
1320 }
1321
Alexey Korolev46a16522006-06-28 19:22:07 +01001322 /* OK Still waiting. Drop the lock, wait a while and retry. */
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001323 mutex_unlock(&chip->mutex);
Alexey Korolev46a16522006-06-28 19:22:07 +01001324 if (sleep_time >= 1000000/HZ) {
1325 /*
1326 * Half of the normal delay still remaining
1327 * can be performed with a sleeping delay instead
1328 * of busy waiting.
1329 */
1330 msleep(sleep_time/1000);
1331 timeo -= sleep_time;
1332 sleep_time = 1000000/HZ;
1333 } else {
1334 udelay(1);
1335 cond_resched();
1336 timeo--;
1337 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001338 mutex_lock(&chip->mutex);
Alexey Korolev46a16522006-06-28 19:22:07 +01001339 }
Nicolas Pitrec1724712006-03-30 15:52:41 +01001340
1341 /* Done and happy. */
1342 chip->state = FL_STATUS;
1343 return 0;
1344}
Nicolas Pitre6da70122005-05-19 18:05:47 +01001345
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346#endif
1347
Anders Grafströme93cafe2008-08-05 18:37:41 +02001348#define WAIT_TIMEOUT(map, chip, adr, udelay, udelay_max) \
1349 INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay, udelay_max);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001350
1351
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
1353{
1354 unsigned long cmd_addr;
1355 struct cfi_private *cfi = map->fldrv_priv;
1356 int ret = 0;
1357
1358 adr += chip->start;
1359
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001360 /* Ensure cmd read/writes are aligned. */
1361 cmd_addr = adr & ~(map_bankwidth(map)-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001363 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
1365 ret = get_chip(map, chip, cmd_addr, FL_POINT);
1366
1367 if (!ret) {
1368 if (chip->state != FL_POINT && chip->state != FL_READY)
1369 map_write(map, CMD(0xff), cmd_addr);
1370
1371 chip->state = FL_POINT;
1372 chip->ref_point_counter++;
1373 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001374 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
1376 return ret;
1377}
1378
Jared Hulberta98889f2008-04-29 23:26:49 -07001379static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len,
1380 size_t *retlen, void **virt, resource_size_t *phys)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381{
1382 struct map_info *map = mtd->priv;
1383 struct cfi_private *cfi = map->fldrv_priv;
Andy Lowe097f2572007-01-12 18:05:10 -05001384 unsigned long ofs, last_end = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 int chipnum;
1386 int ret = 0;
1387
Artem Bityutskiy5def4892012-02-03 16:23:52 +02001388 if (!map->virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 return -EINVAL;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001390
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 /* Now lock the chip(s) to POINT state */
1392
1393 /* ofs: offset within the first chip that the first read should start */
1394 chipnum = (from >> cfi->chipshift);
1395 ofs = from - (chipnum << cfi->chipshift);
1396
Jared Hulberta98889f2008-04-29 23:26:49 -07001397 *virt = map->virt + cfi->chips[chipnum].start + ofs;
Jared Hulberta98889f2008-04-29 23:26:49 -07001398 if (phys)
1399 *phys = map->phys + cfi->chips[chipnum].start + ofs;
Andy Lowe097f2572007-01-12 18:05:10 -05001400
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 while (len) {
1402 unsigned long thislen;
1403
1404 if (chipnum >= cfi->numchips)
1405 break;
1406
Andy Lowe097f2572007-01-12 18:05:10 -05001407 /* We cannot point across chips that are virtually disjoint */
1408 if (!last_end)
1409 last_end = cfi->chips[chipnum].start;
1410 else if (cfi->chips[chipnum].start != last_end)
1411 break;
1412
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 if ((len + ofs -1) >> cfi->chipshift)
1414 thislen = (1<<cfi->chipshift) - ofs;
1415 else
1416 thislen = len;
1417
1418 ret = do_point_onechip(map, &cfi->chips[chipnum], ofs, thislen);
1419 if (ret)
1420 break;
1421
1422 *retlen += thislen;
1423 len -= thislen;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001424
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 ofs = 0;
Andy Lowe097f2572007-01-12 18:05:10 -05001426 last_end += 1 << cfi->chipshift;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 chipnum++;
1428 }
1429 return 0;
1430}
1431
Artem Bityutskiy5e4e6e32012-02-03 13:20:43 +02001432static int cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433{
1434 struct map_info *map = mtd->priv;
1435 struct cfi_private *cfi = map->fldrv_priv;
1436 unsigned long ofs;
Artem Bityutskiy5e4e6e32012-02-03 13:20:43 +02001437 int chipnum, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438
1439 /* Now unlock the chip(s) POINT state */
1440
1441 /* ofs: offset within the first chip that the first read should start */
1442 chipnum = (from >> cfi->chipshift);
1443 ofs = from - (chipnum << cfi->chipshift);
1444
Artem Bityutskiy5e4e6e32012-02-03 13:20:43 +02001445 while (len && !err) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 unsigned long thislen;
1447 struct flchip *chip;
1448
1449 chip = &cfi->chips[chipnum];
1450 if (chipnum >= cfi->numchips)
1451 break;
1452
1453 if ((len + ofs -1) >> cfi->chipshift)
1454 thislen = (1<<cfi->chipshift) - ofs;
1455 else
1456 thislen = len;
1457
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001458 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 if (chip->state == FL_POINT) {
1460 chip->ref_point_counter--;
1461 if(chip->ref_point_counter == 0)
1462 chip->state = FL_READY;
Artem Bityutskiy5e4e6e32012-02-03 13:20:43 +02001463 } else {
1464 printk(KERN_ERR "%s: Error: unpoint called on non pointed region\n", map->name);
1465 err = -EINVAL;
1466 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
1468 put_chip(map, chip, chip->start);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001469 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471 len -= thislen;
1472 ofs = 0;
1473 chipnum++;
1474 }
Artem Bityutskiy5e4e6e32012-02-03 13:20:43 +02001475
1476 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477}
1478
1479static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
1480{
1481 unsigned long cmd_addr;
1482 struct cfi_private *cfi = map->fldrv_priv;
1483 int ret;
1484
1485 adr += chip->start;
1486
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001487 /* Ensure cmd read/writes are aligned. */
1488 cmd_addr = adr & ~(map_bankwidth(map)-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001490 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 ret = get_chip(map, chip, cmd_addr, FL_READY);
1492 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001493 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 return ret;
1495 }
1496
1497 if (chip->state != FL_POINT && chip->state != FL_READY) {
1498 map_write(map, CMD(0xff), cmd_addr);
1499
1500 chip->state = FL_READY;
1501 }
1502
1503 map_copy_from(map, buf, adr, len);
1504
1505 put_chip(map, chip, cmd_addr);
1506
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001507 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 return 0;
1509}
1510
1511static int cfi_intelext_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
1512{
1513 struct map_info *map = mtd->priv;
1514 struct cfi_private *cfi = map->fldrv_priv;
1515 unsigned long ofs;
1516 int chipnum;
1517 int ret = 0;
1518
1519 /* ofs: offset within the first chip that the first read should start */
1520 chipnum = (from >> cfi->chipshift);
1521 ofs = from - (chipnum << cfi->chipshift);
1522
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 while (len) {
1524 unsigned long thislen;
1525
1526 if (chipnum >= cfi->numchips)
1527 break;
1528
1529 if ((len + ofs -1) >> cfi->chipshift)
1530 thislen = (1<<cfi->chipshift) - ofs;
1531 else
1532 thislen = len;
1533
1534 ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
1535 if (ret)
1536 break;
1537
1538 *retlen += thislen;
1539 len -= thislen;
1540 buf += thislen;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001541
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 ofs = 0;
1543 chipnum++;
1544 }
1545 return ret;
1546}
1547
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
Nicolas Pitref77814d2005-02-08 17:11:19 +00001549 unsigned long adr, map_word datum, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550{
1551 struct cfi_private *cfi = map->fldrv_priv;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001552 map_word status, write_cmd;
1553 int ret=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
1555 adr += chip->start;
1556
Nicolas Pitref77814d2005-02-08 17:11:19 +00001557 switch (mode) {
Nicolas Pitre638d9832005-08-06 05:40:46 +01001558 case FL_WRITING:
Guillaume LECERFb5d194c2010-10-26 10:55:29 +01001559 write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0x40) : CMD(0x41);
Nicolas Pitre638d9832005-08-06 05:40:46 +01001560 break;
1561 case FL_OTP_WRITE:
1562 write_cmd = CMD(0xc0);
1563 break;
1564 default:
1565 return -EINVAL;
Nicolas Pitref77814d2005-02-08 17:11:19 +00001566 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001568 mutex_lock(&chip->mutex);
Nicolas Pitref77814d2005-02-08 17:11:19 +00001569 ret = get_chip(map, chip, adr, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001571 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 return ret;
1573 }
1574
1575 XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));
1576 ENABLE_VPP(map);
1577 xip_disable(map, chip, adr);
Nicolas Pitref77814d2005-02-08 17:11:19 +00001578 map_write(map, write_cmd, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 map_write(map, datum, adr);
Nicolas Pitref77814d2005-02-08 17:11:19 +00001580 chip->state = mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581
Nicolas Pitrec1724712006-03-30 15:52:41 +01001582 ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
1583 adr, map_bankwidth(map),
Anders Grafströme93cafe2008-08-05 18:37:41 +02001584 chip->word_write_time,
1585 chip->word_write_time_max);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001586 if (ret) {
1587 xip_enable(map, chip, adr);
1588 printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
1589 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
Nicolas Pitre48436532005-08-06 05:16:52 +01001592 /* check for errors */
Nicolas Pitrec1724712006-03-30 15:52:41 +01001593 status = map_read(map, adr);
Nicolas Pitre48436532005-08-06 05:16:52 +01001594 if (map_word_bitsset(map, status, CMD(0x1a))) {
1595 unsigned long chipstatus = MERGESTATUS(status);
1596
1597 /* reset status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 map_write(map, CMD(0x50), adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 map_write(map, CMD(0x70), adr);
Nicolas Pitre48436532005-08-06 05:16:52 +01001600 xip_enable(map, chip, adr);
1601
1602 if (chipstatus & 0x02) {
1603 ret = -EROFS;
1604 } else if (chipstatus & 0x08) {
1605 printk(KERN_ERR "%s: word write error (bad VPP)\n", map->name);
1606 ret = -EIO;
1607 } else {
1608 printk(KERN_ERR "%s: word write error (status 0x%lx)\n", map->name, chipstatus);
1609 ret = -EINVAL;
1610 }
1611
1612 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 }
1614
1615 xip_enable(map, chip, adr);
Paul Parsons85e5b2f2012-03-07 14:10:33 +00001616 out: DISABLE_VPP(map);
1617 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001618 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 return ret;
1620}
1621
1622
1623static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
1624{
1625 struct map_info *map = mtd->priv;
1626 struct cfi_private *cfi = map->fldrv_priv;
1627 int ret = 0;
1628 int chipnum;
1629 unsigned long ofs;
1630
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 chipnum = to >> cfi->chipshift;
1632 ofs = to - (chipnum << cfi->chipshift);
1633
1634 /* If it's not bus-aligned, do the first byte write */
1635 if (ofs & (map_bankwidth(map)-1)) {
1636 unsigned long bus_ofs = ofs & ~(map_bankwidth(map)-1);
1637 int gap = ofs - bus_ofs;
1638 int n;
1639 map_word datum;
1640
1641 n = min_t(int, len, map_bankwidth(map)-gap);
1642 datum = map_word_ff(map);
1643 datum = map_word_load_partial(map, datum, buf, gap, n);
1644
1645 ret = do_write_oneword(map, &cfi->chips[chipnum],
Nicolas Pitref77814d2005-02-08 17:11:19 +00001646 bus_ofs, datum, FL_WRITING);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001647 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 return ret;
1649
1650 len -= n;
1651 ofs += n;
1652 buf += n;
1653 (*retlen) += n;
1654
1655 if (ofs >> cfi->chipshift) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001656 chipnum ++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 ofs = 0;
1658 if (chipnum == cfi->numchips)
1659 return 0;
1660 }
1661 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001662
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 while(len >= map_bankwidth(map)) {
1664 map_word datum = map_word_load(map, buf);
1665
1666 ret = do_write_oneword(map, &cfi->chips[chipnum],
Nicolas Pitref77814d2005-02-08 17:11:19 +00001667 ofs, datum, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 if (ret)
1669 return ret;
1670
1671 ofs += map_bankwidth(map);
1672 buf += map_bankwidth(map);
1673 (*retlen) += map_bankwidth(map);
1674 len -= map_bankwidth(map);
1675
1676 if (ofs >> cfi->chipshift) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001677 chipnum ++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 ofs = 0;
1679 if (chipnum == cfi->numchips)
1680 return 0;
1681 }
1682 }
1683
1684 if (len & (map_bankwidth(map)-1)) {
1685 map_word datum;
1686
1687 datum = map_word_ff(map);
1688 datum = map_word_load_partial(map, datum, buf, 0, len);
1689
1690 ret = do_write_oneword(map, &cfi->chips[chipnum],
Nicolas Pitref77814d2005-02-08 17:11:19 +00001691 ofs, datum, FL_WRITING);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001692 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 return ret;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001694
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 (*retlen) += len;
1696 }
1697
1698 return 0;
1699}
1700
1701
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001702static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
Nicolas Pitree102d542005-08-06 05:46:59 +01001703 unsigned long adr, const struct kvec **pvec,
1704 unsigned long *pvec_seek, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705{
1706 struct cfi_private *cfi = map->fldrv_priv;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001707 map_word status, write_cmd, datum;
1708 unsigned long cmd_adr;
1709 int ret, wbufsize, word_gap, words;
Nicolas Pitree102d542005-08-06 05:46:59 +01001710 const struct kvec *vec;
1711 unsigned long vec_seek;
Massimo Cirillo646fd122008-01-11 10:24:11 +00001712 unsigned long initial_adr;
1713 int initial_len = len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714
1715 wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
1716 adr += chip->start;
Massimo Cirillo646fd122008-01-11 10:24:11 +00001717 initial_adr = adr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 cmd_adr = adr & ~(wbufsize-1);
Nicolas Pitre638d9832005-08-06 05:40:46 +01001719
Andrea Adami812c5fa2014-06-02 23:38:35 +02001720 /* Sharp LH28F640BF chips need the first address for the
1721 * Page Buffer Program command. See Table 5 of
1722 * LH28F320BF, LH28F640BF, LH28F128BF Series (Appendix FUM00701) */
1723 if (is_LH28F640BF(cfi))
1724 cmd_adr = adr;
1725
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 /* Let's determine this according to the interleave only once */
Guillaume LECERFb5d194c2010-10-26 10:55:29 +01001727 write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0xe8) : CMD(0xe9);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001729 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 ret = get_chip(map, chip, cmd_adr, FL_WRITING);
1731 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001732 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 return ret;
1734 }
1735
Massimo Cirillo646fd122008-01-11 10:24:11 +00001736 XIP_INVAL_CACHED_RANGE(map, initial_adr, initial_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 ENABLE_VPP(map);
1738 xip_disable(map, chip, cmd_adr);
1739
David Woodhouse151e76592006-05-14 01:51:54 +01001740 /* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001741 [...], the device will not accept any more Write to Buffer commands".
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 So we must check here and reset those bits if they're set. Otherwise
1743 we're just pissing in the wind */
Nicolas Pitre6e7a68092006-03-29 23:31:42 +01001744 if (chip->state != FL_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 map_write(map, CMD(0x70), cmd_adr);
Nicolas Pitre6e7a68092006-03-29 23:31:42 +01001746 chip->state = FL_STATUS;
1747 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 status = map_read(map, cmd_adr);
1749 if (map_word_bitsset(map, status, CMD(0x30))) {
1750 xip_enable(map, chip, cmd_adr);
1751 printk(KERN_WARNING "SR.4 or SR.5 bits set in buffer write (status %lx). Clearing.\n", status.x[0]);
1752 xip_disable(map, chip, cmd_adr);
1753 map_write(map, CMD(0x50), cmd_adr);
1754 map_write(map, CMD(0x70), cmd_adr);
1755 }
1756
1757 chip->state = FL_WRITING_TO_BUFFER;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001758 map_write(map, write_cmd, cmd_adr);
Anders Grafströme93cafe2008-08-05 18:37:41 +02001759 ret = WAIT_TIMEOUT(map, chip, cmd_adr, 0, 0);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001760 if (ret) {
1761 /* Argh. Not ready for write to buffer */
1762 map_word Xstatus = map_read(map, cmd_adr);
1763 map_write(map, CMD(0x70), cmd_adr);
1764 chip->state = FL_STATUS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 status = map_read(map, cmd_adr);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001766 map_write(map, CMD(0x50), cmd_adr);
1767 map_write(map, CMD(0x70), cmd_adr);
1768 xip_enable(map, chip, cmd_adr);
1769 printk(KERN_ERR "%s: Chip not ready for buffer write. Xstatus = %lx, status = %lx\n",
1770 map->name, Xstatus.x[0], status.x[0]);
1771 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 }
1773
Nicolas Pitree102d542005-08-06 05:46:59 +01001774 /* Figure out the number of words to write */
1775 word_gap = (-adr & (map_bankwidth(map)-1));
Julia Lawallc8872b02008-08-02 17:14:21 +02001776 words = DIV_ROUND_UP(len - word_gap, map_bankwidth(map));
Nicolas Pitree102d542005-08-06 05:46:59 +01001777 if (!word_gap) {
1778 words--;
1779 } else {
1780 word_gap = map_bankwidth(map) - word_gap;
1781 adr -= word_gap;
1782 datum = map_word_ff(map);
1783 }
1784
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 /* Write length of data to come */
Nicolas Pitree102d542005-08-06 05:46:59 +01001786 map_write(map, CMD(words), cmd_adr );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
1788 /* Write data */
Nicolas Pitree102d542005-08-06 05:46:59 +01001789 vec = *pvec;
1790 vec_seek = *pvec_seek;
1791 do {
1792 int n = map_bankwidth(map) - word_gap;
1793 if (n > vec->iov_len - vec_seek)
1794 n = vec->iov_len - vec_seek;
1795 if (n > len)
1796 n = len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797
Nicolas Pitree102d542005-08-06 05:46:59 +01001798 if (!word_gap && len < map_bankwidth(map))
1799 datum = map_word_ff(map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800
Nicolas Pitree102d542005-08-06 05:46:59 +01001801 datum = map_word_load_partial(map, datum,
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001802 vec->iov_base + vec_seek,
Nicolas Pitree102d542005-08-06 05:46:59 +01001803 word_gap, n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804
Nicolas Pitree102d542005-08-06 05:46:59 +01001805 len -= n;
1806 word_gap += n;
1807 if (!len || word_gap == map_bankwidth(map)) {
1808 map_write(map, datum, adr);
1809 adr += map_bankwidth(map);
1810 word_gap = 0;
1811 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
Nicolas Pitree102d542005-08-06 05:46:59 +01001813 vec_seek += n;
1814 if (vec_seek == vec->iov_len) {
1815 vec++;
1816 vec_seek = 0;
1817 }
1818 } while (len);
1819 *pvec = vec;
1820 *pvec_seek = vec_seek;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821
1822 /* GO GO GO */
1823 map_write(map, CMD(0xd0), cmd_adr);
1824 chip->state = FL_WRITING;
1825
Nicolas Pitrec1724712006-03-30 15:52:41 +01001826 ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
Massimo Cirillo646fd122008-01-11 10:24:11 +00001827 initial_adr, initial_len,
Anders Grafströme93cafe2008-08-05 18:37:41 +02001828 chip->buffer_write_time,
1829 chip->buffer_write_time_max);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001830 if (ret) {
1831 map_write(map, CMD(0x70), cmd_adr);
1832 chip->state = FL_STATUS;
1833 xip_enable(map, chip, cmd_adr);
1834 printk(KERN_ERR "%s: buffer write error (status timeout)\n", map->name);
1835 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837
Nicolas Pitre48436532005-08-06 05:16:52 +01001838 /* check for errors */
Nicolas Pitrec1724712006-03-30 15:52:41 +01001839 status = map_read(map, cmd_adr);
Nicolas Pitre48436532005-08-06 05:16:52 +01001840 if (map_word_bitsset(map, status, CMD(0x1a))) {
1841 unsigned long chipstatus = MERGESTATUS(status);
1842
1843 /* reset status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 map_write(map, CMD(0x50), cmd_adr);
Nicolas Pitre48436532005-08-06 05:16:52 +01001845 map_write(map, CMD(0x70), cmd_adr);
1846 xip_enable(map, chip, cmd_adr);
1847
1848 if (chipstatus & 0x02) {
1849 ret = -EROFS;
1850 } else if (chipstatus & 0x08) {
1851 printk(KERN_ERR "%s: buffer write error (bad VPP)\n", map->name);
1852 ret = -EIO;
1853 } else {
1854 printk(KERN_ERR "%s: buffer write error (status 0x%lx)\n", map->name, chipstatus);
1855 ret = -EINVAL;
1856 }
1857
1858 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 }
1860
1861 xip_enable(map, chip, cmd_adr);
Paul Parsons85e5b2f2012-03-07 14:10:33 +00001862 out: DISABLE_VPP(map);
1863 put_chip(map, chip, cmd_adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001864 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 return ret;
1866}
1867
Nicolas Pitree102d542005-08-06 05:46:59 +01001868static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs,
1869 unsigned long count, loff_t to, size_t *retlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870{
1871 struct map_info *map = mtd->priv;
1872 struct cfi_private *cfi = map->fldrv_priv;
1873 int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
1874 int ret = 0;
1875 int chipnum;
Nicolas Pitree102d542005-08-06 05:46:59 +01001876 unsigned long ofs, vec_seek, i;
1877 size_t len = 0;
1878
1879 for (i = 0; i < count; i++)
1880 len += vecs[i].iov_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 if (!len)
1883 return 0;
1884
1885 chipnum = to >> cfi->chipshift;
Nicolas Pitree102d542005-08-06 05:46:59 +01001886 ofs = to - (chipnum << cfi->chipshift);
1887 vec_seek = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888
Nicolas Pitree102d542005-08-06 05:46:59 +01001889 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 /* We must not cross write block boundaries */
1891 int size = wbufsize - (ofs & (wbufsize-1));
1892
1893 if (size > len)
1894 size = len;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00001895 ret = do_write_buffer(map, &cfi->chips[chipnum],
Nicolas Pitree102d542005-08-06 05:46:59 +01001896 ofs, &vecs, &vec_seek, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 if (ret)
1898 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
1900 ofs += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 (*retlen) += size;
1902 len -= size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903
1904 if (ofs >> cfi->chipshift) {
1905 chipnum ++;
1906 ofs = 0;
1907 if (chipnum == cfi->numchips)
1908 return 0;
1909 }
Josh Boyerdf54b52c2005-12-06 17:28:19 +00001910
1911 /* Be nice and reschedule with the chip in a usable state for other
1912 processes. */
1913 cond_resched();
1914
Nicolas Pitree102d542005-08-06 05:46:59 +01001915 } while (len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 return 0;
1918}
1919
Nicolas Pitree102d542005-08-06 05:46:59 +01001920static int cfi_intelext_write_buffers (struct mtd_info *mtd, loff_t to,
1921 size_t len, size_t *retlen, const u_char *buf)
1922{
1923 struct kvec vec;
1924
1925 vec.iov_base = (void *) buf;
1926 vec.iov_len = len;
1927
1928 return cfi_intelext_writev(mtd, &vec, 1, to, retlen);
1929}
1930
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
1932 unsigned long adr, int len, void *thunk)
1933{
1934 struct cfi_private *cfi = map->fldrv_priv;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001935 map_word status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 int retries = 3;
Nicolas Pitrec1724712006-03-30 15:52:41 +01001937 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
1939 adr += chip->start;
1940
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 retry:
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001942 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 ret = get_chip(map, chip, adr, FL_ERASING);
1944 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02001945 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 return ret;
1947 }
1948
1949 XIP_INVAL_CACHED_RANGE(map, adr, len);
1950 ENABLE_VPP(map);
1951 xip_disable(map, chip, adr);
1952
1953 /* Clear the status register first */
1954 map_write(map, CMD(0x50), adr);
1955
1956 /* Now erase */
1957 map_write(map, CMD(0x20), adr);
1958 map_write(map, CMD(0xD0), adr);
1959 chip->state = FL_ERASING;
1960 chip->erase_suspended = 0;
Joakim Tjernlund6510bbc2018-03-01 14:39:39 +01001961 chip->in_progress_block_addr = adr;
1962 chip->in_progress_block_mask = ~(len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963
Nicolas Pitrec1724712006-03-30 15:52:41 +01001964 ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
1965 adr, len,
Anders Grafströme93cafe2008-08-05 18:37:41 +02001966 chip->erase_time,
1967 chip->erase_time_max);
Nicolas Pitrec1724712006-03-30 15:52:41 +01001968 if (ret) {
1969 map_write(map, CMD(0x70), adr);
1970 chip->state = FL_STATUS;
1971 xip_enable(map, chip, adr);
1972 printk(KERN_ERR "%s: block erase error: (status timeout)\n", map->name);
1973 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 }
1975
1976 /* We've broken this before. It doesn't hurt to be safe */
1977 map_write(map, CMD(0x70), adr);
1978 chip->state = FL_STATUS;
1979 status = map_read(map, adr);
1980
Nicolas Pitre48436532005-08-06 05:16:52 +01001981 /* check for errors */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 if (map_word_bitsset(map, status, CMD(0x3a))) {
Nicolas Pitre48436532005-08-06 05:16:52 +01001983 unsigned long chipstatus = MERGESTATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984
1985 /* Reset the error bits */
1986 map_write(map, CMD(0x50), adr);
1987 map_write(map, CMD(0x70), adr);
1988 xip_enable(map, chip, adr);
1989
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 if ((chipstatus & 0x30) == 0x30) {
Nicolas Pitre48436532005-08-06 05:16:52 +01001991 printk(KERN_ERR "%s: block erase error: (bad command sequence, status 0x%lx)\n", map->name, chipstatus);
1992 ret = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 } else if (chipstatus & 0x02) {
1994 /* Protection bit set */
1995 ret = -EROFS;
1996 } else if (chipstatus & 0x8) {
1997 /* Voltage */
Nicolas Pitre48436532005-08-06 05:16:52 +01001998 printk(KERN_ERR "%s: block erase error: (bad VPP)\n", map->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 ret = -EIO;
Nicolas Pitre48436532005-08-06 05:16:52 +01002000 } else if (chipstatus & 0x20 && retries--) {
2001 printk(KERN_DEBUG "block erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus);
Paul Parsons85e5b2f2012-03-07 14:10:33 +00002002 DISABLE_VPP(map);
Nicolas Pitre48436532005-08-06 05:16:52 +01002003 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002004 mutex_unlock(&chip->mutex);
Nicolas Pitre48436532005-08-06 05:16:52 +01002005 goto retry;
2006 } else {
2007 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 -07002008 ret = -EIO;
2009 }
Nicolas Pitre48436532005-08-06 05:16:52 +01002010
2011 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 }
2013
Nicolas Pitre48436532005-08-06 05:16:52 +01002014 xip_enable(map, chip, adr);
Paul Parsons85e5b2f2012-03-07 14:10:33 +00002015 out: DISABLE_VPP(map);
2016 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002017 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 return ret;
2019}
2020
Ben Dooks029a9eb2007-05-28 20:11:37 +01002021static int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022{
Boris Brezillone7bfb3f2018-02-12 22:03:11 +01002023 return cfi_varsize_frob(mtd, do_erase_oneblock, instr->addr,
2024 instr->len, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025}
2026
2027static void cfi_intelext_sync (struct mtd_info *mtd)
2028{
2029 struct map_info *map = mtd->priv;
2030 struct cfi_private *cfi = map->fldrv_priv;
2031 int i;
2032 struct flchip *chip;
2033 int ret = 0;
2034
2035 for (i=0; !ret && i<cfi->numchips; i++) {
2036 chip = &cfi->chips[i];
2037
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002038 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 ret = get_chip(map, chip, chip->start, FL_SYNCING);
2040
2041 if (!ret) {
2042 chip->oldstate = chip->state;
2043 chip->state = FL_SYNCING;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002044 /* No need to wake_up() on this state change -
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 * as the whole point is that nobody can do anything
2046 * with the chip now anyway.
2047 */
2048 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002049 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 }
2051
2052 /* Unlock the chips again */
2053
2054 for (i--; i >=0; i--) {
2055 chip = &cfi->chips[i];
2056
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002057 mutex_lock(&chip->mutex);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002058
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 if (chip->state == FL_SYNCING) {
2060 chip->state = chip->oldstate;
Nicolas Pitre09c79332005-03-16 22:41:09 +00002061 chip->oldstate = FL_READY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 wake_up(&chip->wq);
2063 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002064 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 }
2066}
2067
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002068static int __xipram do_getlockstatus_oneblock(struct map_info *map,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 struct flchip *chip,
2070 unsigned long adr,
2071 int len, void *thunk)
2072{
2073 struct cfi_private *cfi = map->fldrv_priv;
2074 int status, ofs_factor = cfi->interleave * cfi->device_type;
2075
Todd Poynorc25bb1f2005-04-27 21:01:52 +01002076 adr += chip->start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 xip_disable(map, chip, adr+(2*ofs_factor));
Todd Poynorc25bb1f2005-04-27 21:01:52 +01002078 map_write(map, CMD(0x90), adr+(2*ofs_factor));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 chip->state = FL_JEDEC_QUERY;
2080 status = cfi_read_query(map, adr+(2*ofs_factor));
2081 xip_enable(map, chip, 0);
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002082 return status;
2083}
2084
2085#ifdef DEBUG_LOCK_BITS
2086static int __xipram do_printlockstatus_oneblock(struct map_info *map,
2087 struct flchip *chip,
2088 unsigned long adr,
2089 int len, void *thunk)
2090{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 printk(KERN_DEBUG "block status register for 0x%08lx is %x\n",
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002092 adr, do_getlockstatus_oneblock(map, chip, adr, len, thunk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 return 0;
2094}
2095#endif
2096
2097#define DO_XXLOCK_ONEBLOCK_LOCK ((void *) 1)
2098#define DO_XXLOCK_ONEBLOCK_UNLOCK ((void *) 2)
2099
2100static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip,
2101 unsigned long adr, int len, void *thunk)
2102{
2103 struct cfi_private *cfi = map->fldrv_priv;
Todd Poynor9a6e73e2005-03-29 23:06:40 +01002104 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
Stefan Roese7be1f6b2012-08-28 11:34:13 +02002105 int mdelay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 int ret;
2107
2108 adr += chip->start;
2109
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002110 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 ret = get_chip(map, chip, adr, FL_LOCKING);
2112 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002113 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 return ret;
2115 }
2116
2117 ENABLE_VPP(map);
2118 xip_disable(map, chip, adr);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002119
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 map_write(map, CMD(0x60), adr);
2121 if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) {
2122 map_write(map, CMD(0x01), adr);
2123 chip->state = FL_LOCKING;
2124 } else if (thunk == DO_XXLOCK_ONEBLOCK_UNLOCK) {
2125 map_write(map, CMD(0xD0), adr);
2126 chip->state = FL_UNLOCKING;
2127 } else
2128 BUG();
2129
Todd Poynor9a6e73e2005-03-29 23:06:40 +01002130 /*
2131 * If Instant Individual Block Locking supported then no need
2132 * to delay.
2133 */
Stefan Roese7be1f6b2012-08-28 11:34:13 +02002134 /*
2135 * Unlocking may take up to 1.4 seconds on some Intel flashes. So
2136 * lets use a max of 1.5 seconds (1500ms) as timeout.
2137 *
2138 * See "Clear Block Lock-Bits Time" on page 40 in
2139 * "3 Volt Intel StrataFlash Memory" 28F128J3,28F640J3,28F320J3 manual
2140 * from February 2003
2141 */
2142 mdelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1500 : 0;
Todd Poynor9a6e73e2005-03-29 23:06:40 +01002143
Stefan Roese7be1f6b2012-08-28 11:34:13 +02002144 ret = WAIT_TIMEOUT(map, chip, adr, mdelay, mdelay * 1000);
Nicolas Pitrec1724712006-03-30 15:52:41 +01002145 if (ret) {
2146 map_write(map, CMD(0x70), adr);
2147 chip->state = FL_STATUS;
2148 xip_enable(map, chip, adr);
2149 printk(KERN_ERR "%s: block unlock error: (status timeout)\n", map->name);
2150 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002152
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 xip_enable(map, chip, adr);
Paul Parsons85e5b2f2012-03-07 14:10:33 +00002154 out: DISABLE_VPP(map);
2155 put_chip(map, chip, adr);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002156 mutex_unlock(&chip->mutex);
Nicolas Pitrec1724712006-03-30 15:52:41 +01002157 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158}
2159
Adrian Hunter69423d92008-12-10 13:37:21 +00002160static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161{
2162 int ret;
2163
2164#ifdef DEBUG_LOCK_BITS
2165 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
Harvey Harrisoncb53b3b2008-04-18 13:44:19 -07002166 __func__, ofs, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
Randy Dunlap1da1caf2007-06-28 23:00:09 +01002168 ofs, len, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169#endif
2170
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002171 ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 ofs, len, DO_XXLOCK_ONEBLOCK_LOCK);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002173
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174#ifdef DEBUG_LOCK_BITS
2175 printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
Harvey Harrisoncb53b3b2008-04-18 13:44:19 -07002176 __func__, ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
Randy Dunlap1da1caf2007-06-28 23:00:09 +01002178 ofs, len, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179#endif
2180
2181 return ret;
2182}
2183
Adrian Hunter69423d92008-12-10 13:37:21 +00002184static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185{
2186 int ret;
2187
2188#ifdef DEBUG_LOCK_BITS
2189 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
Harvey Harrisoncb53b3b2008-04-18 13:44:19 -07002190 __func__, ofs, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
Randy Dunlap1da1caf2007-06-28 23:00:09 +01002192 ofs, len, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193#endif
2194
2195 ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
2196 ofs, len, DO_XXLOCK_ONEBLOCK_UNLOCK);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002197
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198#ifdef DEBUG_LOCK_BITS
2199 printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
Harvey Harrisoncb53b3b2008-04-18 13:44:19 -07002200 __func__, ret);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002201 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
Randy Dunlap1da1caf2007-06-28 23:00:09 +01002202 ofs, len, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203#endif
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002204
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 return ret;
2206}
2207
Richard Cochran99384242010-06-14 18:10:33 +02002208static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs,
2209 uint64_t len)
2210{
2211 return cfi_varsize_frob(mtd, do_getlockstatus_oneblock,
2212 ofs, len, NULL) ? 1 : 0;
2213}
2214
Nicolas Pitref77814d2005-02-08 17:11:19 +00002215#ifdef CONFIG_MTD_OTP
2216
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002217typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip,
Nicolas Pitref77814d2005-02-08 17:11:19 +00002218 u_long data_offset, u_char *buf, u_int size,
2219 u_long prot_offset, u_int groupno, u_int groupsize);
2220
2221static int __xipram
2222do_otp_read(struct map_info *map, struct flchip *chip, u_long offset,
2223 u_char *buf, u_int size, u_long prot, u_int grpno, u_int grpsz)
2224{
2225 struct cfi_private *cfi = map->fldrv_priv;
2226 int ret;
2227
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002228 mutex_lock(&chip->mutex);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002229 ret = get_chip(map, chip, chip->start, FL_JEDEC_QUERY);
2230 if (ret) {
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002231 mutex_unlock(&chip->mutex);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002232 return ret;
2233 }
2234
2235 /* let's ensure we're not reading back cached data from array mode */
Nicolas Pitre6da70122005-05-19 18:05:47 +01002236 INVALIDATE_CACHED_RANGE(map, chip->start + offset, size);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002237
2238 xip_disable(map, chip, chip->start);
2239 if (chip->state != FL_JEDEC_QUERY) {
2240 map_write(map, CMD(0x90), chip->start);
2241 chip->state = FL_JEDEC_QUERY;
2242 }
2243 map_copy_from(map, buf, chip->start + offset, size);
2244 xip_enable(map, chip, chip->start);
2245
2246 /* then ensure we don't keep OTP data in the cache */
Nicolas Pitre6da70122005-05-19 18:05:47 +01002247 INVALIDATE_CACHED_RANGE(map, chip->start + offset, size);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002248
2249 put_chip(map, chip, chip->start);
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002250 mutex_unlock(&chip->mutex);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002251 return 0;
2252}
2253
2254static int
2255do_otp_write(struct map_info *map, struct flchip *chip, u_long offset,
2256 u_char *buf, u_int size, u_long prot, u_int grpno, u_int grpsz)
2257{
2258 int ret;
2259
2260 while (size) {
2261 unsigned long bus_ofs = offset & ~(map_bankwidth(map)-1);
2262 int gap = offset - bus_ofs;
2263 int n = min_t(int, size, map_bankwidth(map)-gap);
2264 map_word datum = map_word_ff(map);
2265
2266 datum = map_word_load_partial(map, datum, buf, gap, n);
2267 ret = do_write_oneword(map, chip, bus_ofs, datum, FL_OTP_WRITE);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002268 if (ret)
Nicolas Pitref77814d2005-02-08 17:11:19 +00002269 return ret;
2270
2271 offset += n;
2272 buf += n;
2273 size -= n;
2274 }
2275
2276 return 0;
2277}
2278
2279static int
2280do_otp_lock(struct map_info *map, struct flchip *chip, u_long offset,
2281 u_char *buf, u_int size, u_long prot, u_int grpno, u_int grpsz)
2282{
2283 struct cfi_private *cfi = map->fldrv_priv;
2284 map_word datum;
2285
2286 /* make sure area matches group boundaries */
Nicolas Pitre332d71f2005-02-17 20:35:04 +00002287 if (size != grpsz)
Nicolas Pitref77814d2005-02-08 17:11:19 +00002288 return -EXDEV;
2289
2290 datum = map_word_ff(map);
2291 datum = map_word_clr(map, datum, CMD(1 << grpno));
2292 return do_write_oneword(map, chip, prot, datum, FL_OTP_WRITE);
2293}
2294
2295static int cfi_intelext_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
2296 size_t *retlen, u_char *buf,
2297 otp_op_t action, int user_regs)
2298{
2299 struct map_info *map = mtd->priv;
2300 struct cfi_private *cfi = map->fldrv_priv;
2301 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
2302 struct flchip *chip;
2303 struct cfi_intelext_otpinfo *otp;
2304 u_long devsize, reg_prot_offset, data_offset;
2305 u_int chip_num, chip_step, field, reg_fact_size, reg_user_size;
2306 u_int groups, groupno, groupsize, reg_fact_groups, reg_user_groups;
2307 int ret;
2308
2309 *retlen = 0;
2310
2311 /* Check that we actually have some OTP registers */
2312 if (!extp || !(extp->FeatureSupport & 64) || !extp->NumProtectionFields)
2313 return -ENODATA;
2314
2315 /* we need real chips here not virtual ones */
2316 devsize = (1 << cfi->cfiq->DevSize) * cfi->interleave;
2317 chip_step = devsize >> cfi->chipshift;
Nicolas Pitredce2b4d2005-04-01 17:36:29 +01002318 chip_num = 0;
Nicolas Pitref77814d2005-02-08 17:11:19 +00002319
Nicolas Pitredce2b4d2005-04-01 17:36:29 +01002320 /* Some chips have OTP located in the _top_ partition only.
2321 For example: Intel 28F256L18T (T means top-parameter device) */
Hans-Christian Egtvedtb2ef1a22009-11-05 15:53:43 +01002322 if (cfi->mfr == CFI_MFR_INTEL) {
Nicolas Pitredce2b4d2005-04-01 17:36:29 +01002323 switch (cfi->id) {
2324 case 0x880b:
2325 case 0x880c:
2326 case 0x880d:
2327 chip_num = chip_step - 1;
2328 }
2329 }
2330
2331 for ( ; chip_num < cfi->numchips; chip_num += chip_step) {
Nicolas Pitref77814d2005-02-08 17:11:19 +00002332 chip = &cfi->chips[chip_num];
2333 otp = (struct cfi_intelext_otpinfo *)&extp->extra[0];
2334
2335 /* first OTP region */
2336 field = 0;
2337 reg_prot_offset = extp->ProtRegAddr;
2338 reg_fact_groups = 1;
2339 reg_fact_size = 1 << extp->FactProtRegSize;
2340 reg_user_groups = 1;
2341 reg_user_size = 1 << extp->UserProtRegSize;
2342
2343 while (len > 0) {
2344 /* flash geometry fixup */
2345 data_offset = reg_prot_offset + 1;
2346 data_offset *= cfi->interleave * cfi->device_type;
2347 reg_prot_offset *= cfi->interleave * cfi->device_type;
2348 reg_fact_size *= cfi->interleave;
2349 reg_user_size *= cfi->interleave;
2350
2351 if (user_regs) {
2352 groups = reg_user_groups;
2353 groupsize = reg_user_size;
2354 /* skip over factory reg area */
2355 groupno = reg_fact_groups;
2356 data_offset += reg_fact_groups * reg_fact_size;
2357 } else {
2358 groups = reg_fact_groups;
2359 groupsize = reg_fact_size;
2360 groupno = 0;
2361 }
2362
Nicolas Pitre332d71f2005-02-17 20:35:04 +00002363 while (len > 0 && groups > 0) {
Nicolas Pitref77814d2005-02-08 17:11:19 +00002364 if (!action) {
2365 /*
2366 * Special case: if action is NULL
2367 * we fill buf with otp_info records.
2368 */
2369 struct otp_info *otpinfo;
2370 map_word lockword;
2371 len -= sizeof(struct otp_info);
2372 if (len <= 0)
2373 return -ENOSPC;
2374 ret = do_otp_read(map, chip,
2375 reg_prot_offset,
2376 (u_char *)&lockword,
2377 map_bankwidth(map),
2378 0, 0, 0);
2379 if (ret)
2380 return ret;
2381 otpinfo = (struct otp_info *)buf;
2382 otpinfo->start = from;
2383 otpinfo->length = groupsize;
2384 otpinfo->locked =
2385 !map_word_bitsset(map, lockword,
2386 CMD(1 << groupno));
2387 from += groupsize;
2388 buf += sizeof(*otpinfo);
2389 *retlen += sizeof(*otpinfo);
2390 } else if (from >= groupsize) {
2391 from -= groupsize;
Nicolas Pitre332d71f2005-02-17 20:35:04 +00002392 data_offset += groupsize;
Nicolas Pitref77814d2005-02-08 17:11:19 +00002393 } else {
2394 int size = groupsize;
2395 data_offset += from;
2396 size -= from;
2397 from = 0;
2398 if (size > len)
2399 size = len;
2400 ret = action(map, chip, data_offset,
2401 buf, size, reg_prot_offset,
2402 groupno, groupsize);
2403 if (ret < 0)
2404 return ret;
2405 buf += size;
2406 len -= size;
2407 *retlen += size;
Nicolas Pitre332d71f2005-02-17 20:35:04 +00002408 data_offset += size;
Nicolas Pitref77814d2005-02-08 17:11:19 +00002409 }
2410 groupno++;
2411 groups--;
2412 }
2413
2414 /* next OTP region */
2415 if (++field == extp->NumProtectionFields)
2416 break;
2417 reg_prot_offset = otp->ProtRegAddr;
2418 reg_fact_groups = otp->FactGroups;
2419 reg_fact_size = 1 << otp->FactProtRegSize;
2420 reg_user_groups = otp->UserGroups;
2421 reg_user_size = 1 << otp->UserProtRegSize;
2422 otp++;
2423 }
2424 }
2425
2426 return 0;
2427}
2428
2429static int cfi_intelext_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
2430 size_t len, size_t *retlen,
2431 u_char *buf)
2432{
2433 return cfi_intelext_otp_walk(mtd, from, len, retlen,
2434 buf, do_otp_read, 0);
2435}
2436
2437static int cfi_intelext_read_user_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, 1);
2443}
2444
2445static int cfi_intelext_write_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_write, 1);
2451}
2452
2453static int cfi_intelext_lock_user_prot_reg(struct mtd_info *mtd,
2454 loff_t from, size_t len)
2455{
2456 size_t retlen;
2457 return cfi_intelext_otp_walk(mtd, from, len, &retlen,
2458 NULL, do_otp_lock, 1);
2459}
2460
Christian Riesch4b78fc42f2014-01-28 09:29:44 +01002461static int cfi_intelext_get_fact_prot_info(struct mtd_info *mtd, size_t len,
2462 size_t *retlen, struct otp_info *buf)
Nicolas Pitref77814d2005-02-08 17:11:19 +00002463
Christian Riesch4b78fc42f2014-01-28 09:29:44 +01002464{
2465 return cfi_intelext_otp_walk(mtd, 0, len, retlen, (u_char *)buf,
2466 NULL, 0);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002467}
2468
Christian Riesch4b78fc42f2014-01-28 09:29:44 +01002469static int cfi_intelext_get_user_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 Riesch4b78fc42f2014-01-28 09:29:44 +01002472 return cfi_intelext_otp_walk(mtd, 0, len, retlen, (u_char *)buf,
2473 NULL, 1);
Nicolas Pitref77814d2005-02-08 17:11:19 +00002474}
2475
2476#endif
2477
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002478static void cfi_intelext_save_locks(struct mtd_info *mtd)
2479{
2480 struct mtd_erase_region_info *region;
2481 int block, status, i;
2482 unsigned long adr;
2483 size_t len;
2484
2485 for (i = 0; i < mtd->numeraseregions; i++) {
2486 region = &mtd->eraseregions[i];
2487 if (!region->lockmap)
2488 continue;
2489
2490 for (block = 0; block < region->numblocks; block++){
2491 len = region->erasesize;
2492 adr = region->offset + block * len;
2493
2494 status = cfi_varsize_frob(mtd,
Ben Dooks029a9eb2007-05-28 20:11:37 +01002495 do_getlockstatus_oneblock, adr, len, NULL);
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002496 if (status)
2497 set_bit(block, region->lockmap);
2498 else
2499 clear_bit(block, region->lockmap);
2500 }
2501 }
2502}
2503
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504static int cfi_intelext_suspend(struct mtd_info *mtd)
2505{
2506 struct map_info *map = mtd->priv;
2507 struct cfi_private *cfi = map->fldrv_priv;
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002508 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 int i;
2510 struct flchip *chip;
2511 int ret = 0;
2512
Justin Treone619a752008-01-30 10:25:49 -08002513 if ((mtd->flags & MTD_POWERUP_LOCK)
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002514 && extp && (extp->FeatureSupport & (1 << 5)))
2515 cfi_intelext_save_locks(mtd);
2516
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 for (i=0; !ret && i<cfi->numchips; i++) {
2518 chip = &cfi->chips[i];
2519
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002520 mutex_lock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521
2522 switch (chip->state) {
2523 case FL_READY:
2524 case FL_STATUS:
2525 case FL_CFI_QUERY:
2526 case FL_JEDEC_QUERY:
2527 if (chip->oldstate == FL_READY) {
David Andersa86aaa62006-10-19 19:33:19 +03002528 /* place the chip in a known state before suspend */
2529 map_write(map, CMD(0xFF), cfi->chips[i].start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 chip->oldstate = chip->state;
2531 chip->state = FL_PM_SUSPENDED;
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002532 /* No need to wake_up() on this state change -
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 * as the whole point is that nobody can do anything
2534 * with the chip now anyway.
2535 */
2536 } else {
2537 /* There seems to be an operation pending. We must wait for it. */
2538 printk(KERN_NOTICE "Flash device refused suspend due to pending operation (oldstate %d)\n", chip->oldstate);
2539 ret = -EAGAIN;
2540 }
2541 break;
2542 default:
2543 /* Should we actually wait? Once upon a time these routines weren't
2544 allowed to. Or should we return -EAGAIN, because the upper layers
2545 ought to have already shut down anything which was using the device
2546 anyway? The latter for now. */
Russell King342d3a92012-02-15 11:48:34 +00002547 printk(KERN_NOTICE "Flash device refused suspend due to active operation (state %d)\n", chip->state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 ret = -EAGAIN;
2549 case FL_PM_SUSPENDED:
2550 break;
2551 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002552 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 }
2554
2555 /* Unlock the chips again */
2556
2557 if (ret) {
2558 for (i--; i >=0; i--) {
2559 chip = &cfi->chips[i];
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002560
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002561 mutex_lock(&chip->mutex);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002562
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 if (chip->state == FL_PM_SUSPENDED) {
2564 /* No need to force it into a known state here,
2565 because we're returning failure, and it didn't
2566 get power cycled */
2567 chip->state = chip->oldstate;
2568 chip->oldstate = FL_READY;
2569 wake_up(&chip->wq);
2570 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002571 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002573 }
2574
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 return ret;
2576}
2577
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002578static void cfi_intelext_restore_locks(struct mtd_info *mtd)
2579{
2580 struct mtd_erase_region_info *region;
2581 int block, i;
2582 unsigned long adr;
2583 size_t len;
2584
2585 for (i = 0; i < mtd->numeraseregions; i++) {
2586 region = &mtd->eraseregions[i];
2587 if (!region->lockmap)
2588 continue;
2589
Akinobu Mitac527b412012-03-23 15:02:05 -07002590 for_each_clear_bit(block, region->lockmap, region->numblocks) {
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002591 len = region->erasesize;
2592 adr = region->offset + block * len;
Akinobu Mitac527b412012-03-23 15:02:05 -07002593 cfi_intelext_unlock(mtd, adr, len);
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002594 }
2595 }
2596}
2597
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598static void cfi_intelext_resume(struct mtd_info *mtd)
2599{
2600 struct map_info *map = mtd->priv;
2601 struct cfi_private *cfi = map->fldrv_priv;
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002602 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 int i;
2604 struct flchip *chip;
2605
2606 for (i=0; i<cfi->numchips; i++) {
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002607
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 chip = &cfi->chips[i];
2609
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002610 mutex_lock(&chip->mutex);
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002611
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 /* Go to known state. Chip may have been power cycled */
2613 if (chip->state == FL_PM_SUSPENDED) {
Dmitry Eremin-Solenikov89cf38d2014-10-23 01:23:01 +02002614 /* Refresh LH28F640BF Partition Config. Register */
2615 fixup_LH28F640BF(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 map_write(map, CMD(0xFF), cfi->chips[i].start);
2617 chip->oldstate = chip->state = FL_READY;
2618 wake_up(&chip->wq);
2619 }
2620
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002621 mutex_unlock(&chip->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 }
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002623
Justin Treone619a752008-01-30 10:25:49 -08002624 if ((mtd->flags & MTD_POWERUP_LOCK)
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002625 && extp && (extp->FeatureSupport & (1 << 5)))
2626 cfi_intelext_restore_locks(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627}
2628
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002629static int cfi_intelext_reset(struct mtd_info *mtd)
2630{
2631 struct map_info *map = mtd->priv;
2632 struct cfi_private *cfi = map->fldrv_priv;
2633 int i, ret;
2634
2635 for (i=0; i < cfi->numchips; i++) {
2636 struct flchip *chip = &cfi->chips[i];
2637
2638 /* force the completion of any ongoing operation
Thomas Gleixner1f948b42005-11-07 11:15:37 +00002639 and switch to array mode so any bootloader in
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002640 flash is accessible for soft reboot. */
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002641 mutex_lock(&chip->mutex);
Kevin Haoc4a9f882007-10-02 13:56:04 -07002642 ret = get_chip(map, chip, chip->start, FL_SHUTDOWN);
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002643 if (!ret) {
2644 map_write(map, CMD(0xff), chip->start);
Kevin Haoc4a9f882007-10-02 13:56:04 -07002645 chip->state = FL_SHUTDOWN;
Nicolas Pitrec9f7ec32009-10-23 16:02:42 -04002646 put_chip(map, chip, chip->start);
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002647 }
Stefani Seiboldc4e77372010-04-18 22:46:44 +02002648 mutex_unlock(&chip->mutex);
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002649 }
2650
2651 return 0;
2652}
2653
2654static int cfi_intelext_reboot(struct notifier_block *nb, unsigned long val,
2655 void *v)
2656{
2657 struct mtd_info *mtd;
2658
2659 mtd = container_of(nb, struct mtd_info, reboot_notifier);
2660 cfi_intelext_reset(mtd);
2661 return NOTIFY_DONE;
2662}
2663
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664static void cfi_intelext_destroy(struct mtd_info *mtd)
2665{
2666 struct map_info *map = mtd->priv;
2667 struct cfi_private *cfi = map->fldrv_priv;
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002668 struct mtd_erase_region_info *region;
2669 int i;
Nicolas Pitre963a6fb2005-04-01 02:59:56 +01002670 cfi_intelext_reset(mtd);
2671 unregister_reboot_notifier(&mtd->reboot_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 kfree(cfi->cmdset_priv);
2673 kfree(cfi->cfiq);
2674 kfree(cfi->chips[0].priv);
2675 kfree(cfi);
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002676 for (i = 0; i < mtd->numeraseregions; i++) {
2677 region = &mtd->eraseregions[i];
Markus Elfring05a221b2014-11-20 13:50:43 +01002678 kfree(region->lockmap);
Rodolfo Giometti0ecbc812007-03-26 21:45:43 -08002679 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 kfree(mtd->eraseregions);
2681}
2682
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683MODULE_LICENSE("GPL");
2684MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
2685MODULE_DESCRIPTION("MTD chip driver for Intel/Sharp flash chips");
David Woodhousea15bdee2006-05-08 22:35:05 +01002686MODULE_ALIAS("cfi_cmdset_0003");
2687MODULE_ALIAS("cfi_cmdset_0200");