#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk/tegra.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/interconnect-provider.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/sort.h>
#include <linux/string.h>
#include <soc/tegra/fuse.h>
#include <soc/tegra/mc.h>
#include "mc.h"
#define EMC_FBIO_CFG5 …
#define EMC_FBIO_CFG5_DRAM_TYPE_MASK …
#define EMC_FBIO_CFG5_DRAM_TYPE_SHIFT …
#define EMC_FBIO_CFG5_DRAM_WIDTH_X64 …
#define EMC_INTSTATUS …
#define EMC_INTSTATUS_CLKCHANGE_COMPLETE …
#define EMC_CFG …
#define EMC_CFG_DRAM_CLKSTOP_PD …
#define EMC_CFG_DRAM_CLKSTOP_SR …
#define EMC_CFG_DRAM_ACPD …
#define EMC_CFG_DYN_SREF …
#define EMC_CFG_PWR_MASK …
#define EMC_CFG_DSR_VTTGEN_DRV_EN …
#define EMC_REFCTRL …
#define EMC_REFCTRL_DEV_SEL_SHIFT …
#define EMC_REFCTRL_ENABLE …
#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_ODT_WRITE …
#define EMC_ODT_READ …
#define EMC_WEXT …
#define EMC_CTT …
#define EMC_RFC_SLR …
#define EMC_MRS_WAIT_CNT2 …
#define EMC_MRS_WAIT_CNT …
#define EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT …
#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_MRS …
#define EMC_MODE_SET_DLL_RESET …
#define EMC_MODE_SET_LONG_CNT …
#define EMC_EMRS …
#define EMC_REF …
#define EMC_PRE …
#define EMC_SELF_REF …
#define EMC_SELF_REF_CMD_ENABLED …
#define EMC_SELF_REF_DEV_SEL_SHIFT …
#define EMC_MRW …
#define EMC_MRR …
#define EMC_MRR_MA_SHIFT …
#define LPDDR2_MR4_TEMP_SHIFT …
#define EMC_XM2DQSPADCTRL3 …
#define EMC_FBIO_SPARE …
#define EMC_FBIO_CFG6 …
#define EMC_EMRS2 …
#define EMC_MRW2 …
#define EMC_MRW4 …
#define EMC_EINPUT …
#define EMC_EINPUT_DURATION …
#define EMC_PUTERM_EXTRA …
#define EMC_TCKESR …
#define EMC_TPD …
#define EMC_AUTO_CAL_CONFIG …
#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_START …
#define EMC_AUTO_CAL_INTERVAL …
#define EMC_AUTO_CAL_STATUS …
#define EMC_AUTO_CAL_STATUS_ACTIVE …
#define EMC_STATUS …
#define EMC_STATUS_TIMING_UPDATE_STALLED …
#define EMC_CFG_2 …
#define EMC_CFG_2_MODE_SHIFT …
#define EMC_CFG_2_DIS_STP_OB_CLK_DURING_NON_WR …
#define EMC_CFG_DIG_DLL …
#define EMC_CFG_DIG_DLL_PERIOD …
#define EMC_RDV_MASK …
#define EMC_WDV_MASK …
#define EMC_CTT_DURATION …
#define EMC_CTT_TERM_CTRL …
#define EMC_ZCAL_INTERVAL …
#define EMC_ZCAL_WAIT_CNT …
#define EMC_ZQ_CAL …
#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_XM2CMDPADCTRL …
#define EMC_XM2DQSPADCTRL …
#define EMC_XM2DQSPADCTRL2 …
#define EMC_XM2DQSPADCTRL2_RX_FT_REC_ENABLE …
#define EMC_XM2DQSPADCTRL2_VREF_ENABLE …
#define EMC_XM2DQPADCTRL …
#define EMC_XM2DQPADCTRL2 …
#define EMC_XM2CLKPADCTRL …
#define EMC_XM2COMPPADCTRL …
#define EMC_XM2VTTGENPADCTRL …
#define EMC_XM2VTTGENPADCTRL2 …
#define EMC_XM2VTTGENPADCTRL3 …
#define EMC_XM2DQSPADCTRL4 …
#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_AFTER_CLKCHANGE …
#define EMC_SEL_DPD_CTRL …
#define EMC_SEL_DPD_CTRL_DATA_SEL_DPD …
#define EMC_SEL_DPD_CTRL_ODT_SEL_DPD …
#define EMC_SEL_DPD_CTRL_RESET_SEL_DPD …
#define EMC_SEL_DPD_CTRL_CA_SEL_DPD …
#define EMC_SEL_DPD_CTRL_CLK_SEL_DPD …
#define EMC_SEL_DPD_CTRL_DDR3_MASK …
#define EMC_SEL_DPD_CTRL_MASK …
#define EMC_PRE_REFRESH_REQ_CNT …
#define EMC_DYN_SELF_REF_CONTROL …
#define EMC_TXSRDLL …
#define EMC_CCFIFO_ADDR …
#define EMC_CCFIFO_DATA …
#define EMC_CCFIFO_STATUS …
#define EMC_CDB_CNTL_1 …
#define EMC_CDB_CNTL_2 …
#define EMC_XM2CLKPADCTRL2 …
#define EMC_AUTO_CAL_CONFIG2 …
#define EMC_AUTO_CAL_CONFIG3 …
#define EMC_IBDLY …
#define EMC_DLL_XFORM_ADDR0 …
#define EMC_DLL_XFORM_ADDR1 …
#define EMC_DLL_XFORM_ADDR2 …
#define EMC_DSR_VTTGEN_DRV …
#define EMC_TXDSRVTTGEN …
#define EMC_XM2CMDPADCTRL4 …
#define EMC_XM2CMDPADCTRL5 …
#define EMC_DLL_XFORM_DQS8 …
#define EMC_DLL_XFORM_DQS9 …
#define EMC_DLL_XFORM_DQS10 …
#define EMC_DLL_XFORM_DQS11 …
#define EMC_DLL_XFORM_DQS12 …
#define EMC_DLL_XFORM_DQS13 …
#define EMC_DLL_XFORM_DQS14 …
#define EMC_DLL_XFORM_DQS15 …
#define EMC_DLL_XFORM_QUSE8 …
#define EMC_DLL_XFORM_QUSE9 …
#define EMC_DLL_XFORM_QUSE10 …
#define EMC_DLL_XFORM_QUSE11 …
#define EMC_DLL_XFORM_QUSE12 …
#define EMC_DLL_XFORM_QUSE13 …
#define EMC_DLL_XFORM_QUSE14 …
#define EMC_DLL_XFORM_QUSE15 …
#define EMC_DLL_XFORM_DQ4 …
#define EMC_DLL_XFORM_DQ5 …
#define EMC_DLL_XFORM_DQ6 …
#define EMC_DLL_XFORM_DQ7 …
#define EMC_DLI_TRIM_TXDQS8 …
#define EMC_DLI_TRIM_TXDQS9 …
#define EMC_DLI_TRIM_TXDQS10 …
#define EMC_DLI_TRIM_TXDQS11 …
#define EMC_DLI_TRIM_TXDQS12 …
#define EMC_DLI_TRIM_TXDQS13 …
#define EMC_DLI_TRIM_TXDQS14 …
#define EMC_DLI_TRIM_TXDQS15 …
#define EMC_CDB_CNTL_3 …
#define EMC_XM2DQSPADCTRL5 …
#define EMC_XM2DQSPADCTRL6 …
#define EMC_XM2DQPADCTRL3 …
#define EMC_DLL_XFORM_ADDR3 …
#define EMC_DLL_XFORM_ADDR4 …
#define EMC_DLL_XFORM_ADDR5 …
#define EMC_CFG_PIPE …
#define EMC_QPOP …
#define EMC_QUSE_WIDTH …
#define EMC_PUTERM_WIDTH …
#define EMC_BGBIAS_CTL0 …
#define EMC_BGBIAS_CTL0_BIAS0_DSC_E_PWRD_IBIAS_RX …
#define EMC_BGBIAS_CTL0_BIAS0_DSC_E_PWRD_IBIAS_VTTGEN …
#define EMC_BGBIAS_CTL0_BIAS0_DSC_E_PWRD …
#define EMC_PUTERM_ADJ …
#define DRAM_DEV_SEL_ALL …
#define DRAM_DEV_SEL_0 …
#define DRAM_DEV_SEL_1 …
#define EMC_CFG_POWER_FEATURES_MASK …
#define EMC_REFCTRL_DEV_SEL(n) …
#define EMC_DRAM_DEV_SEL(n) …
#define EMC_STATUS_UPDATE_TIMEOUT …
enum emc_dram_type { … };
enum emc_dll_change { … };
static const unsigned long emc_burst_regs[] = …;
struct emc_timing { … };
enum emc_rate_request_type { … };
struct emc_rate_request { … };
struct tegra_emc { … };
static void emc_ccfifo_writel(struct tegra_emc *emc, u32 value,
unsigned long offset)
{ … }
static void emc_seq_update_timing(struct tegra_emc *emc)
{ … }
static void emc_seq_disable_auto_cal(struct tegra_emc *emc)
{ … }
static void emc_seq_wait_clkchange(struct tegra_emc *emc)
{ … }
static struct emc_timing *tegra_emc_find_timing(struct tegra_emc *emc,
unsigned long rate)
{ … }
static int tegra_emc_prepare_timing_change(struct tegra_emc *emc,
unsigned long rate)
{ … }
static void tegra_emc_complete_timing_change(struct tegra_emc *emc,
unsigned long rate)
{ … }
static void emc_read_current_timing(struct tegra_emc *emc,
struct emc_timing *timing)
{ … }
static int emc_init(struct tegra_emc *emc)
{ … }
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 const struct of_device_id tegra_emc_of_match[] = …;
MODULE_DEVICE_TABLE(of, tegra_emc_of_match);
static struct device_node *
tegra_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code)
{ … }
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)
{ … }
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 emc_debugfs_init(struct device *dev, 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 int tegra_emc_opp_table_init(struct tegra_emc *emc)
{ … }
static void devm_tegra_emc_unset_callback(void *data)
{ … }
static int tegra_emc_probe(struct platform_device *pdev)
{
struct device_node *np;
struct tegra_emc *emc;
u32 ram_code;
int err;
emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
if (!emc)
return -ENOMEM;
mutex_init(&emc->rate_lock);
emc->dev = &pdev->dev;
emc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(emc->regs))
return PTR_ERR(emc->regs);
emc->mc = devm_tegra_memory_controller_get(&pdev->dev);
if (IS_ERR(emc->mc))
return PTR_ERR(emc->mc);
ram_code = tegra_read_ram_code();
np = tegra_emc_find_node_by_ram_code(pdev->dev.of_node, ram_code);
if (np) {
err = tegra_emc_load_timings_from_dt(emc, np);
of_node_put(np);
if (err)
return err;
} else {
dev_info_once(&pdev->dev,
"no memory timings for RAM code %u found in DT\n",
ram_code);
}
err = emc_init(emc);
if (err) {
dev_err(&pdev->dev, "EMC initialization failed: %d\n", err);
return err;
}
platform_set_drvdata(pdev, emc);
tegra124_clk_set_emc_callbacks(tegra_emc_prepare_timing_change,
tegra_emc_complete_timing_change);
err = devm_add_action_or_reset(&pdev->dev, devm_tegra_emc_unset_callback,
NULL);
if (err)
return err;
emc->clk = devm_clk_get(&pdev->dev, "emc");
if (IS_ERR(emc->clk)) {
err = PTR_ERR(emc->clk);
dev_err(&pdev->dev, "failed to get EMC clock: %d\n", err);
return err;
}
err = tegra_emc_opp_table_init(emc);
if (err)
return err;
tegra_emc_rate_requests_init(emc);
if (IS_ENABLED(CONFIG_DEBUG_FS))
emc_debugfs_init(&pdev->dev, emc);
tegra_emc_interconnect_init(emc);
try_module_get(THIS_MODULE);
return 0;
};
static struct platform_driver tegra_emc_driver = …;
module_platform_driver(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;