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 <linux/firmware.h>
0026
0027 #include "radeon.h"
0028 #include "cikd.h"
0029 #include "ppsmc.h"
0030 #include "radeon_ucode.h"
0031 #include "ci_dpm.h"
0032
0033 static int ci_set_smc_sram_address(struct radeon_device *rdev,
0034 u32 smc_address, u32 limit)
0035 {
0036 if (smc_address & 3)
0037 return -EINVAL;
0038 if ((smc_address + 3) > limit)
0039 return -EINVAL;
0040
0041 WREG32(SMC_IND_INDEX_0, smc_address);
0042 WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
0043
0044 return 0;
0045 }
0046
0047 int ci_copy_bytes_to_smc(struct radeon_device *rdev,
0048 u32 smc_start_address,
0049 const u8 *src, u32 byte_count, u32 limit)
0050 {
0051 unsigned long flags;
0052 u32 data, original_data;
0053 u32 addr;
0054 u32 extra_shift;
0055 int ret = 0;
0056
0057 if (smc_start_address & 3)
0058 return -EINVAL;
0059 if ((smc_start_address + byte_count) > limit)
0060 return -EINVAL;
0061
0062 addr = smc_start_address;
0063
0064 spin_lock_irqsave(&rdev->smc_idx_lock, flags);
0065 while (byte_count >= 4) {
0066
0067 data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
0068
0069 ret = ci_set_smc_sram_address(rdev, addr, limit);
0070 if (ret)
0071 goto done;
0072
0073 WREG32(SMC_IND_DATA_0, data);
0074
0075 src += 4;
0076 byte_count -= 4;
0077 addr += 4;
0078 }
0079
0080
0081 if (byte_count > 0) {
0082 data = 0;
0083
0084 ret = ci_set_smc_sram_address(rdev, addr, limit);
0085 if (ret)
0086 goto done;
0087
0088 original_data = RREG32(SMC_IND_DATA_0);
0089
0090 extra_shift = 8 * (4 - byte_count);
0091
0092 while (byte_count > 0) {
0093 data = (data << 8) + *src++;
0094 byte_count--;
0095 }
0096
0097 data <<= extra_shift;
0098
0099 data |= (original_data & ~((~0UL) << extra_shift));
0100
0101 ret = ci_set_smc_sram_address(rdev, addr, limit);
0102 if (ret)
0103 goto done;
0104
0105 WREG32(SMC_IND_DATA_0, data);
0106 }
0107
0108 done:
0109 spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
0110
0111 return ret;
0112 }
0113
0114 void ci_start_smc(struct radeon_device *rdev)
0115 {
0116 u32 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL);
0117
0118 tmp &= ~RST_REG;
0119 WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp);
0120 }
0121
0122 void ci_reset_smc(struct radeon_device *rdev)
0123 {
0124 u32 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL);
0125
0126 tmp |= RST_REG;
0127 WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp);
0128 }
0129
0130 int ci_program_jump_on_start(struct radeon_device *rdev)
0131 {
0132 static const u8 data[] = { 0xE0, 0x00, 0x80, 0x40 };
0133
0134 return ci_copy_bytes_to_smc(rdev, 0x0, data, 4, sizeof(data)+1);
0135 }
0136
0137 void ci_stop_smc_clock(struct radeon_device *rdev)
0138 {
0139 u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
0140
0141 tmp |= CK_DISABLE;
0142
0143 WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp);
0144 }
0145
0146 void ci_start_smc_clock(struct radeon_device *rdev)
0147 {
0148 u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
0149
0150 tmp &= ~CK_DISABLE;
0151
0152 WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp);
0153 }
0154
0155 bool ci_is_smc_running(struct radeon_device *rdev)
0156 {
0157 u32 clk = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
0158 u32 pc_c = RREG32_SMC(SMC_PC_C);
0159
0160 if (!(clk & CK_DISABLE) && (0x20100 <= pc_c))
0161 return true;
0162
0163 return false;
0164 }
0165
0166 #if 0
0167 PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev)
0168 {
0169 u32 tmp;
0170 int i;
0171
0172 if (!ci_is_smc_running(rdev))
0173 return PPSMC_Result_OK;
0174
0175 for (i = 0; i < rdev->usec_timeout; i++) {
0176 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
0177 if ((tmp & CKEN) == 0)
0178 break;
0179 udelay(1);
0180 }
0181
0182 return PPSMC_Result_OK;
0183 }
0184 #endif
0185
0186 int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
0187 {
0188 unsigned long flags;
0189 u32 ucode_start_address;
0190 u32 ucode_size;
0191 const u8 *src;
0192 u32 data;
0193
0194 if (!rdev->smc_fw)
0195 return -EINVAL;
0196
0197 if (rdev->new_fw) {
0198 const struct smc_firmware_header_v1_0 *hdr =
0199 (const struct smc_firmware_header_v1_0 *)rdev->smc_fw->data;
0200
0201 radeon_ucode_print_smc_hdr(&hdr->header);
0202
0203 ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
0204 ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
0205 src = (const u8 *)
0206 (rdev->smc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
0207 } else {
0208 switch (rdev->family) {
0209 case CHIP_BONAIRE:
0210 ucode_start_address = BONAIRE_SMC_UCODE_START;
0211 ucode_size = BONAIRE_SMC_UCODE_SIZE;
0212 break;
0213 case CHIP_HAWAII:
0214 ucode_start_address = HAWAII_SMC_UCODE_START;
0215 ucode_size = HAWAII_SMC_UCODE_SIZE;
0216 break;
0217 default:
0218 DRM_ERROR("unknown asic in smc ucode loader\n");
0219 BUG();
0220 }
0221
0222 src = (const u8 *)rdev->smc_fw->data;
0223 }
0224
0225 if (ucode_size & 3)
0226 return -EINVAL;
0227
0228 spin_lock_irqsave(&rdev->smc_idx_lock, flags);
0229 WREG32(SMC_IND_INDEX_0, ucode_start_address);
0230 WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
0231 while (ucode_size >= 4) {
0232
0233 data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
0234
0235 WREG32(SMC_IND_DATA_0, data);
0236
0237 src += 4;
0238 ucode_size -= 4;
0239 }
0240 WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
0241 spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
0242
0243 return 0;
0244 }
0245
0246 int ci_read_smc_sram_dword(struct radeon_device *rdev,
0247 u32 smc_address, u32 *value, u32 limit)
0248 {
0249 unsigned long flags;
0250 int ret;
0251
0252 spin_lock_irqsave(&rdev->smc_idx_lock, flags);
0253 ret = ci_set_smc_sram_address(rdev, smc_address, limit);
0254 if (ret == 0)
0255 *value = RREG32(SMC_IND_DATA_0);
0256 spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
0257
0258 return ret;
0259 }
0260
0261 int ci_write_smc_sram_dword(struct radeon_device *rdev,
0262 u32 smc_address, u32 value, u32 limit)
0263 {
0264 unsigned long flags;
0265 int ret;
0266
0267 spin_lock_irqsave(&rdev->smc_idx_lock, flags);
0268 ret = ci_set_smc_sram_address(rdev, smc_address, limit);
0269 if (ret == 0)
0270 WREG32(SMC_IND_DATA_0, value);
0271 spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
0272
0273 return ret;
0274 }