1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Interconnect framework driver for i.MX SoC 4 * 5 * Copyright (c) 2019, BayLibre 6 * Copyright (c) 2019-2020, NXP 7 * Author: Alexandre Bailon <abailon@baylibre.com> 8 * Author: Leonard Crestez <leonard.crestez@nxp.com> 9 */ 10 11 #include <linux/device.h> 12 #include <linux/interconnect-provider.h> 13 #include <linux/io.h> 14 #include <linux/module.h> 15 #include <linux/of.h> 16 #include <linux/of_platform.h> 17 #include <linux/platform_device.h> 18 #include <linux/pm_qos.h> 19 20 #include "imx.h" 21 22 /* private icc_node data */ 23 struct imx_icc_node { 24 const struct imx_icc_node_desc *desc; 25 const struct imx_icc_noc_setting *setting; 26 struct device *qos_dev; 27 struct dev_pm_qos_request qos_req; 28 struct imx_icc_provider *imx_provider; 29 }; 30 31 static int imx_icc_get_bw(struct icc_node *node, u32 *avg, u32 *peak) 32 { 33 *avg = 0; 34 *peak = 0; 35 36 return 0; 37 } 38 39 static int imx_icc_node_set(struct icc_node *node) 40 { 41 struct device *dev = node->provider->dev; 42 struct imx_icc_node *node_data = node->data; 43 void __iomem *base; 44 u32 prio; 45 u64 freq; 46 47 if (node_data->setting && node->peak_bw) { 48 base = node_data->setting->reg + node_data->imx_provider->noc_base; 49 if (node_data->setting->mode == IMX_NOC_MODE_FIXED) { 50 prio = node_data->setting->prio_level; 51 prio = PRIORITY_COMP_MARK | (prio << 8) | prio; 52 writel(prio, base + IMX_NOC_PRIO_REG); 53 writel(node_data->setting->mode, base + IMX_NOC_MODE_REG); 54 writel(node_data->setting->ext_control, base + IMX_NOC_EXT_CTL_REG); 55 dev_dbg(dev, "%s: mode: 0x%x, prio: 0x%x, ext_control: 0x%x\n", 56 node_data->desc->name, node_data->setting->mode, prio, 57 node_data->setting->ext_control); 58 } else if (node_data->setting->mode == IMX_NOC_MODE_UNCONFIGURED) { 59 dev_dbg(dev, "%s: mode not unconfigured\n", node_data->desc->name); 60 } else { 61 dev_info(dev, "%s: mode: %d not supported\n", 62 node_data->desc->name, node_data->setting->mode); 63 return -EOPNOTSUPP; 64 } 65 } 66 67 if (!node_data->qos_dev) 68 return 0; 69 70 freq = (node->avg_bw + node->peak_bw) * node_data->desc->adj->bw_mul; 71 do_div(freq, node_data->desc->adj->bw_div); 72 dev_dbg(dev, "node %s device %s avg_bw %ukBps peak_bw %ukBps min_freq %llukHz\n", 73 node->name, dev_name(node_data->qos_dev), 74 node->avg_bw, node->peak_bw, freq); 75 76 if (freq > S32_MAX) { 77 dev_err(dev, "%s can't request more than S32_MAX freq\n", 78 node->name); 79 return -ERANGE; 80 } 81 82 dev_pm_qos_update_request(&node_data->qos_req, freq); 83 84 return 0; 85 } 86 87 static int imx_icc_set(struct icc_node *src, struct icc_node *dst) 88 { 89 int ret; 90 91 ret = imx_icc_node_set(src); 92 if (ret) 93 return ret; 94 95 return imx_icc_node_set(dst); 96 } 97 98 /* imx_icc_node_destroy() - Destroy an imx icc_node, including private data */ 99 static void imx_icc_node_destroy(struct icc_node *node) 100 { 101 struct imx_icc_node *node_data = node->data; 102 int ret; 103 104 if (dev_pm_qos_request_active(&node_data->qos_req)) { 105 ret = dev_pm_qos_remove_request(&node_data->qos_req); 106 if (ret) 107 dev_warn(node->provider->dev, 108 "failed to remove qos request for %s\n", 109 dev_name(node_data->qos_dev)); 110 } 111 112 put_device(node_data->qos_dev); 113 icc_node_del(node); 114 icc_node_destroy(node->id); 115 } 116 117 static int imx_icc_node_init_qos(struct icc_provider *provider, 118 struct icc_node *node) 119 { 120 struct imx_icc_node *node_data = node->data; 121 const struct imx_icc_node_adj_desc *adj = node_data->desc->adj; 122 struct device *dev = provider->dev; 123 struct device_node *dn = NULL; 124 struct platform_device *pdev; 125 126 if (adj->main_noc) { 127 node_data->qos_dev = dev; 128 dev_dbg(dev, "icc node %s[%d] is main noc itself\n", 129 node->name, node->id); 130 } else { 131 dn = of_parse_phandle(dev->of_node, adj->phandle_name, 0); 132 if (!dn) { 133 dev_warn(dev, "Failed to parse %s\n", 134 adj->phandle_name); 135 return -ENODEV; 136 } 137 /* Allow scaling to be disabled on a per-node basis */ 138 if (!of_device_is_available(dn)) { 139 dev_warn(dev, "Missing property %s, skip scaling %s\n", 140 adj->phandle_name, node->name); 141 of_node_put(dn); 142 return 0; 143 } 144 145 pdev = of_find_device_by_node(dn); 146 of_node_put(dn); 147 if (!pdev) { 148 dev_warn(dev, "node %s[%d] missing device for %pOF\n", 149 node->name, node->id, dn); 150 return -EPROBE_DEFER; 151 } 152 node_data->qos_dev = &pdev->dev; 153 dev_dbg(dev, "node %s[%d] has device node %pOF\n", 154 node->name, node->id, dn); 155 } 156 157 return dev_pm_qos_add_request(node_data->qos_dev, 158 &node_data->qos_req, 159 DEV_PM_QOS_MIN_FREQUENCY, 0); 160 } 161 162 static struct icc_node *imx_icc_node_add(struct imx_icc_provider *imx_provider, 163 const struct imx_icc_node_desc *node_desc, 164 const struct imx_icc_noc_setting *setting) 165 { 166 struct icc_provider *provider = &imx_provider->provider; 167 struct device *dev = provider->dev; 168 struct imx_icc_node *node_data; 169 struct icc_node *node; 170 int ret; 171 172 node = icc_node_create(node_desc->id); 173 if (IS_ERR(node)) { 174 dev_err(dev, "failed to create node %d\n", node_desc->id); 175 return node; 176 } 177 178 if (node->data) { 179 dev_err(dev, "already created node %s id=%d\n", 180 node_desc->name, node_desc->id); 181 return ERR_PTR(-EEXIST); 182 } 183 184 node_data = devm_kzalloc(dev, sizeof(*node_data), GFP_KERNEL); 185 if (!node_data) { 186 icc_node_destroy(node->id); 187 return ERR_PTR(-ENOMEM); 188 } 189 190 node->name = node_desc->name; 191 node->data = node_data; 192 node_data->desc = node_desc; 193 node_data->setting = setting; 194 node_data->imx_provider = imx_provider; 195 icc_node_add(node, provider); 196 197 if (node_desc->adj) { 198 ret = imx_icc_node_init_qos(provider, node); 199 if (ret < 0) { 200 imx_icc_node_destroy(node); 201 return ERR_PTR(ret); 202 } 203 } 204 205 return node; 206 } 207 208 static void imx_icc_unregister_nodes(struct icc_provider *provider) 209 { 210 struct icc_node *node, *tmp; 211 212 list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) 213 imx_icc_node_destroy(node); 214 } 215 216 static int imx_icc_register_nodes(struct imx_icc_provider *imx_provider, 217 const struct imx_icc_node_desc *descs, 218 int count, 219 const struct imx_icc_noc_setting *settings) 220 { 221 struct icc_provider *provider = &imx_provider->provider; 222 struct icc_onecell_data *provider_data = provider->data; 223 int ret; 224 int i; 225 226 for (i = 0; i < count; i++) { 227 struct icc_node *node; 228 const struct imx_icc_node_desc *node_desc = &descs[i]; 229 size_t j; 230 231 node = imx_icc_node_add(imx_provider, node_desc, 232 settings ? &settings[node_desc->id] : NULL); 233 if (IS_ERR(node)) { 234 ret = dev_err_probe(provider->dev, PTR_ERR(node), 235 "failed to add %s\n", node_desc->name); 236 goto err; 237 } 238 provider_data->nodes[node->id] = node; 239 240 for (j = 0; j < node_desc->num_links; j++) { 241 ret = icc_link_create(node, node_desc->links[j]); 242 if (ret) { 243 dev_err(provider->dev, "failed to link node %d to %d: %d\n", 244 node->id, node_desc->links[j], ret); 245 goto err; 246 } 247 } 248 } 249 250 return 0; 251 252 err: 253 imx_icc_unregister_nodes(provider); 254 255 return ret; 256 } 257 258 static int get_max_node_id(struct imx_icc_node_desc *nodes, int nodes_count) 259 { 260 int i, ret = 0; 261 262 for (i = 0; i < nodes_count; ++i) 263 if (nodes[i].id > ret) 264 ret = nodes[i].id; 265 266 return ret; 267 } 268 269 int imx_icc_register(struct platform_device *pdev, 270 struct imx_icc_node_desc *nodes, int nodes_count, 271 struct imx_icc_noc_setting *settings) 272 { 273 struct device *dev = &pdev->dev; 274 struct icc_onecell_data *data; 275 struct imx_icc_provider *imx_provider; 276 struct icc_provider *provider; 277 int num_nodes; 278 int ret; 279 280 /* icc_onecell_data is indexed by node_id, unlike nodes param */ 281 num_nodes = get_max_node_id(nodes, nodes_count) + 1; 282 data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes), 283 GFP_KERNEL); 284 if (!data) 285 return -ENOMEM; 286 data->num_nodes = num_nodes; 287 288 imx_provider = devm_kzalloc(dev, sizeof(*imx_provider), GFP_KERNEL); 289 if (!imx_provider) 290 return -ENOMEM; 291 provider = &imx_provider->provider; 292 provider->set = imx_icc_set; 293 provider->get_bw = imx_icc_get_bw; 294 provider->aggregate = icc_std_aggregate; 295 provider->xlate = of_icc_xlate_onecell; 296 provider->data = data; 297 provider->dev = dev->parent; 298 platform_set_drvdata(pdev, imx_provider); 299 300 if (settings) { 301 imx_provider->noc_base = devm_of_iomap(dev, provider->dev->of_node, 0, NULL); 302 if (IS_ERR(imx_provider->noc_base)) { 303 ret = PTR_ERR(imx_provider->noc_base); 304 dev_err(dev, "Error mapping NoC: %d\n", ret); 305 return ret; 306 } 307 } 308 309 ret = icc_provider_add(provider); 310 if (ret) { 311 dev_err(dev, "error adding interconnect provider: %d\n", ret); 312 return ret; 313 } 314 315 ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings); 316 if (ret) 317 goto provider_del; 318 319 return 0; 320 321 provider_del: 322 icc_provider_del(provider); 323 return ret; 324 } 325 EXPORT_SYMBOL_GPL(imx_icc_register); 326 327 int imx_icc_unregister(struct platform_device *pdev) 328 { 329 struct imx_icc_provider *imx_provider = platform_get_drvdata(pdev); 330 331 imx_icc_unregister_nodes(&imx_provider->provider); 332 333 return icc_provider_del(&imx_provider->provider); 334 } 335 EXPORT_SYMBOL_GPL(imx_icc_unregister); 336 337 MODULE_LICENSE("GPL v2"); 338