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