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