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 <ma...@denx.de> Cc: Stefano Babic <sba...@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot