mirror of
https://github.com/smaeul/u-boot.git
synced 2025-10-14 04:46:01 +01:00
dm: add tag support
With dm-tag feature, any U-Boot subsystem is allowed to associate arbitrary number of data with a particular udevice. This can been see as expanding "struct udevice" without modifying the definition. As a first user, UEFI subsystem makes use of tags to associate an efi_disk object with a block device. Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
75a9d75041
commit
6b7a6210fd
@ -2,7 +2,7 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2013 Google, Inc
|
# Copyright (c) 2013 Google, Inc
|
||||||
|
|
||||||
obj-y += device.o fdtaddr.o lists.o root.o uclass.o util.o
|
obj-y += device.o fdtaddr.o lists.o root.o uclass.o util.o tag.o
|
||||||
obj-$(CONFIG_$(SPL_TPL_)ACPIGEN) += acpi.o
|
obj-$(CONFIG_$(SPL_TPL_)ACPIGEN) += acpi.o
|
||||||
obj-$(CONFIG_DEVRES) += devres.o
|
obj-$(CONFIG_DEVRES) += devres.o
|
||||||
obj-$(CONFIG_$(SPL_)DM_DEVICE_REMOVE) += device-remove.o
|
obj-$(CONFIG_$(SPL_)DM_DEVICE_REMOVE) += device-remove.o
|
||||||
|
@ -199,6 +199,8 @@ int dm_init(bool of_live)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INIT_LIST_HEAD((struct list_head *)&gd->dmtag_list);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
139
drivers/core/tag.c
Normal file
139
drivers/core/tag.c
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Linaro Limited
|
||||||
|
* Author: AKASHI Takahiro
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <asm/global_data.h>
|
||||||
|
#include <dm/tag.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
struct udevice;
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
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 -ENOSPC;
|
||||||
|
|
||||||
|
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 -ENOSPC;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
@ -474,6 +474,10 @@ struct global_data {
|
|||||||
*/
|
*/
|
||||||
struct event_state event_state;
|
struct event_state event_state;
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
* @dmtag_list: List of DM tags
|
||||||
|
*/
|
||||||
|
struct list_head dmtag_list;
|
||||||
};
|
};
|
||||||
#ifndef DO_DEPS_ONLY
|
#ifndef DO_DEPS_ONLY
|
||||||
static_assert(sizeof(struct global_data) == GD_SIZE);
|
static_assert(sizeof(struct global_data) == GD_SIZE);
|
||||||
|
110
include/dm/tag.h
Normal file
110
include/dm/tag.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Linaro Limited
|
||||||
|
* Author: AKASHI Takahiro
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DM_TAG_H
|
||||||
|
#define _DM_TAG_H
|
||||||
|
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
struct udevice;
|
||||||
|
|
||||||
|
enum dm_tag_t {
|
||||||
|
/* EFI_LOADER */
|
||||||
|
DM_TAG_EFI = 0,
|
||||||
|
|
||||||
|
DM_TAG_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dmtag_node
|
||||||
|
*
|
||||||
|
* @sibling: List of dm-tag nodes
|
||||||
|
* @dev: Associated udevice
|
||||||
|
* @tag: Tag type
|
||||||
|
* @ptr: Pointer as a value
|
||||||
|
* @val: Value
|
||||||
|
*/
|
||||||
|
struct dmtag_node {
|
||||||
|
struct list_head sibling;
|
||||||
|
struct udevice *dev;
|
||||||
|
enum dm_tag_t tag;
|
||||||
|
union {
|
||||||
|
void *ptr;
|
||||||
|
ulong val;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dev_tag_set_ptr() - set a tag's value as a pointer
|
||||||
|
* @dev: Device to operate
|
||||||
|
* @tag: Tag type
|
||||||
|
* @ptr: Pointer to set
|
||||||
|
*
|
||||||
|
* Set the value, @ptr, as of @tag associated with the device, @dev
|
||||||
|
*
|
||||||
|
* Return: 0 on success, -ve on error
|
||||||
|
*/
|
||||||
|
int dev_tag_set_ptr(struct udevice *dev, enum dm_tag_t tag, void *ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dev_tag_set_val() set a tag's value as an integer
|
||||||
|
* @dev: Device to operate
|
||||||
|
* @tag: Tag type
|
||||||
|
* @val: Value to set
|
||||||
|
*
|
||||||
|
* Set the value, @val, as of @tag associated with the device, @dev
|
||||||
|
*
|
||||||
|
* Return: on success, -ve on error
|
||||||
|
*/
|
||||||
|
int dev_tag_set_val(struct udevice *dev, enum dm_tag_t tag, ulong val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dev_tag_get_ptr() - get a tag's value as a pointer
|
||||||
|
* @dev: Device to operate
|
||||||
|
* @tag: Tag type
|
||||||
|
* @ptrp: Pointer to tag's value (pointer)
|
||||||
|
*
|
||||||
|
* Get a tag's value as a pointer
|
||||||
|
*
|
||||||
|
* Return: on success, -ve on error
|
||||||
|
*/
|
||||||
|
int dev_tag_get_ptr(struct udevice *dev, enum dm_tag_t tag, void **ptrp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dev_tag_get_val() - get a tag's value as an integer
|
||||||
|
* @dev: Device to operate
|
||||||
|
* @tag: Tag type
|
||||||
|
* @valp: Pointer to tag's value (ulong)
|
||||||
|
*
|
||||||
|
* Get a tag's value as an integer
|
||||||
|
*
|
||||||
|
* Return: 0 on success, -ve on error
|
||||||
|
*/
|
||||||
|
int dev_tag_get_val(struct udevice *dev, enum dm_tag_t tag, ulong *valp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dev_tag_del() - delete a tag
|
||||||
|
* @dev: Device to operate
|
||||||
|
* @tag: Tag type
|
||||||
|
*
|
||||||
|
* Delete a tag of @tag associated with the device, @dev
|
||||||
|
*
|
||||||
|
* Return: 0 on success, -ve on error
|
||||||
|
*/
|
||||||
|
int dev_tag_del(struct udevice *dev, enum dm_tag_t tag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dev_tag_del_all() - delete all tags
|
||||||
|
* @dev: Device to operate
|
||||||
|
*
|
||||||
|
* Delete all the tags associated with the device, @dev
|
||||||
|
*
|
||||||
|
* Return: 0 on success, -ve on error
|
||||||
|
*/
|
||||||
|
int dev_tag_del_all(struct udevice *dev);
|
||||||
|
|
||||||
|
#endif /* _DM_TAG_H */
|
Loading…
x
Reference in New Issue
Block a user