diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/core/device-remove.c | 9 | ||||
-rw-r--r-- | drivers/core/device.c | 13 | ||||
-rw-r--r-- | drivers/core/of_access.c | 3 | ||||
-rw-r--r-- | drivers/core/ofnode.c | 26 | ||||
-rw-r--r-- | drivers/core/read.c | 6 | ||||
-rw-r--r-- | drivers/core/uclass.c | 29 | ||||
-rw-r--r-- | drivers/mmc/mmc-uclass.c | 4 | ||||
-rw-r--r-- | drivers/mmc/sandbox_mmc.c | 60 |
8 files changed, 128 insertions, 22 deletions
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c index 11d3959..69c50da 100644 --- a/drivers/core/device-remove.c +++ b/drivers/core/device-remove.c @@ -95,6 +95,9 @@ int device_unbind(struct udevice *dev) if (ret) return log_msg_ret("child unbind", ret); + ret = uclass_pre_unbind_device(dev); + if (ret) + return log_msg_ret("uc", ret); if (dev_get_flags(dev) & DM_FLAG_ALLOC_PDATA) { free(dev_get_plat(dev)); dev_set_plat(dev, NULL); @@ -142,10 +145,8 @@ void device_free(struct udevice *dev) } if (dev->parent) { size = dev->parent->driver->per_child_auto; - if (!size) { - size = dev->parent->uclass->uc_drv-> - per_child_auto; - } + if (!size) + size = dev->parent->uclass->uc_drv->per_child_auto; if (size) { free(dev_get_parent_priv(dev)); dev_set_parent_priv(dev, NULL); diff --git a/drivers/core/device.c b/drivers/core/device.c index efd0717..aed093c 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -902,15 +902,16 @@ int device_find_first_child_by_uclass(const struct udevice *parent, return -ENODEV; } -int device_find_child_by_name(const struct udevice *parent, const char *name, - struct udevice **devp) +int device_find_child_by_namelen(const struct udevice *parent, const char *name, + int len, struct udevice **devp) { struct udevice *dev; *devp = NULL; list_for_each_entry(dev, &parent->child_head, sibling_node) { - if (!strcmp(dev->name, name)) { + if (!strncmp(dev->name, name, len) && + strlen(dev->name) == len) { *devp = dev; return 0; } @@ -919,6 +920,12 @@ int device_find_child_by_name(const struct udevice *parent, const char *name, return -ENODEV; } +int device_find_child_by_name(const struct udevice *parent, const char *name, + struct udevice **devp) +{ + return device_find_child_by_namelen(parent, name, strlen(name), devp); +} + int device_first_child_err(struct udevice *parent, struct udevice **devp) { struct udevice *dev; diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c index 9960e6b..3707143 100644 --- a/drivers/core/of_access.c +++ b/drivers/core/of_access.c @@ -581,7 +581,8 @@ int of_property_match_string(const struct device_node *np, const char *propname, * @propname: name of the property to be searched. * @out_strs: output array of string pointers. * @sz: number of array elements to read. - * @skip: Number of strings to skip over at beginning of list. + * @skip: Number of strings to skip over at beginning of list (cannot be + * negative) * * Don't call this function directly. It is a utility helper for the * of_property_read_string*() family of functions. diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 08705ef..709bea2 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -456,6 +456,32 @@ int ofnode_read_string_count(ofnode node, const char *property) } } +int ofnode_read_string_list(ofnode node, const char *property, + const char ***listp) +{ + const char **prop; + int count; + int i; + + *listp = NULL; + count = ofnode_read_string_count(node, property); + if (count < 0) + return count; + if (!count) + return 0; + + prop = calloc(count + 1, sizeof(char *)); + if (!prop) + return -ENOMEM; + + for (i = 0; i < count; i++) + ofnode_read_string_index(node, property, i, &prop[i]); + prop[count] = NULL; + *listp = prop; + + return count; +} + static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in, struct ofnode_phandle_args *out) { diff --git a/drivers/core/read.c b/drivers/core/read.c index 4307ca4..31f9e78 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -205,6 +205,12 @@ int dev_read_string_count(const struct udevice *dev, const char *propname) return ofnode_read_string_count(dev_ofnode(dev), propname); } +int dev_read_string_list(const struct udevice *dev, const char *propname, + const char ***listp) +{ + return ofnode_read_string_list(dev_ofnode(dev), propname, listp); +} + int dev_read_phandle_with_args(const struct udevice *dev, const char *list_name, const char *cells_name, int cell_count, int index, struct ofnode_phandle_args *out_args) diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index c5a5095..2aa2143 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -180,20 +180,25 @@ void uclass_set_priv(struct uclass *uc, void *priv) uc->priv_ = priv; } -enum uclass_id uclass_get_by_name(const char *name) +enum uclass_id uclass_get_by_name_len(const char *name, int len) { int i; for (i = 0; i < UCLASS_COUNT; i++) { struct uclass_driver *uc_drv = lists_uclass_lookup(i); - if (uc_drv && !strcmp(uc_drv->name, name)) + if (uc_drv && !strncmp(uc_drv->name, name, len)) return i; } return UCLASS_INVALID; } +enum uclass_id uclass_get_by_name(const char *name) +{ + return uclass_get_by_name_len(name, strlen(name)); +} + int dev_get_uclass_index(struct udevice *dev, struct uclass **ucp) { struct udevice *iter; @@ -682,7 +687,7 @@ err: } #if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) -int uclass_unbind_device(struct udevice *dev) +int uclass_pre_unbind_device(struct udevice *dev) { struct uclass *uc; int ret; @@ -694,7 +699,13 @@ int uclass_unbind_device(struct udevice *dev) return ret; } + return 0; +} + +int uclass_unbind_device(struct udevice *dev) +{ list_del(&dev->uclass_node); + return 0; } #endif @@ -783,6 +794,18 @@ int uclass_probe_all(enum uclass_id id) return 0; } +int uclass_id_count(enum uclass_id id) +{ + struct udevice *dev; + struct uclass *uc; + int count = 0; + + uclass_id_foreach_dev(id, dev, uc) + count++; + + return count; +} + UCLASS_DRIVER(nop) = { .id = UCLASS_NOP, .name = "nop", diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 3ee92d0..b80e838 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -320,7 +320,7 @@ struct blk_desc *mmc_get_blk_desc(struct mmc *mmc) struct blk_desc *desc; struct udevice *dev; - device_find_first_child(mmc->dev, &dev); + device_find_first_child_by_uclass(mmc->dev, UCLASS_BLK, &dev); if (!dev) return NULL; desc = dev_get_uclass_plat(dev); @@ -425,7 +425,7 @@ int mmc_unbind(struct udevice *dev) { struct udevice *bdev; - device_find_first_child(dev, &bdev); + device_find_first_child_by_uclass(dev, UCLASS_BLK, &bdev); if (bdev) { device_remove(bdev, DM_REMOVE_NORMAL); device_unbind(bdev); diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index 895fbff..451fe4a 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -9,23 +9,26 @@ #include <errno.h> #include <fdtdec.h> #include <log.h> +#include <malloc.h> #include <mmc.h> +#include <os.h> #include <asm/test.h> struct sandbox_mmc_plat { struct mmc_config cfg; struct mmc mmc; + const char *fname; }; -#define MMC_CSIZE 0 -#define MMC_CMULT 8 /* 8 because the card is high-capacity */ -#define MMC_BL_LEN_SHIFT 10 -#define MMC_BL_LEN BIT(MMC_BL_LEN_SHIFT) -#define MMC_CAPACITY (((MMC_CSIZE + 1) << (MMC_CMULT + 2)) \ - * MMC_BL_LEN) /* 1 MiB */ +#define MMC_CMULT 8 /* 8 because the card is high-capacity */ +#define MMC_BL_LEN_SHIFT 10 +#define MMC_BL_LEN BIT(MMC_BL_LEN_SHIFT) +#define SIZE_MULTIPLE ((1 << (MMC_CMULT + 2)) * MMC_BL_LEN) struct sandbox_mmc_priv { - u8 buf[MMC_CAPACITY]; + char *buf; + int csize; /* CSIZE value to report */ + int size; }; /** @@ -60,8 +63,8 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, case MMC_CMD_SEND_CSD: cmd->response[0] = 0; cmd->response[1] = (MMC_BL_LEN_SHIFT << 16) | - ((MMC_CSIZE >> 16) & 0x3f); - cmd->response[2] = (MMC_CSIZE & 0xffff) << 16; + ((priv->csize >> 16) & 0x3f); + cmd->response[2] = (priv->csize & 0xffff) << 16; cmd->response[3] = 0; break; case SD_CMD_SWITCH_FUNC: { @@ -143,6 +146,8 @@ static int sandbox_mmc_of_to_plat(struct udevice *dev) struct blk_desc *blk; int ret; + plat->fname = dev_read_string(dev, "filename"); + ret = mmc_of_parse(dev, cfg); if (ret) return ret; @@ -156,10 +161,46 @@ static int sandbox_mmc_of_to_plat(struct udevice *dev) static int sandbox_mmc_probe(struct udevice *dev) { struct sandbox_mmc_plat *plat = dev_get_plat(dev); + struct sandbox_mmc_priv *priv = dev_get_priv(dev); + int ret; + + if (plat->fname) { + ret = os_map_file(plat->fname, OS_O_RDWR | OS_O_CREAT, + (void **)&priv->buf, &priv->size); + if (ret) { + log_err("%s: Unable to map file '%s'\n", dev->name, + plat->fname); + return ret; + } + priv->csize = priv->size / SIZE_MULTIPLE - 1; + } else { + priv->csize = 0; + priv->size = (priv->csize + 1) * SIZE_MULTIPLE; /* 1 MiB */ + + priv->buf = malloc(priv->size); + if (!priv->buf) { + log_err("%s: Not enough memory (%x bytes)\n", + dev->name, priv->size); + return -ENOMEM; + } + } return mmc_init(&plat->mmc); } +static int sandbox_mmc_remove(struct udevice *dev) +{ + struct sandbox_mmc_plat *plat = dev_get_plat(dev); + struct sandbox_mmc_priv *priv = dev_get_priv(dev); + + if (plat->fname) + os_unmap(priv->buf, priv->size); + else + free(priv->buf); + + return 0; +} + static int sandbox_mmc_bind(struct udevice *dev) { struct sandbox_mmc_plat *plat = dev_get_plat(dev); @@ -196,6 +237,7 @@ U_BOOT_DRIVER(mmc_sandbox) = { .unbind = sandbox_mmc_unbind, .of_to_plat = sandbox_mmc_of_to_plat, .probe = sandbox_mmc_probe, + .remove = sandbox_mmc_remove, .priv_auto = sizeof(struct sandbox_mmc_priv), .plat_auto = sizeof(struct sandbox_mmc_plat), }; |