Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
0004  */
0005 
0006 #include <linux/bitfield.h>
0007 #include <linux/delay.h>
0008 #include <linux/mutex.h>
0009 #include <linux/of_device.h>
0010 #include <linux/slab.h>
0011 #include <linux/string.h>
0012 
0013 #include <dt-bindings/memory/tegra20-mc.h>
0014 
0015 #include "mc.h"
0016 
0017 #define MC_STAT_CONTROL             0x90
0018 #define MC_STAT_EMC_CLOCK_LIMIT         0xa0
0019 #define MC_STAT_EMC_CLOCKS          0xa4
0020 #define MC_STAT_EMC_CONTROL_0           0xa8
0021 #define MC_STAT_EMC_CONTROL_1           0xac
0022 #define MC_STAT_EMC_COUNT_0         0xb8
0023 #define MC_STAT_EMC_COUNT_1         0xbc
0024 
0025 #define MC_STAT_CONTROL_CLIENT_ID       GENMASK(13,  8)
0026 #define MC_STAT_CONTROL_EVENT           GENMASK(23, 16)
0027 #define MC_STAT_CONTROL_PRI_EVENT       GENMASK(25, 24)
0028 #define MC_STAT_CONTROL_FILTER_CLIENT_ENABLE    GENMASK(26, 26)
0029 #define MC_STAT_CONTROL_FILTER_PRI      GENMASK(29, 28)
0030 
0031 #define MC_STAT_CONTROL_PRI_EVENT_HP        0
0032 #define MC_STAT_CONTROL_PRI_EVENT_TM        1
0033 #define MC_STAT_CONTROL_PRI_EVENT_BW        2
0034 
0035 #define MC_STAT_CONTROL_FILTER_PRI_DISABLE  0
0036 #define MC_STAT_CONTROL_FILTER_PRI_NO       1
0037 #define MC_STAT_CONTROL_FILTER_PRI_YES      2
0038 
0039 #define MC_STAT_CONTROL_EVENT_QUALIFIED     0
0040 #define MC_STAT_CONTROL_EVENT_ANY_READ      1
0041 #define MC_STAT_CONTROL_EVENT_ANY_WRITE     2
0042 #define MC_STAT_CONTROL_EVENT_RD_WR_CHANGE  3
0043 #define MC_STAT_CONTROL_EVENT_SUCCESSIVE    4
0044 #define MC_STAT_CONTROL_EVENT_ARB_BANK_AA   5
0045 #define MC_STAT_CONTROL_EVENT_ARB_BANK_BB   6
0046 #define MC_STAT_CONTROL_EVENT_PAGE_MISS     7
0047 #define MC_STAT_CONTROL_EVENT_AUTO_PRECHARGE    8
0048 
0049 #define EMC_GATHER_RST              (0 << 8)
0050 #define EMC_GATHER_CLEAR            (1 << 8)
0051 #define EMC_GATHER_DISABLE          (2 << 8)
0052 #define EMC_GATHER_ENABLE           (3 << 8)
0053 
0054 #define MC_STAT_SAMPLE_TIME_USEC        16000
0055 
0056 /* we store collected statistics as a fixed point values */
0057 #define MC_FX_FRAC_SCALE            100
0058 
0059 static DEFINE_MUTEX(tegra20_mc_stat_lock);
0060 
0061 struct tegra20_mc_stat_gather {
0062     unsigned int pri_filter;
0063     unsigned int pri_event;
0064     unsigned int result;
0065     unsigned int client;
0066     unsigned int event;
0067     bool client_enb;
0068 };
0069 
0070 struct tegra20_mc_stat {
0071     struct tegra20_mc_stat_gather gather0;
0072     struct tegra20_mc_stat_gather gather1;
0073     unsigned int sample_time_usec;
0074     const struct tegra_mc *mc;
0075 };
0076 
0077 struct tegra20_mc_client_stat {
0078     unsigned int events;
0079     unsigned int arb_high_prio;
0080     unsigned int arb_timeout;
0081     unsigned int arb_bandwidth;
0082     unsigned int rd_wr_change;
0083     unsigned int successive;
0084     unsigned int page_miss;
0085     unsigned int auto_precharge;
0086     unsigned int arb_bank_aa;
0087     unsigned int arb_bank_bb;
0088 };
0089 
0090 static const struct tegra_mc_client tegra20_mc_clients[] = {
0091     {
0092         .id = 0x00,
0093         .name = "display0a",
0094     }, {
0095         .id = 0x01,
0096         .name = "display0ab",
0097     }, {
0098         .id = 0x02,
0099         .name = "display0b",
0100     }, {
0101         .id = 0x03,
0102         .name = "display0bb",
0103     }, {
0104         .id = 0x04,
0105         .name = "display0c",
0106     }, {
0107         .id = 0x05,
0108         .name = "display0cb",
0109     }, {
0110         .id = 0x06,
0111         .name = "display1b",
0112     }, {
0113         .id = 0x07,
0114         .name = "display1bb",
0115     }, {
0116         .id = 0x08,
0117         .name = "eppup",
0118     }, {
0119         .id = 0x09,
0120         .name = "g2pr",
0121     }, {
0122         .id = 0x0a,
0123         .name = "g2sr",
0124     }, {
0125         .id = 0x0b,
0126         .name = "mpeunifbr",
0127     }, {
0128         .id = 0x0c,
0129         .name = "viruv",
0130     }, {
0131         .id = 0x0d,
0132         .name = "avpcarm7r",
0133     }, {
0134         .id = 0x0e,
0135         .name = "displayhc",
0136     }, {
0137         .id = 0x0f,
0138         .name = "displayhcb",
0139     }, {
0140         .id = 0x10,
0141         .name = "fdcdrd",
0142     }, {
0143         .id = 0x11,
0144         .name = "g2dr",
0145     }, {
0146         .id = 0x12,
0147         .name = "host1xdmar",
0148     }, {
0149         .id = 0x13,
0150         .name = "host1xr",
0151     }, {
0152         .id = 0x14,
0153         .name = "idxsrd",
0154     }, {
0155         .id = 0x15,
0156         .name = "mpcorer",
0157     }, {
0158         .id = 0x16,
0159         .name = "mpe_ipred",
0160     }, {
0161         .id = 0x17,
0162         .name = "mpeamemrd",
0163     }, {
0164         .id = 0x18,
0165         .name = "mpecsrd",
0166     }, {
0167         .id = 0x19,
0168         .name = "ppcsahbdmar",
0169     }, {
0170         .id = 0x1a,
0171         .name = "ppcsahbslvr",
0172     }, {
0173         .id = 0x1b,
0174         .name = "texsrd",
0175     }, {
0176         .id = 0x1c,
0177         .name = "vdebsevr",
0178     }, {
0179         .id = 0x1d,
0180         .name = "vdember",
0181     }, {
0182         .id = 0x1e,
0183         .name = "vdemcer",
0184     }, {
0185         .id = 0x1f,
0186         .name = "vdetper",
0187     }, {
0188         .id = 0x20,
0189         .name = "eppu",
0190     }, {
0191         .id = 0x21,
0192         .name = "eppv",
0193     }, {
0194         .id = 0x22,
0195         .name = "eppy",
0196     }, {
0197         .id = 0x23,
0198         .name = "mpeunifbw",
0199     }, {
0200         .id = 0x24,
0201         .name = "viwsb",
0202     }, {
0203         .id = 0x25,
0204         .name = "viwu",
0205     }, {
0206         .id = 0x26,
0207         .name = "viwv",
0208     }, {
0209         .id = 0x27,
0210         .name = "viwy",
0211     }, {
0212         .id = 0x28,
0213         .name = "g2dw",
0214     }, {
0215         .id = 0x29,
0216         .name = "avpcarm7w",
0217     }, {
0218         .id = 0x2a,
0219         .name = "fdcdwr",
0220     }, {
0221         .id = 0x2b,
0222         .name = "host1xw",
0223     }, {
0224         .id = 0x2c,
0225         .name = "ispw",
0226     }, {
0227         .id = 0x2d,
0228         .name = "mpcorew",
0229     }, {
0230         .id = 0x2e,
0231         .name = "mpecswr",
0232     }, {
0233         .id = 0x2f,
0234         .name = "ppcsahbdmaw",
0235     }, {
0236         .id = 0x30,
0237         .name = "ppcsahbslvw",
0238     }, {
0239         .id = 0x31,
0240         .name = "vdebsevw",
0241     }, {
0242         .id = 0x32,
0243         .name = "vdembew",
0244     }, {
0245         .id = 0x33,
0246         .name = "vdetpmw",
0247     },
0248 };
0249 
0250 #define TEGRA20_MC_RESET(_name, _control, _status, _reset, _bit)    \
0251     {                               \
0252         .name = #_name,                     \
0253         .id = TEGRA20_MC_RESET_##_name,             \
0254         .control = _control,                    \
0255         .status = _status,                  \
0256         .reset = _reset,                    \
0257         .bit = _bit,                        \
0258     }
0259 
0260 static const struct tegra_mc_reset tegra20_mc_resets[] = {
0261     TEGRA20_MC_RESET(AVPC,   0x100, 0x140, 0x104,  0),
0262     TEGRA20_MC_RESET(DC,     0x100, 0x144, 0x104,  1),
0263     TEGRA20_MC_RESET(DCB,    0x100, 0x148, 0x104,  2),
0264     TEGRA20_MC_RESET(EPP,    0x100, 0x14c, 0x104,  3),
0265     TEGRA20_MC_RESET(2D,     0x100, 0x150, 0x104,  4),
0266     TEGRA20_MC_RESET(HC,     0x100, 0x154, 0x104,  5),
0267     TEGRA20_MC_RESET(ISP,    0x100, 0x158, 0x104,  6),
0268     TEGRA20_MC_RESET(MPCORE, 0x100, 0x15c, 0x104,  7),
0269     TEGRA20_MC_RESET(MPEA,   0x100, 0x160, 0x104,  8),
0270     TEGRA20_MC_RESET(MPEB,   0x100, 0x164, 0x104,  9),
0271     TEGRA20_MC_RESET(MPEC,   0x100, 0x168, 0x104, 10),
0272     TEGRA20_MC_RESET(3D,     0x100, 0x16c, 0x104, 11),
0273     TEGRA20_MC_RESET(PPCS,   0x100, 0x170, 0x104, 12),
0274     TEGRA20_MC_RESET(VDE,    0x100, 0x174, 0x104, 13),
0275     TEGRA20_MC_RESET(VI,     0x100, 0x178, 0x104, 14),
0276 };
0277 
0278 static int tegra20_mc_hotreset_assert(struct tegra_mc *mc,
0279                       const struct tegra_mc_reset *rst)
0280 {
0281     unsigned long flags;
0282     u32 value;
0283 
0284     spin_lock_irqsave(&mc->lock, flags);
0285 
0286     value = mc_readl(mc, rst->reset);
0287     mc_writel(mc, value & ~BIT(rst->bit), rst->reset);
0288 
0289     spin_unlock_irqrestore(&mc->lock, flags);
0290 
0291     return 0;
0292 }
0293 
0294 static int tegra20_mc_hotreset_deassert(struct tegra_mc *mc,
0295                     const struct tegra_mc_reset *rst)
0296 {
0297     unsigned long flags;
0298     u32 value;
0299 
0300     spin_lock_irqsave(&mc->lock, flags);
0301 
0302     value = mc_readl(mc, rst->reset);
0303     mc_writel(mc, value | BIT(rst->bit), rst->reset);
0304 
0305     spin_unlock_irqrestore(&mc->lock, flags);
0306 
0307     return 0;
0308 }
0309 
0310 static int tegra20_mc_block_dma(struct tegra_mc *mc,
0311                 const struct tegra_mc_reset *rst)
0312 {
0313     unsigned long flags;
0314     u32 value;
0315 
0316     spin_lock_irqsave(&mc->lock, flags);
0317 
0318     value = mc_readl(mc, rst->control) & ~BIT(rst->bit);
0319     mc_writel(mc, value, rst->control);
0320 
0321     spin_unlock_irqrestore(&mc->lock, flags);
0322 
0323     return 0;
0324 }
0325 
0326 static bool tegra20_mc_dma_idling(struct tegra_mc *mc,
0327                   const struct tegra_mc_reset *rst)
0328 {
0329     return mc_readl(mc, rst->status) == 0;
0330 }
0331 
0332 static int tegra20_mc_reset_status(struct tegra_mc *mc,
0333                    const struct tegra_mc_reset *rst)
0334 {
0335     return (mc_readl(mc, rst->reset) & BIT(rst->bit)) == 0;
0336 }
0337 
0338 static int tegra20_mc_unblock_dma(struct tegra_mc *mc,
0339                   const struct tegra_mc_reset *rst)
0340 {
0341     unsigned long flags;
0342     u32 value;
0343 
0344     spin_lock_irqsave(&mc->lock, flags);
0345 
0346     value = mc_readl(mc, rst->control) | BIT(rst->bit);
0347     mc_writel(mc, value, rst->control);
0348 
0349     spin_unlock_irqrestore(&mc->lock, flags);
0350 
0351     return 0;
0352 }
0353 
0354 static const struct tegra_mc_reset_ops tegra20_mc_reset_ops = {
0355     .hotreset_assert = tegra20_mc_hotreset_assert,
0356     .hotreset_deassert = tegra20_mc_hotreset_deassert,
0357     .block_dma = tegra20_mc_block_dma,
0358     .dma_idling = tegra20_mc_dma_idling,
0359     .unblock_dma = tegra20_mc_unblock_dma,
0360     .reset_status = tegra20_mc_reset_status,
0361 };
0362 
0363 static int tegra20_mc_icc_set(struct icc_node *src, struct icc_node *dst)
0364 {
0365     /*
0366      * It should be possible to tune arbitration knobs here, but the
0367      * default values are known to work well on all devices. Hence
0368      * nothing to do here so far.
0369      */
0370     return 0;
0371 }
0372 
0373 static int tegra20_mc_icc_aggreate(struct icc_node *node, u32 tag, u32 avg_bw,
0374                    u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
0375 {
0376     /*
0377      * ISO clients need to reserve extra bandwidth up-front because
0378      * there could be high bandwidth pressure during initial filling
0379      * of the client's FIFO buffers.  Secondly, we need to take into
0380      * account impurities of the memory subsystem.
0381      */
0382     if (tag & TEGRA_MC_ICC_TAG_ISO)
0383         peak_bw = tegra_mc_scale_percents(peak_bw, 300);
0384 
0385     *agg_avg += avg_bw;
0386     *agg_peak = max(*agg_peak, peak_bw);
0387 
0388     return 0;
0389 }
0390 
0391 static struct icc_node_data *
0392 tegra20_mc_of_icc_xlate_extended(struct of_phandle_args *spec, void *data)
0393 {
0394     struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
0395     unsigned int i, idx = spec->args[0];
0396     struct icc_node_data *ndata;
0397     struct icc_node *node;
0398 
0399     list_for_each_entry(node, &mc->provider.nodes, node_list) {
0400         if (node->id != idx)
0401             continue;
0402 
0403         ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
0404         if (!ndata)
0405             return ERR_PTR(-ENOMEM);
0406 
0407         ndata->node = node;
0408 
0409         /* these clients are isochronous by default */
0410         if (strstarts(node->name, "display") ||
0411             strstarts(node->name, "vi"))
0412             ndata->tag = TEGRA_MC_ICC_TAG_ISO;
0413         else
0414             ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
0415 
0416         return ndata;
0417     }
0418 
0419     for (i = 0; i < mc->soc->num_clients; i++) {
0420         if (mc->soc->clients[i].id == idx)
0421             return ERR_PTR(-EPROBE_DEFER);
0422     }
0423 
0424     dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
0425 
0426     return ERR_PTR(-EINVAL);
0427 }
0428 
0429 static const struct tegra_mc_icc_ops tegra20_mc_icc_ops = {
0430     .xlate_extended = tegra20_mc_of_icc_xlate_extended,
0431     .aggregate = tegra20_mc_icc_aggreate,
0432     .set = tegra20_mc_icc_set,
0433 };
0434 
0435 static u32 tegra20_mc_stat_gather_control(const struct tegra20_mc_stat_gather *g)
0436 {
0437     u32 control;
0438 
0439     control  = FIELD_PREP(MC_STAT_CONTROL_EVENT, g->event);
0440     control |= FIELD_PREP(MC_STAT_CONTROL_CLIENT_ID, g->client);
0441     control |= FIELD_PREP(MC_STAT_CONTROL_PRI_EVENT, g->pri_event);
0442     control |= FIELD_PREP(MC_STAT_CONTROL_FILTER_PRI, g->pri_filter);
0443     control |= FIELD_PREP(MC_STAT_CONTROL_FILTER_CLIENT_ENABLE, g->client_enb);
0444 
0445     return control;
0446 }
0447 
0448 static void tegra20_mc_stat_gather(struct tegra20_mc_stat *stat)
0449 {
0450     u32 clocks, count0, count1, control_0, control_1;
0451     const struct tegra_mc *mc = stat->mc;
0452 
0453     control_0 = tegra20_mc_stat_gather_control(&stat->gather0);
0454     control_1 = tegra20_mc_stat_gather_control(&stat->gather1);
0455 
0456     /*
0457      * Reset statistic gathers state, select statistics collection mode
0458      * and set clocks counter saturation limit to maximum.
0459      */
0460     mc_writel(mc, 0x00000000, MC_STAT_CONTROL);
0461     mc_writel(mc,  control_0, MC_STAT_EMC_CONTROL_0);
0462     mc_writel(mc,  control_1, MC_STAT_EMC_CONTROL_1);
0463     mc_writel(mc, 0xffffffff, MC_STAT_EMC_CLOCK_LIMIT);
0464 
0465     mc_writel(mc, EMC_GATHER_ENABLE, MC_STAT_CONTROL);
0466     fsleep(stat->sample_time_usec);
0467     mc_writel(mc, EMC_GATHER_DISABLE, MC_STAT_CONTROL);
0468 
0469     count0 = mc_readl(mc, MC_STAT_EMC_COUNT_0);
0470     count1 = mc_readl(mc, MC_STAT_EMC_COUNT_1);
0471     clocks = mc_readl(mc, MC_STAT_EMC_CLOCKS);
0472     clocks = max(clocks / 100 / MC_FX_FRAC_SCALE, 1u);
0473 
0474     stat->gather0.result = DIV_ROUND_UP(count0, clocks);
0475     stat->gather1.result = DIV_ROUND_UP(count1, clocks);
0476 }
0477 
0478 static void tegra20_mc_stat_events(const struct tegra_mc *mc,
0479                    const struct tegra_mc_client *client0,
0480                    const struct tegra_mc_client *client1,
0481                    unsigned int pri_filter,
0482                    unsigned int pri_event,
0483                    unsigned int event,
0484                    unsigned int *result0,
0485                    unsigned int *result1)
0486 {
0487     struct tegra20_mc_stat stat = {};
0488 
0489     stat.gather0.client = client0 ? client0->id : 0;
0490     stat.gather0.pri_filter = pri_filter;
0491     stat.gather0.client_enb = !!client0;
0492     stat.gather0.pri_event = pri_event;
0493     stat.gather0.event = event;
0494 
0495     stat.gather1.client = client1 ? client1->id : 0;
0496     stat.gather1.pri_filter = pri_filter;
0497     stat.gather1.client_enb = !!client1;
0498     stat.gather1.pri_event = pri_event;
0499     stat.gather1.event = event;
0500 
0501     stat.sample_time_usec = MC_STAT_SAMPLE_TIME_USEC;
0502     stat.mc = mc;
0503 
0504     tegra20_mc_stat_gather(&stat);
0505 
0506     *result0 = stat.gather0.result;
0507     *result1 = stat.gather1.result;
0508 }
0509 
0510 static void tegra20_mc_collect_stats(const struct tegra_mc *mc,
0511                      struct tegra20_mc_client_stat *stats)
0512 {
0513     const struct tegra_mc_client *client0, *client1;
0514     unsigned int i;
0515 
0516     /* collect memory controller utilization percent for each client */
0517     for (i = 0; i < mc->soc->num_clients; i += 2) {
0518         client0 = &mc->soc->clients[i];
0519         client1 = &mc->soc->clients[i + 1];
0520 
0521         if (i + 1 == mc->soc->num_clients)
0522             client1 = NULL;
0523 
0524         tegra20_mc_stat_events(mc, client0, client1,
0525                        MC_STAT_CONTROL_FILTER_PRI_DISABLE,
0526                        MC_STAT_CONTROL_PRI_EVENT_HP,
0527                        MC_STAT_CONTROL_EVENT_QUALIFIED,
0528                        &stats[i + 0].events,
0529                        &stats[i + 1].events);
0530     }
0531 
0532     /* collect more info from active clients */
0533     for (i = 0; i < mc->soc->num_clients; i++) {
0534         unsigned int clienta, clientb = mc->soc->num_clients;
0535 
0536         for (client0 = NULL; i < mc->soc->num_clients; i++) {
0537             if (stats[i].events) {
0538                 client0 = &mc->soc->clients[i];
0539                 clienta = i++;
0540                 break;
0541             }
0542         }
0543 
0544         for (client1 = NULL; i < mc->soc->num_clients; i++) {
0545             if (stats[i].events) {
0546                 client1 = &mc->soc->clients[i];
0547                 clientb = i;
0548                 break;
0549             }
0550         }
0551 
0552         if (!client0 && !client1)
0553             break;
0554 
0555         tegra20_mc_stat_events(mc, client0, client1,
0556                        MC_STAT_CONTROL_FILTER_PRI_YES,
0557                        MC_STAT_CONTROL_PRI_EVENT_HP,
0558                        MC_STAT_CONTROL_EVENT_QUALIFIED,
0559                        &stats[clienta].arb_high_prio,
0560                        &stats[clientb].arb_high_prio);
0561 
0562         tegra20_mc_stat_events(mc, client0, client1,
0563                        MC_STAT_CONTROL_FILTER_PRI_YES,
0564                        MC_STAT_CONTROL_PRI_EVENT_TM,
0565                        MC_STAT_CONTROL_EVENT_QUALIFIED,
0566                        &stats[clienta].arb_timeout,
0567                        &stats[clientb].arb_timeout);
0568 
0569         tegra20_mc_stat_events(mc, client0, client1,
0570                        MC_STAT_CONTROL_FILTER_PRI_YES,
0571                        MC_STAT_CONTROL_PRI_EVENT_BW,
0572                        MC_STAT_CONTROL_EVENT_QUALIFIED,
0573                        &stats[clienta].arb_bandwidth,
0574                        &stats[clientb].arb_bandwidth);
0575 
0576         tegra20_mc_stat_events(mc, client0, client1,
0577                        MC_STAT_CONTROL_FILTER_PRI_DISABLE,
0578                        MC_STAT_CONTROL_PRI_EVENT_HP,
0579                        MC_STAT_CONTROL_EVENT_RD_WR_CHANGE,
0580                        &stats[clienta].rd_wr_change,
0581                        &stats[clientb].rd_wr_change);
0582 
0583         tegra20_mc_stat_events(mc, client0, client1,
0584                        MC_STAT_CONTROL_FILTER_PRI_DISABLE,
0585                        MC_STAT_CONTROL_PRI_EVENT_HP,
0586                        MC_STAT_CONTROL_EVENT_SUCCESSIVE,
0587                        &stats[clienta].successive,
0588                        &stats[clientb].successive);
0589 
0590         tegra20_mc_stat_events(mc, client0, client1,
0591                        MC_STAT_CONTROL_FILTER_PRI_DISABLE,
0592                        MC_STAT_CONTROL_PRI_EVENT_HP,
0593                        MC_STAT_CONTROL_EVENT_PAGE_MISS,
0594                        &stats[clienta].page_miss,
0595                        &stats[clientb].page_miss);
0596     }
0597 }
0598 
0599 static void tegra20_mc_printf_percents(struct seq_file *s,
0600                        const char *fmt,
0601                        unsigned int percents_fx)
0602 {
0603     char percents_str[8];
0604 
0605     snprintf(percents_str, ARRAY_SIZE(percents_str), "%3u.%02u%%",
0606          percents_fx / MC_FX_FRAC_SCALE, percents_fx % MC_FX_FRAC_SCALE);
0607 
0608     seq_printf(s, fmt, percents_str);
0609 }
0610 
0611 static int tegra20_mc_stats_show(struct seq_file *s, void *unused)
0612 {
0613     const struct tegra_mc *mc = dev_get_drvdata(s->private);
0614     struct tegra20_mc_client_stat *stats;
0615     unsigned int i;
0616 
0617     stats = kcalloc(mc->soc->num_clients + 1, sizeof(*stats), GFP_KERNEL);
0618     if (!stats)
0619         return -ENOMEM;
0620 
0621     mutex_lock(&tegra20_mc_stat_lock);
0622 
0623     tegra20_mc_collect_stats(mc, stats);
0624 
0625     mutex_unlock(&tegra20_mc_stat_lock);
0626 
0627     seq_puts(s, "Memory client   Events   Timeout   High priority   Bandwidth ARB   RW change   Successive   Page miss\n");
0628     seq_puts(s, "-----------------------------------------------------------------------------------------------------\n");
0629 
0630     for (i = 0; i < mc->soc->num_clients; i++) {
0631         seq_printf(s, "%-14s  ", mc->soc->clients[i].name);
0632 
0633         /* An event is generated when client performs R/W request. */
0634         tegra20_mc_printf_percents(s,  "%-9s", stats[i].events);
0635 
0636         /*
0637          * An event is generated based on the timeout (TM) signal
0638          * accompanying a request for arbitration.
0639          */
0640         tegra20_mc_printf_percents(s, "%-10s", stats[i].arb_timeout);
0641 
0642         /*
0643          * An event is generated based on the high-priority (HP) signal
0644          * accompanying a request for arbitration.
0645          */
0646         tegra20_mc_printf_percents(s, "%-16s", stats[i].arb_high_prio);
0647 
0648         /*
0649          * An event is generated based on the bandwidth (BW) signal
0650          * accompanying a request for arbitration.
0651          */
0652         tegra20_mc_printf_percents(s, "%-16s", stats[i].arb_bandwidth);
0653 
0654         /*
0655          * An event is generated when the memory controller switches
0656          * between making a read request to making a write request.
0657          */
0658         tegra20_mc_printf_percents(s, "%-12s", stats[i].rd_wr_change);
0659 
0660         /*
0661          * An even generated when the chosen client has wins arbitration
0662          * when it was also the winner at the previous request.  If a
0663          * client makes N requests in a row that are honored, SUCCESSIVE
0664          * will be counted (N-1) times.  Large values for this event
0665          * imply that if we were patient enough, all of those requests
0666          * could have been coalesced.
0667          */
0668         tegra20_mc_printf_percents(s, "%-13s", stats[i].successive);
0669 
0670         /*
0671          * An event is generated when the memory controller detects a
0672          * page miss for the current request.
0673          */
0674         tegra20_mc_printf_percents(s, "%-12s\n", stats[i].page_miss);
0675     }
0676 
0677     kfree(stats);
0678 
0679     return 0;
0680 }
0681 
0682 static int tegra20_mc_probe(struct tegra_mc *mc)
0683 {
0684     debugfs_create_devm_seqfile(mc->dev, "stats", mc->debugfs.root,
0685                     tegra20_mc_stats_show);
0686 
0687     return 0;
0688 }
0689 
0690 static int tegra20_mc_suspend(struct tegra_mc *mc)
0691 {
0692     int err;
0693 
0694     if (IS_ENABLED(CONFIG_TEGRA_IOMMU_GART) && mc->gart) {
0695         err = tegra_gart_suspend(mc->gart);
0696         if (err < 0)
0697             return err;
0698     }
0699 
0700     return 0;
0701 }
0702 
0703 static int tegra20_mc_resume(struct tegra_mc *mc)
0704 {
0705     int err;
0706 
0707     if (IS_ENABLED(CONFIG_TEGRA_IOMMU_GART) && mc->gart) {
0708         err = tegra_gart_resume(mc->gart);
0709         if (err < 0)
0710             return err;
0711     }
0712 
0713     return 0;
0714 }
0715 
0716 static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
0717 {
0718     struct tegra_mc *mc = data;
0719     unsigned long status;
0720     unsigned int bit;
0721 
0722     /* mask all interrupts to avoid flooding */
0723     status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
0724     if (!status)
0725         return IRQ_NONE;
0726 
0727     for_each_set_bit(bit, &status, 32) {
0728         const char *error = tegra_mc_status_names[bit];
0729         const char *direction = "read", *secure = "";
0730         const char *client, *desc;
0731         phys_addr_t addr;
0732         u32 value, reg;
0733         u8 id, type;
0734 
0735         switch (BIT(bit)) {
0736         case MC_INT_DECERR_EMEM:
0737             reg = MC_DECERR_EMEM_OTHERS_STATUS;
0738             value = mc_readl(mc, reg);
0739 
0740             id = value & mc->soc->client_id_mask;
0741             desc = tegra_mc_error_names[2];
0742 
0743             if (value & BIT(31))
0744                 direction = "write";
0745             break;
0746 
0747         case MC_INT_INVALID_GART_PAGE:
0748             reg = MC_GART_ERROR_REQ;
0749             value = mc_readl(mc, reg);
0750 
0751             id = (value >> 1) & mc->soc->client_id_mask;
0752             desc = tegra_mc_error_names[2];
0753 
0754             if (value & BIT(0))
0755                 direction = "write";
0756             break;
0757 
0758         case MC_INT_SECURITY_VIOLATION:
0759             reg = MC_SECURITY_VIOLATION_STATUS;
0760             value = mc_readl(mc, reg);
0761 
0762             id = value & mc->soc->client_id_mask;
0763             type = (value & BIT(30)) ? 4 : 3;
0764             desc = tegra_mc_error_names[type];
0765             secure = "secure ";
0766 
0767             if (value & BIT(31))
0768                 direction = "write";
0769             break;
0770 
0771         default:
0772             continue;
0773         }
0774 
0775         client = mc->soc->clients[id].name;
0776         addr = mc_readl(mc, reg + sizeof(u32));
0777 
0778         dev_err_ratelimited(mc->dev, "%s: %s%s @%pa: %s (%s)\n",
0779                     client, secure, direction, &addr, error,
0780                     desc);
0781     }
0782 
0783     /* clear interrupts */
0784     mc_writel(mc, status, MC_INTSTATUS);
0785 
0786     return IRQ_HANDLED;
0787 }
0788 
0789 static const struct tegra_mc_ops tegra20_mc_ops = {
0790     .probe = tegra20_mc_probe,
0791     .suspend = tegra20_mc_suspend,
0792     .resume = tegra20_mc_resume,
0793     .handle_irq = tegra20_mc_handle_irq,
0794 };
0795 
0796 const struct tegra_mc_soc tegra20_mc_soc = {
0797     .clients = tegra20_mc_clients,
0798     .num_clients = ARRAY_SIZE(tegra20_mc_clients),
0799     .num_address_bits = 32,
0800     .client_id_mask = 0x3f,
0801     .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
0802            MC_INT_DECERR_EMEM,
0803     .reset_ops = &tegra20_mc_reset_ops,
0804     .resets = tegra20_mc_resets,
0805     .num_resets = ARRAY_SIZE(tegra20_mc_resets),
0806     .icc_ops = &tegra20_mc_icc_ops,
0807     .ops = &tegra20_mc_ops,
0808 };