0001
0002
0003
0004
0005
0006
0007
0008
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
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
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
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
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");