aboutsummaryrefslogtreecommitdiff
path: root/include/dm
diff options
context:
space:
mode:
authorTom Rini2020-01-09 08:52:21 -0500
committerTom Rini2020-01-09 08:52:21 -0500
commitd6b92b9742f125542dd0985976c3a6c560ed40fd (patch)
treedf47458afa5280a80aa6ea789ac4d935aabe64ed /include/dm
parenta74a2134b245d19a999c796d29285597a22954ed (diff)
parentaaa05deb1283b6beb7334adfa4094fb6bd4ab750 (diff)
Merge tag 'dm-pull-8jan20' of git://git.denx.de/u-boot-dm
dm: Increased separation of ofdata_to_platdata() and probe methods
Diffstat (limited to 'include/dm')
-rw-r--r--include/dm/device-internal.h16
-rw-r--r--include/dm/device.h259
-rw-r--r--include/dm/devres.h289
-rw-r--r--include/dm/uclass-id.h1
4 files changed, 311 insertions, 254 deletions
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index ee2b24a62a2..294d6c18105 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -84,6 +84,22 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
const struct driver_info *info, struct udevice **devp);
/**
+ * device_ofdata_to_platdata() - Read platform data for a device
+ *
+ * Read platform data for a device (typically from the device tree) so that
+ * the information needed to probe the device is present.
+ *
+ * This may cause some others devices to be probed if this one depends on them,
+ * e.g. a GPIO line will cause a GPIO device to be probed.
+ *
+ * All private data associated with the device is allocated.
+ *
+ * @dev: Pointer to device to process
+ * @return 0 if OK, -ve on error
+ */
+int device_ofdata_to_platdata(struct udevice *dev);
+
+/**
* device_probe() - Probe a device, activating it
*
* Activate a device so that it is ready for use. All its parents are probed
diff --git a/include/dm/device.h b/include/dm/device.h
index d7ad9d6728b..1138a09149f 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -45,6 +45,7 @@ struct driver_info;
/* Device name is allocated and should be freed on unbind() */
#define DM_FLAG_NAME_ALLOCED (1 << 7)
+/* Device has platform data provided by of-platdata */
#define DM_FLAG_OF_PLATDATA (1 << 8)
/*
@@ -64,6 +65,9 @@ struct driver_info;
/* DM does not enable/disable the power domains corresponding to this device */
#define DM_FLAG_DEFAULT_PD_CTRL_OFF (1 << 11)
+/* Driver platdata has been read. Cleared when the device is removed */
+#define DM_FLAG_PLATDATA_VALID (1 << 12)
+
/*
* One or multiple of these flags are passed to device_remove() so that
* a selective device removal as specified by the remove-stage and the
@@ -716,260 +720,7 @@ static inline bool device_is_on_pci_bus(struct udevice *dev)
*/
int dm_scan_fdt_dev(struct udevice *dev);
-/* device resource management */
-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);
-#define _devres_alloc(release, size, gfp) \
- __devres_alloc(release, size, gfp, #release)
-#else
-void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp);
-#endif
-
-/**
- * devres_alloc() - Allocate device resource data
- * @release: Release function devres will be associated with
- * @size: Allocation size
- * @gfp: Allocation flags
- *
- * Allocate devres of @size bytes. The allocated area is associated
- * with @release. The returned pointer can be passed to
- * other devres_*() functions.
- *
- * RETURNS:
- * Pointer to allocated devres on success, NULL on failure.
- */
-#define devres_alloc(release, size, gfp) \
- _devres_alloc(release, size, gfp | __GFP_ZERO)
-
-/**
- * devres_free() - Free device resource data
- * @res: Pointer to devres data to free
- *
- * Free devres created with devres_alloc().
- */
-void devres_free(void *res);
-
-/**
- * devres_add() - Register device resource
- * @dev: Device to add resource to
- * @res: Resource to register
- *
- * Register devres @res to @dev. @res should have been allocated
- * using devres_alloc(). On driver detach, the associated release
- * function will be invoked and devres will be freed automatically.
- */
-void devres_add(struct udevice *dev, void *res);
-
-/**
- * devres_find() - Find device resource
- * @dev: Device to lookup resource from
- * @release: Look for resources associated with this release function
- * @match: Match function (optional)
- * @match_data: Data for the match function
- *
- * Find the latest devres of @dev which is associated with @release
- * and for which @match returns 1. If @match is NULL, it's considered
- * to match all.
- *
- * @return pointer to found devres, NULL if not found.
- */
-void *devres_find(struct udevice *dev, dr_release_t release,
- dr_match_t match, void *match_data);
-
-/**
- * devres_get() - Find devres, if non-existent, add one atomically
- * @dev: Device to lookup or add devres for
- * @new_res: Pointer to new initialized devres to add if not found
- * @match: Match function (optional)
- * @match_data: Data for the match function
- *
- * Find the latest devres of @dev which has the same release function
- * as @new_res and for which @match return 1. If found, @new_res is
- * freed; otherwise, @new_res is added atomically.
- *
- * @return ointer to found or added devres.
- */
-void *devres_get(struct udevice *dev, void *new_res,
- dr_match_t match, void *match_data);
-
-/**
- * devres_remove() - Find a device resource and remove it
- * @dev: Device to find resource from
- * @release: Look for resources associated with this release function
- * @match: Match function (optional)
- * @match_data: Data for the match function
- *
- * Find the latest devres of @dev associated with @release and for
- * which @match returns 1. If @match is NULL, it's considered to
- * match all. If found, the resource is removed atomically and
- * returned.
- *
- * @return ointer to removed devres on success, NULL if not found.
- */
-void *devres_remove(struct udevice *dev, dr_release_t release,
- dr_match_t match, void *match_data);
-
-/**
- * devres_destroy() - Find a device resource and destroy it
- * @dev: Device to find resource from
- * @release: Look for resources associated with this release function
- * @match: Match function (optional)
- * @match_data: Data for the match function
- *
- * Find the latest devres of @dev associated with @release and for
- * which @match returns 1. If @match is NULL, it's considered to
- * match all. If found, the resource is removed atomically and freed.
- *
- * Note that the release function for the resource will not be called,
- * only the devres-allocated data will be freed. The caller becomes
- * responsible for freeing any other data.
- *
- * @return 0 if devres is found and freed, -ENOENT if not found.
- */
-int devres_destroy(struct udevice *dev, dr_release_t release,
- dr_match_t match, void *match_data);
-
-/**
- * devres_release() - Find a device resource and destroy it, calling release
- * @dev: Device to find resource from
- * @release: Look for resources associated with this release function
- * @match: Match function (optional)
- * @match_data: Data for the match function
- *
- * Find the latest devres of @dev associated with @release and for
- * which @match returns 1. If @match is NULL, it's considered to
- * match all. If found, the resource is removed atomically, the
- * release function called and the resource freed.
- *
- * @return 0 if devres is found and freed, -ENOENT if not found.
- */
-int devres_release(struct udevice *dev, dr_release_t release,
- dr_match_t match, void *match_data);
-
-/* managed devm_k.alloc/kfree for device drivers */
-/**
- * devm_kmalloc() - Resource-managed kmalloc
- * @dev: Device to allocate memory for
- * @size: Allocation size
- * @gfp: Allocation gfp flags
- *
- * Managed kmalloc. Memory allocated with this function is
- * automatically freed on driver detach. Like all other devres
- * resources, guaranteed alignment is unsigned long long.
- *
- * @return pointer to allocated memory on success, NULL on failure.
- */
-void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp);
-static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
-{
- return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
-}
-static inline void *devm_kmalloc_array(struct udevice *dev,
- size_t n, size_t size, gfp_t flags)
-{
- if (size != 0 && n > SIZE_MAX / size)
- return NULL;
- return devm_kmalloc(dev, n * size, flags);
-}
-static inline void *devm_kcalloc(struct udevice *dev,
- size_t n, size_t size, gfp_t flags)
-{
- return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
-}
-
-/**
- * devm_kfree() - Resource-managed kfree
- * @dev: Device this memory belongs to
- * @ptr: Memory to free
- *
- * Free memory allocated with devm_kmalloc().
- */
-void devm_kfree(struct udevice *dev, void *ptr);
-
-#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_kmalloc_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 *ptr)
-{
- kfree(ptr);
-}
-
-#endif /* ! CONFIG_DEVRES */
+#include <dm/devres.h>
/*
* REVISIT:
diff --git a/include/dm/devres.h b/include/dm/devres.h
new file mode 100644
index 00000000000..9c691960545
--- /dev/null
+++ b/include/dm/devres.h
@@ -0,0 +1,289 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * Based on the original work in Linux by
+ * Copyright (c) 2006 SUSE Linux Products GmbH
+ * Copyright (c) 2006 Tejun Heo <teheo@suse.de>
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef _DM_DEVRES_H
+#define _DM_DEVRES_H
+
+/* device resource management */
+typedef void (*dr_release_t)(struct udevice *dev, void *res);
+typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);
+
+/**
+ * struct devres_stats - Information about devres allocations for a device
+ *
+ * @allocs: Number of allocations
+ * @total_size: Total size of allocations in bytes
+ */
+struct devres_stats {
+ int allocs;
+ int total_size;
+};
+
+#ifdef CONFIG_DEVRES
+
+#ifdef CONFIG_DEBUG_DEVRES
+void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
+ const char *name);
+#define _devres_alloc(release, size, gfp) \
+ __devres_alloc(release, size, gfp, #release)
+#else
+void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp);
+#endif
+
+/**
+ * devres_alloc() - Allocate device resource data
+ * @release: Release function devres will be associated with
+ * @size: Allocation size
+ * @gfp: Allocation flags
+ *
+ * Allocate devres of @size bytes. The allocated area is associated
+ * with @release. The returned pointer can be passed to
+ * other devres_*() functions.
+ *
+ * RETURNS:
+ * Pointer to allocated devres on success, NULL on failure.
+ */
+#define devres_alloc(release, size, gfp) \
+ _devres_alloc(release, size, (gfp) | __GFP_ZERO)
+
+/**
+ * devres_free() - Free device resource data
+ * @res: Pointer to devres data to free
+ *
+ * Free devres created with devres_alloc().
+ */
+void devres_free(void *res);
+
+/**
+ * devres_add() - Register device resource
+ * @dev: Device to add resource to
+ * @res: Resource to register
+ *
+ * Register devres @res to @dev. @res should have been allocated
+ * using devres_alloc(). On driver detach, the associated release
+ * function will be invoked and devres will be freed automatically.
+ */
+void devres_add(struct udevice *dev, void *res);
+
+/**
+ * devres_find() - Find device resource
+ * @dev: Device to lookup resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev which is associated with @release
+ * and for which @match returns 1. If @match is NULL, it's considered
+ * to match all.
+ *
+ * @return pointer to found devres, NULL if not found.
+ */
+void *devres_find(struct udevice *dev, dr_release_t release,
+ dr_match_t match, void *match_data);
+
+/**
+ * devres_get() - Find devres, if non-existent, add one atomically
+ * @dev: Device to lookup or add devres for
+ * @new_res: Pointer to new initialized devres to add if not found
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev which has the same release function
+ * as @new_res and for which @match return 1. If found, @new_res is
+ * freed; otherwise, @new_res is added atomically.
+ *
+ * @return ointer to found or added devres.
+ */
+void *devres_get(struct udevice *dev, void *new_res,
+ dr_match_t match, void *match_data);
+
+/**
+ * devres_remove() - Find a device resource and remove it
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1. If @match is NULL, it's considered to
+ * match all. If found, the resource is removed atomically and
+ * returned.
+ *
+ * @return ointer to removed devres on success, NULL if not found.
+ */
+void *devres_remove(struct udevice *dev, dr_release_t release,
+ dr_match_t match, void *match_data);
+
+/**
+ * devres_destroy() - Find a device resource and destroy it
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1. If @match is NULL, it's considered to
+ * match all. If found, the resource is removed atomically and freed.
+ *
+ * Note that the release function for the resource will not be called,
+ * only the devres-allocated data will be freed. The caller becomes
+ * responsible for freeing any other data.
+ *
+ * @return 0 if devres is found and freed, -ENOENT if not found.
+ */
+int devres_destroy(struct udevice *dev, dr_release_t release,
+ dr_match_t match, void *match_data);
+
+/**
+ * devres_release() - Find a device resource and destroy it, calling release
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1. If @match is NULL, it's considered to
+ * match all. If found, the resource is removed atomically, the
+ * release function called and the resource freed.
+ *
+ * @return 0 if devres is found and freed, -ENOENT if not found.
+ */
+int devres_release(struct udevice *dev, dr_release_t release,
+ dr_match_t match, void *match_data);
+
+/* managed devm_k.alloc/kfree for device drivers */
+/**
+ * devm_kmalloc() - Resource-managed kmalloc
+ * @dev: Device to allocate memory for
+ * @size: Allocation size
+ * @gfp: Allocation gfp flags
+ *
+ * Managed kmalloc. Memory allocated with this function is
+ * automatically freed on driver detach. Like all other devres
+ * resources, guaranteed alignment is unsigned long long.
+ *
+ * @return pointer to allocated memory on success, NULL on failure.
+ */
+void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp);
+static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
+{
+ return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
+}
+
+static inline void *devm_kmalloc_array(struct udevice *dev,
+ size_t n, size_t size, gfp_t flags)
+{
+ if (size != 0 && n > SIZE_MAX / size)
+ return NULL;
+ return devm_kmalloc(dev, n * size, flags);
+}
+
+static inline void *devm_kcalloc(struct udevice *dev,
+ size_t n, size_t size, gfp_t flags)
+{
+ return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
+}
+
+/**
+ * devm_kfree() - Resource-managed kfree
+ * @dev: Device this memory belongs to
+ * @ptr: Memory to free
+ *
+ * Free memory allocated with devm_kmalloc().
+ */
+void devm_kfree(struct udevice *dev, void *ptr);
+
+/* Get basic stats on allocations */
+void devres_get_stats(const struct udevice *dev, struct devres_stats *stats);
+
+#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_kmalloc_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 *ptr)
+{
+ kfree(ptr);
+}
+
+static inline void devres_get_stats(const struct udevice *dev,
+ struct devres_stats *stats)
+{
+}
+
+#endif /* DEVRES */
+#endif /* _DM_DEVRES_H */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 67f5d673cb8..598f65ea7a3 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -19,6 +19,7 @@ enum uclass_id {
UCLASS_TEST_BUS,
UCLASS_TEST_PROBE,
UCLASS_TEST_DUMMY,
+ UCLASS_TEST_DEVRES,
UCLASS_SPI_EMUL, /* sandbox SPI device emulator */
UCLASS_I2C_EMUL, /* sandbox I2C device emulator */
UCLASS_I2C_EMUL_PARENT, /* parent for I2C device emulators */