diff options
author | Iru Cai <mytbk920423@gmail.com> | 2019-10-30 14:21:52 +0800 |
---|---|---|
committer | Iru Cai <mytbk920423@gmail.com> | 2019-10-30 14:48:38 +0800 |
commit | ae51f41d14f548d494ac41e0d21137c5a4c3f59c (patch) | |
tree | 6ddb9d1aaa7bd5bad5bbf8497edc2e08ff208d79 /include/dm | |
download | uext4-ae51f41d14f548d494ac41e0d21137c5a4c3f59c.tar.xz |
import the U-Boot code and make it compile
Diffstat (limited to 'include/dm')
30 files changed, 6021 insertions, 0 deletions
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h new file mode 100644 index 0000000..ee2b24a --- /dev/null +++ b/include/dm/device-internal.h @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * Marek Vasut <marex@denx.de> + */ + +#ifndef _DM_DEVICE_INTERNAL_H +#define _DM_DEVICE_INTERNAL_H + +#include <dm/ofnode.h> + +struct device_node; +struct udevice; + +/** + * 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: if non-NULL, returns a pointer to the bound device + * @return 0 if OK, -ve on error + */ +int device_bind(struct udevice *parent, const struct driver *drv, + const char *name, void *platdata, int of_offset, + struct udevice **devp); + +int device_bind_ofnode(struct udevice *parent, const struct driver *drv, + const char *name, void *platdata, ofnode node, + struct udevice **devp); + +/** + * device_bind_with_driver_data() - Create a device and bind it to a driver + * + * Called to set up a new device attached to a driver, in the case where the + * driver was matched to the device by means of a match table that provides + * driver_data. + * + * 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) + * @driver_data: The driver_data field from the driver's match table. + * @node: Device tree node for this device. This is invalid for devices which + * don't use device tree. + * @devp: if non-NULL, returns a pointer to the bound device + * @return 0 if OK, -ve on error + */ +int device_bind_with_driver_data(struct udevice *parent, + const struct driver *drv, const char *name, + ulong driver_data, ofnode node, + struct udevice **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 + * @pre_reloc_only: If true, bind the driver only if its DM_FLAG_PRE_RELOC flag + * is set. If false bind the driver always. + * @info: Name and platdata for this device + * @devp: if non-NULL, returns a pointer to the bound device + * @return 0 if OK, -ve on error + */ +int device_bind_by_name(struct udevice *parent, bool pre_reloc_only, + const struct driver_info *info, struct udevice **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 udevice *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 + * @flags: Flags for selective device removal (DM_REMOVE_...) + * @return 0 if OK, -ve on error (an error here is normally a very bad thing) + */ +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) +int device_remove(struct udevice *dev, uint flags); +#else +static inline int device_remove(struct udevice *dev, uint flags) { return 0; } +#endif + +/** + * 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 + */ +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) +int device_unbind(struct udevice *dev); +#else +static inline int device_unbind(struct udevice *dev) { return 0; } +#endif + +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) +void device_free(struct udevice *dev); +#else +static inline void device_free(struct udevice *dev) {} +#endif + +/** + * device_chld_unbind() - Unbind all device's children from the device if bound + * to drv + * + * On error, the function continues to unbind all children, and reports the + * first error. + * + * @dev: The device that is to be stripped of its children + * @drv: The targeted driver + * @return 0 on success, -ve on error + */ +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) +int device_chld_unbind(struct udevice *dev, struct driver *drv); +#else +static inline int device_chld_unbind(struct udevice *dev, struct driver *drv) +{ + return 0; +} +#endif + +/** + * device_chld_remove() - Stop all device's children + * @dev: The device whose children are to be removed + * @drv: The targeted driver + * @flags: Flag, if this functions is called in the pre-OS stage + * @return 0 on success, -ve on error + */ +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) +int device_chld_remove(struct udevice *dev, struct driver *drv, + uint flags); +#else +static inline int device_chld_remove(struct udevice *dev, struct driver *drv, + uint flags) +{ + return 0; +} +#endif + +/** + * simple_bus_translate() - translate a bus address to a system address + * + * This handles the 'ranges' property in a simple bus. It translates the + * device address @addr to a system address using this property. + * + * @dev: Simple bus device (parent of target device) + * @addr: Address to translate + * @return new address + */ +fdt_addr_t simple_bus_translate(struct udevice *dev, fdt_addr_t addr); + +/* Cast away any volatile pointer */ +#define DM_ROOT_NON_CONST (((gd_t *)gd)->dm_root) +#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 + * + * Release all resources allocated for @dev when it was probed or later. + * This function is called on driver removal. + */ +void devres_release_probe(struct udevice *dev); + +/** + * devres_release_all - Release all managed resources + * @dev: Device to release resources for + * + * Release all resources associated with @dev. This function is + * called on driver unbinding. + */ +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 new file mode 100644 index 0000000..d7ad9d6 --- /dev/null +++ b/include/dm/device.h @@ -0,0 +1,1045 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * Marek Vasut <marex@denx.de> + */ + +#ifndef _DM_DEVICE_H +#define _DM_DEVICE_H + +#include <dm/ofnode.h> +#include <dm/uclass-id.h> +#include <fdtdec.h> +#include <linker_lists.h> +#include <linux/compat.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/printk.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 (1 << 1) + +/* DM should init this device prior to relocation */ +#define DM_FLAG_PRE_RELOC (1 << 2) + +/* DM is responsible for allocating and freeing parent_platdata */ +#define DM_FLAG_ALLOC_PARENT_PDATA (1 << 3) + +/* DM is responsible for allocating and freeing uclass_platdata */ +#define DM_FLAG_ALLOC_UCLASS_PDATA (1 << 4) + +/* Allocate driver private data on a DMA boundary */ +#define DM_FLAG_ALLOC_PRIV_DMA (1 << 5) + +/* Device is bound */ +#define DM_FLAG_BOUND (1 << 6) + +/* Device name is allocated and should be freed on unbind() */ +#define DM_FLAG_NAME_ALLOCED (1 << 7) + +#define DM_FLAG_OF_PLATDATA (1 << 8) + +/* + * Call driver remove function to stop currently active DMA transfers or + * give DMA buffers back to the HW / controller. This may be needed for + * some drivers to do some final stage cleanup before the OS is called + * (U-Boot exit) + */ +#define DM_FLAG_ACTIVE_DMA (1 << 9) + +/* + * Call driver remove function to do some final configuration, before + * U-Boot exits and the OS is started + */ +#define DM_FLAG_OS_PREPARE (1 << 10) + +/* DM does not enable/disable the power domains corresponding to this device */ +#define DM_FLAG_DEFAULT_PD_CTRL_OFF (1 << 11) + +/* + * 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 + * driver flags can be done. + */ +enum { + /* Normal remove, remove all devices */ + DM_REMOVE_NORMAL = 1 << 0, + + /* Remove devices with active DMA */ + DM_REMOVE_ACTIVE_DMA = DM_FLAG_ACTIVE_DMA, + + /* Remove devices which need some final OS preparation steps */ + DM_REMOVE_OS_PREPARE = DM_FLAG_OS_PREPARE, + + /* Add more use cases here */ + + /* Remove devices with any active flag */ + DM_REMOVE_ACTIVE_ALL = DM_REMOVE_ACTIVE_DMA | DM_REMOVE_OS_PREPARE, +}; + +/** + * struct udevice - 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 + * @parent_platdata: The parent bus's configuration data for this device + * @uclass_platdata: The uclass's configuration data for this device + * @node: Reference to device tree node for this device + * @driver_data: Driver data word for the entry that matched this device with + * its driver + * @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 + * @parent_priv: The parent'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_... + * @req_seq: Requested sequence number for this device (-1 = any) + * @seq: Allocated sequence number for this device (-1 = none). This is set up + * when the device is probed and will be unique within the device's uclass. + * @devres_head: List of memory allocations associated with this device. + * When CONFIG_DEVRES is enabled, devm_kmalloc() and friends will + * add to this list. Memory so-allocated will be freed + * automatically when the device is removed / unbound + */ +struct udevice { + const struct driver *driver; + const char *name; + void *platdata; + void *parent_platdata; + void *uclass_platdata; + ofnode node; + ulong driver_data; + struct udevice *parent; + void *priv; + struct uclass *uclass; + void *uclass_priv; + void *parent_priv; + struct list_head uclass_node; + struct list_head child_head; + struct list_head sibling_node; + uint32_t flags; + int req_seq; + int seq; +#ifdef CONFIG_DEVRES + struct list_head devres_head; +#endif +}; + +/* Maximum sequence number supported */ +#define DM_MAX_SEQ 999 + +/* 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) + +static inline int dev_of_offset(const struct udevice *dev) +{ + return ofnode_to_offset(dev->node); +} + +static inline void dev_set_of_offset(struct udevice *dev, int of_offset) +{ + dev->node = offset_to_ofnode(of_offset); +} + +static inline bool dev_has_of_node(struct udevice *dev) +{ + return ofnode_valid(dev->node); +} + +/** + * struct udevice_id - Lists the compatible strings supported by a driver + * @compatible: Compatible string + * @data: Data for this compatible string + */ +struct udevice_id { + const char *compatible; + ulong data; +}; + +#if CONFIG_IS_ENABLED(OF_CONTROL) +#define of_match_ptr(_ptr) (_ptr) +#else +#define of_match_ptr(_ptr) NULL +#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ + +/** + * 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: Identifies 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 + * @child_post_bind: Called after a new child has been bound + * @child_pre_probe: Called before a child device is probed. The device has + * memory allocated but it has not yet been probed. + * @child_post_remove: Called after a child device is removed. The device + * has memory allocated but its device_remove() method has been called. + * @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. + * @per_child_auto_alloc_size: Each device can hold private data owned by + * its parent. If required this will be automatically allocated if this + * value is non-zero. + * @per_child_platdata_auto_alloc_size: A bus likes to store information about + * its children. If non-zero this is the size of this data, to be allocated + * in the child's parent_platdata pointer. + * @ops: Driver-specific operations. This is typically a list of function + * pointers defined by the driver, to implement driver functions required by + * the uclass. + * @flags: driver flags - see DM_FLAGS_... + */ +struct driver { + char *name; + enum uclass_id id; + const struct udevice_id *of_match; + int (*bind)(struct udevice *dev); + int (*probe)(struct udevice *dev); + int (*remove)(struct udevice *dev); + int (*unbind)(struct udevice *dev); + int (*ofdata_to_platdata)(struct udevice *dev); + int (*child_post_bind)(struct udevice *dev); + int (*child_pre_probe)(struct udevice *dev); + int (*child_post_remove)(struct udevice *dev); + int priv_auto_alloc_size; + int platdata_auto_alloc_size; + int per_child_auto_alloc_size; + int per_child_platdata_auto_alloc_size; + const void *ops; /* driver-specific operations */ + uint32_t flags; +}; + +/* Declare a new U-Boot driver */ +#define U_BOOT_DRIVER(__name) \ + ll_entry_declare(struct driver, __name, driver) + +/* Get a pointer to a given driver */ +#define DM_GET_DRIVER(__name) \ + ll_entry_get(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(const struct udevice *dev); + +/** + * dev_get_parent_platdata() - Get the parent platform data for a device + * + * This checks that dev is not NULL, but no other checks for now + * + * @dev Device to check + * @return parent's platform data, or NULL if none + */ +void *dev_get_parent_platdata(const struct udevice *dev); + +/** + * dev_get_uclass_platdata() - Get the uclass platform data for a device + * + * This checks that dev is not NULL, but no other checks for now + * + * @dev Device to check + * @return uclass's platform data, or NULL if none + */ +void *dev_get_uclass_platdata(const struct udevice *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(const struct udevice *dev); + +/** + * dev_get_parent_priv() - Get the parent private data for a device + * + * The parent private data is data stored in the device but owned by the + * parent. For example, a USB device may have parent data which contains + * information about how to talk to the device over USB. + * + * This checks that dev is not NULL, but no other checks for now + * + * @dev Device to check + * @return parent data, or NULL if none + */ +void *dev_get_parent_priv(const struct udevice *dev); + +/** + * dev_get_uclass_priv() - Get the private uclass data for a device + * + * This checks that dev is not NULL, but no other checks for now + * + * @dev Device to check + * @return private uclass data for this device, or NULL if none + */ +void *dev_get_uclass_priv(const struct udevice *dev); + +/** + * struct dev_get_parent() - Get the parent of a device + * + * @child: Child to check + * @return parent of child, or NULL if this is the root device + */ +struct udevice *dev_get_parent(const struct udevice *child); + +/** + * dev_get_driver_data() - get the driver data used to bind a device + * + * When a device is bound using a device tree node, it matches a + * particular compatible string in struct udevice_id. This function + * returns the associated data value for that compatible string. This is + * the 'data' field in struct udevice_id. + * + * As an example, consider this structure: + * static const struct udevice_id tegra_i2c_ids[] = { + * { .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 }, + * { .compatible = "nvidia,tegra20-i2c", .data = TYPE_STD }, + * { .compatible = "nvidia,tegra20-i2c-dvc", .data = TYPE_DVC }, + * { } + * }; + * + * When driver model finds a driver for this it will store the 'data' value + * corresponding to the compatible string it matches. This function returns + * that value. This allows the driver to handle several variants of a device. + * + * For USB devices, this is the driver_info field in struct usb_device_id. + * + * @dev: Device to check + * @return driver data (0 if none is provided) + */ +ulong dev_get_driver_data(const struct udevice *dev); + +/** + * dev_get_driver_ops() - get the device's driver's operations + * + * This checks that dev is not NULL, and returns the pointer to device's + * driver's operations. + * + * @dev: Device to check + * @return void pointer to driver's operations or NULL for NULL-dev or NULL-ops + */ +const void *dev_get_driver_ops(const struct udevice *dev); + +/** + * device_get_uclass_id() - return the uclass ID of a device + * + * @dev: Device to check + * @return uclass ID for the device + */ +enum uclass_id device_get_uclass_id(const struct udevice *dev); + +/** + * dev_get_uclass_name() - return the uclass name of a device + * + * This checks that dev is not NULL. + * + * @dev: Device to check + * @return pointer to the uclass name for the device + */ +const char *dev_get_uclass_name(const struct udevice *dev); + +/** + * device_get_child() - Get the child of a device by index + * + * Returns the numbered child, 0 being the first. This does not use + * sequence numbers, only the natural order. + * + * @dev: Parent device to check + * @index: Child index + * @devp: Returns pointer to device + * @return 0 if OK, -ENODEV if no such device, other error if the device fails + * to probe + */ +int device_get_child(struct udevice *parent, int index, struct udevice **devp); + +/** + * device_get_child_count() - Get the available child count of a device + * + * Returns the number of children to a device. + * + * @parent: Parent device to check + */ +int device_get_child_count(struct udevice *parent); + +/** + * device_find_child_by_seq() - Find a child device based on a sequence + * + * This searches for a device with the given seq or req_seq. + * + * For seq, if an active device has this sequence it will be returned. + * If there is no such device then this will return -ENODEV. + * + * For req_seq, if a device (whether activated or not) has this req_seq + * value, that device will be returned. This is a strong indication that + * the device will receive that sequence when activated. + * + * @parent: Parent device + * @seq_or_req_seq: Sequence number to find (0=first) + * @find_req_seq: true to find req_seq, false to find seq + * @devp: Returns pointer to device (there is only one per for each seq). + * Set to NULL if none is found + * @return 0 if OK, -ve on error + */ +int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq, + bool find_req_seq, struct udevice **devp); + +/** + * device_get_child_by_seq() - Get a child device based on a sequence + * + * If an active device has this sequence it will be returned. If there is no + * such device then this will check for a device that is requesting this + * sequence. + * + * The device is probed to activate it ready for use. + * + * @parent: Parent device + * @seq: Sequence number to find (0=first) + * @devp: Returns pointer to device (there is only one per for each seq) + * Set to NULL if none is found + * @return 0 if OK, -ve on error + */ +int device_get_child_by_seq(struct udevice *parent, int seq, + struct udevice **devp); + +/** + * device_find_child_by_of_offset() - Find a child device based on FDT offset + * + * Locates a child device by its device tree offset. + * + * @parent: Parent device + * @of_offset: Device tree offset to find + * @devp: Returns pointer to device if found, otherwise this is set to NULL + * @return 0 if OK, -ve on error + */ +int device_find_child_by_of_offset(struct udevice *parent, int of_offset, + struct udevice **devp); + +/** + * device_get_child_by_of_offset() - Get a child device based on FDT offset + * + * Locates a child device by its device tree offset. + * + * The device is probed to activate it ready for use. + * + * @parent: Parent device + * @of_offset: Device tree offset to find + * @devp: Returns pointer to device if found, otherwise this is set to NULL + * @return 0 if OK, -ve on error + */ +int device_get_child_by_of_offset(struct udevice *parent, int of_offset, + struct udevice **devp); + +/** + * device_find_global_by_ofnode() - Get a device based on ofnode + * + * Locates a device by its device tree ofnode, searching globally throughout + * the all driver model devices. + * + * The device is NOT probed + * + * @node: Device tree ofnode to find + * @devp: Returns pointer to device if found, otherwise this is set to NULL + * @return 0 if OK, -ve on error + */ + +int device_find_global_by_ofnode(ofnode node, struct udevice **devp); + +/** + * device_get_global_by_ofnode() - Get a device based on ofnode + * + * Locates a device by its device tree ofnode, searching globally throughout + * the all driver model devices. + * + * The device is probed to activate it ready for use. + * + * @node: Device tree ofnode to find + * @devp: Returns pointer to device if found, otherwise this is set to NULL + * @return 0 if OK, -ve on error + */ +int device_get_global_by_ofnode(ofnode node, struct udevice **devp); + +/** + * device_find_first_child() - Find the first child of a device + * + * @parent: Parent device to search + * @devp: Returns first child device, or NULL if none + * @return 0 + */ +int device_find_first_child(struct udevice *parent, struct udevice **devp); + +/** + * device_find_next_child() - Find the next child of a device + * + * @devp: Pointer to previous child device on entry. Returns pointer to next + * child device, or NULL if none + * @return 0 + */ +int device_find_next_child(struct udevice **devp); + +/** + * device_find_first_inactive_child() - Find the first inactive child + * + * This is used to locate an existing child of a device which is of a given + * uclass. + * + * The device is NOT probed + * + * @parent: Parent device to search + * @uclass_id: Uclass to look for + * @devp: Returns device found, if any + * @return 0 if found, else -ENODEV + */ +int device_find_first_inactive_child(struct udevice *parent, + enum uclass_id uclass_id, + struct udevice **devp); + +/** + * device_find_first_child_by_uclass() - Find the first child of a device in uc + * + * @parent: Parent device to search + * @uclass_id: Uclass to look for + * @devp: Returns first child device in that uclass, if any + * @return 0 if found, else -ENODEV + */ +int device_find_first_child_by_uclass(struct udevice *parent, + enum uclass_id uclass_id, + struct udevice **devp); + +/** + * device_find_child_by_name() - Find a child by device name + * + * @parent: Parent device to search + * @name: Name to look for + * @devp: Returns device found, if any + * @return 0 if found, else -ENODEV + */ +int device_find_child_by_name(struct udevice *parent, const char *name, + struct udevice **devp); + +/** + * device_has_children() - check if a device has any children + * + * @dev: Device to check + * @return true if the device has one or more children + */ +bool device_has_children(const struct udevice *dev); + +/** + * device_has_active_children() - check if a device has any active children + * + * @dev: Device to check + * @return true if the device has one or more children and at least one of + * them is active (probed). + */ +bool device_has_active_children(struct udevice *dev); + +/** + * device_is_last_sibling() - check if a device is the last sibling + * + * This function can be useful for display purposes, when special action needs + * to be taken when displaying the last sibling. This can happen when a tree + * view of devices is being displayed. + * + * @dev: Device to check + * @return true if there are no more siblings after this one - i.e. is it + * last in the list. + */ +bool device_is_last_sibling(struct udevice *dev); + +/** + * device_set_name() - set the name of a device + * + * This must be called in the device's bind() method and no later. Normally + * this is unnecessary but for probed devices which don't get a useful name + * this function can be helpful. + * + * The name is allocated and will be freed automatically when the device is + * unbound. + * + * @dev: Device to update + * @name: New name (this string is allocated new memory and attached to + * the device) + * @return 0 if OK, -ENOMEM if there is not enough memory to allocate the + * string + */ +int device_set_name(struct udevice *dev, const char *name); + +/** + * device_set_name_alloced() - note that a device name is allocated + * + * This sets the DM_FLAG_NAME_ALLOCED flag for the device, so that when it is + * unbound the name will be freed. This avoids memory leaks. + * + * @dev: Device to update + */ +void device_set_name_alloced(struct udevice *dev); + +/** + * device_is_compatible() - check if the device is compatible with the compat + * + * This allows to check whether the device is comaptible with the compat. + * + * @dev: udevice pointer for which compatible needs to be verified. + * @compat: Compatible string which needs to verified in the given + * device + * @return true if OK, false if the compatible is not found + */ +bool device_is_compatible(struct udevice *dev, const char *compat); + +/** + * of_machine_is_compatible() - check if the machine is compatible with + * the compat + * + * This allows to check whether the machine is comaptible with the compat. + * + * @compat: Compatible string which needs to verified + * @return true if OK, false if the compatible is not found + */ +bool of_machine_is_compatible(const char *compat); + +/** + * dev_disable_by_path() - Disable a device given its device tree path + * + * @path: The device tree path identifying the device to be disabled + * @return 0 on success, -ve on error + */ +int dev_disable_by_path(const char *path); + +/** + * dev_enable_by_path() - Enable a device given its device tree path + * + * @path: The device tree path identifying the device to be enabled + * @return 0 on success, -ve on error + */ +int dev_enable_by_path(const char *path); + +/** + * device_is_on_pci_bus - Test if a device is on a PCI bus + * + * @dev: device to test + * @return: true if it is on a PCI bus, false otherwise + */ +static inline bool device_is_on_pci_bus(struct udevice *dev) +{ + return device_get_uclass_id(dev->parent) == UCLASS_PCI; +} + +/** + * device_foreach_child_safe() - iterate through child devices safely + * + * This allows the @pos child to be removed in the loop if required. + * + * @pos: struct udevice * for the current device + * @next: struct udevice * for the next device + * @parent: parent device to scan + */ +#define device_foreach_child_safe(pos, next, parent) \ + list_for_each_entry_safe(pos, next, &parent->child_head, sibling_node) + +/** + * device_foreach_child() - iterate through child devices + * + * @pos: struct udevice * for the current device + * @parent: parent device to scan + */ +#define device_foreach_child(pos, parent) \ + list_for_each_entry(pos, &parent->child_head, sibling_node) + +/** + * dm_scan_fdt_dev() - Bind child device in a the device tree + * + * This handles device which have sub-nodes in the device tree. It scans all + * sub-nodes and binds drivers for each node where a driver can be found. + * + * If this is called prior to relocation, only pre-relocation devices will be + * bound (those marked with u-boot,dm-pre-reloc in the device tree, or where + * the driver has the DM_FLAG_PRE_RELOC flag set). Otherwise, all devices will + * be bound. + * + * @dev: Device to scan + * @return 0 if OK, -ve on error + */ +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 */ + +/* + * REVISIT: + * remove the following after resolving conflicts with <linux/compat.h> + */ +#ifdef dev_dbg +#undef dev_dbg +#endif +#ifdef dev_vdbg +#undef dev_vdbg +#endif +#ifdef dev_info +#undef dev_info +#endif +#ifdef dev_err +#undef dev_err +#endif +#ifdef dev_warn +#undef dev_warn +#endif + +/* + * REVISIT: + * print device name like Linux + */ +#define dev_printk(dev, fmt, ...) \ +({ \ + printk(fmt, ##__VA_ARGS__); \ +}) + +#define __dev_printk(level, dev, fmt, ...) \ +({ \ + if (level < CONFIG_VAL(LOGLEVEL)) \ + dev_printk(dev, fmt, ##__VA_ARGS__); \ +}) + +#define dev_emerg(dev, fmt, ...) \ + __dev_printk(0, dev, fmt, ##__VA_ARGS__) +#define dev_alert(dev, fmt, ...) \ + __dev_printk(1, dev, fmt, ##__VA_ARGS__) +#define dev_crit(dev, fmt, ...) \ + __dev_printk(2, dev, fmt, ##__VA_ARGS__) +#define dev_err(dev, fmt, ...) \ + __dev_printk(3, dev, fmt, ##__VA_ARGS__) +#define dev_warn(dev, fmt, ...) \ + __dev_printk(4, dev, fmt, ##__VA_ARGS__) +#define dev_notice(dev, fmt, ...) \ + __dev_printk(5, dev, fmt, ##__VA_ARGS__) +#define dev_info(dev, fmt, ...) \ + __dev_printk(6, dev, fmt, ##__VA_ARGS__) + +#ifdef DEBUG +#define dev_dbg(dev, fmt, ...) \ + __dev_printk(7, dev, fmt, ##__VA_ARGS__) +#else +#define dev_dbg(dev, fmt, ...) \ +({ \ + if (0) \ + __dev_printk(7, dev, fmt, ##__VA_ARGS__); \ +}) +#endif + +#ifdef VERBOSE_DEBUG +#define dev_vdbg dev_dbg +#else +#define dev_vdbg(dev, fmt, ...) \ +({ \ + if (0) \ + __dev_printk(7, dev, fmt, ##__VA_ARGS__); \ +}) +#endif + +#endif diff --git a/include/dm/fdtaddr.h b/include/dm/fdtaddr.h new file mode 100644 index 0000000..959d3bc --- /dev/null +++ b/include/dm/fdtaddr.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2017 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * Marek Vasut <marex@denx.de> + */ + +#ifndef _DM_FDTADDR_H +#define _DM_FDTADDR_H + +#include <fdtdec.h> + +struct udevice; + +/** + * devfdt_get_addr() - Get the reg property of a device + * + * @dev: Pointer to a device + * + * @return addr + */ +fdt_addr_t devfdt_get_addr(struct udevice *dev); + +/** + * devfdt_get_addr_ptr() - Return pointer to the address of the reg property + * of a device + * + * @dev: Pointer to a device + * + * @return Pointer to addr, or NULL if there is no such property + */ +void *devfdt_get_addr_ptr(struct udevice *dev); + +/** + * devfdt_remap_addr() - Return pointer to the memory-mapped I/O address + * of the reg property of a device + * + * @dev: Pointer to a device + * + * @return Pointer to addr, or NULL if there is no such property + */ +void *devfdt_remap_addr(struct udevice *dev); + +/** + * devfdt_remap_addr_index() - Return indexed pointer to the memory-mapped + * I/O address of the reg property of a device + * @index: the 'reg' property can hold a list of <addr, size> pairs + * and @index is used to select which one is required + * + * @dev: Pointer to a device + * + * @return Pointer to addr, or NULL if there is no such property + */ +void *devfdt_remap_addr_index(struct udevice *dev, int index); + +/** + * devfdt_remap_addr_name() - Get the reg property of a device, indexed by + * name, as a memory-mapped I/O pointer + * @name: the 'reg' property can hold a list of <addr, size> pairs, with the + * 'reg-names' property providing named-based identification. @index + * indicates the value to search for in 'reg-names'. + * + * @dev: Pointer to a device + * + * @return Pointer to addr, or NULL if there is no such property + */ +void *devfdt_remap_addr_name(struct udevice *dev, const char *name); + +/** + * devfdt_map_physmem() - Read device address from reg property of the + * device node and map the address into CPU address + * space. + * + * @dev: Pointer to device + * @size: size of the memory to map + * + * @return mapped address, or NULL if the device does not have reg + * property. + */ +void *devfdt_map_physmem(struct udevice *dev, unsigned long size); + +/** + * devfdt_get_addr_index() - Get the indexed reg property of a device + * + * @dev: Pointer to a device + * @index: the 'reg' property can hold a list of <addr, size> pairs + * and @index is used to select which one is required + * + * @return addr + */ +fdt_addr_t devfdt_get_addr_index(struct udevice *dev, int index); + +/** + * devfdt_get_addr_size_index() - Get the indexed reg property of a device + * + * Returns the address and size specified in the 'reg' property of a device. + * + * @dev: Pointer to a device + * @index: the 'reg' property can hold a list of <addr, size> pairs + * and @index is used to select which one is required + * @size: Pointer to size varible - this function returns the size + * specified in the 'reg' property here + * + * @return addr + */ +fdt_addr_t devfdt_get_addr_size_index(struct udevice *dev, int index, + fdt_size_t *size); + +/** + * devfdt_get_addr_name() - Get the reg property of a device, indexed by name + * + * @dev: Pointer to a device + * @name: the 'reg' property can hold a list of <addr, size> pairs, with the + * 'reg-names' property providing named-based identification. @index + * indicates the value to search for in 'reg-names'. + * + * @return addr + */ +fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name); + +/** + * devfdt_get_addr_size_name() - Get the reg property and its size for a device, + * indexed by name + * + * Returns the address and size specified in the 'reg' property of a device. + * + * @dev: Pointer to a device + * @name: the 'reg' property can hold a list of <addr, size> pairs, with the + * 'reg-names' property providing named-based identification. @index + * indicates the value to search for in 'reg-names'. + * @size: Pointer to size variable - this function returns the size + * specified in the 'reg' property here + * + * @return addr + */ +fdt_addr_t devfdt_get_addr_size_name(struct udevice *dev, const char *name, + fdt_size_t *size); + +/** + * devfdt_get_addr_pci() - Read an address and handle PCI address translation + * + * @dev: Device to read from + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t devfdt_get_addr_pci(struct udevice *dev); + +#endif diff --git a/include/dm/lists.h b/include/dm/lists.h new file mode 100644 index 0000000..810e244 --- /dev/null +++ b/include/dm/lists.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + */ + +#ifndef _DM_LISTS_H_ +#define _DM_LISTS_H_ + +#include <dm/ofnode.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); + +/** + * lists_bind_drivers() - search for and bind all drivers to parent + * + * This searches the U_BOOT_DEVICE() structures and creates new devices for + * each one. The devices will have @parent as their parent. + * + * @parent: parent device (root) + * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC flag. + * If false bind all drivers. + */ +int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only); + +/** + * lists_bind_fdt() - bind a device tree node + * + * This creates a new device bound to the given device tree node, with + * @parent as its parent. + * + * @parent: parent device (root) + * @node: device tree node to bind + * @devp: if non-NULL, returns a pointer to the bound device + * @pre_reloc_only: If true, bind only nodes with special devicetree properties, + * or drivers with the DM_FLAG_PRE_RELOC flag. If false bind all drivers. + * @return 0 if device was bound, -EINVAL if the device tree is invalid, + * other -ve value on error + */ +int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, + bool pre_reloc_only); + +/** + * device_bind_driver() - bind a device to a driver + * + * This binds a new device to a driver. + * + * @parent: Parent device + * @drv_name: Name of driver to attach to this parent + * @dev_name: Name of the new device thus created + * @devp: If non-NULL, returns the newly bound device + */ +int device_bind_driver(struct udevice *parent, const char *drv_name, + const char *dev_name, struct udevice **devp); + +/** + * device_bind_driver_to_node() - bind a device to a driver for a node + * + * This binds a new device to a driver for a given device tree node. This + * should only be needed if the node lacks a compatible strings. + * + * @parent: Parent device + * @drv_name: Name of driver to attach to this parent + * @dev_name: Name of the new device thus created + * @node: Device tree node + * @devp: If non-NULL, returns the newly bound device + */ +int device_bind_driver_to_node(struct udevice *parent, const char *drv_name, + const char *dev_name, ofnode node, + struct udevice **devp); + +#endif diff --git a/include/dm/of.h b/include/dm/of.h new file mode 100644 index 0000000..6bef73b --- /dev/null +++ b/include/dm/of.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + */ + +#ifndef _DM_OF_H +#define _DM_OF_H + +#include <asm/u-boot.h> +#include <asm/global_data.h> + +/* integer value within a device tree property which references another node */ +typedef u32 phandle; + +/** + * struct property: Device tree property + * + * @name: Property name + * @length: Length of property in bytes + * @value: Pointer to property value + * @next: Pointer to next property, or NULL if none + */ +struct property { + char *name; + int length; + void *value; + struct property *next; +}; + +/** + * struct device_node: Device tree node + * + * @name: Node name + * @type: Node type (value of device_type property) or "<NULL>" if none + * @phandle: Phandle value of this none, or 0 if none + * @full_name: Full path to node, e.g. "/bus@1/spi@1100" + * @properties: Pointer to head of list of properties, or NULL if none + * @parent: Pointer to parent node, or NULL if this is the root node + * @child: Pointer to head of child node list, or NULL if no children + * @sibling: Pointer to the next sibling node, or NULL if this is the last + */ +struct device_node { + const char *name; + const char *type; + phandle phandle; + const char *full_name; + + struct property *properties; + struct device_node *parent; + struct device_node *child; + struct device_node *sibling; +}; + +#define OF_MAX_PHANDLE_ARGS 16 + +/** + * struct of_phandle_args - structure to hold phandle and arguments + * + * This is used when decoding a phandle in a device tree property. Typically + * these look like this: + * + * wibble { + * phandle = <5>; + * }; + * + * ... + * some-prop = <&wibble 1 2 3> + * + * Here &node is the phandle of the node 'wibble', i.e. 5. There are three + * arguments: 1, 2, 3. + * + * So when decoding the phandle in some-prop, np will point to wibble, + * args_count will be 3 and the three arguments will be in args. + * + * @np: Node that the phandle refers to + * @args_count: Number of arguments + * @args: Argument values + */ +struct of_phandle_args { + struct device_node *np; + int args_count; + uint32_t args[OF_MAX_PHANDLE_ARGS]; +}; + +DECLARE_GLOBAL_DATA_PTR; + +/** + * of_live_active() - check if livetree is active + * + * @returns true if livetree is active, false it not + */ +#ifdef CONFIG_OF_LIVE +static inline bool of_live_active(void) +{ + return gd->of_root != NULL; +} +#else +static inline bool of_live_active(void) +{ + return false; +} +#endif + +#define OF_BAD_ADDR ((u64)-1) + +static inline const char *of_node_full_name(const struct device_node *np) +{ + return np ? np->full_name : "<no-node>"; +} + +/* Default #address and #size cells */ +#if !defined(OF_ROOT_NODE_ADDR_CELLS_DEFAULT) +#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 2 +#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 +#endif + +/* Default string compare functions */ +#if !defined(of_compat_cmp) +#define of_compat_cmp(s1, s2, l) strcasecmp((s1), (s2)) +#define of_prop_cmp(s1, s2) strcmp((s1), (s2)) +#define of_node_cmp(s1, s2) strcasecmp((s1), (s2)) +#endif + +/* Helper to read a big number; size is in cells (not bytes) */ +static inline u64 of_read_number(const __be32 *cell, int size) +{ + u64 r = 0; + while (size--) + r = (r << 32) | be32_to_cpu(*(cell++)); + return r; +} + +/* Like of_read_number, but we want an unsigned long result */ +static inline unsigned long of_read_ulong(const __be32 *cell, int size) +{ + /* toss away upper bits if unsigned long is smaller than u64 */ + return of_read_number(cell, size); +} + +#endif diff --git a/include/dm/of_access.h b/include/dm/of_access.h new file mode 100644 index 0000000..13fedb7 --- /dev/null +++ b/include/dm/of_access.h @@ -0,0 +1,444 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Originally from Linux v4.9 + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp. + * Updates for SPARC64 by David S. Miller + * Derived from PowerPC and Sparc prom.h files by Stephen Rothwell, IBM Corp. + * + * Copyright (c) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * Modified for U-Boot + * Copyright (c) 2017 Google, Inc + */ + +#ifndef _DM_OF_ACCESS_H +#define _DM_OF_ACCESS_H + +#include <dm/of.h> + +/** + * of_find_all_nodes - Get next node in global list + * @prev: Previous node or NULL to start iteration + * of_node_put() will be called on it + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_all_nodes(struct device_node *prev); + +#define for_each_of_allnodes_from(from, dn) \ + for (dn = of_find_all_nodes(from); dn; dn = of_find_all_nodes(dn)) +#define for_each_of_allnodes(dn) for_each_of_allnodes_from(NULL, dn) + +/* Dummy functions to mirror Linux. These are not used in U-Boot */ +#define of_node_get(x) (x) +static inline void of_node_put(const struct device_node *np) { } + +/** + * of_n_addr_cells() - Get the number of address cells for a node + * + * This walks back up the tree to find the closest #address-cells property + * which controls the given node. + * + * @np: Node pointer to check + * @return number of address cells this node uses + */ +int of_n_addr_cells(const struct device_node *np); + +/** + * of_n_size_cells() - Get the number of size cells for a node + * + * This walks back up the tree to find the closest #size-cells property + * which controls the given node. + * + * @np: Node pointer to check + * @return number of size cells this node uses + */ +int of_n_size_cells(const struct device_node *np); + +/** + * of_simple_addr_cells() - Get the address cells property in a node + * + * This function matches fdt_address_cells(). + * + * @np: Node pointer to check + * @return value of #address-cells property in this node, or 2 if none + */ +int of_simple_addr_cells(const struct device_node *np); + +/** + * of_simple_size_cells() - Get the size cells property in a node + * + * This function matches fdt_size_cells(). + * + * @np: Node pointer to check + * @return value of #size-cells property in this node, or 2 if none + */ +int of_simple_size_cells(const struct device_node *np); + +/** + * of_find_property() - find a property in a node + * + * @np: Pointer to device node holding property + * @name: Name of property + * @lenp: If non-NULL, returns length of property + * @return pointer to property, or NULL if not found + */ +struct property *of_find_property(const struct device_node *np, + const char *name, int *lenp); + +/** + * of_get_property() - get a property value + * + * Find a property with a given name for a given node and return the value. + * + * @np: Pointer to device node holding property + * @name: Name of property + * @lenp: If non-NULL, returns length of property + * @return pointer to property value, or NULL if not found + */ +const void *of_get_property(const struct device_node *np, const char *name, + int *lenp); + +/** + * of_device_is_compatible() - Check if the node matches given constraints + * @device: pointer to node + * @compat: required compatible string, NULL or "" for any match + * @type: required device_type value, NULL or "" for any match + * @name: required node name, NULL or "" for any match + * + * Checks if the given @compat, @type and @name strings match the + * properties of the given @device. A constraints can be skipped by + * passing NULL or an empty string as the constraint. + * + * @return 0 for no match, and a positive integer on match. The return + * value is a relative score with larger values indicating better + * matches. The score is weighted for the most specific compatible value + * to get the highest score. Matching type is next, followed by matching + * name. Practically speaking, this results in the following priority + * order for matches: + * + * 1. specific compatible && type && name + * 2. specific compatible && type + * 3. specific compatible && name + * 4. specific compatible + * 5. general compatible && type && name + * 6. general compatible && type + * 7. general compatible && name + * 8. general compatible + * 9. type && name + * 10. type + * 11. name + */ +int of_device_is_compatible(const struct device_node *np, const char *compat, + const char *type, const char *name); + +/** + * of_device_is_available() - check if a device is available for use + * + * @device: Node to check for availability + * + * @return true if the status property is absent or set to "okay", false + * otherwise + */ +bool of_device_is_available(const struct device_node *np); + +/** + * of_get_parent() - Get a node's parent, if any + * + * @node: Node to check + * @eturns a node pointer, or NULL if none + */ +struct device_node *of_get_parent(const struct device_node *np); + +/** + * of_find_node_opts_by_path() - Find a node matching a full OF path + * + * @path: Either the full path to match, or if the path does not start with + * '/', the name of a property of the /aliases node (an alias). In the + * case of an alias, the node matching the alias' value will be returned. + * @opts: Address of a pointer into which to store the start of an options + * string appended to the end of the path with a ':' separator. Can be NULL + * + * Valid paths: + * /foo/bar Full path + * foo Valid alias + * foo/bar Valid alias + relative path + * + * @return a node pointer or NULL if not found + */ +struct device_node *of_find_node_opts_by_path(const char *path, + const char **opts); + +static inline struct device_node *of_find_node_by_path(const char *path) +{ + return of_find_node_opts_by_path(path, NULL); +} + +/** + * of_find_compatible_node() - find a node based on its compatible string + * + * Find a node based on type and one of the tokens in its "compatible" property + * @from: Node to start searching from or NULL. the node you pass will not be + * searched, only the next one will; typically, you pass what the previous + * call returned. + * @type: The type string to match "device_type" or NULL to ignore + * @compatible: The string to match to one of the tokens in the device + * "compatible" list. + * @return node pointer or NULL if not found + */ +struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compatible); + +/** + * of_find_node_by_prop_value() - find a node with a given property value + * + * Find a node based on a property value. + * @from: Node to start searching from or NULL. the node you pass will not be + * searched, only the next one will; typically, you pass what the previous + * call returned. + * @propname: property name to check + * @propval: property value to search for + * @proplen: length of the value in propval + * @return node pointer or NULL if not found + */ +struct device_node *of_find_node_by_prop_value(struct device_node *from, + const char *propname, + const void *propval, + int proplen); +/** + * of_find_node_by_phandle() - Find a node given a phandle + * + * @handle: phandle of the node to find + * + * @return node pointer, or NULL if not found + */ +struct device_node *of_find_node_by_phandle(phandle handle); + +/** + * of_read_u32() - Find and read a 32-bit integer from a property + * + * Search for a property in a device node and read a 32-bit value from + * it. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @outp: pointer to return value, modified only if return value is 0. + * + * @return 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + */ +int of_read_u32(const struct device_node *np, const char *propname, u32 *outp); + +/** + * of_read_u64() - Find and read a 64-bit integer from a property + * + * Search for a property in a device node and read a 64-bit value from + * it. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @outp: pointer to return value, modified only if return value is 0. + * + * @return 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + */ +int of_read_u64(const struct device_node *np, const char *propname, u64 *outp); + +/** + * of_read_u32_array() - Find and read an array of 32 bit integers + * + * Search for a property in a device node and read 32-bit value(s) from + * it. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @out_values: pointer to return value, modified only if return value is 0. + * @sz: number of array elements to read + * @return 0 on success, -EINVAL if the property does not exist, -ENODATA + * if property does not have a value, and -EOVERFLOW is longer than sz. + */ +int of_read_u32_array(const struct device_node *np, const char *propname, + u32 *out_values, size_t sz); + +/** + * of_property_match_string() - Find string in a list and return index + * + * This function searches a string list property and returns the index + * of a specific string value. + * + * @np: pointer to node containing string list property + * @propname: string list property name + * @string: pointer to string to search for in string list + * @return 0 on success, -EINVAL if the property does not exist, -ENODATA + * if property does not have a value, and -EOVERFLOW is longer than sz. + */ +int of_property_match_string(const struct device_node *np, const char *propname, + const char *string); + +int of_property_read_string_helper(const struct device_node *np, + const char *propname, const char **out_strs, + size_t sz, int index); + +/** + * of_property_read_string_index() - Find and read a string from a multiple + * strings property. + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @index: index of the string in the list of strings + * @out_string: pointer to null terminated return string, modified only if + * return value is 0. + * + * Search for a property in a device tree node and retrieve a null + * terminated string value (pointer to data, not a copy) in the list of strings + * contained in that property. + * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if + * property does not have a value, and -EILSEQ if the string is not + * null-terminated within the length of the property data. + * + * The out_string pointer is modified only if a valid string can be decoded. + */ +static inline int of_property_read_string_index(const struct device_node *np, + const char *propname, + int index, const char **output) +{ + int rc = of_property_read_string_helper(np, propname, output, 1, index); + return rc < 0 ? rc : 0; +} + +/** + * of_property_count_strings() - Find and return the number of strings from a + * multiple strings property. + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device tree node and retrieve the number of null + * terminated string contain in it. Returns the number of strings on + * success, -EINVAL if the property does not exist, -ENODATA if property + * does not have a value, and -EILSEQ if the string is not null-terminated + * within the length of the property data. + */ +static inline int of_property_count_strings(const struct device_node *np, + const char *propname) +{ + return of_property_read_string_helper(np, propname, NULL, 0, 0); +} + +/** + * of_parse_phandle - Resolve a phandle property to a device_node pointer + * @np: Pointer to device node holding phandle property + * @phandle_name: Name of property holding a phandle value + * @index: For properties holding a table of phandles, this is the index into + * the table + * + * Returns the device_node pointer with refcount incremented. Use + * of_node_put() on it when done. + */ +struct device_node *of_parse_phandle(const struct device_node *np, + const char *phandle_name, int index); + +/** + * of_parse_phandle_with_args() - Find a node pointed by phandle in a list + * + * @np: pointer to a device tree node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * @index: index of a phandle to parse out + * @out_args: optional pointer to output arguments structure (will be filled) + * @return 0 on success (with @out_args filled out if not NULL), -ENOENT if + * @list_name does not exist, -EINVAL if a phandle was not found, + * @cells_name could not be found, the arguments were truncated or there + * were too many arguments. + * + * This function is useful to parse lists of phandles and their arguments. + * Returns 0 on success and fills out_args, on error returns appropriate + * errno value. + * + * Caller is responsible to call of_node_put() on the returned out_args->np + * pointer. + * + * Example: + * + * phandle1: node1 { + * #list-cells = <2>; + * } + * + * phandle2: node2 { + * #list-cells = <1>; + * } + * + * node3 { + * list = <&phandle1 1 2 &phandle2 3>; + * } + * + * To get a device_node of the `node2' node you may call this: + * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); + */ +int of_parse_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name, + int index, struct of_phandle_args *out_args); + +/** + * of_count_phandle_with_args() - Count the number of phandle in a list + * + * @np: pointer to a device tree node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * @return number of phandle found, -ENOENT if + * @list_name does not exist, -EINVAL if a phandle was not found, + * @cells_name could not be found, the arguments were truncated or there + * were too many arguments. + * + * Returns number of phandle found on success, on error returns appropriate + * errno value. + * + */ +int of_count_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name); + +/** + * of_alias_scan() - Scan all properties of the 'aliases' node + * + * The function scans all the properties of the 'aliases' node and populates + * the lookup table with the properties. It returns the number of alias + * properties found, or an error code in case of failure. + * + * @return 9 if OK, -ENOMEM if not enough memory + */ +int of_alias_scan(void); + +/** + * of_alias_get_id - Get alias id for the given device_node + * + * Travels the lookup table to get the alias id for the given device_node and + * alias stem. + * + * @np: Pointer to the given device_node + * @stem: Alias stem of the given device_node + * @return alias ID, if found, else -ENODEV + */ +int of_alias_get_id(const struct device_node *np, const char *stem); + +/** + * of_alias_get_highest_id - Get highest alias id for the given stem + * @stem: Alias stem to be examined + * + * The function travels the lookup table to get the highest alias id for the + * given alias stem. + * @return alias ID, if found, else -1 + */ +int of_alias_get_highest_id(const char *stem); + +/** + * of_get_stdout() - Get node to use for stdout + * + * @return node referred to by stdout-path alias, or NULL if none + */ +struct device_node *of_get_stdout(void); + +#endif diff --git a/include/dm/of_addr.h b/include/dm/of_addr.h new file mode 100644 index 0000000..3fa1ffc --- /dev/null +++ b/include/dm/of_addr.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Taken from Linux v4.9 drivers/of/address.c + * + * Modified for U-Boot + * Copyright (c) 2017 Google, Inc + */ + +#ifndef _DM_OF_ADDR_H +#define _DM_OF_ADDR_H + +/** + * of_translate_address() - translate a device-tree address to a CPU address + * + * Translate an address from the device-tree into a CPU physical address, + * this walks up the tree and applies the various bus mappings on the way. + * + * Note: We consider that crossing any level with #size-cells == 0 to mean + * that translation is impossible (that is we are not dealing with a value + * that can be mapped to a cpu physical address). This is not really specified + * that way, but this is traditionally the way IBM at least do things + * + * @np: node to check + * @in_addr: pointer to input address + * @return translated address or OF_BAD_ADDR on error + */ +u64 of_translate_address(const struct device_node *no, const __be32 *in_addr); + +/** + * of_translate_dma_address() - translate a device-tree DMA address to a CPU + * address + * + * Translate a DMA address from the device-tree into a CPU physical address, + * this walks up the tree and applies the various bus mappings on the way. + * + * Note: We consider that crossing any level with #size-cells == 0 to mean + * that translation is impossible (that is we are not dealing with a value + * that can be mapped to a cpu physical address). This is not really specified + * that way, but this is traditionally the way IBM at least do things + * + * @np: node to check + * @in_addr: pointer to input DMA address + * @return translated DMA address or OF_BAD_ADDR on error + */ +u64 of_translate_dma_address(const struct device_node *no, const __be32 *in_addr); + +/** + * of_get_address() - obtain an address from a node + * + * Extract an address from a node, returns the region size and the address + * space flags too. The PCI version uses a BAR number instead of an absolute + * index. + * + * @np: Node to check + * @index: Index of address to read (0 = first) + * @size: place to put size on success + * @flags: place to put flags on success + * @return pointer to address which can be read + */ +const __be32 *of_get_address(const struct device_node *no, int index, + u64 *size, unsigned int *flags); + +struct resource; + +/** + * of_address_to_resource() - translate device tree address to resource + * + * Note that if your address is a PIO address, the conversion will fail if + * the physical address can't be internally converted to an IO token with + * pci_address_to_pio(), that is because it's either called to early or it + * can't be matched to any host bridge IO space + * + * @np: node to check + * @index: index of address to read (0 = first) + * @r: place to put resource information + * @return 0 if OK, -ve on error + */ +int of_address_to_resource(const struct device_node *no, int index, + struct resource *r); + +#endif diff --git a/include/dm/of_extra.h b/include/dm/of_extra.h new file mode 100644 index 0000000..ca15df2 --- /dev/null +++ b/include/dm/of_extra.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + */ + +#ifndef _DM_OF_EXTRA_H +#define _DM_OF_EXTRA_H + +#include <dm/ofnode.h> + +enum fmap_compress_t { + FMAP_COMPRESS_NONE, + FMAP_COMPRESS_LZ4, +}; + +enum fmap_hash_t { + FMAP_HASH_NONE, + FMAP_HASH_SHA1, + FMAP_HASH_SHA256, +}; + +/* A flash map entry, containing an offset and length */ +struct fmap_entry { + uint32_t offset; + uint32_t length; + uint32_t used; /* Number of bytes used in region */ + enum fmap_compress_t compress_algo; /* Compression type */ + uint32_t unc_length; /* Uncompressed length */ + enum fmap_hash_t hash_algo; /* Hash algorithm */ + const uint8_t *hash; /* Hash value */ + int hash_size; /* Hash size */ +}; + +/** + * Read a flash entry from the fdt + * + * @param node Reference to node to read + * @param entry Place to put offset and size of this node + * @return 0 if ok, -ve on error + */ +int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry); + +/** + * ofnode_decode_region() - Decode a memory region from a node + * + * Look up a property in a node which contains a memory region address and + * size. Then return a pointer to this address. + * + * The property must hold one address with a length. This is only tested on + * 32-bit machines. + * + * @param node ofnode to examine + * @param prop_name name of property to find + * @param basep Returns base address of region + * @param size Returns size of region + * @return 0 if ok, -1 on error (property not found) + */ +int ofnode_decode_region(ofnode node, const char *prop_name, fdt_addr_t *basep, + fdt_size_t *sizep); + +/** + * ofnode_decode_memory_region()- Decode a named region within a memory bank + * + * This function handles selection of a memory region. The region is + * specified as an offset/size within a particular type of memory. + * + * The properties used are: + * + * <mem_type>-memory<suffix> for the name of the memory bank + * <mem_type>-offset<suffix> for the offset in that bank + * + * The property value must have an offset and a size. The function checks + * that the region is entirely within the memory bank.5 + * + * @param node ofnode containing the properties (-1 for /config) + * @param mem_type Type of memory to use, which is a name, such as + * "u-boot" or "kernel". + * @param suffix String to append to the memory/offset + * property names + * @param basep Returns base of region + * @param sizep Returns size of region + * @return 0 if OK, -ive on error + */ +int ofnode_decode_memory_region(ofnode config_node, const char *mem_type, + const char *suffix, fdt_addr_t *basep, + fdt_size_t *sizep); + +#endif diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h new file mode 100644 index 0000000..5c4cbf0 --- /dev/null +++ b/include/dm/ofnode.h @@ -0,0 +1,853 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + */ + +#ifndef _DM_OFNODE_H +#define _DM_OFNODE_H + +/* TODO(sjg@chromium.org): Drop fdtdec.h include */ +#include <fdtdec.h> +#include <dm/of.h> + +/* Enable checks to protect against invalid calls */ +#undef OF_CHECKS + +struct resource; + +/** + * ofnode - reference to a device tree node + * + * This union can hold either a straightforward pointer to a struct device_node + * in the live device tree, or an offset within the flat device tree. In the + * latter case, the pointer value is just the integer offset within the flat DT. + * + * Thus we can reference nodes in both the live tree (once available) and the + * flat tree (until then). Functions are available to translate between an + * ofnode and either an offset or a struct device_node *. + * + * The reference can also hold a null offset, in which case the pointer value + * here is NULL. This corresponds to a struct device_node * value of + * NULL, or an offset of -1. + * + * There is no ambiguity as to whether ofnode holds an offset or a node + * pointer: when the live tree is active it holds a node pointer, otherwise it + * holds an offset. The value itself does not need to be unique and in theory + * the same value could point to a valid device node or a valid offset. We + * could arrange for a unique value to be used (e.g. by making the pointer + * point to an offset within the flat device tree in the case of an offset) but + * this increases code size slightly due to the subtraction. Since it offers no + * real benefit, the approach described here seems best. + * + * For now these points use constant types, since we don't allow writing + * the DT. + * + * @np: Pointer to device node, used for live tree + * @of_offset: Pointer into flat device tree, used for flat tree. Note that this + * is not a really a pointer to a node: it is an offset value. See above. + */ +typedef union ofnode_union { + const struct device_node *np; /* will be used for future live tree */ + long of_offset; +} ofnode; + +struct ofnode_phandle_args { + ofnode node; + int args_count; + uint32_t args[OF_MAX_PHANDLE_ARGS]; +}; + +/** + * _ofnode_to_np() - convert an ofnode to a live DT node pointer + * + * This cannot be called if the reference contains an offset. + * + * @node: Reference containing struct device_node * (possibly invalid) + * @return pointer to device node (can be NULL) + */ +static inline const struct device_node *ofnode_to_np(ofnode node) +{ +#ifdef OF_CHECKS + if (!of_live_active()) + return NULL; +#endif + return node.np; +} + +/** + * ofnode_to_offset() - convert an ofnode to a flat DT offset + * + * This cannot be called if the reference contains a node pointer. + * + * @node: Reference containing offset (possibly invalid) + * @return DT offset (can be -1) + */ +static inline int ofnode_to_offset(ofnode node) +{ +#ifdef OF_CHECKS + if (of_live_active()) + return -1; +#endif + return node.of_offset; +} + +/** + * ofnode_valid() - check if an ofnode is valid + * + * @return true if the reference contains a valid ofnode, false if it is NULL + */ +static inline bool ofnode_valid(ofnode node) +{ + if (of_live_active()) + return node.np != NULL; + else + return node.of_offset != -1; +} + +/** + * offset_to_ofnode() - convert a DT offset to an ofnode + * + * @of_offset: DT offset (either valid, or -1) + * @return reference to the associated DT offset + */ +static inline ofnode offset_to_ofnode(int of_offset) +{ + ofnode node; + + if (of_live_active()) + node.np = NULL; + else + node.of_offset = of_offset; + + return node; +} + +/** + * np_to_ofnode() - convert a node pointer to an ofnode + * + * @np: Live node pointer (can be NULL) + * @return reference to the associated node pointer + */ +static inline ofnode np_to_ofnode(const struct device_node *np) +{ + ofnode node; + + node.np = np; + + return node; +} + +/** + * ofnode_is_np() - check if a reference is a node pointer + * + * This function associated that if there is a valid live tree then all + * references will use it. This is because using the flat DT when the live tree + * is valid is not permitted. + * + * @node: reference to check (possibly invalid) + * @return true if the reference is a live node pointer, false if it is a DT + * offset + */ +static inline bool ofnode_is_np(ofnode node) +{ +#ifdef OF_CHECKS + /* + * Check our assumption that flat tree offsets are not used when a + * live tree is in use. + */ + assert(!ofnode_valid(node) || + (of_live_active() ? _ofnode_to_np(node) + : _ofnode_to_np(node))); +#endif + return of_live_active() && ofnode_valid(node); +} + +/** + * ofnode_equal() - check if two references are equal + * + * @return true if equal, else false + */ +static inline bool ofnode_equal(ofnode ref1, ofnode ref2) +{ + /* We only need to compare the contents */ + return ref1.of_offset == ref2.of_offset; +} + +/** + * ofnode_null() - Obtain a null ofnode + * + * This returns an ofnode which points to no node. It works both with the flat + * tree and livetree. + */ +static inline ofnode ofnode_null(void) +{ + ofnode node; + + if (of_live_active()) + node.np = NULL; + else + node.of_offset = -1; + + return node; +} + +/** + * ofnode_read_u32() - Read a 32-bit integer from a property + * + * @ref: valid node reference to read property from + * @propname: name of the property to read from + * @outp: place to put value (if found) + * @return 0 if OK, -ve on error + */ +int ofnode_read_u32(ofnode node, const char *propname, u32 *outp); + +/** + * ofnode_read_s32() - Read a 32-bit integer from a property + * + * @ref: valid node reference to read property from + * @propname: name of the property to read from + * @outp: place to put value (if found) + * @return 0 if OK, -ve on error + */ +static inline int ofnode_read_s32(ofnode node, const char *propname, + s32 *out_value) +{ + return ofnode_read_u32(node, propname, (u32 *)out_value); +} + +/** + * ofnode_read_u32_default() - Read a 32-bit integer from a property + * + * @ref: valid node reference to read property from + * @propname: name of the property to read from + * @def: default value to return if the property has no value + * @return property value, or @def if not found + */ +u32 ofnode_read_u32_default(ofnode ref, const char *propname, u32 def); + +/** + * ofnode_read_s32_default() - Read a 32-bit integer from a property + * + * @ref: valid node reference to read property from + * @propname: name of the property to read from + * @def: default value to return if the property has no value + * @return property value, or @def if not found + */ +int ofnode_read_s32_default(ofnode node, const char *propname, s32 def); + +/** + * ofnode_read_u64() - Read a 64-bit integer from a property + * + * @node: valid node reference to read property from + * @propname: name of the property to read from + * @outp: place to put value (if found) + * @return 0 if OK, -ve on error + */ +int ofnode_read_u64(ofnode node, const char *propname, u64 *outp); + +/** + * ofnode_read_u64_default() - Read a 64-bit integer from a property + * + * @ref: valid node reference to read property from + * @propname: name of the property to read from + * @def: default value to return if the property has no value + * @return property value, or @def if not found + */ +u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def); + +/** + * ofnode_read_string() - Read a string from a property + * + * @ref: valid node reference to read property from + * @propname: name of the property to read + * @return string from property value, or NULL if there is no such property + */ +const char *ofnode_read_string(ofnode node, const char *propname); + +/** + * ofnode_read_u32_array() - Find and read an array of 32 bit integers + * + * @node: valid node reference to read property from + * @propname: name of the property to read + * @out_values: pointer to return value, modified only if return value is 0 + * @sz: number of array elements to read + * @return 0 if OK, -ve on error + * + * Search for a property in a device node and read 32-bit value(s) from + * it. Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * The out_values is modified only if a valid u32 value can be decoded. + */ +int ofnode_read_u32_array(ofnode node, const char *propname, + u32 *out_values, size_t sz); + +/** + * ofnode_read_bool() - read a boolean value from a property + * + * @node: valid node reference to read property from + * @propname: name of property to read + * @return true if property is present (meaning true), false if not present + */ +bool ofnode_read_bool(ofnode node, const char *propname); + +/** + * ofnode_find_subnode() - find a named subnode of a parent node + * + * @node: valid reference to parent node + * @subnode_name: name of subnode to find + * @return reference to subnode (which can be invalid if there is no such + * subnode) + */ +ofnode ofnode_find_subnode(ofnode node, const char *subnode_name); + +/** + * ofnode_first_subnode() - find the first subnode of a parent node + * + * @node: valid reference to a valid parent node + * @return reference to the first subnode (which can be invalid if the parent + * node has no subnodes) + */ +ofnode ofnode_first_subnode(ofnode node); + +/** + * ofnode_next_subnode() - find the next sibling of a subnode + * + * @node: valid reference to previous node (sibling) + * @return reference to the next subnode (which can be invalid if the node + * has no more siblings) + */ +ofnode ofnode_next_subnode(ofnode node); + +/** + * ofnode_get_parent() - get the ofnode's parent (enclosing ofnode) + * + * @node: valid node to look up + * @return ofnode reference of the parent node + */ +ofnode ofnode_get_parent(ofnode node); + +/** + * ofnode_get_name() - get the name of a node + * + * @node: valid node to look up + * @return name of node + */ +const char *ofnode_get_name(ofnode node); + +/** + * ofnode_get_by_phandle() - get ofnode from phandle + * + * @phandle: phandle to look up + * @return ofnode reference to the phandle + */ +ofnode ofnode_get_by_phandle(uint phandle); + +/** + * ofnode_read_size() - read the size of a property + * + * @node: node to check + * @propname: property to check + * @return size of property if present, or -EINVAL if not + */ +int ofnode_read_size(ofnode node, const char *propname); + +/** + * ofnode_get_addr_size_index() - get an address/size from a node + * based on index + * + * This reads the register address/size from a node based on index + * + * @node: node to read from + * @index: Index of address to read (0 for first) + * @size: Pointer to size of the address + * @return address, or FDT_ADDR_T_NONE if not present or invalid + */ +phys_addr_t ofnode_get_addr_size_index(ofnode node, int index, + fdt_size_t *size); + +/** + * ofnode_get_addr_index() - get an address from a node + * + * This reads the register address from a node + * + * @node: node to read from + * @index: Index of address to read (0 for first) + * @return address, or FDT_ADDR_T_NONE if not present or invalid + */ +phys_addr_t ofnode_get_addr_index(ofnode node, int index); + +/** + * ofnode_get_addr() - get an address from a node + * + * This reads the register address from a node + * + * @node: node to read from + * @return address, or FDT_ADDR_T_NONE if not present or invalid + */ +phys_addr_t ofnode_get_addr(ofnode node); + +/** + * ofnode_stringlist_search() - find a string in a string list and return index + * + * Note that it is possible for this function to succeed on property values + * that are not NUL-terminated. That's because the function will stop after + * finding the first occurrence of @string. This can for example happen with + * small-valued cell properties, such as #address-cells, when searching for + * the empty string. + * + * @node: node to check + * @propname: name of the property containing the string list + * @string: string to look up in the string list + * + * @return: + * the index of the string in the list of strings + * -ENODATA if the property is not found + * -EINVAL on some other error + */ +int ofnode_stringlist_search(ofnode node, const char *propname, + const char *string); + +/** + * ofnode_read_string_index() - obtain an indexed string from a string list + * + * Note that this will successfully extract strings from properties with + * non-NUL-terminated values. For example on small-valued cell properties + * this function will return the empty string. + * + * If non-NULL, the length of the string (on success) or a negative error-code + * (on failure) will be stored in the integer pointer to by lenp. + * + * @node: node to check + * @propname: name of the property containing the string list + * @index: index of the string to return + * @lenp: return location for the string length or an error code on failure + * + * @return: + * length of string, if found or -ve error value if not found + */ +int ofnode_read_string_index(ofnode node, const char *propname, int index, + const char **outp); + +/** + * ofnode_read_string_count() - find the number of strings in a string list + * + * @node: node to check + * @propname: name of the property containing the string list + * @return: + * number of strings in the list, or -ve error value if not found + */ +int ofnode_read_string_count(ofnode node, const char *property); + +/** + * ofnode_parse_phandle_with_args() - Find a node pointed by phandle in a list + * + * This function is useful to parse lists of phandles and their arguments. + * Returns 0 on success and fills out_args, on error returns appropriate + * errno value. + * + * Caller is responsible to call of_node_put() on the returned out_args->np + * pointer. + * + * Example: + * + * phandle1: node1 { + * #list-cells = <2>; + * } + * + * phandle2: node2 { + * #list-cells = <1>; + * } + * + * node3 { + * list = <&phandle1 1 2 &phandle2 3>; + * } + * + * To get a device_node of the `node2' node you may call this: + * ofnode_parse_phandle_with_args(node3, "list", "#list-cells", 0, 1, &args); + * + * @node: device tree node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * @cells_count: Cell count to use if @cells_name is NULL + * @index: index of a phandle to parse out + * @out_args: optional pointer to output arguments structure (will be filled) + * @return 0 on success (with @out_args filled out if not NULL), -ENOENT if + * @list_name does not exist, -EINVAL if a phandle was not found, + * @cells_name could not be found, the arguments were truncated or there + * were too many arguments. + */ +int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, + const char *cells_name, int cell_count, + int index, + struct ofnode_phandle_args *out_args); + +/** + * ofnode_count_phandle_with_args() - Count number of phandle in a list + * + * This function is useful to count phandles into a list. + * Returns number of phandle on success, on error returns appropriate + * errno value. + * + * @node: device tree node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * @return number of phandle on success, -ENOENT if @list_name does not + * exist, -EINVAL if a phandle was not found, @cells_name could not + * be found. + */ +int ofnode_count_phandle_with_args(ofnode node, const char *list_name, + const char *cells_name); + +/** + * ofnode_path() - find a node by full path + * + * @path: Full path to node, e.g. "/bus/spi@1" + * @return reference to the node found. Use ofnode_valid() to check if it exists + */ +ofnode ofnode_path(const char *path); + +/** + * ofnode_get_chosen_prop() - get the value of a chosen property + * + * This looks for a property within the /chosen node and returns its value + * + * @propname: Property name to look for + * @return property value if found, else NULL + */ +const char *ofnode_get_chosen_prop(const char *propname); + +/** + * ofnode_get_chosen_node() - get the chosen node + * + * @return the chosen node if present, else ofnode_null() + */ +ofnode ofnode_get_chosen_node(const char *name); + +struct display_timing; +/** + * ofnode_decode_display_timing() - decode display timings + * + * Decode display timings from the supplied 'display-timings' node. + * See doc/device-tree-bindings/video/display-timing.txt for binding + * information. + * + * @node 'display-timing' node containing the timing subnodes + * @index Index number to read (0=first timing subnode) + * @config Place to put timings + * @return 0 if OK, -FDT_ERR_NOTFOUND if not found + */ +int ofnode_decode_display_timing(ofnode node, int index, + struct display_timing *config); + +/** + * ofnode_get_property()- - get a pointer to the value of a node property + * + * @node: node to read + * @propname: property to read + * @lenp: place to put length on success + * @return pointer to property, or NULL if not found + */ +const void *ofnode_get_property(ofnode node, const char *propname, int *lenp); + +/** + * ofnode_is_available() - check if a node is marked available + * + * @node: node to check + * @return true if node's 'status' property is "okay" (or is missing) + */ +bool ofnode_is_available(ofnode node); + +/** + * ofnode_get_addr_size() - get address and size from a property + * + * This does no address translation. It simply reads an property that contains + * an address and a size value, one after the other. + * + * @node: node to read from + * @propname: property to read + * @sizep: place to put size value (on success) + * @return address value, or FDT_ADDR_T_NONE on error + */ +phys_addr_t ofnode_get_addr_size(ofnode node, const char *propname, + phys_size_t *sizep); + +/** + * ofnode_read_u8_array_ptr() - find an 8-bit array + * + * Look up a property in a node and return a pointer to its contents as a + * byte array of given length. The property must have at least enough data + * for the array (count bytes). It may have more, but this will be ignored. + * The data is not copied. + * + * @node node to examine + * @propname name of property to find + * @sz number of array elements + * @return pointer to byte array if found, or NULL if the property is not + * found or there is not enough data + */ +const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname, + size_t sz); + +/** + * ofnode_read_pci_addr() - look up a PCI address + * + * Look at an address property in a node and return the PCI address which + * corresponds to the given type in the form of fdt_pci_addr. + * The property must hold one fdt_pci_addr with a lengh. + * + * @node node to examine + * @type pci address type (FDT_PCI_SPACE_xxx) + * @propname name of property to find + * @addr returns pci address in the form of fdt_pci_addr + * @return 0 if ok, -ENOENT if the property did not exist, -EINVAL if the + * format of the property was invalid, -ENXIO if the requested + * address type was not found + */ +int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, + const char *propname, struct fdt_pci_addr *addr); + +/** + * ofnode_read_pci_vendev() - look up PCI vendor and device id + * + * Look at the compatible property of a device node that represents a PCI + * device and extract pci vendor id and device id from it. + * + * @param node node to examine + * @param vendor vendor id of the pci device + * @param device device id of the pci device + * @return 0 if ok, negative on error + */ +int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device); + +/** + * ofnode_read_addr_cells() - Get the number of address cells for a node + * + * This walks back up the tree to find the closest #address-cells property + * which controls the given node. + * + * @node: Node to check + * @return number of address cells this node uses + */ +int ofnode_read_addr_cells(ofnode node); + +/** + * ofnode_read_size_cells() - Get the number of size cells for a node + * + * This walks back up the tree to find the closest #size-cells property + * which controls the given node. + * + * @node: Node to check + * @return number of size cells this node uses + */ +int ofnode_read_size_cells(ofnode node); + +/** + * ofnode_read_simple_addr_cells() - Get the address cells property in a node + * + * This function matches fdt_address_cells(). + * + * @np: Node pointer to check + * @return value of #address-cells property in this node, or 2 if none + */ +int ofnode_read_simple_addr_cells(ofnode node); + +/** + * ofnode_read_simple_size_cells() - Get the size cells property in a node + * + * This function matches fdt_size_cells(). + * + * @np: Node pointer to check + * @return value of #size-cells property in this node, or 2 if none + */ +int ofnode_read_simple_size_cells(ofnode node); + +/** + * ofnode_pre_reloc() - check if a node should be bound before relocation + * + * Device tree nodes can be marked as needing-to-be-bound in the loader stages + * via special device tree properties. + * + * Before relocation this function can be used to check if nodes are required + * in either SPL or TPL stages. + * + * After relocation and jumping into the real U-Boot binary it is possible to + * determine if a node was bound in one of SPL/TPL stages. + * + * There are 4 settings currently in use + * - u-boot,dm-pre-proper: U-Boot proper pre-relocation only + * - u-boot,dm-pre-reloc: legacy and indicates any of TPL or SPL + * Existing platforms only use it to indicate nodes needed in + * SPL. Should probably be replaced by u-boot,dm-spl for + * new platforms. + * - u-boot,dm-spl: SPL and U-Boot pre-relocation + * - u-boot,dm-tpl: TPL and U-Boot pre-relocation + * + * @node: node to check + * @return true if node is needed in SPL/TL, false otherwise + */ +bool ofnode_pre_reloc(ofnode node); + +/** + * ofnode_read_resource() - Read a resource from a node + * + * Read resource information from a node at the given index + * + * @node: Node to read from + * @index: Index of resource to read (0 = first) + * @res: Returns resource that was read, on success + * @return 0 if OK, -ve on error + */ +int ofnode_read_resource(ofnode node, uint index, struct resource *res); + +/** + * ofnode_read_resource_byname() - Read a resource from a node by name + * + * Read resource information from a node matching the given name. This uses a + * 'reg-names' string list property with the names matching the associated + * 'reg' property list. + * + * @node: Node to read from + * @name: Name of resource to read + * @res: Returns resource that was read, on success + * @return 0 if OK, -ve on error + */ +int ofnode_read_resource_byname(ofnode node, const char *name, + struct resource *res); + +/** + * ofnode_by_compatible() - Find the next compatible node + * + * Find the next node after @from that is compatible with @compat + * + * @from: ofnode to start from (use ofnode_null() to start at the beginning) + * @compat: Compatible string to match + * @return ofnode found, or ofnode_null() if none + */ +ofnode ofnode_by_compatible(ofnode from, const char *compat); + +/** + * ofnode_by_prop_value() - Find the next node with given property value + * + * Find the next node after @from that has a @propname with a value + * @propval and a length @proplen. + * + * @from: ofnode to start from (use ofnode_null() to start at the + * beginning) @propname: property name to check @propval: property value to + * search for @proplen: length of the value in propval @return ofnode + * found, or ofnode_null() if none + */ +ofnode ofnode_by_prop_value(ofnode from, const char *propname, + const void *propval, int proplen); + +/** + * ofnode_for_each_subnode() - iterate over all subnodes of a parent + * + * @node: child node (ofnode, lvalue) + * @parent: parent node (ofnode) + * + * This is a wrapper around a for loop and is used like so: + * + * ofnode node; + * + * ofnode_for_each_subnode(node, parent) { + * Use node + * ... + * } + * + * Note that this is implemented as a macro and @node is used as + * iterator in the loop. The parent variable can be a constant or even a + * literal. + */ +#define ofnode_for_each_subnode(node, parent) \ + for (node = ofnode_first_subnode(parent); \ + ofnode_valid(node); \ + node = ofnode_next_subnode(node)) + +/** + * ofnode_translate_address() - Translate a device-tree address + * + * Translate an address from the device-tree into a CPU physical address. This + * function walks up the tree and applies the various bus mappings along the + * way. + * + * @ofnode: Device tree node giving the context in which to translate the + * address + * @in_addr: pointer to the address to translate + * @return the translated address; OF_BAD_ADDR on error + */ +u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr); + +/** + * ofnode_translate_dma_address() - Translate a device-tree DMA address + * + * Translate a DMA address from the device-tree into a CPU physical address. + * This function walks up the tree and applies the various bus mappings along + * the way. + * + * @ofnode: Device tree node giving the context in which to translate the + * DMA address + * @in_addr: pointer to the DMA address to translate + * @return the translated DMA address; OF_BAD_ADDR on error + */ +u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr); + +/** + * ofnode_device_is_compatible() - check if the node is compatible with compat + * + * This allows to check whether the node is comaptible with the compat. + * + * @node: Device tree node for which compatible needs to be verified. + * @compat: Compatible string which needs to verified in the given node. + * @return true if OK, false if the compatible is not found + */ +int ofnode_device_is_compatible(ofnode node, const char *compat); + +/** + * ofnode_write_prop() - Set a property of a ofnode + * + * Note that the value passed to the function is *not* allocated by the + * function itself, but must be allocated by the caller if necessary. + * + * @node: The node for whose property should be set + * @propname: The name of the property to set + * @len: The length of the new value of the property + * @value: The new value of the property (must be valid prior to calling + * the function) + * @return 0 if successful, -ve on error + */ +int ofnode_write_prop(ofnode node, const char *propname, int len, + const void *value); + +/** + * ofnode_write_string() - Set a string property of a ofnode + * + * Note that the value passed to the function is *not* allocated by the + * function itself, but must be allocated by the caller if necessary. + * + * @node: The node for whose string property should be set + * @propname: The name of the string property to set + * @value: The new value of the string property (must be valid prior to + * calling the function) + * @return 0 if successful, -ve on error + */ +int ofnode_write_string(ofnode node, const char *propname, const char *value); + +/** + * ofnode_set_enabled() - Enable or disable a device tree node given by its + * ofnode + * + * This function effectively sets the node's "status" property to either "okay" + * or "disable", hence making it available for driver model initialization or + * not. + * + * @node: The node to enable + * @value: Flag that tells the function to either disable or enable the + * node + * @return 0 if successful, -ve on error + */ +int ofnode_set_enabled(ofnode node, bool value); + +#endif diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h new file mode 100644 index 0000000..3eca34f --- /dev/null +++ b/include/dm/pinctrl.h @@ -0,0 +1,457 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef __PINCTRL_H +#define __PINCTRL_H + +#define PINNAME_SIZE 10 +#define PINMUX_SIZE 40 + +/** + * struct pinconf_param - pin config parameters + * + * @property: property name in DT nodes + * @param: ID for this config parameter + * @default_value: default value for this config parameter used in case + * no value is specified in DT nodes + */ +struct pinconf_param { + const char * const property; + unsigned int param; + u32 default_value; +}; + +/** + * struct pinctrl_ops - pin control operations, to be implemented by + * pin controller drivers. + * + * The @set_state is the only mandatory operation. You can implement your + * pinctrl driver with its own @set_state. In this case, the other callbacks + * are not required. Otherwise, generic pinctrl framework is also available; + * use pinctrl_generic_set_state for @set_state, and implement other operations + * depending on your necessity. + * + * @get_pins_count: return number of selectable named pins available + * in this driver. (necessary to parse "pins" property in DTS) + * @get_pin_name: return the pin name of the pin selector, + * called by the core to figure out which pin it shall do + * operations to. (necessary to parse "pins" property in DTS) + * @get_groups_count: return number of selectable named groups available + * in this driver. (necessary to parse "groups" property in DTS) + * @get_group_name: return the group name of the group selector, + * called by the core to figure out which pin group it shall do + * operations to. (necessary to parse "groups" property in DTS) + * @get_functions_count: return number of selectable named functions available + * in this driver. (necessary for pin-muxing) + * @get_function_name: return the function name of the muxing selector, + * called by the core to figure out which mux setting it shall map a + * certain device to. (necessary for pin-muxing) + * @pinmux_set: enable a certain muxing function with a certain pin. + * The @func_selector selects a certain function whereas @pin_selector + * selects a certain pin to be used. On simple controllers one of them + * may be ignored. (necessary for pin-muxing against a single pin) + * @pinmux_group_set: enable a certain muxing function with a certain pin + * group. The @func_selector selects a certain function whereas + * @group_selector selects a certain set of pins to be used. On simple + * controllers one of them may be ignored. + * (necessary for pin-muxing against a pin group) + * @pinconf_num_params: number of driver-specific parameters to be parsed + * from device trees (necessary for pin-configuration) + * @pinconf_params: list of driver_specific parameters to be parsed from + * device trees (necessary for pin-configuration) + * @pinconf_set: configure an individual pin with a given parameter. + * (necessary for pin-configuration against a single pin) + * @pinconf_group_set: configure all pins in a group with a given parameter. + * (necessary for pin-configuration against a pin group) + * @set_state: do pinctrl operations specified by @config, a pseudo device + * pointing a config node. (necessary for pinctrl_full) + * @set_state_simple: do needed pinctrl operations for a peripherl @periph. + * (necessary for pinctrl_simple) + * @get_pin_muxing: display the muxing of a given pin. + * @gpio_request_enable: requests and enables GPIO on a certain pin. + * Implement this only if you can mux every pin individually as GPIO. The + * affected GPIO range is passed along with an offset(pin number) into that + * specific GPIO range - function selectors and pin groups are orthogonal + * to this, the core will however make sure the pins do not collide. + * @gpio_disable_free: free up GPIO muxing on a certain pin, the reverse of + * @gpio_request_enable + */ +struct pinctrl_ops { + int (*get_pins_count)(struct udevice *dev); + const char *(*get_pin_name)(struct udevice *dev, unsigned selector); + int (*get_groups_count)(struct udevice *dev); + const char *(*get_group_name)(struct udevice *dev, unsigned selector); + int (*get_functions_count)(struct udevice *dev); + const char *(*get_function_name)(struct udevice *dev, + unsigned selector); + int (*pinmux_set)(struct udevice *dev, unsigned pin_selector, + unsigned func_selector); + int (*pinmux_group_set)(struct udevice *dev, unsigned group_selector, + unsigned func_selector); + unsigned int pinconf_num_params; + const struct pinconf_param *pinconf_params; + int (*pinconf_set)(struct udevice *dev, unsigned pin_selector, + unsigned param, unsigned argument); + int (*pinconf_group_set)(struct udevice *dev, unsigned group_selector, + unsigned param, unsigned argument); + int (*set_state)(struct udevice *dev, struct udevice *config); + + /* for pinctrl-simple */ + int (*set_state_simple)(struct udevice *dev, struct udevice *periph); + /** + * request() - Request a particular pinctrl function + * + * This activates the selected function. + * + * @dev: Device to adjust (UCLASS_PINCTRL) + * @func: Function number (driver-specific) + * @return 0 if OK, -ve on error + */ + int (*request)(struct udevice *dev, int func, int flags); + + /** + * get_periph_id() - get the peripheral ID for a device + * + * This generally looks at the peripheral's device tree node to work + * out the peripheral ID. The return value is normally interpreted as + * enum periph_id. so long as this is defined by the platform (which it + * should be). + * + * @dev: Pinctrl device to use for decoding + * @periph: Device to check + * @return peripheral ID of @periph, or -ENOENT on error + */ + int (*get_periph_id)(struct udevice *dev, struct udevice *periph); + + /** + * get_gpio_mux() - get the mux value for a particular GPIO + * + * This allows the raw mux value for a GPIO to be obtained. It is + * useful for displaying the function being used by that GPIO, such + * as with the 'gpio' command. This function is internal to the GPIO + * subsystem and should not be used by generic code. Typically it is + * used by a GPIO driver with knowledge of the SoC pinctrl setup. + * + * @dev: Pinctrl device to use + * @banknum: GPIO bank number + * @index: GPIO index within the bank + * @return mux value (SoC-specific, e.g. 0 for input, 1 for output) + */ + int (*get_gpio_mux)(struct udevice *dev, int banknum, int index); + + /** + * get_pin_muxing() - show pin muxing + * + * This allows to display the muxing of a given pin. It's useful for + * debug purpose to know if a pin is configured as GPIO or as an + * alternate function and which one. + * Typically it is used by a PINCTRL driver with knowledge of the SoC + * pinctrl setup. + * + * @dev: Pinctrl device to use + * @selector: Pin selector + * @buf Pin's muxing description + * @size Pin's muxing description length + * return 0 if OK, -ve on error + */ + int (*get_pin_muxing)(struct udevice *dev, unsigned int selector, + char *buf, int size); + + /** + * gpio_request_enable: requests and enables GPIO on a certain pin. + * + * @dev: Pinctrl device to use + * @selector: Pin selector + * return 0 if OK, -ve on error + */ + int (*gpio_request_enable)(struct udevice *dev, unsigned int selector); + + /** + * gpio_disable_free: free up GPIO muxing on a certain pin. + * + * @dev: Pinctrl device to use + * @selector: Pin selector + * return 0 if OK, -ve on error + */ + int (*gpio_disable_free)(struct udevice *dev, unsigned int selector); +}; + +#define pinctrl_get_ops(dev) ((struct pinctrl_ops *)(dev)->driver->ops) + +/** + * Generic pin configuration paramters + * + * enum pin_config_param - possible pin configuration parameters + * @PIN_CONFIG_BIAS_BUS_HOLD: the pin will be set to weakly latch so that it + * weakly drives the last value on a tristate bus, also known as a "bus + * holder", "bus keeper" or "repeater". This allows another device on the + * bus to change the value by driving the bus high or low and switching to + * tristate. The argument is ignored. + * @PIN_CONFIG_BIAS_DISABLE: disable any pin bias on the pin, a + * transition from say pull-up to pull-down implies that you disable + * pull-up in the process, this setting disables all biasing. + * @PIN_CONFIG_BIAS_HIGH_IMPEDANCE: the pin will be set to a high impedance + * mode, also know as "third-state" (tristate) or "high-Z" or "floating". + * On output pins this effectively disconnects the pin, which is useful + * if for example some other pin is going to drive the signal connected + * to it for a while. Pins used for input are usually always high + * impedance. + * @PIN_CONFIG_BIAS_PULL_DOWN: the pin will be pulled down (usually with high + * impedance to GROUND). If the argument is != 0 pull-down is enabled, + * if it is 0, pull-down is total, i.e. the pin is connected to GROUND. + * @PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: the pin will be pulled up or down based + * on embedded knowledge of the controller hardware, like current mux + * function. The pull direction and possibly strength too will normally + * be decided completely inside the hardware block and not be readable + * from the kernel side. + * If the argument is != 0 pull up/down is enabled, if it is 0, the + * configuration is ignored. The proper way to disable it is to use + * @PIN_CONFIG_BIAS_DISABLE. + * @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high + * impedance to VDD). If the argument is != 0 pull-up is enabled, + * if it is 0, pull-up is total, i.e. the pin is connected to VDD. + * @PIN_CONFIG_DRIVE_OPEN_DRAIN: the pin will be driven with open drain (open + * collector) which means it is usually wired with other output ports + * which are then pulled up with an external resistor. Setting this + * config will enable open drain mode, the argument is ignored. + * @PIN_CONFIG_DRIVE_OPEN_SOURCE: the pin will be driven with open source + * (open emitter). Setting this config will enable open source mode, the + * argument is ignored. + * @PIN_CONFIG_DRIVE_PUSH_PULL: the pin will be driven actively high and + * low, this is the most typical case and is typically achieved with two + * active transistors on the output. Setting this config will enable + * push-pull mode, the argument is ignored. + * @PIN_CONFIG_DRIVE_STRENGTH: the pin will sink or source at most the current + * passed as argument. The argument is in mA. + * @PIN_CONFIG_DRIVE_STRENGTH_UA: the pin will sink or source at most the current + * passed as argument. The argument is in uA. + * @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode, + * which means it will wait for signals to settle when reading inputs. The + * argument gives the debounce time in usecs. Setting the + * argument to zero turns debouncing off. + * @PIN_CONFIG_INPUT_ENABLE: enable the pin's input. Note that this does not + * affect the pin's ability to drive output. 1 enables input, 0 disables + * input. + * @PIN_CONFIG_INPUT_SCHMITT: this will configure an input pin to run in + * schmitt-trigger mode. If the schmitt-trigger has adjustable hysteresis, + * the threshold value is given on a custom format as argument when + * setting pins to this mode. + * @PIN_CONFIG_INPUT_SCHMITT_ENABLE: control schmitt-trigger mode on the pin. + * If the argument != 0, schmitt-trigger mode is enabled. If it's 0, + * schmitt-trigger mode is disabled. + * @PIN_CONFIG_LOW_POWER_MODE: this will configure the pin for low power + * operation, if several modes of operation are supported these can be + * passed in the argument on a custom form, else just use argument 1 + * to indicate low power mode, argument 0 turns low power mode off. + * @PIN_CONFIG_OUTPUT_ENABLE: this will enable the pin's output mode + * without driving a value there. For most platforms this reduces to + * enable the output buffers and then let the pin controller current + * configuration (eg. the currently selected mux function) drive values on + * the line. Use argument 1 to enable output mode, argument 0 to disable + * it. + * @PIN_CONFIG_OUTPUT: this will configure the pin as an output and drive a + * value on the line. Use argument 1 to indicate high level, argument 0 to + * indicate low level. (Please see Documentation/driver-api/pinctl.rst, + * section "GPIO mode pitfalls" for a discussion around this parameter.) + * @PIN_CONFIG_POWER_SOURCE: if the pin can select between different power + * supplies, the argument to this parameter (on a custom format) tells + * the driver which alternative power source to use. + * @PIN_CONFIG_SLEEP_HARDWARE_STATE: indicate this is sleep related state. + * @PIN_CONFIG_SLEW_RATE: if the pin can select slew rate, the argument to + * this parameter (on a custom format) tells the driver which alternative + * slew rate to use. + * @PIN_CONFIG_SKEW_DELAY: if the pin has programmable skew rate (on inputs) + * or latch delay (on outputs) this parameter (in a custom format) + * specifies the clock skew or latch delay. It typically controls how + * many double inverters are put in front of the line. + * @PIN_CONFIG_END: this is the last enumerator for pin configurations, if + * you need to pass in custom configurations to the pin controller, use + * PIN_CONFIG_END+1 as the base offset. + * @PIN_CONFIG_MAX: this is the maximum configuration value that can be + * presented using the packed format. + */ +enum pin_config_param { + PIN_CONFIG_BIAS_BUS_HOLD, + PIN_CONFIG_BIAS_DISABLE, + PIN_CONFIG_BIAS_HIGH_IMPEDANCE, + PIN_CONFIG_BIAS_PULL_DOWN, + PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, + PIN_CONFIG_BIAS_PULL_UP, + PIN_CONFIG_DRIVE_OPEN_DRAIN, + PIN_CONFIG_DRIVE_OPEN_SOURCE, + PIN_CONFIG_DRIVE_PUSH_PULL, + PIN_CONFIG_DRIVE_STRENGTH, + PIN_CONFIG_DRIVE_STRENGTH_UA, + PIN_CONFIG_INPUT_DEBOUNCE, + PIN_CONFIG_INPUT_ENABLE, + PIN_CONFIG_INPUT_SCHMITT, + PIN_CONFIG_INPUT_SCHMITT_ENABLE, + PIN_CONFIG_LOW_POWER_MODE, + PIN_CONFIG_OUTPUT_ENABLE, + PIN_CONFIG_OUTPUT, + PIN_CONFIG_POWER_SOURCE, + PIN_CONFIG_SLEEP_HARDWARE_STATE, + PIN_CONFIG_SLEW_RATE, + PIN_CONFIG_SKEW_DELAY, + PIN_CONFIG_END = 0x7F, + PIN_CONFIG_MAX = 0xFF, +}; + +#if CONFIG_IS_ENABLED(PINCTRL_GENERIC) +/** + * pinctrl_generic_set_state() - generic set_state operation + * Parse the DT node of @config and its children and handle generic properties + * such as "pins", "groups", "functions", and pin configuration parameters. + * + * @pctldev: pinctrl device + * @config: config device (pseudo device), pointing a config node in DTS + * @return: 0 on success, or negative error code on failure + */ +int pinctrl_generic_set_state(struct udevice *pctldev, struct udevice *config); +#else +static inline int pinctrl_generic_set_state(struct udevice *pctldev, + struct udevice *config) +{ + return -EINVAL; +} +#endif + +#if CONFIG_IS_ENABLED(PINCTRL) +/** + * pinctrl_select_state() - set a device to a given state + * + * @dev: peripheral device + * @statename: state name, like "default" + * @return: 0 on success, or negative error code on failure + */ +int pinctrl_select_state(struct udevice *dev, const char *statename); +#else +static inline int pinctrl_select_state(struct udevice *dev, + const char *statename) +{ + return -EINVAL; +} +#endif + +/** + * pinctrl_request() - Request a particular pinctrl function + * + * @dev: Device to check (UCLASS_PINCTRL) + * @func: Function number (driver-specific) + * @flags: Flags (driver-specific) + * @return 0 if OK, -ve on error + */ +int pinctrl_request(struct udevice *dev, int func, int flags); + +/** + * pinctrl_request_noflags() - Request a particular pinctrl function + * + * This is similar to pinctrl_request() but uses 0 for @flags. + * + * @dev: Device to check (UCLASS_PINCTRL) + * @func: Function number (driver-specific) + * @return 0 if OK, -ve on error + */ +int pinctrl_request_noflags(struct udevice *dev, int func); + +/** + * pinctrl_get_periph_id() - get the peripheral ID for a device + * + * This generally looks at the peripheral's device tree node to work out the + * peripheral ID. The return value is normally interpreted as enum periph_id. + * so long as this is defined by the platform (which it should be). + * + * @dev: Pinctrl device to use for decoding + * @periph: Device to check + * @return peripheral ID of @periph, or -ENOENT on error + */ +int pinctrl_get_periph_id(struct udevice *dev, struct udevice *periph); + +/** + * pinctrl_decode_pin_config() - decode pin configuration flags + * + * This decodes some of the PIN_CONFIG values into flags, with each value + * being (1 << pin_cfg). This does not support things with values like the + * slew rate. + * + * @blob: Device tree blob + * @node: Node containing the PIN_CONFIG values + * @return decoded flag value, or -ve on error + */ +int pinctrl_decode_pin_config(const void *blob, int node); + +/** + * pinctrl_get_gpio_mux() - get the mux value for a particular GPIO + * + * This allows the raw mux value for a GPIO to be obtained. It is + * useful for displaying the function being used by that GPIO, such + * as with the 'gpio' command. This function is internal to the GPIO + * subsystem and should not be used by generic code. Typically it is + * used by a GPIO driver with knowledge of the SoC pinctrl setup. + * + * @dev: Pinctrl device to use + * @banknum: GPIO bank number + * @index: GPIO index within the bank + * @return mux value (SoC-specific, e.g. 0 for input, 1 for output) +*/ +int pinctrl_get_gpio_mux(struct udevice *dev, int banknum, int index); + +/** + * pinctrl_get_pin_muxing() - Returns the muxing description + * + * This allows to display the muxing description of the given pin for + * debug purpose + * + * @dev: Pinctrl device to use + * @selector Pin index within pin-controller + * @buf Pin's muxing description + * @size Pin's muxing description length + * @return 0 if OK, -ve on error + */ +int pinctrl_get_pin_muxing(struct udevice *dev, int selector, char *buf, + int size); + +/** + * pinctrl_get_pins_count() - display pin-controller pins number + * + * This allows to know the number of pins owned by a given pin-controller + * + * @dev: Pinctrl device to use + * @return pins number if OK, -ve on error + */ +int pinctrl_get_pins_count(struct udevice *dev); + +/** + * pinctrl_get_pin_name() - Returns the pin's name + * + * This allows to display the pin's name for debug purpose + * + * @dev: Pinctrl device to use + * @selector Pin index within pin-controller + * @buf Pin's name + * @return 0 if OK, -ve on error + */ +int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf, + int size); + +/** + * pinctrl_gpio_request() - request a single pin to be used as GPIO + * + * @dev: GPIO peripheral device + * @offset: the GPIO pin offset from the GPIO controller + * @return: 0 on success, or negative error code on failure + */ +int pinctrl_gpio_request(struct udevice *dev, unsigned offset); + +/** + * pinctrl_gpio_free() - free a single pin used as GPIO + * + * @dev: GPIO peripheral device + * @offset: the GPIO pin offset from the GPIO controller + * @return: 0 on success, or negative error code on failure + */ +int pinctrl_gpio_free(struct udevice *dev, unsigned offset); + +#endif /* __PINCTRL_H */ diff --git a/include/dm/platdata.h b/include/dm/platdata.h new file mode 100644 index 0000000..c972fa6 --- /dev/null +++ b/include/dm/platdata.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + * Marek Vasut <marex@denx.de> + */ + +#ifndef _DM_PLATDATA_H +#define _DM_PLATDATA_H + +#include <linker_lists.h> + +/** + * struct driver_info - Information required to instantiate a device + * + * NOTE: Avoid using this except in extreme circumstances, where device tree + * is not feasible (e.g. serial driver in SPL where <8KB of SRAM is + * available). U-Boot's driver model uses device tree for configuration. + * + * @name: Driver name + * @platdata: Driver-specific platform data + * @platdata_size: Size of platform data structure + */ +struct driver_info { + const char *name; + const void *platdata; +#if CONFIG_IS_ENABLED(OF_PLATDATA) + uint platdata_size; +#endif +}; + +/** + * NOTE: Avoid using these except in extreme circumstances, where device tree + * is not feasible (e.g. serial driver in SPL where <8KB of SRAM is + * available). U-Boot's driver model uses device tree for configuration. + */ +#define U_BOOT_DEVICE(__name) \ + ll_entry_declare(struct driver_info, __name, driver_info) + +/* Declare a list of devices. The argument is a driver_info[] array */ +#define U_BOOT_DEVICES(__name) \ + ll_entry_declare_list(struct driver_info, __name, driver_info) + +#endif diff --git a/include/dm/platform_data/lpc32xx_hsuart.h b/include/dm/platform_data/lpc32xx_hsuart.h new file mode 100644 index 0000000..9bfd628 --- /dev/null +++ b/include/dm/platform_data/lpc32xx_hsuart.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2015 Vladimir Zapolskiy <vz@mleia.com> + */ + +#ifndef _LPC32XX_HSUART_PLAT_H +#define _LPC32XX_HSUART_PLAT_H + +/** + * struct lpc32xx_hsuart_platdata - NXP LPC32xx HSUART platform data + * + * @base: Base register address + */ +struct lpc32xx_hsuart_platdata { + unsigned long base; +}; + +#endif diff --git a/include/dm/platform_data/net_ethoc.h b/include/dm/platform_data/net_ethoc.h new file mode 100644 index 0000000..855e999 --- /dev/null +++ b/include/dm/platform_data/net_ethoc.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2016 Cadence Design Systems Inc. + */ + +#ifndef _ETHOC_H +#define _ETHOC_H + +#include <net.h> + +#ifdef CONFIG_DM_ETH + +struct ethoc_eth_pdata { + struct eth_pdata eth_pdata; + phys_addr_t packet_base; +}; + +#endif + +#endif /* _ETHOC_H */ diff --git a/include/dm/platform_data/pfe_dm_eth.h b/include/dm/platform_data/pfe_dm_eth.h new file mode 100644 index 0000000..100a981 --- /dev/null +++ b/include/dm/platform_data/pfe_dm_eth.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + */ + +#ifndef __PFE_DM_ETH_H__ +#define __PFE_DM_ETH_H__ +#include <net.h> + +struct pfe_ddr_address { + void *ddr_pfe_baseaddr; + unsigned long ddr_pfe_phys_baseaddr; +}; + +struct pfe_eth_pdata { + struct eth_pdata pfe_eth_pdata_mac; + struct pfe_ddr_address pfe_ddr_addr; +}; +#endif /* __PFE_DM_ETH_H__ */ diff --git a/include/dm/platform_data/serial_bcm283x_mu.h b/include/dm/platform_data/serial_bcm283x_mu.h new file mode 100644 index 0000000..37f5174 --- /dev/null +++ b/include/dm/platform_data/serial_bcm283x_mu.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2016 Stephen Warren <swarren@wwwdotorg.org> + * + * Derived from pl01x code: + * Copyright (c) 2014 Google, Inc + */ + +#ifndef __serial_bcm283x_mu_h +#define __serial_bcm283x_mu_h + +/* + *Information about a serial port + * + * @base: Register base address + */ +struct bcm283x_mu_serial_platdata { + unsigned long base; + unsigned int clock; + bool skip_init; +}; + +#endif diff --git a/include/dm/platform_data/serial_coldfire.h b/include/dm/platform_data/serial_coldfire.h new file mode 100644 index 0000000..ba916fe --- /dev/null +++ b/include/dm/platform_data/serial_coldfire.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2015 Angelo Dureghello <angelo@sysam.it> + */ + +#ifndef __serial_coldfire_h +#define __serial_coldfire_h + +/* + * struct coldfire_serial_platdata - information about a coldfire port + * + * @base: Uart port base register address + * @port: Uart port index, for cpu with pinmux for uart / gpio + * baudrtatre: Uart port baudrate + */ +struct coldfire_serial_platdata { + unsigned long base; + int port; + int baudrate; +}; + +#endif /* __serial_coldfire_h */ diff --git a/include/dm/platform_data/serial_mxc.h b/include/dm/platform_data/serial_mxc.h new file mode 100644 index 0000000..86cd3bc --- /dev/null +++ b/include/dm/platform_data/serial_mxc.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2014 Google, Inc + */ + +#ifndef __serial_mxc_h +#define __serial_mxc_h + +/* Information about a serial port */ +struct mxc_serial_platdata { + struct mxc_uart *reg; /* address of registers in physical memory */ + bool use_dte; +}; + +#endif diff --git a/include/dm/platform_data/serial_pl01x.h b/include/dm/platform_data/serial_pl01x.h new file mode 100644 index 0000000..77d96c4 --- /dev/null +++ b/include/dm/platform_data/serial_pl01x.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2014 Google, Inc + */ + +#ifndef __serial_pl01x_h +#define __serial_pl01x_h + +enum pl01x_type { + TYPE_PL010, + TYPE_PL011, +}; + +/* + *Information about a serial port + * + * @base: Register base address + * @type: Port type + * @clock: Input clock rate, used for calculating the baud rate divisor + * @skip_init: Don't attempt to change port configuration (also means @clock + * is ignored) + */ +struct pl01x_serial_platdata { + unsigned long base; + enum pl01x_type type; + unsigned int clock; + bool skip_init; +}; + +#endif diff --git a/include/dm/platform_data/serial_pxa.h b/include/dm/platform_data/serial_pxa.h new file mode 100644 index 0000000..408c008 --- /dev/null +++ b/include/dm/platform_data/serial_pxa.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2016 Marcel Ziswiler <marcel.ziswiler@toradex.com> + */ + +#ifndef __SERIAL_PXA_H +#define __SERIAL_PXA_H + +/* + * The numbering scheme differs here for PXA25x, PXA27x and PXA3xx so we can + * easily handle enabling of clock. + */ +#ifdef CONFIG_CPU_MONAHANS +#define UART_CLK_BASE CKENA_21_BTUART +#define UART_CLK_REG CKENA +#define BTUART_INDEX 0 +#define FFUART_INDEX 1 +#define STUART_INDEX 2 +#elif CONFIG_CPU_PXA25X +#define UART_CLK_BASE (1 << 4) /* HWUART */ +#define UART_CLK_REG CKEN +#define HWUART_INDEX 0 +#define STUART_INDEX 1 +#define FFUART_INDEX 2 +#define BTUART_INDEX 3 +#else /* PXA27x */ +#define UART_CLK_BASE CKEN5_STUART +#define UART_CLK_REG CKEN +#define STUART_INDEX 0 +#define FFUART_INDEX 1 +#define BTUART_INDEX 2 +#endif + +/* + * Only PXA250 has HWUART, to avoid poluting the code with more macros, + * artificially introduce this. + */ +#ifndef CONFIG_CPU_PXA25X +#define HWUART_INDEX 0xff +#endif + +/* + * struct pxa_serial_platdata - information about a PXA port + * + * @base: Uart port base register address + * @port: Uart port index, for cpu with pinmux for uart / gpio + * baudrtatre: Uart port baudrate + */ +struct pxa_serial_platdata { + struct pxa_uart_regs *base; + int port; + int baudrate; +}; + +#endif /* __SERIAL_PXA_H */ diff --git a/include/dm/platform_data/serial_sh.h b/include/dm/platform_data/serial_sh.h new file mode 100644 index 0000000..711435d --- /dev/null +++ b/include/dm/platform_data/serial_sh.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2014 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> + * Copyright (c) 2014 Renesas Electronics Corporation + */ + +#ifndef __serial_sh_h +#define __serial_sh_h + +enum sh_clk_mode { + INT_CLK, + EXT_CLK, +}; + +enum sh_serial_type { + PORT_SCI, + PORT_SCIF, + PORT_SCIFA, + PORT_SCIFB, +}; + +/* + * Information about SCIF port + * + * @base: Register base address + * @clk: Input clock rate, used for calculating the baud rate divisor + * @clk_mode: Clock mode, set internal (INT) or external (EXT) + * @type: Type of SCIF + */ +struct sh_serial_platdata { + unsigned long base; + unsigned int clk; + enum sh_clk_mode clk_mode; + enum sh_serial_type type; +}; +#endif /* __serial_sh_h */ diff --git a/include/dm/platform_data/spi_coldfire.h b/include/dm/platform_data/spi_coldfire.h new file mode 100644 index 0000000..8ad8eae --- /dev/null +++ b/include/dm/platform_data/spi_coldfire.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2018 Angelo Dureghello <angelo@sysam.it> + */ + +#ifndef __spi_coldfire_h +#define __spi_coldfire_h + +#define MAX_CTAR_REGS 8 +#define MAX_CTAR_FIELDS 8 + +/* + * struct coldfire_spi_platdata - information about a coldfire spi module + * + * @regs_addr: base address for module registers + * @speed_hz: default SCK frequency + * @mode: default SPI mode + * @num_cs: number of DSPI chipselect signals + */ +struct coldfire_spi_platdata { + fdt_addr_t regs_addr; + uint speed_hz; + uint mode; + uint num_cs; + uint ctar[MAX_CTAR_REGS][MAX_CTAR_FIELDS]; +}; + +#endif /* __spi_coldfire_h */ + diff --git a/include/dm/platform_data/spi_davinci.h b/include/dm/platform_data/spi_davinci.h new file mode 100644 index 0000000..fbc62c2 --- /dev/null +++ b/include/dm/platform_data/spi_davinci.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2018 Jagan Teki <jagan@amarulasolutions.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __spi_davinci_h +#define __spi_davinci_h + +struct davinci_spi_platdata { + struct davinci_spi_regs *regs; + u8 num_cs; /* total no. of CS available */ +}; + +#endif /* __spi_davinci_h */ diff --git a/include/dm/platform_data/spi_pl022.h b/include/dm/platform_data/spi_pl022.h new file mode 100644 index 0000000..63a58ee --- /dev/null +++ b/include/dm/platform_data/spi_pl022.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2018 + * Quentin Schulz, Bootlin, quentin.schulz@bootlin.com + * + * Structure for use with U_BOOT_DEVICE for pl022 SPI devices or to use + * in ofdata_to_platdata. + */ + +#ifndef __spi_pl022_h +#define __spi_pl022_h + +#include <fdtdec.h> + +struct pl022_spi_pdata { + fdt_addr_t addr; + fdt_size_t size; + unsigned int freq; +}; + +#endif /* __spi_pl022_h */ diff --git a/include/dm/read.h b/include/dm/read.h new file mode 100644 index 0000000..d37fcb5 --- /dev/null +++ b/include/dm/read.h @@ -0,0 +1,892 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Function to read values from the device tree node attached to a udevice. + * + * Copyright (c) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + */ + +#ifndef _DM_READ_H +#define _DM_READ_H + +#include <dm/fdtaddr.h> +#include <dm/ofnode.h> +#include <dm/uclass.h> + +struct resource; + +#if CONFIG_IS_ENABLED(OF_LIVE) +static inline const struct device_node *dev_np(struct udevice *dev) +{ + return ofnode_to_np(dev->node); +} +#else +static inline const struct device_node *dev_np(struct udevice *dev) +{ + return NULL; +} +#endif + +/** + * dev_ofnode() - get the DT node reference associated with a udevice + * + * @dev: device to check + * @return reference of the the device's DT node + */ +static inline ofnode dev_ofnode(struct udevice *dev) +{ + return dev->node; +} + +static inline bool dev_of_valid(struct udevice *dev) +{ + return ofnode_valid(dev_ofnode(dev)); +} + +#ifndef CONFIG_DM_DEV_READ_INLINE + +/** + * dev_read_u32() - read a 32-bit integer from a device's DT property + * + * @dev: device to read DT property from + * @propname: name of the property to read from + * @outp: place to put value (if found) + * @return 0 if OK, -ve on error + */ +int dev_read_u32(struct udevice *dev, const char *propname, u32 *outp); + +/** + * dev_read_u32_default() - read a 32-bit integer from a device's DT property + * + * @dev: device to read DT property from + * @propname: name of the property to read from + * @def: default value to return if the property has no value + * @return property value, or @def if not found + */ +int dev_read_u32_default(struct udevice *dev, const char *propname, int def); + +/** + * dev_read_s32() - read a signed 32-bit integer from a device's DT property + * + * @dev: device to read DT property from + * @propname: name of the property to read from + * @outp: place to put value (if found) + * @return 0 if OK, -ve on error + */ +int dev_read_s32(struct udevice *dev, const char *propname, s32 *outp); + +/** + * dev_read_s32_default() - read a signed 32-bit int from a device's DT property + * + * @dev: device to read DT property from + * @propname: name of the property to read from + * @def: default value to return if the property has no value + * @return property value, or @def if not found + */ +int dev_read_s32_default(struct udevice *dev, const char *propname, int def); + +/** + * dev_read_u32u() - read a 32-bit integer from a device's DT property + * + * This version uses a standard uint type. + * + * @dev: device to read DT property from + * @propname: name of the property to read from + * @outp: place to put value (if found) + * @return 0 if OK, -ve on error + */ +int dev_read_u32u(struct udevice *dev, const char *propname, uint *outp); + +/** + * dev_read_u64() - read a 64-bit integer from a device's DT property + * + * @dev: device to read DT property from + * @propname: name of the property to read from + * @outp: place to put value (if found) + * @return 0 if OK, -ve on error + */ +int dev_read_u64(struct udevice *dev, const char *propname, u64 *outp); + +/** + * dev_read_u64_default() - read a 64-bit integer from a device's DT property + * + * @dev: device to read DT property from + * @propname: name of the property to read from + * @def: default value to return if the property has no value + * @return property value, or @def if not found + */ +u64 dev_read_u64_default(struct udevice *dev, const char *propname, u64 def); + +/** + * dev_read_string() - Read a string from a device's DT property + * + * @dev: device to read DT property from + * @propname: name of the property to read + * @return string from property value, or NULL if there is no such property + */ +const char *dev_read_string(struct udevice *dev, const char *propname); + +/** + * dev_read_bool() - read a boolean value from a device's DT property + * + * @dev: device to read DT property from + * @propname: name of property to read + * @return true if property is present (meaning true), false if not present + */ +bool dev_read_bool(struct udevice *dev, const char *propname); + +/** + * dev_read_subnode() - find a named subnode of a device + * + * @dev: device whose DT node contains the subnode + * @subnode_name: name of subnode to find + * @return reference to subnode (which can be invalid if there is no such + * subnode) + */ +ofnode dev_read_subnode(struct udevice *dev, const char *subbnode_name); + +/** + * dev_read_size() - read the size of a property + * + * @dev: device to check + * @propname: property to check + * @return size of property if present, or -EINVAL if not + */ +int dev_read_size(struct udevice *dev, const char *propname); + +/** + * dev_read_addr_index() - Get the indexed reg property of a device + * + * @dev: Device to read from + * @index: the 'reg' property can hold a list of <addr, size> pairs + * and @index is used to select which one is required + * + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t dev_read_addr_index(struct udevice *dev, int index); + +/** + * dev_read_addr_size_index() - Get the indexed reg property of a device + * + * @dev: Device to read from + * @index: the 'reg' property can hold a list of <addr, size> pairs + * and @index is used to select which one is required + * @size: place to put size value (on success) + * + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t dev_read_addr_size_index(struct udevice *dev, int index, + fdt_size_t *size); + +/** + * dev_remap_addr_index() - Get the indexed reg property of a device + * as a memory-mapped I/O pointer + * + * @dev: Device to read from + * @index: the 'reg' property can hold a list of <addr, size> pairs + * and @index is used to select which one is required + * + * @return pointer or NULL if not found + */ +void *dev_remap_addr_index(struct udevice *dev, int index); + +/** + * dev_read_addr_name() - Get the reg property of a device, indexed by name + * + * @dev: Device to read from + * @name: the 'reg' property can hold a list of <addr, size> pairs, with the + * 'reg-names' property providing named-based identification. @index + * indicates the value to search for in 'reg-names'. + * + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t dev_read_addr_name(struct udevice *dev, const char* name); + +/** + * dev_read_addr_size_name() - Get the reg property of a device, indexed by name + * + * @dev: Device to read from + * @name: the 'reg' property can hold a list of <addr, size> pairs, with the + * 'reg-names' property providing named-based identification. @index + * indicates the value to search for in 'reg-names'. + * @size: place to put size value (on success) + * + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t dev_read_addr_size_name(struct udevice *dev, const char *name, + fdt_size_t *size); + +/** + * dev_remap_addr_name() - Get the reg property of a device, indexed by name, + * as a memory-mapped I/O pointer + * + * @dev: Device to read from + * @name: the 'reg' property can hold a list of <addr, size> pairs, with the + * 'reg-names' property providing named-based identification. @index + * indicates the value to search for in 'reg-names'. + * + * @return pointer or NULL if not found + */ +void *dev_remap_addr_name(struct udevice *dev, const char* name); + +/** + * dev_read_addr() - Get the reg property of a device + * + * @dev: Device to read from + * + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t dev_read_addr(struct udevice *dev); + +/** + * dev_read_addr_ptr() - Get the reg property of a device + * as a pointer + * + * @dev: Device to read from + * + * @return pointer or NULL if not found + */ +void *dev_read_addr_ptr(struct udevice *dev); + +/** + * dev_read_addr_pci() - Read an address and handle PCI address translation + * + * At present U-Boot does not have address translation logic for PCI in the + * livetree implementation (of_addr.c). This special function supports this for + * the flat tree implementation. + * + * This function should be removed (and code should use dev_read() instead) + * once: + * + * 1. PCI address translation is added; and either + * 2. everything uses livetree where PCI translation is used (which is feasible + * in SPL and U-Boot proper) or PCI address translation is added to + * fdtdec_get_addr() and friends. + * + * @dev: Device to read from + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t dev_read_addr_pci(struct udevice *dev); + +/** + * dev_remap_addr() - Get the reg property of a device as a + * memory-mapped I/O pointer + * + * @dev: Device to read from + * + * @return pointer or NULL if not found + */ +void *dev_remap_addr(struct udevice *dev); + +/** + * dev_read_addr_size() - get address and size from a device property + * + * This does no address translation. It simply reads an property that contains + * an address and a size value, one after the other. + * + * @dev: Device to read from + * @propname: property to read + * @sizep: place to put size value (on success) + * @return address value, or FDT_ADDR_T_NONE on error + */ +fdt_addr_t dev_read_addr_size(struct udevice *dev, const char *propname, + fdt_size_t *sizep); + +/** + * dev_read_name() - get the name of a device's node + * + * @dev: Device to read from + * @return name of node + */ +const char *dev_read_name(struct udevice *dev); + +/** + * dev_read_stringlist_search() - find string in a string list and return index + * + * Note that it is possible for this function to succeed on property values + * that are not NUL-terminated. That's because the function will stop after + * finding the first occurrence of @string. This can for example happen with + * small-valued cell properties, such as #address-cells, when searching for + * the empty string. + * + * @dev: device to check + * @propname: name of the property containing the string list + * @string: string to look up in the string list + * + * @return: + * the index of the string in the list of strings + * -ENODATA if the property is not found + * -EINVAL on some other error + */ +int dev_read_stringlist_search(struct udevice *dev, const char *property, + const char *string); + +/** + * dev_read_string_index() - obtain an indexed string from a string list + * + * @dev: device to examine + * @propname: name of the property containing the string list + * @index: index of the string to return + * @out: return location for the string + * + * @return: + * length of string, if found or -ve error value if not found + */ +int dev_read_string_index(struct udevice *dev, const char *propname, int index, + const char **outp); + +/** + * dev_read_string_count() - find the number of strings in a string list + * + * @dev: device to examine + * @propname: name of the property containing the string list + * @return: + * number of strings in the list, or -ve error value if not found + */ +int dev_read_string_count(struct udevice *dev, const char *propname); +/** + * dev_read_phandle_with_args() - Find a node pointed by phandle in a list + * + * This function is useful to parse lists of phandles and their arguments. + * Returns 0 on success and fills out_args, on error returns appropriate + * errno value. + * + * Caller is responsible to call of_node_put() on the returned out_args->np + * pointer. + * + * Example: + * + * phandle1: node1 { + * #list-cells = <2>; + * } + * + * phandle2: node2 { + * #list-cells = <1>; + * } + * + * node3 { + * list = <&phandle1 1 2 &phandle2 3>; + * } + * + * To get a device_node of the `node2' node you may call this: + * dev_read_phandle_with_args(dev, "list", "#list-cells", 0, 1, &args); + * + * @dev: device whose node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * @cells_count: Cell count to use if @cells_name is NULL + * @index: index of a phandle to parse out + * @out_args: optional pointer to output arguments structure (will be filled) + * @return 0 on success (with @out_args filled out if not NULL), -ENOENT if + * @list_name does not exist, -EINVAL if a phandle was not found, + * @cells_name could not be found, the arguments were truncated or there + * were too many arguments. + */ +int dev_read_phandle_with_args(struct udevice *dev, const char *list_name, + const char *cells_name, int cell_count, + int index, + struct ofnode_phandle_args *out_args); + +/** + * dev_count_phandle_with_args() - Return phandle number in a list + * + * This function is usefull to get phandle number contained in a property list. + * For example, this allows to allocate the right amount of memory to keep + * clock's reference contained into the "clocks" property. + * + * + * @dev: device whose node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * @Returns number of phandle found on success, on error returns appropriate + * errno value. + */ + +int dev_count_phandle_with_args(struct udevice *dev, const char *list_name, + const char *cells_name); + +/** + * dev_read_addr_cells() - Get the number of address cells for a device's node + * + * This walks back up the tree to find the closest #address-cells property + * which controls the given node. + * + * @dev: device to check + * @return number of address cells this node uses + */ +int dev_read_addr_cells(struct udevice *dev); + +/** + * dev_read_size_cells() - Get the number of size cells for a device's node + * + * This walks back up the tree to find the closest #size-cells property + * which controls the given node. + * + * @dev: device to check + * @return number of size cells this node uses + */ +int dev_read_size_cells(struct udevice *dev); + +/** + * dev_read_addr_cells() - Get the address cells property in a node + * + * This function matches fdt_address_cells(). + * + * @dev: device to check + * @return number of address cells this node uses + */ +int dev_read_simple_addr_cells(struct udevice *dev); + +/** + * dev_read_size_cells() - Get the size cells property in a node + * + * This function matches fdt_size_cells(). + * + * @dev: device to check + * @return number of size cells this node uses + */ +int dev_read_simple_size_cells(struct udevice *dev); + +/** + * dev_read_phandle() - Get the phandle from a device + * + * @dev: device to check + * @return phandle (1 or greater), or 0 if no phandle or other error + */ +int dev_read_phandle(struct udevice *dev); + +/** + * dev_read_prop()- - read a property from a device's node + * + * @dev: device to check + * @propname: property to read + * @lenp: place to put length on success + * @return pointer to property, or NULL if not found + */ +const void *dev_read_prop(struct udevice *dev, const char *propname, int *lenp); + +/** + * dev_read_alias_seq() - Get the alias sequence number of a node + * + * This works out whether a node is pointed to by an alias, and if so, the + * sequence number of that alias. Aliases are of the form <base><num> where + * <num> is the sequence number. For example spi2 would be sequence number 2. + * + * @dev: device to look up + * @devnump: set to the sequence number if one is found + * @return 0 if a sequence was found, -ve if not + */ +int dev_read_alias_seq(struct udevice *dev, int *devnump); + +/** + * dev_read_u32_array() - Find and read an array of 32 bit integers + * + * Search for a property in a device node and read 32-bit value(s) from + * it. + * + * The out_values is modified only if a valid u32 value can be decoded. + * + * @dev: device to look up + * @propname: name of the property to read + * @out_values: pointer to return value, modified only if return value is 0 + * @sz: number of array elements to read + * @return 0 on success, -EINVAL if the property does not exist, -ENODATA if + * property does not have a value, and -EOVERFLOW if the property data isn't + * large enough. + */ +int dev_read_u32_array(struct udevice *dev, const char *propname, + u32 *out_values, size_t sz); + +/** + * dev_read_first_subnode() - find the first subnode of a device's node + * + * @dev: device to look up + * @return reference to the first subnode (which can be invalid if the device's + * node has no subnodes) + */ +ofnode dev_read_first_subnode(struct udevice *dev); + +/** + * ofnode_next_subnode() - find the next sibling of a subnode + * + * @node: valid reference to previous node (sibling) + * @return reference to the next subnode (which can be invalid if the node + * has no more siblings) + */ +ofnode dev_read_next_subnode(ofnode node); + +/** + * dev_read_u8_array_ptr() - find an 8-bit array + * + * Look up a device's node property and return a pointer to its contents as a + * byte array of given length. The property must have at least enough data + * for the array (count bytes). It may have more, but this will be ignored. + * The data is not copied. + * + * @dev: device to look up + * @propname: name of property to find + * @sz: number of array elements + * @return pointer to byte array if found, or NULL if the property is not + * found or there is not enough data + */ +const uint8_t *dev_read_u8_array_ptr(struct udevice *dev, const char *propname, + size_t sz); + +/** + * dev_read_enabled() - check whether a node is enabled + * + * This looks for a 'status' property. If this exists, then returns 1 if + * the status is 'ok' and 0 otherwise. If there is no status property, + * it returns 1 on the assumption that anything mentioned should be enabled + * by default. + * + * @dev: device to examine + * @return integer value 0 (not enabled) or 1 (enabled) + */ +int dev_read_enabled(struct udevice *dev); + +/** + * dev_read_resource() - obtain an indexed resource from a device. + * + * @dev: device to examine + * @index index of the resource to retrieve (0 = first) + * @res returns the resource + * @return 0 if ok, negative on error + */ +int dev_read_resource(struct udevice *dev, uint index, struct resource *res); + +/** + * dev_read_resource_byname() - obtain a named resource from a device. + * + * @dev: device to examine + * @name: name of the resource to retrieve + * @res: returns the resource + * @return 0 if ok, negative on error + */ +int dev_read_resource_byname(struct udevice *dev, const char *name, + struct resource *res); + +/** + * dev_translate_address() - Translate a device-tree address + * + * Translate an address from the device-tree into a CPU physical address. This + * function walks up the tree and applies the various bus mappings along the + * way. + * + * @dev: device giving the context in which to translate the address + * @in_addr: pointer to the address to translate + * @return the translated address; OF_BAD_ADDR on error + */ +u64 dev_translate_address(struct udevice *dev, const fdt32_t *in_addr); + +/** + * dev_translate_dma_address() - Translate a device-tree DMA address + * + * Translate a DMA address from the device-tree into a CPU physical address. + * This function walks up the tree and applies the various bus mappings along + * the way. + * + * @dev: device giving the context in which to translate the DMA address + * @in_addr: pointer to the DMA address to translate + * @return the translated DMA address; OF_BAD_ADDR on error + */ +u64 dev_translate_dma_address(struct udevice *dev, const fdt32_t *in_addr); + +/** + * dev_read_alias_highest_id - Get highest alias id for the given stem + * @stem: Alias stem to be examined + * + * The function travels the lookup table to get the highest alias id for the + * given alias stem. + * @return alias ID, if found, else -1 + */ +int dev_read_alias_highest_id(const char *stem); + +#else /* CONFIG_DM_DEV_READ_INLINE is enabled */ + +static inline int dev_read_u32(struct udevice *dev, + const char *propname, u32 *outp) +{ + return ofnode_read_u32(dev_ofnode(dev), propname, outp); +} + +static inline int dev_read_u32_default(struct udevice *dev, + const char *propname, int def) +{ + return ofnode_read_u32_default(dev_ofnode(dev), propname, def); +} + +static inline int dev_read_s32(struct udevice *dev, + const char *propname, s32 *outp) +{ + return ofnode_read_s32(dev_ofnode(dev), propname, outp); +} + +static inline int dev_read_s32_default(struct udevice *dev, + const char *propname, int def) +{ + return ofnode_read_s32_default(dev_ofnode(dev), propname, def); +} + +static inline int dev_read_u32u(struct udevice *dev, + const char *propname, uint *outp) +{ + u32 val; + int ret; + + ret = ofnode_read_u32(dev_ofnode(dev), propname, &val); + if (ret) + return ret; + *outp = val; + + return 0; +} + +static inline int dev_read_u64(struct udevice *dev, + const char *propname, u64 *outp) +{ + return ofnode_read_u64(dev_ofnode(dev), propname, outp); +} + +static inline u64 dev_read_u64_default(struct udevice *dev, + const char *propname, u64 def) +{ + return ofnode_read_u64_default(dev_ofnode(dev), propname, def); +} + +static inline const char *dev_read_string(struct udevice *dev, + const char *propname) +{ + return ofnode_read_string(dev_ofnode(dev), propname); +} + +static inline bool dev_read_bool(struct udevice *dev, const char *propname) +{ + return ofnode_read_bool(dev_ofnode(dev), propname); +} + +static inline ofnode dev_read_subnode(struct udevice *dev, + const char *subbnode_name) +{ + return ofnode_find_subnode(dev_ofnode(dev), subbnode_name); +} + +static inline int dev_read_size(struct udevice *dev, const char *propname) +{ + return ofnode_read_size(dev_ofnode(dev), propname); +} + +static inline fdt_addr_t dev_read_addr_index(struct udevice *dev, int index) +{ + return devfdt_get_addr_index(dev, index); +} + +static inline fdt_addr_t dev_read_addr_size_index(struct udevice *dev, + int index, + fdt_size_t *size) +{ + return devfdt_get_addr_size_index(dev, index, size); +} + +static inline fdt_addr_t dev_read_addr_name(struct udevice *dev, + const char *name) +{ + return devfdt_get_addr_name(dev, name); +} + +static inline fdt_addr_t dev_read_addr_size_name(struct udevice *dev, + const char *name, + fdt_size_t *size) +{ + return devfdt_get_addr_size_name(dev, name, size); +} + +static inline fdt_addr_t dev_read_addr(struct udevice *dev) +{ + return devfdt_get_addr(dev); +} + +static inline void *dev_read_addr_ptr(struct udevice *dev) +{ + return devfdt_get_addr_ptr(dev); +} + +static inline fdt_addr_t dev_read_addr_pci(struct udevice *dev) +{ + return devfdt_get_addr_pci(dev); +} + +static inline void *dev_remap_addr(struct udevice *dev) +{ + return devfdt_remap_addr(dev); +} + +static inline void *dev_remap_addr_index(struct udevice *dev, int index) +{ + return devfdt_remap_addr_index(dev, index); +} + +static inline void *dev_remap_addr_name(struct udevice *dev, const char *name) +{ + return devfdt_remap_addr_name(dev, name); +} + +static inline fdt_addr_t dev_read_addr_size(struct udevice *dev, + const char *propname, + fdt_size_t *sizep) +{ + return ofnode_get_addr_size(dev_ofnode(dev), propname, sizep); +} + +static inline const char *dev_read_name(struct udevice *dev) +{ + return ofnode_get_name(dev_ofnode(dev)); +} + +static inline int dev_read_stringlist_search(struct udevice *dev, + const char *propname, + const char *string) +{ + return ofnode_stringlist_search(dev_ofnode(dev), propname, string); +} + +static inline int dev_read_string_index(struct udevice *dev, + const char *propname, int index, + const char **outp) +{ + return ofnode_read_string_index(dev_ofnode(dev), propname, index, outp); +} + +static inline int dev_read_string_count(struct udevice *dev, + const char *propname) +{ + return ofnode_read_string_count(dev_ofnode(dev), propname); +} + +static inline int dev_read_phandle_with_args(struct udevice *dev, + const char *list_name, const char *cells_name, int cell_count, + int index, struct ofnode_phandle_args *out_args) +{ + return ofnode_parse_phandle_with_args(dev_ofnode(dev), list_name, + cells_name, cell_count, index, + out_args); +} + +static inline int dev_count_phandle_with_args(struct udevice *dev, + const char *list_name, const char *cells_name) +{ + return ofnode_count_phandle_with_args(dev_ofnode(dev), list_name, + cells_name); +} + +static inline int dev_read_addr_cells(struct udevice *dev) +{ + /* NOTE: this call should walk up the parent stack */ + return fdt_address_cells(gd->fdt_blob, dev_of_offset(dev)); +} + +static inline int dev_read_size_cells(struct udevice *dev) +{ + /* NOTE: this call should walk up the parent stack */ + return fdt_size_cells(gd->fdt_blob, dev_of_offset(dev)); +} + +static inline int dev_read_simple_addr_cells(struct udevice *dev) +{ + return fdt_address_cells(gd->fdt_blob, dev_of_offset(dev)); +} + +static inline int dev_read_simple_size_cells(struct udevice *dev) +{ + return fdt_size_cells(gd->fdt_blob, dev_of_offset(dev)); +} + +static inline int dev_read_phandle(struct udevice *dev) +{ + return fdt_get_phandle(gd->fdt_blob, dev_of_offset(dev)); +} + +static inline const void *dev_read_prop(struct udevice *dev, + const char *propname, int *lenp) +{ + return ofnode_get_property(dev_ofnode(dev), propname, lenp); +} + +static inline int dev_read_alias_seq(struct udevice *dev, int *devnump) +{ + return fdtdec_get_alias_seq(gd->fdt_blob, dev->uclass->uc_drv->name, + dev_of_offset(dev), devnump); +} + +static inline int dev_read_u32_array(struct udevice *dev, const char *propname, + u32 *out_values, size_t sz) +{ + return ofnode_read_u32_array(dev_ofnode(dev), propname, out_values, sz); +} + +static inline ofnode dev_read_first_subnode(struct udevice *dev) +{ + return ofnode_first_subnode(dev_ofnode(dev)); +} + +static inline ofnode dev_read_next_subnode(ofnode node) +{ + return ofnode_next_subnode(node); +} + +static inline const uint8_t *dev_read_u8_array_ptr(struct udevice *dev, + const char *propname, size_t sz) +{ + return ofnode_read_u8_array_ptr(dev_ofnode(dev), propname, sz); +} + +static inline int dev_read_enabled(struct udevice *dev) +{ + return fdtdec_get_is_enabled(gd->fdt_blob, dev_of_offset(dev)); +} + +static inline int dev_read_resource(struct udevice *dev, uint index, + struct resource *res) +{ + return ofnode_read_resource(dev_ofnode(dev), index, res); +} + +static inline int dev_read_resource_byname(struct udevice *dev, + const char *name, + struct resource *res) +{ + return ofnode_read_resource_byname(dev_ofnode(dev), name, res); +} + +static inline u64 dev_translate_address(struct udevice *dev, const fdt32_t *in_addr) +{ + return ofnode_translate_address(dev_ofnode(dev), in_addr); +} + +static inline u64 dev_translate_dma_address(struct udevice *dev, const fdt32_t *in_addr) +{ + return ofnode_translate_dma_address(dev_ofnode(dev), in_addr); +} + +static inline int dev_read_alias_highest_id(const char *stem) +{ + return fdtdec_get_alias_highest_id(gd->fdt_blob, stem); +} + +#endif /* CONFIG_DM_DEV_READ_INLINE */ + +/** + * dev_for_each_subnode() - Helper function to iterate through subnodes + * + * This creates a for() loop which works through the subnodes in a device's + * device-tree node. + * + * @subnode: ofnode holding the current subnode + * @dev: device to use for interation (struct udevice *) + */ +#define dev_for_each_subnode(subnode, dev) \ + for (subnode = dev_read_first_subnode(dev); \ + ofnode_valid(subnode); \ + subnode = ofnode_next_subnode(subnode)) + +#endif diff --git a/include/dm/root.h b/include/dm/root.h new file mode 100644 index 0000000..c8d629b --- /dev/null +++ b/include/dm/root.h @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + */ + +#ifndef _DM_ROOT_H_ +#define _DM_ROOT_H_ + +struct udevice; + +/** + * 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 udevice *dm_root(void); + +struct global_data; +/** + * dm_fixup_for_gd_move() - Handle global_data moving to a new place + * + * The uclass list is part of global_data. Due to the way lists work, moving + * the list will cause it to become invalid. This function fixes that up so + * that the uclass list will work correctly. + */ +void dm_fixup_for_gd_move(struct global_data *new_gd); + +/** + * dm_scan_platdata() - Scan all platform data and bind drivers + * + * This scans all available platdata and creates drivers for each + * + * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC + * flag. If false bind all drivers. + * @return 0 if OK, -ve on error + */ +int dm_scan_platdata(bool pre_reloc_only); + +/** + * dm_scan_fdt() - Scan the device tree and bind drivers + * + * This scans the device tree and creates a driver for each node. Only + * the top-level subnodes are examined. + * + * @blob: Pointer to device tree blob + * @pre_reloc_only: If true, bind only nodes with special devicetree properties, + * or drivers with the DM_FLAG_PRE_RELOC flag. If false bind all drivers. + * @return 0 if OK, -ve on error + */ +int dm_scan_fdt(const void *blob, bool pre_reloc_only); + +/** + * dm_extended_scan_fdt() - Scan the device tree and bind drivers + * + * This calls dm_scna_dft() which scans the device tree and creates a driver + * for each node. the top-level subnodes are examined and also all sub-nodes + * of "clocks" node. + * + * @blob: Pointer to device tree blob + * @pre_reloc_only: If true, bind only nodes with special devicetree properties, + * or drivers with the DM_FLAG_PRE_RELOC flag. If false bind all drivers. + * @return 0 if OK, -ve on error + */ +int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only); + +/** + * dm_scan_other() - Scan for other devices + * + * Some devices may not be visible to Driver Model. This weak function can + * be provided by boards which wish to create their own devices + * programmaticaly. They should do this by calling device_bind() on each + * device. + * + * @pre_reloc_only: If true, bind only nodes with special devicetree properties, + * or drivers with the DM_FLAG_PRE_RELOC flag. If false bind all drivers. + * @return 0 if OK, -ve on error + */ +int dm_scan_other(bool pre_reloc_only); + +/** + * dm_init_and_scan() - Initialise Driver Model structures and scan for devices + * + * This function initialises the roots of the driver tree and uclass trees, + * then scans and binds available devices from platform data and the FDT. + * This calls dm_init() to set up Driver Model structures. + * + * @pre_reloc_only: If true, bind only nodes with special devicetree properties, + * or drivers with the DM_FLAG_PRE_RELOC flag. If false bind all drivers. + * @return 0 if OK, -ve on error + */ +int dm_init_and_scan(bool pre_reloc_only); + +/** + * dm_init() - Initialise Driver Model structures + * + * This function will initialize roots of driver tree and class tree. + * This needs to be called before anything uses the DM + * + * @of_live: Enable live device tree + * @return 0 if OK, -ve on error + */ +int dm_init(bool of_live); + +/** + * dm_uninit - Uninitialise Driver Model structures + * + * All devices will be removed and unbound + * @return 0 if OK, -ve on error + */ +int dm_uninit(void); + +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) +/** + * dm_remove_devices_flags - Call remove function of all drivers with + * specific removal flags set to selectively + * remove drivers + * + * All devices with the matching flags set will be removed + * + * @flags: Flags for selective device removal + * @return 0 if OK, -ve on error + */ +int dm_remove_devices_flags(uint flags); +#else +static inline int dm_remove_devices_flags(uint flags) { return 0; } +#endif + +#endif diff --git a/include/dm/test.h b/include/dm/test.h new file mode 100644 index 0000000..07385cd --- /dev/null +++ b/include/dm/test.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 Google, Inc. + */ + +#ifndef __DM_TEST_H +#define __DM_TEST_H + +#include <dm.h> +#include <test/test.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 udevice *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_PRE_PROBE, + 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]; + int uclass_flag; + int uclass_total; + int uclass_postp; +}; + +/** + * 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; +}; + +/** + * struct dm_test_parent_data - parent's information on each child + * + * @sum: Test value used to check parent data works correctly + * @flag: Used to track calling of parent operations + * @uclass_flag: Used to track calling of parent operations by uclass + */ +struct dm_test_parent_data { + int sum; + int flag; +}; + +/* Test values for test device's uclass platform data */ +enum { + TEST_UC_PDATA_INTVAL1 = 2, + TEST_UC_PDATA_INTVAL2 = 334, + TEST_UC_PDATA_INTVAL3 = 789452, +}; + +/** + * struct dm_test_uclass_platda - uclass's information on each device + * + * @intval1: set to TEST_UC_PDATA_INTVAL1 in .post_bind method of test uclass + * @intval2: set to TEST_UC_PDATA_INTVAL2 in .post_bind method of test uclass + * @intval3: set to TEST_UC_PDATA_INTVAL3 in .post_bind method of test uclass + */ +struct dm_test_perdev_uc_pdata { + int intval1; + int intval2; + int intval3; +}; + +/* + * 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 unit_test_state global_dm_test_state; + +/* + * struct dm_test_state - Entire state of dm test system + * + * This is often abreviated to dms. + * + * @root: Root device + * @testdev: Test device + * @force_fail_alloc: Force all memory allocs to fail + * @skip_post_probe: Skip uclass post-probe processing + * @removed: Used to keep track of a device that was removed + */ +struct dm_test_state { + struct udevice *root; + struct udevice *testdev; + int force_fail_alloc; + int skip_post_probe; + struct udevice *removed; +}; + +/* 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 */ + DM_TESTF_FLAT_TREE = 1 << 3, /* test needs flat DT */ + DM_TESTF_LIVE_TREE = 1 << 4, /* needs live device tree */ +}; + +/* Declare a new driver model test */ +#define DM_TEST(_name, _flags) UNIT_TEST(_name, _flags, dm_test) + +/* This platform data is needed in tests, so declare it here */ +struct sandbox_sdl_plat { + int xres; + int yres; + int bpix; + int rot; + const char *vidconsole_drv_name; + int font_size; +}; + +/* Declare ping methods for the drivers */ +int test_ping(struct udevice *dev, int pingval, int *pingret); +int testfdt_ping(struct udevice *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 unit_test_state *uts, struct udevice *dev, + uint32_t base, struct dm_test_priv *priv); + +/** + * dm_check_devices() - check the devices respond to operations correctly + * + * @dms: Overall test state + * @num_devices: Number of test devices to check + * @return 0 if OK, -ve on error + */ +int dm_check_devices(struct unit_test_state *uts, int num_devices); + +/** + * dm_leak_check_start() - Prepare to check for a memory leak + * + * Call this before allocating memory to record the amount of memory being + * used. + * + * @dms: Overall test state + */ +void dm_leak_check_start(struct unit_test_state *uts); + +/** + * dm_leak_check_end() - Check that no memory has leaked + * + * Call this after dm_leak_check_start() and after you have hopefuilly freed + * all the memory that was allocated. This function will print an error if + * it sees a different amount of total memory allocated than before. + * + * @dms: Overall test state + */int dm_leak_check_end(struct unit_test_state *uts); + +#endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h new file mode 100644 index 0000000..0c563d8 --- /dev/null +++ b/include/dm/uclass-id.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + */ + +#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, + UCLASS_TEST_BUS, + UCLASS_TEST_PROBE, + UCLASS_TEST_DUMMY, + UCLASS_SPI_EMUL, /* sandbox SPI device emulator */ + UCLASS_I2C_EMUL, /* sandbox I2C device emulator */ + UCLASS_I2C_EMUL_PARENT, /* parent for I2C device emulators */ + UCLASS_PCI_EMUL, /* sandbox PCI device emulator */ + UCLASS_PCI_EMUL_PARENT, /* parent for PCI device emulators */ + UCLASS_USB_EMUL, /* sandbox USB bus device emulator */ + UCLASS_AXI_EMUL, /* sandbox AXI bus device emulator */ + + /* U-Boot uclasses start here - in alphabetical order */ + UCLASS_ADC, /* Analog-to-digital converter */ + UCLASS_AHCI, /* SATA disk controller */ + UCLASS_AUDIO_CODEC, /* Audio codec with control and data path */ + UCLASS_AXI, /* AXI bus */ + UCLASS_BLK, /* Block device */ + UCLASS_BOARD, /* Device information from hardware */ + UCLASS_BOOTCOUNT, /* Bootcount backing store */ + UCLASS_CACHE, /* Cache controller */ + UCLASS_CLK, /* Clock source, e.g. used by peripherals */ + UCLASS_CPU, /* CPU, typically part of an SoC */ + UCLASS_CROS_EC, /* Chrome OS EC */ + UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */ + UCLASS_DSI_HOST, /* Display Serial Interface host */ + UCLASS_DMA, /* Direct Memory Access */ + UCLASS_EFI, /* EFI managed devices */ + UCLASS_ETH, /* Ethernet device */ + UCLASS_FIRMWARE, /* Firmware */ + UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */ + UCLASS_GPIO, /* Bank of general-purpose I/O pins */ + UCLASS_HWSPINLOCK, /* Hardware semaphores */ + UCLASS_I2C, /* I2C bus */ + UCLASS_I2C_EEPROM, /* I2C EEPROM device */ + UCLASS_I2C_GENERIC, /* Generic I2C device */ + UCLASS_I2C_MUX, /* I2C multiplexer */ + UCLASS_I2S, /* I2S bus */ + UCLASS_IDE, /* IDE device */ + UCLASS_IRQ, /* Interrupt controller */ + UCLASS_KEYBOARD, /* Keyboard input device */ + UCLASS_LED, /* Light-emitting diode (LED) */ + UCLASS_LPC, /* x86 'low pin count' interface */ + UCLASS_MAILBOX, /* Mailbox controller */ + UCLASS_MASS_STORAGE, /* Mass storage device */ + UCLASS_MDIO, /* MDIO bus */ + UCLASS_MDIO_MUX, /* MDIO MUX/switch */ + UCLASS_MISC, /* Miscellaneous device */ + UCLASS_MMC, /* SD / MMC card or chip */ + UCLASS_MOD_EXP, /* RSA Mod Exp device */ + UCLASS_MTD, /* Memory Technology Device (MTD) device */ + UCLASS_NOP, /* No-op devices */ + UCLASS_NORTHBRIDGE, /* Intel Northbridge / SDRAM controller */ + UCLASS_NVME, /* NVM Express device */ + UCLASS_PANEL, /* Display panel, such as an LCD */ + UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */ + UCLASS_PCH, /* x86 platform controller hub */ + UCLASS_PCI, /* PCI bus */ + UCLASS_PCI_EP, /* PCI endpoint device */ + UCLASS_PCI_GENERIC, /* Generic PCI bus device */ + UCLASS_PHY, /* Physical Layer (PHY) device */ + UCLASS_PINCONFIG, /* Pin configuration node device */ + UCLASS_PINCTRL, /* Pinctrl (pin muxing/configuration) device */ + UCLASS_PMIC, /* PMIC I/O device */ + UCLASS_POWER_DOMAIN, /* (SoC) Power domains */ + UCLASS_PWM, /* Pulse-width modulator */ + UCLASS_PWRSEQ, /* Power sequence device */ + UCLASS_RAM, /* RAM controller */ + UCLASS_REGULATOR, /* Regulator device */ + UCLASS_REMOTEPROC, /* Remote Processor device */ + UCLASS_RESET, /* Reset controller device */ + UCLASS_RTC, /* Real time clock device */ + UCLASS_SCSI, /* SCSI device */ + UCLASS_SERIAL, /* Serial UART */ + UCLASS_SIMPLE_BUS, /* Bus with child devices */ + UCLASS_SMEM, /* Shared memory interface */ + UCLASS_SOUND, /* Playing simple sounds */ + UCLASS_SPI, /* SPI bus */ + UCLASS_SPI_FLASH, /* SPI flash */ + UCLASS_SPI_GENERIC, /* Generic SPI flash target */ + UCLASS_SPMI, /* System Power Management Interface bus */ + UCLASS_SYSCON, /* System configuration device */ + UCLASS_SYSRESET, /* System reset device */ + UCLASS_TEE, /* Trusted Execution Environment device */ + UCLASS_THERMAL, /* Thermal sensor */ + UCLASS_TIMER, /* Timer device */ + UCLASS_TPM, /* Trusted Platform Module TIS interface */ + UCLASS_UFS, /* Universal Flash Storage */ + UCLASS_USB, /* USB bus */ + UCLASS_USB_DEV_GENERIC, /* USB generic device */ + UCLASS_USB_HUB, /* USB hub */ + UCLASS_USB_GADGET_GENERIC, /* USB generic device */ + UCLASS_VIDEO, /* Video or LCD device */ + UCLASS_VIDEO_BRIDGE, /* Video bridge, e.g. DisplayPort to LVDS */ + UCLASS_VIDEO_CONSOLE, /* Text console driver for video device */ + UCLASS_VIDEO_OSD, /* On-screen display */ + UCLASS_VIRTIO, /* VirtIO transport device */ + UCLASS_W1, /* Dallas 1-Wire bus */ + UCLASS_W1_EEPROM, /* one-wire EEPROMs */ + UCLASS_WDT, /* Watchdog Timer driver */ + + 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 0000000..6e3f15c --- /dev/null +++ b/include/dm/uclass-internal.h @@ -0,0 +1,254 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + */ + +#ifndef _DM_UCLASS_INTERNAL_H +#define _DM_UCLASS_INTERNAL_H + +#include <dm/ofnode.h> + +/** + * uclass_find_next_free_req_seq() - Get the next free req_seq number + * + * This returns the next free req_seq number. This is useful only if + * OF_CONTROL is not used. The next free req_seq number is simply the + * maximum req_seq of the uclass + 1. + * This allows assiging req_seq number in the binding order. + * + * @id: Id number of the uclass + * @return The next free req_seq number + */ +int uclass_find_next_free_req_seq(enum uclass_id id); + +/** + * uclass_get_device_tail() - handle the end of a get_device call + * + * This handles returning an error or probing a device as needed. + * + * @dev: Device that needs to be probed + * @ret: Error to return. If non-zero then the device is not probed + * @devp: Returns the value of 'dev' if there is no error + * @return ret, if non-zero, else the result of the device_probe() call + */ +int uclass_get_device_tail(struct udevice *dev, int ret, struct udevice **devp); + +/** + * dev_get_uclass_index() - Get uclass and index of device + * @dev: - in - Device that we want the uclass/index of + * @ucp: - out - A pointer to the uclass the device belongs to + * + * The device is not prepared for use - this is an internal function. + * + * @return the index of the device in the uclass list or -ENODEV if not found. + */ +int dev_get_uclass_index(struct udevice *dev, struct uclass **ucp); + +/** + * 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. + * The function uclass_get_device_tail() can be used to probe the device. + * + * @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 udevice **devp); + +/** + * uclass_find_first_device() - Return the first device in a uclass + * @id: Id number of the uclass + * #devp: Returns pointer to device, or NULL on error + * + * The device is not prepared for use - this is an internal function. + * The function uclass_get_device_tail() can be used to probe the device. + * + * @return 0 if OK (found or not found), -ve on error + */ +int uclass_find_first_device(enum uclass_id id, struct udevice **devp); + +/** + * uclass_find_next_device() - Return 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 + * + * The device is not prepared for use - this is an internal function. + * The function uclass_get_device_tail() can be used to probe the device. + * + * @return 0 if OK (found or not found), -ve on error + */ +int uclass_find_next_device(struct udevice **devp); + +/** + * uclass_find_device_by_name() - Find uclass device based on ID and name + * + * This searches for a device with the exactly given name. + * + * The device is NOT probed, it is merely returned. + * + * @id: ID to look up + * @name: name of a device to find + * @devp: Returns pointer to device (the first one with the name) + * @return 0 if OK, -ve on error + */ +int uclass_find_device_by_name(enum uclass_id id, const char *name, + struct udevice **devp); + +/** + * uclass_find_device_by_seq() - Find uclass device based on ID and sequence + * + * This searches for a device with the given seq or req_seq. + * + * For seq, if an active device has this sequence it will be returned. + * If there is no such device then this will return -ENODEV. + * + * For req_seq, if a device (whether activated or not) has this req_seq + * value, that device will be returned. This is a strong indication that + * the device will receive that sequence when activated. + * + * The device is NOT probed, it is merely returned. + * + * @id: ID to look up + * @seq_or_req_seq: Sequence number to find (0=first) + * @find_req_seq: true to find req_seq, false to find seq + * @devp: Returns pointer to device (there is only one per for each seq) + * @return 0 if OK, -ve on error + */ +int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq, + bool find_req_seq, struct udevice **devp); + +/** + * uclass_find_device_by_of_offset() - Find a uclass device by device tree node + * + * This searches the devices in the uclass for one attached to the given + * device tree node. + * + * The device is NOT probed, it is merely returned. + * + * @id: ID to look up + * @node: Device tree offset to search for (if -ve then -ENODEV is returned) + * @devp: Returns pointer to device (there is only one for each node) + * @return 0 if OK, -ve on error + */ +int uclass_find_device_by_of_offset(enum uclass_id id, int node, + struct udevice **devp); + +/** + * uclass_find_device_by_of_node() - Find a uclass device by device tree node + * + * This searches the devices in the uclass for one attached to the given + * device tree node. + * + * The device is NOT probed, it is merely returned. + * + * @id: ID to look up + * @node: Device tree offset to search for (if NULL then -ENODEV is returned) + * @devp: Returns pointer to device (there is only one for each node) + * @return 0 if OK, -ve on error + */ +int uclass_find_device_by_ofnode(enum uclass_id id, ofnode node, + struct udevice **devp); + +/** + * uclass_find_device_by_phandle() - Find a uclass device by phandle + * + * This searches the devices in the uclass for one with the given phandle. + * + * The device is NOT probed, it is merely returned. + * + * @id: ID to look up + * @parent: Parent device containing the phandle pointer + * @name: Name of property in the parent device node + * @devp: Returns pointer to device (there is only one for each node) + * @return 0 if OK, -ENOENT if there is no @name present in the node, other + * -ve on error + */ +int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent, + const char *name, struct udevice **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 udevice *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 + */ +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) +int uclass_unbind_device(struct udevice *dev); +#else +static inline int uclass_unbind_device(struct udevice *dev) { return 0; } +#endif + +/** + * uclass_pre_probe_device() - Deal with a device that is about to be probed + * + * Perform any pre-processing that is needed by the uclass before it can be + * probed. This includes the uclass' pre-probe() method and the parent + * uclass' child_pre_probe() method. + * + * @dev: Pointer to the device + * #return 0 on success, -ve on error + */ +int uclass_pre_probe_device(struct udevice *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 udevice *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 + */ +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) +int uclass_pre_remove_device(struct udevice *dev); +#else +static inline int uclass_pre_remove_device(struct udevice *dev) { return 0; } +#endif + +/** + * 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 0000000..484d166 --- /dev/null +++ b/include/dm/uclass.h @@ -0,0 +1,412 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann <morpheus.ibis@gmail.com> + */ + +#ifndef _DM_UCLASS_H +#define _DM_UCLASS_H + +#include <dm/ofnode.h> +#include <dm/uclass-id.h> +#include <linker_lists.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 driver; +struct udevice; + +/* Members of this uclass sequence themselves with aliases */ +#define DM_UC_FLAG_SEQ_ALIAS (1 << 0) + +/* Same as DM_FLAG_ALLOC_PRIV_DMA */ +#define DM_UC_FLAG_ALLOC_PRIV_DMA (1 << 5) + +/** + * 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 + * @pre_probe: Called before a new device is probed + * @post_probe: Called after a new device is probed + * @pre_remove: Called before a device is removed + * @child_post_bind: Called after a child is bound to a device in this uclass + * @child_pre_probe: Called before a child in this uclass is probed + * @child_post_probe: Called after a child in this uclass is probed + * @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. + * @per_device_platdata_auto_alloc_size: Each device can hold platform data + * owned by the uclass as 'dev->uclass_platdata'. If the value is non-zero, + * then this will be automatically allocated. + * @per_child_auto_alloc_size: Each child device (of a parent in this + * uclass) can hold parent data for the device/uclass. This value is only + * used as a fallback if this member is 0 in the driver. + * @per_child_platdata_auto_alloc_size: A bus likes to store information about + * its children. If non-zero this is the size of this data, to be allocated + * in the child device's parent_platdata pointer. This value is only used as + * a fallback if this member is 0 in the driver. + * @ops: Uclass operations, providing the consistent interface to devices + * within the uclass. + * @flags: Flags for this uclass (DM_UC_...) + */ +struct uclass_driver { + const char *name; + enum uclass_id id; + int (*post_bind)(struct udevice *dev); + int (*pre_unbind)(struct udevice *dev); + int (*pre_probe)(struct udevice *dev); + int (*post_probe)(struct udevice *dev); + int (*pre_remove)(struct udevice *dev); + int (*child_post_bind)(struct udevice *dev); + int (*child_pre_probe)(struct udevice *dev); + int (*child_post_probe)(struct udevice *dev); + int (*init)(struct uclass *class); + int (*destroy)(struct uclass *class); + int priv_auto_alloc_size; + int per_device_auto_alloc_size; + int per_device_platdata_auto_alloc_size; + int per_child_auto_alloc_size; + int per_child_platdata_auto_alloc_size; + const void *ops; + uint32_t flags; +}; + +/* 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_name() - Get the name of a uclass driver + * + * @id: ID to look up + * @returns the name of the uclass driver for that ID, or NULL if none + */ +const char *uclass_get_name(enum uclass_id id); + +/** + * uclass_get_by_name() - Look up a uclass by its driver name + * + * @name: Name to look up + * @returns the associated uclass ID, or UCLASS_INVALID if not found + */ +enum uclass_id uclass_get_by_name(const char *name); + +/** + * uclass_get_device() - Get a uclass device based on an ID and index + * + * The device is probed to activate it ready for use. + * + * @id: ID to look up + * @index: Device number within that uclass (0=first) + * @devp: Returns pointer to device (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 udevice **devp); + +/** + * uclass_get_device_by_name() - Get a uclass device by its name + * + * This searches the devices in the uclass for one with the exactly given name. + * + * The device is probed to activate it ready for use. + * + * @id: ID to look up + * @name: name of a device to get + * @devp: Returns pointer to device (the first one with the name) + * @return 0 if OK, -ve on error + */ +int uclass_get_device_by_name(enum uclass_id id, const char *name, + struct udevice **devp); + +/** + * uclass_get_device_by_seq() - Get a uclass device based on an ID and sequence + * + * If an active device has this sequence it will be returned. If there is no + * such device then this will check for a device that is requesting this + * sequence. + * + * The device is probed to activate it ready for use. + * + * @id: ID to look up + * @seq: Sequence number to find (0=first) + * @devp: Returns pointer to device (there is only one for each seq) + * @return 0 if OK, -ve on error + */ +int uclass_get_device_by_seq(enum uclass_id id, int seq, struct udevice **devp); + +/** + * uclass_get_device_by_of_offset() - Get a uclass device by device tree node + * + * This searches the devices in the uclass for one attached to the given + * device tree node. + * + * The device is probed to activate it ready for use. + * + * @id: ID to look up + * @node: Device tree offset to search for (if -ve then -ENODEV is returned) + * @devp: Returns pointer to device (there is only one for each node) + * @return 0 if OK, -ve on error + */ +int uclass_get_device_by_of_offset(enum uclass_id id, int node, + struct udevice **devp); + +/** + * uclass_get_device_by_ofnode() - Get a uclass device by device tree node + * + * This searches the devices in the uclass for one attached to the given + * device tree node. + * + * The device is probed to activate it ready for use. + * + * @id: ID to look up + * @np: Device tree node to search for (if NULL then -ENODEV is returned) + * @devp: Returns pointer to device (there is only one for each node) + * @return 0 if OK, -ve on error + */ +int uclass_get_device_by_ofnode(enum uclass_id id, ofnode node, + struct udevice **devp); + +/** + * uclass_get_device_by_phandle_id() - Get a uclass device by phandle id + * + * This searches the devices in the uclass for one with the given phandle id. + * + * The device is probed to activate it ready for use. + * + * @id: uclass ID to look up + * @phandle_id: the phandle id to look up + * @devp: Returns pointer to device (there is only one for each node) + * @return 0 if OK, -ENODEV if there is no device match the phandle, other + * -ve on error + */ +int uclass_get_device_by_phandle_id(enum uclass_id id, uint phandle_id, + struct udevice **devp); + +/** + * uclass_get_device_by_phandle() - Get a uclass device by phandle + * + * This searches the devices in the uclass for one with the given phandle. + * + * The device is probed to activate it ready for use. + * + * @id: uclass ID to look up + * @parent: Parent device containing the phandle pointer + * @name: Name of property in the parent device node + * @devp: Returns pointer to device (there is only one for each node) + * @return 0 if OK, -ENOENT if there is no @name present in the node, other + * -ve on error + */ +int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent, + const char *name, struct udevice **devp); + +/** + * uclass_get_device_by_driver() - Get a uclass device for a driver + * + * This searches the devices in the uclass for one that uses the given + * driver. Use DM_GET_DRIVER(name) for the @drv argument, where 'name' is + * the driver name - as used in U_BOOT_DRIVER(name). + * + * The device is probed to activate it ready for use. + * + * @id: ID to look up + * @drv: Driver to look for + * @devp: Returns pointer to the first device with that driver + * @return 0 if OK, -ve on error + */ +int uclass_get_device_by_driver(enum uclass_id id, const struct driver *drv, + struct udevice **devp); + +/** + * uclass_first_device() - Get the first device in a uclass + * + * The device returned is probed if necessary, and ready for use + * + * This function is useful to start iterating through a list of devices which + * are functioning correctly and can be probed. + * + * @id: Uclass ID to look up + * @devp: Returns pointer to the first device in that uclass if no error + * occurred, or NULL if there is no first device, or an error occurred with + * that device. + * @return 0 if OK (found or not found), other -ve on error + */ +int uclass_first_device(enum uclass_id id, struct udevice **devp); + +/** + * uclass_first_device_err() - Get the first device in a uclass + * + * The device returned is probed if necessary, and ready for use + * + * @id: Uclass ID to look up + * @devp: Returns pointer to the first device in that uclass, or NULL if none + * @return 0 if found, -ENODEV if not found, other -ve on error + */ +int uclass_first_device_err(enum uclass_id id, struct udevice **devp); + +/** + * uclass_next_device() - Get the next device in a uclass + * + * The device returned is probed if necessary, and ready for use + * + * This function is useful to iterate through a list of devices which + * are functioning correctly and can be probed. + * + * @devp: On entry, pointer to device to lookup. On exit, returns pointer + * to the next device in the uclass if no error occurred, or NULL if there is + * no next device, or an error occurred with that next device. + * @return 0 if OK (found or not found), other -ve on error + */ +int uclass_next_device(struct udevice **devp); + +/** + * uclass_next_device_err() - Get the next device in a uclass + * + * The device returned is probed if necessary, and ready for use + * + * @devp: On entry, pointer to device to lookup. On exit, returns pointer + * to the next device in the uclass if no error occurred, or -ENODEV if + * there is no next device. + * @return 0 if found, -ENODEV if not found, other -ve on error + */ +int uclass_next_device_err(struct udevice **devp); + +/** + * uclass_first_device_check() - Get the first device in a uclass + * + * The device returned is probed if necessary, and ready for use + * + * This function is useful to start iterating through a list of devices which + * are functioning correctly and can be probed. + * + * @id: Uclass ID to look up + * @devp: Returns pointer to the first device in that uclass, or NULL if there + * is no first device + * @return 0 if OK (found or not found), other -ve on error. If an error occurs + * it is still possible to move to the next device. + */ +int uclass_first_device_check(enum uclass_id id, struct udevice **devp); + +/** + * uclass_next_device_check() - Get the next device in a uclass + * + * The device returned is probed if necessary, and ready for use + * + * This function is useful to start iterating through a list of devices which + * are functioning correctly and can be probed. + * + * @devp: On entry, pointer to device to lookup. On exit, returns pointer + * to the next device in the uclass if any + * @return 0 if OK (found or not found), other -ve on error. If an error occurs + * it is still possible to move to the next device. + */ +int uclass_next_device_check(struct udevice **devp); + +/** + * uclass_resolve_seq() - Resolve a device's sequence number + * + * On entry dev->seq is -1, and dev->req_seq may be -1 (to allocate a + * sequence number automatically, or >= 0 to select a particular number. + * If the requested sequence number is in use, then this device will + * be allocated another one. + * + * Note that the device's seq value is not changed by this function. + * + * @dev: Device for which to allocate sequence number + * @return sequence number allocated, or -ve on error + */ +int uclass_resolve_seq(struct udevice *dev); + +/** + * 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 udevice * to hold the current device. Set to NULL when there + * are no more devices. + * @uc: uclass to scan + */ +#define uclass_foreach_dev(pos, uc) \ + list_for_each_entry(pos, &uc->dev_head, uclass_node) + +/** + * uclass_foreach_dev_safe() - Helper function to safely iteration through devs + * + * This creates a for() loop which works through the available devices in + * a uclass in order from start to end. Inside the loop, it is safe to remove + * @pos if required. + * + * @pos: struct udevice * to hold the current device. Set to NULL when there + * are no more devices. + * @next: struct udevice * to hold the next next + * @uc: uclass to scan + */ +#define uclass_foreach_dev_safe(pos, next, uc) \ + list_for_each_entry_safe(pos, next, &uc->dev_head, uclass_node) + +/** + * uclass_foreach_dev_probe() - Helper function to iteration through devices + * of given uclass + * + * This creates a for() loop which works through the available devices in + * a uclass in order from start to end. Devices are probed if necessary, + * and ready for use. + * + * @id: Uclass ID + * @dev: struct udevice * to hold the current device. Set to NULL when there + * are no more devices. + */ +#define uclass_foreach_dev_probe(id, dev) \ + for (int _ret = uclass_first_device_err(id, &dev); !_ret && dev; \ + _ret = uclass_next_device_err(&dev)) + +#endif diff --git a/include/dm/util.h b/include/dm/util.h new file mode 100644 index 0000000..348c2ac --- /dev/null +++ b/include/dm/util.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 Google, Inc + */ + +#ifndef __DM_UTIL_H +#define __DM_UTIL_H + +#ifdef CONFIG_DM_WARN +void dm_warn(const char *fmt, ...); +#else +static inline void dm_warn(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); + +/* Dump out a tree of all devices */ +void dm_dump_all(void); + +/* Dump out a list of uclasses and their devices */ +void dm_dump_uclass(void); + +#ifdef CONFIG_DEBUG_DEVRES +/* Dump out a list of device resources */ +void dm_dump_devres(void); +#else +static inline void dm_dump_devres(void) +{ +} +#endif + +/** + * Check if an of node should be or was bound before relocation. + * + * Devicetree nodes can be marked as needed to be bound + * in the loader stages via special devicetree properties. + * + * Before relocation this function can be used to check if nodes + * are required in either SPL or TPL stages. + * + * After relocation and jumping into the real U-Boot binary + * it is possible to determine if a node was bound in one of + * SPL/TPL stages. + * + * There are 4 settings currently in use + * - u-boot,dm-pre-proper: U-Boot proper pre-relocation only + * - u-boot,dm-pre-reloc: legacy and indicates any of TPL or SPL + * Existing platforms only use it to indicate nodes needed in + * SPL. Should probably be replaced by u-boot,dm-spl for + * existing platforms. + * - u-boot,dm-spl: SPL and U-Boot pre-relocation + * - u-boot,dm-tpl: TPL and U-Boot pre-relocation + * @node: of node + * + * Returns true if node is needed in SPL/TL, false otherwise. + */ +bool dm_ofnode_pre_reloc(ofnode node); + +#endif |