[PATCH v5 00/12] iommu/exynos: Fixes and Enhancements of System MMU driver with DT
The current exynos-iommu(System MMU) driver does not work autonomously since it is lack of support for power management of peripheral blocks. For example, MFC device driver must ensure that its System MMU is disabled before MFC block is power-down not to invalidate IOTLB in the System MMU when I/O memory mapping is changed. Because A System MMU is resides in the same H/W block, access to control registers of System MMU while the H/W block is turned off must be prohibited. This set of changes solves the above problem with setting each System MMUs as the parent of the device which owns the System MMU to receive the information when the device is turned off or turned on. Another big change to the driver is the support for devicetree. The bindings for System MMU is described in Documentation/devicetree/bindings/arm/samsung/system-mmu.txt In addition, this patchset also includes several bug fixes and enhancements of the current driver. Change log: v5: - new bugfix: patch 01 - Reordered patches * patch 01 ~ 05: Bugfix and enhancements of the existing driver * patch 06 ~ 10: Device Tree support and callbacks for power management * patch 11 : System MMU 3.2 and 3.3 support * patch 12 ~ 14: Debugging features - Additional code compaction v4: - Remove Change-Id from v3 patches - Change the order of the third and the first patch Thanks to Kukjin Kim. - Fix memory leak when allocating and assigning exynos_iommu_owner to client device if the client device has multiple System MMUs. Thanks to Rahul Sharma. v3: - Fix prefetch buffer flag definition for System MMU 3.3 (patch 10/12) - Fix incorrect setting for SET_RUNTIME_PM_OPS (patch 09/12) Thanks to Prathyush. v2: - Split the patch to iommu/exynos into 9 patches - Support for System MMU 3.3 - Some code compaction Patch summary: [PATCH v5 01/14] iommu/exynos: add missing cache flush for removed pagetable entries [PATCH v5 02/14] iommu/exynos: always use iommu fault handler [PATCH v5 03/14] iommu/exynos: allocate lv2 page table from own slab [PATCH v5 04/14] iommu/exynos: change rwlock to spinlock [PATCH v5 05/14] ARM: EXYNOS: Add clk_ops for gating clocks of System MMU [PATCH v5 06/14] ARM: EXYNOS: add System MMU definition to DT [PATCH v5 07/14] iommu/exynos: support for device tree [PATCH v5 08/14] iommu/exynos: set System MMU as the parent of client device [PATCH v5 09/14] ARM: EXYNOS: remove system mmu initialization from exynos tree [PATCH v5 10/14] iommu/exynos: add support for runtime pm and suspend/resume [PATCH v5 11/14] iommu/exynos: add support for System MMU 3.2 and 3.3 [PATCH v5 12/14] iommu/exynos: pass version information from DT [PATCH v5 13/14] iommu/exynos: add literal name of System MMU for debugging [PATCH v5 14/14] iommu/exynos: add debugfs entries for System MMU Diffstats: .../devicetree/bindings/arm/exynos/system-mmu.txt | 86 ++ arch/arm/boot/dts/exynos4210.dtsi | 96 ++ arch/arm/boot/dts/exynos4x12.dtsi | 124 ++ arch/arm/boot/dts/exynos5250.dtsi | 154 +- arch/arm/mach-exynos/Kconfig |5 - arch/arm/mach-exynos/Makefile |1 - arch/arm/mach-exynos/clock-exynos4.c | 41 +- arch/arm/mach-exynos/clock-exynos4210.c|9 +- arch/arm/mach-exynos/clock-exynos4212.c| 23 +- arch/arm/mach-exynos/clock-exynos5.c | 86 +- arch/arm/mach-exynos/dev-sysmmu.c | 274 arch/arm/mach-exynos/include/mach/sysmmu.h | 66 - arch/arm/mach-exynos/mach-exynos4-dt.c | 34 + arch/arm/mach-exynos/mach-exynos5-dt.c | 30 + drivers/iommu/Kconfig |2 +- drivers/iommu/Makefile |2 +- drivers/iommu/exynos-iommu.c | 1477 +++- 17 files changed, 1745 insertions(+), 765 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 01/14] iommu/exynos: add missing cache flush for removed pagetable entries
This commit adds cache flush for removed small page and large page entries in exynos_iommu_unmap(). Missing cache flush of removed page table entries can cause missing page fault interrupt when a master IP accesses an unmapped area. Signed-off-by: KyongHo Cho pullip@samsung.com --- drivers/iommu/exynos-iommu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 7fe44f8..b96f3b9 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1002,6 +1002,7 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain, if (lv2ent_small(ent)) { *ent = 0; + pgtable_flush(ent, ent + 1); size = SPAGE_SIZE; priv-lv2entcnt[lv1ent_offset(iova)] += 1; goto done; @@ -1011,6 +1012,7 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain, BUG_ON(size LPAGE_SIZE); memset(ent, 0, sizeof(*ent) * SPAGES_PER_LPAGE); + pgtable_flush(ent, ent + SPAGES_PER_LPAGE); size = LPAGE_SIZE; priv-lv2entcnt[lv1ent_offset(iova)] += SPAGES_PER_LPAGE; -- 1.8.0 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 02/14] iommu/exynos: always use iommu fault handler
This commit removes fault handler definition only for exynos-iommu driver. Instead, always call iommu fault handler when a fault is generated by a System MMU. Every new iommu_domain will have a default fault handler and it can be overridden with iommu_set_fault_handler(). The default fault handler also generates debugging messages and kernel woops. Signed-off-by: KyongHo Cho pullip@samsung.com --- drivers/iommu/exynos-iommu.c | 99 1 file changed, 36 insertions(+), 63 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index b96f3b9..ef7dbd1 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -124,16 +124,6 @@ enum exynos_sysmmu_inttype { SYSMMU_FAULTS_NUM }; -/* - * @itype: type of fault. - * @pgtable_base: the physical address of page table base. This is 0 if @itype - *is SYSMMU_BUSERROR. - * @fault_addr: the device (virtual) address that the System MMU tried to - * translated. This is 0 if @itype is SYSMMU_BUSERROR. - */ -typedef int (*sysmmu_fault_handler_t)(enum exynos_sysmmu_inttype itype, - unsigned long pgtable_base, unsigned long fault_addr); - static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = { REG_PAGE_FAULT_ADDR, REG_AR_FAULT_ADDR, @@ -176,7 +166,6 @@ struct sysmmu_drvdata { int activations; rwlock_t lock; struct iommu_domain *domain; - sysmmu_fault_handler_t fault_handler; unsigned long pgtable; }; @@ -291,48 +280,23 @@ finish: read_unlock_irqrestore(data-lock, flags); } -static void __set_fault_handler(struct sysmmu_drvdata *data, - sysmmu_fault_handler_t handler) -{ - unsigned long flags; - - write_lock_irqsave(data-lock, flags); - data-fault_handler = handler; - write_unlock_irqrestore(data-lock, flags); -} - -void exynos_sysmmu_set_fault_handler(struct device *dev, - sysmmu_fault_handler_t handler) -{ - struct sysmmu_drvdata *data = dev_get_drvdata(dev-archdata.iommu); - - __set_fault_handler(data, handler); -} - -static int default_fault_handler(enum exynos_sysmmu_inttype itype, -unsigned long pgtable_base, unsigned long fault_addr) +static void __show_fault_information(unsigned long *pgtable, unsigned long iova, +int flags) { unsigned long *ent; - if ((itype = SYSMMU_FAULTS_NUM) || (itype SYSMMU_PAGEFAULT)) - itype = SYSMMU_FAULT_UNKNOWN; - pr_err(%s occurred at 0x%lx(Page table base: 0x%lx)\n, - sysmmu_fault_name[itype], fault_addr, pgtable_base); + sysmmu_fault_name[flags], iova, __pa(pgtable)); - ent = section_entry(__va(pgtable_base), fault_addr); + ent = section_entry(pgtable, iova); pr_err(\tLv1 entry: 0x%lx\n, *ent); if (lv1ent_page(ent)) { - ent = page_entry(ent, fault_addr); + ent = page_entry(ent, iova); pr_err(\t Lv2 entry: 0x%lx\n, *ent); } pr_err(Generating Kernel OOPS... because it is unrecoverable.\n); - - BUG(); - - return 0; } static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) @@ -341,7 +305,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) struct sysmmu_drvdata *data = dev_id; struct resource *irqres; struct platform_device *pdev; - enum exynos_sysmmu_inttype itype; + enum exynos_sysmmu_inttype itype = SYSMMU_FAULT_UNKNOWN; unsigned long addr = -1; int i, ret = -ENOSYS; @@ -357,9 +321,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) break; } - if (i == pdev-num_resources) { - itype = SYSMMU_FAULT_UNKNOWN; - } else { + if (i pdev-num_resources) { itype = (enum exynos_sysmmu_inttype) __ffs(__raw_readl(data-sfrbases[i] + REG_INT_STATUS)); if (WARN_ON(!((itype = 0) (itype SYSMMU_FAULT_UNKNOWN @@ -370,25 +332,25 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) } if (data-domain) - ret = report_iommu_fault(data-domain, data-dev, - addr, itype); - - if ((ret == -ENOSYS) data-fault_handler) { - unsigned long base = data-pgtable; - if (itype != SYSMMU_FAULT_UNKNOWN) - base = __raw_readl( - data-sfrbases[i] + REG_PT_BASE_ADDR); - ret = data-fault_handler(itype, base, addr); - } - - if (!ret (itype != SYSMMU_FAULT_UNKNOWN)) + ret = report_iommu_fault(data-domain, data-dev, addr, itype); + else +
[PATCH v5 03/14] iommu/exynos: allocate lv2 page table from own slab
Since kmalloc() does not guarantee the alignment of 1KB when it allocates 1KB, it is required to allocate lv2 page table from own slab that guarantees alignment of 1KB. Signed-off-by: KyongHo Cho pullip@samsung.com --- drivers/iommu/exynos-iommu.c | 24 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index ef7dbd1..58d2a24 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -101,6 +101,8 @@ #define REG_PB1_SADDR 0x054 #define REG_PB1_EADDR 0x058 +static struct kmem_cache *lv2table_kmem_cache; + static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova) { return pgtable + lv1ent_offset(iova); @@ -739,7 +741,8 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain) for (i = 0; i NUM_LV1ENTRIES; i++) if (lv1ent_page(priv-pgtable + i)) - kfree(__va(lv2table_base(priv-pgtable + i))); + kmem_cache_free(lv2table_kmem_cache, + __va(lv2table_base(priv-pgtable + i))); free_pages((unsigned long)priv-pgtable, 2); free_pages((unsigned long)priv-lv2entcnt, 1); @@ -833,7 +836,7 @@ static unsigned long *alloc_lv2entry(unsigned long *sent, unsigned long iova, if (lv1ent_fault(sent)) { unsigned long *pent; - pent = kzalloc(LV2TABLE_SIZE, GFP_ATOMIC); + pent = kmem_cache_zalloc(lv2table_kmem_cache, GFP_ATOMIC); BUG_ON((unsigned long)pent (LV2TABLE_SIZE - 1)); if (!pent) return NULL; @@ -856,7 +859,7 @@ static int lv1set_section(unsigned long *sent, phys_addr_t paddr, short *pgcnt) if (*pgcnt != NUM_LV2ENTRIES) return -EADDRINUSE; - kfree(page_entry(sent, 0)); + kmem_cache_free(lv2table_kmem_cache, page_entry(sent, 0)); *pgcnt = 0; } @@ -1044,10 +1047,23 @@ static int __init exynos_iommu_init(void) { int ret; + lv2table_kmem_cache = kmem_cache_create(exynos-iommu-lv2table, + LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL); + if (!lv2table_kmem_cache) { + pr_err(%s: failed to create kmem cache\n, __func__); + return -ENOMEM; + } + ret = platform_driver_register(exynos_sysmmu_driver); if (ret == 0) - bus_set_iommu(platform_bus_type, exynos_iommu_ops); + ret = bus_set_iommu(platform_bus_type, exynos_iommu_ops); + + if (ret) { + pr_err(%s: Failed to register exynos-iommu driver.\n, + __func__); + kmem_cache_destroy(lv2table_kmem_cache); + } return ret; } -- 1.8.0 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 04/14] iommu/exynos: change rwlock to spinlock
Since acquiring read_lock is not more frequent than write_lock, it is not beneficial to use rwlock, this commit changes rwlock to spinlock. Signed-off-by: KyongHo Cho pullip@samsung.com --- drivers/iommu/exynos-iommu.c | 28 ++-- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 58d2a24..5847508 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -166,7 +166,7 @@ struct sysmmu_drvdata { void __iomem **sfrbases; struct clk *clk[2]; int activations; - rwlock_t lock; + spinlock_t lock; struct iommu_domain *domain; unsigned long pgtable; }; @@ -249,7 +249,7 @@ void exynos_sysmmu_set_prefbuf(struct device *dev, BUG_ON((base0 + size0) = base0); BUG_ON((size1 0) ((base1 + size1) = base1)); - read_lock_irqsave(data-lock, flags); + spin_lock_irqsave(data-lock, flags); if (!is_sysmmu_active(data)) goto finish; @@ -279,7 +279,7 @@ void exynos_sysmmu_set_prefbuf(struct device *dev, } } finish: - read_unlock_irqrestore(data-lock, flags); + spin_unlock_irqrestore(data-lock, flags); } static void __show_fault_information(unsigned long *pgtable, unsigned long iova, @@ -312,7 +312,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) int i, ret = -ENOSYS; - read_lock(data-lock); + spin_lock(data-lock); WARN_ON(!is_sysmmu_active(data)); @@ -354,7 +354,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) sysmmu_unblock(data-sfrbases[i]); - read_unlock(data-lock); + spin_unlock(data-lock); return IRQ_HANDLED; } @@ -365,7 +365,7 @@ static bool __exynos_sysmmu_disable(struct sysmmu_drvdata *data) bool disabled = false; int i; - write_lock_irqsave(data-lock, flags); + spin_lock_irqsave(data-lock, flags); if (!set_sysmmu_inactive(data)) goto finish; @@ -382,7 +382,7 @@ static bool __exynos_sysmmu_disable(struct sysmmu_drvdata *data) data-pgtable = 0; data-domain = NULL; finish: - write_unlock_irqrestore(data-lock, flags); + spin_unlock_irqrestore(data-lock, flags); if (disabled) dev_dbg(data-sysmmu, (%s) Disabled\n, data-dbgname); @@ -405,7 +405,7 @@ static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data, int i, ret = 0; unsigned long flags; - write_lock_irqsave(data-lock, flags); + spin_lock_irqsave(data-lock, flags); if (!set_sysmmu_active(data)) { if (WARN_ON(pgtable != data-pgtable)) { @@ -444,7 +444,7 @@ static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data, dev_dbg(data-sysmmu, (%s) Enabled\n, data-dbgname); finish: - write_unlock_irqrestore(data-lock, flags); + spin_unlock_irqrestore(data-lock, flags); return ret; } @@ -491,7 +491,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova) unsigned long flags; struct sysmmu_drvdata *data = dev_get_drvdata(dev-archdata.iommu); - read_lock_irqsave(data-lock, flags); + spin_lock_irqsave(data-lock, flags); if (is_sysmmu_active(data)) { int i; @@ -508,7 +508,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova) data-dbgname); } - read_unlock_irqrestore(data-lock, flags); + spin_unlock_irqrestore(data-lock, flags); } void exynos_sysmmu_tlb_invalidate(struct device *dev) @@ -516,7 +516,7 @@ void exynos_sysmmu_tlb_invalidate(struct device *dev) unsigned long flags; struct sysmmu_drvdata *data = dev_get_drvdata(dev-archdata.iommu); - read_lock_irqsave(data-lock, flags); + spin_lock_irqsave(data-lock, flags); if (is_sysmmu_active(data)) { int i; @@ -532,7 +532,7 @@ void exynos_sysmmu_tlb_invalidate(struct device *dev) data-dbgname); } - read_unlock_irqrestore(data-lock, flags); + spin_unlock_irqrestore(data-lock, flags); } static int exynos_sysmmu_probe(struct platform_device *pdev) @@ -629,7 +629,7 @@ static int exynos_sysmmu_probe(struct platform_device *pdev) } data-sysmmu = dev; - rwlock_init(data-lock); + spin_lock_init(data-lock); INIT_LIST_HEAD(data-node); if (dev-parent) -- 1.8.0 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 05/14] ARM: EXYNOS: Add clk_ops for gating clocks of System MMU
Touching some System MMU needs its master devices' clock to be enabled before. This commit adds clk_ops.set_parent of gating clocks of System MMU to ensure gating clocks of System MMU's mater devices are enabled when enabling gating clocks of System MMU. Signed-off-by: KyongHo Cho pullip@samsung.com --- arch/arm/mach-exynos/clock-exynos5.c | 24 1 file changed, 24 insertions(+) diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c index e48d7c2..a86e88e 100644 --- a/arch/arm/mach-exynos/clock-exynos5.c +++ b/arch/arm/mach-exynos/clock-exynos5.c @@ -614,6 +614,16 @@ static struct clksrc_clk exynos5_clk_aclk_300_gscl = { .reg_src = { .reg = EXYNOS5_CLKSRC_TOP3, .shift = 10, .size = 1 }, }; +static int exynos5_gate_clk_set_parent(struct clk *clk, struct clk *parent) +{ + clk-parent = parent; + return 0; +} + +static struct clk_ops exynos5_gate_clk_ops = { + .set_parent = exynos5_gate_clk_set_parent +}; + static struct clk exynos5_init_clocks_off[] = { { .name = timers, @@ -855,71 +865,85 @@ static struct clk exynos5_init_clocks_off[] = { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(mfc_l, 0), .enable = exynos5_clk_ip_mfc_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (1 1), }, { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(mfc_r, 1), .enable = exynos5_clk_ip_mfc_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (1 2), }, { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(tv, 2), .enable = exynos5_clk_ip_disp1_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (1 9) }, { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(jpeg, 3), .enable = exynos5_clk_ip_gen_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (1 7), }, { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(rot, 4), .enable = exynos5_clk_ip_gen_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (1 6) }, { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(gsc0, 5), .enable = exynos5_clk_ip_gscl_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (1 7), }, { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(gsc1, 6), .enable = exynos5_clk_ip_gscl_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (1 8), }, { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(gsc2, 7), .enable = exynos5_clk_ip_gscl_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (1 9), }, { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(gsc3, 8), .enable = exynos5_clk_ip_gscl_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (1 10), }, { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(isp, 9), .enable = exynos5_clk_ip_isp0_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (0x3F 8), }, { .name = SYSMMU_CLOCK_NAME2, .devname= SYSMMU_CLOCK_DEVNAME(isp, 9), .enable = exynos5_clk_ip_isp1_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (0xF 4), }, { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(camif0, 12), .enable = exynos5_clk_ip_gscl_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (1 11), }, { .name = SYSMMU_CLOCK_NAME, .devname= SYSMMU_CLOCK_DEVNAME(camif1, 13), .enable = exynos5_clk_ip_gscl_ctrl, + .ops= exynos5_gate_clk_ops, .ctrlbit= (1 12), }, { .name =
[PATCH v5 06/14] ARM: EXYNOS: add System MMU definition to DT
This commit adds System MMU nodes to DT of Exynos SoCs. Signed-off-by: KyongHo Cho pullip@samsung.com --- .../devicetree/bindings/arm/exynos/system-mmu.txt | 86 arch/arm/boot/dts/exynos4210.dtsi | 96 ++ arch/arm/boot/dts/exynos4x12.dtsi | 124 + arch/arm/boot/dts/exynos5250.dtsi | 147 - 4 files changed, 451 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/exynos/system-mmu.txt diff --git a/Documentation/devicetree/bindings/arm/exynos/system-mmu.txt b/Documentation/devicetree/bindings/arm/exynos/system-mmu.txt new file mode 100644 index 000..9c30a36 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/exynos/system-mmu.txt @@ -0,0 +1,86 @@ +* Samsung Exynos System MMU + +Samsung's Exynos architecture includes System MMU that enables scattered +physical chunks to be visible as a contiguous region to DMA-capabile peripheral +devices like MFC, FIMC, FIMD, GScaler, FIMC-IS and so forth. + +System MMU is a sort of IOMMU and support identical translation table format to +ARMv7 translation tables with minimum set of page properties including access +permissions, shareability and security protection. In addition System MMU has +another capabilities like L2 TLB or block-fetch buffers to minimize translation +latency + +Each System MMU is included in the H/W block of a peripheral device. Thus, it is +important to specify that a System MMU is dedicated to which peripheral device +before using System MMU. System initialization must specify the relationships +between a System MMU and a peripheral device that owns the System MMU. + +Some device drivers may control several peripheral devices with a single device +descriptor like MFC. Since handling a System MMU with IOMMU API requires a +device descriptor that needs the System MMU, it is best to combine the System +MMUs of the peripheral devices and control them with a single System MMU device +descriptor. If it is unable to combine them into a single device descriptor, +they can be linked with each other by the means of device.parent relationship. + +Required properties: +- compatible: Should be samsung,exynos-sysmmu. +- reg: Tuples of base address and size of System MMU registers. The number of + tuples can be more than one if two or more System MMUs are controlled + by a single device descriptor. +- interrupt-parent: The phandle of the interrupt controller of System MMU +- interrupts: Tuples of numbers that indicates the interrupt source. The + number of elements in the tuple is dependent upon + 'interrupt-parent' property. The number of tuples in this property + must be the same with 'reg' property. + +Optional properties: +- mmuname: Strings of the name of System MMU for debugging purpose. The number + of strings must be the same with the number of tuples in 'reg' + property. +- mmu-master: phandle to the device node that owns System MMU. Only the device + that is specified whith this property can control System MMU with + IOMMU API. + +Examples: + +MFC has 2 System MMUs for each port that MFC is attached. Thus it seems natural +to define 2 System MMUs for each port of the MFC: + + sysmmu-mfc-l { + mmuname = mfc_l; + reg = 0x1121 0x1000; + compatible = samsung,exynos-sysmmu; + interrupt-parent = combiner; + interrupts = 8 5; + mmu-master = mfc; + }; + + sysmmu-mfc-r { + mmuname = mfc_r; + reg = 0x1120 0x1000; + compatible = samsung,exynos-sysmmu; + interrupt-parent = combiner; + interrupts = 6 2; + mmu-master = mfc; + }; + +Actually, MFC device driver requires sub-devices that represents each port and +above 'mmu-master' properties of sysmmu-mfc-l and sysmmu-mfc-r have the phandles +to those sub-devices. + +However, it is also a good idea that treats the above System MMUs as one System +MMU because those System MMUs are actually required by the MFC device: + + sysmmu-mfc { + mmuname = mfc_l, mfc_r; + reg = 0x1121 0x1000 + 0x1120 0x1000; + compatible = samsung,exynos-sysmmu; + interrupt-parent = combiner; + interrupts = 8 5 + 6 2; + mmu-master = mfc; + }; + +If System MMU of MFC is defined like the above, the number of elements and the +order of list in 'mmuname', 'reg' and 'interrupts' must be the same. diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index 939f639..d7a7a06 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi @@ -71,4 +71,100 @@ reg = 0x100C 0x100;
[PATCH v5 07/14] iommu/exynos: support for device tree
This commit adds device tree support for System MMU. Signed-off-by: KyongHo Cho pullip@samsung.com --- drivers/iommu/Kconfig| 2 +- drivers/iommu/exynos-iommu.c | 282 ++- 2 files changed, 174 insertions(+), 110 deletions(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index e39f9db..64586f1 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -168,7 +168,7 @@ config TEGRA_IOMMU_SMMU config EXYNOS_IOMMU bool Exynos IOMMU Support - depends on ARCH_EXYNOS EXYNOS_DEV_SYSMMU + depends on ARCH_EXYNOS select IOMMU_API help Support for the IOMMU(System MMU) of Samsung Exynos application diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 5847508..5b35820 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1,6 +1,6 @@ -/* linux/drivers/iommu/exynos_iommu.c +/* linux/drivers/iommu/exynos-iommu.c * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd. * http://www.samsung.com * * This program is free software; you can redistribute it and/or modify @@ -12,6 +12,7 @@ #define DEBUG #endif +#include linux/kernel.h #include linux/io.h #include linux/interrupt.h #include linux/platform_device.h @@ -25,11 +26,10 @@ #include linux/list.h #include linux/memblock.h #include linux/export.h +#include linux/of.h +#include linux/of_platform.h #include asm/cacheflush.h -#include asm/pgtable.h - -#include mach/sysmmu.h /* We does not consider super section mapping (16MB) */ #define SECT_ORDER 20 @@ -161,14 +161,13 @@ struct sysmmu_drvdata { struct list_head node; /* entry of exynos_iommu_domain.clients */ struct device *sysmmu; /* System MMU's device descriptor */ struct device *dev; /* Owner of system MMU */ - char *dbgname; int nsfrs; - void __iomem **sfrbases; - struct clk *clk[2]; + struct clk *clk; int activations; spinlock_t lock; struct iommu_domain *domain; unsigned long pgtable; + void __iomem *sfrbases[0]; }; static bool set_sysmmu_active(struct sysmmu_drvdata *data) @@ -373,10 +372,8 @@ static bool __exynos_sysmmu_disable(struct sysmmu_drvdata *data) for (i = 0; i data-nsfrs; i++) __raw_writel(CTRL_DISABLE, data-sfrbases[i] + REG_MMU_CTRL); - if (data-clk[1]) - clk_disable(data-clk[1]); - if (data-clk[0]) - clk_disable(data-clk[0]); + if (data-clk) + clk_disable(data-clk); disabled = true; data-pgtable = 0; @@ -385,10 +382,10 @@ finish: spin_unlock_irqrestore(data-lock, flags); if (disabled) - dev_dbg(data-sysmmu, (%s) Disabled\n, data-dbgname); + dev_dbg(data-sysmmu, Disabled\n); else - dev_dbg(data-sysmmu, (%s) %d times left to be disabled\n, - data-dbgname, data-activations); + dev_dbg(data-sysmmu, %d times left to be disabled\n, + data-activations); return disabled; } @@ -415,14 +412,12 @@ static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data, ret = 1; } - dev_dbg(data-sysmmu, (%s) Already enabled\n, data-dbgname); + dev_dbg(data-sysmmu, Already enabled\n); goto finish; } - if (data-clk[0]) - clk_enable(data-clk[0]); - if (data-clk[1]) - clk_enable(data-clk[1]); + if (data-clk) + clk_enable(data-clk); data-pgtable = pgtable; @@ -442,7 +437,7 @@ static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data, data-domain = domain; - dev_dbg(data-sysmmu, (%s) Enabled\n, data-dbgname); + dev_dbg(data-sysmmu, Enabled\n); finish: spin_unlock_irqrestore(data-lock, flags); @@ -458,7 +453,7 @@ int exynos_sysmmu_enable(struct device *dev, unsigned long pgtable) ret = pm_runtime_get_sync(data-sysmmu); if (ret 0) { - dev_dbg(data-sysmmu, (%s) Failed to enable\n, data-dbgname); + dev_dbg(data-sysmmu, Failed to enable\n); return ret; } @@ -466,8 +461,8 @@ int exynos_sysmmu_enable(struct device *dev, unsigned long pgtable) if (WARN_ON(ret 0)) { pm_runtime_put(data-sysmmu); dev_err(data-sysmmu, - (%s) Already enabled with page table %#lx\n, - data-dbgname, data-pgtable); + Already enabled with page table %#lx\n, + data-pgtable); } else { data-dev = dev; } @@ -504,8 +499,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned
[PATCH v5 09/14] ARM: EXYNOS: remove system mmu initialization from exynos tree
This removes System MMU initialization from arch/arm/mach-exynos/ to move them to DT and the exynos-iommu driver except gating clock definitions. Signed-off-by: KyongHo Cho pullip@samsung.com --- arch/arm/mach-exynos/Kconfig | 5 - arch/arm/mach-exynos/Makefile | 1 - arch/arm/mach-exynos/clock-exynos4.c | 41 +++-- arch/arm/mach-exynos/clock-exynos4210.c| 9 +- arch/arm/mach-exynos/clock-exynos4212.c| 23 ++- arch/arm/mach-exynos/clock-exynos5.c | 62 --- arch/arm/mach-exynos/dev-sysmmu.c | 274 - arch/arm/mach-exynos/include/mach/sysmmu.h | 66 --- arch/arm/mach-exynos/mach-exynos4-dt.c | 34 arch/arm/mach-exynos/mach-exynos5-dt.c | 30 10 files changed, 137 insertions(+), 408 deletions(-) delete mode 100644 arch/arm/mach-exynos/dev-sysmmu.c delete mode 100644 arch/arm/mach-exynos/include/mach/sysmmu.h diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index bb3b09a..d5157d7 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -94,11 +94,6 @@ config EXYNOS4_SETUP_FIMD0 help Common setup code for FIMD0. -config EXYNOS_DEV_SYSMMU - bool - help - Common setup code for SYSTEM MMU in EXYNOS platforms - config EXYNOS4_DEV_DWMCI bool help diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 1797dee..7460ba2 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -53,7 +53,6 @@ obj-$(CONFIG_EXYNOS4_DEV_AHCI)+= dev-ahci.o obj-$(CONFIG_EXYNOS4_DEV_DWMCI)+= dev-dwmci.o obj-$(CONFIG_EXYNOS_DEV_DMA) += dma.o obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o -obj-$(CONFIG_EXYNOS_DEV_SYSMMU)+= dev-sysmmu.o obj-$(CONFIG_ARCH_EXYNOS) += setup-i2c0.o obj-$(CONFIG_EXYNOS4_SETUP_FIMC) += setup-fimc.o diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c index efead60..c81a0ca 100644 --- a/arch/arm/mach-exynos/clock-exynos4.c +++ b/arch/arm/mach-exynos/clock-exynos4.c @@ -24,7 +24,6 @@ #include mach/map.h #include mach/regs-clock.h -#include mach/sysmmu.h #include common.h #include clock-exynos4.h @@ -709,53 +708,53 @@ static struct clk exynos4_init_clocks_off[] = { .enable = exynos4_clk_ip_peril_ctrl, .ctrlbit= (1 14), }, { - .name = SYSMMU_CLOCK_NAME, - .devname= SYSMMU_CLOCK_DEVNAME(mfc_l, 0), + .name = sysmmu, + .devname= exynos-sysmmu.0, .enable = exynos4_clk_ip_mfc_ctrl, .ctrlbit= (1 1), }, { - .name = SYSMMU_CLOCK_NAME, - .devname= SYSMMU_CLOCK_DEVNAME(mfc_r, 1), + .name = sysmmu, + .devname= exynos-sysmmu.1, .enable = exynos4_clk_ip_mfc_ctrl, .ctrlbit= (1 2), }, { - .name = SYSMMU_CLOCK_NAME, - .devname= SYSMMU_CLOCK_DEVNAME(tv, 2), + .name = sysmmu, + .devname= exynos-sysmmu.2, .enable = exynos4_clk_ip_tv_ctrl, .ctrlbit= (1 4), }, { - .name = SYSMMU_CLOCK_NAME, - .devname= SYSMMU_CLOCK_DEVNAME(jpeg, 3), + .name = sysmmu, + .devname= exynos-sysmmu.3, .enable = exynos4_clk_ip_cam_ctrl, .ctrlbit= (1 11), }, { - .name = SYSMMU_CLOCK_NAME, - .devname= SYSMMU_CLOCK_DEVNAME(rot, 4), + .name = sysmmu, + .devname= exynos-sysmmu.4, .enable = exynos4_clk_ip_image_ctrl, .ctrlbit= (1 4), }, { - .name = SYSMMU_CLOCK_NAME, - .devname= SYSMMU_CLOCK_DEVNAME(fimc0, 5), + .name = sysmmu, + .devname= exynos-sysmmu.5, .enable = exynos4_clk_ip_cam_ctrl, .ctrlbit= (1 7), }, { - .name = SYSMMU_CLOCK_NAME, - .devname= SYSMMU_CLOCK_DEVNAME(fimc1, 6), + .name = sysmmu, + .devname= exynos-sysmmu.6, .enable = exynos4_clk_ip_cam_ctrl, .ctrlbit= (1 8), }, { - .name = SYSMMU_CLOCK_NAME, - .devname= SYSMMU_CLOCK_DEVNAME(fimc2, 7), + .name = sysmmu, + .devname=
[PATCH v5 13/14] iommu/exynos: add literal name of System MMU for debugging
This commit adds System MMU name to the driver data of each System MMU. It is used by fault information. Signed-off-by: KyongHo Cho pullip@samsung.com --- drivers/iommu/exynos-iommu.c | 72 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 70921e9..9753e0e 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -26,6 +26,7 @@ #include linux/list.h #include linux/memblock.h #include linux/export.h +#include linux/string.h #include linux/of.h #include linux/of_platform.h @@ -180,6 +181,7 @@ struct exynos_iommu_domain { short *lv2entcnt; /* free lv2 entry counter for each section */ spinlock_t lock; /* lock for this structure */ spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */ + const char *fault_info; /* debugging information for fault */ }; /* exynos_iommu_owner @@ -224,6 +226,7 @@ struct sysmmu_drvdata { struct iommu_domain *domain; unsigned long pgtable; bool runtime_active; + const char **mmuname; void __iomem *sfrbases[0]; }; @@ -601,25 +604,29 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) { /* SYSMMU is in blocked when interrupt occurred. */ struct sysmmu_drvdata *data = dev_id; - struct resource *irqres; - struct platform_device *pdev; + struct exynos_iommu_owner *owner = NULL; enum exynos_sysmmu_inttype itype = SYSMMU_FAULT_UNKNOWN; unsigned long addr = -1; - int i, ret = -ENOSYS; - spin_lock(data-lock); + if (data-master) + owner = data-master-archdata.iommu; + + if (owner) + spin_lock(owner-lock); WARN_ON(!is_sysmmu_active(data)); - pdev = to_platform_device(data-sysmmu); - for (i = 0; i (pdev-num_resources / 2); i++) { - irqres = platform_get_resource(pdev, IORESOURCE_IRQ, i); + for (i = 0; i data-nsfrs; i++) { + struct resource *irqres; + irqres = platform_get_resource( + to_platform_device(data-sysmmu), + IORESOURCE_IRQ, i); if (irqres ((int)irqres-start == irq)) break; } - if (i pdev-num_resources) { + if (i data-nsfrs) { itype = (enum exynos_sysmmu_inttype) __ffs(__raw_readl(data-sfrbases[i] + REG_INT_STATUS)); if (WARN_ON(!((itype = 0) (itype SYSMMU_FAULT_UNKNOWN @@ -629,11 +636,17 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) data-sfrbases[i] + fault_reg_offset[itype]); } - if (data-domain) + if ((itype = SYSMMU_FAULTS_NUM) || (itype SYSMMU_PAGEFAULT)) + itype = SYSMMU_FAULT_UNKNOWN; + + if (data-domain) { + struct exynos_iommu_domain *priv = data-domain-priv; + priv-fault_info = data-mmuname[i]; ret = report_iommu_fault(data-domain, data-master, addr, itype); - else + } else { __show_fault_information(__va(data-pgtable), itype, addr); + } if (ret == -ENOSYS) pr_err(NO SYSTEM MMU FAULT HANDLER REGISTERED FOR %s\n, @@ -651,7 +664,8 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) sysmmu_unblock(data-sfrbases[i]); - spin_unlock(data-lock); + if (owner) + spin_unlock(owner-lock); return IRQ_HANDLED; } @@ -1028,6 +1042,30 @@ err_dev_put: return ret; } +static void __init __sysmmu_init_mmuname(struct device *sysmmu, + struct sysmmu_drvdata *drvdata) +{ + int i; + const char *mmuname; + + if (of_property_count_strings(sysmmu-of_node, mmuname) != + drvdata-nsfrs) + return; + + drvdata-mmuname = (void *)drvdata-sfrbases + + sizeof(drvdata-sfrbases[0]) * drvdata-nsfrs; + + for (i = 0; i drvdata-nsfrs; i++) { + if (of_property_read_string_index(sysmmu-of_node, + mmuname, i, mmuname)) + dev_err(sysmmu, Failed read mmuname[%d]\n, i); + else + drvdata-mmuname[i] = kstrdup(mmuname, GFP_KERNEL); + if (!drvdata-mmuname[i]) + drvdata-mmuname[i] = noname; + } +} + static int __init exynos_sysmmu_probe(struct platform_device *pdev) { int i, ret; @@ -1039,9 +1077,14 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) return -ENODEV; } + ret = of_property_count_strings(pdev-dev.of_node, mmuname); +
[PATCH v5 14/14] iommu/exynos: add debugfs entries for System MMU
This commit adds debugfs directory and nodes for inspecting internal state of System MMU. Signed-off-by: KyongHo Cho pullip@samsung.com --- drivers/iommu/exynos-iommu.c | 204 +-- 1 file changed, 198 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 9753e0e..78c0eb7 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -26,12 +26,17 @@ #include linux/list.h #include linux/memblock.h #include linux/export.h +#include linux/fs.h +#include linux/seq_file.h +#include linux/debugfs.h #include linux/string.h #include linux/of.h #include linux/of_platform.h #include asm/cacheflush.h +#define MODULE_NAME exynos-sysmmu + /* We does not consider super section mapping (16MB) */ #define SECT_ORDER 20 #define LPAGE_ORDER 16 @@ -223,6 +228,7 @@ struct sysmmu_drvdata { struct sysmmu_prefbuf pbufs[MAX_NUM_PBUF]; int num_pbufs; struct sysmmu_version ver; + struct dentry *debugfs_root; struct iommu_domain *domain; unsigned long pgtable; bool runtime_active; @@ -1066,6 +1072,8 @@ static void __init __sysmmu_init_mmuname(struct device *sysmmu, } } +static void __create_debugfs_entry(struct sysmmu_drvdata *drvdata); + static int __init exynos_sysmmu_probe(struct platform_device *pdev) { int i, ret; @@ -1134,6 +1142,8 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) data-runtime_active = !pm_runtime_enabled(dev); + __create_debugfs_entry(data); + platform_set_drvdata(pdev, data); dev-archdata.iommu = sysmmu_placeholder; @@ -1238,7 +1248,7 @@ static struct platform_driver exynos_sysmmu_driver __refdata = { .probe = exynos_sysmmu_probe, .driver = { .owner = THIS_MODULE, - .name = exynos-sysmmu, + .name = MODULE_NAME, .pm = __pm_ops, .of_match_table = of_match_ptr(sysmmu_of_match), } @@ -1631,6 +1641,8 @@ static struct iommu_ops exynos_iommu_ops = { .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE, }; +static struct dentry *sysmmu_debugfs_root; /* /sys/kernel/debug/sysmmu */ + static int __init exynos_iommu_init(void) { int ret; @@ -1642,17 +1654,197 @@ static int __init exynos_iommu_init(void) return -ENOMEM; } - ret = platform_driver_register(exynos_sysmmu_driver); + ret = bus_set_iommu(platform_bus_type, exynos_iommu_ops); + if (ret) { + kmem_cache_destroy(lv2table_kmem_cache); + pr_err(%s: Failed to register IOMMU ops\n, __func__); + return -EFAULT; + } - if (ret == 0) - ret = bus_set_iommu(platform_bus_type, exynos_iommu_ops); + sysmmu_debugfs_root = debugfs_create_dir(sysmmu, NULL); + if (!sysmmu_debugfs_root) + pr_err(%s: Failed to create debugfs entry, 'sysmmu'\n, + __func__); + if (IS_ERR(sysmmu_debugfs_root)) + sysmmu_debugfs_root = NULL; + ret = platform_driver_register(exynos_sysmmu_driver); if (ret) { - pr_err(%s: Failed to register exynos-iommu driver.\n, - __func__); kmem_cache_destroy(lv2table_kmem_cache); + pr_err(%s: Failed to register System MMU driver\n, __func__); } return ret; } subsys_initcall(exynos_iommu_init); + +static int debug_string_show(struct seq_file *s, void *unused) +{ + char *str = s-private; + + seq_printf(s, %s\n, str); + + return 0; +} + +static int debug_sysmmu_list_show(struct seq_file *s, void *unused) +{ + struct sysmmu_drvdata *drvdata = s-private; + struct platform_device *pdev = to_platform_device(drvdata-sysmmu); + int idx, maj, min, ret; + + seq_printf(s, SysMMU Name | Ver | SFR Base\n); + + if (pm_runtime_enabled(drvdata-sysmmu)) { + ret = pm_runtime_get_sync(drvdata-sysmmu); + if (ret 0) + return ret; + } + + for (idx = 0; idx drvdata-nsfrs; idx++) { + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, idx); + if (!res) + break; + + maj = __sysmmu_version(drvdata, idx, min); + + if (drvdata-mmuname) { + if (maj == 0) + seq_printf(s, %11.s | N/A | 0x%08x\n, + drvdata-mmuname[idx], res-start); + else + seq_printf(s, %11.s | %d.%d | 0x%08x\n, +
[PATCH v5 08/14] iommu/exynos: set System MMU as the parent of client device
This commit sets System MM as the parent of the client device for power management. If System MMU is the parent of a device, it is guaranteed that System MMU is suspended later than the device and resumed earlier. Runtime suspend/resume on the device is also propagated to the System MMU. If a device is configured to have more than one System MMU, the advantage of power management also works and the System MMUs are also have relationships of parent and child. In this situation, the client device is still the descendant of its System MMUs. Signed-off-by: KyongHo Cho pullip@samsung.com --- drivers/iommu/exynos-iommu.c | 510 +-- 1 file changed, 342 insertions(+), 168 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 5b35820..a0e5ee1 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -101,6 +101,17 @@ #define REG_PB1_SADDR 0x054 #define REG_PB1_EADDR 0x058 +static void *sysmmu_placeholder; /* Inidcate if a device is System MMU */ + +#define is_sysmmu(sysmmu) (sysmmu-archdata.iommu == sysmmu_placeholder) +#define has_sysmmu(dev) \ + (dev-parent dev-archdata.iommu is_sysmmu(dev-parent)) +#define for_each_sysmmu(dev, sysmmu) \ + for (sysmmu = dev-parent; sysmmu is_sysmmu(sysmmu); \ + sysmmu = sysmmu-parent) +#define for_each_sysmmu_until(dev, sysmmu, until) \ + for (sysmmu = dev-parent; sysmmu != until; sysmmu = sysmmu-parent) + static struct kmem_cache *lv2table_kmem_cache; static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova) @@ -157,10 +168,19 @@ struct exynos_iommu_domain { spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */ }; +/* exynos_iommu_owner + * Metadata attached to the owner of a group of System MMUs that belong + * to the same owner device. + */ +struct exynos_iommu_owner { + struct list_head client; /* entry of exynos_iommu_domain.clients */ + struct device *dev; + spinlock_t lock;/* Lock to preserve consistency of System MMU */ +}; + struct sysmmu_drvdata { - struct list_head node; /* entry of exynos_iommu_domain.clients */ struct device *sysmmu; /* System MMU's device descriptor */ - struct device *dev; /* Owner of system MMU */ + struct device *master; /* Client device that needs System MMU */ int nsfrs; struct clk *clk; int activations; @@ -241,44 +261,50 @@ void exynos_sysmmu_set_prefbuf(struct device *dev, unsigned long base0, unsigned long size0, unsigned long base1, unsigned long size1) { - struct sysmmu_drvdata *data = dev_get_drvdata(dev-archdata.iommu); - unsigned long flags; - int i; + struct device *sysmmu; - BUG_ON((base0 + size0) = base0); - BUG_ON((size1 0) ((base1 + size1) = base1)); + for_each_sysmmu(dev, sysmmu) { + int i; + unsigned long flags; + struct sysmmu_drvdata *data = dev_get_drvdata(sysmmu); - spin_lock_irqsave(data-lock, flags); - if (!is_sysmmu_active(data)) - goto finish; + BUG_ON((base0 + size0) = base0); + BUG_ON((size1 0) ((base1 + size1) = base1)); - for (i = 0; i data-nsfrs; i++) { - if ((readl(data-sfrbases[i] + REG_MMU_VERSION) 28) == 3) { - if (!sysmmu_block(data-sfrbases[i])) - continue; + spin_lock_irqsave(data-lock, flags); + if (!is_sysmmu_active(data)) { + spin_unlock_irqrestore(data-lock, flags); + continue; + } - if (size1 == 0) { - if (size0 = SZ_128K) { - base1 = base0; - size1 = size0; - } else { - size1 = size0 - + for (i = 0; i data-nsfrs; i++) { + if ((readl(data-sfrbases[i] + REG_MMU_VERSION) 28) + == 3) { + if (!sysmmu_block(data-sfrbases[i])) + continue; + + if (size1 == 0) { + if (size0 = SZ_128K) { + base1 = base0; + size1 = size0; + } else { + size1 = size0 - ALIGN(size0 / 2, SZ_64K);
[PATCH v5 10/14] iommu/exynos: add support for runtime pm and suspend/resume
This change enables the client device drivers not to care about the state of System MMU since the internal state of System MMU is controlled by the runtime PM and suspend/resume callback functions. Signed-off-by: KyongHo Cho pullip@samsung.com --- drivers/iommu/exynos-iommu.c | 176 ++- 1 file changed, 89 insertions(+), 87 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index a0e5ee1..c3c5b7b 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -187,6 +187,7 @@ struct sysmmu_drvdata { spinlock_t lock; struct iommu_domain *domain; unsigned long pgtable; + bool runtime_active; void __iomem *sfrbases[0]; }; @@ -409,7 +410,8 @@ static bool __sysmmu_disable(struct sysmmu_drvdata *data) data-pgtable = 0; data-domain = NULL; - __sysmmu_disable_nocount(data); + if (data-runtime_active) + __sysmmu_disable_nocount(data); dev_dbg(data-sysmmu, Disabled\n); } else { @@ -422,30 +424,6 @@ static bool __sysmmu_disable(struct sysmmu_drvdata *data) return disabled; } -static bool __exynos_sysmmu_disable(struct device *dev) -{ - unsigned long flags; - bool disabled = true; - struct exynos_iommu_owner *owner = dev-archdata.iommu; - struct device *sysmmu; - - BUG_ON(!has_sysmmu(dev)); - - spin_lock_irqsave(owner-lock, flags); - - /* Every call to __sysmmu_disable() must return same result */ - for_each_sysmmu(dev, sysmmu) { - struct sysmmu_drvdata *data = dev_get_drvdata(sysmmu); - disabled = __sysmmu_disable(data); - if (disabled) - data-master = NULL; - } - - spin_unlock_irqrestore(owner-lock, flags); - - return disabled; -} - static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data) { int i; @@ -481,7 +459,8 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data, data-pgtable = pgtable; data-domain = domain; - __sysmmu_enable_nocount(data); + if (data-runtime_active) + __sysmmu_enable_nocount(data); dev_dbg(data-sysmmu, Enabled\n); } else { @@ -537,42 +516,31 @@ static int __exynos_sysmmu_enable(struct device *dev, unsigned long pgtable, int exynos_sysmmu_enable(struct device *dev, unsigned long pgtable) { - int ret; - struct device *sysmmu; - BUG_ON(!memblock_is_memory(pgtable)); - for_each_sysmmu(dev, sysmmu) { - ret = pm_runtime_get_sync(sysmmu); - if (ret 0) - break; - } - - if (ret 0) { - struct device *start; - for_each_sysmmu_until(dev, start, sysmmu) - pm_runtime_put(start); - - return ret; - } - - ret = __exynos_sysmmu_enable(dev, pgtable, NULL); - if (ret 0) - for_each_sysmmu(dev, sysmmu) - pm_runtime_put(sysmmu); - - return ret; + return __exynos_sysmmu_enable(dev, pgtable, NULL); } bool exynos_sysmmu_disable(struct device *dev) { - bool disabled; + unsigned long flags; + bool disabled = true; + struct exynos_iommu_owner *owner = dev-archdata.iommu; struct device *sysmmu; - disabled = __exynos_sysmmu_disable(dev); + BUG_ON(!has_sysmmu(dev)); + + spin_lock_irqsave(owner-lock, flags); + + /* Every call to __sysmmu_disable() must return same result */ + for_each_sysmmu(dev, sysmmu) { + struct sysmmu_drvdata *drvdata = dev_get_drvdata(sysmmu); + disabled = __sysmmu_disable(drvdata); + if (disabled) + drvdata-master = NULL; + } - for_each_sysmmu(dev, sysmmu) - pm_runtime_put(sysmmu); + spin_unlock_irqrestore(owner-lock, flags); return disabled; } @@ -588,7 +556,8 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova) data = dev_get_drvdata(sysmmu); spin_lock_irqsave(data-lock, flags); - if (is_sysmmu_active(data)) { + if (is_sysmmu_active(data) + data-runtime_active) { int i; for (i = 0; i data-nsfrs; i++) { if (sysmmu_block(data-sfrbases[i])) { @@ -817,7 +786,7 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) data-sysmmu = dev; spin_lock_init(data-lock); - pm_runtime_enable(dev); + data-runtime_active = !pm_runtime_enabled(dev); platform_set_drvdata(pdev, data); @@ -828,6 +797,64 @@ static
[PATCH v5 11/14] iommu/exynos: add support for System MMU 3.2 and 3.3
Since System MMU 3.2 and 3.3 have more prefetch buffers than 2, the existing function to set prefetch buffers, exynos_sysmmu_set_prefbuf() is not able to support them. This commit removes exynos_sysmmu_set_prefbuf() and introduces new interface, exynos_sysmmu_set_pbuf() that can pass information of more buffers than 2. It is safe to remove the existing function because there is no device driver in the kernel yet that calls the removed function. Signed-off-by: KyongHo Cho pullip@samsung.com --- drivers/iommu/exynos-iommu.c | 370 +-- 1 file changed, 322 insertions(+), 48 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index c3c5b7b..a558c51 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -80,6 +80,14 @@ #define CTRL_BLOCK 0x7 #define CTRL_DISABLE 0x0 +#define CFG_LRU0x1 +#define CFG_QOS(n) ((n 0xF) 7) +#define CFG_MASK 0x0150 /* Selecting bit 0-15, 20, 22 and 24 */ +#define CFG_ACGEN (1 24) /* System MMU 3.3 only */ +#define CFG_SYSSEL (1 22) /* System MMU 3.2 only */ +#define CFG_FLPDCACHE (1 20) /* System MMU 3.2+ only */ +#define CFG_SHAREABLE (1 12) /* System MMU 3.x only */ + #define REG_MMU_CTRL 0x000 #define REG_MMU_CFG0x004 #define REG_MMU_STATUS 0x008 @@ -88,6 +96,10 @@ #define REG_PT_BASE_ADDR 0x014 #define REG_INT_STATUS 0x018 #define REG_INT_CLEAR 0x01C +#define REG_PB_INFO0x400 +#define REG_PB_LMM 0x404 +#define REG_PB_INDICATE0x408 +#define REG_PB_CFG 0x40C #define REG_PAGE_FAULT_ADDR0x024 #define REG_AW_FAULT_ADDR 0x028 @@ -96,10 +108,12 @@ #define REG_MMU_VERSION0x034 -#define REG_PB0_SADDR 0x04C -#define REG_PB0_EADDR 0x050 -#define REG_PB1_SADDR 0x054 -#define REG_PB1_EADDR 0x058 +#define MMU_MAJ_VER(reg) (reg 28) +#define MMU_MIN_VER(reg) ((reg 21) 0x7F) + +#define MAX_NUM_PBUF 6 + +#define NUM_MINOR_OF_SYSMMU_V3 4 static void *sysmmu_placeholder; /* Inidcate if a device is System MMU */ @@ -178,6 +192,19 @@ struct exynos_iommu_owner { spinlock_t lock;/* Lock to preserve consistency of System MMU */ }; +#define SYSMMU_PBUFCFG_TLB_UPDATE (1 16) +#define SYSMMU_PBUFCFG_ASCENDING (1 12) +#define SYSMMU_PBUFCFG_DSECENDING (0 12) /* default */ +#define SYSMMU_PBUFCFG_PREFETCH(1 8) +#define SYSMMU_PBUFCFG_WRITE (1 4) +#define SYSMMU_PBUFCFG_READ(0 4) /* default */ + +struct sysmmu_prefbuf { + unsigned long base; + unsigned long size; + unsigned long config; +}; + struct sysmmu_drvdata { struct device *sysmmu; /* System MMU's device descriptor */ struct device *master; /* Client device that needs System MMU */ @@ -185,6 +212,8 @@ struct sysmmu_drvdata { struct clk *clk; int activations; spinlock_t lock; + struct sysmmu_prefbuf pbufs[MAX_NUM_PBUF]; + int num_pbufs; struct iommu_domain *domain; unsigned long pgtable; bool runtime_active; @@ -210,6 +239,21 @@ static bool is_sysmmu_active(struct sysmmu_drvdata *data) return data-activations 0; } +static unsigned int __sysmmu_version(struct sysmmu_drvdata *drvdata, + int idx, unsigned int *minor) +{ + unsigned int major; + + major = readl(drvdata-sfrbases[idx] + REG_MMU_VERSION); + + if (minor) + *minor = MMU_MIN_VER(major); + + major = MMU_MAJ_VER(major); + + return major; +} + static void sysmmu_unblock(void __iomem *sfrbase) { __raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL); @@ -245,32 +289,235 @@ static void __sysmmu_tlb_invalidate_entry(void __iomem *sfrbase, static void __sysmmu_set_ptbase(void __iomem *sfrbase, unsigned long pgd) { - __raw_writel(0x1, sfrbase + REG_MMU_CFG); /* 16KB LV1, LRU */ __raw_writel(pgd, sfrbase + REG_PT_BASE_ADDR); __sysmmu_tlb_invalidate(sfrbase); } -static void __sysmmu_set_prefbuf(void __iomem *sfrbase, unsigned long base, - unsigned long size, int idx) +static void __sysmmu_set_prefbuf(void __iomem *pbufbase, unsigned long base, + unsigned long size, int idx) +{ + __raw_writel(base, pbufbase + idx * 8); + __raw_writel(size - 1 + base, pbufbase + 4 + idx * 8); +} + +/* + * Offset of prefetch buffer setting registers are different + * between SysMMU 3.1 and 3.2. 3.3 has a single prefetch buffer setting. + */ +static unsigned short + pbuf_offset[NUM_MINOR_OF_SYSMMU_V3] = {0x04C, 0x04C, 0x070, 0x410}; + +/** + * __sysmmu_sort_prefbuf - sort the given @prefbuf in descending order. + * @prefbuf:
[PATCH v5 12/14] iommu/exynos: pass version information from DT
System MMUs in some implementation of Exynos core does not include correct version information in the System MMU. If the version information is not correct, exynos-iommu driver cannot take advantages of feature of higher versions of System MMu like prefetching page table entries prior to TLB miss. This commit allows passing version information from DT to the driver. If DT does not pass version information, the driver will read the information from System MMU. Signed-off-by: KyongHo Cho pullip@samsung.com --- drivers/iommu/exynos-iommu.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index a558c51..70921e9 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -205,6 +205,12 @@ struct sysmmu_prefbuf { unsigned long config; }; +struct sysmmu_version { + unsigned char major; /* major = 0 means that driver must use MMU_VERSION + register instead of this structure */ + unsigned char minor; +}; + struct sysmmu_drvdata { struct device *sysmmu; /* System MMU's device descriptor */ struct device *master; /* Client device that needs System MMU */ @@ -214,6 +220,7 @@ struct sysmmu_drvdata { spinlock_t lock; struct sysmmu_prefbuf pbufs[MAX_NUM_PBUF]; int num_pbufs; + struct sysmmu_version ver; struct iommu_domain *domain; unsigned long pgtable; bool runtime_active; @@ -246,6 +253,20 @@ static unsigned int __sysmmu_version(struct sysmmu_drvdata *drvdata, major = readl(drvdata-sfrbases[idx] + REG_MMU_VERSION); + if ((MMU_MAJ_VER(major) == 0) || (MMU_MAJ_VER(major) 3)) { + /* register MMU_VERSION is used for special purpose */ + if (drvdata-ver.major == 0) { + /* min ver. is not important for System MMU 1 and 2 */ + major = 1; + } else { + if (minor) + *minor = drvdata-ver.minor; + major = drvdata-ver.major; + } + + return major; + } + if (minor) *minor = MMU_MIN_VER(major); @@ -933,8 +954,15 @@ static int __init __sysmmu_setup(struct device *sysmmu, const char *compat; struct platform_device *pmaster = NULL; u32 master_inst_no = -1; + u32 ver[2]; int ret; + if (!of_property_read_u32_array(sysmmu-of_node, version, ver, 2)) { + drvdata-ver.major = (unsigned char)ver[0]; + drvdata-ver.minor = (unsigned char)ver[1]; + dev_dbg(sysmmu, Found version %d.%d\n, ver[0], ver[1]); + } + drvdata-pbufs[0].base = 0; drvdata-pbufs[0].size = ~0; drvdata-num_pbufs = 1; -- 1.8.0 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH RFC 01/12] s5p-csis: Add device tree support
Hello Grant, On 12/11/2012 09:36 AM, Grant Likely wrote: On Mon, 10 Dec 2012 20:45:55 +0100, Sylwester Nawrocki s.nawro...@samsung.com wrote: s5p-csis is platform device driver for MIPI-CSI frontend to the FIMC (camera host interface DMA engine and image processor). This patch adds support for instantiating the MIPI-CSIS devices from DT and parsing all SoC and board specific properties from device tree. Signed-off-by: Sylwester Nawrocki s.nawro...@samsung.com Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com --- .../bindings/media/soc/samsung-mipi-csis.txt | 82 +++ drivers/media/platform/s5p-fimc/mipi-csis.c| 155 +++- drivers/media/platform/s5p-fimc/mipi-csis.h|1 + 3 files changed, 202 insertions(+), 36 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt diff --git a/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt b/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt new file mode 100644 index 000..f57cbdc --- /dev/null +++ b/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt @@ -0,0 +1,82 @@ +Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver (MIPI CSIS) +- + +Required properties: + +- compatible : samsung,s5pv210-csis for S5PV210 SoCs, +samsung,exynos4210-csis for Exynos4210 and later SoCs; +- reg : physical base address and size of the device memory mapped +registers; +- interrupts : should contain MIPI CSIS interrupt; the format of the +interrupt specifier depends on the interrupt controller; +- max-data-lanes : maximum number of data lanes supported (SoC specific); +- vddio-supply: MIPI CSIS I/O and PLL voltage supply (e.g. 1.8V); +- vddcore-supply : MIPI CSIS Core voltage supply (e.g. 1.1V). + +Optional properties: + +- clock-frequency : The IP's main (system bus) clock frequency in Hz, default +value when this property is not specified is 166 MHz; +- samsung,csis,wclk : CSI-2 wrapper clock selection. If this property is present +external clock from CMU will be used, if not bus clock will +be selected. + +The device node should contain one 'port' child node with one child 'endpoint' +node, as outlined in the common media bindings specification. See +Documentation/devicetree/bindings/media/v4l2.txt for details. The following are +properties specific to those nodes. (TODO: update the file path) + +port node +- + +- reg : (required) must be 2 for camera C input (CSIS0) or 3 for +camera D input (CSIS1); 'reg' has a very specific definition. If you're going to use a reg property here, then the parent nodes need to have #address-cells=1;#size-cells=0; properties to define the address specifier format. However since you're identifying port numbers that aren't really addresses I would suggest simply changing this property to something like 'port-num'. Otherwise the binding looks good. Thank you for the review. Indeed I should have said about #address-cells, #size-cells here. I thought using 'reg' was agreed during previous discussions on the mailing lists (e.g. [1]), so I just carried on with 'reg'. I should just have addressed the comments from Stephen and Rob, instead of just resending same version of the documentation. I'll try to take care of it in the next post. i.e. rename 'link' node to 'endpoint' and 'remote' phandle to 'remote-endpoint'. I'm not really sure what advantage 'reg' gives over a new property. Would it still be OK to have port nodes names followed by indexes with port-num instead of reg, e.g. foo { port@0 { port-num = 0; }; port@1 { port-num = 1; }; }; ? [1] http://www.spinics.net/lists/linux-sh/msg13383.html -- Thanks, Sylwester -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH RFC 01/12] s5p-csis: Add device tree support
On Tue, 11 Dec 2012 12:24:23 +0100, Sylwester Nawrocki s.nawro...@samsung.com wrote: Hello Grant, On 12/11/2012 09:36 AM, Grant Likely wrote: On Mon, 10 Dec 2012 20:45:55 +0100, Sylwester Nawrocki s.nawro...@samsung.com wrote: s5p-csis is platform device driver for MIPI-CSI frontend to the FIMC (camera host interface DMA engine and image processor). This patch adds support for instantiating the MIPI-CSIS devices from DT and parsing all SoC and board specific properties from device tree. Signed-off-by: Sylwester Nawrocki s.nawro...@samsung.com Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com --- .../bindings/media/soc/samsung-mipi-csis.txt | 82 +++ drivers/media/platform/s5p-fimc/mipi-csis.c| 155 +++- drivers/media/platform/s5p-fimc/mipi-csis.h|1 + 3 files changed, 202 insertions(+), 36 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt diff --git a/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt b/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt new file mode 100644 index 000..f57cbdc --- /dev/null +++ b/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt @@ -0,0 +1,82 @@ +Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver (MIPI CSIS) +- + +Required properties: + +- compatible: samsung,s5pv210-csis for S5PV210 SoCs, + samsung,exynos4210-csis for Exynos4210 and later SoCs; +- reg : physical base address and size of the device memory mapped + registers; +- interrupts : should contain MIPI CSIS interrupt; the format of the + interrupt specifier depends on the interrupt controller; +- max-data-lanes : maximum number of data lanes supported (SoC specific); +- vddio-supply: MIPI CSIS I/O and PLL voltage supply (e.g. 1.8V); +- vddcore-supply : MIPI CSIS Core voltage supply (e.g. 1.1V). + +Optional properties: + +- clock-frequency : The IP's main (system bus) clock frequency in Hz, default + value when this property is not specified is 166 MHz; +- samsung,csis,wclk : CSI-2 wrapper clock selection. If this property is present + external clock from CMU will be used, if not bus clock will + be selected. + +The device node should contain one 'port' child node with one child 'endpoint' +node, as outlined in the common media bindings specification. See +Documentation/devicetree/bindings/media/v4l2.txt for details. The following are +properties specific to those nodes. (TODO: update the file path) + +port node +- + +- reg : (required) must be 2 for camera C input (CSIS0) or 3 for + camera D input (CSIS1); 'reg' has a very specific definition. If you're going to use a reg property here, then the parent nodes need to have #address-cells=1;#size-cells=0; properties to define the address specifier format. However since you're identifying port numbers that aren't really addresses I would suggest simply changing this property to something like 'port-num'. Otherwise the binding looks good. Thank you for the review. Indeed I should have said about #address-cells, #size-cells here. I thought using 'reg' was agreed during previous discussions on the mailing lists (e.g. [1]), so I just carried on with 'reg'. I should just have addressed the comments from Stephen and Rob, instead of just resending same version of the documentation. I'll try to take care of it in the next post. i.e. rename 'link' node to 'endpoint' and 'remote' phandle to 'remote-endpoint'. Could be. I can't remember what has been discussed from one day to the next. :-) If you've got #address/#size-cells in the binding, then reg is fine. If that's what you've already got, then just leave it. As long as the conventions are intact. g. -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 03/19] MAINTAINERS: remove arch/arm/plat-s5p/
These files were merged into plat-samsung. Acked-by: Kukjin Kim kgene@samsung.com Cc: Ben Dooks ben-li...@fluff.org Cc: linux-arm-ker...@lists.infradead.org Cc: linux-samsung-soc@vger.kernel.org Signed-off-by: Cesar Eduardo Barros ces...@cesarb.net --- MAINTAINERS | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f4890a3..e013f00 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1074,7 +1074,6 @@ W:http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/plat-samsung/ F: arch/arm/plat-s3c24xx/ -F: arch/arm/plat-s5p/ F: arch/arm/mach-s3c24*/ F: arch/arm/mach-s3c64xx/ F: drivers/*/*s3c2410* @@ -1105,7 +1104,6 @@ M:Sylwester Nawrocki s.nawro...@samsung.com L: linux-arm-ker...@lists.infradead.org L: linux-me...@vger.kernel.org S: Maintained -F: arch/arm/plat-s5p/dev-fimc* F: arch/arm/plat-samsung/include/plat/*fimc* F: drivers/media/platform/s5p-fimc/ @@ -1116,7 +1114,7 @@ M:Jeongtae Park jtp.p...@samsung.com L: linux-arm-ker...@lists.infradead.org L: linux-me...@vger.kernel.org S: Maintained -F: arch/arm/plat-s5p/dev-mfc.c +F: arch/arm/plat-samsung/s5p-dev-mfc.c F: drivers/media/platform/s5p-mfc/ ARM/SAMSUNG S5P SERIES TV SUBSYSTEM SUPPORT -- 1.7.11.7 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/3] add mie driver for exynos
On Mon, Dec 10, 2012 at 1:27 AM, Inki Dae inki@samsung.com wrote: 2012/12/10 Stéphane Marchesin stephane.marche...@gmail.com On Sun, Dec 9, 2012 at 10:26 PM, Inki Dae inki@samsung.com wrote: 2012/12/6 R. Chandrasekar rcse...@samsung.com From: R. Chandrasekar rcse...@samsung.com this patch set adds the driver support for the dithering functionality of the mobile image enhancement (mie) module. device tree support is added for mie. fimd adds the mie module as plugin and calls the dithering function. dithere is required when the panels bpp is less then fimd output. though mie mie has other functionalities, current system uses only dithereing. Please, move mie module into drivers/video/exynos. The mie is a interface between fimd and lcd panel(or mipi-dsi, eDP) to enhance image to be displayed. And it seems like that this doesn't need drm framework-relevant interfaces, such as gem. Well, if you want to support it from the DRM, it should live in drivers/gpu/drm, and I don't think you should add another platform driver in the first place. The profusion of platform drivers in exynos makes it really difficult to support suspend/resume and initialization properly as many devices which operate separately need to sync through global variables. MIE could be used by linux framebuffer-based specific driver(s3c-fb) also. Yes, but it is a DRM driver we're talking about here. Again it is really difficult to work with it across suspend-resume. I don't think the DRM was ever meant to be a collection of independent platform drivers. If linux framebuffer-based driver want to use this mie module, should the mie module be placed in drivers/video coping it? I think it's not good so it's better way to use this mie module commonly without duplicated codes. And mipi-dsi and eDP drivers also have their own platform device/driver and are being used by exynos drm driver or s3c-fb driver. Of course, for some IPs such as mie between display controller and lcd panel, It seems like that there should be proper framework or interfaces in drivers/video/exynos or somewhere so that other frameworks can use it commonly. And drm and linux framebuffer drivers should call the interfaces. For the short term, I think it's fine to duplicate the code. For the longer term, I think framebuffer support should be provided by the drm framebuffer compat layer, and s3c-fb should disappear. This is what has been done with all the other DRM drivers. Stéphane Thanks, Inki Dae Stéphane And also, please refer to the below link, Common Display Framework, for more generic way. http://lists.freedesktop.org/archives/dri-devel/2012-November/030888.html Thanks, Inki Dae R. Chandrasekar (3): DTS: exynos: add device tree support for exynos mie drm: fimd: add mie plugin support for dithering drm: mie: add mie driver for exynos arch/arm/boot/dts/exynos5250.dtsi |7 +- drivers/gpu/drm/exynos/Kconfig |7 + drivers/gpu/drm/exynos/Makefile |1 + drivers/gpu/drm/exynos/exynos_drm_fimd.c| 58 +- drivers/gpu/drm/exynos/exynos_drm_fimd_common.h | 20 ++ drivers/gpu/drm/exynos/exynos_drm_mie.c | 250 +++ drivers/gpu/drm/exynos/exynos_drm_mie.h | 50 + drivers/gpu/drm/exynos/exynos_regs-mie.h| 75 +++ 8 files changed, 465 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/exynos/exynos_drm_fimd_common.h create mode 100644 drivers/gpu/drm/exynos/exynos_drm_mie.c create mode 100644 drivers/gpu/drm/exynos/exynos_drm_mie.h create mode 100644 drivers/gpu/drm/exynos/exynos_regs-mie.h -- 1.7.9.5 ___ dri-devel mailing list dri-de...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-de...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-de...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] regulator: s5m8767: Fix probe failure due to stack corruption
The function sec_reg_read invokes regmap_read which expects unsigned int * as the destination address. The existing driver is passing address of local variable val which is u8. This causes the stack corruption and following dump is observed during probe. Hence change val from u8 to unsigned int. Unable to handle kernel paging request at virtual address 02410020 pgd = c0004000 [02410020] *pgd= Internal error: Oops: 8005 [#1] PREEMPT SMP ARM Modules linked in: CPU: 0Not tainted (3.6.0-00696-g98a28b18-dirty #27) PC is at 0x2410020 LR is at _regulator_get_voltage+0x3c/0x70 pc : [02410020]lr : [c02395d4]psr: 2013 sp : cf839b68 ip : fp : cf92d410 r10: cfd0 r9 : c06d9878 r8 : f0a0 r7 : cf839b70 r6 : cf92d400 r5 : 0011 r4 : cf00 r3 : 02410020 r2 : r1 : 0048 r0 : cf00 Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel ... . [c02395d4] (_regulator_get_voltage+0x3c/0x70) from [c023ad80] (print_constraints+0x50/0x36c) [c023ad80] (print_constraints+0x50/0x36c) from [c023e504] (set_machine_constraints+0xe8/0x2b0) [c023e504] (set_machine_constraints+0xe8/0x2b0) from [c023e9c8] (regulator_register+0x2fc/0x604) [c023e9c8] (regulator_register+0x2fc/0x604) from [c049d628] (s5m8767_pmic_probe+0x688/0x718) [c049d628] (s5m8767_pmic_probe+0x688/0x718) from [c029915c] (platform_drv_probe+0x18/0x1c) [c029915c] (platform_drv_probe+0x18/0x1c) from [c0297dd0] (really_probe+0x68/0x1f4) [c0297dd0] (really_probe+0x68/0x1f4) from [c0298070] (driver_probe_device+0x30/0x48) Signed-off-by: Inderpal Singh inderpal.si...@linaro.org --- drivers/regulator/s5m8767.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 8ef5b33..9e6850f 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -214,7 +214,7 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int ret, reg; int mask = 0xc0, enable_ctrl; - u8 val; + unsigned int val; ret = s5m8767_get_register(rdev, reg, enable_ctrl); if (ret == -EINVAL) @@ -306,7 +306,7 @@ static int s5m8767_get_voltage_sel(struct regulator_dev *rdev) struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int reg, mask, ret; int reg_id = rdev_get_id(rdev); - u8 val; + unsigned int val; ret = s5m8767_get_voltage_register(rdev, reg); if (ret) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/4] DMA: PL330: add device tree property for DMA_MEMCPY capability
On Fri, Nov 30, 2012 at 4:26 PM, Bartlomiej Zolnierkiewicz b.zolnier...@samsung.com wrote: Thank you for explaining it. Here is a patch implementing the idea: From: Bartlomiej Zolnierkiewicz b.zolnier...@samsung.com Subject: [PATCH] DMA: PL330: add peripherals map to the device tree Add device tree (DT) property (peri-map) for storing indices of peripherals connected to DMAC and fix DT nodes of client drivers to use 'dma peripheral id' instead of 'dma request id'. Also instead of setting DMA_MEMCPY capability unconditionally in pl330_probe() do it only when peri-map DT property is present (idea from Jassi Brar). It fixes the issue on ARM EXYNOS platforms using DT where pdma controller erroneously was used for DMA_MEMCPY operations instead of mdma one (it seems to work correctly but at the cost of worse performance). Sorry, we need to change it as per new generic dma DT bindings http://git.infradead.org/users/vkoul/slave-dma.git/blob/refs/heads/next:/Documentation/devicetree/bindings/dma/dma.txt Thanks. -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html