[PATCH v3 4/8] mmc: zynq_sdhci: Read clock phase delays from dt
Jaehoon Chung
jh80.chung at samsung.com
Mon Oct 26 22:38:20 CET 2020
On 10/26/20 8:42 PM, Michal Simek wrote:
> Define input and output clock phase delays with pre-defined values.
>
> Define arasan_sdhci_clk_data type structure and add it to priv
> structure and store these clock phase delays in it.
>
> Read input and output clock phase delays from dt. If these values are
> not passed through dt, use pre-defined values.
>
> Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma at xilinx.com>
> Signed-off-by: Michal Simek <michal.simek at xilinx.com>
> Reviewed-by: Peng Fan <peng.fan at nxp.com>
Reviewed-by: Jaehoon Chung <jh80.chung at samsung.com>
Best Regards,
Jaehoon Chung
> ---
>
> (no changes since v1)
>
> drivers/mmc/zynq_sdhci.c | 85 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 85 insertions(+)
>
> diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
> index 998a38450680..e69f375cce07 100644
> --- a/drivers/mmc/zynq_sdhci.c
> +++ b/drivers/mmc/zynq_sdhci.c
> @@ -20,6 +20,12 @@
> #include <zynqmp_tap_delay.h>
>
> #define SDHCI_TUNING_LOOP_COUNT 40
> +#define MMC_BANK2 0x2
> +
> +struct arasan_sdhci_clk_data {
> + int clk_phase_in[MMC_TIMING_MMC_HS400 + 1];
> + int clk_phase_out[MMC_TIMING_MMC_HS400 + 1];
> +};
>
> struct arasan_sdhci_plat {
> struct mmc_config cfg;
> @@ -28,12 +34,17 @@ struct arasan_sdhci_plat {
>
> struct arasan_sdhci_priv {
> struct sdhci_host *host;
> + struct arasan_sdhci_clk_data clk_data;
> u8 deviceid;
> u8 bank;
> u8 no_1p8;
> };
>
> #if defined(CONFIG_ARCH_ZYNQMP)
> +/* Default settings for ZynqMP Clock Phases */
> +const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0, 0, 183, 54, 0, 0};
> +const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0};
> +
> static const u8 mode2timing[] = {
> [MMC_LEGACY] = MMC_TIMING_LEGACY,
> [MMC_HS] = MMC_TIMING_MMC_HS,
> @@ -168,6 +179,79 @@ static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
> priv->bank);
> }
>
> +static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
> + const char *prop)
> +{
> + struct arasan_sdhci_priv *priv = dev_get_priv(dev);
> + struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
> + u32 clk_phase[2] = {0};
> +
> + /*
> + * Read Tap Delay values from DT, if the DT does not contain the
> + * Tap Values then use the pre-defined values
> + */
> + if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) {
> + dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n",
> + prop, clk_data->clk_phase_in[timing],
> + clk_data->clk_phase_out[timing]);
> + return;
> + }
> +
> + /* The values read are Input and Output Clock Delays in order */
> + clk_data->clk_phase_in[timing] = clk_phase[0];
> + clk_data->clk_phase_out[timing] = clk_phase[1];
> +}
> +
> +/**
> + * arasan_dt_parse_clk_phases - Read Tap Delay values from DT
> + *
> + * Called at initialization to parse the values of Tap Delays.
> + *
> + * @dev: Pointer to our struct udevice.
> + */
> +static void arasan_dt_parse_clk_phases(struct udevice *dev)
> +{
> + struct arasan_sdhci_priv *priv = dev_get_priv(dev);
> + struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
> + int i;
> +
> + if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
> + device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
> + for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
> + clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i];
> + clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i];
> + }
> +
> + if (priv->bank == MMC_BANK2) {
> + clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90;
> + clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90;
> + }
> + }
> +
> + arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY,
> + "clk-phase-legacy");
> + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
> + "clk-phase-mmc-hs");
> + arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS,
> + "clk-phase-sd-hs");
> + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12,
> + "clk-phase-uhs-sdr12");
> + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25,
> + "clk-phase-uhs-sdr25");
> + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50,
> + "clk-phase-uhs-sdr50");
> + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104,
> + "clk-phase-uhs-sdr104");
> + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50,
> + "clk-phase-uhs-ddr50");
> + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52,
> + "clk-phase-mmc-ddr52");
> + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200,
> + "clk-phase-mmc-hs200");
> + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400,
> + "clk-phase-mmc-hs400");
> +}
> +
> static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
> {
> struct mmc *mmc = (struct mmc *)host->mmc;
> @@ -271,6 +355,7 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
>
> #if defined(CONFIG_ARCH_ZYNQMP)
> priv->host->ops = &arasan_ops;
> + arasan_dt_parse_clk_phases(dev);
> #endif
>
> priv->host->ioaddr = (void *)dev_read_addr(dev);
>
More information about the U-Boot
mailing list