diff options
author | Tom Rini <trini@konsulko.com> | 2020-01-09 08:52:21 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2020-01-09 08:52:21 -0500 |
commit | d6b92b9742f125542dd0985976c3a6c560ed40fd (patch) | |
tree | df47458afa5280a80aa6ea789ac4d935aabe64ed /include/dm | |
parent | a74a2134b245d19a999c796d29285597a22954ed (diff) | |
parent | aaa05deb1283b6beb7334adfa4094fb6bd4ab750 (diff) | |
download | u-boot-d6b92b9742f125542dd0985976c3a6c560ed40fd.tar.gz |
Merge tag 'dm-pull-8jan20' of git://git.denx.de/u-boot-dmWIP/09Jan2020
dm: Increased separation of ofdata_to_platdata() and probe methods
Diffstat (limited to 'include/dm')
-rw-r--r-- | include/dm/device-internal.h | 16 | ||||
-rw-r--r-- | include/dm/device.h | 259 | ||||
-rw-r--r-- | include/dm/devres.h | 289 | ||||
-rw-r--r-- | include/dm/uclass-id.h | 1 |
4 files changed, 311 insertions, 254 deletions
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h index ee2b24a62a..294d6c1810 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 d7ad9d6728..1138a09149 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 0000000000..9c69196054 --- /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 67f5d673cb..598f65ea7a 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 */ |