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> 1223cf98fbSJason Zhu #include <part.h> 1323cf98fbSJason Zhu #include <spl.h> 1423cf98fbSJason Zhu #include <spl_ab.h> 1523cf98fbSJason Zhu #include <spl_rkfw.h> 1623cf98fbSJason Zhu #include <asm/u-boot.h> 1723cf98fbSJason Zhu #include <dm/device-internal.h> 1823cf98fbSJason Zhu #include <linux/compiler.h> 1923cf98fbSJason Zhu #include <linux/mtd/mtd.h> 2023cf98fbSJason Zhu 2123cf98fbSJason Zhu static int spl_mtd_get_device_index(u32 boot_device) 2223cf98fbSJason Zhu { 2323cf98fbSJason Zhu switch (boot_device) { 2423cf98fbSJason Zhu case BOOT_DEVICE_MTD_BLK_NAND: 2523cf98fbSJason Zhu return 0; 2623cf98fbSJason Zhu case BOOT_DEVICE_MTD_BLK_SPI_NAND: 2723cf98fbSJason Zhu return 1; 2823cf98fbSJason Zhu case BOOT_DEVICE_MTD_BLK_SPI_NOR: 2923cf98fbSJason Zhu return 2; 3023cf98fbSJason Zhu } 3123cf98fbSJason Zhu 3223cf98fbSJason Zhu #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 3323cf98fbSJason Zhu printf("spl: unsupported mtd boot device.\n"); 3423cf98fbSJason Zhu #endif 3523cf98fbSJason Zhu 3623cf98fbSJason Zhu return -ENODEV; 3723cf98fbSJason Zhu } 3823cf98fbSJason Zhu 3923cf98fbSJason Zhu struct blk_desc *find_mtd_device(int dev_num) 4023cf98fbSJason Zhu { 4123cf98fbSJason Zhu struct udevice *dev; 4223cf98fbSJason Zhu struct blk_desc *desc; 4323cf98fbSJason Zhu int ret; 4423cf98fbSJason Zhu 4523cf98fbSJason Zhu ret = blk_find_device(IF_TYPE_MTD, dev_num, &dev); 4623cf98fbSJason Zhu 4723cf98fbSJason Zhu if (ret) { 4823cf98fbSJason Zhu #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) 4923cf98fbSJason Zhu printf("MTD Device %d not found\n", dev_num); 5023cf98fbSJason Zhu #endif 5123cf98fbSJason Zhu return NULL; 5223cf98fbSJason Zhu } 5323cf98fbSJason Zhu 5423cf98fbSJason Zhu ret = device_probe(dev); 5523cf98fbSJason Zhu if (ret) { 5623cf98fbSJason Zhu #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) 5723cf98fbSJason Zhu printf("MTD Device %d not found\n", dev_num); 5823cf98fbSJason Zhu #endif 5923cf98fbSJason Zhu return NULL; 6023cf98fbSJason Zhu } 6123cf98fbSJason Zhu 6223cf98fbSJason Zhu desc = dev_get_uclass_platdata(dev); 6323cf98fbSJason Zhu if (!desc) 6423cf98fbSJason Zhu return NULL; 6523cf98fbSJason Zhu 6623cf98fbSJason Zhu return desc; 6723cf98fbSJason Zhu } 6823cf98fbSJason Zhu 6923cf98fbSJason Zhu #ifdef CONFIG_SPL_LOAD_RKFW 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 7823cf98fbSJason Zhu int spl_mtd_load_rkfw(struct spl_image_info *spl_image, struct blk_desc *desc) 7923cf98fbSJason Zhu { 8023cf98fbSJason Zhu int ret = -1; 8123cf98fbSJason Zhu 8223cf98fbSJason Zhu u32 trust_sectors = CONFIG_RKFW_TRUST_SECTOR; 8323cf98fbSJason Zhu u32 uboot_sectors = CONFIG_RKFW_U_BOOT_SECTOR; 8423cf98fbSJason Zhu struct spl_load_info load; 8523cf98fbSJason Zhu 8623cf98fbSJason Zhu load.dev = desc; 8723cf98fbSJason Zhu load.priv = NULL; 8823cf98fbSJason Zhu load.filename = NULL; 8923cf98fbSJason Zhu load.bl_len = desc->blksz; 9023cf98fbSJason Zhu load.read = mtd_spl_load_read; 9123cf98fbSJason Zhu 9223cf98fbSJason Zhu #ifdef CONFIG_SPL_AB 9323cf98fbSJason Zhu char trust_partition[] = "trust"; 9423cf98fbSJason Zhu char uboot_partition[] = "uboot"; 9523cf98fbSJason Zhu 96*01fc0bcdSJason Zhu spl_get_partitions_sector(desc, trust_partition, 9723cf98fbSJason Zhu &trust_sectors); 98*01fc0bcdSJason Zhu spl_get_partitions_sector(desc, uboot_partition, 9923cf98fbSJason Zhu &uboot_sectors); 10023cf98fbSJason Zhu #endif 10123cf98fbSJason Zhu 10223cf98fbSJason Zhu ret = spl_load_rkfw_image(spl_image, &load, 10323cf98fbSJason Zhu trust_sectors, 10423cf98fbSJason Zhu uboot_sectors); 10523cf98fbSJason Zhu if (ret) { 10623cf98fbSJason Zhu #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 10723cf98fbSJason Zhu puts("spl_mtd_load_rkfw: mtd block read error\n"); 10823cf98fbSJason Zhu #endif 10923cf98fbSJason Zhu return -1; 11023cf98fbSJason Zhu } 11123cf98fbSJason Zhu 11223cf98fbSJason Zhu return ret; 11323cf98fbSJason Zhu } 11423cf98fbSJason Zhu #endif 11523cf98fbSJason Zhu 11623cf98fbSJason Zhu int spl_mtd_load_image(struct spl_image_info *spl_image, 11723cf98fbSJason Zhu struct spl_boot_device *bootdev) 11823cf98fbSJason Zhu { 11923cf98fbSJason Zhu struct blk_desc *desc; 12023cf98fbSJason Zhu int ret = 0; 12123cf98fbSJason Zhu 12223cf98fbSJason Zhu desc = find_mtd_device(spl_mtd_get_device_index(bootdev->boot_device)); 12323cf98fbSJason Zhu if (!desc) 12423cf98fbSJason Zhu return -ENODEV; 12523cf98fbSJason Zhu #ifdef CONFIG_SPL_LOAD_RKFW 12623cf98fbSJason Zhu ret = spl_mtd_load_rkfw(spl_image, desc); 12723cf98fbSJason Zhu #endif 12823cf98fbSJason Zhu return ret; 12923cf98fbSJason Zhu } 13023cf98fbSJason Zhu 13123cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD1", 0, BOOT_DEVICE_MTD_BLK_NAND, spl_mtd_load_image); 13223cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD2", 0, BOOT_DEVICE_MTD_BLK_SPI_NAND, spl_mtd_load_image); 13323cf98fbSJason Zhu SPL_LOAD_IMAGE_METHOD("MTD3", 0, BOOT_DEVICE_MTD_BLK_SPI_NOR, spl_mtd_load_image); 134