diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/ahci.c | 6 | ||||
-rw-r--r-- | drivers/block/ide.c | 86 | ||||
-rw-r--r-- | drivers/core/dump.c | 65 | ||||
-rw-r--r-- | drivers/mmc/mmc-uclass.c | 2 | ||||
-rw-r--r-- | drivers/mmc/mmc_bootdev.c | 33 | ||||
-rw-r--r-- | drivers/mmc/sandbox_mmc.c | 2 | ||||
-rw-r--r-- | drivers/mtd/spi/Kconfig | 8 | ||||
-rw-r--r-- | drivers/mtd/spi/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/spi/sf-uclass.c | 11 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_bootdev.c | 82 | ||||
-rw-r--r-- | drivers/nvme/nvme-uclass.c | 54 | ||||
-rw-r--r-- | drivers/nvme/nvme.c | 5 | ||||
-rw-r--r-- | drivers/scsi/Makefile | 7 | ||||
-rw-r--r-- | drivers/scsi/scsi.c | 32 | ||||
-rw-r--r-- | drivers/scsi/scsi_bootdev.c | 62 | ||||
-rw-r--r-- | drivers/usb/host/usb-uclass.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/usb_bootdev.c | 38 | ||||
-rw-r--r-- | drivers/virtio/virtio-uclass.c | 62 | ||||
-rw-r--r-- | drivers/virtio/virtio_sandbox.c | 16 |
19 files changed, 449 insertions, 125 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index de6131f1d9..272c48b8e5 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -675,6 +675,12 @@ static int ata_scsiop_inquiry(struct ahci_uc_priv *uc_priv, /* Read id from sata */ port = pccb->target; + /* If this port number is not valid, give up */ + if (!(uc_priv->port_map & (1 << port))) { + debug("Port %x not valid in map %x\n", port, uc_priv->port_map); + return -ENODEV; + } + if (ahci_device_data_io(uc_priv, port, (u8 *)&fis, sizeof(fis), (u8 *)tmpid, ATA_ID_WORDS * 2, 0)) { debug("scsi_ahci: SCSI inquiry command failure.\n"); diff --git a/drivers/block/ide.c b/drivers/block/ide.c index eaa58d859c..1ad9b6c126 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -9,6 +9,7 @@ #include <common.h> #include <ata.h> #include <blk.h> +#include <bootdev.h> #include <dm.h> #include <ide.h> #include <log.h> @@ -443,9 +444,6 @@ static void atapi_inquiry(struct blk_desc *dev_desc) device = dev_desc->devnum; dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ -#ifndef CONFIG_BLK - dev_desc->block_read = atapi_read; -#endif memset(ccb, 0, sizeof(ccb)); memset(iobuf, 0, sizeof(iobuf)); @@ -692,6 +690,7 @@ __weak unsigned char ide_inb(int dev, int port) void ide_init(void) { + struct udevice *dev; unsigned char c; int i, bus; @@ -759,29 +758,14 @@ void ide_init(void) ide_dev_desc[i].log2blksz = LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); ide_dev_desc[i].lba = 0; -#ifndef CONFIG_BLK - ide_dev_desc[i].block_read = ide_read; - ide_dev_desc[i].block_write = ide_write; -#endif if (!ide_bus_ok[IDE_BUS(i)]) continue; ide_ident(&ide_dev_desc[i]); dev_print(&ide_dev_desc[i]); - -#ifndef CONFIG_BLK - if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { - /* initialize partition type */ - part_init(&ide_dev_desc[i]); - } -#endif } schedule(); -#ifdef CONFIG_BLK - struct udevice *dev; - uclass_first_device(UCLASS_IDE, &dev); -#endif } __weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) @@ -830,17 +814,10 @@ __weak void ide_input_data(int dev, ulong *sect_buf, int words) } } -#ifdef CONFIG_BLK ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer) -#else -ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -#endif { -#ifdef CONFIG_BLK struct blk_desc *block_dev = dev_get_uclass_plat(dev); -#endif int device = block_dev->devnum; ulong n = 0; unsigned char c; @@ -957,17 +934,10 @@ IDE_READ_E: return n; } -#ifdef CONFIG_BLK ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, const void *buffer) -#else -ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - const void *buffer) -#endif { -#ifdef CONFIG_BLK struct blk_desc *block_dev = dev_get_uclass_plat(dev); -#endif int device = block_dev->devnum; ulong n = 0; unsigned char c; @@ -1056,7 +1026,6 @@ int ide_device_present(int dev) } #endif -#ifdef CONFIG_BLK static int ide_blk_probe(struct udevice *udev) { struct blk_desc *desc = dev_get_uclass_plat(udev); @@ -1087,6 +1056,45 @@ U_BOOT_DRIVER(ide_blk) = { .probe = ide_blk_probe, }; +static int ide_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_5_SCAN_SLOW; + + return 0; +} + +static int ide_bootdev_hunt(struct bootdev_hunter *info, bool show) +{ + ide_init(); + + return 0; +} + +struct bootdev_ops ide_bootdev_ops = { +}; + +static const struct udevice_id ide_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-ide" }, + { } +}; + +U_BOOT_DRIVER(ide_bootdev) = { + .name = "ide_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &ide_bootdev_ops, + .bind = ide_bootdev_bind, + .of_match = ide_bootdev_ids, +}; + +BOOTDEV_HUNTER(ide_bootdev_hunter) = { + .prio = BOOTDEVP_5_SCAN_SLOW, + .uclass = UCLASS_IDE, + .hunt = ide_bootdev_hunt, + .drv = DM_DRIVER_REF(ide_bootdev), +}; + static int ide_probe(struct udevice *udev) { struct udevice *blk_dev; @@ -1118,6 +1126,10 @@ static int ide_probe(struct udevice *udev) ret = blk_probe_or_unbind(blk_dev); if (ret) return ret; + + ret = bootdev_setup_for_dev(udev, "ide_bootdev"); + if (ret) + return log_msg_ret("bootdev", ret); } } @@ -1141,11 +1153,3 @@ UCLASS_DRIVER(ide) = { .name = "ide", .id = UCLASS_IDE, }; -#else -U_BOOT_LEGACY_BLK(ide) = { - .uclass_idname = "ide", - .uclass_id = UCLASS_IDE, - .max_devs = CONFIG_SYS_IDE_MAXDEVICE, - .desc = ide_dev_desc, -}; -#endif diff --git a/drivers/core/dump.c b/drivers/core/dump.c index 1c1f7e4d30..0c7d2ec4d0 100644 --- a/drivers/core/dump.c +++ b/drivers/core/dump.c @@ -5,12 +5,34 @@ #include <common.h> #include <dm.h> +#include <malloc.h> #include <mapmem.h> +#include <sort.h> #include <dm/root.h> #include <dm/util.h> #include <dm/uclass-internal.h> -static void show_devices(struct udevice *dev, int depth, int last_flag) +/** + * struct sort_info - information used for sorting + * + * @dev: List of devices + * @alloced: Maximum number of devices in @dev + */ +struct sort_info { + struct udevice **dev; + int size; +}; + +static int h_cmp_uclass_id(const void *d1, const void *d2) +{ + const struct udevice *const *dev1 = d1; + const struct udevice *const *dev2 = d2; + + return device_get_uclass_id(*dev1) - device_get_uclass_id(*dev2); +} + +static void show_devices(struct udevice *dev, int depth, int last_flag, + struct udevice **devs) { int i, is_last; struct udevice *child; @@ -39,21 +61,52 @@ static void show_devices(struct udevice *dev, int depth, int last_flag) printf("%s\n", dev->name); - device_foreach_child(child, dev) { - is_last = list_is_last(&child->sibling_node, &dev->child_head); - show_devices(child, depth + 1, (last_flag << 1) | is_last); + if (devs) { + int count; + int i; + + count = 0; + device_foreach_child(child, dev) + devs[count++] = child; + qsort(devs, count, sizeof(struct udevice *), h_cmp_uclass_id); + + for (i = 0; i < count; i++) { + show_devices(devs[i], depth + 1, + (last_flag << 1) | (i == count - 1), + devs + count); + } + } else { + device_foreach_child(child, dev) { + is_last = list_is_last(&child->sibling_node, + &dev->child_head); + show_devices(child, depth + 1, + (last_flag << 1) | is_last, NULL); + } } } -void dm_dump_tree(void) +void dm_dump_tree(bool sort) { struct udevice *root; root = dm_root(); if (root) { + int dev_count, uclasses; + struct udevice **devs = NULL; + + dm_get_stats(&dev_count, &uclasses); + printf(" Class Index Probed Driver Name\n"); printf("-----------------------------------------------------------\n"); - show_devices(root, -1, 0); + if (sort) { + devs = calloc(dev_count, sizeof(struct udevice *)); + if (!devs) { + printf("(out of memory)\n"); + return; + } + } + show_devices(root, -1, 0, devs); + free(devs); } } diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 759a6b728c..01d9b0201f 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -421,7 +421,7 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) mmc->cfg = cfg; mmc->priv = dev; - ret = bootdev_setup_for_dev(dev, "mmc_bootdev"); + ret = bootdev_setup_sibling_blk(bdev, "mmc_bootdev"); if (ret) return log_msg_ret("bootdev", ret); diff --git a/drivers/mmc/mmc_bootdev.c b/drivers/mmc/mmc_bootdev.c index b4f41fb3a6..b57b8a6227 100644 --- a/drivers/mmc/mmc_bootdev.c +++ b/drivers/mmc/mmc_bootdev.c @@ -11,41 +11,16 @@ #include <dm.h> #include <mmc.h> -static int mmc_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, - struct bootflow *bflow) -{ - struct udevice *mmc_dev = dev_get_parent(dev); - struct udevice *blk; - int ret; - - ret = mmc_get_blk(mmc_dev, &blk); - /* - * If there is no media, indicate that no more partitions should be - * checked - */ - if (ret == -EOPNOTSUPP) - ret = -ESHUTDOWN; - if (ret) - return log_msg_ret("blk", ret); - assert(blk); - ret = bootdev_find_in_blk(dev, blk, iter, bflow); - if (ret) - return log_msg_ret("find", ret); - - return 0; -} - static int mmc_bootdev_bind(struct udevice *dev) { struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); - ucp->prio = BOOTDEVP_0_INTERNAL_FAST; + ucp->prio = BOOTDEVP_2_INTERNAL_FAST; return 0; } struct bootdev_ops mmc_bootdev_ops = { - .get_bootflow = mmc_get_bootflow, }; static const struct udevice_id mmc_bootdev_ids[] = { @@ -60,3 +35,9 @@ U_BOOT_DRIVER(mmc_bootdev) = { .bind = mmc_bootdev_bind, .of_match = mmc_bootdev_ids, }; + +BOOTDEV_HUNTER(mmc_bootdev_hunter) = { + .prio = BOOTDEVP_2_INTERNAL_FAST, + .uclass = UCLASS_MMC, + .drv = DM_DRIVER_REF(mmc_bootdev), +}; diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index ba79a5565c..0ba7940a4d 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -183,7 +183,7 @@ static int sandbox_mmc_probe(struct udevice *dev) priv->csize = 0; priv->size = (priv->csize + 1) * SIZE_MULTIPLE; /* 1 MiB */ - priv->buf = malloc(priv->size); + priv->buf = calloc(1, priv->size); if (!priv->buf) { log_err("%s: Not enough memory (%x bytes)\n", dev->name, priv->size); diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index 7b858a3a91..a9617c6c58 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -80,6 +80,14 @@ config SF_DEFAULT_SPEED if SPI_FLASH +config BOOTDEV_SPI_FLASH + bool "SPI Flash bootdev support" + help + Enable a boot device for SPI flash. This allows reading a script + from SPI flash so that it can be used to boot an Operating System. + + If unsure, say N + config SPI_FLASH_SFDP_SUPPORT bool "SFDP table parsing support for SPI NOR flashes" depends on !SPI_FLASH_BAR diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 99cc418552..409395382f 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_SPI_FLASH) += spi-nor.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o +obj-$(CONFIG_$(SPL_TPL_)BOOTDEV_SPI_FLASH) += sf_bootdev.o diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index e6e650ef8c..df1f75390c 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -6,6 +6,7 @@ #define LOG_CATEGORY UCLASS_SPI_FLASH #include <common.h> +#include <bootdev.h> #include <dm.h> #include <log.h> #include <malloc.h> @@ -13,6 +14,7 @@ #include <spi_flash.h> #include <asm/global_data.h> #include <dm/device-internal.h> +#include <test/test.h> #include "sf_internal.h" DECLARE_GLOBAL_DATA_PTR; @@ -86,6 +88,14 @@ int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, static int spi_flash_post_bind(struct udevice *dev) { + int ret; + + if (CONFIG_IS_ENABLED(BOOTDEV_SPI_FLASH) && test_sf_bootdev_enabled()) { + ret = bootdev_setup_for_dev(dev, "sf_bootdev"); + if (ret) + return log_msg_ret("bd", ret); + } + #if defined(CONFIG_NEEDS_MANUAL_RELOC) struct dm_spi_flash_ops *ops = sf_get_ops(dev); static int reloc_done; @@ -101,6 +111,7 @@ static int spi_flash_post_bind(struct udevice *dev) reloc_done++; } #endif + return 0; } diff --git a/drivers/mtd/spi/sf_bootdev.c b/drivers/mtd/spi/sf_bootdev.c new file mode 100644 index 0000000000..d6b47b11ce --- /dev/null +++ b/drivers/mtd/spi/sf_bootdev.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Read a bootflow from SPI flash + * + * Copyright 2022 Google LLC + */ + +#include <common.h> +#include <bootdev.h> +#include <bootflow.h> +#include <bootmeth.h> +#include <dm.h> +#include <env.h> +#include <malloc.h> +#include <spi_flash.h> + +static int sf_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow) +{ + struct udevice *sf = dev_get_parent(dev); + uint size; + char *buf; + int ret; + + /* We only support the whole device, not partitions */ + if (iter->part) + return log_msg_ret("max", -ESHUTDOWN); + + size = env_get_hex("script_size_f", 0); + if (!size) + return log_msg_ret("sz", -EINVAL); + + buf = malloc(size + 1); + if (!buf) + return log_msg_ret("buf", -ENOMEM); + + ret = spi_flash_read_dm(sf, env_get_hex("script_offset_f", 0), + size, buf); + if (ret) + return log_msg_ret("cmd", -EINVAL); + bflow->state = BOOTFLOWST_MEDIA; + + ret = bootmeth_set_bootflow(bflow->method, bflow, buf, size); + if (ret) { + free(buf); + return log_msg_ret("method", ret); + } + + return 0; +} + +static int sf_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_4_SCAN_FAST; + + return 0; +} + +struct bootdev_ops sf_bootdev_ops = { + .get_bootflow = sf_get_bootflow, +}; + +static const struct udevice_id sf_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-sf" }, + { } +}; + +U_BOOT_DRIVER(sf_bootdev) = { + .name = "sf_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &sf_bootdev_ops, + .bind = sf_bootdev_bind, + .of_match = sf_bootdev_ids, +}; + +BOOTDEV_HUNTER(sf_bootdev_hunter) = { + .prio = BOOTDEVP_4_SCAN_FAST, + .uclass = UCLASS_SPI_FLASH, + .drv = DM_DRIVER_REF(sf_bootdev), +}; diff --git a/drivers/nvme/nvme-uclass.c b/drivers/nvme/nvme-uclass.c index 239a92abba..f3af6a27b6 100644 --- a/drivers/nvme/nvme-uclass.c +++ b/drivers/nvme/nvme-uclass.c @@ -7,9 +7,63 @@ #define LOG_CATEGORY UCLASS_NVME #include <common.h> +#include <bootdev.h> #include <dm.h> +#include <init.h> +#include <log.h> +#include <nvme.h> + +static int nvme_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_4_SCAN_FAST; + + return 0; +} + +static int nvme_bootdev_hunt(struct bootdev_hunter *info, bool show) +{ + int ret; + + /* init PCI first since this is often used to provide NVMe */ + if (IS_ENABLED(CONFIG_PCI)) { + ret = pci_init(); + if (ret) + log_warning("Failed to init PCI (%dE)\n", ret); + } + + ret = nvme_scan_namespace(); + if (ret) + return log_msg_ret("scan", ret); + + return 0; +} UCLASS_DRIVER(nvme) = { .name = "nvme", .id = UCLASS_NVME, }; + +struct bootdev_ops nvme_bootdev_ops = { +}; + +static const struct udevice_id nvme_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-nvme" }, + { } +}; + +U_BOOT_DRIVER(nvme_bootdev) = { + .name = "nvme_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &nvme_bootdev_ops, + .bind = nvme_bootdev_bind, + .of_match = nvme_bootdev_ids, +}; + +BOOTDEV_HUNTER(nvme_bootdev_hunter) = { + .prio = BOOTDEVP_4_SCAN_FAST, + .uclass = UCLASS_NVME, + .hunt = nvme_bootdev_hunt, + .drv = DM_DRIVER_REF(nvme_bootdev), +}; diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 6d0d3f3ca2..74e7a5b011 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -6,6 +6,7 @@ #include <common.h> #include <blk.h> +#include <bootdev.h> #include <cpu_func.h> #include <dm.h> #include <errno.h> @@ -893,6 +894,10 @@ int nvme_init(struct udevice *udev) if (ret) goto free_id; + ret = bootdev_setup_sibling_blk(ns_udev, "nvme_bootdev"); + if (ret) + return log_msg_ret("bootdev", ret); + ret = blk_probe_or_unbind(ns_udev); if (ret) goto free_id; diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index d1b40c6140..d8d6de5909 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -6,6 +6,13 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_DM_SCSI) += scsi-uclass.o obj-$(CONFIG_SCSI) += scsi.o + +ifdef CONFIG_SCSI +ifdef CONFIG_DM_SCSI +obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += scsi_bootdev.o +endif +endif + endif ifdef CONFIG_SPL_BUILD diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index a020a7da23..6caeb3fcdd 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -4,8 +4,11 @@ * Denis Peter, MPL AG Switzerland */ +#define LOG_CATEGORY UCLASS_SCSI + #include <common.h> #include <blk.h> +#include <bootdev.h> #include <bootstage.h> #include <dm.h> #include <env.h> @@ -558,7 +561,7 @@ static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose) struct udevice *bdev; struct blk_desc bd; struct blk_desc *bdesc; - char str[10]; + char str[10], *name; /* * detect the scsi driver to get information about its geometry (block @@ -574,12 +577,16 @@ static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose) * block devices created */ snprintf(str, sizeof(str), "id%dlun%d", id, lun); - ret = blk_create_devicef(dev, "scsi_blk", str, UCLASS_SCSI, -1, + name = strdup(str); + if (!name) + return log_msg_ret("nam", -ENOMEM); + ret = blk_create_devicef(dev, "scsi_blk", name, UCLASS_SCSI, -1, bd.blksz, bd.lba, &bdev); if (ret) { debug("Can't create device\n"); return ret; } + device_set_name_alloced(bdev); bdesc = dev_get_uclass_plat(bdev); bdesc->target = id; @@ -598,7 +605,11 @@ static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose) ret = blk_probe_or_unbind(bdev); if (ret < 0) /* TODO: undo create */ - return ret; + return log_msg_ret("pro", ret); + + ret = bootdev_setup_sibling_blk(bdev, "scsi_bootdev"); + if (ret) + return log_msg_ret("bd", ret); if (verbose) { printf(" Device %d: ", bdesc->devnum); @@ -638,12 +649,23 @@ int scsi_scan(bool verbose) if (verbose) printf("scanning bus for devices...\n"); - blk_unbind_all(UCLASS_SCSI); - ret = uclass_get(UCLASS_SCSI, &uc); if (ret) return ret; + /* remove all children of the SCSI devices */ + uclass_foreach_dev(dev, uc) { + log_debug("unbind %s\n", dev->name); + ret = device_chld_remove(dev, NULL, DM_REMOVE_NORMAL); + if (!ret) + ret = device_chld_unbind(dev, NULL); + if (ret) { + if (verbose) + printf("unable to unbind devices (%dE)\n", ret); + return log_msg_ret("unb", ret); + } + } + uclass_foreach_dev(dev, uc) { ret = scsi_scan_dev(dev, verbose); if (ret) diff --git a/drivers/scsi/scsi_bootdev.c b/drivers/scsi/scsi_bootdev.c new file mode 100644 index 0000000000..991013fe1e --- /dev/null +++ b/drivers/scsi/scsi_bootdev.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootdevice for USB + * + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <bootdev.h> +#include <dm.h> +#include <init.h> +#include <scsi.h> + +static int scsi_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_4_SCAN_FAST; + + return 0; +} + +static int scsi_bootdev_hunt(struct bootdev_hunter *info, bool show) +{ + int ret; + + if (IS_ENABLED(CONFIG_PCI)) { + ret = pci_init(); + if (ret) + return log_msg_ret("pci", ret); + } + + ret = scsi_scan(true); + if (ret) + return log_msg_ret("scs", ret); + + return 0; +} + +struct bootdev_ops scsi_bootdev_ops = { +}; + +static const struct udevice_id scsi_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-scsi" }, + { } +}; + +U_BOOT_DRIVER(scsi_bootdev) = { + .name = "scsi_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &scsi_bootdev_ops, + .bind = scsi_bootdev_bind, + .of_match = scsi_bootdev_ids, +}; + +BOOTDEV_HUNTER(scsi_bootdev_hunter) = { + .prio = BOOTDEVP_4_SCAN_FAST, + .uclass = UCLASS_SCSI, + .hunt = scsi_bootdev_hunt, + .drv = DM_DRIVER_REF(scsi_bootdev), +}; diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index 93c318c3d1..28f7ca9654 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -563,6 +563,8 @@ static int usb_find_and_bind_driver(struct udevice *parent, if (!str) return -ENOMEM; ret = device_bind_driver(parent, "usb_dev_generic_drv", str, devp); + if (!ret) + device_set_name_alloced(*devp); error: debug("%s: No match found: %d\n", __func__, ret); diff --git a/drivers/usb/host/usb_bootdev.c b/drivers/usb/host/usb_bootdev.c index b85f699933..32919f9928 100644 --- a/drivers/usb/host/usb_bootdev.c +++ b/drivers/usb/host/usb_bootdev.c @@ -11,40 +11,21 @@ #include <dm.h> #include <usb.h> -static int usb_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, - struct bootflow *bflow) -{ - struct udevice *blk; - int ret; - - ret = bootdev_get_sibling_blk(dev, &blk); - /* - * If there is no media, indicate that no more partitions should be - * checked - */ - if (ret == -EOPNOTSUPP) - ret = -ESHUTDOWN; - if (ret) - return log_msg_ret("blk", ret); - assert(blk); - ret = bootdev_find_in_blk(dev, blk, iter, bflow); - if (ret) - return log_msg_ret("find", ret); - - return 0; -} - static int usb_bootdev_bind(struct udevice *dev) { struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); - ucp->prio = BOOTDEVP_3_SCAN_SLOW; + ucp->prio = BOOTDEVP_5_SCAN_SLOW; return 0; } +static int usb_bootdev_hunt(struct bootdev_hunter *info, bool show) +{ + return usb_init(); +} + struct bootdev_ops usb_bootdev_ops = { - .get_bootflow = usb_get_bootflow, }; static const struct udevice_id usb_bootdev_ids[] = { @@ -59,3 +40,10 @@ U_BOOT_DRIVER(usb_bootdev) = { .bind = usb_bootdev_bind, .of_match = usb_bootdev_ids, }; + +BOOTDEV_HUNTER(usb_bootdev_hunter) = { + .prio = BOOTDEVP_5_SCAN_SLOW, + .uclass = UCLASS_USB, + .hunt = usb_bootdev_hunt, + .drv = DM_DRIVER_REF(usb_bootdev), +}; diff --git a/drivers/virtio/virtio-uclass.c b/drivers/virtio/virtio-uclass.c index da4f2f26a6..91af412ec1 100644 --- a/drivers/virtio/virtio-uclass.c +++ b/drivers/virtio/virtio-uclass.c @@ -18,6 +18,7 @@ #define LOG_CATEGORY UCLASS_VIRTIO #include <common.h> +#include <bootdev.h> #include <dm.h> #include <log.h> #include <malloc.h> @@ -163,7 +164,7 @@ int virtio_finalize_features(struct udevice *vdev) return ret; if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) { debug("(%s): device refuses features %x\n", vdev->name, status); - return -ENODEV; + return -EINVAL; } return 0; @@ -214,6 +215,7 @@ static int virtio_uclass_post_probe(struct udevice *udev) struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev); char dev_name[30], *str; struct udevice *vdev; + const char *name; int ret; if (uc_priv->device >= VIRTIO_ID_MAX_NUM) { @@ -222,20 +224,19 @@ static int virtio_uclass_post_probe(struct udevice *udev) return 0; } - if (!virtio_drv_name[uc_priv->device]) { + name = virtio_drv_name[uc_priv->device]; + if (!name) { debug("(%s): underlying virtio device driver unavailable\n", udev->name); return 0; } - snprintf(dev_name, sizeof(dev_name), "%s#%d", - virtio_drv_name[uc_priv->device], dev_seq(udev)); + snprintf(dev_name, sizeof(dev_name), "%s#%d", name, dev_seq(udev)); str = strdup(dev_name); if (!str) return -ENOMEM; - ret = device_bind_driver(udev, virtio_drv_name[uc_priv->device], - str, &vdev); + ret = device_bind_driver(udev, name, str, &vdev); if (ret == -ENOENT) { debug("(%s): no driver configured\n", udev->name); return 0; @@ -246,6 +247,12 @@ static int virtio_uclass_post_probe(struct udevice *udev) } device_set_name_alloced(vdev); + if (uc_priv->device == VIRTIO_ID_BLOCK) { + ret = bootdev_setup_for_dev(udev, name); + if (ret) + return log_msg_ret("bootdev", ret); + } + INIT_LIST_HEAD(&uc_priv->vqs); return 0; @@ -349,6 +356,26 @@ static int virtio_uclass_child_post_probe(struct udevice *vdev) return 0; } +static int virtio_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_4_SCAN_FAST; + + return 0; +} + +static int virtio_bootdev_hunt(struct bootdev_hunter *info, bool show) +{ + int ret; + + ret = uclass_probe_all(UCLASS_VIRTIO); + if (ret && ret != -ENOENT) + return log_msg_ret("vir", ret); + + return 0; +} + UCLASS_DRIVER(virtio) = { .name = "virtio", .id = UCLASS_VIRTIO, @@ -360,3 +387,26 @@ UCLASS_DRIVER(virtio) = { .child_post_probe = virtio_uclass_child_post_probe, .per_device_auto = sizeof(struct virtio_dev_priv), }; + +struct bootdev_ops virtio_bootdev_ops = { +}; + +static const struct udevice_id virtio_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-virtio" }, + { } +}; + +U_BOOT_DRIVER(virtio_bootdev) = { + .name = "virtio_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &virtio_bootdev_ops, + .bind = virtio_bootdev_bind, + .of_match = virtio_bootdev_ids, +}; + +BOOTDEV_HUNTER(virtio_bootdev_hunter) = { + .prio = BOOTDEVP_4_SCAN_FAST, + .uclass = UCLASS_VIRTIO, + .hunt = virtio_bootdev_hunt, + .drv = DM_DRIVER_REF(virtio_bootdev), +}; diff --git a/drivers/virtio/virtio_sandbox.c b/drivers/virtio/virtio_sandbox.c index 5484ae3a1a..b34f1d6045 100644 --- a/drivers/virtio/virtio_sandbox.c +++ b/drivers/virtio/virtio_sandbox.c @@ -161,24 +161,13 @@ static int virtio_sandbox_probe(struct udevice *udev) /* fake some information for testing */ priv->device_features = BIT_ULL(VIRTIO_F_VERSION_1); - uc_priv->device = VIRTIO_ID_RNG; + uc_priv->device = dev_read_u32_default(udev, "virtio-type", + VIRTIO_ID_RNG); uc_priv->vendor = ('u' << 24) | ('b' << 16) | ('o' << 8) | 't'; return 0; } -/* check virtio device driver's remove routine was called to reset the device */ -static int virtio_sandbox_child_post_remove(struct udevice *vdev) -{ - u8 status; - - virtio_get_status(vdev, &status); - if (status) - panic("virtio device was not reset\n"); - - return 0; -} - static const struct dm_virtio_ops virtio_sandbox1_ops = { .get_config = virtio_sandbox_get_config, .set_config = virtio_sandbox_set_config, @@ -203,7 +192,6 @@ U_BOOT_DRIVER(virtio_sandbox1) = { .of_match = virtio_sandbox1_ids, .ops = &virtio_sandbox1_ops, .probe = virtio_sandbox_probe, - .child_post_remove = virtio_sandbox_child_post_remove, .priv_auto = sizeof(struct virtio_sandbox_priv), }; |