138 lines
3.9 KiB
C
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);
|
|
}
|