linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] PAMU driver update
@ 2016-03-07 15:34 Codrin Ciubotariu
  2016-03-07 15:34 ` [PATCH 1/7] iommu/fsl: Fix most checkpatch warnings and typos Codrin Ciubotariu
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Codrin Ciubotariu @ 2016-03-07 15:34 UTC (permalink / raw)
  To: iommu; +Cc: scottwood, Varun.Sethi, linuxppc-dev, Codrin Ciubotariu

This patchset addresses a few issues found on PAMU IOMMU
and small changes to enable power management and to support the
L3 cache controller on some newer boards.

The series starts with a clean-up patch, followed by two
errata fixes: A-007907 and A-005982. It continues with
two fixes for PCIe support. The last two patches add support
for power management and compatible strings for new L3 controller
device-tree nodes.

Codrin Ciubotariu (2):
  iommu/fsl: Fix most checkpatch warnings and typos
  iommu/fsl: Work around erratum A-007907

Varun Sethi (5):
  iommu/fsl: Enable OMT cache, before invalidating PAACT and SPAACT
    cache
  iommu/fsl: Factor out PCI specific code
  iommu/fsl: Enable default DMA window for PCIe devices once detached
    from domain
  iommu/fsl: PAMU power management support
  iommu/fsl: Added cache controller compatible strings for SOCs

 drivers/iommu/fsl_pamu.c        | 322 ++++++++++++++++++++++++++++++++--------
 drivers/iommu/fsl_pamu.h        |  30 ++--
 drivers/iommu/fsl_pamu_domain.c | 160 +++++++++++++-------
 drivers/iommu/fsl_pamu_domain.h |   2 +-
 4 files changed, 381 insertions(+), 133 deletions(-)

-- 
1.9.3

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/7] iommu/fsl: Fix most checkpatch warnings and typos
  2016-03-07 15:34 [PATCH 0/7] PAMU driver update Codrin Ciubotariu
@ 2016-03-07 15:34 ` Codrin Ciubotariu
  2016-03-07 15:34 ` [PATCH 2/7] iommu/fsl: Work around erratum A-007907 Codrin Ciubotariu
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Codrin Ciubotariu @ 2016-03-07 15:34 UTC (permalink / raw)
  To: iommu; +Cc: scottwood, Varun.Sethi, linuxppc-dev, Codrin Ciubotariu

Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@nxp.com>
---
 drivers/iommu/fsl_pamu.c        | 92 +++++++++++++++++++++++++++++------------
 drivers/iommu/fsl_pamu.h        | 29 +++++++------
 drivers/iommu/fsl_pamu_domain.c | 41 +++++++++++-------
 drivers/iommu/fsl_pamu_domain.h |  2 +-
 4 files changed, 109 insertions(+), 55 deletions(-)

diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index a34355f..c64cdef 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -128,6 +128,10 @@ int pamu_enable_liodn(int liodn)
 	mb();
 
 	set_bf(ppaace->addr_bitfields, PAACE_AF_V, PAACE_V_VALID);
+	/*
+	 * Ensure that I/O devices use the new PAACE entry
+	 * right after this function returns
+	 */
 	mb();
 
 	return 0;
@@ -150,6 +154,10 @@ int pamu_disable_liodn(int liodn)
 	}
 
 	set_bf(ppaace->addr_bitfields, PAACE_AF_V, PAACE_V_INVALID);
+	/*
+	 * Ensure that I/O devices no longer use this PAACE entry
+	 * right after this function returns
+	 */
 	mb();
 
 	return 0;
@@ -226,16 +234,17 @@ static struct paace *pamu_get_spaace(struct paace *paace, u32 wnum)
  * function returns the index of the first SPAACE entry. The remaining
  * SPAACE entries are reserved contiguously from that index.
  *
- * Returns a valid fspi index in the range of 0 - SPAACE_NUMBER_ENTRIES on success.
- * If no SPAACE entry is available or the allocator can not reserve the required
- * number of contiguous entries function returns ULONG_MAX indicating a failure.
- *
+ * Returns a valid fspi index in the range of 0 - SPAACE_NUMBER_ENTRIES on
+ * success. If no SPAACE entry is available or the allocator can not reserve
+ * the required number of contiguous entries function returns ULONG_MAX
+ * indicating a failure.
  */
 static unsigned long pamu_get_fspi_and_allocate(u32 subwin_cnt)
 {
 	unsigned long spaace_addr;
 
-	spaace_addr = gen_pool_alloc(spaace_pool, subwin_cnt * sizeof(struct paace));
+	spaace_addr = gen_pool_alloc(spaace_pool, subwin_cnt *
+						  sizeof(struct paace));
 	if (!spaace_addr)
 		return ULONG_MAX;
 
@@ -257,16 +266,17 @@ void pamu_free_subwins(int liodn)
 	if (get_bf(ppaace->addr_bitfields, PPAACE_AF_MW)) {
 		subwin_cnt = 1UL << (get_bf(ppaace->impl_attr, PAACE_IA_WCE) + 1);
 		size = (subwin_cnt - 1) * sizeof(struct paace);
-		gen_pool_free(spaace_pool, (unsigned long)&spaact[ppaace->fspi], size);
+		gen_pool_free(spaace_pool,
+			      (unsigned long)&spaact[ppaace->fspi], size);
 		set_bf(ppaace->addr_bitfields, PPAACE_AF_MW, 0);
 	}
 }
 
 /*
- * Function used for updating stash destination for the coressponding
+ * Function used for updating stash destination for the corresponding
  * LIODN.
  */
-int  pamu_update_paace_stash(int liodn, u32 subwin, u32 value)
+int pamu_update_paace_stash(int liodn, u32 subwin, u32 value)
 {
 	struct paace *paace;
 
@@ -282,6 +292,10 @@ int  pamu_update_paace_stash(int liodn, u32 subwin, u32 value)
 	}
 	set_bf(paace->impl_attr, PAACE_IA_CID, value);
 
+	/*
+	 * Ensure that I/O devices see the new stash id
+	 * just after this function returns
+	 */
 	mb();
 
 	return 0;
@@ -307,6 +321,10 @@ int pamu_disable_spaace(int liodn, u32 subwin)
 		       PAACE_AP_PERMS_DENIED);
 	}
 
+	/*
+	 * Ensure that I/O devices no longer use this PAACE entry
+	 * right after this function returns
+	 */
 	mb();
 
 	return 0;
@@ -399,6 +417,10 @@ int pamu_config_ppaace(int liodn, phys_addr_t win_addr, phys_addr_t win_size,
 		set_bf(ppaace->impl_attr, PAACE_IA_WCE, 0);
 		set_bf(ppaace->addr_bitfields, PPAACE_AF_MW, 0);
 	}
+	/*
+	 * Ensure that I/O devices see the updated PPAACE entry
+	 * right after this function returns
+	 */
 	mb();
 
 	return 0;
@@ -483,11 +505,16 @@ int pamu_config_spaace(int liodn, u32 subwin_cnt, u32 subwin,
 	if (~stashid != 0)
 		set_bf(paace->impl_attr, PAACE_IA_CID, stashid);
 
+	/* Ensure that this SPAACE entry updates before we enable it */
 	smp_wmb();
 
 	if (enable)
 		set_bf(paace->addr_bitfields, PAACE_AF_V, PAACE_V_VALID);
 
+	/*
+	 * Ensure that I/O devices use this PAACE entry
+	 * right after this function returns
+	 */
 	mb();
 
 	return 0;
@@ -553,7 +580,8 @@ u32 get_stash_id(u32 stash_dest_hint, u32 vcpu)
 found_cpu_node:
 
 	/* find the hwnode that represents the cache */
-	for (cache_level = PAMU_ATTR_CACHE_L1; (cache_level < PAMU_ATTR_CACHE_L3) && found; cache_level++) {
+	for (cache_level = PAMU_ATTR_CACHE_L1;
+	     (cache_level < PAMU_ATTR_CACHE_L3) && found; cache_level++) {
 		if (stash_dest_hint == cache_level) {
 			prop = of_get_property(node, "cache-stash-id", NULL);
 			if (!prop) {
@@ -598,26 +626,28 @@ found_cpu_node:
  * Memory accesses to QMAN and BMAN private memory need not be coherent, so
  * clear the PAACE entry coherency attribute for them.
  */
-static void setup_qbman_paace(struct paace *ppaace, int  paace_type)
+static void setup_qbman_paace(struct paace *ppaace, int paace_type)
 {
 	switch (paace_type) {
 	case QMAN_PAACE:
 		set_bf(ppaace->impl_attr, PAACE_IA_OTM, PAACE_OTM_INDEXED);
 		ppaace->op_encode.index_ot.omi = OMI_QMAN_PRIV;
 		/* setup QMAN Private data stashing for the L3 cache */
-		set_bf(ppaace->impl_attr, PAACE_IA_CID, get_stash_id(PAMU_ATTR_CACHE_L3, 0));
-		set_bf(ppaace->domain_attr.to_host.coherency_required, PAACE_DA_HOST_CR,
-		       0);
+		set_bf(ppaace->impl_attr, PAACE_IA_CID,
+		       get_stash_id(PAMU_ATTR_CACHE_L3, 0));
+		set_bf(ppaace->domain_attr.to_host.coherency_required,
+		       PAACE_DA_HOST_CR, 0);
 		break;
 	case QMAN_PORTAL_PAACE:
 		set_bf(ppaace->impl_attr, PAACE_IA_OTM, PAACE_OTM_INDEXED);
 		ppaace->op_encode.index_ot.omi = OMI_QMAN;
 		/* Set DQRR and Frame stashing for the L3 cache */
-		set_bf(ppaace->impl_attr, PAACE_IA_CID, get_stash_id(PAMU_ATTR_CACHE_L3, 0));
+		set_bf(ppaace->impl_attr, PAACE_IA_CID,
+		       get_stash_id(PAMU_ATTR_CACHE_L3, 0));
 		break;
 	case BMAN_PAACE:
-		set_bf(ppaace->domain_attr.to_host.coherency_required, PAACE_DA_HOST_CR,
-		       0);
+		set_bf(ppaace->domain_attr.to_host.coherency_required,
+		       PAACE_DA_HOST_CR, 0);
 		break;
 	}
 }
@@ -675,7 +705,8 @@ static void get_pamu_cap_values(unsigned long pamu_reg_base)
 }
 
 /* Setup PAMU registers pointing to PAACT, SPAACT and OMT */
-static int setup_one_pamu(unsigned long pamu_reg_base, unsigned long pamu_reg_size,
+static int setup_one_pamu(unsigned long pamu_reg_base,
+			  unsigned long pamu_reg_size,
 			  phys_addr_t ppaact_phys, phys_addr_t spaact_phys,
 			  phys_addr_t omt_phys)
 {
@@ -752,6 +783,10 @@ static void setup_liodns(void)
 				setup_qbman_paace(ppaace, QMAN_PAACE);
 			if (of_device_is_compatible(node, "fsl,bman"))
 				setup_qbman_paace(ppaace, BMAN_PAACE);
+			/*
+			 * Ensure that the PAACE entry is updated before
+			 * enabling it
+			 */
 			mb();
 			pamu_enable_liodn(liodn);
 		}
@@ -814,7 +849,8 @@ static irqreturn_t pamu_av_isr(int irq, void *arg)
 				pics &= ~PAMU_ACCESS_VIOLATION_ENABLE;
 			} else {
 				/* Disable the LIODN */
-				ret = pamu_disable_liodn(avs1 >> PAMU_AVS1_LIODN_SHIFT);
+				ret = pamu_disable_liodn(avs1 >>
+							 PAMU_AVS1_LIODN_SHIFT);
 				BUG_ON(ret);
 				pr_emerg("Disabling liodn %x\n",
 					 avs1 >> PAMU_AVS1_LIODN_SHIFT);
@@ -957,9 +993,11 @@ static int create_csd(phys_addr_t phys, size_t size, u32 csd_port_id)
 
 	law[i].lawbarh = upper_32_bits(phys);
 	law[i].lawbarl = lower_32_bits(phys);
+	/* Ensure LAW entry is updated before enabling it */
 	wmb();
 	law[i].lawar = LAWAR_EN | law_target | (csd_id << LAWAR_CSDID_SHIFT) |
 		(LAW_SIZE_4K + get_order(size));
+	/* Ensure LAW entry is enabled before moving on */
 	wmb();
 
 error:
@@ -979,10 +1017,10 @@ error:
  * Table of SVRs and the corresponding PORT_ID values. Port ID corresponds to a
  * bit map of snoopers for a given range of memory mapped by a LAW.
  *
- * All future CoreNet-enabled SOCs will have this erratum(A-004510) fixed, so this
- * table should never need to be updated.  SVRs are guaranteed to be unique, so
- * there is no worry that a future SOC will inadvertently have one of these
- * values.
+ * All future CoreNet-enabled SOCs will have this erratum(A-004510) fixed,
+ * so this table should never need to be updated. SVRs are guaranteed to be
+ * unique, so there is no worry that a future SOC will inadvertently have one
+ * of these values.
  */
 static const struct {
 	u32 svr;
@@ -1081,7 +1119,7 @@ static int fsl_pamu_probe(struct platform_device *pdev)
 	get_pamu_cap_values((unsigned long)pamu_regs);
 	/*
 	 * To simplify the allocation of a coherency domain, we allocate the
-	 * PAACT and the OMT in the same memory buffer.  Unfortunately, this
+	 * PAACT and the OMT in the same memory buffer. Unfortunately, this
 	 * wastes more memory compared to allocating the buffers separately.
 	 */
 	/* Determine how much memory we need */
@@ -1215,7 +1253,7 @@ static __init int fsl_pamu_init(void)
 
 	/*
 	 * The normal OF process calls the probe function at some
-	 * indeterminate later time, after most drivers have loaded.  This is
+	 * indeterminate later time, after most drivers have loaded. This is
 	 * too late for us, because PAMU clients (like the Qman driver)
 	 * depend on PAMU being initialized early.
 	 *
@@ -1224,11 +1262,11 @@ static __init int fsl_pamu_init(void)
 	 */
 
 	/*
-	 * We assume that there is only one PAMU node in the device tree.  A
+	 * We assume that there is only one PAMU node in the device tree. A
 	 * single PAMU node represents all of the PAMU devices in the SOC
-	 * already.   Everything else already makes that assumption, and the
+	 * already. Everything else already makes that assumption, and the
 	 * binding for the PAMU nodes doesn't allow for any parent-child
-	 * relationships anyway.  In other words, support for more than one
+	 * relationships anyway. In other words, support for more than one
 	 * PAMU node would require significant changes to a lot of code.
 	 */
 
diff --git a/drivers/iommu/fsl_pamu.h b/drivers/iommu/fsl_pamu.h
index aab723f..bebc2e3 100644
--- a/drivers/iommu/fsl_pamu.h
+++ b/drivers/iommu/fsl_pamu.h
@@ -66,8 +66,9 @@ struct pamu_mmap_regs {
 #define PAMU_AVS1_LAV   0x1c00
 #define PAMU_AVS1_GCV   0x2000
 #define PAMU_AVS1_PDV   0x4000
-#define PAMU_AV_MASK    (PAMU_AVS1_AV | PAMU_AVS1_OTV | PAMU_AVS1_APV | PAMU_AVS1_WAV \
-			 | PAMU_AVS1_LAV | PAMU_AVS1_GCV | PAMU_AVS1_PDV)
+#define PAMU_AV_MASK    (PAMU_AVS1_AV | PAMU_AVS1_OTV | PAMU_AVS1_APV | \
+			 PAMU_AVS1_WAV | PAMU_AVS1_LAV | PAMU_AVS1_GCV | \
+			 PAMU_AVS1_PDV)
 #define PAMU_AVS1_LIODN_SHIFT 16
 #define PAMU_LAV_LIODN_NOT_IN_PPAACT 0x400
 
@@ -270,7 +271,7 @@ struct pamu_mmap_regs {
 /* primary / secondary paact structure */
 struct paace {
 	/* PAACE Offset 0x00 */
-	u32 wbah;				/* only valid for Primary PAACE */
+	u32 wbah;			/* only valid for Primary PAACE */
 	u32 addr_bitfields;		/* See P/S PAACE_AF_* */
 
 	/* PAACE Offset 0x08 */
@@ -294,7 +295,10 @@ struct paace {
 		} to_io;
 	} domain_attr;
 
-	/* Implementation attributes + window count + address & operation translation modes */
+	/*
+	 * Implementation attributes + window count +
+	 * address & operation translation modes
+	 */
 	u32 impl_attr;			/* See PAACE_IA_* */
 
 	/* PAACE Offset 0x10 */
@@ -304,7 +308,7 @@ struct paace {
 
 	/* PAACE Offset 0x18 */
 	/* first secondary paace entry */
-	u32 fspi;				/* only valid for Primary PAACE */
+	u32 fspi;			/* only valid for Primary PAACE */
 	union {
 		struct {
 			u8 ioea;
@@ -324,11 +328,12 @@ struct paace {
 
 /* OME : Operation mapping entry
  * MOE : Mapped Operation Encodings
- * The operation mapping table is table containing operation mapping entries (OME).
- * The index of a particular OME is programmed in the PAACE entry for translation
- * in bound I/O operations corresponding to an LIODN. The OMT is used for translation
- * specifically in case of the indexed translation mode. Each OME contains a 128
- * byte mapped operation encoding (MOE), where each byte represents an MOE.
+ * The operation mapping table is table containing operation mapping entries
+ * (OME). The index of a particular OME is programmed in the PAACE entry for
+ * translation in bound I/O operations corresponding to an LIODN. The OMT is
+ * used for translation specifically in case of the indexed translation mode.
+ * Each OME contains a 128 byte mapped operation encoding (MOE), where each
+ * byte represents an MOE.
  */
 #define NUM_MOE 128
 struct ome {
@@ -396,8 +401,8 @@ int pamu_enable_liodn(int liodn);
 int pamu_disable_liodn(int liodn);
 void pamu_free_subwins(int liodn);
 int pamu_config_ppaace(int liodn, phys_addr_t win_addr, phys_addr_t win_size,
-		       u32 omi, unsigned long rpn, u32 snoopid, uint32_t stashid,
-		       u32 subwin_cnt, int prot);
+		       u32 omi, unsigned long rpn, u32 snoopid,
+		       uint32_t stashid, u32 subwin_cnt, int prot);
 int pamu_config_spaace(int liodn, u32 subwin_cnt, u32 subwin_addr,
 		       phys_addr_t subwin_size, u32 omi, unsigned long rpn,
 		       uint32_t snoopid, u32 stashid, int enable, int prot);
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index da0e1e3..869e55e 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -64,7 +64,8 @@ static int __init iommu_init_mempool(void)
 	return 0;
 }
 
-static phys_addr_t get_phys_addr(struct fsl_dma_domain *dma_domain, dma_addr_t iova)
+static phys_addr_t get_phys_addr(struct fsl_dma_domain *dma_domain,
+				 dma_addr_t iova)
 {
 	u32 win_cnt = dma_domain->win_cnt;
 	struct dma_window *win_ptr = &dma_domain->win_arr[0];
@@ -84,7 +85,8 @@ static phys_addr_t get_phys_addr(struct fsl_dma_domain *dma_domain, dma_addr_t i
 
 		subwin_size = dma_domain->geom_size >> ilog2(win_cnt);
 		subwin_iova = iova & ~(subwin_size - 1);
-		wnd = (subwin_iova - geom->aperture_start) >> ilog2(subwin_size);
+		wnd = (subwin_iova - geom->aperture_start) >>
+		      ilog2(subwin_size);
 		win_ptr = &dma_domain->win_arr[wnd];
 	}
 
@@ -155,7 +157,8 @@ static int map_liodn(int liodn, struct fsl_dma_domain *dma_domain)
 }
 
 /* Update window/subwindow mapping for the LIODN */
-static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr)
+static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain,
+			u32 wnd_nr)
 {
 	int ret;
 	struct dma_window *wnd = &dma_domain->win_arr[wnd_nr];
@@ -183,7 +186,8 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr
 					 wnd->size,
 					 ~(u32)0,
 					 wnd->paddr >> PAMU_PAGE_SHIFT,
-					 dma_domain->snoop_id, dma_domain->stash_id,
+					 dma_domain->snoop_id,
+					 dma_domain->stash_id,
 					 0, wnd->prot);
 		if (ret)
 			pr_debug("Window reconfiguration failed for liodn %d\n",
@@ -249,8 +253,8 @@ static int pamu_set_liodn(int liodn, struct device *dev,
 	spin_lock_irqsave(&iommu_lock, flags);
 	ret = pamu_disable_liodn(liodn);
 	if (!ret)
-		ret = pamu_config_ppaace(liodn, window_addr, window_size, omi_index,
-					 0, dma_domain->snoop_id,
+		ret = pamu_config_ppaace(liodn, window_addr, window_size,
+					 omi_index, 0, dma_domain->snoop_id,
 					 dma_domain->stash_id, win_cnt, 0);
 	spin_unlock_irqrestore(&iommu_lock, flags);
 	if (ret) {
@@ -267,7 +271,8 @@ static int pamu_set_liodn(int liodn, struct device *dev,
 			if (!ret)
 				ret = pamu_config_spaace(liodn, win_cnt, i,
 							 subwin_size, omi_index,
-							 0, dma_domain->snoop_id,
+							 0,
+							 dma_domain->snoop_id,
 							 dma_domain->stash_id,
 							 0, 0);
 			spin_unlock_irqrestore(&iommu_lock, flags);
@@ -352,7 +357,8 @@ static void detach_device(struct device *dev, struct fsl_dma_domain *dma_domain)
 	spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
 }
 
-static void attach_device(struct fsl_dma_domain *dma_domain, int liodn, struct device *dev)
+static void attach_device(struct fsl_dma_domain *dma_domain, int liodn,
+				 struct device *dev)
 {
 	struct device_domain_info *info, *old_domain_info;
 	unsigned long flags;
@@ -632,7 +638,8 @@ static int handle_attach_device(struct fsl_dma_domain *dma_domain,
 		 * the LIODN.
 		 */
 		if (dma_domain->win_arr) {
-			u32 win_cnt = dma_domain->win_cnt > 1 ? dma_domain->win_cnt : 0;
+			u32 win_cnt = dma_domain->win_cnt > 1 ?
+				      dma_domain->win_cnt : 0;
 
 			ret = pamu_set_liodn(liodn[i], dev, dma_domain,
 					     &domain->geometry, win_cnt);
@@ -724,7 +731,7 @@ static void fsl_pamu_detach_device(struct iommu_domain *domain,
 			 dev->of_node->full_name);
 }
 
-static  int configure_domain_geometry(struct iommu_domain *domain, void *data)
+static int configure_domain_geometry(struct iommu_domain *domain, void *data)
 {
 	struct iommu_domain_geometry *geom_attr = data;
 	struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
@@ -746,7 +753,7 @@ static  int configure_domain_geometry(struct iommu_domain *domain, void *data)
 	if (dma_domain->enabled) {
 		pr_debug("Can't set geometry attributes as domain is active\n");
 		spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
-		return  -EBUSY;
+		return -EBUSY;
 	}
 
 	/* Copy the domain geometry information */
@@ -787,7 +794,8 @@ static int configure_domain_stash(struct fsl_dma_domain *dma_domain, void *data)
 }
 
 /* Configure domain dma state i.e. enable/disable DMA */
-static int configure_domain_dma_state(struct fsl_dma_domain *dma_domain, bool enable)
+static int configure_domain_dma_state(struct fsl_dma_domain *dma_domain,
+				      bool enable)
 {
 	struct device_domain_info *info;
 	unsigned long flags;
@@ -934,7 +942,7 @@ static struct iommu_group *get_pci_device_group(struct pci_dev *pdev)
 	} else {
 		/*
 		 * All devices connected to the controller will share the
-		 * PCI controllers device group. If this is the first
+		 * PCI controller's device group. If this is the first
 		 * device to be probed for the pci controller, copy the
 		 * device group information from the PCI controller device
 		 * node and remove the PCI controller iommu group.
@@ -998,11 +1006,14 @@ static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count)
 	int ret;
 
 	spin_lock_irqsave(&dma_domain->domain_lock, flags);
-	/* Ensure domain is inactive i.e. DMA should be disabled for the domain */
+	/*
+	 * Ensure domain is inactive i.e.
+	 * DMA should be disabled for the domain
+	 */
 	if (dma_domain->enabled) {
 		pr_debug("Can't set geometry attributes as domain is active\n");
 		spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
-		return  -EBUSY;
+		return -EBUSY;
 	}
 
 	/* Ensure that the geometry has been set for the domain */
diff --git a/drivers/iommu/fsl_pamu_domain.h b/drivers/iommu/fsl_pamu_domain.h
index f2b0f74..d5afbe4 100644
--- a/drivers/iommu/fsl_pamu_domain.h
+++ b/drivers/iommu/fsl_pamu_domain.h
@@ -36,7 +36,7 @@ struct fsl_dma_domain {
 	 */
 	dma_addr_t			geom_size;
 	/*
-	 * Number of windows assocaited with this domain.
+	 * Number of windows associated with this domain.
 	 * During domain initialization, it is set to the
 	 * the maximum number of subwindows allowed for a LIODN.
 	 * Minimum value for this is 1 indicating a single PAMU
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/7] iommu/fsl: Work around erratum A-007907
  2016-03-07 15:34 [PATCH 0/7] PAMU driver update Codrin Ciubotariu
  2016-03-07 15:34 ` [PATCH 1/7] iommu/fsl: Fix most checkpatch warnings and typos Codrin Ciubotariu
@ 2016-03-07 15:34 ` Codrin Ciubotariu
  2016-03-07 15:34 ` [PATCH 3/7] iommu/fsl: Enable OMT cache, before invalidating PAACT and SPAACT cache Codrin Ciubotariu
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Codrin Ciubotariu @ 2016-03-07 15:34 UTC (permalink / raw)
  To: iommu
  Cc: scottwood, Varun.Sethi, linuxppc-dev, Codrin Ciubotariu, Shengzhou Liu

Erratum A-007907 can cause a core hang under certain circumstances.
Part of the workaround involves not stashing to L1 Cache.  On affected
chips, stash to L2 when L1 is requested.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com>
Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@nxp.com>
---
 drivers/iommu/fsl_pamu.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index c64cdef..a00c473 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -25,6 +25,7 @@
 #include <linux/genalloc.h>
 
 #include <asm/mpc85xx.h>
+#include <asm/reg.h>
 
 /* define indexes for each operation mapping scenario */
 #define OMI_QMAN        0x00
@@ -534,6 +535,16 @@ void get_ome_index(u32 *omi_index, struct device *dev)
 		*omi_index = OMI_QMAN_PRIV;
 }
 
+static bool has_erratum_a007907(void)
+{
+	u32 pvr = mfspr(SPRN_PVR);
+
+	if (PVR_VER(pvr) == PVR_VER_E6500 && PVR_REV(pvr) <= 0x20)
+		return true;
+
+	return false;
+}
+
 /**
  * get_stash_id - Returns stash destination id corresponding to a
  *                cache type and vcpu.
@@ -551,6 +562,9 @@ u32 get_stash_id(u32 stash_dest_hint, u32 vcpu)
 	int len, found = 0;
 	int i;
 
+	if (stash_dest_hint == PAMU_ATTR_CACHE_L1 && has_erratum_a007907())
+		stash_dest_hint = PAMU_ATTR_CACHE_L2;
+
 	/* Fastpath, exit early if L3/CPC cache is target for stashing */
 	if (stash_dest_hint == PAMU_ATTR_CACHE_L3) {
 		node = of_find_matching_node(NULL, l3_device_ids);
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/7] iommu/fsl: Enable OMT cache, before invalidating PAACT and SPAACT cache
  2016-03-07 15:34 [PATCH 0/7] PAMU driver update Codrin Ciubotariu
  2016-03-07 15:34 ` [PATCH 1/7] iommu/fsl: Fix most checkpatch warnings and typos Codrin Ciubotariu
  2016-03-07 15:34 ` [PATCH 2/7] iommu/fsl: Work around erratum A-007907 Codrin Ciubotariu
@ 2016-03-07 15:34 ` Codrin Ciubotariu
  2016-03-07 15:34 ` [PATCH 4/7] iommu/fsl: Factor out PCI specific code Codrin Ciubotariu
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Codrin Ciubotariu @ 2016-03-07 15:34 UTC (permalink / raw)
  To: iommu; +Cc: scottwood, Varun.Sethi, linuxppc-dev, Codrin Ciubotariu

From: Varun Sethi <Varun.Sethi@freescale.com>

Enable OMT cache, before invalidating PAACT and SPAACT cache. This
is a PAMU hardware errata work around.

Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com>
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@nxp.com>
---
 drivers/iommu/fsl_pamu.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index a00c473..ce25084 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -731,6 +731,16 @@ static int setup_one_pamu(unsigned long pamu_reg_base,
 	pamu_regs = (struct pamu_mmap_regs *)
 		(pamu_reg_base + PAMU_MMAP_REGS_BASE);
 
+	/*
+	 * As per PAMU errata A-005982, writing the PAACT and SPAACT
+	 * base address registers wouldn't invalidate the corresponding
+	 * caches if the OMT cache is disabled. The workaround is to
+	 * enable the OMT cache before setting the base registers.
+	 * This can be done without actually enabling PAMU.
+	 */
+
+	out_be32(pc, PAMU_PC_OCE);
+
 	/* set up pointers to corenet control blocks */
 
 	out_be32(&pamu_regs->ppbah, upper_32_bits(ppaact_phys));
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/7] iommu/fsl: Factor out PCI specific code
  2016-03-07 15:34 [PATCH 0/7] PAMU driver update Codrin Ciubotariu
                   ` (2 preceding siblings ...)
  2016-03-07 15:34 ` [PATCH 3/7] iommu/fsl: Enable OMT cache, before invalidating PAACT and SPAACT cache Codrin Ciubotariu
@ 2016-03-07 15:34 ` Codrin Ciubotariu
  2016-03-07 15:34 ` [PATCH 5/7] iommu/fsl: Enable default DMA window for PCIe devices once detached from domain Codrin Ciubotariu
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Codrin Ciubotariu @ 2016-03-07 15:34 UTC (permalink / raw)
  To: iommu; +Cc: scottwood, Varun.Sethi, linuxppc-dev, Codrin Ciubotariu

From: Varun Sethi <Varun.Sethi@freescale.com>

Factor out PCI specific code in the PAMU driver.

Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com>
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@nxp.com>
---
 drivers/iommu/fsl_pamu_domain.c | 77 ++++++++++++++++++++++-------------------
 1 file changed, 41 insertions(+), 36 deletions(-)

diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index 869e55e..37f95d3 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -661,21 +661,14 @@ static int handle_attach_device(struct fsl_dma_domain *dma_domain,
 	return ret;
 }
 
-static int fsl_pamu_attach_device(struct iommu_domain *domain,
-				  struct device *dev)
+static struct device *get_dma_device(struct device *dev)
 {
-	struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
-	const u32 *liodn;
-	u32 liodn_cnt;
-	int len, ret = 0;
-	struct pci_dev *pdev = NULL;
-	struct pci_controller *pci_ctl;
-
-	/*
-	 * Use LIODN of the PCI controller while attaching a
-	 * PCI device.
-	 */
+	struct device *dma_dev = dev;
+#ifdef CONFIG_PCI
 	if (dev_is_pci(dev)) {
+		struct pci_controller *pci_ctl;
+		struct pci_dev *pdev;
+
 		pdev = to_pci_dev(dev);
 		pci_ctl = pci_bus_to_host(pdev->bus);
 		/*
@@ -683,16 +676,30 @@ static int fsl_pamu_attach_device(struct iommu_domain *domain,
 		 * so we can get the LIODN programmed by
 		 * u-boot.
 		 */
-		dev = pci_ctl->parent;
+		dma_dev = pci_ctl->parent;
 	}
+#endif
+	return dma_dev;
+}
+
+static int fsl_pamu_attach_device(struct iommu_domain *domain,
+				  struct device *dev)
+{
+	struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
+	struct device *dma_dev;
+	const u32 *liodn;
+	u32 liodn_cnt;
+	int len, ret = 0;
+
+	dma_dev = get_dma_device(dev);
 
-	liodn = of_get_property(dev->of_node, "fsl,liodn", &len);
+	liodn = of_get_property(dma_dev->of_node, "fsl,liodn", &len);
 	if (liodn) {
 		liodn_cnt = len / sizeof(u32);
 		ret = handle_attach_device(dma_domain, dev, liodn, liodn_cnt);
 	} else {
 		pr_debug("missing fsl,liodn property at %s\n",
-			 dev->of_node->full_name);
+			 dma_dev->of_node->full_name);
 		ret = -EINVAL;
 	}
 
@@ -703,27 +710,13 @@ static void fsl_pamu_detach_device(struct iommu_domain *domain,
 				   struct device *dev)
 {
 	struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain);
+	struct device *dma_dev;
 	const u32 *prop;
 	int len;
-	struct pci_dev *pdev = NULL;
-	struct pci_controller *pci_ctl;
 
-	/*
-	 * Use LIODN of the PCI controller while detaching a
-	 * PCI device.
-	 */
-	if (dev_is_pci(dev)) {
-		pdev = to_pci_dev(dev);
-		pci_ctl = pci_bus_to_host(pdev->bus);
-		/*
-		 * make dev point to pci controller device
-		 * so we can get the LIODN programmed by
-		 * u-boot.
-		 */
-		dev = pci_ctl->parent;
-	}
+	dma_dev = get_dma_device(dev);
 
-	prop = of_get_property(dev->of_node, "fsl,liodn", &len);
+	prop = of_get_property(dma_dev->of_node, "fsl,liodn", &len);
 	if (prop)
 		detach_device(dev, dma_domain);
 	else
@@ -884,6 +877,7 @@ static struct iommu_group *get_device_iommu_group(struct device *dev)
 	return group;
 }
 
+#ifdef CONFIG_PCI
 static  bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl)
 {
 	u32 version;
@@ -927,6 +921,10 @@ static struct iommu_group *get_pci_device_group(struct pci_dev *pdev)
 	bool pci_endpt_partioning;
 	struct iommu_group *group = NULL;
 
+	/* Don't create device groups for virtual PCI bridges */
+	if (pdev->subordinate)
+		return NULL;
+
 	pci_ctl = pci_bus_to_host(pdev->bus);
 	pci_endpt_partioning = check_pci_ctl_endpt_part(pci_ctl);
 	/* We can partition PCIe devices so assign device group to the device */
@@ -963,6 +961,7 @@ static struct iommu_group *get_pci_device_group(struct pci_dev *pdev)
 
 	return group;
 }
+#endif
 
 static struct iommu_group *fsl_pamu_device_group(struct device *dev)
 {
@@ -973,10 +972,14 @@ static struct iommu_group *fsl_pamu_device_group(struct device *dev)
 	 * For platform devices we allocate a separate group for
 	 * each of the devices.
 	 */
-	if (dev_is_pci(dev))
+	if (!dev_is_pci(dev)) {
+		if (of_get_property(dev->of_node, "fsl, liodn", &len))
+			group = get_device_iommu_group(dev);
+#ifdef CONFIG_PCI
+	} else {
 		group = get_pci_device_group(to_pci_dev(dev));
-	else if (of_get_property(dev->of_node, "fsl,liodn", &len))
-		group = get_device_iommu_group(dev);
+#endif
+	}
 
 	return group;
 }
@@ -1085,7 +1088,9 @@ int __init pamu_domain_init(void)
 		return ret;
 
 	bus_set_iommu(&platform_bus_type, &fsl_pamu_ops);
+#ifdef CONFIG_PCI
 	bus_set_iommu(&pci_bus_type, &fsl_pamu_ops);
+#endif
 
 	return ret;
 }
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/7] iommu/fsl: Enable default DMA window for PCIe devices once detached from domain
  2016-03-07 15:34 [PATCH 0/7] PAMU driver update Codrin Ciubotariu
                   ` (3 preceding siblings ...)
  2016-03-07 15:34 ` [PATCH 4/7] iommu/fsl: Factor out PCI specific code Codrin Ciubotariu
@ 2016-03-07 15:34 ` Codrin Ciubotariu
  2016-03-07 15:34 ` [PATCH 6/7] iommu/fsl: PAMU power management support Codrin Ciubotariu
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Codrin Ciubotariu @ 2016-03-07 15:34 UTC (permalink / raw)
  To: iommu; +Cc: scottwood, Varun.Sethi, linuxppc-dev, Codrin Ciubotariu

From: Varun Sethi <Varun.Sethi@freescale.com>

Once the PCIe device assigned to a guest VM (via VFIO) gets detached
from the iommu domain (when guest terminates), its PAMU table entry
is disabled. So, this would prevent the device from being used once
it's assigned back to the host.

This patch allows for creation of a default DMA window corresponding
to the device and subsequently enabling the PAMU table entry. Before
we enable the entry, we ensure that the device's bus master capability
is disabled (device quiesced).

Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com>
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@nxp.com>
---
 drivers/iommu/fsl_pamu.c        | 45 ++++++++++++++++++++++++++++++++---------
 drivers/iommu/fsl_pamu.h        |  1 +
 drivers/iommu/fsl_pamu_domain.c | 42 +++++++++++++++++++++++++++++++++++---
 3 files changed, 76 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index ce25084..181759e 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -302,6 +302,40 @@ int pamu_update_paace_stash(int liodn, u32 subwin, u32 value)
 	return 0;
 }
 
+/* Default PPAACE settings for an LIODN */
+static void setup_default_ppaace(struct paace *ppaace)
+{
+	pamu_init_ppaace(ppaace);
+	/* window size is 2^(WSE+1) bytes */
+	set_bf(ppaace->addr_bitfields, PPAACE_AF_WSE, 35);
+	ppaace->wbah = 0;
+	set_bf(ppaace->addr_bitfields, PPAACE_AF_WBAL, 0);
+	set_bf(ppaace->impl_attr, PAACE_IA_ATM,
+		PAACE_ATM_NO_XLATE);
+	set_bf(ppaace->addr_bitfields, PAACE_AF_AP,
+		PAACE_AP_PERMS_ALL);
+}
+
+/* Reset the PAACE entry to the default state */
+void enable_default_dma_window(int liodn)
+{
+	struct paace *ppaace;
+
+	ppaace = pamu_get_ppaace(liodn);
+	if (!ppaace) {
+		pr_debug("Invalid liodn entry\n");
+		return;
+	}
+
+	memset(ppaace, 0, sizeof(struct paace));
+
+	setup_default_ppaace(ppaace);
+
+	/* Ensure that all other stores to the ppaace complete first */
+	mb();
+	pamu_enable_liodn(liodn);
+}
+
 /* Disable a subwindow corresponding to the LIODN */
 int pamu_disable_spaace(int liodn, u32 subwin)
 {
@@ -792,15 +826,8 @@ static void setup_liodns(void)
 				continue;
 			}
 			ppaace = pamu_get_ppaace(liodn);
-			pamu_init_ppaace(ppaace);
-			/* window size is 2^(WSE+1) bytes */
-			set_bf(ppaace->addr_bitfields, PPAACE_AF_WSE, 35);
-			ppaace->wbah = 0;
-			set_bf(ppaace->addr_bitfields, PPAACE_AF_WBAL, 0);
-			set_bf(ppaace->impl_attr, PAACE_IA_ATM,
-			       PAACE_ATM_NO_XLATE);
-			set_bf(ppaace->addr_bitfields, PAACE_AF_AP,
-			       PAACE_AP_PERMS_ALL);
+			setup_default_ppaace(ppaace);
+
 			if (of_device_is_compatible(node, "fsl,qman-portal"))
 				setup_qbman_paace(ppaace, QMAN_PORTAL_PAACE);
 			if (of_device_is_compatible(node, "fsl,qman"))
diff --git a/drivers/iommu/fsl_pamu.h b/drivers/iommu/fsl_pamu.h
index bebc2e3..3bd0434 100644
--- a/drivers/iommu/fsl_pamu.h
+++ b/drivers/iommu/fsl_pamu.h
@@ -412,5 +412,6 @@ void get_ome_index(u32 *omi_index, struct device *dev);
 int  pamu_update_paace_stash(int liodn, u32 subwin, u32 value);
 int pamu_disable_spaace(int liodn, u32 subwin);
 u32 pamu_get_max_subwin_cnt(void);
+void enable_default_dma_window(int liodn);
 
 #endif  /* __FSL_PAMU_H */
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index 37f95d3..ba2f97b 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -327,17 +327,53 @@ static struct fsl_dma_domain *iommu_alloc_dma_domain(void)
 	return domain;
 }
 
+/* Disable device DMA capability and enable default DMA window */
+static void disable_device_dma(struct device_domain_info *info,
+			       int enable_dma_window)
+{
+#ifdef CONFIG_PCI
+	if (dev_is_pci(info->dev))
+		pci_clear_master(to_pci_dev(info->dev));
+#endif
+
+	if (enable_dma_window)
+		enable_default_dma_window(info->liodn);
+}
+
+static int check_for_shared_liodn(struct device_domain_info *info)
+{
+	struct device_domain_info *tmp;
+
+	/*
+	 * Sanity check, to ensure that this is not a
+	 * shared LIODN. In case of a PCIe controller
+	 * it's possible that all PCIe devices share
+	 * the same LIODN.
+	 */
+	list_for_each_entry(tmp, &info->domain->devices, link) {
+		if (info->liodn == tmp->liodn)
+			return 1;
+	}
+
+	return 0;
+}
+
 static void remove_device_ref(struct device_domain_info *info, u32 win_cnt)
 {
 	unsigned long flags;
+	int enable_dma_window = 0;
 
 	list_del(&info->link);
 	spin_lock_irqsave(&iommu_lock, flags);
-	if (win_cnt > 1)
-		pamu_free_subwins(info->liodn);
-	pamu_disable_liodn(info->liodn);
+	if (!check_for_shared_liodn(info)) {
+		if (win_cnt > 1)
+			pamu_free_subwins(info->liodn);
+		pamu_disable_liodn(info->liodn);
+		enable_dma_window = 1;
+	}
 	spin_unlock_irqrestore(&iommu_lock, flags);
 	spin_lock_irqsave(&device_domain_lock, flags);
+	disable_device_dma(info, enable_dma_window);
 	info->dev->archdata.iommu_domain = NULL;
 	kmem_cache_free(iommu_devinfo_cache, info);
 	spin_unlock_irqrestore(&device_domain_lock, flags);
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/7] iommu/fsl: PAMU power management support
  2016-03-07 15:34 [PATCH 0/7] PAMU driver update Codrin Ciubotariu
                   ` (4 preceding siblings ...)
  2016-03-07 15:34 ` [PATCH 5/7] iommu/fsl: Enable default DMA window for PCIe devices once detached from domain Codrin Ciubotariu
@ 2016-03-07 15:34 ` Codrin Ciubotariu
  2016-03-07 15:34 ` [PATCH 7/7] iommu/fsl: Added cache controller compatible strings for SOCs Codrin Ciubotariu
  2016-03-22 13:59 ` [PATCH 0/7] PAMU driver update Codrin Constantin Ciubotariu
  7 siblings, 0 replies; 9+ messages in thread
From: Codrin Ciubotariu @ 2016-03-07 15:34 UTC (permalink / raw)
  To: iommu; +Cc: scottwood, Varun.Sethi, linuxppc-dev, Codrin Ciubotariu

From: Varun Sethi <Varun.Sethi@freescale.com>

PAMU driver suspend and resume support.

Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com>
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@nxp.com>
---
 drivers/iommu/fsl_pamu.c | 155 +++++++++++++++++++++++++++++++++++++----------
 1 file changed, 123 insertions(+), 32 deletions(-)

diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index 181759e..290231a 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -23,6 +23,7 @@
 #include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/genalloc.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/mpc85xx.h>
 #include <asm/reg.h>
@@ -35,10 +36,13 @@
 
 #define make64(high, low) (((u64)(high) << 32) | (low))
 
-struct pamu_isr_data {
+struct pamu_info {
 	void __iomem *pamu_reg_base;	/* Base address of PAMU regs */
 	unsigned int count;		/* The number of PAMUs */
-};
+} pamu_info_data;
+
+/* Pointer to the device configuration space */
+static struct ccsr_guts __iomem *guts_regs;
 
 static struct paace *ppaact;
 static struct paace *spaact;
@@ -104,6 +108,36 @@ static struct paace *pamu_get_ppaace(int liodn)
 	return &ppaact[liodn];
 }
 
+#ifdef CONFIG_SUSPEND
+/**
+ * set_dcfg_liodn() - set the device LIODN in DCFG
+ * @np: device tree node pointer
+ * @liodn: liodn value to program
+ *
+ * Returns 0 upon success else error code < 0 returned
+ */
+static int set_dcfg_liodn(struct device_node *np, int liodn)
+{
+	const __be32 *prop;
+	u32 liodn_reg_offset;
+	int len;
+	void __iomem *dcfg_region = (void *)guts_regs;
+
+	if (!dcfg_region)
+		return -ENODEV;
+
+	prop = of_get_property(np, "fsl,liodn-reg", &len);
+	if (!prop || len != 8)
+		return -EINVAL;
+
+	liodn_reg_offset = be32_to_cpup(&prop[1]);
+
+	out_be32((u32 *)(dcfg_region + liodn_reg_offset), liodn);
+
+	return 0;
+}
+#endif
+
 /**
  * pamu_enable_liodn() - Set valid bit of PACCE
  * @liodn: liodn PAACT index for desired PAACE
@@ -743,7 +777,7 @@ static void setup_omt(struct ome *omt)
  * Get the maximum number of PAACT table entries
  * and subwindows supported by PAMU
  */
-static void get_pamu_cap_values(unsigned long pamu_reg_base)
+static void get_pamu_cap_values(void *pamu_reg_base)
 {
 	u32 pc_val;
 
@@ -753,10 +787,8 @@ static void get_pamu_cap_values(unsigned long pamu_reg_base)
 }
 
 /* Setup PAMU registers pointing to PAACT, SPAACT and OMT */
-static int setup_one_pamu(unsigned long pamu_reg_base,
-			  unsigned long pamu_reg_size,
-			  phys_addr_t ppaact_phys, phys_addr_t spaact_phys,
-			  phys_addr_t omt_phys)
+static int setup_one_pamu(void *pamu_reg_base, phys_addr_t ppaact_phys,
+			  phys_addr_t spaact_phys, phys_addr_t omt_phys)
 {
 	u32 *pc;
 	struct pamu_mmap_regs *pamu_regs;
@@ -846,7 +878,7 @@ static void setup_liodns(void)
 
 static irqreturn_t pamu_av_isr(int irq, void *arg)
 {
-	struct pamu_isr_data *data = arg;
+	struct pamu_info *data = arg;
 	phys_addr_t phys;
 	unsigned int i, j, ret;
 
@@ -1098,11 +1130,9 @@ static int fsl_pamu_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	void __iomem *pamu_regs = NULL;
-	struct ccsr_guts __iomem *guts_regs = NULL;
 	u32 pamubypenr, pamu_counter;
+	void __iomem *pamu_reg_base;
 	unsigned long pamu_reg_off;
-	unsigned long pamu_reg_base;
-	struct pamu_isr_data *data = NULL;
 	struct device_node *guts_node;
 	u64 size;
 	struct page *p;
@@ -1129,22 +1159,17 @@ static int fsl_pamu_probe(struct platform_device *pdev)
 	}
 	of_get_address(dev->of_node, 0, &size, NULL);
 
+	pamu_info_data.pamu_reg_base = pamu_regs;
+	pamu_info_data.count = size / PAMU_OFFSET;
+
 	irq = irq_of_parse_and_map(dev->of_node, 0);
 	if (irq == NO_IRQ) {
 		dev_warn(dev, "no interrupts listed in PAMU node\n");
 		goto error;
 	}
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		ret = -ENOMEM;
-		goto error;
-	}
-	data->pamu_reg_base = pamu_regs;
-	data->count = size / PAMU_OFFSET;
-
 	/* The ISR needs access to the regs, so we won't iounmap them */
-	ret = request_irq(irq, pamu_av_isr, 0, "pamu", data);
+	ret = request_irq(irq, pamu_av_isr, 0, "pamu", &pamu_info_data);
 	if (ret < 0) {
 		dev_err(dev, "error %i installing ISR for irq %i\n", ret, irq);
 		goto error;
@@ -1167,7 +1192,7 @@ static int fsl_pamu_probe(struct platform_device *pdev)
 	}
 
 	/* read in the PAMU capability registers */
-	get_pamu_cap_values((unsigned long)pamu_regs);
+	get_pamu_cap_values(pamu_regs);
 	/*
 	 * To simplify the allocation of a coherency domain, we allocate the
 	 * PAACT and the OMT in the same memory buffer. Unfortunately, this
@@ -1243,9 +1268,9 @@ static int fsl_pamu_probe(struct platform_device *pdev)
 	for (pamu_reg_off = 0, pamu_counter = 0x80000000; pamu_reg_off < size;
 	     pamu_reg_off += PAMU_OFFSET, pamu_counter >>= 1) {
 
-		pamu_reg_base = (unsigned long)pamu_regs + pamu_reg_off;
-		setup_one_pamu(pamu_reg_base, pamu_reg_off, ppaact_phys,
-			       spaact_phys, omt_phys);
+		pamu_reg_base = pamu_regs + pamu_reg_off;
+		setup_one_pamu(pamu_reg_base, ppaact_phys, spaact_phys,
+			       omt_phys);
 		/* Disable PAMU bypass for this PAMU */
 		pamubypenr &= ~pamu_counter;
 	}
@@ -1255,8 +1280,6 @@ static int fsl_pamu_probe(struct platform_device *pdev)
 	/* Enable all relevant PAMU(s) */
 	out_be32(&guts_regs->pamubypenr, pamubypenr);
 
-	iounmap(guts_regs);
-
 	/* Enable DMA for the LIODNs in the device tree */
 
 	setup_liodns();
@@ -1268,12 +1291,7 @@ error_genpool:
 
 error:
 	if (irq != NO_IRQ)
-		free_irq(irq, data);
-
-	if (data) {
-		memset(data, 0, sizeof(struct pamu_isr_data));
-		kfree(data);
-	}
+		free_irq(irq, &pamu_info_data);
 
 	if (pamu_regs)
 		iounmap(pamu_regs);
@@ -1296,6 +1314,77 @@ static struct platform_driver fsl_of_pamu_driver = {
 	.probe = fsl_pamu_probe,
 };
 
+#ifdef CONFIG_SUSPEND
+static int iommu_suspend(void)
+{
+	int i;
+
+	for (i = 0; i < pamu_info_data.count; i++) {
+		u32 val;
+		void __iomem *p;
+
+		p = pamu_info_data.pamu_reg_base + i * PAMU_OFFSET;
+		val = in_be32((u32 *)(p + PAMU_PICS));
+		/* Disable access violation interrupts */
+		out_be32((u32 *)(p + PAMU_PICS),
+			 val & ~PAMU_ACCESS_VIOLATION_ENABLE);
+	}
+
+	return 0;
+}
+
+static void restore_dcfg_liodns(void)
+{
+	struct device_node *node;
+	const __be32 *prop;
+	int ret, liodn;
+
+	for_each_node_with_property(node, "fsl,liodn-reg") {
+		prop = of_get_property(node, "fsl,liodn", 0);
+		if (!prop)
+			continue;
+		liodn = be32_to_cpup(prop);
+		ret = set_dcfg_liodn(node, liodn);
+		if (ret)
+			pr_debug("LIODN restore failed for %s\n",
+				 node->full_name);
+	}
+}
+
+static void iommu_resume(void)
+{
+	int i;
+	u32 pamubypenr, pamu_counter;
+
+	restore_dcfg_liodns();
+	pamubypenr = in_be32(&guts_regs->pamubypenr);
+	for (i = 0, pamu_counter = 0x80000000; i < pamu_info_data.count;
+		 i++, pamu_counter >>= 1) {
+		void __iomem *p;
+
+		p = pamu_info_data.pamu_reg_base + i * PAMU_OFFSET;
+		setup_one_pamu(p, virt_to_phys(ppaact), virt_to_phys(spaact),
+			       virt_to_phys(omt));
+		pamubypenr &= ~pamu_counter;
+	}
+	/* Enable all PAMUs */
+	out_be32(&guts_regs->pamubypenr, pamubypenr);
+}
+
+static struct syscore_ops iommu_syscore_ops = {
+	.resume		= iommu_resume,
+	.suspend	= iommu_suspend,
+};
+
+static void __init init_iommu_pm_ops(void)
+{
+	register_syscore_ops(&iommu_syscore_ops);
+}
+
+#else
+static inline void init_iommu_pm_ops(void) {}
+#endif	/* CONFIG_SUSPEND */
+
 static __init int fsl_pamu_init(void)
 {
 	struct platform_device *pdev = NULL;
@@ -1353,6 +1442,8 @@ static __init int fsl_pamu_init(void)
 		goto error_device_add;
 	}
 
+	init_iommu_pm_ops();
+
 	return 0;
 
 error_device_add:
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 7/7] iommu/fsl: Added cache controller compatible strings for SOCs
  2016-03-07 15:34 [PATCH 0/7] PAMU driver update Codrin Ciubotariu
                   ` (5 preceding siblings ...)
  2016-03-07 15:34 ` [PATCH 6/7] iommu/fsl: PAMU power management support Codrin Ciubotariu
@ 2016-03-07 15:34 ` Codrin Ciubotariu
  2016-03-22 13:59 ` [PATCH 0/7] PAMU driver update Codrin Constantin Ciubotariu
  7 siblings, 0 replies; 9+ messages in thread
From: Codrin Ciubotariu @ 2016-03-07 15:34 UTC (permalink / raw)
  To: iommu; +Cc: scottwood, Varun.Sethi, linuxppc-dev, Codrin Ciubotariu

From: Varun Sethi <Varun.Sethi@freescale.com>

Added cache controller compatible strings for T2080, B4420, T1040
and T1024. PAMU driver searches for a matching string while setting
up L3 cache stashing.

Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com>
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@nxp.com>
---
 drivers/iommu/fsl_pamu.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index 290231a..47f54fe 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -63,12 +63,20 @@ static const struct of_device_id guts_device_ids[] = {
 /*
  * Table for matching compatible strings, for device tree
  * L3 cache controller node.
+ * "fsl,t1024-l3-cache-controller" corresponds to T1024,
+ * "fsl,t1040-l3-cache-controller" corresponds to T1040,
+ * "fsl,b4420-l3-cache-controller" corresponds to B4420,
+ * "fsl,t2080-l3-cache-controller" corresponds to T2080,
  * "fsl,t4240-l3-cache-controller" corresponds to T4,
  * "fsl,b4860-l3-cache-controller" corresponds to B4 &
  * "fsl,p4080-l3-cache-controller" corresponds to other,
  * SOCs.
  */
 static const struct of_device_id l3_device_ids[] = {
+	{ .compatible = "fsl,t1024-l3-cache-controller", },
+	{ .compatible = "fsl,t1040-l3-cache-controller", },
+	{ .compatible = "fsl,b4420-l3-cache-controller", },
+	{ .compatible = "fsl,t2080-l3-cache-controller", },
 	{ .compatible = "fsl,t4240-l3-cache-controller", },
 	{ .compatible = "fsl,b4860-l3-cache-controller", },
 	{ .compatible = "fsl,p4080-l3-cache-controller", },
@@ -647,6 +655,8 @@ u32 get_stash_id(u32 stash_dest_hint, u32 vcpu)
 			of_node_put(node);
 			return be32_to_cpup(prop);
 		}
+		pr_err("%s: Failed to get L3 cache controller information\n",
+		       __func__);
 		return ~(u32)0;
 	}
 
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* RE: [PATCH 0/7] PAMU driver update
  2016-03-07 15:34 [PATCH 0/7] PAMU driver update Codrin Ciubotariu
                   ` (6 preceding siblings ...)
  2016-03-07 15:34 ` [PATCH 7/7] iommu/fsl: Added cache controller compatible strings for SOCs Codrin Ciubotariu
@ 2016-03-22 13:59 ` Codrin Constantin Ciubotariu
  7 siblings, 0 replies; 9+ messages in thread
From: Codrin Constantin Ciubotariu @ 2016-03-22 13:59 UTC (permalink / raw)
  To: iommu; +Cc: scottwood, Varun.Sethi, linuxppc-dev

Hi,

Anyone has any comments on this patch-set? Please share your thoughts.

Thanks and best regards,
Codrin

> -----Original Message-----
> From: Codrin Ciubotariu [mailto:codrin.ciubotariu@nxp.com]
> Sent: Monday, 07 March, 2016 5:34 PM
> To: iommu@lists.linux-foundation.org
> Cc: scottwood@freescale.com; Varun.Sethi@freescale.com; linuxppc-
> dev@lists.ozlabs.org; Codrin Constantin Ciubotariu
> Subject: [PATCH 0/7] PAMU driver update
>=20
> This patchset addresses a few issues found on PAMU IOMMU and small change=
s to
> enable power management and to support the
> L3 cache controller on some newer boards.
>=20
> The series starts with a clean-up patch, followed by two errata fixes: A-=
007907
> and A-005982. It continues with two fixes for PCIe support. The last two =
patches
> add support for power management and compatible strings for new L3 contro=
ller
> device-tree nodes.
>=20
> Codrin Ciubotariu (2):
>   iommu/fsl: Fix most checkpatch warnings and typos
>   iommu/fsl: Work around erratum A-007907
>=20
> Varun Sethi (5):
>   iommu/fsl: Enable OMT cache, before invalidating PAACT and SPAACT
>     cache
>   iommu/fsl: Factor out PCI specific code
>   iommu/fsl: Enable default DMA window for PCIe devices once detached
>     from domain
>   iommu/fsl: PAMU power management support
>   iommu/fsl: Added cache controller compatible strings for SOCs
>=20
>  drivers/iommu/fsl_pamu.c        | 322 ++++++++++++++++++++++++++++++++--=
------
>  drivers/iommu/fsl_pamu.h        |  30 ++--
>  drivers/iommu/fsl_pamu_domain.c | 160 +++++++++++++-------
>  drivers/iommu/fsl_pamu_domain.h |   2 +-
>  4 files changed, 381 insertions(+), 133 deletions(-)
>=20
> --
> 1.9.3

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-03-22 14:32 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-07 15:34 [PATCH 0/7] PAMU driver update Codrin Ciubotariu
2016-03-07 15:34 ` [PATCH 1/7] iommu/fsl: Fix most checkpatch warnings and typos Codrin Ciubotariu
2016-03-07 15:34 ` [PATCH 2/7] iommu/fsl: Work around erratum A-007907 Codrin Ciubotariu
2016-03-07 15:34 ` [PATCH 3/7] iommu/fsl: Enable OMT cache, before invalidating PAACT and SPAACT cache Codrin Ciubotariu
2016-03-07 15:34 ` [PATCH 4/7] iommu/fsl: Factor out PCI specific code Codrin Ciubotariu
2016-03-07 15:34 ` [PATCH 5/7] iommu/fsl: Enable default DMA window for PCIe devices once detached from domain Codrin Ciubotariu
2016-03-07 15:34 ` [PATCH 6/7] iommu/fsl: PAMU power management support Codrin Ciubotariu
2016-03-07 15:34 ` [PATCH 7/7] iommu/fsl: Added cache controller compatible strings for SOCs Codrin Ciubotariu
2016-03-22 13:59 ` [PATCH 0/7] PAMU driver update Codrin Constantin Ciubotariu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).