123cf98fbSJason Zhu // SPDX-License-Identifier: GPL-2.0 223cf98fbSJason Zhu /* 323cf98fbSJason Zhu * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd 423cf98fbSJason Zhu */ 523cf98fbSJason Zhu 623cf98fbSJason Zhu #include <common.h> 723cf98fbSJason Zhu #include <blk.h> 823cf98fbSJason Zhu #include <dm.h> 923cf98fbSJason Zhu #include <errno.h> 1023cf98fbSJason Zhu #include <image.h> 1123cf98fbSJason Zhu #include <malloc.h> 12*ddb43797SJason Zhu #include <mtd_blk.h> 1323cf98fbSJason Zhu #include <part.h> 1423cf98fbSJason Zhu #include <spl.h> 1523cf98fbSJason Zhu #include <spl_ab.h> 1623cf98fbSJason Zhu #include <spl_rkfw.h> 1723cf98fbSJason Zhu #include <asm/u-boot.h> 1823cf98fbSJason Zhu #include <dm/device-internal.h> 1923cf98fbSJason Zhu #include <linux/compiler.h> 2023cf98fbSJason Zhu #include <linux/mtd/mtd.h> 2123cf98fbSJason Zhu 2223cf98fbSJason Zhu static int spl_mtd_get_device_index(u32 boot_device) 2323cf98fbSJason Zhu { 2423cf98fbSJason Zhu switch (boot_device) { 2523cf98fbSJason Zhu case BOOT_DEVICE_MTD_BLK_NAND: 2623cf98fbSJason Zhu return 0; 2723cf98fbSJason Zhu case BOOT_DEVICE_MTD_BLK_SPI_NAND: 2823cf98fbSJason Zhu return 1; 2923cf98fbSJason Zhu case BOOT_DEVICE_MTD_BLK_SPI_NOR: 3023cf98fbSJason Zhu return 2; 3123cf98fbSJason Zhu } 3223cf98fbSJason Zhu 3323cf98fbSJason Zhu #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 3423cf98fbSJason Zhu printf("spl: unsupported mtd boot device.\n"); 3523cf98fbSJason Zhu #endif 3623cf98fbSJason Zhu 3723cf98fbSJason Zhu return -ENODEV; 3823cf98fbSJason Zhu } 3923cf98fbSJason Zhu 4023cf98fbSJason Zhu struct blk_desc *find_mtd_device(int dev_num) 4123cf98fbSJason Zhu { 4223cf98fbSJason Zhu struct udevice *dev; 4323cf98fbSJason Zhu struct blk_desc *desc; 4423cf98fbSJason Zhu int ret; 4523cf98fbSJason Zhu 4623cf98fbSJason Zhu ret = blk_find_device(IF_TYPE_MTD, dev_num, &dev); 4723cf98fbSJason Zhu 4823cf98fbSJason Zhu if (ret) { 4923cf98fbSJason Zhu #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) 5023cf98fbSJason Zhu printf("MTD Device %d not found\n", dev_num); 5123cf98fbSJason Zhu #endif 5223cf98fbSJason Zhu return NULL; 5323cf98fbSJason Zhu } 5423cf98fbSJason Zhu 5523cf98fbSJason Zhu ret = device_probe(dev); 5623cf98fbSJason Zhu if (ret) { 5723cf98fbSJason Zhu #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) 5823cf98fbSJason Zhu printf("MTD Device %d not found\n", dev_num); 5923cf98fbSJason Zhu #endif 6023cf98fbSJason Zhu return NULL; 6123cf98fbSJason Zhu } 6223cf98fbSJason Zhu 6323cf98fbSJason Zhu desc = dev_get_uclass_platdata(dev); 6423cf98fbSJason Zhu if (!desc) 6523cf98fbSJason Zhu return NULL; 6623cf98fbSJason Zhu 6723cf98fbSJason Zhu return desc; 6823cf98fbSJason Zhu } 6923cf98fbSJason Zhu 7023cf98fbSJason Zhu static ulong mtd_spl_load_read(struct spl_load_info *load, ulong sector, 7123cf98fbSJason Zhu ulong count, void *buf) 7223cf98fbSJason Zhu { 7323cf98fbSJason Zhu struct blk_desc *desc = load->dev; 7423cf98fbSJason Zhu 7523cf98fbSJason Zhu return blk_dread(desc, sector, count, buf); 7623cf98fbSJason Zhu } 7723cf98fbSJason Zhu 78d300a216SJason Zhu #ifdef CONFIG_SPL_LOAD_RKFW 7923cf98fbSJason Zhu int spl_mtd_load_rkfw(struct spl_image_info *spl_image, struct blk_desc *desc) 8023cf98fbSJason Zhu { 8123cf98fbSJason Zhu int ret = -1; 8223cf98fbSJason Zhu 8323cf98fbSJason Zhu u32 trust_sectors = CONFIG_RKFW_TRUST_SECTOR; 8423cf98fbSJason Zhu u32 uboot_sectors = CONFIG_RKFW_U_BOOT_SECTOR; 85440eb126SJason Zhu u32 boot_sectors = CONFIG_RKFW_BOOT_SECTOR; 8623cf98fbSJason Zhu struct spl_load_info load; 8723cf98fbSJason Zhu 8823cf98fbSJason Zhu load.dev = desc; 8923cf98fbSJason Zhu load.priv = NULL; 9023cf98fbSJason Zhu load.filename = NULL; 9123cf98fbSJason Zhu load.bl_len = desc->blksz; 9223cf98fbSJason Zhu load.read = mtd_spl_load_read; 9323cf98fbSJason Zhu 9423cf98fbSJason Zhu #ifdef CONFIG_SPL_AB 9523cf98fbSJason Zhu char trust_partition[] = "trust"; 9623cf98fbSJason Zhu char uboot_partition[] = "uboot"; 9723cf98fbSJason Zhu 9801fc0bcdSJason Zhu spl_get_partitions_sector(desc, trust_partition, 9923cf98fbSJason Zhu &trust_sectors); 10001fc0bcdSJason Zhu spl_get_partitions_sector(desc, uboot_partition, 10123cf98fbSJason Zhu &uboot_sectors); 10223cf98fbSJason Zhu #endif 10323cf98fbSJason Zhu 10423cf98fbSJason Zhu ret = spl_load_rkfw_image(spl_image, &load, 10523cf98fbSJason Zhu trust_sectors, 106440eb126SJason Zhu uboot_sectors, 107440eb126SJason Zhu boot_sectors); 10823cf98fbSJason Zhu if (ret) { 10923cf98fbSJason Zhu #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 11023cf98fbSJason Zhu puts("spl_mtd_load_rkfw: mtd block read error\n"); 11123cf98fbSJason Zhu #endif 11223cf98fbSJason Zhu return -1; 11323cf98fbSJason Zhu } 11423cf98fbSJason Zhu 11523cf98fbSJason Zhu return ret; 11623cf98fbSJason Zhu } 11723cf98fbSJason Zhu #endif 11823cf98fbSJason Zhu 11923cf98fbSJason Zhu int spl_mtd_load_image(struct spl_image_info *spl_image, 12023cf98fbSJason Zhu struct spl_boot_device *bootdev) 12123cf98fbSJason Zhu { 122d300a216SJason Zhu struct image_header *header; 12323cf98fbSJason Zhu struct blk_desc *desc; 124d300a216SJason Zhu int ret = -1; 12523cf98fbSJason Zhu 12623cf98fbSJason Zhu desc = find_mtd_device(spl_mtd_get_device_index(bootdev->boot_device)); 12723cf98fbSJason Zhu if (!desc) 12823cf98fbSJason Zhu return -ENODEV; 129*ddb43797SJason Zhu #ifdef CONFIG_SPL_LIBDISK_SUPPORT 130*ddb43797SJason Zhu mtd_blk_map_partitions(desc); 131*ddb43797SJason Zhu #endif 132d300a216SJason Zhu if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) { 133d300a216SJason Zhu header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - 134d300a216SJason Zhu sizeof(struct image_header)); 135d300a216SJason Zhu ret = blk_dread(desc, CONFIG_SYS_NAND_U_BOOT_OFFS, 1, header); 136d300a216SJason Zhu if (ret != 1) 137d300a216SJason Zhu return -ENODEV; 138d300a216SJason Zhu 139d300a216SJason Zhu #ifdef CONFIG_SPL_FIT_IMAGE_MULTIPLE 140d300a216SJason Zhu if (image_get_magic(header) == FDT_MAGIC || 141d300a216SJason Zhu CONFIG_SPL_FIT_IMAGE_MULTIPLE > 1) { 142d300a216SJason Zhu #else 143d300a216SJason Zhu if (image_get_magic(header) == FDT_MAGIC) { 144d300a216SJason Zhu #endif 145d300a216SJason Zhu struct spl_load_info load; 146d300a216SJason Zhu 147d300a216SJason Zhu load.dev = desc; 148d300a216SJason Zhu load.priv = NULL; 149d300a216SJason Zhu load.filename = NULL; 150d300a216SJason Zhu load.bl_len = desc->blksz; 151d300a216SJason Zhu load.read = mtd_spl_load_read; 152d300a216SJason Zhu 153d300a216SJason Zhu ret = spl_load_simple_fit(spl_image, &load, 154d300a216SJason Zhu CONFIG_SYS_NAND_U_BOOT_OFFS, 155d300a216SJason Zhu header); 156d300a216SJason Zhu } 157d300a216SJason Zhu 158d300a216SJason Zhu } else if (IS_ENABLED(CONFIG_SPL_LOAD_RKFW)) { 15923cf98fbSJason Zhu #ifdef CONFIG_SPL_LOAD_RKFW 16023cf98fbSJason Zhu ret = spl_mtd_load_rkfw(spl_image, desc); 16123cf98fbSJason Zhu #endif 162d300a216SJason Zhu } 163d300a216SJason Zhu 16423cf98fbSJason Zhu return ret; 16523cf98fbSJason Zhu } 16623cf98fbSJason Zhu 16723cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD1", 0, BOOT_DEVICE_MTD_BLK_NAND, spl_mtd_load_image); 16823cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD2", 0, BOOT_DEVICE_MTD_BLK_SPI_NAND, spl_mtd_load_image); 16923cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD3", 0, BOOT_DEVICE_MTD_BLK_SPI_NOR, spl_mtd_load_image); 170