diff options
Diffstat (limited to 'target/linux/layerscape/patches-4.14/821-smmu-support-layerscape.patch')
-rw-r--r-- | target/linux/layerscape/patches-4.14/821-smmu-support-layerscape.patch | 506 |
1 files changed, 0 insertions, 506 deletions
diff --git a/target/linux/layerscape/patches-4.14/821-smmu-support-layerscape.patch b/target/linux/layerscape/patches-4.14/821-smmu-support-layerscape.patch deleted file mode 100644 index 931e09a9fa..0000000000 --- a/target/linux/layerscape/patches-4.14/821-smmu-support-layerscape.patch +++ /dev/null @@ -1,506 +0,0 @@ -From 05375244c8e74f90239db92646a771905fdfc0db Mon Sep 17 00:00:00 2001 -From: Biwen Li <biwen.li@nxp.com> -Date: Tue, 30 Oct 2018 18:28:22 +0800 -Subject: [PATCH 38/40] smmu: support layerscape -This is an integrated patch of smmu for layerscape - -Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com> -Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> -Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com> -Signed-off-by: Biwen Li <biwen.li@nxp.com> ---- - .../devicetree/bindings/misc/fsl,qoriq-mc.txt | 39 ++++++ - drivers/iommu/arm-smmu.c | 7 + - drivers/iommu/iommu.c | 21 +++ - drivers/iommu/of_iommu.c | 126 +++++++++++++++++- - drivers/of/irq.c | 6 +- - drivers/of/of_pci.c | 101 -------------- - include/linux/iommu.h | 2 + - include/linux/of_iommu.h | 10 ++ - include/linux/of_pci.h | 10 -- - 9 files changed, 205 insertions(+), 117 deletions(-) - ---- a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt -+++ b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt -@@ -9,6 +9,25 @@ blocks that can be used to create functi - such as network interfaces, crypto accelerator instances, L2 switches, - etc. - -+For an overview of the DPAA2 architecture and fsl-mc bus see: -+drivers/staging/fsl-mc/README.txt -+ -+As described in the above overview, all DPAA2 objects in a DPRC share the -+same hardware "isolation context" and a 10-bit value called an ICID -+(isolation context id) is expressed by the hardware to identify -+the requester. -+ -+The generic 'iommus' property is insufficient to describe the relationship -+between ICIDs and IOMMUs, so an iommu-map property is used to define -+the set of possible ICIDs under a root DPRC and how they map to -+an IOMMU. -+ -+For generic IOMMU bindings, see -+Documentation/devicetree/bindings/iommu/iommu.txt. -+ -+For arm-smmu binding, see: -+Documentation/devicetree/bindings/iommu/arm,smmu.txt. -+ - Required properties: - - - compatible -@@ -88,14 +107,34 @@ Sub-nodes: - Value type: <phandle> - Definition: Specifies the phandle to the PHY device node associated - with the this dpmac. -+Optional properties: -+ -+- iommu-map: Maps an ICID to an IOMMU and associated iommu-specifier -+ data. -+ -+ The property is an arbitrary number of tuples of -+ (icid-base,iommu,iommu-base,length). -+ -+ Any ICID i in the interval [icid-base, icid-base + length) is -+ associated with the listed IOMMU, with the iommu-specifier -+ (i - icid-base + iommu-base). - - Example: - -+ smmu: iommu@5000000 { -+ compatible = "arm,mmu-500"; -+ #iommu-cells = <2>; -+ stream-match-mask = <0x7C00>; -+ ... -+ }; -+ - fsl_mc: fsl-mc@80c000000 { - compatible = "fsl,qoriq-mc"; - reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */ - <0x00000000 0x08340000 0 0x40000>; /* MC control reg */ - msi-parent = <&its>; -+ /* define map for ICIDs 23-64 */ -+ iommu-map = <23 &smmu 23 41>; - #address-cells = <3>; - #size-cells = <1>; - ---- a/drivers/iommu/arm-smmu.c -+++ b/drivers/iommu/arm-smmu.c -@@ -52,6 +52,7 @@ - #include <linux/spinlock.h> - - #include <linux/amba/bus.h> -+#include <linux/fsl/mc.h> - - #include "io-pgtable.h" - #include "arm-smmu-regs.h" -@@ -1474,6 +1475,8 @@ static struct iommu_group *arm_smmu_devi - - if (dev_is_pci(dev)) - group = pci_device_group(dev); -+ else if (dev_is_fsl_mc(dev)) -+ group = fsl_mc_device_group(dev); - else - group = generic_device_group(dev); - -@@ -2052,6 +2055,10 @@ static void arm_smmu_bus_init(void) - bus_set_iommu(&pci_bus_type, &arm_smmu_ops); - } - #endif -+#ifdef CONFIG_FSL_MC_BUS -+ if (!iommu_present(&fsl_mc_bus_type)) -+ bus_set_iommu(&fsl_mc_bus_type, &arm_smmu_ops); -+#endif - } - - static int arm_smmu_device_probe(struct platform_device *pdev) ---- a/drivers/iommu/iommu.c -+++ b/drivers/iommu/iommu.c -@@ -33,6 +33,7 @@ - #include <linux/bitops.h> - #include <linux/property.h> - #include <trace/events/iommu.h> -+#include <linux/fsl/mc.h> - - static struct kset *iommu_group_kset; - static DEFINE_IDA(iommu_group_ida); -@@ -990,6 +991,26 @@ struct iommu_group *pci_device_group(str - return iommu_group_alloc(); - } - -+/* Get the IOMMU group for device on fsl-mc bus */ -+struct iommu_group *fsl_mc_device_group(struct device *dev) -+{ -+ struct device *cont_dev = fsl_mc_cont_dev(dev); -+ struct iommu_group *group; -+ -+ /* Container device is responsible for creating the iommu group */ -+ if (fsl_mc_is_cont_dev(dev)) { -+ group = iommu_group_alloc(); -+ if (IS_ERR(group)) -+ return NULL; -+ } else { -+ get_device(cont_dev); -+ group = iommu_group_get(cont_dev); -+ put_device(cont_dev); -+ } -+ -+ return group; -+} -+ - /** - * iommu_group_get_for_dev - Find or create the IOMMU group for a device - * @dev: target device ---- a/drivers/iommu/of_iommu.c -+++ b/drivers/iommu/of_iommu.c -@@ -24,6 +24,7 @@ - #include <linux/of_iommu.h> - #include <linux/of_pci.h> - #include <linux/slab.h> -+#include <linux/fsl/mc.h> - - #define NO_IOMMU 1 - -@@ -143,15 +144,115 @@ struct of_pci_iommu_alias_info { - struct device_node *np; - }; - -+/** -+ * of_map_rid - Translate a requester ID through a downstream mapping. -+ * @np: root complex device node. -+ * @rid: Requester ID to map. -+ * @map_name: property name of the map to use. -+ * @map_mask_name: optional property name of the mask to use. -+ * @target: optional pointer to a target device node. -+ * @id_out: optional pointer to receive the translated ID. -+ * -+ * Given PCI/MC requester ID, look up the appropriate implementation-defined -+ * platform ID and/or the target device which receives transactions on that -+ * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or -+ * @id_out may be NULL if only the other is required. If @target points to -+ * a non-NULL device node pointer, only entries targeting that node will be -+ * matched; if it points to a NULL value, it will receive the device node of -+ * the first matching target phandle, with a reference held. -+ * -+ * Return: 0 on success or a standard error code on failure. -+ */ -+int of_map_rid(struct device_node *np, u32 rid, -+ const char *map_name, const char *map_mask_name, -+ struct device_node **target, u32 *id_out) -+{ -+ u32 map_mask, masked_rid; -+ int map_len; -+ const __be32 *map = NULL; -+ -+ if (!np || !map_name || (!target && !id_out)) -+ return -EINVAL; -+ -+ map = of_get_property(np, map_name, &map_len); -+ if (!map) { -+ if (target) -+ return -ENODEV; -+ /* Otherwise, no map implies no translation */ -+ *id_out = rid; -+ return 0; -+ } -+ -+ if (!map_len || map_len % (4 * sizeof(*map))) { -+ pr_err("%pOF: Error: Bad %s length: %d\n", np, -+ map_name, map_len); -+ return -EINVAL; -+ } -+ -+ /* The default is to select all bits. */ -+ map_mask = 0xffffffff; -+ -+ /* -+ * Can be overridden by "{iommu,msi}-map-mask" property. -+ * If of_property_read_u32() fails, the default is used. -+ */ -+ if (map_mask_name) -+ of_property_read_u32(np, map_mask_name, &map_mask); -+ -+ masked_rid = map_mask & rid; -+ for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) { -+ struct device_node *phandle_node; -+ u32 rid_base = be32_to_cpup(map + 0); -+ u32 phandle = be32_to_cpup(map + 1); -+ u32 out_base = be32_to_cpup(map + 2); -+ u32 rid_len = be32_to_cpup(map + 3); -+ -+ if (rid_base & ~map_mask) { -+ pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores rid-base (0x%x)\n", -+ np, map_name, map_name, -+ map_mask, rid_base); -+ return -EFAULT; -+ } -+ -+ if (masked_rid < rid_base || masked_rid >= rid_base + rid_len) -+ continue; -+ -+ phandle_node = of_find_node_by_phandle(phandle); -+ if (!phandle_node) -+ return -ENODEV; -+ -+ if (target) { -+ if (*target) -+ of_node_put(phandle_node); -+ else -+ *target = phandle_node; -+ -+ if (*target != phandle_node) -+ continue; -+ } -+ -+ if (id_out) -+ *id_out = masked_rid - rid_base + out_base; -+ -+ pr_debug("%pOF: %s, using mask %08x, rid-base: %08x, out-base: %08x, length: %08x, rid: %08x -> %08x\n", -+ np, map_name, map_mask, rid_base, out_base, -+ rid_len, rid, *id_out); -+ return 0; -+ } -+ -+ pr_err("%pOF: Invalid %s translation - no match for rid 0x%x on %pOF\n", -+ np, map_name, rid, target && *target ? *target : NULL); -+ return -EFAULT; -+} - static int of_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data) - { - struct of_pci_iommu_alias_info *info = data; - struct of_phandle_args iommu_spec = { .args_count = 1 }; - int err; - -- err = of_pci_map_rid(info->np, alias, "iommu-map", -- "iommu-map-mask", &iommu_spec.np, -- iommu_spec.args); -+ err = of_map_rid(info->np, alias, "iommu-map", -+ "iommu-map-mask", &iommu_spec.np, -+ iommu_spec.args); - if (err) - return err == -ENODEV ? NO_IOMMU : err; - -@@ -160,6 +261,23 @@ static int of_pci_iommu_init(struct pci_ - return err; - } - -+static int of_fsl_mc_iommu_init(struct fsl_mc_device *mc_dev, -+ struct device_node *master_np) -+{ -+ struct of_phandle_args iommu_spec = { .args_count = 1 }; -+ int err; -+ -+ err = of_map_rid(master_np, mc_dev->icid, "iommu-map", -+ "iommu-map-mask", &iommu_spec.np, -+ iommu_spec.args); -+ if (err) -+ return err == -ENODEV ? NO_IOMMU : err; -+ -+ err = of_iommu_xlate(&mc_dev->dev, &iommu_spec); -+ of_node_put(iommu_spec.np); -+ return err; -+} -+ - const struct iommu_ops *of_iommu_configure(struct device *dev, - struct device_node *master_np) - { -@@ -191,6 +309,8 @@ const struct iommu_ops *of_iommu_configu - - err = pci_for_each_dma_alias(to_pci_dev(dev), - of_pci_iommu_init, &info); -+ } else if (dev_is_fsl_mc(dev)) { -+ err = of_fsl_mc_iommu_init(to_fsl_mc_device(dev), master_np); - } else { - struct of_phandle_args iommu_spec; - int idx = 0; ---- a/drivers/of/irq.c -+++ b/drivers/of/irq.c -@@ -26,7 +26,7 @@ - #include <linux/module.h> - #include <linux/of.h> - #include <linux/of_irq.h> --#include <linux/of_pci.h> -+#include <linux/of_iommu.h> - #include <linux/string.h> - #include <linux/slab.h> - -@@ -593,8 +593,8 @@ static u32 __of_msi_map_rid(struct devic - * "msi-map" property. - */ - for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) -- if (!of_pci_map_rid(parent_dev->of_node, rid_in, "msi-map", -- "msi-map-mask", np, &rid_out)) -+ if (!of_map_rid(parent_dev->of_node, rid_in, "msi-map", -+ "msi-map-mask", np, &rid_out)) - break; - return rid_out; - } ---- a/drivers/of/of_pci.c -+++ b/drivers/of/of_pci.c -@@ -281,104 +281,3 @@ parse_failed: - } - EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources); - #endif /* CONFIG_OF_ADDRESS */ -- --/** -- * of_pci_map_rid - Translate a requester ID through a downstream mapping. -- * @np: root complex device node. -- * @rid: PCI requester ID to map. -- * @map_name: property name of the map to use. -- * @map_mask_name: optional property name of the mask to use. -- * @target: optional pointer to a target device node. -- * @id_out: optional pointer to receive the translated ID. -- * -- * Given a PCI requester ID, look up the appropriate implementation-defined -- * platform ID and/or the target device which receives transactions on that -- * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or -- * @id_out may be NULL if only the other is required. If @target points to -- * a non-NULL device node pointer, only entries targeting that node will be -- * matched; if it points to a NULL value, it will receive the device node of -- * the first matching target phandle, with a reference held. -- * -- * Return: 0 on success or a standard error code on failure. -- */ --int of_pci_map_rid(struct device_node *np, u32 rid, -- const char *map_name, const char *map_mask_name, -- struct device_node **target, u32 *id_out) --{ -- u32 map_mask, masked_rid; -- int map_len; -- const __be32 *map = NULL; -- -- if (!np || !map_name || (!target && !id_out)) -- return -EINVAL; -- -- map = of_get_property(np, map_name, &map_len); -- if (!map) { -- if (target) -- return -ENODEV; -- /* Otherwise, no map implies no translation */ -- *id_out = rid; -- return 0; -- } -- -- if (!map_len || map_len % (4 * sizeof(*map))) { -- pr_err("%pOF: Error: Bad %s length: %d\n", np, -- map_name, map_len); -- return -EINVAL; -- } -- -- /* The default is to select all bits. */ -- map_mask = 0xffffffff; -- -- /* -- * Can be overridden by "{iommu,msi}-map-mask" property. -- * If of_property_read_u32() fails, the default is used. -- */ -- if (map_mask_name) -- of_property_read_u32(np, map_mask_name, &map_mask); -- -- masked_rid = map_mask & rid; -- for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) { -- struct device_node *phandle_node; -- u32 rid_base = be32_to_cpup(map + 0); -- u32 phandle = be32_to_cpup(map + 1); -- u32 out_base = be32_to_cpup(map + 2); -- u32 rid_len = be32_to_cpup(map + 3); -- -- if (rid_base & ~map_mask) { -- pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores rid-base (0x%x)\n", -- np, map_name, map_name, -- map_mask, rid_base); -- return -EFAULT; -- } -- -- if (masked_rid < rid_base || masked_rid >= rid_base + rid_len) -- continue; -- -- phandle_node = of_find_node_by_phandle(phandle); -- if (!phandle_node) -- return -ENODEV; -- -- if (target) { -- if (*target) -- of_node_put(phandle_node); -- else -- *target = phandle_node; -- -- if (*target != phandle_node) -- continue; -- } -- -- if (id_out) -- *id_out = masked_rid - rid_base + out_base; -- -- pr_debug("%pOF: %s, using mask %08x, rid-base: %08x, out-base: %08x, length: %08x, rid: %08x -> %08x\n", -- np, map_name, map_mask, rid_base, out_base, -- rid_len, rid, *id_out); -- return 0; -- } -- -- pr_err("%pOF: Invalid %s translation - no match for rid 0x%x on %pOF\n", -- np, map_name, rid, target && *target ? *target : NULL); -- return -EFAULT; --} ---- a/include/linux/iommu.h -+++ b/include/linux/iommu.h -@@ -389,6 +389,8 @@ static inline size_t iommu_map_sg(struct - extern struct iommu_group *pci_device_group(struct device *dev); - /* Generic device grouping function */ - extern struct iommu_group *generic_device_group(struct device *dev); -+/* FSL-MC device grouping function */ -+struct iommu_group *fsl_mc_device_group(struct device *dev); - - /** - * struct iommu_fwspec - per-device IOMMU instance data ---- a/include/linux/of_iommu.h -+++ b/include/linux/of_iommu.h -@@ -15,6 +15,9 @@ extern int of_get_dma_window(struct devi - extern const struct iommu_ops *of_iommu_configure(struct device *dev, - struct device_node *master_np); - -+int of_map_rid(struct device_node *np, u32 rid, -+ const char *map_name, const char *map_mask_name, -+ struct device_node **target, u32 *id_out); - #else - - static inline int of_get_dma_window(struct device_node *dn, const char *prefix, -@@ -30,6 +33,13 @@ static inline const struct iommu_ops *of - return NULL; - } - -+static inline int of_map_rid(struct device_node *np, u32 rid, -+ const char *map_name, const char *map_mask_name, -+ struct device_node **target, u32 *id_out) -+{ -+ return -EINVAL; -+} -+ - #endif /* CONFIG_OF_IOMMU */ - - extern struct of_device_id __iommu_of_table; ---- a/include/linux/of_pci.h -+++ b/include/linux/of_pci.h -@@ -19,9 +19,6 @@ int of_pci_parse_bus_range(struct device - int of_get_pci_domain_nr(struct device_node *node); - int of_pci_get_max_link_speed(struct device_node *node); - void of_pci_check_probe_only(void); --int of_pci_map_rid(struct device_node *np, u32 rid, -- const char *map_name, const char *map_mask_name, -- struct device_node **target, u32 *id_out); - #else - static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq) - { -@@ -57,13 +54,6 @@ of_get_pci_domain_nr(struct device_node - return -1; - } - --static inline int of_pci_map_rid(struct device_node *np, u32 rid, -- const char *map_name, const char *map_mask_name, -- struct device_node **target, u32 *id_out) --{ -- return -EINVAL; --} -- - static inline int - of_pci_get_max_link_speed(struct device_node *node) - { |