1 /* 2 * (C) Copyright 2019 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <blk.h> 9 #include <boot_rkimg.h> 10 #include <dm.h> 11 #include <errno.h> 12 #include <malloc.h> 13 #include <nand.h> 14 #include <part.h> 15 #include <dm/device-internal.h> 16 17 #define MTD_PART_NAND_HEAD "mtdparts=" 18 #define MTD_PART_INFO_MAX_SIZE 512 19 #define MTD_SINGLE_PART_INFO_MAX_SIZE 40 20 21 char *mtd_part_parse(void) 22 { 23 char mtd_part_info_temp[MTD_SINGLE_PART_INFO_MAX_SIZE] = {0}; 24 u32 length, data_len = MTD_PART_INFO_MAX_SIZE; 25 struct blk_desc *dev_desc; 26 disk_partition_t info; 27 char *mtd_part_info_p; 28 char *mtd_part_info; 29 int ret; 30 int p; 31 32 dev_desc = rockchip_get_bootdev(); 33 if (!dev_desc) 34 return NULL; 35 36 mtd_part_info = (char *)calloc(MTD_PART_INFO_MAX_SIZE, sizeof(char)); 37 if (!mtd_part_info) { 38 printf("%s: Fail to malloc!", __func__); 39 return NULL; 40 } 41 42 mtd_part_info_p = mtd_part_info; 43 snprintf(mtd_part_info_p, data_len - 1, "%s%s:", 44 MTD_PART_NAND_HEAD, 45 dev_desc->product); 46 data_len -= strlen(mtd_part_info_p); 47 mtd_part_info_p = mtd_part_info_p + strlen(mtd_part_info_p); 48 49 for (p = 1; p < MAX_SEARCH_PARTITIONS; p++) { 50 ret = part_get_info(dev_desc, p, &info); 51 if (ret) 52 break; 53 54 debug("name is %s, start addr is %x\n", info.name, 55 (int)(size_t)info.start); 56 57 snprintf(mtd_part_info_p, data_len - 1, "0x%x@0x%x(%s)", 58 (int)(size_t)info.size << 9, 59 (int)(size_t)info.start << 9, 60 info.name); 61 snprintf(mtd_part_info_temp, MTD_SINGLE_PART_INFO_MAX_SIZE - 1, 62 "0x%x@0x%x(%s)", 63 (int)(size_t)info.size << 9, 64 (int)(size_t)info.start << 9, 65 info.name); 66 strcat(mtd_part_info, ","); 67 if (part_get_info(dev_desc, p + 1, &info)) { 68 snprintf(mtd_part_info_p, data_len - 1, "-@0x%x(%s)", 69 (int)(size_t)info.start << 9, 70 info.name); 71 break; 72 } 73 length = strlen(mtd_part_info_temp); 74 data_len -= length; 75 mtd_part_info_p = mtd_part_info_p + length + 1; 76 memset(mtd_part_info_temp, 0, MTD_SINGLE_PART_INFO_MAX_SIZE); 77 } 78 79 return mtd_part_info; 80 } 81 82 ulong mtd_dread(struct udevice *udev, lbaint_t start, 83 lbaint_t blkcnt, void *dst) 84 { 85 struct blk_desc *desc = dev_get_uclass_platdata(udev); 86 87 if (!desc) 88 return 0; 89 90 if (blkcnt == 0) 91 return 0; 92 93 if (desc->devnum == BLK_MTD_NAND) { 94 int ret = 0; 95 size_t rwsize = blkcnt * 512; 96 struct mtd_info *mtd = dev_get_priv(udev->parent); 97 struct nand_chip *chip = mtd_to_nand(mtd); 98 loff_t off = (loff_t)(start * 512); 99 100 if (!mtd) { 101 puts("\nno mtd available\n"); 102 return 0; 103 } 104 105 if (!chip) { 106 puts("\nno chip available\n"); 107 return 0; 108 } 109 110 ret = nand_read_skip_bad(&chip->mtd, off, &rwsize, 111 NULL, chip->mtd.size, 112 (u_char *)(dst)); 113 if (ret) 114 return 0; 115 else 116 return blkcnt; 117 } else if (desc->devnum == BLK_MTD_SPI_NAND) { 118 /* Not implemented */ 119 return 0; 120 } else if (desc->devnum == BLK_MTD_SPI_NOR) { 121 /* Not implemented */ 122 return 0; 123 } else { 124 return 0; 125 } 126 } 127 128 ulong mtd_dwrite(struct udevice *udev, lbaint_t start, 129 lbaint_t blkcnt, const void *src) 130 { 131 /* Not implemented */ 132 return 0; 133 } 134 135 ulong mtd_derase(struct udevice *udev, lbaint_t start, 136 lbaint_t blkcnt) 137 { 138 /* Not implemented */ 139 return 0; 140 } 141 142 static int mtd_blk_probe(struct udevice *udev) 143 { 144 struct blk_desc *desc = dev_get_uclass_platdata(udev); 145 struct mtd_info *mtd = dev_get_priv(udev->parent); 146 147 sprintf(desc->vendor, "0x%.4x", 0x2207); 148 memcpy(desc->product, mtd->name, strlen(mtd->name)); 149 memcpy(desc->revision, "V1.00", sizeof("V1.00")); 150 if (mtd->type == MTD_NANDFLASH) { 151 /* Reserve 4 blocks for BBT(Bad Block Table) */ 152 desc->lba = (mtd->size >> 9) - (mtd->erasesize >> 9) * 4; 153 } else { 154 desc->lba = mtd->size >> 9; 155 } 156 157 return 0; 158 } 159 160 static const struct blk_ops mtd_blk_ops = { 161 .read = mtd_dread, 162 #ifndef CONFIG_SPL_BUILD 163 .write = mtd_dwrite, 164 .erase = mtd_derase, 165 #endif 166 }; 167 168 U_BOOT_DRIVER(mtd_blk) = { 169 .name = "mtd_blk", 170 .id = UCLASS_BLK, 171 .ops = &mtd_blk_ops, 172 .probe = mtd_blk_probe, 173 }; 174