xref: /linux/drivers/interconnect/bulk.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1b41b0ce5SGeorgi Djakov // SPDX-License-Identifier: GPL-2.0
2b41b0ce5SGeorgi Djakov 
3b41b0ce5SGeorgi Djakov #include <linux/interconnect-provider.h>
4b41b0ce5SGeorgi Djakov #include <linux/device.h>
5b41b0ce5SGeorgi Djakov #include <linux/export.h>
6b41b0ce5SGeorgi Djakov 
7b41b0ce5SGeorgi Djakov /**
8b41b0ce5SGeorgi Djakov  * of_icc_bulk_get() - get interconnect paths
9b41b0ce5SGeorgi Djakov  * @dev: the device requesting the path
10b41b0ce5SGeorgi Djakov  * @num_paths: the number of icc_bulk_data
11b41b0ce5SGeorgi Djakov  * @paths: the table with the paths we want to get
12b41b0ce5SGeorgi Djakov  *
13b41b0ce5SGeorgi Djakov  * Returns 0 on success or negative errno otherwise.
14b41b0ce5SGeorgi Djakov  */
of_icc_bulk_get(struct device * dev,int num_paths,struct icc_bulk_data * paths)15b41b0ce5SGeorgi Djakov int __must_check of_icc_bulk_get(struct device *dev, int num_paths,
16b41b0ce5SGeorgi Djakov 				 struct icc_bulk_data *paths)
17b41b0ce5SGeorgi Djakov {
18b41b0ce5SGeorgi Djakov 	int ret, i;
19b41b0ce5SGeorgi Djakov 
20b41b0ce5SGeorgi Djakov 	for (i = 0; i < num_paths; i++) {
21b41b0ce5SGeorgi Djakov 		paths[i].path = of_icc_get(dev, paths[i].name);
22b41b0ce5SGeorgi Djakov 		if (IS_ERR(paths[i].path)) {
23b41b0ce5SGeorgi Djakov 			ret = PTR_ERR(paths[i].path);
24b41b0ce5SGeorgi Djakov 			if (ret != -EPROBE_DEFER)
25b41b0ce5SGeorgi Djakov 				dev_err(dev, "of_icc_get() failed on path %s (%d)\n",
26b41b0ce5SGeorgi Djakov 					paths[i].name, ret);
27b41b0ce5SGeorgi Djakov 			paths[i].path = NULL;
28b41b0ce5SGeorgi Djakov 			goto err;
29b41b0ce5SGeorgi Djakov 		}
30b41b0ce5SGeorgi Djakov 	}
31b41b0ce5SGeorgi Djakov 
32b41b0ce5SGeorgi Djakov 	return 0;
33b41b0ce5SGeorgi Djakov 
34b41b0ce5SGeorgi Djakov err:
35b41b0ce5SGeorgi Djakov 	icc_bulk_put(i, paths);
36b41b0ce5SGeorgi Djakov 
37b41b0ce5SGeorgi Djakov 	return ret;
38b41b0ce5SGeorgi Djakov }
39b41b0ce5SGeorgi Djakov EXPORT_SYMBOL_GPL(of_icc_bulk_get);
40b41b0ce5SGeorgi Djakov 
41b41b0ce5SGeorgi Djakov /**
42b41b0ce5SGeorgi Djakov  * icc_bulk_put() - put a list of interconnect paths
43b41b0ce5SGeorgi Djakov  * @num_paths: the number of icc_bulk_data
44b41b0ce5SGeorgi Djakov  * @paths: the icc_bulk_data table with the paths being put
45b41b0ce5SGeorgi Djakov  */
icc_bulk_put(int num_paths,struct icc_bulk_data * paths)46b41b0ce5SGeorgi Djakov void icc_bulk_put(int num_paths, struct icc_bulk_data *paths)
47b41b0ce5SGeorgi Djakov {
48b41b0ce5SGeorgi Djakov 	while (--num_paths >= 0) {
49b41b0ce5SGeorgi Djakov 		icc_put(paths[num_paths].path);
50b41b0ce5SGeorgi Djakov 		paths[num_paths].path = NULL;
51b41b0ce5SGeorgi Djakov 	}
52b41b0ce5SGeorgi Djakov }
53b41b0ce5SGeorgi Djakov EXPORT_SYMBOL_GPL(icc_bulk_put);
54b41b0ce5SGeorgi Djakov 
55b41b0ce5SGeorgi Djakov /**
56491aef7cSGeorgi Djakov  * icc_bulk_set_bw() - set bandwidth to a set of paths
57b41b0ce5SGeorgi Djakov  * @num_paths: the number of icc_bulk_data
58b41b0ce5SGeorgi Djakov  * @paths: the icc_bulk_data table containing the paths and bandwidth
59b41b0ce5SGeorgi Djakov  *
60b41b0ce5SGeorgi Djakov  * Returns 0 on success or negative errno otherwise.
61b41b0ce5SGeorgi Djakov  */
icc_bulk_set_bw(int num_paths,const struct icc_bulk_data * paths)62b41b0ce5SGeorgi Djakov int icc_bulk_set_bw(int num_paths, const struct icc_bulk_data *paths)
63b41b0ce5SGeorgi Djakov {
64b41b0ce5SGeorgi Djakov 	int ret = 0;
65b41b0ce5SGeorgi Djakov 	int i;
66b41b0ce5SGeorgi Djakov 
67b41b0ce5SGeorgi Djakov 	for (i = 0; i < num_paths; i++) {
68b41b0ce5SGeorgi Djakov 		ret = icc_set_bw(paths[i].path, paths[i].avg_bw, paths[i].peak_bw);
69b41b0ce5SGeorgi Djakov 		if (ret) {
70b41b0ce5SGeorgi Djakov 			pr_err("icc_set_bw() failed on path %s (%d)\n", paths[i].name, ret);
71b41b0ce5SGeorgi Djakov 			return ret;
72b41b0ce5SGeorgi Djakov 		}
73b41b0ce5SGeorgi Djakov 	}
74b41b0ce5SGeorgi Djakov 
75b41b0ce5SGeorgi Djakov 	return ret;
76b41b0ce5SGeorgi Djakov }
77b41b0ce5SGeorgi Djakov EXPORT_SYMBOL_GPL(icc_bulk_set_bw);
78b41b0ce5SGeorgi Djakov 
79b41b0ce5SGeorgi Djakov /**
80b41b0ce5SGeorgi Djakov  * icc_bulk_enable() - enable a previously disabled set of paths
81b41b0ce5SGeorgi Djakov  * @num_paths: the number of icc_bulk_data
82b41b0ce5SGeorgi Djakov  * @paths: the icc_bulk_data table containing the paths and bandwidth
83b41b0ce5SGeorgi Djakov  *
84b41b0ce5SGeorgi Djakov  * Returns 0 on success or negative errno otherwise.
85b41b0ce5SGeorgi Djakov  */
icc_bulk_enable(int num_paths,const struct icc_bulk_data * paths)86b41b0ce5SGeorgi Djakov int icc_bulk_enable(int num_paths, const struct icc_bulk_data *paths)
87b41b0ce5SGeorgi Djakov {
88b41b0ce5SGeorgi Djakov 	int ret, i;
89b41b0ce5SGeorgi Djakov 
90b41b0ce5SGeorgi Djakov 	for (i = 0; i < num_paths; i++) {
91b41b0ce5SGeorgi Djakov 		ret = icc_enable(paths[i].path);
92b41b0ce5SGeorgi Djakov 		if (ret) {
93b41b0ce5SGeorgi Djakov 			pr_err("icc_enable() failed on path %s (%d)\n", paths[i].name, ret);
94b41b0ce5SGeorgi Djakov 			goto err;
95b41b0ce5SGeorgi Djakov 		}
96b41b0ce5SGeorgi Djakov 	}
97b41b0ce5SGeorgi Djakov 
98b41b0ce5SGeorgi Djakov 	return 0;
99b41b0ce5SGeorgi Djakov 
100b41b0ce5SGeorgi Djakov err:
101b41b0ce5SGeorgi Djakov 	icc_bulk_disable(i, paths);
102b41b0ce5SGeorgi Djakov 
103b41b0ce5SGeorgi Djakov 	return ret;
104b41b0ce5SGeorgi Djakov }
105b41b0ce5SGeorgi Djakov EXPORT_SYMBOL_GPL(icc_bulk_enable);
106b41b0ce5SGeorgi Djakov 
107b41b0ce5SGeorgi Djakov /**
108b41b0ce5SGeorgi Djakov  * icc_bulk_disable() - disable a set of interconnect paths
109b41b0ce5SGeorgi Djakov  * @num_paths: the number of icc_bulk_data
110b41b0ce5SGeorgi Djakov  * @paths: the icc_bulk_data table containing the paths and bandwidth
111b41b0ce5SGeorgi Djakov  */
icc_bulk_disable(int num_paths,const struct icc_bulk_data * paths)112b41b0ce5SGeorgi Djakov void icc_bulk_disable(int num_paths, const struct icc_bulk_data *paths)
113b41b0ce5SGeorgi Djakov {
114b41b0ce5SGeorgi Djakov 	while (--num_paths >= 0)
115b41b0ce5SGeorgi Djakov 		icc_disable(paths[num_paths].path);
116b41b0ce5SGeorgi Djakov }
117b41b0ce5SGeorgi Djakov EXPORT_SYMBOL_GPL(icc_bulk_disable);
118*2fcfa72fSPeng Fan 
119*2fcfa72fSPeng Fan struct icc_bulk_devres {
120*2fcfa72fSPeng Fan 	struct icc_bulk_data *paths;
121*2fcfa72fSPeng Fan 	int num_paths;
122*2fcfa72fSPeng Fan };
123*2fcfa72fSPeng Fan 
devm_icc_bulk_release(struct device * dev,void * res)124*2fcfa72fSPeng Fan static void devm_icc_bulk_release(struct device *dev, void *res)
125*2fcfa72fSPeng Fan {
126*2fcfa72fSPeng Fan 	struct icc_bulk_devres *devres = res;
127*2fcfa72fSPeng Fan 
128*2fcfa72fSPeng Fan 	icc_bulk_put(devres->num_paths, devres->paths);
129*2fcfa72fSPeng Fan }
130*2fcfa72fSPeng Fan 
131*2fcfa72fSPeng Fan /**
132*2fcfa72fSPeng Fan  * devm_of_icc_bulk_get() - resource managed of_icc_bulk_get
133*2fcfa72fSPeng Fan  * @dev: the device requesting the path
134*2fcfa72fSPeng Fan  * @num_paths: the number of icc_bulk_data
135*2fcfa72fSPeng Fan  * @paths: the table with the paths we want to get
136*2fcfa72fSPeng Fan  *
137*2fcfa72fSPeng Fan  * Returns 0 on success or negative errno otherwise.
138*2fcfa72fSPeng Fan  */
devm_of_icc_bulk_get(struct device * dev,int num_paths,struct icc_bulk_data * paths)139*2fcfa72fSPeng Fan int devm_of_icc_bulk_get(struct device *dev, int num_paths, struct icc_bulk_data *paths)
140*2fcfa72fSPeng Fan {
141*2fcfa72fSPeng Fan 	struct icc_bulk_devres *devres;
142*2fcfa72fSPeng Fan 	int ret;
143*2fcfa72fSPeng Fan 
144*2fcfa72fSPeng Fan 	devres = devres_alloc(devm_icc_bulk_release, sizeof(*devres), GFP_KERNEL);
145*2fcfa72fSPeng Fan 	if (!devres)
146*2fcfa72fSPeng Fan 		return -ENOMEM;
147*2fcfa72fSPeng Fan 
148*2fcfa72fSPeng Fan 	ret = of_icc_bulk_get(dev, num_paths, paths);
149*2fcfa72fSPeng Fan 	if (!ret) {
150*2fcfa72fSPeng Fan 		devres->paths = paths;
151*2fcfa72fSPeng Fan 		devres->num_paths = num_paths;
152*2fcfa72fSPeng Fan 		devres_add(dev, devres);
153*2fcfa72fSPeng Fan 	} else {
154*2fcfa72fSPeng Fan 		devres_free(devres);
155*2fcfa72fSPeng Fan 	}
156*2fcfa72fSPeng Fan 
157*2fcfa72fSPeng Fan 	return ret;
158*2fcfa72fSPeng Fan }
159*2fcfa72fSPeng Fan EXPORT_SYMBOL_GPL(devm_of_icc_bulk_get);
160