qemu-arm
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-arm] [PATCH 09/11] aspeed/smc: add DMA calibration settings


From: Peter Maydell
Subject: Re: [Qemu-arm] [PATCH 09/11] aspeed/smc: add DMA calibration settings
Date: Tue, 18 Sep 2018 19:54:39 +0100

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?

thanks
-- PMM



reply via email to

[Prev in Thread] Current Thread [Next in Thread]