summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/devices/st_spi_fsm.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c
index c902d5b..b4d2a18 100644
--- a/drivers/mtd/devices/st_spi_fsm.c
+++ b/drivers/mtd/devices/st_spi_fsm.c
@@ -312,6 +312,8 @@ struct flash_info {
int (*config)(struct stfsm *);
};
+static int stfsm_n25q_config(struct stfsm *fsm);
+
static struct flash_info flash_types[] = {
/*
* ST Microelectronics/Numonyx --
@@ -354,9 +356,10 @@ static struct flash_info flash_types[] = {
FLASH_FLAG_WRITE_1_2_2 | \
FLASH_FLAG_WRITE_1_1_4 | \
FLASH_FLAG_WRITE_1_4_4)
- { "n25q128", 0x20ba18, 0, 64 * 1024, 256, N25Q_FLAG, 108, NULL },
+ { "n25q128", 0x20ba18, 0, 64 * 1024, 256, N25Q_FLAG, 108,
+ stfsm_n25q_config },
{ "n25q256", 0x20ba19, 0, 64 * 1024, 512,
- N25Q_FLAG | FLASH_FLAG_32BIT_ADDR, 108, NULL },
+ N25Q_FLAG | FLASH_FLAG_32BIT_ADDR, 108, stfsm_n25q_config },
/*
* Spansion S25FLxxxP
@@ -493,6 +496,8 @@ static struct seq_rw_config n25q_read4_configs[] = {
{0x00, 0, 0, 0, 0, 0x00, 0, 0},
};
+static struct stfsm_seq stfsm_seq_read; /* Dynamically populated */
+static struct stfsm_seq stfsm_seq_write; /* Dynamically populated */
static struct stfsm_seq stfsm_seq_en_32bit_addr;/* Dynamically populated */
static struct stfsm_seq stfsm_seq_read_jedec = {
@@ -840,6 +845,71 @@ static int stfsm_search_prepare_rw_seq(struct stfsm *fsm,
return 0;
}
+static int stfsm_n25q_config(struct stfsm *fsm)
+{
+ uint32_t flags = fsm->info->flags;
+ uint8_t vcr;
+ int ret = 0;
+ bool soc_reset;
+
+ /* Configure 'READ' sequence */
+ if (flags & FLASH_FLAG_32BIT_ADDR)
+ ret = stfsm_search_prepare_rw_seq(fsm, &stfsm_seq_read,
+ n25q_read4_configs);
+ else
+ ret = stfsm_search_prepare_rw_seq(fsm, &stfsm_seq_read,
+ n25q_read3_configs);
+ if (ret) {
+ dev_err(fsm->dev,
+ "failed to prepare READ sequence with flags [0x%08x]\n",
+ flags);
+ return ret;
+ }
+
+ /* Configure 'WRITE' sequence (default configs) */
+ ret = stfsm_search_prepare_rw_seq(fsm, &stfsm_seq_write,
+ default_write_configs);
+ if (ret) {
+ dev_err(fsm->dev,
+ "preparing WRITE sequence using flags [0x%08x] failed\n",
+ flags);
+ return ret;
+ }
+
+ /* * Configure 'ERASE_SECTOR' sequence */
+ stfsm_prepare_erasesec_seq(fsm, &stfsm_seq_erase_sector);
+
+ /* Configure 32-bit address support */
+ if (flags & FLASH_FLAG_32BIT_ADDR) {
+ stfsm_n25q_en_32bit_addr_seq(&stfsm_seq_en_32bit_addr);
+
+ soc_reset = stfsm_can_handle_soc_reset(fsm);
+ if (soc_reset || !fsm->booted_from_spi) {
+ /*
+ * If we can handle SoC resets, we enable 32-bit
+ * address mode pervasively
+ */
+ stfsm_enter_32bit_addr(fsm, 1);
+ } else {
+ /*
+ * If not, enable/disable for WRITE and ERASE
+ * operations (READ uses special commands)
+ */
+ fsm->configuration = (CFG_WRITE_TOGGLE_32BIT_ADDR |
+ CFG_ERASESEC_TOGGLE_32BIT_ADDR);
+ }
+ }
+
+ /*
+ * Configure device to use 8 dummy cycles
+ */
+ vcr = (N25Q_VCR_DUMMY_CYCLES(8) | N25Q_VCR_XIP_DISABLED |
+ N25Q_VCR_WRAP_CONT);
+ stfsm_wrvcr(fsm, vcr);
+
+ return 0;
+}
+
static void stfsm_read_jedec(struct stfsm *fsm, uint8_t *const jedec)
{
const struct stfsm_seq *seq = &stfsm_seq_read_jedec;
@@ -1073,6 +1143,16 @@ static int stfsm_probe(struct platform_device *pdev)
if (info->sector_size * info->n_sectors > 0x1000000)
info->flags |= FLASH_FLAG_32BIT_ADDR;
+ /*
+ * Configure READ/WRITE/ERASE sequences according to platform and
+ * device flags.
+ */
+ if (info->config) {
+ ret = info->config(fsm);
+ if (ret)
+ return ret;
+ }
+
fsm->mtd.dev.parent = &pdev->dev;
fsm->mtd.type = MTD_NORFLASH;
fsm->mtd.writesize = 4;
OpenPOWER on IntegriCloud