mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2025-12-10 07:44:53 +01:00
qca: Add uboot-CLI command "flash"
The "flash" command erases given partition and writes the image to flash. Change-Id: I059414fd3d7eefeac0c626e1980a70985f2de986 Signed-off-by: Pavithra Palanisamy <pavip@codeaurora.org>
This commit is contained in:
parent
af7feada2e
commit
316e48fb0d
7 changed files with 293 additions and 0 deletions
|
|
@ -649,6 +649,49 @@ unsigned int get_which_flash_param(char *part_name)
|
||||||
return flash_var;
|
return flash_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getpart_offset_size - retreive partition offset and size
|
||||||
|
* @part_name - partition name
|
||||||
|
* @offset - location where the offset of partition to be stored
|
||||||
|
* @size - location where partition size to be stored
|
||||||
|
*
|
||||||
|
* Retreive partition offset and size in bytes with respect to the
|
||||||
|
* partition specific flash block size
|
||||||
|
*/
|
||||||
|
int getpart_offset_size(char *part_name, uint32_t *offset, uint32_t *size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_t bsize;
|
||||||
|
qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
|
||||||
|
|
||||||
|
for (i = 0; i < smem_ptable.len; i++) {
|
||||||
|
struct smem_ptn *p = &smem_ptable.parts[i];
|
||||||
|
loff_t psize;
|
||||||
|
if (!strncmp(p->name, part_name, SMEM_PTN_NAME_MAX)) {
|
||||||
|
bsize = get_part_block_size(p, sfi);
|
||||||
|
if (p->size == (~0u)) {
|
||||||
|
/*
|
||||||
|
* Partition size is 'till end of device', calculate
|
||||||
|
* appropriately
|
||||||
|
*/
|
||||||
|
psize = nand_info[get_device_id_by_part(p)].size
|
||||||
|
- (((loff_t)p->start) * bsize);
|
||||||
|
} else {
|
||||||
|
psize = ((loff_t)p->size) * bsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
*offset = ((loff_t)p->start) * bsize;
|
||||||
|
*size = psize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == smem_ptable.len)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int do_smeminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
int do_smeminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||||
{
|
{
|
||||||
qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
|
qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ int smem_get_boot_flash(uint32_t *flash_type,
|
||||||
uint32_t *flash_block_size,
|
uint32_t *flash_block_size,
|
||||||
uint32_t *flash_density);
|
uint32_t *flash_density);
|
||||||
int smem_getpart(char *name, uint32_t *start, uint32_t *size);
|
int smem_getpart(char *name, uint32_t *start, uint32_t *size);
|
||||||
|
int getpart_offset_size(char *part_name, uint32_t *offset, uint32_t *size);
|
||||||
unsigned int smem_get_board_machtype(void);
|
unsigned int smem_get_board_machtype(void);
|
||||||
uint32_t get_nand_block_size(uint8_t dev_id);
|
uint32_t get_nand_block_size(uint8_t dev_id);
|
||||||
unsigned int get_which_flash_param(char *part_name);
|
unsigned int get_which_flash_param(char *part_name);
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ obj-$(CONFIG_CMD_FDC) += cmd_fdc.o
|
||||||
obj-$(CONFIG_OF_LIBFDT) += cmd_fdt.o fdt_support.o
|
obj-$(CONFIG_OF_LIBFDT) += cmd_fdt.o fdt_support.o
|
||||||
obj-$(CONFIG_CMD_FITUPD) += cmd_fitupd.o
|
obj-$(CONFIG_CMD_FITUPD) += cmd_fitupd.o
|
||||||
obj-$(CONFIG_CMD_FLASH) += cmd_flash.o
|
obj-$(CONFIG_CMD_FLASH) += cmd_flash.o
|
||||||
|
obj-$(CONFIG_CMD_FLASHWRITE) += cmd_flashwrite.o
|
||||||
ifdef CONFIG_FPGA
|
ifdef CONFIG_FPGA
|
||||||
obj-$(CONFIG_CMD_FPGA) += cmd_fpga.o
|
obj-$(CONFIG_CMD_FPGA) += cmd_fpga.o
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
245
common/cmd_flashwrite.c
Normal file
245
common/cmd_flashwrite.c
Normal file
|
|
@ -0,0 +1,245 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||||
|
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FlashWrite command support
|
||||||
|
*/
|
||||||
|
#include <common.h>
|
||||||
|
#include <command.h>
|
||||||
|
#include <asm/arch-qca-common/smem.h>
|
||||||
|
#include <part.h>
|
||||||
|
#include <linux/mtd/mtd.h>
|
||||||
|
#include <nand.h>
|
||||||
|
#include <mmc.h>
|
||||||
|
#include <sdhci.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
#ifndef CONFIG_SDHCI_SUPPORT
|
||||||
|
extern qca_mmc mmc_host;
|
||||||
|
#else
|
||||||
|
extern struct sdhci_host mmc_host;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SMEM_PTN_NAME_MAX 16
|
||||||
|
|
||||||
|
static int write_to_flash(int flash_type, uint32_t address, uint32_t offset,
|
||||||
|
uint32_t part_size, uint32_t file_size, char *layout)
|
||||||
|
{
|
||||||
|
|
||||||
|
char runcmd[256];
|
||||||
|
int nand_dev = CONFIG_NAND_FLASH_INFO_IDX;
|
||||||
|
|
||||||
|
if (flash_type == SMEM_BOOT_NAND_FLASH) {
|
||||||
|
|
||||||
|
snprintf(runcmd, sizeof(runcmd), "nand device %d && ", nand_dev);
|
||||||
|
|
||||||
|
if (strcmp(layout, "default") != 0) {
|
||||||
|
|
||||||
|
snprintf(runcmd + strlen(runcmd), sizeof(runcmd),
|
||||||
|
"ipq_nand %s && ", layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(runcmd + strlen(runcmd), sizeof(runcmd),
|
||||||
|
"nand erase 0x%x 0x%x && "
|
||||||
|
"nand write 0x%x 0x%x 0x%x && ",
|
||||||
|
offset, part_size,
|
||||||
|
address, offset, file_size);
|
||||||
|
|
||||||
|
} else if (flash_type == SMEM_BOOT_MMC_FLASH) {
|
||||||
|
|
||||||
|
snprintf(runcmd, sizeof(runcmd),
|
||||||
|
"mmc erase 0x%x 0x%x && "
|
||||||
|
"mmc write 0x%x 0x%x 0x%x && ",
|
||||||
|
offset, part_size,
|
||||||
|
address, offset, file_size);
|
||||||
|
|
||||||
|
} else if (flash_type == SMEM_BOOT_SPI_FLASH) {
|
||||||
|
|
||||||
|
snprintf(runcmd, sizeof(runcmd),
|
||||||
|
"sf probe && "
|
||||||
|
"sf erase 0x%x 0x%x && "
|
||||||
|
"sf write 0x%x 0x%x 0x%x && ",
|
||||||
|
offset, part_size,
|
||||||
|
address, offset, file_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
|
||||||
|
return CMD_RET_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_flash(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||||
|
char * const argv[])
|
||||||
|
{
|
||||||
|
uint32_t load_addr, offset, part_size, file_size, adj_size;
|
||||||
|
uint32_t size_block, start_block, file_size_cpy;
|
||||||
|
char *part_name = NULL, *filesize;
|
||||||
|
int flash_type, ret, retn;
|
||||||
|
unsigned int active_part = 0;
|
||||||
|
char *layout = NULL;
|
||||||
|
#ifdef CONFIG_IPQ806X
|
||||||
|
char* layout_linux[] = {"rootfs", "0:BOOTCONFIG", "0:BOOTCONFIG1"};
|
||||||
|
int len, i;
|
||||||
|
#endif
|
||||||
|
retn = CMD_RET_FAILURE;
|
||||||
|
|
||||||
|
block_dev_desc_t *blk_dev;
|
||||||
|
disk_partition_t disk_info;
|
||||||
|
qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
|
||||||
|
nand_info_t *nand = &nand_info[CONFIG_NAND_FLASH_INFO_IDX];
|
||||||
|
|
||||||
|
if ((argc < 3) || (argc > 4))
|
||||||
|
return CMD_RET_USAGE;
|
||||||
|
|
||||||
|
if (argc == 4)
|
||||||
|
file_size = simple_strtoul(argv[3], NULL, 16);
|
||||||
|
else {
|
||||||
|
filesize = getenv("filesize");
|
||||||
|
if (filesize != NULL)
|
||||||
|
file_size = simple_strtoul(filesize, NULL, 16);
|
||||||
|
else
|
||||||
|
return CMD_RET_USAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(argv[2], "default", 7) == 0)
|
||||||
|
load_addr = CONFIG_SYS_LOAD_ADDR;
|
||||||
|
else
|
||||||
|
load_addr = simple_strtoul(argv[2], NULL, 16);
|
||||||
|
|
||||||
|
flash_type = sfi->flash_type;
|
||||||
|
part_name = argv[1];
|
||||||
|
|
||||||
|
if (sfi->flash_type == SMEM_BOOT_NAND_FLASH) {
|
||||||
|
|
||||||
|
ret = smem_getpart(part_name, &start_block, &size_block);
|
||||||
|
if (ret)
|
||||||
|
return retn;
|
||||||
|
|
||||||
|
offset = sfi->flash_block_size * start_block;
|
||||||
|
part_size = sfi->flash_block_size * size_block;
|
||||||
|
layout = "default";
|
||||||
|
#ifdef CONFIG_IPQ806X
|
||||||
|
len = sizeof(layout_linux)/sizeof(layout_linux[0]);
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
|
||||||
|
if (!strncmp(layout_linux[i], part_name,
|
||||||
|
SMEM_PTN_NAME_MAX)) {
|
||||||
|
layout = "linux";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == len )
|
||||||
|
layout = "sbl";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH) {
|
||||||
|
|
||||||
|
blk_dev = mmc_get_dev(mmc_host.dev_num);
|
||||||
|
if (blk_dev != NULL) {
|
||||||
|
|
||||||
|
ret = get_partition_info_efi_by_name(blk_dev,
|
||||||
|
part_name, &disk_info);
|
||||||
|
if (ret)
|
||||||
|
return retn;
|
||||||
|
|
||||||
|
offset = (ulong)disk_info.start;
|
||||||
|
part_size = (ulong)disk_info.size;
|
||||||
|
file_size_cpy = file_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (sfi->flash_type == SMEM_BOOT_SPI_FLASH) {
|
||||||
|
|
||||||
|
if (get_which_flash_param(part_name)) {
|
||||||
|
|
||||||
|
/* NOR + NAND*/
|
||||||
|
flash_type = SMEM_BOOT_NAND_FLASH;
|
||||||
|
ret = getpart_offset_size(part_name, &offset, &part_size);
|
||||||
|
if (ret)
|
||||||
|
return retn;
|
||||||
|
|
||||||
|
} else if ((sfi->flash_secondary_type == SMEM_BOOT_NAND_FLASH)
|
||||||
|
&& (strncmp(part_name, "rootfs", 6) == 0)) {
|
||||||
|
|
||||||
|
/* IPQ806X - NOR + NAND */
|
||||||
|
flash_type = SMEM_BOOT_NAND_FLASH;
|
||||||
|
|
||||||
|
if (sfi->rootfs.offset == 0xBAD0FF5E) {
|
||||||
|
if (smem_bootconfig_info() == 0)
|
||||||
|
active_part = get_rootfs_active_partition();
|
||||||
|
|
||||||
|
offset = (ulong) active_part * IPQ_NAND_ROOTFS_SIZE;
|
||||||
|
part_size = (ulong) IPQ_NAND_ROOTFS_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}else if ((smem_getpart(part_name, &start_block, &size_block)
|
||||||
|
== -ENOENT) && (sfi->rootfs.offset == 0xBAD0FF5E)){
|
||||||
|
|
||||||
|
/* NOR + EMMC */
|
||||||
|
flash_type = SMEM_BOOT_MMC_FLASH;
|
||||||
|
|
||||||
|
blk_dev = mmc_get_dev(mmc_host.dev_num);
|
||||||
|
if (blk_dev != NULL) {
|
||||||
|
|
||||||
|
ret = get_partition_info_efi_by_name(blk_dev,
|
||||||
|
part_name, &disk_info);
|
||||||
|
if (ret)
|
||||||
|
return retn;
|
||||||
|
|
||||||
|
offset = (ulong)disk_info.start;
|
||||||
|
part_size = (ulong)disk_info.size;
|
||||||
|
file_size_cpy = file_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ret = smem_getpart(part_name, &start_block,
|
||||||
|
&size_block);
|
||||||
|
if (ret)
|
||||||
|
return retn;
|
||||||
|
|
||||||
|
offset = sfi->flash_block_size * start_block;
|
||||||
|
part_size = sfi->flash_block_size * size_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flash_type == SMEM_BOOT_NAND_FLASH) {
|
||||||
|
|
||||||
|
adj_size = file_size % nand->writesize;
|
||||||
|
if (adj_size)
|
||||||
|
file_size = file_size + (nand->writesize - adj_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flash_type == SMEM_BOOT_MMC_FLASH) {
|
||||||
|
|
||||||
|
file_size = file_size / disk_info.blksz;
|
||||||
|
adj_size = file_size_cpy % disk_info.blksz;
|
||||||
|
if (adj_size)
|
||||||
|
file_size = file_size + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = write_to_flash(flash_type, load_addr, offset, part_size,
|
||||||
|
file_size, layout);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
U_BOOT_CMD(
|
||||||
|
flash, 4, 0, do_flash,
|
||||||
|
"flash part_name load_addr [file_size] \n"
|
||||||
|
"\tflash part_name 'default' \n",
|
||||||
|
"flash the image at load_addr, given file_size in hex\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
|
@ -122,6 +122,7 @@ typedef struct {
|
||||||
#define QCA_BOOT_PARAMS_ADDR (QCA_KERNEL_START_ADDR + 0x100)
|
#define QCA_BOOT_PARAMS_ADDR (QCA_KERNEL_START_ADDR + 0x100)
|
||||||
#endif
|
#endif
|
||||||
#define CONFIG_FLASH_PROTECT
|
#define CONFIG_FLASH_PROTECT
|
||||||
|
#define CONFIG_CMD_FLASHWRITE
|
||||||
|
|
||||||
/* Environment */
|
/* Environment */
|
||||||
#define CONFIG_ARCH_CPU_INIT
|
#define CONFIG_ARCH_CPU_INIT
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@
|
||||||
|
|
||||||
#define CONFIG_SYS_DEVICE_NULLDEV
|
#define CONFIG_SYS_DEVICE_NULLDEV
|
||||||
#define CONFIG_FLASH_PROTECT
|
#define CONFIG_FLASH_PROTECT
|
||||||
|
#define CONFIG_CMD_FLASHWRITE
|
||||||
|
|
||||||
/* Environment */
|
/* Environment */
|
||||||
#define CONFIG_MSM_PCOMM
|
#define CONFIG_MSM_PCOMM
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ extern loff_t board_env_size;
|
||||||
|
|
||||||
#define CONFIG_ENV_IS_IN_NAND 1
|
#define CONFIG_ENV_IS_IN_NAND 1
|
||||||
#define CONFIG_FLASH_PROTECT
|
#define CONFIG_FLASH_PROTECT
|
||||||
|
#define CONFIG_CMD_FLASHWRITE
|
||||||
|
|
||||||
/* Allow to overwrite serial and ethaddr */
|
/* Allow to overwrite serial and ethaddr */
|
||||||
#define CONFIG_ENV_OVERWRITE
|
#define CONFIG_ENV_OVERWRITE
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue