summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/core/Kconfig15
-rw-r--r--drivers/core/Makefile3
-rw-r--r--drivers/core/device.c2
-rw-r--r--include/dm/device-internal.h13
-rw-r--r--include/dm/device.h82
5 files changed, 113 insertions, 2 deletions
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index a002d69..8ae0072 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -79,9 +79,22 @@ config SYSCON
by this uclass, including accessing registers via regmap and
assigning a unique number to each.
+config DEVRES
+ bool "Managed device resources"
+ depends on DM
+ help
+ This option enables the Managed device resources core support.
+ Device resources managed by the devres framework are automatically
+ released whether initialization fails half-way or the device gets
+ detached.
+
+ If this option is disabled, devres functions fall back to
+ non-managed variants. For example, devres_alloc() to kzalloc(),
+ devm_kmalloc() to kmalloc(), etc.
+
config DEBUG_DEVRES
bool "Managed device resources verbose debug messages"
- depends on DM
+ depends on DEVRES
help
If this option is enabled, devres debug messages are printed.
Select this if you are having a problem with devres or want to
diff --git a/drivers/core/Makefile b/drivers/core/Makefile
index 260833e..ccc2fd4 100644
--- a/drivers/core/Makefile
+++ b/drivers/core/Makefile
@@ -4,7 +4,8 @@
# SPDX-License-Identifier: GPL-2.0+
#
-obj-y += device.o lists.o root.o uclass.o util.o devres.o
+obj-y += device.o lists.o root.o uclass.o util.o
+obj-$(CONFIG_DEVRES) += devres.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_OF_CONTROL) += simple-bus.o
endif
diff --git a/drivers/core/device.c b/drivers/core/device.c
index e3a42dc..caaf231 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -47,7 +47,9 @@ int device_bind(struct udevice *parent, const struct driver *drv,
INIT_LIST_HEAD(&dev->sibling_node);
INIT_LIST_HEAD(&dev->child_head);
INIT_LIST_HEAD(&dev->uclass_node);
+#ifdef CONFIG_DEVRES
INIT_LIST_HEAD(&dev->devres_head);
+#endif
dev->platdata = platdata;
dev->name = name;
dev->of_offset = of_offset;
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index a2bf057..2cd2fe9 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -156,6 +156,8 @@ fdt_addr_t simple_bus_translate(struct udevice *dev, fdt_addr_t addr);
#define DM_UCLASS_ROOT_NON_CONST (((gd_t *)gd)->uclass_root)
/* device resource management */
+#ifdef CONFIG_DEVRES
+
/**
* devres_release_probe - Release managed resources allocated after probing
* @dev: Device to release resources for
@@ -174,4 +176,15 @@ void devres_release_probe(struct udevice *dev);
*/
void devres_release_all(struct udevice *dev);
+#else /* ! CONFIG_DEVRES */
+
+static inline void devres_release_probe(struct udevice *dev)
+{
+}
+
+static inline void devres_release_all(struct udevice *dev)
+{
+}
+
+#endif /* ! CONFIG_DEVRES */
#endif
diff --git a/include/dm/device.h b/include/dm/device.h
index c474f2d..53773a8 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -98,7 +98,9 @@ struct udevice {
uint32_t flags;
int req_seq;
int seq;
+#ifdef CONFIG_DEVRES
struct list_head devres_head;
+#endif
};
/* Maximum sequence number supported */
@@ -472,6 +474,8 @@ bool device_is_last_sibling(struct udevice *dev);
typedef void (*dr_release_t)(struct udevice *dev, void *res);
typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);
+#ifdef CONFIG_DEVRES
+
#ifdef CONFIG_DEBUG_DEVRES
void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
const char *name);
@@ -648,5 +652,83 @@ static inline void *devm_kcalloc(struct udevice *dev,
*/
void devm_kfree(struct udevice *dev, void *p);
+#else /* ! CONFIG_DEVRES */
+
+static inline void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
+{
+ return kzalloc(size, gfp);
+}
+
+static inline void devres_free(void *res)
+{
+ kfree(res);
+}
+
+static inline void devres_add(struct udevice *dev, void *res)
+{
+}
+
+static inline void *devres_find(struct udevice *dev, dr_release_t release,
+ dr_match_t match, void *match_data)
+{
+ return NULL;
+}
+
+static inline void *devres_get(struct udevice *dev, void *new_res,
+ dr_match_t match, void *match_data)
+{
+ return NULL;
+}
+
+static inline void *devres_remove(struct udevice *dev, dr_release_t release,
+ dr_match_t match, void *match_data)
+{
+ return NULL;
+}
+
+static inline int devres_destroy(struct udevice *dev, dr_release_t release,
+ dr_match_t match, void *match_data)
+{
+ return 0;
+}
+
+static inline int devres_release(struct udevice *dev, dr_release_t release,
+ dr_match_t match, void *match_data)
+{
+ return 0;
+}
+
+static inline void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp)
+{
+ return kmalloc(size, gfp);
+}
+
+static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
+{
+ return kzalloc(size, gfp);
+}
+
+static inline void *devm_kmaloc_array(struct udevice *dev,
+ size_t n, size_t size, gfp_t flags)
+{
+ /* TODO: add kmalloc_array() to linux/compat.h */
+ if (size != 0 && n > SIZE_MAX / size)
+ return NULL;
+ return kmalloc(n * size, flags);
+}
+
+static inline void *devm_kcalloc(struct udevice *dev,
+ size_t n, size_t size, gfp_t flags)
+{
+ /* TODO: add kcalloc() to linux/compat.h */
+ return kmalloc(n * size, flags | __GFP_ZERO);
+}
+
+static inline void devm_kfree(struct udevice *dev, void *p)
+{
+ kfree(p);
+}
+
+#endif /* ! CONFIG_DEVRES */
#endif