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

Reply via email to