linux/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
<<
>>
Prefs
   1/*
   2 * Copyright 2018 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 */
  23#include "amdgpu.h"
  24#include "df_v3_6.h"
  25
  26#include "df/df_3_6_default.h"
  27#include "df/df_3_6_offset.h"
  28#include "df/df_3_6_sh_mask.h"
  29
  30#define DF_3_6_SMN_REG_INST_DIST        0x8
  31#define DF_3_6_INST_CNT                 8
  32
  33static u32 df_v3_6_channel_number[] = {1, 2, 0, 4, 0, 8, 0,
  34                                       16, 32, 0, 0, 0, 2, 4, 8};
  35
  36/* init df format attrs */
  37AMDGPU_PMU_ATTR(event,          "config:0-7");
  38AMDGPU_PMU_ATTR(instance,       "config:8-15");
  39AMDGPU_PMU_ATTR(umask,          "config:16-23");
  40
  41/* df format attributes  */
  42static struct attribute *df_v3_6_format_attrs[] = {
  43        &pmu_attr_event.attr,
  44        &pmu_attr_instance.attr,
  45        &pmu_attr_umask.attr,
  46        NULL
  47};
  48
  49/* df format attribute group */
  50static struct attribute_group df_v3_6_format_attr_group = {
  51        .name = "format",
  52        .attrs = df_v3_6_format_attrs,
  53};
  54
  55/* df event attrs */
  56AMDGPU_PMU_ATTR(cake0_pcsout_txdata,
  57                      "event=0x7,instance=0x46,umask=0x2");
  58AMDGPU_PMU_ATTR(cake1_pcsout_txdata,
  59                      "event=0x7,instance=0x47,umask=0x2");
  60AMDGPU_PMU_ATTR(cake0_pcsout_txmeta,
  61                      "event=0x7,instance=0x46,umask=0x4");
  62AMDGPU_PMU_ATTR(cake1_pcsout_txmeta,
  63                      "event=0x7,instance=0x47,umask=0x4");
  64AMDGPU_PMU_ATTR(cake0_ftiinstat_reqalloc,
  65                      "event=0xb,instance=0x46,umask=0x4");
  66AMDGPU_PMU_ATTR(cake1_ftiinstat_reqalloc,
  67                      "event=0xb,instance=0x47,umask=0x4");
  68AMDGPU_PMU_ATTR(cake0_ftiinstat_rspalloc,
  69                      "event=0xb,instance=0x46,umask=0x8");
  70AMDGPU_PMU_ATTR(cake1_ftiinstat_rspalloc,
  71                      "event=0xb,instance=0x47,umask=0x8");
  72
  73/* df event attributes  */
  74static struct attribute *df_v3_6_event_attrs[] = {
  75        &pmu_attr_cake0_pcsout_txdata.attr,
  76        &pmu_attr_cake1_pcsout_txdata.attr,
  77        &pmu_attr_cake0_pcsout_txmeta.attr,
  78        &pmu_attr_cake1_pcsout_txmeta.attr,
  79        &pmu_attr_cake0_ftiinstat_reqalloc.attr,
  80        &pmu_attr_cake1_ftiinstat_reqalloc.attr,
  81        &pmu_attr_cake0_ftiinstat_rspalloc.attr,
  82        &pmu_attr_cake1_ftiinstat_rspalloc.attr,
  83        NULL
  84};
  85
  86/* df event attribute group */
  87static struct attribute_group df_v3_6_event_attr_group = {
  88        .name = "events",
  89        .attrs = df_v3_6_event_attrs
  90};
  91
  92/* df event attr groups  */
  93const struct attribute_group *df_v3_6_attr_groups[] = {
  94                &df_v3_6_format_attr_group,
  95                &df_v3_6_event_attr_group,
  96                NULL
  97};
  98
  99static uint64_t df_v3_6_get_fica(struct amdgpu_device *adev,
 100                                 uint32_t ficaa_val)
 101{
 102        unsigned long flags, address, data;
 103        uint32_t ficadl_val, ficadh_val;
 104
 105        address = adev->nbio.funcs->get_pcie_index_offset(adev);
 106        data = adev->nbio.funcs->get_pcie_data_offset(adev);
 107
 108        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
 109        WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3);
 110        WREG32(data, ficaa_val);
 111
 112        WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataLo3);
 113        ficadl_val = RREG32(data);
 114
 115        WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3);
 116        ficadh_val = RREG32(data);
 117
 118        spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
 119
 120        return (((ficadh_val & 0xFFFFFFFFFFFFFFFF) << 32) | ficadl_val);
 121}
 122
 123static void df_v3_6_set_fica(struct amdgpu_device *adev, uint32_t ficaa_val,
 124                             uint32_t ficadl_val, uint32_t ficadh_val)
 125{
 126        unsigned long flags, address, data;
 127
 128        address = adev->nbio.funcs->get_pcie_index_offset(adev);
 129        data = adev->nbio.funcs->get_pcie_data_offset(adev);
 130
 131        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
 132        WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3);
 133        WREG32(data, ficaa_val);
 134
 135        WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataLo3);
 136        WREG32(data, ficadl_val);
 137
 138        WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3);
 139        WREG32(data, ficadh_val);
 140
 141        spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
 142}
 143
 144/*
 145 * df_v3_6_perfmon_rreg - read perfmon lo and hi
 146 *
 147 * required to be atomic.  no mmio method provided so subsequent reads for lo
 148 * and hi require to preserve df finite state machine
 149 */
 150static void df_v3_6_perfmon_rreg(struct amdgpu_device *adev,
 151                            uint32_t lo_addr, uint32_t *lo_val,
 152                            uint32_t hi_addr, uint32_t *hi_val)
 153{
 154        unsigned long flags, address, data;
 155
 156        address = adev->nbio.funcs->get_pcie_index_offset(adev);
 157        data = adev->nbio.funcs->get_pcie_data_offset(adev);
 158
 159        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
 160        WREG32(address, lo_addr);
 161        *lo_val = RREG32(data);
 162        WREG32(address, hi_addr);
 163        *hi_val = RREG32(data);
 164        spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
 165}
 166
 167/*
 168 * df_v3_6_perfmon_wreg - write to perfmon lo and hi
 169 *
 170 * required to be atomic.  no mmio method provided so subsequent reads after
 171 * data writes cannot occur to preserve data fabrics finite state machine.
 172 */
 173static void df_v3_6_perfmon_wreg(struct amdgpu_device *adev, uint32_t lo_addr,
 174                            uint32_t lo_val, uint32_t hi_addr, uint32_t hi_val)
 175{
 176        unsigned long flags, address, data;
 177
 178        address = adev->nbio.funcs->get_pcie_index_offset(adev);
 179        data = adev->nbio.funcs->get_pcie_data_offset(adev);
 180
 181        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
 182        WREG32(address, lo_addr);
 183        WREG32(data, lo_val);
 184        WREG32(address, hi_addr);
 185        WREG32(data, hi_val);
 186        spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
 187}
 188
 189/* same as perfmon_wreg but return status on write value check */
 190static int df_v3_6_perfmon_arm_with_status(struct amdgpu_device *adev,
 191                                          uint32_t lo_addr, uint32_t lo_val,
 192                                          uint32_t hi_addr, uint32_t  hi_val)
 193{
 194        unsigned long flags, address, data;
 195        uint32_t lo_val_rb, hi_val_rb;
 196
 197        address = adev->nbio.funcs->get_pcie_index_offset(adev);
 198        data = adev->nbio.funcs->get_pcie_data_offset(adev);
 199
 200        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
 201        WREG32(address, lo_addr);
 202        WREG32(data, lo_val);
 203        WREG32(address, hi_addr);
 204        WREG32(data, hi_val);
 205
 206        WREG32(address, lo_addr);
 207        lo_val_rb = RREG32(data);
 208        WREG32(address, hi_addr);
 209        hi_val_rb = RREG32(data);
 210        spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
 211
 212        if (!(lo_val == lo_val_rb && hi_val == hi_val_rb))
 213                return -EBUSY;
 214
 215        return 0;
 216}
 217
 218
 219/*
 220 * retry arming counters every 100 usecs within 1 millisecond interval.
 221 * if retry fails after time out, return error.
 222 */
 223#define ARM_RETRY_USEC_TIMEOUT  1000
 224#define ARM_RETRY_USEC_INTERVAL 100
 225static int df_v3_6_perfmon_arm_with_retry(struct amdgpu_device *adev,
 226                                          uint32_t lo_addr, uint32_t lo_val,
 227                                          uint32_t hi_addr, uint32_t  hi_val)
 228{
 229        int countdown = ARM_RETRY_USEC_TIMEOUT;
 230
 231        while (countdown) {
 232
 233                if (!df_v3_6_perfmon_arm_with_status(adev, lo_addr, lo_val,
 234                                                     hi_addr, hi_val))
 235                        break;
 236
 237                countdown -= ARM_RETRY_USEC_INTERVAL;
 238                udelay(ARM_RETRY_USEC_INTERVAL);
 239        }
 240
 241        return countdown > 0 ? 0 : -ETIME;
 242}
 243
 244/* get the number of df counters available */
 245static ssize_t df_v3_6_get_df_cntr_avail(struct device *dev,
 246                struct device_attribute *attr,
 247                char *buf)
 248{
 249        struct amdgpu_device *adev;
 250        struct drm_device *ddev;
 251        int i, count;
 252
 253        ddev = dev_get_drvdata(dev);
 254        adev = ddev->dev_private;
 255        count = 0;
 256
 257        for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
 258                if (adev->df_perfmon_config_assign_mask[i] == 0)
 259                        count++;
 260        }
 261
 262        return snprintf(buf, PAGE_SIZE, "%i\n", count);
 263}
 264
 265/* device attr for available perfmon counters */
 266static DEVICE_ATTR(df_cntr_avail, S_IRUGO, df_v3_6_get_df_cntr_avail, NULL);
 267
 268static void df_v3_6_query_hashes(struct amdgpu_device *adev)
 269{
 270        u32 tmp;
 271
 272        adev->df.hash_status.hash_64k = false;
 273        adev->df.hash_status.hash_2m = false;
 274        adev->df.hash_status.hash_1g = false;
 275
 276        if (adev->asic_type != CHIP_ARCTURUS)
 277                return;
 278
 279        /* encoding for hash-enabled on Arcturus */
 280        if (adev->df.funcs->get_fb_channel_number(adev) == 0xe) {
 281                tmp = RREG32_SOC15(DF, 0, mmDF_CS_UMC_AON0_DfGlobalCtrl);
 282                adev->df.hash_status.hash_64k = REG_GET_FIELD(tmp,
 283                                                DF_CS_UMC_AON0_DfGlobalCtrl,
 284                                                GlbHashIntlvCtl64K);
 285                adev->df.hash_status.hash_2m = REG_GET_FIELD(tmp,
 286                                                DF_CS_UMC_AON0_DfGlobalCtrl,
 287                                                GlbHashIntlvCtl2M);
 288                adev->df.hash_status.hash_1g = REG_GET_FIELD(tmp,
 289                                                DF_CS_UMC_AON0_DfGlobalCtrl,
 290                                                GlbHashIntlvCtl1G);
 291        }
 292}
 293
 294/* init perfmons */
 295static void df_v3_6_sw_init(struct amdgpu_device *adev)
 296{
 297        int i, ret;
 298
 299        ret = device_create_file(adev->dev, &dev_attr_df_cntr_avail);
 300        if (ret)
 301                DRM_ERROR("failed to create file for available df counters\n");
 302
 303        for (i = 0; i < AMDGPU_MAX_DF_PERFMONS; i++)
 304                adev->df_perfmon_config_assign_mask[i] = 0;
 305
 306        df_v3_6_query_hashes(adev);
 307}
 308
 309static void df_v3_6_sw_fini(struct amdgpu_device *adev)
 310{
 311
 312        device_remove_file(adev->dev, &dev_attr_df_cntr_avail);
 313
 314}
 315
 316static void df_v3_6_enable_broadcast_mode(struct amdgpu_device *adev,
 317                                          bool enable)
 318{
 319        u32 tmp;
 320
 321        if (enable) {
 322                tmp = RREG32_SOC15(DF, 0, mmFabricConfigAccessControl);
 323                tmp &= ~FabricConfigAccessControl__CfgRegInstAccEn_MASK;
 324                WREG32_SOC15(DF, 0, mmFabricConfigAccessControl, tmp);
 325        } else
 326                WREG32_SOC15(DF, 0, mmFabricConfigAccessControl,
 327                             mmFabricConfigAccessControl_DEFAULT);
 328}
 329
 330static u32 df_v3_6_get_fb_channel_number(struct amdgpu_device *adev)
 331{
 332        u32 tmp;
 333
 334        tmp = RREG32_SOC15(DF, 0, mmDF_CS_UMC_AON0_DramBaseAddress0);
 335        tmp &= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan_MASK;
 336        tmp >>= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
 337
 338        return tmp;
 339}
 340
 341static u32 df_v3_6_get_hbm_channel_number(struct amdgpu_device *adev)
 342{
 343        int fb_channel_number;
 344
 345        fb_channel_number = adev->df.funcs->get_fb_channel_number(adev);
 346        if (fb_channel_number >= ARRAY_SIZE(df_v3_6_channel_number))
 347                fb_channel_number = 0;
 348
 349        return df_v3_6_channel_number[fb_channel_number];
 350}
 351
 352static void df_v3_6_update_medium_grain_clock_gating(struct amdgpu_device *adev,
 353                                                     bool enable)
 354{
 355        u32 tmp;
 356
 357        if (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG) {
 358                /* Put DF on broadcast mode */
 359                adev->df.funcs->enable_broadcast_mode(adev, true);
 360
 361                if (enable) {
 362                        tmp = RREG32_SOC15(DF, 0,
 363                                        mmDF_PIE_AON0_DfGlobalClkGater);
 364                        tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
 365                        tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
 366                        WREG32_SOC15(DF, 0,
 367                                        mmDF_PIE_AON0_DfGlobalClkGater, tmp);
 368                } else {
 369                        tmp = RREG32_SOC15(DF, 0,
 370                                        mmDF_PIE_AON0_DfGlobalClkGater);
 371                        tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
 372                        tmp |= DF_V3_6_MGCG_DISABLE;
 373                        WREG32_SOC15(DF, 0,
 374                                        mmDF_PIE_AON0_DfGlobalClkGater, tmp);
 375                }
 376
 377                /* Exit broadcast mode */
 378                adev->df.funcs->enable_broadcast_mode(adev, false);
 379        }
 380}
 381
 382static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
 383                                          u32 *flags)
 384{
 385        u32 tmp;
 386
 387        /* AMD_CG_SUPPORT_DF_MGCG */
 388        tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
 389        if (tmp & DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY)
 390                *flags |= AMD_CG_SUPPORT_DF_MGCG;
 391}
 392
 393/* get assigned df perfmon ctr as int */
 394static int df_v3_6_pmc_config_2_cntr(struct amdgpu_device *adev,
 395                                      uint64_t config)
 396{
 397        int i;
 398
 399        for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
 400                if ((config & 0x0FFFFFFUL) ==
 401                                        adev->df_perfmon_config_assign_mask[i])
 402                        return i;
 403        }
 404
 405        return -EINVAL;
 406}
 407
 408/* get address based on counter assignment */
 409static void df_v3_6_pmc_get_addr(struct amdgpu_device *adev,
 410                                 uint64_t config,
 411                                 int is_ctrl,
 412                                 uint32_t *lo_base_addr,
 413                                 uint32_t *hi_base_addr)
 414{
 415        int target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
 416
 417        if (target_cntr < 0)
 418                return;
 419
 420        switch (target_cntr) {
 421
 422        case 0:
 423                *lo_base_addr = is_ctrl ? smnPerfMonCtlLo4 : smnPerfMonCtrLo4;
 424                *hi_base_addr = is_ctrl ? smnPerfMonCtlHi4 : smnPerfMonCtrHi4;
 425                break;
 426        case 1:
 427                *lo_base_addr = is_ctrl ? smnPerfMonCtlLo5 : smnPerfMonCtrLo5;
 428                *hi_base_addr = is_ctrl ? smnPerfMonCtlHi5 : smnPerfMonCtrHi5;
 429                break;
 430        case 2:
 431                *lo_base_addr = is_ctrl ? smnPerfMonCtlLo6 : smnPerfMonCtrLo6;
 432                *hi_base_addr = is_ctrl ? smnPerfMonCtlHi6 : smnPerfMonCtrHi6;
 433                break;
 434        case 3:
 435                *lo_base_addr = is_ctrl ? smnPerfMonCtlLo7 : smnPerfMonCtrLo7;
 436                *hi_base_addr = is_ctrl ? smnPerfMonCtlHi7 : smnPerfMonCtrHi7;
 437                break;
 438
 439        }
 440
 441}
 442
 443/* get read counter address */
 444static void df_v3_6_pmc_get_read_settings(struct amdgpu_device *adev,
 445                                          uint64_t config,
 446                                          uint32_t *lo_base_addr,
 447                                          uint32_t *hi_base_addr)
 448{
 449        df_v3_6_pmc_get_addr(adev, config, 0, lo_base_addr, hi_base_addr);
 450}
 451
 452/* get control counter settings i.e. address and values to set */
 453static int df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev,
 454                                          uint64_t config,
 455                                          uint32_t *lo_base_addr,
 456                                          uint32_t *hi_base_addr,
 457                                          uint32_t *lo_val,
 458                                          uint32_t *hi_val)
 459{
 460
 461        uint32_t eventsel, instance, unitmask;
 462        uint32_t instance_10, instance_5432, instance_76;
 463
 464        df_v3_6_pmc_get_addr(adev, config, 1, lo_base_addr, hi_base_addr);
 465
 466        if ((*lo_base_addr == 0) || (*hi_base_addr == 0)) {
 467                DRM_ERROR("[DF PMC] addressing not retrieved! Lo: %x, Hi: %x",
 468                                *lo_base_addr, *hi_base_addr);
 469                return -ENXIO;
 470        }
 471
 472        eventsel = DF_V3_6_GET_EVENT(config) & 0x3f;
 473        unitmask = DF_V3_6_GET_UNITMASK(config) & 0xf;
 474        instance = DF_V3_6_GET_INSTANCE(config);
 475
 476        instance_10 = instance & 0x3;
 477        instance_5432 = (instance >> 2) & 0xf;
 478        instance_76 = (instance >> 6) & 0x3;
 479
 480        *lo_val = (unitmask << 8) | (instance_10 << 6) | eventsel | (1 << 22);
 481        *hi_val = (instance_76 << 29) | instance_5432;
 482
 483        DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
 484                config, *lo_base_addr, *hi_base_addr, *lo_val, *hi_val);
 485
 486        return 0;
 487}
 488
 489/* add df performance counters for read */
 490static int df_v3_6_pmc_add_cntr(struct amdgpu_device *adev,
 491                                   uint64_t config)
 492{
 493        int i, target_cntr;
 494
 495        target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
 496
 497        if (target_cntr >= 0)
 498                return 0;
 499
 500        for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
 501                if (adev->df_perfmon_config_assign_mask[i] == 0U) {
 502                        adev->df_perfmon_config_assign_mask[i] =
 503                                                        config & 0x0FFFFFFUL;
 504                        return 0;
 505                }
 506        }
 507
 508        return -ENOSPC;
 509}
 510
 511#define DEFERRED_ARM_MASK       (1 << 31)
 512static int df_v3_6_pmc_set_deferred(struct amdgpu_device *adev,
 513                                    uint64_t config, bool is_deferred)
 514{
 515        int target_cntr;
 516
 517        target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
 518
 519        if (target_cntr < 0)
 520                return -EINVAL;
 521
 522        if (is_deferred)
 523                adev->df_perfmon_config_assign_mask[target_cntr] |=
 524                                                        DEFERRED_ARM_MASK;
 525        else
 526                adev->df_perfmon_config_assign_mask[target_cntr] &=
 527                                                        ~DEFERRED_ARM_MASK;
 528
 529        return 0;
 530}
 531
 532static bool df_v3_6_pmc_is_deferred(struct amdgpu_device *adev,
 533                                    uint64_t config)
 534{
 535        int target_cntr;
 536
 537        target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
 538
 539        /*
 540         * we never get target_cntr < 0 since this funciton is only called in
 541         * pmc_count for now but we should check anyways.
 542         */
 543        return (target_cntr >= 0 &&
 544                        (adev->df_perfmon_config_assign_mask[target_cntr]
 545                        & DEFERRED_ARM_MASK));
 546
 547}
 548
 549/* release performance counter */
 550static void df_v3_6_pmc_release_cntr(struct amdgpu_device *adev,
 551                                     uint64_t config)
 552{
 553        int target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
 554
 555        if (target_cntr >= 0)
 556                adev->df_perfmon_config_assign_mask[target_cntr] = 0ULL;
 557}
 558
 559
 560static void df_v3_6_reset_perfmon_cntr(struct amdgpu_device *adev,
 561                                         uint64_t config)
 562{
 563        uint32_t lo_base_addr, hi_base_addr;
 564
 565        df_v3_6_pmc_get_read_settings(adev, config, &lo_base_addr,
 566                                      &hi_base_addr);
 567
 568        if ((lo_base_addr == 0) || (hi_base_addr == 0))
 569                return;
 570
 571        df_v3_6_perfmon_wreg(adev, lo_base_addr, 0, hi_base_addr, 0);
 572}
 573
 574static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config,
 575                             int is_enable)
 576{
 577        uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
 578        int err = 0, ret = 0;
 579
 580        switch (adev->asic_type) {
 581        case CHIP_VEGA20:
 582                if (is_enable)
 583                        return df_v3_6_pmc_add_cntr(adev, config);
 584
 585                df_v3_6_reset_perfmon_cntr(adev, config);
 586
 587                ret = df_v3_6_pmc_get_ctrl_settings(adev,
 588                                        config,
 589                                        &lo_base_addr,
 590                                        &hi_base_addr,
 591                                        &lo_val,
 592                                        &hi_val);
 593
 594                if (ret)
 595                        return ret;
 596
 597                err = df_v3_6_perfmon_arm_with_retry(adev,
 598                                                     lo_base_addr,
 599                                                     lo_val,
 600                                                     hi_base_addr,
 601                                                     hi_val);
 602
 603                if (err)
 604                        ret = df_v3_6_pmc_set_deferred(adev, config, true);
 605
 606                break;
 607        default:
 608                break;
 609        }
 610
 611        return ret;
 612}
 613
 614static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config,
 615                            int is_disable)
 616{
 617        uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
 618        int ret = 0;
 619
 620        switch (adev->asic_type) {
 621        case CHIP_VEGA20:
 622                ret = df_v3_6_pmc_get_ctrl_settings(adev,
 623                        config,
 624                        &lo_base_addr,
 625                        &hi_base_addr,
 626                        &lo_val,
 627                        &hi_val);
 628
 629                if (ret)
 630                        return ret;
 631
 632                df_v3_6_reset_perfmon_cntr(adev, config);
 633
 634                if (is_disable)
 635                        df_v3_6_pmc_release_cntr(adev, config);
 636
 637                break;
 638        default:
 639                break;
 640        }
 641
 642        return ret;
 643}
 644
 645static void df_v3_6_pmc_get_count(struct amdgpu_device *adev,
 646                                  uint64_t config,
 647                                  uint64_t *count)
 648{
 649        uint32_t lo_base_addr, hi_base_addr, lo_val = 0, hi_val = 0;
 650        *count = 0;
 651
 652        switch (adev->asic_type) {
 653        case CHIP_VEGA20:
 654                df_v3_6_pmc_get_read_settings(adev, config, &lo_base_addr,
 655                                      &hi_base_addr);
 656
 657                if ((lo_base_addr == 0) || (hi_base_addr == 0))
 658                        return;
 659
 660                /* rearm the counter or throw away count value on failure */
 661                if (df_v3_6_pmc_is_deferred(adev, config)) {
 662                        int rearm_err = df_v3_6_perfmon_arm_with_status(adev,
 663                                                        lo_base_addr, lo_val,
 664                                                        hi_base_addr, hi_val);
 665
 666                        if (rearm_err)
 667                                return;
 668
 669                        df_v3_6_pmc_set_deferred(adev, config, false);
 670                }
 671
 672                df_v3_6_perfmon_rreg(adev, lo_base_addr, &lo_val,
 673                                hi_base_addr, &hi_val);
 674
 675                *count  = ((hi_val | 0ULL) << 32) | (lo_val | 0ULL);
 676
 677                if (*count >= DF_V3_6_PERFMON_OVERFLOW)
 678                        *count = 0;
 679
 680                DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
 681                         config, lo_base_addr, hi_base_addr, lo_val, hi_val);
 682
 683                break;
 684        default:
 685                break;
 686        }
 687}
 688
 689static uint64_t df_v3_6_get_dram_base_addr(struct amdgpu_device *adev,
 690                                           uint32_t df_inst)
 691{
 692        uint32_t base_addr_reg_val      = 0;
 693        uint64_t base_addr              = 0;
 694
 695        base_addr_reg_val = RREG32_PCIE(smnDF_CS_UMC_AON0_DramBaseAddress0 +
 696                                        df_inst * DF_3_6_SMN_REG_INST_DIST);
 697
 698        if (REG_GET_FIELD(base_addr_reg_val,
 699                          DF_CS_UMC_AON0_DramBaseAddress0,
 700                          AddrRngVal) == 0) {
 701                DRM_WARN("address range not valid");
 702                return 0;
 703        }
 704
 705        base_addr = REG_GET_FIELD(base_addr_reg_val,
 706                                  DF_CS_UMC_AON0_DramBaseAddress0,
 707                                  DramBaseAddr);
 708
 709        return base_addr << 28;
 710}
 711
 712static uint32_t df_v3_6_get_df_inst_id(struct amdgpu_device *adev)
 713{
 714        uint32_t xgmi_node_id   = 0;
 715        uint32_t df_inst_id     = 0;
 716
 717        /* Walk through DF dst nodes to find current XGMI node */
 718        for (df_inst_id = 0; df_inst_id < DF_3_6_INST_CNT; df_inst_id++) {
 719
 720                xgmi_node_id = RREG32_PCIE(smnDF_CS_UMC_AON0_DramLimitAddress0 +
 721                                           df_inst_id * DF_3_6_SMN_REG_INST_DIST);
 722                xgmi_node_id = REG_GET_FIELD(xgmi_node_id,
 723                                             DF_CS_UMC_AON0_DramLimitAddress0,
 724                                             DstFabricID);
 725
 726                /* TODO: establish reason dest fabric id is offset by 7 */
 727                xgmi_node_id = xgmi_node_id >> 7;
 728
 729                if (adev->gmc.xgmi.physical_node_id == xgmi_node_id)
 730                        break;
 731        }
 732
 733        if (df_inst_id == DF_3_6_INST_CNT) {
 734                DRM_WARN("cant match df dst id with gpu node");
 735                return 0;
 736        }
 737
 738        return df_inst_id;
 739}
 740
 741const struct amdgpu_df_funcs df_v3_6_funcs = {
 742        .sw_init = df_v3_6_sw_init,
 743        .sw_fini = df_v3_6_sw_fini,
 744        .enable_broadcast_mode = df_v3_6_enable_broadcast_mode,
 745        .get_fb_channel_number = df_v3_6_get_fb_channel_number,
 746        .get_hbm_channel_number = df_v3_6_get_hbm_channel_number,
 747        .update_medium_grain_clock_gating =
 748                        df_v3_6_update_medium_grain_clock_gating,
 749        .get_clockgating_state = df_v3_6_get_clockgating_state,
 750        .pmc_start = df_v3_6_pmc_start,
 751        .pmc_stop = df_v3_6_pmc_stop,
 752        .pmc_get_count = df_v3_6_pmc_get_count,
 753        .get_fica = df_v3_6_get_fica,
 754        .set_fica = df_v3_6_set_fica,
 755        .get_dram_base_addr = df_v3_6_get_dram_base_addr,
 756        .get_df_inst_id = df_v3_6_get_df_inst_id
 757};
 758