1 /* 2 * Copyright 2011 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 * Authors: Alex Deucher 23 */ 24 25 #include <linux/firmware.h> 26 #include "drmP.h" 27 #include "radeon.h" 28 #include "sid.h" 29 #include "ppsmc.h" 30 #include "radeon_ucode.h" 31 #include "sislands_smc.h" 32 33 static int si_set_smc_sram_address(struct radeon_device *rdev, 34 u32 smc_address, u32 limit) 35 { 36 if (smc_address & 3) 37 return -EINVAL; 38 if ((smc_address + 3) > limit) 39 return -EINVAL; 40 41 WREG32(SMC_IND_INDEX_0, smc_address); 42 WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); 43 44 return 0; 45 } 46 47 int si_copy_bytes_to_smc(struct radeon_device *rdev, 48 u32 smc_start_address, 49 const u8 *src, u32 byte_count, u32 limit) 50 { 51 unsigned long flags; 52 int ret = 0; 53 u32 data, original_data, addr, extra_shift; 54 55 if (smc_start_address & 3) 56 return -EINVAL; 57 if ((smc_start_address + byte_count) > limit) 58 return -EINVAL; 59 60 addr = smc_start_address; 61 62 spin_lock_irqsave(&rdev->smc_idx_lock, flags); 63 while (byte_count >= 4) { 64 /* SMC address space is BE */ 65 data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; 66 67 ret = si_set_smc_sram_address(rdev, addr, limit); 68 if (ret) 69 goto done; 70 71 WREG32(SMC_IND_DATA_0, data); 72 73 src += 4; 74 byte_count -= 4; 75 addr += 4; 76 } 77 78 /* RMW for the final bytes */ 79 if (byte_count > 0) { 80 data = 0; 81 82 ret = si_set_smc_sram_address(rdev, addr, limit); 83 if (ret) 84 goto done; 85 86 original_data = RREG32(SMC_IND_DATA_0); 87 88 extra_shift = 8 * (4 - byte_count); 89 90 while (byte_count > 0) { 91 /* SMC address space is BE */ 92 data = (data << 8) + *src++; 93 byte_count--; 94 } 95 96 data <<= extra_shift; 97 98 data |= (original_data & ~((~0UL) << extra_shift)); 99 100 ret = si_set_smc_sram_address(rdev, addr, limit); 101 if (ret) 102 goto done; 103 104 WREG32(SMC_IND_DATA_0, data); 105 } 106 107 done: 108 spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); 109 110 return ret; 111 } 112 113 void si_start_smc(struct radeon_device *rdev) 114 { 115 u32 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL); 116 117 tmp &= ~RST_REG; 118 119 WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); 120 } 121 122 void si_reset_smc(struct radeon_device *rdev) 123 { 124 u32 tmp; 125 126 RREG32(CB_CGTT_SCLK_CTRL); 127 RREG32(CB_CGTT_SCLK_CTRL); 128 RREG32(CB_CGTT_SCLK_CTRL); 129 RREG32(CB_CGTT_SCLK_CTRL); 130 131 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL); 132 tmp |= RST_REG; 133 WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); 134 } 135 136 int si_program_jump_on_start(struct radeon_device *rdev) 137 { 138 static u8 data[] = { 0x0E, 0x00, 0x40, 0x40 }; 139 140 return si_copy_bytes_to_smc(rdev, 0x0, data, 4, sizeof(data)+1); 141 } 142 143 void si_stop_smc_clock(struct radeon_device *rdev) 144 { 145 u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); 146 147 tmp |= CK_DISABLE; 148 149 WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp); 150 } 151 152 void si_start_smc_clock(struct radeon_device *rdev) 153 { 154 u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); 155 156 tmp &= ~CK_DISABLE; 157 158 WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp); 159 } 160 161 bool si_is_smc_running(struct radeon_device *rdev) 162 { 163 u32 rst = RREG32_SMC(SMC_SYSCON_RESET_CNTL); 164 u32 clk = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); 165 166 if (!(rst & RST_REG) && !(clk & CK_DISABLE)) 167 return true; 168 169 return false; 170 } 171 172 PPSMC_Result si_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg) 173 { 174 u32 tmp; 175 int i; 176 177 if (!si_is_smc_running(rdev)) 178 return PPSMC_Result_Failed; 179 180 WREG32(SMC_MESSAGE_0, msg); 181 182 for (i = 0; i < rdev->usec_timeout; i++) { 183 tmp = RREG32(SMC_RESP_0); 184 if (tmp != 0) 185 break; 186 udelay(1); 187 } 188 tmp = RREG32(SMC_RESP_0); 189 190 return (PPSMC_Result)tmp; 191 } 192 193 PPSMC_Result si_wait_for_smc_inactive(struct radeon_device *rdev) 194 { 195 u32 tmp; 196 int i; 197 198 if (!si_is_smc_running(rdev)) 199 return PPSMC_Result_OK; 200 201 for (i = 0; i < rdev->usec_timeout; i++) { 202 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); 203 if ((tmp & CKEN) == 0) 204 break; 205 udelay(1); 206 } 207 208 return PPSMC_Result_OK; 209 } 210 211 int si_load_smc_ucode(struct radeon_device *rdev, u32 limit) 212 { 213 unsigned long flags; 214 u32 ucode_start_address; 215 u32 ucode_size; 216 const u8 *src; 217 u32 data; 218 219 if (!rdev->smc_fw) 220 return -EINVAL; 221 222 switch (rdev->family) { 223 case CHIP_TAHITI: 224 ucode_start_address = TAHITI_SMC_UCODE_START; 225 ucode_size = TAHITI_SMC_UCODE_SIZE; 226 break; 227 case CHIP_PITCAIRN: 228 ucode_start_address = PITCAIRN_SMC_UCODE_START; 229 ucode_size = PITCAIRN_SMC_UCODE_SIZE; 230 break; 231 case CHIP_VERDE: 232 ucode_start_address = VERDE_SMC_UCODE_START; 233 ucode_size = VERDE_SMC_UCODE_SIZE; 234 break; 235 case CHIP_OLAND: 236 ucode_start_address = OLAND_SMC_UCODE_START; 237 ucode_size = OLAND_SMC_UCODE_SIZE; 238 break; 239 case CHIP_HAINAN: 240 ucode_start_address = HAINAN_SMC_UCODE_START; 241 ucode_size = HAINAN_SMC_UCODE_SIZE; 242 break; 243 default: 244 DRM_ERROR("unknown asic in smc ucode loader\n"); 245 BUG(); 246 } 247 248 if (ucode_size & 3) 249 return -EINVAL; 250 251 src = (const u8 *)rdev->smc_fw->data; 252 spin_lock_irqsave(&rdev->smc_idx_lock, flags); 253 WREG32(SMC_IND_INDEX_0, ucode_start_address); 254 WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0); 255 while (ucode_size >= 4) { 256 /* SMC address space is BE */ 257 data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; 258 259 WREG32(SMC_IND_DATA_0, data); 260 261 src += 4; 262 ucode_size -= 4; 263 } 264 WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); 265 spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); 266 267 return 0; 268 } 269 270 int si_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, 271 u32 *value, u32 limit) 272 { 273 unsigned long flags; 274 int ret; 275 276 spin_lock_irqsave(&rdev->smc_idx_lock, flags); 277 ret = si_set_smc_sram_address(rdev, smc_address, limit); 278 if (ret == 0) 279 *value = RREG32(SMC_IND_DATA_0); 280 spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); 281 282 return ret; 283 } 284 285 int si_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, 286 u32 value, u32 limit) 287 { 288 unsigned long flags; 289 int ret; 290 291 spin_lock_irqsave(&rdev->smc_idx_lock, flags); 292 ret = si_set_smc_sram_address(rdev, smc_address, limit); 293 if (ret == 0) 294 WREG32(SMC_IND_DATA_0, value); 295 spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); 296 297 return ret; 298 } 299