xref: /rk3399_rockchip-uboot/drivers/rkflash/rkflash_blk.c (revision 1a4f6af8bfd44c8ae6e87a81ff125eed47042cc5)
1ad309a88SDingqiang Lin /*
2ad309a88SDingqiang Lin  * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
3ad309a88SDingqiang Lin  *
4ba0501acSDingqiang Lin  * SPDX-License-Identifier:	GPL-2.0
5ad309a88SDingqiang Lin  */
6ad309a88SDingqiang Lin 
7ad309a88SDingqiang Lin #include <common.h>
8ad309a88SDingqiang Lin #include <dm.h>
9ad309a88SDingqiang Lin #include <dm/device-internal.h>
10ad309a88SDingqiang Lin #include <dm/lists.h>
11ad309a88SDingqiang Lin #include <dm/root.h>
12ad309a88SDingqiang Lin 
13ad309a88SDingqiang Lin #include "rkflash_blk.h"
14ad309a88SDingqiang Lin #include "rkflash_debug.h"
15ad309a88SDingqiang Lin 
rkflash_bread(struct udevice * udev,lbaint_t start,lbaint_t blkcnt,void * dst)16ad309a88SDingqiang Lin ulong rkflash_bread(struct udevice *udev, lbaint_t start,
17ad309a88SDingqiang Lin 		    lbaint_t blkcnt, void *dst)
18ad309a88SDingqiang Lin {
19ad309a88SDingqiang Lin 	struct blk_desc *block_dev = dev_get_uclass_platdata(udev);
20ad309a88SDingqiang Lin 	struct rkflash_info *priv = dev_get_priv(udev->parent);
21ad309a88SDingqiang Lin 
22b331f5a6SDingqiang Lin 	debug("%s lba %x cnt %x\n", __func__, (u32)start, (u32)blkcnt);
23ad309a88SDingqiang Lin 	if (blkcnt == 0)
24*24e0d34aSJon Lin 		return 0;
25ad309a88SDingqiang Lin 
26ad309a88SDingqiang Lin 	if ((start + blkcnt) > block_dev->lba)
27ba0501acSDingqiang Lin 		return -EINVAL;
28ad309a88SDingqiang Lin 
29ad309a88SDingqiang Lin 	if (!priv->read)
30ba0501acSDingqiang Lin 		return -EINVAL;
31ad309a88SDingqiang Lin 
32ad309a88SDingqiang Lin 	return (ulong)priv->read(udev->parent, (u32)start, (u32)blkcnt, dst);
33ad309a88SDingqiang Lin }
34ad309a88SDingqiang Lin 
rkflash_bwrite(struct udevice * udev,lbaint_t start,lbaint_t blkcnt,const void * src)35ad309a88SDingqiang Lin ulong rkflash_bwrite(struct udevice *udev, lbaint_t start,
36ad309a88SDingqiang Lin 		     lbaint_t blkcnt, const void *src)
37ad309a88SDingqiang Lin {
38ad309a88SDingqiang Lin 	struct blk_desc *block_dev = dev_get_uclass_platdata(udev);
39ad309a88SDingqiang Lin 	struct rkflash_info *priv = dev_get_priv(udev->parent);
40ad309a88SDingqiang Lin 
41ad309a88SDingqiang Lin 	if (blkcnt == 0)
42*24e0d34aSJon Lin 		return 0;
43ad309a88SDingqiang Lin 
44ad309a88SDingqiang Lin 	if ((start + blkcnt) > block_dev->lba)
45ba0501acSDingqiang Lin 		return -EINVAL;
46ad309a88SDingqiang Lin 
47ad309a88SDingqiang Lin 	if (!priv->write)
48ba0501acSDingqiang Lin 		return -EINVAL;
49ad309a88SDingqiang Lin 
50ad309a88SDingqiang Lin 	return (ulong)priv->write(udev->parent, (u32)start, (u32)blkcnt, src);
51ad309a88SDingqiang Lin }
52ad309a88SDingqiang Lin 
rkflash_berase(struct udevice * udev,lbaint_t start,lbaint_t blkcnt)53ad309a88SDingqiang Lin ulong rkflash_berase(struct udevice *udev, lbaint_t start,
54ad309a88SDingqiang Lin 		     lbaint_t blkcnt)
55ad309a88SDingqiang Lin {
56ad309a88SDingqiang Lin 	struct blk_desc *block_dev = dev_get_uclass_platdata(udev);
57ad309a88SDingqiang Lin 	struct rkflash_info *priv = dev_get_priv(udev->parent);
58ad309a88SDingqiang Lin 
59ad309a88SDingqiang Lin 	if (blkcnt == 0)
60*24e0d34aSJon Lin 		return 0;
61ad309a88SDingqiang Lin 
62ad309a88SDingqiang Lin 	if ((start + blkcnt) > block_dev->lba)
63ba0501acSDingqiang Lin 		return -EINVAL;
64ad309a88SDingqiang Lin 
65ad309a88SDingqiang Lin 	if (!priv->erase)
66ba0501acSDingqiang Lin 		return -EINVAL;
67ad309a88SDingqiang Lin 
68ad309a88SDingqiang Lin 	return (ulong)priv->erase(udev->parent, (u32)start, (u32)blkcnt);
69ad309a88SDingqiang Lin }
70ad309a88SDingqiang Lin 
rkflash_blk_probe(struct udevice * udev)71ad309a88SDingqiang Lin static int rkflash_blk_probe(struct udevice *udev)
72ad309a88SDingqiang Lin {
73ad309a88SDingqiang Lin 	struct rkflash_info *priv = dev_get_priv(udev->parent);
74ad309a88SDingqiang Lin 	struct blk_desc *desc = dev_get_uclass_platdata(udev);
75b331f5a6SDingqiang Lin 	char *product;
76ad309a88SDingqiang Lin 
77b331f5a6SDingqiang Lin 	if (desc->if_type != priv->flash_con_type)
78b331f5a6SDingqiang Lin 		return  -ENODEV;
79b331f5a6SDingqiang Lin 
80b331f5a6SDingqiang Lin 	switch (priv->flash_con_type) {
81b331f5a6SDingqiang Lin 	case IF_TYPE_RKNAND:
82b331f5a6SDingqiang Lin 		product = "rkflash-NandFlash";
83b331f5a6SDingqiang Lin 		break;
84b331f5a6SDingqiang Lin 	case IF_TYPE_SPINAND:
85b331f5a6SDingqiang Lin 		product = "rkflash-SpiNand";
86b331f5a6SDingqiang Lin 		break;
87b331f5a6SDingqiang Lin 	case IF_TYPE_SPINOR:
88b331f5a6SDingqiang Lin 		product = "rkflash-SpiNor";
89b331f5a6SDingqiang Lin 		break;
90b331f5a6SDingqiang Lin 	default:
91b331f5a6SDingqiang Lin 		product = "unknown";
92b331f5a6SDingqiang Lin 		break;
93b331f5a6SDingqiang Lin 	}
94ad309a88SDingqiang Lin 	debug("%s %d %p ndev = %p %p\n", __func__, __LINE__,
95ad309a88SDingqiang Lin 	      udev, priv, udev->parent);
96ad309a88SDingqiang Lin 	priv->child_dev = udev;
97ad309a88SDingqiang Lin 	desc->lba = priv->density;
98ad309a88SDingqiang Lin 	desc->log2blksz = 9;
99ad309a88SDingqiang Lin 	desc->bdev = udev;
100ad309a88SDingqiang Lin 	sprintf(desc->vendor, "0x%.4x", 0x0308);
101b331f5a6SDingqiang Lin 	memcpy(desc->product, product, strlen(product));
102ad309a88SDingqiang Lin 	memcpy(desc->revision, "V1.00", sizeof("V1.00"));
103ad309a88SDingqiang Lin 	part_init(desc);
104ad309a88SDingqiang Lin 	rkflash_test(udev);
105ad309a88SDingqiang Lin 
106ad309a88SDingqiang Lin 	return 0;
107ad309a88SDingqiang Lin }
108ad309a88SDingqiang Lin 
109ad309a88SDingqiang Lin static const struct blk_ops rkflash_blk_ops = {
110ad309a88SDingqiang Lin 	.read	= rkflash_bread,
111ad309a88SDingqiang Lin 	.write	= rkflash_bwrite,
112ad309a88SDingqiang Lin 	.erase	= rkflash_berase,
113ad309a88SDingqiang Lin };
114ad309a88SDingqiang Lin 
115ad309a88SDingqiang Lin U_BOOT_DRIVER(rkflash_blk) = {
116ad309a88SDingqiang Lin 	.name		= "rkflash_blk",
117ad309a88SDingqiang Lin 	.id		= UCLASS_BLK,
118ad309a88SDingqiang Lin 	.ops		= &rkflash_blk_ops,
119ad309a88SDingqiang Lin 	.probe		= rkflash_blk_probe,
120ad309a88SDingqiang Lin };
121ad309a88SDingqiang Lin 
122