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(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 } 96 EXPORT_SYMBOL(lpddr_cmdset); 97 98 static 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 171 static 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 267 static 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: 311 sleep: 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 322 static 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 377 static 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 458 static 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 485 static 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 509 static 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 562 static 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 607 static 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 619 static 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 666 static 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 690 static 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 } 720 out: put_chip(map, chip); 721 mutex_unlock(&chip->mutex); 722 return ret; 723 } 724 725 static 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 730 static 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 735 MODULE_LICENSE("GPL"); 736 MODULE_AUTHOR("Alexey Korolev <akorolev@infradead.org>"); 737 MODULE_DESCRIPTION("MTD driver for LPDDR flash chips"); 738