+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
+#include <dm/uclass-internal.h>
static const char *if_typename_str[IF_TYPE_COUNT] = {
[IF_TYPE_IDE] = "ide",
[IF_TYPE_SD] = "sd",
[IF_TYPE_SATA] = "sata",
[IF_TYPE_HOST] = "host",
- [IF_TYPE_SYSTEMACE] = "ace",
+ [IF_TYPE_NVME] = "nvme",
+ [IF_TYPE_EFI] = "efi",
};
static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
- [IF_TYPE_IDE] = UCLASS_INVALID,
+ [IF_TYPE_IDE] = UCLASS_IDE,
[IF_TYPE_SCSI] = UCLASS_SCSI,
[IF_TYPE_ATAPI] = UCLASS_INVALID,
[IF_TYPE_USB] = UCLASS_MASS_STORAGE,
[IF_TYPE_SD] = UCLASS_INVALID,
[IF_TYPE_SATA] = UCLASS_AHCI,
[IF_TYPE_HOST] = UCLASS_ROOT,
- [IF_TYPE_SYSTEMACE] = UCLASS_INVALID,
+ [IF_TYPE_NVME] = UCLASS_NVME,
+ [IF_TYPE_EFI] = UCLASS_EFI,
};
static enum if_type if_typename_to_iftype(const char *if_typename)
return if_type_uclass_id[if_type];
}
+const char *blk_get_if_type_name(enum if_type if_type)
+{
+ return if_typename_str[if_type];
+}
+
struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
{
struct blk_desc *desc;
if (IS_ERR_VALUE(n))
return n;
- /* flush cache after read */
- flush_cache((ulong)buffer, blkcnt * desc->blksz);
-
return n;
}
struct blk_desc *desc;
int ret;
- ret = uclass_first_device(UCLASS_BLK, devp);
+ ret = uclass_find_first_device(UCLASS_BLK, devp);
if (ret)
return ret;
if (!*devp)
desc = dev_get_uclass_platdata(*devp);
if (desc->if_type == if_type)
return 0;
- ret = uclass_next_device(devp);
+ ret = uclass_find_next_device(devp);
if (ret)
return ret;
} while (*devp);
desc = dev_get_uclass_platdata(*devp);
if_type = desc->if_type;
do {
- ret = uclass_next_device(devp);
+ ret = uclass_find_next_device(devp);
if (ret)
return ret;
if (!*devp)
} while (1);
}
-int blk_get_device(int if_type, int devnum, struct udevice **devp)
+int blk_find_device(int if_type, int devnum, struct udevice **devp)
{
struct uclass *uc;
struct udevice *dev;
if_type, devnum, dev->name, desc->if_type, desc->devnum);
if (desc->if_type == if_type && desc->devnum == devnum) {
*devp = dev;
- return device_probe(dev);
+ return 0;
}
}
return -ENODEV;
}
+int blk_get_device(int if_type, int devnum, struct udevice **devp)
+{
+ int ret;
+
+ ret = blk_find_device(if_type, devnum, devp);
+ if (ret)
+ return ret;
+
+ return device_probe(*devp);
+}
+
unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
{
return 0;
}
+int blk_get_from_parent(struct udevice *parent, struct udevice **devp)
+{
+ struct udevice *dev;
+ enum uclass_id id;
+ int ret;
+
+ device_find_first_child(parent, &dev);
+ if (!dev) {
+ debug("%s: No block device found for parent '%s'\n", __func__,
+ parent->name);
+ return -ENODEV;
+ }
+ id = device_get_uclass_id(dev);
+ if (id != UCLASS_BLK) {
+ debug("%s: Incorrect uclass %s for block device '%s'\n",
+ __func__, uclass_get_name(id), dev->name);
+ return -ENOTBLK;
+ }
+ ret = device_probe(dev);
+ if (ret)
+ return ret;
+ *devp = dev;
+
+ return 0;
+}
+
int blk_find_max_devnum(enum if_type if_type)
{
struct udevice *dev;
return max_devnum;
}
+static int blk_next_free_devnum(enum if_type if_type)
+{
+ int ret;
+
+ ret = blk_find_max_devnum(if_type);
+ if (ret == -ENODEV)
+ return 0;
+ if (ret < 0)
+ return ret;
+
+ return ret + 1;
+}
+
+static int blk_claim_devnum(enum if_type if_type, int devnum)
+{
+ struct udevice *dev;
+ struct uclass *uc;
+ int ret;
+
+ ret = uclass_get(UCLASS_BLK, &uc);
+ if (ret)
+ return ret;
+ uclass_foreach_dev(dev, uc) {
+ struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+ if (desc->if_type == if_type && desc->devnum == devnum) {
+ int next = blk_next_free_devnum(if_type);
+
+ if (next < 0)
+ return next;
+ desc->devnum = next;
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
int blk_create_device(struct udevice *parent, const char *drv_name,
const char *name, int if_type, int devnum, int blksz,
- lbaint_t size, struct udevice **devp)
+ lbaint_t lba, struct udevice **devp)
{
struct blk_desc *desc;
struct udevice *dev;
int ret;
if (devnum == -1) {
- ret = blk_find_max_devnum(if_type);
- if (ret == -ENODEV)
- devnum = 0;
- else if (ret < 0)
+ devnum = blk_next_free_devnum(if_type);
+ } else {
+ ret = blk_claim_devnum(if_type, devnum);
+ if (ret < 0 && ret != -ENOENT)
return ret;
- else
- devnum = ret + 1;
}
+ if (devnum < 0)
+ return devnum;
ret = device_bind_driver(parent, drv_name, name, &dev);
if (ret)
return ret;
desc = dev_get_uclass_platdata(dev);
desc->if_type = if_type;
desc->blksz = blksz;
- desc->lba = size / blksz;
+ desc->lba = lba;
desc->part_type = PART_TYPE_UNKNOWN;
desc->bdev = dev;
desc->devnum = devnum;
int blk_create_devicef(struct udevice *parent, const char *drv_name,
const char *name, int if_type, int devnum, int blksz,
- lbaint_t size, struct udevice **devp)
+ lbaint_t lba, struct udevice **devp)
{
char dev_name[30], *str;
int ret;
return -ENOMEM;
ret = blk_create_device(parent, drv_name, str, if_type, devnum,
- blksz, size, devp);
+ blksz, lba, devp);
if (ret) {
free(str);
return ret;
}
device_set_name_alloced(*devp);
- return ret;
+ return 0;
}
int blk_unbind_all(int if_type)
struct blk_desc *desc = dev_get_uclass_platdata(dev);
if (desc->if_type == if_type) {
- ret = device_remove(dev);
+ ret = device_remove(dev, DM_REMOVE_NORMAL);
if (ret)
return ret;
ret = device_unbind(dev);