0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include "radeon.h"
0026 #include "cikd.h"
0027 #include "kv_dpm.h"
0028
0029 int kv_notify_message_to_smu(struct radeon_device *rdev, u32 id)
0030 {
0031 u32 i;
0032 u32 tmp = 0;
0033
0034 WREG32(SMC_MESSAGE_0, id & SMC_MSG_MASK);
0035
0036 for (i = 0; i < rdev->usec_timeout; i++) {
0037 if ((RREG32(SMC_RESP_0) & SMC_RESP_MASK) != 0)
0038 break;
0039 udelay(1);
0040 }
0041 tmp = RREG32(SMC_RESP_0) & SMC_RESP_MASK;
0042
0043 if (tmp != 1) {
0044 if (tmp == 0xFF)
0045 return -EINVAL;
0046 else if (tmp == 0xFE)
0047 return -EINVAL;
0048 }
0049
0050 return 0;
0051 }
0052
0053 int kv_dpm_get_enable_mask(struct radeon_device *rdev, u32 *enable_mask)
0054 {
0055 int ret;
0056
0057 ret = kv_notify_message_to_smu(rdev, PPSMC_MSG_SCLKDPM_GetEnabledMask);
0058
0059 if (ret == 0)
0060 *enable_mask = RREG32_SMC(SMC_SYSCON_MSG_ARG_0);
0061
0062 return ret;
0063 }
0064
0065 int kv_send_msg_to_smc_with_parameter(struct radeon_device *rdev,
0066 PPSMC_Msg msg, u32 parameter)
0067 {
0068
0069 WREG32(SMC_MSG_ARG_0, parameter);
0070
0071 return kv_notify_message_to_smu(rdev, msg);
0072 }
0073
0074 static int kv_set_smc_sram_address(struct radeon_device *rdev,
0075 u32 smc_address, u32 limit)
0076 {
0077 if (smc_address & 3)
0078 return -EINVAL;
0079 if ((smc_address + 3) > limit)
0080 return -EINVAL;
0081
0082 WREG32(SMC_IND_INDEX_0, smc_address);
0083 WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
0084
0085 return 0;
0086 }
0087
0088 int kv_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
0089 u32 *value, u32 limit)
0090 {
0091 int ret;
0092
0093 ret = kv_set_smc_sram_address(rdev, smc_address, limit);
0094 if (ret)
0095 return ret;
0096
0097 *value = RREG32(SMC_IND_DATA_0);
0098 return 0;
0099 }
0100
0101 int kv_smc_dpm_enable(struct radeon_device *rdev, bool enable)
0102 {
0103 if (enable)
0104 return kv_notify_message_to_smu(rdev, PPSMC_MSG_DPM_Enable);
0105 else
0106 return kv_notify_message_to_smu(rdev, PPSMC_MSG_DPM_Disable);
0107 }
0108
0109 int kv_smc_bapm_enable(struct radeon_device *rdev, bool enable)
0110 {
0111 if (enable)
0112 return kv_notify_message_to_smu(rdev, PPSMC_MSG_EnableBAPM);
0113 else
0114 return kv_notify_message_to_smu(rdev, PPSMC_MSG_DisableBAPM);
0115 }
0116
0117 int kv_copy_bytes_to_smc(struct radeon_device *rdev,
0118 u32 smc_start_address,
0119 const u8 *src, u32 byte_count, u32 limit)
0120 {
0121 int ret;
0122 u32 data, original_data, addr, extra_shift, t_byte, count, mask;
0123
0124 if ((smc_start_address + byte_count) > limit)
0125 return -EINVAL;
0126
0127 addr = smc_start_address;
0128 t_byte = addr & 3;
0129
0130
0131 if (t_byte != 0) {
0132 addr -= t_byte;
0133
0134 ret = kv_set_smc_sram_address(rdev, addr, limit);
0135 if (ret)
0136 return ret;
0137
0138 original_data = RREG32(SMC_IND_DATA_0);
0139
0140 data = 0;
0141 mask = 0;
0142 count = 4;
0143 while (count > 0) {
0144 if (t_byte > 0) {
0145 mask = (mask << 8) | 0xff;
0146 t_byte--;
0147 } else if (byte_count > 0) {
0148 data = (data << 8) + *src++;
0149 byte_count--;
0150 mask <<= 8;
0151 } else {
0152 data <<= 8;
0153 mask = (mask << 8) | 0xff;
0154 }
0155 count--;
0156 }
0157
0158 data |= original_data & mask;
0159
0160 ret = kv_set_smc_sram_address(rdev, addr, limit);
0161 if (ret)
0162 return ret;
0163
0164 WREG32(SMC_IND_DATA_0, data);
0165
0166 addr += 4;
0167 }
0168
0169 while (byte_count >= 4) {
0170
0171 data = (src[0] << 24) + (src[1] << 16) + (src[2] << 8) + src[3];
0172
0173 ret = kv_set_smc_sram_address(rdev, addr, limit);
0174 if (ret)
0175 return ret;
0176
0177 WREG32(SMC_IND_DATA_0, data);
0178
0179 src += 4;
0180 byte_count -= 4;
0181 addr += 4;
0182 }
0183
0184
0185 if (byte_count > 0) {
0186 data = 0;
0187
0188 ret = kv_set_smc_sram_address(rdev, addr, limit);
0189 if (ret)
0190 return ret;
0191
0192 original_data= RREG32(SMC_IND_DATA_0);
0193
0194 extra_shift = 8 * (4 - byte_count);
0195
0196 while (byte_count > 0) {
0197
0198 data = (data << 8) + *src++;
0199 byte_count--;
0200 }
0201
0202 data <<= extra_shift;
0203
0204 data |= (original_data & ~((~0UL) << extra_shift));
0205
0206 ret = kv_set_smc_sram_address(rdev, addr, limit);
0207 if (ret)
0208 return ret;
0209
0210 WREG32(SMC_IND_DATA_0, data);
0211 }
0212 return 0;
0213 }
0214