Re: [PATCH v3 09/16] aspeed/smc: Add AST2700 support
On 4/16/24 11:18, Jamin Lin wrote: AST2700 fmc/spi controller's address decoding unit is 64KB and only bits [31:16] are used for decoding. Introduce seg_to_reg and reg_to_seg handlers for ast2700 fmc/spi controller. In addition, adds ast2700 fmc, spi0, spi1, and spi2 class init handler. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Thanks, C. --- hw/ssi/aspeed_smc.c | 222 +++- 1 file changed, 220 insertions(+), 2 deletions(-) diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index a67cac3d0f..e768e5463c 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -185,7 +185,7 @@ * 0: 4 bytes * 0x7F: 32M bytes * - * DMA length is from 1 byte to 32MB (AST2600, AST10x0) + * DMA length is from 1 byte to 32MB (AST2600, AST10x0 and AST2700) * 0: 1 byte * 0x1FF: 32M bytes */ @@ -670,7 +670,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = { .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 1, -.max_access_size = 4, +.max_access_size = 8, }, }; @@ -1951,6 +1951,220 @@ static const TypeInfo aspeed_1030_spi2_info = { .class_init = aspeed_1030_spi2_class_init, }; +/* + * The FMC Segment Registers of the AST2700 have a 64KB unit. + * Only bits [31:16] are used for decoding. + */ +#define AST2700_SEG_ADDR_MASK 0x + +static uint32_t aspeed_2700_smc_segment_to_reg(const AspeedSMCState *s, + const AspeedSegments *seg) +{ +uint32_t reg = 0; + +/* Disabled segments have a nil register */ +if (!seg->size) { +return 0; +} + +reg |= (seg->addr & AST2700_SEG_ADDR_MASK) >> 16; /* start offset */ +reg |= (seg->addr + seg->size - 1) & AST2700_SEG_ADDR_MASK; /* end offset */ +return reg; +} + +static void aspeed_2700_smc_reg_to_segment(const AspeedSMCState *s, + uint32_t reg, AspeedSegments *seg) +{ +uint32_t start_offset = (reg << 16) & AST2700_SEG_ADDR_MASK; +uint32_t end_offset = reg & AST2700_SEG_ADDR_MASK; +AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); + +if (reg) { +seg->addr = asc->flash_window_base + start_offset; +seg->size = end_offset + (64 * KiB) - start_offset; +} else { +seg->addr = asc->flash_window_base; +seg->size = 0; +} +} + +static const uint32_t aspeed_2700_fmc_resets[ASPEED_SMC_R_MAX] = { +[R_CONF] = (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0 | +CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1), +[R_CE_CTRL] = 0xaa00, +[R_CTRL0] = 0x406b0641, +[R_CTRL1] = 0x0400, +[R_CTRL2] = 0x0400, +[R_CTRL3] = 0x0400, +[R_SEG_ADDR0] = 0x0800, +[R_SEG_ADDR1] = 0x1800, +[R_SEG_ADDR2] = 0x, +[R_SEG_ADDR3] = 0x, +[R_DUMMY_DATA] = 0x0001, +[R_DMA_DRAM_ADDR_HIGH] = 0x, +[R_TIMINGS] = 0x007b, +}; + +static const AspeedSegments aspeed_2700_fmc_segments[] = { +{ 0x0, 128 * MiB }, /* start address is readonly */ +{ 128 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */ +{ 256 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */ +{ 0x0, 0 }, /* disabled */ +}; + +static void aspeed_2700_fmc_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); +AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass); + +dc->desc = "Aspeed 2700 FMC Controller"; +asc->r_conf= R_CONF; +asc->r_ce_ctrl = R_CE_CTRL; +asc->r_ctrl0 = R_CTRL0; +asc->r_timings = R_TIMINGS; +asc->nregs_timings = 3; +asc->conf_enable_w0= CONF_ENABLE_W0; +asc->cs_num_max= 3; +asc->segments = aspeed_2700_fmc_segments; +asc->segment_addr_mask = 0x; +asc->resets= aspeed_2700_fmc_resets; +asc->flash_window_base = 0x1; +asc->flash_window_size = 1 * GiB; +asc->features = ASPEED_SMC_FEATURE_DMA | + ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH; +asc->dma_flash_mask= 0x2FFC; +asc->dma_dram_mask = 0xFFFC; +asc->dma_start_length = 1; +asc->nregs = ASPEED_SMC_R_MAX; +asc->segment_to_reg= aspeed_2700_smc_segment_to_reg; +asc->reg_to_segment= aspeed_2700_smc_reg_to_segment; +asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; +} + +static const TypeInfo aspeed_2700_fmc_info = { +.name = "aspeed.fmc-ast2700", +.parent = TYPE_ASPEED_SMC, +.class_init = aspeed_2700_fmc_class_init, +}; + +static const AspeedSegments aspeed_2700_spi0_segments[] = { +{ 0x0, 128 * MiB }, /* start address is readonly */ +{ 128 * MiB, 128 * MiB }, /* start address is readonly */ +{ 0x0, 0 }, /* disabled */ +}; + +static void
[PATCH v3 09/16] aspeed/smc: Add AST2700 support
AST2700 fmc/spi controller's address decoding unit is 64KB and only bits [31:16] are used for decoding. Introduce seg_to_reg and reg_to_seg handlers for ast2700 fmc/spi controller. In addition, adds ast2700 fmc, spi0, spi1, and spi2 class init handler. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin --- hw/ssi/aspeed_smc.c | 222 +++- 1 file changed, 220 insertions(+), 2 deletions(-) diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index a67cac3d0f..e768e5463c 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -185,7 +185,7 @@ * 0: 4 bytes * 0x7F: 32M bytes * - * DMA length is from 1 byte to 32MB (AST2600, AST10x0) + * DMA length is from 1 byte to 32MB (AST2600, AST10x0 and AST2700) * 0: 1 byte * 0x1FF: 32M bytes */ @@ -670,7 +670,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = { .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 1, -.max_access_size = 4, +.max_access_size = 8, }, }; @@ -1951,6 +1951,220 @@ static const TypeInfo aspeed_1030_spi2_info = { .class_init = aspeed_1030_spi2_class_init, }; +/* + * The FMC Segment Registers of the AST2700 have a 64KB unit. + * Only bits [31:16] are used for decoding. + */ +#define AST2700_SEG_ADDR_MASK 0x + +static uint32_t aspeed_2700_smc_segment_to_reg(const AspeedSMCState *s, + const AspeedSegments *seg) +{ +uint32_t reg = 0; + +/* Disabled segments have a nil register */ +if (!seg->size) { +return 0; +} + +reg |= (seg->addr & AST2700_SEG_ADDR_MASK) >> 16; /* start offset */ +reg |= (seg->addr + seg->size - 1) & AST2700_SEG_ADDR_MASK; /* end offset */ +return reg; +} + +static void aspeed_2700_smc_reg_to_segment(const AspeedSMCState *s, + uint32_t reg, AspeedSegments *seg) +{ +uint32_t start_offset = (reg << 16) & AST2700_SEG_ADDR_MASK; +uint32_t end_offset = reg & AST2700_SEG_ADDR_MASK; +AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); + +if (reg) { +seg->addr = asc->flash_window_base + start_offset; +seg->size = end_offset + (64 * KiB) - start_offset; +} else { +seg->addr = asc->flash_window_base; +seg->size = 0; +} +} + +static const uint32_t aspeed_2700_fmc_resets[ASPEED_SMC_R_MAX] = { +[R_CONF] = (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0 | +CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1), +[R_CE_CTRL] = 0xaa00, +[R_CTRL0] = 0x406b0641, +[R_CTRL1] = 0x0400, +[R_CTRL2] = 0x0400, +[R_CTRL3] = 0x0400, +[R_SEG_ADDR0] = 0x0800, +[R_SEG_ADDR1] = 0x1800, +[R_SEG_ADDR2] = 0x, +[R_SEG_ADDR3] = 0x, +[R_DUMMY_DATA] = 0x0001, +[R_DMA_DRAM_ADDR_HIGH] = 0x, +[R_TIMINGS] = 0x007b, +}; + +static const AspeedSegments aspeed_2700_fmc_segments[] = { +{ 0x0, 128 * MiB }, /* start address is readonly */ +{ 128 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */ +{ 256 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */ +{ 0x0, 0 }, /* disabled */ +}; + +static void aspeed_2700_fmc_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); +AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass); + +dc->desc = "Aspeed 2700 FMC Controller"; +asc->r_conf= R_CONF; +asc->r_ce_ctrl = R_CE_CTRL; +asc->r_ctrl0 = R_CTRL0; +asc->r_timings = R_TIMINGS; +asc->nregs_timings = 3; +asc->conf_enable_w0= CONF_ENABLE_W0; +asc->cs_num_max= 3; +asc->segments = aspeed_2700_fmc_segments; +asc->segment_addr_mask = 0x; +asc->resets= aspeed_2700_fmc_resets; +asc->flash_window_base = 0x1; +asc->flash_window_size = 1 * GiB; +asc->features = ASPEED_SMC_FEATURE_DMA | + ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH; +asc->dma_flash_mask= 0x2FFC; +asc->dma_dram_mask = 0xFFFC; +asc->dma_start_length = 1; +asc->nregs = ASPEED_SMC_R_MAX; +asc->segment_to_reg= aspeed_2700_smc_segment_to_reg; +asc->reg_to_segment= aspeed_2700_smc_reg_to_segment; +asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; +} + +static const TypeInfo aspeed_2700_fmc_info = { +.name = "aspeed.fmc-ast2700", +.parent = TYPE_ASPEED_SMC, +.class_init = aspeed_2700_fmc_class_init, +}; + +static const AspeedSegments aspeed_2700_spi0_segments[] = { +{ 0x0, 128 * MiB }, /* start address is readonly */ +{ 128 * MiB, 128 * MiB }, /* start address is readonly */ +{ 0x0, 0 }, /* disabled */ +}; + +static void aspeed_2700_spi0_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); +AspeedSMCClass *asc =