]> git.sur5r.net Git - u-boot/blob - drivers/block/blk-uclass.c
Merge branch 'master' of git://git.denx.de/u-boot-video
[u-boot] / drivers / block / blk-uclass.c
1 /*
2  * Copyright (C) 2016 Google, Inc
3  * Written by Simon Glass <sjg@chromium.org>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <blk.h>
10 #include <dm.h>
11 #include <dm/device-internal.h>
12 #include <dm/lists.h>
13
14 int blk_first_device(int if_type, struct udevice **devp)
15 {
16         struct blk_desc *desc;
17         int ret;
18
19         ret = uclass_first_device(UCLASS_BLK, devp);
20         if (ret)
21                 return ret;
22         if (!*devp)
23                 return -ENODEV;
24         do {
25                 desc = dev_get_uclass_platdata(*devp);
26                 if (desc->if_type == if_type)
27                         return 0;
28                 ret = uclass_next_device(devp);
29                 if (ret)
30                         return ret;
31         } while (*devp);
32
33         return -ENODEV;
34 }
35
36 int blk_next_device(struct udevice **devp)
37 {
38         struct blk_desc *desc;
39         int ret, if_type;
40
41         desc = dev_get_uclass_platdata(*devp);
42         if_type = desc->if_type;
43         do {
44                 ret = uclass_next_device(devp);
45                 if (ret)
46                         return ret;
47                 if (!*devp)
48                         return -ENODEV;
49                 desc = dev_get_uclass_platdata(*devp);
50                 if (desc->if_type == if_type)
51                         return 0;
52         } while (1);
53 }
54
55 int blk_get_device(int if_type, int devnum, struct udevice **devp)
56 {
57         struct uclass *uc;
58         struct udevice *dev;
59         int ret;
60
61         ret = uclass_get(UCLASS_BLK, &uc);
62         if (ret)
63                 return ret;
64         uclass_foreach_dev(dev, uc) {
65                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
66
67                 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
68                       if_type, devnum, dev->name, desc->if_type, desc->devnum);
69                 if (desc->if_type == if_type && desc->devnum == devnum) {
70                         *devp = dev;
71                         return device_probe(dev);
72                 }
73         }
74
75         return -ENODEV;
76 }
77
78 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
79                         lbaint_t blkcnt, void *buffer)
80 {
81         struct udevice *dev = block_dev->bdev;
82         const struct blk_ops *ops = blk_get_ops(dev);
83
84         if (!ops->read)
85                 return -ENOSYS;
86
87         return ops->read(dev, start, blkcnt, buffer);
88 }
89
90 unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start,
91                          lbaint_t blkcnt, const void *buffer)
92 {
93         struct udevice *dev = block_dev->bdev;
94         const struct blk_ops *ops = blk_get_ops(dev);
95
96         if (!ops->write)
97                 return -ENOSYS;
98
99         return ops->write(dev, start, blkcnt, buffer);
100 }
101
102 unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
103                          lbaint_t blkcnt)
104 {
105         struct udevice *dev = block_dev->bdev;
106         const struct blk_ops *ops = blk_get_ops(dev);
107
108         if (!ops->erase)
109                 return -ENOSYS;
110
111         return ops->erase(dev, start, blkcnt);
112 }
113
114 int blk_prepare_device(struct udevice *dev)
115 {
116         struct blk_desc *desc = dev_get_uclass_platdata(dev);
117
118         part_init(desc);
119
120         return 0;
121 }
122
123 int blk_create_device(struct udevice *parent, const char *drv_name,
124                       const char *name, int if_type, int devnum, int blksz,
125                       lbaint_t size, struct udevice **devp)
126 {
127         struct blk_desc *desc;
128         struct udevice *dev;
129         int ret;
130
131         ret = device_bind_driver(parent, drv_name, name, &dev);
132         if (ret)
133                 return ret;
134         desc = dev_get_uclass_platdata(dev);
135         desc->if_type = if_type;
136         desc->blksz = blksz;
137         desc->lba = size / blksz;
138         desc->part_type = PART_TYPE_UNKNOWN;
139         desc->bdev = dev;
140         desc->devnum = devnum;
141         *devp = dev;
142
143         return 0;
144 }
145
146 int blk_unbind_all(int if_type)
147 {
148         struct uclass *uc;
149         struct udevice *dev, *next;
150         int ret;
151
152         ret = uclass_get(UCLASS_BLK, &uc);
153         if (ret)
154                 return ret;
155         uclass_foreach_dev_safe(dev, next, uc) {
156                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
157
158                 if (desc->if_type == if_type) {
159                         ret = device_remove(dev);
160                         if (ret)
161                                 return ret;
162                         ret = device_unbind(dev);
163                         if (ret)
164                                 return ret;
165                 }
166         }
167
168         return 0;
169 }
170
171 UCLASS_DRIVER(blk) = {
172         .id             = UCLASS_BLK,
173         .name           = "blk",
174         .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc),
175 };