[PATCH v2 linux dev-4.7 6/7] mtd: spi-nor: aspeed: prepare for fast read

Cédric Le Goater clg at kaod.org
Wed Nov 9 19:15:42 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>
Reviewed-by: Joel Stanley <joel at jms.id.au>
---
 drivers/mtd/spi-nor/aspeed-smc.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c
index bbe505d5d8a3..231d4bda4e97 100644
--- a/drivers/mtd/spi-nor/aspeed-smc.c
+++ b/drivers/mtd/spi-nor/aspeed-smc.c
@@ -306,7 +306,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)
@@ -315,6 +315,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)
@@ -869,14 +873,18 @@ 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;
 	const struct aspeed_smc_info *info = controller->info;
+	u32 cmd;
 
 	if (chip->nor.addr_width == 4 && info->set_4b)
 		info->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;
@@ -886,12 +894,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)
@@ -987,7 +1012,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
@@ -997,7 +1024,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