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 (233868B)


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