Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * LPDDR flash memory device operations. This module provides read, write,
0004  * erase, lock/unlock support for LPDDR flash memories
0005  * (C) 2008 Korolev Alexey <akorolev@infradead.org>
0006  * (C) 2008 Vasiliy Leonenko <vasiliy.leonenko@gmail.com>
0007  * Many thanks to Roman Borisov for initial enabling
0008  *
0009  * TODO:
0010  * Implement VPP management
0011  * Implement XIP support
0012  * Implement OTP support
0013  */
0014 #include <linux/mtd/pfow.h>
0015 #include <linux/mtd/qinfo.h>
0016 #include <linux/slab.h>
0017 #include <linux/module.h>
0018 
0019 static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len,
0020                     size_t *retlen, u_char *buf);
0021 static int lpddr_write_buffers(struct mtd_info *mtd, loff_t to,
0022                 size_t len, size_t *retlen, const u_char *buf);
0023 static int lpddr_writev(struct mtd_info *mtd, const struct kvec *vecs,
0024                 unsigned long count, loff_t to, size_t *retlen);
0025 static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr);
0026 static int lpddr_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
0027 static int lpddr_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
0028 static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
0029             size_t *retlen, void **mtdbuf, resource_size_t *phys);
0030 static int lpddr_unpoint(struct mtd_info *mtd, loff_t adr, size_t len);
0031 static int get_chip(struct map_info *map, struct flchip *chip, int mode);
0032 static int chip_ready(struct map_info *map, struct flchip *chip, int mode);
0033 static void put_chip(struct map_info *map, struct flchip *chip);
0034 
0035 struct mtd_info *lpddr_cmdset(struct map_info *map)
0036 {
0037     struct lpddr_private *lpddr = map->fldrv_priv;
0038     struct flchip_shared *shared;
0039     struct flchip *chip;
0040     struct mtd_info *mtd;
0041     int numchips;
0042     int i, j;
0043 
0044     mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
0045     if (!mtd)
0046         return NULL;
0047     mtd->priv = map;
0048     mtd->type = MTD_NORFLASH;
0049 
0050     /* Fill in the default mtd operations */
0051     mtd->_read = lpddr_read;
0052     mtd->type = MTD_NORFLASH;
0053     mtd->flags = MTD_CAP_NORFLASH;
0054     mtd->flags &= ~MTD_BIT_WRITEABLE;
0055     mtd->_erase = lpddr_erase;
0056     mtd->_write = lpddr_write_buffers;
0057     mtd->_writev = lpddr_writev;
0058     mtd->_lock = lpddr_lock;
0059     mtd->_unlock = lpddr_unlock;
0060     if (map_is_linear(map)) {
0061         mtd->_point = lpddr_point;
0062         mtd->_unpoint = lpddr_unpoint;
0063     }
0064     mtd->size = 1 << lpddr->qinfo->DevSizeShift;
0065     mtd->erasesize = 1 << lpddr->qinfo->UniformBlockSizeShift;
0066     mtd->writesize = 1 << lpddr->qinfo->BufSizeShift;
0067 
0068     shared = kmalloc_array(lpddr->numchips, sizeof(struct flchip_shared),
0069                         GFP_KERNEL);
0070     if (!shared) {
0071         kfree(mtd);
0072         return NULL;
0073     }
0074 
0075     chip = &lpddr->chips[0];
0076     numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum;
0077     for (i = 0; i < numchips; i++) {
0078         shared[i].writing = shared[i].erasing = NULL;
0079         mutex_init(&shared[i].lock);
0080         for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) {
0081             *chip = lpddr->chips[i];
0082             chip->start += j << lpddr->chipshift;
0083             chip->oldstate = chip->state = FL_READY;
0084             chip->priv = &shared[i];
0085             /* those should be reset too since
0086                they create memory references. */
0087             init_waitqueue_head(&chip->wq);
0088             mutex_init(&chip->mutex);
0089             chip++;
0090         }
0091     }
0092 
0093     return mtd;
0094 }
0095 EXPORT_SYMBOL(lpddr_cmdset);
0096 
0097 static void print_drs_error(unsigned int dsr)
0098 {
0099     int prog_status = (dsr & DSR_RPS) >> 8;
0100 
0101     if (!(dsr & DSR_AVAILABLE))
0102         pr_notice("DSR.15: (0) Device not Available\n");
0103     if ((prog_status & 0x03) == 0x03)
0104         pr_notice("DSR.9,8: (11) Attempt to program invalid half with 41h command\n");
0105     else if (prog_status & 0x02)
0106         pr_notice("DSR.9,8: (10) Object Mode Program attempt in region with Control Mode data\n");
0107     else if (prog_status &  0x01)
0108         pr_notice("DSR.9,8: (01) Program attempt in region with Object Mode data\n");
0109     if (!(dsr & DSR_READY_STATUS))
0110         pr_notice("DSR.7: (0) Device is Busy\n");
0111     if (dsr & DSR_ESS)
0112         pr_notice("DSR.6: (1) Erase Suspended\n");
0113     if (dsr & DSR_ERASE_STATUS)
0114         pr_notice("DSR.5: (1) Erase/Blank check error\n");
0115     if (dsr & DSR_PROGRAM_STATUS)
0116         pr_notice("DSR.4: (1) Program Error\n");
0117     if (dsr & DSR_VPPS)
0118         pr_notice("DSR.3: (1) Vpp low detect, operation aborted\n");
0119     if (dsr & DSR_PSS)
0120         pr_notice("DSR.2: (1) Program suspended\n");
0121     if (dsr & DSR_DPS)
0122         pr_notice("DSR.1: (1) Aborted Erase/Program attempt on locked block\n");
0123 }
0124 
0125 static int wait_for_ready(struct map_info *map, struct flchip *chip,
0126         unsigned int chip_op_time)
0127 {
0128     unsigned int timeo, reset_timeo, sleep_time;
0129     unsigned int dsr;
0130     flstate_t chip_state = chip->state;
0131     int ret = 0;
0132 
0133     /* set our timeout to 8 times the expected delay */
0134     timeo = chip_op_time * 8;
0135     if (!timeo)
0136         timeo = 500000;
0137     reset_timeo = timeo;
0138     sleep_time = chip_op_time / 2;
0139 
0140     for (;;) {
0141         dsr = CMDVAL(map_read(map, map->pfow_base + PFOW_DSR));
0142         if (dsr & DSR_READY_STATUS)
0143             break;
0144         if (!timeo) {
0145             printk(KERN_ERR "%s: Flash timeout error state %d \n",
0146                             map->name, chip_state);
0147             ret = -ETIME;
0148             break;
0149         }
0150 
0151         /* OK Still waiting. Drop the lock, wait a while and retry. */
0152         mutex_unlock(&chip->mutex);
0153         if (sleep_time >= 1000000/HZ) {
0154             /*
0155              * Half of the normal delay still remaining
0156              * can be performed with a sleeping delay instead
0157              * of busy waiting.
0158              */
0159             msleep(sleep_time/1000);
0160             timeo -= sleep_time;
0161             sleep_time = 1000000/HZ;
0162         } else {
0163             udelay(1);
0164             cond_resched();
0165             timeo--;
0166         }
0167         mutex_lock(&chip->mutex);
0168 
0169         while (chip->state != chip_state) {
0170             /* Someone's suspended the operation: sleep */
0171             DECLARE_WAITQUEUE(wait, current);
0172             set_current_state(TASK_UNINTERRUPTIBLE);
0173             add_wait_queue(&chip->wq, &wait);
0174             mutex_unlock(&chip->mutex);
0175             schedule();
0176             remove_wait_queue(&chip->wq, &wait);
0177             mutex_lock(&chip->mutex);
0178         }
0179         if (chip->erase_suspended || chip->write_suspended)  {
0180             /* Suspend has occurred while sleep: reset timeout */
0181             timeo = reset_timeo;
0182             chip->erase_suspended = chip->write_suspended = 0;
0183         }
0184     }
0185     /* check status for errors */
0186     if (dsr & DSR_ERR) {
0187         /* Clear DSR*/
0188         map_write(map, CMD(~(DSR_ERR)), map->pfow_base + PFOW_DSR);
0189         printk(KERN_WARNING"%s: Bad status on wait: 0x%x \n",
0190                 map->name, dsr);
0191         print_drs_error(dsr);
0192         ret = -EIO;
0193     }
0194     chip->state = FL_READY;
0195     return ret;
0196 }
0197 
0198 static int get_chip(struct map_info *map, struct flchip *chip, int mode)
0199 {
0200     int ret;
0201     DECLARE_WAITQUEUE(wait, current);
0202 
0203  retry:
0204     if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING)
0205         && chip->state != FL_SYNCING) {
0206         /*
0207          * OK. We have possibility for contension on the write/erase
0208          * operations which are global to the real chip and not per
0209          * partition.  So let's fight it over in the partition which
0210          * currently has authority on the operation.
0211          *
0212          * The rules are as follows:
0213          *
0214          * - any write operation must own shared->writing.
0215          *
0216          * - any erase operation must own _both_ shared->writing and
0217          *   shared->erasing.
0218          *
0219          * - contension arbitration is handled in the owner's context.
0220          *
0221          * The 'shared' struct can be read and/or written only when
0222          * its lock is taken.
0223          */
0224         struct flchip_shared *shared = chip->priv;
0225         struct flchip *contender;
0226         mutex_lock(&shared->lock);
0227         contender = shared->writing;
0228         if (contender && contender != chip) {
0229             /*
0230              * The engine to perform desired operation on this
0231              * partition is already in use by someone else.
0232              * Let's fight over it in the context of the chip
0233              * currently using it.  If it is possible to suspend,
0234              * that other partition will do just that, otherwise
0235              * it'll happily send us to sleep.  In any case, when
0236              * get_chip returns success we're clear to go ahead.
0237              */
0238             ret = mutex_trylock(&contender->mutex);
0239             mutex_unlock(&shared->lock);
0240             if (!ret)
0241                 goto retry;
0242             mutex_unlock(&chip->mutex);
0243             ret = chip_ready(map, contender, mode);
0244             mutex_lock(&chip->mutex);
0245 
0246             if (ret == -EAGAIN) {
0247                 mutex_unlock(&contender->mutex);
0248                 goto retry;
0249             }
0250             if (ret) {
0251                 mutex_unlock(&contender->mutex);
0252                 return ret;
0253             }
0254             mutex_lock(&shared->lock);
0255 
0256             /* We should not own chip if it is already in FL_SYNCING
0257              * state. Put contender and retry. */
0258             if (chip->state == FL_SYNCING) {
0259                 put_chip(map, contender);
0260                 mutex_unlock(&contender->mutex);
0261                 goto retry;
0262             }
0263             mutex_unlock(&contender->mutex);
0264         }
0265 
0266         /* Check if we have suspended erase on this chip.
0267            Must sleep in such a case. */
0268         if (mode == FL_ERASING && shared->erasing
0269             && shared->erasing->oldstate == FL_ERASING) {
0270             mutex_unlock(&shared->lock);
0271             set_current_state(TASK_UNINTERRUPTIBLE);
0272             add_wait_queue(&chip->wq, &wait);
0273             mutex_unlock(&chip->mutex);
0274             schedule();
0275             remove_wait_queue(&chip->wq, &wait);
0276             mutex_lock(&chip->mutex);
0277             goto retry;
0278         }
0279 
0280         /* We now own it */
0281         shared->writing = chip;
0282         if (mode == FL_ERASING)
0283             shared->erasing = chip;
0284         mutex_unlock(&shared->lock);
0285     }
0286 
0287     ret = chip_ready(map, chip, mode);
0288     if (ret == -EAGAIN)
0289         goto retry;
0290 
0291     return ret;
0292 }
0293 
0294 static int chip_ready(struct map_info *map, struct flchip *chip, int mode)
0295 {
0296     struct lpddr_private *lpddr = map->fldrv_priv;
0297     int ret = 0;
0298     DECLARE_WAITQUEUE(wait, current);
0299 
0300     /* Prevent setting state FL_SYNCING for chip in suspended state. */
0301     if (FL_SYNCING == mode && FL_READY != chip->oldstate)
0302         goto sleep;
0303 
0304     switch (chip->state) {
0305     case FL_READY:
0306     case FL_JEDEC_QUERY:
0307         return 0;
0308 
0309     case FL_ERASING:
0310         if (!lpddr->qinfo->SuspEraseSupp ||
0311             !(mode == FL_READY || mode == FL_POINT))
0312             goto sleep;
0313 
0314         map_write(map, CMD(LPDDR_SUSPEND),
0315             map->pfow_base + PFOW_PROGRAM_ERASE_SUSPEND);
0316         chip->oldstate = FL_ERASING;
0317         chip->state = FL_ERASE_SUSPENDING;
0318         ret = wait_for_ready(map, chip, 0);
0319         if (ret) {
0320             /* Oops. something got wrong. */
0321             /* Resume and pretend we weren't here.  */
0322             put_chip(map, chip);
0323             printk(KERN_ERR "%s: suspend operation failed."
0324                     "State may be wrong \n", map->name);
0325             return -EIO;
0326         }
0327         chip->erase_suspended = 1;
0328         chip->state = FL_READY;
0329         return 0;
0330         /* Erase suspend */
0331     case FL_POINT:
0332         /* Only if there's no operation suspended... */
0333         if (mode == FL_READY && chip->oldstate == FL_READY)
0334             return 0;
0335         fallthrough;
0336     default:
0337 sleep:
0338         set_current_state(TASK_UNINTERRUPTIBLE);
0339         add_wait_queue(&chip->wq, &wait);
0340         mutex_unlock(&chip->mutex);
0341         schedule();
0342         remove_wait_queue(&chip->wq, &wait);
0343         mutex_lock(&chip->mutex);
0344         return -EAGAIN;
0345     }
0346 }
0347 
0348 static void put_chip(struct map_info *map, struct flchip *chip)
0349 {
0350     if (chip->priv) {
0351         struct flchip_shared *shared = chip->priv;
0352         mutex_lock(&shared->lock);
0353         if (shared->writing == chip && chip->oldstate == FL_READY) {
0354             /* We own the ability to write, but we're done */
0355             shared->writing = shared->erasing;
0356             if (shared->writing && shared->writing != chip) {
0357                 /* give back the ownership */
0358                 struct flchip *loaner = shared->writing;
0359                 mutex_lock(&loaner->mutex);
0360                 mutex_unlock(&shared->lock);
0361                 mutex_unlock(&chip->mutex);
0362                 put_chip(map, loaner);
0363                 mutex_lock(&chip->mutex);
0364                 mutex_unlock(&loaner->mutex);
0365                 wake_up(&chip->wq);
0366                 return;
0367             }
0368             shared->erasing = NULL;
0369             shared->writing = NULL;
0370         } else if (shared->erasing == chip && shared->writing != chip) {
0371             /*
0372              * We own the ability to erase without the ability
0373              * to write, which means the erase was suspended
0374              * and some other partition is currently writing.
0375              * Don't let the switch below mess things up since
0376              * we don't have ownership to resume anything.
0377              */
0378             mutex_unlock(&shared->lock);
0379             wake_up(&chip->wq);
0380             return;
0381         }
0382         mutex_unlock(&shared->lock);
0383     }
0384 
0385     switch (chip->oldstate) {
0386     case FL_ERASING:
0387         map_write(map, CMD(LPDDR_RESUME),
0388                 map->pfow_base + PFOW_COMMAND_CODE);
0389         map_write(map, CMD(LPDDR_START_EXECUTION),
0390                 map->pfow_base + PFOW_COMMAND_EXECUTE);
0391         chip->oldstate = FL_READY;
0392         chip->state = FL_ERASING;
0393         break;
0394     case FL_READY:
0395         break;
0396     default:
0397         printk(KERN_ERR "%s: put_chip() called with oldstate %d!\n",
0398                 map->name, chip->oldstate);
0399     }
0400     wake_up(&chip->wq);
0401 }
0402 
0403 static int do_write_buffer(struct map_info *map, struct flchip *chip,
0404             unsigned long adr, const struct kvec **pvec,
0405             unsigned long *pvec_seek, int len)
0406 {
0407     struct lpddr_private *lpddr = map->fldrv_priv;
0408     map_word datum;
0409     int ret, wbufsize, word_gap, words;
0410     const struct kvec *vec;
0411     unsigned long vec_seek;
0412     unsigned long prog_buf_ofs;
0413 
0414     wbufsize = 1 << lpddr->qinfo->BufSizeShift;
0415 
0416     mutex_lock(&chip->mutex);
0417     ret = get_chip(map, chip, FL_WRITING);
0418     if (ret) {
0419         mutex_unlock(&chip->mutex);
0420         return ret;
0421     }
0422     /* Figure out the number of words to write */
0423     word_gap = (-adr & (map_bankwidth(map)-1));
0424     words = (len - word_gap + map_bankwidth(map) - 1) / map_bankwidth(map);
0425     if (!word_gap) {
0426         words--;
0427     } else {
0428         word_gap = map_bankwidth(map) - word_gap;
0429         adr -= word_gap;
0430         datum = map_word_ff(map);
0431     }
0432     /* Write data */
0433     /* Get the program buffer offset from PFOW register data first*/
0434     prog_buf_ofs = map->pfow_base + CMDVAL(map_read(map,
0435                 map->pfow_base + PFOW_PROGRAM_BUFFER_OFFSET));
0436     vec = *pvec;
0437     vec_seek = *pvec_seek;
0438     do {
0439         int n = map_bankwidth(map) - word_gap;
0440 
0441         if (n > vec->iov_len - vec_seek)
0442             n = vec->iov_len - vec_seek;
0443         if (n > len)
0444             n = len;
0445 
0446         if (!word_gap && (len < map_bankwidth(map)))
0447             datum = map_word_ff(map);
0448 
0449         datum = map_word_load_partial(map, datum,
0450                 vec->iov_base + vec_seek, word_gap, n);
0451 
0452         len -= n;
0453         word_gap += n;
0454         if (!len || word_gap == map_bankwidth(map)) {
0455             map_write(map, datum, prog_buf_ofs);
0456             prog_buf_ofs += map_bankwidth(map);
0457             word_gap = 0;
0458         }
0459 
0460         vec_seek += n;
0461         if (vec_seek == vec->iov_len) {
0462             vec++;
0463             vec_seek = 0;
0464         }
0465     } while (len);
0466     *pvec = vec;
0467     *pvec_seek = vec_seek;
0468 
0469     /* GO GO GO */
0470     send_pfow_command(map, LPDDR_BUFF_PROGRAM, adr, wbufsize, NULL);
0471     chip->state = FL_WRITING;
0472     ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->ProgBufferTime));
0473     if (ret)    {
0474         printk(KERN_WARNING"%s Buffer program error: %d at %lx; \n",
0475             map->name, ret, adr);
0476         goto out;
0477     }
0478 
0479  out:   put_chip(map, chip);
0480     mutex_unlock(&chip->mutex);
0481     return ret;
0482 }
0483 
0484 static int do_erase_oneblock(struct mtd_info *mtd, loff_t adr)
0485 {
0486     struct map_info *map = mtd->priv;
0487     struct lpddr_private *lpddr = map->fldrv_priv;
0488     int chipnum = adr >> lpddr->chipshift;
0489     struct flchip *chip = &lpddr->chips[chipnum];
0490     int ret;
0491 
0492     mutex_lock(&chip->mutex);
0493     ret = get_chip(map, chip, FL_ERASING);
0494     if (ret) {
0495         mutex_unlock(&chip->mutex);
0496         return ret;
0497     }
0498     send_pfow_command(map, LPDDR_BLOCK_ERASE, adr, 0, NULL);
0499     chip->state = FL_ERASING;
0500     ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->BlockEraseTime)*1000);
0501     if (ret) {
0502         printk(KERN_WARNING"%s Erase block error %d at : %llx\n",
0503             map->name, ret, adr);
0504         goto out;
0505     }
0506  out:   put_chip(map, chip);
0507     mutex_unlock(&chip->mutex);
0508     return ret;
0509 }
0510 
0511 static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len,
0512             size_t *retlen, u_char *buf)
0513 {
0514     struct map_info *map = mtd->priv;
0515     struct lpddr_private *lpddr = map->fldrv_priv;
0516     int chipnum = adr >> lpddr->chipshift;
0517     struct flchip *chip = &lpddr->chips[chipnum];
0518     int ret = 0;
0519 
0520     mutex_lock(&chip->mutex);
0521     ret = get_chip(map, chip, FL_READY);
0522     if (ret) {
0523         mutex_unlock(&chip->mutex);
0524         return ret;
0525     }
0526 
0527     map_copy_from(map, buf, adr, len);
0528     *retlen = len;
0529 
0530     put_chip(map, chip);
0531     mutex_unlock(&chip->mutex);
0532     return ret;
0533 }
0534 
0535 static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
0536             size_t *retlen, void **mtdbuf, resource_size_t *phys)
0537 {
0538     struct map_info *map = mtd->priv;
0539     struct lpddr_private *lpddr = map->fldrv_priv;
0540     int chipnum = adr >> lpddr->chipshift;
0541     unsigned long ofs, last_end = 0;
0542     struct flchip *chip = &lpddr->chips[chipnum];
0543     int ret = 0;
0544 
0545     if (!map->virt)
0546         return -EINVAL;
0547 
0548     /* ofs: offset within the first chip that the first read should start */
0549     ofs = adr - (chipnum << lpddr->chipshift);
0550     *mtdbuf = (void *)map->virt + chip->start + ofs;
0551 
0552     while (len) {
0553         unsigned long thislen;
0554 
0555         if (chipnum >= lpddr->numchips)
0556             break;
0557 
0558         /* We cannot point across chips that are virtually disjoint */
0559         if (!last_end)
0560             last_end = chip->start;
0561         else if (chip->start != last_end)
0562             break;
0563 
0564         if ((len + ofs - 1) >> lpddr->chipshift)
0565             thislen = (1<<lpddr->chipshift) - ofs;
0566         else
0567             thislen = len;
0568         /* get the chip */
0569         mutex_lock(&chip->mutex);
0570         ret = get_chip(map, chip, FL_POINT);
0571         mutex_unlock(&chip->mutex);
0572         if (ret)
0573             break;
0574 
0575         chip->state = FL_POINT;
0576         chip->ref_point_counter++;
0577         *retlen += thislen;
0578         len -= thislen;
0579 
0580         ofs = 0;
0581         last_end += 1 << lpddr->chipshift;
0582         chipnum++;
0583         chip = &lpddr->chips[chipnum];
0584     }
0585     return 0;
0586 }
0587 
0588 static int lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)
0589 {
0590     struct map_info *map = mtd->priv;
0591     struct lpddr_private *lpddr = map->fldrv_priv;
0592     int chipnum = adr >> lpddr->chipshift, err = 0;
0593     unsigned long ofs;
0594 
0595     /* ofs: offset within the first chip that the first read should start */
0596     ofs = adr - (chipnum << lpddr->chipshift);
0597 
0598     while (len) {
0599         unsigned long thislen;
0600         struct flchip *chip;
0601 
0602         chip = &lpddr->chips[chipnum];
0603         if (chipnum >= lpddr->numchips)
0604             break;
0605 
0606         if ((len + ofs - 1) >> lpddr->chipshift)
0607             thislen = (1<<lpddr->chipshift) - ofs;
0608         else
0609             thislen = len;
0610 
0611         mutex_lock(&chip->mutex);
0612         if (chip->state == FL_POINT) {
0613             chip->ref_point_counter--;
0614             if (chip->ref_point_counter == 0)
0615                 chip->state = FL_READY;
0616         } else {
0617             printk(KERN_WARNING "%s: Warning: unpoint called on non"
0618                     "pointed region\n", map->name);
0619             err = -EINVAL;
0620         }
0621 
0622         put_chip(map, chip);
0623         mutex_unlock(&chip->mutex);
0624 
0625         len -= thislen;
0626         ofs = 0;
0627         chipnum++;
0628     }
0629 
0630     return err;
0631 }
0632 
0633 static int lpddr_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
0634                 size_t *retlen, const u_char *buf)
0635 {
0636     struct kvec vec;
0637 
0638     vec.iov_base = (void *) buf;
0639     vec.iov_len = len;
0640 
0641     return lpddr_writev(mtd, &vec, 1, to, retlen);
0642 }
0643 
0644 
0645 static int lpddr_writev(struct mtd_info *mtd, const struct kvec *vecs,
0646                 unsigned long count, loff_t to, size_t *retlen)
0647 {
0648     struct map_info *map = mtd->priv;
0649     struct lpddr_private *lpddr = map->fldrv_priv;
0650     int ret = 0;
0651     int chipnum;
0652     unsigned long ofs, vec_seek, i;
0653     int wbufsize = 1 << lpddr->qinfo->BufSizeShift;
0654     size_t len = 0;
0655 
0656     for (i = 0; i < count; i++)
0657         len += vecs[i].iov_len;
0658 
0659     if (!len)
0660         return 0;
0661 
0662     chipnum = to >> lpddr->chipshift;
0663 
0664     ofs = to;
0665     vec_seek = 0;
0666 
0667     do {
0668         /* We must not cross write block boundaries */
0669         int size = wbufsize - (ofs & (wbufsize-1));
0670 
0671         if (size > len)
0672             size = len;
0673 
0674         ret = do_write_buffer(map, &lpddr->chips[chipnum],
0675                       ofs, &vecs, &vec_seek, size);
0676         if (ret)
0677             return ret;
0678 
0679         ofs += size;
0680         (*retlen) += size;
0681         len -= size;
0682 
0683         /* Be nice and reschedule with the chip in a usable
0684          * state for other processes */
0685         cond_resched();
0686 
0687     } while (len);
0688 
0689     return 0;
0690 }
0691 
0692 static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr)
0693 {
0694     unsigned long ofs, len;
0695     int ret;
0696     struct map_info *map = mtd->priv;
0697     struct lpddr_private *lpddr = map->fldrv_priv;
0698     int size = 1 << lpddr->qinfo->UniformBlockSizeShift;
0699 
0700     ofs = instr->addr;
0701     len = instr->len;
0702 
0703     while (len > 0) {
0704         ret = do_erase_oneblock(mtd, ofs);
0705         if (ret)
0706             return ret;
0707         ofs += size;
0708         len -= size;
0709     }
0710 
0711     return 0;
0712 }
0713 
0714 #define DO_XXLOCK_LOCK      1
0715 #define DO_XXLOCK_UNLOCK    2
0716 static int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk)
0717 {
0718     int ret = 0;
0719     struct map_info *map = mtd->priv;
0720     struct lpddr_private *lpddr = map->fldrv_priv;
0721     int chipnum = adr >> lpddr->chipshift;
0722     struct flchip *chip = &lpddr->chips[chipnum];
0723 
0724     mutex_lock(&chip->mutex);
0725     ret = get_chip(map, chip, FL_LOCKING);
0726     if (ret) {
0727         mutex_unlock(&chip->mutex);
0728         return ret;
0729     }
0730 
0731     if (thunk == DO_XXLOCK_LOCK) {
0732         send_pfow_command(map, LPDDR_LOCK_BLOCK, adr, adr + len, NULL);
0733         chip->state = FL_LOCKING;
0734     } else if (thunk == DO_XXLOCK_UNLOCK) {
0735         send_pfow_command(map, LPDDR_UNLOCK_BLOCK, adr, adr + len, NULL);
0736         chip->state = FL_UNLOCKING;
0737     } else
0738         BUG();
0739 
0740     ret = wait_for_ready(map, chip, 1);
0741     if (ret)    {
0742         printk(KERN_ERR "%s: block unlock error status %d \n",
0743                 map->name, ret);
0744         goto out;
0745     }
0746 out:    put_chip(map, chip);
0747     mutex_unlock(&chip->mutex);
0748     return ret;
0749 }
0750 
0751 static int lpddr_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
0752 {
0753     return do_xxlock(mtd, ofs, len, DO_XXLOCK_LOCK);
0754 }
0755 
0756 static int lpddr_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
0757 {
0758     return do_xxlock(mtd, ofs, len, DO_XXLOCK_UNLOCK);
0759 }
0760 
0761 MODULE_LICENSE("GPL");
0762 MODULE_AUTHOR("Alexey Korolev <akorolev@infradead.org>");
0763 MODULE_DESCRIPTION("MTD driver for LPDDR flash chips");