icc-rpm.c (11016B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2020 Linaro Ltd 4 */ 5 6#include <linux/clk.h> 7#include <linux/device.h> 8#include <linux/interconnect-provider.h> 9#include <linux/io.h> 10#include <linux/module.h> 11#include <linux/of_device.h> 12#include <linux/of_platform.h> 13#include <linux/platform_device.h> 14#include <linux/pm_domain.h> 15#include <linux/regmap.h> 16#include <linux/slab.h> 17 18#include "smd-rpm.h" 19#include "icc-rpm.h" 20 21/* QNOC QoS */ 22#define QNOC_QOS_MCTL_LOWn_ADDR(n) (0x8 + (n * 0x1000)) 23#define QNOC_QOS_MCTL_DFLT_PRIO_MASK 0x70 24#define QNOC_QOS_MCTL_DFLT_PRIO_SHIFT 4 25#define QNOC_QOS_MCTL_URGFWD_EN_MASK 0x8 26#define QNOC_QOS_MCTL_URGFWD_EN_SHIFT 3 27 28/* BIMC QoS */ 29#define M_BKE_REG_BASE(n) (0x300 + (0x4000 * n)) 30#define M_BKE_EN_ADDR(n) (M_BKE_REG_BASE(n)) 31#define M_BKE_HEALTH_CFG_ADDR(i, n) (M_BKE_REG_BASE(n) + 0x40 + (0x4 * i)) 32 33#define M_BKE_HEALTH_CFG_LIMITCMDS_MASK 0x80000000 34#define M_BKE_HEALTH_CFG_AREQPRIO_MASK 0x300 35#define M_BKE_HEALTH_CFG_PRIOLVL_MASK 0x3 36#define M_BKE_HEALTH_CFG_AREQPRIO_SHIFT 0x8 37#define M_BKE_HEALTH_CFG_LIMITCMDS_SHIFT 0x1f 38 39#define M_BKE_EN_EN_BMASK 0x1 40 41/* NoC QoS */ 42#define NOC_QOS_PRIORITYn_ADDR(n) (0x8 + (n * 0x1000)) 43#define NOC_QOS_PRIORITY_P1_MASK 0xc 44#define NOC_QOS_PRIORITY_P0_MASK 0x3 45#define NOC_QOS_PRIORITY_P1_SHIFT 0x2 46 47#define NOC_QOS_MODEn_ADDR(n) (0xc + (n * 0x1000)) 48#define NOC_QOS_MODEn_MASK 0x3 49 50static int qcom_icc_set_qnoc_qos(struct icc_node *src, u64 max_bw) 51{ 52 struct icc_provider *provider = src->provider; 53 struct qcom_icc_provider *qp = to_qcom_provider(provider); 54 struct qcom_icc_node *qn = src->data; 55 struct qcom_icc_qos *qos = &qn->qos; 56 int rc; 57 58 rc = regmap_update_bits(qp->regmap, 59 qp->qos_offset + QNOC_QOS_MCTL_LOWn_ADDR(qos->qos_port), 60 QNOC_QOS_MCTL_DFLT_PRIO_MASK, 61 qos->areq_prio << QNOC_QOS_MCTL_DFLT_PRIO_SHIFT); 62 if (rc) 63 return rc; 64 65 return regmap_update_bits(qp->regmap, 66 qp->qos_offset + QNOC_QOS_MCTL_LOWn_ADDR(qos->qos_port), 67 QNOC_QOS_MCTL_URGFWD_EN_MASK, 68 !!qos->urg_fwd_en << QNOC_QOS_MCTL_URGFWD_EN_SHIFT); 69} 70 71static int qcom_icc_bimc_set_qos_health(struct qcom_icc_provider *qp, 72 struct qcom_icc_qos *qos, 73 int regnum) 74{ 75 u32 val; 76 u32 mask; 77 78 val = qos->prio_level; 79 mask = M_BKE_HEALTH_CFG_PRIOLVL_MASK; 80 81 val |= qos->areq_prio << M_BKE_HEALTH_CFG_AREQPRIO_SHIFT; 82 mask |= M_BKE_HEALTH_CFG_AREQPRIO_MASK; 83 84 /* LIMITCMDS is not present on M_BKE_HEALTH_3 */ 85 if (regnum != 3) { 86 val |= qos->limit_commands << M_BKE_HEALTH_CFG_LIMITCMDS_SHIFT; 87 mask |= M_BKE_HEALTH_CFG_LIMITCMDS_MASK; 88 } 89 90 return regmap_update_bits(qp->regmap, 91 qp->qos_offset + M_BKE_HEALTH_CFG_ADDR(regnum, qos->qos_port), 92 mask, val); 93} 94 95static int qcom_icc_set_bimc_qos(struct icc_node *src, u64 max_bw) 96{ 97 struct qcom_icc_provider *qp; 98 struct qcom_icc_node *qn; 99 struct icc_provider *provider; 100 u32 mode = NOC_QOS_MODE_BYPASS; 101 u32 val = 0; 102 int i, rc = 0; 103 104 qn = src->data; 105 provider = src->provider; 106 qp = to_qcom_provider(provider); 107 108 if (qn->qos.qos_mode != NOC_QOS_MODE_INVALID) 109 mode = qn->qos.qos_mode; 110 111 /* QoS Priority: The QoS Health parameters are getting considered 112 * only if we are NOT in Bypass Mode. 113 */ 114 if (mode != NOC_QOS_MODE_BYPASS) { 115 for (i = 3; i >= 0; i--) { 116 rc = qcom_icc_bimc_set_qos_health(qp, 117 &qn->qos, i); 118 if (rc) 119 return rc; 120 } 121 122 /* Set BKE_EN to 1 when Fixed, Regulator or Limiter Mode */ 123 val = 1; 124 } 125 126 return regmap_update_bits(qp->regmap, 127 qp->qos_offset + M_BKE_EN_ADDR(qn->qos.qos_port), 128 M_BKE_EN_EN_BMASK, val); 129} 130 131static int qcom_icc_noc_set_qos_priority(struct qcom_icc_provider *qp, 132 struct qcom_icc_qos *qos) 133{ 134 u32 val; 135 int rc; 136 137 /* Must be updated one at a time, P1 first, P0 last */ 138 val = qos->areq_prio << NOC_QOS_PRIORITY_P1_SHIFT; 139 rc = regmap_update_bits(qp->regmap, 140 qp->qos_offset + NOC_QOS_PRIORITYn_ADDR(qos->qos_port), 141 NOC_QOS_PRIORITY_P1_MASK, val); 142 if (rc) 143 return rc; 144 145 return regmap_update_bits(qp->regmap, 146 qp->qos_offset + NOC_QOS_PRIORITYn_ADDR(qos->qos_port), 147 NOC_QOS_PRIORITY_P0_MASK, qos->prio_level); 148} 149 150static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw) 151{ 152 struct qcom_icc_provider *qp; 153 struct qcom_icc_node *qn; 154 struct icc_provider *provider; 155 u32 mode = NOC_QOS_MODE_BYPASS; 156 int rc = 0; 157 158 qn = src->data; 159 provider = src->provider; 160 qp = to_qcom_provider(provider); 161 162 if (qn->qos.qos_port < 0) { 163 dev_dbg(src->provider->dev, 164 "NoC QoS: Skipping %s: vote aggregated on parent.\n", 165 qn->name); 166 return 0; 167 } 168 169 if (qn->qos.qos_mode != NOC_QOS_MODE_INVALID) 170 mode = qn->qos.qos_mode; 171 172 if (mode == NOC_QOS_MODE_FIXED) { 173 dev_dbg(src->provider->dev, "NoC QoS: %s: Set Fixed mode\n", 174 qn->name); 175 rc = qcom_icc_noc_set_qos_priority(qp, &qn->qos); 176 if (rc) 177 return rc; 178 } else if (mode == NOC_QOS_MODE_BYPASS) { 179 dev_dbg(src->provider->dev, "NoC QoS: %s: Set Bypass mode\n", 180 qn->name); 181 } 182 183 return regmap_update_bits(qp->regmap, 184 qp->qos_offset + NOC_QOS_MODEn_ADDR(qn->qos.qos_port), 185 NOC_QOS_MODEn_MASK, mode); 186} 187 188static int qcom_icc_qos_set(struct icc_node *node, u64 sum_bw) 189{ 190 struct qcom_icc_provider *qp = to_qcom_provider(node->provider); 191 struct qcom_icc_node *qn = node->data; 192 193 dev_dbg(node->provider->dev, "Setting QoS for %s\n", qn->name); 194 195 switch (qp->type) { 196 case QCOM_ICC_BIMC: 197 return qcom_icc_set_bimc_qos(node, sum_bw); 198 case QCOM_ICC_QNOC: 199 return qcom_icc_set_qnoc_qos(node, sum_bw); 200 default: 201 return qcom_icc_set_noc_qos(node, sum_bw); 202 } 203} 204 205static int qcom_icc_rpm_set(int mas_rpm_id, int slv_rpm_id, u64 sum_bw) 206{ 207 int ret = 0; 208 209 if (mas_rpm_id != -1) { 210 ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, 211 RPM_BUS_MASTER_REQ, 212 mas_rpm_id, 213 sum_bw); 214 if (ret) { 215 pr_err("qcom_icc_rpm_smd_send mas %d error %d\n", 216 mas_rpm_id, ret); 217 return ret; 218 } 219 } 220 221 if (slv_rpm_id != -1) { 222 ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, 223 RPM_BUS_SLAVE_REQ, 224 slv_rpm_id, 225 sum_bw); 226 if (ret) { 227 pr_err("qcom_icc_rpm_smd_send slv %d error %d\n", 228 slv_rpm_id, ret); 229 return ret; 230 } 231 } 232 233 return ret; 234} 235 236static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) 237{ 238 struct qcom_icc_provider *qp; 239 struct qcom_icc_node *qn; 240 struct icc_provider *provider; 241 struct icc_node *n; 242 u64 sum_bw; 243 u64 max_peak_bw; 244 u64 rate; 245 u32 agg_avg = 0; 246 u32 agg_peak = 0; 247 int ret, i; 248 249 qn = src->data; 250 provider = src->provider; 251 qp = to_qcom_provider(provider); 252 253 list_for_each_entry(n, &provider->nodes, node_list) 254 provider->aggregate(n, 0, n->avg_bw, n->peak_bw, 255 &agg_avg, &agg_peak); 256 257 sum_bw = icc_units_to_bps(agg_avg); 258 max_peak_bw = icc_units_to_bps(agg_peak); 259 260 if (!qn->qos.ap_owned) { 261 /* send bandwidth request message to the RPM processor */ 262 ret = qcom_icc_rpm_set(qn->mas_rpm_id, qn->slv_rpm_id, sum_bw); 263 if (ret) 264 return ret; 265 } else if (qn->qos.qos_mode != -1) { 266 /* set bandwidth directly from the AP */ 267 ret = qcom_icc_qos_set(src, sum_bw); 268 if (ret) 269 return ret; 270 } 271 272 rate = max(sum_bw, max_peak_bw); 273 274 do_div(rate, qn->buswidth); 275 rate = min_t(u64, rate, LONG_MAX); 276 277 for (i = 0; i < qp->num_clks; i++) { 278 if (qp->bus_clk_rate[i] == rate) 279 continue; 280 281 ret = clk_set_rate(qp->bus_clks[i].clk, rate); 282 if (ret) { 283 pr_err("%s clk_set_rate error: %d\n", 284 qp->bus_clks[i].id, ret); 285 return ret; 286 } 287 qp->bus_clk_rate[i] = rate; 288 } 289 290 return 0; 291} 292 293static const char * const bus_clocks[] = { 294 "bus", "bus_a", 295}; 296 297int qnoc_probe(struct platform_device *pdev) 298{ 299 struct device *dev = &pdev->dev; 300 const struct qcom_icc_desc *desc; 301 struct icc_onecell_data *data; 302 struct icc_provider *provider; 303 struct qcom_icc_node * const *qnodes; 304 struct qcom_icc_provider *qp; 305 struct icc_node *node; 306 size_t num_nodes, i; 307 const char * const *cds; 308 int cd_num; 309 int ret; 310 311 /* wait for the RPM proxy */ 312 if (!qcom_icc_rpm_smd_available()) 313 return -EPROBE_DEFER; 314 315 desc = of_device_get_match_data(dev); 316 if (!desc) 317 return -EINVAL; 318 319 qnodes = desc->nodes; 320 num_nodes = desc->num_nodes; 321 322 if (desc->num_clocks) { 323 cds = desc->clocks; 324 cd_num = desc->num_clocks; 325 } else { 326 cds = bus_clocks; 327 cd_num = ARRAY_SIZE(bus_clocks); 328 } 329 330 qp = devm_kzalloc(dev, struct_size(qp, bus_clks, cd_num), GFP_KERNEL); 331 if (!qp) 332 return -ENOMEM; 333 334 qp->bus_clk_rate = devm_kcalloc(dev, cd_num, sizeof(*qp->bus_clk_rate), 335 GFP_KERNEL); 336 if (!qp->bus_clk_rate) 337 return -ENOMEM; 338 339 data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes), 340 GFP_KERNEL); 341 if (!data) 342 return -ENOMEM; 343 344 for (i = 0; i < cd_num; i++) 345 qp->bus_clks[i].id = cds[i]; 346 qp->num_clks = cd_num; 347 348 qp->type = desc->type; 349 qp->qos_offset = desc->qos_offset; 350 351 if (desc->regmap_cfg) { 352 struct resource *res; 353 void __iomem *mmio; 354 355 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 356 if (!res) { 357 /* Try parent's regmap */ 358 qp->regmap = dev_get_regmap(dev->parent, NULL); 359 if (qp->regmap) 360 goto regmap_done; 361 return -ENODEV; 362 } 363 364 mmio = devm_ioremap_resource(dev, res); 365 366 if (IS_ERR(mmio)) { 367 dev_err(dev, "Cannot ioremap interconnect bus resource\n"); 368 return PTR_ERR(mmio); 369 } 370 371 qp->regmap = devm_regmap_init_mmio(dev, mmio, desc->regmap_cfg); 372 if (IS_ERR(qp->regmap)) { 373 dev_err(dev, "Cannot regmap interconnect bus resource\n"); 374 return PTR_ERR(qp->regmap); 375 } 376 } 377 378regmap_done: 379 ret = devm_clk_bulk_get(dev, qp->num_clks, qp->bus_clks); 380 if (ret) 381 return ret; 382 383 ret = clk_bulk_prepare_enable(qp->num_clks, qp->bus_clks); 384 if (ret) 385 return ret; 386 387 if (desc->has_bus_pd) { 388 ret = dev_pm_domain_attach(dev, true); 389 if (ret) 390 return ret; 391 } 392 393 provider = &qp->provider; 394 INIT_LIST_HEAD(&provider->nodes); 395 provider->dev = dev; 396 provider->set = qcom_icc_set; 397 provider->aggregate = icc_std_aggregate; 398 provider->xlate = of_icc_xlate_onecell; 399 provider->data = data; 400 401 ret = icc_provider_add(provider); 402 if (ret) { 403 dev_err(dev, "error adding interconnect provider: %d\n", ret); 404 clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); 405 return ret; 406 } 407 408 for (i = 0; i < num_nodes; i++) { 409 size_t j; 410 411 node = icc_node_create(qnodes[i]->id); 412 if (IS_ERR(node)) { 413 ret = PTR_ERR(node); 414 goto err; 415 } 416 417 node->name = qnodes[i]->name; 418 node->data = qnodes[i]; 419 icc_node_add(node, provider); 420 421 for (j = 0; j < qnodes[i]->num_links; j++) 422 icc_link_create(node, qnodes[i]->links[j]); 423 424 data->nodes[i] = node; 425 } 426 data->num_nodes = num_nodes; 427 428 platform_set_drvdata(pdev, qp); 429 430 /* Populate child NoC devices if any */ 431 if (of_get_child_count(dev->of_node) > 0) 432 return of_platform_populate(dev->of_node, NULL, NULL, dev); 433 434 return 0; 435err: 436 icc_nodes_remove(provider); 437 clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); 438 icc_provider_del(provider); 439 440 return ret; 441} 442EXPORT_SYMBOL(qnoc_probe); 443 444int qnoc_remove(struct platform_device *pdev) 445{ 446 struct qcom_icc_provider *qp = platform_get_drvdata(pdev); 447 448 icc_nodes_remove(&qp->provider); 449 clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); 450 return icc_provider_del(&qp->provider); 451} 452EXPORT_SYMBOL(qnoc_remove);