Files

138 lines
3.9 KiB
C

// 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>
/* use STORAGE_ROUND_UP, y must be power of 2 */
#define SPINOR_ROUND_UP_IF_UNALIGN(x, y) ((x) = (((x) + (y) - 1) & (~(y - 1))))
/* 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;
int ret = 1;
cpu_id_t cpu_id = get_cpu_id();
part_num = nbparts + 1;
temp = kzalloc(sizeof(*temp) * part_num, GFP_KERNEL);
if (store_get_device_bootloader_mode() == ADVANCE_BOOTLOADER) {
temp[0].name = BOOT_LOADER;
temp[0].offset = general_boot_part_entry[0].offset;
temp[0].size = (general_boot_part_entry[BOOT_AREA_BB1ST].size +
general_boot_part_entry[BOOT_AREA_BL2E].size +
general_boot_part_entry[BOOT_AREA_BL2X].size +
general_boot_part_entry[BOOT_AREA_DDRFIP].size)
* g_ssp.boot_backups +
general_boot_part_entry[BOOT_AREA_DEVFIP].size
* CONFIG_NOR_TPL_COPY_NUM;
#ifdef BOARD_SNOR_DDR_PARAM_SIZE
temp[0].size += BOARD_SNOR_DDR_PARAM_SIZE;
#endif
if (temp[0].size % SPINOR_ALIGNED_SIZE) {
pr_info("%s %d \"%s\" size auto align to block size\n",
__func__, __LINE__, temp[0].name);
SPINOR_ROUND_UP_IF_UNALIGN(temp[0].size, SPINOR_ALIGNED_SIZE);
}
off = temp[0].offset + temp[0].size;
parts_nm = &temp[1];
if (cpu_id.family_id == MESON_CPU_MAJOR_ID_A4)
off = DIV_ROUND_UP(off, 0x1000) << 12;
} 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);
goto _out;
}
if ((off + parts[i].size) > mtd->size) {
pr_err("%s %d over nand size!\n",
__func__, __LINE__);
goto _out;
}
parts_nm[i].name = parts[i].name;
parts_nm[i].offset = off;
/* it's ok "+=" here because size has been set to 0 */
parts_nm[i].size += parts[i].size;
if (parts_nm[i].size % SPINOR_ALIGNED_SIZE) {
pr_info("%s %d \"%s\" size auto align to block size\n",
__func__, __LINE__, parts[i].name);
SPINOR_ROUND_UP_IF_UNALIGN(parts_nm[i].size, SPINOR_ALIGNED_SIZE);
}
off += parts_nm[i].size;
if (i == (nbparts - 1))
parts_nm[i].size = mtd->size - off;
}
ret = add_mtd_partitions(mtd, temp, part_num);
_out:
kfree(temp);
return ret;
}
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);
}