1 /* 2 * Copyright (C) (C) Copyright 2016-2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <asm/arch/vendor.h> 9 #include <dm.h> 10 #include <dm/device-internal.h> 11 #include <dm/lists.h> 12 #include <dm/root.h> 13 #include "rknand.h" 14 15 struct blk_desc *rknand_get_blk_desc(struct rknand_dev *ndev) 16 { 17 struct blk_desc *desc; 18 struct udevice *dev; 19 20 device_find_first_child(ndev->dev, &dev); 21 if (!dev) 22 return NULL; 23 desc = dev_get_uclass_platdata(dev); 24 25 return desc; 26 } 27 28 ulong rknand_bread(struct udevice *udev, lbaint_t start, 29 lbaint_t blkcnt, void *dst) 30 { 31 struct blk_desc *block_dev = dev_get_uclass_platdata(udev); 32 struct rknand_dev *ndev = dev_get_priv(udev->parent); 33 int err; 34 35 if (blkcnt == 0) 36 return 0; 37 38 if ((start + blkcnt) > block_dev->lba) 39 return 0; 40 41 if (ndev->read == NULL) 42 return 0; 43 44 err = ndev->read(0, (u32)start, (u32)blkcnt, dst); 45 if (err) 46 return err; 47 48 return blkcnt; 49 } 50 51 ulong rknand_bwrite(struct udevice *udev, lbaint_t start, 52 lbaint_t blkcnt, const void *src) 53 { 54 struct blk_desc *block_dev = dev_get_uclass_platdata(udev); 55 struct rknand_dev *ndev = dev_get_priv(udev->parent); 56 int err; 57 58 if (blkcnt == 0) 59 return 0; 60 61 if ((start + blkcnt) > block_dev->lba) 62 return 0; 63 64 if (ndev->write == NULL) 65 return 0; 66 67 err = ndev->write(0, (u32)start, (u32)blkcnt, src); 68 if (err) 69 return err; 70 71 return blkcnt; 72 } 73 74 ulong rknand_berase(struct udevice *udev, lbaint_t start, 75 lbaint_t blkcnt) 76 { 77 struct blk_desc *block_dev = dev_get_uclass_platdata(udev); 78 struct rknand_dev *ndev = dev_get_priv(udev->parent); 79 int err; 80 81 if (blkcnt == 0) 82 return 0; 83 84 if ((start + blkcnt) > block_dev->lba) 85 return 0; 86 87 if (ndev->erase == NULL) 88 return 0; 89 90 err = ndev->erase(0, (u32)start, (u32)blkcnt); 91 if (err) 92 return err; 93 94 return blkcnt; 95 } 96 97 int rkftl_nand_vendor_read(struct blk_desc *dev_desc, 98 u32 index, 99 u32 n_sec, 100 void *p_data) 101 { 102 int ret; 103 104 ret = ftl_vendor_read(index, n_sec, p_data); 105 if (!ret) 106 return n_sec; 107 else 108 return -EIO; 109 } 110 111 int rkftl_nand_vendor_write(struct blk_desc *dev_desc, 112 u32 index, 113 u32 n_sec, 114 void *p_data) 115 { 116 int ret; 117 118 ret = ftl_vendor_write(index, n_sec, p_data); 119 if (!ret) 120 return n_sec; 121 else 122 return -EIO; 123 } 124 125 int rknand_scan_namespace(void) 126 { 127 struct uclass *uc; 128 struct udevice *dev; 129 int ret; 130 131 ret = uclass_get(UCLASS_RKNAND, &uc); 132 if (ret) 133 return ret; 134 135 uclass_foreach_dev(dev, uc) { 136 debug("%s %d %p\n", __func__, __LINE__, dev); 137 ret = device_probe(dev); 138 if (ret) 139 return ret; 140 } 141 142 return 0; 143 } 144 145 static int rknand_blk_bind(struct udevice *udev) 146 { 147 struct udevice *bdev; 148 int ret; 149 150 ret = blk_create_devicef(udev, "rknand_blk", "blk", 151 IF_TYPE_RKNAND, 152 0, 512, 0, &bdev); 153 if (ret) { 154 debug("Cannot create block device\n"); 155 return ret; 156 } 157 158 return 0; 159 } 160 161 static int rknand_blk_probe(struct udevice *udev) 162 { 163 struct rknand_dev *ndev = dev_get_priv(udev->parent); 164 struct blk_desc *desc = dev_get_uclass_platdata(udev); 165 166 debug("%s %d %p ndev = %p %p\n", __func__, __LINE__, 167 udev, ndev, udev->parent); 168 ndev->dev = udev; 169 desc->if_type = IF_TYPE_RKNAND; 170 desc->lba = ndev->density; 171 desc->log2blksz = 9; 172 desc->blksz = 512; 173 desc->bdev = udev; 174 desc->devnum = 0; 175 sprintf(desc->vendor, "0x%.4x", 0x2207); 176 memcpy(desc->product, "rknand", sizeof("rknand")); 177 memcpy(desc->revision, "V1.00", sizeof("V1.00")); 178 part_init(desc); 179 return 0; 180 } 181 182 static int rockchip_nand_probe(struct udevice *udev) 183 { 184 int ret; 185 struct rknand_dev *ndev = dev_get_priv(udev); 186 187 ndev->ioaddr = dev_read_addr_ptr(udev); 188 ret = rk_ftl_init(ndev->ioaddr); 189 if (!ret) { 190 ndev->density = ftl_get_density(0); 191 ndev->read = ftl_read; 192 ndev->write = ftl_write; 193 ndev->erase = ftl_discard; 194 #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 195 flash_vendor_dev_ops_register(rkftl_nand_vendor_read, 196 rkftl_nand_vendor_write); 197 #endif 198 } 199 200 return ret; 201 } 202 203 static const struct blk_ops rknand_blk_ops = { 204 .read = rknand_bread, 205 #ifndef CONFIG_SPL_BUILD 206 .write = rknand_bwrite, 207 .erase = rknand_berase, 208 #endif 209 }; 210 211 static const struct udevice_id rockchip_nand_ids[] = { 212 { .compatible = "rockchip,rk-nandc" }, 213 { } 214 }; 215 216 U_BOOT_DRIVER(rknand_blk) = { 217 .name = "rknand_blk", 218 .id = UCLASS_BLK, 219 .ops = &rknand_blk_ops, 220 .probe = rknand_blk_probe, 221 }; 222 223 UCLASS_DRIVER(rknand) = { 224 .id = UCLASS_RKNAND, 225 .name = "rknand", 226 .flags = DM_UC_FLAG_SEQ_ALIAS, 227 .per_device_auto_alloc_size = sizeof(struct rknand_uclass_priv), 228 }; 229 230 U_BOOT_DRIVER(rknand) = { 231 .name = "rknand", 232 .id = UCLASS_RKNAND, 233 .of_match = rockchip_nand_ids, 234 .bind = rknand_blk_bind, 235 .probe = rockchip_nand_probe, 236 .priv_auto_alloc_size = sizeof(struct rknand_dev), 237 }; 238 239