// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2021 Linaro Limited * Author: AKASHI Takahiro */ #include #include #include #include #include #include #include struct udevice; DECLARE_GLOBAL_DATA_PTR; static const char *const tag_name[] = { [DM_TAG_PLAT] = "plat", [DM_TAG_PARENT_PLAT] = "parent_plat", [DM_TAG_UC_PLAT] = "uclass_plat", [DM_TAG_PRIV] = "priv", [DM_TAG_PARENT_PRIV] = "parent_priv", [DM_TAG_UC_PRIV] = "uclass_priv", [DM_TAG_DRIVER_DATA] = "driver_data", [DM_TAG_EFI] = "efi", }; const char *tag_get_name(enum dm_tag_t tag) { return tag_name[tag]; } int dev_tag_set_ptr(struct udevice *dev, enum dm_tag_t tag, void *ptr) { struct dmtag_node *node; if (!dev || tag >= DM_TAG_COUNT) return -EINVAL; list_for_each_entry(node, &gd->dmtag_list, sibling) { if (node->dev == dev && node->tag == tag) return -EEXIST; } node = calloc(sizeof(*node), 1); if (!node) return -ENOMEM; node->dev = dev; node->tag = tag; node->ptr = ptr; list_add_tail(&node->sibling, (struct list_head *)&gd->dmtag_list); return 0; } int dev_tag_set_val(struct udevice *dev, enum dm_tag_t tag, ulong val) { struct dmtag_node *node; if (!dev || tag >= DM_TAG_COUNT) return -EINVAL; list_for_each_entry(node, &gd->dmtag_list, sibling) { if (node->dev == dev && node->tag == tag) return -EEXIST; } node = calloc(sizeof(*node), 1); if (!node) return -ENOMEM; node->dev = dev; node->tag = tag; node->val = val; list_add_tail(&node->sibling, (struct list_head *)&gd->dmtag_list); return 0; } int dev_tag_get_ptr(struct udevice *dev, enum dm_tag_t tag, void **ptrp) { struct dmtag_node *node; if (!dev || tag >= DM_TAG_COUNT) return -EINVAL; list_for_each_entry(node, &gd->dmtag_list, sibling) { if (node->dev == dev && node->tag == tag) { *ptrp = node->ptr; return 0; } } return -ENOENT; } int dev_tag_get_val(struct udevice *dev, enum dm_tag_t tag, ulong *valp) { struct dmtag_node *node; if (!dev || tag >= DM_TAG_COUNT) return -EINVAL; list_for_each_entry(node, &gd->dmtag_list, sibling) { if (node->dev == dev && node->tag == tag) { *valp = node->val; return 0; } } return -ENOENT; } int dev_tag_del(struct udevice *dev, enum dm_tag_t tag) { struct dmtag_node *node, *tmp; if (!dev || tag >= DM_TAG_COUNT) return -EINVAL; list_for_each_entry_safe(node, tmp, &gd->dmtag_list, sibling) { if (node->dev == dev && node->tag == tag) { list_del(&node->sibling); free(node); return 0; } } return -ENOENT; } int dev_tag_del_all(struct udevice *dev) { struct dmtag_node *node, *tmp; bool found = false; if (!dev) return -EINVAL; list_for_each_entry_safe(node, tmp, &gd->dmtag_list, sibling) { if (node->dev == dev) { list_del(&node->sibling); free(node); found = true; } } if (found) return 0; return -ENOENT; } void dev_tag_collect_stats(struct dm_stats *stats) { struct dmtag_node *node; list_for_each_entry(node, &gd->dmtag_list, sibling) { stats->tag_count++; stats->tag_size += sizeof(struct dmtag_node); } }