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