From: Dmitry Osipenko <digetx@gmail.com>
To: Joseph Lo <josephl@nvidia.com>,
Thierry Reding <thierry.reding@gmail.com>,
Peter De Schrijver <pdeschrijver@nvidia.com>,
Jonathan Hunter <jonathanh@nvidia.com>,
Rob Herring <robh+dt@kernel.org>, Stephen Boyd <sboyd@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org,
linux-tegra@vger.kernel.org, linux-clk@vger.kernel.org,
devicetree@vger.kernel.org
Subject: Re: [PATCH 3/8] memory: tegra: Add Tegra210 EMC clock driver
Date: Wed, 3 Apr 2019 14:55:47 +0300 [thread overview]
Message-ID: <89f6b360-d1d5-d1b9-6b0f-f5e694b1b105@gmail.com> (raw)
In-Reply-To: <20190325074523.26456-4-josephl@nvidia.com>
25.03.2019 10:45, Joseph Lo пишет:
> This is the initial patch for Tegra210 EMC clock driver, which doesn't
> include the support code and detail sequence for clock scaling yet.
>
> The driver is designed to support LPDDR4 SDRAMs. Because of the LPDDR4
> devices need to do initial time training before it can be used, the
> firmware will help to do that at early boot stage. The trained table for
> the rates that we will support in the kernel will be merged to the
> kernel DTB. So the driver can get the trained table for clock scaling
> support.
>
> For the higher rate support (above 800MHz), the periodic training is
> needed for the timing compensation. So basically, two methodologies for
> clock scaling support, one is following the clock changing sequence to
> update the EMC table to EMC registers and another is if the rate needs
> periodic training, then we will start a timer to do that periodically
> until it leaves the rate that doesn't need that.
>
> Based on the work of Peter De Schrijver <pdeschrijver@nvidia.com>.
>
> Signed-off-by: Joseph Lo <josephl@nvidia.com>
> ---
> drivers/memory/tegra/Kconfig | 10 +
> drivers/memory/tegra/Makefile | 1 +
> drivers/memory/tegra/tegra210-dt-parse.c | 340 +++++++
> drivers/memory/tegra/tegra210-emc-reg.h | 1083 ++++++++++++++++++++++
> drivers/memory/tegra/tegra210-emc.c | 886 ++++++++++++++++++
> 5 files changed, 2320 insertions(+)
> create mode 100644 drivers/memory/tegra/tegra210-dt-parse.c
> create mode 100644 drivers/memory/tegra/tegra210-emc-reg.h
> create mode 100644 drivers/memory/tegra/tegra210-emc.c
>
> diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig
> index 34e0b70f5c5f..614e9b370183 100644
> --- a/drivers/memory/tegra/Kconfig
> +++ b/drivers/memory/tegra/Kconfig
> @@ -25,3 +25,13 @@ config TEGRA124_EMC
> Tegra124 chips. The EMC controls the external DRAM on the board.
> This driver is required to change memory timings / clock rate for
> external memory.
> +
> +config TEGRA210_EMC
> + bool "NVIDIA Tegra210 External Memory Controller driver"
> + default y
> + depends on TEGRA_MC && ARCH_TEGRA_210_SOC
> + help
> + This driver is for the External Memory Controller (EMC) found on
> + Tegra210 chips. The EMC controls the external DRAM on the board.
> + This driver is required to change memory timings / clock rate for
> + external memory.
> diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
> index 3971a6b7c487..36a835620bbd 100644
> --- a/drivers/memory/tegra/Makefile
> +++ b/drivers/memory/tegra/Makefile
> @@ -12,4 +12,5 @@ obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
>
> obj-$(CONFIG_TEGRA20_EMC) += tegra20-emc.o
> obj-$(CONFIG_TEGRA124_EMC) += tegra124-emc.o
> +obj-$(CONFIG_TEGRA210_EMC) += tegra210-emc.o tegra210-dt-parse.o
> obj-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o
> diff --git a/drivers/memory/tegra/tegra210-dt-parse.c b/drivers/memory/tegra/tegra210-dt-parse.c
> new file mode 100644
> index 000000000000..6a3a3a28ac64
> --- /dev/null
> +++ b/drivers/memory/tegra/tegra210-dt-parse.c
> @@ -0,0 +1,340 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2013-2019, NVIDIA CORPORATION. All rights reserved.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/err.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <soc/tegra/fuse.h>
> +
> +#include "tegra210-emc-reg.h"
> +
> +static struct device_node *tegra_emc_ramcode_devnode(
> + struct device_node *np)
> +{
> + struct device_node *iter;
> + u32 reg;
> +
> + for_each_child_of_node(np, iter) {
> + if (of_property_read_u32(iter, "nvidia,ram-code", ®))
> + continue;
> + if (reg == tegra_read_ram_code())
> + return of_node_get(iter);
> + }
> +
> + return NULL;
> +}
> +
> +static void *tegra_emc_dt_parse_pdata_comp(const char *emc_mode,
> + const char *comp,
> + void *pdata,
> + struct device_node *tnp,
> + struct platform_device *pdev,
> + int num_tables, int *table_count)
> +{
> +#define PNE_U32(node, entry, tbl_entry) \
> + do { \
> + int __ret__; \
> + u32 __tmp__; \
> + \
> + __ret__ = of_property_read_u32((node), (entry), &__tmp__); \
> + if (__ret__) { \
> + dev_err(&pdev->dev, "Failed to parse %s in %s: %d\n", \
> + (entry), (node)->full_name, __ret__); \
> + continue; \
> + } \
> + \
> + tables[i].tbl_entry = __tmp__; \
> + } while (0)
> +
> +#define PNE_U32_ARRAY(node, entry, tbl_entry, length) \
> + do { \
> + int __ret__; \
> + \
> + __ret__ = of_property_read_u32_array((node), (entry), \
> + (tbl_entry), (length)); \
> + if (__ret__) { \
> + dev_err(&pdev->dev, "Failed to parse %s in %s: %d\n", \
> + (entry), (node)->full_name, __ret__); \
> + continue; \
> + } \
> + } while (0)
> +
> + int i = 0, ret = 0;
> + struct device_node *iter;
> + struct emc_table *tables;
> +
> + tables = devm_kzalloc(&pdev->dev, sizeof(*tables) * num_tables,
> + GFP_KERNEL);
> +
> + if (!tables) {
> + of_node_put(tnp);
> + return tables;
> + }
> +
> + for_each_child_of_node(tnp, iter) {
> + if (of_device_is_compatible(iter, comp)) {
> + const char *source_name;
> + const char *dvfs_ver;
> +
> + ret = of_property_read_string(iter, "nvidia,source",
> + &source_name);
> + if (ret) {
> + dev_err(&pdev->dev, "no source name in %s\n",
> + iter->full_name);
> + continue;
> + }
> + strlcpy(tables[i].clock_src, source_name,
> + sizeof(tables[i].clock_src));
> +
> + ret = of_property_read_string(iter,
> + "nvidia,dvfs-version",
> + &dvfs_ver);
> + if (ret) {
> + dev_err(&pdev->dev, "no dvfs version in %s\n",
> + iter->full_name);
> + continue;
> + }
> + strlcpy(tables[i].dvfs_ver, dvfs_ver,
> + sizeof(tables[i].dvfs_ver));
> +
> + PNE_U32(iter, "nvidia,revision", rev);
> + PNE_U32(iter, "clock-frequency", rate);
> + PNE_U32(iter, "nvidia,emc-min-mv", min_volt);
> + PNE_U32(iter, "nvidia,gk20a-min-mv", gpu_min_volt);
> + PNE_U32(iter, "nvidia,src-sel-reg", clk_src_emc);
> + PNE_U32(iter, "nvidia,burst-regs-num", num_burst);
> + PNE_U32(iter, "nvidia,emc-cfg-2", emc_cfg_2);
> + PNE_U32(iter, "nvidia,emc-sel-dpd-ctrl",
> + emc_sel_dpd_ctrl);
> + PNE_U32(iter, "nvidia,emc-auto-cal-config",
> + emc_auto_cal_config);
> + PNE_U32(iter, "nvidia,emc-auto-cal-config2",
> + emc_auto_cal_config2);
> + PNE_U32(iter, "nvidia,emc-auto-cal-config3",
> + emc_auto_cal_config3);
> + PNE_U32(iter, "nvidia,emc-clock-latency-change",
> + latency);
> + PNE_U32_ARRAY(iter, "nvidia,emc-registers",
> + tables[i].burst_regs,
> + tables[i].num_burst);
> +
> + PNE_U32(iter, "nvidia,needs-training", needs_training);
> + PNE_U32(iter, "nvidia,trained", trained);
> + if (tables[i].rev < 0x6)
> + goto skip_periodic_training_params;
> + PNE_U32(iter, "nvidia,periodic_training",
> + periodic_training);
> + PNE_U32(iter, "nvidia,trained_dram_clktree_c0d0u0",
> + trained_dram_clktree_c0d0u0);
> + PNE_U32(iter, "nvidia,trained_dram_clktree_c0d0u1",
> + trained_dram_clktree_c0d0u1);
> + PNE_U32(iter, "nvidia,trained_dram_clktree_c0d1u0",
> + trained_dram_clktree_c0d1u0);
> + PNE_U32(iter, "nvidia,trained_dram_clktree_c0d1u1",
> + trained_dram_clktree_c0d1u1);
> + PNE_U32(iter, "nvidia,trained_dram_clktree_c1d0u0",
> + trained_dram_clktree_c1d0u0);
> + PNE_U32(iter, "nvidia,trained_dram_clktree_c1d0u1",
> + trained_dram_clktree_c1d0u1);
> + PNE_U32(iter, "nvidia,trained_dram_clktree_c1d1u0",
> + trained_dram_clktree_c1d1u0);
> + PNE_U32(iter, "nvidia,trained_dram_clktree_c1d1u1",
> + trained_dram_clktree_c1d1u1);
> + PNE_U32(iter, "nvidia,current_dram_clktree_c0d0u0",
> + current_dram_clktree_c0d0u0);
> + PNE_U32(iter, "nvidia,current_dram_clktree_c0d0u1",
> + current_dram_clktree_c0d0u1);
> + PNE_U32(iter, "nvidia,current_dram_clktree_c0d1u0",
> + current_dram_clktree_c0d1u0);
> + PNE_U32(iter, "nvidia,current_dram_clktree_c0d1u1",
> + current_dram_clktree_c0d1u1);
> + PNE_U32(iter, "nvidia,current_dram_clktree_c1d0u0",
> + current_dram_clktree_c1d0u0);
> + PNE_U32(iter, "nvidia,current_dram_clktree_c1d0u1",
> + current_dram_clktree_c1d0u1);
> + PNE_U32(iter, "nvidia,current_dram_clktree_c1d1u0",
> + current_dram_clktree_c1d1u0);
> + PNE_U32(iter, "nvidia,current_dram_clktree_c1d1u1",
> + current_dram_clktree_c1d1u1);
> + PNE_U32(iter, "nvidia,run_clocks", run_clocks);
> + PNE_U32(iter, "nvidia,tree_margin", tree_margin);
> +
> +skip_periodic_training_params:
> + PNE_U32(iter, "nvidia,burst-regs-per-ch-num",
> + num_burst_per_ch);
> + PNE_U32(iter, "nvidia,trim-regs-num", num_trim);
> + PNE_U32(iter, "nvidia,trim-regs-per-ch-num",
> + num_trim_per_ch);
> + PNE_U32(iter, "nvidia,burst-mc-regs-num",
> + num_mc_regs);
> + PNE_U32(iter, "nvidia,la-scale-regs-num",
> + num_up_down);
> + PNE_U32(iter, "nvidia,vref-regs-num", vref_num);
> + PNE_U32(iter, "nvidia,dram-timing-regs-num",
> + dram_timing_num);
> + PNE_U32(iter, "nvidia,min-mrs-wait", min_mrs_wait);
> + PNE_U32(iter, "nvidia,emc-mrw", emc_mrw);
> + PNE_U32(iter, "nvidia,emc-mrw2", emc_mrw2);
> + PNE_U32(iter, "nvidia,emc-mrw3", emc_mrw3);
> + PNE_U32(iter, "nvidia,emc-mrw4", emc_mrw4);
> + PNE_U32(iter, "nvidia,emc-mrw9", emc_mrw9);
> + PNE_U32(iter, "nvidia,emc-mrs", emc_mrs);
> + PNE_U32(iter, "nvidia,emc-emrs", emc_emrs);
> + PNE_U32(iter, "nvidia,emc-emrs2", emc_emrs2);
> + PNE_U32(iter, "nvidia,emc-auto-cal-config4",
> + emc_auto_cal_config4);
> + PNE_U32(iter, "nvidia,emc-auto-cal-config5",
> + emc_auto_cal_config5);
> + PNE_U32(iter, "nvidia,emc-auto-cal-config6",
> + emc_auto_cal_config6);
> + PNE_U32(iter, "nvidia,emc-auto-cal-config7",
> + emc_auto_cal_config7);
> + PNE_U32(iter, "nvidia,emc-auto-cal-config8",
> + emc_auto_cal_config8);
> + PNE_U32(iter, "nvidia,emc-fdpd-ctrl-cmd-no-ramp",
> + emc_fdpd_ctrl_cmd_no_ramp);
> + PNE_U32(iter, "nvidia,dll-clk-src", dll_clk_src);
> + PNE_U32(iter, "nvidia,clk-out-enb-x-0-clk-enb-emc-dll",
> + clk_out_enb_x_0_clk_enb_emc_dll);
> +
> + if (tables[i].rev >= 0x7)
> + PNE_U32_ARRAY(iter, "nvidia,ptfv",
> + tables[i].ptfv_list,
> + sizeof(tables[i].ptfv_list)
> + / sizeof(u32));
> +
> + PNE_U32_ARRAY(iter, "nvidia,emc-burst-regs-per-ch",
> + tables[i].burst_reg_per_ch,
> + tables[i].num_burst_per_ch);
> + PNE_U32_ARRAY(iter, "nvidia,emc-shadow-regs-ca-train",
> + tables[i].shadow_regs_ca_train,
> + tables[i].num_burst);
> + PNE_U32_ARRAY(iter, "nvidia,emc-shadow-regs-quse-train",
> + tables[i].shadow_regs_quse_train,
> + tables[i].num_burst);
> + PNE_U32_ARRAY(iter, "nvidia,emc-shadow-regs-rdwr-train",
> + tables[i].shadow_regs_rdwr_train,
> + tables[i].num_burst);
> + PNE_U32_ARRAY(iter, "nvidia,emc-trim-regs",
> + tables[i].trim_regs,
> + tables[i].num_trim);
> + PNE_U32_ARRAY(iter, "nvidia,emc-trim-regs-per-ch",
> + tables[i].trim_perch_regs,
> + tables[i].num_trim_per_ch);
> + PNE_U32_ARRAY(iter, "nvidia,emc-vref-regs",
> + tables[i].vref_perch_regs,
> + tables[i].vref_num);
> + PNE_U32_ARRAY(iter, "nvidia,emc-dram-timing-regs",
> + tables[i].dram_timings,
> + tables[i].dram_timing_num);
> + PNE_U32_ARRAY(iter, "nvidia,emc-burst-mc-regs",
> + tables[i].burst_mc_regs,
> + tables[i].num_mc_regs);
> + PNE_U32_ARRAY(iter, "nvidia,emc-la-scale-regs",
> + tables[i].la_scale_regs,
> + tables[i].num_up_down);
> + i++;
> + }
> + }
> +
> + *table_count = i;
> +
> + return tables;
> +}
> +
> +static const struct of_device_id emc_table_match[] = {
> + {
> + .compatible = "nvidia,tegra210-emc-table",
> + .data = "nvidia,tegra210-emc-table-derated",
> + },
> + {
> + .compatible = "nvidia,tegra21-emc-table",
> + .data = "nvidia,tegra21-emc-table-derated",
> + },
> + { },
> +};
> +
> +int tegra_emc_dt_parse_pdata(struct platform_device *pdev,
> + struct emc_table **tables,
> + struct emc_table **derated_tables,
> + int *num_entries)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + struct device_node *tnp, *iter;
> + int num_tables, table_count;
> + u32 tegra_bct_strapping;
> + const char *emc_mode = "nvidia,emc-mode-0";
> + struct tegra21_emc_pdata *pdata = NULL;
> + const char *comp = NULL;
> + const char *comp_derated = NULL;
> +
> + if (!np) {
> + dev_err(&pdev->dev,
> + "Unable to find external-memory-controller node\n");
> + return -ENODEV;
> + }
> +
> + tegra_bct_strapping = tegra_read_ram_code();
> +
> + if (of_find_property(np, "nvidia,use-ram-code", NULL)) {
> + tnp = tegra_emc_ramcode_devnode(np);
> +
> + if (!tnp) {
> + dev_warn(&pdev->dev,
> + "can't find emc table for ram-code 0x%02x\n",
> + tegra_bct_strapping);
> + return -ENODEV;
> + }
> + } else
> + tnp = of_node_get(np);
> +
> + num_tables = 0;
> + for_each_child_of_node(tnp, iter) {
> + if (!comp) {
> + const struct of_device_id *m =
> + of_match_node(emc_table_match, iter);
> + if (m) {
> + comp = m->compatible;
> + comp_derated = m->data;
> + num_tables++;
> + }
> + continue;
> + }
> + if (of_device_is_compatible(iter, comp))
> + num_tables++;
> + }
> +
> + if (!num_tables) {
> + *tables = NULL;
> + goto out;
> + }
> +
> + *tables = tegra_emc_dt_parse_pdata_comp(emc_mode, comp, pdata, tnp,
> + pdev, num_tables, &table_count);
> + *num_entries = table_count;
> +
> + /* populate the derated tables */
> + num_tables = 0;
> + for_each_child_of_node(tnp, iter) {
> + if (of_device_is_compatible(iter, comp_derated))
> + num_tables++;
> + }
> +
> + if (!num_tables) {
> + *derated_tables = NULL;
> + goto out;
> + }
> +
> + *derated_tables = tegra_emc_dt_parse_pdata_comp(emc_mode,
> + comp_derated,
> + pdata, tnp, pdev,
> + num_tables,
> + &table_count);
> +
> +out:
> + of_node_put(tnp);
> + return 0;
> +}
> diff --git a/drivers/memory/tegra/tegra210-emc-reg.h b/drivers/memory/tegra/tegra210-emc-reg.h
> new file mode 100644
> index 000000000000..84fcc85f3b6d
> --- /dev/null
> +++ b/drivers/memory/tegra/tegra210-emc-reg.h
> @@ -0,0 +1,1083 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2015-2019, NVIDIA CORPORATION. All rights reserved.
> + */
> +
> +#ifndef _TEGRA210_EMC_REG_H
> +#define _TEGRA210_EMC_REG_H
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/platform_device.h>
> +
> +#include "mc.h"
> +
> +#define MC_EMEM_ARB_CFG 0x90
> +#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
> +#define MC_EMEM_ARB_TIMING_RCD 0x98
> +#define MC_EMEM_ARB_TIMING_RP 0x9c
> +#define MC_EMEM_ARB_TIMING_RC 0xa0
> +#define MC_EMEM_ARB_TIMING_RAS 0xa4
> +#define MC_EMEM_ARB_TIMING_FAW 0xa8
> +#define MC_EMEM_ARB_TIMING_RRD 0xac
> +#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0
> +#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4
> +#define MC_EMEM_ARB_TIMING_R2R 0xb8
> +#define MC_EMEM_ARB_TIMING_W2W 0xbc
> +#define MC_EMEM_ARB_TIMING_R2W 0xc0
> +#define MC_EMEM_ARB_TIMING_W2R 0xc4
> +#define MC_EMEM_ARB_MISC2 0xc8
> +#define MC_EMEM_ARB_DA_TURNS 0xd0
> +#define MC_EMEM_ARB_DA_COVERS 0xd4
> +#define MC_EMEM_ARB_MISC0 0xd8
> +#define MC_EMEM_ARB_MISC0_EMC_SAME_FREQ BIT(27)
> +#define MC_EMEM_ARB_MISC1 0xdc
> +#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
> +#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4
> +#define MC_LATENCY_ALLOWANCE_HC_0 0x310
> +#define MC_LATENCY_ALLOWANCE_HC_1 0x314
> +#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320
> +#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328
> +#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344
> +#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348
> +#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370
> +#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374
> +#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c
> +#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380
> +#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390
> +#define MC_LATENCY_ALLOWANCE_VIC_0 0x394
> +#define MC_LATENCY_ALLOWANCE_VI2_0 0x398
> +#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac
> +#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8
> +#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc
> +#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0
> +#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4
> +#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8
> +#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8
> +#define MC_MLL_MPCORER_PTSA_RATE 0x44c
> +#define MC_FTOP_PTSA_RATE 0x50c
> +#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0
> +#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4
> +#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0
> +#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4
> +#define MC_PTSA_GRANT_DECREMENT 0x960
> +#define MC_EMEM_ARB_DHYST_CTRL 0xbcc
> +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0
> +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4
> +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8
> +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc
> +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0
> +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4
> +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8
> +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec
> +
> +#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC 0x19c
> +#define EMC_CLK_EMC_2X_CLK_SRC_SHIFT 29
> +#define EMC_CLK_EMC_2X_CLK_SRC_MASK \
> + (0x7 << EMC_CLK_EMC_2X_CLK_SRC_SHIFT)
> +#define EMC_CLK_MC_EMC_SAME_FREQ BIT(16)
> +#define EMC_CLK_EMC_2X_CLK_DIVISOR_SHIFT 0
> +#define EMC_CLK_EMC_2X_CLK_DIVISOR_MASK \
> + (0xff << EMC_CLK_EMC_2X_CLK_DIVISOR_SHIFT)
> +
> +#define EMC_CFG 0xc
> +#define EMC_RC 0x2c
> +#define EMC_RFC 0x30
> +#define EMC_RAS 0x34
> +#define EMC_RP 0x38
> +#define EMC_R2W 0x3c
> +#define EMC_W2R 0x40
> +#define EMC_R2P 0x44
> +#define EMC_W2P 0x48
> +#define EMC_RD_RCD 0x4c
> +#define EMC_WR_RCD 0x50
> +#define EMC_RRD 0x54
> +#define EMC_REXT 0x58
> +#define EMC_WDV 0x5c
> +#define EMC_QUSE 0x60
> +#define EMC_QRST 0x64
> +#define EMC_QSAFE 0x68
> +#define EMC_RDV 0x6c
> +#define EMC_REFRESH 0x70
> +#define EMC_BURST_REFRESH_NUM 0x74
> +#define EMC_PDEX2WR 0x78
> +#define EMC_PDEX2RD 0x7c
> +#define EMC_PCHG2PDEN 0x80
> +#define EMC_ACT2PDEN 0x84
> +#define EMC_AR2PDEN 0x88
> +#define EMC_RW2PDEN 0x8c
> +#define EMC_TXSR 0x90
> +#define EMC_TCKE 0x94
> +#define EMC_TFAW 0x98
> +#define EMC_TRPAB 0x9c
> +#define EMC_TCLKSTABLE 0xa0
> +#define EMC_TCLKSTOP 0xa4
> +#define EMC_TREFBW 0xa8
> +#define EMC_TPPD 0xac
> +#define EMC_ODT_WRITE 0xb0
> +#define EMC_PDEX2MRR 0xb4
> +#define EMC_WEXT 0xb8
> +#define EMC_RFC_SLR 0xc0
> +#define EMC_MRS_WAIT_CNT2 0xc4
> +#define EMC_MRS_WAIT_CNT 0xc8
> +#define EMC_FBIO_SPARE 0x100
> +#define EMC_FBIO_CFG5 0x104
> +#define EMC_FBIO_CFG5_DRAM_TYPE_SHIFT 0
> +#define EMC_FBIO_CFG5_DRAM_TYPE_MASK \
> + (0x3 << EMC_FBIO_CFG5_DRAM_TYPE_SHIFT)
> +#define EMC_PDEX2CKE 0x118
> +#define EMC_CKE2PDEN 0x11c
> +#define EMC_R2R 0x144
> +#define EMC_EINPUT 0x14c
> +#define EMC_EINPUT_DURATION 0x150
> +#define EMC_PUTERM_EXTRA 0x154
> +#define EMC_TCKESR 0x158
> +#define EMC_TPD 0x15c
> +#define EMC_CFG_DIG_DLL 0x2bc
> +#define EMC_CFG_DIG_DLL_PERIOD 0x2c0
> +#define EMC_RDV_MASK 0x2cc
> +#define EMC_WDV_MASK 0x2d0
> +#define EMC_RDV_EARLY_MASK 0x2d4
> +#define EMC_RDV_EARLY 0x2d8
> +#define EMC_ZCAL_INTERVAL 0x2e0
> +#define EMC_ZCAL_WAIT_CNT 0x2e4
> +#define EMC_FDPD_CTRL_DQ 0x310
> +#define EMC_FDPD_CTRL_CMD 0x314
> +#define EMC_PMACRO_CMD_BRICK_CTRL_FDPD 0x318
> +#define EMC_PMACRO_DATA_BRICK_CTRL_FDPD 0x31c
> +#define EMC_PMACRO_BRICK_CTRL_RFU1 0x330
> +#define EMC_PMACRO_BRICK_CTRL_RFU2 0x334
> +#define EMC_TR_TIMING_0 0x3b4
> +#define EMC_TR_CTRL_1 0x3bc
> +#define EMC_TR_RDV 0x3c4
> +#define EMC_PRE_REFRESH_REQ_CNT 0x3dc
> +#define EMC_DYN_SELF_REF_CONTROL 0x3e0
> +#define EMC_TXSRDLL 0x3e4
> +#define EMC_TR_QPOP 0x3f4
> +#define EMC_TR_RDV_MASK 0x3f8
> +#define EMC_TR_QSAFE 0x3fc
> +#define EMC_TR_QRST 0x400
> +#define EMC_TR_DVFS 0x460
> +#define EMC_AUTO_CAL_CHANNEL 0x464
> +#define EMC_IBDLY 0x468
> +#define EMC_OBDLY 0x46c
> +#define EMC_TXDSRVTTGEN 0x480
> +#define EMC_WE_DURATION 0x48c
> +#define EMC_WS_DURATION 0x490
> +#define EMC_WEV 0x494
> +#define EMC_WSV 0x498
> +#define EMC_CFG_3 0x49c
> +#define EMC_MRW6 0x4a4
> +#define EMC_MRW7 0x4a8
> +#define EMC_MRW8 0x4ac
> +#define EMC_MRW10 0x4b4
> +#define EMC_MRW11 0x4b8
> +#define EMC_MRW12 0x4bc
> +#define EMC_MRW13 0x4c0
> +#define EMC_MRW14 0x4c4
> +#define EMC_MRW15 0x4d0
> +#define EMC_WDV_CHK 0x4e0
> +#define EMC_CFG_PIPE_2 0x554
> +#define EMC_CFG_PIPE_1 0x55c
> +#define EMC_CFG_PIPE 0x560
> +#define EMC_QPOP 0x564
> +#define EMC_QUSE_WIDTH 0x568
> +#define EMC_PUTERM_WIDTH 0x56c
> +#define EMC_REFCTRL2 0x580
> +#define EMC_FBIO_CFG7 0x584
> +#define EMC_DATA_BRLSHFT_0 0x588
> +#define EMC_DATA_BRLSHFT_1 0x58c
> +#define EMC_RFCPB 0x590
> +#define EMC_DQS_BRLSHFT_0 0x594
> +#define EMC_DQS_BRLSHFT_1 0x598
> +#define EMC_CMD_BRLSHFT_0 0x59c
> +#define EMC_CMD_BRLSHFT_1 0x5a0
> +#define EMC_CMD_BRLSHFT_2 0x5a4
> +#define EMC_CMD_BRLSHFT_3 0x5a8
> +#define EMC_QUSE_BRLSHFT_0 0x5ac
> +#define EMC_QUSE_BRLSHFT_1 0x5b8
> +#define EMC_QUSE_BRLSHFT_2 0x5bc
> +#define EMC_CCDMW 0x5c0
> +#define EMC_QUSE_BRLSHFT_3 0x5c4
> +#define EMC_DLL_CFG_0 0x5e4
> +#define EMC_DLL_CFG_1 0x5e8
> +#define EMC_CONFIG_SAMPLE_DELAY 0x5f0
> +#define EMC_PMACRO_QUSE_DDLL_RANK0_0 0x600
> +#define EMC_PMACRO_QUSE_DDLL_RANK0_1 0x604
> +#define EMC_PMACRO_QUSE_DDLL_RANK0_2 0x608
> +#define EMC_PMACRO_QUSE_DDLL_RANK0_3 0x60c
> +#define EMC_PMACRO_QUSE_DDLL_RANK0_4 0x610
> +#define EMC_PMACRO_QUSE_DDLL_RANK0_5 0x614
> +#define EMC_PMACRO_QUSE_DDLL_RANK1_0 0x620
> +#define EMC_PMACRO_QUSE_DDLL_RANK1_1 0x624
> +#define EMC_PMACRO_QUSE_DDLL_RANK1_2 0x628
> +#define EMC_PMACRO_QUSE_DDLL_RANK1_3 0x62c
> +#define EMC_PMACRO_QUSE_DDLL_RANK1_4 0x630
> +#define EMC_PMACRO_QUSE_DDLL_RANK1_5 0x634
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0 0x640
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1 0x644
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2 0x648
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3 0x64c
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4 0x650
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5 0x654
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0 0x660
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1 0x664
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2 0x668
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3 0x66c
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4 0x670
> +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5 0x674
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0 0x680
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1 0x684
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2 0x688
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3 0x68c
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4 0x690
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5 0x694
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0 0x6a0
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1 0x6a4
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2 0x6a8
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3 0x6ac
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4 0x6b0
> +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5 0x6b4
> +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0 0x6c0
> +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1 0x6c4
> +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2 0x6c8
> +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3 0x6cc
> +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0 0x6e0
> +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1 0x6e4
> +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2 0x6e8
> +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3 0x6ec
> +#define EMC_PMACRO_TX_PWRD_0 0x720
> +#define EMC_PMACRO_TX_PWRD_1 0x724
> +#define EMC_PMACRO_TX_PWRD_2 0x728
> +#define EMC_PMACRO_TX_PWRD_3 0x72c
> +#define EMC_PMACRO_TX_PWRD_4 0x730
> +#define EMC_PMACRO_TX_PWRD_5 0x734
> +#define EMC_PMACRO_TX_SEL_CLK_SRC_0 0x740
> +#define EMC_PMACRO_TX_SEL_CLK_SRC_1 0x744
> +#define EMC_PMACRO_TX_SEL_CLK_SRC_3 0x74c
> +#define EMC_PMACRO_TX_SEL_CLK_SRC_2 0x748
> +#define EMC_PMACRO_TX_SEL_CLK_SRC_4 0x750
> +#define EMC_PMACRO_TX_SEL_CLK_SRC_5 0x754
> +#define EMC_PMACRO_DDLL_BYPASS 0x760
> +#define EMC_PMACRO_DDLL_PWRD_0 0x770
> +#define EMC_PMACRO_DDLL_PWRD_1 0x774
> +#define EMC_PMACRO_DDLL_PWRD_2 0x778
> +#define EMC_PMACRO_CMD_CTRL_0 0x780
> +#define EMC_PMACRO_CMD_CTRL_1 0x784
> +#define EMC_PMACRO_CMD_CTRL_2 0x788
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0x800
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0x804
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0x808
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_3 0x80c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0x810
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0x814
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0x818
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_3 0x81c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0x820
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0x824
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0x828
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_3 0x82c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0x830
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0x834
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0x838
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_3 0x83c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0x840
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0x844
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0x848
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_3 0x84c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0x850
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0x854
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0x858
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_3 0x85c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0x860
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0x864
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0x868
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_3 0x86c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0x870
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0x874
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0x878
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_3 0x87c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_0 0x880
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_1 0x884
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_2 0x888
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_3 0x88c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_0 0x890
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_1 0x894
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_2 0x898
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_3 0x89c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_0 0x8a0
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_1 0x8a4
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_2 0x8a8
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_3 0x8ac
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_0 0x8b0
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_1 0x8b4
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_2 0x8b8
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_3 0x8bc
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0x900
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0x904
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0x908
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_3 0x90c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0x910
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0x914
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0x918
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_3 0x91c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0x920
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0x924
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0x928
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_3 0x92c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0x930
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0x934
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0x938
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_3 0x93c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0x940
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0x944
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0x948
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_3 0x94c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0x950
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0x954
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0x958
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_3 0x95c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0x960
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0x964
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0x968
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_3 0x96c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0x970
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0x974
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0x978
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_3 0x97c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_0 0x980
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_1 0x984
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_2 0x988
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_3 0x98c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_0 0x990
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_1 0x994
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_2 0x998
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_3 0x99c
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_0 0x9a0
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_1 0x9a4
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_2 0x9a8
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_3 0x9ac
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_0 0x9b0
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_1 0x9b4
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_2 0x9b8
> +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_3 0x9bc
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0xa00
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0xa04
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0xa08
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0xa10
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0xa14
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0xa18
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0xa20
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0xa24
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0xa28
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0xa30
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0xa34
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0xa38
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0xa40
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0xa44
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0xa48
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0xa50
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0xa54
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0xa58
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0xa60
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0xa64
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0xa68
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0xa70
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0xa74
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0xa78
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0xb00
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0xb04
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0xb08
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0xb10
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0xb14
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0xb18
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0xb20
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0xb24
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0xb28
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0xb30
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0xb34
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0xb38
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0xb40
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0xb44
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0xb48
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0xb50
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0xb54
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0xb58
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0xb60
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0xb64
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0xb68
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0xb70
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0xb74
> +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0xb78
> +#define EMC_PMACRO_IB_VREF_DQ_0 0xbe0
> +#define EMC_PMACRO_IB_VREF_DQ_1 0xbe4
> +#define EMC_PMACRO_IB_VREF_DQS_0 0xbf0
> +#define EMC_PMACRO_IB_VREF_DQS_1 0xbf4
> +#define EMC_PMACRO_DDLL_LONG_CMD_0 0xc00
> +#define EMC_PMACRO_DDLL_LONG_CMD_1 0xc04
> +#define EMC_PMACRO_DDLL_LONG_CMD_2 0xc08
> +#define EMC_PMACRO_DDLL_LONG_CMD_3 0xc0c
> +#define EMC_PMACRO_DDLL_LONG_CMD_4 0xc10
> +#define EMC_PMACRO_DDLL_LONG_CMD_5 0xc14
> +#define EMC_PMACRO_DDLL_SHORT_CMD_0 0xc20
> +#define EMC_PMACRO_DDLL_SHORT_CMD_1 0xc24
> +#define EMC_PMACRO_DDLL_SHORT_CMD_2 0xc28
> +#define EMC_PMACRO_VTTGEN_CTRL_0 0xc34
> +#define EMC_PMACRO_VTTGEN_CTRL_1 0xc38
> +#define EMC_PMACRO_BG_BIAS_CTRL_0 0xc3c
> +#define EMC_PMACRO_PAD_CFG_CTRL 0xc40
> +#define EMC_PMACRO_ZCTRL 0xc44
> +#define EMC_PMACRO_CMD_PAD_RX_CTRL 0xc50
> +#define EMC_PMACRO_DATA_PAD_RX_CTRL 0xc54
> +#define EMC_PMACRO_CMD_RX_TERM_MODE 0xc58
> +#define EMC_PMACRO_DATA_RX_TERM_MODE 0xc5c
> +#define EMC_PMACRO_CMD_PAD_TX_CTRL 0xc60
> +#define EMC_PMACRO_DATA_PAD_TX_CTRL 0xc64
> +#define EMC_PMACRO_COMMON_PAD_TX_CTRL 0xc68
> +#define EMC_PMACRO_AUTOCAL_CFG_COMMON 0xc78
> +#define EMC_PMACRO_VTTGEN_CTRL_2 0xcf0
> +#define EMC_PMACRO_IB_RXRT 0xcf4
> +#define EMC_TRAINING_CTRL 0xe04
> +#define EMC_TRAINING_QUSE_CORS_CTRL 0xe0c
> +#define EMC_TRAINING_QUSE_FINE_CTRL 0xe10
> +#define EMC_TRAINING_QUSE_CTRL_MISC 0xe14
> +#define EMC_TRAINING_WRITE_FINE_CTRL 0xe18
> +#define EMC_TRAINING_WRITE_CTRL_MISC 0xe1c
> +#define EMC_TRAINING_WRITE_VREF_CTRL 0xe20
> +#define EMC_TRAINING_READ_FINE_CTRL 0xe24
> +#define EMC_TRAINING_READ_CTRL_MISC 0xe28
> +#define EMC_TRAINING_READ_VREF_CTRL 0xe2c
> +#define EMC_TRAINING_CA_FINE_CTRL 0xe30
> +#define EMC_TRAINING_CA_CTRL_MISC 0xe34
> +#define EMC_TRAINING_CA_CTRL_MISC1 0xe38
> +#define EMC_TRAINING_CA_VREF_CTRL 0xe3c
> +#define EMC_TRAINING_SETTLE 0xe44
> +#define EMC_TRAINING_MPC 0xe5c
> +#define EMC_TRAINING_VREF_SETTLE 0xe6c
> +#define EMC_TRAINING_QUSE_VREF_CTRL 0xed0
> +#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK0 0xed4
> +#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK1 0xed8
> +
> +#define EMC_COPY_TABLE_PARAM_PERIODIC_FIELDS BIT(0)
> +#define EMC_COPY_TABLE_PARAM_TRIM_REGS BIT(1)
> +
> +enum {
> + REG_MC,
> + REG_EMC,
> + REG_EMC0,
> + REG_EMC1,
> +};
> +
> +#define BURST_REGS_PER_CH_LIST \
> +{ \
> + DEFINE_REG(REG_EMC0, EMC_MRW10), \
> + DEFINE_REG(REG_EMC1, EMC_MRW10), \
> + DEFINE_REG(REG_EMC0, EMC_MRW11), \
> + DEFINE_REG(REG_EMC1, EMC_MRW11), \
> + DEFINE_REG(REG_EMC0, EMC_MRW12), \
> + DEFINE_REG(REG_EMC1, EMC_MRW12), \
> + DEFINE_REG(REG_EMC0, EMC_MRW13), \
> + DEFINE_REG(REG_EMC1, EMC_MRW13), \
> +}
> +
> +#define BURST_REGS_LIST \
> +{ \
> + DEFINE_REG(REG_EMC, EMC_RC), \
> + DEFINE_REG(REG_EMC, EMC_RFC), \
> + DEFINE_REG(REG_EMC, EMC_RFCPB), \
> + DEFINE_REG(REG_EMC, EMC_REFCTRL2), \
> + DEFINE_REG(REG_EMC, EMC_RFC_SLR), \
> + DEFINE_REG(REG_EMC, EMC_RAS), \
> + DEFINE_REG(REG_EMC, EMC_RP), \
> + DEFINE_REG(REG_EMC, EMC_R2W), \
> + DEFINE_REG(REG_EMC, EMC_W2R), \
> + DEFINE_REG(REG_EMC, EMC_R2P), \
> + DEFINE_REG(REG_EMC, EMC_W2P), \
> + DEFINE_REG(REG_EMC, EMC_R2R), \
> + DEFINE_REG(REG_EMC, EMC_TPPD), \
> + DEFINE_REG(REG_EMC, EMC_CCDMW), \
> + DEFINE_REG(REG_EMC, EMC_RD_RCD), \
> + DEFINE_REG(REG_EMC, EMC_WR_RCD), \
> + DEFINE_REG(REG_EMC, EMC_RRD), \
> + DEFINE_REG(REG_EMC, EMC_REXT), \
> + DEFINE_REG(REG_EMC, EMC_WEXT), \
> + DEFINE_REG(REG_EMC, EMC_WDV_CHK), \
> + DEFINE_REG(REG_EMC, EMC_WDV), \
> + DEFINE_REG(REG_EMC, EMC_WSV), \
> + DEFINE_REG(REG_EMC, EMC_WEV), \
> + DEFINE_REG(REG_EMC, EMC_WDV_MASK), \
> + DEFINE_REG(REG_EMC, EMC_WS_DURATION), \
> + DEFINE_REG(REG_EMC, EMC_WE_DURATION), \
> + DEFINE_REG(REG_EMC, EMC_QUSE), \
> + DEFINE_REG(REG_EMC, EMC_QUSE_WIDTH), \
> + DEFINE_REG(REG_EMC, EMC_IBDLY), \
> + DEFINE_REG(REG_EMC, EMC_OBDLY), \
> + DEFINE_REG(REG_EMC, EMC_EINPUT), \
> + DEFINE_REG(REG_EMC, EMC_MRW6), \
> + DEFINE_REG(REG_EMC, EMC_EINPUT_DURATION), \
> + DEFINE_REG(REG_EMC, EMC_PUTERM_EXTRA), \
> + DEFINE_REG(REG_EMC, EMC_PUTERM_WIDTH), \
> + DEFINE_REG(REG_EMC, EMC_QRST), \
> + DEFINE_REG(REG_EMC, EMC_QSAFE), \
> + DEFINE_REG(REG_EMC, EMC_RDV), \
> + DEFINE_REG(REG_EMC, EMC_RDV_MASK), \
> + DEFINE_REG(REG_EMC, EMC_RDV_EARLY), \
> + DEFINE_REG(REG_EMC, EMC_RDV_EARLY_MASK), \
> + DEFINE_REG(REG_EMC, EMC_REFRESH), \
> + DEFINE_REG(REG_EMC, EMC_BURST_REFRESH_NUM), \
> + DEFINE_REG(REG_EMC, EMC_PRE_REFRESH_REQ_CNT), \
> + DEFINE_REG(REG_EMC, EMC_PDEX2WR), \
> + DEFINE_REG(REG_EMC, EMC_PDEX2RD), \
> + DEFINE_REG(REG_EMC, EMC_PCHG2PDEN), \
> + DEFINE_REG(REG_EMC, EMC_ACT2PDEN), \
> + DEFINE_REG(REG_EMC, EMC_AR2PDEN), \
> + DEFINE_REG(REG_EMC, EMC_RW2PDEN), \
> + DEFINE_REG(REG_EMC, EMC_CKE2PDEN), \
> + DEFINE_REG(REG_EMC, EMC_PDEX2CKE), \
> + DEFINE_REG(REG_EMC, EMC_PDEX2MRR), \
> + DEFINE_REG(REG_EMC, EMC_TXSR), \
> + DEFINE_REG(REG_EMC, EMC_TXSRDLL), \
> + DEFINE_REG(REG_EMC, EMC_TCKE), \
> + DEFINE_REG(REG_EMC, EMC_TCKESR), \
> + DEFINE_REG(REG_EMC, EMC_TPD), \
> + DEFINE_REG(REG_EMC, EMC_TFAW), \
> + DEFINE_REG(REG_EMC, EMC_TRPAB), \
> + DEFINE_REG(REG_EMC, EMC_TCLKSTABLE), \
> + DEFINE_REG(REG_EMC, EMC_TCLKSTOP), \
> + DEFINE_REG(REG_EMC, EMC_MRW7), \
> + DEFINE_REG(REG_EMC, EMC_TREFBW), \
> + DEFINE_REG(REG_EMC, EMC_ODT_WRITE), \
> + DEFINE_REG(REG_EMC, EMC_FBIO_CFG5), \
> + DEFINE_REG(REG_EMC, EMC_FBIO_CFG7), \
> + DEFINE_REG(REG_EMC, EMC_CFG_DIG_DLL), \
> + DEFINE_REG(REG_EMC, EMC_CFG_DIG_DLL_PERIOD), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_RXRT), \
> + DEFINE_REG(REG_EMC, EMC_CFG_PIPE_1), \
> + DEFINE_REG(REG_EMC, EMC_CFG_PIPE_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_4), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_5), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_4), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_5), \
> + DEFINE_REG(REG_EMC, EMC_MRW8), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_LONG_CMD_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_LONG_CMD_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_LONG_CMD_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_LONG_CMD_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_LONG_CMD_4), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_SHORT_CMD_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_SHORT_CMD_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_SHORT_CMD_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_3), \
> + DEFINE_REG(REG_EMC, EMC_TXDSRVTTGEN), \
> + DEFINE_REG(REG_EMC, EMC_FDPD_CTRL_DQ), \
> + DEFINE_REG(REG_EMC, EMC_FDPD_CTRL_CMD), \
> + DEFINE_REG(REG_EMC, EMC_FBIO_SPARE), \
> + DEFINE_REG(REG_EMC, EMC_ZCAL_INTERVAL), \
> + DEFINE_REG(REG_EMC, EMC_ZCAL_WAIT_CNT), \
> + DEFINE_REG(REG_EMC, EMC_MRS_WAIT_CNT), \
> + DEFINE_REG(REG_EMC, EMC_MRS_WAIT_CNT2), \
> + DEFINE_REG(REG_EMC, EMC_AUTO_CAL_CHANNEL), \
> + DEFINE_REG(REG_EMC, EMC_DLL_CFG_0), \
> + DEFINE_REG(REG_EMC, EMC_DLL_CFG_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_AUTOCAL_CFG_COMMON), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_ZCTRL), \
> + DEFINE_REG(REG_EMC, EMC_CFG), \
> + DEFINE_REG(REG_EMC, EMC_CFG_PIPE), \
> + DEFINE_REG(REG_EMC, EMC_DYN_SELF_REF_CONTROL), \
> + DEFINE_REG(REG_EMC, EMC_QPOP), \
> + DEFINE_REG(REG_EMC, EMC_DQS_BRLSHFT_0), \
> + DEFINE_REG(REG_EMC, EMC_DQS_BRLSHFT_1), \
> + DEFINE_REG(REG_EMC, EMC_CMD_BRLSHFT_2), \
> + DEFINE_REG(REG_EMC, EMC_CMD_BRLSHFT_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_PAD_CFG_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DATA_PAD_RX_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_PAD_RX_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DATA_RX_TERM_MODE), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_RX_TERM_MODE), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_PAD_TX_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DATA_PAD_TX_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_COMMON_PAD_TX_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_VTTGEN_CTRL_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_VTTGEN_CTRL_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_VTTGEN_CTRL_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_BRICK_CTRL_RFU1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_BRICK_CTRL_FDPD), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_BRICK_CTRL_RFU2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DATA_BRICK_CTRL_FDPD), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_BG_BIAS_CTRL_0), \
> + DEFINE_REG(REG_EMC, EMC_CFG_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_4), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_5), \
> + DEFINE_REG(REG_EMC, EMC_CONFIG_SAMPLE_DELAY), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_4), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_5), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_BYPASS), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_PWRD_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_PWRD_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_PWRD_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_CTRL_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_CTRL_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_CTRL_2), \
> + DEFINE_REG(REG_EMC, EMC_TR_TIMING_0), \
> + DEFINE_REG(REG_EMC, EMC_TR_DVFS), \
> + DEFINE_REG(REG_EMC, EMC_TR_CTRL_1), \
> + DEFINE_REG(REG_EMC, EMC_TR_RDV), \
> + DEFINE_REG(REG_EMC, EMC_TR_QPOP), \
> + DEFINE_REG(REG_EMC, EMC_TR_RDV_MASK), \
> + DEFINE_REG(REG_EMC, EMC_MRW14), \
> + DEFINE_REG(REG_EMC, EMC_TR_QSAFE), \
> + DEFINE_REG(REG_EMC, EMC_TR_QRST), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_SETTLE), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_VREF_SETTLE), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_CA_FINE_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_CA_CTRL_MISC), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_CA_CTRL_MISC1), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_CA_VREF_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_QUSE_CORS_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_QUSE_FINE_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_QUSE_CTRL_MISC), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_QUSE_VREF_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_READ_FINE_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_READ_CTRL_MISC), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_READ_VREF_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_WRITE_FINE_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_WRITE_CTRL_MISC), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_WRITE_VREF_CTRL), \
> + DEFINE_REG(REG_EMC, EMC_TRAINING_MPC), \
> + DEFINE_REG(REG_EMC, EMC_MRW15), \
> +}
> +
> +#define TRIM_REGS_PER_CH_LIST \
> +{ \
> + DEFINE_REG(REG_EMC0, EMC_CMD_BRLSHFT_0), \
> + DEFINE_REG(REG_EMC1, EMC_CMD_BRLSHFT_1), \
> + DEFINE_REG(REG_EMC0, EMC_DATA_BRLSHFT_0), \
> + DEFINE_REG(REG_EMC1, EMC_DATA_BRLSHFT_0), \
> + DEFINE_REG(REG_EMC0, EMC_DATA_BRLSHFT_1), \
> + DEFINE_REG(REG_EMC1, EMC_DATA_BRLSHFT_1), \
> + DEFINE_REG(REG_EMC0, EMC_QUSE_BRLSHFT_0), \
> + DEFINE_REG(REG_EMC1, EMC_QUSE_BRLSHFT_1), \
> + DEFINE_REG(REG_EMC0, EMC_QUSE_BRLSHFT_2), \
> + DEFINE_REG(REG_EMC1, EMC_QUSE_BRLSHFT_3), \
> +}
> +
> +#define TRIM_REGS_LIST \
> +{ \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_VREF_DQS_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_VREF_DQS_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_VREF_DQ_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_VREF_DQ_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_3), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_0), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_1), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_2), \
> + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_3), \
> +}
> +
> +#define BURST_MC_REGS_LIST \
> +{ \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_CFG), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_OUTSTANDING_REQ), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_REFPB_HP_CTRL), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_REFPB_BANK_CTRL), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RCD), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RP), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RC), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RAS), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_FAW), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RRD), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RAP2PRE), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_WAP2PRE), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_R2R), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_W2W), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_R2W), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_CCDMW), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_W2R), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RFCPB), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_DA_TURNS), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_DA_COVERS), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_MISC0), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_MISC1), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_MISC2), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_RING1_THROTTLE), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_CTRL), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6), \
> + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7), \
> +}
> +
> +#define BURST_UP_DOWN_REGS_LIST \
> +{ \
> + DEFINE_REG(REG_MC, MC_MLL_MPCORER_PTSA_RATE), \
> + DEFINE_REG(REG_MC, MC_FTOP_PTSA_RATE), \
> + DEFINE_REG(REG_MC, MC_PTSA_GRANT_DECREMENT), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_XUSB_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_XUSB_1), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_TSEC_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_SDMMCA_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_SDMMCAA_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_SDMMC_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_SDMMCAB_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_PPCS_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_PPCS_1), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_MPCORE_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_HC_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_HC_1), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_AVPC_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_GPU_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_GPU2_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_NVENC_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_NVDEC_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_VIC_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_VI2_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_ISP2_0), \
> + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_ISP2_1), \
> +}
> +
> +#define VREF_REGS_PER_CH_LIST \
> +{ \
> + DEFINE_REG(REG_EMC0, EMC_TRAINING_OPT_DQS_IB_VREF_RANK0), \
> + DEFINE_REG(REG_EMC1, EMC_TRAINING_OPT_DQS_IB_VREF_RANK0), \
> + DEFINE_REG(REG_EMC0, EMC_TRAINING_OPT_DQS_IB_VREF_RANK1), \
> + DEFINE_REG(REG_EMC1, EMC_TRAINING_OPT_DQS_IB_VREF_RANK1), \
> +}
> +
> +#define DEFINE_REG(type, reg) reg##_INDEX
> +enum BURST_REGS_LIST;
> +enum TRIM_REGS_LIST;
> +enum BURST_MC_REGS_LIST;
> +enum BURST_UP_DOWN_REGS_LIST;
> +#undef DEFINE_REG
> +
> +#define DEFINE_REG(type, reg) type##_##reg##_INDEX
> +enum BURST_REGS_PER_CH_LIST;
> +enum TRIM_REGS_PER_CH_LIST;
> +enum VREF_REGS_PER_CH_LIST;
> +#undef DEFINE_REG
> +
> +enum {
> + DRAM_TYPE_DDR3 = 0,
> + DRAM_TYPE_LPDDR4 = 1,
> + DRAM_TYPE_LPDDR2 = 2,
> + DRAM_TYPE_DDR2 = 3,
> +};
> +
> +struct emc_table {
> + u32 rev;
> + char dvfs_ver[60];
> + u32 rate;
> + u32 min_volt;
> + u32 gpu_min_volt;
> + char clock_src[32];
> + u32 clk_src_emc;
> + u32 needs_training;
> + u32 training_parttern;
> + u32 trained;
> +
> + u32 periodic_training;
> + u32 trained_dram_clktree_c0d0u0;
> + u32 trained_dram_clktree_c0d0u1;
> + u32 trained_dram_clktree_c0d1u0;
> + u32 trained_dram_clktree_c0d1u1;
> + u32 trained_dram_clktree_c1d0u0;
> + u32 trained_dram_clktree_c1d0u1;
> + u32 trained_dram_clktree_c1d1u0;
> + u32 trained_dram_clktree_c1d1u1;
> + u32 current_dram_clktree_c0d0u0;
> + u32 current_dram_clktree_c0d0u1;
> + u32 current_dram_clktree_c0d1u0;
> + u32 current_dram_clktree_c0d1u1;
> + u32 current_dram_clktree_c1d0u0;
> + u32 current_dram_clktree_c1d0u1;
> + u32 current_dram_clktree_c1d1u0;
> + u32 current_dram_clktree_c1d1u1;
> + u32 run_clocks;
> + u32 tree_margin;
> +
> + u32 num_burst;
> + u32 num_burst_per_ch;
> + u32 num_trim;
> + u32 num_trim_per_ch;
> + u32 num_mc_regs;
> + u32 num_up_down;
> + u32 vref_num;
> + u32 training_mod_num;
> + u32 dram_timing_num;
> +
> + u32 ptfv_list[12];
> +
> + u32 burst_regs[221];
> + u32 burst_reg_per_ch[8];
> + u32 shadow_regs_ca_train[221];
> + u32 shadow_regs_quse_train[221];
> + u32 shadow_regs_rdwr_train[221];
> +
> + u32 trim_regs[138];
> + u32 trim_perch_regs[10];
> +
> + u32 vref_perch_regs[4];
> +
> + u32 dram_timings[5];
> + u32 training_mod_regs[20];
> + u32 save_restore_mod_regs[12];
> + u32 burst_mc_regs[33];
> + u32 la_scale_regs[24];
> +
> + u32 min_mrs_wait;
> + u32 emc_mrw;
> + u32 emc_mrw2;
> + u32 emc_mrw3;
> + u32 emc_mrw4;
> + u32 emc_mrw9;
> + u32 emc_mrs;
> + u32 emc_emrs;
> + u32 emc_emrs2;
> + u32 emc_auto_cal_config;
> + u32 emc_auto_cal_config2;
> + u32 emc_auto_cal_config3;
> + u32 emc_auto_cal_config4;
> + u32 emc_auto_cal_config5;
> + u32 emc_auto_cal_config6;
> + u32 emc_auto_cal_config7;
> + u32 emc_auto_cal_config8;
> + u32 emc_cfg_2;
> + u32 emc_sel_dpd_ctrl;
> + u32 emc_fdpd_ctrl_cmd_no_ramp;
> + u32 dll_clk_src;
> + u32 clk_out_enb_x_0_clk_enb_emc_dll;
> + u32 latency;
> +};
> +
> +struct tegra_emc {
> + struct clk_hw hw;
> + struct clk *emc_clk;
> + struct device *dev;
> +
> + struct tegra_mc *mc;
> +
> + void __iomem *emc_base;
> + void __iomem *emc0_base;
> + void __iomem *emc1_base;
> +
> + struct emc_table *current_timing;
> + struct emc_table *next_timing;
> + struct emc_table start_timing;
> +
> + struct emc_table *emc_table;
> + struct emc_table *emc_table_normal;
> + struct emc_table *emc_table_derated;
> +
> + unsigned int emc_table_size;
> +
> + int dram_dev_num;
> + u32 dram_type;
> + u32 ram_code;
> + u32 clk_setting;
> +};
> +#define to_emc(_hw) container_of(_hw, struct tegra_emc, hw)
> +
> +struct supported_sequence {
> + u8 table_rev;
> + void (*set_clock)(struct tegra_emc *emc, u32 clksrc);
> + u32 (*periodic_compensation)(struct tegra_emc *emc);
> + char *seq_rev;
> +};
> +
> +int tegra_emc_dt_parse_pdata(struct platform_device *pdev,
> + struct emc_table **tables,
> + struct emc_table **derated_tables,
> + int *num_entries);
> +
> +#endif
> diff --git a/drivers/memory/tegra/tegra210-emc.c b/drivers/memory/tegra/tegra210-emc.c
> new file mode 100644
> index 000000000000..0c20bcd0e6de
> --- /dev/null
> +++ b/drivers/memory/tegra/tegra210-emc.c
> @@ -0,0 +1,886 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2015-2019, NVIDIA CORPORATION. All rights reserved.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk/tegra.h>
> +#include <linux/clk-provider.h>
> +#include <linux/debugfs.h>
> +#include <linux/delay.h>
> +#include <linux/kernel.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <soc/tegra/fuse.h>
> +#include <soc/tegra/mc.h>
> +
> +#include "mc.h"
> +#include "tegra210-emc-reg.h"
> +
> +#define TEGRA_EMC_TABLE_MAX_SIZE 16
> +#define TEGRA210_EMC_SUSPEND_RATE 204000000
> +
> +enum TEGRA_EMC_SOURCE {
> + TEGRA_EMC_SRC_PLLM,
> + TEGRA_EMC_SRC_PLLC,
> + TEGRA_EMC_SRC_PLLP,
> + TEGRA_EMC_SRC_CLKM,
> + TEGRA_EMC_SRC_PLLM_UD,
> + TEGRA_EMC_SRC_PLLMB_UD,
> + TEGRA_EMC_SRC_PLLMB,
> + TEGRA_EMC_SRC_PLLP_UD,
> + TEGRA_EMC_SRC_COUNT,
> +};
> +
> +struct emc_sel {
> + struct clk *input;
> + u32 value;
> + unsigned long input_rate;
> +
> + struct clk *input_b;
> + u32 value_b;
> + unsigned long input_rate_b;
> +};
> +
> +struct emc_stats {
> + u64 time_at_clock[TEGRA_EMC_TABLE_MAX_SIZE];
> + int last_sel;
> + u64 last_update;
> + u64 clkchange_count;
> + spinlock_t spinlock;
> +};
> +
> +static struct emc_sel *emc_clk_sel;
> +static struct clk *emc_src[TEGRA_EMC_SRC_COUNT];
> +static const char *emc_src_names[TEGRA_EMC_SRC_COUNT] = {
> + [TEGRA_EMC_SRC_PLLM] = "pll_m",
> + [TEGRA_EMC_SRC_PLLC] = "pll_c",
> + [TEGRA_EMC_SRC_PLLP] = "pll_p",
> + [TEGRA_EMC_SRC_CLKM] = "clk_m",
> + [TEGRA_EMC_SRC_PLLM_UD] = "pll_m_ud",
> + [TEGRA_EMC_SRC_PLLMB_UD] = "pll_mb_ud",
> + [TEGRA_EMC_SRC_PLLMB] = "pll_mb",
> + [TEGRA_EMC_SRC_PLLP_UD] = "pll_p_ud",
> +};
> +static struct emc_stats emc_stats;
> +static struct supported_sequence supported_seqs[] = {
> + {
> + 0,
> + NULL,
> + NULL,
> + NULL
> + }
> +};
> +static struct supported_sequence *seq;
> +static struct tegra_emc *tegra_emc;
> +static DEFINE_SPINLOCK(emc_access_lock);
> +static ktime_t clkchange_time;
> +static int clkchange_delay = 100;
> +
> +static void emc_train(struct timer_list *tmr);
> +DEFINE_TIMER(emc_training_timer, emc_train);
> +static u32 timer_period_training = 100;
> +
> +#define DEFINE_REG(type, reg) (reg)
> +u32 burst_regs_per_ch_off[] = BURST_REGS_PER_CH_LIST;
> +u32 burst_regs_off[] = BURST_REGS_LIST;
> +u32 burst_mc_regs_off[] = BURST_MC_REGS_LIST;
> +u32 la_scale_regs_off[] = BURST_UP_DOWN_REGS_LIST;
> +u32 trim_regs_per_ch_off[] = TRIM_REGS_PER_CH_LIST;
> +u32 trim_regs_off[] = TRIM_REGS_LIST;
> +u32 vref_regs_per_ch_off[] = VREF_REGS_PER_CH_LIST;
> +#undef DEFINE_REG
> +
> +#define DEFINE_REG(type, reg) (type)
> +u32 burst_regs_per_ch_type[] = BURST_REGS_PER_CH_LIST;
> +u32 trim_regs_per_ch_type[] = TRIM_REGS_PER_CH_LIST;
> +u32 vref_regs_per_ch_type[] = VREF_REGS_PER_CH_LIST;
> +#undef DEFINE_REG
> +
> +#ifdef CONFIG_PM_SLEEP
> +static bool emc_suspend;
> +static unsigned long emc_resume_rate;
> +#endif
> +
> +inline u32 emc_readl(struct tegra_emc *emc, unsigned long offset)
> +{
> + return readl(emc->emc_base + offset);
> +}
> +
> +inline u32 emc_readl_per_ch(struct tegra_emc *emc, int type,
> + unsigned long offset)
> +{
> + u32 val = 0;
> +
> + switch (type) {
> + case REG_EMC:
> + case REG_EMC0:
> + val = readl(emc->emc_base + offset);
> + break;
> + case REG_EMC1:
> + val = readl(emc->emc1_base + offset);
> + break;
> + }
> +
> + return val;
> +}
> +
> +static inline u32 emc_src_val(u32 val)
> +{
> + return (val & EMC_CLK_EMC_2X_CLK_SRC_MASK) >>
> + EMC_CLK_EMC_2X_CLK_SRC_SHIFT;
> +}
> +
> +static inline u32 emc_div_val(u32 val)
> +{
> + return (val & EMC_CLK_EMC_2X_CLK_DIVISOR_MASK) >>
> + EMC_CLK_EMC_2X_CLK_DIVISOR_SHIFT;
> +}
> +
> +static void emc_train(struct timer_list *tmr)
> +{
> + unsigned long flags;
> + struct tegra_emc *emc = tegra_emc;
Looks like you could embed timer into "struct tegra_emc" and then the global variable won't be needed.
> +
> + if (!emc->current_timing)
> + return;
> +
> + spin_lock_irqsave(&emc_access_lock, flags);
> + if (seq->periodic_compensation)
> + seq->periodic_compensation(emc);
> + spin_unlock_irqrestore(&emc_access_lock, flags);
> +
> + mod_timer(&emc_training_timer,
> + jiffies + msecs_to_jiffies(timer_period_training));
> +}
> +
> +static void emc_training_timer_start(void)
> +{
> + mod_timer(&emc_training_timer,
> + jiffies + msecs_to_jiffies(timer_period_training));
> +}
> +
> +static void emc_training_timer_stop(void)
> +{
> + del_timer(&emc_training_timer);
> +}
> +
> +static void emc_set_clock(struct tegra_emc *emc, u32 clksrc)
> +{
> + seq->set_clock(emc, clksrc);
> +
> + if (emc->next_timing->periodic_training)
> + emc_training_timer_start();
> + else
> + emc_training_timer_stop();
> +}
> +
> +static inline void emc_get_timing(struct tegra_emc *emc,
> + struct emc_table *timing)
> +{
> + int i, div;
> + u32 val;
> + unsigned long rate;
> +
> + for (i = 0; i < timing->num_burst; i++) {
> + if (burst_regs_off[i])
> + timing->burst_regs[i] = emc_readl(emc,
> + burst_regs_off[i]);
> + else
> + timing->burst_regs[i] = 0;
> + }
> +
> + for (i = 0; i < timing->num_burst_per_ch; i++)
> + timing->burst_reg_per_ch[i] = emc_readl_per_ch(emc,
> + burst_regs_per_ch_type[i], burst_regs_per_ch_off[i]);
> +
> + for (i = 0; i < timing->num_trim; i++)
> + timing->trim_regs[i] = emc_readl(emc, trim_regs_off[i]);
> +
> + for (i = 0; i < timing->num_trim_per_ch; i++)
> + timing->trim_perch_regs[i] = emc_readl_per_ch(emc,
> + trim_regs_per_ch_type[i], trim_regs_per_ch_off[i]);
> +
> + for (i = 0; i < timing->vref_num; i++)
> + timing->vref_perch_regs[i] = emc_readl_per_ch(emc,
> + vref_regs_per_ch_type[i], vref_regs_per_ch_off[i]);
> +
> + for (i = 0; i < timing->num_mc_regs; i++)
> + timing->burst_mc_regs[i] = mc_readl(emc->mc,
> + burst_mc_regs_off[i]);
> +
> + for (i = 0; i < timing->num_up_down; i++)
> + timing->la_scale_regs[i] = mc_readl(emc->mc,
> + la_scale_regs_off[i]);
> +
> + val = tegra210_clk_emc_get_setting();
> + rate = clk_get_rate(emc_src[emc_src_val(val)]);
> + div = emc_div_val(val);
> + div += 2;
> + rate *= 2;
> + rate += div - 1;
> + do_div(rate, div);
> + timing->rate = rate / 1000;
> +}
> +
> +static void __emc_copy_table_params(struct emc_table *src,
> + struct emc_table *dst, int flags)
> +{
> + int i;
> +
> + if (flags & EMC_COPY_TABLE_PARAM_PERIODIC_FIELDS) {
> + dst->trained_dram_clktree_c0d0u0 =
> + src->trained_dram_clktree_c0d0u0;
> + dst->trained_dram_clktree_c0d0u1 =
> + src->trained_dram_clktree_c0d0u1;
> + dst->trained_dram_clktree_c0d1u0 =
> + src->trained_dram_clktree_c0d1u0;
> + dst->trained_dram_clktree_c0d1u1 =
> + src->trained_dram_clktree_c0d1u1;
> + dst->trained_dram_clktree_c1d0u0 =
> + src->trained_dram_clktree_c1d0u0;
> + dst->trained_dram_clktree_c1d0u1 =
> + src->trained_dram_clktree_c1d0u1;
> + dst->trained_dram_clktree_c1d1u0 =
> + src->trained_dram_clktree_c1d1u0;
> + dst->trained_dram_clktree_c1d1u1 =
> + src->trained_dram_clktree_c1d1u1;
> + dst->current_dram_clktree_c0d0u0 =
> + src->current_dram_clktree_c0d0u0;
> + dst->current_dram_clktree_c0d0u1 =
> + src->current_dram_clktree_c0d0u1;
> + dst->current_dram_clktree_c0d1u0 =
> + src->current_dram_clktree_c0d1u0;
> + dst->current_dram_clktree_c0d1u1 =
> + src->current_dram_clktree_c0d1u1;
> + dst->current_dram_clktree_c1d0u0 =
> + src->current_dram_clktree_c1d0u0;
> + dst->current_dram_clktree_c1d0u1 =
> + src->current_dram_clktree_c1d0u1;
> + dst->current_dram_clktree_c1d1u0 =
> + src->current_dram_clktree_c1d1u0;
> + dst->current_dram_clktree_c1d1u1 =
> + src->current_dram_clktree_c1d1u1;
> + }
> +
> + if (flags & EMC_COPY_TABLE_PARAM_TRIM_REGS) {
> + for (i = 0; i < src->num_trim_per_ch; i++)
> + dst->trim_perch_regs[i] = src->trim_perch_regs[i];
> +
> + for (i = 0; i < src->num_trim; i++)
> + dst->trim_regs[i] = src->trim_regs[i];
> +
> + for (i = 0; i < src->num_burst_per_ch; i++)
> + dst->burst_reg_per_ch[i] = src->burst_reg_per_ch[i];
> +
> + dst->trained = src->trained;
> + }
> +}
> +
> +static void emc_copy_table_params(struct emc_table *src,
> + struct emc_table *dst,
> + int table_size,
> + int flags)
> +{
> + int i;
> +
> + for (i = 0; i < table_size; i++)
> + __emc_copy_table_params(&src[i], &dst[i], flags);
> +}
> +
> +static void emc_last_stats_update(int last_sel)
> +{
> + unsigned long flags;
> + u64 cur_jiffies = get_jiffies_64();
> +
> + spin_lock_irqsave(&emc_stats.spinlock, flags);
> +
> + if (emc_stats.last_sel < TEGRA_EMC_TABLE_MAX_SIZE)
> + emc_stats.time_at_clock[emc_stats.last_sel] =
> + emc_stats.time_at_clock[emc_stats.last_sel]
> + + (cur_jiffies - emc_stats.last_update);
> +
> + emc_stats.last_update = cur_jiffies;
> +
> + if (last_sel < TEGRA_EMC_TABLE_MAX_SIZE) {
> + emc_stats.clkchange_count++;
> + emc_stats.last_sel = last_sel;
> + }
> +
> + spin_unlock_irqrestore(&emc_stats.spinlock, flags);
> +}
> +
> +static int emc_table_lookup(struct tegra_emc *emc, unsigned long rate)
> +{
> + int i;
> +
> + for (i = 0; i < emc->emc_table_size; i++) {
> + if (emc_clk_sel[i].input == NULL)
> + continue;
> +
> + if (emc->emc_table[i].rate == rate)
> + return i;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static struct clk *emc_predict_parent(struct tegra_emc *emc,
> + unsigned long rate)
> +{
> + struct clk *old_parent, *new_parent;
> + unsigned long parent_rate;
> + int idx;
> +
> + idx = emc_table_lookup(emc, rate / 1000);
> + if (idx < 0)
> + return ERR_PTR(-EINVAL);
> +
> + parent_rate = emc_clk_sel[idx].input_rate * 1000;
> + new_parent = emc_clk_sel[idx].input;
> + old_parent = clk_get_parent(emc->emc_clk);
> +
> + if (parent_rate == clk_get_rate(old_parent))
> + return old_parent;
> +
> + if (clk_is_match(new_parent, old_parent))
> + new_parent = emc_clk_sel[idx].input_b;
> +
> + if (parent_rate != clk_get_rate(new_parent))
> + clk_set_rate(new_parent, parent_rate);
> +
> + return new_parent;
> +}
> +
> +static int emc_set_rate(struct tegra_emc *emc, unsigned long rate)
> +{
> + int i;
> + unsigned long flags;
> + s64 last_change_delay;
> + struct clk *parent;
> +
> + if (emc_suspend)
> + rate = TEGRA210_EMC_SUSPEND_RATE;
> +
> + if (rate == emc->current_timing->rate)
> + return 0;
> +
> + i = emc_table_lookup(emc, rate / 1000);
> +
> + if (i < 0)
> + return i;
> +
> + if (rate > 204000000 && !emc->emc_table[i].trained)
> + return -EINVAL;
> +
> + parent = emc_predict_parent(emc, rate);
> + if (clk_is_match(parent, emc_clk_sel[i].input))
> + emc->clk_setting = emc_clk_sel[i].value;
> + else
> + emc->clk_setting = emc_clk_sel[i].value_b;
> +
> + emc->next_timing = &emc->emc_table[i];
> + last_change_delay = ktime_us_delta(ktime_get(), clkchange_time);
> + if ((last_change_delay >= 0) && (last_change_delay < clkchange_delay))
> + udelay(clkchange_delay - (int)last_change_delay);
> +
> + spin_lock_irqsave(&emc_access_lock, flags);
> + emc_set_clock(emc, emc->clk_setting);
> + clkchange_time = ktime_get();
> + emc->current_timing = &emc->emc_table[i];
> + spin_unlock_irqrestore(&emc_access_lock, flags);
> +
> + emc_last_stats_update(i);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_DEBUG_FS
> +static int emc_stats_show(struct seq_file *s, void *data)
> +{
> + int i;
> + struct tegra_emc *emc = (struct tegra_emc *)s->private;
> +
> + if (!emc->emc_table_size || !seq)
> + return 0;
> +
> + emc_last_stats_update(TEGRA_EMC_TABLE_MAX_SIZE);
> +
> + seq_printf(s, "%-10s %-10s\n", "rate kHz", "time");
> + for (i = 0; i < emc->emc_table_size; i++) {
> + if (emc_clk_sel[i].input == NULL)
> + continue;
> +
> + seq_printf(s, "%-10u %-10llu\n",
> + emc->emc_table[i].rate,
> + jiffies_64_to_clock_t(
> + emc_stats.time_at_clock[i]));
> + }
> + seq_printf(s, "%-15s %llu\n", "transitions:",
> + emc_stats.clkchange_count);
> + seq_printf(s, "%-15s %llu\n", "time-stamp:",
> + jiffies_64_to_clock_t(emc_stats.last_update));
> +
> + return 0;
> +}
> +
> +static int emc_stats_open(struct inode *inode, struct file *file)
> +{
> + return single_open(file, emc_stats_show, inode->i_private);
> +}
> +
> +static const struct file_operations emc_stats_fops = {
> + .open = emc_stats_open,
> + .read = seq_read,
> + .llseek = seq_lseek,
> + .release = single_release,
> +};
> +
> +static int debug_emc_get_rate(void *data, u64 *val)
> +{
> + struct clk *c = data;
> +
> + *val = clk_get_rate(c);
> +
> + return 0;
> +}
> +
> +static int debug_emc_set_rate(void *data, u64 val)
> +{
> + struct clk *c = data;
> +
> + return clk_set_rate(c, val);
> +}
> +DEFINE_SIMPLE_ATTRIBUTE(emc_rate_fops, debug_emc_get_rate,
> + debug_emc_set_rate, "%llu\n");
> +
> +static int tegra_emc_debug_init(struct tegra_emc *emc)
> +{
> + struct dentry *emc_debugfs_root;
> +
> + emc_debugfs_root = debugfs_create_dir("tegra_emc", NULL);
> + if (!emc_debugfs_root)
> + return -ENOMEM;
> +
> + if (!debugfs_create_file("stats", 0444, emc_debugfs_root, emc,
> + &emc_stats_fops))
> + goto err_out;
> +
> + if (!debugfs_create_file("rate", 0644, emc_debugfs_root, emc->emc_clk,
> + &emc_rate_fops))
> + goto err_out;
> +
> + return 0;
> +
> +err_out:
> + debugfs_remove_recursive(emc_debugfs_root);
> + return -ENOMEM;
> +}
> +#endif /* CONFIG_DEBUG_FS */
Every downstream EMC driver has this debugfs, but is it useful for upstream? I think it should be generalized and made re-usable by all of the EMC drivers if it has a real value, otherwise it could be dropped.
> +static u8 clk_emc_get_parent(struct clk_hw *hw)
> +{
> + struct tegra_emc *emc = to_emc(hw);
> +
> + if (!emc->clk_setting)
> + emc->clk_setting = tegra210_clk_emc_get_setting();
> +
> + return emc_src_val(emc->clk_setting);
> +}
> +
> +static unsigned long clk_emc_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct tegra_emc *emc = to_emc(hw);
> +
> + if (!emc->emc_table_size || !seq) {
> + u32 emc_setting = tegra210_clk_emc_get_setting();
> +
> + return clk_get_rate(emc_src[emc_src_val(emc_setting)]);
> + }
> +
> + return emc->current_timing->rate * 1000;
> +}
> +
> +static long clk_emc_round_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long *prate)
> +{
> + struct tegra_emc *emc = to_emc(hw);
> + int i;
> +
> + if (!emc->emc_table_size || !seq) {
> + u32 emc_setting = tegra210_clk_emc_get_setting();
> +
> + return clk_get_rate(emc_src[emc_src_val(emc_setting)]);
> + }
> +
> + if (emc_suspend)
> + return TEGRA210_EMC_SUSPEND_RATE;
> +
> + rate /= 1000;
> +
> + for (i = 0; i < emc->emc_table_size; i++) {
> + if (emc->emc_table[i].rate >= rate)
> + return emc->emc_table[i].rate * 1000;
> + }
> +
> + return emc->emc_table[i - 1].rate * 1000;
> +}
> +
> +static int clk_emc_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + struct tegra_emc *emc = to_emc(hw);
> + struct clk *old_parent, *new_parent;
> + int ret = -EINVAL;
> +
> + if (!emc->emc_table_size || !seq)
> + return ret;
> +
> + if (emc_suspend)
> + rate = TEGRA210_EMC_SUSPEND_RATE;
> +
> + old_parent = clk_get_parent(hw->clk);
> + new_parent = emc_predict_parent(emc, rate);
> + if (IS_ERR(new_parent))
> + goto out;
> +
> + if (!clk_is_match(new_parent, old_parent))
> + clk_prepare_enable(new_parent);
> +
> + ret = emc_set_rate(emc, rate);
> + if (ret) {
> + if (new_parent != old_parent)
> + clk_disable_unprepare(new_parent);
> + goto out;
> + }
> +
> + if (!clk_is_match(new_parent, old_parent)) {
> + clk_hw_reparent(hw, __clk_get_hw(new_parent));
> + clk_disable_unprepare(old_parent);
> + }
> +
> +out:
> + return ret;
> +}
> +
> +static const struct clk_ops tegra_clk_emc_ops = {
> + .get_parent = clk_emc_get_parent,
> + .recalc_rate = clk_emc_recalc_rate,
> + .round_rate = clk_emc_round_rate,
> + .set_rate = clk_emc_set_rate,
> +};
Couldn't the "best parent" be selected using the determine_rate() callback and then the rate and parent be applied using set_rate_and_parent(), replacing the set_rate()? It looks like you're re-implementing something that CLK framework already has support for.
> +
> +static int find_matching_input(struct emc_table *table, struct emc_sel *sel)
> +{
> + u32 div_value;
> + u32 src_value;
> + unsigned long input_rate = 0;
> + struct clk *input_clk;
> +
> + div_value = emc_div_val(table->clk_src_emc);
> + src_value = emc_src_val(table->clk_src_emc);
> +
> + if (div_value & 0x1) {
> + pr_warn("Tegra EMC: invalid odd divider for EMC rate %u\n",
> + table->rate);
> + return -EINVAL;
> + }
> +
> + if (!(table->clk_src_emc & EMC_CLK_MC_EMC_SAME_FREQ) !=
> + !(MC_EMEM_ARB_MISC0_EMC_SAME_FREQ &
> + table->burst_regs[MC_EMEM_ARB_MISC0_INDEX])) {
> + pr_warn("Tegra EMC: ambiguous EMC to MC ratio for rate %u\n",
> + table->rate);
> + return -EINVAL;
> + }
> +
> + input_clk = emc_src[src_value];
> + if (input_clk == emc_src[TEGRA_EMC_SRC_PLLM]
> + || input_clk == emc_src[TEGRA_EMC_SRC_PLLM_UD]) {
> + input_rate = table->rate * (1 + div_value / 2);
> + } else {
> + input_rate = clk_get_rate(input_clk) / 1000;
> + if (input_rate != (table->rate * (1 + div_value / 2))) {
> + pr_warn("Tegra EMC: rate %u doesn't match input\n",
> + table->rate);
> + return -EINVAL;
> + }
> + }
> +
> + sel->input = input_clk;
> + sel->input_rate = input_rate;
> + sel->value = table->clk_src_emc;
> + sel->input_b = input_clk;
> + sel->input_rate_b = input_rate;
> + sel->value_b = table->clk_src_emc;
> +
> + if (input_clk == emc_src[TEGRA_EMC_SRC_PLLM]) {
> + sel->input_b = emc_src[TEGRA_EMC_SRC_PLLMB];
> + sel->value_b = table->clk_src_emc &
> + ~EMC_CLK_EMC_2X_CLK_SRC_MASK;
> + sel->value_b |= TEGRA_EMC_SRC_PLLMB <<
> + EMC_CLK_EMC_2X_CLK_SRC_SHIFT;
> + }
> +
> + if (input_clk == emc_src[TEGRA_EMC_SRC_PLLM_UD]) {
> + sel->input_b = emc_src[TEGRA_EMC_SRC_PLLMB_UD];
> + sel->value_b = table->clk_src_emc &
> + ~EMC_CLK_EMC_2X_CLK_SRC_MASK;
> + sel->value_b |= TEGRA_EMC_SRC_PLLMB_UD <<
> + EMC_CLK_EMC_2X_CLK_SRC_SHIFT;
> + }
> +
> + return 0;
> +}
> +
> +static int tegra210_emc_probe(struct platform_device *pdev)
> +{
> + int i, div;
> + unsigned long table_rate;
> + unsigned long current_rate;
> + struct device_node *np;
> + struct platform_device *mc;
> + struct tegra_emc *emc;
> + struct clk_init_data init;
> + struct clk *clk;
> + struct resource *r;
> + u32 emc_setting;
> +
> + emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
> + if (!emc)
> + return -ENOMEM;
> +
> + np = of_parse_phandle(pdev->dev.of_node, "nvidia,memory-controller", 0);
> + if (!np) {
> + dev_err(&pdev->dev, "could not get memory controller\n");
> + return -ENOENT;
> + }
> +
> + mc = of_find_device_by_node(np);
> + of_node_put(np);
> + if (!mc)
> + return -ENOENT;
> +
> + emc->mc = platform_get_drvdata(mc);
> + if (!emc->mc)
> + return -EPROBE_DEFER;
> +
> + emc->ram_code = tegra_read_ram_code();
> + r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + emc->emc_base = devm_ioremap_resource(&pdev->dev, r);
> + r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> + emc->emc0_base = devm_ioremap_resource(&pdev->dev, r);
> + r = platform_get_resource(pdev, IORESOURCE_MEM, 2);
> + emc->emc1_base = devm_ioremap_resource(&pdev->dev, r);
> +
> + for (i = 0; i < TEGRA_EMC_SRC_COUNT; i++) {
> + emc_src[i] = devm_clk_get(&pdev->dev,
> + emc_src_names[i]);
> + if (IS_ERR(emc_src[i])) {
> + dev_err(&pdev->dev, "Can not find EMC source clock\n");
> + return -ENODATA;
> + }
> + }
> +
> + /* Init EMC rate statistic data */
> + emc_stats.clkchange_count = 0;
> + spin_lock_init(&emc_stats.spinlock);
> + emc_stats.last_update = get_jiffies_64();
> + emc_stats.last_sel = TEGRA_EMC_TABLE_MAX_SIZE;
> +
> + emc->dram_type = (emc_readl(emc, EMC_FBIO_CFG5) &
> + EMC_FBIO_CFG5_DRAM_TYPE_MASK) >>
> + EMC_FBIO_CFG5_DRAM_TYPE_SHIFT;
> + if (emc->dram_type != DRAM_TYPE_DDR3 &&
> + emc->dram_type != DRAM_TYPE_LPDDR2 &&
> + emc->dram_type != DRAM_TYPE_LPDDR4) {
> + dev_err(&pdev->dev, "DRAM not supported\n");
> + return -ENODATA;
> + }
> +
> + emc->dram_dev_num = tegra_mc_get_emem_device_count(emc->mc);
> +
> + tegra_emc_dt_parse_pdata(pdev, &emc->emc_table_normal,
> + &emc->emc_table_derated,
> + &emc->emc_table_size);
> + if (!emc->emc_table_size ||
> + emc->emc_table_size > TEGRA_EMC_TABLE_MAX_SIZE) {
> + dev_err(&pdev->dev, "Invalid table size %d\n",
> + emc->emc_table_size);
> + goto emc_clk_register;
Why do you want to continue and not to error out?
> + }
> + emc->emc_table = emc->emc_table_normal;
> +
> + /*
> + * Copy trained trimmers from the normal table to the derated
> + * table for LP4. Bootloader trains only the normal table.
> + * Trimmers are the same for derated and normal tables.
> + */
> + if (emc->emc_table_derated && emc->dram_type == DRAM_TYPE_LPDDR4)
> + emc_copy_table_params(emc->emc_table_normal,
> + emc->emc_table_derated,
> + emc->emc_table_size,
> + EMC_COPY_TABLE_PARAM_PERIODIC_FIELDS |
> + EMC_COPY_TABLE_PARAM_TRIM_REGS);
> +
> + seq = supported_seqs;
> + while (seq->table_rev) {
> + if (seq->table_rev == emc->emc_table[0].rev)
> + break;
> + seq++;
> + }
> + if (!seq->set_clock) {
> + seq = NULL;
> + dev_err(&pdev->dev, "Invalid EMC sequence for table Rev. %d\n",
> + emc->emc_table[0].rev);
> + goto emc_clk_register;
Same as the above.
> + }
> +
> + emc_clk_sel = devm_kcalloc(&pdev->dev,
> + emc->emc_table_size,
> + sizeof(struct emc_sel),
> + GFP_KERNEL);
> + if (!emc_clk_sel) {
> + dev_err(&pdev->dev, "Memory allocation failed\n");
> + return -ENOMEM;
> + }
> +
> + /* calculate the rate from source clock */
> + emc_setting = tegra210_clk_emc_get_setting();
> + current_rate = clk_get_rate(emc_src[emc_src_val(emc_setting)]);
> + div = emc_div_val(emc_setting);
> + div += 2;
> + current_rate *= 2;
> + current_rate += div - 1;
> + do_div(current_rate, div);
> + current_rate /= 1000;
The same is done in emc_get_timing(), hence it probably worth to factor out this hunk into a function.
> +
> + for (i = 0; i < emc->emc_table_size; i++) {
> + table_rate = emc->emc_table[i].rate;
> + if (!table_rate)
> + continue;
> +
> + if (i && ((table_rate <= emc->emc_table[i-1].rate) ||
> + (emc->emc_table[i].min_volt <
> + emc->emc_table[i-1].min_volt)))
> + continue;
> +
> + if (emc->emc_table[i].rev != emc->emc_table[0].rev)
> + continue;
> +
> + if (find_matching_input(&emc->emc_table[i], &emc_clk_sel[i]))
> + continue;
> +
> + if (table_rate == current_rate)
> + emc_stats.last_sel = i;
> + }
> +
> + dev_info(&pdev->dev, "validated EMC DFS table\n");
It is not possible to fail the validation, hence remove this message?
> + /* Update the start_timing base on the settings from firmware */
> + emc->start_timing.num_burst = emc->emc_table[0].num_burst;
> + emc->start_timing.num_burst_per_ch =
> + emc->emc_table[0].num_burst_per_ch;
> + emc->start_timing.num_trim = emc->emc_table[0].num_trim;
> + emc->start_timing.num_trim_per_ch =
> + emc->emc_table[0].num_trim_per_ch;
> + emc->start_timing.num_mc_regs = emc->emc_table[0].num_mc_regs;
> + emc->start_timing.num_up_down = emc->emc_table[0].num_up_down;
> + emc->start_timing.vref_num = emc->emc_table[0].vref_num;
> +
> + emc_get_timing(emc, &emc->start_timing);
> + emc->current_timing = &emc->start_timing;
> + emc->clk_setting = emc_setting;
> +
> +emc_clk_register:
> + init.name = "emc";
> + init.ops = &tegra_clk_emc_ops;
> + init.flags = CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE;
> + init.parent_names = emc_src_names;
> + init.num_parents = ARRAY_SIZE(emc_src_names);
> + emc->hw.init = &init;
> +
> + clk = clk_register(&pdev->dev, &emc->hw);
> + if (IS_ERR(clk))
> + return PTR_ERR(clk);
> + emc->emc_clk = clk;
> + emc->dev = &pdev->dev;
> + tegra_emc = emc;
> + dev_set_drvdata(emc->dev, emc);
> +
> + if (emc->emc_table_size && seq) {
> + for (i = 0; i < emc->emc_table_size; i++) {
> + table_rate = emc->emc_table[i].rate * 1000;
> + if (clk_set_rate(clk, table_rate))
> + dev_info(&pdev->dev,
> + "rate: %lu validation fail\n",
> + table_rate);
dev_err()? Do you really want to continue in a error case? Is it realistic that clk_set_rate() may suddenly fail, maybe remove this "validation" if not..
> +
> + dev_info(&pdev->dev, "rate: %lu validation success\n",
> + table_rate);
> + }
> + }
> +
> + if (IS_ENABLED(CONFIG_DEBUG_FS))
> + tegra_emc_debug_init(emc);
Apparently compilation will fail if CONFIG_DEBUG_FS is disabled because tegra_emc_debug_init() will be undefined. Seems you should remove #ifdef CONFIG_DEBUG_FS and just allow tegra_emc_debug_init() to fail when CONFIG_DEBUG_FS=n and hence the condition "if (IS_ENABLED(CONFIG_DEBUG_FS))" won't be needed too.
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int tegra210_emc_suspend(struct device *dev)
> +{
> + struct tegra_emc *emc = dev_get_drvdata(dev);
> +
> + if (!IS_ERR(emc->emc_clk)) {
> + emc_suspend = true;
> + emc_resume_rate = clk_get_rate(emc->emc_clk);
> + clk_set_rate(emc->emc_clk, TEGRA210_EMC_SUSPEND_RATE);
> +
> + pr_debug("%s at rate %lu\n", __func__,
> + clk_get_rate(emc->emc_clk));
> + }
> +
> + return 0;
> +}
> +
> +static int tegra210_emc_resume(struct device *dev)
> +{
> + struct tegra_emc *emc = dev_get_drvdata(dev);
> +
> + if (!IS_ERR(emc->emc_clk)) {
When emc->emc_clk may become a PTR_ERR?
> + emc_suspend = false;
> + clk_set_rate(emc->emc_clk, emc_resume_rate);
> +
> + pr_debug("%s at rate %lu\n", __func__,
> + clk_get_rate(emc->emc_clk));
> + }
> +
> + return 0;
> +}
> +
> +static const struct dev_pm_ops tegra210_emc_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(tegra210_emc_suspend, tegra210_emc_resume)
> +};
> +#endif
> +
> +static const struct of_device_id tegra210_emc_of_match[] = {
> + { .compatible = "nvidia,tegra210-emc", },
> + { },
> +};
> +
> +static struct platform_driver tegra210_emc_driver = {
> + .driver = {
> + .name = "tegra210-emc",
> + .of_match_table = tegra210_emc_of_match,
> + .pm = &tegra210_emc_pm_ops,
Compilation will fail with CONFIG_PM_SLEEP=n, just remove the "#ifdef CONFIG_PM_SLEEP".
.suppress_bind_attrs = true,
> + },
> + .probe = tegra210_emc_probe,
> +};
> +
> +static int __init tegra210_emc_init(void)
> +{
> + return platform_driver_register(&tegra210_emc_driver);
> +}
> +subsys_initcall(tegra210_emc_init);
>
next prev parent reply other threads:[~2019-04-03 11:56 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-03-25 7:45 [PATCH 0/8] Add EMC scaling support for Tegra210 Joseph Lo
2019-03-25 7:45 ` [PATCH 1/8] dt-bindings: memory: tegra: Add Tegra210 EMC bindings Joseph Lo
2019-03-31 6:41 ` Rob Herring
2019-04-01 7:57 ` Joseph Lo
2019-04-03 4:26 ` Rob Herring
2019-04-10 2:41 ` Joseph Lo
2019-04-01 12:12 ` Dmitry Osipenko
2019-04-02 2:26 ` Joseph Lo
2019-04-02 10:21 ` Dmitry Osipenko
2019-04-04 9:17 ` Dmitry Osipenko
2019-04-04 9:30 ` Dmitry Osipenko
2019-04-08 8:49 ` Joseph Lo
2019-03-25 7:45 ` [PATCH 2/8] clk: tegra: clock changes for emc scaling support on Tegra210 Joseph Lo
2019-04-03 9:22 ` Thierry Reding
2019-04-08 7:52 ` Joseph Lo
2019-04-08 9:15 ` Peter De Schrijver
2019-03-25 7:45 ` [PATCH 3/8] memory: tegra: Add Tegra210 EMC clock driver Joseph Lo
2019-04-03 11:34 ` Thierry Reding
2019-04-08 9:25 ` Peter De Schrijver
2019-04-03 11:55 ` Dmitry Osipenko [this message]
2019-03-25 7:45 ` [PATCH 4/8] memory: tegra: add EMC scaling support code for Tegra210 Joseph Lo
2019-04-02 11:39 ` Dmitry Osipenko
2019-04-02 14:53 ` Joseph Lo
2019-03-25 7:45 ` [PATCH 5/8] memory: tegra: Add EMC scaling sequence " Joseph Lo
2019-04-02 11:36 ` Dmitry Osipenko
2019-04-02 14:49 ` Joseph Lo
2019-03-25 7:45 ` [PATCH 6/8] arm64: tegra: Add external memory controller node " Joseph Lo
2019-03-29 14:41 ` [PATCH 0/8] Add EMC scaling support " Peter De Schrijver
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=89f6b360-d1d5-d1b9-6b0f-f5e694b1b105@gmail.com \
--to=digetx@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=jonathanh@nvidia.com \
--cc=josephl@nvidia.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=pdeschrijver@nvidia.com \
--cc=robh+dt@kernel.org \
--cc=sboyd@kernel.org \
--cc=thierry.reding@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).