blob: 42908c0beea0018a3b669a4e1f5da81d0afca088 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <malloc.h>
#include <spi.h>
#include <spi_flash.h>
#include <linux/mtd/partitions.h>
#include <linux/types.h>
#include <linux/sizes.h>
#include <malloc.h>
#include <linux/errno.h>
#include <mtd.h>
#include <amlogic/aml_mtd.h>
#include <amlogic/storage.h>
#include <amlogic/cpu_id.h>
/* Hard code, all partitions are aligned in block size, fast erasing */
#define SPINOR_ALIGNED_SIZE (64 * 1024)
extern struct storage_startup_parameter g_ssp;
/* do not use default value, rewrite this function in the board file */
uint64_t __weak spiflash_bootloader_size(void)
{
return SZ_2M;
}
uint32_t __weak spiflash_rsv_block_num(void)
{
return 0;
}
extern boot_area_entry_t general_boot_part_entry[MAX_BOOT_AREA_ENTRIES];
/* The size of the partition must be block aligned */
static int _spinor_add_partitions(struct mtd_info *mtd,
const struct mtd_partition *parts,
int nbparts)
{
int part_num = 0, i = 0;
struct mtd_partition *temp, *parts_nm;
loff_t off;
if (store_get_device_bootloader_mode() == DISCRETE_BOOTLOADER)
/* spinor add discrete mode for advanced */
part_num = nbparts + 5;
else
part_num = nbparts + 1;
temp = kzalloc(sizeof(*temp) * part_num, GFP_KERNEL);
memset(temp, 0, sizeof(*temp) * part_num);
if (store_get_device_bootloader_mode() == DISCRETE_BOOTLOADER) {
temp[BOOT_AREA_BB1ST].name = BOOT_LOADER;
temp[BOOT_AREA_BB1ST].offset = general_boot_part_entry[BOOT_AREA_BB1ST].offset;
temp[BOOT_AREA_BB1ST].size = general_boot_part_entry[BOOT_AREA_BB1ST].size * g_ssp.boot_bakups;
if (temp[BOOT_AREA_BB1ST].size % SPINOR_ALIGNED_SIZE)
WARN_ON(1);
temp[BOOT_AREA_BL2E].name = BOOT_BL2E;
temp[BOOT_AREA_BL2E].offset = general_boot_part_entry[BOOT_AREA_BL2E].offset;
temp[BOOT_AREA_BL2E].size = general_boot_part_entry[BOOT_AREA_BL2E].size * g_ssp.boot_bakups;
if (temp[0].size % SPINOR_ALIGNED_SIZE)
WARN_ON(1);
temp[BOOT_AREA_BL2X].name = BOOT_BL2X;
temp[BOOT_AREA_BL2X].offset = general_boot_part_entry[BOOT_AREA_BL2X].offset;
temp[BOOT_AREA_BL2X].size = general_boot_part_entry[BOOT_AREA_BL2X].size * g_ssp.boot_bakups;
if (temp[0].size % SPINOR_ALIGNED_SIZE)
WARN_ON(1);
temp[BOOT_AREA_DDRFIP].name = BOOT_DDRFIP;
temp[BOOT_AREA_DDRFIP].offset = general_boot_part_entry[BOOT_AREA_DDRFIP].offset;
temp[BOOT_AREA_DDRFIP].size = general_boot_part_entry[BOOT_AREA_DDRFIP].size * g_ssp.boot_bakups;
if (temp[0].size % SPINOR_ALIGNED_SIZE)
WARN_ON(1);
temp[BOOT_AREA_DEVFIP].name = BOOT_DEVFIP;
temp[BOOT_AREA_DEVFIP].offset = general_boot_part_entry[BOOT_AREA_DEVFIP].offset;
temp[BOOT_AREA_DEVFIP].size = general_boot_part_entry[BOOT_AREA_DEVFIP].size *
CONFIG_NOR_TPL_COPY_NUM;
if (temp[0].size % SPINOR_ALIGNED_SIZE)
WARN_ON(1);
off = temp[BOOT_AREA_DEVFIP].offset + temp[BOOT_AREA_DEVFIP].size;
parts_nm = &temp[5];
} else {
temp[0].name = BOOT_LOADER;
temp[0].offset = 0;
temp[0].size = spiflash_bootloader_size();
if (temp[0].size % SPINOR_ALIGNED_SIZE)
WARN_ON(1);
/* rsv size is aligned with blocksize(64K) */
off = temp[0].size + spiflash_rsv_block_num() * SPINOR_ALIGNED_SIZE;
parts_nm = &temp[1];
}
for (i = 0; i < nbparts; i++) {
if (!parts[i].name) {
pr_err("name can't be null! ");
pr_err("please check your %d th partition name!\n",
i + 1);
return 1;
}
if ((off + parts[i].size) > mtd->size) {
pr_err("%s %d over nand size!\n",
__func__, __LINE__);
return 1;
}
parts_nm[i].name = parts[i].name;
parts_nm[i].offset = off;
if (parts[i].size % SPINOR_ALIGNED_SIZE) {
pr_err("%s %d \"%s\" size auto align to block size\n",
__func__, __LINE__, parts[i].name);
parts_nm[i].size += parts[i].size % SPINOR_ALIGNED_SIZE;
}
/* it's ok "+=" here because size has been set to 0 */
parts_nm[i].size += parts[i].size;
off += parts_nm[i].size;
if (i == (nbparts - 1))
parts_nm[i].size = mtd->size - off;
}
return add_mtd_partitions(mtd, temp, part_num);
}
extern struct mtd_partition *get_spiflash_partition_table(int *partitions);
int spinor_add_partitions(struct mtd_info *mtd)
{
struct mtd_partition *spiflash_partitions;
int partition_count;
spiflash_partitions = get_spiflash_partition_table(&partition_count);
return _spinor_add_partitions(mtd, spiflash_partitions,
partition_count);
}
int spinor_del_partitions(struct mtd_info *mtd)
{
return del_mtd_partitions(mtd);
}