diff options
Diffstat (limited to 'include/dm')
-rw-r--r-- | include/dm/device-internal.h | 87 | ||||
-rw-r--r-- | include/dm/device.h | 159 | ||||
-rw-r--r-- | include/dm/lists.h | 39 | ||||
-rw-r--r-- | include/dm/platdata.h | 22 | ||||
-rw-r--r-- | include/dm/root.h | 53 | ||||
-rw-r--r-- | include/dm/test.h | 167 | ||||
-rw-r--r-- | include/dm/uclass-id.h | 28 | ||||
-rw-r--r-- | include/dm/uclass-internal.h | 85 | ||||
-rw-r--r-- | include/dm/uclass.h | 142 | ||||
-rw-r--r-- | include/dm/ut.h | 95 | ||||
-rw-r--r-- | include/dm/util.h | 29 |
11 files changed, 906 insertions, 0 deletions
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h new file mode 100644 index 0000000000..c026e8e49c --- /dev/null +++ b/include/dm/device-internal.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * Marek Vasut <marex@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _DM_DEVICE_INTERNAL_H +#define _DM_DEVICE_INTERNAL_H + +struct device; + +/** + * device_bind() - Create a device and bind it to a driver + * + * Called to set up a new device attached to a driver. The device will either + * have platdata, or a device tree node which can be used to create the + * platdata. + * + * Once bound a device exists but is not yet active until device_probe() is + * called. + * + * @parent: Pointer to device's parent, under which this driver will exist + * @drv: Device's driver + * @name: Name of device (e.g. device tree node name) + * @platdata: Pointer to data for this device - the structure is device- + * specific but may include the device's I/O address, etc.. This is NULL for + * devices which use device tree. + * @of_offset: Offset of device tree node for this device. This is -1 for + * devices which don't use device tree. + * @devp: Returns a pointer to the bound device + * @return 0 if OK, -ve on error + */ +int device_bind(struct device *parent, struct driver *drv, + const char *name, void *platdata, int of_offset, + struct device **devp); + +/** + * device_bind_by_name: Create a device and bind it to a driver + * + * This is a helper function used to bind devices which do not use device + * tree. + * + * @parent: Pointer to device's parent + * @info: Name and platdata for this device + * @devp: Returns a pointer to the bound device + * @return 0 if OK, -ve on error + */ +int device_bind_by_name(struct device *parent, const struct driver_info *info, + struct device **devp); + +/** + * device_probe() - Probe a device, activating it + * + * Activate a device so that it is ready for use. All its parents are probed + * first. + * + * @dev: Pointer to device to probe + * @return 0 if OK, -ve on error + */ +int device_probe(struct device *dev); + +/** + * device_remove() - Remove a device, de-activating it + * + * De-activate a device so that it is no longer ready for use. All its + * children are deactivated first. + * + * @dev: Pointer to device to remove + * @return 0 if OK, -ve on error (an error here is normally a very bad thing) + */ +int device_remove(struct device *dev); + +/** + * device_unbind() - Unbind a device, destroying it + * + * Unbind a device and remove all memory used by it + * + * @dev: Pointer to device to unbind + * @return 0 if OK, -ve on error + */ +int device_unbind(struct device *dev); + +#endif diff --git a/include/dm/device.h b/include/dm/device.h new file mode 100644 index 0000000000..4cd38ed2d0 --- /dev/null +++ b/include/dm/device.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * Marek Vasut <marex@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _DM_DEVICE_H +#define _DM_DEVICE_H + +#include <dm/uclass-id.h> +#include <linker_lists.h> +#include <linux/list.h> + +struct driver_info; + +/* Driver is active (probed). Cleared when it is removed */ +#define DM_FLAG_ACTIVATED (1 << 0) + +/* DM is responsible for allocating and freeing platdata */ +#define DM_FLAG_ALLOC_PDATA (2 << 0) + +/** + * struct device - An instance of a driver + * + * This holds information about a device, which is a driver bound to a + * particular port or peripheral (essentially a driver instance). + * + * A device will come into existence through a 'bind' call, either due to + * a U_BOOT_DEVICE() macro (in which case platdata is non-NULL) or a node + * in the device tree (in which case of_offset is >= 0). In the latter case + * we translate the device tree information into platdata in a function + * implemented by the driver ofdata_to_platdata method (called just before the + * probe method if the device has a device tree node. + * + * All three of platdata, priv and uclass_priv can be allocated by the + * driver, or you can use the auto_alloc_size members of struct driver and + * struct uclass_driver to have driver model do this automatically. + * + * @driver: The driver used by this device + * @name: Name of device, typically the FDT node name + * @platdata: Configuration data for this device + * @of_offset: Device tree node offset for this device (- for none) + * @parent: Parent of this device, or NULL for the top level device + * @priv: Private data for this device + * @uclass: Pointer to uclass for this device + * @uclass_priv: The uclass's private data for this device + * @uclass_node: Used by uclass to link its devices + * @child_head: List of children of this device + * @sibling_node: Next device in list of all devices + * @flags: Flags for this device DM_FLAG_... + */ +struct device { + struct driver *driver; + const char *name; + void *platdata; + int of_offset; + struct device *parent; + void *priv; + struct uclass *uclass; + void *uclass_priv; + struct list_head uclass_node; + struct list_head child_head; + struct list_head sibling_node; + uint32_t flags; +}; + +/* Returns the operations for a device */ +#define device_get_ops(dev) (dev->driver->ops) + +/* Returns non-zero if the device is active (probed and not removed) */ +#define device_active(dev) ((dev)->flags & DM_FLAG_ACTIVATED) + +/** + * struct device_id - Lists the compatible strings supported by a driver + * @compatible: Compatible string + * @data: Data for this compatible string + */ +struct device_id { + const char *compatible; + ulong data; +}; + +/** + * struct driver - A driver for a feature or peripheral + * + * This holds methods for setting up a new device, and also removing it. + * The device needs information to set itself up - this is provided either + * by platdata or a device tree node (which we find by looking up + * matching compatible strings with of_match). + * + * Drivers all belong to a uclass, representing a class of devices of the + * same type. Common elements of the drivers can be implemented in the uclass, + * or the uclass can provide a consistent interface to the drivers within + * it. + * + * @name: Device name + * @id: Identiies the uclass we belong to + * @of_match: List of compatible strings to match, and any identifying data + * for each. + * @bind: Called to bind a device to its driver + * @probe: Called to probe a device, i.e. activate it + * @remove: Called to remove a device, i.e. de-activate it + * @unbind: Called to unbind a device from its driver + * @ofdata_to_platdata: Called before probe to decode device tree data + * @priv_auto_alloc_size: If non-zero this is the size of the private data + * to be allocated in the device's ->priv pointer. If zero, then the driver + * is responsible for allocating any data required. + * @platdata_auto_alloc_size: If non-zero this is the size of the + * platform data to be allocated in the device's ->platdata pointer. + * This is typically only useful for device-tree-aware drivers (those with + * an of_match), since drivers which use platdata will have the data + * provided in the U_BOOT_DEVICE() instantiation. + * ops: Driver-specific operations. This is typically a list of function + * pointers defined by the driver, to implement driver functions required by + * the uclass. + */ +struct driver { + char *name; + enum uclass_id id; + const struct device_id *of_match; + int (*bind)(struct device *dev); + int (*probe)(struct device *dev); + int (*remove)(struct device *dev); + int (*unbind)(struct device *dev); + int (*ofdata_to_platdata)(struct device *dev); + int priv_auto_alloc_size; + int platdata_auto_alloc_size; + const void *ops; /* driver-specific operations */ +}; + +/* Declare a new U-Boot driver */ +#define U_BOOT_DRIVER(__name) \ + ll_entry_declare(struct driver, __name, driver) + +/** + * dev_get_platdata() - Get the platform data for a device + * + * This checks that dev is not NULL, but no other checks for now + * + * @dev Device to check + * @return platform data, or NULL if none + */ +void *dev_get_platdata(struct device *dev); + +/** + * dev_get_priv() - Get the private data for a device + * + * This checks that dev is not NULL, but no other checks for now + * + * @dev Device to check + * @return private data, or NULL if none + */ +void *dev_get_priv(struct device *dev); + +#endif diff --git a/include/dm/lists.h b/include/dm/lists.h new file mode 100644 index 0000000000..0d09f9a14f --- /dev/null +++ b/include/dm/lists.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _DM_LISTS_H_ +#define _DM_LISTS_H_ + +#include <dm/uclass-id.h> + +/** + * lists_driver_lookup_name() - Return u_boot_driver corresponding to name + * + * This function returns a pointer to a driver given its name. This is used + * for binding a driver given its name and platdata. + * + * @name: Name of driver to look up + * @return pointer to driver, or NULL if not found + */ +struct driver *lists_driver_lookup_name(const char *name); + +/** + * lists_uclass_lookup() - Return uclass_driver based on ID of the class + * id: ID of the class + * + * This function returns the pointer to uclass_driver, which is the class's + * base structure based on the ID of the class. Returns NULL on error. + */ +struct uclass_driver *lists_uclass_lookup(enum uclass_id id); + +int lists_bind_drivers(struct device *parent); + +int lists_bind_fdt(struct device *parent, const void *blob, int offset); + +#endif diff --git a/include/dm/platdata.h b/include/dm/platdata.h new file mode 100644 index 0000000000..0ef3353e74 --- /dev/null +++ b/include/dm/platdata.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * Marek Vasut <marex@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _DM_PLATDATA_H +#define _DM_PLATDATA_H + +struct driver_info { + const char *name; + const void *platdata; +}; + +#define U_BOOT_DEVICE(__name) \ + ll_entry_declare(struct driver_info, __name, driver_info) + +#endif diff --git a/include/dm/root.h b/include/dm/root.h new file mode 100644 index 0000000000..0ebccda355 --- /dev/null +++ b/include/dm/root.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _DM_ROOT_H_ +#define _DM_ROOT_H_ + +struct device; + +/** + * dm_root() - Return pointer to the top of the driver tree + * + * This function returns pointer to the root node of the driver tree, + * + * @return pointer to root device, or NULL if not inited yet + */ +struct device *dm_root(void); + +/** + * dm_scan_platdata() - Scan all platform data and bind drivers + * + * This scans all available platdata and creates drivers for each + * + * @return 0 if OK, -ve on error + */ +int dm_scan_platdata(void); + +/** + * dm_scan_fdt() - Scan the device tree and bind drivers + * + * This scans the device tree and creates a driver for each node + * + * @blob: Pointer to device tree blob + * @return 0 if OK, -ve on error + */ +int dm_scan_fdt(const void *blob); + +/** + * dm_init() - Initialize Driver Model structures + * + * This function will initialize roots of driver tree and class tree. + * This needs to be called before anything uses the DM + * + * @return 0 if OK, -ve on error + */ +int dm_init(void); + +#endif diff --git a/include/dm/test.h b/include/dm/test.h new file mode 100644 index 0000000000..eeaa2eb2f4 --- /dev/null +++ b/include/dm/test.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2013 Google, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __DM_TEST_H +#define __DM_TEST_H + +#include <dm.h> + +/** + * struct dm_test_cdata - configuration data for test instance + * + * @ping_add: Amonut to add each time we get a ping + * @base: Base address of this device + */ +struct dm_test_pdata { + int ping_add; + uint32_t base; +}; + +/** + * struct test_ops - Operations supported by the test device + * + * @ping: Ping operation + * @dev: Device to operate on + * @pingval: Value to ping the device with + * @pingret: Returns resulting value from driver + * @return 0 if OK, -ve on error + */ +struct test_ops { + int (*ping)(struct device *dev, int pingval, int *pingret); +}; + +/* Operations that our test driver supports */ +enum { + DM_TEST_OP_BIND = 0, + DM_TEST_OP_UNBIND, + DM_TEST_OP_PROBE, + DM_TEST_OP_REMOVE, + + /* For uclass */ + DM_TEST_OP_POST_BIND, + DM_TEST_OP_PRE_UNBIND, + DM_TEST_OP_POST_PROBE, + DM_TEST_OP_PRE_REMOVE, + DM_TEST_OP_INIT, + DM_TEST_OP_DESTROY, + + DM_TEST_OP_COUNT, +}; + +/* Test driver types */ +enum { + DM_TEST_TYPE_FIRST = 0, + DM_TEST_TYPE_SECOND, +}; + +/* The number added to the ping total on each probe */ +#define DM_TEST_START_TOTAL 5 + +/** + * struct dm_test_priv - private data for the test devices + */ +struct dm_test_priv { + int ping_total; + int op_count[DM_TEST_OP_COUNT]; +}; + +/** + * struct dm_test_perdev_class_priv - private per-device data for test uclass + */ +struct dm_test_uclass_perdev_priv { + int base_add; +}; + +/** + * struct dm_test_uclass_priv - private data for test uclass + */ +struct dm_test_uclass_priv { + int total_add; +}; + +/* + * Operation counts for the test driver, used to check that each method is + * called correctly + */ +extern int dm_testdrv_op_count[DM_TEST_OP_COUNT]; + +extern struct dm_test_state global_test_state; + +/* + * struct dm_test_state - Entire state of dm test system + * + * This is often abreviated to dms. + * + * @root: Root device + * @testdev: Test device + * @fail_count: Number of tests that failed + * @force_fail_alloc: Force all memory allocs to fail + * @skip_post_probe: Skip uclass post-probe processing + */ +struct dm_test_state { + struct device *root; + struct device *testdev; + int fail_count; + int force_fail_alloc; + int skip_post_probe; +}; + +/* Test flags for each test */ +enum { + DM_TESTF_SCAN_PDATA = 1 << 0, /* test needs platform data */ + DM_TESTF_PROBE_TEST = 1 << 1, /* probe test uclass */ + DM_TESTF_SCAN_FDT = 1 << 2, /* scan device tree */ +}; + +/** + * struct dm_test - Information about a driver model test + * + * @name: Name of test + * @func: Function to call to perform test + * @flags: Flags indicated pre-conditions for test + */ +struct dm_test { + const char *name; + int (*func)(struct dm_test_state *dms); + int flags; +}; + +/* Declare a new driver model test */ +#define DM_TEST(_name, _flags) \ + ll_entry_declare(struct dm_test, _name, dm_test) = { \ + .name = #_name, \ + .flags = _flags, \ + .func = _name, \ + } + +/* Declare ping methods for the drivers */ +int test_ping(struct device *dev, int pingval, int *pingret); +int testfdt_ping(struct device *dev, int pingval, int *pingret); + +/** + * dm_check_operations() - Check that we can perform ping operations + * + * This checks that the ping operations work as expected for a device + * + * @dms: Overall test state + * @dev: Device to test + * @base: Base address, used to check ping return value + * @priv: Pointer to private test information + * @return 0 if OK, -ve on error + */ +int dm_check_operations(struct dm_test_state *dms, struct device *dev, + uint32_t base, struct dm_test_priv *priv); + +/** + * dm_test_main() - Run all the tests + * + * This runs all available driver model tests + * + * @return 0 if OK, -ve on error + */ +int dm_test_main(void); + +#endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h new file mode 100644 index 0000000000..f0e691c18c --- /dev/null +++ b/include/dm/uclass-id.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _DM_UCLASS_ID_H +#define _DM_UCLASS_ID_H + +/* TODO(sjg@chromium.org): this could be compile-time generated */ +enum uclass_id { + /* These are used internally by driver model */ + UCLASS_ROOT = 0, + UCLASS_DEMO, + UCLASS_TEST, + UCLASS_TEST_FDT, + + /* U-Boot uclasses start here */ + UCLASS_GPIO, + + UCLASS_COUNT, + UCLASS_INVALID = -1, +}; + +#endif diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h new file mode 100644 index 0000000000..cc65d5259f --- /dev/null +++ b/include/dm/uclass-internal.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _DM_UCLASS_INTERNAL_H +#define _DM_UCLASS_INTERNAL_H + +/** + * uclass_find_device() - Return n-th child of uclass + * @id: Id number of the uclass + * @index: Position of the child in uclass's list + * #devp: Returns pointer to device, or NULL on error + * + * The device is not prepared for use - this is an internal function + * + * @return the uclass pointer of a child at the given index or + * return NULL on error. + */ +int uclass_find_device(enum uclass_id id, int index, struct device **devp); + +/** + * uclass_bind_device() - Associate device with a uclass + * + * Connect the device into uclass's list of devices. + * + * @dev: Pointer to the device + * #return 0 on success, -ve on error + */ +int uclass_bind_device(struct device *dev); + +/** + * uclass_unbind_device() - Deassociate device with a uclass + * + * Disconnect the device from uclass's list of devices. + * + * @dev: Pointer to the device + * #return 0 on success, -ve on error + */ +int uclass_unbind_device(struct device *dev); + +/** + * uclass_post_probe_device() - Deal with a device that has just been probed + * + * Perform any post-processing of a probed device that is needed by the + * uclass. + * + * @dev: Pointer to the device + * #return 0 on success, -ve on error + */ +int uclass_post_probe_device(struct device *dev); + +/** + * uclass_pre_remove_device() - Handle a device which is about to be removed + * + * Perform any pre-processing of a device that is about to be removed. + * + * @dev: Pointer to the device + * #return 0 on success, -ve on error + */ +int uclass_pre_remove_device(struct device *dev); + +/** + * uclass_find() - Find uclass by its id + * + * @id: Id to serach for + * @return pointer to uclass, or NULL if not found + */ +struct uclass *uclass_find(enum uclass_id key); + +/** + * uclass_destroy() - Destroy a uclass + * + * Destroy a uclass and all its devices + * + * @uc: uclass to destroy + * @return 0 on success, -ve on error + */ +int uclass_destroy(struct uclass *uc); + +#endif diff --git a/include/dm/uclass.h b/include/dm/uclass.h new file mode 100644 index 0000000000..cd23cfed16 --- /dev/null +++ b/include/dm/uclass.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _DM_UCLASS_H +#define _DM_UCLASS_H + +#include <dm/uclass-id.h> +#include <linux/list.h> + +/** + * struct uclass - a U-Boot drive class, collecting together similar drivers + * + * A uclass provides an interface to a particular function, which is + * implemented by one or more drivers. Every driver belongs to a uclass even + * if it is the only driver in that uclass. An example uclass is GPIO, which + * provides the ability to change read inputs, set and clear outputs, etc. + * There may be drivers for on-chip SoC GPIO banks, I2C GPIO expanders and + * PMIC IO lines, all made available in a unified way through the uclass. + * + * @priv: Private data for this uclass + * @uc_drv: The driver for the uclass itself, not to be confused with a + * 'struct driver' + * dev_head: List of devices in this uclass (devices are attached to their + * uclass when their bind method is called) + * @sibling_node: Next uclass in the linked list of uclasses + */ +struct uclass { + void *priv; + struct uclass_driver *uc_drv; + struct list_head dev_head; + struct list_head sibling_node; +}; + +struct device; + +/** + * struct uclass_driver - Driver for the uclass + * + * A uclass_driver provides a consistent interface to a set of related + * drivers. + * + * @name: Name of uclass driver + * @id: ID number of this uclass + * @post_bind: Called after a new device is bound to this uclass + * @pre_unbind: Called before a device is unbound from this uclass + * @post_probe: Called after a new device is probed + * @pre_remove: Called before a device is removed + * @init: Called to set up the uclass + * @destroy: Called to destroy the uclass + * @priv_auto_alloc_size: If non-zero this is the size of the private data + * to be allocated in the uclass's ->priv pointer. If zero, then the uclass + * driver is responsible for allocating any data required. + * @per_device_auto_alloc_size: Each device can hold private data owned + * by the uclass. If required this will be automatically allocated if this + * value is non-zero. + * @ops: Uclass operations, providing the consistent interface to devices + * within the uclass. + */ +struct uclass_driver { + const char *name; + enum uclass_id id; + int (*post_bind)(struct device *dev); + int (*pre_unbind)(struct device *dev); + int (*post_probe)(struct device *dev); + int (*pre_remove)(struct device *dev); + int (*init)(struct uclass *class); + int (*destroy)(struct uclass *class); + int priv_auto_alloc_size; + int per_device_auto_alloc_size; + const void *ops; +}; + +/* Declare a new uclass_driver */ +#define UCLASS_DRIVER(__name) \ + ll_entry_declare(struct uclass_driver, __name, uclass) + +/** + * uclass_get() - Get a uclass based on an ID, creating it if needed + * + * Every uclass is identified by an ID, a number from 0 to n-1 where n is + * the number of uclasses. This function allows looking up a uclass by its + * ID. + * + * @key: ID to look up + * @ucp: Returns pointer to uclass (there is only one per ID) + * @return 0 if OK, -ve on error + */ +int uclass_get(enum uclass_id key, struct uclass **ucp); + +/** + * uclass_get_device() - Get a uclass device based on an ID and index + * + * id: ID to look up + * @index: Device number within that uclass (0=first) + * @ucp: Returns pointer to uclass (there is only one per for each ID) + * @return 0 if OK, -ve on error + */ +int uclass_get_device(enum uclass_id id, int index, struct device **ucp); + +/** + * uclass_first_device() - Get the first device in a uclass + * + * @id: Uclass ID to look up + * @devp: Returns pointer to the first device in that uclass, or NULL if none + * @return 0 if OK (found or not found), -1 on error + */ +int uclass_first_device(enum uclass_id id, struct device **devp); + +/** + * uclass_next_device() - Get the next device in a uclass + * + * @devp: On entry, pointer to device to lookup. On exit, returns pointer + * to the next device in the same uclass, or NULL if none + * @return 0 if OK (found or not found), -1 on error + */ +int uclass_next_device(struct device **devp); + +/** + * uclass_foreach_dev() - Helper function to iteration through devices + * + * This creates a for() loop which works through the available devices in + * a uclass in order from start to end. + * + * @pos: struct device * to hold the current device. Set to NULL when there + * are no more devices. + * uc: uclass to scan + */ +#define uclass_foreach_dev(pos, uc) \ + for (pos = list_entry((&(uc)->dev_head)->next, typeof(*pos), \ + uclass_node); \ + prefetch(pos->uclass_node.next), \ + &pos->uclass_node != (&(uc)->dev_head); \ + pos = list_entry(pos->uclass_node.next, typeof(*pos), \ + uclass_node)) + +#endif diff --git a/include/dm/ut.h b/include/dm/ut.h new file mode 100644 index 0000000000..fa9eac0226 --- /dev/null +++ b/include/dm/ut.h @@ -0,0 +1,95 @@ +/* + * Simple unit test library for driver model + * + * Copyright (c) 2013 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __DM_UT_H +#define __DM_UT_H + +struct dm_test_state; + +/** + * ut_fail() - Record failure of a unit test + * + * @dms: Test state + * @fname: Filename where the error occured + * @line: Line number where the error occured + * @func: Function name where the error occured + * @cond: The condition that failed + */ +void ut_fail(struct dm_test_state *dms, const char *fname, int line, + const char *func, const char *cond); + +/** + * ut_failf() - Record failure of a unit test + * + * @dms: Test state + * @fname: Filename where the error occured + * @line: Line number where the error occured + * @func: Function name where the error occured + * @cond: The condition that failed + * @fmt: printf() format string for the error, followed by args + */ +void ut_failf(struct dm_test_state *dms, const char *fname, int line, + const char *func, const char *cond, const char *fmt, ...) + __attribute__ ((format (__printf__, 6, 7))); + + +/* Assert that a condition is non-zero */ +#define ut_assert(cond) \ + if (!(cond)) { \ + ut_fail(dms, __FILE__, __LINE__, __func__, #cond); \ + return -1; \ + } + +/* Assert that a condition is non-zero, with printf() string */ +#define ut_assertf(cond, fmt, args...) \ + if (!(cond)) { \ + ut_failf(dms, __FILE__, __LINE__, __func__, #cond, \ + fmt, ##args); \ + return -1; \ + } + +/* Assert that two int expressions are equal */ +#define ut_asserteq(expr1, expr2) { \ + unsigned int val1 = (expr1), val2 = (expr2); \ + \ + if (val1 != val2) { \ + ut_failf(dms, __FILE__, __LINE__, __func__, \ + #expr1 " == " #expr2, \ + "Expected %d, got %d", val1, val2); \ + return -1; \ + } \ +} + +/* Assert that two string expressions are equal */ +#define ut_asserteq_str(expr1, expr2) { \ + const char *val1 = (expr1), *val2 = (expr2); \ + \ + if (strcmp(val1, val2)) { \ + ut_failf(dms, __FILE__, __LINE__, __func__, \ + #expr1 " = " #expr2, \ + "Expected \"%s\", got \"%s\"", val1, val2); \ + return -1; \ + } \ +} + +/* Assert that two pointers are equal */ +#define ut_asserteq_ptr(expr1, expr2) { \ + const void *val1 = (expr1), *val2 = (expr2); \ + \ + if (val1 != val2) { \ + ut_failf(dms, __FILE__, __LINE__, __func__, \ + #expr1 " = " #expr2, \ + "Expected %p, got %p", val1, val2); \ + return -1; \ + } \ +} + +/* Assert that an operation succeeds (returns 0) */ +#define ut_assertok(cond) ut_asserteq(0, cond) + +#endif diff --git a/include/dm/util.h b/include/dm/util.h new file mode 100644 index 0000000000..8be64a921d --- /dev/null +++ b/include/dm/util.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __DM_UTIL_H + +void dm_warn(const char *fmt, ...); + +#ifdef DEBUG +void dm_dbg(const char *fmt, ...); +#else +static inline void dm_dbg(const char *fmt, ...) +{ +} +#endif + +struct list_head; + +/** + * list_count_items() - Count number of items in a list + * + * @param head: Head of list + * @return number of items, or 0 if empty + */ +int list_count_items(struct list_head *head); + +#endif |