diff options
Diffstat (limited to 'drivers/memory')
-rw-r--r-- | drivers/memory/Kconfig | 20 | ||||
-rw-r--r-- | drivers/memory/Makefile | 1 | ||||
-rw-r--r-- | drivers/memory/fsl_ifc.c | 43 | ||||
-rw-r--r-- | drivers/memory/omap-gpmc.c | 7 | ||||
-rw-r--r-- | drivers/memory/pl172.c | 301 | ||||
-rw-r--r-- | drivers/memory/tegra/Makefile | 1 | ||||
-rw-r--r-- | drivers/memory/tegra/mc.c | 8 | ||||
-rw-r--r-- | drivers/memory/tegra/mc.h | 4 | ||||
-rw-r--r-- | drivers/memory/tegra/tegra114.c | 18 | ||||
-rw-r--r-- | drivers/memory/tegra/tegra124-emc.c | 42 | ||||
-rw-r--r-- | drivers/memory/tegra/tegra124.c | 34 | ||||
-rw-r--r-- | drivers/memory/tegra/tegra210.c | 1080 | ||||
-rw-r--r-- | drivers/memory/tegra/tegra30.c | 18 |
13 files changed, 1488 insertions, 89 deletions
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 8406c668e..6f3154613 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -7,6 +7,14 @@ menuconfig MEMORY if MEMORY +config ARM_PL172_MPMC + tristate "ARM PL172 MPMC driver" + depends on ARM_AMBA && OF + help + This selects the ARM PrimeCell PL172 MultiPort Memory Controller. + If you have an embedded system with an AMBA bus and a PL172 + controller, say Y or M here. + config ATMEL_SDRAMC bool "Atmel (Multi-port DDR-)SDRAM Controller" default y @@ -50,12 +58,18 @@ config OMAP_GPMC memory drives like NOR, NAND, OneNAND, SRAM. config OMAP_GPMC_DEBUG - bool + bool "Enable GPMC debug output and skip reset of GPMC during init" depends on OMAP_GPMC help Enables verbose debugging mostly to decode the bootloader provided - timings. Enable this during development to configure devices - connected to the GPMC bus. + timings. To preserve the bootloader provided timings, the reset + of GPMC is skipped during init. Enable this during development to + configure devices connected to the GPMC bus. + + NOTE: In addition to matching the register setup with the bootloader + you also need to match the GPMC FCLK frequency used by the + bootloader or else the GPMC timings won't be identical with the + bootloader timings. config MVEBU_DEVBUS bool "Marvell EBU Device Bus Controller" diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index b670441e3..1c46af501 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -5,6 +5,7 @@ ifeq ($(CONFIG_DDR),y) obj-$(CONFIG_OF) += of_memory.o endif +obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o obj-$(CONFIG_TI_AEMIF) += ti-aemif.o obj-$(CONFIG_TI_EMIF) += emif.o diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c index 410c39749..e87459f6d 100644 --- a/drivers/memory/fsl_ifc.c +++ b/drivers/memory/fsl_ifc.c @@ -62,7 +62,7 @@ int fsl_ifc_find(phys_addr_t addr_base) return -ENODEV; for (i = 0; i < fsl_ifc_ctrl_dev->banks; i++) { - u32 cspr = in_be32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr); + u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr); if (cspr & CSPR_V && (cspr & CSPR_BA) == convert_ifc_address(addr_base)) return i; @@ -79,16 +79,16 @@ static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl) /* * Clear all the common status and event registers */ - if (in_be32(&ifc->cm_evter_stat) & IFC_CM_EVTER_STAT_CSER) - out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER); + if (ifc_in32(&ifc->cm_evter_stat) & IFC_CM_EVTER_STAT_CSER) + ifc_out32(IFC_CM_EVTER_STAT_CSER, &ifc->cm_evter_stat); /* enable all error and events */ - out_be32(&ifc->cm_evter_en, IFC_CM_EVTER_EN_CSEREN); + ifc_out32(IFC_CM_EVTER_EN_CSEREN, &ifc->cm_evter_en); /* enable all error and event interrupts */ - out_be32(&ifc->cm_evter_intr_en, IFC_CM_EVTER_INTR_EN_CSERIREN); - out_be32(&ifc->cm_erattr0, 0x0); - out_be32(&ifc->cm_erattr1, 0x0); + ifc_out32(IFC_CM_EVTER_INTR_EN_CSERIREN, &ifc->cm_evter_intr_en); + ifc_out32(0x0, &ifc->cm_erattr0); + ifc_out32(0x0, &ifc->cm_erattr1); return 0; } @@ -127,9 +127,9 @@ static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl) spin_lock_irqsave(&nand_irq_lock, flags); - stat = in_be32(&ifc->ifc_nand.nand_evter_stat); + stat = ifc_in32(&ifc->ifc_nand.nand_evter_stat); if (stat) { - out_be32(&ifc->ifc_nand.nand_evter_stat, stat); + ifc_out32(stat, &ifc->ifc_nand.nand_evter_stat); ctrl->nand_stat = stat; wake_up(&ctrl->nand_wait); } @@ -161,16 +161,16 @@ static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data) irqreturn_t ret = IRQ_NONE; /* read for chip select error */ - cs_err = in_be32(&ifc->cm_evter_stat); + cs_err = ifc_in32(&ifc->cm_evter_stat); if (cs_err) { dev_err(ctrl->dev, "transaction sent to IFC is not mapped to" "any memory bank 0x%08X\n", cs_err); /* clear the chip select error */ - out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER); + ifc_out32(IFC_CM_EVTER_STAT_CSER, &ifc->cm_evter_stat); /* read error attribute registers print the error information */ - status = in_be32(&ifc->cm_erattr0); - err_addr = in_be32(&ifc->cm_erattr1); + status = ifc_in32(&ifc->cm_erattr0); + err_addr = ifc_in32(&ifc->cm_erattr1); if (status & IFC_CM_ERATTR0_ERTYP_READ) dev_err(ctrl->dev, "Read transaction error" @@ -231,6 +231,23 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) goto err; } + version = ifc_in32(&fsl_ifc_ctrl_dev->regs->ifc_rev) & + FSL_IFC_VERSION_MASK; + banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; + dev_info(&dev->dev, "IFC version %d.%d, %d banks\n", + version >> 24, (version >> 16) & 0xf, banks); + + fsl_ifc_ctrl_dev->version = version; + fsl_ifc_ctrl_dev->banks = banks; + + if (of_property_read_bool(dev->dev.of_node, "little-endian")) { + fsl_ifc_ctrl_dev->little_endian = true; + dev_dbg(&dev->dev, "IFC REGISTERS are LITTLE endian\n"); + } else { + fsl_ifc_ctrl_dev->little_endian = false; + dev_dbg(&dev->dev, "IFC REGISTERS are BIG endian\n"); + } + version = ioread32be(&fsl_ifc_ctrl_dev->regs->ifc_rev) & FSL_IFC_VERSION_MASK; banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 9426276db..6515dfc2b 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -696,7 +696,6 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t, int div; u32 l; - gpmc_cs_show_timings(cs, "before gpmc_cs_set_timings"); div = gpmc_calc_divider(t->sync_clk); if (div < 0) return div; @@ -1176,8 +1175,8 @@ static int gpmc_setup_irq(void) gpmc_client_irq[i].irq = gpmc_irq_start + i; irq_set_chip_and_handler(gpmc_client_irq[i].irq, &gpmc_irq_chip, handle_simple_irq); - set_irq_flags(gpmc_client_irq[i].irq, - IRQF_VALID | IRQF_NOAUTOEN); + irq_modify_status(gpmc_client_irq[i].irq, IRQ_NOREQUEST, + IRQ_NOAUTOEN); } /* Disable interrupts */ @@ -1200,7 +1199,6 @@ static int gpmc_free_irq(void) for (i = 0; i < GPMC_NR_IRQ; i++) { irq_set_handler(gpmc_client_irq[i].irq, NULL); irq_set_chip(gpmc_client_irq[i].irq, &no_irq_chip); - irq_modify_status(gpmc_client_irq[i].irq, 0, 0); } irq_free_descs(gpmc_irq_start, GPMC_NR_IRQ); @@ -1989,6 +1987,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, if (ret < 0) goto err; + gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings"); ret = gpmc_cs_program_settings(cs, &gpmc_s); if (ret < 0) goto err; diff --git a/drivers/memory/pl172.c b/drivers/memory/pl172.c new file mode 100644 index 000000000..b2ef6072f --- /dev/null +++ b/drivers/memory/pl172.c @@ -0,0 +1,301 @@ +/* + * Memory controller driver for ARM PrimeCell PL172 + * PrimeCell MultiPort Memory Controller (PL172) + * + * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> + * + * Based on: + * 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/clk.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/time.h> + +#define MPMC_STATIC_CFG(n) (0x200 + 0x20 * n) +#define MPMC_STATIC_CFG_MW_8BIT 0x0 +#define MPMC_STATIC_CFG_MW_16BIT 0x1 +#define MPMC_STATIC_CFG_MW_32BIT 0x2 +#define MPMC_STATIC_CFG_PM BIT(3) +#define MPMC_STATIC_CFG_PC BIT(6) +#define MPMC_STATIC_CFG_PB BIT(7) +#define MPMC_STATIC_CFG_EW BIT(8) +#define MPMC_STATIC_CFG_B BIT(19) +#define MPMC_STATIC_CFG_P BIT(20) +#define MPMC_STATIC_WAIT_WEN(n) (0x204 + 0x20 * n) +#define MPMC_STATIC_WAIT_WEN_MAX 0x0f +#define MPMC_STATIC_WAIT_OEN(n) (0x208 + 0x20 * n) +#define MPMC_STATIC_WAIT_OEN_MAX 0x0f +#define MPMC_STATIC_WAIT_RD(n) (0x20c + 0x20 * n) +#define MPMC_STATIC_WAIT_RD_MAX 0x1f +#define MPMC_STATIC_WAIT_PAGE(n) (0x210 + 0x20 * n) +#define MPMC_STATIC_WAIT_PAGE_MAX 0x1f +#define MPMC_STATIC_WAIT_WR(n) (0x214 + 0x20 * n) +#define MPMC_STATIC_WAIT_WR_MAX 0x1f +#define MPMC_STATIC_WAIT_TURN(n) (0x218 + 0x20 * n) +#define MPMC_STATIC_WAIT_TURN_MAX 0x0f + +/* Maximum number of static chip selects */ +#define PL172_MAX_CS 4 + +struct pl172_data { + void __iomem *base; + unsigned long rate; + struct clk *clk; +}; + +static int pl172_timing_prop(struct amba_device *adev, + const struct device_node *np, const char *name, + u32 reg_offset, u32 max, int start) +{ + struct pl172_data *pl172 = amba_get_drvdata(adev); + int cycles; + u32 val; + + if (!of_property_read_u32(np, name, &val)) { + cycles = DIV_ROUND_UP(val * pl172->rate, NSEC_PER_MSEC) - start; + if (cycles < 0) { + cycles = 0; + } else if (cycles > max) { + dev_err(&adev->dev, "%s timing too tight\n", name); + return -EINVAL; + } + + writel(cycles, pl172->base + reg_offset); + } + + dev_dbg(&adev->dev, "%s: %u cycle(s)\n", name, start + + readl(pl172->base + reg_offset)); + + return 0; +} + +static int pl172_setup_static(struct amba_device *adev, + struct device_node *np, u32 cs) +{ + struct pl172_data *pl172 = amba_get_drvdata(adev); + u32 cfg; + int ret; + + /* MPMC static memory configuration */ + if (!of_property_read_u32(np, "mpmc,memory-width", &cfg)) { + if (cfg == 8) { + cfg = MPMC_STATIC_CFG_MW_8BIT; + } else if (cfg == 16) { + cfg = MPMC_STATIC_CFG_MW_16BIT; + } else if (cfg == 32) { + cfg = MPMC_STATIC_CFG_MW_32BIT; + } else { + dev_err(&adev->dev, "invalid memory width cs%u\n", cs); + return -EINVAL; + } + } else { + dev_err(&adev->dev, "memory-width property required\n"); + return -EINVAL; + } + + if (of_property_read_bool(np, "mpmc,async-page-mode")) + cfg |= MPMC_STATIC_CFG_PM; + + if (of_property_read_bool(np, "mpmc,cs-active-high")) + cfg |= MPMC_STATIC_CFG_PC; + + if (of_property_read_bool(np, "mpmc,byte-lane-low")) + cfg |= MPMC_STATIC_CFG_PB; + + if (of_property_read_bool(np, "mpmc,extended-wait")) + cfg |= MPMC_STATIC_CFG_EW; + + if (of_property_read_bool(np, "mpmc,buffer-enable")) + cfg |= MPMC_STATIC_CFG_B; + + if (of_property_read_bool(np, "mpmc,write-protect")) + cfg |= MPMC_STATIC_CFG_P; + + writel(cfg, pl172->base + MPMC_STATIC_CFG(cs)); + dev_dbg(&adev->dev, "mpmc static config cs%u: 0x%08x\n", cs, cfg); + + /* MPMC static memory timing */ + ret = pl172_timing_prop(adev, np, "mpmc,write-enable-delay", + MPMC_STATIC_WAIT_WEN(cs), + MPMC_STATIC_WAIT_WEN_MAX, 1); + if (ret) + goto fail; + + ret = pl172_timing_prop(adev, np, "mpmc,output-enable-delay", + MPMC_STATIC_WAIT_OEN(cs), + MPMC_STATIC_WAIT_OEN_MAX, 0); + if (ret) + goto fail; + + ret = pl172_timing_prop(adev, np, "mpmc,read-access-delay", + MPMC_STATIC_WAIT_RD(cs), + MPMC_STATIC_WAIT_RD_MAX, 1); + if (ret) + goto fail; + + ret = pl172_timing_prop(adev, np, "mpmc,page-mode-read-delay", + MPMC_STATIC_WAIT_PAGE(cs), + MPMC_STATIC_WAIT_PAGE_MAX, 1); + if (ret) + goto fail; + + ret = pl172_timing_prop(adev, np, "mpmc,write-access-delay", + MPMC_STATIC_WAIT_WR(cs), + MPMC_STATIC_WAIT_WR_MAX, 2); + if (ret) + goto fail; + + ret = pl172_timing_prop(adev, np, "mpmc,turn-round-delay", + MPMC_STATIC_WAIT_TURN(cs), + MPMC_STATIC_WAIT_TURN_MAX, 1); + if (ret) + goto fail; + + return 0; +fail: + dev_err(&adev->dev, "failed to configure cs%u\n", cs); + return ret; +} + +static int pl172_parse_cs_config(struct amba_device *adev, + struct device_node *np) +{ + u32 cs; + + if (!of_property_read_u32(np, "mpmc,cs", &cs)) { + if (cs >= PL172_MAX_CS) { + dev_err(&adev->dev, "cs%u invalid\n", cs); + return -EINVAL; + } + + return pl172_setup_static(adev, np, cs); + } + + dev_err(&adev->dev, "cs property required\n"); + + return -EINVAL; +} + +static const char * const pl172_revisions[] = {"r1", "r2", "r2p3", "r2p4"}; + +static int pl172_probe(struct amba_device *adev, const struct amba_id *id) +{ + struct device_node *child_np, *np = adev->dev.of_node; + struct device *dev = &adev->dev; + static const char *rev = "?"; + struct pl172_data *pl172; + int ret; + + if (amba_part(adev) == 0x172) { + if (amba_rev(adev) < ARRAY_SIZE(pl172_revisions)) + rev = pl172_revisions[amba_rev(adev)]; + } + + dev_info(dev, "ARM PL%x revision %s\n", amba_part(adev), rev); + + pl172 = devm_kzalloc(dev, sizeof(*pl172), GFP_KERNEL); + if (!pl172) + return -ENOMEM; + + pl172->clk = devm_clk_get(dev, "mpmcclk"); + if (IS_ERR(pl172->clk)) { + dev_err(dev, "no mpmcclk provided clock\n"); + return PTR_ERR(pl172->clk); + } + + ret = clk_prepare_enable(pl172->clk); + if (ret) { + dev_err(dev, "unable to mpmcclk enable clock\n"); + return ret; + } + + pl172->rate = clk_get_rate(pl172->clk) / MSEC_PER_SEC; + if (!pl172->rate) { + dev_err(dev, "unable to get mpmcclk clock rate\n"); + ret = -EINVAL; + goto err_clk_enable; + } + + ret = amba_request_regions(adev, NULL); + if (ret) { + dev_err(dev, "unable to request AMBA regions\n"); + goto err_clk_enable; + } + + pl172->base = devm_ioremap(dev, adev->res.start, + resource_size(&adev->res)); + if (!pl172->base) { + dev_err(dev, "ioremap failed\n"); + ret = -ENOMEM; + goto err_no_ioremap; + } + + amba_set_drvdata(adev, pl172); + + /* + * Loop through each child node, which represent a chip select, and + * configure parameters and timing. If successful; populate devices + * under that node. + */ + for_each_available_child_of_node(np, child_np) { + ret = pl172_parse_cs_config(adev, child_np); + if (ret) + continue; + + of_platform_populate(child_np, NULL, NULL, dev); + } + + return 0; + +err_no_ioremap: + amba_release_regions(adev); +err_clk_enable: + clk_disable_unprepare(pl172->clk); + return ret; +} + +static int pl172_remove(struct amba_device *adev) +{ + struct pl172_data *pl172 = amba_get_drvdata(adev); + + clk_disable_unprepare(pl172->clk); + amba_release_regions(adev); + + return 0; +} + +static const struct amba_id pl172_ids[] = { + { + .id = 0x07341172, + .mask = 0xffffffff, + }, + { 0, 0 }, +}; +MODULE_DEVICE_TABLE(amba, pl172_ids); + +static struct amba_driver pl172_driver = { + .drv = { + .name = "memory-pl172", + }, + .probe = pl172_probe, + .remove = pl172_remove, + .id_table = pl172_ids, +}; +module_amba_driver(pl172_driver); + +MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>"); +MODULE_DESCRIPTION("PL172 Memory Controller Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile index 6a0b9ac54..c2cb671ff 100644 --- a/drivers/memory/tegra/Makefile +++ b/drivers/memory/tegra/Makefile @@ -4,6 +4,7 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30.o tegra-mc-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114.o tegra-mc-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o tegra-mc-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra124.o +tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o obj-$(CONFIG_TEGRA_MC) += tegra-mc.o diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index c71ede67e..a1ae0cc2b 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -42,7 +42,6 @@ #define MC_ERR_STATUS_ADR_HI_MASK 0x3 #define MC_ERR_STATUS_SECURITY (1 << 17) #define MC_ERR_STATUS_RW (1 << 16) -#define MC_ERR_STATUS_CLIENT_MASK 0x7f #define MC_ERR_ADR 0x0c @@ -67,6 +66,9 @@ static const struct of_device_id tegra_mc_of_match[] = { #ifdef CONFIG_ARCH_TEGRA_132_SOC { .compatible = "nvidia,tegra132-mc", .data = &tegra132_mc_soc }, #endif +#ifdef CONFIG_ARCH_TEGRA_210_SOC + { .compatible = "nvidia,tegra210-mc", .data = &tegra210_mc_soc }, +#endif { } }; MODULE_DEVICE_TABLE(of, tegra_mc_of_match); @@ -283,7 +285,7 @@ static irqreturn_t tegra_mc_irq(int irq, void *data) else secure = ""; - id = value & MC_ERR_STATUS_CLIENT_MASK; + id = value & mc->soc->client_id_mask; for (i = 0; i < mc->soc->num_clients; i++) { if (mc->soc->clients[i].id == id) { @@ -410,6 +412,8 @@ static int tegra_mc_probe(struct platform_device *pdev) return err; } + WARN(!mc->soc->client_id_mask, "Missing client ID mask for this SoC\n"); + value = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM; diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index b7361b0a6..ddb16676c 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -41,4 +41,8 @@ extern const struct tegra_mc_soc tegra124_mc_soc; extern const struct tegra_mc_soc tegra132_mc_soc; #endif +#ifdef CONFIG_ARCH_TEGRA_210_SOC +extern const struct tegra_mc_soc tegra210_mc_soc; +#endif + #endif /* MEMORY_TEGRA_MC_H */ diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c index 9bf11ea90..ba8fff3d6 100644 --- a/drivers/memory/tegra/tegra114.c +++ b/drivers/memory/tegra/tegra114.c @@ -9,8 +9,6 @@ #include <linux/of.h> #include <linux/mm.h> -#include <asm/cacheflush.h> - #include <dt-bindings/memory/tegra114-mc.h> #include "mc.h" @@ -914,20 +912,6 @@ static const struct tegra_smmu_swgroup tegra114_swgroups[] = { { .name = "tsec", .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 }, }; -static void tegra114_flush_dcache(struct page *page, unsigned long offset, - size_t size) -{ - phys_addr_t phys = page_to_phys(page) + offset; - void *virt = page_address(page) + offset; - - __cpuc_flush_dcache_area(virt, size); - outer_flush_range(phys, phys + size); -} - -static const struct tegra_smmu_ops tegra114_smmu_ops = { - .flush_dcache = tegra114_flush_dcache, -}; - static const struct tegra_smmu_soc tegra114_smmu_soc = { .clients = tegra114_mc_clients, .num_clients = ARRAY_SIZE(tegra114_mc_clients), @@ -937,7 +921,6 @@ static const struct tegra_smmu_soc tegra114_smmu_soc = { .supports_request_limit = false, .num_tlb_lines = 32, .num_asids = 4, - .ops = &tegra114_smmu_ops, }; const struct tegra_mc_soc tegra114_mc_soc = { @@ -945,5 +928,6 @@ const struct tegra_mc_soc tegra114_mc_soc = { .num_clients = ARRAY_SIZE(tegra114_mc_clients), .num_address_bits = 32, .atom_size = 32, + .client_id_mask = 0x7f, .smmu = &tegra114_smmu_soc, }; diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c index 862035577..3dac7be39 100644 --- a/drivers/memory/tegra/tegra124-emc.c +++ b/drivers/memory/tegra/tegra124-emc.c @@ -1027,7 +1027,40 @@ static int emc_debug_rate_set(void *data, u64 rate) DEFINE_SIMPLE_ATTRIBUTE(emc_debug_rate_fops, emc_debug_rate_get, emc_debug_rate_set, "%lld\n"); -static void emc_debugfs_init(struct device *dev) +static int emc_debug_supported_rates_show(struct seq_file *s, void *data) +{ + struct tegra_emc *emc = s->private; + const char *prefix = ""; + unsigned int i; + + for (i = 0; i < emc->num_timings; i++) { + struct emc_timing *timing = &emc->timings[i]; + + seq_printf(s, "%s%lu", prefix, timing->rate); + + prefix = " "; + } + + seq_puts(s, "\n"); + + return 0; +} + +static int emc_debug_supported_rates_open(struct inode *inode, + struct file *file) +{ + return single_open(file, emc_debug_supported_rates_show, + inode->i_private); +} + +static const struct file_operations emc_debug_supported_rates_fops = { + .open = emc_debug_supported_rates_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc) { struct dentry *root, *file; struct clk *clk; @@ -1048,6 +1081,11 @@ static void emc_debugfs_init(struct device *dev) &emc_debug_rate_fops); if (!file) dev_err(dev, "failed to create debugfs entry\n"); + + file = debugfs_create_file("supported_rates", S_IRUGO, root, emc, + &emc_debug_supported_rates_fops); + if (!file) + dev_err(dev, "failed to create debugfs entry\n"); } static int tegra_emc_probe(struct platform_device *pdev) @@ -1119,7 +1157,7 @@ static int tegra_emc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, emc); if (IS_ENABLED(CONFIG_DEBUG_FS)) - emc_debugfs_init(&pdev->dev); + emc_debugfs_init(&pdev->dev, emc); return 0; }; diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index 70ed80d23..21e7255e3 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -9,8 +9,6 @@ #include <linux/of.h> #include <linux/mm.h> -#include <asm/cacheflush.h> - #include <dt-bindings/memory/tegra124-mc.h> #include "mc.h" @@ -1002,20 +1000,6 @@ static const struct tegra_smmu_swgroup tegra124_swgroups[] = { }; #ifdef CONFIG_ARCH_TEGRA_124_SOC -static void tegra124_flush_dcache(struct page *page, unsigned long offset, - size_t size) -{ - phys_addr_t phys = page_to_phys(page) + offset; - void *virt = page_address(page) + offset; - - __cpuc_flush_dcache_area(virt, size); - outer_flush_range(phys, phys + size); -} - -static const struct tegra_smmu_ops tegra124_smmu_ops = { - .flush_dcache = tegra124_flush_dcache, -}; - static const struct tegra_smmu_soc tegra124_smmu_soc = { .clients = tegra124_mc_clients, .num_clients = ARRAY_SIZE(tegra124_mc_clients), @@ -1023,9 +1007,7 @@ static const struct tegra_smmu_soc tegra124_smmu_soc = { .num_swgroups = ARRAY_SIZE(tegra124_swgroups), .supports_round_robin_arbitration = true, .supports_request_limit = true, - .num_tlb_lines = 32, .num_asids = 128, - .ops = &tegra124_smmu_ops, }; const struct tegra_mc_soc tegra124_mc_soc = { @@ -1033,6 +1015,7 @@ const struct tegra_mc_soc tegra124_mc_soc = { .num_clients = ARRAY_SIZE(tegra124_mc_clients), .num_address_bits = 34, .atom_size = 32, + .client_id_mask = 0x7f, .smmu = &tegra124_smmu_soc, .emem_regs = tegra124_mc_emem_regs, .num_emem_regs = ARRAY_SIZE(tegra124_mc_emem_regs), @@ -1040,18 +1023,6 @@ const struct tegra_mc_soc tegra124_mc_soc = { #endif /* CONFIG_ARCH_TEGRA_124_SOC */ #ifdef CONFIG_ARCH_TEGRA_132_SOC -static void tegra132_flush_dcache(struct page *page, unsigned long offset, - size_t size) -{ - void *virt = page_address(page) + offset; - - __flush_dcache_area(virt, size); -} - -static const struct tegra_smmu_ops tegra132_smmu_ops = { - .flush_dcache = tegra132_flush_dcache, -}; - static const struct tegra_smmu_soc tegra132_smmu_soc = { .clients = tegra124_mc_clients, .num_clients = ARRAY_SIZE(tegra124_mc_clients), @@ -1059,8 +1030,8 @@ static const struct tegra_smmu_soc tegra132_smmu_soc = { .num_swgroups = ARRAY_SIZE(tegra124_swgroups), .supports_round_robin_arbitration = true, .supports_request_limit = true, + .num_tlb_lines = 32, .num_asids = 128, - .ops = &tegra132_smmu_ops, }; const struct tegra_mc_soc tegra132_mc_soc = { @@ -1068,6 +1039,7 @@ const struct tegra_mc_soc tegra132_mc_soc = { .num_clients = ARRAY_SIZE(tegra124_mc_clients), .num_address_bits = 34, .atom_size = 32, + .client_id_mask = 0x7f, .smmu = &tegra132_smmu_soc, }; #endif /* CONFIG_ARCH_TEGRA_132_SOC */ diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c new file mode 100644 index 000000000..5e144abe4 --- /dev/null +++ b/drivers/memory/tegra/tegra210.c @@ -0,0 +1,1080 @@ +/* + * Copyright (C) 2015 NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/of.h> +#include <linux/mm.h> + +#include <asm/cacheflush.h> + +#include <dt-bindings/memory/tegra210-mc.h> + +#include "mc.h" + +static const struct tegra_mc_client tegra210_mc_clients[] = { + { + .id = 0x00, + .name = "ptcr", + .swgroup = TEGRA_SWGROUP_PTC, + }, { + .id = 0x01, + .name = "display0a", + .swgroup = TEGRA_SWGROUP_DC, + .smmu = { + .reg = 0x228, + .bit = 1, + }, + .la = { + .reg = 0x2e8, + .shift = 0, + .mask = 0xff, + .def = 0xc2, + }, + }, { + .id = 0x02, + .name = "display0ab", + .swgroup = TEGRA_SWGROUP_DCB, + .smmu = { + .reg = 0x228, + .bit = 2, + }, + .la = { + .reg = 0x2f4, + .shift = 0, + .mask = 0xff, + .def = 0xc6, + }, + }, { + .id = 0x03, + .name = "display0b", + .swgroup = TEGRA_SWGROUP_DC, + .smmu = { + .reg = 0x228, + .bit = 3, + }, + .la = { + .reg = 0x2e8, + .shift = 16, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x04, + .name = "display0bb", + .swgroup = TEGRA_SWGROUP_DCB, + .smmu = { + .reg = 0x228, + .bit = 4, + }, + .la = { + .reg = 0x2f4, + .shift = 16, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x05, + .name = "display0c", + .swgroup = TEGRA_SWGROUP_DC, + .smmu = { + .reg = 0x228, + .bit = 5, + }, + .la = { + .reg = 0x2ec, + .shift = 0, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x06, + .name = "display0cb", + .swgroup = TEGRA_SWGROUP_DCB, + .smmu = { + .reg = 0x228, + .bit = 6, + }, + .la = { + .reg = 0x2f8, + .shift = 0, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x0e, + .name = "afir", + .swgroup = TEGRA_SWGROUP_AFI, + .smmu = { + .reg = 0x228, + .bit = 14, + }, + .la = { + .reg = 0x2e0, + .shift = 0, + .mask = 0xff, + .def = 0x13, + }, + }, { + .id = 0x0f, + .name = "avpcarm7r", + .swgroup = TEGRA_SWGROUP_AVPC, + .smmu = { + .reg = 0x228, + .bit = 15, + }, + .la = { + .reg = 0x2e4, + .shift = 0, + .mask = 0xff, + .def = 0x04, + }, + }, { + .id = 0x10, + .name = "displayhc", + .swgroup = TEGRA_SWGROUP_DC, + .smmu = { + .reg = 0x228, + .bit = 16, + }, + .la = { + .reg = 0x2f0, + .shift = 0, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x11, + .name = "displayhcb", + .swgroup = TEGRA_SWGROUP_DCB, + .smmu = { + .reg = 0x228, + .bit = 17, + }, + .la = { + .reg = 0x2fc, + .shift = 0, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x15, + .name = "hdar", + .swgroup = TEGRA_SWGROUP_HDA, + .smmu = { + .reg = 0x228, + .bit = 21, + }, + .la = { + .reg = 0x318, + .shift = 0, + .mask = 0xff, + .def = 0x24, + }, + }, { + .id = 0x16, + .name = "host1xdmar", + .swgroup = TEGRA_SWGROUP_HC, + .smmu = { + .reg = 0x228, + .bit = 22, + }, + .la = { + .reg = 0x310, + .shift = 0, + .mask = 0xff, + .def = 0x1e, + }, + }, { + .id = 0x17, + .name = "host1xr", + .swgroup = TEGRA_SWGROUP_HC, + .smmu = { + .reg = 0x228, + .bit = 23, + }, + .la = { + .reg = 0x310, + .shift = 16, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x1c, + .name = "nvencsrd", + .swgroup = TEGRA_SWGROUP_NVENC, + .smmu = { + .reg = 0x228, + .bit = 28, + }, + .la = { + .reg = 0x328, + .shift = 0, + .mask = 0xff, + .def = 0x23, + }, + }, { + .id = 0x1d, + .name = "ppcsahbdmar", + .swgroup = TEGRA_SWGROUP_PPCS, + .smmu = { + .reg = 0x228, + .bit = 29, + }, + .la = { + .reg = 0x344, + .shift = 0, + .mask = 0xff, + .def = 0x49, + }, + }, { + .id = 0x1e, + .name = "ppcsahbslvr", + .swgroup = TEGRA_SWGROUP_PPCS, + .smmu = { + .reg = 0x228, + .bit = 30, + }, + .la = { + .reg = 0x344, + .shift = 16, + .mask = 0xff, + .def = 0x1a, + }, + }, { + .id = 0x1f, + .name = "satar", + .swgroup = TEGRA_SWGROUP_SATA, + .smmu = { + .reg = 0x228, + .bit = 31, + }, + .la = { + .reg = 0x350, + .shift = 0, + .mask = 0xff, + .def = 0x65, + }, + }, { + .id = 0x27, + .name = "mpcorer", + .swgroup = TEGRA_SWGROUP_MPCORE, + .la = { + .reg = 0x320, + .shift = 0, + .mask = 0xff, + .def = 0x04, + }, + }, { + .id = 0x2b, + .name = "nvencswr", + .swgroup = TEGRA_SWGROUP_NVENC, + .smmu = { + .reg = 0x22c, + .bit = 11, + }, + .la = { + .reg = 0x328, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x31, + .name = "afiw", + .swgroup = TEGRA_SWGROUP_AFI, + .smmu = { + .reg = 0x22c, + .bit = 17, + }, + .la = { + .reg = 0x2e0, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x32, + .name = "avpcarm7w", + .swgroup = TEGRA_SWGROUP_AVPC, + .smmu = { + .reg = 0x22c, + .bit = 18, + }, + .la = { + .reg = 0x2e4, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x35, + .name = "hdaw", + .swgroup = TEGRA_SWGROUP_HDA, + .smmu = { + .reg = 0x22c, + .bit = 21, + }, + .la = { + .reg = 0x318, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x36, + .name = "host1xw", + .swgroup = TEGRA_SWGROUP_HC, + .smmu = { + .reg = 0x22c, + .bit = 22, + }, + .la = { + .reg = 0x314, + .shift = 0, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x39, + .name = "mpcorew", + .swgroup = TEGRA_SWGROUP_MPCORE, + .la = { + .reg = 0x320, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x3b, + .name = "ppcsahbdmaw", + .swgroup = TEGRA_SWGROUP_PPCS, + .smmu = { + .reg = 0x22c, + .bit = 27, + }, + .la = { + .reg = 0x348, + .shift = 0, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x3c, + .name = "ppcsahbslvw", + .swgroup = TEGRA_SWGROUP_PPCS, + .smmu = { + .reg = 0x22c, + .bit = 28, + }, + .la = { + .reg = 0x348, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x3d, + .name = "sataw", + .swgroup = TEGRA_SWGROUP_SATA, + .smmu = { + .reg = 0x22c, + .bit = 29, + }, + .la = { + .reg = 0x350, + .shift = 16, + .mask = 0xff, + .def = 0x65, + }, + }, { + .id = 0x44, + .name = "ispra", + .swgroup = TEGRA_SWGROUP_ISP2, + .smmu = { + .reg = 0x230, + .bit = 4, + }, + .la = { + .reg = 0x370, + .shift = 0, + .mask = 0xff, + .def = 0x18, + }, + }, { + .id = 0x46, + .name = "ispwa", + .swgroup = TEGRA_SWGROUP_ISP2, + .smmu = { + .reg = 0x230, + .bit = 6, + }, + .la = { + .reg = 0x374, + .shift = 0, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x47, + .name = "ispwb", + .swgroup = TEGRA_SWGROUP_ISP2, + .smmu = { + .reg = 0x230, + .bit = 7, + }, + .la = { + .reg = 0x374, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x4a, + .name = "xusb_hostr", + .swgroup = TEGRA_SWGROUP_XUSB_HOST, + .smmu = { + .reg = 0x230, + .bit = 10, + }, + .la = { + .reg = 0x37c, + .shift = 0, + .mask = 0xff, + .def = 0x39, + }, + }, { + .id = 0x4b, + .name = "xusb_hostw", + .swgroup = TEGRA_SWGROUP_XUSB_HOST, + .smmu = { + .reg = 0x230, + .bit = 11, + }, + .la = { + .reg = 0x37c, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x4c, + .name = "xusb_devr", + .swgroup = TEGRA_SWGROUP_XUSB_DEV, + .smmu = { + .reg = 0x230, + .bit = 12, + }, + .la = { + .reg = 0x380, + .shift = 0, + .mask = 0xff, + .def = 0x39, + }, + }, { + .id = 0x4d, + .name = "xusb_devw", + .swgroup = TEGRA_SWGROUP_XUSB_DEV, + .smmu = { + .reg = 0x230, + .bit = 13, + }, + .la = { + .reg = 0x380, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x4e, + .name = "isprab", + .swgroup = TEGRA_SWGROUP_ISP2B, + .smmu = { + .reg = 0x230, + .bit = 14, + }, + .la = { + .reg = 0x384, + .shift = 0, + .mask = 0xff, + .def = 0x18, + }, + }, { + .id = 0x50, + .name = "ispwab", + .swgroup = TEGRA_SWGROUP_ISP2B, + .smmu = { + .reg = 0x230, + .bit = 16, + }, + .la = { + .reg = 0x388, + .shift = 0, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x51, + .name = "ispwbb", + .swgroup = TEGRA_SWGROUP_ISP2B, + .smmu = { + .reg = 0x230, + .bit = 17, + }, + .la = { + .reg = 0x388, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x54, + .name = "tsecsrd", + .swgroup = TEGRA_SWGROUP_TSEC, + .smmu = { + .reg = 0x230, + .bit = 20, + }, + .la = { + .reg = 0x390, + .shift = 0, + .mask = 0xff, + .def = 0x9b, + }, + }, { + .id = 0x55, + .name = "tsecswr", + .swgroup = TEGRA_SWGROUP_TSEC, + .smmu = { + .reg = 0x230, + .bit = 21, + }, + .la = { + .reg = 0x390, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x56, + .name = "a9avpscr", + .swgroup = TEGRA_SWGROUP_A9AVP, + .smmu = { + .reg = 0x230, + .bit = 22, + }, + .la = { + .reg = 0x3a4, + .shift = 0, + .mask = 0xff, + .def = 0x04, + }, + }, { + .id = 0x57, + .name = "a9avpscw", + .swgroup = TEGRA_SWGROUP_A9AVP, + .smmu = { + .reg = 0x230, + .bit = 23, + }, + .la = { + .reg = 0x3a4, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x58, + .name = "gpusrd", + .swgroup = TEGRA_SWGROUP_GPU, + .smmu = { + /* read-only */ + .reg = 0x230, + .bit = 24, + }, + .la = { + .reg = 0x3c8, + .shift = 0, + .mask = 0xff, + .def = 0x1a, + }, + }, { + .id = 0x59, + .name = "gpuswr", + .swgroup = TEGRA_SWGROUP_GPU, + .smmu = { + /* read-only */ + .reg = 0x230, + .bit = 25, + }, + .la = { + .reg = 0x3c8, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x5a, + .name = "displayt", + .swgroup = TEGRA_SWGROUP_DC, + .smmu = { + .reg = 0x230, + .bit = 26, + }, + .la = { + .reg = 0x2f0, + .shift = 16, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x60, + .name = "sdmmcra", + .swgroup = TEGRA_SWGROUP_SDMMC1A, + .smmu = { + .reg = 0x234, + .bit = 0, + }, + .la = { + .reg = 0x3b8, + .shift = 0, + .mask = 0xff, + .def = 0x49, + }, + }, { + .id = 0x61, + .name = "sdmmcraa", + .swgroup = TEGRA_SWGROUP_SDMMC2A, + .smmu = { + .reg = 0x234, + .bit = 1, + }, + .la = { + .reg = 0x3bc, + .shift = 0, + .mask = 0xff, + .def = 0x49, + }, + }, { + .id = 0x62, + .name = "sdmmcr", + .swgroup = TEGRA_SWGROUP_SDMMC3A, + .smmu = { + .reg = 0x234, + .bit = 2, + }, + .la = { + .reg = 0x3c0, + .shift = 0, + .mask = 0xff, + .def = 0x49, + }, + }, { + .id = 0x63, + .swgroup = TEGRA_SWGROUP_SDMMC4A, + .name = "sdmmcrab", + .smmu = { + .reg = 0x234, + .bit = 3, + }, + .la = { + .reg = 0x3c4, + .shift = 0, + .mask = 0xff, + .def = 0x49, + }, + }, { + .id = 0x64, + .name = "sdmmcwa", + .swgroup = TEGRA_SWGROUP_SDMMC1A, + .smmu = { + .reg = 0x234, + .bit = 4, + }, + .la = { + .reg = 0x3b8, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x65, + .name = "sdmmcwaa", + .swgroup = TEGRA_SWGROUP_SDMMC2A, + .smmu = { + .reg = 0x234, + .bit = 5, + }, + .la = { + .reg = 0x3bc, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x66, + .name = "sdmmcw", + .swgroup = TEGRA_SWGROUP_SDMMC3A, + .smmu = { + .reg = 0x234, + .bit = 6, + }, + .la = { + .reg = 0x3c0, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x67, + .name = "sdmmcwab", + .swgroup = TEGRA_SWGROUP_SDMMC4A, + .smmu = { + .reg = 0x234, + .bit = 7, + }, + .la = { + .reg = 0x3c4, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x6c, + .name = "vicsrd", + .swgroup = TEGRA_SWGROUP_VIC, + .smmu = { + .reg = 0x234, + .bit = 12, + }, + .la = { + .reg = 0x394, + .shift = 0, + .mask = 0xff, + .def = 0x1a, + }, + }, { + .id = 0x6d, + .name = "vicswr", + .swgroup = TEGRA_SWGROUP_VIC, + .smmu = { + .reg = 0x234, + .bit = 13, + }, + .la = { + .reg = 0x394, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x72, + .name = "viw", + .swgroup = TEGRA_SWGROUP_VI, + .smmu = { + .reg = 0x234, + .bit = 18, + }, + .la = { + .reg = 0x398, + .shift = 0, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x73, + .name = "displayd", + .swgroup = TEGRA_SWGROUP_DC, + .smmu = { + .reg = 0x234, + .bit = 19, + }, + .la = { + .reg = 0x3c8, + .shift = 0, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x78, + .name = "nvdecsrd", + .swgroup = TEGRA_SWGROUP_NVDEC, + .smmu = { + .reg = 0x234, + .bit = 24, + }, + .la = { + .reg = 0x3d8, + .shift = 0, + .mask = 0xff, + .def = 0x23, + }, + }, { + .id = 0x79, + .name = "nvdecswr", + .swgroup = TEGRA_SWGROUP_NVDEC, + .smmu = { + .reg = 0x234, + .bit = 25, + }, + .la = { + .reg = 0x3d8, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x7a, + .name = "aper", + .swgroup = TEGRA_SWGROUP_APE, + .smmu = { + .reg = 0x234, + .bit = 26, + }, + .la = { + .reg = 0x3dc, + .shift = 0, + .mask = 0xff, + .def = 0xff, + }, + }, { + .id = 0x7b, + .name = "apew", + .swgroup = TEGRA_SWGROUP_APE, + .smmu = { + .reg = 0x234, + .bit = 27, + }, + .la = { + .reg = 0x3dc, + .shift = 0, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x7e, + .name = "nvjpgsrd", + .swgroup = TEGRA_SWGROUP_NVJPG, + .smmu = { + .reg = 0x234, + .bit = 30, + }, + .la = { + .reg = 0x3e4, + .shift = 0, + .mask = 0xff, + .def = 0x23, + }, + }, { + .id = 0x7f, + .name = "nvjpgswr", + .swgroup = TEGRA_SWGROUP_NVJPG, + .smmu = { + .reg = 0x234, + .bit = 31, + }, + .la = { + .reg = 0x3e4, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x80, + .name = "sesrd", + .swgroup = TEGRA_SWGROUP_SE, + .smmu = { + .reg = 0xb98, + .bit = 0, + }, + .la = { + .reg = 0x3e0, + .shift = 0, + .mask = 0xff, + .def = 0x2e, + }, + }, { + .id = 0x81, + .name = "seswr", + .swgroup = TEGRA_SWGROUP_SE, + .smmu = { + .reg = 0xb98, + .bit = 1, + }, + .la = { + .reg = 0xb98, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x82, + .name = "axiapr", + .swgroup = TEGRA_SWGROUP_AXIAP, + .smmu = { + .reg = 0xb98, + .bit = 2, + }, + .la = { + .reg = 0x3a0, + .shift = 0, + .mask = 0xff, + .def = 0xff, + }, + }, { + .id = 0x83, + .name = "axiapw", + .swgroup = TEGRA_SWGROUP_AXIAP, + .smmu = { + .reg = 0xb98, + .bit = 3, + }, + .la = { + .reg = 0x3a0, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x84, + .name = "etrr", + .swgroup = TEGRA_SWGROUP_ETR, + .smmu = { + .reg = 0xb98, + .bit = 4, + }, + .la = { + .reg = 0x3ec, + .shift = 0, + .mask = 0xff, + .def = 0xff, + }, + }, { + .id = 0x85, + .name = "etrw", + .swgroup = TEGRA_SWGROUP_ETR, + .smmu = { + .reg = 0xb98, + .bit = 5, + }, + .la = { + .reg = 0x3ec, + .shift = 16, + .mask = 0xff, + .def = 0xff, + }, + }, { + .id = 0x86, + .name = "tsecsrdb", + .swgroup = TEGRA_SWGROUP_TSECB, + .smmu = { + .reg = 0xb98, + .bit = 6, + }, + .la = { + .reg = 0x3f0, + .shift = 0, + .mask = 0xff, + .def = 0x9b, + }, + }, { + .id = 0x87, + .name = "tsecswrb", + .swgroup = TEGRA_SWGROUP_TSECB, + .smmu = { + .reg = 0xb98, + .bit = 7, + }, + .la = { + .reg = 0x3f0, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, { + .id = 0x88, + .name = "gpusrd2", + .swgroup = TEGRA_SWGROUP_GPU, + .smmu = { + /* read-only */ + .reg = 0xb98, + .bit = 8, + }, + .la = { + .reg = 0x3e8, + .shift = 0, + .mask = 0xff, + .def = 0x1a, + }, + }, { + .id = 0x89, + .name = "gpuswr2", + .swgroup = TEGRA_SWGROUP_GPU, + .smmu = { + /* read-only */ + .reg = 0xb98, + .bit = 9, + }, + .la = { + .reg = 0x3e8, + .shift = 16, + .mask = 0xff, + .def = 0x80, + }, + }, +}; + +static const struct tegra_smmu_swgroup tegra210_swgroups[] = { + { .name = "dc", .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 }, + { .name = "dcb", .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 }, + { .name = "afi", .swgroup = TEGRA_SWGROUP_AFI, .reg = 0x238 }, + { .name = "avpc", .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c }, + { .name = "hda", .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 }, + { .name = "hc", .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 }, + { .name = "nvenc", .swgroup = TEGRA_SWGROUP_NVENC, .reg = 0x264 }, + { .name = "ppcs", .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 }, + { .name = "sata", .swgroup = TEGRA_SWGROUP_SATA, .reg = 0x274 }, + { .name = "isp2", .swgroup = TEGRA_SWGROUP_ISP2, .reg = 0x258 }, + { .name = "xusb_host", .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 }, + { .name = "xusb_dev", .swgroup = TEGRA_SWGROUP_XUSB_DEV, .reg = 0x28c }, + { .name = "isp2b", .swgroup = TEGRA_SWGROUP_ISP2B, .reg = 0xaa4 }, + { .name = "tsec", .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 }, + { .name = "a9avp", .swgroup = TEGRA_SWGROUP_A9AVP, .reg = 0x290 }, + { .name = "gpu", .swgroup = TEGRA_SWGROUP_GPU, .reg = 0xaac }, + { .name = "sdmmc1a", .swgroup = TEGRA_SWGROUP_SDMMC1A, .reg = 0xa94 }, + { .name = "sdmmc2a", .swgroup = TEGRA_SWGROUP_SDMMC2A, .reg = 0xa98 }, + { .name = "sdmmc3a", .swgroup = TEGRA_SWGROUP_SDMMC3A, .reg = 0xa9c }, + { .name = "sdmmc4a", .swgroup = TEGRA_SWGROUP_SDMMC4A, .reg = 0xaa0 }, + { .name = "vic", .swgroup = TEGRA_SWGROUP_VIC, .reg = 0x284 }, + { .name = "vi", .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 }, + { .name = "nvdec", .swgroup = TEGRA_SWGROUP_NVDEC, .reg = 0xab4 }, + { .name = "ape", .swgroup = TEGRA_SWGROUP_APE, .reg = 0xab8 }, + { .name = "nvjpg", .swgroup = TEGRA_SWGROUP_NVJPG, .reg = 0xac0 }, + { .name = "se", .swgroup = TEGRA_SWGROUP_SE, .reg = 0xabc }, + { .name = "axiap", .swgroup = TEGRA_SWGROUP_AXIAP, .reg = 0xacc }, + { .name = "etr", .swgroup = TEGRA_SWGROUP_ETR, .reg = 0xad0 }, + { .name = "tsecb", .swgroup = TEGRA_SWGROUP_TSECB, .reg = 0xad4 }, +}; + +static const struct tegra_smmu_soc tegra210_smmu_soc = { + .clients = tegra210_mc_clients, + .num_clients = ARRAY_SIZE(tegra210_mc_clients), + .swgroups = tegra210_swgroups, + .num_swgroups = ARRAY_SIZE(tegra210_swgroups), + .supports_round_robin_arbitration = true, + .supports_request_limit = true, + .num_tlb_lines = 32, + .num_asids = 128, +}; + +const struct tegra_mc_soc tegra210_mc_soc = { + .clients = tegra210_mc_clients, + .num_clients = ARRAY_SIZE(tegra210_mc_clients), + .num_address_bits = 34, + .atom_size = 64, + .client_id_mask = 0xff, + .smmu = &tegra210_smmu_soc, +}; diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c index b2a34fefa..b44737840 100644 --- a/drivers/memory/tegra/tegra30.c +++ b/drivers/memory/tegra/tegra30.c @@ -9,8 +9,6 @@ #include <linux/of.h> #include <linux/mm.h> -#include <asm/cacheflush.h> - #include <dt-bindings/memory/tegra30-mc.h> #include "mc.h" @@ -936,20 +934,6 @@ static const struct tegra_smmu_swgroup tegra30_swgroups[] = { { .name = "isp", .swgroup = TEGRA_SWGROUP_ISP, .reg = 0x258 }, }; -static void tegra30_flush_dcache(struct page *page, unsigned long offset, - size_t size) -{ - phys_addr_t phys = page_to_phys(page) + offset; - void *virt = page_address(page) + offset; - - __cpuc_flush_dcache_area(virt, size); - outer_flush_range(phys, phys + size); -} - -static const struct tegra_smmu_ops tegra30_smmu_ops = { - .flush_dcache = tegra30_flush_dcache, -}; - static const struct tegra_smmu_soc tegra30_smmu_soc = { .clients = tegra30_mc_clients, .num_clients = ARRAY_SIZE(tegra30_mc_clients), @@ -959,7 +943,6 @@ static const struct tegra_smmu_soc tegra30_smmu_soc = { .supports_request_limit = false, .num_tlb_lines = 16, .num_asids = 4, - .ops = &tegra30_smmu_ops, }; const struct tegra_mc_soc tegra30_mc_soc = { @@ -967,5 +950,6 @@ const struct tegra_mc_soc tegra30_mc_soc = { .num_clients = ARRAY_SIZE(tegra30_mc_clients), .num_address_bits = 32, .atom_size = 16, + .client_id_mask = 0x7f, .smmu = &tegra30_smmu_soc, }; |