xref: /rk3399_rockchip-uboot/drivers/rknand/rknand.c (revision 5ce558eee1d84a2b85f2bbc4c4547c8ea1c1dae4)
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