1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <blk.h> 8 #include <boot_rkimg.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <image.h> 12 #include <malloc.h> 13 #include <mtd_blk.h> 14 #include <part.h> 15 #include <spl.h> 16 #include <spl_ab.h> 17 #include <spl_rkfw.h> 18 #include <asm/u-boot.h> 19 #include <dm/device-internal.h> 20 #include <linux/compiler.h> 21 #include <linux/mtd/mtd.h> 22 23 static int spl_mtd_get_device_index(u32 boot_device) 24 { 25 switch (boot_device) { 26 case BOOT_DEVICE_MTD_BLK_NAND: 27 return 0; 28 case BOOT_DEVICE_MTD_BLK_SPI_NAND: 29 return 1; 30 case BOOT_DEVICE_MTD_BLK_SPI_NOR: 31 return 2; 32 } 33 34 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 35 printf("spl: unsupported mtd boot device.\n"); 36 #endif 37 38 return -ENODEV; 39 } 40 41 struct blk_desc *find_mtd_device(int dev_num) 42 { 43 struct udevice *dev; 44 struct blk_desc *desc; 45 int ret; 46 47 ret = blk_find_device(IF_TYPE_MTD, dev_num, &dev); 48 49 if (ret) { 50 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) 51 printf("MTD Device %d not found\n", dev_num); 52 #endif 53 return NULL; 54 } 55 56 ret = device_probe(dev); 57 if (ret) { 58 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) 59 printf("MTD Device %d not found\n", dev_num); 60 #endif 61 return NULL; 62 } 63 64 desc = dev_get_uclass_platdata(dev); 65 if (!desc) 66 return NULL; 67 68 return desc; 69 } 70 71 static ulong mtd_spl_load_read(struct spl_load_info *load, ulong sector, 72 ulong count, void *buf) 73 { 74 struct blk_desc *desc = load->dev; 75 76 return blk_dread(desc, sector, count, buf); 77 } 78 79 #ifdef CONFIG_SPL_LOAD_RKFW 80 int spl_mtd_load_rkfw(struct spl_image_info *spl_image, struct blk_desc *desc) 81 { 82 struct spl_load_info load; 83 int ret; 84 85 load.dev = desc; 86 load.priv = NULL; 87 load.filename = NULL; 88 load.bl_len = desc->blksz; 89 load.read = mtd_spl_load_read; 90 91 ret = spl_load_rkfw_image(spl_image, &load); 92 if (ret) { 93 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 94 puts("spl_mtd_load_rkfw: mtd block read error\n"); 95 #endif 96 return -1; 97 } 98 99 return 0; 100 } 101 #endif 102 103 int spl_mtd_load_image(struct spl_image_info *spl_image, 104 struct spl_boot_device *bootdev) 105 { 106 struct image_header *header; 107 struct blk_desc *desc; 108 int ret = -1; 109 lbaint_t image_sector = CONFIG_MTD_BLK_U_BOOT_OFFS; 110 111 desc = find_mtd_device(spl_mtd_get_device_index(bootdev->boot_device)); 112 if (!desc) 113 return -ENODEV; 114 #ifdef CONFIG_SPL_LIBDISK_SUPPORT 115 disk_partition_t info; 116 117 mtd_blk_map_partitions(desc); 118 ret = part_get_info_by_name(desc, PART_UBOOT, &info); 119 if (ret > 0) 120 image_sector = info.start; 121 122 #endif 123 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) { 124 header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - 125 sizeof(struct image_header)); 126 ret = blk_dread(desc, image_sector, 1, header); 127 if (ret != 1) 128 return -ENODEV; 129 130 #ifdef CONFIG_SPL_FIT_IMAGE_MULTIPLE 131 if (image_get_magic(header) == FDT_MAGIC || 132 CONFIG_SPL_FIT_IMAGE_MULTIPLE > 1) { 133 #else 134 if (image_get_magic(header) == FDT_MAGIC) { 135 #endif 136 struct spl_load_info load; 137 138 load.dev = desc; 139 load.priv = NULL; 140 load.filename = NULL; 141 load.bl_len = desc->blksz; 142 load.read = mtd_spl_load_read; 143 144 ret = spl_load_simple_fit(spl_image, &load, 145 image_sector, 146 header); 147 } 148 } 149 150 if (!ret) 151 return 0; 152 153 if (IS_ENABLED(CONFIG_SPL_LOAD_RKFW)) { 154 #ifdef CONFIG_SPL_LOAD_RKFW 155 ret = spl_mtd_load_rkfw(spl_image, desc); 156 #endif 157 } 158 159 return ret; 160 } 161 162 SPL_LOAD_IMAGE_METHOD("MTD0", 0, BOOT_DEVICE_MTD_BLK_NAND, spl_mtd_load_image); 163 SPL_LOAD_IMAGE_METHOD("MTD1", 0, BOOT_DEVICE_MTD_BLK_SPI_NAND, spl_mtd_load_image); 164 SPL_LOAD_IMAGE_METHOD("MTD2", 0, BOOT_DEVICE_MTD_BLK_SPI_NOR, spl_mtd_load_image); 165