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