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:
Olof Johansson 2020-09-13 11:26:36 -07:00
commit bac9bd958a
12 changed files with 302 additions and 229 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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,
};

View File

@ -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)) {

View File

@ -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. */

View File

@ -842,7 +842,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
},
.la = {
.reg = 0x3dc,
.shift = 0,
.shift = 16,
.mask = 0xff,
.def = 0x80,
},