[PATCH linux dev-4.7 6/8] mtd: spi-nor: aspeed: prepare for fast read
Cédric Le Goater
clg at kaod.org
Sat Nov 5 04:00:45 AEDT 2016
Include dummy cycle in the control register value which will be
required for fast read.
Signed-off-by: Cédric Le Goater <clg at kaod.org>
---
drivers/mtd/spi-nor/aspeed-smc.c | 41 +++++++++++++++++++++++++++++++++++-----
1 file changed, 36 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c
index 73adf409ac34..444af3aff8b5 100644
--- a/drivers/mtd/spi-nor/aspeed-smc.c
+++ b/drivers/mtd/spi-nor/aspeed-smc.c
@@ -295,7 +295,7 @@ struct aspeed_smc_controller {
#define CONTROL_SPI_COMMAND_SHIFT 16
#define CONTROL_SPI_DUMMY_CYCLE_COMMAND_OUTPUT BIT(15)
#define CONTROL_SPI_IO_DUMMY_CYCLES_HI BIT(14)
-#define CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT (14 - 2)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT 14
#define CONTROL_SPI_IO_ADDRESS_4B BIT(13) /* AST2400 SPI */
#define CONTROL_SPI_CLK_DIV4 BIT(13) /* others */
#define CONTROL_SPI_RW_MERGE BIT(12)
@@ -304,6 +304,10 @@ struct aspeed_smc_controller {
CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT)
#define CONTROL_SPI_IO_DUMMY_CYCLES_MASK (CONTROL_SPI_IO_DUMMY_CYCLES_HI | \
CONTROL_SPI_IO_DUMMY_CYCLES_LO)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_SET(dummy) \
+ (((((dummy) >> 2) & 0x1) << CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT) | \
+ (((dummy) & 0x3) << CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT))
+
#define CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT 8
#define CONTROL_SPI_CLOCK_FREQ_SEL_MASK GENMASK(11, \
CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT)
@@ -857,11 +861,17 @@ static int aspeed_smc_chip_setup_init(struct aspeed_smc_chip *chip,
return 0;
}
-static void aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip)
+static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip)
{
+ struct aspeed_smc_controller *controller = chip->controller;
+ u32 cmd;
+
if (chip->nor.mtd.size > SZ_16M)
aspeed_smc_chip_set_4b(chip);
+ /*
+ * base mode has not been optimized yet. use it for writes.
+ */
chip->ctl_val[smc_write] = chip->ctl_val[smc_base] |
spi_control_fill_opcode(chip->nor.program_opcode) |
CONTROL_SPI_COMMAND_MODE_WRITE;
@@ -871,12 +881,29 @@ static void aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip)
/*
* XXX TODO
- * Enable fast read mode as required here.
* Adjust clocks if fast read and write are supported.
* Interpret spi-nor flags to adjust controller settings.
* Check if resource size big enough for detected chip and
* add support assisted (normal or fast-) read and dma.
*/
+ switch (chip->nor.flash_read) {
+ case SPI_NOR_NORMAL:
+ cmd = CONTROL_SPI_COMMAND_MODE_NORMAL;
+ break;
+ case SPI_NOR_FAST:
+ cmd = CONTROL_SPI_COMMAND_MODE_FREAD;
+ break;
+ default:
+ dev_err(chip->nor.dev, "unsupported SPI read mode\n");
+ return -EINVAL;
+ }
+
+ chip->ctl_val[smc_read] |= cmd |
+ CONTROL_SPI_IO_DUMMY_CYCLES_SET(chip->nor.read_dummy / 8);
+
+ dev_dbg(controller->dev, "base control register: %08x\n",
+ chip->ctl_val[smc_read]);
+ return 0;
}
static int aspeed_smc_probe(struct platform_device *pdev)
@@ -972,7 +999,9 @@ static int aspeed_smc_probe(struct platform_device *pdev)
chip->nor.read_reg = aspeed_smc_read_reg;
chip->nor.write_reg = aspeed_smc_write_reg;
- aspeed_smc_chip_setup_init(chip, r);
+ err = aspeed_smc_chip_setup_init(chip, r);
+ if (err)
+ continue;
/*
* XXX Add support for SPI_NOR_QUAD and SPI_NOR_DUAL attach
@@ -982,7 +1011,9 @@ static int aspeed_smc_probe(struct platform_device *pdev)
if (err)
continue;
- aspeed_smc_chip_setup_finish(chip);
+ err = aspeed_smc_chip_setup_finish(chip);
+ if (err)
+ continue;
err = mtd_device_register(&chip->nor.mtd, NULL, 0);
if (err)
--
2.7.4
More information about the openbmc
mailing list