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