1*0cdd5a0dSLikun Gao /* 2*0cdd5a0dSLikun Gao * Copyright 2026 Advanced Micro Devices, Inc. 3*0cdd5a0dSLikun Gao * 4*0cdd5a0dSLikun Gao * Permission is hereby granted, free of charge, to any person obtaining a 5*0cdd5a0dSLikun Gao * copy of this software and associated documentation files (the "Software"), 6*0cdd5a0dSLikun Gao * to deal in the Software without restriction, including without limitation 7*0cdd5a0dSLikun Gao * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*0cdd5a0dSLikun Gao * and/or sell copies of the Software, and to permit persons to whom the 9*0cdd5a0dSLikun Gao * Software is furnished to do so, subject to the following conditions: 10*0cdd5a0dSLikun Gao * 11*0cdd5a0dSLikun Gao * The above copyright notice and this permission notice shall be included in 12*0cdd5a0dSLikun Gao * all copies or substantial portions of the Software. 13*0cdd5a0dSLikun Gao * 14*0cdd5a0dSLikun Gao * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15*0cdd5a0dSLikun Gao * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16*0cdd5a0dSLikun Gao * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17*0cdd5a0dSLikun Gao * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18*0cdd5a0dSLikun Gao * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19*0cdd5a0dSLikun Gao * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20*0cdd5a0dSLikun Gao * OTHER DEALINGS IN THE SOFTWARE. 21*0cdd5a0dSLikun Gao * 22*0cdd5a0dSLikun Gao */ 23*0cdd5a0dSLikun Gao 24*0cdd5a0dSLikun Gao #include <linux/delay.h> 25*0cdd5a0dSLikun Gao #include "amdgpu.h" 26*0cdd5a0dSLikun Gao #include "lsdma_v7_1.h" 27*0cdd5a0dSLikun Gao #include "amdgpu_lsdma.h" 28*0cdd5a0dSLikun Gao 29*0cdd5a0dSLikun Gao #include "lsdma/lsdma_7_1_0_offset.h" 30*0cdd5a0dSLikun Gao #include "lsdma/lsdma_7_1_0_sh_mask.h" 31*0cdd5a0dSLikun Gao 32*0cdd5a0dSLikun Gao static int lsdma_v7_1_wait_pio_status(struct amdgpu_device *adev) 33*0cdd5a0dSLikun Gao { 34*0cdd5a0dSLikun Gao return amdgpu_lsdma_wait_for(adev, SOC15_REG_OFFSET(LSDMA, 0, regLSDMA_PIO_STATUS), 35*0cdd5a0dSLikun Gao LSDMA_PIO_STATUS__PIO_IDLE_MASK | LSDMA_PIO_STATUS__PIO_FIFO_EMPTY_MASK, 36*0cdd5a0dSLikun Gao LSDMA_PIO_STATUS__PIO_IDLE_MASK | LSDMA_PIO_STATUS__PIO_FIFO_EMPTY_MASK); 37*0cdd5a0dSLikun Gao } 38*0cdd5a0dSLikun Gao 39*0cdd5a0dSLikun Gao static int lsdma_v7_1_copy_mem(struct amdgpu_device *adev, 40*0cdd5a0dSLikun Gao uint64_t src_addr, 41*0cdd5a0dSLikun Gao uint64_t dst_addr, 42*0cdd5a0dSLikun Gao uint64_t size) 43*0cdd5a0dSLikun Gao { 44*0cdd5a0dSLikun Gao int ret; 45*0cdd5a0dSLikun Gao uint32_t tmp; 46*0cdd5a0dSLikun Gao 47*0cdd5a0dSLikun Gao WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_SRC_ADDR_LO, lower_32_bits(src_addr)); 48*0cdd5a0dSLikun Gao WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_SRC_ADDR_HI, upper_32_bits(src_addr)); 49*0cdd5a0dSLikun Gao 50*0cdd5a0dSLikun Gao WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_LO, lower_32_bits(dst_addr)); 51*0cdd5a0dSLikun Gao WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_HI, upper_32_bits(dst_addr)); 52*0cdd5a0dSLikun Gao 53*0cdd5a0dSLikun Gao WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_CONTROL, 0x0); 54*0cdd5a0dSLikun Gao 55*0cdd5a0dSLikun Gao tmp = RREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND); 56*0cdd5a0dSLikun Gao tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, COUNT, size); 57*0cdd5a0dSLikun Gao tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, RAW_WAIT, 0); 58*0cdd5a0dSLikun Gao tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, CONSTANT_FILL, 0); 59*0cdd5a0dSLikun Gao WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND, tmp); 60*0cdd5a0dSLikun Gao 61*0cdd5a0dSLikun Gao ret = lsdma_v7_1_wait_pio_status(adev); 62*0cdd5a0dSLikun Gao if (ret) 63*0cdd5a0dSLikun Gao dev_err(adev->dev, "LSDMA PIO failed to copy memory!\n"); 64*0cdd5a0dSLikun Gao 65*0cdd5a0dSLikun Gao return ret; 66*0cdd5a0dSLikun Gao } 67*0cdd5a0dSLikun Gao 68*0cdd5a0dSLikun Gao static int lsdma_v7_1_fill_mem(struct amdgpu_device *adev, 69*0cdd5a0dSLikun Gao uint64_t dst_addr, 70*0cdd5a0dSLikun Gao uint32_t data, 71*0cdd5a0dSLikun Gao uint64_t size) 72*0cdd5a0dSLikun Gao { 73*0cdd5a0dSLikun Gao int ret; 74*0cdd5a0dSLikun Gao uint32_t tmp; 75*0cdd5a0dSLikun Gao 76*0cdd5a0dSLikun Gao WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_CONSTFILL_DATA, data); 77*0cdd5a0dSLikun Gao 78*0cdd5a0dSLikun Gao WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_LO, lower_32_bits(dst_addr)); 79*0cdd5a0dSLikun Gao WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_HI, upper_32_bits(dst_addr)); 80*0cdd5a0dSLikun Gao 81*0cdd5a0dSLikun Gao WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_CONTROL, 0x0); 82*0cdd5a0dSLikun Gao 83*0cdd5a0dSLikun Gao tmp = RREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND); 84*0cdd5a0dSLikun Gao tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, COUNT, size); 85*0cdd5a0dSLikun Gao tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, RAW_WAIT, 0); 86*0cdd5a0dSLikun Gao tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, CONSTANT_FILL, 1); 87*0cdd5a0dSLikun Gao WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND, tmp); 88*0cdd5a0dSLikun Gao 89*0cdd5a0dSLikun Gao ret = lsdma_v7_1_wait_pio_status(adev); 90*0cdd5a0dSLikun Gao if (ret) 91*0cdd5a0dSLikun Gao dev_err(adev->dev, "LSDMA PIO failed to fill memory!\n"); 92*0cdd5a0dSLikun Gao 93*0cdd5a0dSLikun Gao return ret; 94*0cdd5a0dSLikun Gao } 95*0cdd5a0dSLikun Gao 96*0cdd5a0dSLikun Gao const struct amdgpu_lsdma_funcs lsdma_v7_1_funcs = { 97*0cdd5a0dSLikun Gao .copy_mem = lsdma_v7_1_copy_mem, 98*0cdd5a0dSLikun Gao .fill_mem = lsdma_v7_1_fill_mem, 99*0cdd5a0dSLikun Gao }; 100