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> 8*516562c2SJason Zhu #include <boot_rkimg.h> 923cf98fbSJason Zhu #include <dm.h> 1023cf98fbSJason Zhu #include <errno.h> 1123cf98fbSJason Zhu #include <image.h> 1223cf98fbSJason Zhu #include <malloc.h> 13ddb43797SJason Zhu #include <mtd_blk.h> 1423cf98fbSJason Zhu #include <part.h> 1523cf98fbSJason Zhu #include <spl.h> 1623cf98fbSJason Zhu #include <spl_ab.h> 1723cf98fbSJason Zhu #include <spl_rkfw.h> 1823cf98fbSJason Zhu #include <asm/u-boot.h> 1923cf98fbSJason Zhu #include <dm/device-internal.h> 2023cf98fbSJason Zhu #include <linux/compiler.h> 2123cf98fbSJason Zhu #include <linux/mtd/mtd.h> 2223cf98fbSJason Zhu 2323cf98fbSJason Zhu static int spl_mtd_get_device_index(u32 boot_device) 2423cf98fbSJason Zhu { 2523cf98fbSJason Zhu switch (boot_device) { 2623cf98fbSJason Zhu case BOOT_DEVICE_MTD_BLK_NAND: 2723cf98fbSJason Zhu return 0; 2823cf98fbSJason Zhu case BOOT_DEVICE_MTD_BLK_SPI_NAND: 2923cf98fbSJason Zhu return 1; 3023cf98fbSJason Zhu case BOOT_DEVICE_MTD_BLK_SPI_NOR: 3123cf98fbSJason Zhu return 2; 3223cf98fbSJason Zhu } 3323cf98fbSJason Zhu 3423cf98fbSJason Zhu #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 3523cf98fbSJason Zhu printf("spl: unsupported mtd boot device.\n"); 3623cf98fbSJason Zhu #endif 3723cf98fbSJason Zhu 3823cf98fbSJason Zhu return -ENODEV; 3923cf98fbSJason Zhu } 4023cf98fbSJason Zhu 4123cf98fbSJason Zhu struct blk_desc *find_mtd_device(int dev_num) 4223cf98fbSJason Zhu { 4323cf98fbSJason Zhu struct udevice *dev; 4423cf98fbSJason Zhu struct blk_desc *desc; 4523cf98fbSJason Zhu int ret; 4623cf98fbSJason Zhu 4723cf98fbSJason Zhu ret = blk_find_device(IF_TYPE_MTD, dev_num, &dev); 4823cf98fbSJason Zhu 4923cf98fbSJason Zhu if (ret) { 5023cf98fbSJason Zhu #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) 5123cf98fbSJason Zhu printf("MTD Device %d not found\n", dev_num); 5223cf98fbSJason Zhu #endif 5323cf98fbSJason Zhu return NULL; 5423cf98fbSJason Zhu } 5523cf98fbSJason Zhu 5623cf98fbSJason Zhu ret = device_probe(dev); 5723cf98fbSJason Zhu if (ret) { 5823cf98fbSJason Zhu #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) 5923cf98fbSJason Zhu printf("MTD Device %d not found\n", dev_num); 6023cf98fbSJason Zhu #endif 6123cf98fbSJason Zhu return NULL; 6223cf98fbSJason Zhu } 6323cf98fbSJason Zhu 6423cf98fbSJason Zhu desc = dev_get_uclass_platdata(dev); 6523cf98fbSJason Zhu if (!desc) 6623cf98fbSJason Zhu return NULL; 6723cf98fbSJason Zhu 6823cf98fbSJason Zhu return desc; 6923cf98fbSJason Zhu } 7023cf98fbSJason Zhu 7123cf98fbSJason Zhu static ulong mtd_spl_load_read(struct spl_load_info *load, ulong sector, 7223cf98fbSJason Zhu ulong count, void *buf) 7323cf98fbSJason Zhu { 7423cf98fbSJason Zhu struct blk_desc *desc = load->dev; 7523cf98fbSJason Zhu 7623cf98fbSJason Zhu return blk_dread(desc, sector, count, buf); 7723cf98fbSJason Zhu } 7823cf98fbSJason Zhu 79d300a216SJason Zhu #ifdef CONFIG_SPL_LOAD_RKFW 8023cf98fbSJason Zhu int spl_mtd_load_rkfw(struct spl_image_info *spl_image, struct blk_desc *desc) 8123cf98fbSJason Zhu { 8223cf98fbSJason Zhu struct spl_load_info load; 8354ac22e0SJoseph Chen int ret; 8423cf98fbSJason Zhu 8523cf98fbSJason Zhu load.dev = desc; 8623cf98fbSJason Zhu load.priv = NULL; 8723cf98fbSJason Zhu load.filename = NULL; 8823cf98fbSJason Zhu load.bl_len = desc->blksz; 8923cf98fbSJason Zhu load.read = mtd_spl_load_read; 9023cf98fbSJason Zhu 9154ac22e0SJoseph Chen ret = spl_load_rkfw_image(spl_image, &load); 9223cf98fbSJason Zhu if (ret) { 9323cf98fbSJason Zhu #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 9423cf98fbSJason Zhu puts("spl_mtd_load_rkfw: mtd block read error\n"); 9523cf98fbSJason Zhu #endif 9623cf98fbSJason Zhu return -1; 9723cf98fbSJason Zhu } 9823cf98fbSJason Zhu 9954ac22e0SJoseph Chen return 0; 10023cf98fbSJason Zhu } 10123cf98fbSJason Zhu #endif 10223cf98fbSJason Zhu 10323cf98fbSJason Zhu int spl_mtd_load_image(struct spl_image_info *spl_image, 10423cf98fbSJason Zhu struct spl_boot_device *bootdev) 10523cf98fbSJason Zhu { 106d300a216SJason Zhu struct image_header *header; 10723cf98fbSJason Zhu struct blk_desc *desc; 108d300a216SJason Zhu int ret = -1; 109*516562c2SJason Zhu lbaint_t image_sector = CONFIG_MTD_BLK_U_BOOT_OFFS; 11023cf98fbSJason Zhu 11123cf98fbSJason Zhu desc = find_mtd_device(spl_mtd_get_device_index(bootdev->boot_device)); 11223cf98fbSJason Zhu if (!desc) 11323cf98fbSJason Zhu return -ENODEV; 114ddb43797SJason Zhu #ifdef CONFIG_SPL_LIBDISK_SUPPORT 115*516562c2SJason Zhu disk_partition_t info; 116*516562c2SJason Zhu 117ddb43797SJason Zhu mtd_blk_map_partitions(desc); 118*516562c2SJason Zhu ret = part_get_info_by_name(desc, PART_UBOOT, &info); 119*516562c2SJason Zhu if (ret > 0) 120*516562c2SJason Zhu image_sector = info.start; 121*516562c2SJason Zhu 122ddb43797SJason Zhu #endif 123d300a216SJason Zhu if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) { 124d300a216SJason Zhu header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - 125d300a216SJason Zhu sizeof(struct image_header)); 126*516562c2SJason Zhu ret = blk_dread(desc, image_sector, 1, header); 127d300a216SJason Zhu if (ret != 1) 128d300a216SJason Zhu return -ENODEV; 129d300a216SJason Zhu 130d300a216SJason Zhu #ifdef CONFIG_SPL_FIT_IMAGE_MULTIPLE 131d300a216SJason Zhu if (image_get_magic(header) == FDT_MAGIC || 132d300a216SJason Zhu CONFIG_SPL_FIT_IMAGE_MULTIPLE > 1) { 133d300a216SJason Zhu #else 134d300a216SJason Zhu if (image_get_magic(header) == FDT_MAGIC) { 135d300a216SJason Zhu #endif 136d300a216SJason Zhu struct spl_load_info load; 137d300a216SJason Zhu 138d300a216SJason Zhu load.dev = desc; 139d300a216SJason Zhu load.priv = NULL; 140d300a216SJason Zhu load.filename = NULL; 141d300a216SJason Zhu load.bl_len = desc->blksz; 142d300a216SJason Zhu load.read = mtd_spl_load_read; 143d300a216SJason Zhu 144d300a216SJason Zhu ret = spl_load_simple_fit(spl_image, &load, 145*516562c2SJason Zhu image_sector, 146d300a216SJason Zhu header); 147d300a216SJason Zhu } 14844da3fa1SJason Zhu } 149d300a216SJason Zhu 15044da3fa1SJason Zhu if (!ret) 15144da3fa1SJason Zhu return 0; 15244da3fa1SJason Zhu 15344da3fa1SJason Zhu if (IS_ENABLED(CONFIG_SPL_LOAD_RKFW)) { 15423cf98fbSJason Zhu #ifdef CONFIG_SPL_LOAD_RKFW 15523cf98fbSJason Zhu ret = spl_mtd_load_rkfw(spl_image, desc); 15623cf98fbSJason Zhu #endif 157d300a216SJason Zhu } 158d300a216SJason Zhu 15923cf98fbSJason Zhu return ret; 16023cf98fbSJason Zhu } 16123cf98fbSJason Zhu 16223cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD1", 0, BOOT_DEVICE_MTD_BLK_NAND, spl_mtd_load_image); 16323cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD2", 0, BOOT_DEVICE_MTD_BLK_SPI_NAND, spl_mtd_load_image); 16423cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD3", 0, BOOT_DEVICE_MTD_BLK_SPI_NOR, spl_mtd_load_image); 165