29 #include <linux/slab.h>
30 #include <linux/module.h>
32 static int lpddr_read(
struct mtd_info *mtd, loff_t adr,
size_t len,
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);
41 static int lpddr_point(
struct mtd_info *mtd, loff_t adr,
size_t len,
43 static int lpddr_unpoint(
struct mtd_info *mtd, loff_t adr,
size_t len);
66 mtd->
_read = lpddr_read;
71 mtd->
_write = lpddr_write_buffers;
73 mtd->
_lock = lpddr_lock;
79 mtd->
size = 1 << lpddr->
qinfo->DevSizeShift;
91 chip = &lpddr->
chips[0];
93 for (i = 0; i < numchips; i++) {
96 for (j = 0; j < lpddr->
qinfo->HWPartsNum; j++) {
100 chip->
priv = &shared[
i];
114 unsigned int chip_op_time)
116 unsigned int timeo, reset_timeo, sleep_time;
122 timeo = chip_op_time * 8;
126 sleep_time = chip_op_time / 2;
134 map->
name, chip_state);
141 if (sleep_time >= 1000000/
HZ) {
149 sleep_time = 1000000/
HZ;
157 while (chip->
state != chip_state) {
179 print_drs_error(dsr);
216 if (contender && contender != chip) {
231 ret = chip_ready(map, contender, mode);
247 put_chip(map, contender);
275 ret = chip_ready(map, chip, mode);
282 static int chip_ready(
struct map_info *map,
struct flchip *chip,
int mode)
292 switch (chip->
state) {
298 if (!lpddr->
qinfo->SuspEraseSupp ||
306 ret = wait_for_ready(map, chip, 0);
312 "State may be wrong \n", map->
name);
350 put_chip(map, loaner);
392 unsigned long adr,
const struct kvec **pvec,
393 unsigned long *pvec_seek,
int len)
397 int ret, wbufsize, word_gap, words;
398 const struct kvec *vec;
399 unsigned long vec_seek;
400 unsigned long prog_buf_ofs;
402 wbufsize = 1 << lpddr->
qinfo->BufSizeShift;
411 word_gap = (-adr & (map_bankwidth(map)-1));
412 words = (len - word_gap + map_bankwidth(map) - 1) / map_bankwidth(map);
416 word_gap = map_bankwidth(map) - word_gap;
418 datum = map_word_ff(map);
425 vec_seek = *pvec_seek;
427 int n = map_bankwidth(map) - word_gap;
429 if (n > vec->
iov_len - vec_seek)
434 if (!word_gap && (len < map_bankwidth(map)))
435 datum = map_word_ff(map);
437 datum = map_word_load_partial(map, datum,
438 vec->
iov_base + vec_seek, word_gap, n);
442 if (!len || word_gap == map_bankwidth(map)) {
444 prog_buf_ofs += map_bankwidth(map);
449 if (vec_seek == vec->
iov_len) {
455 *pvec_seek = vec_seek;
460 ret = wait_for_ready(map, chip, (1<<lpddr->
qinfo->ProgBufferTime));
463 map->
name, ret, adr);
467 out: put_chip(map, chip);
488 ret = wait_for_ready(map, chip, (1<<lpddr->
qinfo->BlockEraseTime)*1000);
491 map->
name, ret, adr);
494 out: put_chip(map, chip);
499 static int lpddr_read(
struct mtd_info *mtd, loff_t adr,
size_t len,
523 static int lpddr_point(
struct mtd_info *mtd, loff_t adr,
size_t len,
529 unsigned long ofs, last_end = 0;
537 ofs = adr - (chipnum << lpddr->
chipshift);
538 *mtdbuf = (
void *)map->
virt + chip->
start + ofs;
541 unsigned long thislen;
548 last_end = chip->
start;
549 else if (chip->
start != last_end)
571 chip = &lpddr->
chips[chipnum];
576 static int lpddr_unpoint (
struct mtd_info *mtd, loff_t adr,
size_t len)
584 ofs = adr - (chipnum << lpddr->
chipshift);
587 unsigned long thislen;
590 chip = &lpddr->
chips[chipnum];
606 "pointed region\n", map->
name);
621 static int lpddr_write_buffers(
struct mtd_info *mtd, loff_t to,
size_t len,
622 size_t *retlen,
const u_char *buf)
629 return lpddr_writev(mtd, &vec, 1, to, retlen);
633 static int lpddr_writev(
struct mtd_info *mtd,
const struct kvec *vecs,
634 unsigned long count, loff_t to,
size_t *retlen)
640 unsigned long ofs, vec_seek,
i;
641 int wbufsize = 1 << lpddr->
qinfo->BufSizeShift;
644 for (i = 0; i <
count; i++)
645 len += vecs[i].iov_len;
657 int size = wbufsize - (ofs & (wbufsize-1));
663 ofs, &vecs, &vec_seek,
size);
682 unsigned long ofs, len;
686 int size = 1 << lpddr->
qinfo->UniformBlockSizeShift;
704 #define DO_XXLOCK_LOCK 1
705 #define DO_XXLOCK_UNLOCK 2
730 ret = wait_for_ready(map, chip, 1);
736 out: put_chip(map, chip);
767 ret = wait_for_ready(map, chip, (1<<lpddr->
qinfo->SingleWordProgTime));
770 map->
name, adr, curval);
774 out: put_chip(map, chip);