// SPDX-License-Identifier: GPL-2.0
/*
* Tegra20 External Memory Controller driver
*
* Author: Dmitry Osipenko <digetx@gmail.com>
*/
#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 0x000
#define EMC_INTMASK 0x004
#define EMC_DBG 0x008
#define EMC_ADR_CFG_0 0x010
#define EMC_TIMING_CONTROL 0x028
#define EMC_RC 0x02c
#define EMC_RFC 0x030
#define EMC_RAS 0x034
#define EMC_RP 0x038
#define EMC_R2W 0x03c
#define EMC_W2R 0x040
#define EMC_R2P 0x044
#define EMC_W2P 0x048
#define EMC_RD_RCD 0x04c
#define EMC_WR_RCD 0x050
#define EMC_RRD 0x054
#define EMC_REXT 0x058
#define EMC_WDV 0x05c
#define EMC_QUSE 0x060
#define EMC_QRST 0x064
#define EMC_QSAFE 0x068
#define EMC_RDV 0x06c
#define EMC_REFRESH 0x070
#define EMC_BURST_REFRESH_NUM 0x074
#define EMC_PDEX2WR 0x078
#define EMC_PDEX2RD 0x07c
#define EMC_PCHG2PDEN 0x080
#define EMC_ACT2PDEN 0x084
#define EMC_AR2PDEN 0x088
#define EMC_RW2PDEN 0x08c
#define EMC_TXSR 0x090
#define EMC_TCKE 0x094
#define EMC_TFAW 0x098
#define EMC_TRPAB 0x09c
#define EMC_TCLKSTABLE 0x0a0
#define EMC_TCLKSTOP 0x0a4
#define EMC_TREFBW 0x0a8
#define EMC_QUSE_EXTRA 0x0ac
#define EMC_ODT_WRITE 0x0b0
#define EMC_ODT_READ 0x0b4
#define EMC_MRR 0x0ec
#define EMC_FBIO_CFG5 0x104
#define EMC_FBIO_CFG6 0x114
#define EMC_STAT_CONTROL 0x160
#define EMC_STAT_LLMC_CONTROL 0x178
#define EMC_STAT_PWR_CLOCK_LIMIT 0x198
#define EMC_STAT_PWR_CLOCKS 0x19c
#define EMC_STAT_PWR_COUNT 0x1a0
#define EMC_AUTO_CAL_INTERVAL 0x2a8
#define EMC_CFG_2 0x2b8
#define EMC_CFG_DIG_DLL 0x2bc
#define EMC_DLL_XFORM_DQS 0x2c0
#define EMC_DLL_XFORM_QUSE 0x2c4
#define EMC_ZCAL_REF_CNT 0x2e0
#define EMC_ZCAL_WAIT_CNT 0x2e4
#define EMC_CFG_CLKTRIM_0 0x2d0
#define EMC_CFG_CLKTRIM_1 0x2d4
#define EMC_CFG_CLKTRIM_2 0x2d8
#define EMC_CLKCHANGE_REQ_ENABLE BIT(0)
#define EMC_CLKCHANGE_PD_ENABLE BIT(1)
#define EMC_CLKCHANGE_SR_ENABLE BIT(2)
#define EMC_TIMING_UPDATE BIT(0)
#define EMC_REFRESH_OVERFLOW_INT BIT(3)
#define EMC_CLKCHANGE_COMPLETE_INT BIT(4)
#define EMC_MRR_DIVLD_INT BIT(5)
#define EMC_DBG_READ_MUX_ASSEMBLY BIT(0)
#define EMC_DBG_WRITE_MUX_ACTIVE BIT(1)
#define EMC_DBG_FORCE_UPDATE BIT(2)
#define EMC_DBG_READ_DQM_CTRL BIT(9)
#define EMC_DBG_CFG_PRIORITY BIT(24)
#define EMC_FBIO_CFG5_DRAM_WIDTH_X16 BIT(4)
#define EMC_FBIO_CFG5_DRAM_TYPE GENMASK(1, 0)
#define EMC_MRR_DEV_SELECTN GENMASK(31, 30)
#define EMC_MRR_MRR_MA GENMASK(23, 16)
#define EMC_MRR_MRR_DATA GENMASK(15, 0)
#define EMC_ADR_CFG_0_EMEM_NUMDEV GENMASK(25, 24)
#define EMC_PWR_GATHER_CLEAR (1 << 8)
#define EMC_PWR_GATHER_DISABLE (2 << 8)
#define EMC_PWR_GATHER_ENABLE (3 << 8)
enum emc_dram_type {
DRAM_TYPE_RESERVED,
DRAM_TYPE_DDR1,
DRAM_TYPE_LPDDR2,
DRAM_TYPE_DDR2,
};
static const u16 emc_timing_registers[] = {
EMC_RC,
EMC_RFC,
EMC_RAS,
EMC_RP,
EMC_R2W,
EMC_W2R,
EMC_R2P,
EMC_W2P,
EMC_RD_RCD,
EMC_WR_RCD,
EMC_RRD,
EMC_REXT,
EMC_WDV,
EMC_QUSE,
EMC_QRST,
EMC_QSAFE,
EMC_RDV,
EMC_REFRESH,
EMC_BURST_REFRESH_NUM,
EMC_PDEX2WR,
EMC_PDEX2RD,
EMC_PCHG2PDEN,
EMC_ACT2PDEN,
EMC_AR2PDEN,
EMC_RW2PDEN,
EMC_TXSR,
EMC_TCKE,
EMC_TFAW,
EMC_TRPAB,
EMC_TCLKSTABLE,
EMC_TCLKSTOP,
EMC_TREFBW,
EMC_QUSE_EXTRA,
EMC_FBIO_CFG6,
EMC_ODT_WRITE,
EMC_ODT_READ,
EMC_FBIO_CFG5,
EMC_CFG_DIG_DLL,
EMC_DLL_XFORM_DQS,
EMC_DLL_XFORM_QUSE,
EMC_ZCAL_REF_CNT,
EMC_ZCAL_WAIT_CNT,
EMC_AUTO_CAL_INTERVAL,
EMC_CFG_CLKTRIM_0,
EMC_CFG_CLKTRIM_1,
EMC_CFG_CLKTRIM_2,
};
struct emc_timing {
unsigned long rate;
u32 data[ARRAY_SIZE(emc_timing_registers)];
};
enum emc_rate_request_type {
EMC_RATE_DEVFREQ,
EMC_RATE_DEBUG,
EMC_RATE_ICC,
EMC_RATE_TYPE_MAX,
};
struct emc_rate_request {
unsigned long min_rate;
unsigned long max_rate;
};
struct tegra_emc {
struct device *dev;
struct tegra_mc *mc;
struct