mirror of
https://github.com/torvalds/linux.git
synced 2024-12-14 15:13:52 +00:00
Memory controller drivers for v5.10
1. Fixes in several drivers for GCC warnings, including kerneldoc fixes and issues discovered while compile testing. 2. Enable compile testing of most of the drivers. 3. Use dev_err_probe() to simplify the code. 4. omap-gpmc: fix off by one errors, code cleanups and improvements. 5. tegra: remove the GPU from DRM IOMMU group so it would use its own; few minor fixes. 6. brcmstb_dpfe: fix memory leak and array index out of bounds. -----BEGIN PGP SIGNATURE----- iQJEBAABCgAuFiEE3dJiKD0RGyM7briowTdm5oaLg9cFAl9WGpYQHGtyemtAa2Vy bmVsLm9yZwAKCRDBN2bmhouD10jlEACU5EM8ZP0hUf4yPF/tdcUZ1oOdgR3yMb8C F6V0w++GnX/s+m4Zw9MwPM8xZWyvBRDqRPHJ7m0C+/GX9AY58S2T8lgbDxHQCdML cae/JBzEo2CPb+Ma3GLRxsy8ijWwDFMrOcnvVyH98LwwgXOR0/yCsahpiFGPHZr4 HFOtUgXyQ0RvD+Nm6aQMyOH0qaIwGULBbwelQNQdy4nmo5nIJdFFnxQtaj6KhMSu L1JVBFPE/sydTk+PHqeMXZE7D/YaU/8YCM9N5pdo7M8GW6qszlQ/pl4M9y+MDWD7 LrM8FL63B+iT5sDlneeFRNjtkZNHYBK2JmHpevCroHkaCliGoLGOCjT1MqtjJQK2 Vn07AEN8RuUkF//P5KsoaMVxaDWr9rwAQwyIj5kw3L0WwHMXxp7P4YSMETeN4wbD YmHFLNmjqTHtEyM00CIxwXzbClXzaDAQnihnS7eCTpLTz7ReebP5LE/uZ7XjlC1X YGFwQkoVfbiNEz1CzsihyHPfoBXkTXLn+6rTsHxuTOHDSgqqBC5dBAa4FgsSc2wH kkygEg3RRwmXWjiukuv5vAJkUtxvbbuEod4rfqjY18GTslwo9YBCT+sXq+K9qpog bHhPTcHLPvAAJhbzEPya8bhKEPTrsVq4etL1+ZkZ/HgTj1nQn5Tinjj9CNkek2/5 L6OiQBbDsA== =Vo29 -----END PGP SIGNATURE----- Merge tag 'memory-controller-drv-5.10' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl into arm/drivers Memory controller drivers for v5.10 1. Fixes in several drivers for GCC warnings, including kerneldoc fixes and issues discovered while compile testing. 2. Enable compile testing of most of the drivers. 3. Use dev_err_probe() to simplify the code. 4. omap-gpmc: fix off by one errors, code cleanups and improvements. 5. tegra: remove the GPU from DRM IOMMU group so it would use its own; few minor fixes. 6. brcmstb_dpfe: fix memory leak and array index out of bounds. * tag 'memory-controller-drv-5.10' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl: (26 commits) memory: fsl-corenet-cf: Fix handling of platform_get_irq() error memory: omap-gpmc: Fix -Wunused-function warnings memory: tegra: Remove GPU from DRM IOMMU group memory: tegra186-emc: Simplify with dev_err_probe() memory: brcmstb_dpfe: Simplify with dev_err_probe() memory: samsung: exynos5422-dmc: add missing and fix kerneldoc memory: samsung: exynos5422-dmc: remove unused exynos5_dmc members memory: samsung: exynos5422-dmc: rename timing register fields variables memory: emif: Remove bogus debugfs error handling memory: omap-gpmc: Fix build error without CONFIG_OF memory: omap-gpmc: Fix a couple off by ones memory: brcmstb_dpfe: fix array index out of bounds memory: brcmstb_dpfe: Fix memory leak memory: tegra: Correct shift value of apew memory: Enable compile testing for most of the drivers memory: brcmstb_dpfe: add separate entry for compile test memory: tegra: tegra210-emc: fix indentation memory: renesas-rpc-if: simplify with PTR_ERR_OR_ZERO memory: omap-gpmc: consistently use !res for NULL checks memory: omap-gpmc: use WARN() instead of BUG() on wrong free ... Link: https://lore.kernel.org/r/20200907150611.11267-1-krzk@kernel.org Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
bac9bd958a
@ -32,8 +32,9 @@ config ARM_PL172_MPMC
|
||||
|
||||
config ATMEL_SDRAMC
|
||||
bool "Atmel (Multi-port DDR-)SDRAM Controller"
|
||||
default y
|
||||
depends on ARCH_AT91 && OF
|
||||
default y if ARCH_AT91
|
||||
depends on ARCH_AT91 || COMPILE_TEST
|
||||
depends on OF
|
||||
help
|
||||
This driver is for Atmel SDRAM Controller or Atmel Multi-port
|
||||
DDR-SDRAM Controller available on Atmel AT91SAM9 and SAMA5 SoCs.
|
||||
@ -42,8 +43,9 @@ config ATMEL_SDRAMC
|
||||
|
||||
config ATMEL_EBI
|
||||
bool "Atmel EBI driver"
|
||||
default y
|
||||
depends on ARCH_AT91 && OF
|
||||
default y if ARCH_AT91
|
||||
depends on ARCH_AT91 || COMPILE_TEST
|
||||
depends on OF
|
||||
select MFD_SYSCON
|
||||
select MFD_ATMEL_SMC
|
||||
help
|
||||
@ -52,6 +54,18 @@ config ATMEL_EBI
|
||||
tree is used. This bus supports NANDs, external ethernet controller,
|
||||
SRAMs, ATA devices, etc.
|
||||
|
||||
config BRCMSTB_DPFE
|
||||
bool "Broadcom STB DPFE driver" if COMPILE_TEST
|
||||
default y if ARCH_BRCMSTB
|
||||
depends on ARCH_BRCMSTB || COMPILE_TEST
|
||||
help
|
||||
This driver provides access to the DPFE interface of Broadcom
|
||||
STB SoCs. The firmware running on the DCPU inside the DDR PHY can
|
||||
provide current information about the system's RAM, for instance
|
||||
the DRAM refresh rate. This can be used as an indirect indicator
|
||||
for the DRAM's temperature. Slower refresh rate means cooler RAM,
|
||||
higher refresh rate means hotter RAM.
|
||||
|
||||
config BT1_L2_CTL
|
||||
bool "Baikal-T1 CM2 L2-RAM Cache Control Block"
|
||||
depends on MIPS_BAIKAL_T1 || COMPILE_TEST
|
||||
@ -65,7 +79,8 @@ config BT1_L2_CTL
|
||||
|
||||
config TI_AEMIF
|
||||
tristate "Texas Instruments AEMIF driver"
|
||||
depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
|
||||
depends on ARCH_DAVINCI || ARCH_KEYSTONE || COMPILE_TEST
|
||||
depends on OF
|
||||
help
|
||||
This driver is for the AEMIF module available in Texas Instruments
|
||||
SoCs. AEMIF stands for Asynchronous External Memory Interface and
|
||||
@ -76,7 +91,7 @@ config TI_AEMIF
|
||||
|
||||
config TI_EMIF
|
||||
tristate "Texas Instruments EMIF driver"
|
||||
depends on ARCH_OMAP2PLUS
|
||||
depends on ARCH_OMAP2PLUS || COMPILE_TEST
|
||||
select DDR
|
||||
help
|
||||
This driver is for the EMIF module available in Texas Instruments
|
||||
@ -88,7 +103,7 @@ config TI_EMIF
|
||||
temperature changes
|
||||
|
||||
config OMAP_GPMC
|
||||
bool
|
||||
bool "Texas Instruments OMAP SoC GPMC driver" if COMPILE_TEST
|
||||
select GPIOLIB
|
||||
help
|
||||
This driver is for the General Purpose Memory Controller (GPMC)
|
||||
@ -112,7 +127,8 @@ config OMAP_GPMC_DEBUG
|
||||
|
||||
config TI_EMIF_SRAM
|
||||
tristate "Texas Instruments EMIF SRAM driver"
|
||||
depends on (SOC_AM33XX || SOC_AM43XX) && SRAM
|
||||
depends on SOC_AM33XX || SOC_AM43XX || (ARM && COMPILE_TEST)
|
||||
depends on SRAM
|
||||
help
|
||||
This driver is for the EMIF module available on Texas Instruments
|
||||
AM33XX and AM43XX SoCs and is required for PM. Certain parts of
|
||||
@ -122,8 +138,9 @@ config TI_EMIF_SRAM
|
||||
|
||||
config MVEBU_DEVBUS
|
||||
bool "Marvell EBU Device Bus Controller"
|
||||
default y
|
||||
depends on PLAT_ORION && OF
|
||||
default y if PLAT_ORION
|
||||
depends on PLAT_ORION || COMPILE_TEST
|
||||
depends on OF
|
||||
help
|
||||
This driver is for the Device Bus controller available in some
|
||||
Marvell EBU SoCs such as Discovery (mv78xx0), Orion (88f5xxx) and
|
||||
@ -132,7 +149,7 @@ config MVEBU_DEVBUS
|
||||
|
||||
config FSL_CORENET_CF
|
||||
tristate "Freescale CoreNet Error Reporting"
|
||||
depends on FSL_SOC_BOOKE
|
||||
depends on FSL_SOC_BOOKE || COMPILE_TEST
|
||||
help
|
||||
Say Y for reporting of errors from the Freescale CoreNet
|
||||
Coherency Fabric. Errors reported include accesses to
|
||||
@ -141,7 +158,7 @@ config FSL_CORENET_CF
|
||||
represents a coherency violation.
|
||||
|
||||
config FSL_IFC
|
||||
bool
|
||||
bool "Freescale IFC driver" if COMPILE_TEST
|
||||
depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
|
||||
@ -155,7 +172,7 @@ config JZ4780_NEMC
|
||||
memory devices such as NAND and SRAM.
|
||||
|
||||
config MTK_SMI
|
||||
bool
|
||||
bool "Mediatek SoC Memory Controller driver" if COMPILE_TEST
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
help
|
||||
This driver is for the Memory Controller module in MediaTek SoCs,
|
||||
@ -164,7 +181,7 @@ config MTK_SMI
|
||||
|
||||
config DA8XX_DDRCTL
|
||||
bool "Texas Instruments da8xx DDR2/mDDR driver"
|
||||
depends on ARCH_DAVINCI_DA8XX
|
||||
depends on ARCH_DAVINCI_DA8XX || COMPILE_TEST
|
||||
help
|
||||
This driver is for the DDR2/mDDR Memory Controller present on
|
||||
Texas Instruments da8xx SoCs. It's used to tweak various memory
|
||||
@ -172,16 +189,16 @@ config DA8XX_DDRCTL
|
||||
|
||||
config PL353_SMC
|
||||
tristate "ARM PL35X Static Memory Controller(SMC) driver"
|
||||
default y
|
||||
default y if ARM
|
||||
depends on ARM
|
||||
depends on ARM_AMBA
|
||||
depends on ARM_AMBA || COMPILE_TEST
|
||||
help
|
||||
This driver is for the ARM PL351/PL353 Static Memory
|
||||
Controller(SMC) module.
|
||||
|
||||
config RENESAS_RPCIF
|
||||
tristate "Renesas RPC-IF driver"
|
||||
depends on ARCH_RENESAS
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
This supports Renesas R-Car Gen3 RPC-IF which provides either SPI
|
||||
|
@ -10,7 +10,7 @@ endif
|
||||
obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o
|
||||
obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o
|
||||
obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o
|
||||
obj-$(CONFIG_ARCH_BRCMSTB) += brcmstb_dpfe.o
|
||||
obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o
|
||||
obj-$(CONFIG_BT1_L2_CTL) += bt1-l2-ctl.o
|
||||
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
|
||||
obj-$(CONFIG_TI_EMIF) += emif.o
|
||||
|
@ -188,11 +188,6 @@ struct brcmstb_dpfe_priv {
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
static const char * const error_text[] = {
|
||||
"Success", "Header code incorrect", "Unknown command or argument",
|
||||
"Incorrect checksum", "Malformed command", "Timed out",
|
||||
};
|
||||
|
||||
/*
|
||||
* Forward declaration of our sysfs attribute functions, so we can declare the
|
||||
* attribute data structures early.
|
||||
@ -307,6 +302,20 @@ static const struct dpfe_api dpfe_api_v3 = {
|
||||
},
|
||||
};
|
||||
|
||||
static const char *get_error_text(unsigned int i)
|
||||
{
|
||||
static const char * const error_text[] = {
|
||||
"Success", "Header code incorrect",
|
||||
"Unknown command or argument", "Incorrect checksum",
|
||||
"Malformed command", "Timed out", "Unknown error",
|
||||
};
|
||||
|
||||
if (unlikely(i >= ARRAY_SIZE(error_text)))
|
||||
i = ARRAY_SIZE(error_text) - 1;
|
||||
|
||||
return error_text[i];
|
||||
}
|
||||
|
||||
static bool is_dcpu_enabled(struct brcmstb_dpfe_priv *priv)
|
||||
{
|
||||
u32 val;
|
||||
@ -445,7 +454,7 @@ static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd,
|
||||
}
|
||||
if (resp != 0) {
|
||||
mutex_unlock(&priv->lock);
|
||||
return -ETIMEDOUT;
|
||||
return -ffs(DCPU_RET_ERR_TIMEDOUT);
|
||||
}
|
||||
|
||||
/* Compute checksum over the message */
|
||||
@ -647,8 +656,10 @@ static int brcmstb_dpfe_download_firmware(struct brcmstb_dpfe_priv *priv)
|
||||
return (ret == -ENOENT) ? -EPROBE_DEFER : ret;
|
||||
|
||||
ret = __verify_firmware(&init, fw);
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
if (ret) {
|
||||
ret = -EFAULT;
|
||||
goto release_fw;
|
||||
}
|
||||
|
||||
__disable_dcpu(priv);
|
||||
|
||||
@ -667,18 +678,20 @@ static int brcmstb_dpfe_download_firmware(struct brcmstb_dpfe_priv *priv)
|
||||
|
||||
ret = __write_firmware(priv->dmem, dmem, dmem_size, is_big_endian);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto release_fw;
|
||||
ret = __write_firmware(priv->imem, imem, imem_size, is_big_endian);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto release_fw;
|
||||
|
||||
ret = __verify_fw_checksum(&init, priv, header, init.chksum);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto release_fw;
|
||||
|
||||
__enable_dcpu(priv);
|
||||
|
||||
return 0;
|
||||
release_fw:
|
||||
release_firmware(fw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t generic_show(unsigned int command, u32 response[],
|
||||
@ -691,7 +704,7 @@ static ssize_t generic_show(unsigned int command, u32 response[],
|
||||
|
||||
ret = __send_command(priv, command, response);
|
||||
if (ret < 0)
|
||||
return sprintf(buf, "ERROR: %s\n", error_text[-ret]);
|
||||
return sprintf(buf, "ERROR: %s\n", get_error_text(-ret));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -888,11 +901,8 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ret = brcmstb_dpfe_download_firmware(priv);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Couldn't download firmware -- %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Couldn't download firmware\n");
|
||||
|
||||
ret = sysfs_create_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs);
|
||||
if (!ret)
|
||||
|
@ -163,35 +163,12 @@ static const struct file_operations emif_mr4_fops = {
|
||||
|
||||
static int __init_or_module emif_debugfs_init(struct emif_data *emif)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
int ret;
|
||||
|
||||
dentry = debugfs_create_dir(dev_name(emif->dev), NULL);
|
||||
if (!dentry) {
|
||||
ret = -ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
emif->debugfs_root = dentry;
|
||||
|
||||
dentry = debugfs_create_file("regcache_dump", S_IRUGO,
|
||||
emif->debugfs_root, emif, &emif_regdump_fops);
|
||||
if (!dentry) {
|
||||
ret = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
dentry = debugfs_create_file("mr4", S_IRUGO,
|
||||
emif->debugfs_root, emif, &emif_mr4_fops);
|
||||
if (!dentry) {
|
||||
ret = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
emif->debugfs_root = debugfs_create_dir(dev_name(emif->dev), NULL);
|
||||
debugfs_create_file("regcache_dump", S_IRUGO, emif->debugfs_root, emif,
|
||||
&emif_regdump_fops);
|
||||
debugfs_create_file("mr4", S_IRUGO, emif->debugfs_root, emif,
|
||||
&emif_mr4_fops);
|
||||
return 0;
|
||||
err1:
|
||||
debugfs_remove_recursive(emif->debugfs_root);
|
||||
err0:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit emif_debugfs_exit(struct emif_data *emif)
|
||||
|
@ -211,10 +211,8 @@ static int ccf_probe(struct platform_device *pdev)
|
||||
dev_set_drvdata(&pdev->dev, ccf);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (!irq) {
|
||||
dev_err(&pdev->dev, "%s: no irq\n", __func__);
|
||||
return -ENXIO;
|
||||
}
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, ccf_irq, 0, pdev->name, ccf);
|
||||
if (ret) {
|
||||
|
@ -33,8 +33,6 @@
|
||||
|
||||
#include <linux/platform_data/mtd-nand-omap2.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#define DEVICE_NAME "omap-gpmc"
|
||||
|
||||
/* GPMC register offsets */
|
||||
@ -245,7 +243,6 @@ static DEFINE_SPINLOCK(gpmc_mem_lock);
|
||||
/* Define chip-selects as reserved by default until probe completes */
|
||||
static unsigned int gpmc_cs_num = GPMC_CS_NUM;
|
||||
static unsigned int gpmc_nr_waitpins;
|
||||
static resource_size_t phys_base, mem_size;
|
||||
static unsigned int gpmc_capability;
|
||||
static void __iomem *gpmc_base;
|
||||
|
||||
@ -635,14 +632,6 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int max
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define GPMC_SET_ONE_CD_MAX(reg, st, end, max, field, cd) \
|
||||
if (set_gpmc_timing_reg(cs, (reg), (st), (end), (max), \
|
||||
t->field, (cd), #field) < 0) \
|
||||
return -1
|
||||
|
||||
#define GPMC_SET_ONE(reg, st, end, field) \
|
||||
GPMC_SET_ONE_CD_MAX(reg, st, end, 0, field, GPMC_CD_FCLK)
|
||||
|
||||
/**
|
||||
* gpmc_calc_waitmonitoring_divider - calculate proper GPMCFCLKDIVIDER based on WAITMONITORINGTIME
|
||||
* WAITMONITORINGTIME will be _at least_ as long as desired, i.e.
|
||||
@ -701,12 +690,12 @@ int gpmc_calc_divider(unsigned int sync_clk)
|
||||
int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t,
|
||||
const struct gpmc_settings *s)
|
||||
{
|
||||
int div;
|
||||
int div, ret;
|
||||
u32 l;
|
||||
|
||||
div = gpmc_calc_divider(t->sync_clk);
|
||||
if (div < 0)
|
||||
return div;
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* See if we need to change the divider for waitmonitoringtime.
|
||||
@ -730,57 +719,114 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t,
|
||||
__func__,
|
||||
t->wait_monitoring
|
||||
);
|
||||
return -1;
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG2, 0, 3, cs_on);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG2, 8, 12, cs_rd_off);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG2, 16, 20, cs_wr_off);
|
||||
ret = 0;
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG2, 0, 3, 0, t->cs_on,
|
||||
GPMC_CD_FCLK, "cs_on");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG2, 8, 12, 0, t->cs_rd_off,
|
||||
GPMC_CD_FCLK, "cs_rd_off");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG2, 16, 20, 0, t->cs_wr_off,
|
||||
GPMC_CD_FCLK, "cs_wr_off");
|
||||
if (ret)
|
||||
return -ENXIO;
|
||||
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 0, 3, 0, t->adv_on,
|
||||
GPMC_CD_FCLK, "adv_on");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 8, 12, 0, t->adv_rd_off,
|
||||
GPMC_CD_FCLK, "adv_rd_off");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 16, 20, 0, t->adv_wr_off,
|
||||
GPMC_CD_FCLK, "adv_wr_off");
|
||||
if (ret)
|
||||
return -ENXIO;
|
||||
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG3, 0, 3, adv_on);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG3, 8, 12, adv_rd_off);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG3, 16, 20, adv_wr_off);
|
||||
if (gpmc_capability & GPMC_HAS_MUX_AAD) {
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG3, 4, 6, adv_aad_mux_on);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG3, 24, 26, adv_aad_mux_rd_off);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG3, 28, 30, adv_aad_mux_wr_off);
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 4, 6, 0,
|
||||
t->adv_aad_mux_on, GPMC_CD_FCLK,
|
||||
"adv_aad_mux_on");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 24, 26, 0,
|
||||
t->adv_aad_mux_rd_off, GPMC_CD_FCLK,
|
||||
"adv_aad_mux_rd_off");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 28, 30, 0,
|
||||
t->adv_aad_mux_wr_off, GPMC_CD_FCLK,
|
||||
"adv_aad_mux_wr_off");
|
||||
if (ret)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG4, 0, 3, oe_on);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG4, 8, 12, oe_off);
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 0, 3, 0, t->oe_on,
|
||||
GPMC_CD_FCLK, "oe_on");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 8, 12, 0, t->oe_off,
|
||||
GPMC_CD_FCLK, "oe_off");
|
||||
if (gpmc_capability & GPMC_HAS_MUX_AAD) {
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG4, 4, 6, oe_aad_mux_on);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG4, 13, 15, oe_aad_mux_off);
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 4, 6, 0,
|
||||
t->oe_aad_mux_on, GPMC_CD_FCLK,
|
||||
"oe_aad_mux_on");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 13, 15, 0,
|
||||
t->oe_aad_mux_off, GPMC_CD_FCLK,
|
||||
"oe_aad_mux_off");
|
||||
}
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG4, 16, 19, we_on);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG4, 24, 28, we_off);
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 16, 19, 0, t->we_on,
|
||||
GPMC_CD_FCLK, "we_on");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 24, 28, 0, t->we_off,
|
||||
GPMC_CD_FCLK, "we_off");
|
||||
if (ret)
|
||||
return -ENXIO;
|
||||
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG5, 0, 4, rd_cycle);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG5, 8, 12, wr_cycle);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG5, 16, 20, access);
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 0, 4, 0, t->rd_cycle,
|
||||
GPMC_CD_FCLK, "rd_cycle");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 8, 12, 0, t->wr_cycle,
|
||||
GPMC_CD_FCLK, "wr_cycle");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 16, 20, 0, t->access,
|
||||
GPMC_CD_FCLK, "access");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 24, 27, 0,
|
||||
t->page_burst_access, GPMC_CD_FCLK,
|
||||
"page_burst_access");
|
||||
if (ret)
|
||||
return -ENXIO;
|
||||
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 0, 3, 0,
|
||||
t->bus_turnaround, GPMC_CD_FCLK,
|
||||
"bus_turnaround");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 8, 11, 0,
|
||||
t->cycle2cycle_delay, GPMC_CD_FCLK,
|
||||
"cycle2cycle_delay");
|
||||
if (ret)
|
||||
return -ENXIO;
|
||||
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
|
||||
|
||||
if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
|
||||
if (gpmc_capability & GPMC_HAS_WR_ACCESS)
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
|
||||
if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS) {
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 16, 19, 0,
|
||||
t->wr_data_mux_bus, GPMC_CD_FCLK,
|
||||
"wr_data_mux_bus");
|
||||
if (ret)
|
||||
return -ENXIO;
|
||||
}
|
||||
if (gpmc_capability & GPMC_HAS_WR_ACCESS) {
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 24, 28, 0,
|
||||
t->wr_access, GPMC_CD_FCLK,
|
||||
"wr_access");
|
||||
if (ret)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
|
||||
l &= ~0x03;
|
||||
l |= (div - 1);
|
||||
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
|
||||
|
||||
GPMC_SET_ONE_CD_MAX(GPMC_CS_CONFIG1, 18, 19,
|
||||
GPMC_CONFIG1_WAITMONITORINGTIME_MAX,
|
||||
wait_monitoring, GPMC_CD_CLK);
|
||||
GPMC_SET_ONE_CD_MAX(GPMC_CS_CONFIG1, 25, 26,
|
||||
GPMC_CONFIG1_CLKACTIVATIONTIME_MAX,
|
||||
clk_activation, GPMC_CD_FCLK);
|
||||
ret = 0;
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG1, 18, 19,
|
||||
GPMC_CONFIG1_WAITMONITORINGTIME_MAX,
|
||||
t->wait_monitoring, GPMC_CD_CLK,
|
||||
"wait_monitoring");
|
||||
ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG1, 25, 26,
|
||||
GPMC_CONFIG1_CLKACTIVATIONTIME_MAX,
|
||||
t->clk_activation, GPMC_CD_FCLK,
|
||||
"clk_activation");
|
||||
if (ret)
|
||||
return -ENXIO;
|
||||
|
||||
#ifdef CONFIG_OMAP_GPMC_DEBUG
|
||||
pr_info("GPMC CS%d CLK period is %lu ns (div %d)\n",
|
||||
@ -871,20 +917,6 @@ static bool gpmc_cs_reserved(int cs)
|
||||
return gpmc->flags & GPMC_CS_RESERVED;
|
||||
}
|
||||
|
||||
static void gpmc_cs_set_name(int cs, const char *name)
|
||||
{
|
||||
struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
|
||||
|
||||
gpmc->name = name;
|
||||
}
|
||||
|
||||
static const char *gpmc_cs_get_name(int cs)
|
||||
{
|
||||
struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
|
||||
|
||||
return gpmc->name;
|
||||
}
|
||||
|
||||
static unsigned long gpmc_mem_align(unsigned long size)
|
||||
{
|
||||
int order;
|
||||
@ -930,56 +962,13 @@ static int gpmc_cs_delete_mem(int cs)
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* gpmc_cs_remap - remaps a chip-select physical base address
|
||||
* @cs: chip-select to remap
|
||||
* @base: physical base address to re-map chip-select to
|
||||
*
|
||||
* Re-maps a chip-select to a new physical base address specified by
|
||||
* "base". Returns 0 on success and appropriate negative error code
|
||||
* on failure.
|
||||
*/
|
||||
static int gpmc_cs_remap(int cs, u32 base)
|
||||
{
|
||||
int ret;
|
||||
u32 old_base, size;
|
||||
|
||||
if (cs > gpmc_cs_num) {
|
||||
pr_err("%s: requested chip-select is disabled\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we ignore any device offsets from the GPMC partition
|
||||
* allocated for the chip select and that the new base confirms
|
||||
* to the GPMC 16MB minimum granularity.
|
||||
*/
|
||||
base &= ~(SZ_16M - 1);
|
||||
|
||||
gpmc_cs_get_memconf(cs, &old_base, &size);
|
||||
if (base == old_base)
|
||||
return 0;
|
||||
|
||||
ret = gpmc_cs_delete_mem(cs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = gpmc_cs_insert_mem(cs, base, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = gpmc_cs_set_memconf(cs, base, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
|
||||
{
|
||||
struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
|
||||
struct resource *res = &gpmc->mem;
|
||||
int r = -1;
|
||||
|
||||
if (cs > gpmc_cs_num) {
|
||||
if (cs >= gpmc_cs_num) {
|
||||
pr_err("%s: requested chip-select is disabled\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -1026,8 +1015,7 @@ void gpmc_cs_free(int cs)
|
||||
|
||||
spin_lock(&gpmc_mem_lock);
|
||||
if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) {
|
||||
printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
|
||||
BUG();
|
||||
WARN(1, "Trying to free non-reserved GPMC CS%d\n", cs);
|
||||
spin_unlock(&gpmc_mem_lock);
|
||||
return;
|
||||
}
|
||||
@ -1897,6 +1885,63 @@ static const struct of_device_id gpmc_dt_ids[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static void gpmc_cs_set_name(int cs, const char *name)
|
||||
{
|
||||
struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
|
||||
|
||||
gpmc->name = name;
|
||||
}
|
||||
|
||||
static const char *gpmc_cs_get_name(int cs)
|
||||
{
|
||||
struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
|
||||
|
||||
return gpmc->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* gpmc_cs_remap - remaps a chip-select physical base address
|
||||
* @cs: chip-select to remap
|
||||
* @base: physical base address to re-map chip-select to
|
||||
*
|
||||
* Re-maps a chip-select to a new physical base address specified by
|
||||
* "base". Returns 0 on success and appropriate negative error code
|
||||
* on failure.
|
||||
*/
|
||||
static int gpmc_cs_remap(int cs, u32 base)
|
||||
{
|
||||
int ret;
|
||||
u32 old_base, size;
|
||||
|
||||
if (cs >= gpmc_cs_num) {
|
||||
pr_err("%s: requested chip-select is disabled\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we ignore any device offsets from the GPMC partition
|
||||
* allocated for the chip select and that the new base confirms
|
||||
* to the GPMC 16MB minimum granularity.
|
||||
*/
|
||||
base &= ~(SZ_16M - 1);
|
||||
|
||||
gpmc_cs_get_memconf(cs, &old_base, &size);
|
||||
if (base == old_base)
|
||||
return 0;
|
||||
|
||||
ret = gpmc_cs_delete_mem(cs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = gpmc_cs_insert_mem(cs, base, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = gpmc_cs_set_memconf(cs, base, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gpmc_read_settings_dt - read gpmc settings from device-tree
|
||||
* @np: pointer to device-tree node for a gpmc child device
|
||||
@ -2266,6 +2311,10 @@ static void gpmc_probe_dt_children(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
#else
|
||||
void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
|
||||
{
|
||||
memset(p, 0, sizeof(*p));
|
||||
}
|
||||
static int gpmc_probe_dt(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
@ -2348,12 +2397,9 @@ static int gpmc_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, gpmc);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL)
|
||||
if (!res)
|
||||
return -ENOENT;
|
||||
|
||||
phys_base = res->start;
|
||||
mem_size = resource_size(res);
|
||||
|
||||
gpmc_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(gpmc_base))
|
||||
return PTR_ERR(gpmc_base);
|
||||
|
@ -199,10 +199,8 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
|
||||
rpc->dirmap = NULL;
|
||||
|
||||
rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
if (IS_ERR(rpc->rstc))
|
||||
return PTR_ERR(rpc->rstc);
|
||||
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(rpc->rstc);
|
||||
}
|
||||
EXPORT_SYMBOL(rpcif_sw_init);
|
||||
|
||||
|
@ -98,6 +98,8 @@ MODULE_PARM_DESC(irqmode, "Enable IRQ mode (0=off [default], 1=on)");
|
||||
|
||||
/**
|
||||
* struct dmc_opp_table - Operating level desciption
|
||||
* @freq_hz: target frequency in Hz
|
||||
* @volt_uv: target voltage in uV
|
||||
*
|
||||
* Covers frequency and voltage settings of the DMC operating mode.
|
||||
*/
|
||||
@ -108,6 +110,41 @@ struct dmc_opp_table {
|
||||
|
||||
/**
|
||||
* struct exynos5_dmc - main structure describing DMC device
|
||||
* @dev: DMC device
|
||||
* @df: devfreq device structure returned by devfreq framework
|
||||
* @gov_data: configuration of devfreq governor
|
||||
* @base_drexi0: DREX0 registers mapping
|
||||
* @base_drexi1: DREX1 registers mapping
|
||||
* @clk_regmap: regmap for clock controller registers
|
||||
* @lock: protects curr_rate and frequency/voltage setting section
|
||||
* @curr_rate: current frequency
|
||||
* @curr_volt: current voltage
|
||||
* @opp: OPP table
|
||||
* @opp_count: number of 'opp' elements
|
||||
* @timings_arr_size: number of 'timings' elements
|
||||
* @timing_row: values for timing row register, for each OPP
|
||||
* @timing_data: values for timing data register, for each OPP
|
||||
* @timing_power: balues for timing power register, for each OPP
|
||||
* @timings: DDR memory timings, from device tree
|
||||
* @min_tck: DDR memory minimum timing values, from device tree
|
||||
* @bypass_timing_row: value for timing row register for bypass timings
|
||||
* @bypass_timing_data: value for timing data register for bypass timings
|
||||
* @bypass_timing_power: value for timing power register for bypass
|
||||
* timings
|
||||
* @vdd_mif: Memory interface regulator
|
||||
* @fout_spll: clock: SPLL
|
||||
* @fout_bpll: clock: BPLL
|
||||
* @mout_spll: clock: mux SPLL
|
||||
* @mout_bpll: clock: mux BPLL
|
||||
* @mout_mclk_cdrex: clock: mux mclk_cdrex
|
||||
* @mout_mx_mspll_ccore: clock: mux mx_mspll_ccore
|
||||
* @counter: devfreq events
|
||||
* @num_counters: number of 'counter' elements
|
||||
* @last_overflow_ts: time (in ns) of last overflow of each DREX
|
||||
* @load: utilization in percents
|
||||
* @total: total time between devfreq events
|
||||
* @in_irq_mode: whether running in interrupt mode (true)
|
||||
* or polling (false)
|
||||
*
|
||||
* The main structure for the Dynamic Memory Controller which covers clocks,
|
||||
* memory regions, HW information, parameters and current operating mode.
|
||||
@ -119,12 +156,11 @@ struct exynos5_dmc {
|
||||
void __iomem *base_drexi0;
|
||||
void __iomem *base_drexi1;
|
||||
struct regmap *clk_regmap;
|
||||
/* Protects curr_rate and frequency/voltage setting section */
|
||||
struct mutex lock;
|
||||
unsigned long curr_rate;
|
||||
unsigned long curr_volt;
|
||||
unsigned long bypass_rate;
|
||||
struct dmc_opp_table *opp;
|
||||
struct dmc_opp_table opp_bypass;
|
||||
int opp_count;
|
||||
u32 timings_arr_size;
|
||||
u32 *timing_row;
|
||||
@ -142,8 +178,6 @@ struct exynos5_dmc {
|
||||
struct clk *mout_bpll;
|
||||
struct clk *mout_mclk_cdrex;
|
||||
struct clk *mout_mx_mspll_ccore;
|
||||
struct clk *mx_mspll_ccore_phy;
|
||||
struct clk *mout_mx_mspll_ccore_phy;
|
||||
struct devfreq_event_dev **counter;
|
||||
int num_counters;
|
||||
u64 last_overflow_ts[2];
|
||||
@ -169,7 +203,7 @@ struct timing_reg {
|
||||
unsigned int val;
|
||||
};
|
||||
|
||||
static const struct timing_reg timing_row[] = {
|
||||
static const struct timing_reg timing_row_reg_fields[] = {
|
||||
TIMING_FIELD("tRFC", 24, 31),
|
||||
TIMING_FIELD("tRRD", 20, 23),
|
||||
TIMING_FIELD("tRP", 16, 19),
|
||||
@ -178,7 +212,7 @@ static const struct timing_reg timing_row[] = {
|
||||
TIMING_FIELD("tRAS", 0, 5),
|
||||
};
|
||||
|
||||
static const struct timing_reg timing_data[] = {
|
||||
static const struct timing_reg timing_data_reg_fields[] = {
|
||||
TIMING_FIELD("tWTR", 28, 31),
|
||||
TIMING_FIELD("tWR", 24, 27),
|
||||
TIMING_FIELD("tRTP", 20, 23),
|
||||
@ -189,7 +223,7 @@ static const struct timing_reg timing_data[] = {
|
||||
TIMING_FIELD("RL", 0, 3),
|
||||
};
|
||||
|
||||
static const struct timing_reg timing_power[] = {
|
||||
static const struct timing_reg timing_power_reg_fields[] = {
|
||||
TIMING_FIELD("tFAW", 26, 31),
|
||||
TIMING_FIELD("tXSR", 16, 25),
|
||||
TIMING_FIELD("tXP", 8, 15),
|
||||
@ -197,8 +231,9 @@ static const struct timing_reg timing_power[] = {
|
||||
TIMING_FIELD("tMRD", 0, 3),
|
||||
};
|
||||
|
||||
#define TIMING_COUNT (ARRAY_SIZE(timing_row) + ARRAY_SIZE(timing_data) + \
|
||||
ARRAY_SIZE(timing_power))
|
||||
#define TIMING_COUNT (ARRAY_SIZE(timing_row_reg_fields) + \
|
||||
ARRAY_SIZE(timing_data_reg_fields) + \
|
||||
ARRAY_SIZE(timing_power_reg_fields))
|
||||
|
||||
static int exynos5_counters_set_event(struct exynos5_dmc *dmc)
|
||||
{
|
||||
@ -346,7 +381,6 @@ err_opp:
|
||||
/**
|
||||
* exynos5_set_bypass_dram_timings() - Low-level changes of the DRAM timings
|
||||
* @dmc: device for which the new settings is going to be applied
|
||||
* @param: DRAM parameters which passes timing data
|
||||
*
|
||||
* Low-level function for changing timings for DRAM memory clocking from
|
||||
* 'bypass' clock source (fixed frequency @400MHz).
|
||||
@ -453,9 +487,6 @@ static int exynos5_dmc_align_bypass_voltage(struct exynos5_dmc *dmc,
|
||||
unsigned long target_volt)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long bypass_volt = dmc->opp_bypass.volt_uv;
|
||||
|
||||
target_volt = max(bypass_volt, target_volt);
|
||||
|
||||
if (dmc->curr_volt >= target_volt)
|
||||
return 0;
|
||||
@ -617,6 +648,7 @@ disable_clocks:
|
||||
* requested
|
||||
* @target_volt: returned voltage which corresponds to the returned
|
||||
* frequency
|
||||
* @flags: devfreq flags provided for this frequency change request
|
||||
*
|
||||
* Function gets requested frequency and checks OPP framework for needed
|
||||
* frequency and voltage. It populates the values 'target_rate' and
|
||||
@ -908,7 +940,10 @@ static int exynos5_dmc_get_status(struct device *dev,
|
||||
int ret;
|
||||
|
||||
if (dmc->in_irq_mode) {
|
||||
mutex_lock(&dmc->lock);
|
||||
stat->current_frequency = dmc->curr_rate;
|
||||
mutex_unlock(&dmc->lock);
|
||||
|
||||
stat->busy_time = dmc->load;
|
||||
stat->total_time = dmc->total;
|
||||
} else {
|
||||
@ -950,7 +985,7 @@ static int exynos5_dmc_get_cur_freq(struct device *dev, unsigned long *freq)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* exynos5_dmc_df_profile - Devfreq governor's profile structure
|
||||
*
|
||||
* It provides to the devfreq framework needed functions and polling period.
|
||||
@ -993,7 +1028,9 @@ exynos5_dmc_align_init_freq(struct exynos5_dmc *dmc,
|
||||
/**
|
||||
* create_timings_aligned() - Create register values and align with standard
|
||||
* @dmc: device for which the frequency is going to be set
|
||||
* @idx: speed bin in the OPP table
|
||||
* @reg_timing_row: array to fill with values for timing row register
|
||||
* @reg_timing_data: array to fill with values for timing data register
|
||||
* @reg_timing_power: array to fill with values for timing power register
|
||||
* @clk_period_ps: the period of the clock, known as tCK
|
||||
*
|
||||
* The function calculates timings and creates a register value ready for
|
||||
@ -1018,117 +1055,117 @@ static int create_timings_aligned(struct exynos5_dmc *dmc, u32 *reg_timing_row,
|
||||
val = dmc->timings->tRFC / clk_period_ps;
|
||||
val += dmc->timings->tRFC % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tRFC);
|
||||
reg = &timing_row[0];
|
||||
reg = &timing_row_reg_fields[0];
|
||||
*reg_timing_row |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tRRD / clk_period_ps;
|
||||
val += dmc->timings->tRRD % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tRRD);
|
||||
reg = &timing_row[1];
|
||||
reg = &timing_row_reg_fields[1];
|
||||
*reg_timing_row |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tRPab / clk_period_ps;
|
||||
val += dmc->timings->tRPab % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tRPab);
|
||||
reg = &timing_row[2];
|
||||
reg = &timing_row_reg_fields[2];
|
||||
*reg_timing_row |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tRCD / clk_period_ps;
|
||||
val += dmc->timings->tRCD % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tRCD);
|
||||
reg = &timing_row[3];
|
||||
reg = &timing_row_reg_fields[3];
|
||||
*reg_timing_row |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tRC / clk_period_ps;
|
||||
val += dmc->timings->tRC % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tRC);
|
||||
reg = &timing_row[4];
|
||||
reg = &timing_row_reg_fields[4];
|
||||
*reg_timing_row |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tRAS / clk_period_ps;
|
||||
val += dmc->timings->tRAS % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tRAS);
|
||||
reg = &timing_row[5];
|
||||
reg = &timing_row_reg_fields[5];
|
||||
*reg_timing_row |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
/* data related timings */
|
||||
val = dmc->timings->tWTR / clk_period_ps;
|
||||
val += dmc->timings->tWTR % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tWTR);
|
||||
reg = &timing_data[0];
|
||||
reg = &timing_data_reg_fields[0];
|
||||
*reg_timing_data |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tWR / clk_period_ps;
|
||||
val += dmc->timings->tWR % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tWR);
|
||||
reg = &timing_data[1];
|
||||
reg = &timing_data_reg_fields[1];
|
||||
*reg_timing_data |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tRTP / clk_period_ps;
|
||||
val += dmc->timings->tRTP % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tRTP);
|
||||
reg = &timing_data[2];
|
||||
reg = &timing_data_reg_fields[2];
|
||||
*reg_timing_data |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tW2W_C2C / clk_period_ps;
|
||||
val += dmc->timings->tW2W_C2C % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tW2W_C2C);
|
||||
reg = &timing_data[3];
|
||||
reg = &timing_data_reg_fields[3];
|
||||
*reg_timing_data |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tR2R_C2C / clk_period_ps;
|
||||
val += dmc->timings->tR2R_C2C % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tR2R_C2C);
|
||||
reg = &timing_data[4];
|
||||
reg = &timing_data_reg_fields[4];
|
||||
*reg_timing_data |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tWL / clk_period_ps;
|
||||
val += dmc->timings->tWL % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tWL);
|
||||
reg = &timing_data[5];
|
||||
reg = &timing_data_reg_fields[5];
|
||||
*reg_timing_data |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tDQSCK / clk_period_ps;
|
||||
val += dmc->timings->tDQSCK % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tDQSCK);
|
||||
reg = &timing_data[6];
|
||||
reg = &timing_data_reg_fields[6];
|
||||
*reg_timing_data |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tRL / clk_period_ps;
|
||||
val += dmc->timings->tRL % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tRL);
|
||||
reg = &timing_data[7];
|
||||
reg = &timing_data_reg_fields[7];
|
||||
*reg_timing_data |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
/* power related timings */
|
||||
val = dmc->timings->tFAW / clk_period_ps;
|
||||
val += dmc->timings->tFAW % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tFAW);
|
||||
reg = &timing_power[0];
|
||||
reg = &timing_power_reg_fields[0];
|
||||
*reg_timing_power |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tXSR / clk_period_ps;
|
||||
val += dmc->timings->tXSR % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tXSR);
|
||||
reg = &timing_power[1];
|
||||
reg = &timing_power_reg_fields[1];
|
||||
*reg_timing_power |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tXP / clk_period_ps;
|
||||
val += dmc->timings->tXP % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tXP);
|
||||
reg = &timing_power[2];
|
||||
reg = &timing_power_reg_fields[2];
|
||||
*reg_timing_power |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tCKE / clk_period_ps;
|
||||
val += dmc->timings->tCKE % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tCKE);
|
||||
reg = &timing_power[3];
|
||||
reg = &timing_power_reg_fields[3];
|
||||
*reg_timing_power |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
val = dmc->timings->tMRD / clk_period_ps;
|
||||
val += dmc->timings->tMRD % clk_period_ps ? 1 : 0;
|
||||
val = max(val, dmc->min_tck->tMRD);
|
||||
reg = &timing_power[4];
|
||||
reg = &timing_power_reg_fields[4];
|
||||
*reg_timing_power |= TIMING_VAL2REG(reg, val);
|
||||
|
||||
return 0;
|
||||
@ -1263,8 +1300,6 @@ static int exynos5_dmc_init_clks(struct exynos5_dmc *dmc)
|
||||
|
||||
clk_set_parent(dmc->mout_mx_mspll_ccore, dmc->mout_spll);
|
||||
|
||||
dmc->bypass_rate = clk_get_rate(dmc->mout_mx_mspll_ccore);
|
||||
|
||||
clk_prepare_enable(dmc->fout_bpll);
|
||||
clk_prepare_enable(dmc->mout_bpll);
|
||||
|
||||
@ -1330,7 +1365,6 @@ static int exynos5_performance_counters_init(struct exynos5_dmc *dmc)
|
||||
/**
|
||||
* exynos5_dmc_set_pause_on_switching() - Controls a pause feature in DMC
|
||||
* @dmc: device which is used for changing this feature
|
||||
* @set: a boolean state passing enable/disable request
|
||||
*
|
||||
* There is a need of pausing DREX DMC when divider or MUX in clock tree
|
||||
* changes its configuration. In such situation access to the memory is blocked
|
||||
|
@ -957,7 +957,6 @@ static const struct tegra_smmu_swgroup tegra124_swgroups[] = {
|
||||
static const unsigned int tegra124_group_drm[] = {
|
||||
TEGRA_SWGROUP_DC,
|
||||
TEGRA_SWGROUP_DCB,
|
||||
TEGRA_SWGROUP_GPU,
|
||||
TEGRA_SWGROUP_VIC,
|
||||
};
|
||||
|
||||
|
@ -172,14 +172,8 @@ static int tegra186_emc_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
emc->bpmp = tegra_bpmp_get(&pdev->dev);
|
||||
if (IS_ERR(emc->bpmp)) {
|
||||
err = PTR_ERR(emc->bpmp);
|
||||
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "failed to get BPMP: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
if (IS_ERR(emc->bpmp))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(emc->bpmp), "failed to get BPMP\n");
|
||||
|
||||
emc->clk = devm_clk_get(&pdev->dev, "emc");
|
||||
if (IS_ERR(emc->clk)) {
|
||||
|
@ -1044,7 +1044,7 @@ static void tegra210_emc_r21021_set_clock(struct tegra210_emc *emc, u32 clksrc)
|
||||
!opt_cc_short_zcal && opt_short_zcal) {
|
||||
value = (value & ~(EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK <<
|
||||
EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_SHIFT)) |
|
||||
((zq_wait_long & EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK) <<
|
||||
((zq_wait_long & EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK) <<
|
||||
EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT);
|
||||
} else if (offset == EMC_ZCAL_INTERVAL && opt_zcal_en_cc) {
|
||||
value = 0; /* EMC_ZCAL_INTERVAL reset value. */
|
||||
|
@ -842,7 +842,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
|
||||
},
|
||||
.la = {
|
||||
.reg = 0x3dc,
|
||||
.shift = 0,
|
||||
.shift = 16,
|
||||
.mask = 0xff,
|
||||
.def = 0x80,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user