linux/drivers/memory/tegra/tegra30-emc.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Tegra30 External Memory Controller driver
 *
 * Based on downstream driver from NVIDIA and tegra124-emc.c
 * Copyright (C) 2011-2014 NVIDIA Corporation
 *
 * Author: Dmitry Osipenko <[email protected]>
 * Copyright (C) 2019 GRATE-DRIVER project
 */

#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clk/tegra.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interconnect-provider.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/slab.h>
#include <linux/sort.h>
#include <linux/types.h>

#include <soc/tegra/common.h>
#include <soc/tegra/fuse.h>

#include "../jedec_ddr.h"
#include "../of_memory.h"

#include "mc.h"

#define EMC_INTSTATUS
#define EMC_INTMASK
#define EMC_DBG
#define EMC_ADR_CFG
#define EMC_CFG
#define EMC_REFCTRL
#define EMC_TIMING_CONTROL
#define EMC_RC
#define EMC_RFC
#define EMC_RAS
#define EMC_RP
#define EMC_R2W
#define EMC_W2R
#define EMC_R2P
#define EMC_W2P
#define EMC_RD_RCD
#define EMC_WR_RCD
#define EMC_RRD
#define EMC_REXT
#define EMC_WDV
#define EMC_QUSE
#define EMC_QRST
#define EMC_QSAFE
#define EMC_RDV
#define EMC_REFRESH
#define EMC_BURST_REFRESH_NUM
#define EMC_PDEX2WR
#define EMC_PDEX2RD
#define EMC_PCHG2PDEN
#define EMC_ACT2PDEN
#define EMC_AR2PDEN
#define EMC_RW2PDEN
#define EMC_TXSR
#define EMC_TCKE
#define EMC_TFAW
#define EMC_TRPAB
#define EMC_TCLKSTABLE
#define EMC_TCLKSTOP
#define EMC_TREFBW
#define EMC_QUSE_EXTRA
#define EMC_ODT_WRITE
#define EMC_ODT_READ
#define EMC_WEXT
#define EMC_CTT
#define EMC_MRS_WAIT_CNT
#define EMC_MRS
#define EMC_EMRS
#define EMC_SELF_REF
#define EMC_MRW
#define EMC_MRR
#define EMC_XM2DQSPADCTRL3
#define EMC_FBIO_SPARE
#define EMC_FBIO_CFG5
#define EMC_FBIO_CFG6
#define EMC_CFG_RSV
#define EMC_AUTO_CAL_CONFIG
#define EMC_AUTO_CAL_INTERVAL
#define EMC_AUTO_CAL_STATUS
#define EMC_STATUS
#define EMC_CFG_2
#define EMC_CFG_DIG_DLL
#define EMC_CFG_DIG_DLL_PERIOD
#define EMC_CTT_DURATION
#define EMC_CTT_TERM_CTRL
#define EMC_ZCAL_INTERVAL
#define EMC_ZCAL_WAIT_CNT
#define EMC_ZQ_CAL
#define EMC_XM2CMDPADCTRL
#define EMC_XM2DQSPADCTRL2
#define EMC_XM2DQPADCTRL2
#define EMC_XM2CLKPADCTRL
#define EMC_XM2COMPPADCTRL
#define EMC_XM2VTTGENPADCTRL
#define EMC_XM2VTTGENPADCTRL2
#define EMC_XM2QUSEPADCTRL
#define EMC_DLL_XFORM_DQS0
#define EMC_DLL_XFORM_DQS1
#define EMC_DLL_XFORM_DQS2
#define EMC_DLL_XFORM_DQS3
#define EMC_DLL_XFORM_DQS4
#define EMC_DLL_XFORM_DQS5
#define EMC_DLL_XFORM_DQS6
#define EMC_DLL_XFORM_DQS7
#define EMC_DLL_XFORM_QUSE0
#define EMC_DLL_XFORM_QUSE1
#define EMC_DLL_XFORM_QUSE2
#define EMC_DLL_XFORM_QUSE3
#define EMC_DLL_XFORM_QUSE4
#define EMC_DLL_XFORM_QUSE5
#define EMC_DLL_XFORM_QUSE6
#define EMC_DLL_XFORM_QUSE7
#define EMC_DLL_XFORM_DQ0
#define EMC_DLL_XFORM_DQ1
#define EMC_DLL_XFORM_DQ2
#define EMC_DLL_XFORM_DQ3
#define EMC_DLI_TRIM_TXDQS0
#define EMC_DLI_TRIM_TXDQS1
#define EMC_DLI_TRIM_TXDQS2
#define EMC_DLI_TRIM_TXDQS3
#define EMC_DLI_TRIM_TXDQS4
#define EMC_DLI_TRIM_TXDQS5
#define EMC_DLI_TRIM_TXDQS6
#define EMC_DLI_TRIM_TXDQS7
#define EMC_STALL_THEN_EXE_BEFORE_CLKCHANGE
#define EMC_STALL_THEN_EXE_AFTER_CLKCHANGE
#define EMC_UNSTALL_RW_AFTER_CLKCHANGE
#define EMC_SEL_DPD_CTRL
#define EMC_PRE_REFRESH_REQ_CNT
#define EMC_DYN_SELF_REF_CONTROL
#define EMC_TXSRDLL

#define EMC_STATUS_TIMING_UPDATE_STALLED

#define EMC_MODE_SET_DLL_RESET
#define EMC_MODE_SET_LONG_CNT

#define EMC_SELF_REF_CMD_ENABLED

#define DRAM_DEV_SEL_ALL
#define DRAM_DEV_SEL_0
#define DRAM_DEV_SEL_1
#define DRAM_BROADCAST(num)

#define EMC_ZQ_CAL_CMD
#define EMC_ZQ_CAL_LONG
#define EMC_ZQ_CAL_LONG_CMD_DEV0
#define EMC_ZQ_CAL_LONG_CMD_DEV1

#define EMC_DBG_READ_MUX_ASSEMBLY
#define EMC_DBG_WRITE_MUX_ACTIVE
#define EMC_DBG_FORCE_UPDATE
#define EMC_DBG_CFG_PRIORITY

#define EMC_CFG5_QUSE_MODE_SHIFT
#define EMC_CFG5_QUSE_MODE_MASK

#define EMC_CFG5_QUSE_MODE_INTERNAL_LPBK
#define EMC_CFG5_QUSE_MODE_PULSE_INTERN

#define EMC_SEL_DPD_CTRL_QUSE_DPD_ENABLE

#define EMC_XM2COMPPADCTRL_VREF_CAL_ENABLE

#define EMC_XM2QUSEPADCTRL_IVREF_ENABLE

#define EMC_XM2DQSPADCTRL2_VREF_ENABLE
#define EMC_XM2DQSPADCTRL3_VREF_ENABLE

#define EMC_AUTO_CAL_STATUS_ACTIVE

#define EMC_FBIO_CFG5_DRAM_TYPE_MASK

#define EMC_MRS_WAIT_CNT_SHORT_WAIT_MASK
#define EMC_MRS_WAIT_CNT_LONG_WAIT_SHIFT
#define EMC_MRS_WAIT_CNT_LONG_WAIT_MASK

#define EMC_REFCTRL_DEV_SEL_MASK
#define EMC_REFCTRL_ENABLE
#define EMC_REFCTRL_ENABLE_ALL(num)
#define EMC_REFCTRL_DISABLE_ALL(num)

#define EMC_CFG_PERIODIC_QRST
#define EMC_CFG_DYN_SREF_ENABLE

#define EMC_CLKCHANGE_REQ_ENABLE
#define EMC_CLKCHANGE_PD_ENABLE
#define EMC_CLKCHANGE_SR_ENABLE

#define EMC_TIMING_UPDATE

#define EMC_REFRESH_OVERFLOW_INT
#define EMC_CLKCHANGE_COMPLETE_INT
#define EMC_MRR_DIVLD_INT

#define EMC_MRR_DEV_SELECTN
#define EMC_MRR_MRR_MA
#define EMC_MRR_MRR_DATA

#define EMC_ADR_CFG_EMEM_NUMDEV

enum emc_dram_type {};

enum emc_dll_change {};

static const u16 emc_timing_registers[] =;

struct emc_timing {};

enum emc_rate_request_type {};

struct emc_rate_request {};

struct tegra_emc {};

static int emc_seq_update_timing(struct tegra_emc *emc)
{}

static irqreturn_t tegra_emc_isr(int irq, void *data)
{}

static struct emc_timing *emc_find_timing(struct tegra_emc *emc,
					  unsigned long rate)
{}

static bool emc_dqs_preset(struct tegra_emc *emc, struct emc_timing *timing,
			   bool *schmitt_to_vref)
{}

static int emc_prepare_mc_clk_cfg(struct tegra_emc *emc, unsigned long rate)
{}

static int emc_prepare_timing_change(struct tegra_emc *emc, unsigned long rate)
{}

static int emc_complete_timing_change(struct tegra_emc *emc,
				      unsigned long rate)
{}

static int emc_unprepare_timing_change(struct tegra_emc *emc,
				       unsigned long rate)
{}

static int emc_clk_change_notify(struct notifier_block *nb,
				 unsigned long msg, void *data)
{}

static int load_one_timing_from_dt(struct tegra_emc *emc,
				   struct emc_timing *timing,
				   struct device_node *node)
{}

static int cmp_timings(const void *_a, const void *_b)
{}

static int emc_check_mc_timings(struct tegra_emc *emc)
{}

static int emc_load_timings_from_dt(struct tegra_emc *emc,
				    struct device_node *node)
{}

static struct device_node *emc_find_node_by_ram_code(struct tegra_emc *emc)
{}

static int emc_read_lpddr_mode_register(struct tegra_emc *emc,
					unsigned int emem_dev,
					unsigned int register_addr,
					unsigned int *register_data)
{}

static void emc_read_lpddr_sdram_info(struct tegra_emc *emc,
				      unsigned int emem_dev)
{}

static int emc_setup_hw(struct tegra_emc *emc)
{}

static long emc_round_rate(unsigned long rate,
			   unsigned long min_rate,
			   unsigned long max_rate,
			   void *arg)
{}

static void tegra_emc_rate_requests_init(struct tegra_emc *emc)
{}

static int emc_request_rate(struct tegra_emc *emc,
			    unsigned long new_min_rate,
			    unsigned long new_max_rate,
			    enum emc_rate_request_type type)
{}

static int emc_set_min_rate(struct tegra_emc *emc, unsigned long rate,
			    enum emc_rate_request_type type)
{}

static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate,
			    enum emc_rate_request_type type)
{}

/*
 * debugfs interface
 *
 * The memory controller driver exposes some files in debugfs that can be used
 * to control the EMC frequency. The top-level directory can be found here:
 *
 *   /sys/kernel/debug/emc
 *
 * It contains the following files:
 *
 *   - available_rates: This file contains a list of valid, space-separated
 *     EMC frequencies.
 *
 *   - min_rate: Writing a value to this file sets the given frequency as the
 *       floor of the permitted range. If this is higher than the currently
 *       configured EMC frequency, this will cause the frequency to be
 *       increased so that it stays within the valid range.
 *
 *   - max_rate: Similarily to the min_rate file, writing a value to this file
 *       sets the given frequency as the ceiling of the permitted range. If
 *       the value is lower than the currently configured EMC frequency, this
 *       will cause the frequency to be decreased so that it stays within the
 *       valid range.
 */

static bool tegra_emc_validate_rate(struct tegra_emc *emc, unsigned long rate)
{}

static int tegra_emc_debug_available_rates_show(struct seq_file *s, void *data)
{}
DEFINE_SHOW_ATTRIBUTE();

static int tegra_emc_debug_min_rate_get(void *data, u64 *rate)
{}

static int tegra_emc_debug_min_rate_set(void *data, u64 rate)
{}

DEFINE_DEBUGFS_ATTRIBUTE();

static int tegra_emc_debug_max_rate_get(void *data, u64 *rate)
{}

static int tegra_emc_debug_max_rate_set(void *data, u64 rate)
{}

DEFINE_DEBUGFS_ATTRIBUTE();

static void tegra_emc_debugfs_init(struct tegra_emc *emc)
{}

static inline struct tegra_emc *
to_tegra_emc_provider(struct icc_provider *provider)
{}

static struct icc_node_data *
emc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
{}

static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
{}

static int tegra_emc_interconnect_init(struct tegra_emc *emc)
{}

static void devm_tegra_emc_unset_callback(void *data)
{}

static void devm_tegra_emc_unreg_clk_notifier(void *data)
{}

static int tegra_emc_init_clk(struct tegra_emc *emc)
{}

static int tegra_emc_probe(struct platform_device *pdev)
{}

static int tegra_emc_suspend(struct device *dev)
{}

static int tegra_emc_resume(struct device *dev)
{}

static const struct dev_pm_ops tegra_emc_pm_ops =;

static const struct of_device_id tegra_emc_of_match[] =;
MODULE_DEVICE_TABLE(of, tegra_emc_of_match);

static struct platform_driver tegra_emc_driver =;
module_platform_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();