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