Memory controller drivers for v5.9
The drivers/memory directory with memory controller drivers, over the last days grew in numbers but lacked any coordinated care. The generic part (device tree helpers) were pulled in through various trees, depending on driver needs. The patchset is a first try to improve code quality of memory controller drivers. Mostly these are non-intrusive fixes for GCC, checkpatch or sparse warnings. This also fixes missing SPDX tags or improves generic code quality (whitespace, const correctness). Last commit appoints also Krzysztof Kozlowski as a maintainer. -----BEGIN PGP SIGNATURE----- iQJEBAABCgAuFiEE3dJiKD0RGyM7briowTdm5oaLg9cFAl8a9QkQHGtyemtAa2Vy bmVsLm9yZwAKCRDBN2bmhouD1yFoD/9M2SSUmXNM5Znk9opvu1y19SsFUlAD7yx0 NZiiMPFy1iu+xvgEf04WyPeahG20+GUJC7cDirU9/NCbFp5jnPdXzyGMHADI5YgT PcqvHcWQCGeF4p0SzyA+/6skIXqFN+FpCkO2XIdn3nnvwqnmYzIndDCQLEgI5zrJ i3oV8Ds2ZYzPQq+J44XFiFq5QTPtqDM3OPYYotPeXve46ciYpO4YsITsotm0tTHI R5BGTvBPMESGDyYjI3zyj4qPKv3g/dgEKSJIKLsmVNhenpoCuaYsogaq+bAO5dm/ AT1rpGPT0hCSulme+8APIw1rplzV9S6d+FM+dchFhwpi8+8ElCG0qJY6vFttV7Te q+XPoQFuUJnKXrqmbT0HkNTdoeK3/vD1GbA7oagIGd9D0RB05mmTWjI0Vfy4S6fC Yv+jtCZ+5gvYtWsvuq1L6fmQDjns6idMEDb2bGdu4Pu98LiFtgb5yVp8VjQukIFC 4cPwvzzRW7+91QRBL7zx8W8z92jX3iv0J4H/Rv23lB5tBcFNALQjW1qIGH11aXbW 1cjowUQhVC54DtPyofsqPFFbUrezyWTKbTW0+kzd0vw/q9iRKrbxmwnWVfIsCt8U B9oecrf9qn0DzHvm01IyNjcKMM2oAWreeON/CHoR1t7gZspM8Gk0TDIOPqSx+eZM 4LyewRdU4g== =8N1k -----END PGP SIGNATURE----- Merge tag 'memory-controller-drv-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into arm/drivers Memory controller drivers for v5.9 The drivers/memory directory with memory controller drivers, over the last days grew in numbers but lacked any coordinated care. The generic part (device tree helpers) were pulled in through various trees, depending on driver needs. The patchset is a first try to improve code quality of memory controller drivers. Mostly these are non-intrusive fixes for GCC, checkpatch or sparse warnings. This also fixes missing SPDX tags or improves generic code quality (whitespace, const correctness). Last commit appoints also Krzysztof Kozlowski as a maintainer. * tag 'memory-controller-drv-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux: (22 commits) MAINTAINERS: Add Krzysztof Kozlowski as maintainer of memory controllers memory: samsung: exynos-srom: Describe the Kconfig entry memory: Describe the MEMORY Kconfig entry memory: da8xx-ddrctl: Remove unused 'node' variable memory: fsl_ifc: Fix whitespace issues memory: pl172: Add GPLv2 SPDX license header memory: omap-gpmc: Fix whitespace issue memory: omap-gpmc: Include <linux/sizes.h> for SZ_16M memory: mtk-smi: Add argument to function pointer definition memory: brcmstb_dpfe: Remove unneeded braces memory: brcmstb_dpfe: Constify the contents of string memory: ti-emif-pm: Fix cast to iomem pointer memory: ti-aemif: Rename SS to SSTROBE to avoid name conflicts memory: emif: Silence platform_get_irq() error in driver memory: emif: Fix whitespace coding style violations memory: emif: Put constant in comparison on the right side memory: emif-asm-offsets: Add GPLv2 SPDX license header memory: of: Remove unneeded extern from function declarations memory: of: Correct indentation memory: of: Remove __func__ in device related messages ... Link: https://lore.kernel.org/r/20200724160314.8543-1-krzk@kernel.org Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
ab274a7ec8
|
@ -11085,6 +11085,13 @@ F: Documentation/core-api/boot-time-mm.rst
|
||||||
F: include/linux/memblock.h
|
F: include/linux/memblock.h
|
||||||
F: mm/memblock.c
|
F: mm/memblock.c
|
||||||
|
|
||||||
|
MEMORY CONTROLLER DRIVERS
|
||||||
|
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||||
|
L: linux-kernel@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
F: Documentation/devicetree/bindings/memory-controllers/
|
||||||
|
F: drivers/memory/
|
||||||
|
|
||||||
MEMORY MANAGEMENT
|
MEMORY MANAGEMENT
|
||||||
M: Andrew Morton <akpm@linux-foundation.org>
|
M: Andrew Morton <akpm@linux-foundation.org>
|
||||||
L: linux-mm@kvack.org
|
L: linux-mm@kvack.org
|
||||||
|
|
|
@ -5,6 +5,12 @@
|
||||||
|
|
||||||
menuconfig MEMORY
|
menuconfig MEMORY
|
||||||
bool "Memory Controller drivers"
|
bool "Memory Controller drivers"
|
||||||
|
help
|
||||||
|
This option allows to enable specific memory controller drivers,
|
||||||
|
useful mostly on embedded systems. These could be controllers
|
||||||
|
for DRAM (SDR, DDR), ROM, SRAM and others. The drivers features
|
||||||
|
vary from memory tuning and frequency scaling to enabling
|
||||||
|
access to attached peripherals through memory bus.
|
||||||
|
|
||||||
if MEMORY
|
if MEMORY
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ struct brcmstb_dpfe_priv {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *error_text[] = {
|
static const char * const error_text[] = {
|
||||||
"Success", "Header code incorrect", "Unknown command or argument",
|
"Success", "Header code incorrect", "Unknown command or argument",
|
||||||
"Incorrect checksum", "Malformed command", "Timed out",
|
"Incorrect checksum", "Malformed command", "Timed out",
|
||||||
};
|
};
|
||||||
|
@ -379,9 +379,8 @@ static void __iomem *get_msg_ptr(struct brcmstb_dpfe_priv *priv, u32 response,
|
||||||
void __iomem *ptr = NULL;
|
void __iomem *ptr = NULL;
|
||||||
|
|
||||||
/* There is no need to use this function for API v3 or later. */
|
/* There is no need to use this function for API v3 or later. */
|
||||||
if (unlikely(priv->dpfe_api->version >= 3)) {
|
if (unlikely(priv->dpfe_api->version >= 3))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
msg_type = (response >> DRAM_MSG_TYPE_OFFSET) & DRAM_MSG_TYPE_MASK;
|
msg_type = (response >> DRAM_MSG_TYPE_OFFSET) & DRAM_MSG_TYPE_MASK;
|
||||||
offset = (response >> DRAM_MSG_ADDR_OFFSET) & DRAM_MSG_ADDR_MASK;
|
offset = (response >> DRAM_MSG_ADDR_OFFSET) & DRAM_MSG_ADDR_MASK;
|
||||||
|
|
|
@ -102,14 +102,12 @@ static int da8xx_ddrctl_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
const struct da8xx_ddrctl_config_knob *knob;
|
const struct da8xx_ddrctl_config_knob *knob;
|
||||||
const struct da8xx_ddrctl_setting *setting;
|
const struct da8xx_ddrctl_setting *setting;
|
||||||
struct device_node *node;
|
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
void __iomem *ddrctl;
|
void __iomem *ddrctl;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
dev = &pdev->dev;
|
dev = &pdev->dev;
|
||||||
node = dev->of_node;
|
|
||||||
|
|
||||||
setting = da8xx_ddrctl_get_board_settings();
|
setting = da8xx_ddrctl_get_board_settings();
|
||||||
if (!setting) {
|
if (!setting) {
|
||||||
|
|
|
@ -1,16 +1,8 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
/*
|
/*
|
||||||
* TI AM33XX EMIF PM Assembly Offsets
|
* TI AM33XX EMIF PM Assembly Offsets
|
||||||
*
|
*
|
||||||
* Copyright (C) 2016-2017 Texas Instruments Inc.
|
* Copyright (C) 2016-2017 Texas Instruments Inc.
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation version 2.
|
|
||||||
*
|
|
||||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
|
||||||
* kind, whether express or implied; without even the implied warranty
|
|
||||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
*/
|
||||||
#include <linux/ti-emif-sram.h>
|
#include <linux/ti-emif-sram.h>
|
||||||
|
|
||||||
|
|
|
@ -282,10 +282,9 @@ static void set_lpmode(struct emif_data *emif, u8 lpmode)
|
||||||
* the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field to 0x4.
|
* the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field to 0x4.
|
||||||
*/
|
*/
|
||||||
if ((emif->plat_data->ip_rev == EMIF_4D) &&
|
if ((emif->plat_data->ip_rev == EMIF_4D) &&
|
||||||
(EMIF_LP_MODE_PWR_DN == lpmode)) {
|
(lpmode == EMIF_LP_MODE_PWR_DN)) {
|
||||||
WARN_ONCE(1,
|
WARN_ONCE(1,
|
||||||
"REG_LP_MODE = LP_MODE_PWR_DN(4) is prohibited by"
|
"REG_LP_MODE = LP_MODE_PWR_DN(4) is prohibited by erratum i743 switch to LP_MODE_SELF_REFRESH(2)\n");
|
||||||
"erratum i743 switch to LP_MODE_SELF_REFRESH(2)\n");
|
|
||||||
/* rollback LP_MODE to Self-refresh mode */
|
/* rollback LP_MODE to Self-refresh mode */
|
||||||
lpmode = EMIF_LP_MODE_SELF_REFRESH;
|
lpmode = EMIF_LP_MODE_SELF_REFRESH;
|
||||||
}
|
}
|
||||||
|
@ -714,7 +713,7 @@ static u32 get_ext_phy_ctrl_2_intelliphy_4d5(void)
|
||||||
u32 fifo_we_slave_ratio;
|
u32 fifo_we_slave_ratio;
|
||||||
|
|
||||||
fifo_we_slave_ratio = DIV_ROUND_CLOSEST(
|
fifo_we_slave_ratio = DIV_ROUND_CLOSEST(
|
||||||
EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
|
EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256, t_ck);
|
||||||
|
|
||||||
return fifo_we_slave_ratio | fifo_we_slave_ratio << 11 |
|
return fifo_we_slave_ratio | fifo_we_slave_ratio << 11 |
|
||||||
fifo_we_slave_ratio << 22;
|
fifo_we_slave_ratio << 22;
|
||||||
|
@ -725,7 +724,7 @@ static u32 get_ext_phy_ctrl_3_intelliphy_4d5(void)
|
||||||
u32 fifo_we_slave_ratio;
|
u32 fifo_we_slave_ratio;
|
||||||
|
|
||||||
fifo_we_slave_ratio = DIV_ROUND_CLOSEST(
|
fifo_we_slave_ratio = DIV_ROUND_CLOSEST(
|
||||||
EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
|
EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256, t_ck);
|
||||||
|
|
||||||
return fifo_we_slave_ratio >> 10 | fifo_we_slave_ratio << 1 |
|
return fifo_we_slave_ratio >> 10 | fifo_we_slave_ratio << 1 |
|
||||||
fifo_we_slave_ratio << 12 | fifo_we_slave_ratio << 23;
|
fifo_we_slave_ratio << 12 | fifo_we_slave_ratio << 23;
|
||||||
|
@ -736,7 +735,7 @@ static u32 get_ext_phy_ctrl_4_intelliphy_4d5(void)
|
||||||
u32 fifo_we_slave_ratio;
|
u32 fifo_we_slave_ratio;
|
||||||
|
|
||||||
fifo_we_slave_ratio = DIV_ROUND_CLOSEST(
|
fifo_we_slave_ratio = DIV_ROUND_CLOSEST(
|
||||||
EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
|
EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256, t_ck);
|
||||||
|
|
||||||
return fifo_we_slave_ratio >> 9 | fifo_we_slave_ratio << 2 |
|
return fifo_we_slave_ratio >> 9 | fifo_we_slave_ratio << 2 |
|
||||||
fifo_we_slave_ratio << 13;
|
fifo_we_slave_ratio << 13;
|
||||||
|
@ -975,8 +974,7 @@ static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif)
|
||||||
EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART)) {
|
EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART)) {
|
||||||
if (emif->temperature_level >= SDRAM_TEMP_HIGH_DERATE_REFRESH) {
|
if (emif->temperature_level >= SDRAM_TEMP_HIGH_DERATE_REFRESH) {
|
||||||
dev_err(emif->dev,
|
dev_err(emif->dev,
|
||||||
"%s:NOT Extended temperature capable memory."
|
"%s:NOT Extended temperature capable memory. Converting MR4=0x%02x as shutdown event\n",
|
||||||
"Converting MR4=0x%02x as shutdown event\n",
|
|
||||||
__func__, emif->temperature_level);
|
__func__, emif->temperature_level);
|
||||||
/*
|
/*
|
||||||
* Temperature far too high - do kernel_power_off()
|
* Temperature far too high - do kernel_power_off()
|
||||||
|
@ -1318,9 +1316,9 @@ static void __init_or_module of_get_ddr_info(struct device_node *np_emif,
|
||||||
if (of_find_property(np_emif, "cal-resistor-per-cs", &len))
|
if (of_find_property(np_emif, "cal-resistor-per-cs", &len))
|
||||||
dev_info->cal_resistors_per_cs = true;
|
dev_info->cal_resistors_per_cs = true;
|
||||||
|
|
||||||
if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s4"))
|
if (of_device_is_compatible(np_ddr, "jedec,lpddr2-s4"))
|
||||||
dev_info->type = DDR_TYPE_LPDDR2_S4;
|
dev_info->type = DDR_TYPE_LPDDR2_S4;
|
||||||
else if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s2"))
|
else if (of_device_is_compatible(np_ddr, "jedec,lpddr2-s2"))
|
||||||
dev_info->type = DDR_TYPE_LPDDR2_S2;
|
dev_info->type = DDR_TYPE_LPDDR2_S2;
|
||||||
|
|
||||||
of_property_read_u32(np_ddr, "density", &density);
|
of_property_read_u32(np_ddr, "density", &density);
|
||||||
|
@ -1563,11 +1561,8 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0) {
|
if (irq < 0)
|
||||||
dev_err(emif->dev, "%s: error getting IRQ resource - %d\n",
|
|
||||||
__func__, irq);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
emif_onetime_settings(emif);
|
emif_onetime_settings(emif);
|
||||||
emif_debugfs_init(emif);
|
emif_debugfs_init(emif);
|
||||||
|
|
|
@ -53,6 +53,7 @@ int fsl_ifc_find(phys_addr_t addr_base)
|
||||||
|
|
||||||
for (i = 0; i < fsl_ifc_ctrl_dev->banks; i++) {
|
for (i = 0; i < fsl_ifc_ctrl_dev->banks; i++) {
|
||||||
u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->gregs->cspr_cs[i].cspr);
|
u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->gregs->cspr_cs[i].cspr);
|
||||||
|
|
||||||
if (cspr & CSPR_V && (cspr & CSPR_BA) ==
|
if (cspr & CSPR_V && (cspr & CSPR_BA) ==
|
||||||
convert_ifc_address(addr_base))
|
convert_ifc_address(addr_base))
|
||||||
return i;
|
return i;
|
||||||
|
@ -153,8 +154,8 @@ static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data)
|
||||||
/* read for chip select error */
|
/* read for chip select error */
|
||||||
cs_err = ifc_in32(&ifc->cm_evter_stat);
|
cs_err = ifc_in32(&ifc->cm_evter_stat);
|
||||||
if (cs_err) {
|
if (cs_err) {
|
||||||
dev_err(ctrl->dev, "transaction sent to IFC is not mapped to"
|
dev_err(ctrl->dev, "transaction sent to IFC is not mapped to any memory bank 0x%08X\n",
|
||||||
"any memory bank 0x%08X\n", cs_err);
|
cs_err);
|
||||||
/* clear the chip select error */
|
/* clear the chip select error */
|
||||||
ifc_out32(IFC_CM_EVTER_STAT_CSER, &ifc->cm_evter_stat);
|
ifc_out32(IFC_CM_EVTER_STAT_CSER, &ifc->cm_evter_stat);
|
||||||
|
|
||||||
|
@ -163,24 +164,24 @@ static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data)
|
||||||
err_addr = ifc_in32(&ifc->cm_erattr1);
|
err_addr = ifc_in32(&ifc->cm_erattr1);
|
||||||
|
|
||||||
if (status & IFC_CM_ERATTR0_ERTYP_READ)
|
if (status & IFC_CM_ERATTR0_ERTYP_READ)
|
||||||
dev_err(ctrl->dev, "Read transaction error"
|
dev_err(ctrl->dev, "Read transaction error CM_ERATTR0 0x%08X\n",
|
||||||
"CM_ERATTR0 0x%08X\n", status);
|
status);
|
||||||
else
|
else
|
||||||
dev_err(ctrl->dev, "Write transaction error"
|
dev_err(ctrl->dev, "Write transaction error CM_ERATTR0 0x%08X\n",
|
||||||
"CM_ERATTR0 0x%08X\n", status);
|
status);
|
||||||
|
|
||||||
err_axiid = (status & IFC_CM_ERATTR0_ERAID) >>
|
err_axiid = (status & IFC_CM_ERATTR0_ERAID) >>
|
||||||
IFC_CM_ERATTR0_ERAID_SHIFT;
|
IFC_CM_ERATTR0_ERAID_SHIFT;
|
||||||
dev_err(ctrl->dev, "AXI ID of the error"
|
dev_err(ctrl->dev, "AXI ID of the error transaction 0x%08X\n",
|
||||||
"transaction 0x%08X\n", err_axiid);
|
err_axiid);
|
||||||
|
|
||||||
err_srcid = (status & IFC_CM_ERATTR0_ESRCID) >>
|
err_srcid = (status & IFC_CM_ERATTR0_ESRCID) >>
|
||||||
IFC_CM_ERATTR0_ESRCID_SHIFT;
|
IFC_CM_ERATTR0_ESRCID_SHIFT;
|
||||||
dev_err(ctrl->dev, "SRC ID of the error"
|
dev_err(ctrl->dev, "SRC ID of the error transaction 0x%08X\n",
|
||||||
"transaction 0x%08X\n", err_srcid);
|
err_srcid);
|
||||||
|
|
||||||
dev_err(ctrl->dev, "Transaction Address corresponding to error"
|
dev_err(ctrl->dev, "Transaction Address corresponding to error ERADDR 0x%08X\n",
|
||||||
"ERADDR 0x%08X\n", err_addr);
|
err_addr);
|
||||||
|
|
||||||
ret = IRQ_HANDLED;
|
ret = IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
@ -199,7 +200,7 @@ static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data)
|
||||||
* the resources needed for the controller only. The
|
* the resources needed for the controller only. The
|
||||||
* resources for the NAND banks themselves are allocated
|
* resources for the NAND banks themselves are allocated
|
||||||
* in the chip probe function.
|
* in the chip probe function.
|
||||||
*/
|
*/
|
||||||
static int fsl_ifc_ctrl_probe(struct platform_device *dev)
|
static int fsl_ifc_ctrl_probe(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -250,8 +251,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev)
|
||||||
/* get the Controller level irq */
|
/* get the Controller level irq */
|
||||||
fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
|
fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
|
||||||
if (fsl_ifc_ctrl_dev->irq == 0) {
|
if (fsl_ifc_ctrl_dev->irq == 0) {
|
||||||
dev_err(&dev->dev, "failed to get irq resource "
|
dev_err(&dev->dev, "failed to get irq resource for IFC\n");
|
||||||
"for IFC\n");
|
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ struct mtk_smi_common_plat {
|
||||||
|
|
||||||
struct mtk_smi_larb_gen {
|
struct mtk_smi_larb_gen {
|
||||||
int port_in_larb[MTK_LARB_NR_MAX + 1];
|
int port_in_larb[MTK_LARB_NR_MAX + 1];
|
||||||
void (*config_port)(struct device *);
|
void (*config_port)(struct device *dev);
|
||||||
unsigned int larb_direct_to_common_mask;
|
unsigned int larb_direct_to_common_mask;
|
||||||
bool has_gals;
|
bool has_gals;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,11 +4,10 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||||
* Copyright (C) 2019 Samsung Electronics Co., Ltd.
|
* Copyright (C) 2019 Samsung Electronics Co., Ltd.
|
||||||
|
* Copyright (C) 2020 Krzysztof Kozlowski <krzk@kernel.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#include <linux/list.h>
|
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/gfp.h>
|
#include <linux/gfp.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
|
@ -27,7 +26,7 @@
|
||||||
* default min timings provided by JEDEC.
|
* default min timings provided by JEDEC.
|
||||||
*/
|
*/
|
||||||
const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
|
const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct lpddr2_min_tck *min;
|
struct lpddr2_min_tck *min;
|
||||||
|
@ -56,13 +55,13 @@ const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
|
||||||
return min;
|
return min;
|
||||||
|
|
||||||
default_min_tck:
|
default_min_tck:
|
||||||
dev_warn(dev, "%s: using default min-tck values\n", __func__);
|
dev_warn(dev, "Using default min-tck values\n");
|
||||||
return &lpddr2_jedec_min_tck;
|
return &lpddr2_jedec_min_tck;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(of_get_min_tck);
|
EXPORT_SYMBOL(of_get_min_tck);
|
||||||
|
|
||||||
static int of_do_get_timings(struct device_node *np,
|
static int of_do_get_timings(struct device_node *np,
|
||||||
struct lpddr2_timings *tim)
|
struct lpddr2_timings *tim)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -84,7 +83,7 @@ static int of_do_get_timings(struct device_node *np,
|
||||||
ret |= of_property_read_u32(np, "tZQinit", &tim->tZQinit);
|
ret |= of_property_read_u32(np, "tZQinit", &tim->tZQinit);
|
||||||
ret |= of_property_read_u32(np, "tRAS-max-ns", &tim->tRAS_max_ns);
|
ret |= of_property_read_u32(np, "tRAS-max-ns", &tim->tRAS_max_ns);
|
||||||
ret |= of_property_read_u32(np, "tDQSCK-max-derated",
|
ret |= of_property_read_u32(np, "tDQSCK-max-derated",
|
||||||
&tim->tDQSCK_max_derated);
|
&tim->tDQSCK_max_derated);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +102,9 @@ static int of_do_get_timings(struct device_node *np,
|
||||||
* while populating, returns default timings provided by JEDEC.
|
* while populating, returns default timings provided by JEDEC.
|
||||||
*/
|
*/
|
||||||
const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
|
const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
|
||||||
struct device *dev, u32 device_type, u32 *nr_frequencies)
|
struct device *dev,
|
||||||
|
u32 device_type,
|
||||||
|
u32 *nr_frequencies)
|
||||||
{
|
{
|
||||||
struct lpddr2_timings *timings = NULL;
|
struct lpddr2_timings *timings = NULL;
|
||||||
u32 arr_sz = 0, i = 0;
|
u32 arr_sz = 0, i = 0;
|
||||||
|
@ -116,7 +117,7 @@ const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
|
||||||
tim_compat = "jedec,lpddr2-timings";
|
tim_compat = "jedec,lpddr2-timings";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_warn(dev, "%s: un-supported memory type\n", __func__);
|
dev_warn(dev, "Unsupported memory type\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_child_of_node(np_ddr, np_tim)
|
for_each_child_of_node(np_ddr, np_tim)
|
||||||
|
@ -145,7 +146,7 @@ const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
|
||||||
return timings;
|
return timings;
|
||||||
|
|
||||||
default_timings:
|
default_timings:
|
||||||
dev_warn(dev, "%s: using default timings\n", __func__);
|
dev_warn(dev, "Using default memory timings\n");
|
||||||
*nr_frequencies = ARRAY_SIZE(lpddr2_jedec_timings);
|
*nr_frequencies = ARRAY_SIZE(lpddr2_jedec_timings);
|
||||||
return lpddr2_jedec_timings;
|
return lpddr2_jedec_timings;
|
||||||
}
|
}
|
||||||
|
@ -193,8 +194,7 @@ const struct lpddr3_min_tck *of_lpddr3_get_min_tck(struct device_node *np,
|
||||||
ret |= of_property_read_u32(np, "tMRD-min-tck", &min->tMRD);
|
ret |= of_property_read_u32(np, "tMRD-min-tck", &min->tMRD);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_warn(dev, "%s: errors while parsing min-tck values\n",
|
dev_warn(dev, "Errors while parsing min-tck values\n");
|
||||||
__func__);
|
|
||||||
devm_kfree(dev, min);
|
devm_kfree(dev, min);
|
||||||
goto default_min_tck;
|
goto default_min_tck;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ const struct lpddr3_min_tck *of_lpddr3_get_min_tck(struct device_node *np,
|
||||||
return min;
|
return min;
|
||||||
|
|
||||||
default_min_tck:
|
default_min_tck:
|
||||||
dev_warn(dev, "%s: using default min-tck values\n", __func__);
|
dev_warn(dev, "Using default min-tck values\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(of_lpddr3_get_min_tck);
|
EXPORT_SYMBOL(of_lpddr3_get_min_tck);
|
||||||
|
@ -264,7 +264,7 @@ const struct lpddr3_timings
|
||||||
tim_compat = "jedec,lpddr3-timings";
|
tim_compat = "jedec,lpddr3-timings";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_warn(dev, "%s: un-supported memory type\n", __func__);
|
dev_warn(dev, "Unsupported memory type\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_child_of_node(np_ddr, np_tim)
|
for_each_child_of_node(np_ddr, np_tim)
|
||||||
|
@ -293,7 +293,7 @@ const struct lpddr3_timings
|
||||||
return timings;
|
return timings;
|
||||||
|
|
||||||
default_timings:
|
default_timings:
|
||||||
dev_warn(dev, "%s: failed to get timings\n", __func__);
|
dev_warn(dev, "Failed to get timings\n");
|
||||||
*nr_frequencies = 0;
|
*nr_frequencies = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,22 +3,23 @@
|
||||||
* OpenFirmware helpers for memory drivers
|
* OpenFirmware helpers for memory drivers
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||||
|
* Copyright (C) 2020 Krzysztof Kozlowski <krzk@kernel.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __LINUX_MEMORY_OF_REG_H
|
#ifndef __LINUX_MEMORY_OF_REG_H
|
||||||
#define __LINUX_MEMORY_OF_REG_H
|
#define __LINUX_MEMORY_OF_REG_H
|
||||||
|
|
||||||
#if defined(CONFIG_OF) && defined(CONFIG_DDR)
|
#if defined(CONFIG_OF) && defined(CONFIG_DDR)
|
||||||
extern const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
|
const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
|
||||||
struct device *dev);
|
struct device *dev);
|
||||||
extern const struct lpddr2_timings
|
const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
|
||||||
*of_get_ddr_timings(struct device_node *np_ddr, struct device *dev,
|
struct device *dev,
|
||||||
u32 device_type, u32 *nr_frequencies);
|
u32 device_type, u32 *nr_frequencies);
|
||||||
extern const struct lpddr3_min_tck
|
const struct lpddr3_min_tck *of_lpddr3_get_min_tck(struct device_node *np,
|
||||||
*of_lpddr3_get_min_tck(struct device_node *np, struct device *dev);
|
struct device *dev);
|
||||||
extern const struct lpddr3_timings
|
const struct lpddr3_timings *
|
||||||
*of_lpddr3_get_ddr_timings(struct device_node *np_ddr,
|
of_lpddr3_get_ddr_timings(struct device_node *np_ddr,
|
||||||
struct device *dev, u32 device_type, u32 *nr_frequencies);
|
struct device *dev, u32 device_type, u32 *nr_frequencies);
|
||||||
#else
|
#else
|
||||||
static inline const struct lpddr2_min_tck
|
static inline const struct lpddr2_min_tck
|
||||||
*of_get_min_tck(struct device_node *np, struct device *dev)
|
*of_get_min_tck(struct device_node *np, struct device *dev)
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/omap-gpmc.h>
|
#include <linux/omap-gpmc.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/sizes.h>
|
||||||
|
|
||||||
#include <linux/platform_data/mtd-nand-omap2.h>
|
#include <linux/platform_data/mtd-nand-omap2.h>
|
||||||
|
|
||||||
|
@ -958,7 +959,7 @@ static int gpmc_cs_remap(int cs, u32 base)
|
||||||
* Make sure we ignore any device offsets from the GPMC partition
|
* Make sure we ignore any device offsets from the GPMC partition
|
||||||
* allocated for the chip select and that the new base confirms
|
* allocated for the chip select and that the new base confirms
|
||||||
* to the GPMC 16MB minimum granularity.
|
* to the GPMC 16MB minimum granularity.
|
||||||
*/
|
*/
|
||||||
base &= ~(SZ_16M - 1);
|
base &= ~(SZ_16M - 1);
|
||||||
|
|
||||||
gpmc_cs_get_memconf(cs, &old_base, &size);
|
gpmc_cs_get_memconf(cs, &old_base, &size);
|
||||||
|
@ -1753,10 +1754,11 @@ static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: remove this function once all peripherals are confirmed to
|
/*
|
||||||
|
* TODO: remove this function once all peripherals are confirmed to
|
||||||
* work with generic timing. Simultaneously gpmc_cs_set_timings()
|
* work with generic timing. Simultaneously gpmc_cs_set_timings()
|
||||||
* has to be modified to handle timings in ps instead of ns
|
* has to be modified to handle timings in ps instead of ns
|
||||||
*/
|
*/
|
||||||
static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
|
static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
|
||||||
{
|
{
|
||||||
t->cs_on /= 1000;
|
t->cs_on /= 1000;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
/*
|
/*
|
||||||
* Memory controller driver for ARM PrimeCell PL172
|
* Memory controller driver for ARM PrimeCell PL172
|
||||||
* PrimeCell MultiPort Memory Controller (PL172)
|
* PrimeCell MultiPort Memory Controller (PL172)
|
||||||
|
@ -6,10 +7,6 @@
|
||||||
*
|
*
|
||||||
* Based on:
|
* Based on:
|
||||||
* TI AEMIF driver, Copyright (C) 2010 - 2013 Texas Instruments Inc.
|
* TI AEMIF driver, Copyright (C) 2010 - 2013 Texas Instruments Inc.
|
||||||
*
|
|
||||||
* This file is licensed under the terms of the GNU General Public
|
|
||||||
* License version 2. This program is licensed "as is" without any
|
|
||||||
* warranty of any kind, whether express or implied.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/amba/bus.h>
|
#include <linux/amba/bus.h>
|
||||||
|
|
|
@ -23,5 +23,12 @@ config EXYNOS5422_DMC
|
||||||
config EXYNOS_SROM
|
config EXYNOS_SROM
|
||||||
bool "Exynos SROM controller driver" if COMPILE_TEST
|
bool "Exynos SROM controller driver" if COMPILE_TEST
|
||||||
depends on (ARM && ARCH_EXYNOS) || (COMPILE_TEST && HAS_IOMEM)
|
depends on (ARM && ARCH_EXYNOS) || (COMPILE_TEST && HAS_IOMEM)
|
||||||
|
help
|
||||||
|
This adds driver for Samsung Exynos SoC SROM controller. The driver
|
||||||
|
in basic operation mode only saves and restores SROM registers
|
||||||
|
during suspend. If however appropriate device tree configuration
|
||||||
|
is provided, the driver enables support for external memory
|
||||||
|
or external devices.
|
||||||
|
If unsure, say Y on devices with Samsung Exynos SocS.
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -270,12 +270,14 @@ static int find_target_freq_idx(struct exynos5_dmc *dmc,
|
||||||
* This function switches between these banks according to the
|
* This function switches between these banks according to the
|
||||||
* currently used clock source.
|
* currently used clock source.
|
||||||
*/
|
*/
|
||||||
static void exynos5_switch_timing_regs(struct exynos5_dmc *dmc, bool set)
|
static int exynos5_switch_timing_regs(struct exynos5_dmc *dmc, bool set)
|
||||||
{
|
{
|
||||||
unsigned int reg;
|
unsigned int reg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = regmap_read(dmc->clk_regmap, CDREX_LPDDR3PHY_CON3, ®);
|
ret = regmap_read(dmc->clk_regmap, CDREX_LPDDR3PHY_CON3, ®);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (set)
|
if (set)
|
||||||
reg |= EXYNOS5_TIMING_SET_SWI;
|
reg |= EXYNOS5_TIMING_SET_SWI;
|
||||||
|
@ -283,6 +285,8 @@ static void exynos5_switch_timing_regs(struct exynos5_dmc *dmc, bool set)
|
||||||
reg &= ~EXYNOS5_TIMING_SET_SWI;
|
reg &= ~EXYNOS5_TIMING_SET_SWI;
|
||||||
|
|
||||||
regmap_write(dmc->clk_regmap, CDREX_LPDDR3PHY_CON3, reg);
|
regmap_write(dmc->clk_regmap, CDREX_LPDDR3PHY_CON3, reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -516,7 +520,7 @@ exynos5_dmc_switch_to_bypass_configuration(struct exynos5_dmc *dmc,
|
||||||
/*
|
/*
|
||||||
* Delays are long enough, so use them for the new coming clock.
|
* Delays are long enough, so use them for the new coming clock.
|
||||||
*/
|
*/
|
||||||
exynos5_switch_timing_regs(dmc, USE_MX_MSPLL_TIMINGS);
|
ret = exynos5_switch_timing_regs(dmc, USE_MX_MSPLL_TIMINGS);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -577,7 +581,9 @@ exynos5_dmc_change_freq_and_volt(struct exynos5_dmc *dmc,
|
||||||
|
|
||||||
clk_set_rate(dmc->fout_bpll, target_rate);
|
clk_set_rate(dmc->fout_bpll, target_rate);
|
||||||
|
|
||||||
exynos5_switch_timing_regs(dmc, USE_BPLL_TIMINGS);
|
ret = exynos5_switch_timing_regs(dmc, USE_BPLL_TIMINGS);
|
||||||
|
if (ret)
|
||||||
|
goto disable_clocks;
|
||||||
|
|
||||||
ret = clk_set_parent(dmc->mout_mclk_cdrex, dmc->mout_bpll);
|
ret = clk_set_parent(dmc->mout_mclk_cdrex, dmc->mout_bpll);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#define WSTROBE_SHIFT 20
|
#define WSTROBE_SHIFT 20
|
||||||
#define WSETUP_SHIFT 26
|
#define WSETUP_SHIFT 26
|
||||||
#define EW_SHIFT 30
|
#define EW_SHIFT 30
|
||||||
#define SS_SHIFT 31
|
#define SSTROBE_SHIFT 31
|
||||||
|
|
||||||
#define TA(x) ((x) << TA_SHIFT)
|
#define TA(x) ((x) << TA_SHIFT)
|
||||||
#define RHOLD(x) ((x) << RHOLD_SHIFT)
|
#define RHOLD(x) ((x) << RHOLD_SHIFT)
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
#define WSTROBE(x) ((x) << WSTROBE_SHIFT)
|
#define WSTROBE(x) ((x) << WSTROBE_SHIFT)
|
||||||
#define WSETUP(x) ((x) << WSETUP_SHIFT)
|
#define WSETUP(x) ((x) << WSETUP_SHIFT)
|
||||||
#define EW(x) ((x) << EW_SHIFT)
|
#define EW(x) ((x) << EW_SHIFT)
|
||||||
#define SS(x) ((x) << SS_SHIFT)
|
#define SSTROBE(x) ((x) << SSTROBE_SHIFT)
|
||||||
|
|
||||||
#define ASIZE_MAX 0x1
|
#define ASIZE_MAX 0x1
|
||||||
#define TA_MAX 0x3
|
#define TA_MAX 0x3
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
#define WSTROBE_MAX 0x3f
|
#define WSTROBE_MAX 0x3f
|
||||||
#define WSETUP_MAX 0xf
|
#define WSETUP_MAX 0xf
|
||||||
#define EW_MAX 0x1
|
#define EW_MAX 0x1
|
||||||
#define SS_MAX 0x1
|
#define SSTROBE_MAX 0x1
|
||||||
#define NUM_CS 4
|
#define NUM_CS 4
|
||||||
|
|
||||||
#define TA_VAL(x) (((x) & TA(TA_MAX)) >> TA_SHIFT)
|
#define TA_VAL(x) (((x) & TA(TA_MAX)) >> TA_SHIFT)
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
#define WSTROBE_VAL(x) (((x) & WSTROBE(WSTROBE_MAX)) >> WSTROBE_SHIFT)
|
#define WSTROBE_VAL(x) (((x) & WSTROBE(WSTROBE_MAX)) >> WSTROBE_SHIFT)
|
||||||
#define WSETUP_VAL(x) (((x) & WSETUP(WSETUP_MAX)) >> WSETUP_SHIFT)
|
#define WSETUP_VAL(x) (((x) & WSETUP(WSETUP_MAX)) >> WSETUP_SHIFT)
|
||||||
#define EW_VAL(x) (((x) & EW(EW_MAX)) >> EW_SHIFT)
|
#define EW_VAL(x) (((x) & EW(EW_MAX)) >> EW_SHIFT)
|
||||||
#define SS_VAL(x) (((x) & SS(SS_MAX)) >> SS_SHIFT)
|
#define SSTROBE_VAL(x) (((x) & SSTROBE(SSTROBE_MAX)) >> SSTROBE_SHIFT)
|
||||||
|
|
||||||
#define NRCSR_OFFSET 0x00
|
#define NRCSR_OFFSET 0x00
|
||||||
#define AWCCR_OFFSET 0x04
|
#define AWCCR_OFFSET 0x04
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
|
|
||||||
#define ACR_ASIZE_MASK 0x3
|
#define ACR_ASIZE_MASK 0x3
|
||||||
#define ACR_EW_MASK BIT(30)
|
#define ACR_EW_MASK BIT(30)
|
||||||
#define ACR_SS_MASK BIT(31)
|
#define ACR_SSTROBE_MASK BIT(31)
|
||||||
#define ASIZE_16BIT 1
|
#define ASIZE_16BIT 1
|
||||||
|
|
||||||
#define CONFIG_MASK (TA(TA_MAX) | \
|
#define CONFIG_MASK (TA(TA_MAX) | \
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
WHOLD(WHOLD_MAX) | \
|
WHOLD(WHOLD_MAX) | \
|
||||||
WSTROBE(WSTROBE_MAX) | \
|
WSTROBE(WSTROBE_MAX) | \
|
||||||
WSETUP(WSETUP_MAX) | \
|
WSETUP(WSETUP_MAX) | \
|
||||||
EW(EW_MAX) | SS(SS_MAX) | \
|
EW(EW_MAX) | SSTROBE(SSTROBE_MAX) | \
|
||||||
ASIZE_MAX)
|
ASIZE_MAX)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,7 +204,7 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum)
|
||||||
if (data->enable_ew)
|
if (data->enable_ew)
|
||||||
set |= ACR_EW_MASK;
|
set |= ACR_EW_MASK;
|
||||||
if (data->enable_ss)
|
if (data->enable_ss)
|
||||||
set |= ACR_SS_MASK;
|
set |= ACR_SSTROBE_MASK;
|
||||||
|
|
||||||
val = readl(aemif->base + offset);
|
val = readl(aemif->base + offset);
|
||||||
val &= ~CONFIG_MASK;
|
val &= ~CONFIG_MASK;
|
||||||
|
@ -246,7 +246,7 @@ static void aemif_get_hw_params(struct platform_device *pdev, int csnum)
|
||||||
data->wstrobe = aemif_cycles_to_nsec(WSTROBE_VAL(val), clk_rate);
|
data->wstrobe = aemif_cycles_to_nsec(WSTROBE_VAL(val), clk_rate);
|
||||||
data->wsetup = aemif_cycles_to_nsec(WSETUP_VAL(val), clk_rate);
|
data->wsetup = aemif_cycles_to_nsec(WSETUP_VAL(val), clk_rate);
|
||||||
data->enable_ew = EW_VAL(val);
|
data->enable_ew = EW_VAL(val);
|
||||||
data->enable_ss = SS_VAL(val);
|
data->enable_ss = SSTROBE_VAL(val);
|
||||||
data->asize = val & ASIZE_MAX;
|
data->asize = val & ASIZE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -248,7 +248,7 @@ MODULE_DEVICE_TABLE(of, ti_emif_of_match);
|
||||||
static int ti_emif_resume(struct device *dev)
|
static int ti_emif_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
unsigned long tmp =
|
unsigned long tmp =
|
||||||
__raw_readl((void *)emif_instance->ti_emif_sram_virt);
|
__raw_readl((void __iomem *)emif_instance->ti_emif_sram_virt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check to see if what we are copying is already present in the
|
* Check to see if what we are copying is already present in the
|
||||||
|
|
Loading…
Reference in New Issue