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> 12ddb43797SJason 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 struct spl_load_info load; 8254ac22e0SJoseph Chen int ret; 8323cf98fbSJason Zhu 8423cf98fbSJason Zhu load.dev = desc; 8523cf98fbSJason Zhu load.priv = NULL; 8623cf98fbSJason Zhu load.filename = NULL; 8723cf98fbSJason Zhu load.bl_len = desc->blksz; 8823cf98fbSJason Zhu load.read = mtd_spl_load_read; 8923cf98fbSJason Zhu 9054ac22e0SJoseph Chen ret = spl_load_rkfw_image(spl_image, &load); 9123cf98fbSJason Zhu if (ret) { 9223cf98fbSJason Zhu #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 9323cf98fbSJason Zhu puts("spl_mtd_load_rkfw: mtd block read error\n"); 9423cf98fbSJason Zhu #endif 9523cf98fbSJason Zhu return -1; 9623cf98fbSJason Zhu } 9723cf98fbSJason Zhu 9854ac22e0SJoseph Chen return 0; 9923cf98fbSJason Zhu } 10023cf98fbSJason Zhu #endif 10123cf98fbSJason Zhu 10223cf98fbSJason Zhu int spl_mtd_load_image(struct spl_image_info *spl_image, 10323cf98fbSJason Zhu struct spl_boot_device *bootdev) 10423cf98fbSJason Zhu { 105d300a216SJason Zhu struct image_header *header; 10623cf98fbSJason Zhu struct blk_desc *desc; 107d300a216SJason Zhu int ret = -1; 10823cf98fbSJason Zhu 10923cf98fbSJason Zhu desc = find_mtd_device(spl_mtd_get_device_index(bootdev->boot_device)); 11023cf98fbSJason Zhu if (!desc) 11123cf98fbSJason Zhu return -ENODEV; 112ddb43797SJason Zhu #ifdef CONFIG_SPL_LIBDISK_SUPPORT 113ddb43797SJason Zhu mtd_blk_map_partitions(desc); 114ddb43797SJason Zhu #endif 115d300a216SJason Zhu if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) { 116d300a216SJason Zhu header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - 117d300a216SJason Zhu sizeof(struct image_header)); 118d300a216SJason Zhu ret = blk_dread(desc, CONFIG_SYS_NAND_U_BOOT_OFFS, 1, header); 119d300a216SJason Zhu if (ret != 1) 120d300a216SJason Zhu return -ENODEV; 121d300a216SJason Zhu 122d300a216SJason Zhu #ifdef CONFIG_SPL_FIT_IMAGE_MULTIPLE 123d300a216SJason Zhu if (image_get_magic(header) == FDT_MAGIC || 124d300a216SJason Zhu CONFIG_SPL_FIT_IMAGE_MULTIPLE > 1) { 125d300a216SJason Zhu #else 126d300a216SJason Zhu if (image_get_magic(header) == FDT_MAGIC) { 127d300a216SJason Zhu #endif 128d300a216SJason Zhu struct spl_load_info load; 129d300a216SJason Zhu 130d300a216SJason Zhu load.dev = desc; 131d300a216SJason Zhu load.priv = NULL; 132d300a216SJason Zhu load.filename = NULL; 133d300a216SJason Zhu load.bl_len = desc->blksz; 134d300a216SJason Zhu load.read = mtd_spl_load_read; 135d300a216SJason Zhu 136d300a216SJason Zhu ret = spl_load_simple_fit(spl_image, &load, 137d300a216SJason Zhu CONFIG_SYS_NAND_U_BOOT_OFFS, 138d300a216SJason Zhu header); 139d300a216SJason Zhu } 140*44da3fa1SJason Zhu } 141d300a216SJason Zhu 142*44da3fa1SJason Zhu if (!ret) 143*44da3fa1SJason Zhu return 0; 144*44da3fa1SJason Zhu 145*44da3fa1SJason Zhu if (IS_ENABLED(CONFIG_SPL_LOAD_RKFW)) { 14623cf98fbSJason Zhu #ifdef CONFIG_SPL_LOAD_RKFW 14723cf98fbSJason Zhu ret = spl_mtd_load_rkfw(spl_image, desc); 14823cf98fbSJason Zhu #endif 149d300a216SJason Zhu } 150d300a216SJason Zhu 15123cf98fbSJason Zhu return ret; 15223cf98fbSJason Zhu } 15323cf98fbSJason Zhu 15423cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD1", 0, BOOT_DEVICE_MTD_BLK_NAND, spl_mtd_load_image); 15523cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD2", 0, BOOT_DEVICE_MTD_BLK_SPI_NAND, spl_mtd_load_image); 15623cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD3", 0, BOOT_DEVICE_MTD_BLK_SPI_NOR, spl_mtd_load_image); 157