Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Interconnect framework driver for i.MX SoC
0004  *
0005  * Copyright (c) 2019, BayLibre
0006  * Copyright (c) 2019-2020, NXP
0007  * Author: Alexandre Bailon <abailon@baylibre.com>
0008  * Author: Leonard Crestez <leonard.crestez@nxp.com>
0009  */
0010 
0011 #include <linux/device.h>
0012 #include <linux/interconnect-provider.h>
0013 #include <linux/io.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/of_platform.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/pm_qos.h>
0019 
0020 #include "imx.h"
0021 
0022 /* private icc_node data */
0023 struct imx_icc_node {
0024     const struct imx_icc_node_desc *desc;
0025     const struct imx_icc_noc_setting *setting;
0026     struct device *qos_dev;
0027     struct dev_pm_qos_request qos_req;
0028     struct imx_icc_provider *imx_provider;
0029 };
0030 
0031 static int imx_icc_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
0032 {
0033     *avg = 0;
0034     *peak = 0;
0035 
0036     return 0;
0037 }
0038 
0039 static int imx_icc_node_set(struct icc_node *node)
0040 {
0041     struct device *dev = node->provider->dev;
0042     struct imx_icc_node *node_data = node->data;
0043     void __iomem *base;
0044     u32 prio;
0045     u64 freq;
0046 
0047     if (node_data->setting && node->peak_bw) {
0048         base = node_data->setting->reg + node_data->imx_provider->noc_base;
0049         if (node_data->setting->mode == IMX_NOC_MODE_FIXED) {
0050             prio = node_data->setting->prio_level;
0051             prio = PRIORITY_COMP_MARK | (prio << 8) | prio;
0052             writel(prio, base + IMX_NOC_PRIO_REG);
0053             writel(node_data->setting->mode, base + IMX_NOC_MODE_REG);
0054             writel(node_data->setting->ext_control, base + IMX_NOC_EXT_CTL_REG);
0055             dev_dbg(dev, "%s: mode: 0x%x, prio: 0x%x, ext_control: 0x%x\n",
0056                 node_data->desc->name, node_data->setting->mode, prio,
0057                 node_data->setting->ext_control);
0058         } else if (node_data->setting->mode == IMX_NOC_MODE_UNCONFIGURED) {
0059             dev_dbg(dev, "%s: mode not unconfigured\n", node_data->desc->name);
0060         } else {
0061             dev_info(dev, "%s: mode: %d not supported\n",
0062                  node_data->desc->name, node_data->setting->mode);
0063             return -EOPNOTSUPP;
0064         }
0065     }
0066 
0067     if (!node_data->qos_dev)
0068         return 0;
0069 
0070     freq = (node->avg_bw + node->peak_bw) * node_data->desc->adj->bw_mul;
0071     do_div(freq, node_data->desc->adj->bw_div);
0072     dev_dbg(dev, "node %s device %s avg_bw %ukBps peak_bw %ukBps min_freq %llukHz\n",
0073         node->name, dev_name(node_data->qos_dev),
0074         node->avg_bw, node->peak_bw, freq);
0075 
0076     if (freq > S32_MAX) {
0077         dev_err(dev, "%s can't request more than S32_MAX freq\n",
0078                 node->name);
0079         return -ERANGE;
0080     }
0081 
0082     dev_pm_qos_update_request(&node_data->qos_req, freq);
0083 
0084     return 0;
0085 }
0086 
0087 static int imx_icc_set(struct icc_node *src, struct icc_node *dst)
0088 {
0089     int ret;
0090 
0091     ret = imx_icc_node_set(src);
0092     if (ret)
0093         return ret;
0094 
0095     return imx_icc_node_set(dst);
0096 }
0097 
0098 /* imx_icc_node_destroy() - Destroy an imx icc_node, including private data */
0099 static void imx_icc_node_destroy(struct icc_node *node)
0100 {
0101     struct imx_icc_node *node_data = node->data;
0102     int ret;
0103 
0104     if (dev_pm_qos_request_active(&node_data->qos_req)) {
0105         ret = dev_pm_qos_remove_request(&node_data->qos_req);
0106         if (ret)
0107             dev_warn(node->provider->dev,
0108                  "failed to remove qos request for %s\n",
0109                  dev_name(node_data->qos_dev));
0110     }
0111 
0112     put_device(node_data->qos_dev);
0113     icc_node_del(node);
0114     icc_node_destroy(node->id);
0115 }
0116 
0117 static int imx_icc_node_init_qos(struct icc_provider *provider,
0118                  struct icc_node *node)
0119 {
0120     struct imx_icc_node *node_data = node->data;
0121     const struct imx_icc_node_adj_desc *adj = node_data->desc->adj;
0122     struct device *dev = provider->dev;
0123     struct device_node *dn = NULL;
0124     struct platform_device *pdev;
0125 
0126     if (adj->main_noc) {
0127         node_data->qos_dev = dev;
0128         dev_dbg(dev, "icc node %s[%d] is main noc itself\n",
0129             node->name, node->id);
0130     } else {
0131         dn = of_parse_phandle(dev->of_node, adj->phandle_name, 0);
0132         if (!dn) {
0133             dev_warn(dev, "Failed to parse %s\n",
0134                  adj->phandle_name);
0135             return -ENODEV;
0136         }
0137         /* Allow scaling to be disabled on a per-node basis */
0138         if (!of_device_is_available(dn)) {
0139             dev_warn(dev, "Missing property %s, skip scaling %s\n",
0140                  adj->phandle_name, node->name);
0141             of_node_put(dn);
0142             return 0;
0143         }
0144 
0145         pdev = of_find_device_by_node(dn);
0146         of_node_put(dn);
0147         if (!pdev) {
0148             dev_warn(dev, "node %s[%d] missing device for %pOF\n",
0149                  node->name, node->id, dn);
0150             return -EPROBE_DEFER;
0151         }
0152         node_data->qos_dev = &pdev->dev;
0153         dev_dbg(dev, "node %s[%d] has device node %pOF\n",
0154             node->name, node->id, dn);
0155     }
0156 
0157     return dev_pm_qos_add_request(node_data->qos_dev,
0158                       &node_data->qos_req,
0159                       DEV_PM_QOS_MIN_FREQUENCY, 0);
0160 }
0161 
0162 static struct icc_node *imx_icc_node_add(struct imx_icc_provider *imx_provider,
0163                      const struct imx_icc_node_desc *node_desc,
0164                      const struct imx_icc_noc_setting *setting)
0165 {
0166     struct icc_provider *provider = &imx_provider->provider;
0167     struct device *dev = provider->dev;
0168     struct imx_icc_node *node_data;
0169     struct icc_node *node;
0170     int ret;
0171 
0172     node = icc_node_create(node_desc->id);
0173     if (IS_ERR(node)) {
0174         dev_err(dev, "failed to create node %d\n", node_desc->id);
0175         return node;
0176     }
0177 
0178     if (node->data) {
0179         dev_err(dev, "already created node %s id=%d\n",
0180             node_desc->name, node_desc->id);
0181         return ERR_PTR(-EEXIST);
0182     }
0183 
0184     node_data = devm_kzalloc(dev, sizeof(*node_data), GFP_KERNEL);
0185     if (!node_data) {
0186         icc_node_destroy(node->id);
0187         return ERR_PTR(-ENOMEM);
0188     }
0189 
0190     node->name = node_desc->name;
0191     node->data = node_data;
0192     node_data->desc = node_desc;
0193     node_data->setting = setting;
0194     node_data->imx_provider = imx_provider;
0195     icc_node_add(node, provider);
0196 
0197     if (node_desc->adj) {
0198         ret = imx_icc_node_init_qos(provider, node);
0199         if (ret < 0) {
0200             imx_icc_node_destroy(node);
0201             return ERR_PTR(ret);
0202         }
0203     }
0204 
0205     return node;
0206 }
0207 
0208 static void imx_icc_unregister_nodes(struct icc_provider *provider)
0209 {
0210     struct icc_node *node, *tmp;
0211 
0212     list_for_each_entry_safe(node, tmp, &provider->nodes, node_list)
0213         imx_icc_node_destroy(node);
0214 }
0215 
0216 static int imx_icc_register_nodes(struct imx_icc_provider *imx_provider,
0217                   const struct imx_icc_node_desc *descs,
0218                   int count,
0219                   const struct imx_icc_noc_setting *settings)
0220 {
0221     struct icc_provider *provider = &imx_provider->provider;
0222     struct icc_onecell_data *provider_data = provider->data;
0223     int ret;
0224     int i;
0225 
0226     for (i = 0; i < count; i++) {
0227         struct icc_node *node;
0228         const struct imx_icc_node_desc *node_desc = &descs[i];
0229         size_t j;
0230 
0231         node = imx_icc_node_add(imx_provider, node_desc,
0232                     settings ? &settings[node_desc->id] : NULL);
0233         if (IS_ERR(node)) {
0234             ret = dev_err_probe(provider->dev, PTR_ERR(node),
0235                         "failed to add %s\n", node_desc->name);
0236             goto err;
0237         }
0238         provider_data->nodes[node->id] = node;
0239 
0240         for (j = 0; j < node_desc->num_links; j++) {
0241             ret = icc_link_create(node, node_desc->links[j]);
0242             if (ret) {
0243                 dev_err(provider->dev, "failed to link node %d to %d: %d\n",
0244                     node->id, node_desc->links[j], ret);
0245                 goto err;
0246             }
0247         }
0248     }
0249 
0250     return 0;
0251 
0252 err:
0253     imx_icc_unregister_nodes(provider);
0254 
0255     return ret;
0256 }
0257 
0258 static int get_max_node_id(struct imx_icc_node_desc *nodes, int nodes_count)
0259 {
0260     int i, ret = 0;
0261 
0262     for (i = 0; i < nodes_count; ++i)
0263         if (nodes[i].id > ret)
0264             ret = nodes[i].id;
0265 
0266     return ret;
0267 }
0268 
0269 int imx_icc_register(struct platform_device *pdev,
0270              struct imx_icc_node_desc *nodes, int nodes_count,
0271              struct imx_icc_noc_setting *settings)
0272 {
0273     struct device *dev = &pdev->dev;
0274     struct icc_onecell_data *data;
0275     struct imx_icc_provider *imx_provider;
0276     struct icc_provider *provider;
0277     int num_nodes;
0278     int ret;
0279 
0280     /* icc_onecell_data is indexed by node_id, unlike nodes param */
0281     num_nodes = get_max_node_id(nodes, nodes_count) + 1;
0282     data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
0283                 GFP_KERNEL);
0284     if (!data)
0285         return -ENOMEM;
0286     data->num_nodes = num_nodes;
0287 
0288     imx_provider = devm_kzalloc(dev, sizeof(*imx_provider), GFP_KERNEL);
0289     if (!imx_provider)
0290         return -ENOMEM;
0291     provider = &imx_provider->provider;
0292     provider->set = imx_icc_set;
0293     provider->get_bw = imx_icc_get_bw;
0294     provider->aggregate = icc_std_aggregate;
0295     provider->xlate = of_icc_xlate_onecell;
0296     provider->data = data;
0297     provider->dev = dev->parent;
0298     platform_set_drvdata(pdev, imx_provider);
0299 
0300     if (settings) {
0301         imx_provider->noc_base = devm_of_iomap(dev, provider->dev->of_node, 0, NULL);
0302         if (IS_ERR(imx_provider->noc_base)) {
0303             ret = PTR_ERR(imx_provider->noc_base);
0304             dev_err(dev, "Error mapping NoC: %d\n", ret);
0305             return ret;
0306         }
0307     }
0308 
0309     ret = icc_provider_add(provider);
0310     if (ret) {
0311         dev_err(dev, "error adding interconnect provider: %d\n", ret);
0312         return ret;
0313     }
0314 
0315     ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings);
0316     if (ret)
0317         goto provider_del;
0318 
0319     return 0;
0320 
0321 provider_del:
0322     icc_provider_del(provider);
0323     return ret;
0324 }
0325 EXPORT_SYMBOL_GPL(imx_icc_register);
0326 
0327 int imx_icc_unregister(struct platform_device *pdev)
0328 {
0329     struct imx_icc_provider *imx_provider = platform_get_drvdata(pdev);
0330 
0331     imx_icc_unregister_nodes(&imx_provider->provider);
0332 
0333     return icc_provider_del(&imx_provider->provider);
0334 }
0335 EXPORT_SYMBOL_GPL(imx_icc_unregister);
0336 
0337 MODULE_LICENSE("GPL v2");