[U-Boot] [PATCH] tools: mxsboot: Implement SPI SMEM block support

Marek Vasut marex at denx.de
Thu Feb 6 04:43:34 CET 2014


This patch adds support for augmenting the BootStream with the
SMEM block. For further details on the SMEM block, please refer
to i.MX28 datasheet section 12.10 .

NOTE: It is absolutely optional to augment BootStream with SMEM
      block. The SMEM block is only useful if you need to tweak
      SPI NOR clockspeed or place the u-boot.sb elsewhere than
      at block 1 of the SPI NOR (SMEM block resides in block 0).
      The i.MX28 will boot BootStream image placed at block 0 in
      SPI NOR directly.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Stefano Babic <sbabic at denx.de>
---
 tools/mxsboot.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 130 insertions(+), 3 deletions(-)

diff --git a/tools/mxsboot.c b/tools/mxsboot.c
index 90b2173..1575e8d 100644
--- a/tools/mxsboot.c
+++ b/tools/mxsboot.c
@@ -38,6 +38,14 @@ static uint32_t nand_erasesize = 128 * 1024;
 static uint32_t sd_sector = 2048;
 
 /*
+ * Layout for the SPI configuration block with the default settings
+ * in it. This is what the BootROM uses.
+ */
+static uint32_t spi_sector_size = 128;
+static uint32_t spi_image_offset = 64 * 1024;	/* Block 1 */
+static uint32_t spi_clock_idx = 8;		/* BootROM's default clock */
+
+/*
  * Each of the U-Boot bootstreams is at maximum 1MB big.
  *
  * TWEAK this if, for some wild reason, you need to boot bigger image.
@@ -125,6 +133,49 @@ struct mx28_sd_config_block {
 	struct mx28_sd_drive_info	drv_info[1];
 };
 
+#define SSP_CLOCK_CONFIG_CLKSEL(n)	((n) << 0)
+#define SSP_CLOCK_CONFIG_IO_FRAC(n)	((n) << 1)
+#define SSP_CLOCK_CONFIG_SSP_FRAC(n)	((n) << 7)
+#define SSP_CLOCK_CONFIG_SSP_DIV(n)	((n) << 16)
+#define SSP_CLOCK_CONFIG_SSP_RATE(n)	((n) << 24)
+#define SSP_CLOCK_CONFIG(clksel, iofrac, sspfrac, sspdiv, ssprate)	\
+	SSP_CLOCK_CONFIG_CLKSEL(clksel) |				\
+	SSP_CLOCK_CONFIG_IO_FRAC(iofrac) |				\
+	SSP_CLOCK_CONFIG_SSP_FRAC(sspfrac) | 				\
+	SSP_CLOCK_CONFIG_SSP_DIV(sspdiv) |				\
+	SSP_CLOCK_CONFIG_SSP_RATE(ssprate)
+
+#define SSP_BOOT_FLAG_DISABLE_FASTREAD	(1 << 0)
+
+struct mx28_spi_config_block {
+	uint32_t			signature;
+	uint32_t			boot_start_addr;
+	uint32_t			sector_size;
+	uint32_t			flags;
+	uint32_t			clock_config_size;
+	uint32_t			clock_config;
+};
+
+/* This is aligned with Table 12-27 in i.MX28 reference manual. */
+static const uint32_t mx28_spi_clock_config[] = {
+	0x00000000,				/* 0 ... invalid. */
+	SSP_CLOCK_CONFIG(1, 0, 0, 100, 0),	/* 1 ... 0.24 MHz */
+	SSP_CLOCK_CONFIG(1, 0, 0, 24, 0),	/* 2 ... 1 MHz */
+	SSP_CLOCK_CONFIG(1, 0, 0, 12, 0),	/* 3 ... 2 MHz */
+	SSP_CLOCK_CONFIG(1, 0, 0, 6, 0),	/* 4 ... 4 MHz */
+	SSP_CLOCK_CONFIG(1, 0, 0, 4, 0),	/* 5 ... 6 MHz */
+	SSP_CLOCK_CONFIG(0, 18, 6, 10, 0),	/* 6 ... 8 MHz */
+	SSP_CLOCK_CONFIG(0, 18, 6, 8, 0),	/* 7 ... 10 MHz */
+	SSP_CLOCK_CONFIG(1, 0, 0, 2, 0),	/* 8 ... 12 MHz */
+	SSP_CLOCK_CONFIG(0, 18, 5, 6, 0),	/* 9 ... 16 MHz */
+	SSP_CLOCK_CONFIG(0, 18, 6, 4, 0),	/* 10 .. 20 MHz */
+	SSP_CLOCK_CONFIG(0, 18, 8, 2, 0),	/* 11 .. 30 MHz */
+	SSP_CLOCK_CONFIG(0, 18, 6, 2, 0),	/* 12 .. 40 MHz */
+	SSP_CLOCK_CONFIG(0, 18, 5, 2, 0),	/* 13 .. 48 MHz */
+	SSP_CLOCK_CONFIG(0, 21, 4, 2, 0),	/* 14 .. 51.4 MHz */
+	0x00000000				/* 15 .. invalid. */
+};
+
 static inline uint32_t mx28_nand_ecc_size_in_bits(uint32_t ecc_strength)
 {
 	return ecc_strength * 13;
@@ -445,6 +496,7 @@ static void usage(void)
 		"  <type>	type of image:\n"
 		"                 \"nand\" for NAND image\n"
 		"                 \"sd\" for SD image\n"
+		"                 \"spi\" for SPI NOR image\n"
 		"  <infile>     input file, the u-boot.sb bootstream\n"
 		"  <outfile>    output file, the bootable image\n"
 		"\n");
@@ -456,6 +508,11 @@ static void usage(void)
 		"\n"
 		"For SD boot, these options are accepted:\n"
 		"  -p <sector>  Sector where the SGTL partition starts\n"
+		"\n"
+		"For SPI NOR boot, these options are accepted:\n"
+		"  -s <size>    SPI NOR sector size\n"
+		"  -i <size>    SPI NOR image offset (multiple of page size)\n"
+		"  -c <size>    Clock INDEX (see Table 12-27 in MX28 RM)\n"
 	);
 }
 
@@ -577,6 +634,54 @@ err0:
 	return ret;
 }
 
+static int mx28_create_spi_image(int infd, int outfd)
+{
+	int ret = -1;
+	uint32_t *buf;
+	int size;
+	off_t fsize;
+	ssize_t wr_size;
+	struct mx28_spi_config_block *cb;
+
+	fsize = lseek(infd, 0, SEEK_END);
+	lseek(infd, 0, SEEK_SET);
+	size = fsize + spi_image_offset;
+
+	buf = malloc(size);
+	if (!buf) {
+		printf("Can not allocate output buffer of %d bytes\n", size);
+		goto err0;
+	}
+
+	ret = read(infd, (uint8_t *)buf + spi_image_offset, fsize);
+	if (ret != fsize) {
+		ret = -1;
+		goto err1;
+	}
+
+	cb = (struct mx28_spi_config_block *)buf;
+
+	cb->signature		= 0x4d454d53;
+	cb->boot_start_addr	= spi_image_offset;
+	cb->sector_size		= spi_sector_size;
+	cb->flags		= 0x0;
+	cb->clock_config_size	= sizeof(cb->clock_config);
+	cb->clock_config	= mx28_spi_clock_config[spi_clock_idx];
+
+	wr_size = write(outfd, buf, size);
+	if (wr_size != size) {
+		ret = -1;
+		goto err1;
+	}
+
+	ret = 0;
+
+err1:
+	free(buf);
+err0:
+	return ret;
+}
+
 static int parse_ops(int argc, char **argv)
 {
 	int i;
@@ -588,7 +693,10 @@ static int parse_ops(int argc, char **argv)
 		PARAM_ERASE,
 		PARAM_PART,
 		PARAM_SD,
-		PARAM_NAND
+		PARAM_NAND,
+		PARAM_SPI_SECT_SIZE,
+		PARAM_SPI_IMAGE_OFFSET,
+		PARAM_SPI_CLOCK_IDX
 	};
 	int type;
 
@@ -596,15 +704,24 @@ static int parse_ops(int argc, char **argv)
 		return -1;
 
 	for (i = 1; i < argc; i++) {
+		/* NAND */
 		if (!strncmp(argv[i], "-w", 2))
 			type = PARAM_WRITE;
 		else if (!strncmp(argv[i], "-o", 2))
 			type = PARAM_OOB;
 		else if (!strncmp(argv[i], "-e", 2))
 			type = PARAM_ERASE;
+		/* SD/MMC */
 		else if (!strncmp(argv[i], "-p", 2))
 			type = PARAM_PART;
-		else	/* SD/MMC */
+		/* SPI */
+		else if (!strncmp(argv[i], "-s", 2))
+			type = PARAM_SPI_SECT_SIZE;
+		else if (!strncmp(argv[i], "-i", 2))
+			type = PARAM_SPI_IMAGE_OFFSET;
+		else if (!strncmp(argv[i], "-c", 2))
+			type = PARAM_SPI_CLOCK_IDX;
+		else
 			break;
 
 		tmp = strtol(argv[++i], &end, 10);
@@ -621,9 +738,17 @@ static int parse_ops(int argc, char **argv)
 			nand_erasesize = tmp;
 		if (type == PARAM_PART)
 			sd_sector = tmp;
+
+		if (type == PARAM_SPI_SECT_SIZE)
+			spi_sector_size = tmp;
+		if (type == PARAM_SPI_IMAGE_OFFSET)
+			spi_image_offset = tmp;
+		if (type == PARAM_SPI_CLOCK_IDX)
+			spi_clock_idx = tmp;
 	}
 
-	if (strcmp(argv[i], "sd") && strcmp(argv[i], "nand"))
+	if (strcmp(argv[i], "sd") && strcmp(argv[i], "nand") &&
+	    strcmp(argv[i], "spi"))
 		return -1;
 
 	if (i + 3 != argc)
@@ -664,6 +789,8 @@ int main(int argc, char **argv)
 		ret = mx28_create_sd_image(infd, outfd);
 	else if (!strcmp(argv[offset], "nand"))
 		ret = mx28_create_nand_image(infd, outfd);
+	else if (!strcmp(argv[offset], "spi"))
+		ret = mx28_create_spi_image(infd, outfd);
 
 	close(outfd);
 err2:
-- 
1.8.5.3



More information about the U-Boot mailing list