diff options
-rw-r--r-- | drivers/mtd/devices/st_spi_fsm.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index b4afee0e0e33..b1a65c1359d5 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c | |||
@@ -238,6 +238,9 @@ | |||
238 | #define FLASH_CMD_READ4_1_1_4 0x6c | 238 | #define FLASH_CMD_READ4_1_1_4 0x6c |
239 | #define FLASH_CMD_READ4_1_4_4 0xec | 239 | #define FLASH_CMD_READ4_1_4_4 0xec |
240 | 240 | ||
241 | #define FLASH_PAGESIZE 256 /* In Bytes */ | ||
242 | #define FLASH_PAGESIZE_32 (FLASH_PAGESIZE / 4) /* In uint32_t */ | ||
243 | |||
241 | /* | 244 | /* |
242 | * Flags to tweak operation of default read/write/erase routines | 245 | * Flags to tweak operation of default read/write/erase routines |
243 | */ | 246 | */ |
@@ -942,6 +945,99 @@ static int stfsm_n25q_config(struct stfsm *fsm) | |||
942 | return 0; | 945 | return 0; |
943 | } | 946 | } |
944 | 947 | ||
948 | static int stfsm_read(struct stfsm *fsm, uint8_t *buf, uint32_t size, | ||
949 | uint32_t offset) | ||
950 | { | ||
951 | struct stfsm_seq *seq = &stfsm_seq_read; | ||
952 | uint32_t data_pads; | ||
953 | uint32_t read_mask; | ||
954 | uint32_t size_ub; | ||
955 | uint32_t size_lb; | ||
956 | uint32_t size_mop; | ||
957 | uint32_t tmp[4]; | ||
958 | uint32_t page_buf[FLASH_PAGESIZE_32]; | ||
959 | uint8_t *p; | ||
960 | |||
961 | dev_dbg(fsm->dev, "reading %d bytes from 0x%08x\n", size, offset); | ||
962 | |||
963 | /* Enter 32-bit address mode, if required */ | ||
964 | if (fsm->configuration & CFG_READ_TOGGLE_32BIT_ADDR) | ||
965 | stfsm_enter_32bit_addr(fsm, 1); | ||
966 | |||
967 | /* Must read in multiples of 32 cycles (or 32*pads/8 Bytes) */ | ||
968 | data_pads = ((seq->seq_cfg >> 16) & 0x3) + 1; | ||
969 | read_mask = (data_pads << 2) - 1; | ||
970 | |||
971 | /* Handle non-aligned buf */ | ||
972 | p = ((uint32_t)buf & 0x3) ? (uint8_t *)page_buf : buf; | ||
973 | |||
974 | /* Handle non-aligned size */ | ||
975 | size_ub = (size + read_mask) & ~read_mask; | ||
976 | size_lb = size & ~read_mask; | ||
977 | size_mop = size & read_mask; | ||
978 | |||
979 | seq->data_size = TRANSFER_SIZE(size_ub); | ||
980 | seq->addr1 = (offset >> 16) & 0xffff; | ||
981 | seq->addr2 = offset & 0xffff; | ||
982 | |||
983 | stfsm_load_seq(fsm, seq); | ||
984 | |||
985 | if (size_lb) | ||
986 | stfsm_read_fifo(fsm, (uint32_t *)p, size_lb); | ||
987 | |||
988 | if (size_mop) { | ||
989 | stfsm_read_fifo(fsm, tmp, read_mask + 1); | ||
990 | memcpy(p + size_lb, &tmp, size_mop); | ||
991 | } | ||
992 | |||
993 | /* Handle non-aligned buf */ | ||
994 | if ((uint32_t)buf & 0x3) | ||
995 | memcpy(buf, page_buf, size); | ||
996 | |||
997 | /* Wait for sequence to finish */ | ||
998 | stfsm_wait_seq(fsm); | ||
999 | |||
1000 | stfsm_clear_fifo(fsm); | ||
1001 | |||
1002 | /* Exit 32-bit address mode, if required */ | ||
1003 | if (fsm->configuration & CFG_READ_TOGGLE_32BIT_ADDR) | ||
1004 | stfsm_enter_32bit_addr(fsm, 0); | ||
1005 | |||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | /* | ||
1010 | * Read an address range from the flash chip. The address range | ||
1011 | * may be any size provided it is within the physical boundaries. | ||
1012 | */ | ||
1013 | static int stfsm_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
1014 | size_t *retlen, u_char *buf) | ||
1015 | { | ||
1016 | struct stfsm *fsm = dev_get_drvdata(mtd->dev.parent); | ||
1017 | uint32_t bytes; | ||
1018 | |||
1019 | dev_dbg(fsm->dev, "%s from 0x%08x, len %zd\n", | ||
1020 | __func__, (u32)from, len); | ||
1021 | |||
1022 | mutex_lock(&fsm->lock); | ||
1023 | |||
1024 | while (len > 0) { | ||
1025 | bytes = min_t(size_t, len, FLASH_PAGESIZE); | ||
1026 | |||
1027 | stfsm_read(fsm, buf, bytes, from); | ||
1028 | |||
1029 | buf += bytes; | ||
1030 | from += bytes; | ||
1031 | len -= bytes; | ||
1032 | |||
1033 | *retlen += bytes; | ||
1034 | } | ||
1035 | |||
1036 | mutex_unlock(&fsm->lock); | ||
1037 | |||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
945 | static void stfsm_read_jedec(struct stfsm *fsm, uint8_t *const jedec) | 1041 | static void stfsm_read_jedec(struct stfsm *fsm, uint8_t *const jedec) |
946 | { | 1042 | { |
947 | const struct stfsm_seq *seq = &stfsm_seq_read_jedec; | 1043 | const struct stfsm_seq *seq = &stfsm_seq_read_jedec; |
@@ -1197,6 +1293,8 @@ static int stfsm_probe(struct platform_device *pdev) | |||
1197 | fsm->mtd.size = info->sector_size * info->n_sectors; | 1293 | fsm->mtd.size = info->sector_size * info->n_sectors; |
1198 | fsm->mtd.erasesize = info->sector_size; | 1294 | fsm->mtd.erasesize = info->sector_size; |
1199 | 1295 | ||
1296 | fsm->mtd._read = stfsm_mtd_read; | ||
1297 | |||
1200 | dev_err(&pdev->dev, | 1298 | dev_err(&pdev->dev, |
1201 | "Found serial flash device: %s\n" | 1299 | "Found serial flash device: %s\n" |
1202 | " size = %llx (%lldMiB) erasesize = 0x%08x (%uKiB)\n", | 1300 | " size = %llx (%lldMiB) erasesize = 0x%08x (%uKiB)\n", |