aspeed/smc: support 64 bits dma dram address
AST2700 support the maximum dram size is 8GiB and has a "DMA DRAM Side Address High Part(0x7C)" register to support 64 bits dma dram address. Add helper routines functions to compute the dma dram address, new features and update trace-event to support 64 bits dram address. Signed-off-by: Troy Lee <troy_lee@aspeedtech.com> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com>
This commit is contained in:
parent
3a6c0f0e9d
commit
6330be8da4
@ -132,6 +132,9 @@
|
||||
#define FMC_WDT2_CTRL_BOOT_SOURCE BIT(4) /* O: primary 1: alternate */
|
||||
#define FMC_WDT2_CTRL_EN BIT(0)
|
||||
|
||||
/* DMA DRAM Side Address High Part (AST2700) */
|
||||
#define R_DMA_DRAM_ADDR_HIGH (0x7c / 4)
|
||||
|
||||
/* DMA Control/Status Register */
|
||||
#define R_DMA_CTRL (0x80 / 4)
|
||||
#define DMA_CTRL_REQUEST (1 << 31)
|
||||
@ -187,6 +190,7 @@
|
||||
* 0x1FFFFFF: 32M bytes
|
||||
*/
|
||||
#define DMA_DRAM_ADDR(asc, val) ((val) & (asc)->dma_dram_mask)
|
||||
#define DMA_DRAM_ADDR_HIGH(val) ((val) & 0xf)
|
||||
#define DMA_FLASH_ADDR(asc, val) ((val) & (asc)->dma_flash_mask)
|
||||
#define DMA_LENGTH(val) ((val) & 0x01FFFFFF)
|
||||
|
||||
@ -207,6 +211,7 @@ static const AspeedSegments aspeed_2500_spi2_segments[];
|
||||
#define ASPEED_SMC_FEATURE_DMA 0x1
|
||||
#define ASPEED_SMC_FEATURE_DMA_GRANT 0x2
|
||||
#define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4
|
||||
#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08
|
||||
|
||||
static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc)
|
||||
{
|
||||
@ -218,6 +223,11 @@ static inline bool aspeed_smc_has_wdt_control(const AspeedSMCClass *asc)
|
||||
return !!(asc->features & ASPEED_SMC_FEATURE_WDT_CONTROL);
|
||||
}
|
||||
|
||||
static inline bool aspeed_smc_has_dma64(const AspeedSMCClass *asc)
|
||||
{
|
||||
return !!(asc->features & ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH);
|
||||
}
|
||||
|
||||
#define aspeed_smc_error(fmt, ...) \
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__)
|
||||
|
||||
@ -747,6 +757,8 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
(aspeed_smc_has_dma(asc) && addr == R_DMA_CTRL) ||
|
||||
(aspeed_smc_has_dma(asc) && addr == R_DMA_FLASH_ADDR) ||
|
||||
(aspeed_smc_has_dma(asc) && addr == R_DMA_DRAM_ADDR) ||
|
||||
(aspeed_smc_has_dma(asc) && aspeed_smc_has_dma64(asc) &&
|
||||
addr == R_DMA_DRAM_ADDR_HIGH) ||
|
||||
(aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) ||
|
||||
(aspeed_smc_has_dma(asc) && addr == R_DMA_CHECKSUM) ||
|
||||
(addr >= R_SEG_ADDR0 &&
|
||||
@ -847,6 +859,12 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState *s)
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t aspeed_smc_dma_dram_addr(AspeedSMCState *s)
|
||||
{
|
||||
return s->regs[R_DMA_DRAM_ADDR] |
|
||||
((uint64_t) s->regs[R_DMA_DRAM_ADDR_HIGH] << 32);
|
||||
}
|
||||
|
||||
static uint32_t aspeed_smc_dma_len(AspeedSMCState *s)
|
||||
{
|
||||
AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
|
||||
@ -903,24 +921,34 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
|
||||
|
||||
static void aspeed_smc_dma_rw(AspeedSMCState *s)
|
||||
{
|
||||
AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
|
||||
uint64_t dma_dram_offset;
|
||||
uint64_t dma_dram_addr;
|
||||
MemTxResult result;
|
||||
uint32_t dma_len;
|
||||
uint32_t data;
|
||||
|
||||
dma_len = aspeed_smc_dma_len(s);
|
||||
dma_dram_addr = aspeed_smc_dma_dram_addr(s);
|
||||
|
||||
if (aspeed_smc_has_dma64(asc)) {
|
||||
dma_dram_offset = dma_dram_addr - s->dram_base;
|
||||
} else {
|
||||
dma_dram_offset = dma_dram_addr;
|
||||
}
|
||||
|
||||
trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ?
|
||||
"write" : "read",
|
||||
s->regs[R_DMA_FLASH_ADDR],
|
||||
s->regs[R_DMA_DRAM_ADDR],
|
||||
dma_dram_offset,
|
||||
dma_len);
|
||||
while (dma_len) {
|
||||
if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
|
||||
data = address_space_ldl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR],
|
||||
data = address_space_ldl_le(&s->dram_as, dma_dram_offset,
|
||||
MEMTXATTRS_UNSPECIFIED, &result);
|
||||
if (result != MEMTX_OK) {
|
||||
aspeed_smc_error("DRAM read failed @%08x",
|
||||
s->regs[R_DMA_DRAM_ADDR]);
|
||||
aspeed_smc_error("DRAM read failed @%" PRIx64,
|
||||
dma_dram_offset);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -940,11 +968,11 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
|
||||
return;
|
||||
}
|
||||
|
||||
address_space_stl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR],
|
||||
address_space_stl_le(&s->dram_as, dma_dram_offset,
|
||||
data, MEMTXATTRS_UNSPECIFIED, &result);
|
||||
if (result != MEMTX_OK) {
|
||||
aspeed_smc_error("DRAM write failed @%08x",
|
||||
s->regs[R_DMA_DRAM_ADDR]);
|
||||
aspeed_smc_error("DRAM write failed @%" PRIx64,
|
||||
dma_dram_offset);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -953,8 +981,12 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
|
||||
* When the DMA is on-going, the DMA registers are updated
|
||||
* with the current working addresses and length.
|
||||
*/
|
||||
dma_dram_offset += 4;
|
||||
dma_dram_addr += 4;
|
||||
|
||||
s->regs[R_DMA_DRAM_ADDR_HIGH] = dma_dram_addr >> 32;
|
||||
s->regs[R_DMA_DRAM_ADDR] = dma_dram_addr & 0xffffffff;
|
||||
s->regs[R_DMA_FLASH_ADDR] += 4;
|
||||
s->regs[R_DMA_DRAM_ADDR] += 4;
|
||||
dma_len -= 4;
|
||||
s->regs[R_DMA_LEN] = dma_len;
|
||||
s->regs[R_DMA_CHECKSUM] += data;
|
||||
@ -1107,6 +1139,9 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
|
||||
} else if (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN &&
|
||||
aspeed_smc_dma_granted(s)) {
|
||||
s->regs[addr] = DMA_LENGTH(value);
|
||||
} else if (aspeed_smc_has_dma(asc) && aspeed_smc_has_dma64(asc) &&
|
||||
addr == R_DMA_DRAM_ADDR_HIGH) {
|
||||
s->regs[addr] = DMA_DRAM_ADDR_HIGH(value);
|
||||
} else {
|
||||
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
|
||||
__func__, addr);
|
||||
|
@ -6,7 +6,7 @@ aspeed_smc_do_snoop(int cs, int index, int dummies, int data) "CS%d index:0x%x d
|
||||
aspeed_smc_flash_write(int cs, uint64_t addr, uint32_t size, uint64_t data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
|
||||
aspeed_smc_read(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
|
||||
aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
|
||||
aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint32_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%08x size:0x%08x"
|
||||
aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint64_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%" PRIx64 " size:0x%08x"
|
||||
aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
|
||||
aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user