[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