aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBin Meng <bmeng.cn@gmail.com>2017-09-11 05:42:00 -0400
committerCyrille Pitchen <cyrille.pitchen@wedev4u.fr>2017-10-11 03:57:50 -0400
commit3163d125b7b1f9c6844fc3448f8080ad268a8f63 (patch)
tree2a29af22767ab6b8e653e319040b24ca8b8c8032
parent2421f1ccbd4e7c8fc10c5f6a6e9cc403ace4e449 (diff)
spi-nor: intel-spi: Fall back to use SW sequencer to erase
According to the datasheet, the HW sequencer has a predefined list of opcodes, with only the erase opcode being programmable in LVSCC and UVSCC registers. If these registers don't contain a valid erase opcode (eg: BIOS does not program it), erase cannot be done using the HW sequencer, even though the erase operation does not report any error, the flash remains not erased. If such register setting is detected, let's fall back to use the SW sequencer to erase instead. Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
-rw-r--r--drivers/mtd/spi-nor/intel-spi.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c
index 5e7a38994e87..ef034d898a23 100644
--- a/drivers/mtd/spi-nor/intel-spi.c
+++ b/drivers/mtd/spi-nor/intel-spi.c
@@ -111,6 +111,13 @@
111#define BXT_FREG_NUM 12 111#define BXT_FREG_NUM 12
112#define BXT_PR_NUM 6 112#define BXT_PR_NUM 6
113 113
114#define LVSCC 0xc4
115#define UVSCC 0xc8
116#define ERASE_OPCODE_SHIFT 8
117#define ERASE_OPCODE_MASK (0xff << ERASE_OPCODE_SHIFT)
118#define ERASE_64K_OPCODE_SHIFT 16
119#define ERASE_64K_OPCODE_MASK (0xff << ERASE_OPCODE_SHIFT)
120
114#define INTEL_SPI_TIMEOUT 5000 /* ms */ 121#define INTEL_SPI_TIMEOUT 5000 /* ms */
115#define INTEL_SPI_FIFO_SZ 64 122#define INTEL_SPI_FIFO_SZ 64
116 123
@@ -127,6 +134,7 @@
127 * @writeable: Is the chip writeable 134 * @writeable: Is the chip writeable
128 * @locked: Is SPI setting locked 135 * @locked: Is SPI setting locked
129 * @swseq_reg: Use SW sequencer in register reads/writes 136 * @swseq_reg: Use SW sequencer in register reads/writes
137 * @swseq_erase: Use SW sequencer in erase operation
130 * @erase_64k: 64k erase supported 138 * @erase_64k: 64k erase supported
131 * @opcodes: Opcodes which are supported. This are programmed by BIOS 139 * @opcodes: Opcodes which are supported. This are programmed by BIOS
132 * before it locks down the controller. 140 * before it locks down the controller.
@@ -144,6 +152,7 @@ struct intel_spi {
144 bool writeable; 152 bool writeable;
145 bool locked; 153 bool locked;
146 bool swseq_reg; 154 bool swseq_reg;
155 bool swseq_erase;
147 bool erase_64k; 156 bool erase_64k;
148 u8 opcodes[8]; 157 u8 opcodes[8];
149 u8 preopcodes[2]; 158 u8 preopcodes[2];
@@ -191,6 +200,9 @@ static void intel_spi_dump_regs(struct intel_spi *ispi)
191 if (ispi->info->type == INTEL_SPI_BYT) 200 if (ispi->info->type == INTEL_SPI_BYT)
192 dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR)); 201 dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR));
193 202
203 dev_dbg(ispi->dev, "LVSCC=0x%08x\n", readl(ispi->base + LVSCC));
204 dev_dbg(ispi->dev, "UVSCC=0x%08x\n", readl(ispi->base + UVSCC));
205
194 dev_dbg(ispi->dev, "Protected regions:\n"); 206 dev_dbg(ispi->dev, "Protected regions:\n");
195 for (i = 0; i < ispi->pr_num; i++) { 207 for (i = 0; i < ispi->pr_num; i++) {
196 u32 base, limit; 208 u32 base, limit;
@@ -225,6 +237,8 @@ static void intel_spi_dump_regs(struct intel_spi *ispi)
225 237
226 dev_dbg(ispi->dev, "Using %cW sequencer for register access\n", 238 dev_dbg(ispi->dev, "Using %cW sequencer for register access\n",
227 ispi->swseq_reg ? 'S' : 'H'); 239 ispi->swseq_reg ? 'S' : 'H');
240 dev_dbg(ispi->dev, "Using %cW sequencer for erase operation\n",
241 ispi->swseq_erase ? 'S' : 'H');
228} 242}
229 243
230/* Reads max INTEL_SPI_FIFO_SZ bytes from the device fifo */ 244/* Reads max INTEL_SPI_FIFO_SZ bytes from the device fifo */
@@ -288,7 +302,7 @@ static int intel_spi_wait_sw_busy(struct intel_spi *ispi)
288 302
289static int intel_spi_init(struct intel_spi *ispi) 303static int intel_spi_init(struct intel_spi *ispi)
290{ 304{
291 u32 opmenu0, opmenu1, val; 305 u32 opmenu0, opmenu1, lvscc, uvscc, val;
292 int i; 306 int i;
293 307
294 switch (ispi->info->type) { 308 switch (ispi->info->type) {
@@ -339,6 +353,24 @@ static int intel_spi_init(struct intel_spi *ispi)
339 writel(val, ispi->base + HSFSTS_CTL); 353 writel(val, ispi->base + HSFSTS_CTL);
340 354
341 /* 355 /*
356 * Determine whether erase operation should use HW or SW sequencer.
357 *
358 * The HW sequencer has a predefined list of opcodes, with only the
359 * erase opcode being programmable in LVSCC and UVSCC registers.
360 * If these registers don't contain a valid erase opcode, erase
361 * cannot be done using HW sequencer.
362 */
363 lvscc = readl(ispi->base + LVSCC);
364 uvscc = readl(ispi->base + UVSCC);
365 if (!(lvscc & ERASE_OPCODE_MASK) || !(uvscc & ERASE_OPCODE_MASK))
366 ispi->swseq_erase = true;
367 /* SPI controller on Intel BXT supports 64K erase opcode */
368 if (ispi->info->type == INTEL_SPI_BXT && !ispi->swseq_erase)
369 if (!(lvscc & ERASE_64K_OPCODE_MASK) ||
370 !(uvscc & ERASE_64K_OPCODE_MASK))
371 ispi->erase_64k = false;
372
373 /*
342 * Some controllers can only do basic operations using hardware 374 * Some controllers can only do basic operations using hardware
343 * sequencer. All other operations are supposed to be carried out 375 * sequencer. All other operations are supposed to be carried out
344 * using software sequencer. 376 * using software sequencer.
@@ -665,6 +697,22 @@ static int intel_spi_erase(struct spi_nor *nor, loff_t offs)
665 erase_size = SZ_4K; 697 erase_size = SZ_4K;
666 } 698 }
667 699
700 if (ispi->swseq_erase) {
701 while (len > 0) {
702 writel(offs, ispi->base + FADDR);
703
704 ret = intel_spi_sw_cycle(ispi, nor->erase_opcode,
705 0, OPTYPE_WRITE_WITH_ADDR);
706 if (ret)
707 return ret;
708
709 offs += erase_size;
710 len -= erase_size;
711 }
712
713 return 0;
714 }
715
668 while (len > 0) { 716 while (len > 0) {
669 writel(offs, ispi->base + FADDR); 717 writel(offs, ispi->base + FADDR);
670 718