mtd: fix a huge latency problem in the MTD CFI and LPDDR flash drivers.
[linux-2.6.git] / drivers / mtd / lpddr / lpddr_cmds.c
1 /*
2  * LPDDR flash memory device operations. This module provides read, write,
3  * erase, lock/unlock support for LPDDR flash memories
4  * (C) 2008 Korolev Alexey <akorolev@infradead.org>
5  * (C) 2008 Vasiliy Leonenko <vasiliy.leonenko@gmail.com>
6  * Many thanks to Roman Borisov for intial enabling
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301, USA.
22  * TODO:
23  * Implement VPP management
24  * Implement XIP support
25  * Implement OTP support
26  */
27 #include <linux/mtd/pfow.h>
28 #include <linux/mtd/qinfo.h>
29
30 static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len,
31                                         size_t *retlen, u_char *buf);
32 static int lpddr_write_buffers(struct mtd_info *mtd, loff_t to,
33                                 size_t len, size_t *retlen, const u_char *buf);
34 static int lpddr_writev(struct mtd_info *mtd, const struct kvec *vecs,
35                                 unsigned long count, loff_t to, size_t *retlen);
36 static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr);
37 static int lpddr_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
38 static int lpddr_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
39 static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
40                         size_t *retlen, void **mtdbuf, resource_size_t *phys);
41 static void lpddr_unpoint(struct mtd_info *mtd, loff_t adr, size_t len);
42 static int get_chip(struct map_info *map, struct flchip *chip, int mode);
43 static int chip_ready(struct map_info *map, struct flchip *chip, int mode);
44 static void put_chip(struct map_info *map, struct flchip *chip);
45
46 struct mtd_info *lpddr_cmdset(struct map_info *map)
47 {
48         struct lpddr_private *lpddr = map->fldrv_priv;
49         struct flchip_shared *shared;
50         struct flchip *chip;
51         struct mtd_info *mtd;
52         int numchips;
53         int i, j;
54
55         mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
56         if (!mtd) {
57                 printk(KERN_ERR "Failed to allocate memory for MTD device\n");
58                 return NULL;
59         }
60         mtd->priv = map;
61         mtd->type = MTD_NORFLASH;
62
63         /* Fill in the default mtd operations */
64         mtd->read = lpddr_read;
65         mtd->type = MTD_NORFLASH;
66         mtd->flags = MTD_CAP_NORFLASH;
67         mtd->flags &= ~MTD_BIT_WRITEABLE;
68         mtd->erase = lpddr_erase;
69         mtd->write = lpddr_write_buffers;
70         mtd->writev = lpddr_writev;
71         mtd->read_oob = NULL;
72         mtd->write_oob = NULL;
73         mtd->sync = NULL;
74         mtd->lock = lpddr_lock;
75         mtd->unlock = lpddr_unlock;
76         mtd->suspend = NULL;
77         mtd->resume = NULL;
78         if (map_is_linear(map)) {
79                 mtd->point = lpddr_point;
80                 mtd->unpoint = lpddr_unpoint;
81         }
82         mtd->block_isbad = NULL;
83         mtd->block_markbad = NULL;
84         mtd->size = 1 << lpddr->qinfo->DevSizeShift;
85         mtd->erasesize = 1 << lpddr->qinfo->UniformBlockSizeShift;
86         mtd->writesize = 1 << lpddr->qinfo->BufSizeShift;
87
88         shared = kmalloc(sizeof(struct flchip_shared) * lpddr->numchips,
89                                                 GFP_KERNEL);
90         if (!shared) {
91                 kfree(lpddr);
92                 kfree(mtd);
93                 return NULL;
94         }
95
96         chip = &lpddr->chips[0];
97         numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum;
98         for (i = 0; i < numchips; i++) {
99                 shared[i].writing = shared[i].erasing = NULL;
100                 spin_lock_init(&shared[i].lock);
101                 for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) {
102                         *chip = lpddr->chips[i];
103                         chip->start += j << lpddr->chipshift;
104                         chip->oldstate = chip->state = FL_READY;
105                         chip->priv = &shared[i];
106                         /* those should be reset too since
107                            they create memory references. */
108                         init_waitqueue_head(&chip->wq);
109                         mutex_init(&chip->mutex);
110                         chip++;
111                 }
112         }
113
114         return mtd;
115 }
116 EXPORT_SYMBOL(lpddr_cmdset);
117
118 static int wait_for_ready(struct map_info *map, struct flchip *chip,
119                 unsigned int chip_op_time)
120 {
121         unsigned int timeo, reset_timeo, sleep_time;
122         unsigned int dsr;
123         flstate_t chip_state = chip->state;
124         int ret = 0;
125
126         /* set our timeout to 8 times the expected delay */
127         timeo = chip_op_time * 8;
128         if (!timeo)
129                 timeo = 500000;
130         reset_timeo = timeo;
131         sleep_time = chip_op_time / 2;
132
133         for (;;) {
134                 dsr = CMDVAL(map_read(map, map->pfow_base + PFOW_DSR));
135                 if (dsr & DSR_READY_STATUS)
136                         break;
137                 if (!timeo) {
138                         printk(KERN_ERR "%s: Flash timeout error state %d \n",
139                                                         map->name, chip_state);
140                         ret = -ETIME;
141                         break;
142                 }
143
144                 /* OK Still waiting. Drop the lock, wait a while and retry. */
145                 mutex_unlock(&chip->mutex);
146                 if (sleep_time >= 1000000/HZ) {
147                         /*
148                          * Half of the normal delay still remaining
149                          * can be performed with a sleeping delay instead
150                          * of busy waiting.
151                          */
152                         msleep(sleep_time/1000);
153                         timeo -= sleep_time;
154                         sleep_time = 1000000/HZ;
155                 } else {
156                         udelay(1);
157                         cond_resched();
158                         timeo--;
159                 }
160                 mutex_lock(&chip->mutex);
161
162                 while (chip->state != chip_state) {
163                         /* Someone's suspended the operation: sleep */
164                         DECLARE_WAITQUEUE(wait, current);
165                         set_current_state(TASK_UNINTERRUPTIBLE);
166                         add_wait_queue(&chip->wq, &wait);
167                         mutex_unlock(&chip->mutex);
168                         schedule();
169                         remove_wait_queue(&chip->wq, &wait);
170                         mutex_lock(&chip->mutex);
171                 }
172                 if (chip->erase_suspended || chip->write_suspended)  {
173                         /* Suspend has occured while sleep: reset timeout */
174                         timeo = reset_timeo;
175                         chip->erase_suspended = chip->write_suspended = 0;
176                 }
177         }
178         /* check status for errors */
179         if (dsr & DSR_ERR) {
180                 /* Clear DSR*/
181                 map_write(map, CMD(~(DSR_ERR)), map->pfow_base + PFOW_DSR);
182                 printk(KERN_WARNING"%s: Bad status on wait: 0x%x \n",
183                                 map->name, dsr);
184                 print_drs_error(dsr);
185                 ret = -EIO;
186         }
187         chip->state = FL_READY;
188         return ret;
189 }
190
191 static int get_chip(struct map_info *map, struct flchip *chip, int mode)
192 {
193         int ret;
194         DECLARE_WAITQUEUE(wait, current);
195
196  retry:
197         if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING)
198                 && chip->state != FL_SYNCING) {
199                 /*
200                  * OK. We have possibility for contension on the write/erase
201                  * operations which are global to the real chip and not per
202                  * partition.  So let's fight it over in the partition which
203                  * currently has authority on the operation.
204                  *
205                  * The rules are as follows:
206                  *
207                  * - any write operation must own shared->writing.
208                  *
209                  * - any erase operation must own _both_ shared->writing and
210                  *   shared->erasing.
211                  *
212                  * - contension arbitration is handled in the owner's context.
213                  *
214                  * The 'shared' struct can be read and/or written only when
215                  * its lock is taken.
216                  */
217                 struct flchip_shared *shared = chip->priv;
218                 struct flchip *contender;
219                 spin_lock(&shared->lock);
220                 contender = shared->writing;
221                 if (contender && contender != chip) {
222                         /*
223                          * The engine to perform desired operation on this
224                          * partition is already in use by someone else.
225                          * Let's fight over it in the context of the chip
226                          * currently using it.  If it is possible to suspend,
227                          * that other partition will do just that, otherwise
228                          * it'll happily send us to sleep.  In any case, when
229                          * get_chip returns success we're clear to go ahead.
230                          */
231                         ret = mutex_trylock(&contender->mutex);
232                         spin_unlock(&shared->lock);
233                         if (!ret)
234                                 goto retry;
235                         mutex_unlock(&chip->mutex);
236                         ret = chip_ready(map, contender, mode);
237                         mutex_lock(&chip->mutex);
238
239                         if (ret == -EAGAIN) {
240                                 mutex_unlock(&contender->mutex);
241                                 goto retry;
242                         }
243                         if (ret) {
244                                 mutex_unlock(&contender->mutex);
245                                 return ret;
246                         }
247                         spin_lock(&shared->lock);
248
249                         /* We should not own chip if it is already in FL_SYNCING
250                          * state. Put contender and retry. */
251                         if (chip->state == FL_SYNCING) {
252                                 put_chip(map, contender);
253                                 mutex_unlock(&contender->mutex);
254                                 goto retry;
255                         }
256                         mutex_unlock(&contender->mutex);
257                 }
258
259                 /* Check if we have suspended erase on this chip.
260                    Must sleep in such a case. */
261                 if (mode == FL_ERASING && shared->erasing
262                     && shared->erasing->oldstate == FL_ERASING) {
263                         spin_unlock(&shared->lock);
264                         set_current_state(TASK_UNINTERRUPTIBLE);
265                         add_wait_queue(&chip->wq, &wait);
266                         mutex_unlock(&chip->mutex);
267                         schedule();
268                         remove_wait_queue(&chip->wq, &wait);
269                         mutex_lock(&chip->mutex);
270                         goto retry;
271                 }
272
273                 /* We now own it */
274                 shared->writing = chip;
275                 if (mode == FL_ERASING)
276                         shared->erasing = chip;
277                 spin_unlock(&shared->lock);
278         }
279
280         ret = chip_ready(map, chip, mode);
281         if (ret == -EAGAIN)
282                 goto retry;
283
284         return ret;
285 }
286
287 static int chip_ready(struct map_info *map, struct flchip *chip, int mode)
288 {
289         struct lpddr_private *lpddr = map->fldrv_priv;
290         int ret = 0;
291         DECLARE_WAITQUEUE(wait, current);
292
293         /* Prevent setting state FL_SYNCING for chip in suspended state. */
294         if (FL_SYNCING == mode && FL_READY != chip->oldstate)
295                 goto sleep;
296
297         switch (chip->state) {
298         case FL_READY:
299         case FL_JEDEC_QUERY:
300                 return 0;
301
302         case FL_ERASING:
303                 if (!lpddr->qinfo->SuspEraseSupp ||
304                         !(mode == FL_READY || mode == FL_POINT))
305                         goto sleep;
306
307                 map_write(map, CMD(LPDDR_SUSPEND),
308                         map->pfow_base + PFOW_PROGRAM_ERASE_SUSPEND);
309                 chip->oldstate = FL_ERASING;
310                 chip->state = FL_ERASE_SUSPENDING;
311                 ret = wait_for_ready(map, chip, 0);
312                 if (ret) {
313                         /* Oops. something got wrong. */
314                         /* Resume and pretend we weren't here.  */
315                         map_write(map, CMD(LPDDR_RESUME),
316                                 map->pfow_base + PFOW_COMMAND_CODE);
317                         map_write(map, CMD(LPDDR_START_EXECUTION),
318                                 map->pfow_base + PFOW_COMMAND_EXECUTE);
319                         chip->state = FL_ERASING;
320                         chip->oldstate = FL_READY;
321                         printk(KERN_ERR "%s: suspend operation failed."
322                                         "State may be wrong \n", map->name);
323                         return -EIO;
324                 }
325                 chip->erase_suspended = 1;
326                 chip->state = FL_READY;
327                 return 0;
328                 /* Erase suspend */
329         case FL_POINT:
330                 /* Only if there's no operation suspended... */
331                 if (mode == FL_READY && chip->oldstate == FL_READY)
332                         return 0;
333
334         default:
335 sleep:
336                 set_current_state(TASK_UNINTERRUPTIBLE);
337                 add_wait_queue(&chip->wq, &wait);
338                 mutex_unlock(&chip->mutex);
339                 schedule();
340                 remove_wait_queue(&chip->wq, &wait);
341                 mutex_lock(&chip->mutex);
342                 return -EAGAIN;
343         }
344 }
345
346 static void put_chip(struct map_info *map, struct flchip *chip)
347 {
348         if (chip->priv) {
349                 struct flchip_shared *shared = chip->priv;
350                 spin_lock(&shared->lock);
351                 if (shared->writing == chip && chip->oldstate == FL_READY) {
352                         /* We own the ability to write, but we're done */
353                         shared->writing = shared->erasing;
354                         if (shared->writing && shared->writing != chip) {
355                                 /* give back the ownership */
356                                 struct flchip *loaner = shared->writing;
357                                 mutex_lock(&loaner->mutex);
358                                 spin_unlock(&shared->lock);
359                                 mutex_unlock(&chip->mutex);
360                                 put_chip(map, loaner);
361                                 mutex_lock(&chip->mutex);
362                                 mutex_unlock(&loaner->mutex);
363                                 wake_up(&chip->wq);
364                                 return;
365                         }
366                         shared->erasing = NULL;
367                         shared->writing = NULL;
368                 } else if (shared->erasing == chip && shared->writing != chip) {
369                         /*
370                          * We own the ability to erase without the ability
371                          * to write, which means the erase was suspended
372                          * and some other partition is currently writing.
373                          * Don't let the switch below mess things up since
374                          * we don't have ownership to resume anything.
375                          */
376                         spin_unlock(&shared->lock);
377                         wake_up(&chip->wq);
378                         return;
379                 }
380                 spin_unlock(&shared->lock);
381         }
382
383         switch (chip->oldstate) {
384         case FL_ERASING:
385                 chip->state = chip->oldstate;
386                 map_write(map, CMD(LPDDR_RESUME),
387                                 map->pfow_base + PFOW_COMMAND_CODE);
388                 map_write(map, CMD(LPDDR_START_EXECUTION),
389                                 map->pfow_base + PFOW_COMMAND_EXECUTE);
390                 chip->oldstate = FL_READY;
391                 chip->state = FL_ERASING;
392                 break;
393         case FL_READY:
394                 break;
395         default:
396                 printk(KERN_ERR "%s: put_chip() called with oldstate %d!\n",
397                                 map->name, chip->oldstate);
398         }
399         wake_up(&chip->wq);
400 }
401
402 int do_write_buffer(struct map_info *map, struct flchip *chip,
403                         unsigned long adr, const struct kvec **pvec,
404                         unsigned long *pvec_seek, int len)
405 {
406         struct lpddr_private *lpddr = map->fldrv_priv;
407         map_word datum;
408         int ret, wbufsize, word_gap, words;
409         const struct kvec *vec;
410         unsigned long vec_seek;
411         unsigned long prog_buf_ofs;
412
413         wbufsize = 1 << lpddr->qinfo->BufSizeShift;
414
415         mutex_lock(&chip->mutex);
416         ret = get_chip(map, chip, FL_WRITING);
417         if (ret) {
418                 mutex_unlock(&chip->mutex);
419                 return ret;
420         }
421         /* Figure out the number of words to write */
422         word_gap = (-adr & (map_bankwidth(map)-1));
423         words = (len - word_gap + map_bankwidth(map) - 1) / map_bankwidth(map);
424         if (!word_gap) {
425                 words--;
426         } else {
427                 word_gap = map_bankwidth(map) - word_gap;
428                 adr -= word_gap;
429                 datum = map_word_ff(map);
430         }
431         /* Write data */
432         /* Get the program buffer offset from PFOW register data first*/
433         prog_buf_ofs = map->pfow_base + CMDVAL(map_read(map,
434                                 map->pfow_base + PFOW_PROGRAM_BUFFER_OFFSET));
435         vec = *pvec;
436         vec_seek = *pvec_seek;
437         do {
438                 int n = map_bankwidth(map) - word_gap;
439
440                 if (n > vec->iov_len - vec_seek)
441                         n = vec->iov_len - vec_seek;
442                 if (n > len)
443                         n = len;
444
445                 if (!word_gap && (len < map_bankwidth(map)))
446                         datum = map_word_ff(map);
447
448                 datum = map_word_load_partial(map, datum,
449                                 vec->iov_base + vec_seek, word_gap, n);
450
451                 len -= n;
452                 word_gap += n;
453                 if (!len || word_gap == map_bankwidth(map)) {
454                         map_write(map, datum, prog_buf_ofs);
455                         prog_buf_ofs += map_bankwidth(map);
456                         word_gap = 0;
457                 }
458
459                 vec_seek += n;
460                 if (vec_seek == vec->iov_len) {
461                         vec++;
462                         vec_seek = 0;
463                 }
464         } while (len);
465         *pvec = vec;
466         *pvec_seek = vec_seek;
467
468         /* GO GO GO */
469         send_pfow_command(map, LPDDR_BUFF_PROGRAM, adr, wbufsize, NULL);
470         chip->state = FL_WRITING;
471         ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->ProgBufferTime));
472         if (ret)        {
473                 printk(KERN_WARNING"%s Buffer program error: %d at %lx; \n",
474                         map->name, ret, adr);
475                 goto out;
476         }
477
478  out:   put_chip(map, chip);
479         mutex_unlock(&chip->mutex);
480         return ret;
481 }
482
483 int do_erase_oneblock(struct mtd_info *mtd, loff_t adr)
484 {
485         struct map_info *map = mtd->priv;
486         struct lpddr_private *lpddr = map->fldrv_priv;
487         int chipnum = adr >> lpddr->chipshift;
488         struct flchip *chip = &lpddr->chips[chipnum];
489         int ret;
490
491         mutex_lock(&chip->mutex);
492         ret = get_chip(map, chip, FL_ERASING);
493         if (ret) {
494                 mutex_unlock(&chip->mutex);
495                 return ret;
496         }
497         send_pfow_command(map, LPDDR_BLOCK_ERASE, adr, 0, NULL);
498         chip->state = FL_ERASING;
499         ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->BlockEraseTime)*1000);
500         if (ret) {
501                 printk(KERN_WARNING"%s Erase block error %d at : %llx\n",
502                         map->name, ret, adr);
503                 goto out;
504         }
505  out:   put_chip(map, chip);
506         mutex_unlock(&chip->mutex);
507         return ret;
508 }
509
510 static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len,
511                         size_t *retlen, u_char *buf)
512 {
513         struct map_info *map = mtd->priv;
514         struct lpddr_private *lpddr = map->fldrv_priv;
515         int chipnum = adr >> lpddr->chipshift;
516         struct flchip *chip = &lpddr->chips[chipnum];
517         int ret = 0;
518
519         mutex_lock(&chip->mutex);
520         ret = get_chip(map, chip, FL_READY);
521         if (ret) {
522                 mutex_unlock(&chip->mutex);
523                 return ret;
524         }
525
526         map_copy_from(map, buf, adr, len);
527         *retlen = len;
528
529         put_chip(map, chip);
530         mutex_unlock(&chip->mutex);
531         return ret;
532 }
533
534 static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
535                         size_t *retlen, void **mtdbuf, resource_size_t *phys)
536 {
537         struct map_info *map = mtd->priv;
538         struct lpddr_private *lpddr = map->fldrv_priv;
539         int chipnum = adr >> lpddr->chipshift;
540         unsigned long ofs, last_end = 0;
541         struct flchip *chip = &lpddr->chips[chipnum];
542         int ret = 0;
543
544         if (!map->virt || (adr + len > mtd->size))
545                 return -EINVAL;
546
547         /* ofs: offset within the first chip that the first read should start */
548         ofs = adr - (chipnum << lpddr->chipshift);
549
550         *mtdbuf = (void *)map->virt + chip->start + ofs;
551         *retlen = 0;
552
553         while (len) {
554                 unsigned long thislen;
555
556                 if (chipnum >= lpddr->numchips)
557                         break;
558
559                 /* We cannot point across chips that are virtually disjoint */
560                 if (!last_end)
561                         last_end = chip->start;
562                 else if (chip->start != last_end)
563                         break;
564
565                 if ((len + ofs - 1) >> lpddr->chipshift)
566                         thislen = (1<<lpddr->chipshift) - ofs;
567                 else
568                         thislen = len;
569                 /* get the chip */
570                 mutex_lock(&chip->mutex);
571                 ret = get_chip(map, chip, FL_POINT);
572                 mutex_unlock(&chip->mutex);
573                 if (ret)
574                         break;
575
576                 chip->state = FL_POINT;
577                 chip->ref_point_counter++;
578                 *retlen += thislen;
579                 len -= thislen;
580
581                 ofs = 0;
582                 last_end += 1 << lpddr->chipshift;
583                 chipnum++;
584                 chip = &lpddr->chips[chipnum];
585         }
586         return 0;
587 }
588
589 static void lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)
590 {
591         struct map_info *map = mtd->priv;
592         struct lpddr_private *lpddr = map->fldrv_priv;
593         int chipnum = adr >> lpddr->chipshift;
594         unsigned long ofs;
595
596         /* ofs: offset within the first chip that the first read should start */
597         ofs = adr - (chipnum << lpddr->chipshift);
598
599         while (len) {
600                 unsigned long thislen;
601                 struct flchip *chip;
602
603                 chip = &lpddr->chips[chipnum];
604                 if (chipnum >= lpddr->numchips)
605                         break;
606
607                 if ((len + ofs - 1) >> lpddr->chipshift)
608                         thislen = (1<<lpddr->chipshift) - ofs;
609                 else
610                         thislen = len;
611
612                 mutex_lock(&chip->mutex);
613                 if (chip->state == FL_POINT) {
614                         chip->ref_point_counter--;
615                         if (chip->ref_point_counter == 0)
616                                 chip->state = FL_READY;
617                 } else
618                         printk(KERN_WARNING "%s: Warning: unpoint called on non"
619                                         "pointed region\n", map->name);
620
621                 put_chip(map, chip);
622                 mutex_unlock(&chip->mutex);
623
624                 len -= thislen;
625                 ofs = 0;
626                 chipnum++;
627         }
628 }
629
630 static int lpddr_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
631                                 size_t *retlen, const u_char *buf)
632 {
633         struct kvec vec;
634
635         vec.iov_base = (void *) buf;
636         vec.iov_len = len;
637
638         return lpddr_writev(mtd, &vec, 1, to, retlen);
639 }
640
641
642 static int lpddr_writev(struct mtd_info *mtd, const struct kvec *vecs,
643                                 unsigned long count, loff_t to, size_t *retlen)
644 {
645         struct map_info *map = mtd->priv;
646         struct lpddr_private *lpddr = map->fldrv_priv;
647         int ret = 0;
648         int chipnum;
649         unsigned long ofs, vec_seek, i;
650         int wbufsize = 1 << lpddr->qinfo->BufSizeShift;
651
652         size_t len = 0;
653
654         for (i = 0; i < count; i++)
655                 len += vecs[i].iov_len;
656
657         *retlen = 0;
658         if (!len)
659                 return 0;
660
661         chipnum = to >> lpddr->chipshift;
662
663         ofs = to;
664         vec_seek = 0;
665
666         do {
667                 /* We must not cross write block boundaries */
668                 int size = wbufsize - (ofs & (wbufsize-1));
669
670                 if (size > len)
671                         size = len;
672
673                 ret = do_write_buffer(map, &lpddr->chips[chipnum],
674                                           ofs, &vecs, &vec_seek, size);
675                 if (ret)
676                         return ret;
677
678                 ofs += size;
679                 (*retlen) += size;
680                 len -= size;
681
682                 /* Be nice and reschedule with the chip in a usable
683                  * state for other processes */
684                 cond_resched();
685
686         } while (len);
687
688         return 0;
689 }
690
691 static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr)
692 {
693         unsigned long ofs, len;
694         int ret;
695         struct map_info *map = mtd->priv;
696         struct lpddr_private *lpddr = map->fldrv_priv;
697         int size = 1 << lpddr->qinfo->UniformBlockSizeShift;
698
699         ofs = instr->addr;
700         len = instr->len;
701
702         if (ofs > mtd->size || (len + ofs) > mtd->size)
703                 return -EINVAL;
704
705         while (len > 0) {
706                 ret = do_erase_oneblock(mtd, ofs);
707                 if (ret)
708                         return ret;
709                 ofs += size;
710                 len -= size;
711         }
712         instr->state = MTD_ERASE_DONE;
713         mtd_erase_callback(instr);
714
715         return 0;
716 }
717
718 #define DO_XXLOCK_LOCK          1
719 #define DO_XXLOCK_UNLOCK        2
720 int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk)
721 {
722         int ret = 0;
723         struct map_info *map = mtd->priv;
724         struct lpddr_private *lpddr = map->fldrv_priv;
725         int chipnum = adr >> lpddr->chipshift;
726         struct flchip *chip = &lpddr->chips[chipnum];
727
728         mutex_lock(&chip->mutex);
729         ret = get_chip(map, chip, FL_LOCKING);
730         if (ret) {
731                 mutex_unlock(&chip->mutex);
732                 return ret;
733         }
734
735         if (thunk == DO_XXLOCK_LOCK) {
736                 send_pfow_command(map, LPDDR_LOCK_BLOCK, adr, adr + len, NULL);
737                 chip->state = FL_LOCKING;
738         } else if (thunk == DO_XXLOCK_UNLOCK) {
739                 send_pfow_command(map, LPDDR_UNLOCK_BLOCK, adr, adr + len, NULL);
740                 chip->state = FL_UNLOCKING;
741         } else
742                 BUG();
743
744         ret = wait_for_ready(map, chip, 1);
745         if (ret)        {
746                 printk(KERN_ERR "%s: block unlock error status %d \n",
747                                 map->name, ret);
748                 goto out;
749         }
750 out:    put_chip(map, chip);
751         mutex_unlock(&chip->mutex);
752         return ret;
753 }
754
755 static int lpddr_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
756 {
757         return do_xxlock(mtd, ofs, len, DO_XXLOCK_LOCK);
758 }
759
760 static int lpddr_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
761 {
762         return do_xxlock(mtd, ofs, len, DO_XXLOCK_UNLOCK);
763 }
764
765 int word_program(struct map_info *map, loff_t adr, uint32_t curval)
766 {
767     int ret;
768         struct lpddr_private *lpddr = map->fldrv_priv;
769         int chipnum = adr >> lpddr->chipshift;
770         struct flchip *chip = &lpddr->chips[chipnum];
771
772         mutex_lock(&chip->mutex);
773         ret = get_chip(map, chip, FL_WRITING);
774         if (ret) {
775                 mutex_unlock(&chip->mutex);
776                 return ret;
777         }
778
779         send_pfow_command(map, LPDDR_WORD_PROGRAM, adr, 0x00, (map_word *)&curval);
780
781         ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->SingleWordProgTime));
782         if (ret)        {
783                 printk(KERN_WARNING"%s word_program error at: %llx; val: %x\n",
784                         map->name, adr, curval);
785                 goto out;
786         }
787
788 out:    put_chip(map, chip);
789         mutex_unlock(&chip->mutex);
790         return ret;
791 }
792
793 MODULE_LICENSE("GPL");
794 MODULE_AUTHOR("Alexey Korolev <akorolev@infradead.org>");
795 MODULE_DESCRIPTION("MTD driver for LPDDR flash chips");