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

// SPDX-License-Identifier: GPL-2.0
/*
 * Tegra20 External Memory Controller driver
 *
 * Author: Dmitry Osipenko <[email protected]>
 */

#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clk/tegra.h>
#include <linux/debugfs.h>
#include <linux/devfreq.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_0
#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_MRR
#define EMC_FBIO_CFG5
#define EMC_FBIO_CFG6
#define EMC_STAT_CONTROL
#define EMC_STAT_LLMC_CONTROL
#define EMC_STAT_PWR_CLOCK_LIMIT
#define EMC_STAT_PWR_CLOCKS
#define EMC_STAT_PWR_COUNT
#define EMC_AUTO_CAL_INTERVAL
#define EMC_CFG_2
#define EMC_CFG_DIG_DLL
#define EMC_DLL_XFORM_DQS
#define EMC_DLL_XFORM_QUSE
#define EMC_ZCAL_REF_CNT
#define EMC_ZCAL_WAIT_CNT
#define EMC_CFG_CLKTRIM_0
#define EMC_CFG_CLKTRIM_1
#define EMC_CFG_CLKTRIM_2

#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_DBG_READ_MUX_ASSEMBLY
#define EMC_DBG_WRITE_MUX_ACTIVE
#define EMC_DBG_FORCE_UPDATE
#define EMC_DBG_READ_DQM_CTRL
#define EMC_DBG_CFG_PRIORITY

#define EMC_FBIO_CFG5_DRAM_WIDTH_X16
#define EMC_FBIO_CFG5_DRAM_TYPE

#define EMC_MRR_DEV_SELECTN
#define EMC_MRR_MRR_MA
#define EMC_MRR_MRR_DATA

#define EMC_ADR_CFG_0_EMEM_NUMDEV

#define EMC_PWR_GATHER_CLEAR
#define EMC_PWR_GATHER_DISABLE
#define EMC_PWR_GATHER_ENABLE

enum emc_dram_type {};

static const u16 emc_timing_registers[] =;

struct emc_timing {};

enum emc_rate_request_type {};

struct emc_rate_request {};

struct tegra_emc {};

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

static struct emc_timing *tegra_emc_find_timing(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, bool flush)
{}

static int tegra_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 tegra_emc_load_timings_from_dt(struct tegra_emc *emc,
					  struct device_node *node)
{}

static struct device_node *
tegra_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,
				      bool print_out)
{}

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_SIMPLE_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_SIMPLE_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_devfreq_target(struct device *dev, unsigned long *freq,
				    u32 flags)
{}

static int tegra_emc_devfreq_get_dev_status(struct device *dev,
					    struct devfreq_dev_status *stat)
{}

static struct devfreq_dev_profile tegra_emc_devfreq_profile =;

static int tegra_emc_devfreq_init(struct tegra_emc *emc)
{}

static int tegra_emc_probe(struct platform_device *pdev)
{}

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_SOFTDEP();
MODULE_LICENSE();