blob: 30f4466b31e89fe1fc7ca36305cd733df812fe96 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <linux/amlogic/aml_mtd_nand.h>
#include <linux/amlogic/gki_module.h>
extern struct mtd_info *aml_mtd_info[NAND_MAX_DEVICE];
static char *cmdline;
struct boot_area_entry general_boot_part_entry[MAX_BOOT_AREA_ENTRIES] = {
{BAE_BB1ST, BOOT_AREA_BB1ST, 0, BOOT_FIRST_BLOB_SIZE},
{BAE_BL2E, BOOT_AREA_BL2E, 0, 0x40000},
{BAE_BL2X, BOOT_AREA_BL2X, 0, 0x40000},
{BAE_DDRFIP, BOOT_AREA_DDRFIP, 0, 0x40000},
{BAE_DEVFIP, BOOT_AREA_DEVFIP, 0, 0x380000},
};
struct boot_layout general_boot_layout = {
.boot_entry = general_boot_part_entry
};
struct storage_startup_parameter g_ssp;
static void storage_boot_layout_debug_info(struct boot_layout *boot_layout)
{
struct boot_area_entry *boot_entry = boot_layout->boot_entry;
int i;
pr_info("boot area list:\n");
for (i = 0; i < MAX_BOOT_AREA_ENTRIES && boot_entry[i].size; i++) {
pr_info("%10s ", boot_entry[i].name);
pr_info("%10llx ", boot_entry[i].offset);
pr_info("%10llx\n", boot_entry[i].size);
}
}
#define NAND_RSV_BLOCK_NUM 48
#define NSP_PAGE0_DISABLE 1
static int storage_get_and_parse_ssp(void)
{
struct storage_startup_parameter *ssp;
union storage_independent_parameter *sip;
struct mtd_info *mtd;
mtd = aml_mtd_info[0];
ssp = &g_ssp;
memset(ssp, 0, sizeof(struct storage_startup_parameter));
sip = &ssp->sip;
ssp->boot_backups = 8;
sip->nsp.page_size = mtd->writesize;
sip->nsp.block_size = mtd->erasesize;
sip->nsp.pages_per_block = mtd->erasesize /
mtd->writesize;
sip->nsp.layout_reserve_size =
NAND_RSV_BLOCK_NUM * sip->nsp.block_size;
pr_info("boot_device:%d\n", ssp->boot_device);
pr_info("boot_seq:%d\n", ssp->boot_seq);
pr_info("boot_backups:%d\n", ssp->boot_backups);
return 0;
}
#define STORAGE_ROUND_UP_IF_UNALIGN(x, y) \
({ \
typeof(y) y_ = y; \
(((x) + (y_) - 1) & (~(y_ - 1))); \
})
#define NAND_RSV_OFFSET 1024
#define ALIGN_SIZE (4096)
int storage_boot_layout_general_setting(struct boot_layout *boot_layout)
{
struct storage_startup_parameter *ssp = &g_ssp;
struct boot_area_entry *boot_entry = NULL;
u64 align_size, reserved_size = 0;
u8 i, cal_copy = ssp->boot_backups;
boot_entry = boot_layout->boot_entry;
reserved_size = ssp->sip.nsp.layout_reserve_size;
align_size =
((NAND_RSV_OFFSET / cal_copy) * (u64)(ssp->sip.nsp.page_size));
boot_entry[0].size =
STORAGE_ROUND_UP_IF_UNALIGN(boot_entry[0].size, align_size);
ssp->boot_entry[0].size = boot_entry[0].size;
pr_info("ssp->boot_entry[0] offset:0x%x, size:0x%x\n",
ssp->boot_entry[0].offset, ssp->boot_entry[0].size);
pr_info("cal_copy:0x%x\n", cal_copy);
pr_info("align_size:0x%llx\n", align_size);
pr_info("reserved_size:0x%llx\n", reserved_size);
align_size = ssp->sip.nsp.block_size;
for (i = 1; i < MAX_BOOT_AREA_ENTRIES && boot_entry[i - 1].size; i++) {
boot_entry[i].size =
STORAGE_ROUND_UP_IF_UNALIGN(boot_entry[i].size, align_size);
boot_entry[i].offset = boot_entry[i - 1].offset +
boot_entry[i - 1].size * cal_copy + reserved_size;
reserved_size = 0;
ssp->boot_entry[i].size = boot_entry[i].size;
ssp->boot_entry[i].offset = boot_entry[i].offset;
}
return 0;
}
int aml_nand_parse_env(char *cmd)
{
struct boot_area_entry *boot_entry = NULL;
char *p = cmd;
u8 i;
p = p ? strchr(p, ':') : NULL;
if (!p) {
pr_info("WARN, no bl2e/x, so use reserved\n");
return 0;
}
p++;
pr_info("%s\n", p);
boot_entry = general_boot_layout.boot_entry;
for (i = BOOT_AREA_BL2E; i <= BOOT_AREA_DEVFIP && p; i++) {
boot_entry[i].size = memparse(p, NULL);
p = strchr(p, ',') + 1;
pr_info("%s_size(0x%llx)\n", boot_entry[i].name, boot_entry[i].size);
}
return 0;
}
int aml_nand_param_check_and_layout_init(void)
{
int ret = -1;
ret = storage_get_and_parse_ssp();
if (ret < 0)
return -1;
aml_nand_parse_env(cmdline);
storage_boot_layout_general_setting(&general_boot_layout);
storage_boot_layout_debug_info(&general_boot_layout);
return ret;
}
static int mtdbootpart_setup(char *s)
{
cmdline = s;
return 0;
}
__setup("mtdbootparts=", mtdbootpart_setup);