Re: [PATCH v5 4/4] mmc: sdhci-of-aspeed: Configure the SDHCIs as specified by the devicetree.
From: Ulf Hansson
Date: Mon May 24 2021 - 10:12:09 EST
On Mon, 24 May 2021 at 09:33, Steven Lee <steven_lee@xxxxxxxxxxxxxx> wrote:
>
> The hardware provides capability configuration registers for each SDHCI
> in the global configuration space for the SD controller. Writes to the
> global capability registers are mirrored to the capability registers in
> the associated SDHCI. Configuration of the capabilities must be written
> through the mirror registers prior to initialisation of the SDHCI.
>
> Signed-off-by: Steven Lee <steven_lee@xxxxxxxxxxxxxx>
> Reviewed-by: Andrew Jeffery <andrew@xxxxxxxx>
> Reviewed-by: Joel Stanley <joel@xxxxxxxxx>
Applied for next, thanks!
Kind regards
Uffe
> ---
> drivers/mmc/host/sdhci-of-aspeed.c | 48 ++++++++++++++++++++++++++++++
> 1 file changed, 48 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c
> index d001c51074a0..65b5685f6c15 100644
> --- a/drivers/mmc/host/sdhci-of-aspeed.c
> +++ b/drivers/mmc/host/sdhci-of-aspeed.c
> @@ -31,6 +31,11 @@
> #define ASPEED_SDC_S0_PHASE_OUT_EN GENMASK(1, 0)
> #define ASPEED_SDC_PHASE_MAX 31
>
> +/* SDIO{10,20} */
> +#define ASPEED_SDC_CAP1_1_8V (0 * 32 + 26)
> +/* SDIO{14,24} */
> +#define ASPEED_SDC_CAP2_SDR104 (1 * 32 + 1)
> +
> struct aspeed_sdc {
> struct clk *clk;
> struct resource *res;
> @@ -72,6 +77,37 @@ struct aspeed_sdhci {
> const struct aspeed_sdhci_phase_desc *phase_desc;
> };
>
> +/*
> + * The function sets the mirror register for updating
> + * capbilities of the current slot.
> + *
> + * slot | capability | caps_reg | mirror_reg
> + * -----|-------------|----------|------------
> + * 0 | CAP1_1_8V | SDIO140 | SDIO10
> + * 0 | CAP2_SDR104 | SDIO144 | SDIO14
> + * 1 | CAP1_1_8V | SDIO240 | SDIO20
> + * 1 | CAP2_SDR104 | SDIO244 | SDIO24
> + */
> +static void aspeed_sdc_set_slot_capability(struct sdhci_host *host, struct aspeed_sdc *sdc,
> + int capability, bool enable, u8 slot)
> +{
> + u32 mirror_reg_offset;
> + u32 cap_val;
> + u8 cap_reg;
> +
> + if (slot > 1)
> + return;
> +
> + cap_reg = capability / 32;
> + cap_val = sdhci_readl(host, 0x40 + (cap_reg * 4));
> + if (enable)
> + cap_val |= BIT(capability % 32);
> + else
> + cap_val &= ~BIT(capability % 32);
> + mirror_reg_offset = ((slot + 1) * 0x10) + (cap_reg * 4);
> + writel(cap_val, sdc->regs + mirror_reg_offset);
> +}
> +
> static void aspeed_sdc_configure_8bit_mode(struct aspeed_sdc *sdc,
> struct aspeed_sdhci *sdhci,
> bool bus8)
> @@ -328,6 +364,7 @@ static inline int aspeed_sdhci_calculate_slot(struct aspeed_sdhci *dev,
> static int aspeed_sdhci_probe(struct platform_device *pdev)
> {
> const struct aspeed_sdhci_pdata *aspeed_pdata;
> + struct device_node *np = pdev->dev.of_node;
> struct sdhci_pltfm_host *pltfm_host;
> struct aspeed_sdhci *dev;
> struct sdhci_host *host;
> @@ -372,6 +409,17 @@ static int aspeed_sdhci_probe(struct platform_device *pdev)
>
> sdhci_get_of_property(pdev);
>
> + if (of_property_read_bool(np, "mmc-hs200-1_8v") ||
> + of_property_read_bool(np, "sd-uhs-sdr104")) {
> + aspeed_sdc_set_slot_capability(host, dev->parent, ASPEED_SDC_CAP1_1_8V,
> + true, slot);
> + }
> +
> + if (of_property_read_bool(np, "sd-uhs-sdr104")) {
> + aspeed_sdc_set_slot_capability(host, dev->parent, ASPEED_SDC_CAP2_SDR104,
> + true, slot);
> + }
> +
> pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
> if (IS_ERR(pltfm_host->clk))
> return PTR_ERR(pltfm_host->clk);
> --
> 2.17.1
>