cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

si_dpm.c (260764B)


      1/*
      2 * Copyright 2013 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 <linux/module.h>
     25#include <linux/pci.h>
     26
     27#include "amdgpu.h"
     28#include "amdgpu_pm.h"
     29#include "amdgpu_dpm.h"
     30#include "amdgpu_atombios.h"
     31#include "amdgpu_dpm_internal.h"
     32#include "amd_pcie.h"
     33#include "sid.h"
     34#include "r600_dpm.h"
     35#include "si_dpm.h"
     36#include "atom.h"
     37#include "../include/pptable.h"
     38#include <linux/math64.h>
     39#include <linux/seq_file.h>
     40#include <linux/firmware.h>
     41#include <legacy_dpm.h>
     42
     43#define MC_CG_ARB_FREQ_F0           0x0a
     44#define MC_CG_ARB_FREQ_F1           0x0b
     45#define MC_CG_ARB_FREQ_F2           0x0c
     46#define MC_CG_ARB_FREQ_F3           0x0d
     47
     48#define SMC_RAM_END                 0x20000
     49
     50#define SCLK_MIN_DEEPSLEEP_FREQ     1350
     51
     52
     53/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */
     54#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
     55#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
     56#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
     57#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
     58#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
     59#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
     60
     61#define BIOS_SCRATCH_4                                    0x5cd
     62
     63MODULE_FIRMWARE("amdgpu/tahiti_smc.bin");
     64MODULE_FIRMWARE("amdgpu/pitcairn_smc.bin");
     65MODULE_FIRMWARE("amdgpu/pitcairn_k_smc.bin");
     66MODULE_FIRMWARE("amdgpu/verde_smc.bin");
     67MODULE_FIRMWARE("amdgpu/verde_k_smc.bin");
     68MODULE_FIRMWARE("amdgpu/oland_smc.bin");
     69MODULE_FIRMWARE("amdgpu/oland_k_smc.bin");
     70MODULE_FIRMWARE("amdgpu/hainan_smc.bin");
     71MODULE_FIRMWARE("amdgpu/hainan_k_smc.bin");
     72MODULE_FIRMWARE("amdgpu/banks_k_2_smc.bin");
     73
     74static const struct amd_pm_funcs si_dpm_funcs;
     75
     76union power_info {
     77	struct _ATOM_POWERPLAY_INFO info;
     78	struct _ATOM_POWERPLAY_INFO_V2 info_2;
     79	struct _ATOM_POWERPLAY_INFO_V3 info_3;
     80	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
     81	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
     82	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
     83	struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4;
     84	struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5;
     85};
     86
     87union fan_info {
     88	struct _ATOM_PPLIB_FANTABLE fan;
     89	struct _ATOM_PPLIB_FANTABLE2 fan2;
     90	struct _ATOM_PPLIB_FANTABLE3 fan3;
     91};
     92
     93union pplib_clock_info {
     94	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
     95	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
     96	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
     97	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
     98	struct _ATOM_PPLIB_SI_CLOCK_INFO si;
     99};
    100
    101enum si_dpm_auto_throttle_src {
    102	SI_DPM_AUTO_THROTTLE_SRC_THERMAL,
    103	SI_DPM_AUTO_THROTTLE_SRC_EXTERNAL
    104};
    105
    106enum si_dpm_event_src {
    107	SI_DPM_EVENT_SRC_ANALOG = 0,
    108	SI_DPM_EVENT_SRC_EXTERNAL = 1,
    109	SI_DPM_EVENT_SRC_DIGITAL = 2,
    110	SI_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,
    111	SI_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4
    112};
    113
    114static const u32 r600_utc[R600_PM_NUMBER_OF_TC] =
    115{
    116	R600_UTC_DFLT_00,
    117	R600_UTC_DFLT_01,
    118	R600_UTC_DFLT_02,
    119	R600_UTC_DFLT_03,
    120	R600_UTC_DFLT_04,
    121	R600_UTC_DFLT_05,
    122	R600_UTC_DFLT_06,
    123	R600_UTC_DFLT_07,
    124	R600_UTC_DFLT_08,
    125	R600_UTC_DFLT_09,
    126	R600_UTC_DFLT_10,
    127	R600_UTC_DFLT_11,
    128	R600_UTC_DFLT_12,
    129	R600_UTC_DFLT_13,
    130	R600_UTC_DFLT_14,
    131};
    132
    133static const u32 r600_dtc[R600_PM_NUMBER_OF_TC] =
    134{
    135	R600_DTC_DFLT_00,
    136	R600_DTC_DFLT_01,
    137	R600_DTC_DFLT_02,
    138	R600_DTC_DFLT_03,
    139	R600_DTC_DFLT_04,
    140	R600_DTC_DFLT_05,
    141	R600_DTC_DFLT_06,
    142	R600_DTC_DFLT_07,
    143	R600_DTC_DFLT_08,
    144	R600_DTC_DFLT_09,
    145	R600_DTC_DFLT_10,
    146	R600_DTC_DFLT_11,
    147	R600_DTC_DFLT_12,
    148	R600_DTC_DFLT_13,
    149	R600_DTC_DFLT_14,
    150};
    151
    152static const struct si_cac_config_reg cac_weights_tahiti[] =
    153{
    154	{ 0x0, 0x0000ffff, 0, 0xc, SISLANDS_CACCONFIG_CGIND },
    155	{ 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    156	{ 0x1, 0x0000ffff, 0, 0x101, SISLANDS_CACCONFIG_CGIND },
    157	{ 0x1, 0xffff0000, 16, 0xc, SISLANDS_CACCONFIG_CGIND },
    158	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    159	{ 0x3, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    160	{ 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    161	{ 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    162	{ 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    163	{ 0x5, 0x0000ffff, 0, 0x8fc, SISLANDS_CACCONFIG_CGIND },
    164	{ 0x5, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    165	{ 0x6, 0x0000ffff, 0, 0x95, SISLANDS_CACCONFIG_CGIND },
    166	{ 0x6, 0xffff0000, 16, 0x34e, SISLANDS_CACCONFIG_CGIND },
    167	{ 0x18f, 0x0000ffff, 0, 0x1a1, SISLANDS_CACCONFIG_CGIND },
    168	{ 0x7, 0x0000ffff, 0, 0xda, SISLANDS_CACCONFIG_CGIND },
    169	{ 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    170	{ 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    171	{ 0x8, 0xffff0000, 16, 0x46, SISLANDS_CACCONFIG_CGIND },
    172	{ 0x9, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    173	{ 0xa, 0x0000ffff, 0, 0x208, SISLANDS_CACCONFIG_CGIND },
    174	{ 0xb, 0x0000ffff, 0, 0xe7, SISLANDS_CACCONFIG_CGIND },
    175	{ 0xb, 0xffff0000, 16, 0x948, SISLANDS_CACCONFIG_CGIND },
    176	{ 0xc, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    177	{ 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    178	{ 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    179	{ 0xe, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    180	{ 0xf, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    181	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    182	{ 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    183	{ 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    184	{ 0x11, 0x0000ffff, 0, 0x167, SISLANDS_CACCONFIG_CGIND },
    185	{ 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    186	{ 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    187	{ 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    188	{ 0x13, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
    189	{ 0x14, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    190	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    191	{ 0x15, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },
    192	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    193	{ 0x16, 0x0000ffff, 0, 0x31, SISLANDS_CACCONFIG_CGIND },
    194	{ 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    195	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    196	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    197	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    198	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    199	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    200	{ 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    201	{ 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    202	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    203	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    204	{ 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    205	{ 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    206	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    207	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    208	{ 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    209	{ 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    210	{ 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    211	{ 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    212	{ 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    213	{ 0x6d, 0x0000ffff, 0, 0x18e, SISLANDS_CACCONFIG_CGIND },
    214	{ 0xFFFFFFFF }
    215};
    216
    217static const struct si_cac_config_reg lcac_tahiti[] =
    218{
    219	{ 0x143, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },
    220	{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    221	{ 0x146, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },
    222	{ 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    223	{ 0x149, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },
    224	{ 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    225	{ 0x14c, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },
    226	{ 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    227	{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    228	{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    229	{ 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    230	{ 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    231	{ 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    232	{ 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    233	{ 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    234	{ 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    235	{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    236	{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    237	{ 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    238	{ 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    239	{ 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    240	{ 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    241	{ 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    242	{ 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    243	{ 0x8c, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    244	{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    245	{ 0x8f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    246	{ 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    247	{ 0x92, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    248	{ 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    249	{ 0x95, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    250	{ 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    251	{ 0x14f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    252	{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    253	{ 0x152, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    254	{ 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    255	{ 0x155, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    256	{ 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    257	{ 0x158, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    258	{ 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    259	{ 0x110, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    260	{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    261	{ 0x113, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    262	{ 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    263	{ 0x116, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    264	{ 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    265	{ 0x119, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
    266	{ 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    267	{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    268	{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    269	{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    270	{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    271	{ 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    272	{ 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    273	{ 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    274	{ 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    275	{ 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    276	{ 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    277	{ 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    278	{ 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    279	{ 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    280	{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    281	{ 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    282	{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    283	{ 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    284	{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    285	{ 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    286	{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    287	{ 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    288	{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    289	{ 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    290	{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    291	{ 0x16d, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
    292	{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    293	{ 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    294	{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    295	{ 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    296	{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    297	{ 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    298	{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    299	{ 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    300	{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    301	{ 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    302	{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    303	{ 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    304	{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    305	{ 0xFFFFFFFF }
    306
    307};
    308
    309static const struct si_cac_config_reg cac_override_tahiti[] =
    310{
    311	{ 0xFFFFFFFF }
    312};
    313
    314static const struct si_powertune_data powertune_data_tahiti =
    315{
    316	((1 << 16) | 27027),
    317	6,
    318	0,
    319	4,
    320	95,
    321	{
    322		0UL,
    323		0UL,
    324		4521550UL,
    325		309631529UL,
    326		-1270850L,
    327		4513710L,
    328		40
    329	},
    330	595000000UL,
    331	12,
    332	{
    333		0,
    334		0,
    335		0,
    336		0,
    337		0,
    338		0,
    339		0,
    340		0
    341	},
    342	true
    343};
    344
    345static const struct si_dte_data dte_data_tahiti =
    346{
    347	{ 1159409, 0, 0, 0, 0 },
    348	{ 777, 0, 0, 0, 0 },
    349	2,
    350	54000,
    351	127000,
    352	25,
    353	2,
    354	10,
    355	13,
    356	{ 27, 31, 35, 39, 43, 47, 54, 61, 67, 74, 81, 88, 95, 0, 0, 0 },
    357	{ 240888759, 221057860, 235370597, 162287531, 158510299, 131423027, 116673180, 103067515, 87941937, 76209048, 68209175, 64090048, 58301890, 0, 0, 0 },
    358	{ 12024, 11189, 11451, 8411, 7939, 6666, 5681, 4905, 4241, 3720, 3354, 3122, 2890, 0, 0, 0 },
    359	85,
    360	false
    361};
    362
    363static const struct si_dte_data dte_data_tahiti_pro =
    364{
    365	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
    366	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
    367	5,
    368	45000,
    369	100,
    370	0xA,
    371	1,
    372	0,
    373	0x10,
    374	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
    375	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
    376	{ 0x7D0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
    377	90,
    378	true
    379};
    380
    381static const struct si_dte_data dte_data_new_zealand =
    382{
    383	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0 },
    384	{ 0x29B, 0x3E9, 0x537, 0x7D2, 0 },
    385	0x5,
    386	0xAFC8,
    387	0x69,
    388	0x32,
    389	1,
    390	0,
    391	0x10,
    392	{ 0x82, 0xA0, 0xB4, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
    393	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
    394	{ 0xDAC, 0x1388, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685 },
    395	85,
    396	true
    397};
    398
    399static const struct si_dte_data dte_data_aruba_pro =
    400{
    401	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
    402	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
    403	5,
    404	45000,
    405	100,
    406	0xA,
    407	1,
    408	0,
    409	0x10,
    410	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
    411	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
    412	{ 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
    413	90,
    414	true
    415};
    416
    417static const struct si_dte_data dte_data_malta =
    418{
    419	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
    420	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
    421	5,
    422	45000,
    423	100,
    424	0xA,
    425	1,
    426	0,
    427	0x10,
    428	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
    429	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
    430	{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
    431	90,
    432	true
    433};
    434
    435static const struct si_cac_config_reg cac_weights_pitcairn[] =
    436{
    437	{ 0x0, 0x0000ffff, 0, 0x8a, SISLANDS_CACCONFIG_CGIND },
    438	{ 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    439	{ 0x1, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    440	{ 0x1, 0xffff0000, 16, 0x24d, SISLANDS_CACCONFIG_CGIND },
    441	{ 0x2, 0x0000ffff, 0, 0x19, SISLANDS_CACCONFIG_CGIND },
    442	{ 0x3, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
    443	{ 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    444	{ 0x4, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },
    445	{ 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    446	{ 0x5, 0x0000ffff, 0, 0xc11, SISLANDS_CACCONFIG_CGIND },
    447	{ 0x5, 0xffff0000, 16, 0x7f3, SISLANDS_CACCONFIG_CGIND },
    448	{ 0x6, 0x0000ffff, 0, 0x403, SISLANDS_CACCONFIG_CGIND },
    449	{ 0x6, 0xffff0000, 16, 0x367, SISLANDS_CACCONFIG_CGIND },
    450	{ 0x18f, 0x0000ffff, 0, 0x4c9, SISLANDS_CACCONFIG_CGIND },
    451	{ 0x7, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    452	{ 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    453	{ 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    454	{ 0x8, 0xffff0000, 16, 0x45d, SISLANDS_CACCONFIG_CGIND },
    455	{ 0x9, 0x0000ffff, 0, 0x36d, SISLANDS_CACCONFIG_CGIND },
    456	{ 0xa, 0x0000ffff, 0, 0x534, SISLANDS_CACCONFIG_CGIND },
    457	{ 0xb, 0x0000ffff, 0, 0x5da, SISLANDS_CACCONFIG_CGIND },
    458	{ 0xb, 0xffff0000, 16, 0x880, SISLANDS_CACCONFIG_CGIND },
    459	{ 0xc, 0x0000ffff, 0, 0x201, SISLANDS_CACCONFIG_CGIND },
    460	{ 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    461	{ 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    462	{ 0xe, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND },
    463	{ 0xf, 0x0000ffff, 0, 0x1f, SISLANDS_CACCONFIG_CGIND },
    464	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    465	{ 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    466	{ 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    467	{ 0x11, 0x0000ffff, 0, 0x5de, SISLANDS_CACCONFIG_CGIND },
    468	{ 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    469	{ 0x12, 0x0000ffff, 0, 0x7b, SISLANDS_CACCONFIG_CGIND },
    470	{ 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    471	{ 0x13, 0xffff0000, 16, 0x13, SISLANDS_CACCONFIG_CGIND },
    472	{ 0x14, 0x0000ffff, 0, 0xf9, SISLANDS_CACCONFIG_CGIND },
    473	{ 0x15, 0x0000ffff, 0, 0x66, SISLANDS_CACCONFIG_CGIND },
    474	{ 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    475	{ 0x4e, 0x0000ffff, 0, 0x13, SISLANDS_CACCONFIG_CGIND },
    476	{ 0x16, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    477	{ 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    478	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    479	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    480	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    481	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    482	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    483	{ 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    484	{ 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    485	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    486	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    487	{ 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    488	{ 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    489	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    490	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    491	{ 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    492	{ 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    493	{ 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    494	{ 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    495	{ 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    496	{ 0x6d, 0x0000ffff, 0, 0x186, SISLANDS_CACCONFIG_CGIND },
    497	{ 0xFFFFFFFF }
    498};
    499
    500static const struct si_cac_config_reg lcac_pitcairn[] =
    501{
    502	{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    503	{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    504	{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    505	{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    506	{ 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    507	{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    508	{ 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    509	{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    510	{ 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    511	{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    512	{ 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    513	{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    514	{ 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    515	{ 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    516	{ 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    517	{ 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    518	{ 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    519	{ 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    520	{ 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    521	{ 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    522	{ 0x8f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    523	{ 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    524	{ 0x146, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    525	{ 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    526	{ 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    527	{ 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    528	{ 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    529	{ 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    530	{ 0x116, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    531	{ 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    532	{ 0x155, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    533	{ 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    534	{ 0x92, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    535	{ 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    536	{ 0x149, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    537	{ 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    538	{ 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    539	{ 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    540	{ 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    541	{ 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    542	{ 0x119, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    543	{ 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    544	{ 0x158, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    545	{ 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    546	{ 0x95, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
    547	{ 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    548	{ 0x14c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    549	{ 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    550	{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    551	{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    552	{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    553	{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    554	{ 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    555	{ 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    556	{ 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    557	{ 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    558	{ 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    559	{ 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    560	{ 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    561	{ 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    562	{ 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    563	{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    564	{ 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    565	{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    566	{ 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    567	{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    568	{ 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    569	{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    570	{ 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    571	{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    572	{ 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    573	{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    574	{ 0x16d, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
    575	{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    576	{ 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    577	{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    578	{ 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    579	{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    580	{ 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    581	{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    582	{ 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    583	{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    584	{ 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    585	{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    586	{ 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
    587	{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    588	{ 0xFFFFFFFF }
    589};
    590
    591static const struct si_cac_config_reg cac_override_pitcairn[] =
    592{
    593    { 0xFFFFFFFF }
    594};
    595
    596static const struct si_powertune_data powertune_data_pitcairn =
    597{
    598	((1 << 16) | 27027),
    599	5,
    600	0,
    601	6,
    602	100,
    603	{
    604		51600000UL,
    605		1800000UL,
    606		7194395UL,
    607		309631529UL,
    608		-1270850L,
    609		4513710L,
    610		100
    611	},
    612	117830498UL,
    613	12,
    614	{
    615		0,
    616		0,
    617		0,
    618		0,
    619		0,
    620		0,
    621		0,
    622		0
    623	},
    624	true
    625};
    626
    627static const struct si_dte_data dte_data_pitcairn =
    628{
    629	{ 0, 0, 0, 0, 0 },
    630	{ 0, 0, 0, 0, 0 },
    631	0,
    632	0,
    633	0,
    634	0,
    635	0,
    636	0,
    637	0,
    638	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    639	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    640	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    641	0,
    642	false
    643};
    644
    645static const struct si_dte_data dte_data_curacao_xt =
    646{
    647	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
    648	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
    649	5,
    650	45000,
    651	100,
    652	0xA,
    653	1,
    654	0,
    655	0x10,
    656	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
    657	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
    658	{ 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
    659	90,
    660	true
    661};
    662
    663static const struct si_dte_data dte_data_curacao_pro =
    664{
    665	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
    666	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
    667	5,
    668	45000,
    669	100,
    670	0xA,
    671	1,
    672	0,
    673	0x10,
    674	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
    675	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
    676	{ 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
    677	90,
    678	true
    679};
    680
    681static const struct si_dte_data dte_data_neptune_xt =
    682{
    683	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
    684	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
    685	5,
    686	45000,
    687	100,
    688	0xA,
    689	1,
    690	0,
    691	0x10,
    692	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
    693	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
    694	{ 0x3A2F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
    695	90,
    696	true
    697};
    698
    699static const struct si_cac_config_reg cac_weights_chelsea_pro[] =
    700{
    701	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
    702	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
    703	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
    704	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
    705	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    706	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
    707	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
    708	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
    709	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
    710	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
    711	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
    712	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
    713	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
    714	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
    715	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
    716	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
    717	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
    718	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
    719	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
    720	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
    721	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
    722	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
    723	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
    724	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
    725	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
    726	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
    727	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
    728	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    729	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    730	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
    731	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
    732	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
    733	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
    734	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
    735	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
    736	{ 0x14, 0x0000ffff, 0, 0x2BD, SISLANDS_CACCONFIG_CGIND },
    737	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    738	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
    739	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    740	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
    741	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
    742	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    743	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    744	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    745	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    746	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    747	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    748	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    749	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    750	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    751	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    752	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    753	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    754	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    755	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    756	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    757	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    758	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    759	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    760	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
    761	{ 0xFFFFFFFF }
    762};
    763
    764static const struct si_cac_config_reg cac_weights_chelsea_xt[] =
    765{
    766	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
    767	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
    768	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
    769	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
    770	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    771	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
    772	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
    773	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
    774	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
    775	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
    776	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
    777	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
    778	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
    779	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
    780	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
    781	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
    782	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
    783	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
    784	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
    785	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
    786	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
    787	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
    788	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
    789	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
    790	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
    791	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
    792	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
    793	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    794	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    795	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
    796	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
    797	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
    798	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
    799	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
    800	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
    801	{ 0x14, 0x0000ffff, 0, 0x30A, SISLANDS_CACCONFIG_CGIND },
    802	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    803	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
    804	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    805	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
    806	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
    807	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    808	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    809	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    810	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    811	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    812	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    813	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    814	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    815	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    816	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    817	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    818	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    819	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    820	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    821	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    822	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    823	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    824	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    825	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
    826	{ 0xFFFFFFFF }
    827};
    828
    829static const struct si_cac_config_reg cac_weights_heathrow[] =
    830{
    831	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
    832	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
    833	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
    834	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
    835	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    836	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
    837	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
    838	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
    839	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
    840	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
    841	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
    842	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
    843	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
    844	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
    845	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
    846	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
    847	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
    848	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
    849	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
    850	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
    851	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
    852	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
    853	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
    854	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
    855	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
    856	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
    857	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
    858	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    859	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    860	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
    861	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
    862	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
    863	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
    864	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
    865	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
    866	{ 0x14, 0x0000ffff, 0, 0x362, SISLANDS_CACCONFIG_CGIND },
    867	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    868	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
    869	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    870	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
    871	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
    872	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    873	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    874	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    875	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    876	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    877	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    878	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    879	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    880	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    881	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    882	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    883	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    884	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    885	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    886	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    887	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    888	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    889	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    890	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
    891	{ 0xFFFFFFFF }
    892};
    893
    894static const struct si_cac_config_reg cac_weights_cape_verde_pro[] =
    895{
    896	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
    897	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
    898	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
    899	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
    900	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    901	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
    902	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
    903	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
    904	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
    905	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
    906	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
    907	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
    908	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
    909	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
    910	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
    911	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
    912	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
    913	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
    914	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
    915	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
    916	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
    917	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
    918	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
    919	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
    920	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
    921	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
    922	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
    923	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    924	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    925	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
    926	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
    927	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
    928	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
    929	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
    930	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
    931	{ 0x14, 0x0000ffff, 0, 0x315, SISLANDS_CACCONFIG_CGIND },
    932	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    933	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
    934	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    935	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
    936	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
    937	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    938	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    939	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    940	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    941	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    942	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    943	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    944	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    945	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    946	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    947	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    948	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    949	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    950	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    951	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    952	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    953	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
    954	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
    955	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
    956	{ 0xFFFFFFFF }
    957};
    958
    959static const struct si_cac_config_reg cac_weights_cape_verde[] =
    960{
    961	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
    962	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
    963	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
    964	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
    965	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    966	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
    967	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
    968	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
    969	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
    970	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
    971	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
    972	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
    973	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
    974	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
    975	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
    976	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
    977	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
    978	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
    979	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
    980	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
    981	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
    982	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
    983	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
    984	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
    985	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
    986	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
    987	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
    988	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
    989	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
    990	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
    991	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
    992	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
    993	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
    994	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
    995	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
    996	{ 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND },
    997	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
    998	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
    999	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1000	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
   1001	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
   1002	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1003	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1004	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1005	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1006	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1007	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1008	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1009	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1010	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1011	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1012	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1013	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1014	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1015	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1016	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1017	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1018	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1019	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1020	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
   1021	{ 0xFFFFFFFF }
   1022};
   1023
   1024static const struct si_cac_config_reg lcac_cape_verde[] =
   1025{
   1026	{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1027	{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1028	{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1029	{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1030	{ 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
   1031	{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1032	{ 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
   1033	{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1034	{ 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
   1035	{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1036	{ 0x143, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1037	{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1038	{ 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1039	{ 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1040	{ 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1041	{ 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1042	{ 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
   1043	{ 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1044	{ 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
   1045	{ 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1046	{ 0x8f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1047	{ 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1048	{ 0x146, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1049	{ 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1050	{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1051	{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1052	{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1053	{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1054	{ 0x164, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1055	{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1056	{ 0x167, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1057	{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1058	{ 0x16a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1059	{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1060	{ 0x15e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1061	{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1062	{ 0x161, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1063	{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1064	{ 0x15b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1065	{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1066	{ 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1067	{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1068	{ 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1069	{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1070	{ 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1071	{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1072	{ 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1073	{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1074	{ 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1075	{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1076	{ 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1077	{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1078	{ 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1079	{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1080	{ 0xFFFFFFFF }
   1081};
   1082
   1083static const struct si_cac_config_reg cac_override_cape_verde[] =
   1084{
   1085    { 0xFFFFFFFF }
   1086};
   1087
   1088static const struct si_powertune_data powertune_data_cape_verde =
   1089{
   1090	((1 << 16) | 0x6993),
   1091	5,
   1092	0,
   1093	7,
   1094	105,
   1095	{
   1096		0UL,
   1097		0UL,
   1098		7194395UL,
   1099		309631529UL,
   1100		-1270850L,
   1101		4513710L,
   1102		100
   1103	},
   1104	117830498UL,
   1105	12,
   1106	{
   1107		0,
   1108		0,
   1109		0,
   1110		0,
   1111		0,
   1112		0,
   1113		0,
   1114		0
   1115	},
   1116	true
   1117};
   1118
   1119static const struct si_dte_data dte_data_cape_verde =
   1120{
   1121	{ 0, 0, 0, 0, 0 },
   1122	{ 0, 0, 0, 0, 0 },
   1123	0,
   1124	0,
   1125	0,
   1126	0,
   1127	0,
   1128	0,
   1129	0,
   1130	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
   1131	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
   1132	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
   1133	0,
   1134	false
   1135};
   1136
   1137static const struct si_dte_data dte_data_venus_xtx =
   1138{
   1139	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
   1140	{ 0x71C, 0xAAB, 0xE39, 0x11C7, 0x0 },
   1141	5,
   1142	55000,
   1143	0x69,
   1144	0xA,
   1145	1,
   1146	0,
   1147	0x3,
   1148	{ 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
   1149	{ 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
   1150	{ 0xD6D8, 0x88B8, 0x1555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
   1151	90,
   1152	true
   1153};
   1154
   1155static const struct si_dte_data dte_data_venus_xt =
   1156{
   1157	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
   1158	{ 0xBDA, 0x11C7, 0x17B4, 0x1DA1, 0x0 },
   1159	5,
   1160	55000,
   1161	0x69,
   1162	0xA,
   1163	1,
   1164	0,
   1165	0x3,
   1166	{ 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
   1167	{ 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
   1168	{ 0xAFC8, 0x88B8, 0x238E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
   1169	90,
   1170	true
   1171};
   1172
   1173static const struct si_dte_data dte_data_venus_pro =
   1174{
   1175	{  0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
   1176	{ 0x11C7, 0x1AAB, 0x238E, 0x2C72, 0x0 },
   1177	5,
   1178	55000,
   1179	0x69,
   1180	0xA,
   1181	1,
   1182	0,
   1183	0x3,
   1184	{ 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
   1185	{ 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
   1186	{ 0x88B8, 0x88B8, 0x3555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
   1187	90,
   1188	true
   1189};
   1190
   1191static const struct si_cac_config_reg cac_weights_oland[] =
   1192{
   1193	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
   1194	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
   1195	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
   1196	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
   1197	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1198	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
   1199	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
   1200	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
   1201	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
   1202	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
   1203	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
   1204	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
   1205	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
   1206	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
   1207	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
   1208	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
   1209	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
   1210	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
   1211	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
   1212	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
   1213	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
   1214	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
   1215	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
   1216	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
   1217	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
   1218	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
   1219	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
   1220	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1221	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1222	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
   1223	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
   1224	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
   1225	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
   1226	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
   1227	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
   1228	{ 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND },
   1229	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1230	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
   1231	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1232	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
   1233	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
   1234	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1235	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1236	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1237	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1238	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1239	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1240	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1241	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1242	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1243	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1244	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1245	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1246	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1247	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1248	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1249	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1250	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1251	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1252	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
   1253	{ 0xFFFFFFFF }
   1254};
   1255
   1256static const struct si_cac_config_reg cac_weights_mars_pro[] =
   1257{
   1258	{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },
   1259	{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
   1260	{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },
   1261	{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },
   1262	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1263	{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
   1264	{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
   1265	{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
   1266	{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },
   1267	{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },
   1268	{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },
   1269	{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },
   1270	{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },
   1271	{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },
   1272	{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },
   1273	{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },
   1274	{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },
   1275	{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },
   1276	{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },
   1277	{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },
   1278	{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },
   1279	{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },
   1280	{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },
   1281	{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
   1282	{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },
   1283	{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },
   1284	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
   1285	{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },
   1286	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1287	{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
   1288	{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },
   1289	{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
   1290	{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },
   1291	{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },
   1292	{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },
   1293	{ 0x14, 0x0000ffff, 0, 0x2, SISLANDS_CACCONFIG_CGIND },
   1294	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1295	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
   1296	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1297	{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },
   1298	{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },
   1299	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1300	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1301	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1302	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1303	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1304	{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },
   1305	{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
   1306	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1307	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1308	{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },
   1309	{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },
   1310	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1311	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1312	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1313	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1314	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1315	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1316	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1317	{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },
   1318	{ 0xFFFFFFFF }
   1319};
   1320
   1321static const struct si_cac_config_reg cac_weights_mars_xt[] =
   1322{
   1323	{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },
   1324	{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
   1325	{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },
   1326	{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },
   1327	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1328	{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
   1329	{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
   1330	{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
   1331	{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },
   1332	{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },
   1333	{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },
   1334	{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },
   1335	{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },
   1336	{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },
   1337	{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },
   1338	{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },
   1339	{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },
   1340	{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },
   1341	{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },
   1342	{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },
   1343	{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },
   1344	{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },
   1345	{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },
   1346	{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
   1347	{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },
   1348	{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },
   1349	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
   1350	{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },
   1351	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1352	{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
   1353	{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },
   1354	{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
   1355	{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },
   1356	{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },
   1357	{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },
   1358	{ 0x14, 0x0000ffff, 0, 0x60, SISLANDS_CACCONFIG_CGIND },
   1359	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1360	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
   1361	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1362	{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },
   1363	{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },
   1364	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1365	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1366	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1367	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1368	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1369	{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },
   1370	{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
   1371	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1372	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1373	{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },
   1374	{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },
   1375	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1376	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1377	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1378	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1379	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1380	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1381	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1382	{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },
   1383	{ 0xFFFFFFFF }
   1384};
   1385
   1386static const struct si_cac_config_reg cac_weights_oland_pro[] =
   1387{
   1388	{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },
   1389	{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
   1390	{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },
   1391	{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },
   1392	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1393	{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
   1394	{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
   1395	{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
   1396	{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },
   1397	{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },
   1398	{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },
   1399	{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },
   1400	{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },
   1401	{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },
   1402	{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },
   1403	{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },
   1404	{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },
   1405	{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },
   1406	{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },
   1407	{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },
   1408	{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },
   1409	{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },
   1410	{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },
   1411	{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
   1412	{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },
   1413	{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },
   1414	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
   1415	{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },
   1416	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1417	{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
   1418	{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },
   1419	{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
   1420	{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },
   1421	{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },
   1422	{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },
   1423	{ 0x14, 0x0000ffff, 0, 0x90, SISLANDS_CACCONFIG_CGIND },
   1424	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1425	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
   1426	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1427	{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },
   1428	{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },
   1429	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1430	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1431	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1432	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1433	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1434	{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },
   1435	{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
   1436	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1437	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1438	{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },
   1439	{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },
   1440	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1441	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1442	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1443	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1444	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1445	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1446	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1447	{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },
   1448	{ 0xFFFFFFFF }
   1449};
   1450
   1451static const struct si_cac_config_reg cac_weights_oland_xt[] =
   1452{
   1453	{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },
   1454	{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
   1455	{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },
   1456	{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },
   1457	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1458	{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
   1459	{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
   1460	{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
   1461	{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },
   1462	{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },
   1463	{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },
   1464	{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },
   1465	{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },
   1466	{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },
   1467	{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },
   1468	{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },
   1469	{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },
   1470	{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },
   1471	{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },
   1472	{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },
   1473	{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },
   1474	{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },
   1475	{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },
   1476	{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
   1477	{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },
   1478	{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },
   1479	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
   1480	{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },
   1481	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1482	{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
   1483	{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },
   1484	{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
   1485	{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },
   1486	{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },
   1487	{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },
   1488	{ 0x14, 0x0000ffff, 0, 0x120, SISLANDS_CACCONFIG_CGIND },
   1489	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1490	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
   1491	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1492	{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },
   1493	{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },
   1494	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1495	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1496	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1497	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1498	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1499	{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },
   1500	{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
   1501	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1502	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1503	{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },
   1504	{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },
   1505	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1506	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1507	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1508	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1509	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1510	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1511	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1512	{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },
   1513	{ 0xFFFFFFFF }
   1514};
   1515
   1516static const struct si_cac_config_reg lcac_oland[] =
   1517{
   1518	{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1519	{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1520	{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1521	{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1522	{ 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
   1523	{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1524	{ 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
   1525	{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1526	{ 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
   1527	{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1528	{ 0x143, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
   1529	{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1530	{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1531	{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1532	{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1533	{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1534	{ 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1535	{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1536	{ 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1537	{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1538	{ 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1539	{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1540	{ 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1541	{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1542	{ 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1543	{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1544	{ 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1545	{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1546	{ 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1547	{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1548	{ 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1549	{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1550	{ 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1551	{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1552	{ 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1553	{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1554	{ 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1555	{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1556	{ 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1557	{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1558	{ 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1559	{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1560	{ 0xFFFFFFFF }
   1561};
   1562
   1563static const struct si_cac_config_reg lcac_mars_pro[] =
   1564{
   1565	{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1566	{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1567	{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1568	{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1569	{ 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
   1570	{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1571	{ 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
   1572	{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1573	{ 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
   1574	{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1575	{ 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1576	{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1577	{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1578	{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1579	{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1580	{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1581	{ 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1582	{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1583	{ 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1584	{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1585	{ 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1586	{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1587	{ 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1588	{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1589	{ 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1590	{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1591	{ 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1592	{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1593	{ 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
   1594	{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1595	{ 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1596	{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1597	{ 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1598	{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1599	{ 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1600	{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1601	{ 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1602	{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1603	{ 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1604	{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1605	{ 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
   1606	{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
   1607	{ 0xFFFFFFFF }
   1608};
   1609
   1610static const struct si_cac_config_reg cac_override_oland[] =
   1611{
   1612	{ 0xFFFFFFFF }
   1613};
   1614
   1615static const struct si_powertune_data powertune_data_oland =
   1616{
   1617	((1 << 16) | 0x6993),
   1618	5,
   1619	0,
   1620	7,
   1621	105,
   1622	{
   1623		0UL,
   1624		0UL,
   1625		7194395UL,
   1626		309631529UL,
   1627		-1270850L,
   1628		4513710L,
   1629		100
   1630	},
   1631	117830498UL,
   1632	12,
   1633	{
   1634		0,
   1635		0,
   1636		0,
   1637		0,
   1638		0,
   1639		0,
   1640		0,
   1641		0
   1642	},
   1643	true
   1644};
   1645
   1646static const struct si_powertune_data powertune_data_mars_pro =
   1647{
   1648	((1 << 16) | 0x6993),
   1649	5,
   1650	0,
   1651	7,
   1652	105,
   1653	{
   1654		0UL,
   1655		0UL,
   1656		7194395UL,
   1657		309631529UL,
   1658		-1270850L,
   1659		4513710L,
   1660		100
   1661	},
   1662	117830498UL,
   1663	12,
   1664	{
   1665		0,
   1666		0,
   1667		0,
   1668		0,
   1669		0,
   1670		0,
   1671		0,
   1672		0
   1673	},
   1674	true
   1675};
   1676
   1677static const struct si_dte_data dte_data_oland =
   1678{
   1679	{ 0, 0, 0, 0, 0 },
   1680	{ 0, 0, 0, 0, 0 },
   1681	0,
   1682	0,
   1683	0,
   1684	0,
   1685	0,
   1686	0,
   1687	0,
   1688	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
   1689	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
   1690	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
   1691	0,
   1692	false
   1693};
   1694
   1695static const struct si_dte_data dte_data_mars_pro =
   1696{
   1697	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
   1698	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
   1699	5,
   1700	55000,
   1701	105,
   1702	0xA,
   1703	1,
   1704	0,
   1705	0x10,
   1706	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
   1707	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
   1708	{ 0xF627, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
   1709	90,
   1710	true
   1711};
   1712
   1713static const struct si_dte_data dte_data_sun_xt =
   1714{
   1715	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
   1716	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
   1717	5,
   1718	55000,
   1719	105,
   1720	0xA,
   1721	1,
   1722	0,
   1723	0x10,
   1724	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
   1725	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
   1726	{ 0xD555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
   1727	90,
   1728	true
   1729};
   1730
   1731
   1732static const struct si_cac_config_reg cac_weights_hainan[] =
   1733{
   1734	{ 0x0, 0x0000ffff, 0, 0x2d9, SISLANDS_CACCONFIG_CGIND },
   1735	{ 0x0, 0xffff0000, 16, 0x22b, SISLANDS_CACCONFIG_CGIND },
   1736	{ 0x1, 0x0000ffff, 0, 0x21c, SISLANDS_CACCONFIG_CGIND },
   1737	{ 0x1, 0xffff0000, 16, 0x1dc, SISLANDS_CACCONFIG_CGIND },
   1738	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1739	{ 0x3, 0x0000ffff, 0, 0x24e, SISLANDS_CACCONFIG_CGIND },
   1740	{ 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1741	{ 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1742	{ 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1743	{ 0x5, 0x0000ffff, 0, 0x35e, SISLANDS_CACCONFIG_CGIND },
   1744	{ 0x5, 0xffff0000, 16, 0x1143, SISLANDS_CACCONFIG_CGIND },
   1745	{ 0x6, 0x0000ffff, 0, 0xe17, SISLANDS_CACCONFIG_CGIND },
   1746	{ 0x6, 0xffff0000, 16, 0x441, SISLANDS_CACCONFIG_CGIND },
   1747	{ 0x18f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1748	{ 0x7, 0x0000ffff, 0, 0x28b, SISLANDS_CACCONFIG_CGIND },
   1749	{ 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1750	{ 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1751	{ 0x8, 0xffff0000, 16, 0xabe, SISLANDS_CACCONFIG_CGIND },
   1752	{ 0x9, 0x0000ffff, 0, 0xf11, SISLANDS_CACCONFIG_CGIND },
   1753	{ 0xa, 0x0000ffff, 0, 0x907, SISLANDS_CACCONFIG_CGIND },
   1754	{ 0xb, 0x0000ffff, 0, 0xb45, SISLANDS_CACCONFIG_CGIND },
   1755	{ 0xb, 0xffff0000, 16, 0xd1e, SISLANDS_CACCONFIG_CGIND },
   1756	{ 0xc, 0x0000ffff, 0, 0xa2c, SISLANDS_CACCONFIG_CGIND },
   1757	{ 0xd, 0x0000ffff, 0, 0x62, SISLANDS_CACCONFIG_CGIND },
   1758	{ 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1759	{ 0xe, 0x0000ffff, 0, 0x1f3, SISLANDS_CACCONFIG_CGIND },
   1760	{ 0xf, 0x0000ffff, 0, 0x42, SISLANDS_CACCONFIG_CGIND },
   1761	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1762	{ 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1763	{ 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1764	{ 0x11, 0x0000ffff, 0, 0x709, SISLANDS_CACCONFIG_CGIND },
   1765	{ 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1766	{ 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1767	{ 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1768	{ 0x13, 0xffff0000, 16, 0x3a, SISLANDS_CACCONFIG_CGIND },
   1769	{ 0x14, 0x0000ffff, 0, 0x357, SISLANDS_CACCONFIG_CGIND },
   1770	{ 0x15, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND },
   1771	{ 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1772	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1773	{ 0x16, 0x0000ffff, 0, 0x314, SISLANDS_CACCONFIG_CGIND },
   1774	{ 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1775	{ 0x17, 0x0000ffff, 0, 0x6d, SISLANDS_CACCONFIG_CGIND },
   1776	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1777	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1778	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
   1779	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
   1780	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1781	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1782	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1783	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1784	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1785	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1786	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1787	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1788	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1789	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1790	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1791	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
   1792	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
   1793	{ 0x6d, 0x0000ffff, 0, 0x1b9, SISLANDS_CACCONFIG_CGIND },
   1794	{ 0xFFFFFFFF }
   1795};
   1796
   1797static const struct si_powertune_data powertune_data_hainan =
   1798{
   1799	((1 << 16) | 0x6993),
   1800	5,
   1801	0,
   1802	9,
   1803	105,
   1804	{
   1805		0UL,
   1806		0UL,
   1807		7194395UL,
   1808		309631529UL,
   1809		-1270850L,
   1810		4513710L,
   1811		100
   1812	},
   1813	117830498UL,
   1814	12,
   1815	{
   1816		0,
   1817		0,
   1818		0,
   1819		0,
   1820		0,
   1821		0,
   1822		0,
   1823		0
   1824	},
   1825	true
   1826};
   1827
   1828static struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev);
   1829static struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev);
   1830static struct ni_power_info *ni_get_pi(struct amdgpu_device *adev);
   1831static struct  si_ps *si_get_ps(struct amdgpu_ps *rps);
   1832
   1833static int si_populate_voltage_value(struct amdgpu_device *adev,
   1834				     const struct atom_voltage_table *table,
   1835				     u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage);
   1836static int si_get_std_voltage_value(struct amdgpu_device *adev,
   1837				    SISLANDS_SMC_VOLTAGE_VALUE *voltage,
   1838				    u16 *std_voltage);
   1839static int si_write_smc_soft_register(struct amdgpu_device *adev,
   1840				      u16 reg_offset, u32 value);
   1841static int si_convert_power_level_to_smc(struct amdgpu_device *adev,
   1842					 struct rv7xx_pl *pl,
   1843					 SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level);
   1844static int si_calculate_sclk_params(struct amdgpu_device *adev,
   1845				    u32 engine_clock,
   1846				    SISLANDS_SMC_SCLK_VALUE *sclk);
   1847
   1848static void si_thermal_start_smc_fan_control(struct amdgpu_device *adev);
   1849static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev);
   1850static void si_dpm_set_irq_funcs(struct amdgpu_device *adev);
   1851
   1852static struct si_power_info *si_get_pi(struct amdgpu_device *adev)
   1853{
   1854	struct si_power_info *pi = adev->pm.dpm.priv;
   1855	return pi;
   1856}
   1857
   1858static void si_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coeffients *coeff,
   1859						     u16 v, s32 t, u32 ileakage, u32 *leakage)
   1860{
   1861	s64 kt, kv, leakage_w, i_leakage, vddc;
   1862	s64 temperature, t_slope, t_intercept, av, bv, t_ref;
   1863	s64 tmp;
   1864
   1865	i_leakage = div64_s64(drm_int2fixp(ileakage), 100);
   1866	vddc = div64_s64(drm_int2fixp(v), 1000);
   1867	temperature = div64_s64(drm_int2fixp(t), 1000);
   1868
   1869	t_slope = div64_s64(drm_int2fixp(coeff->t_slope), 100000000);
   1870	t_intercept = div64_s64(drm_int2fixp(coeff->t_intercept), 100000000);
   1871	av = div64_s64(drm_int2fixp(coeff->av), 100000000);
   1872	bv = div64_s64(drm_int2fixp(coeff->bv), 100000000);
   1873	t_ref = drm_int2fixp(coeff->t_ref);
   1874
   1875	tmp = drm_fixp_mul(t_slope, vddc) + t_intercept;
   1876	kt = drm_fixp_exp(drm_fixp_mul(tmp, temperature));
   1877	kt = drm_fixp_div(kt, drm_fixp_exp(drm_fixp_mul(tmp, t_ref)));
   1878	kv = drm_fixp_mul(av, drm_fixp_exp(drm_fixp_mul(bv, vddc)));
   1879
   1880	leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc);
   1881
   1882	*leakage = drm_fixp2int(leakage_w * 1000);
   1883}
   1884
   1885static void si_calculate_leakage_for_v_and_t(struct amdgpu_device *adev,
   1886					     const struct ni_leakage_coeffients *coeff,
   1887					     u16 v,
   1888					     s32 t,
   1889					     u32 i_leakage,
   1890					     u32 *leakage)
   1891{
   1892	si_calculate_leakage_for_v_and_t_formula(coeff, v, t, i_leakage, leakage);
   1893}
   1894
   1895static void si_calculate_leakage_for_v_formula(const struct ni_leakage_coeffients *coeff,
   1896					       const u32 fixed_kt, u16 v,
   1897					       u32 ileakage, u32 *leakage)
   1898{
   1899	s64 kt, kv, leakage_w, i_leakage, vddc;
   1900
   1901	i_leakage = div64_s64(drm_int2fixp(ileakage), 100);
   1902	vddc = div64_s64(drm_int2fixp(v), 1000);
   1903
   1904	kt = div64_s64(drm_int2fixp(fixed_kt), 100000000);
   1905	kv = drm_fixp_mul(div64_s64(drm_int2fixp(coeff->av), 100000000),
   1906			  drm_fixp_exp(drm_fixp_mul(div64_s64(drm_int2fixp(coeff->bv), 100000000), vddc)));
   1907
   1908	leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc);
   1909
   1910	*leakage = drm_fixp2int(leakage_w * 1000);
   1911}
   1912
   1913static void si_calculate_leakage_for_v(struct amdgpu_device *adev,
   1914				       const struct ni_leakage_coeffients *coeff,
   1915				       const u32 fixed_kt,
   1916				       u16 v,
   1917				       u32 i_leakage,
   1918				       u32 *leakage)
   1919{
   1920	si_calculate_leakage_for_v_formula(coeff, fixed_kt, v, i_leakage, leakage);
   1921}
   1922
   1923
   1924static void si_update_dte_from_pl2(struct amdgpu_device *adev,
   1925				   struct si_dte_data *dte_data)
   1926{
   1927	u32 p_limit1 = adev->pm.dpm.tdp_limit;
   1928	u32 p_limit2 = adev->pm.dpm.near_tdp_limit;
   1929	u32 k = dte_data->k;
   1930	u32 t_max = dte_data->max_t;
   1931	u32 t_split[5] = { 10, 15, 20, 25, 30 };
   1932	u32 t_0 = dte_data->t0;
   1933	u32 i;
   1934
   1935	if (p_limit2 != 0 && p_limit2 <= p_limit1) {
   1936		dte_data->tdep_count = 3;
   1937
   1938		for (i = 0; i < k; i++) {
   1939			dte_data->r[i] =
   1940				(t_split[i] * (t_max - t_0/(u32)1000) * (1 << 14)) /
   1941				(p_limit2  * (u32)100);
   1942		}
   1943
   1944		dte_data->tdep_r[1] = dte_data->r[4] * 2;
   1945
   1946		for (i = 2; i < SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE; i++) {
   1947			dte_data->tdep_r[i] = dte_data->r[4];
   1948		}
   1949	} else {
   1950		DRM_ERROR("Invalid PL2! DTE will not be updated.\n");
   1951	}
   1952}
   1953
   1954static struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev)
   1955{
   1956	struct rv7xx_power_info *pi = adev->pm.dpm.priv;
   1957
   1958	return pi;
   1959}
   1960
   1961static struct ni_power_info *ni_get_pi(struct amdgpu_device *adev)
   1962{
   1963	struct ni_power_info *pi = adev->pm.dpm.priv;
   1964
   1965	return pi;
   1966}
   1967
   1968static struct si_ps *si_get_ps(struct amdgpu_ps *aps)
   1969{
   1970	struct  si_ps *ps = aps->ps_priv;
   1971
   1972	return ps;
   1973}
   1974
   1975static void si_initialize_powertune_defaults(struct amdgpu_device *adev)
   1976{
   1977	struct ni_power_info *ni_pi = ni_get_pi(adev);
   1978	struct si_power_info *si_pi = si_get_pi(adev);
   1979	bool update_dte_from_pl2 = false;
   1980
   1981	if (adev->asic_type == CHIP_TAHITI) {
   1982		si_pi->cac_weights = cac_weights_tahiti;
   1983		si_pi->lcac_config = lcac_tahiti;
   1984		si_pi->cac_override = cac_override_tahiti;
   1985		si_pi->powertune_data = &powertune_data_tahiti;
   1986		si_pi->dte_data = dte_data_tahiti;
   1987
   1988		switch (adev->pdev->device) {
   1989		case 0x6798:
   1990			si_pi->dte_data.enable_dte_by_default = true;
   1991			break;
   1992		case 0x6799:
   1993			si_pi->dte_data = dte_data_new_zealand;
   1994			break;
   1995		case 0x6790:
   1996		case 0x6791:
   1997		case 0x6792:
   1998		case 0x679E:
   1999			si_pi->dte_data = dte_data_aruba_pro;
   2000			update_dte_from_pl2 = true;
   2001			break;
   2002		case 0x679B:
   2003			si_pi->dte_data = dte_data_malta;
   2004			update_dte_from_pl2 = true;
   2005			break;
   2006		case 0x679A:
   2007			si_pi->dte_data = dte_data_tahiti_pro;
   2008			update_dte_from_pl2 = true;
   2009			break;
   2010		default:
   2011			if (si_pi->dte_data.enable_dte_by_default == true)
   2012				DRM_ERROR("DTE is not enabled!\n");
   2013			break;
   2014		}
   2015	} else if (adev->asic_type == CHIP_PITCAIRN) {
   2016		si_pi->cac_weights = cac_weights_pitcairn;
   2017		si_pi->lcac_config = lcac_pitcairn;
   2018		si_pi->cac_override = cac_override_pitcairn;
   2019		si_pi->powertune_data = &powertune_data_pitcairn;
   2020
   2021		switch (adev->pdev->device) {
   2022		case 0x6810:
   2023		case 0x6818:
   2024			si_pi->dte_data = dte_data_curacao_xt;
   2025			update_dte_from_pl2 = true;
   2026			break;
   2027		case 0x6819:
   2028		case 0x6811:
   2029			si_pi->dte_data = dte_data_curacao_pro;
   2030			update_dte_from_pl2 = true;
   2031			break;
   2032		case 0x6800:
   2033		case 0x6806:
   2034			si_pi->dte_data = dte_data_neptune_xt;
   2035			update_dte_from_pl2 = true;
   2036			break;
   2037		default:
   2038			si_pi->dte_data = dte_data_pitcairn;
   2039			break;
   2040		}
   2041	} else if (adev->asic_type == CHIP_VERDE) {
   2042		si_pi->lcac_config = lcac_cape_verde;
   2043		si_pi->cac_override = cac_override_cape_verde;
   2044		si_pi->powertune_data = &powertune_data_cape_verde;
   2045
   2046		switch (adev->pdev->device) {
   2047		case 0x683B:
   2048		case 0x683F:
   2049		case 0x6829:
   2050		case 0x6835:
   2051			si_pi->cac_weights = cac_weights_cape_verde_pro;
   2052			si_pi->dte_data = dte_data_cape_verde;
   2053			break;
   2054		case 0x682C:
   2055			si_pi->cac_weights = cac_weights_cape_verde_pro;
   2056			si_pi->dte_data = dte_data_sun_xt;
   2057			update_dte_from_pl2 = true;
   2058			break;
   2059		case 0x6825:
   2060		case 0x6827:
   2061			si_pi->cac_weights = cac_weights_heathrow;
   2062			si_pi->dte_data = dte_data_cape_verde;
   2063			break;
   2064		case 0x6824:
   2065		case 0x682D:
   2066			si_pi->cac_weights = cac_weights_chelsea_xt;
   2067			si_pi->dte_data = dte_data_cape_verde;
   2068			break;
   2069		case 0x682F:
   2070			si_pi->cac_weights = cac_weights_chelsea_pro;
   2071			si_pi->dte_data = dte_data_cape_verde;
   2072			break;
   2073		case 0x6820:
   2074			si_pi->cac_weights = cac_weights_heathrow;
   2075			si_pi->dte_data = dte_data_venus_xtx;
   2076			break;
   2077		case 0x6821:
   2078			si_pi->cac_weights = cac_weights_heathrow;
   2079			si_pi->dte_data = dte_data_venus_xt;
   2080			break;
   2081		case 0x6823:
   2082		case 0x682B:
   2083		case 0x6822:
   2084		case 0x682A:
   2085			si_pi->cac_weights = cac_weights_chelsea_pro;
   2086			si_pi->dte_data = dte_data_venus_pro;
   2087			break;
   2088		default:
   2089			si_pi->cac_weights = cac_weights_cape_verde;
   2090			si_pi->dte_data = dte_data_cape_verde;
   2091			break;
   2092		}
   2093	} else if (adev->asic_type == CHIP_OLAND) {
   2094		si_pi->lcac_config = lcac_mars_pro;
   2095		si_pi->cac_override = cac_override_oland;
   2096		si_pi->powertune_data = &powertune_data_mars_pro;
   2097		si_pi->dte_data = dte_data_mars_pro;
   2098
   2099		switch (adev->pdev->device) {
   2100		case 0x6601:
   2101		case 0x6621:
   2102		case 0x6603:
   2103		case 0x6605:
   2104			si_pi->cac_weights = cac_weights_mars_pro;
   2105			update_dte_from_pl2 = true;
   2106			break;
   2107		case 0x6600:
   2108		case 0x6606:
   2109		case 0x6620:
   2110		case 0x6604:
   2111			si_pi->cac_weights = cac_weights_mars_xt;
   2112			update_dte_from_pl2 = true;
   2113			break;
   2114		case 0x6611:
   2115		case 0x6613:
   2116		case 0x6608:
   2117			si_pi->cac_weights = cac_weights_oland_pro;
   2118			update_dte_from_pl2 = true;
   2119			break;
   2120		case 0x6610:
   2121			si_pi->cac_weights = cac_weights_oland_xt;
   2122			update_dte_from_pl2 = true;
   2123			break;
   2124		default:
   2125			si_pi->cac_weights = cac_weights_oland;
   2126			si_pi->lcac_config = lcac_oland;
   2127			si_pi->cac_override = cac_override_oland;
   2128			si_pi->powertune_data = &powertune_data_oland;
   2129			si_pi->dte_data = dte_data_oland;
   2130			break;
   2131		}
   2132	} else if (adev->asic_type == CHIP_HAINAN) {
   2133		si_pi->cac_weights = cac_weights_hainan;
   2134		si_pi->lcac_config = lcac_oland;
   2135		si_pi->cac_override = cac_override_oland;
   2136		si_pi->powertune_data = &powertune_data_hainan;
   2137		si_pi->dte_data = dte_data_sun_xt;
   2138		update_dte_from_pl2 = true;
   2139	} else {
   2140		DRM_ERROR("Unknown SI asic revision, failed to initialize PowerTune!\n");
   2141		return;
   2142	}
   2143
   2144	ni_pi->enable_power_containment = false;
   2145	ni_pi->enable_cac = false;
   2146	ni_pi->enable_sq_ramping = false;
   2147	si_pi->enable_dte = false;
   2148
   2149	if (si_pi->powertune_data->enable_powertune_by_default) {
   2150		ni_pi->enable_power_containment = true;
   2151		ni_pi->enable_cac = true;
   2152		if (si_pi->dte_data.enable_dte_by_default) {
   2153			si_pi->enable_dte = true;
   2154			if (update_dte_from_pl2)
   2155				si_update_dte_from_pl2(adev, &si_pi->dte_data);
   2156
   2157		}
   2158		ni_pi->enable_sq_ramping = true;
   2159	}
   2160
   2161	ni_pi->driver_calculate_cac_leakage = true;
   2162	ni_pi->cac_configuration_required = true;
   2163
   2164	if (ni_pi->cac_configuration_required) {
   2165		ni_pi->support_cac_long_term_average = true;
   2166		si_pi->dyn_powertune_data.l2_lta_window_size =
   2167			si_pi->powertune_data->l2_lta_window_size_default;
   2168		si_pi->dyn_powertune_data.lts_truncate =
   2169			si_pi->powertune_data->lts_truncate_default;
   2170	} else {
   2171		ni_pi->support_cac_long_term_average = false;
   2172		si_pi->dyn_powertune_data.l2_lta_window_size = 0;
   2173		si_pi->dyn_powertune_data.lts_truncate = 0;
   2174	}
   2175
   2176	si_pi->dyn_powertune_data.disable_uvd_powertune = false;
   2177}
   2178
   2179static u32 si_get_smc_power_scaling_factor(struct amdgpu_device *adev)
   2180{
   2181	return 1;
   2182}
   2183
   2184static u32 si_calculate_cac_wintime(struct amdgpu_device *adev)
   2185{
   2186	u32 xclk;
   2187	u32 wintime;
   2188	u32 cac_window;
   2189	u32 cac_window_size;
   2190
   2191	xclk = amdgpu_asic_get_xclk(adev);
   2192
   2193	if (xclk == 0)
   2194		return 0;
   2195
   2196	cac_window = RREG32(CG_CAC_CTRL) & CAC_WINDOW_MASK;
   2197	cac_window_size = ((cac_window & 0xFFFF0000) >> 16) * (cac_window & 0x0000FFFF);
   2198
   2199	wintime = (cac_window_size * 100) / xclk;
   2200
   2201	return wintime;
   2202}
   2203
   2204static u32 si_scale_power_for_smc(u32 power_in_watts, u32 scaling_factor)
   2205{
   2206	return power_in_watts;
   2207}
   2208
   2209static int si_calculate_adjusted_tdp_limits(struct amdgpu_device *adev,
   2210					    bool adjust_polarity,
   2211					    u32 tdp_adjustment,
   2212					    u32 *tdp_limit,
   2213					    u32 *near_tdp_limit)
   2214{
   2215	u32 adjustment_delta, max_tdp_limit;
   2216
   2217	if (tdp_adjustment > (u32)adev->pm.dpm.tdp_od_limit)
   2218		return -EINVAL;
   2219
   2220	max_tdp_limit = ((100 + 100) * adev->pm.dpm.tdp_limit) / 100;
   2221
   2222	if (adjust_polarity) {
   2223		*tdp_limit = ((100 + tdp_adjustment) * adev->pm.dpm.tdp_limit) / 100;
   2224		*near_tdp_limit = adev->pm.dpm.near_tdp_limit_adjusted + (*tdp_limit - adev->pm.dpm.tdp_limit);
   2225	} else {
   2226		*tdp_limit = ((100 - tdp_adjustment) * adev->pm.dpm.tdp_limit) / 100;
   2227		adjustment_delta  = adev->pm.dpm.tdp_limit - *tdp_limit;
   2228		if (adjustment_delta < adev->pm.dpm.near_tdp_limit_adjusted)
   2229			*near_tdp_limit = adev->pm.dpm.near_tdp_limit_adjusted - adjustment_delta;
   2230		else
   2231			*near_tdp_limit = 0;
   2232	}
   2233
   2234	if ((*tdp_limit <= 0) || (*tdp_limit > max_tdp_limit))
   2235		return -EINVAL;
   2236	if ((*near_tdp_limit <= 0) || (*near_tdp_limit > *tdp_limit))
   2237		return -EINVAL;
   2238
   2239	return 0;
   2240}
   2241
   2242static int si_populate_smc_tdp_limits(struct amdgpu_device *adev,
   2243				      struct amdgpu_ps *amdgpu_state)
   2244{
   2245	struct ni_power_info *ni_pi = ni_get_pi(adev);
   2246	struct si_power_info *si_pi = si_get_pi(adev);
   2247
   2248	if (ni_pi->enable_power_containment) {
   2249		SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable;
   2250		PP_SIslands_PAPMParameters *papm_parm;
   2251		struct amdgpu_ppm_table *ppm = adev->pm.dpm.dyn_state.ppm_table;
   2252		u32 scaling_factor = si_get_smc_power_scaling_factor(adev);
   2253		u32 tdp_limit;
   2254		u32 near_tdp_limit;
   2255		int ret;
   2256
   2257		if (scaling_factor == 0)
   2258			return -EINVAL;
   2259
   2260		memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
   2261
   2262		ret = si_calculate_adjusted_tdp_limits(adev,
   2263						       false, /* ??? */
   2264						       adev->pm.dpm.tdp_adjustment,
   2265						       &tdp_limit,
   2266						       &near_tdp_limit);
   2267		if (ret)
   2268			return ret;
   2269
   2270		smc_table->dpm2Params.TDPLimit =
   2271			cpu_to_be32(si_scale_power_for_smc(tdp_limit, scaling_factor) * 1000);
   2272		smc_table->dpm2Params.NearTDPLimit =
   2273			cpu_to_be32(si_scale_power_for_smc(near_tdp_limit, scaling_factor) * 1000);
   2274		smc_table->dpm2Params.SafePowerLimit =
   2275			cpu_to_be32(si_scale_power_for_smc((near_tdp_limit * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000);
   2276
   2277		ret = amdgpu_si_copy_bytes_to_smc(adev,
   2278						  (si_pi->state_table_start + offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) +
   2279						   offsetof(PP_SIslands_DPM2Parameters, TDPLimit)),
   2280						  (u8 *)(&(smc_table->dpm2Params.TDPLimit)),
   2281						  sizeof(u32) * 3,
   2282						  si_pi->sram_end);
   2283		if (ret)
   2284			return ret;
   2285
   2286		if (si_pi->enable_ppm) {
   2287			papm_parm = &si_pi->papm_parm;
   2288			memset(papm_parm, 0, sizeof(PP_SIslands_PAPMParameters));
   2289			papm_parm->NearTDPLimitTherm = cpu_to_be32(ppm->dgpu_tdp);
   2290			papm_parm->dGPU_T_Limit = cpu_to_be32(ppm->tj_max);
   2291			papm_parm->dGPU_T_Warning = cpu_to_be32(95);
   2292			papm_parm->dGPU_T_Hysteresis = cpu_to_be32(5);
   2293			papm_parm->PlatformPowerLimit = 0xffffffff;
   2294			papm_parm->NearTDPLimitPAPM = 0xffffffff;
   2295
   2296			ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->papm_cfg_table_start,
   2297							  (u8 *)papm_parm,
   2298							  sizeof(PP_SIslands_PAPMParameters),
   2299							  si_pi->sram_end);
   2300			if (ret)
   2301				return ret;
   2302		}
   2303	}
   2304	return 0;
   2305}
   2306
   2307static int si_populate_smc_tdp_limits_2(struct amdgpu_device *adev,
   2308					struct amdgpu_ps *amdgpu_state)
   2309{
   2310	struct ni_power_info *ni_pi = ni_get_pi(adev);
   2311	struct si_power_info *si_pi = si_get_pi(adev);
   2312
   2313	if (ni_pi->enable_power_containment) {
   2314		SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable;
   2315		u32 scaling_factor = si_get_smc_power_scaling_factor(adev);
   2316		int ret;
   2317
   2318		memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
   2319
   2320		smc_table->dpm2Params.NearTDPLimit =
   2321			cpu_to_be32(si_scale_power_for_smc(adev->pm.dpm.near_tdp_limit_adjusted, scaling_factor) * 1000);
   2322		smc_table->dpm2Params.SafePowerLimit =
   2323			cpu_to_be32(si_scale_power_for_smc((adev->pm.dpm.near_tdp_limit_adjusted * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000);
   2324
   2325		ret = amdgpu_si_copy_bytes_to_smc(adev,
   2326						  (si_pi->state_table_start +
   2327						   offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) +
   2328						   offsetof(PP_SIslands_DPM2Parameters, NearTDPLimit)),
   2329						  (u8 *)(&(smc_table->dpm2Params.NearTDPLimit)),
   2330						  sizeof(u32) * 2,
   2331						  si_pi->sram_end);
   2332		if (ret)
   2333			return ret;
   2334	}
   2335
   2336	return 0;
   2337}
   2338
   2339static u16 si_calculate_power_efficiency_ratio(struct amdgpu_device *adev,
   2340					       const u16 prev_std_vddc,
   2341					       const u16 curr_std_vddc)
   2342{
   2343	u64 margin = (u64)SISLANDS_DPM2_PWREFFICIENCYRATIO_MARGIN;
   2344	u64 prev_vddc = (u64)prev_std_vddc;
   2345	u64 curr_vddc = (u64)curr_std_vddc;
   2346	u64 pwr_efficiency_ratio, n, d;
   2347
   2348	if ((prev_vddc == 0) || (curr_vddc == 0))
   2349		return 0;
   2350
   2351	n = div64_u64((u64)1024 * curr_vddc * curr_vddc * ((u64)1000 + margin), (u64)1000);
   2352	d = prev_vddc * prev_vddc;
   2353	pwr_efficiency_ratio = div64_u64(n, d);
   2354
   2355	if (pwr_efficiency_ratio > (u64)0xFFFF)
   2356		return 0;
   2357
   2358	return (u16)pwr_efficiency_ratio;
   2359}
   2360
   2361static bool si_should_disable_uvd_powertune(struct amdgpu_device *adev,
   2362					    struct amdgpu_ps *amdgpu_state)
   2363{
   2364	struct si_power_info *si_pi = si_get_pi(adev);
   2365
   2366	if (si_pi->dyn_powertune_data.disable_uvd_powertune &&
   2367	    amdgpu_state->vclk && amdgpu_state->dclk)
   2368		return true;
   2369
   2370	return false;
   2371}
   2372
   2373struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev)
   2374{
   2375	struct evergreen_power_info *pi = adev->pm.dpm.priv;
   2376
   2377	return pi;
   2378}
   2379
   2380static int si_populate_power_containment_values(struct amdgpu_device *adev,
   2381						struct amdgpu_ps *amdgpu_state,
   2382						SISLANDS_SMC_SWSTATE *smc_state)
   2383{
   2384	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   2385	struct ni_power_info *ni_pi = ni_get_pi(adev);
   2386	struct  si_ps *state = si_get_ps(amdgpu_state);
   2387	SISLANDS_SMC_VOLTAGE_VALUE vddc;
   2388	u32 prev_sclk;
   2389	u32 max_sclk;
   2390	u32 min_sclk;
   2391	u16 prev_std_vddc;
   2392	u16 curr_std_vddc;
   2393	int i;
   2394	u16 pwr_efficiency_ratio;
   2395	u8 max_ps_percent;
   2396	bool disable_uvd_power_tune;
   2397	int ret;
   2398
   2399	if (ni_pi->enable_power_containment == false)
   2400		return 0;
   2401
   2402	if (state->performance_level_count == 0)
   2403		return -EINVAL;
   2404
   2405	if (smc_state->levelCount != state->performance_level_count)
   2406		return -EINVAL;
   2407
   2408	disable_uvd_power_tune = si_should_disable_uvd_powertune(adev, amdgpu_state);
   2409
   2410	smc_state->levels[0].dpm2.MaxPS = 0;
   2411	smc_state->levels[0].dpm2.NearTDPDec = 0;
   2412	smc_state->levels[0].dpm2.AboveSafeInc = 0;
   2413	smc_state->levels[0].dpm2.BelowSafeInc = 0;
   2414	smc_state->levels[0].dpm2.PwrEfficiencyRatio = 0;
   2415
   2416	for (i = 1; i < state->performance_level_count; i++) {
   2417		prev_sclk = state->performance_levels[i-1].sclk;
   2418		max_sclk  = state->performance_levels[i].sclk;
   2419		if (i == 1)
   2420			max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_M;
   2421		else
   2422			max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_H;
   2423
   2424		if (prev_sclk > max_sclk)
   2425			return -EINVAL;
   2426
   2427		if ((max_ps_percent == 0) ||
   2428		    (prev_sclk == max_sclk) ||
   2429		    disable_uvd_power_tune)
   2430			min_sclk = max_sclk;
   2431		else if (i == 1)
   2432			min_sclk = prev_sclk;
   2433		else
   2434			min_sclk = (prev_sclk * (u32)max_ps_percent) / 100;
   2435
   2436		if (min_sclk < state->performance_levels[0].sclk)
   2437			min_sclk = state->performance_levels[0].sclk;
   2438
   2439		if (min_sclk == 0)
   2440			return -EINVAL;
   2441
   2442		ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table,
   2443						state->performance_levels[i-1].vddc, &vddc);
   2444		if (ret)
   2445			return ret;
   2446
   2447		ret = si_get_std_voltage_value(adev, &vddc, &prev_std_vddc);
   2448		if (ret)
   2449			return ret;
   2450
   2451		ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table,
   2452						state->performance_levels[i].vddc, &vddc);
   2453		if (ret)
   2454			return ret;
   2455
   2456		ret = si_get_std_voltage_value(adev, &vddc, &curr_std_vddc);
   2457		if (ret)
   2458			return ret;
   2459
   2460		pwr_efficiency_ratio = si_calculate_power_efficiency_ratio(adev,
   2461									   prev_std_vddc, curr_std_vddc);
   2462
   2463		smc_state->levels[i].dpm2.MaxPS = (u8)((SISLANDS_DPM2_MAX_PULSE_SKIP * (max_sclk - min_sclk)) / max_sclk);
   2464		smc_state->levels[i].dpm2.NearTDPDec = SISLANDS_DPM2_NEAR_TDP_DEC;
   2465		smc_state->levels[i].dpm2.AboveSafeInc = SISLANDS_DPM2_ABOVE_SAFE_INC;
   2466		smc_state->levels[i].dpm2.BelowSafeInc = SISLANDS_DPM2_BELOW_SAFE_INC;
   2467		smc_state->levels[i].dpm2.PwrEfficiencyRatio = cpu_to_be16(pwr_efficiency_ratio);
   2468	}
   2469
   2470	return 0;
   2471}
   2472
   2473static int si_populate_sq_ramping_values(struct amdgpu_device *adev,
   2474					 struct amdgpu_ps *amdgpu_state,
   2475					 SISLANDS_SMC_SWSTATE *smc_state)
   2476{
   2477	struct ni_power_info *ni_pi = ni_get_pi(adev);
   2478	struct  si_ps *state = si_get_ps(amdgpu_state);
   2479	u32 sq_power_throttle, sq_power_throttle2;
   2480	bool enable_sq_ramping = ni_pi->enable_sq_ramping;
   2481	int i;
   2482
   2483	if (state->performance_level_count == 0)
   2484		return -EINVAL;
   2485
   2486	if (smc_state->levelCount != state->performance_level_count)
   2487		return -EINVAL;
   2488
   2489	if (adev->pm.dpm.sq_ramping_threshold == 0)
   2490		return -EINVAL;
   2491
   2492	if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER > (MAX_POWER_MASK >> MAX_POWER_SHIFT))
   2493		enable_sq_ramping = false;
   2494
   2495	if (SISLANDS_DPM2_SQ_RAMP_MIN_POWER > (MIN_POWER_MASK >> MIN_POWER_SHIFT))
   2496		enable_sq_ramping = false;
   2497
   2498	if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA > (MAX_POWER_DELTA_MASK >> MAX_POWER_DELTA_SHIFT))
   2499		enable_sq_ramping = false;
   2500
   2501	if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
   2502		enable_sq_ramping = false;
   2503
   2504	if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
   2505		enable_sq_ramping = false;
   2506
   2507	for (i = 0; i < state->performance_level_count; i++) {
   2508		sq_power_throttle = 0;
   2509		sq_power_throttle2 = 0;
   2510
   2511		if ((state->performance_levels[i].sclk >= adev->pm.dpm.sq_ramping_threshold) &&
   2512		    enable_sq_ramping) {
   2513			sq_power_throttle |= MAX_POWER(SISLANDS_DPM2_SQ_RAMP_MAX_POWER);
   2514			sq_power_throttle |= MIN_POWER(SISLANDS_DPM2_SQ_RAMP_MIN_POWER);
   2515			sq_power_throttle2 |= MAX_POWER_DELTA(SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA);
   2516			sq_power_throttle2 |= STI_SIZE(SISLANDS_DPM2_SQ_RAMP_STI_SIZE);
   2517			sq_power_throttle2 |= LTI_RATIO(SISLANDS_DPM2_SQ_RAMP_LTI_RATIO);
   2518		} else {
   2519			sq_power_throttle |= MAX_POWER_MASK | MIN_POWER_MASK;
   2520			sq_power_throttle2 |= MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
   2521		}
   2522
   2523		smc_state->levels[i].SQPowerThrottle = cpu_to_be32(sq_power_throttle);
   2524		smc_state->levels[i].SQPowerThrottle_2 = cpu_to_be32(sq_power_throttle2);
   2525	}
   2526
   2527	return 0;
   2528}
   2529
   2530static int si_enable_power_containment(struct amdgpu_device *adev,
   2531				       struct amdgpu_ps *amdgpu_new_state,
   2532				       bool enable)
   2533{
   2534	struct ni_power_info *ni_pi = ni_get_pi(adev);
   2535	PPSMC_Result smc_result;
   2536	int ret = 0;
   2537
   2538	if (ni_pi->enable_power_containment) {
   2539		if (enable) {
   2540			if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) {
   2541				smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_TDPClampingActive);
   2542				if (smc_result != PPSMC_Result_OK) {
   2543					ret = -EINVAL;
   2544					ni_pi->pc_enabled = false;
   2545				} else {
   2546					ni_pi->pc_enabled = true;
   2547				}
   2548			}
   2549		} else {
   2550			smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_TDPClampingInactive);
   2551			if (smc_result != PPSMC_Result_OK)
   2552				ret = -EINVAL;
   2553			ni_pi->pc_enabled = false;
   2554		}
   2555	}
   2556
   2557	return ret;
   2558}
   2559
   2560static int si_initialize_smc_dte_tables(struct amdgpu_device *adev)
   2561{
   2562	struct si_power_info *si_pi = si_get_pi(adev);
   2563	int ret = 0;
   2564	struct si_dte_data *dte_data = &si_pi->dte_data;
   2565	Smc_SIslands_DTE_Configuration *dte_tables = NULL;
   2566	u32 table_size;
   2567	u8 tdep_count;
   2568	u32 i;
   2569
   2570	if (dte_data == NULL)
   2571		si_pi->enable_dte = false;
   2572
   2573	if (si_pi->enable_dte == false)
   2574		return 0;
   2575
   2576	if (dte_data->k <= 0)
   2577		return -EINVAL;
   2578
   2579	dte_tables = kzalloc(sizeof(Smc_SIslands_DTE_Configuration), GFP_KERNEL);
   2580	if (dte_tables == NULL) {
   2581		si_pi->enable_dte = false;
   2582		return -ENOMEM;
   2583	}
   2584
   2585	table_size = dte_data->k;
   2586
   2587	if (table_size > SMC_SISLANDS_DTE_MAX_FILTER_STAGES)
   2588		table_size = SMC_SISLANDS_DTE_MAX_FILTER_STAGES;
   2589
   2590	tdep_count = dte_data->tdep_count;
   2591	if (tdep_count > SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE)
   2592		tdep_count = SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE;
   2593
   2594	dte_tables->K = cpu_to_be32(table_size);
   2595	dte_tables->T0 = cpu_to_be32(dte_data->t0);
   2596	dte_tables->MaxT = cpu_to_be32(dte_data->max_t);
   2597	dte_tables->WindowSize = dte_data->window_size;
   2598	dte_tables->temp_select = dte_data->temp_select;
   2599	dte_tables->DTE_mode = dte_data->dte_mode;
   2600	dte_tables->Tthreshold = cpu_to_be32(dte_data->t_threshold);
   2601
   2602	if (tdep_count > 0)
   2603		table_size--;
   2604
   2605	for (i = 0; i < table_size; i++) {
   2606		dte_tables->tau[i] = cpu_to_be32(dte_data->tau[i]);
   2607		dte_tables->R[i]   = cpu_to_be32(dte_data->r[i]);
   2608	}
   2609
   2610	dte_tables->Tdep_count = tdep_count;
   2611
   2612	for (i = 0; i < (u32)tdep_count; i++) {
   2613		dte_tables->T_limits[i] = dte_data->t_limits[i];
   2614		dte_tables->Tdep_tau[i] = cpu_to_be32(dte_data->tdep_tau[i]);
   2615		dte_tables->Tdep_R[i] = cpu_to_be32(dte_data->tdep_r[i]);
   2616	}
   2617
   2618	ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->dte_table_start,
   2619					  (u8 *)dte_tables,
   2620					  sizeof(Smc_SIslands_DTE_Configuration),
   2621					  si_pi->sram_end);
   2622	kfree(dte_tables);
   2623
   2624	return ret;
   2625}
   2626
   2627static int si_get_cac_std_voltage_max_min(struct amdgpu_device *adev,
   2628					  u16 *max, u16 *min)
   2629{
   2630	struct si_power_info *si_pi = si_get_pi(adev);
   2631	struct amdgpu_cac_leakage_table *table =
   2632		&adev->pm.dpm.dyn_state.cac_leakage_table;
   2633	u32 i;
   2634	u32 v0_loadline;
   2635
   2636	if (table == NULL)
   2637		return -EINVAL;
   2638
   2639	*max = 0;
   2640	*min = 0xFFFF;
   2641
   2642	for (i = 0; i < table->count; i++) {
   2643		if (table->entries[i].vddc > *max)
   2644			*max = table->entries[i].vddc;
   2645		if (table->entries[i].vddc < *min)
   2646			*min = table->entries[i].vddc;
   2647	}
   2648
   2649	if (si_pi->powertune_data->lkge_lut_v0_percent > 100)
   2650		return -EINVAL;
   2651
   2652	v0_loadline = (*min) * (100 - si_pi->powertune_data->lkge_lut_v0_percent) / 100;
   2653
   2654	if (v0_loadline > 0xFFFFUL)
   2655		return -EINVAL;
   2656
   2657	*min = (u16)v0_loadline;
   2658
   2659	if ((*min > *max) || (*max == 0) || (*min == 0))
   2660		return -EINVAL;
   2661
   2662	return 0;
   2663}
   2664
   2665static u16 si_get_cac_std_voltage_step(u16 max, u16 min)
   2666{
   2667	return ((max - min) + (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1)) /
   2668		SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES;
   2669}
   2670
   2671static int si_init_dte_leakage_table(struct amdgpu_device *adev,
   2672				     PP_SIslands_CacConfig *cac_tables,
   2673				     u16 vddc_max, u16 vddc_min, u16 vddc_step,
   2674				     u16 t0, u16 t_step)
   2675{
   2676	struct si_power_info *si_pi = si_get_pi(adev);
   2677	u32 leakage;
   2678	unsigned int i, j;
   2679	s32 t;
   2680	u32 smc_leakage;
   2681	u32 scaling_factor;
   2682	u16 voltage;
   2683
   2684	scaling_factor = si_get_smc_power_scaling_factor(adev);
   2685
   2686	for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++) {
   2687		t = (1000 * (i * t_step + t0));
   2688
   2689		for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) {
   2690			voltage = vddc_max - (vddc_step * j);
   2691
   2692			si_calculate_leakage_for_v_and_t(adev,
   2693							 &si_pi->powertune_data->leakage_coefficients,
   2694							 voltage,
   2695							 t,
   2696							 si_pi->dyn_powertune_data.cac_leakage,
   2697							 &leakage);
   2698
   2699			smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4;
   2700
   2701			if (smc_leakage > 0xFFFF)
   2702				smc_leakage = 0xFFFF;
   2703
   2704			cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] =
   2705				cpu_to_be16((u16)smc_leakage);
   2706		}
   2707	}
   2708	return 0;
   2709}
   2710
   2711static int si_init_simplified_leakage_table(struct amdgpu_device *adev,
   2712					    PP_SIslands_CacConfig *cac_tables,
   2713					    u16 vddc_max, u16 vddc_min, u16 vddc_step)
   2714{
   2715	struct si_power_info *si_pi = si_get_pi(adev);
   2716	u32 leakage;
   2717	unsigned int i, j;
   2718	u32 smc_leakage;
   2719	u32 scaling_factor;
   2720	u16 voltage;
   2721
   2722	scaling_factor = si_get_smc_power_scaling_factor(adev);
   2723
   2724	for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) {
   2725		voltage = vddc_max - (vddc_step * j);
   2726
   2727		si_calculate_leakage_for_v(adev,
   2728					   &si_pi->powertune_data->leakage_coefficients,
   2729					   si_pi->powertune_data->fixed_kt,
   2730					   voltage,
   2731					   si_pi->dyn_powertune_data.cac_leakage,
   2732					   &leakage);
   2733
   2734		smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4;
   2735
   2736		if (smc_leakage > 0xFFFF)
   2737			smc_leakage = 0xFFFF;
   2738
   2739		for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++)
   2740			cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] =
   2741				cpu_to_be16((u16)smc_leakage);
   2742	}
   2743	return 0;
   2744}
   2745
   2746static int si_initialize_smc_cac_tables(struct amdgpu_device *adev)
   2747{
   2748	struct ni_power_info *ni_pi = ni_get_pi(adev);
   2749	struct si_power_info *si_pi = si_get_pi(adev);
   2750	PP_SIslands_CacConfig *cac_tables = NULL;
   2751	u16 vddc_max, vddc_min, vddc_step;
   2752	u16 t0, t_step;
   2753	u32 load_line_slope, reg;
   2754	int ret = 0;
   2755	u32 ticks_per_us = amdgpu_asic_get_xclk(adev) / 100;
   2756
   2757	if (ni_pi->enable_cac == false)
   2758		return 0;
   2759
   2760	cac_tables = kzalloc(sizeof(PP_SIslands_CacConfig), GFP_KERNEL);
   2761	if (!cac_tables)
   2762		return -ENOMEM;
   2763
   2764	reg = RREG32(CG_CAC_CTRL) & ~CAC_WINDOW_MASK;
   2765	reg |= CAC_WINDOW(si_pi->powertune_data->cac_window);
   2766	WREG32(CG_CAC_CTRL, reg);
   2767
   2768	si_pi->dyn_powertune_data.cac_leakage = adev->pm.dpm.cac_leakage;
   2769	si_pi->dyn_powertune_data.dc_pwr_value =
   2770		si_pi->powertune_data->dc_cac[NISLANDS_DCCAC_LEVEL_0];
   2771	si_pi->dyn_powertune_data.wintime = si_calculate_cac_wintime(adev);
   2772	si_pi->dyn_powertune_data.shift_n = si_pi->powertune_data->shift_n_default;
   2773
   2774	si_pi->dyn_powertune_data.leakage_minimum_temperature = 80 * 1000;
   2775
   2776	ret = si_get_cac_std_voltage_max_min(adev, &vddc_max, &vddc_min);
   2777	if (ret)
   2778		goto done_free;
   2779
   2780	vddc_step = si_get_cac_std_voltage_step(vddc_max, vddc_min);
   2781	vddc_min = vddc_max - (vddc_step * (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1));
   2782	t_step = 4;
   2783	t0 = 60;
   2784
   2785	if (si_pi->enable_dte || ni_pi->driver_calculate_cac_leakage)
   2786		ret = si_init_dte_leakage_table(adev, cac_tables,
   2787						vddc_max, vddc_min, vddc_step,
   2788						t0, t_step);
   2789	else
   2790		ret = si_init_simplified_leakage_table(adev, cac_tables,
   2791						       vddc_max, vddc_min, vddc_step);
   2792	if (ret)
   2793		goto done_free;
   2794
   2795	load_line_slope = ((u32)adev->pm.dpm.load_line_slope << SMC_SISLANDS_SCALE_R) / 100;
   2796
   2797	cac_tables->l2numWin_TDP = cpu_to_be32(si_pi->dyn_powertune_data.l2_lta_window_size);
   2798	cac_tables->lts_truncate_n = si_pi->dyn_powertune_data.lts_truncate;
   2799	cac_tables->SHIFT_N = si_pi->dyn_powertune_data.shift_n;
   2800	cac_tables->lkge_lut_V0 = cpu_to_be32((u32)vddc_min);
   2801	cac_tables->lkge_lut_Vstep = cpu_to_be32((u32)vddc_step);
   2802	cac_tables->R_LL = cpu_to_be32(load_line_slope);
   2803	cac_tables->WinTime = cpu_to_be32(si_pi->dyn_powertune_data.wintime);
   2804	cac_tables->calculation_repeats = cpu_to_be32(2);
   2805	cac_tables->dc_cac = cpu_to_be32(0);
   2806	cac_tables->log2_PG_LKG_SCALE = 12;
   2807	cac_tables->cac_temp = si_pi->powertune_data->operating_temp;
   2808	cac_tables->lkge_lut_T0 = cpu_to_be32((u32)t0);
   2809	cac_tables->lkge_lut_Tstep = cpu_to_be32((u32)t_step);
   2810
   2811	ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->cac_table_start,
   2812					  (u8 *)cac_tables,
   2813					  sizeof(PP_SIslands_CacConfig),
   2814					  si_pi->sram_end);
   2815
   2816	if (ret)
   2817		goto done_free;
   2818
   2819	ret = si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_ticks_per_us, ticks_per_us);
   2820
   2821done_free:
   2822	if (ret) {
   2823		ni_pi->enable_cac = false;
   2824		ni_pi->enable_power_containment = false;
   2825	}
   2826
   2827	kfree(cac_tables);
   2828
   2829	return ret;
   2830}
   2831
   2832static int si_program_cac_config_registers(struct amdgpu_device *adev,
   2833					   const struct si_cac_config_reg *cac_config_regs)
   2834{
   2835	const struct si_cac_config_reg *config_regs = cac_config_regs;
   2836	u32 data = 0, offset;
   2837
   2838	if (!config_regs)
   2839		return -EINVAL;
   2840
   2841	while (config_regs->offset != 0xFFFFFFFF) {
   2842		switch (config_regs->type) {
   2843		case SISLANDS_CACCONFIG_CGIND:
   2844			offset = SMC_CG_IND_START + config_regs->offset;
   2845			if (offset < SMC_CG_IND_END)
   2846				data = RREG32_SMC(offset);
   2847			break;
   2848		default:
   2849			data = RREG32(config_regs->offset);
   2850			break;
   2851		}
   2852
   2853		data &= ~config_regs->mask;
   2854		data |= ((config_regs->value << config_regs->shift) & config_regs->mask);
   2855
   2856		switch (config_regs->type) {
   2857		case SISLANDS_CACCONFIG_CGIND:
   2858			offset = SMC_CG_IND_START + config_regs->offset;
   2859			if (offset < SMC_CG_IND_END)
   2860				WREG32_SMC(offset, data);
   2861			break;
   2862		default:
   2863			WREG32(config_regs->offset, data);
   2864			break;
   2865		}
   2866		config_regs++;
   2867	}
   2868	return 0;
   2869}
   2870
   2871static int si_initialize_hardware_cac_manager(struct amdgpu_device *adev)
   2872{
   2873	struct ni_power_info *ni_pi = ni_get_pi(adev);
   2874	struct si_power_info *si_pi = si_get_pi(adev);
   2875	int ret;
   2876
   2877	if ((ni_pi->enable_cac == false) ||
   2878	    (ni_pi->cac_configuration_required == false))
   2879		return 0;
   2880
   2881	ret = si_program_cac_config_registers(adev, si_pi->lcac_config);
   2882	if (ret)
   2883		return ret;
   2884	ret = si_program_cac_config_registers(adev, si_pi->cac_override);
   2885	if (ret)
   2886		return ret;
   2887	ret = si_program_cac_config_registers(adev, si_pi->cac_weights);
   2888	if (ret)
   2889		return ret;
   2890
   2891	return 0;
   2892}
   2893
   2894static int si_enable_smc_cac(struct amdgpu_device *adev,
   2895			     struct amdgpu_ps *amdgpu_new_state,
   2896			     bool enable)
   2897{
   2898	struct ni_power_info *ni_pi = ni_get_pi(adev);
   2899	struct si_power_info *si_pi = si_get_pi(adev);
   2900	PPSMC_Result smc_result;
   2901	int ret = 0;
   2902
   2903	if (ni_pi->enable_cac) {
   2904		if (enable) {
   2905			if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) {
   2906				if (ni_pi->support_cac_long_term_average) {
   2907					smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgEnable);
   2908					if (smc_result != PPSMC_Result_OK)
   2909						ni_pi->support_cac_long_term_average = false;
   2910				}
   2911
   2912				smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableCac);
   2913				if (smc_result != PPSMC_Result_OK) {
   2914					ret = -EINVAL;
   2915					ni_pi->cac_enabled = false;
   2916				} else {
   2917					ni_pi->cac_enabled = true;
   2918				}
   2919
   2920				if (si_pi->enable_dte) {
   2921					smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableDTE);
   2922					if (smc_result != PPSMC_Result_OK)
   2923						ret = -EINVAL;
   2924				}
   2925			}
   2926		} else if (ni_pi->cac_enabled) {
   2927			if (si_pi->enable_dte)
   2928				smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableDTE);
   2929
   2930			smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableCac);
   2931
   2932			ni_pi->cac_enabled = false;
   2933
   2934			if (ni_pi->support_cac_long_term_average)
   2935				smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgDisable);
   2936		}
   2937	}
   2938	return ret;
   2939}
   2940
   2941static int si_init_smc_spll_table(struct amdgpu_device *adev)
   2942{
   2943	struct ni_power_info *ni_pi = ni_get_pi(adev);
   2944	struct si_power_info *si_pi = si_get_pi(adev);
   2945	SMC_SISLANDS_SPLL_DIV_TABLE *spll_table;
   2946	SISLANDS_SMC_SCLK_VALUE sclk_params;
   2947	u32 fb_div, p_div;
   2948	u32 clk_s, clk_v;
   2949	u32 sclk = 0;
   2950	int ret = 0;
   2951	u32 tmp;
   2952	int i;
   2953
   2954	if (si_pi->spll_table_start == 0)
   2955		return -EINVAL;
   2956
   2957	spll_table = kzalloc(sizeof(SMC_SISLANDS_SPLL_DIV_TABLE), GFP_KERNEL);
   2958	if (spll_table == NULL)
   2959		return -ENOMEM;
   2960
   2961	for (i = 0; i < 256; i++) {
   2962		ret = si_calculate_sclk_params(adev, sclk, &sclk_params);
   2963		if (ret)
   2964			break;
   2965		p_div = (sclk_params.vCG_SPLL_FUNC_CNTL & SPLL_PDIV_A_MASK) >> SPLL_PDIV_A_SHIFT;
   2966		fb_div = (sclk_params.vCG_SPLL_FUNC_CNTL_3 & SPLL_FB_DIV_MASK) >> SPLL_FB_DIV_SHIFT;
   2967		clk_s = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM & CLK_S_MASK) >> CLK_S_SHIFT;
   2968		clk_v = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM_2 & CLK_V_MASK) >> CLK_V_SHIFT;
   2969
   2970		fb_div &= ~0x00001FFF;
   2971		fb_div >>= 1;
   2972		clk_v >>= 6;
   2973
   2974		if (p_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT))
   2975			ret = -EINVAL;
   2976		if (fb_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT))
   2977			ret = -EINVAL;
   2978		if (clk_s & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT))
   2979			ret = -EINVAL;
   2980		if (clk_v & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT))
   2981			ret = -EINVAL;
   2982
   2983		if (ret)
   2984			break;
   2985
   2986		tmp = ((fb_div << SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK) |
   2987			((p_div << SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK);
   2988		spll_table->freq[i] = cpu_to_be32(tmp);
   2989
   2990		tmp = ((clk_v << SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK) |
   2991			((clk_s << SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK);
   2992		spll_table->ss[i] = cpu_to_be32(tmp);
   2993
   2994		sclk += 512;
   2995	}
   2996
   2997
   2998	if (!ret)
   2999		ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->spll_table_start,
   3000						  (u8 *)spll_table,
   3001						  sizeof(SMC_SISLANDS_SPLL_DIV_TABLE),
   3002						  si_pi->sram_end);
   3003
   3004	if (ret)
   3005		ni_pi->enable_power_containment = false;
   3006
   3007	kfree(spll_table);
   3008
   3009	return ret;
   3010}
   3011
   3012static u16 si_get_lower_of_leakage_and_vce_voltage(struct amdgpu_device *adev,
   3013						   u16 vce_voltage)
   3014{
   3015	u16 highest_leakage = 0;
   3016	struct si_power_info *si_pi = si_get_pi(adev);
   3017	int i;
   3018
   3019	for (i = 0; i < si_pi->leakage_voltage.count; i++){
   3020		if (highest_leakage < si_pi->leakage_voltage.entries[i].voltage)
   3021			highest_leakage = si_pi->leakage_voltage.entries[i].voltage;
   3022	}
   3023
   3024	if (si_pi->leakage_voltage.count && (highest_leakage < vce_voltage))
   3025		return highest_leakage;
   3026
   3027	return vce_voltage;
   3028}
   3029
   3030static int si_get_vce_clock_voltage(struct amdgpu_device *adev,
   3031				    u32 evclk, u32 ecclk, u16 *voltage)
   3032{
   3033	u32 i;
   3034	int ret = -EINVAL;
   3035	struct amdgpu_vce_clock_voltage_dependency_table *table =
   3036		&adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
   3037
   3038	if (((evclk == 0) && (ecclk == 0)) ||
   3039	    (table && (table->count == 0))) {
   3040		*voltage = 0;
   3041		return 0;
   3042	}
   3043
   3044	for (i = 0; i < table->count; i++) {
   3045		if ((evclk <= table->entries[i].evclk) &&
   3046		    (ecclk <= table->entries[i].ecclk)) {
   3047			*voltage = table->entries[i].v;
   3048			ret = 0;
   3049			break;
   3050		}
   3051	}
   3052
   3053	/* if no match return the highest voltage */
   3054	if (ret)
   3055		*voltage = table->entries[table->count - 1].v;
   3056
   3057	*voltage = si_get_lower_of_leakage_and_vce_voltage(adev, *voltage);
   3058
   3059	return ret;
   3060}
   3061
   3062static bool si_dpm_vblank_too_short(void *handle)
   3063{
   3064	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   3065	u32 vblank_time = amdgpu_dpm_get_vblank_time(adev);
   3066	/* we never hit the non-gddr5 limit so disable it */
   3067	u32 switch_limit = adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 0;
   3068
   3069	if (vblank_time < switch_limit)
   3070		return true;
   3071	else
   3072		return false;
   3073
   3074}
   3075
   3076static int ni_copy_and_switch_arb_sets(struct amdgpu_device *adev,
   3077				u32 arb_freq_src, u32 arb_freq_dest)
   3078{
   3079	u32 mc_arb_dram_timing;
   3080	u32 mc_arb_dram_timing2;
   3081	u32 burst_time;
   3082	u32 mc_cg_config;
   3083
   3084	switch (arb_freq_src) {
   3085	case MC_CG_ARB_FREQ_F0:
   3086		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING);
   3087		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
   3088		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE0_MASK) >> STATE0_SHIFT;
   3089		break;
   3090	case MC_CG_ARB_FREQ_F1:
   3091		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_1);
   3092		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_1);
   3093		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE1_MASK) >> STATE1_SHIFT;
   3094		break;
   3095	case MC_CG_ARB_FREQ_F2:
   3096		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_2);
   3097		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_2);
   3098		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE2_MASK) >> STATE2_SHIFT;
   3099		break;
   3100	case MC_CG_ARB_FREQ_F3:
   3101		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_3);
   3102		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_3);
   3103		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE3_MASK) >> STATE3_SHIFT;
   3104		break;
   3105	default:
   3106		return -EINVAL;
   3107	}
   3108
   3109	switch (arb_freq_dest) {
   3110	case MC_CG_ARB_FREQ_F0:
   3111		WREG32(MC_ARB_DRAM_TIMING, mc_arb_dram_timing);
   3112		WREG32(MC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);
   3113		WREG32_P(MC_ARB_BURST_TIME, STATE0(burst_time), ~STATE0_MASK);
   3114		break;
   3115	case MC_CG_ARB_FREQ_F1:
   3116		WREG32(MC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);
   3117		WREG32(MC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);
   3118		WREG32_P(MC_ARB_BURST_TIME, STATE1(burst_time), ~STATE1_MASK);
   3119		break;
   3120	case MC_CG_ARB_FREQ_F2:
   3121		WREG32(MC_ARB_DRAM_TIMING_2, mc_arb_dram_timing);
   3122		WREG32(MC_ARB_DRAM_TIMING2_2, mc_arb_dram_timing2);
   3123		WREG32_P(MC_ARB_BURST_TIME, STATE2(burst_time), ~STATE2_MASK);
   3124		break;
   3125	case MC_CG_ARB_FREQ_F3:
   3126		WREG32(MC_ARB_DRAM_TIMING_3, mc_arb_dram_timing);
   3127		WREG32(MC_ARB_DRAM_TIMING2_3, mc_arb_dram_timing2);
   3128		WREG32_P(MC_ARB_BURST_TIME, STATE3(burst_time), ~STATE3_MASK);
   3129		break;
   3130	default:
   3131		return -EINVAL;
   3132	}
   3133
   3134	mc_cg_config = RREG32(MC_CG_CONFIG) | 0x0000000F;
   3135	WREG32(MC_CG_CONFIG, mc_cg_config);
   3136	WREG32_P(MC_ARB_CG, CG_ARB_REQ(arb_freq_dest), ~CG_ARB_REQ_MASK);
   3137
   3138	return 0;
   3139}
   3140
   3141static void ni_update_current_ps(struct amdgpu_device *adev,
   3142			  struct amdgpu_ps *rps)
   3143{
   3144	struct si_ps *new_ps = si_get_ps(rps);
   3145	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   3146	struct ni_power_info *ni_pi = ni_get_pi(adev);
   3147
   3148	eg_pi->current_rps = *rps;
   3149	ni_pi->current_ps = *new_ps;
   3150	eg_pi->current_rps.ps_priv = &ni_pi->current_ps;
   3151	adev->pm.dpm.current_ps = &eg_pi->current_rps;
   3152}
   3153
   3154static void ni_update_requested_ps(struct amdgpu_device *adev,
   3155			    struct amdgpu_ps *rps)
   3156{
   3157	struct si_ps *new_ps = si_get_ps(rps);
   3158	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   3159	struct ni_power_info *ni_pi = ni_get_pi(adev);
   3160
   3161	eg_pi->requested_rps = *rps;
   3162	ni_pi->requested_ps = *new_ps;
   3163	eg_pi->requested_rps.ps_priv = &ni_pi->requested_ps;
   3164	adev->pm.dpm.requested_ps = &eg_pi->requested_rps;
   3165}
   3166
   3167static void ni_set_uvd_clock_before_set_eng_clock(struct amdgpu_device *adev,
   3168					   struct amdgpu_ps *new_ps,
   3169					   struct amdgpu_ps *old_ps)
   3170{
   3171	struct si_ps *new_state = si_get_ps(new_ps);
   3172	struct si_ps *current_state = si_get_ps(old_ps);
   3173
   3174	if ((new_ps->vclk == old_ps->vclk) &&
   3175	    (new_ps->dclk == old_ps->dclk))
   3176		return;
   3177
   3178	if (new_state->performance_levels[new_state->performance_level_count - 1].sclk >=
   3179	    current_state->performance_levels[current_state->performance_level_count - 1].sclk)
   3180		return;
   3181
   3182	amdgpu_asic_set_uvd_clocks(adev, new_ps->vclk, new_ps->dclk);
   3183}
   3184
   3185static void ni_set_uvd_clock_after_set_eng_clock(struct amdgpu_device *adev,
   3186					  struct amdgpu_ps *new_ps,
   3187					  struct amdgpu_ps *old_ps)
   3188{
   3189	struct si_ps *new_state = si_get_ps(new_ps);
   3190	struct si_ps *current_state = si_get_ps(old_ps);
   3191
   3192	if ((new_ps->vclk == old_ps->vclk) &&
   3193	    (new_ps->dclk == old_ps->dclk))
   3194		return;
   3195
   3196	if (new_state->performance_levels[new_state->performance_level_count - 1].sclk <
   3197	    current_state->performance_levels[current_state->performance_level_count - 1].sclk)
   3198		return;
   3199
   3200	amdgpu_asic_set_uvd_clocks(adev, new_ps->vclk, new_ps->dclk);
   3201}
   3202
   3203static u16 btc_find_voltage(struct atom_voltage_table *table, u16 voltage)
   3204{
   3205	unsigned int i;
   3206
   3207	for (i = 0; i < table->count; i++)
   3208		if (voltage <= table->entries[i].value)
   3209			return table->entries[i].value;
   3210
   3211	return table->entries[table->count - 1].value;
   3212}
   3213
   3214static u32 btc_find_valid_clock(struct amdgpu_clock_array *clocks,
   3215		                u32 max_clock, u32 requested_clock)
   3216{
   3217	unsigned int i;
   3218
   3219	if ((clocks == NULL) || (clocks->count == 0))
   3220		return (requested_clock < max_clock) ? requested_clock : max_clock;
   3221
   3222	for (i = 0; i < clocks->count; i++) {
   3223		if (clocks->values[i] >= requested_clock)
   3224			return (clocks->values[i] < max_clock) ? clocks->values[i] : max_clock;
   3225	}
   3226
   3227	return (clocks->values[clocks->count - 1] < max_clock) ?
   3228		clocks->values[clocks->count - 1] : max_clock;
   3229}
   3230
   3231static u32 btc_get_valid_mclk(struct amdgpu_device *adev,
   3232			      u32 max_mclk, u32 requested_mclk)
   3233{
   3234	return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_mclk_values,
   3235				    max_mclk, requested_mclk);
   3236}
   3237
   3238static u32 btc_get_valid_sclk(struct amdgpu_device *adev,
   3239		              u32 max_sclk, u32 requested_sclk)
   3240{
   3241	return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_sclk_values,
   3242				    max_sclk, requested_sclk);
   3243}
   3244
   3245static void btc_get_max_clock_from_voltage_dependency_table(struct amdgpu_clock_voltage_dependency_table *table,
   3246							    u32 *max_clock)
   3247{
   3248	u32 i, clock = 0;
   3249
   3250	if ((table == NULL) || (table->count == 0)) {
   3251		*max_clock = clock;
   3252		return;
   3253	}
   3254
   3255	for (i = 0; i < table->count; i++) {
   3256		if (clock < table->entries[i].clk)
   3257			clock = table->entries[i].clk;
   3258	}
   3259	*max_clock = clock;
   3260}
   3261
   3262static void btc_apply_voltage_dependency_rules(struct amdgpu_clock_voltage_dependency_table *table,
   3263					       u32 clock, u16 max_voltage, u16 *voltage)
   3264{
   3265	u32 i;
   3266
   3267	if ((table == NULL) || (table->count == 0))
   3268		return;
   3269
   3270	for (i= 0; i < table->count; i++) {
   3271		if (clock <= table->entries[i].clk) {
   3272			if (*voltage < table->entries[i].v)
   3273				*voltage = (u16)((table->entries[i].v < max_voltage) ?
   3274					   table->entries[i].v : max_voltage);
   3275			return;
   3276		}
   3277	}
   3278
   3279	*voltage = (*voltage > max_voltage) ? *voltage : max_voltage;
   3280}
   3281
   3282static void btc_adjust_clock_combinations(struct amdgpu_device *adev,
   3283					  const struct amdgpu_clock_and_voltage_limits *max_limits,
   3284					  struct rv7xx_pl *pl)
   3285{
   3286
   3287	if ((pl->mclk == 0) || (pl->sclk == 0))
   3288		return;
   3289
   3290	if (pl->mclk == pl->sclk)
   3291		return;
   3292
   3293	if (pl->mclk > pl->sclk) {
   3294		if (((pl->mclk + (pl->sclk - 1)) / pl->sclk) > adev->pm.dpm.dyn_state.mclk_sclk_ratio)
   3295			pl->sclk = btc_get_valid_sclk(adev,
   3296						      max_limits->sclk,
   3297						      (pl->mclk +
   3298						      (adev->pm.dpm.dyn_state.mclk_sclk_ratio - 1)) /
   3299						      adev->pm.dpm.dyn_state.mclk_sclk_ratio);
   3300	} else {
   3301		if ((pl->sclk - pl->mclk) > adev->pm.dpm.dyn_state.sclk_mclk_delta)
   3302			pl->mclk = btc_get_valid_mclk(adev,
   3303						      max_limits->mclk,
   3304						      pl->sclk -
   3305						      adev->pm.dpm.dyn_state.sclk_mclk_delta);
   3306	}
   3307}
   3308
   3309static void btc_apply_voltage_delta_rules(struct amdgpu_device *adev,
   3310					  u16 max_vddc, u16 max_vddci,
   3311					  u16 *vddc, u16 *vddci)
   3312{
   3313	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   3314	u16 new_voltage;
   3315
   3316	if ((0 == *vddc) || (0 == *vddci))
   3317		return;
   3318
   3319	if (*vddc > *vddci) {
   3320		if ((*vddc - *vddci) > adev->pm.dpm.dyn_state.vddc_vddci_delta) {
   3321			new_voltage = btc_find_voltage(&eg_pi->vddci_voltage_table,
   3322						       (*vddc - adev->pm.dpm.dyn_state.vddc_vddci_delta));
   3323			*vddci = (new_voltage < max_vddci) ? new_voltage : max_vddci;
   3324		}
   3325	} else {
   3326		if ((*vddci - *vddc) > adev->pm.dpm.dyn_state.vddc_vddci_delta) {
   3327			new_voltage = btc_find_voltage(&eg_pi->vddc_voltage_table,
   3328						       (*vddci - adev->pm.dpm.dyn_state.vddc_vddci_delta));
   3329			*vddc = (new_voltage < max_vddc) ? new_voltage : max_vddc;
   3330		}
   3331	}
   3332}
   3333
   3334static void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b,
   3335			    u32 *p, u32 *u)
   3336{
   3337	u32 b_c = 0;
   3338	u32 i_c;
   3339	u32 tmp;
   3340
   3341	i_c = (i * r_c) / 100;
   3342	tmp = i_c >> p_b;
   3343
   3344	while (tmp) {
   3345		b_c++;
   3346		tmp >>= 1;
   3347	}
   3348
   3349	*u = (b_c + 1) / 2;
   3350	*p = i_c / (1 << (2 * (*u)));
   3351}
   3352
   3353static int r600_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th)
   3354{
   3355	u32 k, a, ah, al;
   3356	u32 t1;
   3357
   3358	if ((fl == 0) || (fh == 0) || (fl > fh))
   3359		return -EINVAL;
   3360
   3361	k = (100 * fh) / fl;
   3362	t1 = (t * (k - 100));
   3363	a = (1000 * (100 * h + t1)) / (10000 + (t1 / 100));
   3364	a = (a + 5) / 10;
   3365	ah = ((a * t) + 5000) / 10000;
   3366	al = a - ah;
   3367
   3368	*th = t - ah;
   3369	*tl = t + al;
   3370
   3371	return 0;
   3372}
   3373
   3374static bool r600_is_uvd_state(u32 class, u32 class2)
   3375{
   3376	if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
   3377		return true;
   3378	if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
   3379		return true;
   3380	if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
   3381		return true;
   3382	if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
   3383		return true;
   3384	if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
   3385		return true;
   3386	return false;
   3387}
   3388
   3389static u8 rv770_get_memory_module_index(struct amdgpu_device *adev)
   3390{
   3391	return (u8) ((RREG32(BIOS_SCRATCH_4) >> 16) & 0xff);
   3392}
   3393
   3394static void rv770_get_max_vddc(struct amdgpu_device *adev)
   3395{
   3396	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   3397	u16 vddc;
   3398
   3399	if (amdgpu_atombios_get_max_vddc(adev, 0, 0, &vddc))
   3400		pi->max_vddc = 0;
   3401	else
   3402		pi->max_vddc = vddc;
   3403}
   3404
   3405static void rv770_get_engine_memory_ss(struct amdgpu_device *adev)
   3406{
   3407	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   3408	struct amdgpu_atom_ss ss;
   3409
   3410	pi->sclk_ss = amdgpu_atombios_get_asic_ss_info(adev, &ss,
   3411						       ASIC_INTERNAL_ENGINE_SS, 0);
   3412	pi->mclk_ss = amdgpu_atombios_get_asic_ss_info(adev, &ss,
   3413						       ASIC_INTERNAL_MEMORY_SS, 0);
   3414
   3415	if (pi->sclk_ss || pi->mclk_ss)
   3416		pi->dynamic_ss = true;
   3417	else
   3418		pi->dynamic_ss = false;
   3419}
   3420
   3421
   3422static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
   3423					struct amdgpu_ps *rps)
   3424{
   3425	struct  si_ps *ps = si_get_ps(rps);
   3426	struct amdgpu_clock_and_voltage_limits *max_limits;
   3427	bool disable_mclk_switching = false;
   3428	bool disable_sclk_switching = false;
   3429	u32 mclk, sclk;
   3430	u16 vddc, vddci, min_vce_voltage = 0;
   3431	u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
   3432	u32 max_sclk = 0, max_mclk = 0;
   3433	int i;
   3434
   3435	if (adev->asic_type == CHIP_HAINAN) {
   3436		if ((adev->pdev->revision == 0x81) ||
   3437		    (adev->pdev->revision == 0xC3) ||
   3438		    (adev->pdev->device == 0x6664) ||
   3439		    (adev->pdev->device == 0x6665) ||
   3440		    (adev->pdev->device == 0x6667)) {
   3441			max_sclk = 75000;
   3442		}
   3443		if ((adev->pdev->revision == 0xC3) ||
   3444		    (adev->pdev->device == 0x6665)) {
   3445			max_sclk = 60000;
   3446			max_mclk = 80000;
   3447		}
   3448	} else if (adev->asic_type == CHIP_OLAND) {
   3449		if ((adev->pdev->revision == 0xC7) ||
   3450		    (adev->pdev->revision == 0x80) ||
   3451		    (adev->pdev->revision == 0x81) ||
   3452		    (adev->pdev->revision == 0x83) ||
   3453		    (adev->pdev->revision == 0x87) ||
   3454		    (adev->pdev->device == 0x6604) ||
   3455		    (adev->pdev->device == 0x6605)) {
   3456			max_sclk = 75000;
   3457		}
   3458	}
   3459
   3460	if (rps->vce_active) {
   3461		rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk;
   3462		rps->ecclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].ecclk;
   3463		si_get_vce_clock_voltage(adev, rps->evclk, rps->ecclk,
   3464					 &min_vce_voltage);
   3465	} else {
   3466		rps->evclk = 0;
   3467		rps->ecclk = 0;
   3468	}
   3469
   3470	if ((adev->pm.dpm.new_active_crtc_count > 1) ||
   3471	    si_dpm_vblank_too_short(adev))
   3472		disable_mclk_switching = true;
   3473
   3474	if (rps->vclk || rps->dclk) {
   3475		disable_mclk_switching = true;
   3476		disable_sclk_switching = true;
   3477	}
   3478
   3479	if (adev->pm.ac_power)
   3480		max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
   3481	else
   3482		max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
   3483
   3484	for (i = ps->performance_level_count - 2; i >= 0; i--) {
   3485		if (ps->performance_levels[i].vddc > ps->performance_levels[i+1].vddc)
   3486			ps->performance_levels[i].vddc = ps->performance_levels[i+1].vddc;
   3487	}
   3488	if (adev->pm.ac_power == false) {
   3489		for (i = 0; i < ps->performance_level_count; i++) {
   3490			if (ps->performance_levels[i].mclk > max_limits->mclk)
   3491				ps->performance_levels[i].mclk = max_limits->mclk;
   3492			if (ps->performance_levels[i].sclk > max_limits->sclk)
   3493				ps->performance_levels[i].sclk = max_limits->sclk;
   3494			if (ps->performance_levels[i].vddc > max_limits->vddc)
   3495				ps->performance_levels[i].vddc = max_limits->vddc;
   3496			if (ps->performance_levels[i].vddci > max_limits->vddci)
   3497				ps->performance_levels[i].vddci = max_limits->vddci;
   3498		}
   3499	}
   3500
   3501	/* limit clocks to max supported clocks based on voltage dependency tables */
   3502	btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
   3503							&max_sclk_vddc);
   3504	btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
   3505							&max_mclk_vddci);
   3506	btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
   3507							&max_mclk_vddc);
   3508
   3509	for (i = 0; i < ps->performance_level_count; i++) {
   3510		if (max_sclk_vddc) {
   3511			if (ps->performance_levels[i].sclk > max_sclk_vddc)
   3512				ps->performance_levels[i].sclk = max_sclk_vddc;
   3513		}
   3514		if (max_mclk_vddci) {
   3515			if (ps->performance_levels[i].mclk > max_mclk_vddci)
   3516				ps->performance_levels[i].mclk = max_mclk_vddci;
   3517		}
   3518		if (max_mclk_vddc) {
   3519			if (ps->performance_levels[i].mclk > max_mclk_vddc)
   3520				ps->performance_levels[i].mclk = max_mclk_vddc;
   3521		}
   3522		if (max_mclk) {
   3523			if (ps->performance_levels[i].mclk > max_mclk)
   3524				ps->performance_levels[i].mclk = max_mclk;
   3525		}
   3526		if (max_sclk) {
   3527			if (ps->performance_levels[i].sclk > max_sclk)
   3528				ps->performance_levels[i].sclk = max_sclk;
   3529		}
   3530	}
   3531
   3532	/* XXX validate the min clocks required for display */
   3533
   3534	if (disable_mclk_switching) {
   3535		mclk  = ps->performance_levels[ps->performance_level_count - 1].mclk;
   3536		vddci = ps->performance_levels[ps->performance_level_count - 1].vddci;
   3537	} else {
   3538		mclk = ps->performance_levels[0].mclk;
   3539		vddci = ps->performance_levels[0].vddci;
   3540	}
   3541
   3542	if (disable_sclk_switching) {
   3543		sclk = ps->performance_levels[ps->performance_level_count - 1].sclk;
   3544		vddc = ps->performance_levels[ps->performance_level_count - 1].vddc;
   3545	} else {
   3546		sclk = ps->performance_levels[0].sclk;
   3547		vddc = ps->performance_levels[0].vddc;
   3548	}
   3549
   3550	if (rps->vce_active) {
   3551		if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk)
   3552			sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk;
   3553		if (mclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk)
   3554			mclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk;
   3555	}
   3556
   3557	/* adjusted low state */
   3558	ps->performance_levels[0].sclk = sclk;
   3559	ps->performance_levels[0].mclk = mclk;
   3560	ps->performance_levels[0].vddc = vddc;
   3561	ps->performance_levels[0].vddci = vddci;
   3562
   3563	if (disable_sclk_switching) {
   3564		sclk = ps->performance_levels[0].sclk;
   3565		for (i = 1; i < ps->performance_level_count; i++) {
   3566			if (sclk < ps->performance_levels[i].sclk)
   3567				sclk = ps->performance_levels[i].sclk;
   3568		}
   3569		for (i = 0; i < ps->performance_level_count; i++) {
   3570			ps->performance_levels[i].sclk = sclk;
   3571			ps->performance_levels[i].vddc = vddc;
   3572		}
   3573	} else {
   3574		for (i = 1; i < ps->performance_level_count; i++) {
   3575			if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk)
   3576				ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk;
   3577			if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc)
   3578				ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
   3579		}
   3580	}
   3581
   3582	if (disable_mclk_switching) {
   3583		mclk = ps->performance_levels[0].mclk;
   3584		for (i = 1; i < ps->performance_level_count; i++) {
   3585			if (mclk < ps->performance_levels[i].mclk)
   3586				mclk = ps->performance_levels[i].mclk;
   3587		}
   3588		for (i = 0; i < ps->performance_level_count; i++) {
   3589			ps->performance_levels[i].mclk = mclk;
   3590			ps->performance_levels[i].vddci = vddci;
   3591		}
   3592	} else {
   3593		for (i = 1; i < ps->performance_level_count; i++) {
   3594			if (ps->performance_levels[i].mclk < ps->performance_levels[i - 1].mclk)
   3595				ps->performance_levels[i].mclk = ps->performance_levels[i - 1].mclk;
   3596			if (ps->performance_levels[i].vddci < ps->performance_levels[i - 1].vddci)
   3597				ps->performance_levels[i].vddci = ps->performance_levels[i - 1].vddci;
   3598		}
   3599	}
   3600
   3601	for (i = 0; i < ps->performance_level_count; i++)
   3602		btc_adjust_clock_combinations(adev, max_limits,
   3603					      &ps->performance_levels[i]);
   3604
   3605	for (i = 0; i < ps->performance_level_count; i++) {
   3606		if (ps->performance_levels[i].vddc < min_vce_voltage)
   3607			ps->performance_levels[i].vddc = min_vce_voltage;
   3608		btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
   3609						   ps->performance_levels[i].sclk,
   3610						   max_limits->vddc,  &ps->performance_levels[i].vddc);
   3611		btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
   3612						   ps->performance_levels[i].mclk,
   3613						   max_limits->vddci, &ps->performance_levels[i].vddci);
   3614		btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
   3615						   ps->performance_levels[i].mclk,
   3616						   max_limits->vddc,  &ps->performance_levels[i].vddc);
   3617		btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk,
   3618						   adev->clock.current_dispclk,
   3619						   max_limits->vddc,  &ps->performance_levels[i].vddc);
   3620	}
   3621
   3622	for (i = 0; i < ps->performance_level_count; i++) {
   3623		btc_apply_voltage_delta_rules(adev,
   3624					      max_limits->vddc, max_limits->vddci,
   3625					      &ps->performance_levels[i].vddc,
   3626					      &ps->performance_levels[i].vddci);
   3627	}
   3628
   3629	ps->dc_compatible = true;
   3630	for (i = 0; i < ps->performance_level_count; i++) {
   3631		if (ps->performance_levels[i].vddc > adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc)
   3632			ps->dc_compatible = false;
   3633	}
   3634}
   3635
   3636#if 0
   3637static int si_read_smc_soft_register(struct amdgpu_device *adev,
   3638				     u16 reg_offset, u32 *value)
   3639{
   3640	struct si_power_info *si_pi = si_get_pi(adev);
   3641
   3642	return amdgpu_si_read_smc_sram_dword(adev,
   3643					     si_pi->soft_regs_start + reg_offset, value,
   3644					     si_pi->sram_end);
   3645}
   3646#endif
   3647
   3648static int si_write_smc_soft_register(struct amdgpu_device *adev,
   3649				      u16 reg_offset, u32 value)
   3650{
   3651	struct si_power_info *si_pi = si_get_pi(adev);
   3652
   3653	return amdgpu_si_write_smc_sram_dword(adev,
   3654					      si_pi->soft_regs_start + reg_offset,
   3655					      value, si_pi->sram_end);
   3656}
   3657
   3658static bool si_is_special_1gb_platform(struct amdgpu_device *adev)
   3659{
   3660	bool ret = false;
   3661	u32 tmp, width, row, column, bank, density;
   3662	bool is_memory_gddr5, is_special;
   3663
   3664	tmp = RREG32(MC_SEQ_MISC0);
   3665	is_memory_gddr5 = (MC_SEQ_MISC0_GDDR5_VALUE == ((tmp & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT));
   3666	is_special = (MC_SEQ_MISC0_REV_ID_VALUE == ((tmp & MC_SEQ_MISC0_REV_ID_MASK) >> MC_SEQ_MISC0_REV_ID_SHIFT))
   3667		& (MC_SEQ_MISC0_VEN_ID_VALUE == ((tmp & MC_SEQ_MISC0_VEN_ID_MASK) >> MC_SEQ_MISC0_VEN_ID_SHIFT));
   3668
   3669	WREG32(MC_SEQ_IO_DEBUG_INDEX, 0xb);
   3670	width = ((RREG32(MC_SEQ_IO_DEBUG_DATA) >> 1) & 1) ? 16 : 32;
   3671
   3672	tmp = RREG32(MC_ARB_RAMCFG);
   3673	row = ((tmp & NOOFROWS_MASK) >> NOOFROWS_SHIFT) + 10;
   3674	column = ((tmp & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT) + 8;
   3675	bank = ((tmp & NOOFBANK_MASK) >> NOOFBANK_SHIFT) + 2;
   3676
   3677	density = (1 << (row + column - 20 + bank)) * width;
   3678
   3679	if ((adev->pdev->device == 0x6819) &&
   3680	    is_memory_gddr5 && is_special && (density == 0x400))
   3681		ret = true;
   3682
   3683	return ret;
   3684}
   3685
   3686static void si_get_leakage_vddc(struct amdgpu_device *adev)
   3687{
   3688	struct si_power_info *si_pi = si_get_pi(adev);
   3689	u16 vddc, count = 0;
   3690	int i, ret;
   3691
   3692	for (i = 0; i < SISLANDS_MAX_LEAKAGE_COUNT; i++) {
   3693		ret = amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(adev, &vddc, SISLANDS_LEAKAGE_INDEX0 + i);
   3694
   3695		if (!ret && (vddc > 0) && (vddc != (SISLANDS_LEAKAGE_INDEX0 + i))) {
   3696			si_pi->leakage_voltage.entries[count].voltage = vddc;
   3697			si_pi->leakage_voltage.entries[count].leakage_index =
   3698				SISLANDS_LEAKAGE_INDEX0 + i;
   3699			count++;
   3700		}
   3701	}
   3702	si_pi->leakage_voltage.count = count;
   3703}
   3704
   3705static int si_get_leakage_voltage_from_leakage_index(struct amdgpu_device *adev,
   3706						     u32 index, u16 *leakage_voltage)
   3707{
   3708	struct si_power_info *si_pi = si_get_pi(adev);
   3709	int i;
   3710
   3711	if (leakage_voltage == NULL)
   3712		return -EINVAL;
   3713
   3714	if ((index & 0xff00) != 0xff00)
   3715		return -EINVAL;
   3716
   3717	if ((index & 0xff) > SISLANDS_MAX_LEAKAGE_COUNT + 1)
   3718		return -EINVAL;
   3719
   3720	if (index < SISLANDS_LEAKAGE_INDEX0)
   3721		return -EINVAL;
   3722
   3723	for (i = 0; i < si_pi->leakage_voltage.count; i++) {
   3724		if (si_pi->leakage_voltage.entries[i].leakage_index == index) {
   3725			*leakage_voltage = si_pi->leakage_voltage.entries[i].voltage;
   3726			return 0;
   3727		}
   3728	}
   3729	return -EAGAIN;
   3730}
   3731
   3732static void si_set_dpm_event_sources(struct amdgpu_device *adev, u32 sources)
   3733{
   3734	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   3735	bool want_thermal_protection;
   3736	enum si_dpm_event_src dpm_event_src;
   3737
   3738	switch (sources) {
   3739	case 0:
   3740	default:
   3741		want_thermal_protection = false;
   3742		break;
   3743	case (1 << SI_DPM_AUTO_THROTTLE_SRC_THERMAL):
   3744		want_thermal_protection = true;
   3745		dpm_event_src = SI_DPM_EVENT_SRC_DIGITAL;
   3746		break;
   3747	case (1 << SI_DPM_AUTO_THROTTLE_SRC_EXTERNAL):
   3748		want_thermal_protection = true;
   3749		dpm_event_src = SI_DPM_EVENT_SRC_EXTERNAL;
   3750		break;
   3751	case ((1 << SI_DPM_AUTO_THROTTLE_SRC_EXTERNAL) |
   3752	      (1 << SI_DPM_AUTO_THROTTLE_SRC_THERMAL)):
   3753		want_thermal_protection = true;
   3754		dpm_event_src = SI_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL;
   3755		break;
   3756	}
   3757
   3758	if (want_thermal_protection) {
   3759		WREG32_P(CG_THERMAL_CTRL, DPM_EVENT_SRC(dpm_event_src), ~DPM_EVENT_SRC_MASK);
   3760		if (pi->thermal_protection)
   3761			WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS);
   3762	} else {
   3763		WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS);
   3764	}
   3765}
   3766
   3767static void si_enable_auto_throttle_source(struct amdgpu_device *adev,
   3768					   enum si_dpm_auto_throttle_src source,
   3769					   bool enable)
   3770{
   3771	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   3772
   3773	if (enable) {
   3774		if (!(pi->active_auto_throttle_sources & (1 << source))) {
   3775			pi->active_auto_throttle_sources |= 1 << source;
   3776			si_set_dpm_event_sources(adev, pi->active_auto_throttle_sources);
   3777		}
   3778	} else {
   3779		if (pi->active_auto_throttle_sources & (1 << source)) {
   3780			pi->active_auto_throttle_sources &= ~(1 << source);
   3781			si_set_dpm_event_sources(adev, pi->active_auto_throttle_sources);
   3782		}
   3783	}
   3784}
   3785
   3786static void si_start_dpm(struct amdgpu_device *adev)
   3787{
   3788	WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
   3789}
   3790
   3791static void si_stop_dpm(struct amdgpu_device *adev)
   3792{
   3793	WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);
   3794}
   3795
   3796static void si_enable_sclk_control(struct amdgpu_device *adev, bool enable)
   3797{
   3798	if (enable)
   3799		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF);
   3800	else
   3801		WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF);
   3802
   3803}
   3804
   3805#if 0
   3806static int si_notify_hardware_of_thermal_state(struct amdgpu_device *adev,
   3807					       u32 thermal_level)
   3808{
   3809	PPSMC_Result ret;
   3810
   3811	if (thermal_level == 0) {
   3812		ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt);
   3813		if (ret == PPSMC_Result_OK)
   3814			return 0;
   3815		else
   3816			return -EINVAL;
   3817	}
   3818	return 0;
   3819}
   3820
   3821static void si_notify_hardware_vpu_recovery_event(struct amdgpu_device *adev)
   3822{
   3823	si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen, true);
   3824}
   3825#endif
   3826
   3827#if 0
   3828static int si_notify_hw_of_powersource(struct amdgpu_device *adev, bool ac_power)
   3829{
   3830	if (ac_power)
   3831		return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_RunningOnAC) == PPSMC_Result_OK) ?
   3832			0 : -EINVAL;
   3833
   3834	return 0;
   3835}
   3836#endif
   3837
   3838static PPSMC_Result si_send_msg_to_smc_with_parameter(struct amdgpu_device *adev,
   3839						      PPSMC_Msg msg, u32 parameter)
   3840{
   3841	WREG32(SMC_SCRATCH0, parameter);
   3842	return amdgpu_si_send_msg_to_smc(adev, msg);
   3843}
   3844
   3845static int si_restrict_performance_levels_before_switch(struct amdgpu_device *adev)
   3846{
   3847	if (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK)
   3848		return -EINVAL;
   3849
   3850	return (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, 1) == PPSMC_Result_OK) ?
   3851		0 : -EINVAL;
   3852}
   3853
   3854static int si_dpm_force_performance_level(void *handle,
   3855				   enum amd_dpm_forced_level level)
   3856{
   3857	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   3858	struct amdgpu_ps *rps = adev->pm.dpm.current_ps;
   3859	struct  si_ps *ps = si_get_ps(rps);
   3860	u32 levels = ps->performance_level_count;
   3861
   3862	if (level == AMD_DPM_FORCED_LEVEL_HIGH) {
   3863		if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)
   3864			return -EINVAL;
   3865
   3866		if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 1) != PPSMC_Result_OK)
   3867			return -EINVAL;
   3868	} else if (level == AMD_DPM_FORCED_LEVEL_LOW) {
   3869		if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
   3870			return -EINVAL;
   3871
   3872		if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, 1) != PPSMC_Result_OK)
   3873			return -EINVAL;
   3874	} else if (level == AMD_DPM_FORCED_LEVEL_AUTO) {
   3875		if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
   3876			return -EINVAL;
   3877
   3878		if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)
   3879			return -EINVAL;
   3880	}
   3881
   3882	adev->pm.dpm.forced_level = level;
   3883
   3884	return 0;
   3885}
   3886
   3887#if 0
   3888static int si_set_boot_state(struct amdgpu_device *adev)
   3889{
   3890	return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ?
   3891		0 : -EINVAL;
   3892}
   3893#endif
   3894
   3895static int si_set_sw_state(struct amdgpu_device *adev)
   3896{
   3897	return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToSwState) == PPSMC_Result_OK) ?
   3898		0 : -EINVAL;
   3899}
   3900
   3901static int si_halt_smc(struct amdgpu_device *adev)
   3902{
   3903	if (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_Halt) != PPSMC_Result_OK)
   3904		return -EINVAL;
   3905
   3906	return (amdgpu_si_wait_for_smc_inactive(adev) == PPSMC_Result_OK) ?
   3907		0 : -EINVAL;
   3908}
   3909
   3910static int si_resume_smc(struct amdgpu_device *adev)
   3911{
   3912	if (amdgpu_si_send_msg_to_smc(adev, PPSMC_FlushDataCache) != PPSMC_Result_OK)
   3913		return -EINVAL;
   3914
   3915	return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_Resume) == PPSMC_Result_OK) ?
   3916		0 : -EINVAL;
   3917}
   3918
   3919static void si_dpm_start_smc(struct amdgpu_device *adev)
   3920{
   3921	amdgpu_si_program_jump_on_start(adev);
   3922	amdgpu_si_start_smc(adev);
   3923	amdgpu_si_smc_clock(adev, true);
   3924}
   3925
   3926static void si_dpm_stop_smc(struct amdgpu_device *adev)
   3927{
   3928	amdgpu_si_reset_smc(adev);
   3929	amdgpu_si_smc_clock(adev, false);
   3930}
   3931
   3932static int si_process_firmware_header(struct amdgpu_device *adev)
   3933{
   3934	struct si_power_info *si_pi = si_get_pi(adev);
   3935	u32 tmp;
   3936	int ret;
   3937
   3938	ret = amdgpu_si_read_smc_sram_dword(adev,
   3939					    SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
   3940					    SISLANDS_SMC_FIRMWARE_HEADER_stateTable,
   3941					    &tmp, si_pi->sram_end);
   3942	if (ret)
   3943		return ret;
   3944
   3945	si_pi->state_table_start = tmp;
   3946
   3947	ret = amdgpu_si_read_smc_sram_dword(adev,
   3948					    SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
   3949					    SISLANDS_SMC_FIRMWARE_HEADER_softRegisters,
   3950					    &tmp, si_pi->sram_end);
   3951	if (ret)
   3952		return ret;
   3953
   3954	si_pi->soft_regs_start = tmp;
   3955
   3956	ret = amdgpu_si_read_smc_sram_dword(adev,
   3957					    SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
   3958					    SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable,
   3959					    &tmp, si_pi->sram_end);
   3960	if (ret)
   3961		return ret;
   3962
   3963	si_pi->mc_reg_table_start = tmp;
   3964
   3965	ret = amdgpu_si_read_smc_sram_dword(adev,
   3966					    SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
   3967					    SISLANDS_SMC_FIRMWARE_HEADER_fanTable,
   3968					    &tmp, si_pi->sram_end);
   3969	if (ret)
   3970		return ret;
   3971
   3972	si_pi->fan_table_start = tmp;
   3973
   3974	ret = amdgpu_si_read_smc_sram_dword(adev,
   3975					    SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
   3976					    SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable,
   3977					    &tmp, si_pi->sram_end);
   3978	if (ret)
   3979		return ret;
   3980
   3981	si_pi->arb_table_start = tmp;
   3982
   3983	ret = amdgpu_si_read_smc_sram_dword(adev,
   3984					    SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
   3985					    SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable,
   3986					    &tmp, si_pi->sram_end);
   3987	if (ret)
   3988		return ret;
   3989
   3990	si_pi->cac_table_start = tmp;
   3991
   3992	ret = amdgpu_si_read_smc_sram_dword(adev,
   3993					    SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
   3994					    SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration,
   3995					    &tmp, si_pi->sram_end);
   3996	if (ret)
   3997		return ret;
   3998
   3999	si_pi->dte_table_start = tmp;
   4000
   4001	ret = amdgpu_si_read_smc_sram_dword(adev,
   4002					    SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
   4003					    SISLANDS_SMC_FIRMWARE_HEADER_spllTable,
   4004					    &tmp, si_pi->sram_end);
   4005	if (ret)
   4006		return ret;
   4007
   4008	si_pi->spll_table_start = tmp;
   4009
   4010	ret = amdgpu_si_read_smc_sram_dword(adev,
   4011					    SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
   4012					    SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters,
   4013					    &tmp, si_pi->sram_end);
   4014	if (ret)
   4015		return ret;
   4016
   4017	si_pi->papm_cfg_table_start = tmp;
   4018
   4019	return ret;
   4020}
   4021
   4022static void si_read_clock_registers(struct amdgpu_device *adev)
   4023{
   4024	struct si_power_info *si_pi = si_get_pi(adev);
   4025
   4026	si_pi->clock_registers.cg_spll_func_cntl = RREG32(CG_SPLL_FUNC_CNTL);
   4027	si_pi->clock_registers.cg_spll_func_cntl_2 = RREG32(CG_SPLL_FUNC_CNTL_2);
   4028	si_pi->clock_registers.cg_spll_func_cntl_3 = RREG32(CG_SPLL_FUNC_CNTL_3);
   4029	si_pi->clock_registers.cg_spll_func_cntl_4 = RREG32(CG_SPLL_FUNC_CNTL_4);
   4030	si_pi->clock_registers.cg_spll_spread_spectrum = RREG32(CG_SPLL_SPREAD_SPECTRUM);
   4031	si_pi->clock_registers.cg_spll_spread_spectrum_2 = RREG32(CG_SPLL_SPREAD_SPECTRUM_2);
   4032	si_pi->clock_registers.dll_cntl = RREG32(DLL_CNTL);
   4033	si_pi->clock_registers.mclk_pwrmgt_cntl = RREG32(MCLK_PWRMGT_CNTL);
   4034	si_pi->clock_registers.mpll_ad_func_cntl = RREG32(MPLL_AD_FUNC_CNTL);
   4035	si_pi->clock_registers.mpll_dq_func_cntl = RREG32(MPLL_DQ_FUNC_CNTL);
   4036	si_pi->clock_registers.mpll_func_cntl = RREG32(MPLL_FUNC_CNTL);
   4037	si_pi->clock_registers.mpll_func_cntl_1 = RREG32(MPLL_FUNC_CNTL_1);
   4038	si_pi->clock_registers.mpll_func_cntl_2 = RREG32(MPLL_FUNC_CNTL_2);
   4039	si_pi->clock_registers.mpll_ss1 = RREG32(MPLL_SS1);
   4040	si_pi->clock_registers.mpll_ss2 = RREG32(MPLL_SS2);
   4041}
   4042
   4043static void si_enable_thermal_protection(struct amdgpu_device *adev,
   4044					  bool enable)
   4045{
   4046	if (enable)
   4047		WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS);
   4048	else
   4049		WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS);
   4050}
   4051
   4052static void si_enable_acpi_power_management(struct amdgpu_device *adev)
   4053{
   4054	WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN);
   4055}
   4056
   4057#if 0
   4058static int si_enter_ulp_state(struct amdgpu_device *adev)
   4059{
   4060	WREG32(SMC_MESSAGE_0, PPSMC_MSG_SwitchToMinimumPower);
   4061
   4062	udelay(25000);
   4063
   4064	return 0;
   4065}
   4066
   4067static int si_exit_ulp_state(struct amdgpu_device *adev)
   4068{
   4069	int i;
   4070
   4071	WREG32(SMC_MESSAGE_0, PPSMC_MSG_ResumeFromMinimumPower);
   4072
   4073	udelay(7000);
   4074
   4075	for (i = 0; i < adev->usec_timeout; i++) {
   4076		if (RREG32(SMC_RESP_0) == 1)
   4077			break;
   4078		udelay(1000);
   4079	}
   4080
   4081	return 0;
   4082}
   4083#endif
   4084
   4085static int si_notify_smc_display_change(struct amdgpu_device *adev,
   4086				     bool has_display)
   4087{
   4088	PPSMC_Msg msg = has_display ?
   4089		PPSMC_MSG_HasDisplay : PPSMC_MSG_NoDisplay;
   4090
   4091	return (amdgpu_si_send_msg_to_smc(adev, msg) == PPSMC_Result_OK) ?
   4092		0 : -EINVAL;
   4093}
   4094
   4095static void si_program_response_times(struct amdgpu_device *adev)
   4096{
   4097	u32 voltage_response_time, acpi_delay_time, vbi_time_out;
   4098	u32 vddc_dly, acpi_dly, vbi_dly;
   4099	u32 reference_clock;
   4100
   4101	si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mvdd_chg_time, 1);
   4102
   4103	voltage_response_time = (u32)adev->pm.dpm.voltage_response_time;
   4104
   4105	if (voltage_response_time == 0)
   4106		voltage_response_time = 1000;
   4107
   4108	acpi_delay_time = 15000;
   4109	vbi_time_out = 100000;
   4110
   4111	reference_clock = amdgpu_asic_get_xclk(adev);
   4112
   4113	vddc_dly = (voltage_response_time  * reference_clock) / 100;
   4114	acpi_dly = (acpi_delay_time * reference_clock) / 100;
   4115	vbi_dly  = (vbi_time_out * reference_clock) / 100;
   4116
   4117	si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_delay_vreg,  vddc_dly);
   4118	si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_delay_acpi,  acpi_dly);
   4119	si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly);
   4120	si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mc_block_delay, 0xAA);
   4121}
   4122
   4123static void si_program_ds_registers(struct amdgpu_device *adev)
   4124{
   4125	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   4126	u32 tmp;
   4127
   4128	/* DEEP_SLEEP_CLK_SEL field should be 0x10 on tahiti A0 */
   4129	if (adev->asic_type == CHIP_TAHITI && adev->rev_id == 0x0)
   4130		tmp = 0x10;
   4131	else
   4132		tmp = 0x1;
   4133
   4134	if (eg_pi->sclk_deep_sleep) {
   4135		WREG32_P(MISC_CLK_CNTL, DEEP_SLEEP_CLK_SEL(tmp), ~DEEP_SLEEP_CLK_SEL_MASK);
   4136		WREG32_P(CG_SPLL_AUTOSCALE_CNTL, AUTOSCALE_ON_SS_CLEAR,
   4137			 ~AUTOSCALE_ON_SS_CLEAR);
   4138	}
   4139}
   4140
   4141static void si_program_display_gap(struct amdgpu_device *adev)
   4142{
   4143	u32 tmp, pipe;
   4144	int i;
   4145
   4146	tmp = RREG32(CG_DISPLAY_GAP_CNTL) & ~(DISP1_GAP_MASK | DISP2_GAP_MASK);
   4147	if (adev->pm.dpm.new_active_crtc_count > 0)
   4148		tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM);
   4149	else
   4150		tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE);
   4151
   4152	if (adev->pm.dpm.new_active_crtc_count > 1)
   4153		tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM);
   4154	else
   4155		tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE);
   4156
   4157	WREG32(CG_DISPLAY_GAP_CNTL, tmp);
   4158
   4159	tmp = RREG32(DCCG_DISP_SLOW_SELECT_REG);
   4160	pipe = (tmp & DCCG_DISP1_SLOW_SELECT_MASK) >> DCCG_DISP1_SLOW_SELECT_SHIFT;
   4161
   4162	if ((adev->pm.dpm.new_active_crtc_count > 0) &&
   4163	    (!(adev->pm.dpm.new_active_crtcs & (1 << pipe)))) {
   4164		/* find the first active crtc */
   4165		for (i = 0; i < adev->mode_info.num_crtc; i++) {
   4166			if (adev->pm.dpm.new_active_crtcs & (1 << i))
   4167				break;
   4168		}
   4169		if (i == adev->mode_info.num_crtc)
   4170			pipe = 0;
   4171		else
   4172			pipe = i;
   4173
   4174		tmp &= ~DCCG_DISP1_SLOW_SELECT_MASK;
   4175		tmp |= DCCG_DISP1_SLOW_SELECT(pipe);
   4176		WREG32(DCCG_DISP_SLOW_SELECT_REG, tmp);
   4177	}
   4178
   4179	/* Setting this to false forces the performance state to low if the crtcs are disabled.
   4180	 * This can be a problem on PowerXpress systems or if you want to use the card
   4181	 * for offscreen rendering or compute if there are no crtcs enabled.
   4182	 */
   4183	si_notify_smc_display_change(adev, adev->pm.dpm.new_active_crtc_count > 0);
   4184}
   4185
   4186static void si_enable_spread_spectrum(struct amdgpu_device *adev, bool enable)
   4187{
   4188	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   4189
   4190	if (enable) {
   4191		if (pi->sclk_ss)
   4192			WREG32_P(GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, ~DYN_SPREAD_SPECTRUM_EN);
   4193	} else {
   4194		WREG32_P(CG_SPLL_SPREAD_SPECTRUM, 0, ~SSEN);
   4195		WREG32_P(GENERAL_PWRMGT, 0, ~DYN_SPREAD_SPECTRUM_EN);
   4196	}
   4197}
   4198
   4199static void si_setup_bsp(struct amdgpu_device *adev)
   4200{
   4201	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   4202	u32 xclk = amdgpu_asic_get_xclk(adev);
   4203
   4204	r600_calculate_u_and_p(pi->asi,
   4205			       xclk,
   4206			       16,
   4207			       &pi->bsp,
   4208			       &pi->bsu);
   4209
   4210	r600_calculate_u_and_p(pi->pasi,
   4211			       xclk,
   4212			       16,
   4213			       &pi->pbsp,
   4214			       &pi->pbsu);
   4215
   4216
   4217        pi->dsp = BSP(pi->bsp) | BSU(pi->bsu);
   4218	pi->psp = BSP(pi->pbsp) | BSU(pi->pbsu);
   4219
   4220	WREG32(CG_BSP, pi->dsp);
   4221}
   4222
   4223static void si_program_git(struct amdgpu_device *adev)
   4224{
   4225	WREG32_P(CG_GIT, CG_GICST(R600_GICST_DFLT), ~CG_GICST_MASK);
   4226}
   4227
   4228static void si_program_tp(struct amdgpu_device *adev)
   4229{
   4230	int i;
   4231	enum r600_td td = R600_TD_DFLT;
   4232
   4233	for (i = 0; i < R600_PM_NUMBER_OF_TC; i++)
   4234		WREG32(CG_FFCT_0 + i, (UTC_0(r600_utc[i]) | DTC_0(r600_dtc[i])));
   4235
   4236	if (td == R600_TD_AUTO)
   4237		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL);
   4238	else
   4239		WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL);
   4240
   4241	if (td == R600_TD_UP)
   4242		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE);
   4243
   4244	if (td == R600_TD_DOWN)
   4245		WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE);
   4246}
   4247
   4248static void si_program_tpp(struct amdgpu_device *adev)
   4249{
   4250	WREG32(CG_TPC, R600_TPC_DFLT);
   4251}
   4252
   4253static void si_program_sstp(struct amdgpu_device *adev)
   4254{
   4255	WREG32(CG_SSP, (SSTU(R600_SSTU_DFLT) | SST(R600_SST_DFLT)));
   4256}
   4257
   4258static void si_enable_display_gap(struct amdgpu_device *adev)
   4259{
   4260	u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL);
   4261
   4262	tmp &= ~(DISP1_GAP_MASK | DISP2_GAP_MASK);
   4263	tmp |= (DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE) |
   4264		DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE));
   4265
   4266	tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK);
   4267	tmp |= (DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK) |
   4268		DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE));
   4269	WREG32(CG_DISPLAY_GAP_CNTL, tmp);
   4270}
   4271
   4272static void si_program_vc(struct amdgpu_device *adev)
   4273{
   4274	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   4275
   4276	WREG32(CG_FTV, pi->vrc);
   4277}
   4278
   4279static void si_clear_vc(struct amdgpu_device *adev)
   4280{
   4281	WREG32(CG_FTV, 0);
   4282}
   4283
   4284static u8 si_get_ddr3_mclk_frequency_ratio(u32 memory_clock)
   4285{
   4286	u8 mc_para_index;
   4287
   4288	if (memory_clock < 10000)
   4289		mc_para_index = 0;
   4290	else if (memory_clock >= 80000)
   4291		mc_para_index = 0x0f;
   4292	else
   4293		mc_para_index = (u8)((memory_clock - 10000) / 5000 + 1);
   4294	return mc_para_index;
   4295}
   4296
   4297static u8 si_get_mclk_frequency_ratio(u32 memory_clock, bool strobe_mode)
   4298{
   4299	u8 mc_para_index;
   4300
   4301	if (strobe_mode) {
   4302		if (memory_clock < 12500)
   4303			mc_para_index = 0x00;
   4304		else if (memory_clock > 47500)
   4305			mc_para_index = 0x0f;
   4306		else
   4307			mc_para_index = (u8)((memory_clock - 10000) / 2500);
   4308	} else {
   4309		if (memory_clock < 65000)
   4310			mc_para_index = 0x00;
   4311		else if (memory_clock > 135000)
   4312			mc_para_index = 0x0f;
   4313		else
   4314			mc_para_index = (u8)((memory_clock - 60000) / 5000);
   4315	}
   4316	return mc_para_index;
   4317}
   4318
   4319static u8 si_get_strobe_mode_settings(struct amdgpu_device *adev, u32 mclk)
   4320{
   4321	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   4322	bool strobe_mode = false;
   4323	u8 result = 0;
   4324
   4325	if (mclk <= pi->mclk_strobe_mode_threshold)
   4326		strobe_mode = true;
   4327
   4328	if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5)
   4329		result = si_get_mclk_frequency_ratio(mclk, strobe_mode);
   4330	else
   4331		result = si_get_ddr3_mclk_frequency_ratio(mclk);
   4332
   4333	if (strobe_mode)
   4334		result |= SISLANDS_SMC_STROBE_ENABLE;
   4335
   4336	return result;
   4337}
   4338
   4339static int si_upload_firmware(struct amdgpu_device *adev)
   4340{
   4341	struct si_power_info *si_pi = si_get_pi(adev);
   4342
   4343	amdgpu_si_reset_smc(adev);
   4344	amdgpu_si_smc_clock(adev, false);
   4345
   4346	return amdgpu_si_load_smc_ucode(adev, si_pi->sram_end);
   4347}
   4348
   4349static bool si_validate_phase_shedding_tables(struct amdgpu_device *adev,
   4350					      const struct atom_voltage_table *table,
   4351					      const struct amdgpu_phase_shedding_limits_table *limits)
   4352{
   4353	u32 data, num_bits, num_levels;
   4354
   4355	if ((table == NULL) || (limits == NULL))
   4356		return false;
   4357
   4358	data = table->mask_low;
   4359
   4360	num_bits = hweight32(data);
   4361
   4362	if (num_bits == 0)
   4363		return false;
   4364
   4365	num_levels = (1 << num_bits);
   4366
   4367	if (table->count != num_levels)
   4368		return false;
   4369
   4370	if (limits->count != (num_levels - 1))
   4371		return false;
   4372
   4373	return true;
   4374}
   4375
   4376static void si_trim_voltage_table_to_fit_state_table(struct amdgpu_device *adev,
   4377					      u32 max_voltage_steps,
   4378					      struct atom_voltage_table *voltage_table)
   4379{
   4380	unsigned int i, diff;
   4381
   4382	if (voltage_table->count <= max_voltage_steps)
   4383		return;
   4384
   4385	diff = voltage_table->count - max_voltage_steps;
   4386
   4387	for (i= 0; i < max_voltage_steps; i++)
   4388		voltage_table->entries[i] = voltage_table->entries[i + diff];
   4389
   4390	voltage_table->count = max_voltage_steps;
   4391}
   4392
   4393static int si_get_svi2_voltage_table(struct amdgpu_device *adev,
   4394				     struct amdgpu_clock_voltage_dependency_table *voltage_dependency_table,
   4395				     struct atom_voltage_table *voltage_table)
   4396{
   4397	u32 i;
   4398
   4399	if (voltage_dependency_table == NULL)
   4400		return -EINVAL;
   4401
   4402	voltage_table->mask_low = 0;
   4403	voltage_table->phase_delay = 0;
   4404
   4405	voltage_table->count = voltage_dependency_table->count;
   4406	for (i = 0; i < voltage_table->count; i++) {
   4407		voltage_table->entries[i].value = voltage_dependency_table->entries[i].v;
   4408		voltage_table->entries[i].smio_low = 0;
   4409	}
   4410
   4411	return 0;
   4412}
   4413
   4414static int si_construct_voltage_tables(struct amdgpu_device *adev)
   4415{
   4416	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   4417	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   4418	struct si_power_info *si_pi = si_get_pi(adev);
   4419	int ret;
   4420
   4421	if (pi->voltage_control) {
   4422		ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDC,
   4423						    VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table);
   4424		if (ret)
   4425			return ret;
   4426
   4427		if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)
   4428			si_trim_voltage_table_to_fit_state_table(adev,
   4429								 SISLANDS_MAX_NO_VREG_STEPS,
   4430								 &eg_pi->vddc_voltage_table);
   4431	} else if (si_pi->voltage_control_svi2) {
   4432		ret = si_get_svi2_voltage_table(adev,
   4433						&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
   4434						&eg_pi->vddc_voltage_table);
   4435		if (ret)
   4436			return ret;
   4437	} else {
   4438		return -EINVAL;
   4439	}
   4440
   4441	if (eg_pi->vddci_control) {
   4442		ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDCI,
   4443						    VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddci_voltage_table);
   4444		if (ret)
   4445			return ret;
   4446
   4447		if (eg_pi->vddci_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)
   4448			si_trim_voltage_table_to_fit_state_table(adev,
   4449								 SISLANDS_MAX_NO_VREG_STEPS,
   4450								 &eg_pi->vddci_voltage_table);
   4451	}
   4452	if (si_pi->vddci_control_svi2) {
   4453		ret = si_get_svi2_voltage_table(adev,
   4454						&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
   4455						&eg_pi->vddci_voltage_table);
   4456		if (ret)
   4457			return ret;
   4458	}
   4459
   4460	if (pi->mvdd_control) {
   4461		ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_MVDDC,
   4462						    VOLTAGE_OBJ_GPIO_LUT, &si_pi->mvdd_voltage_table);
   4463
   4464		if (ret) {
   4465			pi->mvdd_control = false;
   4466			return ret;
   4467		}
   4468
   4469		if (si_pi->mvdd_voltage_table.count == 0) {
   4470			pi->mvdd_control = false;
   4471			return -EINVAL;
   4472		}
   4473
   4474		if (si_pi->mvdd_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)
   4475			si_trim_voltage_table_to_fit_state_table(adev,
   4476								 SISLANDS_MAX_NO_VREG_STEPS,
   4477								 &si_pi->mvdd_voltage_table);
   4478	}
   4479
   4480	if (si_pi->vddc_phase_shed_control) {
   4481		ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDC,
   4482						    VOLTAGE_OBJ_PHASE_LUT, &si_pi->vddc_phase_shed_table);
   4483		if (ret)
   4484			si_pi->vddc_phase_shed_control = false;
   4485
   4486		if ((si_pi->vddc_phase_shed_table.count == 0) ||
   4487		    (si_pi->vddc_phase_shed_table.count > SISLANDS_MAX_NO_VREG_STEPS))
   4488			si_pi->vddc_phase_shed_control = false;
   4489	}
   4490
   4491	return 0;
   4492}
   4493
   4494static void si_populate_smc_voltage_table(struct amdgpu_device *adev,
   4495					  const struct atom_voltage_table *voltage_table,
   4496					  SISLANDS_SMC_STATETABLE *table)
   4497{
   4498	unsigned int i;
   4499
   4500	for (i = 0; i < voltage_table->count; i++)
   4501		table->lowSMIO[i] |= cpu_to_be32(voltage_table->entries[i].smio_low);
   4502}
   4503
   4504static int si_populate_smc_voltage_tables(struct amdgpu_device *adev,
   4505					  SISLANDS_SMC_STATETABLE *table)
   4506{
   4507	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   4508	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   4509	struct si_power_info *si_pi = si_get_pi(adev);
   4510	u8 i;
   4511
   4512	if (si_pi->voltage_control_svi2) {
   4513		si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc,
   4514			si_pi->svc_gpio_id);
   4515		si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd,
   4516			si_pi->svd_gpio_id);
   4517		si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_plat_type,
   4518					   2);
   4519	} else {
   4520		if (eg_pi->vddc_voltage_table.count) {
   4521			si_populate_smc_voltage_table(adev, &eg_pi->vddc_voltage_table, table);
   4522			table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
   4523				cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
   4524
   4525			for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {
   4526				if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) {
   4527					table->maxVDDCIndexInPPTable = i;
   4528					break;
   4529				}
   4530			}
   4531		}
   4532
   4533		if (eg_pi->vddci_voltage_table.count) {
   4534			si_populate_smc_voltage_table(adev, &eg_pi->vddci_voltage_table, table);
   4535
   4536			table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] =
   4537				cpu_to_be32(eg_pi->vddci_voltage_table.mask_low);
   4538		}
   4539
   4540
   4541		if (si_pi->mvdd_voltage_table.count) {
   4542			si_populate_smc_voltage_table(adev, &si_pi->mvdd_voltage_table, table);
   4543
   4544			table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] =
   4545				cpu_to_be32(si_pi->mvdd_voltage_table.mask_low);
   4546		}
   4547
   4548		if (si_pi->vddc_phase_shed_control) {
   4549			if (si_validate_phase_shedding_tables(adev, &si_pi->vddc_phase_shed_table,
   4550							      &adev->pm.dpm.dyn_state.phase_shedding_limits_table)) {
   4551				si_populate_smc_voltage_table(adev, &si_pi->vddc_phase_shed_table, table);
   4552
   4553				table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING] =
   4554					cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low);
   4555
   4556				si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_phase_shedding_delay,
   4557							   (u32)si_pi->vddc_phase_shed_table.phase_delay);
   4558			} else {
   4559				si_pi->vddc_phase_shed_control = false;
   4560			}
   4561		}
   4562	}
   4563
   4564	return 0;
   4565}
   4566
   4567static int si_populate_voltage_value(struct amdgpu_device *adev,
   4568				     const struct atom_voltage_table *table,
   4569				     u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage)
   4570{
   4571	unsigned int i;
   4572
   4573	for (i = 0; i < table->count; i++) {
   4574		if (value <= table->entries[i].value) {
   4575			voltage->index = (u8)i;
   4576			voltage->value = cpu_to_be16(table->entries[i].value);
   4577			break;
   4578		}
   4579	}
   4580
   4581	if (i >= table->count)
   4582		return -EINVAL;
   4583
   4584	return 0;
   4585}
   4586
   4587static int si_populate_mvdd_value(struct amdgpu_device *adev, u32 mclk,
   4588				  SISLANDS_SMC_VOLTAGE_VALUE *voltage)
   4589{
   4590	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   4591	struct si_power_info *si_pi = si_get_pi(adev);
   4592
   4593	if (pi->mvdd_control) {
   4594		if (mclk <= pi->mvdd_split_frequency)
   4595			voltage->index = 0;
   4596		else
   4597			voltage->index = (u8)(si_pi->mvdd_voltage_table.count) - 1;
   4598
   4599		voltage->value = cpu_to_be16(si_pi->mvdd_voltage_table.entries[voltage->index].value);
   4600	}
   4601	return 0;
   4602}
   4603
   4604static int si_get_std_voltage_value(struct amdgpu_device *adev,
   4605				    SISLANDS_SMC_VOLTAGE_VALUE *voltage,
   4606				    u16 *std_voltage)
   4607{
   4608	u16 v_index;
   4609	bool voltage_found = false;
   4610	*std_voltage = be16_to_cpu(voltage->value);
   4611
   4612	if (adev->pm.dpm.dyn_state.cac_leakage_table.entries) {
   4613		if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE) {
   4614			if (adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries == NULL)
   4615				return -EINVAL;
   4616
   4617			for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) {
   4618				if (be16_to_cpu(voltage->value) ==
   4619				    (u16)adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) {
   4620					voltage_found = true;
   4621					if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count)
   4622						*std_voltage =
   4623							adev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc;
   4624					else
   4625						*std_voltage =
   4626							adev->pm.dpm.dyn_state.cac_leakage_table.entries[adev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc;
   4627					break;
   4628				}
   4629			}
   4630
   4631			if (!voltage_found) {
   4632				for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) {
   4633					if (be16_to_cpu(voltage->value) <=
   4634					    (u16)adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) {
   4635						voltage_found = true;
   4636						if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count)
   4637							*std_voltage =
   4638								adev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc;
   4639						else
   4640							*std_voltage =
   4641								adev->pm.dpm.dyn_state.cac_leakage_table.entries[adev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc;
   4642						break;
   4643					}
   4644				}
   4645			}
   4646		} else {
   4647			if ((u32)voltage->index < adev->pm.dpm.dyn_state.cac_leakage_table.count)
   4648				*std_voltage = adev->pm.dpm.dyn_state.cac_leakage_table.entries[voltage->index].vddc;
   4649		}
   4650	}
   4651
   4652	return 0;
   4653}
   4654
   4655static int si_populate_std_voltage_value(struct amdgpu_device *adev,
   4656					 u16 value, u8 index,
   4657					 SISLANDS_SMC_VOLTAGE_VALUE *voltage)
   4658{
   4659	voltage->index = index;
   4660	voltage->value = cpu_to_be16(value);
   4661
   4662	return 0;
   4663}
   4664
   4665static int si_populate_phase_shedding_value(struct amdgpu_device *adev,
   4666					    const struct amdgpu_phase_shedding_limits_table *limits,
   4667					    u16 voltage, u32 sclk, u32 mclk,
   4668					    SISLANDS_SMC_VOLTAGE_VALUE *smc_voltage)
   4669{
   4670	unsigned int i;
   4671
   4672	for (i = 0; i < limits->count; i++) {
   4673		if ((voltage <= limits->entries[i].voltage) &&
   4674		    (sclk <= limits->entries[i].sclk) &&
   4675		    (mclk <= limits->entries[i].mclk))
   4676			break;
   4677	}
   4678
   4679	smc_voltage->phase_settings = (u8)i;
   4680
   4681	return 0;
   4682}
   4683
   4684static int si_init_arb_table_index(struct amdgpu_device *adev)
   4685{
   4686	struct si_power_info *si_pi = si_get_pi(adev);
   4687	u32 tmp;
   4688	int ret;
   4689
   4690	ret = amdgpu_si_read_smc_sram_dword(adev, si_pi->arb_table_start,
   4691					    &tmp, si_pi->sram_end);
   4692	if (ret)
   4693		return ret;
   4694
   4695	tmp &= 0x00FFFFFF;
   4696	tmp |= MC_CG_ARB_FREQ_F1 << 24;
   4697
   4698	return amdgpu_si_write_smc_sram_dword(adev, si_pi->arb_table_start,
   4699					      tmp, si_pi->sram_end);
   4700}
   4701
   4702static int si_initial_switch_from_arb_f0_to_f1(struct amdgpu_device *adev)
   4703{
   4704	return ni_copy_and_switch_arb_sets(adev, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
   4705}
   4706
   4707static int si_reset_to_default(struct amdgpu_device *adev)
   4708{
   4709	return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_ResetToDefaults) == PPSMC_Result_OK) ?
   4710		0 : -EINVAL;
   4711}
   4712
   4713static int si_force_switch_to_arb_f0(struct amdgpu_device *adev)
   4714{
   4715	struct si_power_info *si_pi = si_get_pi(adev);
   4716	u32 tmp;
   4717	int ret;
   4718
   4719	ret = amdgpu_si_read_smc_sram_dword(adev, si_pi->arb_table_start,
   4720					    &tmp, si_pi->sram_end);
   4721	if (ret)
   4722		return ret;
   4723
   4724	tmp = (tmp >> 24) & 0xff;
   4725
   4726	if (tmp == MC_CG_ARB_FREQ_F0)
   4727		return 0;
   4728
   4729	return ni_copy_and_switch_arb_sets(adev, tmp, MC_CG_ARB_FREQ_F0);
   4730}
   4731
   4732static u32 si_calculate_memory_refresh_rate(struct amdgpu_device *adev,
   4733					    u32 engine_clock)
   4734{
   4735	u32 dram_rows;
   4736	u32 dram_refresh_rate;
   4737	u32 mc_arb_rfsh_rate;
   4738	u32 tmp = (RREG32(MC_ARB_RAMCFG) & NOOFROWS_MASK) >> NOOFROWS_SHIFT;
   4739
   4740	if (tmp >= 4)
   4741		dram_rows = 16384;
   4742	else
   4743		dram_rows = 1 << (tmp + 10);
   4744
   4745	dram_refresh_rate = 1 << ((RREG32(MC_SEQ_MISC0) & 0x3) + 3);
   4746	mc_arb_rfsh_rate = ((engine_clock * 10) * dram_refresh_rate / dram_rows - 32) / 64;
   4747
   4748	return mc_arb_rfsh_rate;
   4749}
   4750
   4751static int si_populate_memory_timing_parameters(struct amdgpu_device *adev,
   4752						struct rv7xx_pl *pl,
   4753						SMC_SIslands_MCArbDramTimingRegisterSet *arb_regs)
   4754{
   4755	u32 dram_timing;
   4756	u32 dram_timing2;
   4757	u32 burst_time;
   4758
   4759	arb_regs->mc_arb_rfsh_rate =
   4760		(u8)si_calculate_memory_refresh_rate(adev, pl->sclk);
   4761
   4762	amdgpu_atombios_set_engine_dram_timings(adev,
   4763					    pl->sclk,
   4764		                            pl->mclk);
   4765
   4766	dram_timing  = RREG32(MC_ARB_DRAM_TIMING);
   4767	dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
   4768	burst_time = RREG32(MC_ARB_BURST_TIME) & STATE0_MASK;
   4769
   4770	arb_regs->mc_arb_dram_timing  = cpu_to_be32(dram_timing);
   4771	arb_regs->mc_arb_dram_timing2 = cpu_to_be32(dram_timing2);
   4772	arb_regs->mc_arb_burst_time = (u8)burst_time;
   4773
   4774	return 0;
   4775}
   4776
   4777static int si_do_program_memory_timing_parameters(struct amdgpu_device *adev,
   4778						  struct amdgpu_ps *amdgpu_state,
   4779						  unsigned int first_arb_set)
   4780{
   4781	struct si_power_info *si_pi = si_get_pi(adev);
   4782	struct  si_ps *state = si_get_ps(amdgpu_state);
   4783	SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 };
   4784	int i, ret = 0;
   4785
   4786	for (i = 0; i < state->performance_level_count; i++) {
   4787		ret = si_populate_memory_timing_parameters(adev, &state->performance_levels[i], &arb_regs);
   4788		if (ret)
   4789			break;
   4790		ret = amdgpu_si_copy_bytes_to_smc(adev,
   4791						  si_pi->arb_table_start +
   4792						  offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) +
   4793						  sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * (first_arb_set + i),
   4794						  (u8 *)&arb_regs,
   4795						  sizeof(SMC_SIslands_MCArbDramTimingRegisterSet),
   4796						  si_pi->sram_end);
   4797		if (ret)
   4798			break;
   4799	}
   4800
   4801	return ret;
   4802}
   4803
   4804static int si_program_memory_timing_parameters(struct amdgpu_device *adev,
   4805					       struct amdgpu_ps *amdgpu_new_state)
   4806{
   4807	return si_do_program_memory_timing_parameters(adev, amdgpu_new_state,
   4808						      SISLANDS_DRIVER_STATE_ARB_INDEX);
   4809}
   4810
   4811static int si_populate_initial_mvdd_value(struct amdgpu_device *adev,
   4812					  struct SISLANDS_SMC_VOLTAGE_VALUE *voltage)
   4813{
   4814	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   4815	struct si_power_info *si_pi = si_get_pi(adev);
   4816
   4817	if (pi->mvdd_control)
   4818		return si_populate_voltage_value(adev, &si_pi->mvdd_voltage_table,
   4819						 si_pi->mvdd_bootup_value, voltage);
   4820
   4821	return 0;
   4822}
   4823
   4824static int si_populate_smc_initial_state(struct amdgpu_device *adev,
   4825					 struct amdgpu_ps *amdgpu_initial_state,
   4826					 SISLANDS_SMC_STATETABLE *table)
   4827{
   4828	struct  si_ps *initial_state = si_get_ps(amdgpu_initial_state);
   4829	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   4830	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   4831	struct si_power_info *si_pi = si_get_pi(adev);
   4832	u32 reg;
   4833	int ret;
   4834
   4835	table->initialState.level.mclk.vDLL_CNTL =
   4836		cpu_to_be32(si_pi->clock_registers.dll_cntl);
   4837	table->initialState.level.mclk.vMCLK_PWRMGT_CNTL =
   4838		cpu_to_be32(si_pi->clock_registers.mclk_pwrmgt_cntl);
   4839	table->initialState.level.mclk.vMPLL_AD_FUNC_CNTL =
   4840		cpu_to_be32(si_pi->clock_registers.mpll_ad_func_cntl);
   4841	table->initialState.level.mclk.vMPLL_DQ_FUNC_CNTL =
   4842		cpu_to_be32(si_pi->clock_registers.mpll_dq_func_cntl);
   4843	table->initialState.level.mclk.vMPLL_FUNC_CNTL =
   4844		cpu_to_be32(si_pi->clock_registers.mpll_func_cntl);
   4845	table->initialState.level.mclk.vMPLL_FUNC_CNTL_1 =
   4846		cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_1);
   4847	table->initialState.level.mclk.vMPLL_FUNC_CNTL_2 =
   4848		cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_2);
   4849	table->initialState.level.mclk.vMPLL_SS =
   4850		cpu_to_be32(si_pi->clock_registers.mpll_ss1);
   4851	table->initialState.level.mclk.vMPLL_SS2 =
   4852		cpu_to_be32(si_pi->clock_registers.mpll_ss2);
   4853
   4854	table->initialState.level.mclk.mclk_value =
   4855		cpu_to_be32(initial_state->performance_levels[0].mclk);
   4856
   4857	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL =
   4858		cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl);
   4859	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_2 =
   4860		cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_2);
   4861	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_3 =
   4862		cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_3);
   4863	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_4 =
   4864		cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_4);
   4865	table->initialState.level.sclk.vCG_SPLL_SPREAD_SPECTRUM =
   4866		cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum);
   4867	table->initialState.level.sclk.vCG_SPLL_SPREAD_SPECTRUM_2  =
   4868		cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum_2);
   4869
   4870	table->initialState.level.sclk.sclk_value =
   4871		cpu_to_be32(initial_state->performance_levels[0].sclk);
   4872
   4873	table->initialState.level.arbRefreshState =
   4874		SISLANDS_INITIAL_STATE_ARB_INDEX;
   4875
   4876	table->initialState.level.ACIndex = 0;
   4877
   4878	ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table,
   4879					initial_state->performance_levels[0].vddc,
   4880					&table->initialState.level.vddc);
   4881
   4882	if (!ret) {
   4883		u16 std_vddc;
   4884
   4885		ret = si_get_std_voltage_value(adev,
   4886					       &table->initialState.level.vddc,
   4887					       &std_vddc);
   4888		if (!ret)
   4889			si_populate_std_voltage_value(adev, std_vddc,
   4890						      table->initialState.level.vddc.index,
   4891						      &table->initialState.level.std_vddc);
   4892	}
   4893
   4894	if (eg_pi->vddci_control)
   4895		si_populate_voltage_value(adev,
   4896					  &eg_pi->vddci_voltage_table,
   4897					  initial_state->performance_levels[0].vddci,
   4898					  &table->initialState.level.vddci);
   4899
   4900	if (si_pi->vddc_phase_shed_control)
   4901		si_populate_phase_shedding_value(adev,
   4902						 &adev->pm.dpm.dyn_state.phase_shedding_limits_table,
   4903						 initial_state->performance_levels[0].vddc,
   4904						 initial_state->performance_levels[0].sclk,
   4905						 initial_state->performance_levels[0].mclk,
   4906						 &table->initialState.level.vddc);
   4907
   4908	si_populate_initial_mvdd_value(adev, &table->initialState.level.mvdd);
   4909
   4910	reg = CG_R(0xffff) | CG_L(0);
   4911	table->initialState.level.aT = cpu_to_be32(reg);
   4912	table->initialState.level.bSP = cpu_to_be32(pi->dsp);
   4913	table->initialState.level.gen2PCIE = (u8)si_pi->boot_pcie_gen;
   4914
   4915	if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) {
   4916		table->initialState.level.strobeMode =
   4917			si_get_strobe_mode_settings(adev,
   4918						    initial_state->performance_levels[0].mclk);
   4919
   4920		if (initial_state->performance_levels[0].mclk > pi->mclk_edc_enable_threshold)
   4921			table->initialState.level.mcFlags = SISLANDS_SMC_MC_EDC_RD_FLAG | SISLANDS_SMC_MC_EDC_WR_FLAG;
   4922		else
   4923			table->initialState.level.mcFlags =  0;
   4924	}
   4925
   4926	table->initialState.levelCount = 1;
   4927
   4928	table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC;
   4929
   4930	table->initialState.level.dpm2.MaxPS = 0;
   4931	table->initialState.level.dpm2.NearTDPDec = 0;
   4932	table->initialState.level.dpm2.AboveSafeInc = 0;
   4933	table->initialState.level.dpm2.BelowSafeInc = 0;
   4934	table->initialState.level.dpm2.PwrEfficiencyRatio = 0;
   4935
   4936	reg = MIN_POWER_MASK | MAX_POWER_MASK;
   4937	table->initialState.level.SQPowerThrottle = cpu_to_be32(reg);
   4938
   4939	reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
   4940	table->initialState.level.SQPowerThrottle_2 = cpu_to_be32(reg);
   4941
   4942	return 0;
   4943}
   4944
   4945static enum si_pcie_gen si_gen_pcie_gen_support(struct amdgpu_device *adev,
   4946						u32 sys_mask,
   4947						enum si_pcie_gen asic_gen,
   4948						enum si_pcie_gen default_gen)
   4949{
   4950	switch (asic_gen) {
   4951	case SI_PCIE_GEN1:
   4952		return SI_PCIE_GEN1;
   4953	case SI_PCIE_GEN2:
   4954		return SI_PCIE_GEN2;
   4955	case SI_PCIE_GEN3:
   4956		return SI_PCIE_GEN3;
   4957	default:
   4958		if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) &&
   4959		    (default_gen == SI_PCIE_GEN3))
   4960			return SI_PCIE_GEN3;
   4961		else if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) &&
   4962			 (default_gen == SI_PCIE_GEN2))
   4963			return SI_PCIE_GEN2;
   4964		else
   4965			return SI_PCIE_GEN1;
   4966	}
   4967	return SI_PCIE_GEN1;
   4968}
   4969
   4970static int si_populate_smc_acpi_state(struct amdgpu_device *adev,
   4971				      SISLANDS_SMC_STATETABLE *table)
   4972{
   4973	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   4974	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   4975	struct si_power_info *si_pi = si_get_pi(adev);
   4976	u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl;
   4977	u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2;
   4978	u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3;
   4979	u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4;
   4980	u32 dll_cntl = si_pi->clock_registers.dll_cntl;
   4981	u32 mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl;
   4982	u32 mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl;
   4983	u32 mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl;
   4984	u32 mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl;
   4985	u32 mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1;
   4986	u32 mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2;
   4987	u32 reg;
   4988	int ret;
   4989
   4990	table->ACPIState = table->initialState;
   4991
   4992	table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
   4993
   4994	if (pi->acpi_vddc) {
   4995		ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table,
   4996						pi->acpi_vddc, &table->ACPIState.level.vddc);
   4997		if (!ret) {
   4998			u16 std_vddc;
   4999
   5000			ret = si_get_std_voltage_value(adev,
   5001						       &table->ACPIState.level.vddc, &std_vddc);
   5002			if (!ret)
   5003				si_populate_std_voltage_value(adev, std_vddc,
   5004							      table->ACPIState.level.vddc.index,
   5005							      &table->ACPIState.level.std_vddc);
   5006		}
   5007		table->ACPIState.level.gen2PCIE = si_pi->acpi_pcie_gen;
   5008
   5009		if (si_pi->vddc_phase_shed_control) {
   5010			si_populate_phase_shedding_value(adev,
   5011							 &adev->pm.dpm.dyn_state.phase_shedding_limits_table,
   5012							 pi->acpi_vddc,
   5013							 0,
   5014							 0,
   5015							 &table->ACPIState.level.vddc);
   5016		}
   5017	} else {
   5018		ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table,
   5019						pi->min_vddc_in_table, &table->ACPIState.level.vddc);
   5020		if (!ret) {
   5021			u16 std_vddc;
   5022
   5023			ret = si_get_std_voltage_value(adev,
   5024						       &table->ACPIState.level.vddc, &std_vddc);
   5025
   5026			if (!ret)
   5027				si_populate_std_voltage_value(adev, std_vddc,
   5028							      table->ACPIState.level.vddc.index,
   5029							      &table->ACPIState.level.std_vddc);
   5030		}
   5031		table->ACPIState.level.gen2PCIE =
   5032			(u8)si_gen_pcie_gen_support(adev,
   5033						    si_pi->sys_pcie_mask,
   5034						    si_pi->boot_pcie_gen,
   5035						    SI_PCIE_GEN1);
   5036
   5037		if (si_pi->vddc_phase_shed_control)
   5038			si_populate_phase_shedding_value(adev,
   5039							 &adev->pm.dpm.dyn_state.phase_shedding_limits_table,
   5040							 pi->min_vddc_in_table,
   5041							 0,
   5042							 0,
   5043							 &table->ACPIState.level.vddc);
   5044	}
   5045
   5046	if (pi->acpi_vddc) {
   5047		if (eg_pi->acpi_vddci)
   5048			si_populate_voltage_value(adev, &eg_pi->vddci_voltage_table,
   5049						  eg_pi->acpi_vddci,
   5050						  &table->ACPIState.level.vddci);
   5051	}
   5052
   5053	mclk_pwrmgt_cntl |= MRDCK0_RESET | MRDCK1_RESET;
   5054	mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB);
   5055
   5056	dll_cntl &= ~(MRDCK0_BYPASS | MRDCK1_BYPASS);
   5057
   5058	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
   5059	spll_func_cntl_2 |= SCLK_MUX_SEL(4);
   5060
   5061	table->ACPIState.level.mclk.vDLL_CNTL =
   5062		cpu_to_be32(dll_cntl);
   5063	table->ACPIState.level.mclk.vMCLK_PWRMGT_CNTL =
   5064		cpu_to_be32(mclk_pwrmgt_cntl);
   5065	table->ACPIState.level.mclk.vMPLL_AD_FUNC_CNTL =
   5066		cpu_to_be32(mpll_ad_func_cntl);
   5067	table->ACPIState.level.mclk.vMPLL_DQ_FUNC_CNTL =
   5068		cpu_to_be32(mpll_dq_func_cntl);
   5069	table->ACPIState.level.mclk.vMPLL_FUNC_CNTL =
   5070		cpu_to_be32(mpll_func_cntl);
   5071	table->ACPIState.level.mclk.vMPLL_FUNC_CNTL_1 =
   5072		cpu_to_be32(mpll_func_cntl_1);
   5073	table->ACPIState.level.mclk.vMPLL_FUNC_CNTL_2 =
   5074		cpu_to_be32(mpll_func_cntl_2);
   5075	table->ACPIState.level.mclk.vMPLL_SS =
   5076		cpu_to_be32(si_pi->clock_registers.mpll_ss1);
   5077	table->ACPIState.level.mclk.vMPLL_SS2 =
   5078		cpu_to_be32(si_pi->clock_registers.mpll_ss2);
   5079
   5080	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL =
   5081		cpu_to_be32(spll_func_cntl);
   5082	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_2 =
   5083		cpu_to_be32(spll_func_cntl_2);
   5084	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_3 =
   5085		cpu_to_be32(spll_func_cntl_3);
   5086	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_4 =
   5087		cpu_to_be32(spll_func_cntl_4);
   5088
   5089	table->ACPIState.level.mclk.mclk_value = 0;
   5090	table->ACPIState.level.sclk.sclk_value = 0;
   5091
   5092	si_populate_mvdd_value(adev, 0, &table->ACPIState.level.mvdd);
   5093
   5094	if (eg_pi->dynamic_ac_timing)
   5095		table->ACPIState.level.ACIndex = 0;
   5096
   5097	table->ACPIState.level.dpm2.MaxPS = 0;
   5098	table->ACPIState.level.dpm2.NearTDPDec = 0;
   5099	table->ACPIState.level.dpm2.AboveSafeInc = 0;
   5100	table->ACPIState.level.dpm2.BelowSafeInc = 0;
   5101	table->ACPIState.level.dpm2.PwrEfficiencyRatio = 0;
   5102
   5103	reg = MIN_POWER_MASK | MAX_POWER_MASK;
   5104	table->ACPIState.level.SQPowerThrottle = cpu_to_be32(reg);
   5105
   5106	reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
   5107	table->ACPIState.level.SQPowerThrottle_2 = cpu_to_be32(reg);
   5108
   5109	return 0;
   5110}
   5111
   5112static int si_populate_ulv_state(struct amdgpu_device *adev,
   5113				 struct SISLANDS_SMC_SWSTATE_SINGLE *state)
   5114{
   5115	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   5116	struct si_power_info *si_pi = si_get_pi(adev);
   5117	struct si_ulv_param *ulv = &si_pi->ulv;
   5118	u32 sclk_in_sr = 1350; /* ??? */
   5119	int ret;
   5120
   5121	ret = si_convert_power_level_to_smc(adev, &ulv->pl,
   5122					    &state->level);
   5123	if (!ret) {
   5124		if (eg_pi->sclk_deep_sleep) {
   5125			if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ)
   5126				state->level.stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS;
   5127			else
   5128				state->level.stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE;
   5129		}
   5130		if (ulv->one_pcie_lane_in_ulv)
   5131			state->flags |= PPSMC_SWSTATE_FLAG_PCIE_X1;
   5132		state->level.arbRefreshState = (u8)(SISLANDS_ULV_STATE_ARB_INDEX);
   5133		state->level.ACIndex = 1;
   5134		state->level.std_vddc = state->level.vddc;
   5135		state->levelCount = 1;
   5136
   5137		state->flags |= PPSMC_SWSTATE_FLAG_DC;
   5138	}
   5139
   5140	return ret;
   5141}
   5142
   5143static int si_program_ulv_memory_timing_parameters(struct amdgpu_device *adev)
   5144{
   5145	struct si_power_info *si_pi = si_get_pi(adev);
   5146	struct si_ulv_param *ulv = &si_pi->ulv;
   5147	SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 };
   5148	int ret;
   5149
   5150	ret = si_populate_memory_timing_parameters(adev, &ulv->pl,
   5151						   &arb_regs);
   5152	if (ret)
   5153		return ret;
   5154
   5155	si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_ulv_volt_change_delay,
   5156				   ulv->volt_change_delay);
   5157
   5158	ret = amdgpu_si_copy_bytes_to_smc(adev,
   5159					  si_pi->arb_table_start +
   5160					  offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) +
   5161					  sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * SISLANDS_ULV_STATE_ARB_INDEX,
   5162					  (u8 *)&arb_regs,
   5163					  sizeof(SMC_SIslands_MCArbDramTimingRegisterSet),
   5164					  si_pi->sram_end);
   5165
   5166	return ret;
   5167}
   5168
   5169static void si_get_mvdd_configuration(struct amdgpu_device *adev)
   5170{
   5171	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   5172
   5173	pi->mvdd_split_frequency = 30000;
   5174}
   5175
   5176static int si_init_smc_table(struct amdgpu_device *adev)
   5177{
   5178	struct si_power_info *si_pi = si_get_pi(adev);
   5179	struct amdgpu_ps *amdgpu_boot_state = adev->pm.dpm.boot_ps;
   5180	const struct si_ulv_param *ulv = &si_pi->ulv;
   5181	SISLANDS_SMC_STATETABLE  *table = &si_pi->smc_statetable;
   5182	int ret;
   5183	u32 lane_width;
   5184	u32 vr_hot_gpio;
   5185
   5186	si_populate_smc_voltage_tables(adev, table);
   5187
   5188	switch (adev->pm.int_thermal_type) {
   5189	case THERMAL_TYPE_SI:
   5190	case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
   5191		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL;
   5192		break;
   5193	case THERMAL_TYPE_NONE:
   5194		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE;
   5195		break;
   5196	default:
   5197		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL;
   5198		break;
   5199	}
   5200
   5201	if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC)
   5202		table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
   5203
   5204	if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT) {
   5205		if ((adev->pdev->device != 0x6818) && (adev->pdev->device != 0x6819))
   5206			table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT;
   5207	}
   5208
   5209	if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
   5210		table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
   5211
   5212	if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5)
   5213		table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
   5214
   5215	if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY)
   5216		table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH;
   5217
   5218	if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE) {
   5219		table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT_PROG_GPIO;
   5220		vr_hot_gpio = adev->pm.dpm.backbias_response_time;
   5221		si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_vr_hot_gpio,
   5222					   vr_hot_gpio);
   5223	}
   5224
   5225	ret = si_populate_smc_initial_state(adev, amdgpu_boot_state, table);
   5226	if (ret)
   5227		return ret;
   5228
   5229	ret = si_populate_smc_acpi_state(adev, table);
   5230	if (ret)
   5231		return ret;
   5232
   5233	table->driverState.flags = table->initialState.flags;
   5234	table->driverState.levelCount = table->initialState.levelCount;
   5235	table->driverState.levels[0] = table->initialState.level;
   5236
   5237	ret = si_do_program_memory_timing_parameters(adev, amdgpu_boot_state,
   5238						     SISLANDS_INITIAL_STATE_ARB_INDEX);
   5239	if (ret)
   5240		return ret;
   5241
   5242	if (ulv->supported && ulv->pl.vddc) {
   5243		ret = si_populate_ulv_state(adev, &table->ULVState);
   5244		if (ret)
   5245			return ret;
   5246
   5247		ret = si_program_ulv_memory_timing_parameters(adev);
   5248		if (ret)
   5249			return ret;
   5250
   5251		WREG32(CG_ULV_CONTROL, ulv->cg_ulv_control);
   5252		WREG32(CG_ULV_PARAMETER, ulv->cg_ulv_parameter);
   5253
   5254		lane_width = amdgpu_get_pcie_lanes(adev);
   5255		si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width);
   5256	} else {
   5257		table->ULVState = table->initialState;
   5258	}
   5259
   5260	return amdgpu_si_copy_bytes_to_smc(adev, si_pi->state_table_start,
   5261					   (u8 *)table, sizeof(SISLANDS_SMC_STATETABLE),
   5262					   si_pi->sram_end);
   5263}
   5264
   5265static int si_calculate_sclk_params(struct amdgpu_device *adev,
   5266				    u32 engine_clock,
   5267				    SISLANDS_SMC_SCLK_VALUE *sclk)
   5268{
   5269	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   5270	struct si_power_info *si_pi = si_get_pi(adev);
   5271	struct atom_clock_dividers dividers;
   5272	u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl;
   5273	u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2;
   5274	u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3;
   5275	u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4;
   5276	u32 cg_spll_spread_spectrum = si_pi->clock_registers.cg_spll_spread_spectrum;
   5277	u32 cg_spll_spread_spectrum_2 = si_pi->clock_registers.cg_spll_spread_spectrum_2;
   5278	u64 tmp;
   5279	u32 reference_clock = adev->clock.spll.reference_freq;
   5280	u32 reference_divider;
   5281	u32 fbdiv;
   5282	int ret;
   5283
   5284	ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM,
   5285					     engine_clock, false, &dividers);
   5286	if (ret)
   5287		return ret;
   5288
   5289	reference_divider = 1 + dividers.ref_div;
   5290
   5291	tmp = (u64) engine_clock * reference_divider * dividers.post_div * 16384;
   5292	do_div(tmp, reference_clock);
   5293	fbdiv = (u32) tmp;
   5294
   5295	spll_func_cntl &= ~(SPLL_PDIV_A_MASK | SPLL_REF_DIV_MASK);
   5296	spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
   5297	spll_func_cntl |= SPLL_PDIV_A(dividers.post_div);
   5298
   5299	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
   5300	spll_func_cntl_2 |= SCLK_MUX_SEL(2);
   5301
   5302	spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
   5303	spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
   5304	spll_func_cntl_3 |= SPLL_DITHEN;
   5305
   5306	if (pi->sclk_ss) {
   5307		struct amdgpu_atom_ss ss;
   5308		u32 vco_freq = engine_clock * dividers.post_div;
   5309
   5310		if (amdgpu_atombios_get_asic_ss_info(adev, &ss,
   5311						     ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
   5312			u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
   5313			u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000);
   5314
   5315			cg_spll_spread_spectrum &= ~CLK_S_MASK;
   5316			cg_spll_spread_spectrum |= CLK_S(clk_s);
   5317			cg_spll_spread_spectrum |= SSEN;
   5318
   5319			cg_spll_spread_spectrum_2 &= ~CLK_V_MASK;
   5320			cg_spll_spread_spectrum_2 |= CLK_V(clk_v);
   5321		}
   5322	}
   5323
   5324	sclk->sclk_value = engine_clock;
   5325	sclk->vCG_SPLL_FUNC_CNTL = spll_func_cntl;
   5326	sclk->vCG_SPLL_FUNC_CNTL_2 = spll_func_cntl_2;
   5327	sclk->vCG_SPLL_FUNC_CNTL_3 = spll_func_cntl_3;
   5328	sclk->vCG_SPLL_FUNC_CNTL_4 = spll_func_cntl_4;
   5329	sclk->vCG_SPLL_SPREAD_SPECTRUM = cg_spll_spread_spectrum;
   5330	sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cg_spll_spread_spectrum_2;
   5331
   5332	return 0;
   5333}
   5334
   5335static int si_populate_sclk_value(struct amdgpu_device *adev,
   5336				  u32 engine_clock,
   5337				  SISLANDS_SMC_SCLK_VALUE *sclk)
   5338{
   5339	SISLANDS_SMC_SCLK_VALUE sclk_tmp;
   5340	int ret;
   5341
   5342	ret = si_calculate_sclk_params(adev, engine_clock, &sclk_tmp);
   5343	if (!ret) {
   5344		sclk->sclk_value = cpu_to_be32(sclk_tmp.sclk_value);
   5345		sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL);
   5346		sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_2);
   5347		sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_3);
   5348		sclk->vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_4);
   5349		sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM);
   5350		sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM_2);
   5351	}
   5352
   5353	return ret;
   5354}
   5355
   5356static int si_populate_mclk_value(struct amdgpu_device *adev,
   5357				  u32 engine_clock,
   5358				  u32 memory_clock,
   5359				  SISLANDS_SMC_MCLK_VALUE *mclk,
   5360				  bool strobe_mode,
   5361				  bool dll_state_on)
   5362{
   5363	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   5364	struct si_power_info *si_pi = si_get_pi(adev);
   5365	u32  dll_cntl = si_pi->clock_registers.dll_cntl;
   5366	u32  mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl;
   5367	u32  mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl;
   5368	u32  mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl;
   5369	u32  mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl;
   5370	u32  mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1;
   5371	u32  mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2;
   5372	u32  mpll_ss1 = si_pi->clock_registers.mpll_ss1;
   5373	u32  mpll_ss2 = si_pi->clock_registers.mpll_ss2;
   5374	struct atom_mpll_param mpll_param;
   5375	int ret;
   5376
   5377	ret = amdgpu_atombios_get_memory_pll_dividers(adev, memory_clock, strobe_mode, &mpll_param);
   5378	if (ret)
   5379		return ret;
   5380
   5381	mpll_func_cntl &= ~BWCTRL_MASK;
   5382	mpll_func_cntl |= BWCTRL(mpll_param.bwcntl);
   5383
   5384	mpll_func_cntl_1 &= ~(CLKF_MASK | CLKFRAC_MASK | VCO_MODE_MASK);
   5385	mpll_func_cntl_1 |= CLKF(mpll_param.clkf) |
   5386		CLKFRAC(mpll_param.clkfrac) | VCO_MODE(mpll_param.vco_mode);
   5387
   5388	mpll_ad_func_cntl &= ~YCLK_POST_DIV_MASK;
   5389	mpll_ad_func_cntl |= YCLK_POST_DIV(mpll_param.post_div);
   5390
   5391	if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) {
   5392		mpll_dq_func_cntl &= ~(YCLK_SEL_MASK | YCLK_POST_DIV_MASK);
   5393		mpll_dq_func_cntl |= YCLK_SEL(mpll_param.yclk_sel) |
   5394			YCLK_POST_DIV(mpll_param.post_div);
   5395	}
   5396
   5397	if (pi->mclk_ss) {
   5398		struct amdgpu_atom_ss ss;
   5399		u32 freq_nom;
   5400		u32 tmp;
   5401		u32 reference_clock = adev->clock.mpll.reference_freq;
   5402
   5403		if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5)
   5404			freq_nom = memory_clock * 4;
   5405		else
   5406			freq_nom = memory_clock * 2;
   5407
   5408		tmp = freq_nom / reference_clock;
   5409		tmp = tmp * tmp;
   5410		if (amdgpu_atombios_get_asic_ss_info(adev, &ss,
   5411		                                     ASIC_INTERNAL_MEMORY_SS, freq_nom)) {
   5412			u32 clks = reference_clock * 5 / ss.rate;
   5413			u32 clkv = (u32)((((131 * ss.percentage * ss.rate) / 100) * tmp) / freq_nom);
   5414
   5415		        mpll_ss1 &= ~CLKV_MASK;
   5416		        mpll_ss1 |= CLKV(clkv);
   5417
   5418		        mpll_ss2 &= ~CLKS_MASK;
   5419		        mpll_ss2 |= CLKS(clks);
   5420		}
   5421	}
   5422
   5423	mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK;
   5424	mclk_pwrmgt_cntl |= DLL_SPEED(mpll_param.dll_speed);
   5425
   5426	if (dll_state_on)
   5427		mclk_pwrmgt_cntl |= MRDCK0_PDNB | MRDCK1_PDNB;
   5428	else
   5429		mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB);
   5430
   5431	mclk->mclk_value = cpu_to_be32(memory_clock);
   5432	mclk->vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl);
   5433	mclk->vMPLL_FUNC_CNTL_1 = cpu_to_be32(mpll_func_cntl_1);
   5434	mclk->vMPLL_FUNC_CNTL_2 = cpu_to_be32(mpll_func_cntl_2);
   5435	mclk->vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
   5436	mclk->vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
   5437	mclk->vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
   5438	mclk->vDLL_CNTL = cpu_to_be32(dll_cntl);
   5439	mclk->vMPLL_SS = cpu_to_be32(mpll_ss1);
   5440	mclk->vMPLL_SS2 = cpu_to_be32(mpll_ss2);
   5441
   5442	return 0;
   5443}
   5444
   5445static void si_populate_smc_sp(struct amdgpu_device *adev,
   5446			       struct amdgpu_ps *amdgpu_state,
   5447			       SISLANDS_SMC_SWSTATE *smc_state)
   5448{
   5449	struct  si_ps *ps = si_get_ps(amdgpu_state);
   5450	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   5451	int i;
   5452
   5453	for (i = 0; i < ps->performance_level_count - 1; i++)
   5454		smc_state->levels[i].bSP = cpu_to_be32(pi->dsp);
   5455
   5456	smc_state->levels[ps->performance_level_count - 1].bSP =
   5457		cpu_to_be32(pi->psp);
   5458}
   5459
   5460static int si_convert_power_level_to_smc(struct amdgpu_device *adev,
   5461					 struct rv7xx_pl *pl,
   5462					 SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level)
   5463{
   5464	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   5465	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   5466	struct si_power_info *si_pi = si_get_pi(adev);
   5467	int ret;
   5468	bool dll_state_on;
   5469	u16 std_vddc;
   5470	bool gmc_pg = false;
   5471
   5472	if (eg_pi->pcie_performance_request &&
   5473	    (si_pi->force_pcie_gen != SI_PCIE_GEN_INVALID))
   5474		level->gen2PCIE = (u8)si_pi->force_pcie_gen;
   5475	else
   5476		level->gen2PCIE = (u8)pl->pcie_gen;
   5477
   5478	ret = si_populate_sclk_value(adev, pl->sclk, &level->sclk);
   5479	if (ret)
   5480		return ret;
   5481
   5482	level->mcFlags =  0;
   5483
   5484	if (pi->mclk_stutter_mode_threshold &&
   5485	    (pl->mclk <= pi->mclk_stutter_mode_threshold) &&
   5486	    !eg_pi->uvd_enabled &&
   5487	    (RREG32(DPG_PIPE_STUTTER_CONTROL) & STUTTER_ENABLE) &&
   5488	    (adev->pm.dpm.new_active_crtc_count <= 2)) {
   5489		level->mcFlags |= SISLANDS_SMC_MC_STUTTER_EN;
   5490
   5491		if (gmc_pg)
   5492			level->mcFlags |= SISLANDS_SMC_MC_PG_EN;
   5493	}
   5494
   5495	if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) {
   5496		if (pl->mclk > pi->mclk_edc_enable_threshold)
   5497			level->mcFlags |= SISLANDS_SMC_MC_EDC_RD_FLAG;
   5498
   5499		if (pl->mclk > eg_pi->mclk_edc_wr_enable_threshold)
   5500			level->mcFlags |= SISLANDS_SMC_MC_EDC_WR_FLAG;
   5501
   5502		level->strobeMode = si_get_strobe_mode_settings(adev, pl->mclk);
   5503
   5504		if (level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) {
   5505			if (si_get_mclk_frequency_ratio(pl->mclk, true) >=
   5506			    ((RREG32(MC_SEQ_MISC7) >> 16) & 0xf))
   5507				dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false;
   5508			else
   5509				dll_state_on = ((RREG32(MC_SEQ_MISC6) >> 1) & 0x1) ? true : false;
   5510		} else {
   5511			dll_state_on = false;
   5512		}
   5513	} else {
   5514		level->strobeMode = si_get_strobe_mode_settings(adev,
   5515								pl->mclk);
   5516
   5517		dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false;
   5518	}
   5519
   5520	ret = si_populate_mclk_value(adev,
   5521				     pl->sclk,
   5522				     pl->mclk,
   5523				     &level->mclk,
   5524				     (level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) != 0, dll_state_on);
   5525	if (ret)
   5526		return ret;
   5527
   5528	ret = si_populate_voltage_value(adev,
   5529					&eg_pi->vddc_voltage_table,
   5530					pl->vddc, &level->vddc);
   5531	if (ret)
   5532		return ret;
   5533
   5534
   5535	ret = si_get_std_voltage_value(adev, &level->vddc, &std_vddc);
   5536	if (ret)
   5537		return ret;
   5538
   5539	ret = si_populate_std_voltage_value(adev, std_vddc,
   5540					    level->vddc.index, &level->std_vddc);
   5541	if (ret)
   5542		return ret;
   5543
   5544	if (eg_pi->vddci_control) {
   5545		ret = si_populate_voltage_value(adev, &eg_pi->vddci_voltage_table,
   5546						pl->vddci, &level->vddci);
   5547		if (ret)
   5548			return ret;
   5549	}
   5550
   5551	if (si_pi->vddc_phase_shed_control) {
   5552		ret = si_populate_phase_shedding_value(adev,
   5553						       &adev->pm.dpm.dyn_state.phase_shedding_limits_table,
   5554						       pl->vddc,
   5555						       pl->sclk,
   5556						       pl->mclk,
   5557						       &level->vddc);
   5558		if (ret)
   5559			return ret;
   5560	}
   5561
   5562	level->MaxPoweredUpCU = si_pi->max_cu;
   5563
   5564	ret = si_populate_mvdd_value(adev, pl->mclk, &level->mvdd);
   5565
   5566	return ret;
   5567}
   5568
   5569static int si_populate_smc_t(struct amdgpu_device *adev,
   5570			     struct amdgpu_ps *amdgpu_state,
   5571			     SISLANDS_SMC_SWSTATE *smc_state)
   5572{
   5573	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   5574	struct  si_ps *state = si_get_ps(amdgpu_state);
   5575	u32 a_t;
   5576	u32 t_l, t_h;
   5577	u32 high_bsp;
   5578	int i, ret;
   5579
   5580	if (state->performance_level_count >= 9)
   5581		return -EINVAL;
   5582
   5583	if (state->performance_level_count < 2) {
   5584		a_t = CG_R(0xffff) | CG_L(0);
   5585		smc_state->levels[0].aT = cpu_to_be32(a_t);
   5586		return 0;
   5587	}
   5588
   5589	smc_state->levels[0].aT = cpu_to_be32(0);
   5590
   5591	for (i = 0; i <= state->performance_level_count - 2; i++) {
   5592		ret = r600_calculate_at(
   5593			(50 / SISLANDS_MAX_HARDWARE_POWERLEVELS) * 100 * (i + 1),
   5594			100 * R600_AH_DFLT,
   5595			state->performance_levels[i + 1].sclk,
   5596			state->performance_levels[i].sclk,
   5597			&t_l,
   5598			&t_h);
   5599
   5600		if (ret) {
   5601			t_h = (i + 1) * 1000 - 50 * R600_AH_DFLT;
   5602			t_l = (i + 1) * 1000 + 50 * R600_AH_DFLT;
   5603		}
   5604
   5605		a_t = be32_to_cpu(smc_state->levels[i].aT) & ~CG_R_MASK;
   5606		a_t |= CG_R(t_l * pi->bsp / 20000);
   5607		smc_state->levels[i].aT = cpu_to_be32(a_t);
   5608
   5609		high_bsp = (i == state->performance_level_count - 2) ?
   5610			pi->pbsp : pi->bsp;
   5611		a_t = CG_R(0xffff) | CG_L(t_h * high_bsp / 20000);
   5612		smc_state->levels[i + 1].aT = cpu_to_be32(a_t);
   5613	}
   5614
   5615	return 0;
   5616}
   5617
   5618static int si_disable_ulv(struct amdgpu_device *adev)
   5619{
   5620	struct si_power_info *si_pi = si_get_pi(adev);
   5621	struct si_ulv_param *ulv = &si_pi->ulv;
   5622
   5623	if (ulv->supported)
   5624		return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableULV) == PPSMC_Result_OK) ?
   5625			0 : -EINVAL;
   5626
   5627	return 0;
   5628}
   5629
   5630static bool si_is_state_ulv_compatible(struct amdgpu_device *adev,
   5631				       struct amdgpu_ps *amdgpu_state)
   5632{
   5633	const struct si_power_info *si_pi = si_get_pi(adev);
   5634	const struct si_ulv_param *ulv = &si_pi->ulv;
   5635	const struct  si_ps *state = si_get_ps(amdgpu_state);
   5636	int i;
   5637
   5638	if (state->performance_levels[0].mclk != ulv->pl.mclk)
   5639		return false;
   5640
   5641	/* XXX validate against display requirements! */
   5642
   5643	for (i = 0; i < adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count; i++) {
   5644		if (adev->clock.current_dispclk <=
   5645		    adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].clk) {
   5646			if (ulv->pl.vddc <
   5647			    adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].v)
   5648				return false;
   5649		}
   5650	}
   5651
   5652	if ((amdgpu_state->vclk != 0) || (amdgpu_state->dclk != 0))
   5653		return false;
   5654
   5655	return true;
   5656}
   5657
   5658static int si_set_power_state_conditionally_enable_ulv(struct amdgpu_device *adev,
   5659						       struct amdgpu_ps *amdgpu_new_state)
   5660{
   5661	const struct si_power_info *si_pi = si_get_pi(adev);
   5662	const struct si_ulv_param *ulv = &si_pi->ulv;
   5663
   5664	if (ulv->supported) {
   5665		if (si_is_state_ulv_compatible(adev, amdgpu_new_state))
   5666			return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableULV) == PPSMC_Result_OK) ?
   5667				0 : -EINVAL;
   5668	}
   5669	return 0;
   5670}
   5671
   5672static int si_convert_power_state_to_smc(struct amdgpu_device *adev,
   5673					 struct amdgpu_ps *amdgpu_state,
   5674					 SISLANDS_SMC_SWSTATE *smc_state)
   5675{
   5676	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   5677	struct ni_power_info *ni_pi = ni_get_pi(adev);
   5678	struct si_power_info *si_pi = si_get_pi(adev);
   5679	struct  si_ps *state = si_get_ps(amdgpu_state);
   5680	int i, ret;
   5681	u32 threshold;
   5682	u32 sclk_in_sr = 1350; /* ??? */
   5683
   5684	if (state->performance_level_count > SISLANDS_MAX_HARDWARE_POWERLEVELS)
   5685		return -EINVAL;
   5686
   5687	threshold = state->performance_levels[state->performance_level_count-1].sclk * 100 / 100;
   5688
   5689	if (amdgpu_state->vclk && amdgpu_state->dclk) {
   5690		eg_pi->uvd_enabled = true;
   5691		if (eg_pi->smu_uvd_hs)
   5692			smc_state->flags |= PPSMC_SWSTATE_FLAG_UVD;
   5693	} else {
   5694		eg_pi->uvd_enabled = false;
   5695	}
   5696
   5697	if (state->dc_compatible)
   5698		smc_state->flags |= PPSMC_SWSTATE_FLAG_DC;
   5699
   5700	smc_state->levelCount = 0;
   5701	for (i = 0; i < state->performance_level_count; i++) {
   5702		if (eg_pi->sclk_deep_sleep) {
   5703			if ((i == 0) || si_pi->sclk_deep_sleep_above_low) {
   5704				if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ)
   5705					smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS;
   5706				else
   5707					smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE;
   5708			}
   5709		}
   5710
   5711		ret = si_convert_power_level_to_smc(adev, &state->performance_levels[i],
   5712						    &smc_state->levels[i]);
   5713		smc_state->levels[i].arbRefreshState =
   5714			(u8)(SISLANDS_DRIVER_STATE_ARB_INDEX + i);
   5715
   5716		if (ret)
   5717			return ret;
   5718
   5719		if (ni_pi->enable_power_containment)
   5720			smc_state->levels[i].displayWatermark =
   5721				(state->performance_levels[i].sclk < threshold) ?
   5722				PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;
   5723		else
   5724			smc_state->levels[i].displayWatermark = (i < 2) ?
   5725				PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;
   5726
   5727		if (eg_pi->dynamic_ac_timing)
   5728			smc_state->levels[i].ACIndex = SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i;
   5729		else
   5730			smc_state->levels[i].ACIndex = 0;
   5731
   5732		smc_state->levelCount++;
   5733	}
   5734
   5735	si_write_smc_soft_register(adev,
   5736				   SI_SMC_SOFT_REGISTER_watermark_threshold,
   5737				   threshold / 512);
   5738
   5739	si_populate_smc_sp(adev, amdgpu_state, smc_state);
   5740
   5741	ret = si_populate_power_containment_values(adev, amdgpu_state, smc_state);
   5742	if (ret)
   5743		ni_pi->enable_power_containment = false;
   5744
   5745	ret = si_populate_sq_ramping_values(adev, amdgpu_state, smc_state);
   5746	if (ret)
   5747		ni_pi->enable_sq_ramping = false;
   5748
   5749	return si_populate_smc_t(adev, amdgpu_state, smc_state);
   5750}
   5751
   5752static int si_upload_sw_state(struct amdgpu_device *adev,
   5753			      struct amdgpu_ps *amdgpu_new_state)
   5754{
   5755	struct si_power_info *si_pi = si_get_pi(adev);
   5756	struct  si_ps *new_state = si_get_ps(amdgpu_new_state);
   5757	int ret;
   5758	u32 address = si_pi->state_table_start +
   5759		offsetof(SISLANDS_SMC_STATETABLE, driverState);
   5760	SISLANDS_SMC_SWSTATE *smc_state = &si_pi->smc_statetable.driverState;
   5761	size_t state_size = struct_size(smc_state, levels,
   5762					new_state->performance_level_count);
   5763	memset(smc_state, 0, state_size);
   5764
   5765	ret = si_convert_power_state_to_smc(adev, amdgpu_new_state, smc_state);
   5766	if (ret)
   5767		return ret;
   5768
   5769	return amdgpu_si_copy_bytes_to_smc(adev, address, (u8 *)smc_state,
   5770					   state_size, si_pi->sram_end);
   5771}
   5772
   5773static int si_upload_ulv_state(struct amdgpu_device *adev)
   5774{
   5775	struct si_power_info *si_pi = si_get_pi(adev);
   5776	struct si_ulv_param *ulv = &si_pi->ulv;
   5777	int ret = 0;
   5778
   5779	if (ulv->supported && ulv->pl.vddc) {
   5780		u32 address = si_pi->state_table_start +
   5781			offsetof(SISLANDS_SMC_STATETABLE, ULVState);
   5782		struct SISLANDS_SMC_SWSTATE_SINGLE *smc_state = &si_pi->smc_statetable.ULVState;
   5783		u32 state_size = sizeof(struct SISLANDS_SMC_SWSTATE_SINGLE);
   5784
   5785		memset(smc_state, 0, state_size);
   5786
   5787		ret = si_populate_ulv_state(adev, smc_state);
   5788		if (!ret)
   5789			ret = amdgpu_si_copy_bytes_to_smc(adev, address, (u8 *)smc_state,
   5790							  state_size, si_pi->sram_end);
   5791	}
   5792
   5793	return ret;
   5794}
   5795
   5796static int si_upload_smc_data(struct amdgpu_device *adev)
   5797{
   5798	struct amdgpu_crtc *amdgpu_crtc = NULL;
   5799	int i;
   5800
   5801	if (adev->pm.dpm.new_active_crtc_count == 0)
   5802		return 0;
   5803
   5804	for (i = 0; i < adev->mode_info.num_crtc; i++) {
   5805		if (adev->pm.dpm.new_active_crtcs & (1 << i)) {
   5806			amdgpu_crtc = adev->mode_info.crtcs[i];
   5807			break;
   5808		}
   5809	}
   5810
   5811	if (amdgpu_crtc == NULL)
   5812		return 0;
   5813
   5814	if (amdgpu_crtc->line_time <= 0)
   5815		return 0;
   5816
   5817	if (si_write_smc_soft_register(adev,
   5818				       SI_SMC_SOFT_REGISTER_crtc_index,
   5819				       amdgpu_crtc->crtc_id) != PPSMC_Result_OK)
   5820		return 0;
   5821
   5822	if (si_write_smc_soft_register(adev,
   5823				       SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min,
   5824				       amdgpu_crtc->wm_high / amdgpu_crtc->line_time) != PPSMC_Result_OK)
   5825		return 0;
   5826
   5827	if (si_write_smc_soft_register(adev,
   5828				       SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max,
   5829				       amdgpu_crtc->wm_low / amdgpu_crtc->line_time) != PPSMC_Result_OK)
   5830		return 0;
   5831
   5832	return 0;
   5833}
   5834
   5835static int si_set_mc_special_registers(struct amdgpu_device *adev,
   5836				       struct si_mc_reg_table *table)
   5837{
   5838	u8 i, j, k;
   5839	u32 temp_reg;
   5840
   5841	for (i = 0, j = table->last; i < table->last; i++) {
   5842		if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
   5843			return -EINVAL;
   5844		switch (table->mc_reg_address[i].s1) {
   5845		case MC_SEQ_MISC1:
   5846			temp_reg = RREG32(MC_PMG_CMD_EMRS);
   5847			table->mc_reg_address[j].s1 = MC_PMG_CMD_EMRS;
   5848			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_EMRS_LP;
   5849			for (k = 0; k < table->num_entries; k++)
   5850				table->mc_reg_table_entry[k].mc_data[j] =
   5851					((temp_reg & 0xffff0000)) |
   5852					((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
   5853			j++;
   5854
   5855			if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
   5856				return -EINVAL;
   5857			temp_reg = RREG32(MC_PMG_CMD_MRS);
   5858			table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS;
   5859			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS_LP;
   5860			for (k = 0; k < table->num_entries; k++) {
   5861				table->mc_reg_table_entry[k].mc_data[j] =
   5862					(temp_reg & 0xffff0000) |
   5863					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
   5864				if (adev->gmc.vram_type != AMDGPU_VRAM_TYPE_GDDR5)
   5865					table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
   5866			}
   5867			j++;
   5868
   5869			if (adev->gmc.vram_type != AMDGPU_VRAM_TYPE_GDDR5) {
   5870				if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
   5871					return -EINVAL;
   5872				table->mc_reg_address[j].s1 = MC_PMG_AUTO_CMD;
   5873				table->mc_reg_address[j].s0 = MC_PMG_AUTO_CMD;
   5874				for (k = 0; k < table->num_entries; k++)
   5875					table->mc_reg_table_entry[k].mc_data[j] =
   5876						(table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;
   5877				j++;
   5878			}
   5879			break;
   5880		case MC_SEQ_RESERVE_M:
   5881			temp_reg = RREG32(MC_PMG_CMD_MRS1);
   5882			table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS1;
   5883			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS1_LP;
   5884			for(k = 0; k < table->num_entries; k++)
   5885				table->mc_reg_table_entry[k].mc_data[j] =
   5886					(temp_reg & 0xffff0000) |
   5887					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
   5888			j++;
   5889			break;
   5890		default:
   5891			break;
   5892		}
   5893	}
   5894
   5895	table->last = j;
   5896
   5897	return 0;
   5898}
   5899
   5900static bool si_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg)
   5901{
   5902	bool result = true;
   5903	switch (in_reg) {
   5904	case  MC_SEQ_RAS_TIMING:
   5905		*out_reg = MC_SEQ_RAS_TIMING_LP;
   5906		break;
   5907	case MC_SEQ_CAS_TIMING:
   5908		*out_reg = MC_SEQ_CAS_TIMING_LP;
   5909		break;
   5910	case MC_SEQ_MISC_TIMING:
   5911		*out_reg = MC_SEQ_MISC_TIMING_LP;
   5912		break;
   5913	case MC_SEQ_MISC_TIMING2:
   5914		*out_reg = MC_SEQ_MISC_TIMING2_LP;
   5915		break;
   5916	case MC_SEQ_RD_CTL_D0:
   5917		*out_reg = MC_SEQ_RD_CTL_D0_LP;
   5918		break;
   5919	case MC_SEQ_RD_CTL_D1:
   5920		*out_reg = MC_SEQ_RD_CTL_D1_LP;
   5921		break;
   5922	case MC_SEQ_WR_CTL_D0:
   5923		*out_reg = MC_SEQ_WR_CTL_D0_LP;
   5924		break;
   5925	case MC_SEQ_WR_CTL_D1:
   5926		*out_reg = MC_SEQ_WR_CTL_D1_LP;
   5927		break;
   5928	case MC_PMG_CMD_EMRS:
   5929		*out_reg = MC_SEQ_PMG_CMD_EMRS_LP;
   5930		break;
   5931	case MC_PMG_CMD_MRS:
   5932		*out_reg = MC_SEQ_PMG_CMD_MRS_LP;
   5933		break;
   5934	case MC_PMG_CMD_MRS1:
   5935		*out_reg = MC_SEQ_PMG_CMD_MRS1_LP;
   5936		break;
   5937	case MC_SEQ_PMG_TIMING:
   5938		*out_reg = MC_SEQ_PMG_TIMING_LP;
   5939		break;
   5940	case MC_PMG_CMD_MRS2:
   5941		*out_reg = MC_SEQ_PMG_CMD_MRS2_LP;
   5942		break;
   5943	case MC_SEQ_WR_CTL_2:
   5944		*out_reg = MC_SEQ_WR_CTL_2_LP;
   5945		break;
   5946	default:
   5947		result = false;
   5948		break;
   5949	}
   5950
   5951	return result;
   5952}
   5953
   5954static void si_set_valid_flag(struct si_mc_reg_table *table)
   5955{
   5956	u8 i, j;
   5957
   5958	for (i = 0; i < table->last; i++) {
   5959		for (j = 1; j < table->num_entries; j++) {
   5960			if (table->mc_reg_table_entry[j-1].mc_data[i] != table->mc_reg_table_entry[j].mc_data[i]) {
   5961				table->valid_flag |= 1 << i;
   5962				break;
   5963			}
   5964		}
   5965	}
   5966}
   5967
   5968static void si_set_s0_mc_reg_index(struct si_mc_reg_table *table)
   5969{
   5970	u32 i;
   5971	u16 address;
   5972
   5973	for (i = 0; i < table->last; i++)
   5974		table->mc_reg_address[i].s0 = si_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) ?
   5975			address : table->mc_reg_address[i].s1;
   5976
   5977}
   5978
   5979static int si_copy_vbios_mc_reg_table(struct atom_mc_reg_table *table,
   5980				      struct si_mc_reg_table *si_table)
   5981{
   5982	u8 i, j;
   5983
   5984	if (table->last > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
   5985		return -EINVAL;
   5986	if (table->num_entries > MAX_AC_TIMING_ENTRIES)
   5987		return -EINVAL;
   5988
   5989	for (i = 0; i < table->last; i++)
   5990		si_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
   5991	si_table->last = table->last;
   5992
   5993	for (i = 0; i < table->num_entries; i++) {
   5994		si_table->mc_reg_table_entry[i].mclk_max =
   5995			table->mc_reg_table_entry[i].mclk_max;
   5996		for (j = 0; j < table->last; j++) {
   5997			si_table->mc_reg_table_entry[i].mc_data[j] =
   5998				table->mc_reg_table_entry[i].mc_data[j];
   5999		}
   6000	}
   6001	si_table->num_entries = table->num_entries;
   6002
   6003	return 0;
   6004}
   6005
   6006static int si_initialize_mc_reg_table(struct amdgpu_device *adev)
   6007{
   6008	struct si_power_info *si_pi = si_get_pi(adev);
   6009	struct atom_mc_reg_table *table;
   6010	struct si_mc_reg_table *si_table = &si_pi->mc_reg_table;
   6011	u8 module_index = rv770_get_memory_module_index(adev);
   6012	int ret;
   6013
   6014	table = kzalloc(sizeof(struct atom_mc_reg_table), GFP_KERNEL);
   6015	if (!table)
   6016		return -ENOMEM;
   6017
   6018	WREG32(MC_SEQ_RAS_TIMING_LP, RREG32(MC_SEQ_RAS_TIMING));
   6019	WREG32(MC_SEQ_CAS_TIMING_LP, RREG32(MC_SEQ_CAS_TIMING));
   6020	WREG32(MC_SEQ_MISC_TIMING_LP, RREG32(MC_SEQ_MISC_TIMING));
   6021	WREG32(MC_SEQ_MISC_TIMING2_LP, RREG32(MC_SEQ_MISC_TIMING2));
   6022	WREG32(MC_SEQ_PMG_CMD_EMRS_LP, RREG32(MC_PMG_CMD_EMRS));
   6023	WREG32(MC_SEQ_PMG_CMD_MRS_LP, RREG32(MC_PMG_CMD_MRS));
   6024	WREG32(MC_SEQ_PMG_CMD_MRS1_LP, RREG32(MC_PMG_CMD_MRS1));
   6025	WREG32(MC_SEQ_WR_CTL_D0_LP, RREG32(MC_SEQ_WR_CTL_D0));
   6026	WREG32(MC_SEQ_WR_CTL_D1_LP, RREG32(MC_SEQ_WR_CTL_D1));
   6027	WREG32(MC_SEQ_RD_CTL_D0_LP, RREG32(MC_SEQ_RD_CTL_D0));
   6028	WREG32(MC_SEQ_RD_CTL_D1_LP, RREG32(MC_SEQ_RD_CTL_D1));
   6029	WREG32(MC_SEQ_PMG_TIMING_LP, RREG32(MC_SEQ_PMG_TIMING));
   6030	WREG32(MC_SEQ_PMG_CMD_MRS2_LP, RREG32(MC_PMG_CMD_MRS2));
   6031	WREG32(MC_SEQ_WR_CTL_2_LP, RREG32(MC_SEQ_WR_CTL_2));
   6032
   6033	ret = amdgpu_atombios_init_mc_reg_table(adev, module_index, table);
   6034	if (ret)
   6035		goto init_mc_done;
   6036
   6037	ret = si_copy_vbios_mc_reg_table(table, si_table);
   6038	if (ret)
   6039		goto init_mc_done;
   6040
   6041	si_set_s0_mc_reg_index(si_table);
   6042
   6043	ret = si_set_mc_special_registers(adev, si_table);
   6044	if (ret)
   6045		goto init_mc_done;
   6046
   6047	si_set_valid_flag(si_table);
   6048
   6049init_mc_done:
   6050	kfree(table);
   6051
   6052	return ret;
   6053
   6054}
   6055
   6056static void si_populate_mc_reg_addresses(struct amdgpu_device *adev,
   6057					 SMC_SIslands_MCRegisters *mc_reg_table)
   6058{
   6059	struct si_power_info *si_pi = si_get_pi(adev);
   6060	u32 i, j;
   6061
   6062	for (i = 0, j = 0; j < si_pi->mc_reg_table.last; j++) {
   6063		if (si_pi->mc_reg_table.valid_flag & (1 << j)) {
   6064			if (i >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
   6065				break;
   6066			mc_reg_table->address[i].s0 =
   6067				cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s0);
   6068			mc_reg_table->address[i].s1 =
   6069				cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s1);
   6070			i++;
   6071		}
   6072	}
   6073	mc_reg_table->last = (u8)i;
   6074}
   6075
   6076static void si_convert_mc_registers(const struct si_mc_reg_entry *entry,
   6077				    SMC_SIslands_MCRegisterSet *data,
   6078				    u32 num_entries, u32 valid_flag)
   6079{
   6080	u32 i, j;
   6081
   6082	for(i = 0, j = 0; j < num_entries; j++) {
   6083		if (valid_flag & (1 << j)) {
   6084			data->value[i] = cpu_to_be32(entry->mc_data[j]);
   6085			i++;
   6086		}
   6087	}
   6088}
   6089
   6090static void si_convert_mc_reg_table_entry_to_smc(struct amdgpu_device *adev,
   6091						 struct rv7xx_pl *pl,
   6092						 SMC_SIslands_MCRegisterSet *mc_reg_table_data)
   6093{
   6094	struct si_power_info *si_pi = si_get_pi(adev);
   6095	u32 i = 0;
   6096
   6097	for (i = 0; i < si_pi->mc_reg_table.num_entries; i++) {
   6098		if (pl->mclk <= si_pi->mc_reg_table.mc_reg_table_entry[i].mclk_max)
   6099			break;
   6100	}
   6101
   6102	if ((i == si_pi->mc_reg_table.num_entries) && (i > 0))
   6103		--i;
   6104
   6105	si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[i],
   6106				mc_reg_table_data, si_pi->mc_reg_table.last,
   6107				si_pi->mc_reg_table.valid_flag);
   6108}
   6109
   6110static void si_convert_mc_reg_table_to_smc(struct amdgpu_device *adev,
   6111					   struct amdgpu_ps *amdgpu_state,
   6112					   SMC_SIslands_MCRegisters *mc_reg_table)
   6113{
   6114	struct si_ps *state = si_get_ps(amdgpu_state);
   6115	int i;
   6116
   6117	for (i = 0; i < state->performance_level_count; i++) {
   6118		si_convert_mc_reg_table_entry_to_smc(adev,
   6119						     &state->performance_levels[i],
   6120						     &mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i]);
   6121	}
   6122}
   6123
   6124static int si_populate_mc_reg_table(struct amdgpu_device *adev,
   6125				    struct amdgpu_ps *amdgpu_boot_state)
   6126{
   6127	struct  si_ps *boot_state = si_get_ps(amdgpu_boot_state);
   6128	struct si_power_info *si_pi = si_get_pi(adev);
   6129	struct si_ulv_param *ulv = &si_pi->ulv;
   6130	SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table;
   6131
   6132	memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters));
   6133
   6134	si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_seq_index, 1);
   6135
   6136	si_populate_mc_reg_addresses(adev, smc_mc_reg_table);
   6137
   6138	si_convert_mc_reg_table_entry_to_smc(adev, &boot_state->performance_levels[0],
   6139					     &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_INITIAL_SLOT]);
   6140
   6141	si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0],
   6142				&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ACPI_SLOT],
   6143				si_pi->mc_reg_table.last,
   6144				si_pi->mc_reg_table.valid_flag);
   6145
   6146	if (ulv->supported && ulv->pl.vddc != 0)
   6147		si_convert_mc_reg_table_entry_to_smc(adev, &ulv->pl,
   6148						     &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT]);
   6149	else
   6150		si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0],
   6151					&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT],
   6152					si_pi->mc_reg_table.last,
   6153					si_pi->mc_reg_table.valid_flag);
   6154
   6155	si_convert_mc_reg_table_to_smc(adev, amdgpu_boot_state, smc_mc_reg_table);
   6156
   6157	return amdgpu_si_copy_bytes_to_smc(adev, si_pi->mc_reg_table_start,
   6158					   (u8 *)smc_mc_reg_table,
   6159					   sizeof(SMC_SIslands_MCRegisters), si_pi->sram_end);
   6160}
   6161
   6162static int si_upload_mc_reg_table(struct amdgpu_device *adev,
   6163				  struct amdgpu_ps *amdgpu_new_state)
   6164{
   6165	struct si_ps *new_state = si_get_ps(amdgpu_new_state);
   6166	struct si_power_info *si_pi = si_get_pi(adev);
   6167	u32 address = si_pi->mc_reg_table_start +
   6168		offsetof(SMC_SIslands_MCRegisters,
   6169			 data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT]);
   6170	SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table;
   6171
   6172	memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters));
   6173
   6174	si_convert_mc_reg_table_to_smc(adev, amdgpu_new_state, smc_mc_reg_table);
   6175
   6176	return amdgpu_si_copy_bytes_to_smc(adev, address,
   6177					   (u8 *)&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT],
   6178					   sizeof(SMC_SIslands_MCRegisterSet) * new_state->performance_level_count,
   6179					   si_pi->sram_end);
   6180}
   6181
   6182static void si_enable_voltage_control(struct amdgpu_device *adev, bool enable)
   6183{
   6184	if (enable)
   6185		WREG32_P(GENERAL_PWRMGT, VOLT_PWRMGT_EN, ~VOLT_PWRMGT_EN);
   6186	else
   6187		WREG32_P(GENERAL_PWRMGT, 0, ~VOLT_PWRMGT_EN);
   6188}
   6189
   6190static enum si_pcie_gen si_get_maximum_link_speed(struct amdgpu_device *adev,
   6191						  struct amdgpu_ps *amdgpu_state)
   6192{
   6193	struct si_ps *state = si_get_ps(amdgpu_state);
   6194	int i;
   6195	u16 pcie_speed, max_speed = 0;
   6196
   6197	for (i = 0; i < state->performance_level_count; i++) {
   6198		pcie_speed = state->performance_levels[i].pcie_gen;
   6199		if (max_speed < pcie_speed)
   6200			max_speed = pcie_speed;
   6201	}
   6202	return max_speed;
   6203}
   6204
   6205static u16 si_get_current_pcie_speed(struct amdgpu_device *adev)
   6206{
   6207	u32 speed_cntl;
   6208
   6209	speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL) & LC_CURRENT_DATA_RATE_MASK;
   6210	speed_cntl >>= LC_CURRENT_DATA_RATE_SHIFT;
   6211
   6212	return (u16)speed_cntl;
   6213}
   6214
   6215static void si_request_link_speed_change_before_state_change(struct amdgpu_device *adev,
   6216							     struct amdgpu_ps *amdgpu_new_state,
   6217							     struct amdgpu_ps *amdgpu_current_state)
   6218{
   6219	struct si_power_info *si_pi = si_get_pi(adev);
   6220	enum si_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state);
   6221	enum si_pcie_gen current_link_speed;
   6222
   6223	if (si_pi->force_pcie_gen == SI_PCIE_GEN_INVALID)
   6224		current_link_speed = si_get_maximum_link_speed(adev, amdgpu_current_state);
   6225	else
   6226		current_link_speed = si_pi->force_pcie_gen;
   6227
   6228	si_pi->force_pcie_gen = SI_PCIE_GEN_INVALID;
   6229	si_pi->pspp_notify_required = false;
   6230	if (target_link_speed > current_link_speed) {
   6231		switch (target_link_speed) {
   6232#if defined(CONFIG_ACPI)
   6233		case SI_PCIE_GEN3:
   6234			if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN3, false) == 0)
   6235				break;
   6236			si_pi->force_pcie_gen = SI_PCIE_GEN2;
   6237			if (current_link_speed == SI_PCIE_GEN2)
   6238				break;
   6239			fallthrough;
   6240		case SI_PCIE_GEN2:
   6241			if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN2, false) == 0)
   6242				break;
   6243			fallthrough;
   6244#endif
   6245		default:
   6246			si_pi->force_pcie_gen = si_get_current_pcie_speed(adev);
   6247			break;
   6248		}
   6249	} else {
   6250		if (target_link_speed < current_link_speed)
   6251			si_pi->pspp_notify_required = true;
   6252	}
   6253}
   6254
   6255static void si_notify_link_speed_change_after_state_change(struct amdgpu_device *adev,
   6256							   struct amdgpu_ps *amdgpu_new_state,
   6257							   struct amdgpu_ps *amdgpu_current_state)
   6258{
   6259	struct si_power_info *si_pi = si_get_pi(adev);
   6260	enum si_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state);
   6261	u8 request;
   6262
   6263	if (si_pi->pspp_notify_required) {
   6264		if (target_link_speed == SI_PCIE_GEN3)
   6265			request = PCIE_PERF_REQ_PECI_GEN3;
   6266		else if (target_link_speed == SI_PCIE_GEN2)
   6267			request = PCIE_PERF_REQ_PECI_GEN2;
   6268		else
   6269			request = PCIE_PERF_REQ_PECI_GEN1;
   6270
   6271		if ((request == PCIE_PERF_REQ_PECI_GEN1) &&
   6272		    (si_get_current_pcie_speed(adev) > 0))
   6273			return;
   6274
   6275#if defined(CONFIG_ACPI)
   6276		amdgpu_acpi_pcie_performance_request(adev, request, false);
   6277#endif
   6278	}
   6279}
   6280
   6281#if 0
   6282static int si_ds_request(struct amdgpu_device *adev,
   6283			 bool ds_status_on, u32 count_write)
   6284{
   6285	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   6286
   6287	if (eg_pi->sclk_deep_sleep) {
   6288		if (ds_status_on)
   6289			return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_CancelThrottleOVRDSCLKDS) ==
   6290				PPSMC_Result_OK) ?
   6291				0 : -EINVAL;
   6292		else
   6293			return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_ThrottleOVRDSCLKDS) ==
   6294				PPSMC_Result_OK) ? 0 : -EINVAL;
   6295	}
   6296	return 0;
   6297}
   6298#endif
   6299
   6300static void si_set_max_cu_value(struct amdgpu_device *adev)
   6301{
   6302	struct si_power_info *si_pi = si_get_pi(adev);
   6303
   6304	if (adev->asic_type == CHIP_VERDE) {
   6305		switch (adev->pdev->device) {
   6306		case 0x6820:
   6307		case 0x6825:
   6308		case 0x6821:
   6309		case 0x6823:
   6310		case 0x6827:
   6311			si_pi->max_cu = 10;
   6312			break;
   6313		case 0x682D:
   6314		case 0x6824:
   6315		case 0x682F:
   6316		case 0x6826:
   6317			si_pi->max_cu = 8;
   6318			break;
   6319		case 0x6828:
   6320		case 0x6830:
   6321		case 0x6831:
   6322		case 0x6838:
   6323		case 0x6839:
   6324		case 0x683D:
   6325			si_pi->max_cu = 10;
   6326			break;
   6327		case 0x683B:
   6328		case 0x683F:
   6329		case 0x6829:
   6330			si_pi->max_cu = 8;
   6331			break;
   6332		default:
   6333			si_pi->max_cu = 0;
   6334			break;
   6335		}
   6336	} else {
   6337		si_pi->max_cu = 0;
   6338	}
   6339}
   6340
   6341static int si_patch_single_dependency_table_based_on_leakage(struct amdgpu_device *adev,
   6342							     struct amdgpu_clock_voltage_dependency_table *table)
   6343{
   6344	u32 i;
   6345	int j;
   6346	u16 leakage_voltage;
   6347
   6348	if (table) {
   6349		for (i = 0; i < table->count; i++) {
   6350			switch (si_get_leakage_voltage_from_leakage_index(adev,
   6351									  table->entries[i].v,
   6352									  &leakage_voltage)) {
   6353			case 0:
   6354				table->entries[i].v = leakage_voltage;
   6355				break;
   6356			case -EAGAIN:
   6357				return -EINVAL;
   6358			case -EINVAL:
   6359			default:
   6360				break;
   6361			}
   6362		}
   6363
   6364		for (j = (table->count - 2); j >= 0; j--) {
   6365			table->entries[j].v = (table->entries[j].v <= table->entries[j + 1].v) ?
   6366				table->entries[j].v : table->entries[j + 1].v;
   6367		}
   6368	}
   6369	return 0;
   6370}
   6371
   6372static int si_patch_dependency_tables_based_on_leakage(struct amdgpu_device *adev)
   6373{
   6374	int ret = 0;
   6375
   6376	ret = si_patch_single_dependency_table_based_on_leakage(adev,
   6377								&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk);
   6378	if (ret)
   6379		DRM_ERROR("Could not patch vddc_on_sclk leakage table\n");
   6380	ret = si_patch_single_dependency_table_based_on_leakage(adev,
   6381								&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk);
   6382	if (ret)
   6383		DRM_ERROR("Could not patch vddc_on_mclk leakage table\n");
   6384	ret = si_patch_single_dependency_table_based_on_leakage(adev,
   6385								&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk);
   6386	if (ret)
   6387		DRM_ERROR("Could not patch vddci_on_mclk leakage table\n");
   6388	return ret;
   6389}
   6390
   6391static void si_set_pcie_lane_width_in_smc(struct amdgpu_device *adev,
   6392					  struct amdgpu_ps *amdgpu_new_state,
   6393					  struct amdgpu_ps *amdgpu_current_state)
   6394{
   6395	u32 lane_width;
   6396	u32 new_lane_width =
   6397		((amdgpu_new_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
   6398	u32 current_lane_width =
   6399		((amdgpu_current_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
   6400
   6401	if (new_lane_width != current_lane_width) {
   6402		amdgpu_set_pcie_lanes(adev, new_lane_width);
   6403		lane_width = amdgpu_get_pcie_lanes(adev);
   6404		si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width);
   6405	}
   6406}
   6407
   6408static void si_dpm_setup_asic(struct amdgpu_device *adev)
   6409{
   6410	si_read_clock_registers(adev);
   6411	si_enable_acpi_power_management(adev);
   6412}
   6413
   6414static int si_thermal_enable_alert(struct amdgpu_device *adev,
   6415				   bool enable)
   6416{
   6417	u32 thermal_int = RREG32(CG_THERMAL_INT);
   6418
   6419	if (enable) {
   6420		PPSMC_Result result;
   6421
   6422		thermal_int &= ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
   6423		WREG32(CG_THERMAL_INT, thermal_int);
   6424		result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt);
   6425		if (result != PPSMC_Result_OK) {
   6426			DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
   6427			return -EINVAL;
   6428		}
   6429	} else {
   6430		thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
   6431		WREG32(CG_THERMAL_INT, thermal_int);
   6432	}
   6433
   6434	return 0;
   6435}
   6436
   6437static int si_thermal_set_temperature_range(struct amdgpu_device *adev,
   6438					    int min_temp, int max_temp)
   6439{
   6440	int low_temp = 0 * 1000;
   6441	int high_temp = 255 * 1000;
   6442
   6443	if (low_temp < min_temp)
   6444		low_temp = min_temp;
   6445	if (high_temp > max_temp)
   6446		high_temp = max_temp;
   6447	if (high_temp < low_temp) {
   6448		DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
   6449		return -EINVAL;
   6450	}
   6451
   6452	WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(high_temp / 1000), ~DIG_THERM_INTH_MASK);
   6453	WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(low_temp / 1000), ~DIG_THERM_INTL_MASK);
   6454	WREG32_P(CG_THERMAL_CTRL, DIG_THERM_DPM(high_temp / 1000), ~DIG_THERM_DPM_MASK);
   6455
   6456	adev->pm.dpm.thermal.min_temp = low_temp;
   6457	adev->pm.dpm.thermal.max_temp = high_temp;
   6458
   6459	return 0;
   6460}
   6461
   6462static void si_fan_ctrl_set_static_mode(struct amdgpu_device *adev, u32 mode)
   6463{
   6464	struct si_power_info *si_pi = si_get_pi(adev);
   6465	u32 tmp;
   6466
   6467	if (si_pi->fan_ctrl_is_in_default_mode) {
   6468		tmp = (RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK) >> FDO_PWM_MODE_SHIFT;
   6469		si_pi->fan_ctrl_default_mode = tmp;
   6470		tmp = (RREG32(CG_FDO_CTRL2) & TMIN_MASK) >> TMIN_SHIFT;
   6471		si_pi->t_min = tmp;
   6472		si_pi->fan_ctrl_is_in_default_mode = false;
   6473	}
   6474
   6475	tmp = RREG32(CG_FDO_CTRL2) & ~TMIN_MASK;
   6476	tmp |= TMIN(0);
   6477	WREG32(CG_FDO_CTRL2, tmp);
   6478
   6479	tmp = RREG32(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK;
   6480	tmp |= FDO_PWM_MODE(mode);
   6481	WREG32(CG_FDO_CTRL2, tmp);
   6482}
   6483
   6484static int si_thermal_setup_fan_table(struct amdgpu_device *adev)
   6485{
   6486	struct si_power_info *si_pi = si_get_pi(adev);
   6487	PP_SIslands_FanTable fan_table = { FDO_MODE_HARDWARE };
   6488	u32 duty100;
   6489	u32 t_diff1, t_diff2, pwm_diff1, pwm_diff2;
   6490	u16 fdo_min, slope1, slope2;
   6491	u32 reference_clock, tmp;
   6492	int ret;
   6493	u64 tmp64;
   6494
   6495	if (!si_pi->fan_table_start) {
   6496		adev->pm.dpm.fan.ucode_fan_control = false;
   6497		return 0;
   6498	}
   6499
   6500	duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;
   6501
   6502	if (duty100 == 0) {
   6503		adev->pm.dpm.fan.ucode_fan_control = false;
   6504		return 0;
   6505	}
   6506
   6507	tmp64 = (u64)adev->pm.dpm.fan.pwm_min * duty100;
   6508	do_div(tmp64, 10000);
   6509	fdo_min = (u16)tmp64;
   6510
   6511	t_diff1 = adev->pm.dpm.fan.t_med - adev->pm.dpm.fan.t_min;
   6512	t_diff2 = adev->pm.dpm.fan.t_high - adev->pm.dpm.fan.t_med;
   6513
   6514	pwm_diff1 = adev->pm.dpm.fan.pwm_med - adev->pm.dpm.fan.pwm_min;
   6515	pwm_diff2 = adev->pm.dpm.fan.pwm_high - adev->pm.dpm.fan.pwm_med;
   6516
   6517	slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
   6518	slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
   6519
   6520	fan_table.temp_min = cpu_to_be16((50 + adev->pm.dpm.fan.t_min) / 100);
   6521	fan_table.temp_med = cpu_to_be16((50 + adev->pm.dpm.fan.t_med) / 100);
   6522	fan_table.temp_max = cpu_to_be16((50 + adev->pm.dpm.fan.t_max) / 100);
   6523	fan_table.slope1 = cpu_to_be16(slope1);
   6524	fan_table.slope2 = cpu_to_be16(slope2);
   6525	fan_table.fdo_min = cpu_to_be16(fdo_min);
   6526	fan_table.hys_down = cpu_to_be16(adev->pm.dpm.fan.t_hyst);
   6527	fan_table.hys_up = cpu_to_be16(1);
   6528	fan_table.hys_slope = cpu_to_be16(1);
   6529	fan_table.temp_resp_lim = cpu_to_be16(5);
   6530	reference_clock = amdgpu_asic_get_xclk(adev);
   6531
   6532	fan_table.refresh_period = cpu_to_be32((adev->pm.dpm.fan.cycle_delay *
   6533						reference_clock) / 1600);
   6534	fan_table.fdo_max = cpu_to_be16((u16)duty100);
   6535
   6536	tmp = (RREG32(CG_MULT_THERMAL_CTRL) & TEMP_SEL_MASK) >> TEMP_SEL_SHIFT;
   6537	fan_table.temp_src = (uint8_t)tmp;
   6538
   6539	ret = amdgpu_si_copy_bytes_to_smc(adev,
   6540					  si_pi->fan_table_start,
   6541					  (u8 *)(&fan_table),
   6542					  sizeof(fan_table),
   6543					  si_pi->sram_end);
   6544
   6545	if (ret) {
   6546		DRM_ERROR("Failed to load fan table to the SMC.");
   6547		adev->pm.dpm.fan.ucode_fan_control = false;
   6548	}
   6549
   6550	return ret;
   6551}
   6552
   6553static int si_fan_ctrl_start_smc_fan_control(struct amdgpu_device *adev)
   6554{
   6555	struct si_power_info *si_pi = si_get_pi(adev);
   6556	PPSMC_Result ret;
   6557
   6558	ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_StartFanControl);
   6559	if (ret == PPSMC_Result_OK) {
   6560		si_pi->fan_is_controlled_by_smc = true;
   6561		return 0;
   6562	} else {
   6563		return -EINVAL;
   6564	}
   6565}
   6566
   6567static int si_fan_ctrl_stop_smc_fan_control(struct amdgpu_device *adev)
   6568{
   6569	struct si_power_info *si_pi = si_get_pi(adev);
   6570	PPSMC_Result ret;
   6571
   6572	ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_StopFanControl);
   6573
   6574	if (ret == PPSMC_Result_OK) {
   6575		si_pi->fan_is_controlled_by_smc = false;
   6576		return 0;
   6577	} else {
   6578		return -EINVAL;
   6579	}
   6580}
   6581
   6582static int si_dpm_get_fan_speed_pwm(void *handle,
   6583				      u32 *speed)
   6584{
   6585	u32 duty, duty100;
   6586	u64 tmp64;
   6587	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   6588
   6589	if (!speed)
   6590		return -EINVAL;
   6591
   6592	if (adev->pm.no_fan)
   6593		return -ENOENT;
   6594
   6595	duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;
   6596	duty = (RREG32(CG_THERMAL_STATUS) & FDO_PWM_DUTY_MASK) >> FDO_PWM_DUTY_SHIFT;
   6597
   6598	if (duty100 == 0)
   6599		return -EINVAL;
   6600
   6601	tmp64 = (u64)duty * 255;
   6602	do_div(tmp64, duty100);
   6603	*speed = MIN((u32)tmp64, 255);
   6604
   6605	return 0;
   6606}
   6607
   6608static int si_dpm_set_fan_speed_pwm(void *handle,
   6609				      u32 speed)
   6610{
   6611	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   6612	struct si_power_info *si_pi = si_get_pi(adev);
   6613	u32 tmp;
   6614	u32 duty, duty100;
   6615	u64 tmp64;
   6616
   6617	if (adev->pm.no_fan)
   6618		return -ENOENT;
   6619
   6620	if (si_pi->fan_is_controlled_by_smc)
   6621		return -EINVAL;
   6622
   6623	if (speed > 255)
   6624		return -EINVAL;
   6625
   6626	duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;
   6627
   6628	if (duty100 == 0)
   6629		return -EINVAL;
   6630
   6631	tmp64 = (u64)speed * duty100;
   6632	do_div(tmp64, 255);
   6633	duty = (u32)tmp64;
   6634
   6635	tmp = RREG32(CG_FDO_CTRL0) & ~FDO_STATIC_DUTY_MASK;
   6636	tmp |= FDO_STATIC_DUTY(duty);
   6637	WREG32(CG_FDO_CTRL0, tmp);
   6638
   6639	return 0;
   6640}
   6641
   6642static int si_dpm_set_fan_control_mode(void *handle, u32 mode)
   6643{
   6644	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   6645
   6646	if (mode == U32_MAX)
   6647		return -EINVAL;
   6648
   6649	if (mode) {
   6650		/* stop auto-manage */
   6651		if (adev->pm.dpm.fan.ucode_fan_control)
   6652			si_fan_ctrl_stop_smc_fan_control(adev);
   6653		si_fan_ctrl_set_static_mode(adev, mode);
   6654	} else {
   6655		/* restart auto-manage */
   6656		if (adev->pm.dpm.fan.ucode_fan_control)
   6657			si_thermal_start_smc_fan_control(adev);
   6658		else
   6659			si_fan_ctrl_set_default_mode(adev);
   6660	}
   6661
   6662	return 0;
   6663}
   6664
   6665static int si_dpm_get_fan_control_mode(void *handle, u32 *fan_mode)
   6666{
   6667	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   6668	struct si_power_info *si_pi = si_get_pi(adev);
   6669	u32 tmp;
   6670
   6671	if (!fan_mode)
   6672		return -EINVAL;
   6673
   6674	if (si_pi->fan_is_controlled_by_smc)
   6675		return 0;
   6676
   6677	tmp = RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK;
   6678	*fan_mode = (tmp >> FDO_PWM_MODE_SHIFT);
   6679
   6680	return 0;
   6681}
   6682
   6683#if 0
   6684static int si_fan_ctrl_get_fan_speed_rpm(struct amdgpu_device *adev,
   6685					 u32 *speed)
   6686{
   6687	u32 tach_period;
   6688	u32 xclk = amdgpu_asic_get_xclk(adev);
   6689
   6690	if (adev->pm.no_fan)
   6691		return -ENOENT;
   6692
   6693	if (adev->pm.fan_pulses_per_revolution == 0)
   6694		return -ENOENT;
   6695
   6696	tach_period = (RREG32(CG_TACH_STATUS) & TACH_PERIOD_MASK) >> TACH_PERIOD_SHIFT;
   6697	if (tach_period == 0)
   6698		return -ENOENT;
   6699
   6700	*speed = 60 * xclk * 10000 / tach_period;
   6701
   6702	return 0;
   6703}
   6704
   6705static int si_fan_ctrl_set_fan_speed_rpm(struct amdgpu_device *adev,
   6706					 u32 speed)
   6707{
   6708	u32 tach_period, tmp;
   6709	u32 xclk = amdgpu_asic_get_xclk(adev);
   6710
   6711	if (adev->pm.no_fan)
   6712		return -ENOENT;
   6713
   6714	if (adev->pm.fan_pulses_per_revolution == 0)
   6715		return -ENOENT;
   6716
   6717	if ((speed < adev->pm.fan_min_rpm) ||
   6718	    (speed > adev->pm.fan_max_rpm))
   6719		return -EINVAL;
   6720
   6721	if (adev->pm.dpm.fan.ucode_fan_control)
   6722		si_fan_ctrl_stop_smc_fan_control(adev);
   6723
   6724	tach_period = 60 * xclk * 10000 / (8 * speed);
   6725	tmp = RREG32(CG_TACH_CTRL) & ~TARGET_PERIOD_MASK;
   6726	tmp |= TARGET_PERIOD(tach_period);
   6727	WREG32(CG_TACH_CTRL, tmp);
   6728
   6729	si_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC_RPM);
   6730
   6731	return 0;
   6732}
   6733#endif
   6734
   6735static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev)
   6736{
   6737	struct si_power_info *si_pi = si_get_pi(adev);
   6738	u32 tmp;
   6739
   6740	if (!si_pi->fan_ctrl_is_in_default_mode) {
   6741		tmp = RREG32(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK;
   6742		tmp |= FDO_PWM_MODE(si_pi->fan_ctrl_default_mode);
   6743		WREG32(CG_FDO_CTRL2, tmp);
   6744
   6745		tmp = RREG32(CG_FDO_CTRL2) & ~TMIN_MASK;
   6746		tmp |= TMIN(si_pi->t_min);
   6747		WREG32(CG_FDO_CTRL2, tmp);
   6748		si_pi->fan_ctrl_is_in_default_mode = true;
   6749	}
   6750}
   6751
   6752static void si_thermal_start_smc_fan_control(struct amdgpu_device *adev)
   6753{
   6754	if (adev->pm.dpm.fan.ucode_fan_control) {
   6755		si_fan_ctrl_start_smc_fan_control(adev);
   6756		si_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC);
   6757	}
   6758}
   6759
   6760static void si_thermal_initialize(struct amdgpu_device *adev)
   6761{
   6762	u32 tmp;
   6763
   6764	if (adev->pm.fan_pulses_per_revolution) {
   6765		tmp = RREG32(CG_TACH_CTRL) & ~EDGE_PER_REV_MASK;
   6766		tmp |= EDGE_PER_REV(adev->pm.fan_pulses_per_revolution -1);
   6767		WREG32(CG_TACH_CTRL, tmp);
   6768	}
   6769
   6770	tmp = RREG32(CG_FDO_CTRL2) & ~TACH_PWM_RESP_RATE_MASK;
   6771	tmp |= TACH_PWM_RESP_RATE(0x28);
   6772	WREG32(CG_FDO_CTRL2, tmp);
   6773}
   6774
   6775static int si_thermal_start_thermal_controller(struct amdgpu_device *adev)
   6776{
   6777	int ret;
   6778
   6779	si_thermal_initialize(adev);
   6780	ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
   6781	if (ret)
   6782		return ret;
   6783	ret = si_thermal_enable_alert(adev, true);
   6784	if (ret)
   6785		return ret;
   6786	if (adev->pm.dpm.fan.ucode_fan_control) {
   6787		ret = si_halt_smc(adev);
   6788		if (ret)
   6789			return ret;
   6790		ret = si_thermal_setup_fan_table(adev);
   6791		if (ret)
   6792			return ret;
   6793		ret = si_resume_smc(adev);
   6794		if (ret)
   6795			return ret;
   6796		si_thermal_start_smc_fan_control(adev);
   6797	}
   6798
   6799	return 0;
   6800}
   6801
   6802static void si_thermal_stop_thermal_controller(struct amdgpu_device *adev)
   6803{
   6804	if (!adev->pm.no_fan) {
   6805		si_fan_ctrl_set_default_mode(adev);
   6806		si_fan_ctrl_stop_smc_fan_control(adev);
   6807	}
   6808}
   6809
   6810static int si_dpm_enable(struct amdgpu_device *adev)
   6811{
   6812	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   6813	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   6814	struct si_power_info *si_pi = si_get_pi(adev);
   6815	struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps;
   6816	int ret;
   6817
   6818	if (amdgpu_si_is_smc_running(adev))
   6819		return -EINVAL;
   6820	if (pi->voltage_control || si_pi->voltage_control_svi2)
   6821		si_enable_voltage_control(adev, true);
   6822	if (pi->mvdd_control)
   6823		si_get_mvdd_configuration(adev);
   6824	if (pi->voltage_control || si_pi->voltage_control_svi2) {
   6825		ret = si_construct_voltage_tables(adev);
   6826		if (ret) {
   6827			DRM_ERROR("si_construct_voltage_tables failed\n");
   6828			return ret;
   6829		}
   6830	}
   6831	if (eg_pi->dynamic_ac_timing) {
   6832		ret = si_initialize_mc_reg_table(adev);
   6833		if (ret)
   6834			eg_pi->dynamic_ac_timing = false;
   6835	}
   6836	if (pi->dynamic_ss)
   6837		si_enable_spread_spectrum(adev, true);
   6838	if (pi->thermal_protection)
   6839		si_enable_thermal_protection(adev, true);
   6840	si_setup_bsp(adev);
   6841	si_program_git(adev);
   6842	si_program_tp(adev);
   6843	si_program_tpp(adev);
   6844	si_program_sstp(adev);
   6845	si_enable_display_gap(adev);
   6846	si_program_vc(adev);
   6847	ret = si_upload_firmware(adev);
   6848	if (ret) {
   6849		DRM_ERROR("si_upload_firmware failed\n");
   6850		return ret;
   6851	}
   6852	ret = si_process_firmware_header(adev);
   6853	if (ret) {
   6854		DRM_ERROR("si_process_firmware_header failed\n");
   6855		return ret;
   6856	}
   6857	ret = si_initial_switch_from_arb_f0_to_f1(adev);
   6858	if (ret) {
   6859		DRM_ERROR("si_initial_switch_from_arb_f0_to_f1 failed\n");
   6860		return ret;
   6861	}
   6862	ret = si_init_smc_table(adev);
   6863	if (ret) {
   6864		DRM_ERROR("si_init_smc_table failed\n");
   6865		return ret;
   6866	}
   6867	ret = si_init_smc_spll_table(adev);
   6868	if (ret) {
   6869		DRM_ERROR("si_init_smc_spll_table failed\n");
   6870		return ret;
   6871	}
   6872	ret = si_init_arb_table_index(adev);
   6873	if (ret) {
   6874		DRM_ERROR("si_init_arb_table_index failed\n");
   6875		return ret;
   6876	}
   6877	if (eg_pi->dynamic_ac_timing) {
   6878		ret = si_populate_mc_reg_table(adev, boot_ps);
   6879		if (ret) {
   6880			DRM_ERROR("si_populate_mc_reg_table failed\n");
   6881			return ret;
   6882		}
   6883	}
   6884	ret = si_initialize_smc_cac_tables(adev);
   6885	if (ret) {
   6886		DRM_ERROR("si_initialize_smc_cac_tables failed\n");
   6887		return ret;
   6888	}
   6889	ret = si_initialize_hardware_cac_manager(adev);
   6890	if (ret) {
   6891		DRM_ERROR("si_initialize_hardware_cac_manager failed\n");
   6892		return ret;
   6893	}
   6894	ret = si_initialize_smc_dte_tables(adev);
   6895	if (ret) {
   6896		DRM_ERROR("si_initialize_smc_dte_tables failed\n");
   6897		return ret;
   6898	}
   6899	ret = si_populate_smc_tdp_limits(adev, boot_ps);
   6900	if (ret) {
   6901		DRM_ERROR("si_populate_smc_tdp_limits failed\n");
   6902		return ret;
   6903	}
   6904	ret = si_populate_smc_tdp_limits_2(adev, boot_ps);
   6905	if (ret) {
   6906		DRM_ERROR("si_populate_smc_tdp_limits_2 failed\n");
   6907		return ret;
   6908	}
   6909	si_program_response_times(adev);
   6910	si_program_ds_registers(adev);
   6911	si_dpm_start_smc(adev);
   6912	ret = si_notify_smc_display_change(adev, false);
   6913	if (ret) {
   6914		DRM_ERROR("si_notify_smc_display_change failed\n");
   6915		return ret;
   6916	}
   6917	si_enable_sclk_control(adev, true);
   6918	si_start_dpm(adev);
   6919
   6920	si_enable_auto_throttle_source(adev, SI_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
   6921	si_thermal_start_thermal_controller(adev);
   6922
   6923	ni_update_current_ps(adev, boot_ps);
   6924
   6925	return 0;
   6926}
   6927
   6928static int si_set_temperature_range(struct amdgpu_device *adev)
   6929{
   6930	int ret;
   6931
   6932	ret = si_thermal_enable_alert(adev, false);
   6933	if (ret)
   6934		return ret;
   6935	ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
   6936	if (ret)
   6937		return ret;
   6938	ret = si_thermal_enable_alert(adev, true);
   6939	if (ret)
   6940		return ret;
   6941
   6942	return ret;
   6943}
   6944
   6945static void si_dpm_disable(struct amdgpu_device *adev)
   6946{
   6947	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   6948	struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps;
   6949
   6950	if (!amdgpu_si_is_smc_running(adev))
   6951		return;
   6952	si_thermal_stop_thermal_controller(adev);
   6953	si_disable_ulv(adev);
   6954	si_clear_vc(adev);
   6955	if (pi->thermal_protection)
   6956		si_enable_thermal_protection(adev, false);
   6957	si_enable_power_containment(adev, boot_ps, false);
   6958	si_enable_smc_cac(adev, boot_ps, false);
   6959	si_enable_spread_spectrum(adev, false);
   6960	si_enable_auto_throttle_source(adev, SI_DPM_AUTO_THROTTLE_SRC_THERMAL, false);
   6961	si_stop_dpm(adev);
   6962	si_reset_to_default(adev);
   6963	si_dpm_stop_smc(adev);
   6964	si_force_switch_to_arb_f0(adev);
   6965
   6966	ni_update_current_ps(adev, boot_ps);
   6967}
   6968
   6969static int si_dpm_pre_set_power_state(void *handle)
   6970{
   6971	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   6972	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   6973	struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps;
   6974	struct amdgpu_ps *new_ps = &requested_ps;
   6975
   6976	ni_update_requested_ps(adev, new_ps);
   6977	si_apply_state_adjust_rules(adev, &eg_pi->requested_rps);
   6978
   6979	return 0;
   6980}
   6981
   6982static int si_power_control_set_level(struct amdgpu_device *adev)
   6983{
   6984	struct amdgpu_ps *new_ps = adev->pm.dpm.requested_ps;
   6985	int ret;
   6986
   6987	ret = si_restrict_performance_levels_before_switch(adev);
   6988	if (ret)
   6989		return ret;
   6990	ret = si_halt_smc(adev);
   6991	if (ret)
   6992		return ret;
   6993	ret = si_populate_smc_tdp_limits(adev, new_ps);
   6994	if (ret)
   6995		return ret;
   6996	ret = si_populate_smc_tdp_limits_2(adev, new_ps);
   6997	if (ret)
   6998		return ret;
   6999	ret = si_resume_smc(adev);
   7000	if (ret)
   7001		return ret;
   7002	return si_set_sw_state(adev);
   7003}
   7004
   7005static void si_set_vce_clock(struct amdgpu_device *adev,
   7006			     struct amdgpu_ps *new_rps,
   7007			     struct amdgpu_ps *old_rps)
   7008{
   7009	if ((old_rps->evclk != new_rps->evclk) ||
   7010	    (old_rps->ecclk != new_rps->ecclk)) {
   7011		/* Turn the clocks on when encoding, off otherwise */
   7012		if (new_rps->evclk || new_rps->ecclk) {
   7013			/* Place holder for future VCE1.0 porting to amdgpu
   7014			vce_v1_0_enable_mgcg(adev, false, false);*/
   7015		} else {
   7016			/* Place holder for future VCE1.0 porting to amdgpu
   7017			vce_v1_0_enable_mgcg(adev, true, false);
   7018			amdgpu_asic_set_vce_clocks(adev, new_rps->evclk, new_rps->ecclk);*/
   7019		}
   7020	}
   7021}
   7022
   7023static int si_dpm_set_power_state(void *handle)
   7024{
   7025	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7026	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   7027	struct amdgpu_ps *new_ps = &eg_pi->requested_rps;
   7028	struct amdgpu_ps *old_ps = &eg_pi->current_rps;
   7029	int ret;
   7030
   7031	ret = si_disable_ulv(adev);
   7032	if (ret) {
   7033		DRM_ERROR("si_disable_ulv failed\n");
   7034		return ret;
   7035	}
   7036	ret = si_restrict_performance_levels_before_switch(adev);
   7037	if (ret) {
   7038		DRM_ERROR("si_restrict_performance_levels_before_switch failed\n");
   7039		return ret;
   7040	}
   7041	if (eg_pi->pcie_performance_request)
   7042		si_request_link_speed_change_before_state_change(adev, new_ps, old_ps);
   7043	ni_set_uvd_clock_before_set_eng_clock(adev, new_ps, old_ps);
   7044	ret = si_enable_power_containment(adev, new_ps, false);
   7045	if (ret) {
   7046		DRM_ERROR("si_enable_power_containment failed\n");
   7047		return ret;
   7048	}
   7049	ret = si_enable_smc_cac(adev, new_ps, false);
   7050	if (ret) {
   7051		DRM_ERROR("si_enable_smc_cac failed\n");
   7052		return ret;
   7053	}
   7054	ret = si_halt_smc(adev);
   7055	if (ret) {
   7056		DRM_ERROR("si_halt_smc failed\n");
   7057		return ret;
   7058	}
   7059	ret = si_upload_sw_state(adev, new_ps);
   7060	if (ret) {
   7061		DRM_ERROR("si_upload_sw_state failed\n");
   7062		return ret;
   7063	}
   7064	ret = si_upload_smc_data(adev);
   7065	if (ret) {
   7066		DRM_ERROR("si_upload_smc_data failed\n");
   7067		return ret;
   7068	}
   7069	ret = si_upload_ulv_state(adev);
   7070	if (ret) {
   7071		DRM_ERROR("si_upload_ulv_state failed\n");
   7072		return ret;
   7073	}
   7074	if (eg_pi->dynamic_ac_timing) {
   7075		ret = si_upload_mc_reg_table(adev, new_ps);
   7076		if (ret) {
   7077			DRM_ERROR("si_upload_mc_reg_table failed\n");
   7078			return ret;
   7079		}
   7080	}
   7081	ret = si_program_memory_timing_parameters(adev, new_ps);
   7082	if (ret) {
   7083		DRM_ERROR("si_program_memory_timing_parameters failed\n");
   7084		return ret;
   7085	}
   7086	si_set_pcie_lane_width_in_smc(adev, new_ps, old_ps);
   7087
   7088	ret = si_resume_smc(adev);
   7089	if (ret) {
   7090		DRM_ERROR("si_resume_smc failed\n");
   7091		return ret;
   7092	}
   7093	ret = si_set_sw_state(adev);
   7094	if (ret) {
   7095		DRM_ERROR("si_set_sw_state failed\n");
   7096		return ret;
   7097	}
   7098	ni_set_uvd_clock_after_set_eng_clock(adev, new_ps, old_ps);
   7099	si_set_vce_clock(adev, new_ps, old_ps);
   7100	if (eg_pi->pcie_performance_request)
   7101		si_notify_link_speed_change_after_state_change(adev, new_ps, old_ps);
   7102	ret = si_set_power_state_conditionally_enable_ulv(adev, new_ps);
   7103	if (ret) {
   7104		DRM_ERROR("si_set_power_state_conditionally_enable_ulv failed\n");
   7105		return ret;
   7106	}
   7107	ret = si_enable_smc_cac(adev, new_ps, true);
   7108	if (ret) {
   7109		DRM_ERROR("si_enable_smc_cac failed\n");
   7110		return ret;
   7111	}
   7112	ret = si_enable_power_containment(adev, new_ps, true);
   7113	if (ret) {
   7114		DRM_ERROR("si_enable_power_containment failed\n");
   7115		return ret;
   7116	}
   7117
   7118	ret = si_power_control_set_level(adev);
   7119	if (ret) {
   7120		DRM_ERROR("si_power_control_set_level failed\n");
   7121		return ret;
   7122	}
   7123
   7124	return 0;
   7125}
   7126
   7127static void si_dpm_post_set_power_state(void *handle)
   7128{
   7129	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7130	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   7131	struct amdgpu_ps *new_ps = &eg_pi->requested_rps;
   7132
   7133	ni_update_current_ps(adev, new_ps);
   7134}
   7135
   7136#if 0
   7137void si_dpm_reset_asic(struct amdgpu_device *adev)
   7138{
   7139	si_restrict_performance_levels_before_switch(adev);
   7140	si_disable_ulv(adev);
   7141	si_set_boot_state(adev);
   7142}
   7143#endif
   7144
   7145static void si_dpm_display_configuration_changed(void *handle)
   7146{
   7147	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7148
   7149	si_program_display_gap(adev);
   7150}
   7151
   7152
   7153static void si_parse_pplib_non_clock_info(struct amdgpu_device *adev,
   7154					  struct amdgpu_ps *rps,
   7155					  struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
   7156					  u8 table_rev)
   7157{
   7158	rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
   7159	rps->class = le16_to_cpu(non_clock_info->usClassification);
   7160	rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
   7161
   7162	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
   7163		rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
   7164		rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
   7165	} else if (r600_is_uvd_state(rps->class, rps->class2)) {
   7166		rps->vclk = RV770_DEFAULT_VCLK_FREQ;
   7167		rps->dclk = RV770_DEFAULT_DCLK_FREQ;
   7168	} else {
   7169		rps->vclk = 0;
   7170		rps->dclk = 0;
   7171	}
   7172
   7173	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT)
   7174		adev->pm.dpm.boot_ps = rps;
   7175	if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
   7176		adev->pm.dpm.uvd_ps = rps;
   7177}
   7178
   7179static void si_parse_pplib_clock_info(struct amdgpu_device *adev,
   7180				      struct amdgpu_ps *rps, int index,
   7181				      union pplib_clock_info *clock_info)
   7182{
   7183	struct rv7xx_power_info *pi = rv770_get_pi(adev);
   7184	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   7185	struct si_power_info *si_pi = si_get_pi(adev);
   7186	struct  si_ps *ps = si_get_ps(rps);
   7187	u16 leakage_voltage;
   7188	struct rv7xx_pl *pl = &ps->performance_levels[index];
   7189	int ret;
   7190
   7191	ps->performance_level_count = index + 1;
   7192
   7193	pl->sclk = le16_to_cpu(clock_info->si.usEngineClockLow);
   7194	pl->sclk |= clock_info->si.ucEngineClockHigh << 16;
   7195	pl->mclk = le16_to_cpu(clock_info->si.usMemoryClockLow);
   7196	pl->mclk |= clock_info->si.ucMemoryClockHigh << 16;
   7197
   7198	pl->vddc = le16_to_cpu(clock_info->si.usVDDC);
   7199	pl->vddci = le16_to_cpu(clock_info->si.usVDDCI);
   7200	pl->flags = le32_to_cpu(clock_info->si.ulFlags);
   7201	pl->pcie_gen = si_gen_pcie_gen_support(adev,
   7202					       si_pi->sys_pcie_mask,
   7203					       si_pi->boot_pcie_gen,
   7204					       clock_info->si.ucPCIEGen);
   7205
   7206	/* patch up vddc if necessary */
   7207	ret = si_get_leakage_voltage_from_leakage_index(adev, pl->vddc,
   7208							&leakage_voltage);
   7209	if (ret == 0)
   7210		pl->vddc = leakage_voltage;
   7211
   7212	if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) {
   7213		pi->acpi_vddc = pl->vddc;
   7214		eg_pi->acpi_vddci = pl->vddci;
   7215		si_pi->acpi_pcie_gen = pl->pcie_gen;
   7216	}
   7217
   7218	if ((rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) &&
   7219	    index == 0) {
   7220		/* XXX disable for A0 tahiti */
   7221		si_pi->ulv.supported = false;
   7222		si_pi->ulv.pl = *pl;
   7223		si_pi->ulv.one_pcie_lane_in_ulv = false;
   7224		si_pi->ulv.volt_change_delay = SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT;
   7225		si_pi->ulv.cg_ulv_parameter = SISLANDS_CGULVPARAMETER_DFLT;
   7226		si_pi->ulv.cg_ulv_control = SISLANDS_CGULVCONTROL_DFLT;
   7227	}
   7228
   7229	if (pi->min_vddc_in_table > pl->vddc)
   7230		pi->min_vddc_in_table = pl->vddc;
   7231
   7232	if (pi->max_vddc_in_table < pl->vddc)
   7233		pi->max_vddc_in_table = pl->vddc;
   7234
   7235	/* patch up boot state */
   7236	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
   7237		u16 vddc, vddci, mvdd;
   7238		amdgpu_atombios_get_default_voltages(adev, &vddc, &vddci, &mvdd);
   7239		pl->mclk = adev->clock.default_mclk;
   7240		pl->sclk = adev->clock.default_sclk;
   7241		pl->vddc = vddc;
   7242		pl->vddci = vddci;
   7243		si_pi->mvdd_bootup_value = mvdd;
   7244	}
   7245
   7246	if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
   7247	    ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
   7248		adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
   7249		adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
   7250		adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
   7251		adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
   7252	}
   7253}
   7254
   7255union pplib_power_state {
   7256	struct _ATOM_PPLIB_STATE v1;
   7257	struct _ATOM_PPLIB_STATE_V2 v2;
   7258};
   7259
   7260static int si_parse_power_table(struct amdgpu_device *adev)
   7261{
   7262	struct amdgpu_mode_info *mode_info = &adev->mode_info;
   7263	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
   7264	union pplib_power_state *power_state;
   7265	int i, j, k, non_clock_array_index, clock_array_index;
   7266	union pplib_clock_info *clock_info;
   7267	struct _StateArray *state_array;
   7268	struct _ClockInfoArray *clock_info_array;
   7269	struct _NonClockInfoArray *non_clock_info_array;
   7270	union power_info *power_info;
   7271	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
   7272	u16 data_offset;
   7273	u8 frev, crev;
   7274	u8 *power_state_offset;
   7275	struct  si_ps *ps;
   7276
   7277	if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
   7278				   &frev, &crev, &data_offset))
   7279		return -EINVAL;
   7280	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
   7281
   7282	amdgpu_add_thermal_controller(adev);
   7283
   7284	state_array = (struct _StateArray *)
   7285		(mode_info->atom_context->bios + data_offset +
   7286		 le16_to_cpu(power_info->pplib.usStateArrayOffset));
   7287	clock_info_array = (struct _ClockInfoArray *)
   7288		(mode_info->atom_context->bios + data_offset +
   7289		 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
   7290	non_clock_info_array = (struct _NonClockInfoArray *)
   7291		(mode_info->atom_context->bios + data_offset +
   7292		 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
   7293
   7294	adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
   7295				  sizeof(struct amdgpu_ps),
   7296				  GFP_KERNEL);
   7297	if (!adev->pm.dpm.ps)
   7298		return -ENOMEM;
   7299	power_state_offset = (u8 *)state_array->states;
   7300	for (adev->pm.dpm.num_ps = 0, i = 0; i < state_array->ucNumEntries; i++) {
   7301		u8 *idx;
   7302		power_state = (union pplib_power_state *)power_state_offset;
   7303		non_clock_array_index = power_state->v2.nonClockInfoIndex;
   7304		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
   7305			&non_clock_info_array->nonClockInfo[non_clock_array_index];
   7306		ps = kzalloc(sizeof(struct  si_ps), GFP_KERNEL);
   7307		if (ps == NULL)
   7308			return -ENOMEM;
   7309		adev->pm.dpm.ps[i].ps_priv = ps;
   7310		si_parse_pplib_non_clock_info(adev, &adev->pm.dpm.ps[i],
   7311					      non_clock_info,
   7312					      non_clock_info_array->ucEntrySize);
   7313		k = 0;
   7314		idx = (u8 *)&power_state->v2.clockInfoIndex[0];
   7315		for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
   7316			clock_array_index = idx[j];
   7317			if (clock_array_index >= clock_info_array->ucNumEntries)
   7318				continue;
   7319			if (k >= SISLANDS_MAX_HARDWARE_POWERLEVELS)
   7320				break;
   7321			clock_info = (union pplib_clock_info *)
   7322				((u8 *)&clock_info_array->clockInfo[0] +
   7323				 (clock_array_index * clock_info_array->ucEntrySize));
   7324			si_parse_pplib_clock_info(adev,
   7325						  &adev->pm.dpm.ps[i], k,
   7326						  clock_info);
   7327			k++;
   7328		}
   7329		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
   7330		adev->pm.dpm.num_ps++;
   7331	}
   7332
   7333	/* fill in the vce power states */
   7334	for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
   7335		u32 sclk, mclk;
   7336		clock_array_index = adev->pm.dpm.vce_states[i].clk_idx;
   7337		clock_info = (union pplib_clock_info *)
   7338			&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
   7339		sclk = le16_to_cpu(clock_info->si.usEngineClockLow);
   7340		sclk |= clock_info->si.ucEngineClockHigh << 16;
   7341		mclk = le16_to_cpu(clock_info->si.usMemoryClockLow);
   7342		mclk |= clock_info->si.ucMemoryClockHigh << 16;
   7343		adev->pm.dpm.vce_states[i].sclk = sclk;
   7344		adev->pm.dpm.vce_states[i].mclk = mclk;
   7345	}
   7346
   7347	return 0;
   7348}
   7349
   7350static int si_dpm_init(struct amdgpu_device *adev)
   7351{
   7352	struct rv7xx_power_info *pi;
   7353	struct evergreen_power_info *eg_pi;
   7354	struct ni_power_info *ni_pi;
   7355	struct si_power_info *si_pi;
   7356	struct atom_clock_dividers dividers;
   7357	int ret;
   7358
   7359	si_pi = kzalloc(sizeof(struct si_power_info), GFP_KERNEL);
   7360	if (si_pi == NULL)
   7361		return -ENOMEM;
   7362	adev->pm.dpm.priv = si_pi;
   7363	ni_pi = &si_pi->ni;
   7364	eg_pi = &ni_pi->eg;
   7365	pi = &eg_pi->rv7xx;
   7366
   7367	si_pi->sys_pcie_mask =
   7368		adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_MASK;
   7369	si_pi->force_pcie_gen = SI_PCIE_GEN_INVALID;
   7370	si_pi->boot_pcie_gen = si_get_current_pcie_speed(adev);
   7371
   7372	si_set_max_cu_value(adev);
   7373
   7374	rv770_get_max_vddc(adev);
   7375	si_get_leakage_vddc(adev);
   7376	si_patch_dependency_tables_based_on_leakage(adev);
   7377
   7378	pi->acpi_vddc = 0;
   7379	eg_pi->acpi_vddci = 0;
   7380	pi->min_vddc_in_table = 0;
   7381	pi->max_vddc_in_table = 0;
   7382
   7383	ret = amdgpu_get_platform_caps(adev);
   7384	if (ret)
   7385		return ret;
   7386
   7387	ret = amdgpu_parse_extended_power_table(adev);
   7388	if (ret)
   7389		return ret;
   7390
   7391	ret = si_parse_power_table(adev);
   7392	if (ret)
   7393		return ret;
   7394
   7395	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
   7396		kcalloc(4,
   7397			sizeof(struct amdgpu_clock_voltage_dependency_entry),
   7398			GFP_KERNEL);
   7399	if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
   7400		amdgpu_free_extended_power_table(adev);
   7401		return -ENOMEM;
   7402	}
   7403	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4;
   7404	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0;
   7405	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0;
   7406	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000;
   7407	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 720;
   7408	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000;
   7409	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 810;
   7410	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000;
   7411	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 900;
   7412
   7413	if (adev->pm.dpm.voltage_response_time == 0)
   7414		adev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT;
   7415	if (adev->pm.dpm.backbias_response_time == 0)
   7416		adev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT;
   7417
   7418	ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM,
   7419					     0, false, &dividers);
   7420	if (ret)
   7421		pi->ref_div = dividers.ref_div + 1;
   7422	else
   7423		pi->ref_div = R600_REFERENCEDIVIDER_DFLT;
   7424
   7425	eg_pi->smu_uvd_hs = false;
   7426
   7427	pi->mclk_strobe_mode_threshold = 40000;
   7428	if (si_is_special_1gb_platform(adev))
   7429		pi->mclk_stutter_mode_threshold = 0;
   7430	else
   7431		pi->mclk_stutter_mode_threshold = pi->mclk_strobe_mode_threshold;
   7432	pi->mclk_edc_enable_threshold = 40000;
   7433	eg_pi->mclk_edc_wr_enable_threshold = 40000;
   7434
   7435	ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold;
   7436
   7437	pi->voltage_control =
   7438		amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC,
   7439					    VOLTAGE_OBJ_GPIO_LUT);
   7440	if (!pi->voltage_control) {
   7441		si_pi->voltage_control_svi2 =
   7442			amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC,
   7443						    VOLTAGE_OBJ_SVID2);
   7444		if (si_pi->voltage_control_svi2)
   7445			amdgpu_atombios_get_svi2_info(adev, SET_VOLTAGE_TYPE_ASIC_VDDC,
   7446						  &si_pi->svd_gpio_id, &si_pi->svc_gpio_id);
   7447	}
   7448
   7449	pi->mvdd_control =
   7450		amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_MVDDC,
   7451					    VOLTAGE_OBJ_GPIO_LUT);
   7452
   7453	eg_pi->vddci_control =
   7454		amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
   7455					    VOLTAGE_OBJ_GPIO_LUT);
   7456	if (!eg_pi->vddci_control)
   7457		si_pi->vddci_control_svi2 =
   7458			amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
   7459						    VOLTAGE_OBJ_SVID2);
   7460
   7461	si_pi->vddc_phase_shed_control =
   7462		amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC,
   7463					    VOLTAGE_OBJ_PHASE_LUT);
   7464
   7465	rv770_get_engine_memory_ss(adev);
   7466
   7467	pi->asi = RV770_ASI_DFLT;
   7468	pi->pasi = CYPRESS_HASI_DFLT;
   7469	pi->vrc = SISLANDS_VRC_DFLT;
   7470
   7471	pi->gfx_clock_gating = true;
   7472
   7473	eg_pi->sclk_deep_sleep = true;
   7474	si_pi->sclk_deep_sleep_above_low = false;
   7475
   7476	if (adev->pm.int_thermal_type != THERMAL_TYPE_NONE)
   7477		pi->thermal_protection = true;
   7478	else
   7479		pi->thermal_protection = false;
   7480
   7481	eg_pi->dynamic_ac_timing = true;
   7482
   7483	eg_pi->light_sleep = true;
   7484#if defined(CONFIG_ACPI)
   7485	eg_pi->pcie_performance_request =
   7486		amdgpu_acpi_is_pcie_performance_request_supported(adev);
   7487#else
   7488	eg_pi->pcie_performance_request = false;
   7489#endif
   7490
   7491	si_pi->sram_end = SMC_RAM_END;
   7492
   7493	adev->pm.dpm.dyn_state.mclk_sclk_ratio = 4;
   7494	adev->pm.dpm.dyn_state.sclk_mclk_delta = 15000;
   7495	adev->pm.dpm.dyn_state.vddc_vddci_delta = 200;
   7496	adev->pm.dpm.dyn_state.valid_sclk_values.count = 0;
   7497	adev->pm.dpm.dyn_state.valid_sclk_values.values = NULL;
   7498	adev->pm.dpm.dyn_state.valid_mclk_values.count = 0;
   7499	adev->pm.dpm.dyn_state.valid_mclk_values.values = NULL;
   7500
   7501	si_initialize_powertune_defaults(adev);
   7502
   7503	/* make sure dc limits are valid */
   7504	if ((adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk == 0) ||
   7505	    (adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk == 0))
   7506		adev->pm.dpm.dyn_state.max_clock_voltage_on_dc =
   7507			adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
   7508
   7509	si_pi->fan_ctrl_is_in_default_mode = true;
   7510
   7511	return 0;
   7512}
   7513
   7514static void si_dpm_fini(struct amdgpu_device *adev)
   7515{
   7516	int i;
   7517
   7518	if (adev->pm.dpm.ps)
   7519		for (i = 0; i < adev->pm.dpm.num_ps; i++)
   7520			kfree(adev->pm.dpm.ps[i].ps_priv);
   7521	kfree(adev->pm.dpm.ps);
   7522	kfree(adev->pm.dpm.priv);
   7523	kfree(adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries);
   7524	amdgpu_free_extended_power_table(adev);
   7525}
   7526
   7527static void si_dpm_debugfs_print_current_performance_level(void *handle,
   7528						    struct seq_file *m)
   7529{
   7530	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7531	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   7532	struct amdgpu_ps *rps = &eg_pi->current_rps;
   7533	struct  si_ps *ps = si_get_ps(rps);
   7534	struct rv7xx_pl *pl;
   7535	u32 current_index =
   7536		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
   7537		CURRENT_STATE_INDEX_SHIFT;
   7538
   7539	if (current_index >= ps->performance_level_count) {
   7540		seq_printf(m, "invalid dpm profile %d\n", current_index);
   7541	} else {
   7542		pl = &ps->performance_levels[current_index];
   7543		seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
   7544		seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n",
   7545			   current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1);
   7546	}
   7547}
   7548
   7549static int si_dpm_set_interrupt_state(struct amdgpu_device *adev,
   7550				      struct amdgpu_irq_src *source,
   7551				      unsigned type,
   7552				      enum amdgpu_interrupt_state state)
   7553{
   7554	u32 cg_thermal_int;
   7555
   7556	switch (type) {
   7557	case AMDGPU_THERMAL_IRQ_LOW_TO_HIGH:
   7558		switch (state) {
   7559		case AMDGPU_IRQ_STATE_DISABLE:
   7560			cg_thermal_int = RREG32_SMC(CG_THERMAL_INT);
   7561			cg_thermal_int |= THERM_INT_MASK_HIGH;
   7562			WREG32_SMC(CG_THERMAL_INT, cg_thermal_int);
   7563			break;
   7564		case AMDGPU_IRQ_STATE_ENABLE:
   7565			cg_thermal_int = RREG32_SMC(CG_THERMAL_INT);
   7566			cg_thermal_int &= ~THERM_INT_MASK_HIGH;
   7567			WREG32_SMC(CG_THERMAL_INT, cg_thermal_int);
   7568			break;
   7569		default:
   7570			break;
   7571		}
   7572		break;
   7573
   7574	case AMDGPU_THERMAL_IRQ_HIGH_TO_LOW:
   7575		switch (state) {
   7576		case AMDGPU_IRQ_STATE_DISABLE:
   7577			cg_thermal_int = RREG32_SMC(CG_THERMAL_INT);
   7578			cg_thermal_int |= THERM_INT_MASK_LOW;
   7579			WREG32_SMC(CG_THERMAL_INT, cg_thermal_int);
   7580			break;
   7581		case AMDGPU_IRQ_STATE_ENABLE:
   7582			cg_thermal_int = RREG32_SMC(CG_THERMAL_INT);
   7583			cg_thermal_int &= ~THERM_INT_MASK_LOW;
   7584			WREG32_SMC(CG_THERMAL_INT, cg_thermal_int);
   7585			break;
   7586		default:
   7587			break;
   7588		}
   7589		break;
   7590
   7591	default:
   7592		break;
   7593	}
   7594	return 0;
   7595}
   7596
   7597static int si_dpm_process_interrupt(struct amdgpu_device *adev,
   7598				    struct amdgpu_irq_src *source,
   7599				    struct amdgpu_iv_entry *entry)
   7600{
   7601	bool queue_thermal = false;
   7602
   7603	if (entry == NULL)
   7604		return -EINVAL;
   7605
   7606	switch (entry->src_id) {
   7607	case 230: /* thermal low to high */
   7608		DRM_DEBUG("IH: thermal low to high\n");
   7609		adev->pm.dpm.thermal.high_to_low = false;
   7610		queue_thermal = true;
   7611		break;
   7612	case 231: /* thermal high to low */
   7613		DRM_DEBUG("IH: thermal high to low\n");
   7614		adev->pm.dpm.thermal.high_to_low = true;
   7615		queue_thermal = true;
   7616		break;
   7617	default:
   7618		break;
   7619	}
   7620
   7621	if (queue_thermal)
   7622		schedule_work(&adev->pm.dpm.thermal.work);
   7623
   7624	return 0;
   7625}
   7626
   7627static int si_dpm_late_init(void *handle)
   7628{
   7629	int ret;
   7630	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7631
   7632	if (!adev->pm.dpm_enabled)
   7633		return 0;
   7634
   7635	ret = si_set_temperature_range(adev);
   7636	if (ret)
   7637		return ret;
   7638#if 0 //TODO ?
   7639	si_dpm_powergate_uvd(adev, true);
   7640#endif
   7641	return 0;
   7642}
   7643
   7644/**
   7645 * si_dpm_init_microcode - load ucode images from disk
   7646 *
   7647 * @adev: amdgpu_device pointer
   7648 *
   7649 * Use the firmware interface to load the ucode images into
   7650 * the driver (not loaded into hw).
   7651 * Returns 0 on success, error on failure.
   7652 */
   7653static int si_dpm_init_microcode(struct amdgpu_device *adev)
   7654{
   7655	const char *chip_name;
   7656	char fw_name[30];
   7657	int err;
   7658
   7659	DRM_DEBUG("\n");
   7660	switch (adev->asic_type) {
   7661	case CHIP_TAHITI:
   7662		chip_name = "tahiti";
   7663		break;
   7664	case CHIP_PITCAIRN:
   7665		if ((adev->pdev->revision == 0x81) &&
   7666		    ((adev->pdev->device == 0x6810) ||
   7667		    (adev->pdev->device == 0x6811)))
   7668			chip_name = "pitcairn_k";
   7669		else
   7670			chip_name = "pitcairn";
   7671		break;
   7672	case CHIP_VERDE:
   7673		if (((adev->pdev->device == 0x6820) &&
   7674			((adev->pdev->revision == 0x81) ||
   7675			(adev->pdev->revision == 0x83))) ||
   7676		    ((adev->pdev->device == 0x6821) &&
   7677			((adev->pdev->revision == 0x83) ||
   7678			(adev->pdev->revision == 0x87))) ||
   7679		    ((adev->pdev->revision == 0x87) &&
   7680			((adev->pdev->device == 0x6823) ||
   7681			(adev->pdev->device == 0x682b))))
   7682			chip_name = "verde_k";
   7683		else
   7684			chip_name = "verde";
   7685		break;
   7686	case CHIP_OLAND:
   7687		if (((adev->pdev->revision == 0x81) &&
   7688			((adev->pdev->device == 0x6600) ||
   7689			(adev->pdev->device == 0x6604) ||
   7690			(adev->pdev->device == 0x6605) ||
   7691			(adev->pdev->device == 0x6610))) ||
   7692		    ((adev->pdev->revision == 0x83) &&
   7693			(adev->pdev->device == 0x6610)))
   7694			chip_name = "oland_k";
   7695		else
   7696			chip_name = "oland";
   7697		break;
   7698	case CHIP_HAINAN:
   7699		if (((adev->pdev->revision == 0x81) &&
   7700			(adev->pdev->device == 0x6660)) ||
   7701		    ((adev->pdev->revision == 0x83) &&
   7702			((adev->pdev->device == 0x6660) ||
   7703			(adev->pdev->device == 0x6663) ||
   7704			(adev->pdev->device == 0x6665) ||
   7705			 (adev->pdev->device == 0x6667))))
   7706			chip_name = "hainan_k";
   7707		else if ((adev->pdev->revision == 0xc3) &&
   7708			 (adev->pdev->device == 0x6665))
   7709			chip_name = "banks_k_2";
   7710		else
   7711			chip_name = "hainan";
   7712		break;
   7713	default: BUG();
   7714	}
   7715
   7716	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name);
   7717	err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
   7718	if (err)
   7719		goto out;
   7720	err = amdgpu_ucode_validate(adev->pm.fw);
   7721
   7722out:
   7723	if (err) {
   7724		DRM_ERROR("si_smc: Failed to load firmware. err = %d\"%s\"\n",
   7725			  err, fw_name);
   7726		release_firmware(adev->pm.fw);
   7727		adev->pm.fw = NULL;
   7728	}
   7729	return err;
   7730
   7731}
   7732
   7733static int si_dpm_sw_init(void *handle)
   7734{
   7735	int ret;
   7736	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7737
   7738	ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 230, &adev->pm.dpm.thermal.irq);
   7739	if (ret)
   7740		return ret;
   7741
   7742	ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 231, &adev->pm.dpm.thermal.irq);
   7743	if (ret)
   7744		return ret;
   7745
   7746	/* default to balanced state */
   7747	adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED;
   7748	adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED;
   7749	adev->pm.dpm.forced_level = AMD_DPM_FORCED_LEVEL_AUTO;
   7750	adev->pm.default_sclk = adev->clock.default_sclk;
   7751	adev->pm.default_mclk = adev->clock.default_mclk;
   7752	adev->pm.current_sclk = adev->clock.default_sclk;
   7753	adev->pm.current_mclk = adev->clock.default_mclk;
   7754	adev->pm.int_thermal_type = THERMAL_TYPE_NONE;
   7755
   7756	if (amdgpu_dpm == 0)
   7757		return 0;
   7758
   7759	ret = si_dpm_init_microcode(adev);
   7760	if (ret)
   7761		return ret;
   7762
   7763	INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler);
   7764	ret = si_dpm_init(adev);
   7765	if (ret)
   7766		goto dpm_failed;
   7767	adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
   7768	if (amdgpu_dpm == 1)
   7769		amdgpu_pm_print_power_states(adev);
   7770	DRM_INFO("amdgpu: dpm initialized\n");
   7771
   7772	return 0;
   7773
   7774dpm_failed:
   7775	si_dpm_fini(adev);
   7776	DRM_ERROR("amdgpu: dpm initialization failed\n");
   7777	return ret;
   7778}
   7779
   7780static int si_dpm_sw_fini(void *handle)
   7781{
   7782	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7783
   7784	flush_work(&adev->pm.dpm.thermal.work);
   7785
   7786	si_dpm_fini(adev);
   7787
   7788	return 0;
   7789}
   7790
   7791static int si_dpm_hw_init(void *handle)
   7792{
   7793	int ret;
   7794
   7795	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7796
   7797	if (!amdgpu_dpm)
   7798		return 0;
   7799
   7800	si_dpm_setup_asic(adev);
   7801	ret = si_dpm_enable(adev);
   7802	if (ret)
   7803		adev->pm.dpm_enabled = false;
   7804	else
   7805		adev->pm.dpm_enabled = true;
   7806	amdgpu_legacy_dpm_compute_clocks(adev);
   7807	return ret;
   7808}
   7809
   7810static int si_dpm_hw_fini(void *handle)
   7811{
   7812	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7813
   7814	if (adev->pm.dpm_enabled)
   7815		si_dpm_disable(adev);
   7816
   7817	return 0;
   7818}
   7819
   7820static int si_dpm_suspend(void *handle)
   7821{
   7822	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7823
   7824	if (adev->pm.dpm_enabled) {
   7825		/* disable dpm */
   7826		si_dpm_disable(adev);
   7827		/* reset the power state */
   7828		adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
   7829	}
   7830	return 0;
   7831}
   7832
   7833static int si_dpm_resume(void *handle)
   7834{
   7835	int ret;
   7836	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7837
   7838	if (adev->pm.dpm_enabled) {
   7839		/* asic init will reset to the boot state */
   7840		si_dpm_setup_asic(adev);
   7841		ret = si_dpm_enable(adev);
   7842		if (ret)
   7843			adev->pm.dpm_enabled = false;
   7844		else
   7845			adev->pm.dpm_enabled = true;
   7846		if (adev->pm.dpm_enabled)
   7847			amdgpu_legacy_dpm_compute_clocks(adev);
   7848	}
   7849	return 0;
   7850}
   7851
   7852static bool si_dpm_is_idle(void *handle)
   7853{
   7854	/* XXX */
   7855	return true;
   7856}
   7857
   7858static int si_dpm_wait_for_idle(void *handle)
   7859{
   7860	/* XXX */
   7861	return 0;
   7862}
   7863
   7864static int si_dpm_soft_reset(void *handle)
   7865{
   7866	return 0;
   7867}
   7868
   7869static int si_dpm_set_clockgating_state(void *handle,
   7870					enum amd_clockgating_state state)
   7871{
   7872	return 0;
   7873}
   7874
   7875static int si_dpm_set_powergating_state(void *handle,
   7876					enum amd_powergating_state state)
   7877{
   7878	return 0;
   7879}
   7880
   7881/* get temperature in millidegrees */
   7882static int si_dpm_get_temp(void *handle)
   7883{
   7884	u32 temp;
   7885	int actual_temp = 0;
   7886	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7887
   7888	temp = (RREG32(CG_MULT_THERMAL_STATUS) & CTF_TEMP_MASK) >>
   7889		CTF_TEMP_SHIFT;
   7890
   7891	if (temp & 0x200)
   7892		actual_temp = 255;
   7893	else
   7894		actual_temp = temp & 0x1ff;
   7895
   7896	actual_temp = (actual_temp * 1000);
   7897
   7898	return actual_temp;
   7899}
   7900
   7901static u32 si_dpm_get_sclk(void *handle, bool low)
   7902{
   7903	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7904	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   7905	struct  si_ps *requested_state = si_get_ps(&eg_pi->requested_rps);
   7906
   7907	if (low)
   7908		return requested_state->performance_levels[0].sclk;
   7909	else
   7910		return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk;
   7911}
   7912
   7913static u32 si_dpm_get_mclk(void *handle, bool low)
   7914{
   7915	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7916	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   7917	struct  si_ps *requested_state = si_get_ps(&eg_pi->requested_rps);
   7918
   7919	if (low)
   7920		return requested_state->performance_levels[0].mclk;
   7921	else
   7922		return requested_state->performance_levels[requested_state->performance_level_count - 1].mclk;
   7923}
   7924
   7925static void si_dpm_print_power_state(void *handle,
   7926				     void *current_ps)
   7927{
   7928	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7929	struct amdgpu_ps *rps = (struct amdgpu_ps *)current_ps;
   7930	struct  si_ps *ps = si_get_ps(rps);
   7931	struct rv7xx_pl *pl;
   7932	int i;
   7933
   7934	amdgpu_dpm_print_class_info(rps->class, rps->class2);
   7935	amdgpu_dpm_print_cap_info(rps->caps);
   7936	DRM_INFO("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
   7937	for (i = 0; i < ps->performance_level_count; i++) {
   7938		pl = &ps->performance_levels[i];
   7939		if (adev->asic_type >= CHIP_TAHITI)
   7940			DRM_INFO("\t\tpower level %d    sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n",
   7941				 i, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1);
   7942		else
   7943			DRM_INFO("\t\tpower level %d    sclk: %u mclk: %u vddc: %u vddci: %u\n",
   7944				 i, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
   7945	}
   7946	amdgpu_dpm_print_ps_status(adev, rps);
   7947}
   7948
   7949static int si_dpm_early_init(void *handle)
   7950{
   7951
   7952	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7953
   7954	adev->powerplay.pp_funcs = &si_dpm_funcs;
   7955	adev->powerplay.pp_handle = adev;
   7956	si_dpm_set_irq_funcs(adev);
   7957	return 0;
   7958}
   7959
   7960static inline bool si_are_power_levels_equal(const struct rv7xx_pl  *si_cpl1,
   7961						const struct rv7xx_pl *si_cpl2)
   7962{
   7963	return ((si_cpl1->mclk == si_cpl2->mclk) &&
   7964		  (si_cpl1->sclk == si_cpl2->sclk) &&
   7965		  (si_cpl1->pcie_gen == si_cpl2->pcie_gen) &&
   7966		  (si_cpl1->vddc == si_cpl2->vddc) &&
   7967		  (si_cpl1->vddci == si_cpl2->vddci));
   7968}
   7969
   7970static int si_check_state_equal(void *handle,
   7971				void *current_ps,
   7972				void *request_ps,
   7973				bool *equal)
   7974{
   7975	struct si_ps *si_cps;
   7976	struct si_ps *si_rps;
   7977	int i;
   7978	struct amdgpu_ps *cps = (struct amdgpu_ps *)current_ps;
   7979	struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps;
   7980	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   7981
   7982	if (adev == NULL || cps == NULL || rps == NULL || equal == NULL)
   7983		return -EINVAL;
   7984
   7985	si_cps = si_get_ps((struct amdgpu_ps *)cps);
   7986	si_rps = si_get_ps((struct amdgpu_ps *)rps);
   7987
   7988	if (si_cps == NULL) {
   7989		printk("si_cps is NULL\n");
   7990		*equal = false;
   7991		return 0;
   7992	}
   7993
   7994	if (si_cps->performance_level_count != si_rps->performance_level_count) {
   7995		*equal = false;
   7996		return 0;
   7997	}
   7998
   7999	for (i = 0; i < si_cps->performance_level_count; i++) {
   8000		if (!si_are_power_levels_equal(&(si_cps->performance_levels[i]),
   8001					&(si_rps->performance_levels[i]))) {
   8002			*equal = false;
   8003			return 0;
   8004		}
   8005	}
   8006
   8007	/* If all performance levels are the same try to use the UVD clocks to break the tie.*/
   8008	*equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk));
   8009	*equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk));
   8010
   8011	return 0;
   8012}
   8013
   8014static int si_dpm_read_sensor(void *handle, int idx,
   8015			      void *value, int *size)
   8016{
   8017	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
   8018	struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);
   8019	struct amdgpu_ps *rps = &eg_pi->current_rps;
   8020	struct  si_ps *ps = si_get_ps(rps);
   8021	uint32_t sclk, mclk;
   8022	u32 pl_index =
   8023		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
   8024		CURRENT_STATE_INDEX_SHIFT;
   8025
   8026	/* size must be at least 4 bytes for all sensors */
   8027	if (*size < 4)
   8028		return -EINVAL;
   8029
   8030	switch (idx) {
   8031	case AMDGPU_PP_SENSOR_GFX_SCLK:
   8032		if (pl_index < ps->performance_level_count) {
   8033			sclk = ps->performance_levels[pl_index].sclk;
   8034			*((uint32_t *)value) = sclk;
   8035			*size = 4;
   8036			return 0;
   8037		}
   8038		return -EINVAL;
   8039	case AMDGPU_PP_SENSOR_GFX_MCLK:
   8040		if (pl_index < ps->performance_level_count) {
   8041			mclk = ps->performance_levels[pl_index].mclk;
   8042			*((uint32_t *)value) = mclk;
   8043			*size = 4;
   8044			return 0;
   8045		}
   8046		return -EINVAL;
   8047	case AMDGPU_PP_SENSOR_GPU_TEMP:
   8048		*((uint32_t *)value) = si_dpm_get_temp(adev);
   8049		*size = 4;
   8050		return 0;
   8051	default:
   8052		return -EOPNOTSUPP;
   8053	}
   8054}
   8055
   8056static const struct amd_ip_funcs si_dpm_ip_funcs = {
   8057	.name = "si_dpm",
   8058	.early_init = si_dpm_early_init,
   8059	.late_init = si_dpm_late_init,
   8060	.sw_init = si_dpm_sw_init,
   8061	.sw_fini = si_dpm_sw_fini,
   8062	.hw_init = si_dpm_hw_init,
   8063	.hw_fini = si_dpm_hw_fini,
   8064	.suspend = si_dpm_suspend,
   8065	.resume = si_dpm_resume,
   8066	.is_idle = si_dpm_is_idle,
   8067	.wait_for_idle = si_dpm_wait_for_idle,
   8068	.soft_reset = si_dpm_soft_reset,
   8069	.set_clockgating_state = si_dpm_set_clockgating_state,
   8070	.set_powergating_state = si_dpm_set_powergating_state,
   8071};
   8072
   8073const struct amdgpu_ip_block_version si_smu_ip_block =
   8074{
   8075	.type = AMD_IP_BLOCK_TYPE_SMC,
   8076	.major = 6,
   8077	.minor = 0,
   8078	.rev = 0,
   8079	.funcs = &si_dpm_ip_funcs,
   8080};
   8081
   8082static const struct amd_pm_funcs si_dpm_funcs = {
   8083	.pre_set_power_state = &si_dpm_pre_set_power_state,
   8084	.set_power_state = &si_dpm_set_power_state,
   8085	.post_set_power_state = &si_dpm_post_set_power_state,
   8086	.display_configuration_changed = &si_dpm_display_configuration_changed,
   8087	.get_sclk = &si_dpm_get_sclk,
   8088	.get_mclk = &si_dpm_get_mclk,
   8089	.print_power_state = &si_dpm_print_power_state,
   8090	.debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level,
   8091	.force_performance_level = &si_dpm_force_performance_level,
   8092	.vblank_too_short = &si_dpm_vblank_too_short,
   8093	.set_fan_control_mode = &si_dpm_set_fan_control_mode,
   8094	.get_fan_control_mode = &si_dpm_get_fan_control_mode,
   8095	.set_fan_speed_pwm = &si_dpm_set_fan_speed_pwm,
   8096	.get_fan_speed_pwm = &si_dpm_get_fan_speed_pwm,
   8097	.check_state_equal = &si_check_state_equal,
   8098	.get_vce_clock_state = amdgpu_get_vce_clock_state,
   8099	.read_sensor = &si_dpm_read_sensor,
   8100	.pm_compute_clocks = amdgpu_legacy_dpm_compute_clocks,
   8101};
   8102
   8103static const struct amdgpu_irq_src_funcs si_dpm_irq_funcs = {
   8104	.set = si_dpm_set_interrupt_state,
   8105	.process = si_dpm_process_interrupt,
   8106};
   8107
   8108static void si_dpm_set_irq_funcs(struct amdgpu_device *adev)
   8109{
   8110	adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST;
   8111	adev->pm.dpm.thermal.irq.funcs = &si_dpm_irq_funcs;
   8112}
   8113