tegra20.c (20114B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. 4 */ 5 6#include <linux/bitfield.h> 7#include <linux/delay.h> 8#include <linux/mutex.h> 9#include <linux/of_device.h> 10#include <linux/slab.h> 11#include <linux/string.h> 12 13#include <dt-bindings/memory/tegra20-mc.h> 14 15#include "mc.h" 16 17#define MC_STAT_CONTROL 0x90 18#define MC_STAT_EMC_CLOCK_LIMIT 0xa0 19#define MC_STAT_EMC_CLOCKS 0xa4 20#define MC_STAT_EMC_CONTROL_0 0xa8 21#define MC_STAT_EMC_CONTROL_1 0xac 22#define MC_STAT_EMC_COUNT_0 0xb8 23#define MC_STAT_EMC_COUNT_1 0xbc 24 25#define MC_STAT_CONTROL_CLIENT_ID GENMASK(13, 8) 26#define MC_STAT_CONTROL_EVENT GENMASK(23, 16) 27#define MC_STAT_CONTROL_PRI_EVENT GENMASK(25, 24) 28#define MC_STAT_CONTROL_FILTER_CLIENT_ENABLE GENMASK(26, 26) 29#define MC_STAT_CONTROL_FILTER_PRI GENMASK(29, 28) 30 31#define MC_STAT_CONTROL_PRI_EVENT_HP 0 32#define MC_STAT_CONTROL_PRI_EVENT_TM 1 33#define MC_STAT_CONTROL_PRI_EVENT_BW 2 34 35#define MC_STAT_CONTROL_FILTER_PRI_DISABLE 0 36#define MC_STAT_CONTROL_FILTER_PRI_NO 1 37#define MC_STAT_CONTROL_FILTER_PRI_YES 2 38 39#define MC_STAT_CONTROL_EVENT_QUALIFIED 0 40#define MC_STAT_CONTROL_EVENT_ANY_READ 1 41#define MC_STAT_CONTROL_EVENT_ANY_WRITE 2 42#define MC_STAT_CONTROL_EVENT_RD_WR_CHANGE 3 43#define MC_STAT_CONTROL_EVENT_SUCCESSIVE 4 44#define MC_STAT_CONTROL_EVENT_ARB_BANK_AA 5 45#define MC_STAT_CONTROL_EVENT_ARB_BANK_BB 6 46#define MC_STAT_CONTROL_EVENT_PAGE_MISS 7 47#define MC_STAT_CONTROL_EVENT_AUTO_PRECHARGE 8 48 49#define EMC_GATHER_RST (0 << 8) 50#define EMC_GATHER_CLEAR (1 << 8) 51#define EMC_GATHER_DISABLE (2 << 8) 52#define EMC_GATHER_ENABLE (3 << 8) 53 54#define MC_STAT_SAMPLE_TIME_USEC 16000 55 56/* we store collected statistics as a fixed point values */ 57#define MC_FX_FRAC_SCALE 100 58 59static DEFINE_MUTEX(tegra20_mc_stat_lock); 60 61struct tegra20_mc_stat_gather { 62 unsigned int pri_filter; 63 unsigned int pri_event; 64 unsigned int result; 65 unsigned int client; 66 unsigned int event; 67 bool client_enb; 68}; 69 70struct tegra20_mc_stat { 71 struct tegra20_mc_stat_gather gather0; 72 struct tegra20_mc_stat_gather gather1; 73 unsigned int sample_time_usec; 74 const struct tegra_mc *mc; 75}; 76 77struct tegra20_mc_client_stat { 78 unsigned int events; 79 unsigned int arb_high_prio; 80 unsigned int arb_timeout; 81 unsigned int arb_bandwidth; 82 unsigned int rd_wr_change; 83 unsigned int successive; 84 unsigned int page_miss; 85 unsigned int auto_precharge; 86 unsigned int arb_bank_aa; 87 unsigned int arb_bank_bb; 88}; 89 90static const struct tegra_mc_client tegra20_mc_clients[] = { 91 { 92 .id = 0x00, 93 .name = "display0a", 94 }, { 95 .id = 0x01, 96 .name = "display0ab", 97 }, { 98 .id = 0x02, 99 .name = "display0b", 100 }, { 101 .id = 0x03, 102 .name = "display0bb", 103 }, { 104 .id = 0x04, 105 .name = "display0c", 106 }, { 107 .id = 0x05, 108 .name = "display0cb", 109 }, { 110 .id = 0x06, 111 .name = "display1b", 112 }, { 113 .id = 0x07, 114 .name = "display1bb", 115 }, { 116 .id = 0x08, 117 .name = "eppup", 118 }, { 119 .id = 0x09, 120 .name = "g2pr", 121 }, { 122 .id = 0x0a, 123 .name = "g2sr", 124 }, { 125 .id = 0x0b, 126 .name = "mpeunifbr", 127 }, { 128 .id = 0x0c, 129 .name = "viruv", 130 }, { 131 .id = 0x0d, 132 .name = "avpcarm7r", 133 }, { 134 .id = 0x0e, 135 .name = "displayhc", 136 }, { 137 .id = 0x0f, 138 .name = "displayhcb", 139 }, { 140 .id = 0x10, 141 .name = "fdcdrd", 142 }, { 143 .id = 0x11, 144 .name = "g2dr", 145 }, { 146 .id = 0x12, 147 .name = "host1xdmar", 148 }, { 149 .id = 0x13, 150 .name = "host1xr", 151 }, { 152 .id = 0x14, 153 .name = "idxsrd", 154 }, { 155 .id = 0x15, 156 .name = "mpcorer", 157 }, { 158 .id = 0x16, 159 .name = "mpe_ipred", 160 }, { 161 .id = 0x17, 162 .name = "mpeamemrd", 163 }, { 164 .id = 0x18, 165 .name = "mpecsrd", 166 }, { 167 .id = 0x19, 168 .name = "ppcsahbdmar", 169 }, { 170 .id = 0x1a, 171 .name = "ppcsahbslvr", 172 }, { 173 .id = 0x1b, 174 .name = "texsrd", 175 }, { 176 .id = 0x1c, 177 .name = "vdebsevr", 178 }, { 179 .id = 0x1d, 180 .name = "vdember", 181 }, { 182 .id = 0x1e, 183 .name = "vdemcer", 184 }, { 185 .id = 0x1f, 186 .name = "vdetper", 187 }, { 188 .id = 0x20, 189 .name = "eppu", 190 }, { 191 .id = 0x21, 192 .name = "eppv", 193 }, { 194 .id = 0x22, 195 .name = "eppy", 196 }, { 197 .id = 0x23, 198 .name = "mpeunifbw", 199 }, { 200 .id = 0x24, 201 .name = "viwsb", 202 }, { 203 .id = 0x25, 204 .name = "viwu", 205 }, { 206 .id = 0x26, 207 .name = "viwv", 208 }, { 209 .id = 0x27, 210 .name = "viwy", 211 }, { 212 .id = 0x28, 213 .name = "g2dw", 214 }, { 215 .id = 0x29, 216 .name = "avpcarm7w", 217 }, { 218 .id = 0x2a, 219 .name = "fdcdwr", 220 }, { 221 .id = 0x2b, 222 .name = "host1xw", 223 }, { 224 .id = 0x2c, 225 .name = "ispw", 226 }, { 227 .id = 0x2d, 228 .name = "mpcorew", 229 }, { 230 .id = 0x2e, 231 .name = "mpecswr", 232 }, { 233 .id = 0x2f, 234 .name = "ppcsahbdmaw", 235 }, { 236 .id = 0x30, 237 .name = "ppcsahbslvw", 238 }, { 239 .id = 0x31, 240 .name = "vdebsevw", 241 }, { 242 .id = 0x32, 243 .name = "vdembew", 244 }, { 245 .id = 0x33, 246 .name = "vdetpmw", 247 }, 248}; 249 250#define TEGRA20_MC_RESET(_name, _control, _status, _reset, _bit) \ 251 { \ 252 .name = #_name, \ 253 .id = TEGRA20_MC_RESET_##_name, \ 254 .control = _control, \ 255 .status = _status, \ 256 .reset = _reset, \ 257 .bit = _bit, \ 258 } 259 260static const struct tegra_mc_reset tegra20_mc_resets[] = { 261 TEGRA20_MC_RESET(AVPC, 0x100, 0x140, 0x104, 0), 262 TEGRA20_MC_RESET(DC, 0x100, 0x144, 0x104, 1), 263 TEGRA20_MC_RESET(DCB, 0x100, 0x148, 0x104, 2), 264 TEGRA20_MC_RESET(EPP, 0x100, 0x14c, 0x104, 3), 265 TEGRA20_MC_RESET(2D, 0x100, 0x150, 0x104, 4), 266 TEGRA20_MC_RESET(HC, 0x100, 0x154, 0x104, 5), 267 TEGRA20_MC_RESET(ISP, 0x100, 0x158, 0x104, 6), 268 TEGRA20_MC_RESET(MPCORE, 0x100, 0x15c, 0x104, 7), 269 TEGRA20_MC_RESET(MPEA, 0x100, 0x160, 0x104, 8), 270 TEGRA20_MC_RESET(MPEB, 0x100, 0x164, 0x104, 9), 271 TEGRA20_MC_RESET(MPEC, 0x100, 0x168, 0x104, 10), 272 TEGRA20_MC_RESET(3D, 0x100, 0x16c, 0x104, 11), 273 TEGRA20_MC_RESET(PPCS, 0x100, 0x170, 0x104, 12), 274 TEGRA20_MC_RESET(VDE, 0x100, 0x174, 0x104, 13), 275 TEGRA20_MC_RESET(VI, 0x100, 0x178, 0x104, 14), 276}; 277 278static int tegra20_mc_hotreset_assert(struct tegra_mc *mc, 279 const struct tegra_mc_reset *rst) 280{ 281 unsigned long flags; 282 u32 value; 283 284 spin_lock_irqsave(&mc->lock, flags); 285 286 value = mc_readl(mc, rst->reset); 287 mc_writel(mc, value & ~BIT(rst->bit), rst->reset); 288 289 spin_unlock_irqrestore(&mc->lock, flags); 290 291 return 0; 292} 293 294static int tegra20_mc_hotreset_deassert(struct tegra_mc *mc, 295 const struct tegra_mc_reset *rst) 296{ 297 unsigned long flags; 298 u32 value; 299 300 spin_lock_irqsave(&mc->lock, flags); 301 302 value = mc_readl(mc, rst->reset); 303 mc_writel(mc, value | BIT(rst->bit), rst->reset); 304 305 spin_unlock_irqrestore(&mc->lock, flags); 306 307 return 0; 308} 309 310static int tegra20_mc_block_dma(struct tegra_mc *mc, 311 const struct tegra_mc_reset *rst) 312{ 313 unsigned long flags; 314 u32 value; 315 316 spin_lock_irqsave(&mc->lock, flags); 317 318 value = mc_readl(mc, rst->control) & ~BIT(rst->bit); 319 mc_writel(mc, value, rst->control); 320 321 spin_unlock_irqrestore(&mc->lock, flags); 322 323 return 0; 324} 325 326static bool tegra20_mc_dma_idling(struct tegra_mc *mc, 327 const struct tegra_mc_reset *rst) 328{ 329 return mc_readl(mc, rst->status) == 0; 330} 331 332static int tegra20_mc_reset_status(struct tegra_mc *mc, 333 const struct tegra_mc_reset *rst) 334{ 335 return (mc_readl(mc, rst->reset) & BIT(rst->bit)) == 0; 336} 337 338static int tegra20_mc_unblock_dma(struct tegra_mc *mc, 339 const struct tegra_mc_reset *rst) 340{ 341 unsigned long flags; 342 u32 value; 343 344 spin_lock_irqsave(&mc->lock, flags); 345 346 value = mc_readl(mc, rst->control) | BIT(rst->bit); 347 mc_writel(mc, value, rst->control); 348 349 spin_unlock_irqrestore(&mc->lock, flags); 350 351 return 0; 352} 353 354static const struct tegra_mc_reset_ops tegra20_mc_reset_ops = { 355 .hotreset_assert = tegra20_mc_hotreset_assert, 356 .hotreset_deassert = tegra20_mc_hotreset_deassert, 357 .block_dma = tegra20_mc_block_dma, 358 .dma_idling = tegra20_mc_dma_idling, 359 .unblock_dma = tegra20_mc_unblock_dma, 360 .reset_status = tegra20_mc_reset_status, 361}; 362 363static int tegra20_mc_icc_set(struct icc_node *src, struct icc_node *dst) 364{ 365 /* 366 * It should be possible to tune arbitration knobs here, but the 367 * default values are known to work well on all devices. Hence 368 * nothing to do here so far. 369 */ 370 return 0; 371} 372 373static int tegra20_mc_icc_aggreate(struct icc_node *node, u32 tag, u32 avg_bw, 374 u32 peak_bw, u32 *agg_avg, u32 *agg_peak) 375{ 376 /* 377 * ISO clients need to reserve extra bandwidth up-front because 378 * there could be high bandwidth pressure during initial filling 379 * of the client's FIFO buffers. Secondly, we need to take into 380 * account impurities of the memory subsystem. 381 */ 382 if (tag & TEGRA_MC_ICC_TAG_ISO) 383 peak_bw = tegra_mc_scale_percents(peak_bw, 300); 384 385 *agg_avg += avg_bw; 386 *agg_peak = max(*agg_peak, peak_bw); 387 388 return 0; 389} 390 391static struct icc_node_data * 392tegra20_mc_of_icc_xlate_extended(struct of_phandle_args *spec, void *data) 393{ 394 struct tegra_mc *mc = icc_provider_to_tegra_mc(data); 395 unsigned int i, idx = spec->args[0]; 396 struct icc_node_data *ndata; 397 struct icc_node *node; 398 399 list_for_each_entry(node, &mc->provider.nodes, node_list) { 400 if (node->id != idx) 401 continue; 402 403 ndata = kzalloc(sizeof(*ndata), GFP_KERNEL); 404 if (!ndata) 405 return ERR_PTR(-ENOMEM); 406 407 ndata->node = node; 408 409 /* these clients are isochronous by default */ 410 if (strstarts(node->name, "display") || 411 strstarts(node->name, "vi")) 412 ndata->tag = TEGRA_MC_ICC_TAG_ISO; 413 else 414 ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT; 415 416 return ndata; 417 } 418 419 for (i = 0; i < mc->soc->num_clients; i++) { 420 if (mc->soc->clients[i].id == idx) 421 return ERR_PTR(-EPROBE_DEFER); 422 } 423 424 dev_err(mc->dev, "invalid ICC client ID %u\n", idx); 425 426 return ERR_PTR(-EINVAL); 427} 428 429static const struct tegra_mc_icc_ops tegra20_mc_icc_ops = { 430 .xlate_extended = tegra20_mc_of_icc_xlate_extended, 431 .aggregate = tegra20_mc_icc_aggreate, 432 .set = tegra20_mc_icc_set, 433}; 434 435static u32 tegra20_mc_stat_gather_control(const struct tegra20_mc_stat_gather *g) 436{ 437 u32 control; 438 439 control = FIELD_PREP(MC_STAT_CONTROL_EVENT, g->event); 440 control |= FIELD_PREP(MC_STAT_CONTROL_CLIENT_ID, g->client); 441 control |= FIELD_PREP(MC_STAT_CONTROL_PRI_EVENT, g->pri_event); 442 control |= FIELD_PREP(MC_STAT_CONTROL_FILTER_PRI, g->pri_filter); 443 control |= FIELD_PREP(MC_STAT_CONTROL_FILTER_CLIENT_ENABLE, g->client_enb); 444 445 return control; 446} 447 448static void tegra20_mc_stat_gather(struct tegra20_mc_stat *stat) 449{ 450 u32 clocks, count0, count1, control_0, control_1; 451 const struct tegra_mc *mc = stat->mc; 452 453 control_0 = tegra20_mc_stat_gather_control(&stat->gather0); 454 control_1 = tegra20_mc_stat_gather_control(&stat->gather1); 455 456 /* 457 * Reset statistic gathers state, select statistics collection mode 458 * and set clocks counter saturation limit to maximum. 459 */ 460 mc_writel(mc, 0x00000000, MC_STAT_CONTROL); 461 mc_writel(mc, control_0, MC_STAT_EMC_CONTROL_0); 462 mc_writel(mc, control_1, MC_STAT_EMC_CONTROL_1); 463 mc_writel(mc, 0xffffffff, MC_STAT_EMC_CLOCK_LIMIT); 464 465 mc_writel(mc, EMC_GATHER_ENABLE, MC_STAT_CONTROL); 466 fsleep(stat->sample_time_usec); 467 mc_writel(mc, EMC_GATHER_DISABLE, MC_STAT_CONTROL); 468 469 count0 = mc_readl(mc, MC_STAT_EMC_COUNT_0); 470 count1 = mc_readl(mc, MC_STAT_EMC_COUNT_1); 471 clocks = mc_readl(mc, MC_STAT_EMC_CLOCKS); 472 clocks = max(clocks / 100 / MC_FX_FRAC_SCALE, 1u); 473 474 stat->gather0.result = DIV_ROUND_UP(count0, clocks); 475 stat->gather1.result = DIV_ROUND_UP(count1, clocks); 476} 477 478static void tegra20_mc_stat_events(const struct tegra_mc *mc, 479 const struct tegra_mc_client *client0, 480 const struct tegra_mc_client *client1, 481 unsigned int pri_filter, 482 unsigned int pri_event, 483 unsigned int event, 484 unsigned int *result0, 485 unsigned int *result1) 486{ 487 struct tegra20_mc_stat stat = {}; 488 489 stat.gather0.client = client0 ? client0->id : 0; 490 stat.gather0.pri_filter = pri_filter; 491 stat.gather0.client_enb = !!client0; 492 stat.gather0.pri_event = pri_event; 493 stat.gather0.event = event; 494 495 stat.gather1.client = client1 ? client1->id : 0; 496 stat.gather1.pri_filter = pri_filter; 497 stat.gather1.client_enb = !!client1; 498 stat.gather1.pri_event = pri_event; 499 stat.gather1.event = event; 500 501 stat.sample_time_usec = MC_STAT_SAMPLE_TIME_USEC; 502 stat.mc = mc; 503 504 tegra20_mc_stat_gather(&stat); 505 506 *result0 = stat.gather0.result; 507 *result1 = stat.gather1.result; 508} 509 510static void tegra20_mc_collect_stats(const struct tegra_mc *mc, 511 struct tegra20_mc_client_stat *stats) 512{ 513 const struct tegra_mc_client *client0, *client1; 514 unsigned int i; 515 516 /* collect memory controller utilization percent for each client */ 517 for (i = 0; i < mc->soc->num_clients; i += 2) { 518 client0 = &mc->soc->clients[i]; 519 client1 = &mc->soc->clients[i + 1]; 520 521 if (i + 1 == mc->soc->num_clients) 522 client1 = NULL; 523 524 tegra20_mc_stat_events(mc, client0, client1, 525 MC_STAT_CONTROL_FILTER_PRI_DISABLE, 526 MC_STAT_CONTROL_PRI_EVENT_HP, 527 MC_STAT_CONTROL_EVENT_QUALIFIED, 528 &stats[i + 0].events, 529 &stats[i + 1].events); 530 } 531 532 /* collect more info from active clients */ 533 for (i = 0; i < mc->soc->num_clients; i++) { 534 unsigned int clienta, clientb = mc->soc->num_clients; 535 536 for (client0 = NULL; i < mc->soc->num_clients; i++) { 537 if (stats[i].events) { 538 client0 = &mc->soc->clients[i]; 539 clienta = i++; 540 break; 541 } 542 } 543 544 for (client1 = NULL; i < mc->soc->num_clients; i++) { 545 if (stats[i].events) { 546 client1 = &mc->soc->clients[i]; 547 clientb = i; 548 break; 549 } 550 } 551 552 if (!client0 && !client1) 553 break; 554 555 tegra20_mc_stat_events(mc, client0, client1, 556 MC_STAT_CONTROL_FILTER_PRI_YES, 557 MC_STAT_CONTROL_PRI_EVENT_HP, 558 MC_STAT_CONTROL_EVENT_QUALIFIED, 559 &stats[clienta].arb_high_prio, 560 &stats[clientb].arb_high_prio); 561 562 tegra20_mc_stat_events(mc, client0, client1, 563 MC_STAT_CONTROL_FILTER_PRI_YES, 564 MC_STAT_CONTROL_PRI_EVENT_TM, 565 MC_STAT_CONTROL_EVENT_QUALIFIED, 566 &stats[clienta].arb_timeout, 567 &stats[clientb].arb_timeout); 568 569 tegra20_mc_stat_events(mc, client0, client1, 570 MC_STAT_CONTROL_FILTER_PRI_YES, 571 MC_STAT_CONTROL_PRI_EVENT_BW, 572 MC_STAT_CONTROL_EVENT_QUALIFIED, 573 &stats[clienta].arb_bandwidth, 574 &stats[clientb].arb_bandwidth); 575 576 tegra20_mc_stat_events(mc, client0, client1, 577 MC_STAT_CONTROL_FILTER_PRI_DISABLE, 578 MC_STAT_CONTROL_PRI_EVENT_HP, 579 MC_STAT_CONTROL_EVENT_RD_WR_CHANGE, 580 &stats[clienta].rd_wr_change, 581 &stats[clientb].rd_wr_change); 582 583 tegra20_mc_stat_events(mc, client0, client1, 584 MC_STAT_CONTROL_FILTER_PRI_DISABLE, 585 MC_STAT_CONTROL_PRI_EVENT_HP, 586 MC_STAT_CONTROL_EVENT_SUCCESSIVE, 587 &stats[clienta].successive, 588 &stats[clientb].successive); 589 590 tegra20_mc_stat_events(mc, client0, client1, 591 MC_STAT_CONTROL_FILTER_PRI_DISABLE, 592 MC_STAT_CONTROL_PRI_EVENT_HP, 593 MC_STAT_CONTROL_EVENT_PAGE_MISS, 594 &stats[clienta].page_miss, 595 &stats[clientb].page_miss); 596 } 597} 598 599static void tegra20_mc_printf_percents(struct seq_file *s, 600 const char *fmt, 601 unsigned int percents_fx) 602{ 603 char percents_str[8]; 604 605 snprintf(percents_str, ARRAY_SIZE(percents_str), "%3u.%02u%%", 606 percents_fx / MC_FX_FRAC_SCALE, percents_fx % MC_FX_FRAC_SCALE); 607 608 seq_printf(s, fmt, percents_str); 609} 610 611static int tegra20_mc_stats_show(struct seq_file *s, void *unused) 612{ 613 const struct tegra_mc *mc = dev_get_drvdata(s->private); 614 struct tegra20_mc_client_stat *stats; 615 unsigned int i; 616 617 stats = kcalloc(mc->soc->num_clients + 1, sizeof(*stats), GFP_KERNEL); 618 if (!stats) 619 return -ENOMEM; 620 621 mutex_lock(&tegra20_mc_stat_lock); 622 623 tegra20_mc_collect_stats(mc, stats); 624 625 mutex_unlock(&tegra20_mc_stat_lock); 626 627 seq_puts(s, "Memory client Events Timeout High priority Bandwidth ARB RW change Successive Page miss\n"); 628 seq_puts(s, "-----------------------------------------------------------------------------------------------------\n"); 629 630 for (i = 0; i < mc->soc->num_clients; i++) { 631 seq_printf(s, "%-14s ", mc->soc->clients[i].name); 632 633 /* An event is generated when client performs R/W request. */ 634 tegra20_mc_printf_percents(s, "%-9s", stats[i].events); 635 636 /* 637 * An event is generated based on the timeout (TM) signal 638 * accompanying a request for arbitration. 639 */ 640 tegra20_mc_printf_percents(s, "%-10s", stats[i].arb_timeout); 641 642 /* 643 * An event is generated based on the high-priority (HP) signal 644 * accompanying a request for arbitration. 645 */ 646 tegra20_mc_printf_percents(s, "%-16s", stats[i].arb_high_prio); 647 648 /* 649 * An event is generated based on the bandwidth (BW) signal 650 * accompanying a request for arbitration. 651 */ 652 tegra20_mc_printf_percents(s, "%-16s", stats[i].arb_bandwidth); 653 654 /* 655 * An event is generated when the memory controller switches 656 * between making a read request to making a write request. 657 */ 658 tegra20_mc_printf_percents(s, "%-12s", stats[i].rd_wr_change); 659 660 /* 661 * An even generated when the chosen client has wins arbitration 662 * when it was also the winner at the previous request. If a 663 * client makes N requests in a row that are honored, SUCCESSIVE 664 * will be counted (N-1) times. Large values for this event 665 * imply that if we were patient enough, all of those requests 666 * could have been coalesced. 667 */ 668 tegra20_mc_printf_percents(s, "%-13s", stats[i].successive); 669 670 /* 671 * An event is generated when the memory controller detects a 672 * page miss for the current request. 673 */ 674 tegra20_mc_printf_percents(s, "%-12s\n", stats[i].page_miss); 675 } 676 677 kfree(stats); 678 679 return 0; 680} 681 682static int tegra20_mc_probe(struct tegra_mc *mc) 683{ 684 debugfs_create_devm_seqfile(mc->dev, "stats", mc->debugfs.root, 685 tegra20_mc_stats_show); 686 687 return 0; 688} 689 690static int tegra20_mc_suspend(struct tegra_mc *mc) 691{ 692 int err; 693 694 if (IS_ENABLED(CONFIG_TEGRA_IOMMU_GART) && mc->gart) { 695 err = tegra_gart_suspend(mc->gart); 696 if (err < 0) 697 return err; 698 } 699 700 return 0; 701} 702 703static int tegra20_mc_resume(struct tegra_mc *mc) 704{ 705 int err; 706 707 if (IS_ENABLED(CONFIG_TEGRA_IOMMU_GART) && mc->gart) { 708 err = tegra_gart_resume(mc->gart); 709 if (err < 0) 710 return err; 711 } 712 713 return 0; 714} 715 716static irqreturn_t tegra20_mc_handle_irq(int irq, void *data) 717{ 718 struct tegra_mc *mc = data; 719 unsigned long status; 720 unsigned int bit; 721 722 /* mask all interrupts to avoid flooding */ 723 status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask; 724 if (!status) 725 return IRQ_NONE; 726 727 for_each_set_bit(bit, &status, 32) { 728 const char *error = tegra_mc_status_names[bit]; 729 const char *direction = "read", *secure = ""; 730 const char *client, *desc; 731 phys_addr_t addr; 732 u32 value, reg; 733 u8 id, type; 734 735 switch (BIT(bit)) { 736 case MC_INT_DECERR_EMEM: 737 reg = MC_DECERR_EMEM_OTHERS_STATUS; 738 value = mc_readl(mc, reg); 739 740 id = value & mc->soc->client_id_mask; 741 desc = tegra_mc_error_names[2]; 742 743 if (value & BIT(31)) 744 direction = "write"; 745 break; 746 747 case MC_INT_INVALID_GART_PAGE: 748 reg = MC_GART_ERROR_REQ; 749 value = mc_readl(mc, reg); 750 751 id = (value >> 1) & mc->soc->client_id_mask; 752 desc = tegra_mc_error_names[2]; 753 754 if (value & BIT(0)) 755 direction = "write"; 756 break; 757 758 case MC_INT_SECURITY_VIOLATION: 759 reg = MC_SECURITY_VIOLATION_STATUS; 760 value = mc_readl(mc, reg); 761 762 id = value & mc->soc->client_id_mask; 763 type = (value & BIT(30)) ? 4 : 3; 764 desc = tegra_mc_error_names[type]; 765 secure = "secure "; 766 767 if (value & BIT(31)) 768 direction = "write"; 769 break; 770 771 default: 772 continue; 773 } 774 775 client = mc->soc->clients[id].name; 776 addr = mc_readl(mc, reg + sizeof(u32)); 777 778 dev_err_ratelimited(mc->dev, "%s: %s%s @%pa: %s (%s)\n", 779 client, secure, direction, &addr, error, 780 desc); 781 } 782 783 /* clear interrupts */ 784 mc_writel(mc, status, MC_INTSTATUS); 785 786 return IRQ_HANDLED; 787} 788 789static const struct tegra_mc_ops tegra20_mc_ops = { 790 .probe = tegra20_mc_probe, 791 .suspend = tegra20_mc_suspend, 792 .resume = tegra20_mc_resume, 793 .handle_irq = tegra20_mc_handle_irq, 794}; 795 796const struct tegra_mc_soc tegra20_mc_soc = { 797 .clients = tegra20_mc_clients, 798 .num_clients = ARRAY_SIZE(tegra20_mc_clients), 799 .num_address_bits = 32, 800 .client_id_mask = 0x3f, 801 .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE | 802 MC_INT_DECERR_EMEM, 803 .reset_ops = &tegra20_mc_reset_ops, 804 .resets = tegra20_mc_resets, 805 .num_resets = ARRAY_SIZE(tegra20_mc_resets), 806 .icc_ops = &tegra20_mc_icc_ops, 807 .ops = &tegra20_mc_ops, 808};