int ci_copy_bytes_to_smc(struct radeon_device *rdev, u32 smc_start_address, const u8 *src, u32 byte_count, u32 limit) { u32 data, original_data; u32 addr; u32 extra_shift; int ret; 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 = ci_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 = ci_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) { data = (data << 8) + *src++; byte_count--; } data <<= extra_shift; data |= (original_data & ~((~0UL) << extra_shift)); ret = ci_set_smc_sram_address(rdev, addr, limit); if (ret) return ret; WREG32(SMC_IND_DATA_0, data); } return 0; }
int ci_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 *value, u32 limit) { int ret; ret = ci_set_smc_sram_address(rdev, smc_address, limit); if (ret) return ret; *value = RREG32(SMC_IND_DATA_0); return 0; }
int ci_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 value, u32 limit) { int ret; ret = ci_set_smc_sram_address(rdev, smc_address, limit); if (ret) return ret; WREG32(SMC_IND_DATA_0, value); return 0; }
int ci_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 value, u32 limit) { int ret; spin_lock(&rdev->smc_idx_lock); ret = ci_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 ci_write_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 = ci_set_smc_sram_address(rdev, smc_address, limit); if (ret == 0) WREG32(SMC_IND_DATA_0, value); spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); return ret; }