Merge tag 'arm-drivers-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM driver updates from Arnd Bergmann:
"There are a few separately maintained driver subsystems that we merge
through the SoC tree, notable changes are:
- Memory controller updates, mainly for Tegra and Mediatek SoCs, and
clarifications for the memory controller DT bindings
- SCMI firmware interface updates, in particular a new transport
based on OPTEE and support for atomic operations.
- Cleanups to the TEE subsystem, refactoring its memory management
For SoC specific drivers without a separate subsystem, changes include
- Smaller updates and fixes for TI, AT91/SAMA5, Qualcomm and NXP
Layerscape SoCs.
- Driver support for Microchip SAMA5D29, Tesla FSD, Renesas RZ/G2L,
and Qualcomm SM8450.
- Better power management on Mediatek MT81xx, NXP i.MX8MQ and older
NVIDIA Tegra chips"
* tag 'arm-drivers-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (154 commits)
ARM: spear: fix typos in comments
soc/microchip: fix invalid free in mpfs_sys_controller_delete
soc: s4: Add support for power domains controller
dt-bindings: power: add Amlogic s4 power domains bindings
ARM: at91: add support in soc driver for new SAMA5D29
soc: mediatek: mmsys: add sw0_rst_offset in mmsys driver data
dt-bindings: memory: renesas,rpc-if: Document RZ/V2L SoC
memory: emif: check the pointer temp in get_device_details()
memory: emif: Add check for setup_interrupts
dt-bindings: arm: mediatek: mmsys: add support for MT8186
dt-bindings: mediatek: add compatible for MT8186 pwrap
soc: mediatek: pwrap: add pwrap driver for MT8186 SoC
soc: mediatek: mmsys: add mmsys reset control for MT8186
soc: mediatek: mtk-infracfg: Disable ACP on MT8192
soc: ti: k3-socinfo: Add AM62x JTAG ID
soc: mediatek: add MTK mutex support for MT8186
soc: mediatek: mmsys: add mt8186 mmsys routing table
soc: mediatek: pm-domains: Add support for mt8186
dt-bindings: power: Add MT8186 power domains
soc: mediatek: pm-domains: Add support for mt8195
...
This commit is contained in:
@@ -424,7 +424,7 @@ static void __finalize_command(struct brcmstb_dpfe_priv *priv)
|
||||
|
||||
/*
|
||||
* It depends on the API version which MBOX register we have to write to
|
||||
* to signal we are done.
|
||||
* signal we are done.
|
||||
*/
|
||||
release_mbox = (priv->dpfe_api->version < 2)
|
||||
? REG_TO_HOST_MBOX : REG_TO_DCPU_MBOX;
|
||||
|
||||
@@ -1025,7 +1025,7 @@ static struct emif_data *__init_or_module get_device_details(
|
||||
temp = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
|
||||
dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL);
|
||||
|
||||
if (!emif || !pd || !dev_info) {
|
||||
if (!emif || !temp || !dev_info) {
|
||||
dev_err(dev, "%s:%d: allocation error\n", __func__, __LINE__);
|
||||
goto error;
|
||||
}
|
||||
@@ -1117,7 +1117,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct emif_data *emif;
|
||||
struct resource *res;
|
||||
int irq;
|
||||
int irq, ret;
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
emif = of_get_memory_device_details(pdev->dev.of_node, &pdev->dev);
|
||||
@@ -1147,7 +1147,9 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
|
||||
emif_onetime_settings(emif);
|
||||
emif_debugfs_init(emif);
|
||||
disable_and_clear_all_interrupts(emif);
|
||||
setup_interrupts(emif, irq);
|
||||
ret = setup_interrupts(emif, irq);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* One-time actions taken on probing the first device */
|
||||
if (!emif1) {
|
||||
|
||||
@@ -88,6 +88,7 @@ static int fsl_ifc_ctrl_remove(struct platform_device *dev)
|
||||
{
|
||||
struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(&dev->dev);
|
||||
|
||||
of_platform_depopulate(&dev->dev);
|
||||
free_irq(ctrl->nand_irq, ctrl);
|
||||
free_irq(ctrl->irq, ctrl);
|
||||
|
||||
@@ -285,8 +286,16 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
/* legacy dts may still use "simple-bus" compatible */
|
||||
ret = of_platform_populate(dev->dev.of_node, NULL, NULL,
|
||||
&dev->dev);
|
||||
if (ret)
|
||||
goto err_free_nandirq;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_nandirq:
|
||||
free_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_ctrl_dev);
|
||||
err_free_irq:
|
||||
free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev);
|
||||
err_unmap_nandirq:
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
@@ -32,6 +33,10 @@
|
||||
#define SMI_DUMMY 0x444
|
||||
|
||||
/* SMI LARB */
|
||||
#define SMI_LARB_SLP_CON 0xc
|
||||
#define SLP_PROT_EN BIT(0)
|
||||
#define SLP_PROT_RDY BIT(16)
|
||||
|
||||
#define SMI_LARB_CMD_THRT_CON 0x24
|
||||
#define SMI_LARB_THRT_RD_NU_LMT_MSK GENMASK(7, 4)
|
||||
#define SMI_LARB_THRT_RD_NU_LMT (5 << 4)
|
||||
@@ -81,6 +86,7 @@
|
||||
|
||||
#define MTK_SMI_FLAG_THRT_UPDATE BIT(0)
|
||||
#define MTK_SMI_FLAG_SW_FLAG BIT(1)
|
||||
#define MTK_SMI_FLAG_SLEEP_CTL BIT(2)
|
||||
#define MTK_SMI_CAPS(flags, _x) (!!((flags) & (_x)))
|
||||
|
||||
struct mtk_smi_reg_pair {
|
||||
@@ -94,8 +100,6 @@ enum mtk_smi_type {
|
||||
MTK_SMI_GEN2_SUB_COMM, /* gen2 smi sub common */
|
||||
};
|
||||
|
||||
#define MTK_SMI_CLK_NR_MAX 4
|
||||
|
||||
/* larbs: Require apb/smi clocks while gals is optional. */
|
||||
static const char * const mtk_smi_larb_clks[] = {"apb", "smi", "gals"};
|
||||
#define MTK_SMI_LARB_REQ_CLK_NR 2
|
||||
@@ -106,6 +110,7 @@ static const char * const mtk_smi_larb_clks[] = {"apb", "smi", "gals"};
|
||||
* sub common: Require apb/smi/gals0 clocks in has_gals case. Otherwise, only apb/smi are required.
|
||||
*/
|
||||
static const char * const mtk_smi_common_clks[] = {"apb", "smi", "gals0", "gals1"};
|
||||
#define MTK_SMI_CLK_NR_MAX ARRAY_SIZE(mtk_smi_common_clks)
|
||||
#define MTK_SMI_COM_REQ_CLK_NR 2
|
||||
#define MTK_SMI_COM_GALS_REQ_CLK_NR MTK_SMI_CLK_NR_MAX
|
||||
#define MTK_SMI_SUB_COM_GALS_REQ_CLK_NR 3
|
||||
@@ -335,13 +340,19 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = {
|
||||
/* IPU0 | IPU1 | CCU */
|
||||
};
|
||||
|
||||
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8186 = {
|
||||
.config_port = mtk_smi_larb_config_port_gen2_general,
|
||||
.flags_general = MTK_SMI_FLAG_SLEEP_CTL,
|
||||
};
|
||||
|
||||
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = {
|
||||
.config_port = mtk_smi_larb_config_port_gen2_general,
|
||||
};
|
||||
|
||||
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8195 = {
|
||||
.config_port = mtk_smi_larb_config_port_gen2_general,
|
||||
.flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG,
|
||||
.flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG |
|
||||
MTK_SMI_FLAG_SLEEP_CTL,
|
||||
.ostd = mtk_smi_larb_mt8195_ostd,
|
||||
};
|
||||
|
||||
@@ -352,11 +363,32 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = {
|
||||
{.compatible = "mediatek,mt8167-smi-larb", .data = &mtk_smi_larb_mt8167},
|
||||
{.compatible = "mediatek,mt8173-smi-larb", .data = &mtk_smi_larb_mt8173},
|
||||
{.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183},
|
||||
{.compatible = "mediatek,mt8186-smi-larb", .data = &mtk_smi_larb_mt8186},
|
||||
{.compatible = "mediatek,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192},
|
||||
{.compatible = "mediatek,mt8195-smi-larb", .data = &mtk_smi_larb_mt8195},
|
||||
{}
|
||||
};
|
||||
|
||||
static int mtk_smi_larb_sleep_ctrl_enable(struct mtk_smi_larb *larb)
|
||||
{
|
||||
int ret;
|
||||
u32 tmp;
|
||||
|
||||
writel_relaxed(SLP_PROT_EN, larb->base + SMI_LARB_SLP_CON);
|
||||
ret = readl_poll_timeout_atomic(larb->base + SMI_LARB_SLP_CON,
|
||||
tmp, !!(tmp & SLP_PROT_RDY), 10, 1000);
|
||||
if (ret) {
|
||||
/* TODO: Reset this larb if it fails here. */
|
||||
dev_err(larb->smi.dev, "sleep ctrl is not ready(0x%x).\n", tmp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mtk_smi_larb_sleep_ctrl_disable(struct mtk_smi_larb *larb)
|
||||
{
|
||||
writel_relaxed(0, larb->base + SMI_LARB_SLP_CON);
|
||||
}
|
||||
|
||||
static int mtk_smi_device_link_common(struct device *dev, struct device **com_dev)
|
||||
{
|
||||
struct platform_device *smi_com_pdev;
|
||||
@@ -466,9 +498,12 @@ static int __maybe_unused mtk_smi_larb_resume(struct device *dev)
|
||||
int ret;
|
||||
|
||||
ret = clk_bulk_prepare_enable(larb->smi.clk_num, larb->smi.clks);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (MTK_SMI_CAPS(larb->larb_gen->flags_general, MTK_SMI_FLAG_SLEEP_CTL))
|
||||
mtk_smi_larb_sleep_ctrl_disable(larb);
|
||||
|
||||
/* Configure the basic setting for this larb */
|
||||
larb_gen->config_port(dev);
|
||||
|
||||
@@ -478,6 +513,13 @@ static int __maybe_unused mtk_smi_larb_resume(struct device *dev)
|
||||
static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
|
||||
{
|
||||
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
if (MTK_SMI_CAPS(larb->larb_gen->flags_general, MTK_SMI_FLAG_SLEEP_CTL)) {
|
||||
ret = mtk_smi_larb_sleep_ctrl_enable(larb);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
clk_bulk_disable_unprepare(larb->smi.clk_num, larb->smi.clks);
|
||||
return 0;
|
||||
@@ -530,6 +572,12 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
|
||||
F_MMU1_LARB(7),
|
||||
};
|
||||
|
||||
static const struct mtk_smi_common_plat mtk_smi_common_mt8186 = {
|
||||
.type = MTK_SMI_GEN2,
|
||||
.has_gals = true,
|
||||
.bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(4) | F_MMU1_LARB(7),
|
||||
};
|
||||
|
||||
static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
|
||||
.type = MTK_SMI_GEN2,
|
||||
.has_gals = true,
|
||||
@@ -564,6 +612,7 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
|
||||
{.compatible = "mediatek,mt8167-smi-common", .data = &mtk_smi_common_gen2},
|
||||
{.compatible = "mediatek,mt8173-smi-common", .data = &mtk_smi_common_gen2},
|
||||
{.compatible = "mediatek,mt8183-smi-common", .data = &mtk_smi_common_mt8183},
|
||||
{.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186},
|
||||
{.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192},
|
||||
{.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
|
||||
{.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},
|
||||
|
||||
@@ -212,8 +212,10 @@ static int of_lpddr3_do_get_timings(struct device_node *np,
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* The 'reg' param required since DT has changed, used as 'max-freq' */
|
||||
ret = of_property_read_u32(np, "reg", &tim->max_freq);
|
||||
ret = of_property_read_u32(np, "max-freq", &tim->max_freq);
|
||||
if (ret)
|
||||
/* Deprecated way of passing max-freq as 'reg' */
|
||||
ret = of_property_read_u32(np, "reg", &tim->max_freq);
|
||||
ret |= of_property_read_u32(np, "min-freq", &tim->min_freq);
|
||||
ret |= of_property_read_u32(np, "tRFC", &tim->tRFC);
|
||||
ret |= of_property_read_u32(np, "tRRD", &tim->tRRD);
|
||||
@@ -316,14 +318,21 @@ const struct lpddr2_info
|
||||
struct property *prop;
|
||||
const char *cp;
|
||||
int err;
|
||||
u32 revision_id[2];
|
||||
|
||||
err = of_property_read_u32(np, "revision-id1", &info.revision_id1);
|
||||
if (err)
|
||||
info.revision_id1 = -ENOENT;
|
||||
err = of_property_read_u32_array(np, "revision-id", revision_id, 2);
|
||||
if (!err) {
|
||||
info.revision_id1 = revision_id[0];
|
||||
info.revision_id2 = revision_id[1];
|
||||
} else {
|
||||
err = of_property_read_u32(np, "revision-id1", &info.revision_id1);
|
||||
if (err)
|
||||
info.revision_id1 = -ENOENT;
|
||||
|
||||
err = of_property_read_u32(np, "revision-id2", &info.revision_id2);
|
||||
if (err)
|
||||
info.revision_id2 = -ENOENT;
|
||||
err = of_property_read_u32(np, "revision-id2", &info.revision_id2);
|
||||
if (err)
|
||||
info.revision_id2 = -ENOENT;
|
||||
}
|
||||
|
||||
err = of_property_read_u32(np, "io-width", &info.io_width);
|
||||
if (err)
|
||||
|
||||
@@ -28,6 +28,7 @@ config TEGRA30_EMC
|
||||
default y
|
||||
depends on ARCH_TEGRA_3x_SOC || COMPILE_TEST
|
||||
select PM_OPP
|
||||
select DDR
|
||||
help
|
||||
This driver is for the External Memory Controller (EMC) found on
|
||||
Tegra30 chips. The EMC controls the external DRAM on the board.
|
||||
|
||||
@@ -540,7 +540,7 @@ static int emc_read_lpddr_mode_register(struct tegra_emc *emc,
|
||||
unsigned int register_addr,
|
||||
unsigned int *register_data)
|
||||
{
|
||||
u32 memory_dev = emem_dev + 1;
|
||||
u32 memory_dev = emem_dev ? 1 : 2;
|
||||
u32 val, mr_mask = 0xff;
|
||||
int err;
|
||||
|
||||
|
||||
@@ -711,7 +711,7 @@ static int tegra210_emc_cd_set_state(struct thermal_cooling_device *cd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct thermal_cooling_device_ops tegra210_emc_cd_ops = {
|
||||
static const struct thermal_cooling_device_ops tegra210_emc_cd_ops = {
|
||||
.get_max_state = tegra210_emc_cd_max_state,
|
||||
.get_cur_state = tegra210_emc_cd_get_state,
|
||||
.set_cur_state = tegra210_emc_cd_set_state,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* Copyright (C) 2019 GRATE-DRIVER project
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
#include <linux/debugfs.h>
|
||||
@@ -31,11 +32,15 @@
|
||||
#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 0x010
|
||||
#define EMC_CFG 0x00c
|
||||
#define EMC_REFCTRL 0x020
|
||||
#define EMC_TIMING_CONTROL 0x028
|
||||
@@ -81,6 +86,7 @@
|
||||
#define EMC_EMRS 0x0d0
|
||||
#define EMC_SELF_REF 0x0e0
|
||||
#define EMC_MRW 0x0e8
|
||||
#define EMC_MRR 0x0ec
|
||||
#define EMC_XM2DQSPADCTRL3 0x0f8
|
||||
#define EMC_FBIO_SPARE 0x100
|
||||
#define EMC_FBIO_CFG5 0x104
|
||||
@@ -208,6 +214,13 @@
|
||||
|
||||
#define EMC_REFRESH_OVERFLOW_INT BIT(3)
|
||||
#define EMC_CLKCHANGE_COMPLETE_INT BIT(4)
|
||||
#define EMC_MRR_DIVLD_INT BIT(5)
|
||||
|
||||
#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_EMEM_NUMDEV BIT(0)
|
||||
|
||||
enum emc_dram_type {
|
||||
DRAM_TYPE_DDR3,
|
||||
@@ -378,6 +391,8 @@ struct tegra_emc {
|
||||
|
||||
/* protect shared rate-change code path */
|
||||
struct mutex rate_lock;
|
||||
|
||||
bool mrr_error;
|
||||
};
|
||||
|
||||
static int emc_seq_update_timing(struct tegra_emc *emc)
|
||||
@@ -1008,12 +1023,18 @@ static int emc_load_timings_from_dt(struct tegra_emc *emc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_node *emc_find_node_by_ram_code(struct device *dev)
|
||||
static struct device_node *emc_find_node_by_ram_code(struct tegra_emc *emc)
|
||||
{
|
||||
struct device *dev = emc->dev;
|
||||
struct device_node *np;
|
||||
u32 value, ram_code;
|
||||
int err;
|
||||
|
||||
if (emc->mrr_error) {
|
||||
dev_warn(dev, "memory timings skipped due to MRR error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (of_get_child_count(dev->of_node) == 0) {
|
||||
dev_info_once(dev, "device-tree doesn't have memory timings\n");
|
||||
return NULL;
|
||||
@@ -1035,11 +1056,73 @@ static struct device_node *emc_find_node_by_ram_code(struct device *dev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int emc_read_lpddr_mode_register(struct tegra_emc *emc,
|
||||
unsigned int emem_dev,
|
||||
unsigned int register_addr,
|
||||
unsigned int *register_data)
|
||||
{
|
||||
u32 memory_dev = emem_dev ? 1 : 2;
|
||||
u32 val, mr_mask = 0xff;
|
||||
int err;
|
||||
|
||||
/* clear data-valid interrupt status */
|
||||
writel_relaxed(EMC_MRR_DIVLD_INT, emc->regs + EMC_INTSTATUS);
|
||||
|
||||
/* issue mode register read request */
|
||||
val = FIELD_PREP(EMC_MRR_DEV_SELECTN, memory_dev);
|
||||
val |= FIELD_PREP(EMC_MRR_MRR_MA, register_addr);
|
||||
|
||||
writel_relaxed(val, emc->regs + EMC_MRR);
|
||||
|
||||
/* wait for the LPDDR2 data-valid interrupt */
|
||||
err = readl_relaxed_poll_timeout_atomic(emc->regs + EMC_INTSTATUS, val,
|
||||
val & EMC_MRR_DIVLD_INT,
|
||||
1, 100);
|
||||
if (err) {
|
||||
dev_err(emc->dev, "mode register %u read failed: %d\n",
|
||||
register_addr, err);
|
||||
emc->mrr_error = true;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* read out mode register data */
|
||||
val = readl_relaxed(emc->regs + EMC_MRR);
|
||||
*register_data = FIELD_GET(EMC_MRR_MRR_DATA, val) & mr_mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void emc_read_lpddr_sdram_info(struct tegra_emc *emc,
|
||||
unsigned int emem_dev)
|
||||
{
|
||||
union lpddr2_basic_config4 basic_conf4;
|
||||
unsigned int manufacturer_id;
|
||||
unsigned int revision_id1;
|
||||
unsigned int revision_id2;
|
||||
|
||||
/* these registers are standard for all LPDDR JEDEC memory chips */
|
||||
emc_read_lpddr_mode_register(emc, emem_dev, 5, &manufacturer_id);
|
||||
emc_read_lpddr_mode_register(emc, emem_dev, 6, &revision_id1);
|
||||
emc_read_lpddr_mode_register(emc, emem_dev, 7, &revision_id2);
|
||||
emc_read_lpddr_mode_register(emc, emem_dev, 8, &basic_conf4.value);
|
||||
|
||||
dev_info(emc->dev, "SDRAM[dev%u]: manufacturer: 0x%x (%s) rev1: 0x%x rev2: 0x%x prefetch: S%u density: %uMbit iowidth: %ubit\n",
|
||||
emem_dev, manufacturer_id,
|
||||
lpddr2_jedec_manufacturer(manufacturer_id),
|
||||
revision_id1, revision_id2,
|
||||
4 >> basic_conf4.arch_type,
|
||||
64 << basic_conf4.density,
|
||||
32 >> basic_conf4.io_width);
|
||||
}
|
||||
|
||||
static int emc_setup_hw(struct tegra_emc *emc)
|
||||
{
|
||||
u32 fbio_cfg5, emc_cfg, emc_dbg, emc_adr_cfg;
|
||||
u32 intmask = EMC_REFRESH_OVERFLOW_INT;
|
||||
u32 fbio_cfg5, emc_cfg, emc_dbg;
|
||||
static bool print_sdram_info_once;
|
||||
enum emc_dram_type dram_type;
|
||||
const char *dram_type_str;
|
||||
unsigned int emem_numdev;
|
||||
|
||||
fbio_cfg5 = readl_relaxed(emc->regs + EMC_FBIO_CFG5);
|
||||
dram_type = fbio_cfg5 & EMC_FBIO_CFG5_DRAM_TYPE_MASK;
|
||||
@@ -1076,6 +1159,34 @@ static int emc_setup_hw(struct tegra_emc *emc)
|
||||
emc_dbg &= ~EMC_DBG_FORCE_UPDATE;
|
||||
writel_relaxed(emc_dbg, emc->regs + EMC_DBG);
|
||||
|
||||
switch (dram_type) {
|
||||
case DRAM_TYPE_DDR1:
|
||||
dram_type_str = "DDR1";
|
||||
break;
|
||||
case DRAM_TYPE_LPDDR2:
|
||||
dram_type_str = "LPDDR2";
|
||||
break;
|
||||
case DRAM_TYPE_DDR2:
|
||||
dram_type_str = "DDR2";
|
||||
break;
|
||||
case DRAM_TYPE_DDR3:
|
||||
dram_type_str = "DDR3";
|
||||
break;
|
||||
}
|
||||
|
||||
emc_adr_cfg = readl_relaxed(emc->regs + EMC_ADR_CFG);
|
||||
emem_numdev = FIELD_GET(EMC_ADR_CFG_EMEM_NUMDEV, emc_adr_cfg) + 1;
|
||||
|
||||
dev_info_once(emc->dev, "%u %s %s attached\n", emem_numdev,
|
||||
dram_type_str, emem_numdev == 2 ? "devices" : "device");
|
||||
|
||||
if (dram_type == DRAM_TYPE_LPDDR2 && !print_sdram_info_once) {
|
||||
while (emem_numdev--)
|
||||
emc_read_lpddr_sdram_info(emc, emem_numdev);
|
||||
|
||||
print_sdram_info_once = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1538,14 +1649,6 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
emc->clk_nb.notifier_call = emc_clk_change_notify;
|
||||
emc->dev = &pdev->dev;
|
||||
|
||||
np = emc_find_node_by_ram_code(&pdev->dev);
|
||||
if (np) {
|
||||
err = emc_load_timings_from_dt(emc, np);
|
||||
of_node_put(np);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
emc->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(emc->regs))
|
||||
return PTR_ERR(emc->regs);
|
||||
@@ -1554,6 +1657,14 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
np = emc_find_node_by_ram_code(emc);
|
||||
if (np) {
|
||||
err = emc_load_timings_from_dt(emc, np);
|
||||
of_node_put(np);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = platform_get_irq(pdev, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
Reference in New Issue
Block a user