diff options
| author | Tom Rini <[email protected]> | 2025-11-20 08:00:11 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-11-20 08:00:11 -0600 |
| commit | 8ff90aa64b730c3f511921d4ff79e9f64e625867 (patch) | |
| tree | e43ed96f7840d878bd9da89f3afdbd82eda2f5d9 /include | |
| parent | b8872deb4450b09586e28550c23d33a71084d94f (diff) | |
| parent | fb3db4aa8df2ae5093a5c1580b9cd5789c248de4 (diff) | |
Merge tag 'interconnect-next-20251120' of https://source.denx.de/u-boot/custodians/u-boot-snapdragon into next
- Qualcomm RPMh cmd_db_read_slave_id() & cmd_db_read_aux_data()
- Initial Interconnect implementation + Qualcomm RPMh support
Diffstat (limited to 'include')
| -rw-r--r-- | include/dm/uclass-id.h | 2 | ||||
| -rw-r--r-- | include/interconnect-uclass.h | 136 | ||||
| -rw-r--r-- | include/interconnect.h | 155 | ||||
| -rw-r--r-- | include/soc/qcom/cmd-db.h | 2 |
4 files changed, 295 insertions, 0 deletions
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index eb6416b5917..36b5d87c304 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -83,6 +83,8 @@ enum uclass_id { UCLASS_I3C, /* I3C bus */ UCLASS_IDE, /* IDE device */ UCLASS_IOMMU, /* IOMMU */ + UCLASS_INTERCONNECT, /* Interconnect */ + UCLASS_ICC_NODE, /* Interconnect Node */ UCLASS_IRQ, /* Interrupt controller */ UCLASS_KEYBOARD, /* Keyboard input device */ UCLASS_LED, /* Light-emitting diode (LED) */ diff --git a/include/interconnect-uclass.h b/include/interconnect-uclass.h new file mode 100644 index 00000000000..d942ddec41b --- /dev/null +++ b/include/interconnect-uclass.h @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2025 Linaro Limited + */ + +#ifndef _INTERCONNECT_UCLASS_H +#define _INTERCONNECT_UCLASS_H + +#include <interconnect.h> + +#define icc_units_to_bps(bw) ((bw) * 1000ULL) + +struct udevice; + +/** + * struct icc_req - constraints that are attached to each node + * + * @req_node: entry in list of requests for the particular @node + * @node: the interconnect node to which this constraint applies + * @enabled: indicates whether the path with this request is enabled + * @tag: path tag (optional) + * @avg_bw: an integer describing the average bandwidth in kBps + * @peak_bw: an integer describing the peak bandwidth in kBps + */ +struct icc_req { + struct hlist_node req_node; + struct icc_node *node; + bool enabled; + u32 tag; + u32 avg_bw; + u32 peak_bw; +}; + +/** + * struct icc_path - An interconnect path + * + * @dev: Device who requested the path + * @num_nodes: number of nodes (hops) in the path + * @reqs: array of the requests applicable to this path of nodes + */ +struct icc_path { + struct udevice *dev; + size_t num_nodes; + struct icc_req reqs[]; +}; + +/** + * struct icc_provider - interconnect provider (controller) entity that might + * provide multiple interconnect controls + * + * @inter_set: whether inter-provider pairs will be configured with @set + * @xlate_num_nodes: provider-specific nodes counts for mapping nodes from phandle arguments + * @xlate_nodes: provider-specific array for mapping nodes from phandle arguments + */ +struct icc_provider { + bool inter_set; + unsigned int xlate_num_nodes; + struct icc_node **xlate_nodes; +}; + +/** + * struct icc_node - entity that is part of the interconnect topology + * + * @dev: points to the interconnect provider of this node + * @links: a list of targets pointing to where we can go next when traversing + * @num_links: number of links to other interconnect nodes + * @users: count of active users + * @node_list: the list entry in the parent provider's "nodes" list + * @search_list: list used when walking the nodes graph + * @reverse: pointer to previous node when walking the nodes graph + * @is_traversed: flag that is used when walking the nodes graph + * @req_list: a list of QoS constraint requests associated with this node + * @avg_bw: aggregated value of average bandwidth requests from all consumers + * @peak_bw: aggregated value of peak bandwidth requests from all consumers + * @data: pointer to private data + */ +struct icc_node { + struct udevice *dev; + ulong *links; + size_t num_links; + int users; + + struct list_head node_list; + struct list_head search_list; + struct icc_node *reverse; + u8 is_traversed:1; + struct hlist_head req_list; + u32 avg_bw; + u32 peak_bw; + void *data; +}; + +/** + * struct interconnect_ops - Interconnect uclass operations + * + * @of_xlate: provider-specific callback for mapping nodes from phandle arguments + * @set: pointer to device specific set operation function + * @pre_aggregate: pointer to device specific function that is called + * before the aggregation begins (optional) + * @aggregate: pointer to device specific aggregate operation function + */ +struct interconnect_ops { + struct icc_node *(*of_xlate)(struct udevice *dev, + const struct ofnode_phandle_args *args); + int (*set)(struct icc_node *src, struct icc_node *dst); + void (*pre_aggregate)(struct icc_node *node); + int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw, + u32 peak_bw, u32 *agg_avg, u32 *agg_peak); +}; + +/** + * icc_node_create() - create a node + * + * @dev: Provider device + * @id: node id, can be a numeric ID or pointer casted to ulong + * @name: node name + * + * Return: icc_node pointer on success, or ERR_PTR() on error + */ +struct icc_node *icc_node_create(struct udevice *dev, + ulong id, const char *name); + +/** + * icc_link_create() - create a link between two nodes + * @node: source node id + * @dst_id: destination node id + * + * Create a link between two nodes. The nodes might belong to different + * interconnect providers and the @dst_id node might not exist, the link + * will be done at runtime in `icc_path_find()`. + * + * Return: 0 on success, or an error code otherwise + */ +int icc_link_create(struct icc_node *node, const ulong dst_id); + +#endif diff --git a/include/interconnect.h b/include/interconnect.h new file mode 100644 index 00000000000..11ed30d79d6 --- /dev/null +++ b/include/interconnect.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2025 Linaro Limited + */ + +#ifndef _INTERCONNECT_H +#define _INTERCONNECT_H + +#include <linux/errno.h> + +struct udevice; + +/* macros for converting to icc units */ +#define Bps_to_icc(x) ((x) / 1000) +#define kBps_to_icc(x) (x) +#define MBps_to_icc(x) ((x) * 1000) +#define GBps_to_icc(x) ((x) * 1000 * 1000) +#define bps_to_icc(x) (1) +#define kbps_to_icc(x) ((x) / 8 + ((x) % 8 ? 1 : 0)) +#define Mbps_to_icc(x) ((x) * 1000 / 8) +#define Gbps_to_icc(x) ((x) * 1000 * 1000 / 8) + +struct icc_path; + +/** + * of_icc_get - Get an Interconnect path from a DT node based on name + * + * This function will search for a path between two endpoints and return an + * icc_path handle on success. Use icc_put() to release constraints when they + * are not needed anymore. + * If the interconnect API is disabled, NULL is returned and the consumer + * drivers will still build. Drivers are free to handle this specifically, + * but they don't have to. + * + * @dev: The client device. + * @name: Name of the interconnect endpoint pair. + * Return: icc_path pointer on success or ERR_PTR() on error. NULL is returned + * when the API is disabled or the "interconnects" DT property is missing. + */ +#if CONFIG_IS_ENABLED(INTERCONNECT) +struct icc_path *of_icc_get(struct udevice *dev, const char *name); +#else +static inline +struct icc_path *of_icc_get(struct udevice *dev, const char *name) +{ + return NULL; +} +#endif + +/** + * of_icc_get - Get an Interconnect path from a DT node based on index + * + * This function will search for a path between two endpoints and return an + * icc_path handle on success. Use icc_put() to release constraints when they + * are not needed anymore. + * If the interconnect API is disabled, NULL is returned and the consumer + * drivers will still build. Drivers are free to handle this specifically, + * but they don't have to. + * + * @dev: The client device. + * @idx: Index of the interconnect endpoint pair. + * Return: icc_path pointer on success or ERR_PTR() on error. NULL is returned + * when the API is disabled or the "interconnects" DT property is missing. + */ +#if CONFIG_IS_ENABLED(INTERCONNECT) +struct icc_path *of_icc_get_by_index(struct udevice *dev, int idx); +#else +static inline +struct icc_path *of_icc_get_by_index(struct udevice *dev, int idx) +{ + return NULL; +} +#endif + +/** + * icc_put - release the reference to the Interconnect path. + * + * Use this function to release the constraints on a path when the path is + * no longer needed. The constraints will be re-aggregated. + * + * @path: An interconnect path + * Return: 0 if OK, or a negative error code. + */ +#if CONFIG_IS_ENABLED(INTERCONNECT) +int icc_put(struct icc_path *path); +#else +static inline int icc_put(struct icc_path *path) +{ + return 0; +} +#endif + +/** + * icc_enable - Enable an Interconnect path. + * + * This will enable all the endpoints in the path, using the + * bandwidth set by the `icc_set_bw()` call. Otherwise a zero + * bandwidth will be set. Usually used after a call to `icc_disable()`. + * + * @path: An interconnect path + * Return: 0 if OK, or a negative error code. -ENOSYS if not implemented. + */ +#if CONFIG_IS_ENABLED(INTERCONNECT) +int icc_enable(struct icc_path *path); +#else +static inline int icc_enable(struct icc_path *path) +{ + return -ENOSYS; +} +#endif + +/** + * icc_disable - Disable an Interconnect path. + * + * This will disable all the endpoints in the path, effectively setting + * a zero bandwidth. Calling `icc_enable()` will restore the bandwidth set + * by calling `icc_set_bw()`. + * + * @path: An interconnect path + * Return: 0 if OK, or a negative error code. -ENOSYS if not implemented. + */ +#if CONFIG_IS_ENABLED(INTERCONNECT) +int icc_disable(struct icc_path *path); +#else +static inline int icc_disable(struct icc_path *path) +{ + return -ENOSYS; +} +#endif + +/** + * icc_set_bw - set bandwidth constraints on an interconnect path. + * + * This function is used by an interconnect consumer to express its own needs + * in terms of bandwidth for a previously requested path between two endpoints. + * The requests are aggregated and each node is updated accordingly. The entire + * path is locked by a mutex to ensure that the set() is completed. + * The @path can be NULL when the "interconnects" DT properties is missing, + * which will mean that no constraints will be set. + * + * @path: An interconnect path + * @avg_bw: Average bandwidth request in kBps + * @peak_bw: Peak bandwidth in request kBps + * Return: 0 if OK, or a negative error code. -ENOSYS if not implemented. + */ +#if CONFIG_IS_ENABLED(INTERCONNECT) +int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw); +#else +static inline int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw) +{ + return -ENOSYS; +} +#endif + +#endif diff --git a/include/soc/qcom/cmd-db.h b/include/soc/qcom/cmd-db.h index 1190f2c22ca..16609ac9d78 100644 --- a/include/soc/qcom/cmd-db.h +++ b/include/soc/qcom/cmd-db.h @@ -21,6 +21,8 @@ enum cmd_db_hw_type { #if IS_ENABLED(CONFIG_QCOM_COMMAND_DB) u32 cmd_db_read_addr(const char *resource_id); +enum cmd_db_hw_type cmd_db_read_slave_id(const char *resource_id); +const void *cmd_db_read_aux_data(const char *resource_id, size_t *len); #else static inline u32 cmd_db_read_addr(const char *resource_id) |
