* [PATCH 1/6] iommu/tegra124: smmu: optionaly AHB enables SMMU
[not found] ` <1386246319-17851-1-git-send-email-hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2013-12-05 12:25 ` Hiroshi Doyu
[not found] ` <1386246319-17851-2-git-send-email-hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-12-05 12:25 ` [PATCH 2/6] iommu/tegra124: smmu: convert swgroup ID to asid offset Hiroshi Doyu
` (5 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Hiroshi Doyu @ 2013-12-05 12:25 UTC (permalink / raw)
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
Cc: joro-zLv9SwRftAIdnm+yROfE0A, Hiroshi Doyu
SMMU used to depend on AHB bus. AHB driver needs to be populated and
AHB_XBAR_CTRL_SMMU_INIT_DONE bit needs to be set earliear than SMMU
being populated. Later Tegra SoC (>= T124) doesn't need AHB to enable
SMMU on AHB_XBAR_CTRL for AHB_XBAR_CTRL_SMMU_INIT_DONE any more. This
setting bit is now optional, depending on DT passing ahb phandle or
not.
Signed-off-by: Hiroshi Doyu <hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/iommu/tegra-smmu.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index d0f0ba7..f63d54a 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -500,7 +500,10 @@ static int smmu_setup_regs(struct smmu_device *smmu)
smmu_flush_regs(smmu, 1);
- return tegra_ahb_enable_smmu(smmu->ahb);
+ if (smmu->ahb)
+ return tegra_ahb_enable_smmu(smmu->ahb);
+
+ return 0;
}
static void flush_ptc_and_tlb(struct smmu_device *smmu,
@@ -1284,9 +1287,6 @@ static int tegra_smmu_probe(struct platform_device *pdev)
return -EINVAL;
smmu->ahb = of_parse_phandle(dev->of_node, "nvidia,ahb", 0);
- if (!smmu->ahb)
- return -ENODEV;
-
smmu->iommu.dev = dev;
smmu->num_as = asids;
smmu->iovmm_base = base;
--
1.8.1.5
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 2/6] iommu/tegra124: smmu: convert swgroup ID to asid offset
[not found] ` <1386246319-17851-1-git-send-email-hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-12-05 12:25 ` [PATCH 1/6] iommu/tegra124: smmu: optionaly AHB enables SMMU Hiroshi Doyu
@ 2013-12-05 12:25 ` Hiroshi Doyu
2013-12-05 12:25 ` [PATCH 3/6] iommu/tegra124: smmu: add support platform data Hiroshi Doyu
` (4 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Hiroshi Doyu @ 2013-12-05 12:25 UTC (permalink / raw)
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
Provide a conversion table from swgroup ID to MC_SMMU_<swgroup
name>_ASID_0 register offset to support non-linear conversion. This
conversion used to be exactly linear but after T124 we need a
conversion table to support non-linear cases. We would also need
another table to convert swgroup ID to HOTRESET bit.
Signed-off-by: Hiroshi Doyu <hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/iommu/tegra-smmu.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index f63d54a..a723a1b 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -184,8 +184,6 @@ enum {
#define __smmu_client_enable_swgroups(c, m) __smmu_client_set_swgroups(c, m, 1)
#define __smmu_client_disable_swgroups(c) __smmu_client_set_swgroups(c, 0, 0)
-#define SWGROUPS_ASID_REG(x) ((x) * sizeof(u32) + SMMU_ASID_BASE)
-
/*
* Per client for address space
*/
@@ -314,6 +312,23 @@ static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs)
*/
#define FLUSH_SMMU_REGS(smmu) smmu_read(smmu, SMMU_CONFIG)
+static size_t smmu_get_asid_offset(int id)
+{
+ switch (id) {
+ case TEGRA_SWGROUP_DC14:
+ return 0x490;
+ case TEGRA_SWGROUP_DC12:
+ return 0xa88;
+ case TEGRA_SWGROUP_AFI...TEGRA_SWGROUP_ISP:
+ case TEGRA_SWGROUP_MPE...TEGRA_SWGROUP_PPCS1:
+ return (id - TEGRA_SWGROUP_AFI) * sizeof(u32) + SMMU_ASID_BASE;
+ case TEGRA_SWGROUP_SDMMC1A...63:
+ return (id - TEGRA_SWGROUP_SDMMC1A) * sizeof(u32) + 0xa94;
+ };
+
+ BUG();
+}
+
static struct smmu_client *find_smmu_client(struct smmu_device *smmu,
struct device_node *dev_node)
{
@@ -416,7 +431,7 @@ static int __smmu_client_set_swgroups(struct smmu_client *c,
map = c->swgroups;
for_each_set_bit(i, map, TEGRA_SWGROUP_MAX) {
- offs = SWGROUPS_ASID_REG(i);
+ offs = smmu_get_asid_offset(i);
val = smmu_read(smmu, offs);
if (on) {
if (val) {
--
1.8.1.5
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 3/6] iommu/tegra124: smmu: add support platform data
[not found] ` <1386246319-17851-1-git-send-email-hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-12-05 12:25 ` [PATCH 1/6] iommu/tegra124: smmu: optionaly AHB enables SMMU Hiroshi Doyu
2013-12-05 12:25 ` [PATCH 2/6] iommu/tegra124: smmu: convert swgroup ID to asid offset Hiroshi Doyu
@ 2013-12-05 12:25 ` Hiroshi Doyu
[not found] ` <1386246319-17851-4-git-send-email-hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-12-05 12:25 ` [PATCH 4/6] iommu/tegra124: smmu: support more than 32 bit pa Hiroshi Doyu
` (3 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Hiroshi Doyu @ 2013-12-05 12:25 UTC (permalink / raw)
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
Cc: joro-zLv9SwRftAIdnm+yROfE0A, Hiroshi Doyu
The later Tegra SoC(>= T124) has more registers for
MC_SMMU_TRANSLATION_ENABLE_*. Now those info is provided as platfrom
data. If those varies a lot on SoCs in the future, we can consider
putting them into DT later.
Signed-off-by: Hiroshi Doyu <hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
.../bindings/iommu/nvidia,tegra30-smmu.txt | 4 +-
drivers/iommu/tegra-smmu.c | 68 ++++++++++++++--------
2 files changed, 47 insertions(+), 25 deletions(-)
diff --git a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
index fd53f54..71be0d2 100644
--- a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt
@@ -1,8 +1,8 @@
NVIDIA Tegra 30 IOMMU H/W, SMMU (System Memory Management Unit)
Required properties in the IOMMU node:
-- compatible : "nvidia,tegra30-smmu"
-- reg : Should contain 3 register banks(address and length) for each
+- compatible : "nvidia,tegra124-smmu", "nvidia,tegra30-smmu"
+- reg : Can contain multiple register banks(address and length) for each
of the SMMU register blocks.
- interrupts : Should contain MC General interrupt.
- nvidia,#asids : # of ASIDs
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index a723a1b..b5737f9 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -32,6 +32,7 @@
#include <linux/iommu.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/of_iommu.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
@@ -108,8 +109,6 @@ enum {
(SMMU_STATS_CACHE_COUNT_BASE + 8 * cache + 4 * hitmiss)
#define SMMU_TRANSLATION_ENABLE_0 0x228
-#define SMMU_TRANSLATION_ENABLE_1 0x22c
-#define SMMU_TRANSLATION_ENABLE_2 0x230
#define SMMU_AFI_ASID 0x238 /* PCIE */
#define SMMU_ASID_BASE SMMU_AFI_ASID
@@ -237,12 +236,12 @@ struct smmu_device {
struct rb_root clients;
struct page *avp_vector_page; /* dummy page shared by all AS's */
+ int nr_xlats; /* number of translation_enable registers */
+
/*
* Register image savers for suspend/resume
*/
- unsigned long translation_enable_0;
- unsigned long translation_enable_1;
- unsigned long translation_enable_2;
+ u32 *xlat;
unsigned long asid_security;
struct dentry *debugfs_root;
@@ -256,6 +255,11 @@ struct smmu_device {
struct smmu_as as[0]; /* Run-time allocated array */
};
+struct smmu_platform_data {
+ int asids; /* number of asids */
+ int nr_xlats; /* number of translation_enable registers */
+};
+
static struct smmu_device *smmu_handle; /* unique for a system */
/*
@@ -506,9 +510,10 @@ static int smmu_setup_regs(struct smmu_device *smmu)
__smmu_client_set_swgroups(c, c->swgroups, 1);
}
- smmu_write(smmu, smmu->translation_enable_0, SMMU_TRANSLATION_ENABLE_0);
- smmu_write(smmu, smmu->translation_enable_1, SMMU_TRANSLATION_ENABLE_1);
- smmu_write(smmu, smmu->translation_enable_2, SMMU_TRANSLATION_ENABLE_2);
+ for (i = 0; i < smmu->nr_xlats; i++)
+ smmu_write(smmu, smmu->xlat[i],
+ SMMU_TRANSLATION_ENABLE_0 + i * sizeof(u32));
+
smmu_write(smmu, smmu->asid_security, SMMU_ASID_SECURITY);
smmu_write(smmu, SMMU_TLB_CONFIG_RESET_VAL, SMMU_CACHE_CONFIG(_TLB));
smmu_write(smmu, SMMU_PTC_CONFIG_RESET_VAL, SMMU_CACHE_CONFIG(_PTC));
@@ -1205,11 +1210,13 @@ err_out:
static int tegra_smmu_suspend(struct device *dev)
{
+ int i;
struct smmu_device *smmu = dev_get_drvdata(dev);
- smmu->translation_enable_0 = smmu_read(smmu, SMMU_TRANSLATION_ENABLE_0);
- smmu->translation_enable_1 = smmu_read(smmu, SMMU_TRANSLATION_ENABLE_1);
- smmu->translation_enable_2 = smmu_read(smmu, SMMU_TRANSLATION_ENABLE_2);
+ for (i = 0; i < smmu->nr_xlats; i++)
+ smmu->xlat[i] = smmu_read(smmu,
+ SMMU_TRANSLATION_ENABLE_0 + i * sizeof(u32));
+
smmu->asid_security = smmu_read(smmu, SMMU_ASID_SECURITY);
return 0;
}
@@ -1243,6 +1250,18 @@ static void tegra_smmu_create_default_map(struct smmu_device *smmu)
}
}
+static const struct smmu_platform_data tegra124_smmu_pdata = {
+ .asids = 128,
+ .nr_xlats = 4,
+};
+
+static struct of_device_id tegra_smmu_of_match[] = {
+ { .compatible = "nvidia,tegra124-smmu", .data = &tegra124_smmu_pdata, },
+ { .compatible = "nvidia,tegra30-smmu", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tegra_smmu_of_match);
+
static int tegra_smmu_probe(struct platform_device *pdev)
{
struct smmu_device *smmu;
@@ -1250,20 +1269,29 @@ static int tegra_smmu_probe(struct platform_device *pdev)
int i, asids, err = 0;
dma_addr_t uninitialized_var(base);
size_t bytes, uninitialized_var(size);
+ const struct of_device_id *match;
+ const struct smmu_platform_data *pdata;
+ int nr_xlats;
if (smmu_handle)
return -EIO;
BUILD_BUG_ON(PAGE_SHIFT != SMMU_PAGE_SHIFT);
- if (of_property_read_u32(dev->of_node, "nvidia,#asids", &asids))
- return -ENODEV;
+ match = of_match_device(tegra_smmu_of_match, &pdev->dev);
+ if (!match)
+ return -EINVAL;
+ pdata = match->data;
+ nr_xlats = (pdata && pdata->nr_xlats) ? pdata->nr_xlats : 3;
+ if (of_property_read_u32(dev->of_node, "nvidia,#asids", &asids))
+ asids = (pdata && pdata->asids) ? pdata->asids : 4;
if (asids < NUM_OF_STATIC_MAPS)
return -EINVAL;
bytes = sizeof(*smmu) + asids * (sizeof(*smmu->as) +
sizeof(struct dma_iommu_mapping *));
+ bytes += sizeof(u32) * nr_xlats;
smmu = devm_kzalloc(dev, bytes, GFP_KERNEL);
if (!smmu) {
dev_err(dev, "failed to allocate smmu_device\n");
@@ -1272,6 +1300,7 @@ static int tegra_smmu_probe(struct platform_device *pdev)
smmu->clients = RB_ROOT;
smmu->map = (struct dma_iommu_mapping **)(smmu->as + asids);
+ smmu->xlat = (u32 *)(smmu->map + smmu->num_as);
smmu->nregs = pdev->num_resources;
smmu->regs = devm_kzalloc(dev, 2 * smmu->nregs * sizeof(*smmu->regs),
GFP_KERNEL);
@@ -1304,13 +1333,12 @@ static int tegra_smmu_probe(struct platform_device *pdev)
smmu->ahb = of_parse_phandle(dev->of_node, "nvidia,ahb", 0);
smmu->iommu.dev = dev;
smmu->num_as = asids;
+ smmu->nr_xlats = nr_xlats;
smmu->iovmm_base = base;
smmu->page_count = size;
-
- smmu->translation_enable_0 = ~0;
- smmu->translation_enable_1 = ~0;
- smmu->translation_enable_2 = ~0;
smmu->asid_security = 0;
+ for (i = 0; i < smmu->nr_xlats; i++)
+ smmu->xlat[i] = ~0;
for (i = 0; i < smmu->num_as; i++) {
struct smmu_as *as = &smmu->as[i];
@@ -1365,12 +1393,6 @@ static const struct dev_pm_ops tegra_smmu_pm_ops = {
.resume = tegra_smmu_resume,
};
-static struct of_device_id tegra_smmu_of_match[] = {
- { .compatible = "nvidia,tegra30-smmu", },
- { },
-};
-MODULE_DEVICE_TABLE(of, tegra_smmu_of_match);
-
static struct platform_driver tegra_smmu_driver = {
.probe = tegra_smmu_probe,
.remove = tegra_smmu_remove,
--
1.8.1.5
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 4/6] iommu/tegra124: smmu: support more than 32 bit pa
[not found] ` <1386246319-17851-1-git-send-email-hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (2 preceding siblings ...)
2013-12-05 12:25 ` [PATCH 3/6] iommu/tegra124: smmu: add support platform data Hiroshi Doyu
@ 2013-12-05 12:25 ` Hiroshi Doyu
[not found] ` <1386246319-17851-5-git-send-email-hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-12-05 12:25 ` [PATCH 5/6] iommu/tegra124: smmu: {TLB,PTC} reset value per SoC Hiroshi Doyu
` (2 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Hiroshi Doyu @ 2013-12-05 12:25 UTC (permalink / raw)
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
Cc: joro-zLv9SwRftAIdnm+yROfE0A, Hiroshi Doyu, Pavan Kunapuli
Add support for more than 32 bit physical address. If physical
address space is 32bit, there will be no register write
happening. Based on Pavan's internal patch.
Signed-off-by: Hiroshi Doyu <hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Cc: Pavan Kunapuli <pkunapuli-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/iommu/tegra-smmu.c | 32 +++++++++++++++++++++++++-------
1 file changed, 25 insertions(+), 7 deletions(-)
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index b5737f9..04e7199 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -101,6 +101,8 @@ enum {
#define SMMU_PTC_FLUSH_TYPE_ADR 1
#define SMMU_PTC_FLUSH_ADR_SHIFT 4
+#define SMMU_PTC_FLUSH_1 0x9b8
+
#define SMMU_ASID_SECURITY 0x38
#define SMMU_STATS_CACHE_COUNT_BASE 0x1f0
@@ -143,7 +145,7 @@ enum {
#define SMMU_PDIR_SHIFT 12
#define SMMU_PDE_SHIFT 12
#define SMMU_PTE_SHIFT 12
-#define SMMU_PFN_MASK 0x000fffff
+#define SMMU_PFN_MASK 0x0fffffff
#define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
#define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
@@ -301,6 +303,8 @@ static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs)
#define VA_PAGE_TO_PA(va, page) \
(page_to_phys(page) + ((unsigned long)(va) & ~PAGE_MASK))
+#define VA_PAGE_TO_PA_HI(va, page) (u32)((u64)page_to_phys(page) >> 32)
+
#define FLUSH_CPU_DCACHE(va, page, size) \
do { \
unsigned long _pa_ = VA_PAGE_TO_PA(va, page); \
@@ -526,6 +530,21 @@ static int smmu_setup_regs(struct smmu_device *smmu)
return 0;
}
+static void flush_ptc_by_addr(struct smmu_device *smmu, unsigned long *pte,
+ struct page *page)
+{
+ u32 val;
+
+ val = VA_PAGE_TO_PA_HI(pte, page);
+ if (val)
+ smmu_write(smmu, val, SMMU_PTC_FLUSH_1);
+
+ val = SMMU_PTC_FLUSH_TYPE_ADR | VA_PAGE_TO_PA(pte, page);
+ smmu_write(smmu, val, SMMU_PTC_FLUSH);
+
+ FLUSH_SMMU_REGS(smmu);
+}
+
static void flush_ptc_and_tlb(struct smmu_device *smmu,
struct smmu_as *as, dma_addr_t iova,
unsigned long *pte, struct page *page, int is_pde)
@@ -535,9 +554,8 @@ static void flush_ptc_and_tlb(struct smmu_device *smmu,
? SMMU_TLB_FLUSH_VA(iova, SECTION)
: SMMU_TLB_FLUSH_VA(iova, GROUP);
- val = SMMU_PTC_FLUSH_TYPE_ADR | VA_PAGE_TO_PA(pte, page);
- smmu_write(smmu, val, SMMU_PTC_FLUSH);
- FLUSH_SMMU_REGS(smmu);
+ flush_ptc_by_addr(smmu, pte, page);
+
val = tlb_flush_va |
SMMU_TLB_FLUSH_ASID_MATCH__ENABLE |
(as->asid << SMMU_TLB_FLUSH_ASID_SHIFT);
@@ -702,9 +720,9 @@ static int alloc_pdir(struct smmu_as *as)
for (pdn = 0; pdn < SMMU_PDIR_COUNT; pdn++)
pdir[pdn] = _PDE_VACANT(pdn);
FLUSH_CPU_DCACHE(pdir, as->pdir_page, SMMU_PDIR_SIZE);
- val = SMMU_PTC_FLUSH_TYPE_ADR | VA_PAGE_TO_PA(pdir, as->pdir_page);
- smmu_write(smmu, val, SMMU_PTC_FLUSH);
- FLUSH_SMMU_REGS(as->smmu);
+
+ flush_ptc_by_addr(as->smmu, pdir, page);
+
val = SMMU_TLB_FLUSH_VA_MATCH_ALL |
SMMU_TLB_FLUSH_ASID_MATCH__ENABLE |
(as->asid << SMMU_TLB_FLUSH_ASID_SHIFT);
--
1.8.1.5
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 5/6] iommu/tegra124: smmu: {TLB,PTC} reset value per SoC
[not found] ` <1386246319-17851-1-git-send-email-hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (3 preceding siblings ...)
2013-12-05 12:25 ` [PATCH 4/6] iommu/tegra124: smmu: support more than 32 bit pa Hiroshi Doyu
@ 2013-12-05 12:25 ` Hiroshi Doyu
[not found] ` <1386246319-17851-6-git-send-email-hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-12-05 12:25 ` [PATCH 6/6] iommu/tegra124: smmu: adjust TLB_FLUSH_ASID bit range Hiroshi Doyu
2013-12-09 7:16 ` [PATCH 7/6] iommu/tegra124: smmu: add multiple asid_security support Hiroshi Doyu
6 siblings, 1 reply; 14+ messages in thread
From: Hiroshi Doyu @ 2013-12-05 12:25 UTC (permalink / raw)
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
Cc: joro-zLv9SwRftAIdnm+yROfE0A, Hiroshi Doyu
T124 has some new register bits in {TLB,PTC}_CONFIG:
- TLB_RR_ARB and PTC_REQ_LIMIT
- TLB_ACTIVE_LINES 0x20 instead of 0x10
They are defined as platform data now.
Signed-off-by: Hiroshi Doyu <hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/iommu/tegra-smmu.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 04e7199..9b81e3a 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -71,12 +71,13 @@ enum {
#define SMMU_CACHE_CONFIG_STATS_TEST (1 << SMMU_CACHE_CONFIG_STATS_TEST_SHIFT)
#define SMMU_TLB_CONFIG_HIT_UNDER_MISS__ENABLE (1 << 29)
-#define SMMU_TLB_CONFIG_ACTIVE_LINES__VALUE 0x10
-#define SMMU_TLB_CONFIG_RESET_VAL 0x20000010
+#define SMMU_TLB_CONFIG_RESET_VAL 0x20000000
+#define SMMU_TLB_RR_ARB (1 << 28)
#define SMMU_PTC_CONFIG_CACHE__ENABLE (1 << 29)
#define SMMU_PTC_CONFIG_INDEX_MAP__PATTERN 0x3f
#define SMMU_PTC_CONFIG_RESET_VAL 0x2000003f
+#define SMMU_PTC_REQ_LIMIT (8 << 24)
#define SMMU_PTB_ASID 0x1c
#define SMMU_PTB_ASID_CURRENT_SHIFT 0
@@ -239,6 +240,8 @@ struct smmu_device {
struct page *avp_vector_page; /* dummy page shared by all AS's */
int nr_xlats; /* number of translation_enable registers */
+ u32 tlb_reset; /* TLB config reset value */
+ u32 ptc_reset; /* PTC config reset value */
/*
* Register image savers for suspend/resume
@@ -260,6 +263,8 @@ struct smmu_device {
struct smmu_platform_data {
int asids; /* number of asids */
int nr_xlats; /* number of translation_enable registers */
+ u32 tlb_reset; /* TLB config reset value */
+ u32 ptc_reset; /* PTC config reset value */
};
static struct smmu_device *smmu_handle; /* unique for a system */
@@ -519,8 +524,8 @@ static int smmu_setup_regs(struct smmu_device *smmu)
SMMU_TRANSLATION_ENABLE_0 + i * sizeof(u32));
smmu_write(smmu, smmu->asid_security, SMMU_ASID_SECURITY);
- smmu_write(smmu, SMMU_TLB_CONFIG_RESET_VAL, SMMU_CACHE_CONFIG(_TLB));
- smmu_write(smmu, SMMU_PTC_CONFIG_RESET_VAL, SMMU_CACHE_CONFIG(_PTC));
+ smmu_write(smmu, smmu->ptc_reset, SMMU_CACHE_CONFIG(_PTC));
+ smmu_write(smmu, smmu->tlb_reset, SMMU_CACHE_CONFIG(_TLB));
smmu_flush_regs(smmu, 1);
@@ -1271,6 +1276,8 @@ static void tegra_smmu_create_default_map(struct smmu_device *smmu)
static const struct smmu_platform_data tegra124_smmu_pdata = {
.asids = 128,
.nr_xlats = 4,
+ .tlb_reset = SMMU_TLB_CONFIG_RESET_VAL | SMMU_TLB_RR_ARB | 0x20,
+ .ptc_reset = SMMU_PTC_CONFIG_RESET_VAL | SMMU_PTC_REQ_LIMIT,
};
static struct of_device_id tegra_smmu_of_match[] = {
@@ -1320,6 +1327,10 @@ static int tegra_smmu_probe(struct platform_device *pdev)
smmu->map = (struct dma_iommu_mapping **)(smmu->as + asids);
smmu->xlat = (u32 *)(smmu->map + smmu->num_as);
smmu->nregs = pdev->num_resources;
+ smmu->tlb_reset = (pdata && pdata->tlb_reset) ? pdata->tlb_reset :
+ (SMMU_TLB_CONFIG_RESET_VAL | 0x10);
+ smmu->ptc_reset = (pdata && pdata->ptc_reset) ? pdata->ptc_reset :
+ (SMMU_PTC_CONFIG_RESET_VAL | SMMU_PTC_REQ_LIMIT);
smmu->regs = devm_kzalloc(dev, 2 * smmu->nregs * sizeof(*smmu->regs),
GFP_KERNEL);
smmu->rege = smmu->regs + smmu->nregs;
--
1.8.1.5
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 6/6] iommu/tegra124: smmu: adjust TLB_FLUSH_ASID bit range
[not found] ` <1386246319-17851-1-git-send-email-hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (4 preceding siblings ...)
2013-12-05 12:25 ` [PATCH 5/6] iommu/tegra124: smmu: {TLB,PTC} reset value per SoC Hiroshi Doyu
@ 2013-12-05 12:25 ` Hiroshi Doyu
2013-12-09 7:16 ` [PATCH 7/6] iommu/tegra124: smmu: add multiple asid_security support Hiroshi Doyu
6 siblings, 0 replies; 14+ messages in thread
From: Hiroshi Doyu @ 2013-12-05 12:25 UTC (permalink / raw)
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
Cc: joro-zLv9SwRftAIdnm+yROfE0A, Hiroshi Doyu, Terje Bergstrom
TLB_FLUSH_ASID bit range depends on the number of asids to support
other number than the current 4, especially for a new Tegra124. Based
on Terje's internal patch.
Signed-off-by: Hiroshi Doyu <hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Cc: Terje Bergstrom <tbergstrom-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/iommu/tegra-smmu.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 9b81e3a..535b14a 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -92,11 +92,14 @@ enum {
#define SMMU_TLB_FLUSH_VA_MATCH_ALL 0
#define SMMU_TLB_FLUSH_VA_MATCH_SECTION 2
#define SMMU_TLB_FLUSH_VA_MATCH_GROUP 3
-#define SMMU_TLB_FLUSH_ASID_SHIFT 29
+#define SMMU_TLB_FLUSH_ASID_SHIFT_BASE 31
#define SMMU_TLB_FLUSH_ASID_MATCH_DISABLE 0
#define SMMU_TLB_FLUSH_ASID_MATCH_ENABLE 1
#define SMMU_TLB_FLUSH_ASID_MATCH_SHIFT 31
+#define SMMU_TLB_FLUSH_ASID_SHIFT(as) \
+ (SMMU_TLB_FLUSH_ASID_SHIFT_BASE - __ffs((as)->smmu->num_as))
+
#define SMMU_PTC_FLUSH 0x34
#define SMMU_PTC_FLUSH_TYPE_ALL 0
#define SMMU_PTC_FLUSH_TYPE_ADR 1
@@ -563,7 +566,7 @@ static void flush_ptc_and_tlb(struct smmu_device *smmu,
val = tlb_flush_va |
SMMU_TLB_FLUSH_ASID_MATCH__ENABLE |
- (as->asid << SMMU_TLB_FLUSH_ASID_SHIFT);
+ (as->asid << SMMU_TLB_FLUSH_ASID_SHIFT(as));
smmu_write(smmu, val, SMMU_TLB_FLUSH);
FLUSH_SMMU_REGS(smmu);
}
@@ -730,7 +733,7 @@ static int alloc_pdir(struct smmu_as *as)
val = SMMU_TLB_FLUSH_VA_MATCH_ALL |
SMMU_TLB_FLUSH_ASID_MATCH__ENABLE |
- (as->asid << SMMU_TLB_FLUSH_ASID_SHIFT);
+ (as->asid << SMMU_TLB_FLUSH_ASID_SHIFT(as));
smmu_write(smmu, val, SMMU_TLB_FLUSH);
FLUSH_SMMU_REGS(as->smmu);
--
1.8.1.5
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 7/6] iommu/tegra124: smmu: add multiple asid_security support
[not found] ` <1386246319-17851-1-git-send-email-hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (5 preceding siblings ...)
2013-12-05 12:25 ` [PATCH 6/6] iommu/tegra124: smmu: adjust TLB_FLUSH_ASID bit range Hiroshi Doyu
@ 2013-12-09 7:16 ` Hiroshi Doyu
6 siblings, 0 replies; 14+ messages in thread
From: Hiroshi Doyu @ 2013-12-09 7:16 UTC (permalink / raw)
To: hdoyu-DDmLM1+adcrQT0dZR+AlfA,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
Cc: joro-zLv9SwRftAIdnm+yROfE0A
In Tegra124 the number of MC_SMMU_ASID_SECURITY_# registers
increased. Now this info is provided as platfrom data. If no platfrom
data the default valude(1) is used.
Signed-off-by: Hiroshi Doyu <hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Sending now as [PATCH 7/6] because this was missed from the thread.
---
drivers/iommu/tegra-smmu.c | 39 +++++++++++++++++++++++++++++++++------
1 file changed, 33 insertions(+), 6 deletions(-)
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 535b14a..5524773 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -108,6 +108,13 @@ enum {
#define SMMU_PTC_FLUSH_1 0x9b8
#define SMMU_ASID_SECURITY 0x38
+#define SMMU_ASID_SECURITY_1 0x3c
+#define SMMU_ASID_SECURITY_2 0x9e0
+#define SMMU_ASID_SECURITY_3 0x9e4
+#define SMMU_ASID_SECURITY_4 0x9e8
+#define SMMU_ASID_SECURITY_5 0x9ec
+#define SMMU_ASID_SECURITY_6 0x9f0
+#define SMMU_ASID_SECURITY_7 0x9f4
#define SMMU_STATS_CACHE_COUNT_BASE 0x1f0
@@ -243,6 +250,7 @@ struct smmu_device {
struct page *avp_vector_page; /* dummy page shared by all AS's */
int nr_xlats; /* number of translation_enable registers */
+ int nr_asid_secs; /* number of asid_security registers */
u32 tlb_reset; /* TLB config reset value */
u32 ptc_reset; /* PTC config reset value */
@@ -250,7 +258,7 @@ struct smmu_device {
* Register image savers for suspend/resume
*/
u32 *xlat;
- unsigned long asid_security;
+ u32 *asid_sec;
struct dentry *debugfs_root;
struct smmu_debugfs_info *debugfs_info;
@@ -266,6 +274,7 @@ struct smmu_device {
struct smmu_platform_data {
int asids; /* number of asids */
int nr_xlats; /* number of translation_enable registers */
+ int nr_asid_secs; /* number of asid_security registers */
u32 tlb_reset; /* TLB config reset value */
u32 ptc_reset; /* PTC config reset value */
};
@@ -328,6 +337,17 @@ static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs)
*/
#define FLUSH_SMMU_REGS(smmu) smmu_read(smmu, SMMU_CONFIG)
+static const u32 smmu_asid_sec_ofs[] = {
+ SMMU_ASID_SECURITY,
+ SMMU_ASID_SECURITY_1,
+ SMMU_ASID_SECURITY_2,
+ SMMU_ASID_SECURITY_3,
+ SMMU_ASID_SECURITY_4,
+ SMMU_ASID_SECURITY_5,
+ SMMU_ASID_SECURITY_6,
+ SMMU_ASID_SECURITY_7,
+};
+
static size_t smmu_get_asid_offset(int id)
{
switch (id) {
@@ -526,7 +546,9 @@ static int smmu_setup_regs(struct smmu_device *smmu)
smmu_write(smmu, smmu->xlat[i],
SMMU_TRANSLATION_ENABLE_0 + i * sizeof(u32));
- smmu_write(smmu, smmu->asid_security, SMMU_ASID_SECURITY);
+ for (i = 0; i < smmu->nr_asid_secs; i++)
+ smmu_write(smmu, smmu->asid_sec[i], smmu_asid_sec_ofs[i]);
+
smmu_write(smmu, smmu->ptc_reset, SMMU_CACHE_CONFIG(_PTC));
smmu_write(smmu, smmu->tlb_reset, SMMU_CACHE_CONFIG(_TLB));
@@ -1243,7 +1265,9 @@ static int tegra_smmu_suspend(struct device *dev)
smmu->xlat[i] = smmu_read(smmu,
SMMU_TRANSLATION_ENABLE_0 + i * sizeof(u32));
- smmu->asid_security = smmu_read(smmu, SMMU_ASID_SECURITY);
+ for (i = 0; i < smmu->nr_asid_secs; i++)
+ smmu->asid_sec[i] =
+ smmu_read(smmu, smmu_asid_sec_ofs[i]);
return 0;
}
@@ -1279,6 +1303,7 @@ static void tegra_smmu_create_default_map(struct smmu_device *smmu)
static const struct smmu_platform_data tegra124_smmu_pdata = {
.asids = 128,
.nr_xlats = 4,
+ .nr_asid_secs = 8,
.tlb_reset = SMMU_TLB_CONFIG_RESET_VAL | SMMU_TLB_RR_ARB | 0x20,
.ptc_reset = SMMU_PTC_CONFIG_RESET_VAL | SMMU_PTC_REQ_LIMIT,
};
@@ -1299,7 +1324,7 @@ static int tegra_smmu_probe(struct platform_device *pdev)
size_t bytes, uninitialized_var(size);
const struct of_device_id *match;
const struct smmu_platform_data *pdata;
- int nr_xlats;
+ int nr_xlats, nr_asid_secs;
if (smmu_handle)
return -EIO;
@@ -1311,6 +1336,7 @@ static int tegra_smmu_probe(struct platform_device *pdev)
return -EINVAL;
pdata = match->data;
nr_xlats = (pdata && pdata->nr_xlats) ? pdata->nr_xlats : 3;
+ nr_asid_secs = (pdata && pdata->nr_asid_secs) ? pdata->nr_asid_secs : 1;
if (of_property_read_u32(dev->of_node, "nvidia,#asids", &asids))
asids = (pdata && pdata->asids) ? pdata->asids : 4;
@@ -1319,7 +1345,7 @@ static int tegra_smmu_probe(struct platform_device *pdev)
bytes = sizeof(*smmu) + asids * (sizeof(*smmu->as) +
sizeof(struct dma_iommu_mapping *));
- bytes += sizeof(u32) * nr_xlats;
+ bytes += sizeof(u32) * (nr_asid_secs + nr_xlats);
smmu = devm_kzalloc(dev, bytes, GFP_KERNEL);
if (!smmu) {
dev_err(dev, "failed to allocate smmu_device\n");
@@ -1329,6 +1355,7 @@ static int tegra_smmu_probe(struct platform_device *pdev)
smmu->clients = RB_ROOT;
smmu->map = (struct dma_iommu_mapping **)(smmu->as + asids);
smmu->xlat = (u32 *)(smmu->map + smmu->num_as);
+ smmu->asid_sec = smmu->xlat + smmu->nr_xlats;
smmu->nregs = pdev->num_resources;
smmu->tlb_reset = (pdata && pdata->tlb_reset) ? pdata->tlb_reset :
(SMMU_TLB_CONFIG_RESET_VAL | 0x10);
@@ -1368,7 +1395,7 @@ static int tegra_smmu_probe(struct platform_device *pdev)
smmu->nr_xlats = nr_xlats;
smmu->iovmm_base = base;
smmu->page_count = size;
- smmu->asid_security = 0;
+ smmu->nr_asid_secs = nr_asid_secs;
for (i = 0; i < smmu->nr_xlats; i++)
smmu->xlat[i] = ~0;
--
1.8.1.5
^ permalink raw reply related [flat|nested] 14+ messages in thread