111f1cecaSGeorgi Djakov /* SPDX-License-Identifier: GPL-2.0 */
211f1cecaSGeorgi Djakov /*
311f1cecaSGeorgi Djakov  * Copyright (c) 2018, Linaro Ltd.
411f1cecaSGeorgi Djakov  * Author: Georgi Djakov <georgi.djakov@linaro.org>
511f1cecaSGeorgi Djakov  */
611f1cecaSGeorgi Djakov 
711f1cecaSGeorgi Djakov #ifndef __LINUX_INTERCONNECT_PROVIDER_H
811f1cecaSGeorgi Djakov #define __LINUX_INTERCONNECT_PROVIDER_H
911f1cecaSGeorgi Djakov 
1011f1cecaSGeorgi Djakov #include <linux/interconnect.h>
1111f1cecaSGeorgi Djakov 
1211f1cecaSGeorgi Djakov #define icc_units_to_bps(bw)  ((bw) * 1000ULL)
1311f1cecaSGeorgi Djakov 
1411f1cecaSGeorgi Djakov struct icc_node;
1587e3031bSGeorgi Djakov struct of_phandle_args;
1687e3031bSGeorgi Djakov 
1787e3031bSGeorgi Djakov /**
181521e22bSGeorgi Djakov  * struct icc_node_data - icc node data
191521e22bSGeorgi Djakov  *
201521e22bSGeorgi Djakov  * @node: icc node
211521e22bSGeorgi Djakov  * @tag: tag
221521e22bSGeorgi Djakov  */
231521e22bSGeorgi Djakov struct icc_node_data {
241521e22bSGeorgi Djakov 	struct icc_node *node;
251521e22bSGeorgi Djakov 	u32 tag;
261521e22bSGeorgi Djakov };
271521e22bSGeorgi Djakov 
281521e22bSGeorgi Djakov /**
2987e3031bSGeorgi Djakov  * struct icc_onecell_data - driver data for onecell interconnect providers
3087e3031bSGeorgi Djakov  *
3187e3031bSGeorgi Djakov  * @num_nodes: number of nodes in this device
3287e3031bSGeorgi Djakov  * @nodes: array of pointers to the nodes in this device
3387e3031bSGeorgi Djakov  */
3487e3031bSGeorgi Djakov struct icc_onecell_data {
3587e3031bSGeorgi Djakov 	unsigned int num_nodes;
36*dd4904f3SKees Cook 	struct icc_node *nodes[] __counted_by(num_nodes);
3787e3031bSGeorgi Djakov };
3887e3031bSGeorgi Djakov 
3987e3031bSGeorgi Djakov struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec,
4087e3031bSGeorgi Djakov 				      void *data);
4111f1cecaSGeorgi Djakov 
4211f1cecaSGeorgi Djakov /**
4311f1cecaSGeorgi Djakov  * struct icc_provider - interconnect provider (controller) entity that might
4411f1cecaSGeorgi Djakov  * provide multiple interconnect controls
4511f1cecaSGeorgi Djakov  *
4611f1cecaSGeorgi Djakov  * @provider_list: list of the registered interconnect providers
4711f1cecaSGeorgi Djakov  * @nodes: internal list of the interconnect provider nodes
4811f1cecaSGeorgi Djakov  * @set: pointer to device specific set operation function
4911f1cecaSGeorgi Djakov  * @aggregate: pointer to device specific aggregate operation function
50cbd5a9c2SGeorgi Djakov  * @pre_aggregate: pointer to device specific function that is called
51cbd5a9c2SGeorgi Djakov  *		   before the aggregation begins (optional)
52cc80d10dSGeorgi Djakov  * @get_bw: pointer to device specific function to get current bandwidth
5387e3031bSGeorgi Djakov  * @xlate: provider-specific callback for mapping nodes from phandle arguments
541521e22bSGeorgi Djakov  * @xlate_extended: vendor-specific callback for mapping node data from phandle arguments
5511f1cecaSGeorgi Djakov  * @dev: the device this interconnect provider belongs to
5611f1cecaSGeorgi Djakov  * @users: count of active users
5765461e26SArtur Świgoń  * @inter_set: whether inter-provider pairs will be configured with @set
5811f1cecaSGeorgi Djakov  * @data: pointer to private data
5911f1cecaSGeorgi Djakov  */
6011f1cecaSGeorgi Djakov struct icc_provider {
6111f1cecaSGeorgi Djakov 	struct list_head	provider_list;
6211f1cecaSGeorgi Djakov 	struct list_head	nodes;
6311f1cecaSGeorgi Djakov 	int (*set)(struct icc_node *src, struct icc_node *dst);
64127ab2ccSGeorgi Djakov 	int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw,
65127ab2ccSGeorgi Djakov 			 u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
66cbd5a9c2SGeorgi Djakov 	void (*pre_aggregate)(struct icc_node *node);
67cc80d10dSGeorgi Djakov 	int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak);
6887e3031bSGeorgi Djakov 	struct icc_node* (*xlate)(struct of_phandle_args *spec, void *data);
691521e22bSGeorgi Djakov 	struct icc_node_data* (*xlate_extended)(struct of_phandle_args *spec, void *data);
7011f1cecaSGeorgi Djakov 	struct device		*dev;
7111f1cecaSGeorgi Djakov 	int			users;
7265461e26SArtur Świgoń 	bool			inter_set;
7311f1cecaSGeorgi Djakov 	void			*data;
7411f1cecaSGeorgi Djakov };
7511f1cecaSGeorgi Djakov 
7611f1cecaSGeorgi Djakov /**
7711f1cecaSGeorgi Djakov  * struct icc_node - entity that is part of the interconnect topology
7811f1cecaSGeorgi Djakov  *
7911f1cecaSGeorgi Djakov  * @id: platform specific node id
8011f1cecaSGeorgi Djakov  * @name: node name used in debugfs
8111f1cecaSGeorgi Djakov  * @links: a list of targets pointing to where we can go next when traversing
8211f1cecaSGeorgi Djakov  * @num_links: number of links to other interconnect nodes
8311f1cecaSGeorgi Djakov  * @provider: points to the interconnect provider of this node
8411f1cecaSGeorgi Djakov  * @node_list: the list entry in the parent provider's "nodes" list
8511f1cecaSGeorgi Djakov  * @search_list: list used when walking the nodes graph
8611f1cecaSGeorgi Djakov  * @reverse: pointer to previous node when walking the nodes graph
8711f1cecaSGeorgi Djakov  * @is_traversed: flag that is used when walking the nodes graph
8811f1cecaSGeorgi Djakov  * @req_list: a list of QoS constraint requests associated with this node
8911f1cecaSGeorgi Djakov  * @avg_bw: aggregated value of average bandwidth requests from all consumers
9011f1cecaSGeorgi Djakov  * @peak_bw: aggregated value of peak bandwidth requests from all consumers
91b1d681d8SGeorgi Djakov  * @init_avg: average bandwidth value that is read from the hardware during init
92b1d681d8SGeorgi Djakov  * @init_peak: peak bandwidth value that is read from the hardware during init
9311f1cecaSGeorgi Djakov  * @data: pointer to private data
9411f1cecaSGeorgi Djakov  */
9511f1cecaSGeorgi Djakov struct icc_node {
9611f1cecaSGeorgi Djakov 	int			id;
9711f1cecaSGeorgi Djakov 	const char              *name;
9811f1cecaSGeorgi Djakov 	struct icc_node		**links;
9911f1cecaSGeorgi Djakov 	size_t			num_links;
10011f1cecaSGeorgi Djakov 
10111f1cecaSGeorgi Djakov 	struct icc_provider	*provider;
10211f1cecaSGeorgi Djakov 	struct list_head	node_list;
10311f1cecaSGeorgi Djakov 	struct list_head	search_list;
10411f1cecaSGeorgi Djakov 	struct icc_node		*reverse;
10511f1cecaSGeorgi Djakov 	u8			is_traversed:1;
10611f1cecaSGeorgi Djakov 	struct hlist_head	req_list;
10711f1cecaSGeorgi Djakov 	u32			avg_bw;
10811f1cecaSGeorgi Djakov 	u32			peak_bw;
109b1d681d8SGeorgi Djakov 	u32			init_avg;
110b1d681d8SGeorgi Djakov 	u32			init_peak;
11111f1cecaSGeorgi Djakov 	void			*data;
11211f1cecaSGeorgi Djakov };
11311f1cecaSGeorgi Djakov 
11411f1cecaSGeorgi Djakov #if IS_ENABLED(CONFIG_INTERCONNECT)
11511f1cecaSGeorgi Djakov 
1163172e4d2SGeorgi Djakov int icc_std_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
1173172e4d2SGeorgi Djakov 		      u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
11811f1cecaSGeorgi Djakov struct icc_node *icc_node_create(int id);
11911f1cecaSGeorgi Djakov void icc_node_destroy(int id);
12011f1cecaSGeorgi Djakov int icc_link_create(struct icc_node *node, const int dst_id);
12111f1cecaSGeorgi Djakov void icc_node_add(struct icc_node *node, struct icc_provider *provider);
12211f1cecaSGeorgi Djakov void icc_node_del(struct icc_node *node);
1233cce2c6fSGeorgi Djakov int icc_nodes_remove(struct icc_provider *provider);
124eb59eca0SJohan Hovold void icc_provider_init(struct icc_provider *provider);
125eb59eca0SJohan Hovold int icc_provider_register(struct icc_provider *provider);
126eb59eca0SJohan Hovold void icc_provider_deregister(struct icc_provider *provider);
1271521e22bSGeorgi Djakov struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec);
128b1d681d8SGeorgi Djakov void icc_sync_state(struct device *dev);
12911f1cecaSGeorgi Djakov 
13011f1cecaSGeorgi Djakov #else
13111f1cecaSGeorgi Djakov 
icc_std_aggregate(struct icc_node * node,u32 tag,u32 avg_bw,u32 peak_bw,u32 * agg_avg,u32 * agg_peak)1323172e4d2SGeorgi Djakov static inline int icc_std_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
1333172e4d2SGeorgi Djakov 				    u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
1343172e4d2SGeorgi Djakov {
1353172e4d2SGeorgi Djakov 	return -ENOTSUPP;
1363172e4d2SGeorgi Djakov }
1373172e4d2SGeorgi Djakov 
icc_node_create(int id)13811f1cecaSGeorgi Djakov static inline struct icc_node *icc_node_create(int id)
13911f1cecaSGeorgi Djakov {
14011f1cecaSGeorgi Djakov 	return ERR_PTR(-ENOTSUPP);
14111f1cecaSGeorgi Djakov }
14211f1cecaSGeorgi Djakov 
icc_node_destroy(int id)14312a400b0SGeorgi Djakov static inline void icc_node_destroy(int id)
14411f1cecaSGeorgi Djakov {
14511f1cecaSGeorgi Djakov }
14611f1cecaSGeorgi Djakov 
icc_link_create(struct icc_node * node,const int dst_id)14711f1cecaSGeorgi Djakov static inline int icc_link_create(struct icc_node *node, const int dst_id)
14811f1cecaSGeorgi Djakov {
14911f1cecaSGeorgi Djakov 	return -ENOTSUPP;
15011f1cecaSGeorgi Djakov }
15111f1cecaSGeorgi Djakov 
icc_node_add(struct icc_node * node,struct icc_provider * provider)15212a400b0SGeorgi Djakov static inline void icc_node_add(struct icc_node *node, struct icc_provider *provider)
15311f1cecaSGeorgi Djakov {
15411f1cecaSGeorgi Djakov }
15511f1cecaSGeorgi Djakov 
icc_node_del(struct icc_node * node)15612a400b0SGeorgi Djakov static inline void icc_node_del(struct icc_node *node)
15711f1cecaSGeorgi Djakov {
15811f1cecaSGeorgi Djakov }
15911f1cecaSGeorgi Djakov 
icc_nodes_remove(struct icc_provider * provider)1603cce2c6fSGeorgi Djakov static inline int icc_nodes_remove(struct icc_provider *provider)
1613cce2c6fSGeorgi Djakov {
1623cce2c6fSGeorgi Djakov 	return -ENOTSUPP;
1633cce2c6fSGeorgi Djakov }
1643cce2c6fSGeorgi Djakov 
icc_provider_init(struct icc_provider * provider)165eb59eca0SJohan Hovold static inline void icc_provider_init(struct icc_provider *provider) { }
166eb59eca0SJohan Hovold 
icc_provider_register(struct icc_provider * provider)167eb59eca0SJohan Hovold static inline int icc_provider_register(struct icc_provider *provider)
168eb59eca0SJohan Hovold {
169eb59eca0SJohan Hovold 	return -ENOTSUPP;
170eb59eca0SJohan Hovold }
171eb59eca0SJohan Hovold 
icc_provider_deregister(struct icc_provider * provider)172eb59eca0SJohan Hovold static inline void icc_provider_deregister(struct icc_provider *provider) { }
173eb59eca0SJohan Hovold 
of_icc_get_from_provider(struct of_phandle_args * spec)1741521e22bSGeorgi Djakov static inline struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec)
1758a307d36SArtur Świgoń {
1768a307d36SArtur Świgoń 	return ERR_PTR(-ENOTSUPP);
1778a307d36SArtur Świgoń }
1788a307d36SArtur Świgoń 
17911f1cecaSGeorgi Djakov #endif /* CONFIG_INTERCONNECT */
18011f1cecaSGeorgi Djakov 
18111f1cecaSGeorgi Djakov #endif /* __LINUX_INTERCONNECT_PROVIDER_H */
182