[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 09/11] aspeed/smc: add DMA calibration settings
From: |
Cédric Le Goater |
Subject: |
Re: [Qemu-devel] [PATCH 09/11] aspeed/smc: add DMA calibration settings |
Date: |
Wed, 19 Sep 2018 09:01:49 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 |
On 09/18/2018 08:54 PM, Peter Maydell wrote:
> On 31 August 2018 at 11:38, Cédric Le Goater <address@hidden> 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 <address@hidden>
>> ---
>> 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.