int si_copy_bytes_to_smc(struct radeon_device *rdev, u32 smc_start_address, const u8 *src, u32 byte_count, u32 limit) { int ret; u32 data, original_data, addr, extra_shift; if (smc_start_address & 3) return -EINVAL; if ((smc_start_address + byte_count) > limit) return -EINVAL; addr = smc_start_address; while (byte_count >= 4) { /* SMC address space is BE */ data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; ret = si_set_smc_sram_address(rdev, addr, limit); if (ret) return ret; WREG32(SMC_IND_DATA_0, data); src += 4; byte_count -= 4; addr += 4; } /* RMW for the final bytes */ if (byte_count > 0) { data = 0; ret = si_set_smc_sram_address(rdev, addr, limit); if (ret) return ret; original_data = RREG32(SMC_IND_DATA_0); extra_shift = 8 * (4 - byte_count); while (byte_count > 0) { /* SMC address space is BE */ data = (data << 8) + *src++; byte_count--; } data <<= extra_shift; data |= (original_data & ~((~0UL) << extra_shift)); ret = si_set_smc_sram_address(rdev, addr, limit); if (ret) return ret; WREG32(SMC_IND_DATA_0, data); } return 0; }
int si_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 value, u32 limit) { int ret; ret = si_set_smc_sram_address(rdev, smc_address, limit); if (ret) return ret; WREG32(SMC_IND_DATA_0, value); return 0; }
int si_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 *value, u32 limit) { int ret; ret = si_set_smc_sram_address(rdev, smc_address, limit); if (ret) return ret; *value = RREG32(SMC_IND_DATA_0); return 0; }
int si_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 value, u32 limit) { int ret; spin_lock(&rdev->smc_idx_lock); ret = si_set_smc_sram_address(rdev, smc_address, limit); if (ret == 0) WREG32(SMC_IND_DATA_0, value); spin_unlock(&rdev->smc_idx_lock); return ret; }
int amdgpu_si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, u32 value, u32 limit) { unsigned long flags; int ret; spin_lock_irqsave(&adev->smc_idx_lock, flags); ret = si_set_smc_sram_address(adev, smc_address, limit); if (ret == 0) WREG32(SMC_IND_DATA_0, value); spin_unlock_irqrestore(&adev->smc_idx_lock, flags); return ret; }
int si_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 *value, u32 limit) { unsigned long flags; int ret; spin_lock_irqsave(&rdev->smc_idx_lock, flags); ret = si_set_smc_sram_address(rdev, smc_address, limit); if (ret == 0) *value = RREG32(SMC_IND_DATA_0); spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); return ret; }
int amdgpu_si_copy_bytes_to_smc(struct amdgpu_device *adev, u32 smc_start_address, const u8 *src, u32 byte_count, u32 limit) { unsigned long flags; int ret = 0; u32 data, original_data, addr, extra_shift; if (smc_start_address & 3) return -EINVAL; if ((smc_start_address + byte_count) > limit) return -EINVAL; addr = smc_start_address; spin_lock_irqsave(&adev->smc_idx_lock, flags); while (byte_count >= 4) { /* SMC address space is BE */ data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; ret = si_set_smc_sram_address(adev, addr, limit); if (ret) goto done; WREG32(SMC_IND_DATA_0, data); src += 4; byte_count -= 4; addr += 4; } /* RMW for the final bytes */ if (byte_count > 0) { data = 0; ret = si_set_smc_sram_address(adev, addr, limit); if (ret) goto done; original_data = RREG32(SMC_IND_DATA_0); extra_shift = 8 * (4 - byte_count); while (byte_count > 0) { /* SMC address space is BE */ data = (data << 8) + *src++; byte_count--; } data <<= extra_shift; data |= (original_data & ~((~0UL) << extra_shift)); ret = si_set_smc_sram_address(adev, addr, limit); if (ret) goto done; WREG32(SMC_IND_DATA_0, data); } done: spin_unlock_irqrestore(&adev->smc_idx_lock, flags); return ret; }