On 09/18/2018 08:54 PM, Peter Maydell wrote: > On 31 August 2018 at 11:38, Cédric Le Goater <c...@kaod.org> wrote: >> When doing calibration, the SPI clock rate in the CE0 Control Register >> and the read delay cycles in the Read Timing Compensation Register are >> replaced by bit[11:4] of the DMA Control Register. >> >> Signed-off-by: Cédric Le Goater <c...@kaod.org> >> --- >> hw/ssi/aspeed_smc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 54 insertions(+) >> >> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c >> index 534faec4c111..983066f5ad1d 100644 >> --- a/hw/ssi/aspeed_smc.c >> +++ b/hw/ssi/aspeed_smc.c >> @@ -695,6 +695,56 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr >> addr, unsigned int size) >> } >> } >> >> +static uint8_t aspeed_smc_hclk_divisor(uint8_t hclk_mask) >> +{ >> + /* HCLK/1 .. HCLK/16 */ >> + const uint8_t hclk_divisors[] = { >> + 15, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 0 >> + }; >> + int i; >> + >> + for (i = 0; i < ARRAY_SIZE(hclk_divisors); i++) { >> + if (hclk_mask == hclk_divisors[i]) { >> + return i + 1; >> + } >> + } >> + >> + qemu_log_mask(LOG_GUEST_ERROR, "invalid HCLK mask %x", hclk_mask); >> + return 0; >> +} >> + >> +/* >> + * When doing calibration, the SPI clock rate in the CE0 Control >> + * Register and the read delay cycles in the Read Timing >> + * Compensation Register are replaced by bit[11:4] of the DMA >> + * Control Register. >> + */ >> +static void aspeed_smc_dma_calibration(AspeedSMCState *s) >> +{ >> + uint8_t delay = >> + (s->regs[R_DMA_CTRL] >> DMA_CTRL_DELAY_SHIFT) & DMA_CTRL_DELAY_MASK; >> + uint8_t hclk_mask = >> + (s->regs[R_DMA_CTRL] >> DMA_CTRL_FREQ_SHIFT) & DMA_CTRL_FREQ_MASK; >> + uint8_t hclk_div = aspeed_smc_hclk_divisor(hclk_mask); >> + uint32_t hclk_shift = (hclk_div - 1) << 2; >> + uint8_t cs; >> + >> + /* Only HCLK/1 - HCLK/5 have tunable delays */ >> + if (hclk_div && hclk_div < 6) { >> + s->regs[s->r_timings] &= ~(0xf << hclk_shift); >> + s->regs[s->r_timings] |= delay << hclk_shift; >> + } >> + >> + /* >> + * TODO: choose CS depending on the DMA address. This is not used >> + * on the field. >> + */ > > Not entirely sure what you have in mind by "on the field" here? > Not used by Linux?
Today, the FMC/SPI calibration using the DMA registers is done by the U-Boot bootloader from the SDK. I don't know of any other implementation a part from the patchset I just sent adding a new Aspeed FMC/SPI driver in U-Boot, which is not merged yet. Linux uses a similar algorithm but without the DMA registers because they are not available on the non-FMC/SPI controllers. That was for the "on the field" survey. As for the comment statement it self, There is not much reason choosing a DMA Flash address pointing to another CS, because the Read Timing Compensation Register values apply to all CS on the SPI bus. So the model limitation is not a big problem. Nevertheless we could compute the CS from the DMA address and the segment registers if needed. Thanks, C. C.