xref: /OK3568_Linux_fs/u-boot/drivers/rknand/rknand.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 
rknand_get_blk_desc(struct rknand_dev * ndev)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 
rknand_bread(struct udevice * udev,lbaint_t start,lbaint_t blkcnt,void * dst)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 
rknand_bwrite(struct udevice * udev,lbaint_t start,lbaint_t blkcnt,const void * src)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 
rknand_berase(struct udevice * udev,lbaint_t start,lbaint_t blkcnt)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 
rkftl_nand_vendor_read(struct blk_desc * dev_desc,u32 index,u32 n_sec,void * p_data)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 
rkftl_nand_vendor_write(struct blk_desc * dev_desc,u32 index,u32 n_sec,void * p_data)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 
rknand_scan_namespace(void)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 
rknand_blk_bind(struct udevice * udev)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 
rknand_blk_probe(struct udevice * udev)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 
rockchip_nand_probe(struct udevice * udev)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 #ifndef CONFIG_SPL_BUILD
195 #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
196 		flash_vendor_dev_ops_register(rkftl_nand_vendor_read,
197 					      rkftl_nand_vendor_write);
198 #endif
199 #endif
200 	}
201 
202 	return ret;
203 }
204 
205 static const struct blk_ops rknand_blk_ops = {
206 	.read	= rknand_bread,
207 	.write	= rknand_bwrite,
208 	.erase	= rknand_berase,
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