Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2012 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.  
  24. #include "drmP.h"
  25. #include "radeon.h"
  26. #include "sumod.h"
  27. #include "sumo_dpm.h"
  28. #include "ppsmc.h"
  29.  
  30. #define SUMO_SMU_SERVICE_ROUTINE_PG_INIT        1
  31. #define SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY  27
  32. #define SUMO_SMU_SERVICE_ROUTINE_GFX_SRV_ID_20  20
  33.  
  34. struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev);
  35.  
  36. static void sumo_send_msg_to_smu(struct radeon_device *rdev, u32 id)
  37. {
  38.         u32 gfx_int_req;
  39.         int i;
  40.  
  41.         for (i = 0; i < rdev->usec_timeout; i++) {
  42.                 if (RREG32(GFX_INT_STATUS) & INT_DONE)
  43.                         break;
  44.                 udelay(1);
  45.         }
  46.  
  47.         gfx_int_req = SERV_INDEX(id) | INT_REQ;
  48.         WREG32(GFX_INT_REQ, gfx_int_req);
  49.  
  50.         for (i = 0; i < rdev->usec_timeout; i++) {
  51.                 if (RREG32(GFX_INT_REQ) & INT_REQ)
  52.                         break;
  53.                 udelay(1);
  54.         }
  55.  
  56.         for (i = 0; i < rdev->usec_timeout; i++) {
  57.                 if (RREG32(GFX_INT_STATUS) & INT_ACK)
  58.                         break;
  59.                 udelay(1);
  60.         }
  61.  
  62.         for (i = 0; i < rdev->usec_timeout; i++) {
  63.                 if (RREG32(GFX_INT_STATUS) & INT_DONE)
  64.                         break;
  65.                 udelay(1);
  66.         }
  67.  
  68.         gfx_int_req &= ~INT_REQ;
  69.         WREG32(GFX_INT_REQ, gfx_int_req);
  70. }
  71.  
  72. void sumo_initialize_m3_arb(struct radeon_device *rdev)
  73. {
  74.         struct sumo_power_info *pi = sumo_get_pi(rdev);
  75.         u32 i;
  76.  
  77.         if (!pi->enable_dynamic_m3_arbiter)
  78.                 return;
  79.  
  80.         for (i = 0; i < NUMBER_OF_M3ARB_PARAM_SETS; i++)
  81.                 WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4),
  82.                            pi->sys_info.csr_m3_arb_cntl_default[i]);
  83.  
  84.         for (; i < NUMBER_OF_M3ARB_PARAM_SETS * 2; i++)
  85.                 WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4),
  86.                            pi->sys_info.csr_m3_arb_cntl_uvd[i % NUMBER_OF_M3ARB_PARAM_SETS]);
  87.  
  88.         for (; i < NUMBER_OF_M3ARB_PARAM_SETS * 3; i++)
  89.                 WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4),
  90.                            pi->sys_info.csr_m3_arb_cntl_fs3d[i % NUMBER_OF_M3ARB_PARAM_SETS]);
  91. }
  92.  
  93. static bool sumo_is_alt_vddnb_supported(struct radeon_device *rdev)
  94. {
  95.         struct sumo_power_info *pi = sumo_get_pi(rdev);
  96.         bool return_code = false;
  97.  
  98.         if (!pi->enable_alt_vddnb)
  99.                 return return_code;
  100.  
  101.         if ((rdev->family == CHIP_SUMO) || (rdev->family == CHIP_SUMO2)) {
  102.                 if (pi->fw_version >= 0x00010C00)
  103.                         return_code = true;
  104.         }
  105.  
  106.         return return_code;
  107. }
  108.  
  109. void sumo_smu_notify_alt_vddnb_change(struct radeon_device *rdev,
  110.                                       bool powersaving, bool force_nbps1)
  111. {
  112.         u32 param = 0;
  113.  
  114.         if (!sumo_is_alt_vddnb_supported(rdev))
  115.                 return;
  116.  
  117.         if (powersaving)
  118.                 param |= 1;
  119.  
  120.         if (force_nbps1)
  121.                 param |= 2;
  122.  
  123.         WREG32_RCU(RCU_ALTVDDNB_NOTIFY, param);
  124.  
  125.         sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY);
  126. }
  127.  
  128. void sumo_smu_pg_init(struct radeon_device *rdev)
  129. {
  130.         sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_PG_INIT);
  131. }
  132.  
  133. static u32 sumo_power_of_4(u32 unit)
  134. {
  135.         u32 ret = 1;
  136.         u32 i;
  137.  
  138.         for (i = 0; i < unit; i++)
  139.                 ret *= 4;
  140.  
  141.         return ret;
  142. }
  143.  
  144. void sumo_enable_boost_timer(struct radeon_device *rdev)
  145. {
  146.         struct sumo_power_info *pi = sumo_get_pi(rdev);
  147.         u32 period, unit, timer_value;
  148.         u32 xclk = radeon_get_xclk(rdev);
  149.  
  150.         unit = (RREG32_RCU(RCU_LCLK_SCALING_CNTL) & LCLK_SCALING_TIMER_PRESCALER_MASK)
  151.                 >> LCLK_SCALING_TIMER_PRESCALER_SHIFT;
  152.  
  153.         period = 100 * (xclk / 100 / sumo_power_of_4(unit));
  154.  
  155.         timer_value = (period << 16) | (unit << 4);
  156.  
  157.         WREG32_RCU(RCU_GNB_PWR_REP_TIMER_CNTL, timer_value);
  158.         WREG32_RCU(RCU_BOOST_MARGIN, pi->sys_info.sclk_dpm_boost_margin);
  159.         WREG32_RCU(RCU_THROTTLE_MARGIN, pi->sys_info.sclk_dpm_throttle_margin);
  160.         WREG32_RCU(GNB_TDP_LIMIT, pi->sys_info.gnb_tdp_limit);
  161.         WREG32_RCU(RCU_SclkDpmTdpLimitPG, pi->sys_info.sclk_dpm_tdp_limit_pg);
  162.  
  163.         sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_GFX_SRV_ID_20);
  164. }
  165.  
  166. void sumo_set_tdp_limit(struct radeon_device *rdev, u32 index, u32 tdp_limit)
  167. {
  168.         u32 regoffset = 0;
  169.         u32 shift = 0;
  170.         u32 mask = 0xFFF;
  171.         u32 sclk_dpm_tdp_limit;
  172.  
  173.         switch (index) {
  174.         case 0:
  175.                 regoffset = RCU_SclkDpmTdpLimit01;
  176.                 shift = 16;
  177.                 break;
  178.         case 1:
  179.                 regoffset = RCU_SclkDpmTdpLimit01;
  180.                 shift = 0;
  181.                 break;
  182.         case 2:
  183.                 regoffset = RCU_SclkDpmTdpLimit23;
  184.                 shift = 16;
  185.                 break;
  186.         case 3:
  187.                 regoffset = RCU_SclkDpmTdpLimit23;
  188.                 shift = 0;
  189.                 break;
  190.         case 4:
  191.                 regoffset = RCU_SclkDpmTdpLimit47;
  192.                 shift = 16;
  193.                 break;
  194.         case 7:
  195.                 regoffset = RCU_SclkDpmTdpLimit47;
  196.                 shift = 0;
  197.                 break;
  198.         default:
  199.                 break;
  200.         }
  201.  
  202.         sclk_dpm_tdp_limit = RREG32_RCU(regoffset);
  203.         sclk_dpm_tdp_limit &= ~(mask << shift);
  204.         sclk_dpm_tdp_limit |= (tdp_limit << shift);
  205.         WREG32_RCU(regoffset, sclk_dpm_tdp_limit);
  206. }
  207.  
  208. void sumo_boost_state_enable(struct radeon_device *rdev, bool enable)
  209. {
  210.         u32 boost_disable = RREG32_RCU(RCU_GPU_BOOST_DISABLE);
  211.  
  212.         boost_disable &= 0xFFFFFFFE;
  213.         boost_disable |= (enable ? 0 : 1);
  214.         WREG32_RCU(RCU_GPU_BOOST_DISABLE, boost_disable);
  215. }
  216.  
  217. u32 sumo_get_running_fw_version(struct radeon_device *rdev)
  218. {
  219.         return RREG32_RCU(RCU_FW_VERSION);
  220. }
  221.  
  222.