diff options
-rw-r--r-- | drivers/mtd/devices/st_spi_fsm.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index 58b8761dc30e..99e08b01a32d 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c | |||
@@ -238,8 +238,18 @@ | |||
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 | /* Status register */ | ||
242 | #define FLASH_STATUS_BUSY 0x01 | ||
243 | #define FLASH_STATUS_WEL 0x02 | ||
244 | #define FLASH_STATUS_BP0 0x04 | ||
245 | #define FLASH_STATUS_BP1 0x08 | ||
246 | #define FLASH_STATUS_BP2 0x10 | ||
247 | #define FLASH_STATUS_SRWP0 0x80 | ||
248 | #define FLASH_STATUS_TIMEOUT 0xff | ||
249 | |||
241 | #define FLASH_PAGESIZE 256 /* In Bytes */ | 250 | #define FLASH_PAGESIZE 256 /* In Bytes */ |
242 | #define FLASH_PAGESIZE_32 (FLASH_PAGESIZE / 4) /* In uint32_t */ | 251 | #define FLASH_PAGESIZE_32 (FLASH_PAGESIZE / 4) /* In uint32_t */ |
252 | #define FLASH_MAX_BUSY_WAIT (300 * HZ) /* Maximum 'CHIPERASE' time */ | ||
243 | 253 | ||
244 | /* | 254 | /* |
245 | * Flags to tweak operation of default read/write/erase routines | 255 | * Flags to tweak operation of default read/write/erase routines |
@@ -519,6 +529,22 @@ static struct stfsm_seq stfsm_seq_read_jedec = { | |||
519 | SEQ_CFG_STARTSEQ), | 529 | SEQ_CFG_STARTSEQ), |
520 | }; | 530 | }; |
521 | 531 | ||
532 | static struct stfsm_seq stfsm_seq_read_status_fifo = { | ||
533 | .data_size = TRANSFER_SIZE(4), | ||
534 | .seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
535 | SEQ_OPC_CYCLES(8) | | ||
536 | SEQ_OPC_OPCODE(FLASH_CMD_RDSR)), | ||
537 | .seq = { | ||
538 | STFSM_INST_CMD1, | ||
539 | STFSM_INST_DATA_READ, | ||
540 | STFSM_INST_STOP, | ||
541 | }, | ||
542 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
543 | SEQ_CFG_READNOTWRITE | | ||
544 | SEQ_CFG_CSDEASSERT | | ||
545 | SEQ_CFG_STARTSEQ), | ||
546 | }; | ||
547 | |||
522 | static struct stfsm_seq stfsm_seq_erase_sector = { | 548 | static struct stfsm_seq stfsm_seq_erase_sector = { |
523 | /* 'addr_cfg' configured during initialisation */ | 549 | /* 'addr_cfg' configured during initialisation */ |
524 | .seq_opc = { | 550 | .seq_opc = { |
@@ -699,6 +725,53 @@ static int stfsm_enter_32bit_addr(struct stfsm *fsm, int enter) | |||
699 | return 0; | 725 | return 0; |
700 | } | 726 | } |
701 | 727 | ||
728 | static uint8_t stfsm_wait_busy(struct stfsm *fsm) | ||
729 | { | ||
730 | struct stfsm_seq *seq = &stfsm_seq_read_status_fifo; | ||
731 | unsigned long deadline; | ||
732 | uint32_t status; | ||
733 | int timeout = 0; | ||
734 | |||
735 | /* Use RDRS1 */ | ||
736 | seq->seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
737 | SEQ_OPC_CYCLES(8) | | ||
738 | SEQ_OPC_OPCODE(FLASH_CMD_RDSR)); | ||
739 | |||
740 | /* Load read_status sequence */ | ||
741 | stfsm_load_seq(fsm, seq); | ||
742 | |||
743 | /* | ||
744 | * Repeat until busy bit is deasserted, or timeout, or error (S25FLxxxS) | ||
745 | */ | ||
746 | deadline = jiffies + FLASH_MAX_BUSY_WAIT; | ||
747 | while (!timeout) { | ||
748 | cond_resched(); | ||
749 | |||
750 | if (time_after_eq(jiffies, deadline)) | ||
751 | timeout = 1; | ||
752 | |||
753 | stfsm_wait_seq(fsm); | ||
754 | |||
755 | stfsm_read_fifo(fsm, &status, 4); | ||
756 | |||
757 | if ((status & FLASH_STATUS_BUSY) == 0) | ||
758 | return 0; | ||
759 | |||
760 | if ((fsm->configuration & CFG_S25FL_CHECK_ERROR_FLAGS) && | ||
761 | ((status & S25FL_STATUS_P_ERR) || | ||
762 | (status & S25FL_STATUS_E_ERR))) | ||
763 | return (uint8_t)(status & 0xff); | ||
764 | |||
765 | if (!timeout) | ||
766 | /* Restart */ | ||
767 | writel(seq->seq_cfg, fsm->base + SPI_FAST_SEQ_CFG); | ||
768 | } | ||
769 | |||
770 | dev_err(fsm->dev, "timeout on wait_busy\n"); | ||
771 | |||
772 | return FLASH_STATUS_TIMEOUT; | ||
773 | } | ||
774 | |||
702 | static int stfsm_wrvcr(struct stfsm *fsm, uint8_t data) | 775 | static int stfsm_wrvcr(struct stfsm *fsm, uint8_t data) |
703 | { | 776 | { |
704 | struct stfsm_seq *seq = &stfsm_seq_wrvcr; | 777 | struct stfsm_seq *seq = &stfsm_seq_wrvcr; |
@@ -1020,6 +1093,98 @@ static int stfsm_read(struct stfsm *fsm, uint8_t *buf, uint32_t size, | |||
1020 | return 0; | 1093 | return 0; |
1021 | } | 1094 | } |
1022 | 1095 | ||
1096 | static int stfsm_write(struct stfsm *fsm, const uint8_t *const buf, | ||
1097 | const uint32_t size, const uint32_t offset) | ||
1098 | { | ||
1099 | struct stfsm_seq *seq = &stfsm_seq_write; | ||
1100 | uint32_t data_pads; | ||
1101 | uint32_t write_mask; | ||
1102 | uint32_t size_ub; | ||
1103 | uint32_t size_lb; | ||
1104 | uint32_t size_mop; | ||
1105 | uint32_t tmp[4]; | ||
1106 | uint32_t page_buf[FLASH_PAGESIZE_32]; | ||
1107 | uint8_t *t = (uint8_t *)&tmp; | ||
1108 | const uint8_t *p; | ||
1109 | int ret; | ||
1110 | int i; | ||
1111 | |||
1112 | dev_dbg(fsm->dev, "writing %d bytes to 0x%08x\n", size, offset); | ||
1113 | |||
1114 | /* Enter 32-bit address mode, if required */ | ||
1115 | if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR) | ||
1116 | stfsm_enter_32bit_addr(fsm, 1); | ||
1117 | |||
1118 | /* Must write in multiples of 32 cycles (or 32*pads/8 bytes) */ | ||
1119 | data_pads = ((seq->seq_cfg >> 16) & 0x3) + 1; | ||
1120 | write_mask = (data_pads << 2) - 1; | ||
1121 | |||
1122 | /* Handle non-aligned buf */ | ||
1123 | if ((uint32_t)buf & 0x3) { | ||
1124 | memcpy(page_buf, buf, size); | ||
1125 | p = (uint8_t *)page_buf; | ||
1126 | } else { | ||
1127 | p = buf; | ||
1128 | } | ||
1129 | |||
1130 | /* Handle non-aligned size */ | ||
1131 | size_ub = (size + write_mask) & ~write_mask; | ||
1132 | size_lb = size & ~write_mask; | ||
1133 | size_mop = size & write_mask; | ||
1134 | |||
1135 | seq->data_size = TRANSFER_SIZE(size_ub); | ||
1136 | seq->addr1 = (offset >> 16) & 0xffff; | ||
1137 | seq->addr2 = offset & 0xffff; | ||
1138 | |||
1139 | /* Need to set FIFO to write mode, before writing data to FIFO (see | ||
1140 | * GNBvb79594) | ||
1141 | */ | ||
1142 | writel(0x00040000, fsm->base + SPI_FAST_SEQ_CFG); | ||
1143 | |||
1144 | /* | ||
1145 | * Before writing data to the FIFO, apply a small delay to allow a | ||
1146 | * potential change of FIFO direction to complete. | ||
1147 | */ | ||
1148 | if (fsm->fifo_dir_delay == 0) | ||
1149 | readl(fsm->base + SPI_FAST_SEQ_CFG); | ||
1150 | else | ||
1151 | udelay(fsm->fifo_dir_delay); | ||
1152 | |||
1153 | |||
1154 | /* Write data to FIFO, before starting sequence (see GNBvd79593) */ | ||
1155 | if (size_lb) { | ||
1156 | stfsm_write_fifo(fsm, (uint32_t *)p, size_lb); | ||
1157 | p += size_lb; | ||
1158 | } | ||
1159 | |||
1160 | /* Handle non-aligned size */ | ||
1161 | if (size_mop) { | ||
1162 | memset(t, 0xff, write_mask + 1); /* fill with 0xff's */ | ||
1163 | for (i = 0; i < size_mop; i++) | ||
1164 | t[i] = *p++; | ||
1165 | |||
1166 | stfsm_write_fifo(fsm, tmp, write_mask + 1); | ||
1167 | } | ||
1168 | |||
1169 | /* Start sequence */ | ||
1170 | stfsm_load_seq(fsm, seq); | ||
1171 | |||
1172 | /* Wait for sequence to finish */ | ||
1173 | stfsm_wait_seq(fsm); | ||
1174 | |||
1175 | /* Wait for completion */ | ||
1176 | ret = stfsm_wait_busy(fsm); | ||
1177 | |||
1178 | /* Exit 32-bit address mode, if required */ | ||
1179 | if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR) { | ||
1180 | stfsm_enter_32bit_addr(fsm, 0); | ||
1181 | if (fsm->configuration & CFG_WRITE_EX_32BIT_ADDR_DELAY) | ||
1182 | udelay(1); | ||
1183 | } | ||
1184 | |||
1185 | return 0; | ||
1186 | } | ||
1187 | |||
1023 | /* | 1188 | /* |
1024 | * Read an address range from the flash chip. The address range | 1189 | * Read an address range from the flash chip. The address range |
1025 | * may be any size provided it is within the physical boundaries. | 1190 | * may be any size provided it is within the physical boundaries. |
@@ -1052,6 +1217,61 @@ static int stfsm_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
1052 | return 0; | 1217 | return 0; |
1053 | } | 1218 | } |
1054 | 1219 | ||
1220 | /* | ||
1221 | * Write an address range to the flash chip. Data must be written in | ||
1222 | * FLASH_PAGESIZE chunks. The address range may be any size provided | ||
1223 | * it is within the physical boundaries. | ||
1224 | */ | ||
1225 | static int stfsm_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
1226 | size_t *retlen, const u_char *buf) | ||
1227 | { | ||
1228 | struct stfsm *fsm = dev_get_drvdata(mtd->dev.parent); | ||
1229 | |||
1230 | u32 page_offs; | ||
1231 | u32 bytes; | ||
1232 | uint8_t *b = (uint8_t *)buf; | ||
1233 | int ret = 0; | ||
1234 | |||
1235 | dev_dbg(fsm->dev, "%s to 0x%08x, len %zd\n", __func__, (u32)to, len); | ||
1236 | |||
1237 | *retlen = 0; | ||
1238 | |||
1239 | if (!len) | ||
1240 | return 0; | ||
1241 | |||
1242 | if (to + len > mtd->size) | ||
1243 | return -EINVAL; | ||
1244 | |||
1245 | /* Offset within page */ | ||
1246 | page_offs = to % FLASH_PAGESIZE; | ||
1247 | |||
1248 | mutex_lock(&fsm->lock); | ||
1249 | |||
1250 | while (len) { | ||
1251 | /* Write up to page boundary */ | ||
1252 | bytes = min(FLASH_PAGESIZE - page_offs, len); | ||
1253 | |||
1254 | ret = stfsm_write(fsm, b, bytes, to); | ||
1255 | if (ret) | ||
1256 | goto out1; | ||
1257 | |||
1258 | b += bytes; | ||
1259 | len -= bytes; | ||
1260 | to += bytes; | ||
1261 | |||
1262 | /* We are now page-aligned */ | ||
1263 | page_offs = 0; | ||
1264 | |||
1265 | *retlen += bytes; | ||
1266 | |||
1267 | } | ||
1268 | |||
1269 | out1: | ||
1270 | mutex_unlock(&fsm->lock); | ||
1271 | |||
1272 | return ret; | ||
1273 | } | ||
1274 | |||
1055 | static void stfsm_read_jedec(struct stfsm *fsm, uint8_t *const jedec) | 1275 | static void stfsm_read_jedec(struct stfsm *fsm, uint8_t *const jedec) |
1056 | { | 1276 | { |
1057 | const struct stfsm_seq *seq = &stfsm_seq_read_jedec; | 1277 | const struct stfsm_seq *seq = &stfsm_seq_read_jedec; |
@@ -1308,6 +1528,7 @@ static int stfsm_probe(struct platform_device *pdev) | |||
1308 | fsm->mtd.erasesize = info->sector_size; | 1528 | fsm->mtd.erasesize = info->sector_size; |
1309 | 1529 | ||
1310 | fsm->mtd._read = stfsm_mtd_read; | 1530 | fsm->mtd._read = stfsm_mtd_read; |
1531 | fsm->mtd._write = stfsm_mtd_write; | ||
1311 | 1532 | ||
1312 | dev_err(&pdev->dev, | 1533 | dev_err(&pdev->dev, |
1313 | "Found serial flash device: %s\n" | 1534 | "Found serial flash device: %s\n" |